From: Fabian Grünbichler Date: Thu, 24 Apr 2025 15:47:57 +0000 (+0200) Subject: rustc (1.85.0+dfsg3-1) unstable; urgency=medium X-Git-Tag: archive/raspbian/1.85.0+dfsg3-1+rpi1^2~51 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=35f03cd80d1b7eb077711e719c7772fdb0110b68;p=rustc.git rustc (1.85.0+dfsg3-1) unstable; urgency=medium * backport fix for gix-features CVE-2025-31130 * rust-lldb: fix lldb version (Closes: #1100950) * cherry-pick fix for crossbeam-channel RUSTSEC-2025-0024 [dgit import unpatched rustc 1.85.0+dfsg3-1] --- 35f03cd80d1b7eb077711e719c7772fdb0110b68 diff --cc debian/NEWS index 0000000000,0000000000,0000000000..067259d3da new file mode 100644 --- /dev/null +++ b/debian/NEWS @@@@ -1,0 -1,0 -1,0 +1,29 @@@@ +++rustc (1.20.0+dfsg1-2) unstable; urgency=medium +++ +++ Starting from version 1.20.0+dfsg1-1 (i.e. the previous version) the Debian +++ packages of rustc no longer fail their build if any tests fail. In other +++ words, some tests might have failed when building this and future versions of +++ the package. This is due to lack of maintainer time to investigate failures. +++ +++ Many previous test failures were reported to upstream and did not receive a +++ timely response, suggesting the failures were not important. I was then +++ forced to patch out the test to make the build proceed, so several tests were +++ being ignored in practise anyway. +++ +++ This brings the Debian package in line with the Fedora package which also +++ ignores all test failures. (Many other distributions don't run tests at all.) +++ +++ If you think that the Debian rustc package is miscompiling your program in a +++ way that the upstream distributed compiler doesn't, you may check the test +++ failures here: +++ +++ https://buildd.debian.org/status/package.php?p=rustc +++ +++ If you can identify a relevant test failure as well as the patches needed to +++ fix it (either to rustc or LLVM), this will speed up the processing of any +++ bug reports on the Debian side. +++ +++ We will also examine these failures ourselves on a best-effort basis and +++ attempt to fix the more serious-looking ones. +++ +++ -- Ximin Luo Mon, 16 Oct 2017 18:02:23 +0200 diff --cc debian/README.Debian index 0000000000,0000000000,0000000000..6ae59b7af7 new file mode 100644 --- /dev/null +++ b/debian/README.Debian @@@@ -1,0 -1,0 -1,0 +1,346 @@@@ +++Architecture-specific notes +++=========================== +++ +++This section talks about the rustc compiler on your host architecture. For +++cross-compiling to a foreign target architecture, see the next section. +++ +++armhf armel mips mipsel powerpc powerpcspe +++------------------------------------------ +++ +++We only ship debuginfo for libstd and not the compiler itself, otherwise builds +++run out of memory on the Debian buildds, with non-obvious and random errors. +++ +++See https://github.com/rust-lang/rust/issues/45854 for details. +++ +++If all your armhf build machines have ~8GB memory or more, you can experiment +++with disabling this work-around (i.e. revert to normal) in d/rules. +++ +++ +++Cross-compiling +++=============== +++ +++Rust supports cross-compiling to many different architectures, and we expose +++this feature as fully as feasible in Debian, including to wasm and windows. +++ +++Introduction and terminology +++---------------------------- +++ +++Rust uses LLVM, so cross-compiling works a bit differently from the GNU +++toolchain. The most important difference is that there are no "cross" +++compilers, every compiler is already a cross compiler. For cross-compiling, all +++you need to do (on the rustc / LLVM side) is to install the standard libraries +++for each target architecture you want to compile to, i.e. libstd-rust-dev. +++ +++Before we go further, we must clarify some terminology. The rust ecosystem +++generally uses the term "host" for the native architecture running the +++compiler, equivalent to DEB_BUILD_RUST_TYPE or "build" in GNU terminology, and +++"target" for the foreign architecture that the build products run on, +++equivalent to DEB_HOST_RUST_TYPE or "host" in GNU terminology. For example, +++rustc --version --verbose will output something like: +++ +++ rustc 1.16.0 +++ [..] +++ host: x86_64-unknown-linux-gnu +++ +++And both rustc and cargo have --target flags: +++ +++ $ rustc --help | grep '\-\-target' +++ --target TARGET Target triple for which the code is compiled +++ $ cargo build --help | grep '\-\-target' +++ --target TRIPLE Build for the target triple +++ +++One major exception to this naming scheme is in CERTAIN PARTS OF the build +++scripts of cargo and rustc themselves, such as the `./configure` scripts and +++SOME PARTS of the `config.toml` files. Here, "build", "host" and "target" mean +++the same things they do in GNU toolchain terminology. However, IN OTHER PARTS +++OF the build scripts of cargo and rustc, as well as cargo and rustc's own +++output and logging messages, the term "host" and "target" mean as they do in +++the previous paragraph. Yes, it's a total mind fuck. :( Table for clarity: +++ +++======================================= =============== ======================== +++ Rust ecosystem, Some parts of the rustc +++GNU term / Debian envvar rustc and cargo and cargo build scripts +++======================================= =============== ======================== +++build DEB_BUILD_{ARCH,RUST_TYPE} host build +++ the machine running the build +++--------------------------------------- --------------- ------------------------ +++host DEB_HOST_{ARCH,RUST_TYPE} target host(s) +++ the machine the build products run on +++--------------------------------------- --------------- ------------------------ +++only relevant when building a compiler +++target DEB_TARGET_{ARCH,RUST_TYPE} N/A target(s) +++ the one architecture that the built extra architectures +++ cross-compiler itself builds for to build "std" for +++--------------------------------------- --------------- ------------------------ +++ +++General case for other Debian platforms +++--------------------------------------- +++ +++To manually use the Debian rustc binary for cross-compiling: +++ +++0. If you haven't done so previously, run: +++ +++ dpkg --add-architecture ${DEB_TARGET_ARCH} +++ apt-get update +++ +++ (This is something that you need to do for all Debian crossbuilding or +++ multi-architecture installing.) +++ +++1. Install crossbuild-essential-${DEB_TARGET_ARCH} e.g. arm64. +++ +++ (This is something that you need to do for all Debian crossbuilding.) +++ +++ For certain (HOST, TARGET) pairs you can instead install gcc-multilib, e.g. +++ when compiling from amd64 to i386. +++ +++2. Install libstd-rust-dev:${DEB_TARGET_ARCH}. +++ +++3. Add the following flags to your rustc invocation: +++ +++ -C linker=${DEB_TARGET_GNU_TYPE}-gcc # e.g. aarch64-linux-gnu +++ --target ${DEB_TARGET_RUST_TYPE} # e.g. aarch64-unknown-linux-gnu +++ +++ For certain (HOST, TARGET) pairs, namely the same ones as above that are +++ supported by gcc-multilib, you can omit the linker flag since the default +++ ``gcc`` linker (with multilib support) will work. +++ +++You can find the right TARGET vars to use in dpkg-architecture(1) and/or +++/usr/share/rustc/architecture.mk and/or possibly on the Debian wiki. +++ +++These steps are different when cross-building a Debian package, or preparing +++one for cross-compiling. (1) is performed automatically by cross-building tools +++such as sbuild, and (3) is performed automatically by our cargo wrapper script. +++The details of how to do (2) correctly are explained in the section below +++called "Using rustc in a Debian package". +++ +++Foreign non-Debian platforms +++---------------------------- +++ +++Targeting a non-Debian platform is not a common Debian crossbuilding pattern, +++so we do something ad-hoc for our Debian rust packages. +++ +++Instead of libstd-rust-dev:$arch (for an $arch that is not in Debian), we +++provide a libstd-rust-dev-$platform:$arch package. For example, +++libstd-rust-dev-windows:i386. For VM platforms such as WASM, $arch is omitted. +++ +++Instead of implicitly relying on crossbuild-essential-$arch (for an $arch that +++is not in Debian), we have the libstd-rust-dev-$platform:$arch package +++Recommend the appropriate linker. For example, Clang or MinGW. +++ +++To use these for manual crossbuilding: +++ +++1. Install the appropriate library package, as well as the corresponding linker +++ package from its Recommends if it isn't pulled in automatically. +++ +++2. Pass in the appropriate ``-C linker`` and ``--target`` flags to ``rustc``. +++ +++WASM +++~~~~ +++ +++We ship three different wasm32 targets - wasm32-unknown-unknown, wasm32-wasip1 +++(previously known as wasm32-wasi) and wasm32-p2 - in the libstd-rust-dev-wasm32 +++package. +++ +++wasm32-unknown-unknown is suitable for web stuff, where you typically will need +++to depending on the rust-wasm-bindgen, js-sys, and web-sys crates. Here, calls +++to libstd stuff (such as println!()) will silently do nothing, as defined in +++``library/std/src/sys/wasm/mod.rs`` and explained in upstream #48564. +++ +++wasm32-wasip1/wasm32-wasip2 are suitable for non-web stuff, and are closer to a +++"normal" target where you expect libstd to be available, and for println!() to +++actually print to stdout. If you just want to cross-compile a regular non-wasm +++library or program to wasm for whatever reason, and only want to run it +++natively and not inside a web browser, use one of these targets. +++ +++To run the generated wasm, you can either: +++ +++1. Use /usr/share/rustc/bin/wasi-node, which depends on nodejs. +++ +++ Pending #986616, this will be added to the nodejs package directly. +++ +++2. Compile and use one of the following runtimes: +++ +++ - https://github.com/bytecodealliance/wasmtime +++ - https://github.com/bytecodealliance/lucet +++ - https://github.com/wasmerio/wasmer +++ +++Windows +++~~~~~~~ +++ +++We ship the following targets: +++ +++- x86_64-pc-windows-gnu in the libstd-rust-dev-windows:amd64 package +++- i686-pc-windows-gnu in the libstd-rust-dev-windows:i386 package +++ +++To run the compiled binaries, you can use wine. You will need to set one of: +++ +++- WINEPATH="/usr/lib/gcc/x86_64-w64-mingw32/10-posix;/usr/lib/rustlib/x86_64-pc-windows-gnu/lib" +++- WINEPATH="/usr/lib/gcc/i686-w64-mingw32/10-posix;/usr/lib/rustlib/i686-pc-windows-gnu/lib" +++ +++If you get "import_dll ... not found" errors, check that these paths are mapped +++to some windows drive path - run "winecfg $path" for each path in the component +++of WINEPATH; if any begin with "\\?\unix\" then you'll need to map them to a +++drive in "winecfg" -> Drives. If all begin with some windows drive letter, then +++your error is something unrelated and we sadly can't help you here. +++ +++ +++Using rustc in a Debian package +++=============================== +++ +++You are encouraged to support cross-compiling. See the above section for more +++details; in summary you need to install rustc for the host architecture and +++libstd-rust-dev for the target architecture, so your debian/control would look +++something like this: +++ +++ Build-Depends: +++ [..] +++ rustc:native (>= $version), +++ libstd-rust-dev (>= $version), +++ [..] +++ +++You need both, this is important. When Debian build toolchains satisfy the +++build-depends of a cross-build, (1) a "rustc:native" Build-Depends selects +++rustc for the native architecture, which is possible because it's "Multi-Arch: +++allowed", and this will implicitly pull in libstd-rust-dev also for the native +++architecture; and (2) a "libstd-rust-dev" Build-Depends implies libstd-rust-dev +++for the foreign architecture, since it's "Multi-Arch: same". +++ +++You'll probably also want to add +++ +++ include /usr/share/rustc/architecture.mk +++ +++to your debian/rules. This sets some useful variables like DEB_HOST_RUST_TYPE. +++See the cargo package for an example. +++ +++If your build uses cargo, you'll want to add: +++ +++ Build-Depends: +++ [..] +++ cargo:native, +++ [..] +++ +++and use our cargo wrapper script instead of /usr/bin/cargo directly. See +++/usr/share/cargo/bin/cargo for details on how to use it. +++ +++ +++Porting to new architectures (on the same distro) +++================================================= +++ +++As mentioned above, to cross-compile rust packages you need to install the rust +++standard library for each relevant foreign architecture. However, this is not +++needed when cross-compiling rustc itself; its build system will build any +++relevant foreign-architecture standard libraries automatically. +++ +++Cross-build, in a schroot using sbuild +++-------------------------------------- +++ +++0. Set up an schroot for your native architecture, for sbuild: +++ +++ sudo apt-get install sbuild +++ sudo sbuild-adduser $LOGNAME +++ newgrp sbuild # or log out and log back in +++ sudo sbuild-createchroot --include=eatmydata,ccache,gnupg unstable \ +++ /srv/chroot/unstable-$(dpkg-architecture -qDEB_BUILD_ARCH)-sbuild \ +++ http://deb.debian.org/debian +++ +++ See https://wiki.debian.org/sbuild for more details. +++ +++1. Build it: +++ +++ sudo apt-get source --download-only rustc +++ sbuild --host=$new_arch rustc_*.dsc +++ +++Cross-build, directly on your own system +++---------------------------------------- +++ +++0. Install the build-dependencies of rustc (including cargo and itself): +++ +++ sudo dpkg --add-architecture $new_arch +++ sudo apt-get --no-install-recommends build-dep --host-architecture=$new_arch rustc +++ +++1. Build it: +++ +++ apt-get source --compile --host-architecture=$new_arch rustc +++ +++Native-build using bundled upstream binary blobs +++------------------------------------------------ +++ +++Use the same instructions as given in "Bootstrapping" in debian/README.source +++in the source package, making sure to set the relevant architectures. +++ +++Responsible distribution of cross-built binaries +++------------------------------------------------ +++ +++By nature, cross-builds do not run tests. These are important for rustc and +++many tests often fail on newly-supported architectures even if builds and +++cross-builds work fine. You should find some appropriate way to test your +++cross-built packages rather than blindly shipping them to users. +++ +++For example, Debian experimental is an appropriate place to upload them, so +++that they can be installed and tested on Debian porter boxes, before being +++uploaded to unstable and distributed to users. +++ +++ +++Test failures +++============= +++ +++Starting from version 1.20.0+dfsg1-1 the Debian packages of rustc no longer +++fail the overall build if > 0 tests fail. Instead, we allow up to around 5 +++tests to fail. In other words, if you're reading this in a binary package, +++between 0 and 5 tests might have failed when building this. +++ +++This is due to lack of maintainer time to investigate all failures. Many +++previous test failures were reported to upstream and did not receive a timely +++response, suggesting the failures were not important. I was then forced to +++patch out the test to make the build proceed, so several tests were being +++ignored in practise anyway. +++ +++This brings the Debian package in line with the Fedora package which also +++ignores all test failures. (Many other distributions don't run tests at all.) +++ +++If you think that the Debian rustc package is miscompiling your program in a +++way that the upstream distributed compiler doesn't, you may check the test +++failures here: +++ +++https://buildd.debian.org/status/package.php?p=rustc +++ +++If you can identify a relevant test failure, as well as the patches needed to +++fix it (either to rustc or LLVM), this will speed up the processing of any bug +++reports on the Debian side. +++ +++We will also examine these failures ourselves on a best-effort basis and +++attempt to fix the more serious-looking ones. +++ +++Uncommon architectures +++---------------------- +++ +++Debian release architectures armel and s390x currently have more test failures, +++being tracked by upstream here: +++ +++- https://github.com/rust-lang/rust/issues/52493 armel +++- https://github.com/rust-lang/rust/issues/52491 s390x +++ +++Ports architectures +++------------------- +++ +++The number of allowed test failures on certain Debian ports architectures +++(currently powerpc, powerpcspe, sparc64, x32) is raised greatly to help unblock +++progress for porters. Of course, as a user this means you may run into more +++bugs than usual; as mentioned above bugs reports and patches are welcome. +++ +++ +++Shared libraries +++================ +++ +++For now, the shared libraries of Rust are private. +++The rational is the following: +++ * Upstream prefers static linking for now +++ - https://github.com/rust-lang/rust/issues/10209 +++ * rust is still under heavy development. As far as we know, there is +++ no commitement from upstream to provide a stable ABI for now. +++ Until we know more, we cannot take the chance to have Rust-built packages +++ failing at each release of the compiler. +++ * Static builds are working out of the box just fine +++ * However, LD_LIBRARY_PATH has to be updated when -C prefer-dynamic is used +++ +++ -- Sylvestre Ledru , Fri, 13 Feb 2015 15:08:43 +0100 diff --cc debian/README.source index 0000000000,0000000000,0000000000..9783addc1c new file mode 100644 --- /dev/null +++ b/debian/README.source @@@@ -1,0 -1,0 -1,0 +1,248 @@@@ +++Document by Ximin Luo, Luca Bruno, Sylvestre Ledru & Fabian Grünbichler +++ +++This source package is unfortunately quite tricky and with several cutting +++edges, due to the complexity of rust-lang bootstrapping system and the high +++rate of language changes still ongoing. +++ +++We try to describe here inner packaging details and the reasons behind them. +++ +++If you are looking to help maintain this package, be sure to read the "Notes +++for package maintainers" section further below. +++ +++ +++Embedded libraries +++================== +++ +++The upstream source package embeds many external libraries. We make a great +++effort to remove them and use system versions where possible, but there are a +++few more remaining: +++ +++ * vendor/dlmalloc +++ +++ These are small C libraries designed to be statically linked; their upstream +++ does not support building them as a shared library and they are too small to +++ justify their own Debian package. +++ +++ +++Building from source +++==================== +++ +++The Debian rustc package will use the system rustc to bootstrap itself from. +++The system rustc has to be either the previous or the same version as the rustc +++being built; the build will fail if this is not the case. +++ +++ sudo apt-get build-dep ./ +++ dpkg-buildpackage +++ # Or, to directly use what's in the Debian FTP archive +++ sudo apt-get build-dep rustc +++ apt-get source --compile rustc +++ +++Alternatively, you may give the "pkg.rustc.dlstage0" DEB_BUILD_PROFILE to +++instead use the process defined by Rust upstream. This downloads the "official" +++stage0 compiler for the version being built from rust-lang.org. At the time of +++writing "official" means "the previous stable version". +++ +++ sudo apt-get build-dep -P pkg.rustc.dlstage0 ./ +++ dpkg-buildpackage -P pkg.rustc.dlstage0 +++ # Or, to directly use what's in the Debian FTP archive +++ sudo apt-get build-dep -P pkg.rustc.dlstage0 rustc +++ apt-get source --compile -P pkg.rustc.dlstage0 rustc +++ +++After [1] is fixed, both of these should in theory give identical results. +++ +++If neither of these options are acceptable to you, e.g. because your distro +++does not have rustc already and your build process cannot access the network, +++see "Bootstrapping" below. +++ +++[1] https://github.com/rust-lang/rust/issues/34902 +++ +++ +++Bootstrapping +++============= +++ +++To bootstrap rustc on a distro that does not have it or cargo available on any +++architecture (so cross-compiling is not an option) you can run `debian/rules +++source_orig-stage0`. This creates a .dsc that does not Build-Depend on rustc or +++cargo. Instead, it includes an extra orig-stage0 source tarball that contains +++the official stage0 compiler, pre-downloaded from rust-lang.org so that your +++build daemons don't need to access the network during the build. +++ +++ debian/rules source_orig-stage0 +++ # Follow the final manual instructions that it outputs. Then: +++ sbuild ../rustc_*.dsc && dput ../rustc_*.dsc +++ +++To only bootstrap specific architectures, run this instead: +++ +++ upstream_bootstrap_arch="arm64 armhf" debian/rules source_orig-stage0 +++ +++This way, other architectures will be omitted from the orig-stage0 tarball. You +++might want to do this e.g. if these other architectures are already present in +++your distro, but the $upstream_bootstrap_arch ones are not yet present. +++ +++If the toolchain for the architecture you are attempting to bootstrap is not +++provided upstream (i.e., it's not at Tier 2 with Host Tools or higher[2]), you +++can manually prepare such a stage0 tarball via cross compilation using +++upstream's build process. +++ +++[2] https://doc.rust-lang.org/nightly/rustc/platform-support.html +++ +++Notes +++----- +++ +++The approach bundles the upstream bootstrapping binaries inside the Debian +++source package. This is a nasty hack that stretches the definition of "source +++package", but has a few advantages explained below. +++ +++The traditional Debian way of bootstrapping compilers - and other distros have +++similar approaches - is some variant of the following: +++ +++1. A developer locally installs some upstream bootstrapping binaries. +++2. They locally build a Debian package, using these binaries as undeclared +++ build dependencies. +++3. They upload these binary packages to Debian, which can be used as declared +++ Build-Depends in the future, including by the same package. +++ +++The problem with this is, Debian does not have any policy nor infrastructure +++that can try to reproduce what this developer supposedly did. +++ +++Using bootstrapping binary blobs *at some point of the process* is unavoidable. +++Rather than pretending we didn't do this, it is better to record *which blobs* +++we used, so it can be audited later. If we bundle non-Debian build-dependencies +++inside the source package, then we can do a *source-only upload*, and the +++building of the binary packages can be done by the normal build infrastructure. +++ +++If the build process is reproducible [1] then we can be sure that *you* (as the +++developer that prepared the source-only upload) didn't backdoor the binaries, +++nor did the build daemons even if they were compromised during the build. +++ +++The bootstrapping binaries may still have been backdoored, but this is true in +++both scenarios. So our arrangement is still a strict improvement in security, +++because it reduces the set of "things that may have been backdoored". Also, +++more people use the upstream binaries than the "magical original Debian +++package", so backdoors have a greater chance of being detected in the former. +++ +++In the long run, this process is laying the foundations for doing Diverse +++Double-Compilation [2], where we use *many independent* bootstrapping binaries +++to reproduce bit-for-bit identical output compilers, giving confidence that +++nothing was backdoored along the way. +++ +++[1] The build process for rustc is currently *not* reproducible but we're +++ working towards it. https://github.com/rust-lang/rust/issues/34902 +++[2] http://www.dwheeler.com/trusting-trust/ +++ +++ +++Maintaining this package +++======================== +++ +++Import of a new upstream version +++-------------------------------- +++ +++$ apt install equivs python3-magic +++$ sudo mk-build-deps -irt 'aptitude -R' +++$ uscan --verbose # or debian/rules source_orig-beta, for beta +++$ ver=UPDATE-ME # whatever it is, probably X.YY.Z or X.YY.Z~beta.N +++ +++$ debian/rebase-patches.sh $ver +++# This will require an understanding of how git-rebase and git-mergetool works +++# We recommend either kdiff3 or p4merge (proprietary) as the git-mergetool. +++# See individual patches for instructions on rebasing. +++ +++$ tar -C /tmp -xf ../rustc-${ver/\~/-}-src.tar.xz && ( dir=$PWD; cd /tmp/rustc-${ver/*~*/beta}-src/ && pwd && $dir/debian/prune-unused-deps ) && rm -rf /tmp/rustc-${ver/*~*/beta}-src/ +++$ git diff +++# Review the diff. If it removes too much stuff, it could mean that rustc +++# pulled in new unnecessary dependencies in this newer version. See if you can +++# drop them by amending the patch "d-0000-ignore-removed-submodules.patch". +++# Rerun the above "tar ..." commands again and check that your patch works. +++# For example, there is absolutely no reason to pull in windows-sys/windows or +++# openssl-src. +++ +++$ git commit -m "Update Files-Excluded for new upstream version ${ver/\~/-}" debian/copyright +++$ uscan --verbose # yes, again, to pick up the new Files-Excluded stuff +++ # or debian/rules source_orig-beta, for beta +++ +++# Keep running this and follow its instructions, until it gives no output: +++$ debian/check-orig-suspicious.sh $ver +++# When you are satisfied with the above, proceed: +++ +++$ git checkout debian/experimental +++$ gbp import-orig ../rustc_$ver+dfsg1.orig.tar.xz +++$ dch -v $ver+dfsg1-1~exp1 "New upstream release." +++$ debian/rules update-version +++# then refresh patches, etc etc +++# Use /usr/share/cargo/scripts/guess-crate-copyright to help update d/copyright quickly +++ +++# If you need to repack again, bump the 'repacksuffix' in d/watch then run +++$ uscan --verbose --force-download +++# This will do a local repack using the new Files-Excluded rules, without +++# redownloading the orig tarball (despite the slightly misleading flag). +++ +++ +++Proceeding after build failure +++------------------------------ +++ +++If your build fails, don't run `./x.py` directly as that will detect it's being +++run with different settings, and run the build from scratch all over again. +++overwriting all intermediate files. Instead, do: +++ +++$ debian/rules run_rustbuild X_CMD="build|test|install" X_FLAGS="whatever" +++ +++Hopefully, this will directly proceed to the step that failed, without +++rebuilding everything in between. +++ +++ +++Comparing Debian rustc vs upstream rustc +++---------------------------------------- +++ +++This package does things the Debian way, which differs significantly from +++upstream practices. If you find a bug, you might want to check if it is present +++in the upstream package. Run "debian/rules debian/config.toml" to generate our +++config.toml that you can then use in an upstream directory **unpacked from the +++release tarball*. (It is more complex to get this working with their git repo.) +++ +++This will configure it in a "halfway" style between upstream and Debian. +++Specifically, it will not build LLVM nor download stuff from crates.io, yet +++Debian patches are *not* applied. These specific settings were chosen as a +++tradeoff between convenience vs being close to what upstream does - so that the +++chances of a bug here being a genuine upstream issue rather than a Debian bug, +++is much higher. Also, with the exception of LLVM, these are non-default modes +++*supported by* upstream so they would be happy to receive bug reports about it +++even if your issue only occurs here. +++ +++OTOH if you need to test a completely clean upstream build, including all the +++annoying stuff like building LLVM and downloading dependencies from crates.io, +++simply unpack the tarball and run `./configure && ./x.py build` etc as normal. +++This can be useful for confirming that an issue is caused by Debian's LLVM. +++ +++If you need to test a LLVM patch, do something like this: +++ +++# build your patched LLVM debs, then: +++$ mkdir -p llvm-destdir && cd llvm-destdir +++$ ver=4.0; VERSION=FIXME +++$ for i in llvm-$ver llvm-$ver-dev llvm-$ver-runtime llvm-$ver-tools libllvm$ver; do \ +++ dpkg -x ../"$i"_*${VERSION}_*.deb .; done +++$ cd ../rustc +++$ debian/rules LLVM_DESTDIR=$PWD/../llvm-destdir build +++ +++If you need to test a patch to the stage0 rustc, do something like this: +++ +++# build your patched rustc debs or upstream rustc, then: +++$ mkdir -p rust-destdir && cd rust-destdir +++$ ver=1.20; VERSION=FIXME; +++$ for i in rustc libstd-rust-$ver libstd-rust-dev; do \ +++ dpkg -x ../"$i"_*${VERSION}_*.deb .; done +++$ cd ../rustc +++$ debian/rules RUST_DESTDIR=$PWD/../rust-destdir build +++ +++ +++Useful links +++------------ +++ +++The Fedora rust team is more active than the Debian one. Here are their links: +++ +++Source code +++https://src.fedoraproject.org/rpms/rust/tree/ +++ +++Binary packages and test logs +++https://kojipkgs.fedoraproject.org//packages/rust/ +++If the same test fails both on Fedora and Debian it's a good indication that +++we're not Doing It Wrong and can file a valid bug upstream. diff --cc debian/TODO index 0000000000,0000000000,0000000000..ed9f05bc11 new file mode 100644 --- /dev/null +++ b/debian/TODO @@@@ -1,0 -1,0 -1,0 +1,12 @@@@ +++Older backlog +++============= +++ +++ * Use Compiler-rt package +++ * Improve the bootstrap (do the local build first on our systems, upload +++ to Debian and use the packages) +++ * Port on other archs +++ * Create a runtime package (rust-runtime) +++ * Move the runtime library into a public directory +++ * Package the various editors plugins (emacs, kate & vim) +++ +++ -- Sylvestre Ledru Tue, 20 Jan 2015 08:50:28 +0100 diff --cc debian/architecture-test.mk index 0000000000,0000000000,0000000000..071f63aa20 new file mode 100644 --- /dev/null +++ b/debian/architecture-test.mk @@@@ -1,0 -1,0 -1,0 +1,16 @@@@ +++# Used for testing architecture.mk, and for make_orig-stage0_tarball.sh. +++# Not for end users. +++# +++# Usage: +++# $ make -s --no-print-directory -f debian/architecture-test.mk rust-for-deb_arm64 +++# arm64 aarch64-unknown-linux-gnu +++ +++include debian/architecture.mk +++ +++deb_arch_setvars = $(foreach var,ARCH ARCH_OS ARCH_CPU ARCH_BITS ARCH_ENDIAN GNU_CPU GNU_SYSTEM GNU_TYPE MULTIARCH,\ +++ $(eval DEB_$(1)_$(var) = $(shell dpkg-architecture -f -a$(1) -qDEB_HOST_$(var) 2>/dev/null))) +++ +++rust-for-deb_%: +++ $(eval $(call deb_arch_setvars,$*)) +++ $(eval $(call rust_type_setvar,DEB_$*)) +++ @echo $(DEB_$(*)_ARCH) $(DEB_$(*)_RUST_TYPE) diff --cc debian/architecture.mk index 0000000000,0000000000,0000000000..bbf81eef05 new file mode 100644 --- /dev/null +++ b/debian/architecture.mk @@@@ -1,0 -1,0 -1,0 +1,21 @@@@ +++# This Makefile snippet defines DEB_*_RUST_TYPE triples based on DEB_*_GNU_TYPE +++ +++include /usr/share/dpkg/architecture.mk +++ +++rust_cpu = $(subst i586,i686,\ +++$(if $(findstring -riscv64-,-$(2)-),$(subst riscv64,riscv64gc,$(1)),\ +++$(if $(findstring -armhf-,-$(2)-),$(subst arm,armv7,$(1)),\ +++$(if $(findstring -armel-,-$(2)-),$(subst arm,armv5te,$(1)),\ +++$(1))))) +++ +++rust_os = $(if $(findstring -hurd-,-$(2)-),$(subst gnu,hurd-gnu,$(1)),$1) +++ +++rust_type_setvar = $(1)_RUST_TYPE ?= $(call rust_cpu,$($(1)_GNU_CPU),$($(1)_ARCH))-unknown-$(call rust_os,$($(1)_GNU_SYSTEM),$($(1)_ARCH_OS)) +++ +++$(foreach machine,BUILD HOST TARGET,\ +++ $(eval $(call rust_type_setvar,DEB_$(machine)))) +++ +++# fallback for older dpkg versions +++ifeq ($(DEB_TARGET_RUST_TYPE),-unknown-) +++ DEB_TARGET_RUST_TYPE = $(DEB_HOST_RUST_TYPE) +++endif diff --cc debian/bin/cargo index 0000000000,0000000000,0000000000..f99d3fdb10 new file mode 100755 --- /dev/null +++ b/debian/bin/cargo @@@@ -1,0 -1,0 -1,0 +1,259 @@@@ +++#!/usr/bin/python3 +++""" +++Wrapper around cargo to have it build using Debian settings. +++ +++Usage: +++ export PATH=/path/to/dir/of/this/script:$PATH +++ export CARGO_HOME=debian/cargo_home +++ cargo prepare-debian /path/to/local/registry [--link-from-system] +++ cargo build +++ cargo test +++ cargo install +++ cargo clean +++ [rm -rf /path/to/local/registry] +++ +++The "prepare-debian" subcommand writes a config file to $CARGO_HOME that makes +++the subsequent invocations use our Debian flags. The "--link-from-system" flag +++is optional; if you use it we will create /path/to/local/registry and symlink +++the contents of /usr/share/cargo/registry into it. You are then responsible for +++cleaning it up afterwards (a simple `rm -rf` should do). +++ +++See cargo:d/rules and dh-cargo:cargo.pm for more examples. +++ +++Make sure you add "Build-Depends: python3:native" if you use this directly. +++If using this only indirectly via dh-cargo, then you only need "Build-Depends: +++dh-cargo"; this is a general principle when declaring dependencies. +++ +++If CARGO_HOME doesn't end with debian/cargo_home, then this script does nothing +++and passes through directly to cargo. +++ +++Otherwise, you *must* set the following environment variables: +++ +++- DEB_CARGO_CRATE +++ ${crate}_${version} of whatever you're building. +++ +++- CFLAGS CXXFLAGS CPPFLAGS LDFLAGS [*] +++- DEB_HOST_GNU_TYPE DEB_HOST_RUST_TYPE [*] +++ +++- (required only for `cargo install`) DESTDIR +++ DESTDIR to install build artifacts under. If running via dh-cargo, this will +++ be set automatically by debhelper, see `dh_auto_install` for details. +++ +++- (optional) DEB_BUILD_OPTIONS DEB_BUILD_PROFILES +++ +++- (optional) DEB_CARGO_INSTALL_PREFIX +++ Prefix to install build artifacts under. Default: /usr. Sometimes you might +++ want to change this to /usr/lib/cargo if the binary clashes with something +++ else, and then symlink it into /usr/bin under an alternative name. +++ +++- (optional) DEB_CARGO_CRATE_IN_REGISTRY +++ Whether the crate is in the local-registry (1) or cwd (0, empty, default). +++ +++For the envvars marked [*], it is easiest to set these in your d/rules via: +++ +++ include /usr/share/dpkg/architecture.mk +++ include /usr/share/dpkg/buildflags.mk +++ include /usr/share/rustc/architecture.mk +++ export CFLAGS CXXFLAGS CPPFLAGS LDFLAGS +++ export DEB_HOST_RUST_TYPE DEB_HOST_GNU_TYPE +++""" +++ +++import os +++import os.path +++import shutil +++import subprocess +++import sys +++ +++FLAGS = ('CFLAGS', 'CXXFLAGS', 'CPPFLAGS', 'LDFLAGS') +++ARCHES = ('DEB_HOST_GNU_TYPE', 'DEB_HOST_RUST_TYPE') +++SYSTEM_REGISTRY = "/usr/share/cargo/registry" +++ +++def log(*args): +++ print("debian cargo wrapper:", *args, file=sys.stderr, flush=True) +++ +++def logrun(*args, **kwargs): +++ log("running subprocess", args, kwargs) +++ return subprocess.run(*args, **kwargs) +++ +++def in_cwd(p=None): +++ cwd = os.getcwd() +++ return os.path.join(cwd, p) if p else cwd +++ +++def prepare_debian(cargo_home, registry, cratespec, host_gnu_type, ldflags, link_from_system, extra_rustflags): +++ registry_path = in_cwd(registry) +++ if link_from_system: +++ log(f'linking {SYSTEM_REGISTRY}/* into {registry_path}/') +++ os.makedirs(registry_path, exist_ok=True) +++ crates = os.listdir(SYSTEM_REGISTRY) if os.path.isdir(SYSTEM_REGISTRY) else [] +++ for c in crates: +++ target = os.path.join(registry_path, c) +++ if not os.path.islink(target): +++ os.symlink(os.path.join(SYSTEM_REGISTRY, c), target) +++ elif not os.path.exists(registry_path): +++ raise ValueError(f'non-existent registry: {registry}') +++ +++ rustflags = "-C debuginfo=2 -C strip=none --cap-lints warn".split() +++ rustflags.extend(["-C", f'linker={host_gnu_type}-gcc']) +++ for f in ldflags: +++ rustflags.extend(["-C", f'link-arg={f}']) +++ if link_from_system: +++ rustflags.extend([ +++ # Note that this order is important! Rust evaluates these options in +++ # priority of reverse order, so if the second option were in front, +++ # it would never be used, because any paths in registry_path are +++ # also in in_cwd(). +++ "--remap-path-prefix", f'{in_cwd()}={SYSTEM_REGISTRY}/{cratespec.replace("_", "-")}', +++ "--remap-path-prefix", f'{registry_path}={SYSTEM_REGISTRY}', +++ ]) +++ rustflags.extend(extra_rustflags.split()) +++ +++ # TODO: we cannot enable this until dh_shlibdeps works correctly; atm we get: +++ # dpkg-shlibdeps: warning: can't extract name and version from library name 'libstd-XXXXXXXX.so' +++ # and the resulting cargo.deb does not depend on the correct version of libstd-rust-1.XX +++ # We probably need to add override_dh_makeshlibs to d/rules of rustc +++ #rustflags.extend(["-C", "prefer-dynamic"]) +++ +++ os.makedirs(cargo_home, exist_ok=True) +++ with open(os.path.join(cargo_home, 'config.toml'), "w") as fp: +++ fp.write("""[source.crates-io] +++replace-with = "dh-cargo-registry" +++ +++[source.dh-cargo-registry] +++directory = "{0}" +++ +++[build] +++rustflags = {1} +++ +++[profile.release] +++debug = true +++""".format(registry_path, repr(rustflags))) +++ +++ return 0 +++ +++def install(destdir, cratespec, host_rust_type, crate_in_registry, install_prefix, *args): +++ crate, version = cratespec.rsplit("_", 1) +++ log(f"installing into destdir '{destdir}' prefix '{install_prefix}'") +++ install_target = destdir + install_prefix +++ logrun(["env", "RUST_BACKTRACE=1", +++ # set CARGO_TARGET_DIR so build products are saved in target/ +++ # normally `cargo install` deletes them when it exits +++ "CARGO_TARGET_DIR=" + in_cwd("target"), +++ "/usr/bin/cargo"] + list(args) + +++ ([crate, "--vers", version] if crate_in_registry else ["--path", in_cwd()]) + +++ ["--root", install_target], check=True) +++ logrun(["rm", "-f", "%s/.crates.toml" % install_target]) +++ logrun(["rm", "-f", "%s/.crates2.json" % install_target]) +++ +++ # if there was a custom build output, symlink it to debian/cargo_out_dir +++ # hopefully cargo will provide a better solution in future https://github.com/rust-lang/cargo/issues/5457 +++ r = logrun('''ls -td "target/%s/release/build/%s"-*/out 2>/dev/null | head -n1''' +++ % (host_rust_type, crate), shell=True, stdout=subprocess.PIPE).stdout +++ r = r.decode("utf-8").rstrip() +++ if r: +++ logrun(["ln", "-sfT", "../%s" % r, "debian/cargo_out_dir"], check=True) +++ return 0 +++ +++def main(*args): +++ cargo_home = os.getenv("CARGO_HOME", "") +++ if not cargo_home.endswith("/debian/cargo_home"): +++ os.execv("/usr/bin/cargo", ["cargo"] + list(args)) +++ +++ if any(f not in os.environ for f in FLAGS): +++ raise ValueError(f'not all of {FLAGS} set; did you call dpkg-buildflags?') +++ +++ if any(f not in os.environ for f in ARCHES): +++ raise ValueError(f'not all of {ARCHES} set; did you include architecture.mk?') +++ +++ build_options = os.getenv("DEB_BUILD_OPTIONS", "").split() +++ build_profiles = os.getenv("DEB_BUILD_PROFILES", "").split() +++ +++ parallel = [] +++ lto = "" +++ for o in build_options: +++ if o.startswith("parallel="): +++ parallel = ["-j" + o[9:]] +++ elif o.startswith("optimize="): +++ opt_arg = o[9:] +++ for arg in opt_arg.split(","): +++ if opt_arg == "-lto": +++ lto = "false" +++ elif opt_arg == "+lto": +++ lto = "\"thin\"" +++ else: +++ log(f"WARNING: unhandled optimization flag: {opt_arg}") +++ +++ nodoc = "nodoc" in build_options or "nodoc" in build_profiles +++ nocheck = "nocheck" in build_options or "nocheck" in build_profiles +++ +++ # note this is actually the "build target" type, see rustc's README.Debian +++ # for full details of the messed-up terminology here +++ host_rust_type = os.getenv("DEB_HOST_RUST_TYPE", "") +++ host_gnu_type = os.getenv("DEB_HOST_GNU_TYPE", "") +++ +++ log(f'options = {build_options}, profiles = {build_profiles}, parallel = {parallel}, lto = {lto}') +++ log(f'rust_type = {host_rust_type}, gnu_type = {host_gnu_type}') +++ +++ if "RUSTFLAGS" in os.environ: +++ # https://github.com/rust-lang/cargo/issues/6338 +++ log('unsetting RUSTFLAGS for rust-lang/cargo#6338; add them to .cargo/config.toml') +++ extra_rustflags = os.environ["RUSTFLAGS"] +++ del os.environ["RUSTFLAGS"] +++ else: +++ extra_rustflags = "" +++ +++ if args[0] == "prepare-debian": +++ registry = args[1] +++ link_from_system = False +++ if len(args) > 2 and args[2] == "--link-from-system": +++ link_from_system = True +++ return prepare_debian(cargo_home, registry, +++ os.environ["DEB_CARGO_CRATE"], host_gnu_type, +++ os.getenv("LDFLAGS", "").split(), link_from_system, extra_rustflags) +++ +++ newargs = [] +++ subcmd = None +++ for a in args: +++ if (subcmd is None) and (a in ("build", "rustc", "doc", "test", "bench", "install")): +++ subcmd = a +++ newargs.extend(["-Zavoid-dev-deps", a, "--verbose", "--verbose"] + +++ parallel + ["--target", host_rust_type]) +++ if lto: +++ newargs.append("--config") +++ newargs.append(f"profile.release.lto={lto}") +++ elif (subcmd is None) and (a == "clean"): +++ subcmd = a +++ newargs.extend([a, "--verbose", "--verbose"]) +++ else: +++ newargs.append(a) +++ +++ if subcmd is not None and "--verbose" in newargs and "--quiet" in newargs: +++ newargs.remove("--quiet") +++ +++ if nodoc and subcmd == "doc": +++ return 0 +++ if nocheck and subcmd in ("test", "bench"): +++ return 0 +++ +++ +++ if subcmd == "clean": +++ logrun(["env", "RUST_BACKTRACE=1", "/usr/bin/cargo"] + list(newargs), check=True) +++ if os.path.exists(cargo_home): +++ shutil.rmtree(cargo_home) +++ return 0 +++ +++ cargo_config = os.path.join(cargo_home, 'config.toml') +++ if not os.path.exists(cargo_config): +++ raise ValueError(f'does not exist: {cargo_config}, did you run `cargo prepare-debian `?') +++ +++ if subcmd == "install": +++ return install(os.getenv("DESTDIR", ""), +++ os.environ["DEB_CARGO_CRATE"], +++ host_rust_type, +++ os.getenv("DEB_CARGO_CRATE_IN_REGISTRY", "") == "1", +++ os.getenv("DEB_CARGO_INSTALL_PREFIX", "/usr"), +++ *newargs) +++ else: +++ return logrun(["env", "RUST_BACKTRACE=1", "/usr/bin/cargo"] + list(newargs)).returncode +++ +++if __name__ == "__main__": +++ sys.exit(main(*sys.argv[1:])) diff --cc debian/bin/rust-lld index 0000000000,0000000000,0000000000..7443a39db5 new file mode 100755 --- /dev/null +++ b/debian/bin/rust-lld @@@@ -1,0 -1,0 -1,0 +1,9 @@@@ +++#!/bin/bash +++# Wrapper around lld that strips away -Wl, which it doesn't recognise. +++# We need this for the wasm32 tests, where we have generic RUSTFLAGS that +++# includes LDFLAGS from dpkg-buildflags which assumes a GCC linker. +++# +++# However the tests fail for other reasons, namely we can't build rustdoc +++# (which runs the tests) in wasm32 yet. So this is just WIP at the moment, +++# it is not expect to work nor to be installed on user machines. +++exec /usr/bin/lld-19 "${@/#-Wl,/}" diff --cc debian/cargo-doc.docs index 0000000000,0000000000,0000000000..1d0004d699 new file mode 100644 --- /dev/null +++ b/debian/cargo-doc.docs @@@@ -1,0 -1,0 -1,0 +1,2 @@@@ +++usr/share/doc/cargo/reference +++usr/share/doc/cargo/book diff --cc debian/cargo.bash-completion index 0000000000,0000000000,0000000000..e3d4b28571 new file mode 100644 --- /dev/null +++ b/debian/cargo.bash-completion @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++etc/bash_completion.d/cargo cargo diff --cc debian/cargo.install index 0000000000,0000000000,0000000000..4895cfba0e new file mode 100644 --- /dev/null +++ b/debian/cargo.install @@@@ -1,0 -1,0 -1,0 +1,4 @@@@ +++usr/bin/cargo +++debian/scripts/* usr/share/cargo/scripts +++debian/bin/cargo usr/share/cargo/bin +++usr/share/zsh/site-functions/_cargo usr/share/zsh/vendor-completions diff --cc debian/cargo.manpages index 0000000000,0000000000,0000000000..585a8af0fe new file mode 100644 --- /dev/null +++ b/debian/cargo.manpages @@@@ -1,0 -1,0 -1,0 +1,2 @@@@ +++usr/share/man/man1/cargo-*.1 +++usr/share/man/man1/cargo.1 diff --cc debian/changelog index 0000000000,0000000000,0000000000..0ff29de706 new file mode 100644 --- /dev/null +++ b/debian/changelog @@@@ -1,0 -1,0 -1,0 +1,2455 @@@@ +++rustc (1.85.0+dfsg3-1) unstable; urgency=medium +++ +++ * backport fix for gix-features CVE-2025-31130 +++ * rust-lldb: fix lldb version (Closes: #1100950) +++ * cherry-pick fix for crossbeam-channel RUSTSEC-2025-0024 +++ +++ -- Fabian Grünbichler Thu, 24 Apr 2025 17:47:57 +0200 +++ +++rustc (1.85.0+dfsg2-3) unstable; urgency=medium +++ +++ * baseline: enable SSE2 for i386 build (Closes: #1095862) +++ +++ -- Fabian Grünbichler Fri, 11 Apr 2025 13:40:09 +0200 +++ +++rustc (1.85.0+dfsg2-2) unstable; urgency=medium +++ +++ * Upload to unstable +++ +++ -- Fabian Grünbichler Fri, 04 Apr 2025 18:24:50 +0200 +++ +++rustc (1.85.0+dfsg2-1) experimental; urgency=medium +++ +++ * d/control: bump libgit2-dev version +++ * vendor git2, git2-curl and libgit2-sys bindings for libgit2 1.9 +++ * cargo: bump git2* dependencies +++ +++ -- Fabian Grünbichler Mon, 17 Mar 2025 06:54:23 +0100 +++ +++rustc (1.85.0+dfsg1-1) unstable; urgency=medium +++ +++ * New (stable) upstream release. +++ +++ -- Fabian Grünbichler Thu, 20 Feb 2025 19:23:02 +0100 +++ +++rustc (1.85.0~beta.9+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release 1.85.0~beta999 +++ * build docs with -j1 to make them reproducible +++ * build: make windows libstd build opt-in +++ +++ -- Fabian Grünbichler Mon, 17 Feb 2025 13:24:42 +0100 +++ +++rustc (1.84.0+dfsg1-2) unstable; urgency=medium +++ +++ * revert upstream commit breaking cross builds +++ * rust-llvm: ship symlink to llvm-objcopy instead of copy of binary +++ +++ -- Fabian Grünbichler Tue, 21 Jan 2025 11:38:15 +0100 +++ +++rustc (1.84.0+dfsg1-1) unstable; urgency=medium +++ +++ * rust-analyzer: fix build on mips64el +++ * fix hurd build (Closes: #1093125) +++ * d/control: add Conflicts with rustup (Closes: #1093031) +++ +++ -- Fabian Grünbichler Thu, 16 Jan 2025 20:46:05 +0100 +++ +++rustc (1.84.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ * Stop building wasm32-wasi target +++ * Build rust-analyzer (Closes: #1052319) +++ * rust-llvm: ship rust-objcopy helper +++ * rust-all: add rust-llvm and rust-analyzer packages +++ +++ -- Fabian Grünbichler Sat, 11 Jan 2025 16:04:50 +0100 +++ +++rustc (1.83.0+dfsg1-1) unstable; urgency=medium +++ +++ * upload to unstable +++ * fix/ignore some test failures +++ +++ -- Fabian Grünbichler Wed, 04 Dec 2024 18:07:54 +0100 +++ +++rustc (1.83.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release +++ * config: disable downloading LLVM from CI +++ * blake3: adapt build.rs to skip bundled C code +++ * remove libstd shared library +++ +++ -- Fabian Grünbichler Sun, 01 Dec 2024 16:53:12 +0100 +++ +++rustc (1.82.0+dfsg1-2) unstable; urgency=medium +++ +++ * build: re-enable clang-rt on armel/armhf +++ * build: drop workaround for riscv64/loong64 +++ +++ -- Fabian Grünbichler Tue, 29 Oct 2024 13:18:35 +0100 +++ +++rustc (1.82.0+dfsg1-1) unstable; urgency=medium +++ +++ * rust-src: ship original Cargo.lock file to fix rust-analyzer for libstd, +++ and allow `-Z build-std` +++ * build: disable profiler support on armel/armhf +++ * build: extend riscv64 workaround to loong64 +++ * cargo wrapper: fix LTO position in argument lists (Closes: #1086025) +++ +++ -- Fabian Grünbichler Fri, 25 Oct 2024 16:21:38 +0200 +++ +++rustc (1.82.0+dfsg1-1~exp3) experimental; urgency=medium +++ +++ * conditonalize riscv64 workaround +++ * fix or disable more broken tests +++ +++ -- Fabian Grünbichler Wed, 23 Oct 2024 20:39:25 +0200 +++ +++rustc (1.82.0+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * fix some test breakage +++ * riscv64: unbreak compiler_builtin build +++ +++ -- Fabian Grünbichler Wed, 23 Oct 2024 18:03:55 +0200 +++ +++rustc (1.82.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release +++ * New wasi-libc version 0.0~git20240708.3f43ea9 +++ * switch to LLVM 19 +++ * set LLVM profiler RT path via config +++ * update bootstrap git commit info patch +++ * re-instate bootstrap test config patch +++ * make rust-src cleanup more robust +++ +++ -- Fabian Grünbichler Tue, 22 Oct 2024 11:17:40 +0200 +++ +++rustc (1.81.0+dfsg1-2) unstable; urgency=medium +++ +++ * use system libz-sys even when cross-building (Closes: #1084754) +++ * drop no longer needed loongarch64 patch +++ * add temporary Breaks to force migration of libgit2 +++ +++ -- Fabian Grünbichler Tue, 08 Oct 2024 14:34:41 +0200 +++ +++rustc (1.81.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable +++ +++ -- Fabian Grünbichler Sat, 05 Oct 2024 15:54:29 +0200 +++ +++rustc (1.81.0+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * source: duplicate lintian overrides to make ftp-masters happy +++ * cargo wrapper: fix LTO handling (Closes: #1079071) +++ +++ -- Fabian Grünbichler Sat, 05 Oct 2024 15:54:14 +0200 +++ +++rustc (1.81.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ [ Fabian Grünbichler ] +++ * New upstream release +++ * switch to LLVM 18 +++ * bump libgit2 to 1.8.1 +++ * build and install wasm-component-ld for wasm-wasip2 +++ * make rust-llvm arch:any +++ +++ [ Samuel Thibault ] +++ * add hurd-amd64 support +++ +++ -- Fabian Grünbichler Wed, 11 Sep 2024 08:26:59 +0200 +++ +++rustc (1.80.1+dfsg1-1) unstable; urgency=medium +++ +++ * upload to unstable +++ +++ -- Fabian Grünbichler Wed, 04 Sep 2024 20:13:19 +0200 +++ +++rustc (1.80.1+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream point release +++ +++ -- Fabian Grünbichler Fri, 09 Aug 2024 12:03:01 +0200 +++ +++rustc (1.80.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release +++ * Build wasi-p2 target +++ * Use packaged libonig +++ * Update lintian overrides +++ * d/control: drop Build-Conflicts on gdb-minimal +++ +++ -- Fabian Grünbichler Sun, 04 Aug 2024 10:38:52 +0200 +++ +++rustc (1.79.0+dfsg1-2) unstable; urgency=medium +++ +++ [ Fabian Grünbichler ] +++ * build: remove more cache files (Closes: #1074373) +++ * d/control: update Standards-Version to 4.7.0 +++ +++ [ Samuel Thibault ] +++ * Avoid hurd-stuck test +++ +++ -- Fabian Grünbichler Thu, 27 Jun 2024 14:30:53 +0200 +++ +++rustc (1.79.0+dfsg1-1) unstable; urgency=medium +++ +++ * cargo wrapper: switch to config.toml +++ * cargo wrapper: ensure debug symbols are not stripped +++ * add missing rustfmt dependency (Closes: #1074290) +++ +++ -- Fabian Grünbichler Wed, 26 Jun 2024 08:36:52 +0200 +++ +++rustc (1.79.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release +++ * New wasi-libc version (SDK 22) +++ * config: adapt to new change tracking mechanism +++ +++ -- Fabian Grünbichler Tue, 25 Jun 2024 09:40:12 +0200 +++ +++rustc (1.78.0+dfsg1-2) unstable; urgency=medium +++ +++ * unbreak loongson64 build +++ +++ -- Fabian Grünbichler Mon, 24 Jun 2024 08:25:58 +0200 +++ +++rustc (1.78.0+dfsg1-1) unstable; urgency=medium +++ +++ [ Samuel Thibault ] +++ * debian/patches/vendor/u-hurd-rustix.patch: Fix Hurd build. +++ +++ -- Fabian Grünbichler Mon, 24 Jun 2024 07:36:42 +0200 +++ +++rustc (1.78.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release +++ * cherry-pick rmake v2 test fix +++ +++ -- Fabian Grünbichler Fri, 21 Jun 2024 12:33:24 +0200 +++ +++rustc (1.77.2+dfsg1-1) unstable; urgency=medium +++ +++ [ Fabian Grünbichler ] +++ * fix builds on porter boxes +++ * d/control: tighten libgit2-dev dependency +++ +++ [ Samuel Thibault ] +++ * fix hurd patches +++ +++ -- Fabian Grünbichler Thu, 20 Jun 2024 13:40:40 +0200 +++ +++rustc (1.77.2+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ * config: don't attempt to optimize compiler-rt +++ +++ -- Fabian Grünbichler Wed, 19 Jun 2024 12:44:26 +0200 +++ +++rustc (1.76.0+dfsg1-1) unstable; urgency=medium +++ +++ [ Samuel Thibault ] +++ * Fix hurd build: +++ - debian/patches/vendor/u-hurd-gix-index-2.patch +++ - debian/patches/vendor/u-hurd-gix-index.patch +++ +++ -- Fabian Grünbichler Wed, 19 Jun 2024 07:51:49 +0200 +++ +++rustc (1.76.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release (Closes: #1073068) +++ * switch to gbp pq and topics for patches +++ * adapt rebasing script to patch changes +++ * d/control: add libsqlite3-dev to B-D +++ * doc: fix rust-by-example theme +++ +++ -- Fabian Grünbichler Fri, 14 Jun 2024 14:50:17 +0200 +++ +++rustc (1.75.0+dfsg1-5) unstable; urgency=medium +++ +++ [ Samuel Thibault ] +++ * hurd-i386 build fixes: +++ - d/patches/u-hurd-backtrace.patch +++ - d/patches/u-hurd-getrandom.patch +++ - d/patches/u-hurd-libc.3.patch +++ - d/patches/u-hurd-libc.4.patch +++ - d/patches/u-hurd-libloading-0.7.4.patch +++ - d/patches/u-hurd-socket2.patch +++ - d/patches/u-hurd-tests.patch +++ +++ [ Fabian Grünbichler ] +++ * hurd: also skip problematic run-make test +++ * powerpc: disable test running into timeout (Closes: #1072897) +++ * d/control: replace non-ASCII apostrophe (Closes: #1072926) +++ * stage0: drop mips64el from default list +++ +++ [ Rob Shearman ] +++ * fix get-stage0.py +++ +++ -- Fabian Grünbichler Wed, 12 Jun 2024 17:33:10 +0200 +++ +++rustc (1.75.0+dfsg1-4) unstable; urgency=medium +++ +++ * d/rules: fix comparison (unbreak 32-bit builds) +++ +++ -- Fabian Grünbichler Thu, 06 Jun 2024 10:25:40 +0200 +++ +++rustc (1.75.0+dfsg1-3) unstable; urgency=medium +++ +++ * d/rules: fix variable typo +++ * fix changelog +++ +++ -- Fabian Grünbichler Thu, 06 Jun 2024 09:16:53 +0200 +++ +++rustc (1.75.0+dfsg1-1) unstable; urgency=medium +++ +++ * d/rules: switch low-mem check to cover all 32-bits archs +++ +++ -- Fabian Grünbichler Thu, 06 Jun 2024 08:14:17 +0200 +++ +++rustc (1.75.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ [ Fabian Grünbichler ] +++ * New upstream release (Closes: #1068008) +++ * fix cross-building (thanks John Paul Adrian Glaubitz!) +++ +++ [ Samuel Thibault ] +++ * rules: Use 32bit limitations workaround on !linux as well +++ +++ +++ -- Fabian Grünbichler Tue, 04 Jun 2024 21:24:09 +0200 +++ +++rustc (1.74.1+dfsg1-1) unstable; urgency=medium +++ +++ * dwz: bump limit to avoid s390x build failures +++ +++ -- Fabian Grünbichler Thu, 30 May 2024 11:25:53 +0200 +++ +++rustc (1.74.1+dfsg1-1~exp1) experimental; urgency=medium +++ +++ [ Fabian Grünbichler ] +++ * New upstream release +++ +++ [ Samuel Thibault ] +++ * architecture.mk: Adapt to llvm/rust's hurd naming +++ * rules: Disable profiling on Hurd ports, llvm does not provide it yet +++ * rules: Set the number of expected failures on Hurd ports +++ +++ -- Fabian Grünbichler Wed, 29 May 2024 11:24:48 +0200 +++ +++rustc (1.73.0+dfsg1-1) unstable; urgency=medium +++ +++ * libstd-rust-1.73: fix ldconfig trigger +++ +++ -- Fabian Grünbichler Tue, 28 May 2024 17:06:58 +0200 +++ +++rustc (1.73.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * new upstream release +++ * switch to LLVM 17 +++ * update wasi-libc to ~git20230821.ec4566b +++ * cargo: remove cargo-credential-1password helper binary +++ +++ -- Fabian Grünbichler Mon, 27 May 2024 22:20:44 +0200 +++ +++rustc (1.72.1+dfsg1-1) unstable; urgency=medium +++ +++ * upload to unstable +++ +++ -- Fabian Grünbichler Mon, 27 May 2024 13:28:20 +0200 +++ +++rustc (1.72.1+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * patches: apply rustix fixup to all versions +++ +++ -- Fabian Grünbichler Mon, 27 May 2024 10:20:22 +0200 +++ +++rustc (1.72.1+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release +++ * Update wasi-libc to ~git20230621.7018e24 +++ * Allow more test failures on loong64, and less on riscv64 (Closes: 1071707) +++ +++ -- Fabian Grünbichler Thu, 23 May 2024 21:16:03 +0200 +++ +++rustc (1.71.1+dfsg1-2) unstable; urgency=medium +++ +++ * d/control: fix package names in B+R (Closes: #1071242) +++ +++ -- Fabian Grünbichler Fri, 17 May 2024 08:38:11 +0200 +++ +++rustc (1.71.1+dfsg1-1) unstable; urgency=medium +++ +++ * upload to unstable +++ +++ -- Fabian Grünbichler Thu, 16 May 2024 21:46:58 +0200 +++ +++rustc (1.71.1+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * d/control: properly B+R old rustc packages (Closes: #1071005) +++ +++ -- Fabian Grünbichler Wed, 15 May 2024 07:21:42 +0200 +++ +++rustc (1.71.1+dfsg1-1~exp1) experimental; urgency=medium +++ +++ [ Fabian Grünbichler ] +++ * New upstream release (Closes: #1069019) +++ * d/control: tighten cargo versions (Closes: #1029007) +++ * d/control: remove B-D on cmake-3 (Closes: #1067109) +++ * d/control: re-enable git-using tests +++ * rust-doc: fix references to cargo-doc (Closes: #969210, #1063390) +++ * rust-src: ship Cargo.lock (Closes: #1057736) +++ * d/control: add libssl and prefer curl with openssl (Closes: #962508) +++ * d/control: move LLVM symlinks to own package (Closes: #1021868) +++ +++ [ Rob Shearman ] +++ * Support finding llvm-profdata & llvm-cov with cargo-binutils +++ +++ -- Fabian Grünbichler Wed, 08 May 2024 18:48:48 +0200 +++ +++rustc (1.70.0+dfsg2-1) unstable; urgency=medium +++ +++ * upload to unstable +++ +++ -- Fabian Grünbichler Sat, 04 May 2024 13:38:10 +0200 +++ +++rustc (1.70.0+dfsg2-1~exp3) experimental; urgency=medium +++ +++ * d/rules: fix last package cache removal +++ +++ -- Fabian Grünbichler Fri, 03 May 2024 17:02:14 +0200 +++ +++rustc (1.70.0+dfsg2-1~exp2) experimental; urgency=medium +++ +++ * d/rules: allow removal of package cache to fail +++ * autopkgtest: disable full build test +++ +++ -- Fabian Grünbichler Fri, 03 May 2024 15:10:49 +0200 +++ +++rustc (1.70.0+dfsg2-1~exp1) experimental; urgency=medium +++ +++ [ liushuyu ] +++ * d/*: initial merge of cargo into rustc source package (Closes: #1054658) +++ +++ [ Fabian Grünbichler ] +++ * update libgit2 +++ * cargo: sync test disabling changes +++ * adapt to current rustc/cargo version +++ * cargo: actually install, not just build +++ * add extra component tarball +++ * scripts/guess-crate-copyright: switch to python3-toml +++ * d/check-orig-suspicious.sh: remove duplicate comment stripping +++ * d/check-orig-suspicious.sh: support extra tar ball +++ * fix autopkgtest control file +++ * update d/copyright +++ * extend lintian overrides +++ +++ -- Fabian Grünbichler Fri, 03 May 2024 09:27:25 +0200 +++ +++rustc (1.70.0+dfsg1-9) unstable; urgency=medium +++ +++ * temporarily skip git(-cli) tests +++ +++ -- Fabian Grünbichler Mon, 25 Mar 2024 17:47:08 +0100 +++ +++rustc (1.70.0+dfsg1-8.1) unstable; urgency=medium +++ +++ * Non-maintainer upload +++ * Binary upload to rebootstrap on armel +++ +++ -- Emanuele Rocca Thu, 21 Mar 2024 10:52:23 +0000 +++ +++rustc (1.70.0+dfsg1-8) unstable; urgency=medium +++ +++ * d/control: switch to libllvm16t64 +++ * d/control: switch to pkgconf +++ * d/rules: fix make warning in filter invocation +++ +++ -- Fabian Grünbichler Fri, 15 Mar 2024 17:18:37 +0100 +++ +++rustc (1.70.0+dfsg1-7) unstable; urgency=medium +++ +++ * profiler: disable on mips64el for now, it's buggy +++ +++ -- Fabian Grünbichler Thu, 15 Feb 2024 06:52:19 +0100 +++ +++rustc (1.70.0+dfsg1-6) unstable; urgency=medium +++ +++ [ Fabian Grünbichler ] +++ * fix bootstrap helpers (Closes: #1060808) +++ * rustix: patch both versions to fix racy build +++ +++ [ Andres Salomon ] +++ * Fix source_orig-stage0 bootstrapping process to actually include all +++ architectures (closes: #1021711). +++ * Run 'd/rules clean' after running make_orig-stage0_tarball.sh so that the +++ suggestion to rebuild the .dsc actually works. +++ * Don't allow upstream's bootstrap.py to delete .cargo/ directory. +++ +++ [ Fabian Grünbichler ] +++ * stage0: use current release architectures as default +++ * disable LLVM profiler support on sparc64 (Closes: #1061125) +++ +++ -- Fabian Grünbichler Sun, 11 Feb 2024 20:59:19 +0100 +++ +++rustc (1.70.0+dfsg1-5) unstable; urgency=medium +++ +++ * adapt LLVM_PROFILER_RT_LIB path +++ +++ -- Fabian Grünbichler Mon, 15 Jan 2024 08:16:35 +0100 +++ +++rustc (1.70.0+dfsg1-4) unstable; urgency=medium +++ +++ * fix libclang-rt-16-dev Build-dep +++ +++ -- Fabian Grünbichler Mon, 15 Jan 2024 07:00:08 +0100 +++ +++rustc (1.70.0+dfsg1-3) unstable; urgency=medium +++ +++ [ Andres Salomon ] +++ * Enable profiler builtin and backport u-profiler.patch (closes: #1043311). +++ * Build-dep on libclang-rt-16-dev. +++ +++ -- Fabian Grünbichler Sun, 14 Jan 2024 20:06:29 +0100 +++ +++rustc (1.70.0+dfsg1-2) unstable; urgency=medium +++ +++ * Upload to unstable +++ +++ -- Fabian Grünbichler Sat, 30 Dec 2023 14:52:00 +0100 +++ +++rustc (1.70.0+dfsg1-2~exp1) experimental; urgency=medium +++ +++ * riscv: disable split debuginfo support +++ +++ -- Fabian Grünbichler Sat, 02 Dec 2023 11:19:31 +0100 +++ +++rustc (1.70.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable +++ +++ -- Fabian Grünbichler Wed, 20 Sep 2023 20:18:40 +0200 +++ +++rustc (1.70.0+dfsg1-1~exp3) experimental; urgency=medium +++ +++ * more test fixes +++ +++ -- Fabian Grünbichler Fri, 15 Sep 2023 15:07:01 +0200 +++ +++rustc (1.70.0+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * don't remove replace-version-placeholder from workspace +++ * disable download tests +++ * fix x86 tests checking for SSE2 +++ +++ -- Fabian Grünbichler Fri, 15 Sep 2023 10:10:52 +0200 +++ +++rustc (1.70.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release +++ * switch to LLVM 16 +++ * properly drop more components +++ * rust-src: fix path of installed example config +++ * fix lintian overrides +++ * update d/copyright +++ +++ -- Fabian Grünbichler Thu, 14 Sep 2023 09:07:26 +0200 +++ +++rustc (1.69.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable +++ +++ -- Fabian Grünbichler Wed, 13 Sep 2023 13:57:58 +0200 +++ +++rustc (1.69.0+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * config: also enable rustdoc explicitly +++ * bump wasi-libc to revert stack protection (Closes: #1051815) +++ +++ -- Fabian Grünbichler Wed, 13 Sep 2023 08:02:53 +0200 +++ +++rustc (1.69.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ [ Eric Long ] +++ * New upstream release +++ * Manually include `rust-analyzer-proc-macro-srv` (again) +++ +++ [ Fabian Grünbichler ] +++ * add libc with "extra_traits" to feature sync patch +++ * update d/copyright +++ * update lintian overrides +++ +++ -- Fabian Grünbichler Tue, 12 Sep 2023 10:17:15 +0200 +++ +++rustc (1.68.2+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable +++ +++ -- Fabian Grünbichler Sun, 10 Sep 2023 19:22:53 +0200 +++ +++rustc (1.68.2+dfsg1-1~exp1) experimental; urgency=medium +++ +++ [ Eric Long ] +++ * New upstream version 1.68.2+dfsg1 +++ * Update patches to adapt to upstream test path change +++ +++ [ Fabian Grünbichler ] +++ * Update wasi-libc to 4362b18 +++ * Update doc path to fix linkcheck +++ * Update d/copyright +++ * Update lintian overrides +++ * Update privacy breach removal (github badge) +++ * Bump Standards-Version to 4.6.2 +++ +++ [Helmut Grohne] +++ * Fix FTCBFS: Do not pass host CFLAGS to the build compiler +++ (Closes: #1050975) +++ +++ -- Fabian Grünbichler Wed, 02 Aug 2023 13:17:47 +0200 +++ +++rustc (1.67.1+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable +++ +++ -- Fabian Grünbichler Sun, 03 Sep 2023 19:58:53 +0200 +++ +++rustc (1.67.1+dfsg1-1~exp1) experimental; urgency=medium +++ +++ [ Fabian Grünbichler ] +++ * update/rebase/drop patches (based on work by Blair Noctis) +++ * d/copyright: add missing statements +++ * add missing lintian overrides for test cases +++ +++ [ Blair Noctis ] +++ * New upstream release +++ * Cherry-pick sysroot detection fix +++ * Update d/copyright for some vendored +++ +++ -- Fabian Grünbichler Fri, 07 Jul 2023 10:01:33 +0200 +++ +++rustc (1.66.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable +++ +++ -- Fabian Grünbichler Tue, 27 Jun 2023 17:12:20 +0200 +++ +++rustc (1.66.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ [ Blair Noctis ] +++ * New upstream version 1.66.0+dfsg1 +++ * Drop outdated patches +++ * Work around incorrect config handling (picking up initial rustc) when +++ running tests +++ +++ -- Fabian Grünbichler Sun, 23 Apr 2023 20:45:41 +0200 +++ +++rustc (1.65.0+dfsg1-2) unstable; urgency=medium +++ +++ * Team upload +++ * Source-only upload +++ +++ -- Jeremy Bícha Mon, 26 Jun 2023 17:16:27 -0400 +++ +++rustc (1.65.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable +++ +++ -- Fabian Grünbichler Tue, 20 Jun 2023 20:16:50 +0200 +++ +++rustc (1.65.0+dfsg1-1~exp3) experimental; urgency=medium +++ +++ * d/rules: fix typo in mipsel workaround +++ +++ -- Fabian Grünbichler Sun, 12 Mar 2023 08:54:15 +0100 +++ +++rustc (1.65.0+dfsg1-1~exp2) experimental; urgency=medium +++ +++ [ Fabian Grünbichler ] +++ * d/control: add myself to Uploaders +++ * cherry-pick fix for failing backtrace test +++ * bump mipsel test failure allowance to work around broken gdb 13.1 +++ * drop duplicate lintian override +++ +++ -- Fabian Grünbichler Sat, 11 Mar 2023 18:50:19 +0100 +++ +++rustc (1.65.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ [ Fabian Grünbichler ] +++ * New upstream version 1.65.0+dfsg1 +++ * switch to LLVM-15 +++ * cherry-pick fix for compiletest with rpath=false +++ * add overrides for rust-analyzer test data +++ +++ -- Fabian Gruenbichler Wed, 15 Feb 2023 20:12:05 +0100 +++ +++rustc (1.64.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable +++ * Add myself to Uploaders +++ +++ -- Fabian Grünbichler Mon, 12 Jun 2023 18:36:56 +0200 +++ +++rustc (1.64.0+dfsg1-1~exp4) experimental; urgency=medium +++ +++ [ John Paul Adrian Glaubitz ] +++ * fix sparc64 rustix build (Closes: #1030053) +++ +++ -- Fabian Gruenbichler Tue, 31 Jan 2023 19:55:48 +0100 +++ +++rustc (1.64.0+dfsg1-1~exp3) experimental; urgency=medium +++ +++ [ Simon Chopin ] +++ * cherry-pick riscv64 fix from ubuntu +++ +++ -- Fabian Gruenbichler Fri, 20 Jan 2023 20:48:11 +0100 +++ +++rustc (1.64.0+dfsg1-1~exp2) experimental; urgency=medium +++ +++ [ Fabian Grünbichler ] +++ * d/prune-unused-deps: unify cargo update calls +++ * fix rustix on arches requiring outline building +++ * fix libstd-rust-dev-windows lintian override +++ * fix compiler_builtins linkage on arm(el) +++ * add compiler_builtins sync fallbacks for arm(el) +++ * fix panicking lldb check on armel +++ +++ -- Fabian Gruenbichler Wed, 11 Jan 2023 17:22:16 +0100 +++ +++rustc (1.64.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release +++ * d/rules: auto_clean: preserve .cargo/config.toml +++ * d/rules: also clear bootstrap/rust-analyzer Cargo.lock +++ * d/rules: extend privacy-breach removal +++ * ship rust-analyzer-proc-macro-srv binary +++ +++ -- Fabian Gruenbichler Thu, 08 Dec 2022 09:17:59 +0100 +++ +++rustc (1.63.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable (Closes: #1018859) +++ +++ [ Pietro Albini ] +++ * clarify the licensing of the mpsc implementation +++ +++ -- Fabian Gruenbichler Wed, 07 Dec 2022 17:29:00 +0100 +++ +++rustc (1.63.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release +++ +++ -- Fabian Gruenbichler Tue, 15 Nov 2022 19:47:53 +0100 +++ +++rustc (1.62.1+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable +++ * Fix armhf build +++ +++ -- Fabian Gruenbichler Mon, 31 Oct 2022 14:19:34 +0100 +++ +++rustc (1.62.1+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release +++ +++ -- Fabian Gruenbichler Fri, 28 Oct 2022 11:35:48 +0200 +++ +++rustc (1.61.0+dfsg1-2) unstable; urgency=medium +++ +++ [ Ximin Luo] +++ * Improve cross-building documentation +++ +++ [ Adrian Bunk ] +++ * Disable kernel_user_helpers on armel (duplicate symbols) +++ * Increase allowed failures on armel/mips64el/ppc64 (Closes: #1020860) +++ +++ [ Fabian Grünbichler ] +++ * cherry-pick patches from Ubuntu +++ * fix rebuild of 1.61 with 1.61 +++ +++ -- Fabian Gruenbichler Mon, 10 Oct 2022 20:19:05 +0200 +++ +++rustc (1.61.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable (Closes: #1020394) +++ +++ -- Sylvestre Ledru Thu, 22 Sep 2022 09:00:21 +0200 +++ +++rustc (1.61.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release +++ +++ * Switch to LLVM-14 (Closes: #1017656) +++ +++ -- Fabian Gruenbichler Wed, 07 Sep 2022 17:33:04 +0200 +++ +++rustc (1.60.0+dfsg1-1) unstable; urgency=medium +++ +++ * Ignore more test failures on mips64el for lack of inline assembly support. +++ +++ * Add i386 and x32 to list of "low-memory" architectures requiring build +++ workarounds. +++ +++ -- Fabian Gruenbichler Mon, 5 Sep 2022 10:03:18 +0200 +++ +++rustc (1.60.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Fabian Gruenbichler Thu, 14 Jul 2022 13:08:16 +0200 +++ +++rustc (1.59.0+dfsg1-2) unstable; urgency=medium +++ +++ * Backport a patch for riscv64. +++ * Ignore some test failures on armhf due to regression in GDB 11.2. +++ +++ -- Ximin Luo Tue, 21 Jun 2022 11:06:16 +0100 +++ +++rustc (1.59.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ +++ -- Ximin Luo Wed, 11 May 2022 14:11:46 +0100 +++ +++rustc (1.59.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ [ Fabian Grünbichler ] +++ * New upstream release +++ +++ -- Ximin Luo Tue, 29 Mar 2022 14:32:01 +0100 +++ +++rustc (1.58.1+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ +++ -- Ximin Luo Tue, 29 Mar 2022 12:23:46 +0100 +++ +++rustc (1.58.1+dfsg1-1~exp1) experimental; urgency=medium +++ +++ [ Fabian Gruenbichler ] +++ * New upstream release. +++ +++ -- Ximin Luo Tue, 08 Mar 2022 11:32:29 +0000 +++ +++rustc (1.57.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. (Closes: #1005203) +++ +++ -- Ximin Luo Tue, 08 Mar 2022 10:51:18 +0000 +++ +++rustc (1.57.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ [ Simon Chopin ] +++ * d/p/d-bootstrap-rustflags.patch: remove the warnings bit, use the option +++ "deny-warnings = false" in d/config.toml.in instead +++ +++ [ Fabian Grünbichler ] +++ * Fix CVE-2022-21658 - std::fs::remove_dir_all TOCTOU symlink issue +++ * New upstream release. (Closes: #1005203) +++ +++ -- Fabian Grünbichler Thu, 03 Feb 2022 19:14:04 +0100 +++ +++rustc (1.56.0+dfsg1-2) unstable; urgency=medium +++ +++ * Update to debhelper 13. +++ +++ -- Ximin Luo Fri, 22 Oct 2021 23:29:14 +0100 +++ +++rustc (1.56.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release. +++ * Support terse and verbose DEB_BUILD_OPTIONS. +++ * Support -Z gcc-ld=lld via symlinks. +++ * Fix RUSTC_SYSROOT in rust-gdb and rust-lldb, thanks James McCoy. +++ +++ -- Ximin Luo Fri, 22 Oct 2021 18:54:49 +0100 +++ +++rustc (1.56.0~beta.4+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Include upstream patch for x32 support. (Closes: #993855) +++ * Update to LLVM 13. +++ +++ -- Ximin Luo Fri, 15 Oct 2021 10:44:35 +0100 +++ +++rustc (1.56.0~beta.4+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Thu, 14 Oct 2021 22:50:58 +0100 +++ +++rustc (1.55.0+dfsg1-2) unstable; urgency=medium +++ +++ * Actually work around segfault on ppc64el. +++ * Fix FTBFS on armhf caused by GCC 11 changes. +++ +++ -- Ximin Luo Thu, 14 Oct 2021 00:36:15 +0100 +++ +++rustc (1.55.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Bump test failures-allowed on s390x to 40. +++ * Work around a segfault on ppc64el +++ +++ -- Ximin Luo Wed, 13 Oct 2021 22:06:15 +0100 +++ +++rustc (1.55.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Sat, 09 Oct 2021 03:22:08 +0100 +++ +++rustc (1.54.0+dfsg1-3) unstable; urgency=medium +++ +++ * Fix links to cargo-doc. +++ +++ -- Ximin Luo Sat, 09 Oct 2021 11:46:08 +0100 +++ +++rustc (1.54.0+dfsg1-2) unstable; urgency=medium +++ +++ * Fix some more build & test failures. +++ +++ -- Ximin Luo Sat, 09 Oct 2021 03:12:35 +0100 +++ +++rustc (1.54.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Re-enable backported patch for armhf & reset its allowed-failures. +++ * Add compatibility patch for cargo 0.47. +++ * Ignore more spurious test failures, and filed upstream. +++ * Bump powerpc allowed-failures to 180 at the request of ports maintainers. +++ +++ -- Ximin Luo Sat, 09 Oct 2021 00:24:37 +0100 +++ +++rustc (1.54.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Wed, 06 Oct 2021 10:37:55 +0100 +++ +++rustc (1.53.0+dfsg1-4) unstable; urgency=medium +++ +++ * Ignore some hanging test regressions on non-release arches powerpc, ppc64. +++ +++ -- Ximin Luo Wed, 06 Oct 2021 19:24:11 +0100 +++ +++rustc (1.53.0+dfsg1-3) unstable; urgency=medium +++ +++ * Disable patch that was backported incorrectly. +++ * Temporarily increase armhf allowed-failures to 12. +++ +++ -- Ximin Luo Wed, 06 Oct 2021 19:01:54 +0100 +++ +++rustc (1.53.0+dfsg1-2) unstable; urgency=medium +++ +++ * Fix some test failures. +++ +++ -- Ximin Luo Wed, 06 Oct 2021 10:29:03 +0100 +++ +++rustc (1.53.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Update mips patches, disable a test as our workaround makes it invalid. +++ * Temporarily ignore some tests that fail on big-endian. +++ +++ -- Ximin Luo Tue, 05 Oct 2021 23:19:31 +0100 +++ +++rustc (1.53.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. (Closes: #986803) +++ * Honour parallel option in DEB_BUILD_OPTIONS. (Closes: #993871) +++ +++ -- Ximin Luo Sat, 02 Oct 2021 12:46:49 +0100 +++ +++rustc (1.52.1+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Reorganise dependencies, move optional rustc deps to rust-all. +++ +++ -- Ximin Luo Wed, 29 Sep 2021 20:05:55 +0100 +++ +++rustc (1.52.1+dfsg1-1~exp3) experimental; urgency=medium +++ +++ * Update to LLVM 12. +++ +++ -- Ximin Luo Wed, 19 May 2021 17:52:44 +0100 +++ +++rustc (1.52.1+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Fix rust-clippy dependency on libstd-rust-* +++ +++ -- Ximin Luo Sat, 15 May 2021 22:42:38 +0100 +++ +++rustc (1.52.1+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Sat, 15 May 2021 15:21:27 +0100 +++ +++rustc (1.52.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Fri, 07 May 2021 20:38:38 +0100 +++ +++rustc (1.52.0~beta.3+dfsg1-1~exp4) experimental; urgency=medium +++ +++ * Fix issue with dh_missing --fail-missing +++ +++ -- Ximin Luo Thu, 06 May 2021 01:52:30 +0100 +++ +++rustc (1.52.0~beta.3+dfsg1-1~exp3) experimental; urgency=medium +++ +++ * Fix Makefile addition syntax. +++ +++ -- Ximin Luo Wed, 05 May 2021 22:24:22 +0100 +++ +++rustc (1.52.0~beta.3+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Install the rust-llvm-dwp symlink. +++ +++ -- Ximin Luo Wed, 05 May 2021 22:20:13 +0100 +++ +++rustc (1.52.0~beta.3+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Mon, 26 Apr 2021 12:31:27 +0100 +++ +++rustc (1.51.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Install the rust-llvm-dwp symlink. +++ * Bump ppc64 allowed-failures to 24. +++ +++ -- Ximin Luo Sun, 19 Sep 2021 19:48:33 +0100 +++ +++rustc (1.51.0+dfsg1-1~exp3) experimental; urgency=medium +++ +++ * Restore patch, not actually fixed upstream. +++ +++ -- Ximin Luo Mon, 26 Apr 2021 16:17:12 +0100 +++ +++rustc (1.51.0+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Drop patch fixed upstream. +++ * Fix bootstrap with self version. +++ +++ -- Ximin Luo Mon, 26 Apr 2021 12:26:43 +0100 +++ +++rustc (1.51.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ * Enable 32-bit windows support. +++ +++ -- Ximin Luo Mon, 12 Apr 2021 11:04:36 +0100 +++ +++rustc (1.50.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ +++ -- Ximin Luo Sat, 18 Sep 2021 11:45:21 +0100 +++ +++rustc (1.50.0+dfsg1-1~exp4) experimental; urgency=medium +++ +++ * Fix more tests with a backported upstream PR. +++ +++ -- Ximin Luo Mon, 12 Apr 2021 01:51:22 +0100 +++ +++rustc (1.50.0+dfsg1-1~exp3) experimental; urgency=medium +++ +++ * Fix cross-compile to windows using same-version stage0. +++ +++ -- Ximin Luo Sun, 11 Apr 2021 13:52:41 +0100 +++ +++rustc (1.50.0+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Fix tests, fix s390x breakage. +++ +++ -- Ximin Luo Fri, 09 Apr 2021 16:54:20 +0100 +++ +++rustc (1.50.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Mon, 05 Apr 2021 21:30:18 +0100 +++ +++rustc (1.49.0+dfsg1-2) unstable; urgency=medium +++ +++ * Backport upstream PR 85807 to fix powerpc test issues. +++ +++ -- Ximin Luo Sat, 18 Sep 2021 11:33:09 +0100 +++ +++rustc (1.49.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ +++ -- Ximin Luo Sat, 28 Aug 2021 10:48:11 +0100 +++ +++rustc (1.49.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Mon, 05 Apr 2021 14:59:34 +0100 +++ +++rustc (1.49.0~beta.4+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Sun, 20 Dec 2020 23:26:55 +0000 +++ +++rustc (1.48.0+dfsg1-2) unstable; urgency=medium +++ +++ * Enable +xgot on mips64*, see upstream #52108 for details. +++ +++ -- Ximin Luo Sun, 20 Dec 2020 18:52:10 +0000 +++ +++rustc (1.48.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Tue, 01 Dec 2020 19:57:48 +0000 +++ +++rustc (1.48.0~beta.8+dfsg1-1~exp3) experimental; urgency=medium +++ +++ * Update u-update-version-check.patch +++ +++ -- Ximin Luo Fri, 13 Nov 2020 01:36:31 +0000 +++ +++rustc (1.48.0~beta.8+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Disable copy_file_range optimisation for now, see upstream #78979. +++ * Ignore some other minor tests, bugs have been filed upstream. +++ +++ -- Ximin Luo Thu, 12 Nov 2020 23:51:53 +0000 +++ +++rustc (1.48.0~beta.8+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Wed, 11 Nov 2020 12:31:18 +0000 +++ +++rustc (1.47.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release. +++ * Update to LLVM 11. +++ * Ignore more tests on big-endian. +++ +++ -- Ximin Luo Sat, 07 Nov 2020 21:21:03 +0000 +++ +++rustc (1.47.0~beta.2+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Sat, 05 Sep 2020 16:11:16 +0100 +++ +++rustc (1.46.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Sat, 29 Aug 2020 16:54:36 +0100 +++ +++rustc (1.46.0~beta.2+dfsg1-1~exp5) experimental; urgency=medium +++ +++ * Fix rust-gdb install path. (Closes: #968279) +++ * Drop powerpc allowed-failures to 12. (Closes: #955774) +++ * Update d-fix-mips64el-bootstrap.patch for newer LLVM. +++ +++ -- Ximin Luo Fri, 14 Aug 2020 23:45:25 +0100 +++ +++rustc (1.46.0~beta.2+dfsg1-1~exp4) experimental; urgency=medium +++ +++ * Move cross-linker Depends to Recommends - for cross-compiling support +++ libraries should never hard-depend on toolchains. This also allows us to +++ add the usual M-A annotations for libraries. +++ +++ -- Ximin Luo Sun, 09 Aug 2020 18:16:16 +0100 +++ +++rustc (1.46.0~beta.2+dfsg1-1~exp3) experimental; urgency=medium +++ +++ * Drop "-cross" suffix from libstd naming, after discussion with Helmut +++ Grohne. Since libstd-rust-dev-wasm-cross is not yet in stable and only +++ has 4 installed users, we do not retain a migration package. +++ +++ -- Ximin Luo Sun, 09 Aug 2020 14:27:54 +0100 +++ +++rustc (1.46.0~beta.2+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Add support for cross-compiling to windows. See README.Debian for details. +++ Currently only 64-bit works, we are waiting on #540782 for 32-bit. +++ +++ -- Ximin Luo Sun, 09 Aug 2020 03:52:34 +0100 +++ +++rustc (1.46.0~beta.2+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Fri, 07 Aug 2020 00:15:46 +0100 +++ +++rustc (1.45.0+dfsg1-2) unstable; urgency=medium +++ +++ * Add some more big-endian test patches. +++ * Backport some patches to fix some testsuite ICEs. +++ +++ -- Ximin Luo Thu, 06 Aug 2020 21:11:39 +0100 +++ +++rustc (1.45.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ +++ -- Ximin Luo Wed, 05 Aug 2020 21:41:39 +0100 +++ +++rustc (1.45.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Mon, 27 Jul 2020 17:45:24 +0100 +++ +++rustc (1.44.1+dfsg1-3) unstable; urgency=medium +++ +++ * Fix patch for line numbers on little-endian arches. +++ +++ -- Ximin Luo Tue, 28 Jul 2020 21:51:36 +0100 +++ +++rustc (1.44.1+dfsg1-2) unstable; urgency=medium +++ +++ * Ignore tests that assume little-endian on big-endian arches. +++ See upstream #74829 for details. +++ +++ -- Ximin Luo Tue, 28 Jul 2020 21:20:24 +0100 +++ +++rustc (1.44.1+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Backport a typenum fix for i386. +++ * Work around upstream #74786 involving debuginfo maps. +++ +++ -- Ximin Luo Mon, 27 Jul 2020 13:15:20 +0100 +++ +++rustc (1.44.1+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Sat, 04 Jul 2020 18:04:42 +0100 +++ +++rustc (1.43.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Bump LLVM B-D version for some backported fixes affecting rustc. +++ +++ -- Ximin Luo Sun, 05 Jul 2020 15:06:52 +0100 +++ +++rustc (1.43.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * Drop sparc64 workaround. (Closes: #956413) +++ * Drop stack-gap workaround for old kernels and rust versions. +++ * New upstream release. +++ +++ -- Ximin Luo Mon, 27 Apr 2020 13:09:20 +0100 +++ +++rustc (1.42.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ +++ -- Ximin Luo Fri, 10 Apr 2020 11:33:25 +0100 +++ +++rustc (1.42.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ [ Fabian Grünbichler ] +++ * Team upload. +++ * New upstream release. +++ +++ -- Ximin Luo Sat, 04 Apr 2020 16:06:03 +0100 +++ +++rustc (1.41.1+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ +++ -- Ximin Luo Fri, 03 Apr 2020 23:41:11 +0100 +++ +++rustc (1.41.1+dfsg1-1~exp1) experimental; urgency=medium +++ +++ [ Ximin Luo ] +++ * More python 2 -> 3 fixes. +++ * Enable the wasm32-wasi target for code that needs a "real" libstd. +++ * Don't strip static rlibs. This sometimes breaks wasm, and more generally +++ the stripped debuginfo is actually totally lost rather than being moved +++ into the -dbgsym packages. Shared libraries are unaffected and work. +++ * Allow 180 failing tests on riscv64, none were actually run last time. +++ +++ [ Fabian Grünbichler ] +++ * New upstream release. +++ +++ -- Ximin Luo Mon, 09 Mar 2020 00:31:34 +0000 +++ +++rustc (1.40.0+dfsg1-5) unstable; urgency=medium +++ +++ * More python 2 -> 3 fixes. +++ * Allow 24 failing tests on riscv64. +++ * Reenable debuginfo for rustc, not just libstd. +++ * Reenable backtraces during tests. +++ +++ -- Ximin Luo Sun, 05 Jan 2020 13:35:46 +0000 +++ +++rustc (1.40.0+dfsg1-4) unstable; urgency=medium +++ +++ * Experimental riscv64 support. +++ +++ -- Ximin Luo Sat, 04 Jan 2020 05:40:11 +0000 +++ +++rustc (1.40.0+dfsg1-3) unstable; urgency=medium +++ +++ * Work around upstream #59264 again. :/ +++ +++ -- Ximin Luo Fri, 03 Jan 2020 22:05:16 +0000 +++ +++rustc (1.40.0+dfsg1-2) unstable; urgency=medium +++ +++ * Fix more internal build scripts so they use python3. +++ * Don't add -L/usr/lib/llvm when cross-compiling. (Closes: #941783) +++ +++ -- Ximin Luo Fri, 03 Jan 2020 20:18:46 +0000 +++ +++rustc (1.40.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Ignore new test failing on arm that also fails in previous versions. +++ +++ -- Ximin Luo Sun, 29 Dec 2019 22:17:04 +0000 +++ +++rustc (1.40.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Wed, 25 Dec 2019 00:09:24 +0000 +++ +++rustc (1.39.0+dfsg1-4) unstable; urgency=medium +++ +++ * Update to LLVM 9. (Closes: #946886) +++ +++ -- Ximin Luo Mon, 23 Dec 2019 03:21:02 +0000 +++ +++rustc (1.39.0+dfsg1-3) unstable; urgency=medium +++ +++ * Fix mips patch involving mxgot for new RUSTFLAGS behaviour. +++ +++ -- Ximin Luo Fri, 06 Dec 2019 22:18:53 +0000 +++ +++rustc (1.39.0+dfsg1-2) unstable; urgency=medium +++ +++ * Include reproducibility patch for compiler-builtins. +++ * Use python3 instead of python to run rustbuild. (Closes: #938422) +++ * Expand d-ignore-error-detail-diff.patch for unfixed upstream #53081. +++ +++ -- Ximin Luo Thu, 05 Dec 2019 22:51:41 +0000 +++ +++rustc (1.39.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Sat, 30 Nov 2019 22:20:48 +0000 +++ +++rustc (1.38.0+dfsg1-2) unstable; urgency=medium +++ +++ * Fix building with rustc 1.38.0 +++ * Fix building with cargo 0.40.0 +++ +++ -- Ximin Luo Fri, 29 Nov 2019 00:05:16 +0000 +++ +++rustc (1.38.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Tue, 26 Nov 2019 14:41:46 +0000 +++ +++rustc (1.37.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Fix a typo in debian/rules regex causing FTBFS on some arches. +++ +++ -- Ximin Luo Thu, 05 Sep 2019 00:06:23 -0700 +++ +++rustc (1.37.0+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Support cross-compiling to wasm32. (Closes: #903110) +++ To do that, install the libstd-rust-dev-wasm32-cross package and give +++ --target wasm32-unknown-unknown. +++ * Drop dependency on system compiler-rt, these new versions of rustc +++ actually don't need it at all. +++ +++ -- Ximin Luo Thu, 29 Aug 2019 09:00:03 -0700 +++ +++rustc (1.37.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ * Use system compiler-rt. +++ +++ -- Ximin Luo Sun, 25 Aug 2019 03:06:33 -0700 +++ +++rustc (1.36.0+dfsg1-2) unstable; urgency=medium +++ +++ * Set CARGO_HOME to debian/cargo_home (instead of $HOME/.cargo) as newer +++ versions of cargo must take a file lock that has to exist. +++ +++ -- Ximin Luo Wed, 17 Jul 2019 18:25:06 -0700 +++ +++rustc (1.36.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ +++ -- Ximin Luo Tue, 16 Jul 2019 20:27:55 -0700 +++ +++rustc (1.36.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Sat, 13 Jul 2019 12:42:05 -0700 +++ +++rustc (1.35.0+dfsg1-1) unstable; urgency=medium +++ +++ * Add entry in 1.34.2+dfsg1-1 to note that it uses LLVM 7. +++ * Add entry in 1.35.0+dfsg1-1~exp2 to note that it uses LLVM 8. +++ * Fix ICE on sparc64 by including upstream PR #61881. +++ +++ -- Ximin Luo Sat, 13 Jul 2019 10:30:35 -0700 +++ +++rustc (1.35.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * Don't use system compiler-rt, it's not ready yet. +++ * Update to LLVM 8. +++ * New upstream release. +++ +++ -- Ximin Luo Sun, 09 Jun 2019 23:20:52 -0700 +++ +++rustc (1.34.2+dfsg1-1) unstable; urgency=medium +++ +++ * Don't use system compiler-rt, there are issues with that for now. +++ * Use LLVM 7 for the Debian buster release. +++ +++ -- Ximin Luo Wed, 29 May 2019 21:52:37 -0700 +++ +++rustc (1.34.2+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Fix doc build, add version 1 compat mode hack for mdBook 2. +++ * Use system compiler-rt from libclang-common-*-dev. +++ +++ -- Ximin Luo Fri, 24 May 2019 00:39:59 -0700 +++ +++rustc (1.34.2+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * Ensure Cargo.toml is in rust-src. +++ * New upstream release. +++ * Update to LLVM 8. +++ +++ -- Ximin Luo Sun, 19 May 2019 02:40:02 -0700 +++ +++rustc (1.33.0+dfsg1-2) unstable; urgency=medium +++ +++ * Add Fedora patches. +++ * Bump i386 allowed test failures to 12. +++ +++ -- Ximin Luo Sat, 18 May 2019 12:18:25 -0700 +++ +++rustc (1.33.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Fix build on mips, flags needed whitespace massaging. +++ * Drop obsolete patches. +++ +++ -- Ximin Luo Fri, 17 May 2019 21:04:20 -0700 +++ +++rustc (1.33.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ [ Hiroaki Nakamura ] +++ * Delete obsolete patch. +++ +++ [ Sylvestre Ledru ] +++ * Update compiler-rt patch. +++ * Improve build-related docs a bit. +++ +++ -- Ximin Luo Mon, 29 Apr 2019 19:50:48 -0700 +++ +++rustc (1.32.0+dfsg1-3) unstable; urgency=medium +++ +++ * Conditionally-apply u-compiletest.patch based on stage0 compiler. +++ * Fix syntax error in d/rules compiletest check. +++ +++ -- Ximin Luo Sun, 17 Mar 2019 16:40:05 -0700 +++ +++rustc (1.32.0+dfsg1-2) unstable; urgency=medium +++ +++ * More verbose logging during builds. +++ * Fix compiletest compile error, and check log has at least 1 pass. +++ +++ -- Ximin Luo Sun, 17 Mar 2019 12:52:57 -0700 +++ +++rustc (1.32.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Sun, 27 Jan 2019 22:02:48 -0800 +++ +++rustc (1.32.0~beta.2+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Note that this upstream version already Closes: #917191. +++ * Backport other upstream fixes. (Closes: #916818, #917000, #917192). +++ +++ -- Ximin Luo Tue, 01 Jan 2019 15:26:57 -0800 +++ +++rustc (1.32.0~beta.2+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ * Drop obsolete d-sparc64-dont-pack-spans.patch +++ +++ -- Ximin Luo Sun, 16 Dec 2018 13:48:25 -0800 +++ +++rustc (1.31.0+dfsg1-2) unstable; urgency=medium +++ +++ * Bump mips mipsel s390x allowed-failures to 24. +++ +++ -- Ximin Luo Sun, 16 Dec 2018 14:34:44 -0800 +++ +++rustc (1.31.0+dfsg1-1) unstable; urgency=medium +++ +++ * Revert debuginfo patches, they're not ready yet. +++ +++ -- Ximin Luo Sun, 16 Dec 2018 09:58:06 -0800 +++ +++rustc (1.31.0+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Drop redundant patches. +++ * Fix line numbers in some test-case patches. +++ * Backport an updated patch for gdb 8.2. +++ +++ -- Ximin Luo Sat, 15 Dec 2018 13:52:26 -0800 +++ +++rustc (1.31.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Fri, 14 Dec 2018 21:30:56 -0800 +++ +++rustc (1.31.0~beta.19+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Filter LLVM build flags to not be stupid. +++ +++ -- Ximin Luo Sat, 01 Dec 2018 12:17:52 -0800 +++ +++rustc (1.31.0~beta.19+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Thu, 29 Nov 2018 22:29:16 -0800 +++ +++rustc (1.31.0~beta.4+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Merge changes from Debian unstable. +++ +++ -- Ximin Luo Tue, 06 Nov 2018 19:45:26 -0800 +++ +++rustc (1.31.0~beta.4+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ * Drop old maintainers from Uploaders. +++ +++ -- Ximin Luo Sun, 04 Nov 2018 19:00:16 -0800 +++ +++rustc (1.30.0+dfsg1-2) unstable; urgency=medium +++ +++ * Increase FAILURES_ALLOWED for mips mipsel to 20. +++ * Set debuginfo-only-std = false for 32-bit powerpc architectures. +++ +++ -- Ximin Luo Fri, 02 Nov 2018 01:42:36 -0700 +++ +++rustc (1.30.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. (Closes: #881845) +++ * Increase FAILURES_ALLOWED for mips architectures. +++ * Set debuginfo-only-std = false for mips architectures. +++ +++ -- Ximin Luo Thu, 01 Nov 2018 10:05:52 -0700 +++ +++rustc (1.30.0+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Disable debuginfo-gdb tests relating to enums. These will be fixed in an +++ upcoming version, see upstream #54614 for details. +++ +++ -- Ximin Luo Wed, 31 Oct 2018 00:02:25 -0700 +++ +++rustc (1.30.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * Actually don't build docs in an arch-only build. +++ * Add mips patch, hopefully closes #881845 but let's see. +++ * New upstream release. +++ +++ -- Ximin Luo Tue, 30 Oct 2018 22:05:59 -0700 +++ +++rustc (1.30.0~beta.7+dfsg1-1~exp3) experimental; urgency=medium +++ +++ * Do the necessary bookkeeping for the LLVM update. +++ +++ -- Ximin Luo Wed, 26 Sep 2018 23:29:18 -0700 +++ +++rustc (1.30.0~beta.7+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Tweak test failure rules: armel <= 8, ppc64 <= 12. +++ * Update to LLVM 7. +++ +++ -- Ximin Luo Wed, 26 Sep 2018 21:43:30 -0700 +++ +++rustc (1.30.0~beta.7+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Sun, 23 Sep 2018 10:40:30 -0700 +++ +++rustc (1.29.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Drop d-armel-disable-kernel-helpers.patch as a necessary part of the +++ fix to #906520, so it is actually fixed. +++ * Backport a patch to fix the rand crate on powerpc. (Closes: #909400) +++ * Lower the s390x allowed failures back to 25. +++ +++ -- Ximin Luo Sun, 23 Sep 2018 10:16:53 -0700 +++ +++rustc (1.29.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ * Include patch for armel atomics. (Closes: #906520) +++ * Update to latest Standards-Version; no changes required. +++ +++ -- Ximin Luo Thu, 20 Sep 2018 22:33:20 -0700 +++ +++rustc (1.28.0+dfsg1-3) unstable; urgency=medium +++ +++ * Team upload. +++ +++ [ Ximin Luo ] +++ * More sparc64 fixes, and increase allowed-test-failures there to 180. +++ +++ [ Julien Cristau ] +++ * Don't use pentium4 as i686 baseline (closes: #908561) +++ +++ -- Julien Cristau Tue, 11 Sep 2018 15:54:27 +0200 +++ +++rustc (1.28.0+dfsg1-2) unstable; urgency=medium +++ +++ * Switch on verbose-tests to restore the old pre-1.28 behaviour, and restore +++ old failure-counting logic. +++ * Allow 50 test failures on s390x, restored failure-counting logic avoids +++ more double-counts. +++ +++ -- Ximin Luo Sun, 05 Aug 2018 02:18:10 -0700 +++ +++rustc (1.28.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release. +++ * Add patches from Fedora to fix some test failures. +++ * Ignore a failure testing specific error output, under investigation. +++ * Allow 100 test failures on s390x, should be reducible later with LLVM 7. +++ * Temporary fix for mips64el bootstrap. +++ * Be even more verbose during the build. +++ * Update to latest Standards-Version. +++ +++ -- Ximin Luo Sat, 04 Aug 2018 23:04:41 -0700 +++ +++rustc (1.28.0~beta.14+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Update test-failure counting logic. +++ * Fix version constraints for Recommends: cargo. +++ * Add patch to fix sparc64 CABI. +++ +++ -- Ximin Luo Fri, 27 Jul 2018 04:26:52 -0700 +++ +++rustc (1.28.0~beta.14+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ * Update to latest Standards-Version; no changes required. +++ +++ -- Ximin Luo Wed, 25 Jul 2018 03:11:11 -0700 +++ +++rustc (1.27.2+dfsg1-1) unstable; urgency=medium +++ +++ [ Sylvestre Ledru ] +++ * Update of the alioth ML address. +++ +++ [ Ximin Luo ] +++ * Fail the build if our version contains ~exp and we are not releasing to +++ experimental, this has happened by accident a few times already. +++ * Allow 36 and 44 test failures on armel and s390x respectively. +++ * New upstream release. +++ +++ -- Ximin Luo Tue, 24 Jul 2018 21:35:56 -0700 +++ +++rustc (1.27.1+dfsg1-1~exp4) experimental; urgency=medium +++ +++ * Unconditonally prune crate checksums to avoid having to manually prune them +++ whenever we patch the vendored crates. +++ +++ -- Ximin Luo Thu, 19 Jul 2018 14:49:18 -0700 +++ +++rustc (1.27.1+dfsg1-1~exp3) experimental; urgency=medium +++ +++ * Add patch from Fedora to fix rebuild against same version. +++ +++ -- Ximin Luo Thu, 19 Jul 2018 08:52:03 -0700 +++ +++rustc (1.27.1+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Fix some failing tests. +++ +++ -- Ximin Luo Wed, 18 Jul 2018 09:06:44 -0700 +++ +++rustc (1.27.1+dfsg1-1~exp1) unstable; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Fri, 13 Jul 2018 22:58:02 -0700 +++ +++rustc (1.26.2+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release. +++ * Stop ignoring tests that now pass. +++ * Don't ignore tests that still fail, instead raise FAILURES_ALLOWED. +++ This allows us to see the test failures in the build logs, rather than +++ hiding them. +++ +++ -- Ximin Luo Sat, 16 Jun 2018 12:39:59 -0700 +++ +++rustc (1.26.1+dfsg1-3) unstable; urgency=medium +++ +++ * Fix build-dep version range to build against myself. +++ +++ -- Ximin Luo Thu, 31 May 2018 09:25:17 -0700 +++ +++rustc (1.26.1+dfsg1-2) unstable; urgency=medium +++ +++ * Also ignore test_loading_cosine on ppc64el. +++ +++ -- Ximin Luo Wed, 30 May 2018 20:58:46 -0700 +++ +++rustc (1.26.1+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Wed, 30 May 2018 08:18:04 -0700 +++ +++rustc (1.26.0+dfsg1-1~exp4) experimental; urgency=medium +++ +++ * Try alternative patch to ignore x86 stdsimd tests suggested by upstream. +++ * Bump up allowed-test-failures to 8 to account for the fact that we're now +++ double-counting some failures. +++ +++ -- Ximin Luo Tue, 29 May 2018 20:36:56 -0700 +++ +++rustc (1.26.0+dfsg1-1~exp3) experimental; urgency=medium +++ +++ * Ignore some irrelevant tests on ppc64 and non-x86 platforms. +++ +++ -- Ximin Luo Tue, 29 May 2018 09:32:38 -0700 +++ +++rustc (1.26.0+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Add Breaks+Replaces for older libstd-rust-dev with codegen-backends. +++ (Closes: #899180) +++ * Backport some test and packaging fixes from Ubuntu. +++ +++ -- Ximin Luo Tue, 22 May 2018 22:00:53 -0700 +++ +++rustc (1.26.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ * Update to latest Standards-Version; no changes required. +++ * Update doc-base files. (Closes: #876831) +++ +++ -- Ximin Luo Sun, 20 May 2018 03:11:45 -0700 +++ +++rustc (1.25.0+dfsg1-2) unstable; urgency=medium +++ +++ * Add patches for LLVM's compiler-rt to fix bugs on sparc64 and mips64. +++ (Closes: #898982) +++ * Install codegen-backends into rustc rather than libstd-rust-dev. +++ (Closes: #899087) +++ +++ -- Ximin Luo Sat, 19 May 2018 13:10:33 -0700 +++ +++rustc (1.25.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Allow up to 15 test failures on s390x. +++ * Set CARGO_INCREMENTAL=0 on sparc64. +++ +++ -- Ximin Luo Fri, 18 May 2018 01:11:15 -0700 +++ +++rustc (1.25.0+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Install missing codegen-backends. +++ +++ -- Ximin Luo Fri, 06 Apr 2018 14:05:36 -0700 +++ +++rustc (1.25.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ * Update to LLVM 6.0. +++ +++ -- Ximin Luo Sun, 01 Apr 2018 15:59:47 +0200 +++ +++rustc (1.24.1+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Raise allowed-test-failures to 160 on some non-release arches: powerpc, +++ powerpcspe, sparc64, x32. +++ +++ -- Ximin Luo Wed, 07 Mar 2018 20:07:27 +0100 +++ +++rustc (1.24.1+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Steal some patches from Fedora to fix some test failures. +++ * Update debian/patches/u-make-tests-work-without-rpath.patch to try to fix +++ some more test failures. +++ +++ -- Ximin Luo Mon, 05 Mar 2018 16:25:26 +0100 +++ +++rustc (1.24.1+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * More sparc64 CABI fixes. (Closes: #888757) +++ * New upstream release. +++ * Note that s390x baseline was updated in the meantime. (Closes: #851150) +++ * Include Debian-specific patch to disable kernel helpers on armel. +++ (Closes: #891902) +++ * Include missing build-dependencies for pkg.rustc.dlstage0 build profile. +++ (Closes: #891022) +++ * Add architecture.mk mapping for armel => armv5te-unknown-linux-gnueabi. +++ (Closes: #891913) +++ * Enable debuginfo-only-std on armel as well. (Closes: #891961) +++ * Backport upstream patch to support powerpcspe. (Closes: #891542) +++ * Disable full-bootstrap again to work around upstream #48319. +++ +++ -- Ximin Luo Sat, 03 Mar 2018 14:23:29 +0100 +++ +++rustc (1.23.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable. +++ +++ -- Ximin Luo Fri, 19 Jan 2018 11:49:31 +0100 +++ +++rustc (1.23.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ * Update to latest Standards-Version; no changes required. +++ +++ -- Ximin Luo Sun, 14 Jan 2018 00:08:17 +0100 +++ +++rustc (1.22.1+dfsg1-2) unstable; urgency=medium +++ +++ * Fix B-D rustc version so this package can be built using itself. +++ +++ -- Ximin Luo Mon, 01 Jan 2018 14:27:19 +0100 +++ +++rustc (1.22.1+dfsg1-1) unstable; urgency=medium +++ +++ [ Ximin Luo ] +++ * Remove unimportant files that autoload remote resources from rust-src. +++ * Fix more symlinks in rust-doc. +++ * On armhf, only generate debuginfo for libstd and not the compiler itself. +++ This works around buildds running out of memory, see upstream #45854. +++ * Update to latest Standards-Version; no changes required. +++ +++ [ Chris Coulson ] +++ * Fix some test failures that occur because we build rust without an rpath. +++ +++ -- Ximin Luo Mon, 18 Dec 2017 19:46:25 +0100 +++ +++rustc (1.22.1+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release. +++ * Fix symlink target. (Closes: #877276) +++ +++ -- Ximin Luo Sat, 25 Nov 2017 22:29:12 +0100 +++ +++rustc (1.21.0+dfsg1-3) unstable; urgency=medium +++ +++ * Add/fix detection for sparc64, thanks to John Paul Adrian Glaubitz. +++ * Workaround FTBFS when building docs. (Closes: #880262) +++ +++ -- Ximin Luo Mon, 06 Nov 2017 10:03:32 +0100 +++ +++rustc (1.21.0+dfsg1-2) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Fix bootstrapping using 1.21.0, which is more strict about redundant &mut +++ previously used in u-output-failed-commands.patch. +++ * Only allow up to 5 test failures. +++ +++ -- Ximin Luo Wed, 25 Oct 2017 20:27:30 +0200 +++ +++rustc (1.21.0+dfsg1-1) experimental; urgency=medium +++ +++ * New upstream release. +++ * Fix the "install" target for cross-compilations; cross-compiling with +++ sbuild --host=$foreign-arch should work again. +++ * Update to latest Standards-Version; changes: +++ - Priority changed to optional from extra. +++ +++ -- Ximin Luo Tue, 17 Oct 2017 00:42:54 +0200 +++ +++rustc (1.20.0+dfsg1-3) unstable; urgency=medium +++ +++ * Disable jemalloc to fix FTBFS with 1.21 on armhf. +++ +++ -- Ximin Luo Wed, 25 Oct 2017 12:01:19 +0200 +++ +++rustc (1.20.0+dfsg1-2) unstable; urgency=medium +++ +++ * Update changelog entry for 1.20.0+dfsg1-1 to reflect that it was actually +++ and accidentally uploaded to unstable. No harm, no foul. +++ * We are no longer failing the build when tests fail, see NEWS or +++ README.Debian for details. +++ * Bump LLVM requirement to fix some failing tests. +++ +++ -- Ximin Luo Sat, 21 Oct 2017 14:20:17 +0200 +++ +++rustc (1.20.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Sun, 15 Oct 2017 23:30:35 +0200 +++ +++rustc (1.19.0+dfsg3-4) unstable; urgency=medium +++ +++ * Bump LLVM requirement to pull in a fix for a FTBFS on ppc64el. +++ +++ -- Ximin Luo Sun, 15 Oct 2017 21:31:03 +0200 +++ +++rustc (1.19.0+dfsg3-3) unstable; urgency=medium +++ +++ * Fix a trailing whitespace for tidy. +++ +++ -- Ximin Luo Tue, 19 Sep 2017 16:09:41 +0200 +++ +++rustc (1.19.0+dfsg3-2) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Add a patch to print extra information when tests fail. +++ +++ -- Ximin Luo Tue, 19 Sep 2017 12:32:03 +0200 +++ +++rustc (1.19.0+dfsg3-1) experimental; urgency=medium +++ +++ * New upstream release. +++ * Upgrade to LLVM 4.0. (Closes: #873421) +++ * rust-src: install Debian patches as well +++ +++ -- Ximin Luo Fri, 15 Sep 2017 04:02:09 +0200 +++ +++rustc (1.18.0+dfsg1-4) unstable; urgency=medium +++ +++ * Support gperf 3.1. (Closes: #869610) +++ +++ -- Ximin Luo Tue, 25 Jul 2017 23:19:47 +0200 +++ +++rustc (1.18.0+dfsg1-3) unstable; urgency=medium +++ +++ * Upload to unstable. +++ * Disable failing run-make test on armhf. +++ +++ -- Ximin Luo Sat, 22 Jul 2017 20:30:25 +0200 +++ +++rustc (1.18.0+dfsg1-2) experimental; urgency=medium +++ +++ * Update to latest Standards-Version; no changes required. +++ * Change rustc to Multi-Arch: allowed and update Build-Depends with :native +++ annotations. Multi-Arch: foreign is typically for arch-indep packages that +++ might need to satisfy dependency chains of different architectures. Also +++ update instructions on cross-compiling to match this newer situation. +++ * Build debugging symbols for non-libstd parts of rustc. +++ +++ -- Ximin Luo Mon, 17 Jul 2017 23:04:03 +0200 +++ +++rustc (1.18.0+dfsg1-1) experimental; urgency=medium +++ +++ * New upstream release. +++ +++ -- Ximin Luo Tue, 27 Jun 2017 12:51:22 +0200 +++ +++rustc (1.17.0+dfsg2-8) unstable; urgency=medium +++ +++ * Workaround for linux #865549, fix FTBFS on ppc64el. +++ +++ -- Ximin Luo Mon, 17 Jul 2017 13:41:59 +0200 +++ +++rustc (1.17.0+dfsg2-7) unstable; urgency=medium +++ +++ * Show exception traceback in bootstrap.py to examine ppc64el build failure. +++ +++ -- Ximin Luo Wed, 21 Jun 2017 10:46:27 +0200 +++ +++rustc (1.17.0+dfsg2-6) unstable; urgency=medium +++ +++ * Upload to unstable. +++ +++ -- Ximin Luo Wed, 21 Jun 2017 00:24:22 +0200 +++ +++rustc (1.17.0+dfsg2-5) experimental; urgency=medium +++ +++ * More work-arounds for armhf test failures. +++ +++ -- Ximin Luo Fri, 16 Jun 2017 13:27:45 +0200 +++ +++rustc (1.17.0+dfsg2-4) experimental; urgency=medium +++ +++ * Fix arch-indep and arch-dep tests. +++ * Bump the LLVM requirement to fix FTBFS on armhf. +++ +++ -- Ximin Luo Wed, 14 Jun 2017 21:37:16 +0200 +++ +++rustc (1.17.0+dfsg2-3) experimental; urgency=medium +++ +++ * Try to force the real gdb package. Some resolvers like aspcud will select +++ gdb-minimal under some circumstances, but this causes the debuginfo-gdb +++ tests to break. +++ +++ -- Ximin Luo Wed, 14 Jun 2017 00:48:37 +0200 +++ +++rustc (1.17.0+dfsg2-2) experimental; urgency=medium +++ +++ * Support and document cross-compiling of rustc itself. +++ * Document cross-compiling other rust packages such as cargo. +++ * Work around upstream #39015 by disabling those tests rather than by +++ disabling optimisation, which causes FTBFS on 1.17.0 ppc64el. See +++ upstream #42476 and #42532 for details. +++ +++ -- Ximin Luo Tue, 13 Jun 2017 21:13:31 +0200 +++ +++rustc (1.17.0+dfsg2-1) experimental; urgency=medium +++ +++ [ Sylvestre Ledru ] +++ * New upstream release +++ +++ [ Ximin Luo ] +++ * Adapt packaging for rustbuild, the new upstream cargo-based build system. +++ +++ [ Matthijs van Otterdijk ] +++ * Add a binary package, rust-src. (Closes: #846177) +++ * Link to local Debian web resources in the docs, instead of remote ones. +++ +++ -- Ximin Luo Tue, 16 May 2017 18:00:53 +0200 +++ +++rustc (1.16.0+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable so we have something to build 1.17 with. +++ * Update u-ignoretest-powerpc.patch for 1.16. +++ +++ -- Ximin Luo Wed, 19 Apr 2017 22:47:18 +0200 +++ +++rustc (1.16.0+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Don't ignore test failures on Debian unstable. +++ * Re-fix ignoring armhf test, accidentally reverted in previous version. +++ * Try to fix buildd failure by swapping B-D alternatives. +++ +++ -- Ximin Luo Sun, 16 Apr 2017 15:05:47 +0200 +++ +++rustc (1.16.0+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release +++ * u-ignoretest-jemalloc.patch removed (applied upstream) +++ +++ [ Matthias Klose ] +++ * Bootstrap using the rustc version in the archive, on all architectures. +++ * Work around a GCC 4.8 ICE on AArch64. +++ * Use alternative build dependencies on cmake3 and binutils-2.26 for +++ builds on 14.04 LTS (trusty). +++ * debian/make_orig*dl_tarball.sh: Include all Ubuntu architectures. +++ * debian/rules: Ignore test results for now. +++ +++ -- Sylvestre Ledru Thu, 13 Apr 2017 15:24:03 +0200 +++ +++rustc (1.15.1+dfsg1-1) unstable; urgency=medium +++ +++ * Upload to unstable so we have something to build 1.16 with. +++ * Try to fix ignoring atomic-lock-free tests on armhf. +++ +++ -- Ximin Luo Wed, 22 Mar 2017 00:13:27 +0100 +++ +++rustc (1.15.1+dfsg1-1~exp3) experimental; urgency=medium +++ +++ * Ignore atomic-lock-free tests on armhf. +++ * Update ignoretest-armhf_03.patch for newer 1.15.1 behaviour. +++ * Tidy up some other patches to do with ignoring tests. +++ +++ -- Ximin Luo Sun, 12 Mar 2017 04:15:33 +0100 +++ +++rustc (1.15.1+dfsg1-1~exp2) experimental; urgency=medium +++ +++ * Update armhf ignoretest patch. +++ * Bootstrap armhf. (Closes: #809316, #834003) +++ * Bootstrap ppc4el. (Closes: #839643) +++ * Fix rust-lldb symlink. (Closes: #850639) +++ +++ -- Ximin Luo Thu, 02 Mar 2017 23:01:26 +0100 +++ +++rustc (1.15.1+dfsg1-1~exp1) experimental; urgency=medium +++ +++ * New upstream release (won't probably be in stretch). +++ see the 1.4 git branch for the follow up for stable +++ * Call to the test renamed from check-notidy => check +++ * d/p/u-destdir-support.diff: Apply upstream patch to support +++ destdir in the make install (for rustbuild, in later versions) +++ * Overrides the 'binary-or-shlib-defines-rpath' lintian warnings. +++ We need them for now +++ * Refresh of the patches +++ +++ [ Sven Joachim ] +++ * Drop Pre-Depends on multiarch-support. (Closes: #856109) +++ +++ [ Erwan Prioul ] +++ * Fix test and build failures for ppc64el. (Closes: #839643) +++ +++ [ Ximin Luo ] +++ * Disable rustbuild for the time being (as it was in 1.14) and instead +++ bootstrap two new arches, armhf and ppc64el. +++ * Switch back to debhelper 9 to make backporting easier. +++ * Switch Build-Depends on binutils-multiarch back to binutils, the former is +++ no longer needed by the upstream tests. +++ +++ [ Matthias Klose ] +++ * Compatibility fixes and improvements to help work better on Ubuntu. +++ +++ -- Sylvestre Ledru Sun, 26 Feb 2017 21:12:27 +0100 +++ +++rustc (1.14.0+dfsg1-3) unstable; urgency=medium +++ +++ * Fix mips64 Makefile patches. +++ * Don't run arch-dep tests in a arch-indep build. +++ +++ -- Ximin Luo Wed, 04 Jan 2017 21:34:56 +0100 +++ +++rustc (1.14.0+dfsg1-2) unstable; urgency=medium +++ +++ * Update README.Debian, the old one was way out of date. +++ * Detect mips CPUs in ./configure and fill in mips Makefile rules. +++ * Work around jemalloc-related problems in the upstream bootstrapping +++ binaries for arm64, ppc64el, s390x. +++ * Disable jemalloc on s390x - upstream already disable it for some other +++ arches. +++ * Disable jemalloc tests for arches where jemalloc is disabled. +++ * We still expect the following failures: +++ * arm64 should be fixed (i.e. no failures) compared to the previous upload. +++ * armhf will FTBFS due to 'Illegal instruction' and this can only be fixed +++ with the next stable rustc release. +++ * mips mipsel mips64el ppc64 ppc64el s390x will FTBFS due to yet other +++ test failures beyond the ones I fixed above; this upload is only to save +++ me manual work in producing nice reports that exhibit these failures. +++ +++ -- Ximin Luo Thu, 29 Dec 2016 23:00:47 +0100 +++ +++rustc (1.14.0+dfsg1-1) unstable; urgency=medium +++ +++ [ Sylvestre Ledru ] +++ * New upstream release +++ * Update debian/watch +++ +++ [ Ximin Luo ] +++ * Try to bootstrap armhf ppc64 ppc64el s390x mips mipsel mips64el. +++ (Closes: #809316, #834003, #839643) +++ * Make rust-gdb and rust-lldb arch:all packages. +++ * Switch to debhelper 10. +++ +++ -- Ximin Luo Sat, 24 Dec 2016 18:03:03 +0100 +++ +++rustc (1.13.0+dfsg1-2) unstable; urgency=high +++ +++ * Skip macro-stepping test on arm64, until +++ https://github.com/rust-lang/rust/issues/37225 is resolved. +++ +++ -- Luca Bruno Sat, 26 Nov 2016 23:40:14 +0000 +++ +++rustc (1.13.0+dfsg1-1) unstable; urgency=medium +++ +++ [ Sylvestre Ledru ] +++ * New upstream release. +++ +++ [ Ximin Luo ] +++ * Use Debian system jquery instead of upstream's embedded copy. +++ +++ -- Sylvestre Ledru Fri, 11 Nov 2016 13:35:23 +0100 +++ +++rustc (1.12.1+dfsg1-1) unstable; urgency=medium +++ +++ [ Sylvestre Ledru ] +++ * New (minor) upstream release +++ * Missing dependency from rust-lldb to python-lldb-3.8 (Closes: #841833) +++ * Switch to llvm 3.9. (Closes: #841834) +++ +++ [ Ximin Luo ] +++ * Dynamically apply rust-boot-1.12.1-from-1.12.0.diff. +++ This allows us to bootstrap from either 1.11.0 or 1.12.0. +++ * Bump LLVM Build-Depends version to get the backported patches for LLVM +++ #30402 and #29163. +++ * Install debugger_pretty_printers_common to rust-gdb and rust-lldb. +++ (Closes: #841835) +++ +++ -- Ximin Luo Mon, 07 Nov 2016 14:15:14 +0100 +++ +++rustc (1.12.0+dfsg1-2) unstable; urgency=medium +++ +++ * Ignore test run-make/no-duplicate-libs. Fails on i386 +++ * Ignore test run-pass-valgrind/down-with-thread-dtors.rs . Fails on arm64 +++ * I am not switching to llvm 3.9 now because a test freezes. The plan is +++ to silent the warning breaking the build and upload 1.12.1 after +++ +++ -- Sylvestre Ledru Wed, 05 Oct 2016 10:48:01 +0200 +++ +++rustc (1.12.0+dfsg1-1) unstable; urgency=medium +++ +++ * new upstream release +++ - Rebase of the patches and removal of deprecated patches +++ +++ -- Sylvestre Ledru Thu, 29 Sep 2016 20:45:04 +0200 +++ +++rustc (1.11.0+dfsg1-3) unstable; urgency=medium +++ +++ * Fix separate build-arch and build-indep builds. +++ +++ -- Ximin Luo Tue, 13 Sep 2016 12:30:41 +0200 +++ +++rustc (1.11.0+dfsg1-2) unstable; urgency=medium +++ +++ * Fix rebuilding against the current version, by backporting a patch I wrote +++ that was already applied upstream. Should fix the FTBFS that was observed +++ by tests.reproducible-builds.org. +++ * Ignore a failing stdcall test on arm64; should fix the FTBFS there. +++ * Backport a doctest fix I wrote, already applied upstream. +++ +++ -- Ximin Luo Mon, 12 Sep 2016 17:40:12 +0200 +++ +++rustc (1.11.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release +++ * Add versioned binutils dependency. (Closes: #819475, #823540) +++ +++ -- Ximin Luo Wed, 07 Sep 2016 10:31:57 +0200 +++ +++rustc (1.10.0+dfsg1-3) unstable; urgency=medium +++ +++ * Rebuild with LLVM 3.8, same as what upstream are using +++ * Dynamically link against LLVM. (Closes: #832565) +++ +++ -- Ximin Luo Sat, 30 Jul 2016 22:36:41 +0200 +++ +++rustc (1.10.0+dfsg1-2) unstable; urgency=medium +++ +++ * Tentatively support ARM architectures +++ * Include upstream arm64,armel,armhf stage0 compilers (i.e. 1.9.0 stable) +++ in a orig-dl tarball, like how we previously did for amd64,i386. +++ +++ -- Ximin Luo Fri, 22 Jul 2016 15:54:51 +0200 +++ +++rustc (1.10.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release +++ * Add myself to uploaders +++ * Update our build process to bootstrap from the previous Debian rustc stable +++ version by default. See README.Debian for other options. +++ * Update to latest Standards-Version; no changes required. +++ +++ -- Ximin Luo Sun, 17 Jul 2016 03:40:49 +0200 +++ +++rustc (1.9.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release (Closes: #825752) +++ +++ -- Sylvestre Ledru Sun, 29 May 2016 17:57:38 +0200 +++ +++rustc (1.8.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release +++ +++ [ Ximin Luo ] +++ * Fix using XZ for the orig tarball: needs explicit --repack in debian/watch +++ * Drop wno-error patch; applied upstream. +++ +++ -- Sylvestre Ledru Fri, 15 Apr 2016 12:01:45 +0200 +++ +++rustc (1.7.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release +++ +++ -- Sylvestre Ledru Thu, 03 Mar 2016 22:41:24 +0100 +++ +++rustc (1.6.0+dfsg1-3) unstable; urgency=medium +++ +++ * Apply upstream fix to silent a valgrind issue in the test suite +++ (Closes: ##812825) +++ * Add gcc & libc-dev as dependency of rustc to make sure it works +++ out of the box +++ +++ [ Ximin Luo ] +++ * Work around rust bug https://github.com/rust-lang/rust/issues/31529 +++ * Enable optional tests, and add verbosity/backtraces to tests +++ * Use XZ instead of GZ compression (will apply to the next new upload) +++ +++ -- Sylvestre Ledru Tue, 02 Feb 2016 15:08:11 +0100 +++ +++rustc (1.6.0+dfsg1-2) unstable; urgency=medium +++ +++ * mk/rt.mk: Modify upstream code to append -Wno-error rather than trying +++ to remove the string "-Werror". (Closes: #812448) +++ * Disable new gcc-6 "-Wmisleading-indentation" warning, which triggers +++ (incorrectly) on src/rt/miniz.c. (Closes: #811573) +++ * Guard arch-dependent dh_install commands appropriately, fixing +++ arch-indep-only builds. (Closes: #809124) +++ +++ -- Angus Lees Tue, 26 Jan 2016 05:40:14 +1100 +++ +++rustc (1.6.0+dfsg1-1) unstable; urgency=medium +++ +++ * new upstream release +++ +++ [ Ximin Luo ] +++ * Use secure links for Vcs-* fields. +++ +++ -- Sylvestre Ledru Fri, 22 Jan 2016 10:56:08 +0100 +++ +++rustc (1.5.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release +++ - We believe that we should let rust transit to testing +++ (Closes: #786836) +++ * Move away from hash to the same rust naming schema +++ +++ -- Sylvestre Ledru Thu, 10 Dec 2015 17:23:32 +0100 +++ +++rustc (1.4.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release +++ 198068b3 => 1bf6e69c +++ * Update the download url in debian/watch +++ +++ -- Sylvestre Ledru Fri, 30 Oct 2015 09:36:02 +0100 +++ +++rustc (1.3.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release +++ 62abc69f => 198068b3 +++ * jquery updated from 2.1.0 to 2.1.4 +++ +++ [ Ximin Luo ] +++ * Use LLVM 3.7 as upstream does, now that it's released. (Closes: #797626) +++ * Fix debian/copyright syntax mistakes. +++ * Don't Replace/Break previous versions of libstd-rust-* +++ * Check that the libstd-rust-* name in d/control matches upstream. +++ * Several other minor build tweaks. +++ +++ -- Sylvestre Ledru Sat, 19 Sep 2015 14:39:35 +0200 +++ +++rustc (1.2.0+dfsg1-1) unstable; urgency=medium +++ +++ * New upstream release +++ libstd-rust-7d23ff90 => libstd-rust-62abc69f +++ * Add llvm-3.6-tools to the build dep as it is +++ now needed for tests +++ * Fix the Vcs-Browser value +++ +++ -- Sylvestre Ledru Sat, 08 Aug 2015 23:13:44 +0200 +++ +++rustc (1.1.0+dfsg1-3) unstable; urgency=medium +++ +++ * rust-{gdb,lldb} now Replaces pre-split rustc package. +++ Closes: #793433. +++ * Several minor lintian cleanups. +++ +++ -- Angus Lees Fri, 24 Jul 2015 17:47:48 +1000 +++ +++rustc (1.1.0+dfsg1-2) unstable; urgency=medium +++ +++ [ Angus Lees ] +++ * Replace remote Rust logo with local file in HTML docs. +++ * Symlink rust-{gdb,lldb}.1 to {gdb,lldb}.1 manpages. +++ Note that gdb.1 requires the gdb-doc package, and that lldb.1 doesn't +++ exist yet (see #792908). +++ * Restore "Architecture: amd64 i386" filter, mistakenly removed in +++ previous version. Unfortunately the toolchain bootstrap isn't ready +++ to support all Debian archs yet. Closes: #793147. +++ +++ -- Angus Lees Wed, 22 Jul 2015 09:51:08 +1000 +++ +++rustc (1.1.0+dfsg1-1) unstable; urgency=low +++ +++ [ Angus Lees ] +++ * Set SONAME when building dylibs +++ * Split out libstd-rust, libstd-rust-dev, rust-gdb, rust-lldb from rustc +++ - libs are now installed into multiarch-friendly locations +++ - rpath is no longer required to use dylibs (but talk to Debian Rust +++ maintainers before building a package that depends on the dylibs) +++ * Install /usr/share/rustc/architecture.mk, which declares Rust arch +++ triples for Debian archs and is intended to help future Rust packaging +++ efforts. Warning: it may not be complete/accurate yet. +++ * New upstream release (1.1) +++ +++ -- Angus Lees Thu, 16 Jul 2015 14:23:47 +1000 +++ +++rustc (1.0.0+dfsg1-1) unstable; urgency=medium +++ +++ [ Angus Lees ] +++ * New upstream release (1.0!) +++ +++ [ Sylvestre Ledru ] +++ * Fix the watch file +++ * Update of the repack to remove llvm sources +++ +++ -- Sylvestre Ledru Sat, 16 May 2015 08:24:32 +1000 +++ +++rustc (1.0.0~beta.4-1~exp1) experimental; urgency=low +++ +++ [ Angus Lees ] +++ * New upstream release (beta 3) +++ - Drop manpage patch - now included upstream +++ * Replace duplicated compile-time dylibs with symlinks to run-time libs +++ (reduces installed size by ~68MB) +++ +++ [ Sylvestre Ledru ] +++ * New upstream release (beta 4) +++ * Replace two more occurrences of jquery by the package +++ * Repack upstream to remove an LLVM file with a non-DFSG license +++ +++ -- Sylvestre Ledru Wed, 06 May 2015 11:14:30 +0200 +++ +++rustc (1.0.0~alpha.2-1~exp1) experimental; urgency=low +++ +++ [ Angus Lees ] +++ * Patch upstream manpages to address minor troff issues +++ * Make 'debian/rules clean' also clean LLVM source +++ * Rename primary 'rust' binary package to 'rustc' +++ * Fix potential FTBFS: rust-doc requires texlive-fonts-recommended (for +++ pzdr.tfm) +++ * Build against system LLVM +++ +++ [ Sylvestre Ledru ] +++ * New testing release +++ * Renaming of the source package +++ * Set a minimal version for dpkg-dev and debhelper (for profiles) +++ * For now, disable build profiles as they are not supported in Debian +++ * Introduce some changes by Angus Lees +++ - Introduction of build stages +++ - Disable the parallel execution of tests +++ - Improving of the parallel syntax +++ - Use override_dh_auto_build-arch +++ - Use override_dh_auto_build-indep +++ - Better declarations of the doc +++ - Update of the description +++ - Watch file updated (with key check) +++ +++ [ Luca Bruno ] +++ * rules: respect 'nocheck' DEB_BUILD_OPTIONS +++ +++ -- Sylvestre Ledru Sat, 07 Mar 2015 09:25:47 +0100 +++ +++rust (1.0.0~alpha-0~exp1) experimental; urgency=low +++ +++ * Initial package (Closes: #689207) +++ Work done by Luca Bruno, Jordan Justen and Sylvestre Ledru +++ +++ -- Sylvestre Ledru Fri, 23 Jan 2015 15:47:37 +0100 diff --cc debian/check-orig-suspicious.sh index 0000000000,0000000000,0000000000..a168b7866b new file mode 100755 --- /dev/null +++ b/debian/check-orig-suspicious.sh @@@@ -1,0 -1,0 -1,0 +1,25 @@@@ +++#!/bin/bash +++set -e +++ +++ver="$1" +++test -n "$ver" || exit 2 +++dfsg="$2" +++if test -z "$dfsg"; then +++ dfsg=1 +++fi +++ +++SUS_WHITELIST="$(find "${PWD}/debian" -name upstream-tarball-unsuspicious.txt -type f)" +++ +++rm -rf "rustc-${ver/*~*/beta}-src/" +++tar xf "../rustc_$ver+dfsg$dfsg.orig.tar.xz" && cd "rustc-${ver/*~*/beta}-src/" +++if test -f "../../rustc_$ver+dfsg$dfsg.orig-extra.tar.xz" ; then +++ tar xf "../../rustc_$ver+dfsg$dfsg.orig-extra.tar.xz" +++fi +++ +++../debian/scripts/audit-vendor-source \ +++ "$SUS_WHITELIST" \ +++ "Files-Excluded: in debian/copyright and run a repack." \ +++ -m text/x-script.python \ +++ -m application/csv +++ +++echo "Artifacts left in rustc-$ver-src, please remove them yourself." diff --cc debian/config.toml.in index 0000000000,0000000000,0000000000..b399ade572 new file mode 100644 --- /dev/null +++ b/debian/config.toml.in @@@@ -1,0 -1,0 -1,0 +1,100 @@@@ +++change-id = 133207 +++ +++[build] +++submodules = false +++vendor = true +++locked-deps = false +++verbose = VERBOSITY +++profiler = PROFILER +++ +++rustc = "RUST_DESTDIR/usr/bin/rustc" +++cargo = "RUST_DESTDIR/usr/bin/cargo" +++ +++build = "DEB_BUILD_RUST_TYPE" +++host = ["DEB_HOST_RUST_TYPE"] +++target = ["DEB_TARGET_RUST_TYPE"] +++ +++#full-bootstrap = true +++# originally needed to work around #45317 but no longer necessary +++# currently we have to omit it because it breaks #48319 +++ +++# this might get changed later by override_dh_auto_configure-indep +++# we do it this way to avoid spurious rebuilds +++docs = false +++ +++extended = true +++tools = [ +++ "cargo", +++ "clippy", +++ "rust-analyzer", +++ "rust-analyzer-proc-macro-srv", +++ "rustdoc", +++ "rustfmt", +++ "wasm-component-ld", +++] +++ +++# we use pre-built LLVM, so can't optimize compiler-rt +++optimized-compiler-builtins = false +++ +++[install] +++prefix = "/usr" +++ +++[target.DEB_BUILD_RUST_TYPE] +++llvm-config = "LLVM_DESTDIR/usr/lib/llvm-LLVM_VERSION/bin/llvm-config" +++linker = "DEB_BUILD_GNU_TYPE-gcc" +++PROFILER_PATH +++ +++ifelse(DEB_BUILD_RUST_TYPE,DEB_HOST_RUST_TYPE,, +++[target.DEB_HOST_RUST_TYPE] +++llvm-config = "LLVM_DESTDIR/usr/lib/llvm-LLVM_VERSION/bin/llvm-config" +++linker = "DEB_HOST_GNU_TYPE-gcc" +++PROFILER_PATH +++ +++)dnl +++ifelse(DEB_BUILD_RUST_TYPE,DEB_TARGET_RUST_TYPE,,DEB_HOST_RUST_TYPE,DEB_TARGET_RUST_TYPE,, +++[target.DEB_TARGET_RUST_TYPE] +++llvm-config = "LLVM_DESTDIR/usr/lib/llvm-LLVM_VERSION/bin/llvm-config" +++linker = "DEB_TARGET_GNU_TYPE-gcc" +++PROFILER_PATH +++ +++)dnl +++[target.wasm32-wasip1] +++wasi-root = "/usr" +++profiler = false +++[target.wasm32-wasip2] +++wasi-root = "/usr" +++profiler = false +++[target.wasm32-unknown-unknown] +++profiler = false +++ +++ifelse(WINDOWS_ARCH,,, +++[target.WINDOWS_ARCH-pc-windows-gnu] +++profiler = false +++ +++)dnl +++[llvm] +++link-shared = true +++download-ci-llvm = false +++ +++[rust] +++download-rustc = false +++jemalloc = false +++optimize = MAKE_OPTIMISATIONS +++dist-src = false +++ +++channel = "RELEASE_CHANNEL" +++ +++# parallel codegen interferes with reproducibility, see +++# https://github.com/rust-lang/rust/issues/34902#issuecomment-319463586 +++#codegen-units = 0 +++debuginfo-level = 2 +++debuginfo-level-std = 2 +++rpath = false +++# see also d-custom-debuginfo-path.patch +++remap-debuginfo = true +++ +++omit-git-hash = true +++verbose-tests = true +++backtrace-on-ice = true +++ +++deny-warnings = false diff --cc debian/control index 0000000000,0000000000,0000000000..c8b037c2e1 new file mode 100644 --- /dev/null +++ b/debian/control @@@@ -1,0 -1,0 -1,0 +1,468 @@@@ +++Source: rustc +++Section: devel +++Priority: optional +++Maintainer: Debian Rust Maintainers +++Uploaders: +++ Ximin Luo , +++ Sylvestre Ledru , +++ Fabian Grünbichler +++Rules-Requires-Root: no +++# :native annotations are to support cross-compiling, see README.Debian +++Build-Depends: +++ debhelper (>= 9), +++ debhelper-compat (= 13), +++ dpkg-dev (>= 1.17.14), +++ python3:native, +++ cargo:native (>= 1.84.0+dfsg) , +++ rustc:native (>= 1.84.0+dfsg) , +++ rustc:native (<= 1.85.0+dfsg++) , +++ llvm-19-dev:native, +++ llvm-19-tools:native, +++ gcc-mingw-w64-x86-64-posix:native [amd64] , +++ gcc-mingw-w64-i686-posix:native [i386] , +++ libllvm19 (>= 1:19.0.0), +++ libclang-rt-19-dev:native, +++ libclang-rt-19-dev, +++ cmake (>= 3.0), +++# needed by some vendor crates +++ pkgconf:native, +++ pkgconf, +++# this is sometimes needed by rustc_llvm +++ zlib1g-dev:native, +++ zlib1g-dev, +++# used by rust-installer +++ liblzma-dev:native, +++# used by cargo +++ bash-completion, +++ libcurl4-openssl-dev | libcurl4-gnutls-dev, +++ libssh2-1-dev, +++ libssl-dev, +++ libsqlite3-dev, +++ libgit2-dev (>= 1.9), +++ libgit2-dev (<< 1.10~~), +++ libhttp-parser-dev, +++ libonig-dev, +++# test dependencies: +++ binutils (>= 2.26) | binutils-2.26 , +++# temporarily disabled cause of #1066794 / t64 transition +++ git , +++ procps , +++# below are optional tools even for 'make check' +++ gdb (>= 7.12) , +++# Extra build-deps needed for x.py to download stuff in pkg.rustc.dlstage0. +++ curl , +++ ca-certificates , +++Build-Depends-Indep: +++ wasi-libc (>= 0.0~git20241209.574b88d~~) , +++ wasi-libc (<= 0.0~git20241209.574b88d++) , +++ clang-19:native, +++# see #1057780, gdb now Conflicts gdb-minimal +++#Build-Conflicts: gdb-minimal +++Standards-Version: 4.7.0 +++Homepage: http://www.rust-lang.org/ +++Vcs-Git: https://salsa.debian.org/rust-team/rust.git +++Vcs-Browser: https://salsa.debian.org/rust-team/rust +++ +++Package: rustc +++Architecture: any +++Multi-Arch: allowed +++Pre-Depends: ${misc:Pre-Depends} +++Depends: ${shlibs:Depends}, ${misc:Depends}, +++ libstd-rust-dev (= ${binary:Version}), +++ gcc, libc-dev, binutils (>= 2.26) +++Recommends: +++ cargo (= ${binary:Version}), +++# llvm is needed for llvm-dwp for -C split-debuginfo=packed +++ rust-llvm, +++Replaces: libstd-rust-dev (<< 1.25.0+dfsg1-2~~) +++Breaks: libstd-rust-dev (<< 1.25.0+dfsg1-2~~), +++Conflicts: rustup +++Description: Rust systems programming language +++ Rust is a curly-brace, block-structured expression language. It +++ visually resembles the C language family, but differs significantly +++ in syntactic and semantic details. Its design is oriented toward +++ concerns of "programming in the large", that is, of creating and +++ maintaining boundaries - both abstract and operational - that +++ preserve large-system integrity, availability and concurrency. +++ . +++ It supports a mixture of imperative procedural, concurrent actor, +++ object-oriented and pure functional styles. Rust also supports +++ generic programming and meta-programming, in both static and dynamic +++ styles. +++ +++Package: libstd-rust-1.85 +++Section: libs +++Architecture: any +++Multi-Arch: same +++Pre-Depends: ${misc:Pre-Depends} +++Depends: ${shlibs:Depends}, ${misc:Depends} +++Conflicts: rustup +++Description: Rust standard libraries +++ Rust is a curly-brace, block-structured expression language. It +++ visually resembles the C language family, but differs significantly +++ in syntactic and semantic details. Its design is oriented toward +++ concerns of "programming in the large", that is, of creating and +++ maintaining boundaries - both abstract and operational - that +++ preserve large-system integrity, availability and concurrency. +++ . +++ It supports a mixture of imperative procedural, concurrent actor, +++ object-oriented and pure functional styles. Rust also supports +++ generic programming and meta-programming, in both static and dynamic +++ styles. +++ . +++ This package contains the standard Rust libraries, built as dylibs, +++ needed to run dynamically-linked Rust programs (-C prefer-dynamic). +++ +++Package: libstd-rust-dev +++Section: libdevel +++Architecture: any +++Multi-Arch: same +++Depends: ${shlibs:Depends}, ${misc:Depends}, +++ libstd-rust-1.85 (= ${binary:Version}), +++Conflicts: rustup +++Description: Rust standard libraries - development files +++ Rust is a curly-brace, block-structured expression language. It +++ visually resembles the C language family, but differs significantly +++ in syntactic and semantic details. Its design is oriented toward +++ concerns of "programming in the large", that is, of creating and +++ maintaining boundaries - both abstract and operational - that +++ preserve large-system integrity, availability and concurrency. +++ . +++ It supports a mixture of imperative procedural, concurrent actor, +++ object-oriented and pure functional styles. Rust also supports +++ generic programming and meta-programming, in both static and dynamic +++ styles. +++ . +++ This package contains development files for the standard Rust libraries, +++ needed to compile Rust programs. It may also be installed on a system +++ of another host architecture, for cross-compiling to this architecture. +++ +++Package: libstd-rust-dev-windows +++Section: libdevel +++Architecture: amd64 i386 +++Multi-Arch: same +++Depends: ${shlibs:Depends}, ${misc:Depends} +++Recommends: +++ gcc-mingw-w64-x86-64-posix [amd64], +++ gcc-mingw-w64-i686-posix [i386], +++Build-Profiles: +++Description: Rust standard libraries - development files +++ Rust is a curly-brace, block-structured expression language. It +++ visually resembles the C language family, but differs significantly +++ in syntactic and semantic details. Its design is oriented toward +++ concerns of "programming in the large", that is, of creating and +++ maintaining boundaries - both abstract and operational - that +++ preserve large-system integrity, availability and concurrency. +++ . +++ It supports a mixture of imperative procedural, concurrent actor, +++ object-oriented and pure functional styles. Rust also supports +++ generic programming and meta-programming, in both static and dynamic +++ styles. +++ . +++ This package contains the standard Rust libraries including development files, +++ needed to cross-compile Rust programs to the *-pc-windows-gnu target +++ corresponding to the architecture of this package. +++ +++Package: libstd-rust-dev-wasm32 +++Section: libdevel +++Architecture: all +++Multi-Arch: foreign +++Depends: ${shlibs:Depends}, ${misc:Depends} +++# Embeds wasi-libc so doesn't need to depend on it +++# None of its licenses require source redistrib, so no need for Built-Using +++Recommends: +++ lld-19, clang-19, +++Suggests: +++# nodejs contains wasi-node for running the program +++ nodejs (>= 12.16), +++Build-Profiles: +++Description: Rust standard libraries - development files +++ Rust is a curly-brace, block-structured expression language. It +++ visually resembles the C language family, but differs significantly +++ in syntactic and semantic details. Its design is oriented toward +++ concerns of "programming in the large", that is, of creating and +++ maintaining boundaries - both abstract and operational - that +++ preserve large-system integrity, availability and concurrency. +++ . +++ It supports a mixture of imperative procedural, concurrent actor, +++ object-oriented and pure functional styles. Rust also supports +++ generic programming and meta-programming, in both static and dynamic +++ styles. +++ . +++ This package contains the standard Rust libraries including development files, +++ needed to cross-compile Rust programs to the wasm32-unknown-unknown and +++ wasm32-wasip1/wasm32-wasip2 targets. +++ +++Package: rust-gdb +++Architecture: all +++Depends: gdb, ${misc:Depends} +++Suggests: gdb-doc +++Replaces: rustc (<< 1.1.0+dfsg1-1) +++Description: Rust debugger (gdb) +++ Rust is a curly-brace, block-structured expression language. It +++ visually resembles the C language family, but differs significantly +++ in syntactic and semantic details. Its design is oriented toward +++ concerns of "programming in the large", that is, of creating and +++ maintaining boundaries - both abstract and operational - that +++ preserve large-system integrity, availability and concurrency. +++ . +++ It supports a mixture of imperative procedural, concurrent actor, +++ object-oriented and pure functional styles. Rust also supports +++ generic programming and meta-programming, in both static and dynamic +++ styles. +++ . +++ This package contains pretty printers and a wrapper script for +++ invoking gdb on rust binaries. +++ +++Package: rust-lldb +++Architecture: all +++# When updating, also update rust-lldb.links +++Depends: lldb-19, ${misc:Depends}, python3-lldb-19 +++Replaces: rustc (<< 1.1.0+dfsg1-1) +++Description: Rust debugger (lldb) +++ Rust is a curly-brace, block-structured expression language. It +++ visually resembles the C language family, but differs significantly +++ in syntactic and semantic details. Its design is oriented toward +++ concerns of "programming in the large", that is, of creating and +++ maintaining boundaries - both abstract and operational - that +++ preserve large-system integrity, availability and concurrency. +++ . +++ It supports a mixture of imperative procedural, concurrent actor, +++ object-oriented and pure functional styles. Rust also supports +++ generic programming and meta-programming, in both static and dynamic +++ styles. +++ . +++ This package contains pretty printers and a wrapper script for +++ invoking lldb on rust binaries. +++ +++Package: rust-llvm +++Architecture: any +++Breaks: +++ rustc (<< 1.71.1+dfsg1-1~exp1), +++ rustc-web (<< 1.71.1+dfsg1-1~exp1), +++ rustc-mozilla (<< 1.71.1+dfsg1-1~exp1), +++Replaces: +++ rustc (<< 1.71.1+dfsg1-1~exp1), +++ rustc-web (<< 1.71.1+dfsg1-1~exp1), +++ rustc-mozilla (<< 1.71.1+dfsg1-1~exp1), +++Depends: ${shlibs:Depends}, ${misc:Depends}, +++# lld and clang are needed for wasm compilation +++ lld-19, clang-19, +++# llvm is needed for llvm-dwp for split-debuginfo=packed +++ llvm-19 +++Description: Rust LLVM integration +++ Rust is a curly-brace, block-structured expression language. It +++ visually resembles the C language family, but differs significantly +++ in syntactic and semantic details. Its design is oriented toward +++ concerns of "programming in the large", that is, of creating and +++ maintaining boundaries - both abstract and operational - that +++ preserve large-system integrity, availability and concurrency. +++ . +++ It supports a mixture of imperative procedural, concurrent actor, +++ object-oriented and pure functional styles. Rust also supports +++ generic programming and meta-programming, in both static and dynamic +++ styles. +++ . +++ This package contains symlinks for integration with LLVM tools such as lld and +++ grcov, and the wasm-component-ld helper binary for the wasm-wasip2 target. +++ +++Package: rust-doc +++Section: doc +++Architecture: all +++Build-Profiles: +++Depends: ${misc:Depends}, +++ libjs-jquery, libjs-highlight.js, libjs-mathjax, +++ fonts-open-sans, fonts-font-awesome +++Recommends: cargo-doc +++Description: Rust systems programming language - Documentation +++ Rust is a curly-brace, block-structured expression language. It +++ visually resembles the C language family, but differs significantly +++ in syntactic and semantic details. Its design is oriented toward +++ concerns of "programming in the large", that is, of creating and +++ maintaining boundaries - both abstract and operational - that +++ preserve large-system integrity, availability and concurrency. +++ . +++ It supports a mixture of imperative procedural, concurrent actor, +++ object-oriented and pure functional styles. Rust also supports +++ generic programming and meta-programming, in both static and dynamic +++ styles. +++ . +++ This package contains the Rust tutorial, language reference and +++ standard library documentation. +++ +++Package: rust-src +++Architecture: all +++Depends: ${misc:Depends} +++Conflicts: rustup +++Description: Rust systems programming language - source code +++ Rust is a curly-brace, block-structured expression language. It +++ visually resembles the C language family, but differs significantly +++ in syntactic and semantic details. Its design is oriented toward +++ concerns of "programming in the large", that is, of creating and +++ maintaining boundaries - both abstract and operational - that +++ preserve large-system integrity, availability and concurrency. +++ . +++ It supports a mixture of imperative procedural, concurrent actor, +++ object-oriented and pure functional styles. Rust also supports +++ generic programming and meta-programming, in both static and dynamic +++ styles. +++ . +++ This package contains sources of the Rust compiler and standard +++ libraries, useful for IDEs and code analysis tools such as Racer. +++ +++Package: rust-clippy +++Architecture: any +++Multi-Arch: allowed +++Depends: ${misc:Depends}, ${shlibs:Depends}, +++ libstd-rust-1.85 (= ${binary:Version}) +++Conflicts: rustup +++Recommends: cargo +++Description: Rust linter +++ Rust is a curly-brace, block-structured expression language. It +++ visually resembles the C language family, but differs significantly +++ in syntactic and semantic details. Its design is oriented toward +++ concerns of "programming in the large", that is, of creating and +++ maintaining boundaries - both abstract and operational - that +++ preserve large-system integrity, availability and concurrency. +++ . +++ It supports a mixture of imperative procedural, concurrent actor, +++ object-oriented and pure functional styles. Rust also supports +++ generic programming and meta-programming, in both static and dynamic +++ styles. +++ . +++ This package contains 'clippy', a linter to catch common mistakes and improve +++ your Rust code as well a collection of over 400 compatible lints. +++ . +++ Lints are divided into categories, each with a default lint level. You can +++ choose how much Clippy is supposed to annoy help you by changing the lint +++ level by category. +++ . +++ Clippy is integrated into the 'cargo' build tool, available via 'cargo clippy'. +++ +++Package: rustfmt +++Architecture: any +++Multi-Arch: allowed +++Depends: ${misc:Depends}, ${shlibs:Depends}, +++ libstd-rust-1.85 (= ${binary:Version}), +++Conflicts: rustup +++Recommends: cargo +++Description: Rust formatting helper +++ Rust is a curly-brace, block-structured expression language. It +++ visually resembles the C language family, but differs significantly +++ in syntactic and semantic details. Its design is oriented toward +++ concerns of "programming in the large", that is, of creating and +++ maintaining boundaries - both abstract and operational - that +++ preserve large-system integrity, availability and concurrency. +++ . +++ It supports a mixture of imperative procedural, concurrent actor, +++ object-oriented and pure functional styles. Rust also supports +++ generic programming and meta-programming, in both static and dynamic +++ styles. +++ . +++ This package contains 'rustfmt', a tool for formatting Rust code according to +++ style guidelines, as well as 'cargo-fmt', a helper enabling running rustfmt +++ directly with 'cargo fmt'. +++ +++Package: rust-analyzer +++Architecture: any +++Multi-Arch: allowed +++Depends: ${misc:Depends}, ${shlibs:Depends}, +++ libstd-rust-1.85 (= ${binary:Version}), +++Conflicts: rustup +++Recommends: cargo +++Description: Rust Language Server Protocol (LSP) implementation +++ Rust is a curly-brace, block-structured expression language. It +++ visually resembles the C language family, but differs significantly +++ in syntactic and semantic details. Its design is oriented toward +++ concerns of "programming in the large", that is, of creating and +++ maintaining boundaries - both abstract and operational - that +++ preserve large-system integrity, availability and concurrency. +++ . +++ It supports a mixture of imperative procedural, concurrent actor, +++ object-oriented and pure functional styles. Rust also supports +++ generic programming and meta-programming, in both static and dynamic +++ styles. +++ . +++ This package contains 'rust-analyzer', an implementation of the Language +++ Server Protocol for the Rust language. It provides features like completion +++ and goto definition for many editors, like Emacs and (Neo)Vim. +++ +++Package: rust-all +++Architecture: all +++Depends: ${misc:Depends}, ${shlibs:Depends}, +++ rustc (>= ${binary:Version}), +++ rustfmt (>= ${binary:Version}), +++ rust-analyzer (>= ${binary:Version}), +++ rust-clippy (>= ${binary:Version}), +++ rust-gdb (>= ${binary:Version}) | rust-lldb (>= ${binary:Version}), +++ rust-llvm (>= ${binary:Version}), +++ cargo, +++Recommends: +++ cargo (= ${binary:Version}) +++Suggests: +++ rust-doc (>= ${binary:Version}), +++ rust-src (>= ${binary:Version}), +++ libstd-rust-dev-wasm32 (>= ${binary:Version}), +++Description: Rust systems programming language - all developer tools +++ Rust is a curly-brace, block-structured expression language. It +++ visually resembles the C language family, but differs significantly +++ in syntactic and semantic details. Its design is oriented toward +++ concerns of "programming in the large", that is, of creating and +++ maintaining boundaries - both abstract and operational - that +++ preserve large-system integrity, availability and concurrency. +++ . +++ It supports a mixture of imperative procedural, concurrent actor, +++ object-oriented and pure functional styles. Rust also supports +++ generic programming and meta-programming, in both static and dynamic +++ styles. +++ . +++ This package is an empty metapackage that depends on all developer tools +++ in the standard rustc distribution that have been packaged for Debian. +++ +++# Cargo binaries +++Package: cargo +++Architecture: any +++Multi-Arch: allowed +++Depends: ${shlibs:Depends}, ${misc:Depends}, +++ rustc (= ${binary:Version}), +++ binutils, +++ gcc | clang | c-compiler +++Conflicts: rustup +++Suggests: cargo-doc, python3 +++Description: Rust package manager +++ Cargo is a tool that allows Rust projects to declare their various +++ dependencies, and ensure that you'll always get a repeatable build. +++ . +++ To accomplish this goal, Cargo does four things: +++ * Introduces two metadata files with various bits of project information. +++ * Fetches and builds your project's dependencies. +++ * Invokes rustc or another build tool with the correct parameters to build +++ your project. +++ * Introduces conventions, making working with Rust projects easier. +++ . +++ Cargo downloads your Rust project's dependencies and compiles your +++ project. +++ +++Package: cargo-doc +++Section: doc +++Architecture: all +++Build-Profiles: +++Recommends: rust-doc +++Depends: ${misc:Depends} +++Description: Rust package manager, documentation +++ Cargo is a tool that allows Rust projects to declare their various +++ dependencies, and ensure that you'll always get a repeatable build. +++ . +++ To accomplish this goal, Cargo does four things: +++ * Introduces two metadata files with various bits of project information. +++ * Fetches and builds your project's dependencies. +++ * Invokes rustc or another build tool with the correct parameters to build +++ your project. +++ * Introduces conventions, making working with Rust projects easier. +++ . +++ Cargo downloads your Rust project's dependencies and compiles your +++ project. +++ . +++ This package contains the documentation. +++ +++# TODO: add a cargo-src package diff --cc debian/copyright index 0000000000,0000000000,0000000000..9d450ec55d new file mode 100644 --- /dev/null +++ b/debian/copyright @@@@ -1,0 -1,0 -1,0 +1,4452 @@@@ +++Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +++Upstream-Name: rust +++Source: https://www.rust-lang.org +++Files-Excluded: +++ .gitmodules +++ *.min.js +++ src/llvm-project +++# Pre-generated docs +++ src/tools/rustfmt/docs +++# Fonts already in Debian, covered by d-0003-mdbook-strip-embedded-libs.patch +++ vendor/mdbook-*/src/theme/fonts +++ vendor/mdbook-*/src/theme/FontAwesome +++ vendor/mdbook-*/src/theme/highlight.js +++ vendor/mdbook-*/src/theme/highlight.css +++# DOCX versions of TRPL book prepared for No Starch Press +++ src/doc/book/nostarch/docx +++# Exclude submodules https://github.com/rust-lang/rust/tree/master/src/tools +++# We prefer to do them in different Debian packages so they can have their own +++# version numbers. If upstream merges them "properly" (i.e. unify the version +++# numbers) then we can merge the packages in Debian. Note that cargotest here +++# does actually belong to rustc, it is an integration test suite for rustc to +++# check that certain popular crates continue to compile. It is not the same as +++# cargo's own test suite (in its own package) also called cargotest. +++# NB: don't exclude rust-installer, it's needed for "install" functionality +++ src/tools/enzyme +++ src/tools/rls +++ src/tools/remote-test-client +++ src/tools/remote-test-server +++ src/tools/miri +++# rust-analyzer parts we don't need (yet) +++ src/tools/rust-analyzer/editors +++ src/tools/rust-analyzer/.github +++# Embedded GH pages +++ src/tools/clippy/util/gh-pages +++# Embedded C libraries +++ vendor/blake3-*/c +++ vendor/curl-sys-*/curl +++ vendor/libdbus-sys-*/vendor +++ vendor/libgit2-sys-*/libgit2 +++ vendor/libssh2-sys-*/libssh2 +++ vendor/libsqlite3-sys-*/sqlite3 +++ vendor/libsqlite3-sys-*/sqlcipher +++ vendor/libz-sys-*/src/zlib* +++ vendor/lzma-sys*/xz-* +++ vendor/onig_sys*/oniguruma/* +++# Embedded binary blobs +++ vendor/jsonpath_lib-*/docs +++ vendor/mdbook-*/src/theme/playground_editor +++ vendor/psm-*/src/arch/wasm32.o +++# test binary files +++ vendor/libloading-*/tests/*.dll +++# Misc +++ vendor/blake3-*/media +++ vendor/*/icon_CLion.svg +++ vendor/prettydiff-*/screens/*.png +++# unused dependencies, generated by debian/prune-unused-deps +++# DO NOT EDIT below, AUTOGENERATED +++ vendor/addr2line-0.17.0 +++ vendor/aes-0.8.4 +++ vendor/ahash-0.8.10 +++ vendor/aho-corasick-0.5.3 +++ vendor/aho-corasick-0.6.10 +++ vendor/aho-corasick-0.7.18 +++ vendor/aho-corasick-0.7.20 +++ vendor/aho-corasick-1.0.2 +++ vendor/allocator-api2-0.2.16 +++ vendor/allocator-api2-0.2.18 +++ vendor/alloc-no-stdlib-2.0.4 +++ vendor/alloc-stdlib-0.2.2 +++ vendor/analyzeme-12.0.0 +++ vendor/annotate-snippets-0.11.4 +++ vendor/ansi-str-0.8.0 +++ vendor/ansi_term-0.12.1 +++ vendor/ansitok-0.2.0 +++ vendor/anstream-0.6.15 +++ vendor/anstyle-1.0.8 +++ vendor/anstyle-lossy-1.1.2 +++ vendor/anstyle-parse-0.2.5 +++ vendor/anstyle-query-1.1.1 +++ vendor/anstyle-svg-0.1.4 +++ vendor/anstyle-wincon-3.0.4 +++ vendor/anstyle-wincon-3.0.6 +++ vendor/anyhow-1.0.55 +++ vendor/anyhow-1.0.56 +++ vendor/anyhow-1.0.71 +++ vendor/anyhow-1.0.86 +++ vendor/arc-swap-1.6.0 +++ vendor/arrayref-0.3.7 +++ vendor/arrayvec-0.5.2 +++ vendor/arrayvec-0.7.2 +++ vendor/arrayvec-0.7.4 +++ vendor/async-stream-0.3.2 +++ vendor/async-stream-impl-0.3.2 +++ vendor/async-trait-0.1.67 +++ vendor/atty-0.2.14 +++ vendor/autocfg-1.0.1 +++ vendor/autocfg-1.1.0 +++ vendor/autocfg-1.3.0 +++ vendor/automod-1.0.2 +++ vendor/backtrace-0.3.63 +++ vendor/backtrace-0.3.64 +++ vendor/base64-0.13.0 +++ vendor/base64-0.13.1 +++ vendor/base64-0.21.0 +++ vendor/bigdecimal-0.1.2 +++ vendor/bitflags-1.2.1 +++ vendor/bit-set-0.5.2 +++ vendor/blake3-1.5.2 +++ vendor/boml-0.3.1 +++ vendor/brotli-3.3.4 +++ vendor/brotli-decompressor-2.3.4 +++ vendor/bstr-0.2.16 +++ vendor/bstr-0.2.17 +++ vendor/bstr-1.10.0 +++ vendor/bstr-1.4.0 +++ vendor/bstr-1.9.1 +++ vendor/bumpalo-3.12.0 +++ vendor/bumpalo-3.8.0 +++ vendor/bumpalo-3.9.1 +++ vendor/bytecount-0.6.2 +++ vendor/bytecount-0.6.7 +++ vendor/bytemuck-1.13.1 +++ vendor/byteorder-1.4.3 +++ vendor/bytes-1.1.0 +++ vendor/bytes-1.4.0 +++ vendor/bytes-1.6.0 +++ vendor/bytes-1.7.1 +++ vendor/bytesize-1.1.0 +++ vendor/camino-1.1.4 +++ vendor/camino-1.1.6 +++ vendor/camino-1.1.7 +++ vendor/cargo_metadata-0.15.3 +++ vendor/cargo_metadata-0.19.0 +++ vendor/cargo-platform-0.1.2 +++ vendor/cargo-platform-0.1.8 +++ vendor/cargo-util-0.1.2 +++ vendor/cast-0.2.7 +++ vendor/cc-1.0.68 +++ vendor/cc-1.0.72 +++ vendor/cc-1.0.73 +++ vendor/cc-1.0.98 +++ vendor/cc-1.0.99 +++ vendor/cc-1.1.22 +++ vendor/cfg-if-0.1.10 +++ vendor/chrono-0.4.19 +++ vendor/chrono-0.4.38 +++ vendor/chrono-tz-0.10.0 +++ vendor/chrono-tz-build-0.4.0 +++ vendor/cipher-0.4.4 +++ vendor/clap-2.33.3 +++ vendor/clap-2.34.0 +++ vendor/clap-4.1.10 +++ vendor/clap-4.5.20 +++ vendor/clap_builder-4.5.20 +++ vendor/clap_complete-4.5.35 +++ vendor/clap_complete-4.5.37 +++ vendor/clap_derive-3.1.4 +++ vendor/clap_derive-4.1.9 +++ vendor/clap_lex-0.3.3 +++ vendor/clap_lex-0.7.2 +++ vendor/colorchoice-1.0.2 +++ vendor/color-print-0.3.6 +++ vendor/color-print-proc-macro-0.3.6 +++ vendor/combine-4.6.3 +++ vendor/commoncrypto-0.2.0 +++ vendor/commoncrypto-sys-0.2.0 +++ vendor/concolor-0.0.8 +++ vendor/concolor-query-0.0.5 +++ vendor/console-0.15.0 +++ vendor/console-0.15.7 +++ vendor/constant_time_eq-0.3.0 +++ vendor/core-foundation-0.10.0 +++ vendor/core-foundation-0.9.3 +++ vendor/core-foundation-sys-0.8.3 +++ vendor/cpufeatures-0.2.12 +++ vendor/cpufeatures-0.2.15 +++ vendor/cpufeatures-0.2.5 +++ vendor/crabgrind-0.1.10 +++ vendor/cranelift-bforest-0.114.0 +++ vendor/cranelift-bitset-0.114.0 +++ vendor/cranelift-codegen-0.114.0 +++ vendor/cranelift-codegen-meta-0.114.0 +++ vendor/cranelift-codegen-shared-0.114.0 +++ vendor/cranelift-control-0.114.0 +++ vendor/cranelift-entity-0.114.0 +++ vendor/cranelift-frontend-0.114.0 +++ vendor/cranelift-isle-0.114.0 +++ vendor/cranelift-jit-0.114.0 +++ vendor/cranelift-module-0.114.0 +++ vendor/cranelift-native-0.114.0 +++ vendor/cranelift-object-0.114.0 +++ vendor/crates-io-0.33.1 +++ vendor/crc32fast-1.3.2 +++ vendor/crc32fast-1.4.0 +++ vendor/criterion-0.3.5 +++ vendor/criterion-plot-0.4.4 +++ vendor/crossbeam-channel-0.5.12 +++ vendor/crossbeam-channel-0.5.13 +++ vendor/crossbeam-channel-0.5.1 +++ vendor/crossbeam-channel-0.5.4 +++ vendor/crossbeam-deque-0.8.1 +++ vendor/crossbeam-deque-0.8.4 +++ vendor/crossbeam-deque-0.8.5 +++ vendor/crossbeam-epoch-0.9.17 +++ vendor/crossbeam-epoch-0.9.5 +++ vendor/crossbeam-epoch-0.9.8 +++ vendor/crossbeam-utils-0.8.18 +++ vendor/crossbeam-utils-0.8.19 +++ vendor/crossbeam-utils-0.8.20 +++ vendor/crossbeam-utils-0.8.5 +++ vendor/crossbeam-utils-0.8.7 +++ vendor/crossbeam-utils-0.8.8 +++ vendor/crypto-hash-0.3.4 +++ vendor/cssparser-0.31.2 +++ vendor/cssparser-macros-0.6.1 +++ vendor/csv-1.1.6 +++ vendor/csv-1.2.1 +++ vendor/csv-core-0.1.10 +++ vendor/ctrlc-3.4.4 +++ vendor/curl-0.4.42 +++ vendor/curl-0.4.46 +++ vendor/curl-sys-0.4.52+curl-7.81.0 +++ vendor/curl-sys-0.4.74+curl-8.9.0 +++ vendor/decodeme-10.1.3 +++ vendor/decodeme-12.0.0 +++ vendor/der_derive-0.7.3 +++ vendor/derive-error-chain-0.10.1 +++ vendor/derive_more-0.99.18 +++ vendor/diesel_derives-1.4.1 +++ vendor/difflib-0.4.0 +++ vendor/digest-0.10.6 +++ vendor/dirs-4.0.0 +++ vendor/dirs-sys-0.3.7 +++ vendor/dotenv-0.10.1 +++ vendor/dtoa-1.0.9 +++ vendor/dtoa-short-0.3.5 +++ vendor/ego-tree-0.6.3 +++ vendor/either-1.10.0 +++ vendor/either-1.6.1 +++ vendor/either-1.8.1 +++ vendor/encode_unicode-0.3.6 +++ vendor/encode_unicode-1.0.0 +++ vendor/encoding_rs-0.8.28 +++ vendor/encoding_rs-0.8.30 +++ vendor/encoding_rs-0.8.32 +++ vendor/encoding_rs_io-0.1.7 +++ vendor/env_logger-0.10.0 +++ vendor/env_logger-0.3.5 +++ vendor/env_logger-0.7.1 +++ vendor/env_logger-0.9.0 +++ vendor/errno-0.2.8 +++ vendor/errno-0.3.9 +++ vendor/errno-dragonfly-0.1.2 +++ vendor/error-chain-0.10.0 +++ vendor/escargot-0.5.7 +++ vendor/expect-test-1.5.0 +++ vendor/fallible-iterator-0.2.0 +++ vendor/fastrand-1.7.0 +++ vendor/fastrand-1.9.0 +++ vendor/fastrand-2.1.0 +++ vendor/filetime-0.2.15 +++ vendor/filetime-0.2.20 +++ vendor/filetime-0.2.23 +++ vendor/filetime-0.2.24 +++ vendor/flagset-0.4.6 +++ vendor/flate2-1.0.22 +++ vendor/flate2-1.0.25 +++ vendor/flate2-1.0.31 +++ vendor/flate2-1.0.34 +++ vendor/fm-0.2.2 +++ vendor/form_urlencoded-1.0.1 +++ vendor/form_urlencoded-1.1.0 +++ vendor/fs_extra-1.2.0 +++ vendor/fuchsia-cprng-0.1.1 +++ vendor/futures-0.3.27 +++ vendor/futures-0.3.30 +++ vendor/futures-channel-0.3.19 +++ vendor/futures-channel-0.3.21 +++ vendor/futures-channel-0.3.27 +++ vendor/futures-channel-0.3.30 +++ vendor/futures-core-0.3.19 +++ vendor/futures-core-0.3.21 +++ vendor/futures-core-0.3.27 +++ vendor/futures-core-0.3.30 +++ vendor/futures-executor-0.3.27 +++ vendor/futures-executor-0.3.30 +++ vendor/futures-io-0.3.21 +++ vendor/futures-io-0.3.27 +++ vendor/futures-io-0.3.30 +++ vendor/futures-macro-0.3.27 +++ vendor/futures-macro-0.3.30 +++ vendor/futures-sink-0.3.19 +++ vendor/futures-sink-0.3.21 +++ vendor/futures-sink-0.3.27 +++ vendor/futures-sink-0.3.30 +++ vendor/futures-task-0.3.19 +++ vendor/futures-task-0.3.21 +++ vendor/futures-task-0.3.27 +++ vendor/futures-task-0.3.30 +++ vendor/futures-util-0.3.19 +++ vendor/futures-util-0.3.21 +++ vendor/futures-util-0.3.27 +++ vendor/futures-util-0.3.30 +++ vendor/fwdansi-1.1.0 +++ vendor/fxhash-0.2.1 +++ vendor/gccjit-2.2.0 +++ vendor/gccjit_sys-0.3.0 +++ vendor/generic-array-0.14.6 +++ vendor/getrandom-0.2.2 +++ vendor/getrandom-0.2.6 +++ vendor/getrandom-0.2.8 +++ vendor/gimli-0.26.1 +++ vendor/git2-0.13.25 +++ vendor/git2-curl-0.14.1 +++ vendor/glob-0.3.0 +++ vendor/glob-0.3.1 +++ vendor/globset-0.4.10 +++ vendor/globset-0.4.14 +++ vendor/globset-0.4.7 +++ vendor/globset-0.4.8 +++ vendor/globwalk-0.8.1 +++ vendor/grep-0.2.8 +++ vendor/grep-cli-0.1.6 +++ vendor/grep-matcher-0.1.5 +++ vendor/grep-pcre2-0.1.5 +++ vendor/grep-printer-0.1.6 +++ vendor/grep-regex-0.1.9 +++ vendor/grep-searcher-0.1.8 +++ vendor/h2-0.3.10 +++ vendor/h2-0.3.12 +++ vendor/h2-0.3.26 +++ vendor/half-1.8.2 +++ vendor/hashbrown-0.11.2 +++ vendor/hashbrown-0.14.3 +++ vendor/hashlink-0.8.4 +++ vendor/headers-0.3.8 +++ vendor/headers-core-0.2.0 +++ vendor/heck-0.4.0 +++ vendor/hermit-abi-0.1.18 +++ vendor/hermit-abi-0.1.19 +++ vendor/hermit-abi-0.3.1 +++ vendor/hex-0.3.2 +++ vendor/home-0.5.3 +++ vendor/home-0.5.9 +++ vendor/http-0.2.6 +++ vendor/http-0.2.9 +++ vendor/http-1.1.0 +++ vendor/httparse-1.6.0 +++ vendor/httparse-1.8.0 +++ vendor/httparse-1.9.4 +++ vendor/http-body-0.4.4 +++ vendor/http-body-0.4.5 +++ vendor/http-body-1.0.1 +++ vendor/http-body-util-0.1.2 +++ vendor/httpdate-1.0.2 +++ vendor/humantime-1.3.0 +++ vendor/humantime-serde-1.0.1 +++ vendor/hyper-0.14.18 +++ vendor/hyper-0.14.25 +++ vendor/hyper-1.4.1 +++ vendor/hyper-rustls-0.27.3 +++ vendor/hyper-tls-0.5.0 +++ vendor/hyper-util-0.1.8 +++ vendor/iana-time-zone-0.1.53 +++ vendor/idna-0.1.5 +++ vendor/idna-0.2.3 +++ vendor/idna-0.3.0 +++ vendor/idna-0.5.0 +++ vendor/ignore-0.4.18 +++ vendor/ignore-0.4.20 +++ vendor/ignore-0.4.22 +++ vendor/im-rc-15.0.0 +++ vendor/indexmap-1.7.0 +++ vendor/indexmap-1.8.0 +++ vendor/indexmap-2.1.0 +++ vendor/indexmap-2.2.6 +++ vendor/indexmap-2.3.0 +++ vendor/inferno-0.11.15 +++ vendor/inout-0.1.3 +++ vendor/insta-1.13.0 +++ vendor/instant-0.1.12 +++ vendor/io-lifetimes-1.0.8 +++ vendor/ipnet-2.10.0 +++ vendor/ipnet-2.4.0 +++ vendor/ipnet-2.7.1 +++ vendor/ipnetwork-0.17.0 +++ vendor/ipnetwork-0.18.0 +++ vendor/is-terminal-0.4.5 +++ vendor/itertools-0.10.1 +++ vendor/itertools-0.10.3 +++ vendor/itoa-0.4.7 +++ vendor/itoa-1.0.11 +++ vendor/itoa-1.0.1 +++ vendor/itoa-1.0.6 +++ vendor/jemallocator-0.3.2 +++ vendor/jemallocator-0.5.0 +++ vendor/jemalloc-ctl-0.5.0 +++ vendor/jemalloc-sys-0.3.2 +++ vendor/jemalloc-sys-0.5.3+5.3.0-patched +++ vendor/jiff-tzdb-0.1.1 +++ vendor/jiff-tzdb-platform-0.1.1 +++ vendor/jobserver-0.1.22 +++ vendor/jobserver-0.1.24 +++ vendor/jobserver-0.1.31 +++ vendor/js-sys-0.3.55 +++ vendor/js-sys-0.3.56 +++ vendor/js-sys-0.3.61 +++ vendor/js-sys-0.3.69 +++ vendor/js-sys-0.3.70 +++ vendor/junction-1.2.0 +++ vendor/kernel32-sys-0.2.2 +++ vendor/kstring-1.0.6 +++ vendor/lang_tester-0.8.0 +++ vendor/lazy_static-1.4.0 +++ vendor/libc-0.2.107 +++ vendor/libc-0.2.112 +++ vendor/libc-0.2.119 +++ vendor/libc-0.2.121 +++ vendor/libc-0.2.124 +++ vendor/libc-0.2.150 +++ vendor/libc-0.2.155 +++ vendor/libc-0.2.158 +++ vendor/libc-0.2.167 +++ vendor/libc-0.2.94 +++ vendor/libc-0.2.97 +++ vendor/libffi-3.2.0 +++ vendor/libffi-sys-2.3.0 +++ vendor/libgit2-sys-0.12.26+1.3.0 +++ vendor/libloading-0.8.4 +++ vendor/libloading-0.8.5 +++ vendor/libm-0.1.4 +++ vendor/libm-0.2.6 +++ vendor/libm-0.2.8 +++ vendor/libmimalloc-sys-0.1.39 +++ vendor/libnghttp2-sys-0.1.10+1.61.0 +++ vendor/libnghttp2-sys-0.1.7+1.45.0 +++ vendor/libsqlite3-sys-0.22.2 +++ vendor/libsqlite3-sys-0.25.2 +++ vendor/libssh2-sys-0.2.23 +++ vendor/libz-sys-1.1.3 +++ vendor/linked-hash-map-0.5.4 +++ vendor/linux-raw-sys-0.1.4 +++ vendor/lock_api-0.4.11 +++ vendor/lock_api-0.4.6 +++ vendor/lock_api-0.4.9 +++ vendor/log-0.3.9 +++ vendor/log-0.4.14 +++ vendor/log-0.4.16 +++ vendor/log-0.4.17 +++ vendor/lru-0.12.0 +++ vendor/mach2-0.4.2 +++ vendor/matches-0.1.9 +++ vendor/md-5-0.10.5 +++ vendor/measureme-10.1.3 +++ vendor/measureme-12.0.0 +++ vendor/memchr-0.1.11 +++ vendor/memchr-2.4.0 +++ vendor/memchr-2.4.1 +++ vendor/memchr-2.5.0 +++ vendor/memchr-2.7.2 +++ vendor/memmap2-0.3.0 +++ vendor/memoffset-0.6.4 +++ vendor/memoffset-0.6.5 +++ vendor/mimalloc-0.1.43 +++ vendor/mime-0.3.16 +++ vendor/miniz_oxide-0.4.4 +++ vendor/miniz_oxide-0.6.2 +++ vendor/miniz_oxide-0.7.3 +++ vendor/miniz_oxide-0.8.0 +++ vendor/mio-0.7.14 +++ vendor/mio-0.8.2 +++ vendor/miow-0.3.7 +++ vendor/miow-0.6.0 +++ vendor/mysqlclient-sys-0.2.5 +++ vendor/native-tls-0.2.11 +++ vendor/native-tls-0.2.8 +++ vendor/normpath-1.2.0 +++ vendor/normpath-1.3.0 +++ vendor/ntapi-0.3.6 +++ vendor/ntapi-0.3.7 +++ vendor/ntapi-0.4.1 +++ vendor/num-bigint-0.2.6 +++ vendor/num_cpus-1.13.0 +++ vendor/num_cpus-1.13.1 +++ vendor/num-format-0.4.4 +++ vendor/num-integer-0.1.44 +++ vendor/num-traits-0.2.14 +++ vendor/num-traits-0.2.15 +++ vendor/object-0.27.1 +++ vendor/object-0.36.1 +++ vendor/object-0.36.2 +++ vendor/object-0.36.3 +++ vendor/object-0.36.5 +++ vendor/once_cell-1.10.0 +++ vendor/once_cell-1.19.0 +++ vendor/once_cell-1.20.0 +++ vendor/once_cell-1.7.2 +++ vendor/once_cell-1.8.0 +++ vendor/once_cell-1.9.0 +++ vendor/oorandom-11.1.3 +++ vendor/opener-0.5.0 +++ vendor/opener-0.7.1 +++ vendor/openssl-0.10.38 +++ vendor/openssl-0.10.64 +++ vendor/openssl-macros-0.1.0 +++ vendor/openssl-src-111.17.0+1.1.1m +++ vendor/openssl-src-111.28.2+1.1.1w +++ vendor/openssl-sys-0.9.102 +++ vendor/openssl-sys-0.9.72 +++ vendor/openssl-sys-0.9.92 +++ vendor/os_info-3.2.0 +++ vendor/os_pipe-1.0.0 +++ vendor/os_str_bytes-6.0.0 +++ vendor/os_str_bytes-6.4.1 +++ vendor/packed_simd_2-0.3.5 +++ vendor/papergrid-0.10.0 +++ vendor/parking_lot-0.11.2 +++ vendor/parking_lot-0.12.1 +++ vendor/parking_lot_core-0.8.5 +++ vendor/parking_lot_core-0.9.7 +++ vendor/parking_lot_core-0.9.9 +++ vendor/parse-zoneinfo-0.3.1 +++ vendor/paste-1.0.12 +++ vendor/paste-1.0.15 +++ vendor/pathdiff-0.2.1 +++ vendor/pcre2-0.2.3 +++ vendor/pcre2-sys-0.2.5 +++ vendor/percent-encoding-1.0.1 +++ vendor/percent-encoding-2.1.0 +++ vendor/percent-encoding-2.2.0 +++ vendor/perf-event-0.4.8 +++ vendor/perf-event-open-sys-4.0.0 +++ vendor/pest-2.5.6 +++ vendor/pest-2.7.9 +++ vendor/pest_derive-2.5.6 +++ vendor/pest_derive-2.7.9 +++ vendor/pest_generator-2.5.6 +++ vendor/pest_generator-2.7.9 +++ vendor/pest_meta-2.5.6 +++ vendor/pest_meta-2.7.9 +++ vendor/phf-0.10.1 +++ vendor/phf-0.11.1 +++ vendor/phf_codegen-0.10.0 +++ vendor/phf_macros-0.11.2 +++ vendor/phf_shared-0.11.1 +++ vendor/pin-project-1.0.10 +++ vendor/pin-project-1.1.5 +++ vendor/pin-project-internal-1.0.10 +++ vendor/pin-project-internal-1.1.5 +++ vendor/pin-project-lite-0.2.14 +++ vendor/pin-project-lite-0.2.8 +++ vendor/pin-project-lite-0.2.9 +++ vendor/pkg-config-0.3.19 +++ vendor/pkg-config-0.3.24 +++ vendor/pkg-config-0.3.26 +++ vendor/pkg-config-0.3.30 +++ vendor/plotters-0.3.1 +++ vendor/plotters-backend-0.3.2 +++ vendor/plotters-svg-0.3.1 +++ vendor/pnet_base-0.27.2 +++ vendor/pnet_datalink-0.27.2 +++ vendor/pnet_sys-0.27.2 +++ vendor/postgres-native-tls-0.5.0 +++ vendor/postgres-protocol-0.6.4 +++ vendor/postgres-types-0.2.4 +++ vendor/ppv-lite86-0.2.16 +++ vendor/ppv-lite86-0.2.17 +++ vendor/pq-sys-0.4.6 +++ vendor/pretty_env_logger-0.4.0 +++ vendor/proc-macro2-0.4.30 +++ vendor/proc-macro2-1.0.27 +++ vendor/proc-macro2-1.0.32 +++ vendor/proc-macro2-1.0.36 +++ vendor/proc-macro2-1.0.70 +++ vendor/proc-macro2-1.0.84 +++ vendor/proc-macro2-1.0.89 +++ vendor/proc-macro-error-1.0.4 +++ vendor/proc-macro-error-attr-1.0.4 +++ vendor/prometheus-0.13.3 +++ vendor/proptest-1.0.0 +++ vendor/proptest-derive-0.3.0 +++ vendor/pulldown-cmark-0.12.1 +++ vendor/quickcheck-1.0.3 +++ vendor/quick-error-2.0.1 +++ vendor/quick-xml-0.26.0 +++ vendor/quinn-0.11.3 +++ vendor/quinn-proto-0.11.8 +++ vendor/quinn-udp-0.5.4 +++ vendor/quote-0.3.15 +++ vendor/quote-0.6.13 +++ vendor/quote-1.0.10 +++ vendor/quote-1.0.14 +++ vendor/quote-1.0.15 +++ vendor/quote-1.0.16 +++ vendor/quote-1.0.33 +++ vendor/quote-1.0.36 +++ vendor/quote-1.0.37 +++ vendor/quote-1.0.9 +++ vendor/r2d2-0.8.9 +++ vendor/rand-0.3.23 +++ vendor/rand-0.4.6 +++ vendor/rand-0.8.3 +++ vendor/rand_core-0.3.1 +++ vendor/rand_core-0.4.2 +++ vendor/rand_core-0.5.1 +++ vendor/rand_core-0.6.2 +++ vendor/rand_core-0.6.3 +++ vendor/rand_xoshiro-0.4.0 +++ vendor/rayon-1.5.1 +++ vendor/rayon-1.8.0 +++ vendor/rayon-core-1.12.0 +++ vendor/rayon-core-1.9.1 +++ vendor/rdrand-0.4.0 +++ vendor/redox_syscall-0.2.10 +++ vendor/redox_syscall-0.2.11 +++ vendor/redox_syscall-0.2.13 +++ vendor/redox_syscall-0.2.16 +++ vendor/redox_syscall-0.4.1 +++ vendor/redox_syscall-0.5.3 +++ vendor/redox_syscall-0.5.4 +++ vendor/redox_syscall-0.5.7 +++ vendor/redox_users-0.4.3 +++ vendor/redox_users-0.4.5 +++ vendor/ref-cast-1.0.6 +++ vendor/ref-cast-impl-1.0.6 +++ vendor/regalloc2-0.10.2 +++ vendor/regex-0.1.80 +++ vendor/regex-0.2.11 +++ vendor/regex-1.10.5 +++ vendor/regex-1.5.4 +++ vendor/regex-1.5.5 +++ vendor/regex-1.7.1 +++ vendor/regex-1.8.4 +++ vendor/regex-automata-0.4.7 +++ vendor/regex-syntax-0.3.9 +++ vendor/regex-syntax-0.5.6 +++ vendor/regex-syntax-0.6.25 +++ vendor/regex-syntax-0.6.28 +++ vendor/regex-syntax-0.7.2 +++ vendor/regex-syntax-0.8.4 +++ vendor/region-3.0.2 +++ vendor/remove_dir_all-0.5.3 +++ vendor/reqwest-0.11.10 +++ vendor/reqwest-0.11.14 +++ vendor/reqwest-0.12.7 +++ vendor/rgb-0.8.36 +++ vendor/ring-0.16.20 +++ vendor/ring-0.17.8 +++ vendor/rmp-0.8.11 +++ vendor/rmp-serde-1.1.1 +++ vendor/rusqlite-0.28.0 +++ vendor/rustc_apfloat-0.2.1+llvm-462a31f5a5ab +++ vendor/rustc-build-sysroot-0.5.4 +++ vendor/rustc-demangle-0.1.21 +++ vendor/rustc-demangle-0.1.23 +++ vendor/rustc-hash-2.0.0 +++ vendor/rustc_version-0.4.0 +++ vendor/rustc-workspace-hack-1.0.0 +++ vendor/rust-embed-6.6.0 +++ vendor/rust-embed-impl-6.5.0 +++ vendor/rust-embed-utils-7.5.0 +++ vendor/rustfix-0.6.0 +++ vendor/rustix-0.36.10 +++ vendor/rustix-0.38.37 +++ vendor/rustix-0.38.40 +++ vendor/rustls-0.23.13 +++ vendor/rustls-pemfile-2.1.3 +++ vendor/rustls-pki-types-1.8.0 +++ vendor/rustls-webpki-0.102.8 +++ vendor/rust_team_data-1.0.0 +++ vendor/rustversion-1.0.5 +++ vendor/ruzstd-0.7.0 +++ vendor/ryu-1.0.13 +++ vendor/ryu-1.0.5 +++ vendor/ryu-1.0.9 +++ vendor/schannel-0.1.19 +++ vendor/schannel-0.1.21 +++ vendor/schannel-0.1.23 +++ vendor/schannel-0.1.27 +++ vendor/scheduled-thread-pool-0.2.5 +++ vendor/scopeguard-1.1.0 +++ vendor/scraper-0.20.0 +++ vendor/security-framework-2.6.1 +++ vendor/security-framework-2.8.2 +++ vendor/security-framework-3.0.0 +++ vendor/security-framework-sys-2.12.0 +++ vendor/security-framework-sys-2.6.1 +++ vendor/security-framework-sys-2.8.0 +++ vendor/selectors-0.25.0 +++ vendor/semver-1.0.17 +++ vendor/semver-1.0.23 +++ vendor/semver-1.0.4 +++ vendor/semver-1.0.6 +++ vendor/serde-1.0.126 +++ vendor/serde-1.0.130 +++ vendor/serde-1.0.133 +++ vendor/serde-1.0.136 +++ vendor/serde-1.0.157 +++ vendor/serde-1.0.204 +++ vendor/serde-1.0.210 +++ vendor/serde-1.0.215 +++ vendor/serde-1.0.216 +++ vendor/serde_cbor-0.11.2 +++ vendor/serde_derive-1.0.126 +++ vendor/serde_derive-1.0.130 +++ vendor/serde_derive-1.0.133 +++ vendor/serde_derive-1.0.136 +++ vendor/serde_derive-1.0.157 +++ vendor/serde_derive-1.0.204 +++ vendor/serde_derive-1.0.210 +++ vendor/serde_derive-1.0.215 +++ vendor/serde_derive-1.0.216 +++ vendor/serde_ignored-0.1.2 +++ vendor/serde_json-1.0.121 +++ vendor/serde_json-1.0.124 +++ vendor/serde_json-1.0.128 +++ vendor/serde_json-1.0.132 +++ vendor/serde_json-1.0.64 +++ vendor/serde_json-1.0.69 +++ vendor/serde_json-1.0.74 +++ vendor/serde_json-1.0.79 +++ vendor/serde_json-1.0.99 +++ vendor/serde_spanned-0.6.5 +++ vendor/serde_spanned-0.6.7 +++ vendor/serde_urlencoded-0.7.1 +++ vendor/serde_yaml-0.8.23 +++ vendor/servo_arc-0.3.0 +++ vendor/sha1-0.10.5 +++ vendor/sha2-0.10.6 +++ vendor/shellexpand-2.1.2 +++ vendor/shlex-1.1.0 +++ vendor/signal-hook-registry-1.4.1 +++ vendor/similar-2.1.0 +++ vendor/similar-2.2.1 +++ vendor/siphasher-0.3.10 +++ vendor/slab-0.4.5 +++ vendor/slab-0.4.8 +++ vendor/slice-group-by-0.3.1 +++ vendor/smallvec-1.10.0 +++ vendor/smallvec-1.8.0 +++ vendor/snap-1.1.0 +++ vendor/socket2-0.4.2 +++ vendor/socket2-0.4.4 +++ vendor/socket2-0.4.9 +++ vendor/socket2-0.5.6 +++ vendor/socket2-0.5.7 +++ vendor/spin-0.5.2 +++ vendor/spin-0.9.8 +++ vendor/spmc-0.3.0 +++ vendor/stringprep-0.1.2 +++ vendor/strip-ansi-escapes-0.1.1 +++ vendor/strsim-0.10.0 +++ vendor/strsim-0.8.0 +++ vendor/str_stack-0.1.0 +++ vendor/subtle-2.4.1 +++ vendor/subtle-2.5.0 +++ vendor/syn-0.11.11 +++ vendor/syn-0.15.44 +++ vendor/syn-1.0.73 +++ vendor/syn-1.0.81 +++ vendor/syn-1.0.85 +++ vendor/syn-1.0.86 +++ vendor/syn-1.0.89 +++ vendor/syn-2.0.41 +++ vendor/syn-2.0.66 +++ vendor/syn-2.0.70 +++ vendor/syn-2.0.90 +++ vendor/sync_wrapper-1.0.1 +++ vendor/synom-0.11.3 +++ vendor/syn-test-suite-0.0.0+test +++ vendor/tabled-0.14.0 +++ vendor/tabled_derive-0.6.0 +++ vendor/tar-0.4.38 +++ vendor/tar-0.4.42 +++ vendor/target-lexicon-0.12.16 +++ vendor/tempdir-0.3.7 +++ vendor/tempfile-3.10.1 +++ vendor/tempfile-3.3.0 +++ vendor/tempfile-3.4.0 +++ vendor/tera-1.19.1 +++ vendor/termcolor-1.1.2 +++ vendor/termcolor-1.1.3 +++ vendor/termcolor-1.2.0 +++ vendor/terminal_size-0.1.17 +++ vendor/terminal_size-0.4.0 +++ vendor/textwrap-0.11.0 +++ vendor/textwrap-0.15.0 +++ vendor/thiserror-1.0.40 +++ vendor/thiserror-1.0.63 +++ vendor/thiserror-1.0.65 +++ vendor/thiserror-2.0.3 +++ vendor/thiserror-impl-1.0.40 +++ vendor/thiserror-impl-1.0.63 +++ vendor/thiserror-impl-1.0.65 +++ vendor/thiserror-impl-2.0.3 +++ vendor/thousands-0.2.0 +++ vendor/thread-id-2.0.0 +++ vendor/thread_local-0.2.7 +++ vendor/thread_local-0.3.6 +++ vendor/thread_local-1.1.3 +++ vendor/thread_local-1.1.4 +++ vendor/tikv-jemallocator-0.5.4 +++ vendor/tikv-jemalloc-ctl-0.5.4 +++ vendor/tikv-jemalloc-sys-0.5.4+5.3.0-patched +++ vendor/tikv-jemalloc-sys-0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7 +++ vendor/time-0.1.44 +++ vendor/time-0.3.36 +++ vendor/time-macros-0.2.18 +++ vendor/tinyvec-1.5.1 +++ vendor/tinyvec-1.6.0 +++ vendor/tinyvec-1.8.0 +++ vendor/tinyvec_macros-0.1.0 +++ vendor/tls_codec-0.4.1 +++ vendor/tls_codec_derive-0.4.1 +++ vendor/tokio-1.16.1 +++ vendor/tokio-1.17.0 +++ vendor/tokio-1.26.0 +++ vendor/tokio-1.37.0 +++ vendor/tokio-macros-1.7.0 +++ vendor/tokio-macros-1.8.2 +++ vendor/tokio-native-tls-0.3.0 +++ vendor/tokio-native-tls-0.3.1 +++ vendor/tokio-postgres-0.7.7 +++ vendor/tokio-rustls-0.26.0 +++ vendor/tokio-stream-0.1.15 +++ vendor/tokio-stream-0.1.8 +++ vendor/tokio-test-0.4.2 +++ vendor/tokio-util-0.6.9 +++ vendor/tokio-util-0.7.7 +++ vendor/toml-0.5.8 +++ vendor/toml_datetime-0.6.5 +++ vendor/toml_edit-0.12.6 +++ vendor/toml_edit-0.22.20 +++ vendor/tower-0.4.11 +++ vendor/tower-0.4.13 +++ vendor/tower-layer-0.3.1 +++ vendor/tower-layer-0.3.3 +++ vendor/tower-service-0.3.1 +++ vendor/tower-service-0.3.2 +++ vendor/tower-service-0.3.3 +++ vendor/tracing-0.1.29 +++ vendor/tracing-0.1.32 +++ vendor/tracing-attributes-0.1.18 +++ vendor/tracing-attributes-0.1.27 +++ vendor/tracing-core-0.1.21 +++ vendor/tracing-core-0.1.23 +++ vendor/trybuild-1.0.52 +++ vendor/trycmd-0.12.2 +++ vendor/try-lock-0.2.3 +++ vendor/try-lock-0.2.4 +++ vendor/try-lock-0.2.5 +++ vendor/typenum-1.15.0 +++ vendor/typenum-1.16.0 +++ vendor/ucd-trie-0.1.5 +++ vendor/ucd-trie-0.1.6 +++ vendor/ucd-util-0.1.8 +++ vendor/unicase-2.6.0 +++ vendor/unicase-2.7.0 +++ vendor/unic-char-property-0.9.0 +++ vendor/unic-char-range-0.9.0 +++ vendor/unic-common-0.9.0 +++ vendor/unicode-bidi-0.3.12 +++ vendor/unicode-bidi-0.3.15 +++ vendor/unicode-bidi-0.3.7 +++ vendor/unicode-ident-1.0.12 +++ vendor/unicode-ident-1.0.13 +++ vendor/unicode-ident-1.0.8 +++ vendor/unicode-normalization-0.1.19 +++ vendor/unicode-normalization-0.1.22 +++ vendor/unicode-normalization-0.1.23 +++ vendor/unicode-properties-0.1.1 +++ vendor/unicode-width-0.1.10 +++ vendor/unicode-width-0.1.13 +++ vendor/unicode-width-0.1.8 +++ vendor/unicode-width-0.1.9 +++ vendor/unicode-xid-0.0.4 +++ vendor/unicode-xid-0.1.0 +++ vendor/unicode-xid-0.2.2 +++ vendor/unicode-xid-0.2.4 +++ vendor/unic-segment-0.9.0 +++ vendor/unic-ucd-segment-0.9.0 +++ vendor/unic-ucd-version-0.9.0 +++ vendor/untrusted-0.7.1 +++ vendor/untrusted-0.9.0 +++ vendor/url-1.7.2 +++ vendor/url-2.2.2 +++ vendor/url-2.3.1 +++ vendor/url-2.5.2 +++ vendor/utf8parse-0.2.0 +++ vendor/utf8parse-0.2.1 +++ vendor/utf8-ranges-0.1.3 +++ vendor/utf8-ranges-1.0.4 +++ vendor/uuid-0.6.5 +++ vendor/uuid-0.8.2 +++ vendor/uuid-1.3.0 +++ vendor/vec_map-0.8.2 +++ vendor/version_check-0.9.3 +++ vendor/version_check-0.9.4 +++ vendor/vte-0.10.1 +++ vendor/vte_generate_state_changes-0.1.1 +++ vendor/walkdir-2.3.2 +++ vendor/walkdir-2.3.3 +++ vendor/want-0.3.0 +++ vendor/want-0.3.1 +++ vendor/wasi-0.10.0+wasi-snapshot-preview1 +++ vendor/wasi-0.10.2+wasi-snapshot-preview1 +++ vendor/wasm-bindgen-0.2.78 +++ vendor/wasm-bindgen-0.2.79 +++ vendor/wasm-bindgen-0.2.84 +++ vendor/wasm-bindgen-0.2.92 +++ vendor/wasm-bindgen-0.2.93 +++ vendor/wasm-bindgen-backend-0.2.78 +++ vendor/wasm-bindgen-backend-0.2.79 +++ vendor/wasm-bindgen-backend-0.2.84 +++ vendor/wasm-bindgen-backend-0.2.92 +++ vendor/wasm-bindgen-backend-0.2.93 +++ vendor/wasm-bindgen-futures-0.4.29 +++ vendor/wasm-bindgen-futures-0.4.34 +++ vendor/wasm-bindgen-futures-0.4.43 +++ vendor/wasm-bindgen-macro-0.2.78 +++ vendor/wasm-bindgen-macro-0.2.79 +++ vendor/wasm-bindgen-macro-0.2.84 +++ vendor/wasm-bindgen-macro-0.2.92 +++ vendor/wasm-bindgen-macro-0.2.93 +++ vendor/wasm-bindgen-macro-support-0.2.78 +++ vendor/wasm-bindgen-macro-support-0.2.79 +++ vendor/wasm-bindgen-macro-support-0.2.84 +++ vendor/wasm-bindgen-macro-support-0.2.92 +++ vendor/wasm-bindgen-macro-support-0.2.93 +++ vendor/wasm-bindgen-shared-0.2.78 +++ vendor/wasm-bindgen-shared-0.2.79 +++ vendor/wasm-bindgen-shared-0.2.84 +++ vendor/wasm-bindgen-shared-0.2.92 +++ vendor/wasm-bindgen-shared-0.2.93 +++ vendor/wasmtime-jit-icache-coherence-27.0.0 +++ vendor/webpki-roots-0.26.3 +++ vendor/web-sys-0.3.55 +++ vendor/web-sys-0.3.56 +++ vendor/web-sys-0.3.61 +++ vendor/web-sys-0.3.69 +++ vendor/winapi-0.2.8 +++ vendor/winapi-0.3.9 +++ vendor/winapi-build-0.1.1 +++ vendor/winapi-i686-pc-windows-gnu-0.4.0 +++ vendor/winapi-util-0.1.5 +++ vendor/winapi-util-0.1.8 +++ vendor/winapi-util-0.1.9 +++ vendor/winapi-x86_64-pc-windows-gnu-0.4.0 +++ vendor/windows-0.52.0 +++ vendor/windows-0.56.0 +++ vendor/windows-0.57.0 +++ vendor/windows_aarch64_gnullvm-0.42.2 +++ vendor/windows_aarch64_gnullvm-0.48.5 +++ vendor/windows_aarch64_gnullvm-0.52.6 +++ vendor/windows_aarch64_msvc-0.42.2 +++ vendor/windows_aarch64_msvc-0.48.5 +++ vendor/windows_aarch64_msvc-0.52.6 +++ vendor/windows-core-0.52.0 +++ vendor/windows-core-0.56.0 +++ vendor/windows-core-0.57.0 +++ vendor/windows_i686_gnu-0.42.2 +++ vendor/windows_i686_gnu-0.48.5 +++ vendor/windows_i686_gnu-0.52.6 +++ vendor/windows_i686_gnullvm-0.52.6 +++ vendor/windows_i686_msvc-0.42.2 +++ vendor/windows_i686_msvc-0.48.5 +++ vendor/windows_i686_msvc-0.52.6 +++ vendor/windows-implement-0.56.0 +++ vendor/windows-implement-0.57.0 +++ vendor/windows-interface-0.56.0 +++ vendor/windows-interface-0.57.0 +++ vendor/windows-registry-0.2.0 +++ vendor/windows-result-0.1.2 +++ vendor/windows-result-0.2.0 +++ vendor/windows-strings-0.1.0 +++ vendor/windows-sys-0.42.0 +++ vendor/windows-sys-0.45.0 +++ vendor/windows-sys-0.48.0 +++ vendor/windows-sys-0.52.0 +++ vendor/windows-sys-0.59.0 +++ vendor/windows-targets-0.42.2 +++ vendor/windows-targets-0.48.5 +++ vendor/windows-targets-0.52.6 +++ vendor/windows_x86_64_gnu-0.42.2 +++ vendor/windows_x86_64_gnu-0.48.5 +++ vendor/windows_x86_64_gnu-0.52.6 +++ vendor/windows_x86_64_gnullvm-0.42.2 +++ vendor/windows_x86_64_gnullvm-0.48.5 +++ vendor/windows_x86_64_gnullvm-0.52.6 +++ vendor/windows_x86_64_msvc-0.42.2 +++ vendor/windows_x86_64_msvc-0.48.5 +++ vendor/windows_x86_64_msvc-0.52.6 +++ vendor/winnow-0.5.30 +++ vendor/winnow-0.6.18 +++ vendor/winreg-0.10.1 +++ vendor/winsplit-0.1.0 +++ vendor/x509-cert-0.2.5 +++ vendor/xattr-0.2.2 +++ vendor/xattr-0.2.3 +++ vendor/yaml-rust-0.4.5 +++ vendor/yansi-0.5.0 +++ vendor/zerocopy-0.7.32 +++ vendor/zerocopy-derive-0.7.32 +++ vendor/zeroize-1.7.0 +++ vendor/zeroize_derive-1.4.2 +++# DO NOT EDIT above, AUTOGENERATED +++ +++Files: C*.md +++ R*.md +++ Cargo.lock +++ Cargo.toml +++ COPYRIGHT +++ LICENSE* +++ compiler/* +++ configure +++ config.example.toml +++ git-commit-hash +++ git-commit-info +++ library/* +++ src/README.md +++ src/bootstrap/* +++ src/build_helper/* +++ src/ci/* +++ src/doc/* +++ src/etc/* +++ src/lib* +++ src/rust* +++ src/stage0 +++ src/tools/* +++ src/version +++ tests/* +++ version +++ x.py +++ .cargo/config.toml +++Copyright: 2006-2009 Graydon Hoare +++ 2009-2012 Mozilla Foundation +++ 2012-2017 The Rust Project Developers (see AUTHORS.txt) +++License: MIT or Apache-2.0 +++ +++Files: src/librustdoc/html/static/fonts/FiraSans* +++Copyright: 2014, Mozilla Foundation, 2014, Telefonica S.A. +++License: SIL-OPEN-FONT +++ +++Files: src/librustdoc/html/static/fonts/NanumBarun* +++Copyright: 2010 NAVER Corporation +++License: SIL-OPEN-FONT +++ +++Files: src/librustdoc/html/static/fonts/SourceCodePro* +++Copyright: 2010, 2012 Adobe Systems Incorporated +++License: SIL-OPEN-FONT +++ +++Files: src/librustdoc/html/static/fonts/SourceSerif4* +++Copyright: 2014-2021 Adobe Systems Incorporated +++License: SIL-OPEN-FONT +++ +++Files: vendor/compiler_builtins-*/* +++Copyright: 2016-2019 Jorge Aparicio +++License: MIT or Apache-2.0 +++Comment: see https://github.com/rust-lang-nursery/compiler-builtins +++ +++Files: vendor/ahash-*/* +++Copyright: 2019-2022 Tom Kaitchuck +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/tkaitchuck/ahash +++ +++Files: vendor/android_system_properties-*/* +++Copyright: 2022-2022 Nicolas Silva +++License: MIT or Apache-2.0 +++Comment: see https://github.com/nical/android_system_properties +++ +++Files: vendor/anes-*/* +++Copyright: 2019-2023 Robert Vojta +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/zrzka/anes-rs +++ +++Files: +++ vendor/anstream-*/* +++ vendor/anstyle-*/* +++ vendor/anstyle-lossy-*/* +++ vendor/anstyle-parse-*/* +++ vendor/anstyle-svg-*/* +++ vendor/anstyle-query-*/* +++ vendor/colorchoice-*/* +++Copyright: 2023-2024 Ed Page +++License: MIT or Apache-2.0 +++Comment: see https://github.com/rust-cli/anstyle +++ +++Files: vendor/ar_archive_writer-*/* +++Copyright: 2003-2017 University of Illinois at Urbana-Champaign. +++License: Apache-2.0 with LLVM exception +++Comment: +++ see https://github.com/rust-lang/ar_archive_writer +++ derived from LLVM code +++ +++Files: +++ vendor/arbitrary-*/* +++ vendor/derive_arbitrary-*/* +++Copyright: 2017-2024 The Rust-Fuzz Project Developers +++ 2017-2024 Nick Fitzgerald +++ 2017-2024 Manish Goregaokar +++ 2017-2024 Simonas Kazlauskas +++ 2017-2024 Brian L. Troutwine +++ 2017-2024 Corey Farwell +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rust-fuzz/arbitrary/ +++ +++Files: +++ vendor/bitflags-*/* +++ vendor/cc-*/* +++ vendor/cmake-*/* +++ vendor/env_filter-*/* +++ vendor/env_logger-*/* +++ vendor/getopts-*/* +++ vendor/glob-*/* +++ vendor/libc-*/* +++ vendor/log-*/* +++ vendor/regex-*/* +++ vendor/regex-1.*/* +++ vendor/regex-lite-*/* +++ vendor/regex-syntax-*/* +++ vendor/regex-syntax-0.*/* +++ vendor/rustc-hash-*/* +++ vendor/rustc-stable-hash-*/* +++ vendor/time-*/* +++Copyright: 2010-2024 The Rust Project Developers +++License: MIT or Apache-2.0 +++Comment: +++ This is a collection of external crates embedded here to bootstrap cargo. +++ Most of them come from the original upstream Rust project, thus share the +++ same MIT/Apache-2.0 dual-license. See https://github.com/rust-lang. +++ Exceptions are noted below. +++ +++Files: +++ vendor/time-core-*/* +++Copyright: 2019-2023 Jacob Pratt +++ 2019-2023 Time contributors +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/time-rs/time +++ +++Files: +++ vendor/core-foundation-*/* +++ vendor/core-foundation-sys-*/* +++Copyright: 2012-2024 The Servo Project Developers +++License: MIT or Apache-2.0 +++Comment: see https://github.com/servo/core-foundation-rs +++ +++Files: vendor/num-conv-*/* +++Copyright: 2023-2023 Jacob Pratt +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/jhpratt/num-conv +++ +++Files: +++ vendor/num-0.*/* +++ vendor/num-bigint-0.*/* +++ vendor/num-complex-0.*/* +++ vendor/num-integer-0.*/* +++ vendor/num-iter-0.*/* +++ vendor/num-rational-0.*/* +++ vendor/num-traits-*/* +++Copyright: 2014-2024 The Rust Project Developers +++License: MIT or Apache-2.0 +++Comment: see https://github.com/rust-num/num +++ +++Files: +++ vendor/string_cache-*/* +++ vendor/string_cache_codegen-*/* +++Copyright: 2015-2017 Alex Crichton +++ 2015-2017 Keegan McAllister +++ 2015-2017 Chris Morgan +++ 2014-2017 The html5ever Project Developers +++ 2014-2017 The Servo Project Developers +++ 2013-2017 Simon Sapin +++License: MIT or Apache-2.0 +++Comment: see https://github.com/servo/ +++ +++Files: +++ vendor/getrandom-*/* +++ vendor/rand-*/* +++ vendor/rand_chacha-*/* +++ vendor/rand_core-*/* +++ vendor/rand_xorshift-*/* +++ vendor/rand_xoshiro-*/* +++Copyright: 2010-2019 The Rand Project Developers +++ 2010-2019 The Rust Project Developers +++License: MIT or Apache-2.0 +++Comment: +++ see https://github.com/rust-random/getrandom +++ see https://github.com/rust-random/rand +++ see https://github.com/rust-random/small-rngs +++ +++Files: vendor/cfg_aliases-*/* +++Copyright: 2020-2024 Zicklag +++License: MIT +++Comment: see https://github.com/katharostech/cfg_aliases +++ +++Files: +++ vendor/cfg-if-*/* +++ vendor/filetime-*/* +++ vendor/flate2-*/* +++ vendor/fnv-*/* +++ vendor/jobserver-*/* +++ vendor/lzma-sys-*/* +++ vendor/pkg-config-*/* +++ vendor/proc-macro2-*/* +++ vendor/rustc-demangle-*/* +++ vendor/scoped-tls-*/* +++ vendor/tar-*/* +++ vendor/xz2-*/* +++Copyright: 2014-2020 Alex Crichton +++ 2015-2017 The Rust Project Developers +++License: MIT or Apache-2.0 +++Comment: see https://github.com/alexcrichton/ +++ +++Files: +++ vendor/chalk-derive-0.*/* +++ vendor/chalk-ir-0.*/* +++ vendor/chalk-recursive-0.*/* +++ vendor/chalk-solve-0.*/* +++Copyright: 2015-2025 Rust Compiler Team +++ 2015-2025 Chalk developers +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rust-lang/chalk +++ +++Files: vendor/crunchy-*/* +++Copyright: 2018-2024 Vurich +++License: MIT +++ +++Files: vendor/dlmalloc-*/* +++Copyright: 2017-2019 Alex Crichton +++License: MIT or Apache-2.0 +++Comment: see https://github.com/alexcrichton/dlmalloc-rs +++ +++Files: vendor/dlmalloc-*/src/dlmalloc.c +++Copyright: 2000-2012 Doug Lea +++License: CC0-1.0 +++ +++Files: vendor/addr2line-*/* +++Copyright: +++ 2016-2021 Nick Fitzgerald +++ 2016-2021 Philip Craig +++ 2016-2021 Jon Gjengset +++ 2016-2021 Noah Bergbauer +++License: Apache-2.0 or MIT +++Comment: see https://github.com/gimli-rs/addr2line +++ +++Files: +++ vendor/adler-*/* +++Copyright: 2020-2021 Jonas Schievink +++License: 0BSD or MIT or Apache-2.0 +++Comment: see https://github.com/jonas-schievink/adler.git +++ +++Files: vendor/adler2-*/* +++Copyright: 2020-2024 Jonas Schievink +++ 2020-2024 oyvindln +++License: 0BSD OR MIT OR Apache-2.0 +++Comment: see https://github.com/oyvindln/adler2 +++ +++Files: vendor/allocator-api2-*/* +++Copyright: 2023-2024 Zakarum +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/zakarumych/allocator-api2 +++ +++Files: vendor/always-assert-*/* +++Copyright: 2021-2021 Aleksey Kladov +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/matklad/always-assert +++ +++Files: vendor/ammonia-*/* +++Copyright: 2015-2018 Michael Howell +++License: MIT or Apache-2.0 +++Comment: see https://github.com/notriddle/ammonia +++ +++Files: vendor/android-tzdata-*/* +++Copyright: 2023-2023 RumovZ +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/RumovZ/android-tzdata +++ +++Files: vendor/annotate-snippets-*/* +++Copyright: 2018-2020 Zibi Braniecki +++License: Apache-2.0 or MIT +++Comment: see https://github.com/zbraniecki/annotate-snippets-rs +++ +++Files: vendor/aho-corasick-*/* +++ vendor/memchr-*/* +++Copyright: 2015 Andrew Gallant +++ 2015-2018 bluss +++License: MIT or Unlicense +++Comment: see upstream projects, +++ * https://github.com/BurntSushi/aho-corasick +++ * https://github.com/BurntSushi/rust-memchr +++ +++Files: vendor/arc-swap-*/* +++Copyright: 2018-2024 Michal 'vorner' Vaner +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/vorner/arc-swap +++ +++Files: vendor/arrayref-*/* +++Copyright: 2015-2024 David Roundy +++License: BSD-2-Clause +++Comment: see https://github.com/droundy/arrayref +++ +++Files: vendor/autocfg-*/* +++Copyright: 2018-2020 Josh Stone +++License: Apache-2.0 or MIT +++ +++Files: vendor/backtrace-*/* +++Copyright: 2015-2022 The Rust Project Developers +++License: MIT or Apache-2.0 +++Comment: see https://github.com/rust-lang/backtrace-rs +++ +++Files: vendor/base64-*/* +++Copyright: 2015-2024 Alice Maz +++ 2015-2024 Marshall Pierce +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/marshallpierce/rust-base64 +++ +++Files: vendor/basic-toml-*/* +++Copyright: 2014-2023 Alex Crichton +++ 2014-2023 David Tolnay +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/dtolnay/basic-toml +++ +++Files: vendor/bincode-*/* +++Copyright: 2014-2024 Ty Overby +++ 2014-2024 Francesco Mazzoli +++ 2014-2024 David Tolnay +++ 2014-2024 Zoey Riordan +++License: MIT +++Comment: see https://github.com/servo/bincode +++ +++Files: vendor/bitmaps-*/* +++Copyright: 2019-2024 Bodil Stokke +++License: MPL-2.0+ +++Comment: see https://github.com/bodil/bitmaps +++ +++Files: vendor/bit-set-*/* +++Copyright: 2015-2023 Alexis Beingessner +++License: MIT or Apache-2.0 +++Comment: see https://github.com/contain-rs/bit-set +++ +++Files: vendor/bit-vec-*/* +++Copyright: 2015-2023 Alexis Beingessner +++License: MIT or Apache-2.0 +++Comment: see https://github.com/contain-rs/bit-vec +++ +++Files: +++ vendor/base16ct-*/* +++ vendor/base64ct-*/* +++ vendor/block-buffer-*/* +++ vendor/const-oid-*/* +++ vendor/cpufeatures-*/* +++ vendor/crypto-bigint-*/* +++ vendor/crypto-common-*/* +++ vendor/der-*/* +++ vendor/digest-*/* +++ vendor/ecdsa-*/* +++ vendor/elliptic-curve-*/* +++ vendor/hkdf-*/* +++ vendor/hmac-*/* +++ vendor/md-5-*/* +++ vendor/p384-*/* +++ vendor/pem-rfc7468-*/* +++ vendor/pkcs8-*/* +++ vendor/primeorder-*/* +++ vendor/rfc6979-*/* +++ vendor/sec1-*/* +++ vendor/sha1-*/* +++ vendor/sha2-*/* +++ vendor/signature-*/* +++ vendor/spki-*/* +++ vendor/zeroize-*/* +++Copyright: 2015-2024 RustCrypto Developers +++License: MIT or Apache-2.0 +++Comment: +++ see https://github.com/RustCrypto/elliptic-curves +++ see https://github.com/RustCrypto/formats +++ see https://github.com/RustCrypto/hashes +++ see https://github.com/RustCrypto/signatures +++ see https://github.com/RustCrypto/traits +++ see https://github.com/RustCrypto/utils +++ see https://github.com/RustCrypto/KDFs +++ see https://github.com/RustCrypto/MACs +++ +++Files: vendor/blake3-*/* +++Copyright: 2019-2024 Jack O'Connor +++ 2019-2024 Samuel Neves +++License: CC0-1.0 OR Apache-2.0 OR Apache-2.0 with LLVM exception +++Comment: see https://github.com/BLAKE3-team/BLAKE3 +++ +++Files: vendor/borsh-*/* +++Copyright: 2019-2024 Near Inc +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/near/borsh-rs +++ +++Files: +++ vendor/bstr-*/* +++ vendor/bstr-1.*/* +++Copyright: 2018-2024 Andrew Gallant +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/BurntSushi/bstr +++ +++Files: vendor/bumpalo-*/* +++Copyright: 2018-2024 Nick Fitzgerald +++License: MIT or Apache-2.0 +++Comment: see https://github.com/fitzgen/bumpalo +++ +++Files: vendor/bytecount-*/* +++Copyright: 2016-2020 Andre Bogus +++ 2016-2020 Joshua Landau +++License: Apache-2.0 or MIT +++Comment: see https://github.com/llogiq/bytecount +++ +++Files: vendor/byteorder-*/* +++Copyright: 2015-2023 Andrew Gallant +++License: Unlicense OR MIT +++Comment: see https://github.com/BurntSushi/byteorder +++ +++Files: vendor/bytesize-*/* +++Copyright: 2015-2023 Hyunsik Choi +++License: Apache-2.0 +++Comment: see https://github.com/hyunsik/bytesize/ +++ +++Files: +++ vendor/globset-*/* +++ vendor/globset-0.*/* +++ vendor/ignore-*/* +++ vendor/ignore-0.*/* +++ vendor/same-file-*/* +++ vendor/termcolor-*/* +++ vendor/walkdir-*/* +++Copyright: 2015-2020 Andrew Gallant +++License: Unlicense or MIT +++Comment: +++ see https://github.com/BurntSushi/same-file +++ see https://github.com/BurntSushi/walkdir +++ see https://github.com/BurntSushi/winapi-util +++ see https://github.com/BurntSushi/ripgrep/tree/master/globset +++ see https://github.com/BurntSushi/ripgrep/tree/master/ignore +++ see https://github.com/BurntSushi/ripgrep/tree/master/termcolor +++ +++Files: vendor/camino-*/* +++Copyright: 2020-2022 Without Boats +++ 2020-2022 Ashley Williams +++ 2020-2022 Steve Klabnik +++ 2020-2022 Rain +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/withoutboats/camino +++ +++Files: +++ vendor/cargo_metadata-*/* +++ vendor/cargo_metadata-0.*/* +++Copyright: 2016-2020 Oliver Schneider +++License: MIT +++Comment: +++ see https://github.com/oli-obk/cargo_metadata +++ +++Files: vendor/cargo-platform-*/* +++Copyright: 2019-2022 The Cargo Project Developers +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rust-lang/cargo +++ +++Files: vendor/cast-*/* +++Copyright: 2014-2021 Jorge Aparicio +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/japaric/cast.rs +++ +++Files: vendor/ppv-lite86-*/* +++Copyright: 2019-2019 The CryptoCorrosion Contributors +++License: MIT or Apache-2.0 +++Comment: see https://github.com/cryptocorrosion/cryptocorrosion +++ +++Files: vendor/chrono-*/* +++Copyright: 2014-2018 Kang Seonghoon +++License: MIT or Apache-2.0 +++Comment: see https://github.com/chronotope/chrono +++ +++Files: +++ vendor/ciborium-*/* +++ vendor/ciborium-io-*/* +++ vendor/ciborium-ll-*/* +++Copyright: 2020-2024 Nathaniel McCallum +++License: Apache-2.0 +++Comment: see https://github.com/enarx/ciborium +++ +++Files: +++ vendor/clap-*/* +++ vendor/clap_builder-*/* +++ vendor/clap_complete-*/* +++ vendor/clap_derive-*/* +++ vendor/clap_lex-*/* +++Copyright: 2015-2022 Kevin K. +++License: MIT +++Comment: see https://github.com/clap-rs/clap +++ +++Files: vendor/clap-cargo-*/* +++Copyright: 2019-2024 Ed Page +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/crate-ci/clap-cargo +++ +++Files: vendor/clru-*/* +++Copyright: 2020-2023 marmeladema +++License: MIT +++Comment: see https://github.com/marmeladema/clru-rs +++ +++Files: vendor/color-eyre-*/* +++Copyright: 2020-2023 Jane Lusby +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/yaahc/color-eyre +++ +++Files: vendor/color-spantrace-*/* +++Copyright: 2020-2024 Jane Lusby +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/yaahc/color-spantrace +++ +++Files: vendor/colored-*/* +++Copyright: 2016-2020 Thomas Wickham +++License: MPL-2.0 +++Comment: see https://github.com/mackwic/colored +++ +++Files: +++ vendor/color-print-*/* +++ vendor/color-print-proc-macro-*/* +++Copyright: 2021-2024 Johann David +++License: MIT OR Apache-2.0 +++Comment: see https://gitlab.com/yolenoyer/color-print +++ +++Files: vendor/comma-*/* +++Copyright: 2019-2023 Ethan McTague +++License: MIT +++Comment: see https://github.com/emctague/comma +++ +++Files: vendor/constant_time_eq-*/* +++Copyright: 2015-2024 Cesar Eduardo Barros +++License: CC0-1.0 OR MIT-0 OR Apache-2.0 +++Comment: see https://github.com/cesarb/constant_time_eq +++ +++Files: +++ vendor/console-*/* +++ vendor/indicatif-*/* +++Copyright: 2017-2024 Armin Ronacher +++License: MIT +++Comment: +++ see https://github.com/console-rs/console +++ see https://github.com/console-rs/indicatif +++ +++Files: vendor/content_inspector-*/* +++Copyright: 2018-2018 David Peter +++License: MIT or Apache-2.0 +++Comment: see https://github.com/sharkdp/content_inspector +++ +++Files: vendor/countme-*/* +++Copyright: 2021-2022 Aleksey Kladov +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/matklad/countme +++ +++Files: vendor/cov-mark-*/* +++Copyright: 2020-2021 Aleksey Kladov +++ 2020-2021 Simonas Kazlauskas +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/matklad/cov-mark +++ +++Files: vendor/crc32fast-*/* +++Copyright: 2018-2019 Sam Rijs +++ 2018-2019 Alex Crichton +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/srijs/rust-crc32fast +++ +++Files: +++ vendor/criterion-*/* +++ vendor/criterion-plot-*/* +++Copyright: 2014-2024 Jorge Aparicio +++ 2014-2024 Brook Heisler +++License: Apache-2.0 or MIT +++Comment: see https://github.com/bheisler/criterion.rs +++ +++Files: +++ vendor/crossbeam-channel-*/* +++ vendor/crossbeam-deque-*/* +++ vendor/crossbeam-epoch-*/* +++ vendor/crossbeam-utils-*/* +++Copyright: 2015-2022 The Crossbeam Project Developers +++License: MIT or Apache-2.0 +++Comment: see https://github.com/crossbeam-rs +++ +++Files: vendor/ct-codecs-*/* +++Copyright: 2020-2022 Frank Denis +++License: MIT +++Comment: see https://github.com/jedisct1/rust-ct-codecs +++ +++Files: vendor/ctrlc-*/* +++Copyright: 2015-2024 Antti Keränen +++License: MIT or Apache-2.0 +++Comment: see https://github.com/Detegr/rust-ctrlc.git +++ +++Files: +++ vendor/curl-*/* +++ vendor/curl-sys-*/* +++Copyright: 2014-2024 Alex Crichton +++License: MIT +++Comment: see https://github.com/alexcrichton/curl-rust +++ +++Files: +++ vendor/darling-*/* +++ vendor/darling_core-*/* +++ vendor/darling_macro-*/* +++Copyright: 2017-2024 Ted Driggs +++License: MIT +++Comment: see https://github.com/TedDriggs/darling +++ +++Files: vendor/dashmap-5.*/* +++Copyright: 2019-2024 Acrimon +++License: MIT +++Comment: see https://github.com/xacrimon/dashmap +++ +++Files: vendor/datafrog-*/* +++Copyright: +++ 2018 Frank McSherry +++ 2018 The Rust Project Developers +++ 2018 Datafrog Developers +++License: Apache-2.0 or MIT +++Comment: see https://github.com/rust-lang-nursery/datafrog +++ +++Files: vendor/dateparser-*/* +++Copyright: 2021-2024 Rollie Ma +++License: MIT +++Comment: see https://github.com/waltzofpearls/dateparser +++ +++Files: +++ vendor/dbus-*/* +++ vendor/libdbus-sys-*/* +++Copyright: 2014-2024 David Henningsson +++License: Apache-2.0 or MIT +++Comment: see https://github.com/diwic/dbus-rs +++ +++Files: vendor/deranged-*/* +++Copyright: 2020-2023 Jacob Pratt +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/jhpratt/deranged +++ +++Files: +++ vendor/derive_builder-*/* +++ vendor/derive_builder_core-*/* +++ vendor/derive_builder_macro-*/* +++Copyright: 2016-2024 Colin Kiegel +++ 2016-2024 Pascal Hertleif +++ 2016-2024 Jan-Erik Rediger +++ 2016-2024 Ted Driggs +++License: MIT or Apache-2.0 +++Comment: see https://github.com/colin-kiegel/rust-derive-builder +++ +++Files: vendor/derive_setters-*/* +++Copyright: 2019-2023 Lymia Aluysia +++License: MIT or Apache-2.0 +++Comment: see https://github.com/Lymia/derive_setters +++ +++Files: vendor/derive-where-1.*/* +++Copyright: 2021 Roland Fredenhagen +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/ModProg/derive-where +++ +++Files: vendor/diff-*/* +++Copyright: 2015-2017 Utkarsh Kukreti +++License: MIT or Apache-2.0 +++Comment: see https://github.com/utkarshkukreti/diff.rs +++ +++Files: vendor/directories-5.0.1/* +++Copyright: 2017-2023 Simon Ochsenreither +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/soc/directories-rs +++ +++Files: +++ vendor/anyhow-*/* +++ vendor/dissimilar-*/* +++ vendor/itoa-*/* +++ vendor/itoa-0.*/* +++ vendor/quote-*/* +++ vendor/syn-*/* +++ vendor/syn-1.*/* +++ vendor/unicode-ident-*/* +++Copyright: 2016-2024 David Tolnay +++License: MIT or Apache-2.0 +++Comment: +++ see https://github.com/dtolnay/anyhow +++ see https://github.com/dtolnay/dissimilar +++ see https://github.com/dtolnay/itoa +++ see https://github.com/dtolnay/quote +++ see https://github.com/dtolnay/syn +++ see https://github.com/dtolnay/unicode-ident +++ +++Files: +++ vendor/arrayvec-*/* +++ vendor/either-*/* +++ vendor/itertools-*/* +++ vendor/itertools-0.*/* +++ vendor/maplit-*/* +++ vendor/scopeguard-*/* +++Copyright: 2014-2020 bluss +++License: MIT or Apache-2.0 +++Comment: +++ see https://github.com/bluss/rust-itertools +++ see https://github.com/bluss/either +++ see https://github.com/bluss/arrayvec +++ see https://github.com/bluss/fixedbitset +++ see https://github.com/bluss/maplit +++ see https://github.com/bluss/scopeguard +++ +++Files: +++ vendor/dirs-*/* +++ vendor/dirs-sys-0.*/* +++Copyright: 2015-2024 Simon Ochsenreither +++ 2015-2024 dirs-rs contributors +++License: MIT OR Apache-2.0 +++Comment: +++ see https://github.com/dirs-dev/dirs-rs +++ see https://github.com/dirs-dev/dirs-sys-rs +++ +++Files: +++ vendor/dirs-next-*/* +++ vendor/dirs-sys-next-*/* +++Copyright: 2017-2021 The @xdg-rs members +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/xdg-rs/dirs +++ +++Files: vendor/displaydoc-*/* +++Copyright: 2019-2023 Jane Lusby +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/yaahc/displaydoc +++ +++Files: vendor/drop_bomb-*/* +++Copyright: 2018-2020 Aleksey Kladov +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/matklad/drop_bomb +++ +++Files: vendor/doc-comment-*/* +++Copyright: 2018-2020 Guillaume Gomez +++License: MIT +++Comment: see https://github.com/GuillaumeGomez/doc-comment +++ +++Files: vendor/dot-0.*/* +++Copyright: 2015-2023 The Rust Project Developers +++ 2015-2023 Graham Dennis +++License: MIT or Apache-2.0 +++Comment: see https://github.com/GrahamDennis/dot-rust +++ +++Files: vendor/dunce-*/* +++Copyright: 2017-2023 Kornel +++License: CC0-1.0 +++Comment: see https://gitlab.com/kornelski/dunce +++ +++Files: vendor/dyn-clone-1.*/* +++Copyright: 2018-2024 David Tolnay +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/dtolnay/dyn-clone +++ +++Files: vendor/ed25519-compact-*/* +++Copyright: 2020-2024 Frank Denis +++License: MIT +++Comment: see https://github.com/jedisct1/rust-ed25519-compact +++ +++Files: vendor/elasticlunr-rs-*/* +++Copyright: 2017-2018 Matt Ickstadt +++License: MIT or Apache-2.0 +++Comment: see https://github.com/mattico/elasticlunr-rs +++ +++Files: vendor/elsa-*/* +++Copyright: 2018-2023 Manish Goregaokar +++License: MIT or Apache-2.0 +++Comment: see https://github.com/manishearth/elsa +++ +++Files: vendor/ena-*/* +++Copyright: 2015-2020 Niko Matsakis +++License: MIT or Apache-2.0 +++Comment: see https://github.com/nikomatsakis/ena +++ +++Files: vendor/encoding_rs-*/* +++Copyright: 2016-2024 Henri Sivonen +++License: (Apache-2.0 OR MIT) AND BSD-3-Clause +++Comment: see https://github.com/hsivonen/encoding_rs +++ +++Files: vendor/erased-serde-*/* +++Copyright: 2016-2024 David Tolnay +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/dtolnay/erased-serde +++ +++Files: vendor/errno-*/* +++Copyright: 2015-2022 Chris Wong +++License: MIT or Apache-2.0 +++Comment: see https://github.com/lambda-fairy/rust-errno +++ +++Files: vendor/equivalent-*/* +++Copyright: 2016-2023 Josh Stone +++License: Apache-2.0 OR MIT +++Comment: see https://github.com/cuviper/equivalent +++ +++Files: vendor/escargot-*/* +++Copyright: 2018-2024 Ed Page +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/crate-ci/escargot.git +++ +++Files: vendor/expect-test-*/* +++Copyright: 2020-2022 rust-analyzer developers +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rust-analyzer/expect-test +++ +++Files: vendor/eyre-*/* +++Copyright: 2019-2024 David Tolnay +++ 2019-2024 Jane Lusby +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/yaahc/eyre +++ +++Files: vendor/fallible-iterator-*/* +++Copyright: 2016-2019 Steven Fackler +++License: MIT or Apache-2.0 +++Comment: see https://github.com/sfackler/rust-fallible-iterator +++ +++Files: vendor/fallible-streaming-iterator-*/* +++Copyright: 2016-2018 Steven Fackler +++License: MIT or Apache-2.0 +++Comment: see https://github.com/sfackler/fallible-streaming-iterator +++ +++Files: vendor/faster-hex-*/* +++Copyright: 2018-2023 zhangsoledad <787953403@qq.com> +++License: MIT +++Comment: see https://github.com/NervosFoundation/faster-hex +++ +++Files: vendor/fastrand-*/* +++Copyright: 2020-2023 Stjepan Glavina +++License: Apache-2.0 OR MIT +++Comment: see https://github.com/smol-rs/fastrand +++ +++Files: vendor/fd-lock-*/* +++Copyright: 2019-2022 Yoshua Wuyts +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/yoshuawuyts/fd-lock +++ +++Files: vendor/ff-*/* +++Copyright: 2017-2023 Sean Bowe +++ 2017-2023 Jack Grigg +++License: MIT or Apache-2.0 +++Comment: see https://github.com/zkcrypto/ff +++ +++Files: vendor/fiat-crypto-*/* +++Copyright: 2015-2024 Fiat Crypto library authors +++License: MIT OR Apache-2.0 OR BSD-1-Clause-fiat-crypto +++Comment: see https://github.com/mit-plv/fiat-crypto +++ +++Files: vendor/field-offset-*/* +++Copyright: 2016-2023 Diggory Blake +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/Diggsey/rust-field-offset +++ +++Files: vendor/fixedbitset-0.*/* +++Copyright: 2015-2024 bluss +++License: MIT or Apache-2.0 +++Comment: see https://github.com/petgraph/fixedbitset +++ +++Files: +++ vendor/fluent-bundle-*/* +++ vendor/fluent-syntax-*/* +++ vendor/intl-memoizer-*/* +++Copyright: 2016-2022 Zibi Braniecki +++ 2016-2022 Staś Małolepszy +++ 2016-2022 Manish Goregaokar +++License: Apache-2.0 or MIT +++Comment: see https://github.com/projectfluent/fluent-rs +++ +++Files: vendor/fluent-langneg-*/* +++Copyright: 2017-2021 Zibi Braniecki +++License: Apache-2.0 +++Comment: see https://github.com/projectfluent/fluent-langneg-rs +++ +++Files: vendor/foldhash-0.*/* +++Copyright: 2024-2024 Orson Peters +++License: Zlib +++Comment: see https://github.com/orlp/foldhash +++ +++Files: +++ vendor/foreign-types-*/* +++ vendor/foreign-types-shared-*/* +++Copyright: 2017-2023 Steven Fackler +++License: MIT or Apache-2.0 +++Comment: see https://github.com/sfackler/foreign-types +++ +++Files: vendor/fortanix-sgx-abi-*/* +++Copyright: 2015-2019 Jethro Beekman +++License: MPL-2.0 +++Comment: see https://github.com/fortanix/rust-sgx +++ +++Files: vendor/fs-err-*/* +++Copyright: 2020-2020 Andrew Hickman +++License: MIT or Apache-2.0 +++Comment: see https://github.com/andrewhickman/fs-err +++ +++ +++Files: vendor/fsevent-sys-*/* +++Copyright: 2014-2019 Pierre Baillet +++License: MIT +++Comment: see https://github.com/octplane/fsevent-rust/ +++ +++Files: vendor/fs_extra-*/* +++Copyright: 2017-2023 Denis Kurilenko +++License: MIT +++Comment: see https://github.com/webdesus/fs_extra +++ +++Files: vendor/fst-*/* +++Copyright: 2015-2023 Andrew Gallant +++License: Unlicense or MIT +++Comment: see https://github.com/BurntSushi/fst +++ +++Files: vendor/futf-*/* +++Copyright: 2015-2018 Keegan McAllister +++License: MIT or Apache-2.0 +++Comment: see https://github.com/servo/futf +++ +++Files: +++ vendor/generic-array-*/* +++Copyright: +++ 2015-2020 Bartłomiej Kamiński +++ 2015-2020 Aaron Trent +++License: MIT +++Comment: see https://github.com/fizyk20/generic-array.git +++ +++Files: vendor/gimli-*/* +++Copyright: +++ 2016-2021 Nick Fitzgerald +++ 2016-2021 Philip Craig +++License: Apache-2.0 or MIT +++Comment: see https://github.com/gimli-rs/gimli +++ +++FIles: extra/sha1-checked-*/* +++Copyright: 2024 RustCrypto Developers +++License: MIT or Apache-2.0 +++Comment: see https://github.com/RustCrypto/hashes +++ +++Files: +++ extra/git2/* +++ extra/git2-curl/* +++ extra/libgit2-sys/* +++ vendor/git2-*/* +++ vendor/git2-curl-*/* +++ vendor/libgit2-sys-*/* +++Copyright: 2014-2024 Josh Triplett +++ 2014-2024 Alex Crichton +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rust-lang/git2-rs +++ +++Files: +++ vendor/gix-*/* +++ vendor/gix-actor-*/* +++ vendor/gix-attributes-*/* +++ vendor/gix-bitmap-*/* +++ vendor/gix-chunk-*/* +++ vendor/gix-command-*/* +++ vendor/gix-commitgraph-*/* +++ vendor/gix-config-*/* +++ vendor/gix-config-value-*/* +++ vendor/gix-credentials-*/* +++ vendor/gix-date-*/* +++ vendor/gix-diff-*/* +++ vendor/gix-discover-*/* +++ vendor/gix-features-*/* +++ vendor/gix-filter-*/* +++ vendor/gix-fs-*/* +++ vendor/gix-glob-*/* +++ vendor/gix-hash-*/* +++ vendor/gix-hashtable-*/* +++ vendor/gix-ignore-*/* +++ vendor/gix-index-*/* +++ vendor/gix-lock-*/* +++ vendor/gix-negotiate-*/* +++ vendor/gix-object-*/* +++ vendor/gix-odb-*/* +++ vendor/gix-pack-*/* +++ vendor/gix-packetline-*/* +++ vendor/gix-packetline-blocking-*/* +++ vendor/gix-path-*/* +++ vendor/gix-pathspec-*/* +++ vendor/gix-prompt-*/* +++ vendor/gix-protocol-*/* +++ vendor/gix-quote-*/* +++ vendor/gix-ref-*/* +++ vendor/gix-refspec-*/* +++ vendor/gix-revision-*/* +++ vendor/gix-revwalk-*/* +++ vendor/gix-sec-*/* +++ vendor/gix-submodule-*/* +++ vendor/gix-tempfile-*/* +++ vendor/gix-trace-*/* +++ vendor/gix-transport-*/* +++ vendor/gix-traverse-*/* +++ vendor/gix-url-*/* +++ vendor/gix-utils-*/* +++ vendor/gix-validate-*/* +++ vendor/gix-worktree-*/* +++Copyright: +++ 2018-2024 Conor Davis +++ 2018-2024 Jiahao XU +++ 2018-2024 Sebastian Thiel +++License: MIT or Apache-2.0 +++Comment: see https://github.com/Byron/gitoxide +++ +++Files: vendor/group-*/* +++Copyright: 2018-2023 Sean Bowe +++ 2018-2023 Jack Grigg +++License: MIT or Apache-2.0 +++Comment: see https://github.com/zkcrypto/group +++ +++Files: vendor/gsgdt-*/* +++Copyright: 2020 Vishnunarayan K I +++License: MIT or Apache-2.0 +++Comment: see https://github.com/vn-ki/gsgdt-rs +++ +++Files: vendor/half-*/* +++Copyright: 2016-2024 Kathryn Long +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/starkat99/half-rs +++ +++Files: vendor/handlebars-*/* +++Copyright: 2014-2017 Ning Sun +++License: MIT +++Comment: see https://github.com/sunng87/handlebars-rust +++ +++Files: vendor/hashlink-*/* +++Copyright: 2019-2024 kyren +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/kyren/hashlink +++ +++Files: vendor/heck-*/* +++Copyright: 2017-2018 Without Boats +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/withoutboats/heck +++ +++Files: vendor/hermit-abi-*/* +++Copyright: 2019-2019 Stefan Lankes +++License: MIT or Apache-2.0 +++Comment: see https://github.com/hermitcore/hermit-abi +++ +++Files: vendor/hex-*/* +++Copyright: 2015-2020 KokaKiwi +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/KokaKiwi/rust-hex +++ +++Files: vendor/home-*/* +++Copyright: 2017-2022 Brian Anderson +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/brson/home +++ +++Files: +++ vendor/html5ever-*/* +++ vendor/markup5ever-*/* +++Copyright: 2014-2020 The html5ever Project Developers +++License: MIT or Apache-2.0 +++Comment: see https://github.com/servo/html5ever +++ +++Files: vendor/html-escape-*/* +++Copyright: 2020-2023 Magic Len +++License: MIT +++Comment: see https://github.com/magiclen/html-escape +++ +++Files: vendor/html_parser-0.*/* +++Copyright: 2020-2023 Mathias Iversen +++License: MIT +++Comment: see https://github.com/mathiversen/html-parser +++ +++Files: vendor/http-auth-*/* +++Copyright: 2021-2023 Scott Lamp +++License: MIT or Apache-2.0 +++Comment: see https://github.com/scottlamb/http-auth +++ +++Files: vendor/humansize-*/* +++Copyright: 2016-2022 Leopold Arkham +++License: MIT or Apache-2.0 +++Comment: see https://github.com/LeopoldArkham/humansize +++ +++Files: +++ vendor/humantime-*/* +++Copyright: +++ 2016-2018 Paul Colomiets +++ 2016 The humantime Developers +++ 2016 Pyfisch +++ 2005-2013 Rich Felker +++License: MIT or Apache-2.0 +++ +++Files: vendor/if_chain-*/* +++Copyright: 2016-2020 Chris Wong +++License: MIT or Apache-2.0 +++Comment: see https://github.com/lfairy/if_chain +++ +++Files: +++ vendor/iana-time-zone-*/* +++ vendor/iana-time-zone-haiku-*/* +++Copyright: 2020-2024 Andrew Straw +++ 2020-2024 René Kijewski +++ 2020-2024 Ryan Lopopolo +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/strawlab/iana-time-zone +++ +++Files: +++ vendor/form_urlencoded-*/* +++ vendor/idna-*/* +++ vendor/percent-encoding-*/* +++ vendor/url-*/* +++Copyright: 2013-2021 The rust-url developers +++License: MIT or Apache-2.0 +++Comment: see https://github.com/servo/rust-url/ +++ +++Files: vendor/ident_case-*/* +++Copyright: 2017-2021 Ted Driggs +++License: MIT or Apache-2.0 +++Comment: see https://github.com/TedDriggs/ident_case +++ +++Files: vendor/id-arena-*/* +++Copyright: 2018-2023 Nick Fitzgerald +++ 2018-2023 Aleksey Kladov +++License: MIT or Apache-2.0 +++Comment: see https://github.com/fitzgen/id-arena +++ +++Files: vendor/idna_adapter-*/* +++Copyright: 2024-2024 The rust-url developers +++License: Apache-2.0 OR MIT +++Comment: see https://github.com/hsivonen/idna_adapter +++ +++Files: vendor/im-rc-*/* +++Copyright: 2017-2022 Bodil Stokke +++License: MPL-2.0+ +++Comment: see https://github.com/bodil/im-rs +++ +++Files: vendor/indenter-*/* +++Copyright: 2020-2023 Jane Lusby +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/yaahc/indenter +++ +++Files: vendor/indexmap-*/* +++Copyright: 2016-2019 bluss +++ 2016-2019 Josh Stone +++License: Apache-2.0 or MIT +++Comment: see https://github.com/bluss/indexmap +++ +++Files: +++ vendor/indoc-*/* +++Copyright: 2016-2022 David Tolnay +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/dtolnay/indoc +++ +++Files: vendor/inotify-0.*/* +++Copyright: 2014-2025 Hanno Braun +++ 2014-2025 Félix Saparelli +++ 2014-2025 Cristian Kubis +++ 2014-2025 Frank Denis +++License: ISC +++Comment: see https://github.com/hannobraun/inotify +++ +++Files: vendor/inotify-sys-0.*/* +++Copyright: 2017-2021 Hanno Braun +++License: ISC +++Comment: see https://github.com/hannobraun/inotify-sys +++ +++Files: vendor/intl_pluralrules-*/* +++Copyright: 2018-2021 Kekoa Riggin +++ 2018-2021 Zibi Braniecki +++License: Apache-2.0 or MIT +++Comment: see https://github.com/zbraniecki/pluralrules +++ +++Files: vendor/is_executable-*/* +++Copyright: 2017-2024 Nick Fitzgerald +++License: Apache-2.0 or MIT +++Comment: see https://github.com/fitzgen/is_executable +++ +++Files: vendor/is-terminal-*/* +++Copyright: 2022-2023 softprops +++ 2022-2023 Dan Gohman +++License: MIT +++Comment: see https://github.com/sunfishcode/is-terminal +++ +++Files: vendor/is_terminal_polyfill-*/* +++Copyright: 2023-2024 Ed Page +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/polyfill-rs/is_terminal_polyfill +++ +++Files: vendor/jiff-0.*/* +++Copyright: 2024-2025 Andrew Gallant +++License: Unlicense OR MIT +++Comment: see https://github.com/BurntSushi/jiff +++ +++Files: vendor/jod-thread-*/* +++Copyright: 2019-2020 Aleksey Kladov +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/matklad/jod-thread +++ +++Files: +++ vendor/js-sys-*/* +++ vendor/wasm-bindgen-*/* +++ vendor/wasm-bindgen-backend-*/* +++ vendor/wasm-bindgen-macro-support-*/* +++ vendor/wasm-bindgen-macro-*/* +++ vendor/wasm-bindgen-shared-*/* +++Copyright: +++ 2018-2023 The wasm-bindgen Developers +++ 2014-2023 Alex Crichton +++License: MIT or Apache-2.0 +++Comment: +++ see https://github.com/rustwasm/wasm-bindgen +++ +++Files: vendor/web-sys-*/* +++Copyright: 2018-2024 The wasm-bindgen Developers +++License: MIT or Apache-2.0 +++Comment: +++ see https://github.com/rustwasm/wasm-bindgen/tee/master/crates/web-sys +++ +++Files: vendor/jsonpath_lib-*/* +++Copyright: 2018-2021 Changseok Han +++License: MIT +++Comment: see https://github.com/freestrings/jsonpath +++ +++Files: vendor/kqueue-1.*/* +++Copyright: 2016-2024 William Orr +++License: MIT +++Comment: see https://gitlab.com/rust-kqueue/rust-kqueue +++ +++Files: vendor/kqueue-sys-1.*/* +++Copyright: 2016-2023 William Orr +++ 2016-2023 Daniel (dmilith) Dettlaff +++License: MIT +++Comment: see https://gitlab.com/rust-kqueue/rust-kqueue-sys +++ +++Files: vendor/kstring-*/* +++Copyright: 2014-2024 Ed Page +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/cobalt-org/kstring +++ +++Files: vendor/la-arena-*/* +++Copyright: 2024 rust-analyzer team +++License: MIT or Apache-2.0 +++Comment: see https://github.com/rust-lang/rust-analyzer/tree/master/lib/la-arena +++ +++Files: vendor/lazycell-*/* +++Copyright: 2016-2020 Alex Crichton +++ 2016-2020 Nikita Pekin +++License: MIT or Apache-2.0 +++Comment: see https://github.com/indiv0/lazycell +++ +++Files: vendor/lazy_static-*/* +++Copyright: 2014-2018 Marvin Löbel +++License: MIT or Apache-2.0 +++Comment: +++ see https://github.com/rust-lang-nursery/lazy-static.rs +++ see https://github.com/Kimundi/owning-ref-rs +++ +++Files: vendor/leb128-*/* +++Copyright: 2016-2022 Nick Fitzgerald +++ 2016-2022 Philip Craig +++License: Apache-2.0 or MIT +++Comment: see https://github.com/gimli-rs/leb128 +++ +++Files: vendor/lexopt-*/* +++Copyright: 2021-2023 Jan Verbeek +++License: MIT +++Comment: see https://github.com/blyxxyz/lexopt +++ +++Files: vendor/levenshtein-*/* +++Copyright: 2016-2021 Titus Wormer +++License: MIT +++Comment: see https://github.com/wooorm/levenshtein-rs +++ +++Files: vendor/libloading-*/* +++Copyright: 2015-2022 Simonas Kazlauskas +++License: ISC +++Comment: see https://github.com/nagisa/rust_libloading/ +++ +++Files: vendor/libm-*/* +++Copyright: 2018-2024 Jorge Aparicio +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rust-lang-nursery/libm +++ +++Files: vendor/libssh2-sys-*/* +++Copyright: 2014-2024 Alex Crichton +++ 2014-2024 Wez Furlong +++ 2014-2024 Matteo Bigoi +++License: MIT or Apache-2.0 +++Comment: see https://github.com/alexcrichton/ssh2-rs +++ +++Files: +++ vendor/libsqlite3-sys-*/* +++ vendor/rusqlite-*/* +++Copyright: 2014-2024 The rusqlite developers +++License: MIT +++Comment: see https://github.com/rusqlite/rusqlite +++ +++Files: vendor/libz-sys-*/* +++Copyright: 2014-2024 Alex Crichton +++ 2014-2024 Josh Triplett +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rust-lang/libz-sys +++ +++Files: vendor/line-index-*/* +++Copyright: +++ 2024 Ariel Davis +++ 2024 rust-analyzer team +++License: MIT or Apache-2.0 +++Comment: see https://github.com/rust-lang/rust-analyzer/tree/master/lib/line-index +++ +++Files: vendor/linereader-*/* +++Copyright: 2018-2019 Thomas Hurst +++License: MIT +++Comment: see https://github.com/Freaky/rust-linereader.git +++ +++Files: vendor/linked-hash-map-*/* +++Copyright: 2015-2022 Stepan Koltsov +++ 2015-2022 Andrew Paseltiner +++License: MIT or Apache-2.0 +++Comment: see https://github.com/contain-rs/linked-hash-map +++ +++Files: vendor/linux-raw-sys-*/* +++Copyright: 2021-2022 Dan Gohman +++License: Apache-2.0 with LLVM exception OR Apache-2.0 OR MIT +++Comment: see https://github.com/sunfishcode/linux-raw-sys +++ +++Files: vendor/lsp-server-*/* +++Copyright: 2024 rust-analyzer team +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rust-lang/rust-analyzer/tree/master/lib/lsp-server +++ +++Files: vendor/lsp-types-*/* +++Copyright: 2016-2022 Markus Westerlind +++ 2016-2022 Bruno Medeiros +++License: MIT +++Comment: see https://github.com/gluon-lang/lsp-types +++ +++Files: vendor/lz4_flex-*/* +++Copyright: 2020-2024 Pascal Seitz +++ 2020-2024 Arthur Silva +++ 2020-2024 ticki +++License: MIT +++Comment: see https://github.com/pseitz/lz4_flex +++ +++Files: vendor/mac-*/* +++Copyright: 2014-2017 Jonathan Reem +++License: MIT +++Comment: +++ see https://github.com/reem/rust-mac.git +++ +++Files: vendor/matchers-*/* +++Copyright: 2019-2019 Eliza Weisman +++License: MIT +++Comment: see https://github.com/hawkw/matchers +++ +++Files: vendor/maybe-async-*/* +++Copyright: 2020-2024 Guoli Lyu +++License: MIT +++Comment: see https://github.com/fMeow/maybe-async-rs +++ +++Files: vendor/mdbook-*/* +++Copyright: 2015-2017 Mathieu David +++License: MPL-2.0 +++Comment: see https://github.com/azerupi/mdBook +++ +++Files: vendor/measureme-*/* +++Copyright: 2019-2020 Wesley Wiser +++ 2019-2020 Michael Woerister +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rust-lang/measureme +++ +++Files: vendor/memmap2-*/* +++Copyright: 2015-2021 Dan Burkert +++ 2015-2021 Evgeniy Reizner +++License: MIT or Apache-2.0 +++Comment: see https://github.com/RazrFalcon/memmap2-rs +++ +++Files: vendor/memoffset-*/* +++Copyright: 2017-2019 Gilad Naaman +++License: MIT +++Comment: see https://github.com/Gilnaa/memoffset +++ +++Files: vendor/mime-*/* +++Copyright: 2014-2019 Sean McArthur +++License: MIT or Apache-2.0 +++Comment: see https://github.com/hyperium/mime +++ +++Files: vendor/mime_guess-*/* +++Copyright: 2015-2023 Austin Bonander +++License: MIT +++Comment: see https://github.com/abonander/mime_guess +++ +++Files: vendor/minifier-*/* +++Copyright: 2017-2018 Guillaume Gomez +++License: MIT +++Comment: +++ see https://github.com/GuillaumeGomez/minifier-rs +++ +++Files: vendor/miniz_oxide-*/* +++Copyright: 2017-2020 Frommi +++License: MIT +++Comment: see https://github.com/Frommi/miniz_oxide +++ +++Files: vendor/mio-0.*/* +++Copyright: 2014-2024 Carl Lerche +++ 2014-2024 Thomas de Zeeuw +++ 2014-2024 Tokio Contributors +++License: MIT +++Comment: see https://github.com/tokio-rs/mio +++ +++Files: vendor/new_debug_unreachable-*/* +++Copyright: 2014-2018 Matt Brubeck +++ 2014-2018 Jonathan Reem +++License: MIT +++Comment: see https://github.com/mbrubeck/rust-debug-unreachable +++ +++Files: vendor/nix-*/* +++Copyright: 2014-2024 The nix-rust Project Developers +++License: MIT +++Comment: see https://github.com/nix-rust/nix +++ +++Files: vendor/nohash-hasher-*/* +++Copyright: 2018-2020 Parity Technologies +++License: Apache-2.0 OR MIT +++Comment: see https://github.com/paritytech/nohash-hasher +++ +++Files: vendor/normalize-line-endings-*/* +++Copyright: 2016-2018 Richard Dodd +++License: Apache-2.0 +++Comment: see https://github.com/derekdreery/normalize-line-endings +++ +++Files: vendor/notify-6.*/* +++Copyright: 2014-2025 Félix Saparelli +++ 2014-2025 Daniel Faust +++ 2014-2025 Aron Heinecke +++License: CC0-1.0 +++Comment: see https://github.com/notify-rs/notify.git +++ +++Files: vendor/nu-ansi-term-*/* +++Copyright: 2014-2024 ogham@bsago.me +++ 2014-2024 Ryan Scheel (Havvy) +++ 2014-2024 Josh Triplett +++ 2014-2024 The Nushell Project Developers +++License: MIT +++Comment: see https://github.com/nushell/nu-ansi-term +++ +++Files: vendor/num-modular-0.*/* +++Copyright: 2021-2023 Jacob Zhong +++License: Apache-2.0 +++Comment: see https://github.com/cmpute/num-modular +++ +++Files: vendor/num-order-1.*/* +++Copyright: 2021-2023 Jacob Zhong +++License: Apache-2.0 +++Comment: see https://github.com/cmpute/num-order +++ +++Files: vendor/num_threads-*/* +++Copyright: 2021-2024 Jacob Pratt +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/jhpratt/num_threads +++ +++Files: vendor/nu-ansi-term-0.46.0/* +++Copyright: 2014-2023 ogham@bsago.me +++ 2014-2023 Ryan Scheel (Havvy) +++ 2014-2023 Josh Triplett +++ 2014-2023 The Nushell Project Developers +++License: MIT +++Comment: see https://github.com/nushell/nu-ansi-term +++ +++Files: vendor/num_cpus-*/* +++Copyright: 2015 Sean McArthur +++License: MIT +++Comment: see https://github.com/seanmonstar/num_cpus +++ +++Files: vendor/number_prefix-*/* +++Copyright: 2014-2020 Benjamin Sago +++License: MIT +++Comment: see https://github.com/ogham/rust-number-prefix +++ +++Files: +++ vendor/object-*/* +++ vendor/object-0.*/* +++Copyright: +++ 2016-2020 Nick Fitzgerald +++ 2016-2020 Philip Craig +++License: Apache-2.0 or MIT +++Comment: see https://github.com/gimli-rs/object +++ +++Files: vendor/odht-*/* +++Copyright: 2021 Michael Woerister +++License: Apache-2.0 or MIT +++Comment: see https://github.com/rust-lang/odht +++ +++Files: vendor/once_cell-*/* +++Copyright: 2018-2019 Aleksey Kladov +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/matklad/once_cell +++ +++Files: +++ vendor/onig-*/* +++ vendor/onig_sys-*/* +++Copyright: 2015-2023 Will Speak +++ 2015-2023 Ivan Ivashchenko +++License: MIT +++Comment: see http://github.com/iwillspeak/rust-onig +++ +++Files: vendor/oorandom-*/* +++Copyright: 2019-2021 Simon Heath +++License: MIT +++Comment: see https://sr.ht/~icefox/oorandom/ +++ +++Files: +++ vendor/opener-*/* +++ vendor/opener-0.*/* +++Copyright: 2018-2024 Brian Bowman +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/Seeker14491/opener +++ +++Files: vendor/openssl-*/* +++Copyright: 2011-2024 Steven Fackler +++License: Apache-2.0 +++Comment: see https://github.com/sfackler/rust-openssl +++ +++Files: vendor/openssl-macros-*/* +++Copyright: 2022-2024 Steven Fackler +++License: MIT or Apache-2.0 +++Comment: see https://github.com/sfackler/rust-openssl +++ +++Files: vendor/openssl-probe-*/* +++Copyright: 2016-2022 Alex Crichton +++License: MIT or Apache-2.0 +++Comment: see https://github.com/sfackler/rust-openssl +++ +++Files: vendor/openssl-sys-*/* +++Copyright: 2011-2024 Alex Crichton +++ 2011-2024 Steven Fackler +++License: MIT +++Comment: see https://github.com/sfackler/rust-openssl +++ +++Files: vendor/option-ext-*/* +++Copyright: 2022-2023 Simon Ochsenreither +++License: MPL-2.0 +++Comment: see https://github.com/soc/option-ext.git +++ +++Files: vendor/ordered-float-*/* +++Copyright: 2014-2024 Jonathan Reem +++ 2014-2024 Matt Brubeck +++License: MIT +++Comment: see https://github.com/reem/rust-ordered-float +++ +++Files: vendor/orion-*/* +++Copyright: 2018-2024 brycx +++License: MIT +++Comment: see https://github.com/orion-rs/orion +++ +++Files: vendor/os_info-*/* +++Copyright: 2015-2024 Jan Schulte +++ 2015-2024 Stanislav Tkach +++License: MIT +++Comment: see https://github.com/stanislav-tkach/os_info +++ +++Files: vendor/overload-*/* +++Copyright: 2019-2022 Daniel Salvadori +++License: MIT +++Comment: see https://github.com/danaugrs/overload +++ +++Files: vendor/owo-colors-*/* +++Copyright: 2020-2024 jam1garner <8260240+jam1garner@users.noreply.github.com> +++License: MIT +++Comment: see https://github.com/jam1garner/owo-colors +++ +++Files: +++ vendor/hashbrown-*/* +++ vendor/lock_api-*/* +++ vendor/thread_local-*/* +++ vendor/parking_lot-*/* +++ vendor/parking_lot_core-*/* +++Copyright: 2016-2019 Amanieu d'Antras +++License: MIT or Apache-2.0 +++Comment: +++ see https://github.com/rust-lang/hashbrown +++ see https://github.com/Amanieu/thread_local-rs +++ see https://github.com/Amanieu/parking_lot +++ +++Files: vendor/pad-*/* +++Copyright: 2018-2024 Ben S +++License: MIT +++ +++Files: vendor/papergrid-*/* +++Copyright: 2020-2024 Maxim Zhiburt +++License: MIT +++Comment: see https://github.com/zhiburt/tabled +++ +++Files: +++ vendor/partial_ref-*/* +++ vendor/partial_ref_derive-*/* +++Copyright: 2018-2021 Jannis Harder +++License: MIT or Apache-2.0 +++Comment: see https://github.com/jix/partial_ref +++ +++Files: vendor/pasetors-*/* +++Copyright: 2020-2024 brycx +++License: MIT +++Comment: see https://github.com/brycx/pasetors +++ +++Files: vendor/pathdiff-*/* +++Copyright: 2017-2020 Manish Goregaokar +++License: MIT or Apache-2.0 +++Comment: see https://github.com/Manishearth/pathdiff +++ +++Files: +++ vendor/perf-event-*/* +++ vendor/perf-event-open-sys-*/* +++ vendor/perf-event-open-sys-1.*/* +++Copyright: 2019-2022 Jim Blandy +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/jimblandy/perf-event.git +++ +++Files: +++ vendor/pest-*/* +++ vendor/pest_derive-*/* +++ vendor/pest_generator-*/* +++ vendor/pest_meta-*/* +++Copyright: 2016-2019 Dragoș Tiselice +++License: MIT or Apache-2.0 +++Comment: +++ see https://github.com/dragostis/pest +++ see https://github.com/pest-parser/pest +++ +++Files: vendor/petgraph-0.*/* +++Copyright: 2014-2025 bluss +++ 2014-2025 mitchmindtree +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/petgraph/petgraph +++ +++Files: vendor/polonius-engine-*/* +++Copyright: 2018-2018 The Rust Project Developers +++ 2018-2018 Polonius Developers +++License: Apache-2.0 or MIT +++Comment: see https://github.com/rust-lang-nursery/polonius +++ +++Files: +++ vendor/phf-*/* +++ vendor/phf_codegen-*/* +++ vendor/phf_generator-*/* +++ vendor/phf_shared-*/* +++Copyright: 2014-2018 Steven Fackler +++License: MIT +++Comment: see https://github.com/sfackler/rust-phf +++ +++Files: vendor/pin-project-lite-*/* +++Copyright: 2018-2021 Taiki Endo +++License: Apache-2.0 or MIT +++Comment: +++ see https://github.com/taiki-e/pin-project-lite +++ +++Files: +++ vendor/plotters-*/* +++ vendor/plotters-backend-*/* +++ vendor/plotters-svg-*/* +++Copyright: 2019-2024 Hao Hou +++License: MIT +++Comment: see https://github.com/plotters-rs/plotters +++ +++Files: vendor/polib-*/* +++Copyright: 2022-2024 Brett Dong +++License: MIT +++Comment: see https://github.com/brettdong/polib +++ +++Files: vendor/portable-atomic-*/* +++Copyright: 2022 Taiki Endo +++License: Apache-2.0 OR MIT +++Comment: see https://github.com/taiki-e/portable-atomic +++ +++Files: vendor/powerfmt-*/* +++Copyright: 2023-2024 Jacob Pratt +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/jhpratt/powerfmt +++ +++Files: vendor/precomputed-hash-*/* +++Copyright: 2017-2017 Emilio Cobos Álvarez +++License: MIT +++Comment: see https://github.com/emilio/precomputed-hash +++ +++Files: vendor/pretty_assertions-*/* +++Copyright: 2017-2022 Colin Kiegel +++ 2017-2022 Florent Fayolle +++ 2017-2022 Tom Milligan +++License: MIT or Apache-2.0 +++Comment: see https://github.com/colin-kiegel/rust-pretty-assertions +++ +++Files: vendor/prettydiff-*/* +++Copyright: 2019-2024 Roman Koblov +++License: MIT +++Comment: see https://github.com/romankoblov/prettydiff +++ +++Files: vendor/proc-macro-hack-*/* +++Copyright: 2016-2022 David Tolnay +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/dtolnay/proc-macro-hack +++ +++Files: vendor/process-wrap-8.*/* +++Copyright: 2021-2024 Félix Saparelli +++License: Apache-2.0 OR MIT +++Comment: see https://github.com/watchexec/process-wrap +++ +++Files: vendor/prodash-*/* +++Copyright: 2020-2023 Sebastian Thiel +++License: MIT +++Comment: see https://github.com/Byron/prodash +++ +++Files: vendor/proptest-*/* +++Copyright: 2017-2024 Jason Lingle +++License: MIT or Apache-2.0 +++Comment: see https://github.com/proptest-rs/proptest +++ +++Files: +++ vendor/protobuf-3.*/* +++ vendor/protobuf-support-3.*/* +++Copyright: 2013-2024 Stepan Koltsov +++License: MIT +++Comment: see https://github.com/stepancheg/rust-protobuf/ +++ +++Files: vendor/psm-*/* +++Copyright: 2015-2020 Simonas Kazlauskas +++License: MIT or Apache-2.0 +++Comment: see https://github.com/rust-lang/stacker/ +++ +++Files: +++ vendor/pulldown-cmark-*/* +++ vendor/pulldown-cmark-escape-*/* +++ vendor/pulldown-cmark-0.*/* +++Copyright: 2015-2017 Raph Levien +++License: MIT +++Comment: see https://github.com/google/pulldown-cmark +++ +++Files: vendor/punycode-*/* +++Copyright: 2015-2019 mcarton +++License: MIT +++Comment: see https://github.com/mcarton/rust-punycode.git +++ +++Files: vendor/quickcheck-0.4.1/* +++Copyright: 2014-2023 Andrew Gallant +++License: Unlicense or MIT +++Comment: see https://github.com/BurntSushi/quickcheck +++ +++Files: vendor/quick-error-*/* +++Copyright: +++ 2015-2023 Paul Colomiets +++ 2015-2023 Colin Kiegel +++License: MIT or Apache-2.0 +++Comment: see http://github.com/tailhook/quick-error +++ +++Files: vendor/quine-mc_cluskey-*/* +++Copyright: 2016-2016 Oliver Schneider +++License: MIT +++Comment: see https://github.com/oli-obk/quine-mc_cluskey +++ +++Files: +++ vendor/rayon-*/* +++ vendor/rayon-core-*/* +++ vendor/rustc-rayon-*/* +++ vendor/rustc-rayon-core-*/* +++Copyright: 2014-2018 Niko Matsakis +++ 2014-2018 Josh Stone +++License: Apache-2.0 or MIT +++Comment: +++ see https://github.com/rayon-rs/rayon +++ see https://github.com/Zoxc/rayon/tree/rustc +++ +++Files: vendor/r-efi-*/* +++Copyright: 2018-2024 David Rheinsberg +++ 2018-2024 Tom Gundersen +++License: MIT OR Apache-2.0 OR LGPL-2.1+ +++Comment: see https://github.com/r-efi/r-efi +++ +++Files: vendor/r-efi-alloc-*/* +++Copyright: 2018-2022 David Rheinsberg +++ 2018-2022 Tom Gundersen +++License: MIT OR Apache-2.0 OR LGPL-2.1+ +++Comment: see https://github.com/r-efi/r-efi-alloc +++ +++Files: vendor/libredox-*/* +++Copyright: 2023-2024 4lDO2 <4lDO2@protonmail.com> +++License: MIT +++Comment: see https://gitlab.redox-os.org/redox-os/libredox.git +++ +++Files: vendor/redox_users-*/* +++Copyright: 2017-2021 Jose Narvaez +++ 2017-2021 Wesley Hershberger +++License: MIT +++Comment: see https://gitlab.redox-os.org/redox-os/users +++ +++Files: vendor/redox_syscall-*/* +++Copyright: 2016-2021 Jeremy Soller +++License: MIT +++Comment: +++ see https://github.com/redox-os/syscall +++ +++Files: +++ vendor/regex-automata-*/* +++ vendor/regex-automata-0.1.*/* +++ vendor/regex-automata-0.2.*/* +++Copyright: 2018-2020 Andrew Gallant +++License: Unlicense or MIT +++Comment: see https://github.com/BurntSushi/regex-automata +++ +++Files: +++ vendor/rinja-0.*/* +++ vendor/rinja_derive-0.*/* +++ vendor/rinja_parser-0.*/* +++Copyright: 2017-2020 Dirkjan Ochtman +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rinja-rs/rinja +++ +++Files: vendor/rowan-*/* +++Copyright: 2018-2022 Aleksey Kladov +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rust-analyzer/rowan +++ +++Files: +++ vendor/ra-ap-rustc_abi-*/* +++ vendor/ra-ap-rustc_index-*/* +++ vendor/ra-ap-rustc_index_macros-*/* +++ vendor/ra-ap-rustc_lexer-*/* +++ vendor/ra-ap-rustc_parse_format-*/* +++ vendor/ra-ap-rustc_pattern_analysis-*/* +++Copyright: 2010-2025 The Rust Project Developers +++License: MIT or Apache-2.0 +++Comment: see https://github.com/rust-lang/rust +++ +++Files: vendor/rustc_apfloat-*/* +++Copyright: 2003-2017 University of Illinois at Urbana-Champaign. +++License: Apache-2.0 with LLVM exception +++Comment: see https://github.com/rust-lang/rustc_apfloat , in particular LICENSE-DETAILS.md +++ +++Files: vendor/rustc_tools_util-*/* +++Copyright: 2014-2022 The Rust Project Developers +++License: MIT or Apache-2.0 +++Comment: see https://github.com/rust-lang/rust-clippy/tree/master/rustc_tools_util +++ +++Files: vendor/rustc_version-*/* +++Copyright: 2015-2021 Dirkjan Ochtman +++ 2015-2021 Marvin Löbel +++License: MIT or Apache-2.0 +++Comment: see https://github.com/Kimundi/rustc-version-rs +++ +++Files: vendor/rustfix-*/* +++Copyright: +++ 2016-2021 Pascal Hertleif +++ 2016-2021 Oliver Schneider +++License: Apache-2.0 or MIT +++Comment: see https://github.com/killercup/rustfix +++ +++Files: vendor/rustix-*/* +++Copyright: 2020-2023 Dan Gohman +++ 2020-2023 Jakub Konka +++License: Apache-2.0 with LLVM exception OR Apache-2.0 OR MIT +++Comment: see https://github.com/bytecodealliance/rustix +++ +++Files: vendor/rustversion-*/* +++Copyright: 2019-2021 David Tolnay +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/dtolnay/rustversion +++ +++Files: vendor/rusty-fork-*/* +++Copyright: 2018-2020 Jason Lingle +++License: MIT or Apache-2.0 +++Comment: see https://github.com/altsysrq/rusty-fork +++ +++Files: vendor/ruzstd-*/* +++Copyright: 2019-2024 Moritz Borcherding +++License: MIT +++Comment: see https://github.com/KillingSpark/zstd-rs +++ +++Files: vendor/ryu-*/* +++Copyright: 2018-2018 David Tolnay +++License: Apache-2.0 or BSL-1.0 +++Comment: see https://github.com/dtolnay/ryu +++ +++Files: +++ vendor/schemars-0.*/* +++ vendor/schemars_derive-0.*/* +++Copyright: 2019-2024 Graham Esau +++License: MIT +++Comment: see https://github.com/GREsau/schemars +++ +++Files: vendor/scip-0.*/* +++Copyright: 2022 TJ DeVries +++License: Apache-2.0 +++Comment: see https://github.com/sourcegraph/scip +++ +++Files: +++ vendor/self_cell-*/* +++ vendor/self_cell-0.*/* +++Copyright: 2020-2021 Lukas Bergdoll +++License: Apache-2.0 +++Comment: see https://github.com/Voultapher/self_cell +++ +++Files: vendor/semver-*/* +++Copyright: +++ 2014-2020 Steve Klabnik +++ 2014-2020 The Rust Project Developers +++License: MIT or Apache-2.0 +++Comment: +++ see https://github.com/steveklabnik/semver +++ see https://github.com/steveklabnik/semver-parser +++ +++Files: +++ vendor/serde-*/* +++ vendor/serde_json-*/* +++Copyright: 2014-2017 Erick Tryzelaar +++License: MIT or Apache-2.0 +++Comment: +++ see https://github.com/serde-rs/serde +++ see https://github.com/serde-rs/json +++ +++Files: +++ vendor/serde_derive-*/* +++ vendor/serde_derive_internals-*/* +++Copyright: 2014-2024 Erick Tryzelaar +++ 2016-2024 David Tolnay +++License: MIT or Apache-2.0 +++Comment: see https://github.com/serde-rs/serde +++ +++Files: vendor/serde_ignored-*/* +++Copyright: 2017-2024 David Tolnay +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/dtolnay/serde-ignored +++ +++Files: vendor/serde_repr-*/* +++Copyright: 2019-2022 David Tolnay +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/dtolnay/serde-repr +++ +++Files: vendor/serde_spanned-*/* +++Copyright: +++ 2014-2023 Alex Crichton +++ 2023 Ed Page +++License: MIT or Apache-2.0 +++Comment: see https://github.com/toml-rs/toml +++ +++Files: vendor/serde-untagged-*/* +++Copyright: 2023-2024 David Tolnay +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/dtolnay/serde-untagged +++ +++Files: vendor/serde-value-*/* +++Copyright: 2016-2020 arcnmx +++License: MIT +++Comment: see https://github.com/arcnmx/serde-value +++ +++Files: vendor/sha1_smol-*/* +++Copyright: 2014-2022 Armin Ronacher +++License: BSD-3-Clause +++Comment: see https://github.com/mitsuhiko/sha1-smol +++ +++Files: vendor/sharded-slab-*/* +++Copyright: 2019-2020 Eliza Weisman +++License: MIT +++Comment: see https://github.com/hawkw/sharded-slab +++ +++Files: vendor/shell-escape-*/* +++Copyright: 2016-2020 Steven Fackler +++License: MIT or Apache-2.0 +++Comment: see https://github.com/sfackler/shell-escape +++ +++Files: vendor/shell-words-*/* +++Copyright: 2018-2022 Tomasz Miąsko +++License: MIT or Apache-2.0 +++Comment: see https://github.com/tmiasko/shell-words +++ +++Files: vendor/shlex-*/* +++Copyright: 2015-2015 comex +++License: MIT or Apache-2.0 +++Comment: see https://github.com/comex/rust-shlex +++ +++Files: vendor/similar-*/* +++Copyright: 2021-2024 Armin Ronacher +++ 2021-2024 Pierre-Étienne Meunier +++ 2021-2024 Brandon Williams +++License: Apache-2.0 +++Comment: see https://github.com/mitsuhiko/similar +++ +++Files: vendor/siphasher-*/* +++Copyright: 2016-2018 Frank Denis +++License: MIT or Apache-2.0 +++Comment: see https://github.com/jedisct1/rust-siphash +++ +++Files: vendor/sized-chunks-*/* +++Copyright: 2019-2022 Bodil Stokke +++License: MPL-2.0+ +++Comment: see https://github.com/bodil/sized-chunks +++ +++Files: vendor/smallvec-*/* +++Copyright: 2015-2020 Simon Sapin +++License: MPL-2.0 +++Comment: see https://github.com/servo/rust-smallvec +++ +++Files: vendor/smol_str-*/* +++Copyright: 2018-2022 Aleksey Kladov +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rust-analyzer/smol_str +++ +++Files: +++ vendor/snapbox-*/* +++ vendor/snapbox-macros-*/* +++Copyright: Ed Page 2022 +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/assert-rs/trycmd/ +++ +++Files: vendor/socket2-*/* +++Copyright: 2017-2024 Alex Crichton +++ 2017-2024 Thomas de Zeeuw +++License: MIT or Apache-2.0 +++Comment: see https://github.com/rust-lang/socket2 +++ +++Files: vendor/spanned-*/* +++Copyright: 2024 Oli Scherer +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/oli-obk/spanned +++ +++Files: vendor/spdx-*/* +++Copyright: 2019-2024 Embark +++ 2019-2024 Jake Shadle +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/EmbarkStudios/spdx +++ +++Files: +++ vendor/spdx-expression-*/* +++ vendor/spdx-rs-*/* +++Copyright: 2021-2022 Mikko Murto +++License: MIT +++Comment: +++ see https://github.com/doubleopen-project/spdx-expression +++ see https://github.com/doubleopen-project/spdx-rs +++ +++Files: vendor/sptr-0.*/* +++Copyright: 2022 Ralf Jung +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/Gankra/sptr +++ +++Files: vendor/stable_deref_trait-*/* +++Copyright: 2017-2017 Robert Grosse +++License: MIT or Apache-2.0 +++Comment: see https://github.com/storyyeller/stable_deref_trait +++ +++Files: vendor/stacker-*/* +++Copyright: 2015-2020 Alex Crichton +++ 2015-2020 Simonas Kazlauskas +++License: MIT or Apache-2.0 +++Comment: see https://github.com/rust-lang/stacker +++ +++Files: vendor/static_assertions-*/* +++Copyright: 2017-2020 Nikolai Vazquez +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/nvzqz/static-assertions-rs +++ +++Files: +++ vendor/strsim-*/* +++ vendor/strsim-0.*/* +++Copyright: 2015-2021 Danny Guo +++License: MIT +++Comment: see https://github.com/dguo/strsim-rs +++ +++Files: +++ vendor/strum-*/* +++ vendor/strum_macros-*/* +++Copyright: 2017-2023 Peter Glotfelty +++License: MIT +++Comment: see https://github.com/Peternator7/strum +++ +++Files: vendor/subtle-*/* +++Copyright: 2017-2023 Isis Lovecruft +++ 2017-2023 Henry de Valence +++License: BSD-3-Clause +++Comment: see https://github.com/dalek-cryptography/subtle +++ +++Files: vendor/supports-hyperlinks-*/* +++Copyright: 2021-2024 Kat Marchán +++License: Apache-2.0 +++Comment: see https://github.com/zkat/supports-hyperlinks +++ +++Files: vendor/supports-unicode-*/* +++Copyright: 2021-2024 Kat Marchán +++License: Apache-2.0 +++Comment: see https://github.com/zkat/supports-unicode +++ +++Files: +++ vendor/synstructure-*/* +++ vendor/synstructure-0.*/* +++Copyright: +++ 2016-2023 Nika Layzell +++License: MIT +++Comment: see https://github.com/mystor/synstructure +++ +++Files: vendor/syntect-5.*/* +++Copyright: 2016-2024 Tristan Hume +++License: MIT +++Comment: see https://github.com/trishume/syntect +++ +++Files: vendor/sysinfo-*/* +++Copyright: 2015-2022 Guillaume Gomez +++License: MIT +++Comment: see https://github.com/GuillaumeGomez/sysinfo +++ +++Files: vendor/tabled-*/* +++Copyright: 2020-2024 Maxim Zhiburt +++License: MIT +++Comment: see https://github.com/zhiburt/tabled +++ +++Files: vendor/tempfile-*/* +++Copyright: 2015-2018 Steven Allen +++ 2015-2018 The Rust Project Developers +++ 2015-2018 Ashley Mannix +++ 2015-2018 Jason White +++License: MIT or Apache-2.0 +++Comment: see https://github.com/Stebalien/tempfile +++ +++Files: vendor/tendril-*/* +++Copyright: 2015-2017 Keegan McAllister +++ 2015-2017 Simon Sapin +++ 2015-2017 Chris Morgan +++License: MIT or Apache-2.0 +++Comment: see https://github.com/servo/tendril +++ +++Files: vendor/tenthash-*/* +++Copyright: 2022-2025 Nathan Vegdahl +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/cessen/tenthash/ +++ +++Files: vendor/term-*/* +++Copyright: +++ 2014-2021 The Rust Project Developers +++ 2014-2021 Steven Allen +++License: MIT or Apache-2.0 +++Comment: see https://github.com/Stebalien/term +++ +++Files: vendor/terminal_size-*/* +++Copyright: 2015-2023 Andrew Chin +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/eminence/terminal-size +++ +++Files: vendor/termize-*/* +++Copyright: 2016-2020 Yuki Okushi +++License: MIT or Apache-2.0 +++Comment: see https://github.com/JohnTitor/termize +++ +++Files: vendor/text-size-*/* +++Copyright: 2018-2021 Aleksey Kladov +++ 2018-2021 Christopher Durham (CAD97) +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rust-analyzer/text-size +++ +++Files: vendor/textwrap-0.*/* +++Copyright: 2016-2024 Martin Geisler +++License: MIT +++Comment: see https://github.com/mgeisler/textwrap +++ +++Files: vendor/thin-vec-*/* +++Copyright: 2017-2022 Aria Beingessner +++License: MIT or Apache-2.0 +++Comment: see https://github.com/gankra/thin-vec +++ +++Files: +++ vendor/thiserror-*/* +++ vendor/thiserror-impl-*/* +++Copyright: 2019-2020 David Tolnay +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/dtolnay/thiserror +++ +++Files: vendor/thorin-dwp-*/* +++Copyright: 2021-2022 David Wood +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/davidtwco/thorin +++ +++Files: vendor/threadpool-*/* +++Copyright: 2015-2021 The Rust Project Developers +++ 2015-2021 Corey Farwell +++ 2015-2021 Stefan Schindler +++License: MIT or Apache-2.0 +++Comment: see https://github.com/rust-threadpool/rust-threadpool +++ +++Files: vendor/time-macros-*/* +++Copyright: 2019-2024 Jacob Pratt +++ 2019-2024 Time contributors +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/time-rs/time +++ +++Files: vendor/tinystr-*/* +++Copyright: 2019-2022 Raph Levien +++ 2019-2022 Zibi Braniecki +++License: Apache-2.0 or MIT +++Comment: see https://github.com/zbraniecki/tinystr +++ +++Files: vendor/tinytemplate-*/* +++Copyright: 2018-2022 Brook Heisler +++License: Apache-2.0 OR MIT +++Comment: see https://github.com/bheisler/TinyTemplate +++ +++Files: vendor/tinyvec-*/* +++Copyright: 2020 Lokathor +++License: Zlib +++Comment: see https://github.com/Lokathor/tinyvec +++ +++Files: vendor/tinyvec_macros-*/* +++Copyright: 2020 Soveu +++License: MIT or Apache-2.0 or Zlib +++Comment: see https://github.com/Soveu/tinyvec_macros +++ +++Files: vendor/topological-sort-*/* +++Copyright: 2015-2018 gifnksm +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/gifnksm/topological-sort-rs +++ +++Files: vendor/toml-*/* +++Copyright: 2014-2024 Alex Crichton +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/toml-rs/toml +++ +++Files: vendor/toml_datetime-*/* +++Copyright: 2014-2024 Alex Crichton +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/toml-rs/toml +++ +++Files: vendor/toml_edit-*/* +++Copyright: 2014-2024 Andronik Ordian +++ 2014-2024 Ed Page +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/ordian/toml_edit +++ +++Files: +++ vendor/tracing-*/* +++ vendor/tracing-0.*/* +++ vendor/tracing-attributes-*/* +++ vendor/tracing-core-*/* +++ vendor/tracing-core-0.*/* +++ vendor/tracing-error-*/* +++ vendor/tracing-log-*/* +++ vendor/tracing-log-0.*/* +++ vendor/tracing-subscriber-*/* +++Copyright: +++ 2018-2024 David Barsky +++ 2018-2024 Eliza Weisman +++ 2018-2024 Jane Lusby +++ 2018-2024 Tokio Contributors +++License: MIT +++Comment: see https://github.com/tokio-rs/tracing +++ +++Files: vendor/tracing-chrome-*/* +++Copyright: 2020-2024 Thoren Paulson +++License: MIT +++Comment: see https://github.com/thoren-d/tracing-chrome +++ +++Files: vendor/tracing-tree-0.*/* +++Copyright: 2020-2020 David Barsky +++ 2020-2020 Nathan Whitaker +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/davidbarsky/tracing-tree +++ +++Files: vendor/triomphe-*/* +++Copyright: 2018-2024 The Servo Project Developers +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/Manishearth/triomphe +++ +++Files: vendor/twox-hash-*/* +++Copyright: 2015-2022 Jake Goulding +++License: MIT +++Comment: see https://github.com/shepmaster/twox-hash +++ +++Files: vendor/typed-arena-2.0.2/* +++Copyright: 2015-2023 The typed-arena developers +++License: MIT +++Comment: see https://github.com/SimonSapin/rust-typed-arena +++ +++Files: vendor/typeid-*/* +++Copyright: 2024-2024 David Tolnay +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/dtolnay/typeid +++ +++Files: vendor/type-map-*/* +++Copyright: 2019-2022 Jacob Brown +++License: MIT or Apache-2.0 +++Comment: see https://github.com/kardeiz/type-map +++ +++Files: vendor/typenum-*/* +++Copyright: 2015-2019 Paho Lurie-Gregg +++ 2015-2019 Andre Bogus +++License: MIT or Apache-2.0 +++Comment: see https://github.com/paholg/typenum +++ +++Files: vendor/ui_test-*/* +++Copyright: +++ 2010-2024 The Rust Project Developers +++ 2015-2024 Thomas Bracht Laumann Jespersen +++ 2015-2024 Manish Goregaokar +++ 2022-2024 Oli Scherer +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/oli-obk/ui_test +++ extraction of compiletest-rs from rustc itself +++ +++Files: vendor/unarray-*/* +++Copyright: 2022 Cameron +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/cameron1024/unarray +++ +++Files: vendor/unicode-bom-*/* +++Copyright: 2018-2023 Phil Booth +++License: Apache-2.0 +++Comment: see https://gitlab.com/philbooth/unicode-bom +++ +++Files: vendor/unicode-properties-*/* +++Copyright: 2022-2024 Charles Lew +++ 2022-2024 Manish Goregaokar +++License: MIT or Apache-2.0 +++Comment: see https://github.com/unicode-rs/unicode-properties +++ +++Files: vendor/unwinding-*/* +++Copyright: 2021-2024 Gary Guo +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/nbdd0121/unwinding/ +++ +++Files: vendor/utf16_iter-*/* +++Copyright: 2022-2023 Henri Sivonen +++License: Apache-2.0 OR MIT +++Comment: see https://github.com/hsivonen/utf16_iter +++ +++Files: vendor/utf8_iter-*/* +++Copyright: 2022-2023 Henri Sivonen +++License: Apache-2.0 OR MIT +++Comment: see https://github.com/hsivonen/utf8_iter +++ +++Files: vendor/utf8-width-*/* +++Copyright: 2020-2023 Magic Len +++License: MIT +++Comment: see https://github.com/magiclen/utf8-width +++ +++Files: +++ vendor/varisat-*/* +++ vendor/varisat-checker-*/* +++ vendor/varisat-dimacs-*/* +++ vendor/varisat-formula-*/* +++ vendor/varisat-internal-macros-*/* +++ vendor/varisat-internal-proof-*/* +++Copyright: 2018-2022 Jannis Harder +++License: MIT or Apache-2.0 +++Comment: see https://github.com/jix/varisat +++ +++Files: vendor/vcpkg-*/* +++Copyright: 2017-2024 Jim McGrath +++License: MIT or Apache-2.0 +++Comment: see https://github.com/mcgoo/vcpkg-rs +++ +++Files: vendor/vec_mut_scan-*/* +++Copyright: 2019-2023 Jannis Harder +++License: 0BSD +++Comment: see https://github.com/jix/vec_mut_scan +++ +++Files: vendor/version_check-*/* +++Copyright: 2017-2019 Sergio Benitez +++License: MIT or Apache-2.0 +++Comment: see https://github.com/SergioBenitez/version_check +++ +++Files: +++ vendor/ucd-parse-*/* +++ vendor/ucd-trie-*/* +++Copyright: 2017-2020 Andrew Gallant +++License: MIT or Apache-2.0 +++Comment: +++ see https://github.com/BurntSushi/rucd +++ see https://github.com/BurntSushi/ucd-generate +++ +++Files: vendor/ungrammar-*/* +++Copyright: 2020-2022 Aleksey Kladov +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/matklad/ungrammar +++ +++Files: vendor/unicase-*/* +++Copyright: 2014-2019 Sean McArthur +++License: MIT or Apache-2.0 +++Comment: see https://github.com/seanmonstar/unicase +++ +++Files: vendor/unic-*/* +++Copyright: 2017-2022 The UNIC Project Developers +++License: MIT or Apache-2.0 +++Comment: see https://github.com/open-i18n/rust-unic/ +++ +++Files: +++ vendor/unicode-normalization-*/* +++ vendor/unicode-segmentation-*/* +++ vendor/unicode-width-*/* +++Copyright: 2015-2019 kwantam +++License: MIT or Apache-2.0 +++Comment: +++ see https://github.com/unicode-rs/unicode-normalization +++ see https://github.com/unicode-rs/unicode-segmentation +++ see https://github.com/unicode-rs/unicode-width +++ +++Files: vendor/unicode-xid-*/* +++Copyright: 2015-2017 erick.tryzelaar +++ 2015-2017 kwantam +++License: MIT or Apache-2.0 +++Comment: see https://github.com/unicode-rs/unicode-xid +++ +++Files: vendor/unicode-script-*/* +++Copyright: 2017-2020 Manish Goregaokar +++License: MIT or Apache-2.0 +++Comment: see https://github.com/unicode-rs/unicode-script +++ +++Files: vendor/unicode-security-*/* +++Copyright: 2020-2020 Charles Lew +++ 2020-2020 Manish Goregaokar +++License: MIT or Apache-2.0 +++Comment: see https://github.com/unicode-rs/unicode-security +++ +++Files: vendor/unified-diff-*/* +++Copyright: 2021-2021 Michael Howell +++ 2021-2021 The Rust Project Developers +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/notriddle/rust-unified-diff +++ +++Files: vendor/utf-8-*/* +++Copyright: 2015-2018 Simon Sapin +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/SimonSapin/rust-utf8 +++ +++Files: vendor/utf8parse-*/* +++Copyright: 2016-2023 Joe Wilm +++ 2016-2023 Christian Duerr +++License: Apache-2.0 OR MIT +++Comment: see https://github.com/alacritty/vte +++ +++Files: vendor/uuid-*/* +++Copyright: 2014-2023 Ashley Mannix +++ 2014-2023 Christopher Armstrong +++ 2014-2023 Dylan DPC +++ 2014-2023 Hunar Roop Kahlon +++License: Apache-2.0 OR MIT +++Comment: see https://github.com/uuid-rs/uuid +++ +++Files: vendor/wait-timeout-*/* +++Copyright: 2015-2021 Alex Crichton +++License: MIT or Apache-2.0 +++Comment: see https://github.com/alexcrichton/wait-timeout +++ +++Files: vendor/wasi-*/* +++Copyright: 2019-2020 The Cranelift Project Developers +++License: Apache-2.0 with LLVM exception or Apache-2.0 or MIT +++Comment: see https://github.com/CraneStation/rust-wasi +++ +++Files: vendor/wasm-encoder-*/* +++Copyright: Nick Fitzgerald +++License: Apache-2.0 with LLVM exception +++Comment: see https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-encoder +++ +++Files: vendor/wasm-component-ld-*/* +++Copyright: 2023-2024 Alex Crichton +++License: Apache-2.0 with LLVM exception or Apache-2.0 or MIT +++Comment: see https://github.com/bytecodealliance/wasm-component-ld +++ +++Files: +++ vendor/wasmparser-*/* +++ vendor/wasm-metadata-*/* +++ vendor/wast-*/* +++ vendor/wat-*/* +++ vendor/wit-component-*/* +++ vendor/wit-parser-*/* +++Copyright: +++ Yury Delendik +++ The Wasmtime Project Developers +++License: Apache-2.0 with LLVM exception or Apache-2.0 or MIT +++Comment: see https://github.com/bytecodealliance/wasm-tools +++ +++Files: vendor/windows-bindgen-*/* +++Copyright: 2019-2024 Microsoft +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/microsoft/windows-rs +++ this contains pre-generated files which are also MIT or Apache-2.0 licensed, +++ see vendor/windows-bindgen-*/default/readme.md +++ +++Files: vendor/windows-metadata-*/* +++Copyright: Microsoft 2024 +++License: MIT or Apache-2.0 +++Comment: +++ see https://github.com/microsoft/windows-rs +++ +++Files: +++ vendor/winnow-*/* +++ vendor/winnow-0.*/* +++Copyright: +++ 2023 winnow contributors +++ 2014-2023 nom contributors +++ 2014-2023 Geoffroy Couprie +++License: MIT +++Comment: see https://github.com/winnow-rs/winnow +++ +++Files: vendor/xattr-*/* +++Copyright: 2015-2017 Steven Allen +++License: MIT or Apache-2.0 +++Comment: see https://github.com/Stebalien/xattr +++ +++Files: vendor/yansi-*/* +++Copyright: 2017-2022 Sergio Benitez +++License: MIT or Apache-2.0 +++Comment: see https://github.com/SergioBenitez/yansi +++ +++Files: vendor/yansi-term-*/* +++Copyright: 2014-2020 ogham@bsago.me +++ 2014-2020 Ryan Scheel (Havvy) +++ 2014-2020 Josh Triplett +++ 2014-2020 Juan Aguilar Santillana +++License: MIT +++Comment: see https://github.com/botika/yansi-term +++ +++Files: +++ vendor/zerocopy-*/* +++ vendor/zerocopy-derive-*/* +++Copyright: 2019-2024 Joshua Liebow-Feeser +++License: BSD-2-Clause OR Apache-2.0 OR MIT +++Comment: see https://github.com/google/zerocopy +++ +++Files: vendor/bytes-*/* +++Copyright: 2015-2022 Carl Lerche +++ 2015-2022 Sean McArthur +++License: MIT +++Comment: see https://github.com/tokio-rs/bytes +++ +++Files: +++ vendor/futures-*/* +++ vendor/futures-channel-*/* +++ vendor/futures-core-*/* +++ vendor/futures-executor-*/* +++ vendor/futures-io-*/* +++ vendor/futures-macro-*/* +++ vendor/futures-sink-*/* +++ vendor/futures-task-*/* +++ vendor/futures-util-*/* +++Copyright: +++ 2016-2018 Alex Crichton +++ 2017 The Tokio Authors +++ 2018-2022 The Rust Project Developers +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rust-lang/futures-rs +++ +++Files: vendor/minimal-lexical-*/* +++Copyright: 2020-2022 Alex Huszagh +++License: MIT or Apache-2.0 +++Comment: see https://github.com/Alexhuszagh/minimal-lexical +++ +++Files: vendor/nom-*/* +++Copyright: 2014-2022 contact@geoffroycouprie.com +++License: MIT +++Comment: see https://github.com/Geal/nom +++ +++Files: vendor/pin-utils-*/* +++Copyright: 2018-2022 Josef Brandl +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/rust-lang-nursery/pin-utils +++ +++Files: vendor/slab-*/* +++Copyright: 2015-2022 Carl Lerche +++License: MIT +++Comment: see https://github.com/carllerche/slab +++ +++Files: vendor/tokio-*/* +++Copyright: 2016-2022 Tokio Contributors +++License: MIT +++Comment: see https://github.com/tokio-rs/tokio +++ +++Files: vendor/valuable-*/* +++Copyright: +++ 2021 Valuable Contributors +++ 2021-2022 Carl Lerche +++ 2021-2022 Taiki Endo +++License: MIT +++Comment: see https://github.com/tokio-rs/valuable +++ +++Files: vendor/web-time-*/* +++Copyright: Copyright (c) 2023 dAxpeDDa +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/daxpedda/web-time +++ +++Files: vendor/write16-*/* +++Copyright: 2022-2023 Henri Sivonen +++License: Apache-2.0 OR MIT +++Comment: see https://github.com/hsivonen/write16 +++ +++Files: vendor/write-json-*/* +++Copyright: 2020-2020 Aleksey Kladov +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/matklad/write-json +++ +++Files: +++ vendor/xflags-*/* +++ vendor/xflags-macros-*/* +++Copyright: 2021-2022 Aleksey Kladov +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/matklad/xflags +++ +++Files: +++ vendor/xshell-*/* +++ vendor/xshell-macros-*/* +++Copyright: 2020-2022 Aleksey Kladov +++License: MIT OR Apache-2.0 +++Comment: see https://github.com/matklad/xshell +++ +++Files: vendor/zip-*/* +++Copyright: 2014-2023 Mathijs van de Nes +++ 2014-2023 Marli Frost +++ 2014-2023 Ryan Levick +++License: MIT +++Comment: see https://github.com/zip-rs/zip.git +++ +++Files: +++ vendor/icu_collections-*/* +++ vendor/icu_list-*/* +++ vendor/icu_list_data-*/* +++ vendor/icu_locid-*/* +++ vendor/icu_locid_transform-*/* +++ vendor/icu_locid_transform_data-*/* +++ vendor/icu_normalizer-*/* +++ vendor/icu_normalizer_data-*/* +++ vendor/icu_properties-*/* +++ vendor/icu_properties_data-*/* +++ vendor/icu_provider-*/* +++ vendor/icu_provider_adapters-*/* +++ vendor/icu_provider_macros-*/* +++ vendor/litemap-*/* +++ vendor/yoke-*/* +++ vendor/yoke-derive-*/* +++ vendor/writeable-*/* +++ vendor/zerofrom-*/* +++ vendor/zerofrom-derive-*/* +++ vendor/zerovec-*/* +++ vendor/zerovec-derive-*/* +++Copyright: 1999-2022 Unicode, Inc. +++License: Unicode-Data-Files-and-Software-License +++Comment: See https://github.com/unicode-org/icu4x +++ +++Files: debian/* +++Copyright: 2013-2018 Debian Rust Maintainers +++License: MIT or Apache-2.0 +++ +++Files: debian/icons/rust-logo-32x32-blk.png +++Copyright: Mozilla Foundation +++License: CC-BY +++Comment: +++ Relevant discussion in https://github.com/rust-lang/rust/issues/11562 +++ +++License: 0BSD +++ Permission to use, copy, modify, and/or distribute this software for +++ any purpose with or without fee is hereby granted. +++ . +++ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +++ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +++ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +++ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +++ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +++ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +++ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +++ +++License: Apache-2.0 +++ On Debian systems, the full text of the Apache License Version 2.0 +++ can be found in the file `/usr/share/common-licenses/Apache-2.0'. +++ +++License: Apache-2.0 with LLVM exception +++ On Debian systems, the full text of the Apache License Version 2.0 +++ can be found in the file `/usr/share/common-licenses/Apache-2.0'. +++ Additionally, the LLVM exception is as follows: +++ . +++ As an exception, if, as a result of your compiling your source code, portions +++ of this Software are embedded into an Object form of such source code, you +++ may redistribute such embedded portions in such Object form without complying +++ with the conditions of Sections 4(a), 4(b) and 4(d) of the License. +++ . +++ In addition, if you combine or link compiled forms of this Software with +++ software that is licensed under the GPLv2 ("Combined Software") and if a +++ court of competent jurisdiction determines that the patent provision (Section +++ 3), the indemnity provision (Section 9) or other Section of the License +++ conflicts with the conditions of the GPLv2, you may retroactively and +++ prospectively choose to deem waived or otherwise exclude such Section(s) of +++ the License, but only in their entirety and only with respect to the Combined +++ Software. +++ +++License: BSD-2-clause +++ Redistribution and use in source and binary forms, with +++ or without modification, are permitted provided that the +++ following conditions are met: +++ . +++ 1. Redistributions of source code must retain the above +++ copyright notice, this list of conditions and the +++ following disclaimer. +++ 2. Redistributions in binary form must reproduce the +++ above copyright notice, this list of conditions and +++ the following disclaimer in the documentation and/or +++ other materials provided with the distribution. +++ . +++ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS +++ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +++ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +++ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +++ DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR +++ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +++ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +++ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +++ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +++ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +++ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +++ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +++ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +++ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +++ +++License: CC0-1.0 +++ On Debian systems, the full text of the CC0 1.0 Universal +++ License can be found in the file +++ `/usr/share/common-licenses/CC0-1.0'. +++ +++License: ISC +++ Permission to use, copy, modify, and/or distribute this software for any purpose +++ with or without fee is hereby granted, provided that the above copyright notice +++ and this permission notice appear in all copies. +++ . +++ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +++ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +++ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +++ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +++ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +++ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +++ THIS SOFTWARE. +++ +++License: MIT-0 +++ Permission is hereby granted, free of charge, to any person obtaining a +++ copy of this software and associated documentation files (the +++ "Software"), to deal in the Software without restriction, including +++ without limitation the rights to use, copy, modify, merge, publish, +++ distribute, sublicense, and/or sell copies of the Software, and to +++ permit persons to whom the Software is furnished to do so. +++ . +++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +++ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +++ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +++ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +++ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +++ +++License: MIT +++ Permission is hereby granted, free of charge, to any +++ person obtaining a copy of this software and associated +++ documentation files (the "Software"), to deal in the +++ Software without restriction, including without +++ limitation the rights to use, copy, modify, merge, +++ publish, distribute, sublicense, and/or sell copies of +++ the Software, and to permit persons to whom the Software +++ is furnished to do so, subject to the following +++ conditions: +++ . +++ The above copyright notice and this permission notice +++ shall be included in all copies or substantial portions +++ of the Software. +++ . +++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +++ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +++ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +++ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +++ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +++ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +++ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +++ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +++ DEALINGS IN THE SOFTWARE. +++ +++License: BSL-1.0 +++ Permission is hereby granted, free of charge, to any person or organization +++ obtaining a copy of the software and accompanying documentation covered by +++ this license (the "Software") to use, reproduce, display, distribute, +++ execute, and transmit the Software, and to prepare derivative works of the +++ Software, and to permit third-parties to whom the Software is furnished to +++ do so, all subject to the following: +++ . +++ The copyright notices in the Software and this entire statement, including +++ the above license grant, this restriction and the following disclaimer, +++ must be included in all copies of the Software, in whole or in part, and +++ all derivative works of the Software, unless such copies or derivative +++ works are solely in the form of machine-executable object code generated by +++ a source language processor. +++ . +++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +++ FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +++ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +++ FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +++ DEALINGS IN THE SOFTWARE. +++ +++License: BSD-3-clause +++ Redistribution and use in source and binary forms, with or without +++ modification, are permitted provided that the following conditions +++ are met: +++ 1. Redistributions of source code must retain the above copyright +++ notice, this list of conditions and the following disclaimer. +++ 2. Redistributions in binary form must reproduce the above copyright +++ notice, this list of conditions and the following disclaimer in the +++ documentation and/or other materials provided with the distribution. +++ 3. Neither the name of the organization nor the names of its contributors +++ may be used to endorse or promote products derived from this software +++ without specific prior written permission. +++ . +++ THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' AND +++ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +++ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +++ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +++ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +++ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +++ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +++ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +++ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +++ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +++ SUCH DAMAGE. +++ +++License: Unlicense +++ This is free and unencumbered software released into the public domain. +++ . +++ Anyone is free to copy, modify, publish, use, compile, sell, or +++ distribute this software, either in source code form or as a compiled +++ binary, for any purpose, commercial or non-commercial, and by any +++ means. +++ . +++ In jurisdictions that recognize copyright laws, the author or authors +++ of this software dedicate any and all copyright interest in the +++ software to the public domain. We make this dedication for the +++ benefit of the public at large and to the detriment of our heirs and +++ successors. We intend this dedication to be an overt act of +++ relinquishment in perpetuity of all present and future rights to this +++ software under copyright law. +++ . +++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +++ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY +++ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +++ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +++ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +++ . +++ For more information, please refer to +++ +++License: SIL-OPEN-FONT +++ This Font Software is licensed under the SIL Open Font License, +++ Version 1.1. +++ . +++ This license is copied below, and is also available with a FAQ at: +++ http://scripts.sil.org/OFL +++ . +++ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +++ . +++ PREAMBLE The goals of the Open Font License (OFL) are to stimulate +++ worldwide development of collaborative font projects, to support the font +++ creation efforts of academic and linguistic communities, and to provide +++ a free and open framework in which fonts may be shared and improved in +++ partnership with others. +++ . +++ The OFL allows the licensed fonts to be used, studied, modified and +++ redistributed freely as long as they are not sold by themselves. +++ The fonts, including any derivative works, can be bundled, embedded, +++ redistributed and/or sold with any software provided that any reserved +++ names are not used by derivative works. The fonts and derivatives, +++ however, cannot be released under any other type of license. The +++ requirement for fonts to remain under this license does not apply to +++ any document created using the fonts or their derivatives. +++ . +++ DEFINITIONS +++ "Font Software" refers to the set of files released by the Copyright +++ Holder(s) under this license and clearly marked as such. +++ This may include source files, build scripts and documentation. +++ . +++ "Reserved Font Name" refers to any names specified as such after the +++ copyright statement(s). +++ . +++ "Original Version" refers to the collection of Font Software components +++ as distributed by the Copyright Holder(s). +++ . +++ "Modified Version" refers to any derivative made by adding to, deleting, +++ or substituting ? in part or in whole ? +++ any of the components of the Original Version, by changing formats or +++ by porting the Font Software to a new environment. +++ . +++ "Author" refers to any designer, engineer, programmer, technical writer +++ or other person who contributed to the Font Software. +++ . +++ PERMISSION & CONDITIONS +++ . +++ Permission is hereby granted, free of charge, to any person obtaining a +++ copy of the Font Software, to use, study, copy, merge, embed, modify, +++ redistribute, and sell modified and unmodified copies of the Font +++ Software, subject to the following conditions: +++ . +++ 1) Neither the Font Software nor any of its individual components,in +++ Original or Modified Versions, may be sold by itself. +++ . +++ 2) Original or Modified Versions of the Font Software may be bundled, +++ redistributed and/or sold with any software, provided that each copy +++ contains the above copyright notice and this license. These can be +++ included either as stand-alone text files, human-readable headers or +++ in the appropriate machine-readable metadata fields within text or +++ binary files as long as those fields can be easily viewed by the user. +++ . +++ 3) No Modified Version of the Font Software may use the Reserved Font +++ Name(s) unless explicit written permission is granted by the +++ corresponding Copyright Holder. This restriction only applies to the +++ primary font name as presented to the users. +++ . +++ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +++ Software shall not be used to promote, endorse or advertise any +++ Modified Version, except to acknowledge the contribution(s) of the +++ Copyright Holder(s) and the Author(s) or with their explicit written +++ permission. +++ 5) The Font Software, modified or unmodified, in part or in whole, must +++ be distributed entirely under this license, and must not be distributed +++ under any other license. The requirement for fonts to remain under +++ this license does not apply to any document created using the Font +++ Software. +++ . +++ TERMINATION +++ This license becomes null and void if any of the above conditions are not met. +++ . +++ DISCLAIMER +++ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +++ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +++ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +++ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +++ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +++ FROM, OUT OF THE USE OR INABILITY +++ +++License: LGPL-2.1+ +++ This library is free software; you can redistribute it and/or +++ modify it under the terms of the GNU Lesser General Public +++ License as published by the Free Software Foundation; either +++ version 2.1 of the License, or (at your option) any later version. +++ . +++ This library is distributed in the hope that it will be useful, +++ but WITHOUT ANY WARRANTY; without even the implied warranty of +++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +++ Lesser General Public License for more details. +++ . +++ You should have received a copy of the GNU Lesser General Public +++ License along with this library; if not, write to the Free Software +++ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +++ . +++ On Debian systems, see /usr/share/common-licenses/LGPL-2.1 for the full +++ text of the LGPL version 2.1. +++ +++License: GPL-2+ +++ This program is free software; you can redistribute it and/or modify +++ it under the terms of the GNU General Public License as published by +++ the Free Software Foundation; either version 2 of the License, or +++ (at your option) any later version. +++ . +++ This program is distributed in the hope that it will be useful, +++ but WITHOUT ANY WARRANTY; without even the implied warranty of +++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +++ GNU General Public License for more details. +++ . +++ You should have received a copy of the GNU General Public License +++ along with this program; if not, write to the Free Software +++ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +++ . +++ On Debian systems, see /usr/share/common-licenses/GPL-2 for the full +++ text of the GPL version 2. +++ +++License: CC-BY +++ Attribution 4.0 International +++ . +++ ======================================================================= +++ . +++ Creative Commons Corporation ("Creative Commons") is not a law firm and +++ does not provide legal services or legal advice. Distribution of +++ Creative Commons public licenses does not create a lawyer-client or +++ other relationship. Creative Commons makes its licenses and related +++ information available on an "as-is" basis. Creative Commons gives no +++ warranties regarding its licenses, any material licensed under their +++ terms and conditions, or any related information. Creative Commons +++ disclaims all liability for damages resulting from their use to the +++ fullest extent possible. +++ . +++ Using Creative Commons Public Licenses +++ . +++ Creative Commons public licenses provide a standard set of terms and +++ conditions that creators and other rights holders may use to share +++ original works of authorship and other material subject to copyright +++ and certain other rights specified in the public license below. The +++ following considerations are for informational purposes only, are not +++ exhaustive, and do not form part of our licenses. +++ . +++ Considerations for licensors: Our public licenses are +++ intended for use by those authorized to give the public +++ permission to use material in ways otherwise restricted by +++ copyright and certain other rights. Our licenses are +++ irrevocable. Licensors should read and understand the terms +++ and conditions of the license they choose before applying it. +++ Licensors should also secure all rights necessary before +++ applying our licenses so that the public can reuse the +++ material as expected. Licensors should clearly mark any +++ material not subject to the license. This includes other CC- +++ licensed material, or material used under an exception or +++ limitation to copyright. More considerations for licensors: +++ wiki.creativecommons.org/Considerations_for_licensors +++ . +++ Considerations for the public: By using one of our public +++ licenses, a licensor grants the public permission to use the +++ licensed material under specified terms and conditions. If +++ the licensor's permission is not necessary for any reason--for +++ example, because of any applicable exception or limitation to +++ copyright--then that use is not regulated by the license. Our +++ licenses grant only permissions under copyright and certain +++ other rights that a licensor has authority to grant. Use of +++ the licensed material may still be restricted for other +++ reasons, including because others have copyright or other +++ rights in the material. A licensor may make special requests, +++ such as asking that all changes be marked or described. +++ Although not required by our licenses, you are encouraged to +++ respect those requests where reasonable. More_considerations +++ for the public: +++ wiki.creativecommons.org/Considerations_for_licensees +++ . +++ ======================================================================= +++ . +++ Creative Commons Attribution 4.0 International Public License +++ . +++ By exercising the Licensed Rights (defined below), You accept and agree +++ to be bound by the terms and conditions of this Creative Commons +++ Attribution 4.0 International Public License ("Public License"). To the +++ extent this Public License may be interpreted as a contract, You are +++ granted the Licensed Rights in consideration of Your acceptance of +++ these terms and conditions, and the Licensor grants You such rights in +++ consideration of benefits the Licensor receives from making the +++ Licensed Material available under these terms and conditions. +++ . +++ . +++ Section 1 -- Definitions. +++ . +++ a. Adapted Material means material subject to Copyright and Similar +++ Rights that is derived from or based upon the Licensed Material +++ and in which the Licensed Material is translated, altered, +++ arranged, transformed, or otherwise modified in a manner requiring +++ permission under the Copyright and Similar Rights held by the +++ Licensor. For purposes of this Public License, where the Licensed +++ Material is a musical work, performance, or sound recording, +++ Adapted Material is always produced where the Licensed Material is +++ synched in timed relation with a moving image. +++ . +++ b. Adapter's License means the license You apply to Your Copyright +++ and Similar Rights in Your contributions to Adapted Material in +++ accordance with the terms and conditions of this Public License. +++ . +++ c. Copyright and Similar Rights means copyright and/or similar rights +++ closely related to copyright including, without limitation, +++ performance, broadcast, sound recording, and Sui Generis Database +++ Rights, without regard to how the rights are labeled or +++ categorized. For purposes of this Public License, the rights +++ specified in Section 2(b)(1)-(2) are not Copyright and Similar +++ Rights. +++ . +++ d. Effective Technological Measures means those measures that, in the +++ absence of proper authority, may not be circumvented under laws +++ fulfilling obligations under Article 11 of the WIPO Copyright +++ Treaty adopted on December 20, 1996, and/or similar international +++ agreements. +++ . +++ e. Exceptions and Limitations means fair use, fair dealing, and/or +++ any other exception or limitation to Copyright and Similar Rights +++ that applies to Your use of the Licensed Material. +++ . +++ f. Licensed Material means the artistic or literary work, database, +++ or other material to which the Licensor applied this Public +++ License. +++ . +++ g. Licensed Rights means the rights granted to You subject to the +++ terms and conditions of this Public License, which are limited to +++ all Copyright and Similar Rights that apply to Your use of the +++ Licensed Material and that the Licensor has authority to license. +++ . +++ h. Licensor means the individual(s) or entity(ies) granting rights +++ under this Public License. +++ . +++ i. Share means to provide material to the public by any means or +++ process that requires permission under the Licensed Rights, such +++ as reproduction, public display, public performance, distribution, +++ dissemination, communication, or importation, and to make material +++ available to the public including in ways that members of the +++ public may access the material from a place and at a time +++ individually chosen by them. +++ . +++ j. Sui Generis Database Rights means rights other than copyright +++ resulting from Directive 96/9/EC of the European Parliament and of +++ the Council of 11 March 1996 on the legal protection of databases, +++ as amended and/or succeeded, as well as other essentially +++ equivalent rights anywhere in the world. +++ . +++ k. You means the individual or entity exercising the Licensed Rights +++ under this Public License. Your has a corresponding meaning. +++ . +++ . +++ Section 2 -- Scope. +++ . +++ a. License grant. +++ . +++ 1. Subject to the terms and conditions of this Public License, +++ the Licensor hereby grants You a worldwide, royalty-free, +++ non-sublicensable, non-exclusive, irrevocable license to +++ exercise the Licensed Rights in the Licensed Material to: +++ . +++ a. reproduce and Share the Licensed Material, in whole or +++ in part; and +++ . +++ b. produce, reproduce, and Share Adapted Material. +++ . +++ 2. Exceptions and Limitations. For the avoidance of doubt, where +++ Exceptions and Limitations apply to Your use, this Public +++ License does not apply, and You do not need to comply with +++ its terms and conditions. +++ . +++ 3. Term. The term of this Public License is specified in Section +++ 6(a). +++ . +++ 4. Media and formats; technical modifications allowed. The +++ Licensor authorizes You to exercise the Licensed Rights in +++ all media and formats whether now known or hereafter created, +++ and to make technical modifications necessary to do so. The +++ Licensor waives and/or agrees not to assert any right or +++ authority to forbid You from making technical modifications +++ necessary to exercise the Licensed Rights, including +++ technical modifications necessary to circumvent Effective +++ Technological Measures. For purposes of this Public License, +++ simply making modifications authorized by this Section 2(a) +++ (4) never produces Adapted Material. +++ . +++ 5. Downstream recipients. +++ . +++ a. Offer from the Licensor -- Licensed Material. Every +++ recipient of the Licensed Material automatically +++ receives an offer from the Licensor to exercise the +++ Licensed Rights under the terms and conditions of this +++ Public License. +++ . +++ b. No downstream restrictions. You may not offer or impose +++ any additional or different terms or conditions on, or +++ apply any Effective Technological Measures to, the +++ Licensed Material if doing so restricts exercise of the +++ Licensed Rights by any recipient of the Licensed +++ Material. +++ . +++ 6. No endorsement. Nothing in this Public License constitutes or +++ may be construed as permission to assert or imply that You +++ are, or that Your use of the Licensed Material is, connected +++ with, or sponsored, endorsed, or granted official status by, +++ the Licensor or others designated to receive attribution as +++ provided in Section 3(a)(1)(A)(i). +++ . +++ b. Other rights. +++ . +++ 1. Moral rights, such as the right of integrity, are not +++ licensed under this Public License, nor are publicity, +++ privacy, and/or other similar personality rights; however, to +++ the extent possible, the Licensor waives and/or agrees not to +++ assert any such rights held by the Licensor to the limited +++ extent necessary to allow You to exercise the Licensed +++ Rights, but not otherwise. +++ . +++ 2. Patent and trademark rights are not licensed under this +++ Public License. +++ . +++ 3. To the extent possible, the Licensor waives any right to +++ collect royalties from You for the exercise of the Licensed +++ Rights, whether directly or through a collecting society +++ under any voluntary or waivable statutory or compulsory +++ licensing scheme. In all other cases the Licensor expressly +++ reserves any right to collect such royalties. +++ . +++ . +++ Section 3 -- License Conditions. +++ . +++ Your exercise of the Licensed Rights is expressly made subject to the +++ following conditions. +++ . +++ a. Attribution. +++ . +++ 1. If You Share the Licensed Material (including in modified +++ form), You must: +++ . +++ a. retain the following if it is supplied by the Licensor +++ with the Licensed Material: +++ . +++ i. identification of the creator(s) of the Licensed +++ Material and any others designated to receive +++ attribution, in any reasonable manner requested by +++ the Licensor (including by pseudonym if +++ designated); +++ . +++ ii. a copyright notice; +++ . +++ iii. a notice that refers to this Public License; +++ . +++ iv. a notice that refers to the disclaimer of +++ warranties; +++ . +++ v. a URI or hyperlink to the Licensed Material to the +++ extent reasonably practicable; +++ . +++ b. indicate if You modified the Licensed Material and +++ retain an indication of any previous modifications; and +++ . +++ c. indicate the Licensed Material is licensed under this +++ Public License, and include the text of, or the URI or +++ hyperlink to, this Public License. +++ . +++ 2. You may satisfy the conditions in Section 3(a)(1) in any +++ reasonable manner based on the medium, means, and context in +++ which You Share the Licensed Material. For example, it may be +++ reasonable to satisfy the conditions by providing a URI or +++ hyperlink to a resource that includes the required +++ information. +++ . +++ 3. If requested by the Licensor, You must remove any of the +++ information required by Section 3(a)(1)(A) to the extent +++ reasonably practicable. +++ . +++ 4. If You Share Adapted Material You produce, the Adapter's +++ License You apply must not prevent recipients of the Adapted +++ Material from complying with this Public License. +++ . +++ . +++ Section 4 -- Sui Generis Database Rights. +++ . +++ Where the Licensed Rights include Sui Generis Database Rights that +++ apply to Your use of the Licensed Material: +++ . +++ a. for the avoidance of doubt, Section 2(a)(1) grants You the right +++ to extract, reuse, reproduce, and Share all or a substantial +++ portion of the contents of the database; +++ . +++ b. if You include all or a substantial portion of the database +++ contents in a database in which You have Sui Generis Database +++ Rights, then the database in which You have Sui Generis Database +++ Rights (but not its individual contents) is Adapted Material; and +++ . +++ c. You must comply with the conditions in Section 3(a) if You Share +++ all or a substantial portion of the contents of the database. +++ . +++ For the avoidance of doubt, this Section 4 supplements and does not +++ replace Your obligations under this Public License where the Licensed +++ Rights include other Copyright and Similar Rights. +++ . +++ . +++ Section 5 -- Disclaimer of Warranties and Limitation of Liability. +++ . +++ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE +++ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS +++ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF +++ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, +++ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, +++ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR +++ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, +++ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT +++ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT +++ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. +++ . +++ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE +++ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, +++ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, +++ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, +++ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR +++ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN +++ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR +++ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR +++ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. +++ . +++ c. The disclaimer of warranties and limitation of liability provided +++ above shall be interpreted in a manner that, to the extent +++ possible, most closely approximates an absolute disclaimer and +++ waiver of all liability. +++ . +++ . +++ Section 6 -- Term and Termination. +++ . +++ a. This Public License applies for the term of the Copyright and +++ Similar Rights licensed here. However, if You fail to comply with +++ this Public License, then Your rights under this Public License +++ terminate automatically. +++ . +++ b. Where Your right to use the Licensed Material has terminated under +++ Section 6(a), it reinstates: +++ . +++ 1. automatically as of the date the violation is cured, provided +++ it is cured within 30 days of Your discovery of the +++ violation; or +++ . +++ 2. upon express reinstatement by the Licensor. +++ . +++ For the avoidance of doubt, this Section 6(b) does not affect any +++ right the Licensor may have to seek remedies for Your violations +++ of this Public License. +++ . +++ c. For the avoidance of doubt, the Licensor may also offer the +++ Licensed Material under separate terms or conditions or stop +++ distributing the Licensed Material at any time; however, doing so +++ will not terminate this Public License. +++ . +++ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public +++ License. +++ . +++ . +++ Section 7 -- Other Terms and Conditions. +++ . +++ a. The Licensor shall not be bound by any additional or different +++ terms or conditions communicated by You unless expressly agreed. +++ . +++ b. Any arrangements, understandings, or agreements regarding the +++ Licensed Material not stated herein are separate from and +++ independent of the terms and conditions of this Public License. +++ . +++ . +++ Section 8 -- Interpretation. +++ . +++ a. For the avoidance of doubt, this Public License does not, and +++ shall not be interpreted to, reduce, limit, restrict, or impose +++ conditions on any use of the Licensed Material that could lawfully +++ be made without permission under this Public License. +++ . +++ b. To the extent possible, if any provision of this Public License is +++ deemed unenforceable, it shall be automatically reformed to the +++ minimum extent necessary to make it enforceable. If the provision +++ cannot be reformed, it shall be severed from this Public License +++ without affecting the enforceability of the remaining terms and +++ conditions. +++ . +++ c. No term or condition of this Public License will be waived and no +++ failure to comply consented to unless expressly agreed to by the +++ Licensor. +++ . +++ d. Nothing in this Public License constitutes or may be interpreted +++ as a limitation upon, or waiver of, any privileges and immunities +++ that apply to the Licensor or You, including from the legal +++ processes of any jurisdiction or authority. +++ . +++ . +++ ======================================================================= +++ . +++ Creative Commons is not a party to its public licenses. +++ Notwithstanding, Creative Commons may elect to apply one of its public +++ licenses to material it publishes and in those instances will be +++ considered the "Licensor." Except for the limited purpose of indicating +++ that material is shared under a Creative Commons public license or as +++ otherwise permitted by the Creative Commons policies published at +++ creativecommons.org/policies, Creative Commons does not authorize the +++ use of the trademark "Creative Commons" or any other trademark or logo +++ of Creative Commons without its prior written consent including, +++ without limitation, in connection with any unauthorized modifications +++ to any of its public licenses or any other arrangements, +++ understandings, or agreements concerning use of licensed material. For +++ the avoidance of doubt, this paragraph does not form part of the public +++ licenses. +++ . +++ Creative Commons may be contacted at creativecommons.org. +++ +++License: MPL-2.0 +++ This Source Code Form is subject to the terms of the Mozilla Public +++ License, v. 2.0. If a copy of the MPL was not distributed with this +++ file, You can obtain one at http://mozilla.org/MPL/2.0/. +++ . +++ On Debian systems, see /usr/share/common-licenses/MPL-2.0 for the full +++ text of the MPL version 2.0. +++ +++License: Zlib +++ This software is provided 'as-is', without any express or implied +++ warranty. In no event will the authors be held liable for any damages +++ arising from the use of this software. +++ . +++ Permission is granted to anyone to use this software for any purpose, +++ including commercial applications, and to alter it and redistribute it +++ freely, subject to the following restrictions: +++ . +++ 1. The origin of this software must not be misrepresented; you must not +++ claim that you wrote the original software. If you use this software +++ in a product, an acknowledgment in the product documentation would be +++ appreciated but is not required. +++ 2. Altered source versions must be plainly marked as such, and must not be +++ misrepresented as being the original software. +++ 3. This notice may not be removed or altered from any source distribution. +++ +++License: Unicode-Data-Files-and-Software-License +++ UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE +++ . +++ See Terms of Use +++ for definitions of Unicode Inc.’s Data Files and Software. +++ . +++ NOTICE TO USER: Carefully read the following legal agreement. +++ BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +++ DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +++ YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +++ TERMS AND CONDITIONS OF THIS AGREEMENT. +++ IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +++ THE DATA FILES OR SOFTWARE. +++ . +++ COPYRIGHT AND PERMISSION NOTICE +++ . +++ Copyright © 1991-2022 Unicode, Inc. All rights reserved. +++ Distributed under the Terms of Use in https://www.unicode.org/copyright.html. +++ . +++ Permission is hereby granted, free of charge, to any person obtaining +++ a copy of the Unicode data files and any associated documentation +++ (the "Data Files") or Unicode software and any associated documentation +++ (the "Software") to deal in the Data Files or Software +++ without restriction, including without limitation the rights to use, +++ copy, modify, merge, publish, distribute, and/or sell copies of +++ the Data Files or Software, and to permit persons to whom the Data Files +++ or Software are furnished to do so, provided that either +++ (a) this copyright and permission notice appear with all copies +++ of the Data Files or Software, or +++ (b) this copyright and permission notice appear in associated +++ Documentation. +++ . +++ THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +++ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +++ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +++ NONINFRINGEMENT OF THIRD PARTY RIGHTS. +++ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +++ NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +++ DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +++ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +++ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +++ PERFORMANCE OF THE DATA FILES OR SOFTWARE. +++ . +++ Except as contained in this notice, the name of a copyright holder +++ shall not be used in advertising or otherwise to promote the sale, +++ use or other dealings in these Data Files or Software without prior +++ written authorization of the copyright holder. +++ +++License: BSD-1-Clause-fiat-crypto +++ Copyright (c) 2015-2020 the fiat-crypto authors (see the AUTHORS file) +++ All rights reserved. +++ . +++ Redistribution and use in source and binary forms, with or without +++ modification, are permitted provided that the following conditions are +++ met: +++ . +++ 1. Redistributions of source code must retain the above copyright +++ notice, this list of conditions and the following disclaimer. +++ . +++ THIS SOFTWARE IS PROVIDED BY the fiat-crypto authors "AS IS" +++ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +++ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +++ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, +++ Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +++ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +++ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +++ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +++ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +++ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +++ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +++ diff --cc debian/docs index 0000000000,0000000000,0000000000..b43bf86b50 new file mode 100644 --- /dev/null +++ b/debian/docs @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++README.md diff --cc debian/ensure-patch index 0000000000,0000000000,0000000000..b8562f2d93 new file mode 100755 --- /dev/null +++ b/debian/ensure-patch @@@@ -1,0 -1,0 -1,0 +1,15 @@@@ +++#!/bin/sh +++set -e +++ +++case "$1" in +++"-N") fwd=-N; rev=-R; verb="applied";; +++"-R") fwd=-R; rev=-N; verb="reversed";; +++*) echo >&2 "Usage: $0 <-N|-R> "; exit 2;; +++esac +++ +++if patch --dry-run -F0 -f $rev -p1 < "$2" >/dev/null; then +++ echo >&2 "patch already $verb: $2" +++ exit 0 +++fi +++patch --dry-run -F0 -f $fwd -p1 < "$2" +++patch -F0 -f $fwd -p1 < "$2" diff --cc debian/gbp.conf index 0000000000,0000000000,0000000000..9d845d635a new file mode 100644 --- /dev/null +++ b/debian/gbp.conf @@@@ -1,0 -1,0 -1,0 +1,12 @@@@ +++[DEFAULT] +++pristine-tar = True +++ignore-branch = True +++component = extra +++ +++[import-orig] +++upstream-branch = upstream/experimental +++debian-branch = debian/experimental +++ +++[pq] +++patch-numbers = False +++drop = True diff --cc debian/get-stage0.py index 0000000000,0000000000,0000000000..f37ef2b618 new file mode 100755 --- /dev/null +++ b/debian/get-stage0.py @@@@ -1,0 -1,0 -1,0 +1,38 @@@@ +++#!/usr/bin/python3 +++# Sometimes this might fail due to upstream changes. +++# In that case, you probably just need to override the failing step in our +++# DownloadOnlyRustBuild class below. +++ +++import shutil +++import sys +++ +++import bootstrap +++from bootstrap import RustBuild +++ +++class DownloadOnlyRustBuild(RustBuild): +++ triple = None +++ def build_bootstrap(self): +++ pass +++ def run(self, *args): +++ pass +++ def build_triple(self): +++ return self.triple +++ def update_submodules(self): +++ pass +++ def bootstrap_binary(self): +++ return "true" +++ +++def main(argv): +++ triple = argv.pop(1) +++ DownloadOnlyRustBuild.triple = triple +++ bootstrap.RustBuild = DownloadOnlyRustBuild +++ args = bootstrap.parse_args(argv) +++ # bootstrap.py likes to delete our .cargo directory out from under us +++ shutil.move(".cargo", ".cargo-bak") +++ try: +++ bootstrap.bootstrap(args) +++ finally: +++ shutil.move(".cargo-bak", ".cargo") +++ +++if __name__ == '__main__': +++ main(sys.argv) diff --cc debian/icons/rust-logo-32x32-blk.png index 0000000000,0000000000,0000000000..9cc1452e37 new file mode 100644 Binary files differ diff --cc debian/libstd-rust-1.85.install index 0000000000,0000000000,0000000000..cd4545cca3 new file mode 100644 --- /dev/null +++ b/debian/libstd-rust-1.85.install @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++usr/lib/${DEB_HOST_MULTIARCH}/ diff --cc debian/libstd-rust-1.85.lintian-overrides index 0000000000,0000000000,0000000000..6433c2da40 new file mode 100644 --- /dev/null +++ b/debian/libstd-rust-1.85.lintian-overrides @@@@ -1,0 -1,0 -1,0 +1,16 @@@@ +++# "libstd" just seemed too generic +++libstd-rust-1.85 binary: package-name-doesnt-match-sonames +++libstd-rust-1.85 binary: sharedobject-in-library-directory-missing-soname +++ +++# Rust doesn't use dev shlib symlinks nor any of the other shlib support stuff +++libstd-rust-1.85 binary: dev-pkg-without-shlib-symlink +++libstd-rust-1.85 binary: shlib-without-versioned-soname +++libstd-rust-1.85 binary: unused-shlib-entry-in-control-file +++ +++# can trigger if all its so files' hashes start with a latter and not a digit +++libstd-rust-1.85 binary: empty-shlibs +++ +++# Libraries that use libc symbols (libterm, libstd, etc) *are* linked +++# to libc. Lintian gets upset that some Rust libraries don't need +++# libc, boo hoo. +++libstd-rust-1.85 binary: library-not-linked-against-libc diff --cc debian/libstd-rust-1.85.triggers index 0000000000,0000000000,0000000000..a88c20f92b new file mode 100644 --- /dev/null +++ b/debian/libstd-rust-1.85.triggers @@@@ -1,0 -1,0 -1,0 +1,2 @@@@ +++# normally added by dh_makeshlibs, but fails for our versioning scheme +++activate-noawait ldconfig diff --cc debian/libstd-rust-dev-wasm32.install index 0000000000,0000000000,0000000000..a2949f140c new file mode 100644 --- /dev/null +++ b/debian/libstd-rust-dev-wasm32.install @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++usr/lib/rustlib/wasm32-*/lib/ diff --cc debian/libstd-rust-dev-wasm32.lintian-overrides index 0000000000,0000000000,0000000000..2664d9cf30 new file mode 100644 --- /dev/null +++ b/debian/libstd-rust-dev-wasm32.lintian-overrides @@@@ -1,0 -1,0 -1,0 +1,6 @@@@ +++# wasm object files count as arch-independent for now, +++# at least until we starting offering Debian in wasm +++libstd-rust-dev-wasm32 binary: arch-independent-package-contains-binary-or-object * +++ +++# lintian doesn't understand rlib files +++libstd-rust-dev-wasm32 binary: no-code-sections * diff --cc debian/libstd-rust-dev-windows.install index 0000000000,0000000000,0000000000..1a0734fa9e new file mode 100644 --- /dev/null +++ b/debian/libstd-rust-dev-windows.install @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++usr/lib/rustlib/${env:WINDOWS_ARCH}-pc-windows-gnu/lib/ diff --cc debian/libstd-rust-dev-windows.lintian-overrides index 0000000000,0000000000,0000000000..8ab4804c56 new file mode 100644 --- /dev/null +++ b/debian/libstd-rust-dev-windows.lintian-overrides @@@@ -1,0 -1,0 -1,0 +1,8 @@@@ +++# lintian does not know about rust arch-specific directories +++libstd-rust-dev-windows binary: arch-dependent-file-not-in-arch-specific-directory [usr/lib/rustlib/*/lib/lib*.rlib] +++libstd-rust-dev-windows binary: arch-dependent-file-not-in-arch-specific-directory [usr/lib/rustlib/*/lib/lib*.a] +++libstd-rust-dev-windows binary: executable-not-elf-or-script [usr/lib/rustlib/*/lib/*.dll] +++ +++# lintian doesn't understand these files +++libstd-rust-dev-windows binary: no-code-sections [*.rlib] +++libstd-rust-dev-windows binary: no-code-sections [usr/lib/rustlib/*-pc-windows-gnu/lib/lib*.dll.a] diff --cc debian/libstd-rust-dev.install index 0000000000,0000000000,0000000000..399e4c0754 new file mode 100644 --- /dev/null +++ b/debian/libstd-rust-dev.install @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++usr/lib/rustlib/${env:DEB_HOST_RUST_TYPE}/lib/ diff --cc debian/libstd-rust-dev.lintian-overrides index 0000000000,0000000000,0000000000..33ea50b57e new file mode 100644 --- /dev/null +++ b/debian/libstd-rust-dev.lintian-overrides @@@@ -1,0 -1,0 -1,0 +1,11 @@@@ +++# lintian does not know about rust arch-specific directories +++libstd-rust-dev binary: arch-dependent-file-not-in-arch-specific-directory [usr/lib/rustlib/*/lib/lib*.rlib] +++libstd-rust-dev binary: breakout-link usr/lib/rustlib/*/lib/lib*.so -> usr/lib/*/lib*.so +++ +++# lintian doesn't understand rlib files +++libstd-rust-dev binary: no-code-sections [*.rlib] +++ +++# See debhelper bug #875780. This override is commented out because it's not +++# always needed, but we want it here for documentation purposes. Basically, +++# if you see it then you probably don't need to worry about it. +++#libstd-rust-dev binary: unstripped-static-library usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/lib*.rlib(*) diff --cc debian/lintian-to-copyright.sh index 0000000000,0000000000,0000000000..866e31bcd0 new file mode 100755 --- /dev/null +++ b/debian/lintian-to-copyright.sh @@@@ -1,0 -1,0 -1,0 +1,5 @@@@ +++#!/bin/sh +++# Pipe the output of lintian into this. +++sed -ne 's/.* file-without-copyright-information //p' | cut -d/ -f1-2 | sort -u | while read x; do +++ debian/scripts/guess-crate-copyright "$x" +++done diff --cc debian/llvm-upstream-patch.sh index 0000000000,0000000000,0000000000..fc87971361 new file mode 100755 --- /dev/null +++ b/debian/llvm-upstream-patch.sh @@@@ -1,0 -1,0 -1,0 +1,9 @@@@ +++#!/bin/sh +++# Run this on https://github.com/llvm-mirror/llvm +++# Or another repo where the above is the "upstream" remote +++set -e +++head=$(git rev-parse --verify -q remotes/upstream/master || git rev-parse --verify -q remotes/origin/master) +++test -n "$head" +++for i in "$@"; do +++ git show $(git rev-list "$head" -n1 --grep='git-svn-id: .*@'"$i") > rL"$i".patch +++done diff --cc debian/make_orig-stage0_tarball.sh index 0000000000,0000000000,0000000000..b6010532ae new file mode 100755 --- /dev/null +++ b/debian/make_orig-stage0_tarball.sh @@@@ -1,0 -1,0 -1,0 +1,48 @@@@ +++#!/bin/sh +++# See README.Debian "Bootstrapping" for details. +++# +++# You may want to use `debian/rules source_orig-stage0` instead of calling this +++# directly. +++ +++set -e +++ +++upstream_version="$(dpkg-parsechangelog -SVersion | sed -e 's/\(.*\)-.*/\1/g')" +++upstream_bootstrap_arch="${upstream_bootstrap_arch:-amd64 arm64 armhf i386 ppc64el riscv64 s390x}" +++ +++rm -f stage0/*/*.sha256 +++mkdir -p stage0 build && ln -sf ../stage0 build/cache +++if [ -n "$(find stage0/ -type f)" ]; then +++ echo >&2 "$0: NOTE: extra artifacts in stage0/ will be included:" +++ find stage0/ -type f +++fi +++for deb_host_arch in $upstream_bootstrap_arch; do +++ make -s --no-print-directory -f debian/architecture-test.mk "rust-for-deb_${deb_host_arch}" | { +++ read deb_host_arch rust_triplet +++ PYTHONPATH=src/bootstrap debian/get-stage0.py "${rust_triplet}" +++ rm -rf "${rust_triplet}" +++ } +++done +++ +++echo >&2 "building stage0 tar file now, this will take a while..." +++stamp=@${SOURCE_DATE_EPOCH:-$(date +%s)} +++touch --date="$stamp" stage0/dpkg-source-dont-rename-parent-directory +++tar --mtime="$stamp" --clamp-mtime \ +++ --owner=root --group=root \ +++ -cJf "../rustc_${upstream_version}.orig-stage0.tar.xz" \ +++ --transform "s/^stage0\///" \ +++ stage0/* +++ +++rm -f src/bootstrap/bootstrap.pyc +++ +++cat < text.length) { +++ // Something went terribly wrong, ABORT, ABORT! +++ break tokenloop; +++ } +++ +++ if (str instanceof Token) { +++ continue; +++ } +++ +++ pattern.lastIndex = 0; +++ +++ var match = pattern.exec(str); +++ +++ if (match) { +++ if(lookbehind) { +++ lookbehindLength = match[1].length; +++ } +++ +++ var from = match.index - 1 + lookbehindLength, +++ match = match[0].slice(lookbehindLength), +++ len = match.length, +++ to = from + len, +++ before = str.slice(0, from + 1), +++ after = str.slice(to + 1); +++ +++ var args = [i, 1]; +++ +++ if (before) { +++ args.push(before); +++ } +++ +++ var wrapped = new Token(token, inside? _.tokenize(match, inside) : match, alias); +++ +++ args.push(wrapped); +++ +++ if (after) { +++ args.push(after); +++ } +++ +++ Array.prototype.splice.apply(strarr, args); +++ } +++ } +++ } +++ } +++ +++ return strarr; +++ }, +++ +++ hooks: { +++ all: {}, +++ +++ add: function (name, callback) { +++ var hooks = _.hooks.all; +++ +++ hooks[name] = hooks[name] || []; +++ +++ hooks[name].push(callback); +++ }, +++ +++ run: function (name, env) { +++ var callbacks = _.hooks.all[name]; +++ +++ if (!callbacks || !callbacks.length) { +++ return; +++ } +++ +++ for (var i=0, callback; callback = callbacks[i++];) { +++ callback(env); +++ } +++ } +++ } +++}; +++ +++var Token = _.Token = function(type, content, alias) { +++ this.type = type; +++ this.content = content; +++ this.alias = alias; +++}; +++ +++Token.stringify = function(o, language, parent) { +++ if (typeof o == 'string') { +++ return o; +++ } +++ +++ if (_.util.type(o) === 'Array') { +++ return o.map(function(element) { +++ return Token.stringify(element, language, o); +++ }).join(''); +++ } +++ +++ var env = { +++ type: o.type, +++ content: Token.stringify(o.content, language, parent), +++ tag: 'span', +++ classes: ['token', o.type], +++ attributes: {}, +++ language: language, +++ parent: parent +++ }; +++ +++ if (env.type == 'comment') { +++ env.attributes['spellcheck'] = 'true'; +++ } +++ +++ if (o.alias) { +++ var aliases = _.util.type(o.alias) === 'Array' ? o.alias : [o.alias]; +++ Array.prototype.push.apply(env.classes, aliases); +++ } +++ +++ _.hooks.run('wrap', env); +++ +++ var attributes = ''; +++ +++ for (var name in env.attributes) { +++ attributes += name + '="' + (env.attributes[name] || '') + '"'; +++ } +++ +++ return '<' + env.tag + ' class="' + env.classes.join(' ') + '" ' + attributes + '>' + env.content + ''; +++ +++}; +++ +++if (!_self.document) { +++ if (!_self.addEventListener) { +++ // in Node.js +++ return _self.Prism; +++ } +++ // In worker +++ _self.addEventListener('message', function(evt) { +++ var message = JSON.parse(evt.data), +++ lang = message.language, +++ code = message.code; +++ +++ _self.postMessage(JSON.stringify(_.util.encode(_.tokenize(code, _.languages[lang])))); +++ _self.close(); +++ }, false); +++ +++ return _self.Prism; +++} +++ +++// Get current script and highlight +++var script = document.getElementsByTagName('script'); +++ +++script = script[script.length - 1]; +++ +++if (script) { +++ _.filename = script.src; +++ +++ if (document.addEventListener && !script.hasAttribute('data-manual')) { +++ document.addEventListener('DOMContentLoaded', _.highlightAll); +++ } +++} +++ +++return _self.Prism; +++ +++})(); +++ +++if (typeof module !== 'undefined' && module.exports) { +++ module.exports = Prism; +++} +++; +++Prism.languages.markup = { +++ 'comment': //, +++ 'prolog': /<\?[\w\W]+?\?>/, +++ 'doctype': //, +++ 'cdata': //i, +++ 'tag': { +++ pattern: /<\/?[^\s>\/]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i, +++ inside: { +++ 'tag': { +++ pattern: /^<\/?[^\s>\/]+/i, +++ inside: { +++ 'punctuation': /^<\/?/, +++ 'namespace': /^[^\s>\/:]+:/ +++ } +++ }, +++ 'attr-value': { +++ pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i, +++ inside: { +++ 'punctuation': /[=>"']/ +++ } +++ }, +++ 'punctuation': /\/?>/, +++ 'attr-name': { +++ pattern: /[^\s>\/]+/, +++ inside: { +++ 'namespace': /^[^\s>\/:]+:/ +++ } +++ } +++ +++ } +++ }, +++ 'entity': /&#?[\da-z]{1,8};/i +++}; +++ +++// Plugin to make entity title show the real entity, idea by Roman Komarov +++Prism.hooks.add('wrap', function(env) { +++ +++ if (env.type === 'entity') { +++ env.attributes['title'] = env.content.replace(/&/, '&'); +++ } +++}); +++; +++Prism.languages.css = { +++ 'comment': /\/\*[\w\W]*?\*\//, +++ 'atrule': { +++ pattern: /@[\w-]+?.*?(;|(?=\s*\{))/i, +++ inside: { +++ 'rule': /@[\w-]+/ +++ // See rest below +++ } +++ }, +++ 'url': /url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i, +++ 'selector': /[^\{\}\s][^\{\};]*?(?=\s*\{)/, +++ 'string': /("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/, +++ 'property': /(\b|\B)[\w-]+(?=\s*:)/i, +++ 'important': /\B!important\b/i, +++ 'function': /[-a-z0-9]+(?=\()/i, +++ 'punctuation': /[(){};:]/ +++}; +++ +++Prism.languages.css['atrule'].inside.rest = Prism.util.clone(Prism.languages.css); +++ +++if (Prism.languages.markup) { +++ Prism.languages.insertBefore('markup', 'tag', { +++ 'style': { +++ pattern: /[\w\W]*?<\/style>/i, +++ inside: { +++ 'tag': { +++ pattern: /|<\/style>/i, +++ inside: Prism.languages.markup.tag.inside +++ }, +++ rest: Prism.languages.css +++ }, +++ alias: 'language-css' +++ } +++ }); +++ +++ Prism.languages.insertBefore('inside', 'attr-value', { +++ 'style-attr': { +++ pattern: /\s*style=("|').*?\1/i, +++ inside: { +++ 'attr-name': { +++ pattern: /^\s*style/i, +++ inside: Prism.languages.markup.tag.inside +++ }, +++ 'punctuation': /^\s*=\s*['"]|['"]\s*$/, +++ 'attr-value': { +++ pattern: /.+/i, +++ inside: Prism.languages.css +++ } +++ }, +++ alias: 'language-css' +++ } +++ }, Prism.languages.markup.tag); +++}; +++Prism.languages.clike = { +++ 'comment': [ +++ { +++ pattern: /(^|[^\\])\/\*[\w\W]*?\*\//, +++ lookbehind: true +++ }, +++ { +++ pattern: /(^|[^\\:])\/\/.*/, +++ lookbehind: true +++ } +++ ], +++ 'string': /("|')(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, +++ 'class-name': { +++ pattern: /((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i, +++ lookbehind: true, +++ inside: { +++ punctuation: /(\.|\\)/ +++ } +++ }, +++ 'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/, +++ 'boolean': /\b(true|false)\b/, +++ 'function': /[a-z0-9_]+(?=\()/i, +++ 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/, +++ 'operator': /[-+]{1,2}|!|<=?|>=?|={1,3}|&{1,2}|\|?\||\?|\*|\/|~|\^|%/, +++ 'punctuation': /[{}[\];(),.:]/ +++}; +++; +++Prism.languages.javascript = Prism.languages.extend('clike', { +++ 'keyword': /\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/, +++ 'number': /\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/, +++ 'function': /(?!\d)[a-z0-9_$]+(?=\()/i +++}); +++ +++Prism.languages.insertBefore('javascript', 'keyword', { +++ 'regex': { +++ pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/, +++ lookbehind: true +++ } +++}); +++ +++Prism.languages.insertBefore('javascript', 'class-name', { +++ 'template-string': { +++ pattern: /`(?:\\`|\\?[^`])*`/, +++ inside: { +++ 'interpolation': { +++ pattern: /\$\{[^}]+\}/, +++ inside: { +++ 'interpolation-punctuation': { +++ pattern: /^\$\{|\}$/, +++ alias: 'punctuation' +++ }, +++ rest: Prism.languages.javascript +++ } +++ }, +++ 'string': /[\s\S]+/ +++ } +++ } +++}); +++ +++if (Prism.languages.markup) { +++ Prism.languages.insertBefore('markup', 'tag', { +++ 'script': { +++ pattern: /[\w\W]*?<\/script>/i, +++ inside: { +++ 'tag': { +++ pattern: /|<\/script>/i, +++ inside: Prism.languages.markup.tag.inside +++ }, +++ rest: Prism.languages.javascript +++ }, +++ alias: 'language-javascript' +++ } +++ }); +++} +++; diff --cc debian/not-installed index 0000000000,0000000000,0000000000..dc6ebbe131 new file mode 100644 --- /dev/null +++ b/debian/not-installed @@@@ -1,0 -1,0 -1,0 +1,26 @@@@ +++# rust-installer stuff, not relevant for Debian +++usr/lib/rustlib/components +++usr/lib/rustlib/install.log +++usr/lib/rustlib/manifest-* +++usr/lib/rustlib/rust-installer-version +++usr/lib/rustlib/uninstall.sh +++ +++# redundant copy of llvm-dwp, we already link it in rustc.links +++usr/lib/rustlib/*/bin/rust-llvm-dwp +++ +++# redundant copy of llvm-objcopy, we already link it in rustc.links +++usr/lib/rustlib/*/bin/rust-objcopy +++ +++# docs, we already install into /usr/share/doc/rustc +++usr/share/doc/docs/* +++ +++# already contained in d/copyright and rust-src +++usr/share/doc/*/LICENSE-* +++usr/share/doc/*/README.md +++usr/share/doc/rustc/COPYRIGHT +++ +++# should be claimed by dh_bash-completion +++etc/bash_completion.d/cargo +++ +++# backup files from the previous stages +++usr/bin/*.old diff --cc debian/patches-unused/d-bootstrap-use-system-compiler-rt.patch index 0000000000,0000000000,0000000000..9c34e7257b new file mode 100644 --- /dev/null +++ b/debian/patches-unused/d-bootstrap-use-system-compiler-rt.patch @@@@ -1,0 -1,0 -1,0 +1,40 @@@@ +++Description: Use system compiler-rt from clang, EXPERIMENTAL AND NOT WORKING YET +++Forwarded: not-needed +++--- a/src/bootstrap/compile.rs ++++++ b/src/bootstrap/compile.rs +++@@ -200,6 +200,12 @@ +++ let mut features = builder.std_features(); +++ features.push_str(&compiler_builtins_c_feature); +++ ++++ // In Debian this is always available ++++ let llvm_config = builder.ensure(native::Llvm { ++++ target: builder.config.build, ++++ emscripten: false, ++++ }); ++++ cargo.env("LLVM_CONFIG", llvm_config); +++ if compiler.stage != 0 && builder.config.sanitizers { +++ // This variable is used by the sanitizer runtime crates, e.g. +++ // rustc_lsan, to build the sanitizer runtime from C code +++@@ -208,11 +214,6 @@ +++ // missing +++ // We also only build the runtimes when --enable-sanitizers (or its +++ // config.toml equivalent) is used +++- let llvm_config = builder.ensure(native::Llvm { +++- target: builder.config.build, +++- emscripten: false, +++- }); +++- cargo.env("LLVM_CONFIG", llvm_config); +++ cargo.env("RUSTC_BUILD_SANITIZERS", "1"); +++ } +++ +++--- a/vendor/compiler_builtins/Cargo.toml ++++++ b/vendor/compiler_builtins/Cargo.toml +++@@ -49,7 +49,7 @@ +++ # LLVM_CONFIG or CLANG (more reliable) must be set. +++ c-system = [] +++ +++-c = ["c-vendor"] ++++c = ["c-system"] +++ compiler-builtins = [] +++ default = ["compiler-builtins"] +++ mangled-names = [] diff --cc debian/patches-unused/d-rustc-prefer-dynamic.patch index 0000000000,0000000000,0000000000..13bb429220 new file mode 100644 --- /dev/null +++ b/debian/patches-unused/d-rustc-prefer-dynamic.patch @@@@ -1,0 -1,0 -1,0 +1,18 @@@@ +++Description: Prefer dynamic linking (currently disabled, not applied) +++ As per Debian policy, we basically revert +++ https://github.com/rust-lang/rfcs/blob/master/text/0404-change-prefer-dynamic.md +++ TODO: this does not yet work: https://github.com/rust-lang/rust/issues/43289 +++ Perhaps a better method would be to modify dh-cargo instead of rustc +++Author: Ximin Luo +++Forwarded: not-needed +++--- a/src/librustc/session/config.rs ++++++ b/src/librustc/session/config.rs +++@@ -846,7 +846,7 @@ +++ "don't run LLVM's SLP vectorization pass"), +++ soft_float: bool = (false, parse_bool, [TRACKED], +++ "use soft float ABI (*eabihf targets only)"), +++- prefer_dynamic: bool = (false, parse_bool, [TRACKED], ++++ prefer_dynamic: bool = (true, parse_bool, [TRACKED], +++ "prefer dynamic linking to static linking"), +++ no_integrated_as: bool = (false, parse_bool, [TRACKED], +++ "use an external assembler rather than LLVM's integrated one"), diff --cc debian/patches-unused/d-test-host-duplicates.patch index 0000000000,0000000000,0000000000..50c39adf90 new file mode 100644 --- /dev/null +++ b/debian/patches-unused/d-test-host-duplicates.patch @@@@ -1,0 -1,0 -1,0 +1,20 @@@@ +++Description: Work around #842634 on some machines, e.g. Debian porterboxes +++ This should remain commented-out in debian/patches/series, it's not needed everywhere +++Author: Ximin Luo +++Forwarded: not-needed +++--- +++This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +++--- a/library/std/src/sys_common/net/tests.rs ++++++ b/library/std/src/sys_common/net/tests.rs +++@@ -11,8 +11,10 @@ +++ for sa in lh { +++ *addrs.entry(sa).or_insert(0) += 1; +++ } ++++ let mut v = addrs.iter().filter(|&(_, &v)| v > 1).collect::>(); ++++ v.clear(); +++ assert_eq!( +++- addrs.iter().filter(|&(_, &v)| v > 1).collect::>(), ++++ v, +++ vec![], +++ "There should be no duplicate localhost entries" +++ ); diff --cc debian/patches-unused/u-allow-system-compiler-rt.patch index 0000000000,0000000000,0000000000..3bd874a5ce new file mode 100644 --- /dev/null +++ b/debian/patches-unused/u-allow-system-compiler-rt.patch @@@@ -1,0 -1,0 -1,0 +1,327 @@@@ +++Description: Support linking against system clang libs +++ Note: the above PR only covers the compiler_builtins crate, rustc itself also +++ needs patching as per below once that is accepted. +++Forwarded: https://github.com/rust-lang-nursery/compiler-builtins/pull/296 +++--- a/vendor/compiler_builtins/Cargo.toml ++++++ b/vendor/compiler_builtins/Cargo.toml +++@@ -43,7 +43,13 @@ +++ optional = true +++ +++ [features] +++-c = ["cc"] ++++c-vendor = ["cc"] ++++ ++++# Link against system clang_rt.* libraries. ++++# LLVM_CONFIG or CLANG (more reliable) must be set. ++++c-system = [] ++++ ++++c = ["c-vendor"] +++ compiler-builtins = [] +++ default = ["compiler-builtins"] +++ mangled-names = [] +++--- a/vendor/compiler_builtins/build.rs ++++++ b/vendor/compiler_builtins/build.rs +++@@ -37,7 +37,7 @@ +++ // mangling names though we assume that we're also in test mode so we don't +++ // build anything and we rely on the upstream implementation of compiler-rt +++ // functions +++- if !cfg!(feature = "mangled-names") && cfg!(feature = "c") { ++++ if !cfg!(feature = "mangled-names") && cfg!(any(feature = "c-vendor", feature = "c-system")) { +++ // Don't use a C compiler for these targets: +++ // +++ // * wasm32 - clang 8 for wasm is somewhat hard to come by and it's +++@@ -47,8 +47,10 @@ +++ // compiler nor is cc-rs ready for compilation to riscv (at this +++ // time). This can probably be removed in the future +++ if !target.contains("wasm32") && !target.contains("nvptx") && !target.starts_with("riscv") { +++- #[cfg(feature = "c")] +++- c::compile(&llvm_target); ++++ #[cfg(feature = "c-vendor")] ++++ c_vendor::compile(&llvm_target); ++++ #[cfg(feature = "c-system")] ++++ c_system::compile(&llvm_target); +++ } +++ } +++ +++@@ -70,17 +72,14 @@ +++ } +++ } +++ +++-#[cfg(feature = "c")] +++-mod c { +++- extern crate cc; +++- ++++#[cfg(any(feature = "c-vendor", feature = "c-system"))] ++++mod sources { +++ use std::collections::BTreeMap; +++ use std::env; +++- use std::path::PathBuf; +++ +++- struct Sources { ++++ pub struct Sources { +++ // SYMBOL -> PATH TO SOURCE +++- map: BTreeMap<&'static str, &'static str>, ++++ pub map: BTreeMap<&'static str, &'static str>, +++ } +++ +++ impl Sources { +++@@ -117,39 +116,11 @@ +++ } +++ } +++ +++- /// Compile intrinsics from the compiler-rt C source code +++- pub fn compile(llvm_target: &[&str]) { ++++ pub fn get_sources(llvm_target: &[&str]) -> Sources { +++ let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); +++ let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); +++ let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); +++ let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap(); +++- let cfg = &mut cc::Build::new(); +++- +++- cfg.warnings(false); +++- +++- if target_env == "msvc" { +++- // Don't pull in extra libraries on MSVC +++- cfg.flag("/Zl"); +++- +++- // Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP +++- cfg.define("__func__", Some("__FUNCTION__")); +++- } else { +++- // Turn off various features of gcc and such, mostly copying +++- // compiler-rt's build system already +++- cfg.flag("-fno-builtin"); +++- cfg.flag("-fvisibility=hidden"); +++- cfg.flag("-ffreestanding"); +++- // Avoid the following warning appearing once **per file**: +++- // clang: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7' [-Wignored-optimization-argument] +++- // +++- // Note that compiler-rt's build system also checks +++- // +++- // `check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)` +++- // +++- // in https://github.com/rust-lang/compiler-rt/blob/c8fbcb3/cmake/config-ix.cmake#L19. +++- cfg.flag_if_supported("-fomit-frame-pointer"); +++- cfg.define("VISIBILITY_HIDDEN", None); +++- } +++ +++ let mut sources = Sources::new(); +++ sources.extend(&[ +++@@ -411,6 +382,48 @@ +++ sources.remove(&["__aeabi_cdcmp", "__aeabi_cfcmp"]); +++ } +++ ++++ sources ++++ } ++++} ++++ ++++#[cfg(feature = "c-vendor")] ++++mod c_vendor { ++++ extern crate cc; ++++ ++++ use std::env; ++++ use std::path::PathBuf; ++++ use sources; ++++ ++++ /// Compile intrinsics from the compiler-rt C source code ++++ pub fn compile(llvm_target: &[&str]) { ++++ let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); ++++ let cfg = &mut cc::Build::new(); ++++ cfg.warnings(false); ++++ ++++ if target_env == "msvc" { ++++ // Don't pull in extra libraries on MSVC ++++ cfg.flag("/Zl"); ++++ ++++ // Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP ++++ cfg.define("__func__", Some("__FUNCTION__")); ++++ } else { ++++ // Turn off various features of gcc and such, mostly copying ++++ // compiler-rt's build system already ++++ cfg.flag("-fno-builtin"); ++++ cfg.flag("-fvisibility=hidden"); ++++ cfg.flag("-ffreestanding"); ++++ // Avoid the following warning appearing once **per file**: ++++ // clang: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7' [-Wignored-optimization-argument] ++++ // ++++ // Note that compiler-rt's build system also checks ++++ // ++++ // `check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)` ++++ // ++++ // in https://github.com/rust-lang/compiler-rt/blob/c8fbcb3/cmake/config-ix.cmake#L19. ++++ cfg.flag_if_supported("-fomit-frame-pointer"); ++++ cfg.define("VISIBILITY_HIDDEN", None); ++++ } ++++ +++ // When compiling the C code we require the user to tell us where the +++ // source code is, and this is largely done so when we're compiling as +++ // part of rust-lang/rust we can use the same llvm-project repository as +++@@ -423,6 +436,7 @@ +++ panic!("RUST_COMPILER_RT_ROOT={} does not exist", root.display()); +++ } +++ ++++ let sources = sources::get_sources(llvm_target); +++ let src_dir = root.join("lib/builtins"); +++ for (sym, src) in sources.map.iter() { +++ let src = src_dir.join(src); +++@@ -434,3 +448,103 @@ +++ cfg.compile("libcompiler-rt.a"); +++ } +++ } ++++ ++++#[cfg(feature = "c-system")] ++++mod c_system { ++++ use std::env; ++++ use std::process::{Command, Output}; ++++ use std::str; ++++ use std::path::Path; ++++ use sources; ++++ ++++ fn success_output(err: &str, cmd: &mut Command) -> Output { ++++ let output = cmd.output().expect(err); ++++ let status = output.status; ++++ if !status.success() { ++++ panic!("{}: {:?}", err, status.code()); ++++ } ++++ output ++++ } ++++ ++++ // This can be obtained by adding the line: ++++ // message(STATUS "All builtin supported architectures: ${ALL_BUILTIN_SUPPORTED_ARCH}") ++++ // to the bottom of compiler-rt/cmake/builtin-config-ix.cmake, then running ++++ // cmake and looking at the output. ++++ const ALL_SUPPORTED_ARCHES : &'static str = "i386;x86_64;arm;armhf;armv6m;armv7m;armv7em;armv7;armv7s;armv7k;aarch64;hexagon;mips;mipsel;mips64;mips64el;powerpc64;powerpc64le;riscv32;riscv64;wasm32;wasm64"; ++++ ++++ // This function recreates the logic of getArchNameForCompilerRTLib, ++++ // defined in clang/lib/Driver/ToolChain.cpp. ++++ fn get_arch_name_for_compiler_rtlib() -> String { ++++ let target = env::var("TARGET").unwrap(); ++++ let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); ++++ let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); ++++ let r = match target_arch.as_str() { ++++ "arm" => if target.ends_with("eabihf") && target_os != "windows" { ++++ "armhf" ++++ } else { ++++ "arm" ++++ }, ++++ "x86" => if target_os == "android" { ++++ "i686" ++++ } else { ++++ "i386" ++++ }, ++++ _ => target_arch.as_str(), ++++ }; ++++ r.to_string() ++++ } ++++ ++++ /// Link against system clang runtime libraries ++++ pub fn compile(llvm_target: &[&str]) { ++++ let target = env::var("TARGET").unwrap(); ++++ let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); ++++ let compiler_rt_arch = get_arch_name_for_compiler_rtlib(); ++++ ++++ if ALL_SUPPORTED_ARCHES.split(";").find(|x| *x == compiler_rt_arch) == None { ++++ return; ++++ } ++++ ++++ if let Ok(clang) = env::var("CLANG") { ++++ let output = success_output( ++++ "failed to find clang's compiler-rt", ++++ Command::new(clang) ++++ .arg(format!("--target={}", target)) ++++ .arg("--rtlib=compiler-rt") ++++ .arg("--print-libgcc-file-name"), ++++ ); ++++ let fullpath = Path::new(str::from_utf8(&output.stdout).unwrap()); ++++ let libpath = fullpath.parent().unwrap().display(); ++++ let libname = fullpath ++++ .file_stem() ++++ .unwrap() ++++ .to_str() ++++ .unwrap() ++++ .trim_start_matches("lib"); ++++ println!("cargo:rustc-link-search=native={}", libpath); ++++ println!("cargo:rustc-link-lib=static={}", libname); ++++ } else if let Ok(llvm_config) = env::var("LLVM_CONFIG") { ++++ // fallback if clang is not installed ++++ let (subpath, libname) = match target_os.as_str() { ++++ "linux" => ("linux", format!("clang_rt.builtins-{}", &compiler_rt_arch)), ++++ "macos" => ("darwin", "clang_rt.builtins_osx_dynamic".to_string()), ++++ _ => panic!("unsupported target os: {}", target_os), ++++ }; ++++ let cmd = format!("ls -1d $({} --libdir)/clang/*/lib/{}", llvm_config, subpath); ++++ let output = success_output( ++++ "failed to find clang's lib dir", ++++ Command::new("sh").args(&["-ec", &cmd]), ++++ ); ++++ for search_dir in str::from_utf8(&output.stdout).unwrap().lines() { ++++ println!("cargo:rustc-link-search=native={}", search_dir); ++++ } ++++ println!("cargo:rustc-link-lib=static={}", libname); ++++ } else { ++++ panic!("neither CLANG nor LLVM_CONFIG could be read"); ++++ } ++++ ++++ let sources = sources::get_sources(llvm_target); ++++ for (sym, _src) in sources.map.iter() { ++++ println!("cargo:rustc-cfg={}=\"optimized-c\"", sym); ++++ } ++++ } ++++} +++--- a/src/bootstrap/compile.rs ++++++ b/src/bootstrap/compile.rs +++@@ -213,6 +213,7 @@ +++ emscripten: false, +++ }); +++ cargo.env("LLVM_CONFIG", llvm_config); ++++ cargo.env("RUSTC_BUILD_SANITIZERS", "1"); +++ } +++ +++ cargo.arg("--features").arg(features) +++--- a/src/librustc_asan/build.rs ++++++ b/src/librustc_asan/build.rs +++@@ -4,6 +4,9 @@ +++ use cmake::Config; +++ +++ fn main() { ++++ if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { ++++ return; ++++ } +++ if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { +++ build_helper::restore_library_path(); +++ +++--- a/src/librustc_lsan/build.rs ++++++ b/src/librustc_lsan/build.rs +++@@ -4,6 +4,9 @@ +++ use cmake::Config; +++ +++ fn main() { ++++ if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { ++++ return; ++++ } +++ if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { +++ build_helper::restore_library_path(); +++ +++--- a/src/librustc_msan/build.rs ++++++ b/src/librustc_msan/build.rs +++@@ -4,6 +4,9 @@ +++ use cmake::Config; +++ +++ fn main() { ++++ if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { ++++ return; ++++ } +++ if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { +++ build_helper::restore_library_path(); +++ +++--- a/src/librustc_tsan/build.rs ++++++ b/src/librustc_tsan/build.rs +++@@ -4,6 +4,9 @@ +++ use cmake::Config; +++ +++ fn main() { ++++ if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { ++++ return; ++++ } +++ if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { +++ build_helper::restore_library_path(); +++ diff --cc debian/patches/behaviour/d-rust-gdb-paths.patch index 0000000000,0000000000,0000000000..86d9c2d4dd new file mode 100644 --- /dev/null +++ b/debian/patches/behaviour/d-rust-gdb-paths.patch @@@@ -1,0 -1,0 -1,0 +1,25 @@@@ +++From: Angus Lees +++Date: Thu, 14 Jul 2022 13:17:39 +0200 +++Subject: Hardcode GDB python module directory +++ +++Debian package installs python modules into a fixed directory, so +++just hardcode path in wrapper script. +++ +++Forwarded: not-needed +++--- +++ src/etc/rust-gdbgui | 2 +- +++ 1 file changed, 1 insertion(+), 1 deletion(-) +++ +++diff --git a/src/etc/rust-gdbgui b/src/etc/rust-gdbgui +++index 471810c..be62b44 100755 +++--- a/src/etc/rust-gdbgui ++++++ b/src/etc/rust-gdbgui +++@@ -40,7 +40,7 @@ else +++ fi +++ +++ # Find out where the pretty printer Python module is +++-RUSTC_SYSROOT="$("$RUSTC" --print=sysroot)" ++++RUSTC_SYSROOT="$(if type "$RUSTC" >/dev/null 2>&1; then "$RUSTC" --print=sysroot; else echo /usr; fi)" +++ GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc" +++ # Get the commit hash for path remapping +++ RUSTC_COMMIT_HASH="$("$RUSTC" -vV | sed -n 's/commit-hash: \([a-zA-Z0-9_]*\)/\1/p')" diff --cc debian/patches/behaviour/d-rust-lldb-paths.patch index 0000000000,0000000000,0000000000..99b4c6bffa new file mode 100644 --- /dev/null +++ b/debian/patches/behaviour/d-rust-lldb-paths.patch @@@@ -1,0 -1,0 -1,0 +1,29 @@@@ +++From: Angus Lees +++Date: Thu, 14 Jul 2022 13:17:39 +0200 +++Subject: Hardcode LLDB python module directory +++ +++Debian package installs python modules into a fixed directory, so +++just hardcode path in wrapper script. +++ +++Forwarded: not-needed +++--- +++ src/etc/rust-lldb | 4 ++-- +++ 1 file changed, 2 insertions(+), 2 deletions(-) +++ +++diff --git a/src/etc/rust-lldb b/src/etc/rust-lldb +++index bce72f1..38e76c2 100755 +++--- a/src/etc/rust-lldb ++++++ b/src/etc/rust-lldb +++@@ -7,10 +7,10 @@ set -e +++ host=$(rustc -vV | sed -n -e 's/^host: //p') +++ +++ # Find out where to look for the pretty printer Python module +++-RUSTC_SYSROOT=$(rustc --print sysroot) ++++RUSTC_SYSROOT="$(if type "$RUSTC" >/dev/null 2>&1; then "$RUSTC" --print=sysroot; else echo /usr; fi)" +++ RUST_LLDB="$RUSTC_SYSROOT/lib/rustlib/$host/bin/lldb" +++ +++-lldb=lldb ++++lldb=lldb-19 +++ if [ -f "$RUST_LLDB" ]; then +++ lldb="$RUST_LLDB" +++ else diff --cc debian/patches/behaviour/d-rustc-add-soname.patch index 0000000000,0000000000,0000000000..1e45a70f12 new file mode 100644 --- /dev/null +++ b/debian/patches/behaviour/d-rustc-add-soname.patch @@@@ -1,0 -1,0 -1,0 +1,63 @@@@ +++From: Angus Lees +++Date: Thu, 14 Jul 2022 13:17:39 +0200 +++Subject: Set DT_SONAME when building dylibs +++ +++In Rust, library filenames include a version-specific hash to help +++the run-time linker find the correct version. Unlike in C/C++, the +++compiler looks for all libraries matching a glob that ignores the +++hash and reads embedded metadata to work out versions, etc. +++ +++The upshot is that there is no need for the usual "libfoo.so -> +++libfoo-1.2.3.so" symlink common with C/C++ when building with Rust, +++and no need to communicate an alternate filename to use at run-time +++vs compile time. If linking to a Rust dylib from C/C++ however, a +++"libfoo.so -> libfoo-$hash.so" symlink may well be useful and in +++this case DT_SONAME=libfoo-$hash.so would be required. More +++mundanely, various tools (eg: dpkg-shlibdeps) complain if they don't +++find DT_SONAME on shared libraries in public directories. +++ +++This patch passes -Wl,-soname=$outfile when building dylibs (and +++using a GNU linker). +++ +++Forwarded: no +++--- +++ compiler/rustc_codegen_ssa/src/back/link.rs | 7 +++++++ +++ tests/run-make/dylib-soname/rmake.rs | 4 +++- +++ 2 files changed, 10 insertions(+), 1 deletion(-) +++ +++diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs +++index e2081ad..e0594f9 100644 +++--- a/compiler/rustc_codegen_ssa/src/back/link.rs ++++++ b/compiler/rustc_codegen_ssa/src/back/link.rs +++@@ -2548,6 +2548,13 @@ fn add_order_independent_options( +++ } +++ +++ add_rpath_args(cmd, sess, codegen_results, out_filename); ++++ ++++ if (crate_type == config::CrateType::Dylib || crate_type == config::CrateType::Cdylib) ++++ && sess.target.linker_flavor.is_gnu() { ++++ let filename = String::from(out_filename.file_name().unwrap().to_str().unwrap()); ++++ let soname = [String::from("-Wl,-soname=") + &filename]; ++++ cmd.cc_args(&soname); ++++ } +++ } +++ +++ // Write the NatVis debugger visualizer files for each crate to the temp directory and gather the file paths. +++diff --git a/tests/run-make/dylib-soname/rmake.rs b/tests/run-make/dylib-soname/rmake.rs +++index 714997c..653a0fe 100644 +++--- a/tests/run-make/dylib-soname/rmake.rs ++++++ b/tests/run-make/dylib-soname/rmake.rs +++@@ -3,10 +3,12 @@ +++ +++ //@ only-linux +++ //@ ignore-cross-compile +++- +++ use run_make_support::{cmd, run_in_tmpdir, rustc}; +++ +++ fn main() { ++++ // Debian: we patch rustc to intentionally insert the soname ++++ return; ++++ +++ let check = |ty: &str| { +++ rustc().crate_name("foo").crate_type(ty).input("foo.rs").run(); +++ cmd("readelf").arg("-d").arg("libfoo.so").run() diff --cc debian/patches/behaviour/d-rustc-windows-ssp.patch index 0000000000,0000000000,0000000000..256b4e981d new file mode 100644 --- /dev/null +++ b/debian/patches/behaviour/d-rustc-windows-ssp.patch @@@@ -1,0 -1,0 -1,0 +1,22 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 14 Jul 2022 13:17:39 +0200 +++Subject: d-rustc-windows-ssp +++ +++Bug: https://github.com/rust-lang/rust/issues/68973 +++--- +++ compiler/rustc_target/src/spec/base/windows_gnu.rs | 2 ++ +++ 1 file changed, 2 insertions(+) +++ +++diff --git a/compiler/rustc_target/src/spec/base/windows_gnu.rs b/compiler/rustc_target/src/spec/base/windows_gnu.rs +++index e975102..9876a4f 100644 +++--- a/compiler/rustc_target/src/spec/base/windows_gnu.rs ++++++ b/compiler/rustc_target/src/spec/base/windows_gnu.rs +++@@ -40,6 +40,8 @@ pub(crate) fn opts() -> TargetOptions { +++ "-lmingwex", +++ "-luser32", +++ "-lkernel32", ++++ "-lssp_nonshared", ++++ "-lssp", +++ ]; +++ let mut late_link_args = +++ TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs); diff --cc debian/patches/behaviour/d-rustdoc-disable-embedded-fonts.patch index 0000000000,0000000000,0000000000..cfe1848581 new file mode 100644 --- /dev/null +++ b/debian/patches/behaviour/d-rustdoc-disable-embedded-fonts.patch @@@@ -1,0 -1,0 -1,0 +1,43 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 14 Jul 2022 13:17:39 +0200 +++Subject: removed some embedded fonts +++ +++Forwarded: not-needed +++=================================================================== +++--- +++ src/librustdoc/html/static/css/rustdoc.css | 8 -------- +++ src/librustdoc/html/static_files.rs | 2 -- +++ 2 files changed, 10 deletions(-) +++ +++diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css +++index 2749638..4bb6ec7 100644 +++--- a/src/librustdoc/html/static/css/rustdoc.css ++++++ b/src/librustdoc/html/static/css/rustdoc.css +++@@ -109,14 +109,6 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\ +++ font-display: swap; +++ } +++ +++-/* Avoid using legacy CJK serif fonts in Windows like Batang. */ +++-@font-face { +++- font-family: 'NanumBarunGothic'; +++- src: url("NanumBarunGothic-13b3dcba.ttf.woff2") format("woff2"); +++- font-display: swap; +++- unicode-range: U+AC00-D7AF, U+1100-11FF, U+3130-318F, U+A960-A97F, U+D7B0-D7FF; +++-} +++- +++ * { +++ box-sizing: border-box; +++ } +++diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs +++index 6457ac7..e8eaf3b 100644 +++--- a/src/librustdoc/html/static_files.rs ++++++ b/src/librustdoc/html/static_files.rs +++@@ -109,8 +109,6 @@ static_files! { +++ source_code_pro_semibold => "static/fonts/SourceCodePro-Semibold.ttf.woff2", +++ source_code_pro_italic => "static/fonts/SourceCodePro-It.ttf.woff2", +++ source_code_pro_license => "static/fonts/SourceCodePro-LICENSE.txt", +++- nanum_barun_gothic_regular => "static/fonts/NanumBarunGothic.ttf.woff2", +++- nanum_barun_gothic_license => "static/fonts/NanumBarunGothic-LICENSE.txt", +++ } +++ +++ pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/scrape-examples-help.md"); diff --cc debian/patches/behaviour/proc-macro-srv-make-usage-of-RTLD_DEEPBIND-portable.patch index 0000000000,0000000000,0000000000..24d8eb3c71 new file mode 100644 --- /dev/null +++ b/debian/patches/behaviour/proc-macro-srv-make-usage-of-RTLD_DEEPBIND-portable.patch @@@@ -1,0 -1,0 -1,0 +1,71 @@@@ +++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= +++Date: Thu, 16 Jan 2025 16:34:12 +0100 +++Subject: proc-macro-srv: make usage of RTLD_DEEPBIND portable +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++the constant is wrong on some platforms (e.g., on mips64el it's 0x10, and 0x8 +++is RTLD_NOLOAD which makes all this functionality broken), the libc crate takes +++care of those differences for us. +++ +++fallback to old hard-coded value for non-glibc environments (which might or +++might not of DEEPBIND support). +++ +++Forwarded: https://github.com/rust-lang/rust/pull/135591 +++ +++Signed-off-by: Fabian Grünbichler +++--- +++ src/tools/rust-analyzer/Cargo.lock | 1 + +++ src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml | 1 + +++ src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs | 11 ++++++++--- +++ 3 files changed, 10 insertions(+), 3 deletions(-) +++ +++diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock +++index 2323fdf..9e0a24d 100644 +++--- a/src/tools/rust-analyzer/Cargo.lock ++++++ b/src/tools/rust-analyzer/Cargo.lock +++@@ -1371,6 +1371,7 @@ version = "0.0.0" +++ dependencies = [ +++ "expect-test", +++ "intern", ++++ "libc", +++ "libloading", +++ "memmap2", +++ "object 0.33.0", +++diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml +++index 9838596..c0881b0 100644 +++--- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml ++++++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml +++@@ -14,6 +14,7 @@ doctest = false +++ +++ [dependencies] +++ object.workspace = true ++++libc.workspace = true +++ libloading.workspace = true +++ memmap2.workspace = true +++ +++diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs +++index 26f6af8..4599e65 100644 +++--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs ++++++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs +++@@ -59,11 +59,16 @@ fn load_library(file: &Utf8Path) -> Result { +++ +++ #[cfg(unix)] +++ fn load_library(file: &Utf8Path) -> Result { ++++ // not defined by POSIX, different values on mips vs other targets ++++ #[cfg(target_env = "gnu")] ++++ use libc::RTLD_DEEPBIND; +++ use libloading::os::unix::Library as UnixLibrary; +++- use std::os::raw::c_int; ++++ // defined by POSIX ++++ use libloading::os::unix::RTLD_NOW; +++ +++- const RTLD_NOW: c_int = 0x00002; +++- const RTLD_DEEPBIND: c_int = 0x00008; ++++ // MUSL and bionic don't have it.. ++++ #[cfg(not(target_env = "gnu"))] ++++ const RTLD_DEEPBIND: std::os::raw::c_int = 0x0; +++ +++ unsafe { UnixLibrary::open(Some(file), RTLD_NOW | RTLD_DEEPBIND).map(|lib| lib.into()) } +++ } diff --cc debian/patches/bootstrap/bootstrap-revert-cross-build-breaking-change.patch index 0000000000,0000000000,0000000000..a65ddaf14f new file mode 100644 --- /dev/null +++ b/debian/patches/bootstrap/bootstrap-revert-cross-build-breaking-change.patch @@@@ -1,0 -1,0 -1,0 +1,49 @@@@ +++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= +++Date: Tue, 21 Jan 2025 10:43:33 +0100 +++Subject: bootstrap: revert cross-build breaking change +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++this reverts 68034f837a39387e49fc7d7c5b088f5372a1127e modulo file split that +++happened afterwards. +++ +++Forwarded: https://github.com/rust-lang/rust/issues/133629 +++ +++Signed-off-by: Fabian Grünbichler +++--- +++ src/bootstrap/src/core/builder/cargo.rs | 20 +++----------------- +++ 1 file changed, 3 insertions(+), 17 deletions(-) +++ +++diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs +++index 55e4cc4..47ab244 100644 +++--- a/src/bootstrap/src/core/builder/cargo.rs ++++++ b/src/bootstrap/src/core/builder/cargo.rs +++@@ -657,24 +657,10 @@ impl Builder<'_> { +++ match mode { +++ Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {} +++ Mode::Rustc | Mode::Codegen | Mode::ToolRustc => { +++- // Build proc macros both for the host and the target unless proc-macros are not +++- // supported by the target. ++++ // Build proc macros both for the host and the target +++ if target != compiler.host && cmd_kind != Kind::Check { +++- let error = command(self.rustc(compiler)) +++- .arg("--target") +++- .arg(target.rustc_target_arg()) +++- .arg("--print=file-names") +++- .arg("--crate-type=proc-macro") +++- .arg("-") +++- .run_capture(self) +++- .stderr(); +++- let not_supported = error +++- .lines() +++- .any(|line| line.contains("unsupported crate type `proc-macro`")); +++- if !not_supported { +++- cargo.arg("-Zdual-proc-macros"); +++- rustflags.arg("-Zdual-proc-macros"); +++- } ++++ cargo.arg("-Zdual-proc-macros"); ++++ rustflags.arg("-Zdual-proc-macros"); +++ } +++ } +++ } diff --cc debian/patches/build/bootstrap-don-t-attempt-to-download-rustc-in-tests.patch index 0000000000,0000000000,0000000000..b761cf2ddc new file mode 100644 --- /dev/null +++ b/debian/patches/build/bootstrap-don-t-attempt-to-download-rustc-in-tests.patch @@@@ -1,0 -1,0 -1,0 +1,30 @@@@ +++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= +++Date: Sat, 11 Jan 2025 16:37:16 +0100 +++Subject: bootstrap: don't attempt to download rustc in tests +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++the tests use a default config, so we need to manually override this +++option.. +++ +++Signed-off-by: Fabian Grünbichler +++--- +++ src/bootstrap/src/core/config/config.rs | 4 ++++ +++ 1 file changed, 4 insertions(+) +++ +++diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs +++index d77da96..b1c6238 100644 +++--- a/src/bootstrap/src/core/config/config.rs ++++++ b/src/bootstrap/src/core/config/config.rs +++@@ -1456,6 +1456,10 @@ impl Config { +++ build.cargo = build.cargo.take().or(std::env::var_os("CARGO").map(|p| p.into())); +++ // Debian: don't optimize compiler-rt, the bundled sources are not available.. +++ build.optimized_compiler_builtins = Some(false); ++++ ++++ if let Some(ref mut rust) = toml.rust { ++++ rust.download_rustc = Some(StringOrBool::Bool(false)); ++++ } +++ } +++ +++ if let Some(include) = &toml.profile { diff --cc debian/patches/build/bootstrap-tests-disable-compiler-rt-optimizing.patch index 0000000000,0000000000,0000000000..6b67a7b9db new file mode 100644 --- /dev/null +++ b/debian/patches/build/bootstrap-tests-disable-compiler-rt-optimizing.patch @@@@ -1,0 -1,0 -1,0 +1,30 @@@@ +++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= +++Date: Tue, 22 Oct 2024 09:03:38 +0200 +++Subject: bootstrap tests: disable compiler-rt optimizing +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++it cannot work since there are no bundled LLVM (and thus no bundled +++compiler-rt) sources available. during the regular build this is handled by our +++config, but bootstrap tests don't use that.. +++ +++ +++Signed-off-by: Fabian Grünbichler +++--- +++ src/bootstrap/src/core/config/config.rs | 2 ++ +++ 1 file changed, 2 insertions(+) +++ +++diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs +++index 0587408..d77da96 100644 +++--- a/src/bootstrap/src/core/config/config.rs ++++++ b/src/bootstrap/src/core/config/config.rs +++@@ -1454,6 +1454,8 @@ impl Config { +++ let build = toml.build.get_or_insert_with(Default::default); +++ build.rustc = build.rustc.take().or(std::env::var_os("RUSTC").map(|p| p.into())); +++ build.cargo = build.cargo.take().or(std::env::var_os("CARGO").map(|p| p.into())); ++++ // Debian: don't optimize compiler-rt, the bundled sources are not available.. ++++ build.optimized_compiler_builtins = Some(false); +++ } +++ +++ if let Some(include) = &toml.profile { diff --cc debian/patches/build/ci_rustc-disable-test-that-requires-upstream-git-repo.patch index 0000000000,0000000000,0000000000..452e2762c1 new file mode 100644 --- /dev/null +++ b/debian/patches/build/ci_rustc-disable-test-that-requires-upstream-git-repo.patch @@@@ -1,0 -1,0 -1,0 +1,28 @@@@ +++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= +++Date: Wed, 4 Dec 2024 17:50:43 +0100 +++Subject: ci_rustc: disable test that requires upstream git repo +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++Forwarded: not-needed +++ +++Signed-off-by: Fabian Grünbichler +++--- +++ src/bootstrap/src/core/builder/tests.rs | 3 ++- +++ 1 file changed, 2 insertions(+), 1 deletion(-) +++ +++diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs +++index 6f5ff53..756a25c 100644 +++--- a/src/bootstrap/src/core/builder/tests.rs ++++++ b/src/bootstrap/src/core/builder/tests.rs +++@@ -202,7 +202,8 @@ fn alias_and_path_for_library() { +++ ]); +++ } +++ +++-#[test] ++++// Debian: this test doesn't work since it tries to detect dirty git state.. ++++#[allow(dead_code)] +++ fn ci_rustc_if_unchanged_logic() { +++ let config = Config::parse_inner( +++ Flags::parse(&[ diff --cc debian/patches/build/d-bootstrap-cargo-doc-paths.patch index 0000000000,0000000000,0000000000..33964537fa new file mode 100644 --- /dev/null +++ b/debian/patches/build/d-bootstrap-cargo-doc-paths.patch @@@@ -1,0 -1,0 -1,0 +1,391 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 14 Jul 2022 13:17:39 +0200 +++Subject: Fix links to cargo-doc +++ +++We package cargo docs in a slightly different location; also tweak linkchecker +++to not fail these links. +++ +++Forwarded: not-needed +++--- +++ compiler/rustc_error_codes/src/error_codes/E0460.md | 2 +- +++ compiler/rustc_error_codes/src/error_codes/E0461.md | 2 +- +++ compiler/rustc_error_codes/src/error_codes/E0462.md | 2 +- +++ compiler/rustc_error_codes/src/error_codes/E0514.md | 2 +- +++ compiler/rustc_error_codes/src/error_codes/E0519.md | 2 +- +++ src/doc/edition-guide/book.toml | 18 +++++++++--------- +++ .../edition-guide/src/editions/advanced-migrations.md | 14 +++++++------- +++ ...ansitioning-an-existing-project-to-a-new-edition.md | 4 ++-- +++ .../src/rust-2021/default-cargo-resolver.md | 10 +++++----- +++ src/doc/index.md | 2 +- +++ src/doc/reference/src/conditional-compilation.md | 2 +- +++ src/doc/reference/src/introduction.md | 4 ++-- +++ src/doc/reference/src/linkage.md | 2 +- +++ src/doc/reference/src/procedural-macros.md | 2 +- +++ src/doc/rustc/src/linker-plugin-lto.md | 2 +- +++ src/doc/rustc/src/platform-support/fuchsia.md | 2 +- +++ src/doc/rustc/src/targets/custom.md | 2 +- +++ src/doc/rustc/src/tests/index.md | 4 ++-- +++ src/doc/rustc/src/what-is-rustc.md | 2 +- +++ .../src/compiler-flags/branch-protection.md | 2 +- +++ .../src/compiler-flags/control-flow-guard.md | 2 +- +++ src/doc/unstable-book/src/compiler-flags/sanitizer.md | 2 +- +++ src/tools/linkchecker/main.rs | 4 ++++ +++ 23 files changed, 47 insertions(+), 43 deletions(-) +++ +++diff --git a/compiler/rustc_error_codes/src/error_codes/E0460.md b/compiler/rustc_error_codes/src/error_codes/E0460.md +++index 001678a..e8b77bf 100644 +++--- a/compiler/rustc_error_codes/src/error_codes/E0460.md ++++++ b/compiler/rustc_error_codes/src/error_codes/E0460.md +++@@ -68,4 +68,4 @@ This error can be fixed by: +++ * Recompiling crate `a` so that both crate `b` and `main` have a uniform +++ version to depend on. +++ +++-[Cargo]: ../cargo/index.html ++++[Cargo]: ../../../cargo/book/index.html +++diff --git a/compiler/rustc_error_codes/src/error_codes/E0461.md b/compiler/rustc_error_codes/src/error_codes/E0461.md +++index 33105c4..088833d 100644 +++--- a/compiler/rustc_error_codes/src/error_codes/E0461.md ++++++ b/compiler/rustc_error_codes/src/error_codes/E0461.md +++@@ -25,6 +25,6 @@ architectures. This issue also extends to any difference in target triples, as +++ `std` is operating-system specific. +++ +++ This error can be fixed by: +++- * Using [Cargo](../cargo/index.html), the Rust package manager, automatically ++++ * Using [Cargo](../../../cargo/book/index.html), the Rust package manager, automatically +++ fixing this issue. +++ * Recompiling either crate so that they target a consistent target triple. +++diff --git a/compiler/rustc_error_codes/src/error_codes/E0462.md b/compiler/rustc_error_codes/src/error_codes/E0462.md +++index 4509cc6..b0538b9 100644 +++--- a/compiler/rustc_error_codes/src/error_codes/E0462.md ++++++ b/compiler/rustc_error_codes/src/error_codes/E0462.md +++@@ -26,7 +26,7 @@ prefer `staticlib` for linking with C programs. Learn more about different +++ `crate_type`s in [this section of the Reference](../reference/linkage.html). +++ +++ This error can be fixed by: +++- * Using [Cargo](../cargo/index.html), the Rust package manager, automatically ++++ * Using [Cargo](../../../cargo/book/index.html), the Rust package manager, automatically +++ fixing this issue. +++ * Recompiling the crate as a `rlib` or `dylib`; formats suitable for Rust +++ linking. +++diff --git a/compiler/rustc_error_codes/src/error_codes/E0514.md b/compiler/rustc_error_codes/src/error_codes/E0514.md +++index ce2bbc5..0b2dab8 100644 +++--- a/compiler/rustc_error_codes/src/error_codes/E0514.md ++++++ b/compiler/rustc_error_codes/src/error_codes/E0514.md +++@@ -27,7 +27,7 @@ the compiler cannot be sure about *how* to call a function between compiler +++ versions, and therefore this error occurs. +++ +++ This error can be fixed by: +++- * Using [Cargo](../cargo/index.html), the Rust package manager and ++++ * Using [Cargo](../../../cargo/book/index.html), the Rust package manager and +++ [Rustup](https://rust-lang.github.io/rustup/), the Rust toolchain installer, +++ automatically fixing this issue. +++ * Recompiling the crates with a uniform `rustc` version. +++diff --git a/compiler/rustc_error_codes/src/error_codes/E0519.md b/compiler/rustc_error_codes/src/error_codes/E0519.md +++index 12876e2..09bd221 100644 +++--- a/compiler/rustc_error_codes/src/error_codes/E0519.md ++++++ b/compiler/rustc_error_codes/src/error_codes/E0519.md +++@@ -34,7 +34,7 @@ The above example compiles two crates with exactly the same name and +++ impossible for the compiler to distinguish between symbols (`pub` item names). +++ +++ This error can be fixed by: +++- * Using [Cargo](../cargo/index.html), the Rust package manager, automatically ++++ * Using [Cargo](../../../cargo/book/index.html), the Rust package manager, automatically +++ fixing this issue. +++ * Recompiling the crate with different metadata (different name/ +++ `crate_type`). +++diff --git a/src/doc/edition-guide/book.toml b/src/doc/edition-guide/book.toml +++index 998a817..9ca0dc7 100644 +++--- a/src/doc/edition-guide/book.toml ++++++ b/src/doc/edition-guide/book.toml +++@@ -55,15 +55,15 @@ search.use-boolean-and = true +++ "/rust-2018/the-compiler/incremental-compilation-for-faster-compiles.html" = "https://blog.rust-lang.org/2018/02/15/Rust-1.24.html#incremental-compilation" +++ "/rust-2018/the-compiler/an-attribute-for-deprecation.html" = "../../../reference/attributes/diagnostics.html#the-deprecated-attribute" +++ "/rust-2018/rustup-for-managing-rust-versions.html" = "https://rust-lang.github.io/rustup/" +++-"/rust-2018/cargo-and-crates-io/index.html" = "../../../cargo/index.html" +++-"/rust-2018/cargo-and-crates-io/cargo-check-for-faster-checking.html" = "../../../cargo/commands/cargo-check.html" +++-"/rust-2018/cargo-and-crates-io/cargo-install-for-easy-installation-of-tools.html" = "../../../cargo/commands/cargo-install.html" ++++"/rust-2018/cargo-and-crates-io/index.html" = "../../../../../cargo/book/index.html" ++++"/rust-2018/cargo-and-crates-io/cargo-check-for-faster-checking.html" = "../../../../../cargo/book/commands/cargo-check.html" ++++"/rust-2018/cargo-and-crates-io/cargo-install-for-easy-installation-of-tools.html" = "../../../../../cargo/book/commands/cargo-install.html" +++ "/rust-2018/cargo-and-crates-io/cargo-new-defaults-to-a-binary-project.html" = "https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#cargo-features" +++-"/rust-2018/cargo-and-crates-io/cargo-rustc-for-passing-arbitrary-flags-to-rustc.html" = "../../../cargo/commands/cargo-rustc.html" +++-"/rust-2018/cargo-and-crates-io/cargo-workspaces-for-multi-package-projects.html" = "../../../cargo/reference/workspaces.html" +++-"/rust-2018/cargo-and-crates-io/multi-file-examples.html" = "../../../cargo/guide/project-layout.html" +++-"/rust-2018/cargo-and-crates-io/replacing-dependencies-with-patch.html" = "../../../cargo/reference/overriding-dependencies.html#the-patch-section" +++-"/rust-2018/cargo-and-crates-io/cargo-can-use-a-local-registry-replacement.html" = "../../../cargo/reference/source-replacement.html" ++++"/rust-2018/cargo-and-crates-io/cargo-rustc-for-passing-arbitrary-flags-to-rustc.html" = "../../../../../cargo/book/commands/cargo-rustc.html" ++++"/rust-2018/cargo-and-crates-io/cargo-workspaces-for-multi-package-projects.html" = "../../../../../cargo/book/reference/workspaces.html" ++++"/rust-2018/cargo-and-crates-io/multi-file-examples.html" = "../../../../../cargo/book/guide/project-layout.html" ++++"/rust-2018/cargo-and-crates-io/replacing-dependencies-with-patch.html" = "../../../../../cargo/book/reference/overriding-dependencies.html#the-patch-section" ++++"/rust-2018/cargo-and-crates-io/cargo-can-use-a-local-registry-replacement.html" = "../../../../../cargo/book/reference/source-replacement.html" +++ "/rust-2018/cargo-and-crates-io/crates-io-disallows-wildcard-dependencies.html" = "https://blog.rust-lang.org/2016/01/21/Rust-1.6.html#cratesio-disallows-wildcards" +++ "/rust-2018/documentation/index.html" = "../../../index.html" +++ "/rust-2018/documentation/new-editions-of-the-book.html" = "../../../book/index.html" +++@@ -96,4 +96,4 @@ search.use-boolean-and = true +++ "/rust-next/future.html" = "../../std/future/trait.Future.html" +++ "/rust-next/alloc.html" = "https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html#the-alloc-crate-is-stable" +++ "/rust-next/maybe-uninit.html" = "https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html#maybeuninitt-instead-of-memuninitialized" +++-"/rust-next/cargo-vendor.html" = "../../cargo/commands/cargo-vendor.html" ++++"/rust-next/cargo-vendor.html" = "../../../../cargo/book/commands/cargo-vendor.html" +++diff --git a/src/doc/edition-guide/src/editions/advanced-migrations.md b/src/doc/edition-guide/src/editions/advanced-migrations.md +++index d2f07b0..ef52242 100644 +++--- a/src/doc/edition-guide/src/editions/advanced-migrations.md ++++++ b/src/doc/edition-guide/src/editions/advanced-migrations.md +++@@ -186,18 +186,18 @@ Afterwards, the line with `extern crate rand;` in `src/lib.rs` will be removed. +++ +++ We're now more idiomatic, and we didn't have to fix our code manually! +++ +++-[`cargo check`]: ../../cargo/commands/cargo-check.html +++-[`cargo fix`]: ../../cargo/commands/cargo-fix.html ++++[`cargo check`]: ../../../../cargo/book/commands/cargo-check.html ++++[`cargo fix`]: ../../../../cargo/book/commands/cargo-fix.html +++ [`explicit-outlives-requirements`]: ../../rustc/lints/listing/allowed-by-default.html#explicit-outlives-requirements +++ [`keyword-idents`]: ../../rustc/lints/listing/allowed-by-default.html#keyword-idents +++ [`rustfix`]: https://crates.io/crates/rustfix +++ [`unused-extern-crates`]: ../../rustc/lints/listing/allowed-by-default.html#unused-extern-crates +++-[Cargo features]: ../../cargo/reference/features.html +++-[Cargo package]: ../../cargo/reference/manifest.html#the-package-section +++-[Cargo targets]: ../../cargo/reference/cargo-targets.html +++-[Cargo workspace]: ../../cargo/reference/workspaces.html ++++[Cargo features]: ../../../../cargo/book/reference/features.html ++++[Cargo package]: ../../../../cargo/book/reference/manifest.html#the-package-section ++++[Cargo targets]: ../../../../cargo/book/reference/cargo-targets.html ++++[Cargo workspace]: ../../../../cargo/book/reference/workspaces.html +++ [CLI flag]: ../../rustc/lints/levels.html#via-compiler-flag +++-[Code generation]: ../../cargo/reference/build-script-examples.html#code-generation ++++[Code generation]: ../../../../cargo/book/reference/build-script-examples.html#code-generation +++ [conditional compilation]: ../../reference/conditional-compilation.html +++ [documentation tests]: ../../rustdoc/documentation-tests.html +++ [JSON messages]: ../../rustc/json.html +++diff --git a/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md b/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md +++index 67615af..ecbe81b 100644 +++--- a/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md ++++++ b/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md +++@@ -134,8 +134,8 @@ The steps are roughly similar to the stable channel: +++ > on nightly along with more information about their status. +++ > A few months before the edition is stabilized, all of the new features should be fully implemented, and the [Rust Blog] will announce a call for testing. +++ +++-[`cargo fix`]: ../../cargo/commands/cargo-fix.html +++-[`cargo test`]: ../../cargo/commands/cargo-test.html ++++[`cargo fix`]: ../../../../cargo/book/commands/cargo-fix.html ++++[`cargo test`]: ../../../../cargo/book/commands/cargo-test.html +++ [Advanced migration strategies]: advanced-migrations.md +++ [nightly channel]: ../../book/appendix-07-nightly-rust.html +++ [Rust Blog]: https://blog.rust-lang.org/ +++diff --git a/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md b/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md +++index 5f6653d..99332c3 100644 +++--- a/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md ++++++ b/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md +++@@ -21,11 +21,11 @@ The new feature resolver no longer merges all requested features for +++ crates that are depended on in multiple ways. +++ See [the announcement of Rust 1.51][5] for details. +++ +++-[4]: ../../cargo/reference/resolver.html#feature-resolver-version-2 ++++[4]: ../../../../cargo/book/reference/resolver.html#feature-resolver-version-2 +++ [5]: https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#cargos-new-feature-resolver +++-[workspace]: ../../cargo/reference/workspaces.html +++-[virtual workspace]: ../../cargo/reference/workspaces.html#virtual-workspace +++-[`resolver` field]: ../../cargo/reference/resolver.html#resolver-versions ++++[workspace]: ../../../../cargo/book/reference/workspaces.html ++++[virtual workspace]: ../../../../cargo/book/reference/workspaces.html#virtual-workspace ++++[`resolver` field]: ../../../../cargo/book/reference/resolver.html#resolver-versions +++ +++ ## Migration +++ +++@@ -176,4 +176,4 @@ This snippet of output shows that the project `foo` depends on `bar` with the "d +++ Then, `bar` depends on `bstr` as a build-dependency with the "default" feature. +++ We can further see that `bstr`'s "default" feature enables "unicode" (among other features). +++ +++-[`cargo tree`]: ../../cargo/commands/cargo-tree.html ++++[`cargo tree`]: ../../../../cargo/book/commands/cargo-tree.html +++diff --git a/src/doc/index.md b/src/doc/index.md +++index 8ad5b42..f93d3da 100644 +++--- a/src/doc/index.md ++++++ b/src/doc/index.md +++@@ -128,7 +128,7 @@ historical editions. +++ +++ ### The Cargo Book +++ +++-[The Cargo Book](cargo/index.html) is a guide to Cargo, Rust's build tool and ++++[The Cargo Book](../../cargo/book/index.html) is a guide to Cargo, Rust's build tool and +++ dependency manager. +++ +++ ### The Rustdoc Book +++diff --git a/src/doc/reference/src/conditional-compilation.md b/src/doc/reference/src/conditional-compilation.md +++index 5255bb8..46a477b 100644 +++--- a/src/doc/reference/src/conditional-compilation.md ++++++ b/src/doc/reference/src/conditional-compilation.md +++@@ -483,6 +483,6 @@ println!("I'm running on a {} machine!", machine_kind); +++ [`target_feature` attribute]: attributes/codegen.md#the-target_feature-attribute +++ [attribute]: attributes.md +++ [attributes]: attributes.md +++-[cargo-feature]: ../cargo/reference/features.html ++++[cargo-feature]: ../../../cargo/book/reference/features.html +++ [crate type]: linkage.md +++ [static C runtime]: linkage.md#static-and-dynamic-c-runtimes +++diff --git a/src/doc/reference/src/introduction.md b/src/doc/reference/src/introduction.md +++index 4cd205b..25a7b49 100644 +++--- a/src/doc/reference/src/introduction.md ++++++ b/src/doc/reference/src/introduction.md +++@@ -137,8 +137,8 @@ We also want the reference to be as normative as possible, so if you see anythin +++ [the Rust Reference repository]: https://github.com/rust-lang/reference/ +++ [Unstable Book]: https://doc.rust-lang.org/nightly/unstable-book/ +++ [_Expression_]: expressions.md +++-[cargo book]: ../cargo/index.html +++-[cargo reference]: ../cargo/reference/index.html ++++[cargo book]: ../../../cargo/book/index.html ++++[cargo reference]: ../../../cargo/book/reference/index.html +++ [expressions chapter]: expressions.html +++ [file an issue]: https://github.com/rust-lang/reference/issues +++ [lifetime of temporaries]: expressions.html#temporaries +++diff --git a/src/doc/reference/src/linkage.md b/src/doc/reference/src/linkage.md +++index ff41a14..4d1b72e 100644 +++--- a/src/doc/reference/src/linkage.md ++++++ b/src/doc/reference/src/linkage.md +++@@ -242,7 +242,7 @@ fn main() { +++ } +++ ``` +++ +++-[cargo]: ../cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts ++++[cargo]: ../../../cargo/book/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts +++ +++ To use this feature locally, you typically will use the `RUSTFLAGS` environment +++ variable to specify flags to the compiler through Cargo. For example to compile +++diff --git a/src/doc/reference/src/procedural-macros.md b/src/doc/reference/src/procedural-macros.md +++index 0ae6e26..e6b61be 100644 +++--- a/src/doc/reference/src/procedural-macros.md ++++++ b/src/doc/reference/src/procedural-macros.md +++@@ -381,7 +381,7 @@ Note that neither declarative nor procedural macros support doc comment tokens +++ their equivalent `#[doc = r"str"]` attributes when passed to macros. +++ +++ [Attribute macros]: #attribute-macros +++-[Cargo's build scripts]: ../cargo/reference/build-scripts.html ++++[Cargo's build scripts]: ../../../cargo/book/reference/build-scripts.html +++ [Derive macros]: #derive-macros +++ [Function-like macros]: #function-like-procedural-macros +++ [`Delimiter::None`]: proc_macro::Delimiter::None +++diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md +++index ab95aa2..8023f33 100644 +++--- a/src/doc/rustc/src/linker-plugin-lto.md ++++++ b/src/doc/rustc/src/linker-plugin-lto.md +++@@ -112,7 +112,7 @@ targeting Windows-like targets +++ This is fixed if you explicitly set the target, for example +++ `cargo build --target x86_64-pc-windows-msvc` +++ Without an explicit --target the flags will be passed to all compiler invocations (including build +++-scripts and proc macros), see [cargo docs on rustflags](../cargo/reference/config.html#buildrustflags) ++++scripts and proc macros), see [cargo docs on rustflags](../../../cargo/book/reference/config.html#buildrustflags) +++ +++ If you have dependencies using the `cc` crate, you will need to set these +++ environment variables: +++diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md +++index 489f46e..8f299a9 100644 +++--- a/src/doc/rustc/src/platform-support/fuchsia.md ++++++ b/src/doc/rustc/src/platform-support/fuchsia.md +++@@ -925,7 +925,7 @@ attach and load any relevant debug symbols. +++ [Fuchsia]: https://fuchsia.dev/ +++ [source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build +++ [rustup]: https://rustup.rs/ +++-[cargo]: ../../cargo/index.html ++++[cargo]: ../../../../cargo/book/index.html +++ [Fuchsia SDK]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core +++ [overview of CML]: https://fuchsia.dev/fuchsia-src/concepts/components/v2/component_manifests +++ [reference for the file format]: https://fuchsia.dev/reference/cml +++diff --git a/src/doc/rustc/src/targets/custom.md b/src/doc/rustc/src/targets/custom.md +++index 6c14941..7f548e9 100644 +++--- a/src/doc/rustc/src/targets/custom.md ++++++ b/src/doc/rustc/src/targets/custom.md +++@@ -14,7 +14,7 @@ To see it for a different target, add the `--target` flag: +++ rustc +nightly -Z unstable-options --target=wasm32-unknown-unknown --print target-spec-json +++ ``` +++ +++-To use a custom target, see the (unstable) [`build-std` feature](../../cargo/reference/unstable.html#build-std) of `cargo`. ++++To use a custom target, see the (unstable) [`build-std` feature](../../../../cargo/book/reference/unstable.html#build-std) of `cargo`. +++ +++ ## Custom Target Lookup Path +++ +++diff --git a/src/doc/rustc/src/tests/index.md b/src/doc/rustc/src/tests/index.md +++index 32baed9..2c36c1d 100644 +++--- a/src/doc/rustc/src/tests/index.md ++++++ b/src/doc/rustc/src/tests/index.md +++@@ -301,7 +301,7 @@ Experimental support for using custom test harnesses is available on the +++ [`--test` option]: ../command-line-arguments.md#option-test +++ [`-Z panic-abort-tests`]: https://github.com/rust-lang/rust/issues/67650 +++ [`available_parallelism`]: ../../std/thread/fn.available_parallelism.html +++-[`cargo test`]: ../../cargo/commands/cargo-test.html ++++[`cargo test`]: ../../../../cargo/book/commands/cargo-test.html +++ [`libtest`]: ../../test/index.html +++ [`main` function]: ../../reference/crates-and-source-files.html#main-functions +++ [`Result`]: ../../std/result/index.html +++@@ -311,7 +311,7 @@ Experimental support for using custom test harnesses is available on the +++ [attribute-should_panic]: ../../reference/attributes/testing.html#the-should_panic-attribute +++ [attribute-test]: ../../reference/attributes/testing.html#the-test-attribute +++ [bench-docs]: ../../unstable-book/library-features/test.html +++-[Cargo]: ../../cargo/index.html ++++[Cargo]: ../../../../cargo/book/index.html +++ [crate type]: ../../reference/linkage.html +++ [custom_test_frameworks documentation]: ../../unstable-book/language-features/custom-test-frameworks.html +++ [nightly channel]: ../../book/appendix-07-nightly-rust.html +++diff --git a/src/doc/rustc/src/what-is-rustc.md b/src/doc/rustc/src/what-is-rustc.md +++index 39a05cf..7e450ae 100644 +++--- a/src/doc/rustc/src/what-is-rustc.md ++++++ b/src/doc/rustc/src/what-is-rustc.md +++@@ -5,7 +5,7 @@ language, provided by the project itself. Compilers take your source code and +++ produce binary code, either as a library or executable. +++ +++ Most Rust programmers don't invoke `rustc` directly, but instead do it through +++-[Cargo](../cargo/index.html). It's all in service of `rustc` though! If you ++++[Cargo](../../../cargo/book/index.html). It's all in service of `rustc` though! If you +++ want to see how Cargo calls `rustc`, you can +++ +++ ```bash +++diff --git a/src/doc/unstable-book/src/compiler-flags/branch-protection.md b/src/doc/unstable-book/src/compiler-flags/branch-protection.md +++index f0cc44a..bf92669 100644 +++--- a/src/doc/unstable-book/src/compiler-flags/branch-protection.md ++++++ b/src/doc/unstable-book/src/compiler-flags/branch-protection.md +++@@ -20,4 +20,4 @@ For example, `-Z branch-protection=bti,pac-ret,leaf` is valid, but +++ +++ Rust's standard library does not ship with BTI or pointer authentication enabled by default. +++ In Cargo projects the standard library can be recompiled with pointer authentication using the nightly +++-[build-std](../../cargo/reference/unstable.html#build-std) feature. ++++[build-std](../../../../cargo/book/reference/unstable.html#build-std) feature. +++diff --git a/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md +++index dbb7414..73876b0 100644 +++--- a/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md ++++++ b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md +++@@ -39,7 +39,7 @@ It is strongly recommended to also enable CFG checks for all linked libraries, i +++ +++ To enable CFG in the standard library, use the [cargo `-Z build-std` functionality][build-std] to recompile the standard library with the same configuration options as the main program. +++ +++-[build-std]: ../../cargo/reference/unstable.html#build-std ++++[build-std]: ../../../../cargo/book/reference/unstable.html#build-std +++ +++ For example: +++ ```cmd +++diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++index 4679acf..b6c3eb5 100644 +++--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md ++++++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++@@ -882,7 +882,7 @@ It is strongly recommended to combine sanitizers with recompiled and +++ instrumented standard library, for example using [cargo `-Zbuild-std` +++ functionality][build-std]. +++ +++-[build-std]: ../../cargo/reference/unstable.html#build-std ++++[build-std]: ../../../../cargo/book/reference/unstable.html#build-std +++ +++ # Working with other languages +++ +++diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs +++index d39ed99..4a64008 100644 +++--- a/src/tools/linkchecker/main.rs ++++++ b/src/tools/linkchecker/main.rs +++@@ -297,6 +297,10 @@ impl Checker { +++ return; +++ } +++ } ++++ if url.contains("../../cargo/book/") { ++++ // link to related cargo-doc, ok for our Debian build ++++ return; ++++ } +++ if is_exception(file, &target_pretty_path) { +++ report.links_ignored_exception += 1; +++ } else { diff --cc debian/patches/build/d-bootstrap-custom-debuginfo-path.patch index 0000000000,0000000000,0000000000..3268bb9118 new file mode 100644 --- /dev/null +++ b/debian/patches/build/d-bootstrap-custom-debuginfo-path.patch @@@@ -1,0 -1,0 -1,0 +1,41 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 14 Jul 2022 13:17:39 +0200 +++Subject: d-bootstrap-custom-debuginfo-path +++ +++Forwarded: not-needed +++=================================================================== +++--- +++ src/bootstrap/src/lib.rs | 5 ++--- +++ tests/codegen/remap_path_prefix/issue-73167-remap-std.rs | 2 +- +++ 2 files changed, 3 insertions(+), 4 deletions(-) +++ +++diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs +++index ccc115a..d483301 100644 +++--- a/src/bootstrap/src/lib.rs ++++++ b/src/bootstrap/src/lib.rs +++@@ -1148,10 +1148,9 @@ Executed at: {executed_at}"#, +++ +++ match which { +++ GitRepo::Rustc => { +++- let sha = self.rust_sha().unwrap_or(&self.version); +++- Some(format!("/rustc/{sha}")) ++++ Some(format!("/usr/src/rustc-{}", &self.version)) +++ } +++- GitRepo::Llvm => Some(String::from("/rustc/llvm")), ++++ GitRepo::Llvm => panic!("GitRepo::Llvm unsupported on Debian"), +++ } +++ } +++ +++diff --git a/tests/codegen/remap_path_prefix/issue-73167-remap-std.rs b/tests/codegen/remap_path_prefix/issue-73167-remap-std.rs +++index eb61016..9119c1d 100644 +++--- a/tests/codegen/remap_path_prefix/issue-73167-remap-std.rs ++++++ b/tests/codegen/remap_path_prefix/issue-73167-remap-std.rs +++@@ -7,7 +7,7 @@ +++ // true automatically. If paths to std library hasn't been remapped, we use the +++ // above simulate-remapped-rust-src-base option to do it temporarily +++ +++-// CHECK: !DIFile(filename: "{{/rustc/.*/library/std/src/panic.rs}}" ++++// CHECK: !DIFile(filename: "{{/usr/src/rustc-.*/library/std/src/panic.rs}}" +++ fn main() { +++ std::thread::spawn(|| { +++ println!("hello"); diff --cc debian/patches/build/d-bootstrap-disable-git.patch index 0000000000,0000000000,0000000000..30e12c90a0 new file mode 100644 --- /dev/null +++ b/debian/patches/build/d-bootstrap-disable-git.patch @@@@ -1,0 -1,0 -1,0 +1,29 @@@@ +++From: Matthijs van Otterdijk +++Date: Thu, 14 Jul 2022 13:17:38 +0200 +++Subject: bootstrap: always use commit info file instead of checking .git +++ +++Forwarded: not-needed +++--- +++ src/bootstrap/src/utils/channel.rs | 5 +++-- +++ 1 file changed, 3 insertions(+), 2 deletions(-) +++ +++diff --git a/src/bootstrap/src/utils/channel.rs b/src/bootstrap/src/utils/channel.rs +++index 4a9ecc7..8f98bfa 100644 +++--- a/src/bootstrap/src/utils/channel.rs ++++++ b/src/bootstrap/src/utils/channel.rs +++@@ -36,12 +36,13 @@ pub struct Info { +++ impl GitInfo { +++ pub fn new(omit_git_hash: bool, dir: &Path) -> GitInfo { +++ // See if this even begins to look like a git dir +++- if !dir.join(".git").exists() { ++++ // Debian: always use commit info file, since our .git is not upstreams.. ++++ //if !dir.join(".git").exists() { +++ match read_commit_info_file(dir) { +++ Some(info) => return GitInfo::RecordedForTarball(info), +++ None => return GitInfo::Absent, +++ } +++- } ++++ //} +++ +++ // Make sure git commands work +++ match helpers::git(Some(dir)).arg("rev-parse").as_command_mut().output() { diff --cc debian/patches/build/d-bootstrap-install-symlinks.patch index 0000000000,0000000000,0000000000..4686206691 new file mode 100644 --- /dev/null +++ b/debian/patches/build/d-bootstrap-install-symlinks.patch @@@@ -1,0 -1,0 -1,0 +1,38 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 14 Jul 2022 13:17:38 +0200 +++Subject: Install symlinks as-is, don't dereference them +++ +++Our patch to mdbook installs symlinks to systems versions of font-awesome, +++highlight, etc. Upstream mdbook otherwise doesn't use symlinks, so this +++doesn't affect anything else that's already generated. +++ +++Forwarded: not-needed +++--- +++ src/tools/rust-installer/install-template.sh | 7 +++++-- +++ 1 file changed, 5 insertions(+), 2 deletions(-) +++ +++diff --git a/src/tools/rust-installer/install-template.sh b/src/tools/rust-installer/install-template.sh +++index f7f408b..a3f0ceb 100644 +++--- a/src/tools/rust-installer/install-template.sh ++++++ b/src/tools/rust-installer/install-template.sh +++@@ -617,7 +617,10 @@ install_components() { +++ +++ maybe_backup_path "$_file_install_path" +++ +++- if echo "$_file" | grep "^bin/" > /dev/null || test -x "$_src_dir/$_component/$_file" ++++ if [ -h "$_src_dir/$_component/$_file" ] ++++ then ++++ run cp -d "$_src_dir/$_component/$_file" "$_file_install_path" ++++ elif echo "$_file" | grep "^bin/" > /dev/null || test -x "$_src_dir/$_component/$_file" +++ then +++ run cp "$_src_dir/$_component/$_file" "$_file_install_path" +++ run chmod 755 "$_file_install_path" +++@@ -639,7 +642,7 @@ install_components() { +++ +++ maybe_backup_path "$_file_install_path" +++ +++- run cp -R "$_src_dir/$_component/$_file" "$_file_install_path" ++++ run cp -dR "$_src_dir/$_component/$_file" "$_file_install_path" +++ critical_need_ok "failed to copy directory" +++ +++ # Set permissions. 0755 for dirs, 644 for files diff --cc debian/patches/build/d-bootstrap-no-assume-tools.patch index 0000000000,0000000000,0000000000..e26d67934f new file mode 100644 --- /dev/null +++ b/debian/patches/build/d-bootstrap-no-assume-tools.patch @@@@ -1,0 -1,0 -1,0 +1,28 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 14 Jul 2022 13:17:39 +0200 +++Subject: set tools to those built in Debian +++ +++Forwarded: not-needed +++=================================================================== +++--- +++ src/bootstrap/src/core/builder/tests.rs | 4 ++++ +++ 1 file changed, 4 insertions(+) +++ +++diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs +++index 21694cf..6f5ff53 100644 +++--- a/src/bootstrap/src/core/builder/tests.rs ++++++ b/src/bootstrap/src/core/builder/tests.rs +++@@ -438,9 +438,13 @@ mod dist { +++ let b = TargetSelection::from_user(TEST_TRIPLE_2); +++ let mut config = +++ configure(&[TEST_TRIPLE_1, TEST_TRIPLE_2], &[TEST_TRIPLE_1, TEST_TRIPLE_2]); ++++ let mut tools = std::collections::HashSet::new(); ++++ tools.insert("clippy".to_string()); ++++ tools.insert("rustfmt".to_string()); +++ config.docs = false; +++ config.extended = true; +++ config.hosts = vec![b]; ++++ config.tools = Some(tools); +++ let mut cache = run_build(&[], config); +++ +++ assert_eq!(first(cache.all::()), &[dist::Rustc { diff --cc debian/patches/build/d-bootstrap-permit-symlink-in-docs.patch index 0000000000,0000000000,0000000000..79eb22252d new file mode 100644 --- /dev/null +++ b/debian/patches/build/d-bootstrap-permit-symlink-in-docs.patch @@@@ -1,0 -1,0 -1,0 +1,21 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 13 Jun 2024 11:16:40 +0200 +++Subject: partial revert of b9eedea4b0368fd1f00f204db75109ff444fab5b upstream +++ +++Forwarded: not-needed +++--- +++ src/bootstrap/src/core/build_steps/dist.rs | 1 + +++ 1 file changed, 1 insertion(+) +++ +++diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs +++index 34e6a1e..658e73c 100644 +++--- a/src/bootstrap/src/core/build_steps/dist.rs ++++++ b/src/bootstrap/src/core/build_steps/dist.rs +++@@ -79,6 +79,7 @@ impl Step for Docs { +++ tarball.set_product_name("Rust Documentation"); +++ tarball.add_bulk_dir(builder.doc_out(host), dest); +++ tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, 0o644); ++++ tarball.permit_symlinks(true); +++ Some(tarball.generate()) +++ } +++ } diff --cc debian/patches/build/d-bootstrap-rustflags.patch index 0000000000,0000000000,0000000000..a51c81bdfe new file mode 100644 --- /dev/null +++ b/debian/patches/build/d-bootstrap-rustflags.patch @@@@ -1,0 -1,0 -1,0 +1,34 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 14 Jul 2022 13:17:38 +0200 +++Subject: d-bootstrap-rustflags +++ +++Forwarded: not-needed +++ +++=================================================================== +++--- +++ src/bootstrap/src/core/builder/cargo.rs | 12 ++++++++++++ +++ 1 file changed, 12 insertions(+) +++ +++diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs +++index a73e6cf..55e4cc4 100644 +++--- a/src/bootstrap/src/core/builder/cargo.rs ++++++ b/src/bootstrap/src/core/builder/cargo.rs +++@@ -627,6 +627,18 @@ impl Builder<'_> { +++ // #[cfg(bootstrap)] as we are transition `test` to userspace cfg +++ hostflags.arg("--check-cfg=cfg(test)"); +++ ++++ // Debian-specific stuff here ++++ // set linker flags from LDFLAGS ++++ if let Ok(ldflags) = env::var("LDFLAGS") { ++++ for flag in ldflags.split_whitespace() { ++++ if target.contains("windows") && flag.contains("relro") { ++++ // relro is ELF-specific ++++ continue; ++++ } ++++ rustflags.arg(&format!("-Clink-args={}", flag)); ++++ } ++++ } ++++ +++ // FIXME: It might be better to use the same value for both `RUSTFLAGS` and `RUSTDOCFLAGS`, +++ // but this breaks CI. At the very least, stage0 `rustdoc` needs `--cfg bootstrap`. See +++ // #71458. diff --cc debian/patches/build/d-bootstrap-use-local-css.patch index 0000000000,0000000000,0000000000..c50567bcb2 new file mode 100644 --- /dev/null +++ b/debian/patches/build/d-bootstrap-use-local-css.patch @@@@ -1,0 -1,0 -1,0 +1,55 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 14 Jul 2022 13:17:39 +0200 +++Subject: d-bootstrap-use-local-css +++ +++Forwarded: not-needed +++=================================================================== +++--- +++ src/bootstrap/src/core/build_steps/doc.rs | 27 +++++++++++++++++++++------ +++ 1 file changed, 21 insertions(+), 6 deletions(-) +++ +++diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs +++index 1e9f7cb..c4d8b2f 100644 +++--- a/src/bootstrap/src/core/build_steps/doc.rs ++++++ b/src/bootstrap/src/core/build_steps/doc.rs +++@@ -390,7 +390,27 @@ impl Step for Standalone { +++ .arg("--index-page") +++ .arg(builder.src.join("src/doc/index.md")) +++ .arg("--markdown-playground-url") +++- .arg("https://play.rust-lang.org/") ++++ .arg("https://play.rust-lang.org/"); ++++ ++++ // Debian: librustdoc now generates a resource-suffix for static ++++ // files with rustc_hash::FxHasher, so we need to find it. ++++ let _dir = out.join("static.files"); ++++ if _dir.is_dir() { ++++ let _css = _dir.read_dir().expect("Debian: failed to read static.files/ when is_dir() == true") ++++ .find_map(|entry| entry.ok().map(|entry| { ++++ let name = entry.file_name().into_string() ++++ .expect("Debian: rustc files should have UTF-8 name"); ++++ if name.starts_with("rustdoc-") && name.ends_with(".css") { ++++ Some(format!("static.files/{name}")) ++++ } else { None } ++++ })).flatten(); ++++ if let Some(name) = _css { ++++ cmd.arg("--markdown-css").arg(name); ++++ } ++++ } ++++ ++++ cmd.arg("--markdown-css") ++++ .arg("rust.css") +++ .arg("-o") +++ .arg(&out) +++ .arg(&path); +++@@ -399,11 +419,6 @@ impl Step for Standalone { +++ cmd.arg("--disable-minification"); +++ } +++ +++- if filename == "not_found.md" { +++- cmd.arg("--markdown-css").arg("https://doc.rust-lang.org/rust.css"); +++- } else { +++- cmd.arg("--markdown-css").arg("rust.css"); +++- } +++ cmd.run(builder); +++ } +++ diff --cc debian/patches/build/d-test-ignore-avx-44056.patch index 0000000000,0000000000,0000000000..17637ad6b2 new file mode 100644 --- /dev/null +++ b/debian/patches/build/d-test-ignore-avx-44056.patch @@@@ -1,0 -1,0 -1,0 +1,23 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 14 Jul 2022 13:17:39 +0200 +++Subject: d-test-ignore-avx-44056 +++ +++Bug: https://github.com/rust-lang/rust/pull/55667 +++Forwarded: not-needed +++ +++=================================================================== +++--- +++ tests/ui/issues/issue-44056.rs | 2 +- +++ 1 file changed, 1 insertion(+), 1 deletion(-) +++ +++diff --git a/tests/ui/issues/issue-44056.rs b/tests/ui/issues/issue-44056.rs +++index 12e4f01..156dd9c 100644 +++--- a/tests/ui/issues/issue-44056.rs ++++++ b/tests/ui/issues/issue-44056.rs +++@@ -1,5 +1,5 @@ +++ //@ build-pass (FIXME(55996): should be run on targets supporting avx) +++-//@ only-x86_64 ++++//@ ignore-test +++ //@ no-prefer-dynamic +++ //@ compile-flags: -Ctarget-feature=+avx -Clto +++ diff --cc debian/patches/build/ignore-broken-debuginfo-tests.patch index 0000000000,0000000000,0000000000..3b3a982cc8 new file mode 100644 --- /dev/null +++ b/debian/patches/build/ignore-broken-debuginfo-tests.patch @@@@ -1,0 -1,0 -1,0 +1,55 @@@@ +++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= +++Date: Wed, 23 Oct 2024 22:37:25 +0200 +++Subject: ignore broken debuginfo tests +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++Forwarded: yes +++ +++Signed-off-by: Fabian Grünbichler +++--- +++ tests/debuginfo/by-value-non-immediate-argument.rs | 2 ++ +++ tests/debuginfo/macro-stepping.rs | 3 ++- +++ tests/debuginfo/method-on-enum.rs | 2 ++ +++ 3 files changed, 6 insertions(+), 1 deletion(-) +++ +++diff --git a/tests/debuginfo/by-value-non-immediate-argument.rs b/tests/debuginfo/by-value-non-immediate-argument.rs +++index 192f6ef..f0807ee 100644 +++--- a/tests/debuginfo/by-value-non-immediate-argument.rs ++++++ b/tests/debuginfo/by-value-non-immediate-argument.rs +++@@ -2,6 +2,8 @@ +++ //@ min-gdb-version: 13.0 +++ //@ compile-flags:-g +++ //@ ignore-windows-gnu: #128973 ++++//Debian: broken, see https://github.com/rust-lang/rust/issues/129662#issuecomment-2313102689 ++++//@ ignore-gdb +++ +++ // === GDB TESTS =================================================================================== +++ +++diff --git a/tests/debuginfo/macro-stepping.rs b/tests/debuginfo/macro-stepping.rs +++index 35bb6de..dec0eff 100644 +++--- a/tests/debuginfo/macro-stepping.rs ++++++ b/tests/debuginfo/macro-stepping.rs +++@@ -2,7 +2,8 @@ +++ //@ ignore-aarch64 +++ //@ min-lldb-version: 1800 +++ //@ min-gdb-version: 13.0 +++- ++++//Debian: broken, see https://github.com/rust-lang/rust/issues/130896 ++++//@ ignore-gdb +++ //@ aux-build:macro-stepping.rs +++ +++ #![allow(unused)] +++diff --git a/tests/debuginfo/method-on-enum.rs b/tests/debuginfo/method-on-enum.rs +++index 754b4a2..7fd5411 100644 +++--- a/tests/debuginfo/method-on-enum.rs ++++++ b/tests/debuginfo/method-on-enum.rs +++@@ -1,5 +1,7 @@ +++ //@ min-lldb-version: 1800 +++ //@ min-gdb-version: 13.0 ++++//Debian: broken, see https://github.com/rust-lang/rust/issues/129662#issuecomment-2313102689 ++++//@ ignore-gdb +++ +++ //@ compile-flags:-g +++ diff --cc debian/patches/cargo/c-0003-tests-add-missing-cross-disabled-checks.patch index 0000000000,0000000000,0000000000..1505067f11 new file mode 100644 --- /dev/null +++ b/debian/patches/cargo/c-0003-tests-add-missing-cross-disabled-checks.patch @@@@ -1,0 -1,0 -1,0 +1,42 @@@@ +++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= +++Date: Sat, 19 Nov 2022 10:24:08 +0100 +++Subject: [PATCH] tests: add missing cross disabled checks +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++cross_conmpile::alternate states it should only be used in test cases +++after checking cross_compile::disabled(), which is missing here. these +++tests fail despite setting CFG_DISABLE_CROSS_TESTS on i386, since both +++the host and the alternate cross target would be i686 in that case. +++ +++ +++Signed-off-by: Fabian Grünbichler +++--- +++ src/tools/cargo/tests/testsuite/build_script.rs | 6 ++++++ +++ 1 file changed, 6 insertions(+) +++ +++diff --git a/src/tools/cargo/tests/testsuite/build_script.rs b/src/tools/cargo/tests/testsuite/build_script.rs +++index 280575e..c66dc87 100644 +++--- a/src/tools/cargo/tests/testsuite/build_script.rs ++++++ b/src/tools/cargo/tests/testsuite/build_script.rs +++@@ -739,6 +739,9 @@ fn custom_build_linker_bad_host_with_arch() { +++ #[cargo_test] +++ fn custom_build_env_var_rustc_linker_cross_arch_host() { +++ let target = rustc_host(); ++++ if cross_compile::disabled() { ++++ return; ++++ } +++ let cross_target = cross_compile::alternate(); +++ let p = project() +++ .file( +++@@ -777,6 +780,9 @@ fn custom_build_env_var_rustc_linker_cross_arch_host() { +++ #[cargo_test] +++ fn custom_build_linker_bad_cross_arch_host() { +++ let target = rustc_host(); ++++ if cross_compile::disabled() { ++++ return; ++++ } +++ let cross_target = cross_compile::alternate(); +++ let p = project() +++ .file( diff --cc debian/patches/cargo/c-2002_disable-net-tests.patch index 0000000000,0000000000,0000000000..89e427000e new file mode 100644 --- /dev/null +++ b/debian/patches/cargo/c-2002_disable-net-tests.patch @@@@ -1,0 -1,0 -1,0 +1,632 @@@@ +++From: Ximin Luo +++Date: Thu, 13 Jun 2024 11:16:38 +0200 +++Subject: Disable network tests +++ +++Forwarded: TODO +++--- +++ .../cargo/tests/testsuite/credential_process.rs | 14 +-- +++ src/tools/cargo/tests/testsuite/git_auth.rs | 4 +- +++ src/tools/cargo/tests/testsuite/net_config.rs | 4 +- +++ src/tools/cargo/tests/testsuite/publish.rs | 113 +++++++++++---------- +++ 4 files changed, 68 insertions(+), 67 deletions(-) +++ +++diff --git a/src/tools/cargo/tests/testsuite/credential_process.rs b/src/tools/cargo/tests/testsuite/credential_process.rs +++index 130ca88..ab94fae 100644 +++--- a/src/tools/cargo/tests/testsuite/credential_process.rs ++++++ b/src/tools/cargo/tests/testsuite/credential_process.rs +++@@ -65,7 +65,7 @@ fn get_token_test() -> (Project, TestRegistry) { +++ (p, server) +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish() { +++ // Checks that credential-process is used for `cargo publish`. +++ let (p, _t) = get_token_test(); +++@@ -87,7 +87,7 @@ You may press ctrl-c [..] +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn basic_unsupported() { +++ // Non-action commands don't support login/logout. +++ let registry = registry::RegistryBuilder::new() +++@@ -121,7 +121,7 @@ Caused by: +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn login() { +++ let registry = registry::RegistryBuilder::new() +++ .no_configure_token() +++@@ -142,7 +142,7 @@ fn login() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn logout() { +++ let server = registry::RegistryBuilder::new() +++ .no_configure_token() +++@@ -161,7 +161,7 @@ fn logout() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn yank() { +++ let (p, _t) = get_token_test(); +++ +++@@ -176,7 +176,7 @@ fn yank() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn owner() { +++ let (p, _t) = get_token_test(); +++ +++@@ -191,7 +191,7 @@ fn owner() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn invalid_token_output() { +++ // Error when credential process does not output the expected format for a token. +++ let cred_proj = project() +++diff --git a/src/tools/cargo/tests/testsuite/git_auth.rs b/src/tools/cargo/tests/testsuite/git_auth.rs +++index c5fb553..99e9405 100644 +++--- a/src/tools/cargo/tests/testsuite/git_auth.rs ++++++ b/src/tools/cargo/tests/testsuite/git_auth.rs +++@@ -105,7 +105,7 @@ fn setup_failed_auth_test() -> (SocketAddr, JoinHandle<()>, Arc) { +++ } +++ +++ // Tests that HTTP auth is offered from `credential.helper`. +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn http_auth_offered() { +++ let (addr, t, connections) = setup_failed_auth_test(); +++ let p = project() +++@@ -178,7 +178,7 @@ Caused by: +++ } +++ +++ // Boy, sure would be nice to have a TLS implementation in rust! +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn https_something_happens() { +++ let server = TcpListener::bind("127.0.0.1:0").unwrap(); +++ let addr = server.local_addr().unwrap(); +++diff --git a/src/tools/cargo/tests/testsuite/net_config.rs b/src/tools/cargo/tests/testsuite/net_config.rs +++index b765678..ed695bd 100644 +++--- a/src/tools/cargo/tests/testsuite/net_config.rs ++++++ b/src/tools/cargo/tests/testsuite/net_config.rs +++@@ -4,7 +4,7 @@ use cargo_test_support::prelude::*; +++ use cargo_test_support::project; +++ use cargo_test_support::str; +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn net_retry_loads_from_config() { +++ let p = project() +++ .file( +++@@ -41,7 +41,7 @@ fn net_retry_loads_from_config() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn net_retry_git_outputs_warning() { +++ let p = project() +++ .file( +++diff --git a/src/tools/cargo/tests/testsuite/publish.rs b/src/tools/cargo/tests/testsuite/publish.rs +++index 4bcb9194..0fce483 100644 +++--- a/src/tools/cargo/tests/testsuite/publish.rs ++++++ b/src/tools/cargo/tests/testsuite/publish.rs +++@@ -90,7 +90,7 @@ fn validate_upload_li() { +++ ); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn simple() { +++ let registry = RegistryBuilder::new().http_api().http_index().build(); +++ +++@@ -182,7 +182,7 @@ See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for +++ +++ // Check that the `token` key works at the root instead of under a +++ // `[registry]` table. +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn simple_publish_with_http() { +++ let _reg = registry::RegistryBuilder::new() +++ .http_api() +++@@ -222,7 +222,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn simple_publish_with_asymmetric() { +++ let _reg = registry::RegistryBuilder::new() +++ .http_api() +++@@ -265,7 +265,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn old_token_location() { +++ // `publish` generally requires a remote registry +++ let registry = registry::RegistryBuilder::new().http_api().build(); +++@@ -324,7 +324,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ // Other tests will verify the endpoint gets the right payload. +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn simple_with_index() { +++ // `publish` generally requires a remote registry +++ let registry = registry::RegistryBuilder::new().http_api().build(); +++@@ -369,7 +369,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ // Other tests will verify the endpoint gets the right payload. +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn git_deps() { +++ // Use local registry for faster test times since no publish will occur +++ let registry = registry::init(); +++@@ -407,7 +407,7 @@ the `git` specification will be removed from the dependency declaration. +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn path_dependency_no_version() { +++ // Use local registry for faster test times since no publish will occur +++ let registry = registry::init(); +++@@ -447,7 +447,7 @@ the `path` specification will be removed from the dependency declaration. +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn unpublishable_crate() { +++ // Use local registry for faster test times since no publish will occur +++ let registry = registry::init(); +++@@ -480,7 +480,7 @@ fn unpublishable_crate() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn dont_publish_dirty() { +++ // Use local registry for faster test times since no publish will occur +++ let registry = registry::init(); +++@@ -521,7 +521,7 @@ to proceed despite this and include the uncommitted changes, pass the `--allow-d +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_clean() { +++ // `publish` generally requires a remote registry +++ let registry = registry::RegistryBuilder::new().http_api().build(); +++@@ -569,7 +569,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ // Other tests will verify the endpoint gets the right payload. +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_in_sub_repo() { +++ // `publish` generally requires a remote registry +++ let registry = registry::RegistryBuilder::new().http_api().build(); +++@@ -618,7 +618,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ // Other tests will verify the endpoint gets the right payload. +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_when_ignored() { +++ // `publish` generally requires a remote registry +++ let registry = registry::RegistryBuilder::new().http_api().build(); +++@@ -667,7 +667,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ // Other tests will verify the endpoint gets the right payload. +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn ignore_when_crate_ignored() { +++ // `publish` generally requires a remote registry +++ let registry = registry::RegistryBuilder::new().http_api().build(); +++@@ -715,7 +715,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ // Other tests will verify the endpoint gets the right payload. +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn new_crate_rejected() { +++ // Use local registry for faster test times since no publish will occur +++ let registry = registry::init(); +++@@ -750,7 +750,7 @@ fn new_crate_rejected() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn dry_run() { +++ // Use local registry for faster test times since no publish will occur +++ let registry = registry::init(); +++@@ -793,7 +793,7 @@ See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for +++ assert!(!registry::api_path().join("api/v1/crates/new").exists()); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn registry_not_in_publish_list() { +++ let p = project() +++ .file( +++@@ -826,7 +826,7 @@ The registry `alternative` is not listed in the `package.publish` value in Cargo +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_empty_list() { +++ let p = project() +++ .file( +++@@ -855,7 +855,7 @@ fn publish_empty_list() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_allowed_registry() { +++ let _registry = RegistryBuilder::new() +++ .http_api() +++@@ -915,7 +915,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ ); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_implicitly_to_only_allowed_registry() { +++ let _registry = RegistryBuilder::new() +++ .http_api() +++@@ -976,7 +976,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ ); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_failed_with_index_and_only_allowed_registry() { +++ let registry = RegistryBuilder::new() +++ .http_api() +++@@ -1017,7 +1017,7 @@ fn publish_failed_with_index_and_only_allowed_registry() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_fail_with_no_registry_specified() { +++ let p = project().build(); +++ +++@@ -1050,7 +1050,7 @@ fn publish_fail_with_no_registry_specified() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn block_publish_no_registry() { +++ let p = project() +++ .file( +++@@ -1080,7 +1080,7 @@ fn block_publish_no_registry() { +++ } +++ +++ // Explicitly setting `crates-io` in the publish list. +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_with_crates_io_explicit() { +++ // `publish` generally requires a remote registry +++ let registry = registry::RegistryBuilder::new().http_api().build(); +++@@ -1132,7 +1132,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_with_select_features() { +++ // `publish` generally requires a remote registry +++ let registry = registry::RegistryBuilder::new().http_api().build(); +++@@ -1183,7 +1183,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_with_all_features() { +++ // `publish` generally requires a remote registry +++ let registry = registry::RegistryBuilder::new().http_api().build(); +++@@ -1234,7 +1234,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_with_no_default_features() { +++ // Use local registry for faster test times since no publish will occur +++ let registry = registry::init(); +++@@ -1275,7 +1275,7 @@ fn publish_with_no_default_features() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_with_patch() { +++ let registry = RegistryBuilder::new().http_api().http_index().build(); +++ Package::new("bar", "1.0.0").publish(); +++@@ -1385,7 +1385,8 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ ); +++ } +++ +++-#[cargo_test] ++++#[expect(deprecated)] ++++#[allow(dead_code)] +++ fn publish_checks_for_token_before_verify() { +++ let registry = registry::RegistryBuilder::new() +++ .no_configure_token() +++@@ -1439,7 +1440,7 @@ See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_with_bad_source() { +++ let p = project() +++ .file( +++@@ -1486,7 +1487,7 @@ include `--registry crates-io` to use crates.io +++ } +++ +++ // A dependency with both `git` and `version`. +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_git_with_version() { +++ let registry = RegistryBuilder::new().http_api().http_index().build(); +++ +++@@ -1656,7 +1657,7 @@ dependencies = [ +++ ); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn publish_dev_dep_stripping() { +++ let registry = RegistryBuilder::new().http_api().http_index().build(); +++ Package::new("normal-only", "1.0.0") +++@@ -2092,7 +2093,7 @@ features = ["cat"] +++ ); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn credentials_ambiguous_filename() { +++ // `publish` generally requires a remote registry +++ let registry = registry::RegistryBuilder::new().http_api().build(); +++@@ -2152,7 +2153,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ +++ // --index will not load registry.token to avoid possibly leaking +++ // crates.io token to another server. +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn index_requires_token() { +++ // Use local registry for faster test times since no publish will occur +++ let registry = registry::init(); +++@@ -2187,7 +2188,7 @@ fn index_requires_token() { +++ } +++ +++ // publish with source replacement without --registry +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn cratesio_source_replacement() { +++ registry::init(); +++ let p = project() +++@@ -2217,7 +2218,7 @@ include `--registry dummy-registry` or `--registry crates-io` +++ } +++ +++ // Registry returns an API error. +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn api_error_json() { +++ let _registry = registry::RegistryBuilder::new() +++ .alternative() +++@@ -2265,7 +2266,7 @@ Caused by: +++ } +++ +++ // Registry returns an API error with a 200 status code. +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn api_error_200() { +++ let _registry = registry::RegistryBuilder::new() +++ .alternative() +++@@ -2313,7 +2314,7 @@ Caused by: +++ } +++ +++ // Registry returns an error code without a JSON message. +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn api_error_code() { +++ let _registry = registry::RegistryBuilder::new() +++ .alternative() +++@@ -2368,7 +2369,7 @@ Caused by: +++ } +++ +++ // Registry has a network error. +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn api_curl_error() { +++ let _registry = registry::RegistryBuilder::new() +++ .alternative() +++@@ -2418,7 +2419,7 @@ Caused by: +++ } +++ +++ // Registry returns an invalid response. +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn api_other_error() { +++ let _registry = registry::RegistryBuilder::new() +++ .alternative() +++@@ -2468,7 +2469,7 @@ Caused by: +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn in_package_workspace() { +++ let registry = RegistryBuilder::new().http_api().http_index().build(); +++ +++@@ -2520,7 +2521,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ validate_upload_li(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn with_duplicate_spec_in_members() { +++ // Use local registry for faster test times since no publish will occur +++ let registry = registry::init(); +++@@ -2576,7 +2577,7 @@ fn with_duplicate_spec_in_members() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn in_package_workspace_with_members_with_features_old() { +++ let registry = RegistryBuilder::new().http_api().http_index().build(); +++ +++@@ -2628,7 +2629,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ validate_upload_li(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn in_virtual_workspace() { +++ // Use local registry for faster test times since no publish will occur +++ let registry = registry::init(); +++@@ -2666,7 +2667,7 @@ fn in_virtual_workspace() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn in_virtual_workspace_with_p() { +++ // `publish` generally requires a remote registry +++ let registry = registry::RegistryBuilder::new().http_api().build(); +++@@ -2725,7 +2726,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn in_package_workspace_not_found() { +++ // Use local registry for faster test times since no publish will occur +++ let registry = registry::init(); +++@@ -2769,7 +2770,7 @@ fn in_package_workspace_not_found() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn in_package_workspace_found_multiple() { +++ // Use local registry for faster test times since no publish will occur +++ let registry = registry::init(); +++@@ -2825,7 +2826,7 @@ fn in_package_workspace_found_multiple() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ // https://github.com/rust-lang/cargo/issues/10536 +++ fn publish_path_dependency_without_workspace() { +++ // Use local registry for faster test times since no publish will occur +++@@ -2871,7 +2872,7 @@ fn publish_path_dependency_without_workspace() { +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn http_api_not_noop() { +++ let registry = registry::RegistryBuilder::new().http_api().build(); +++ +++@@ -2933,7 +2934,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ p.cargo("build").run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn wait_for_first_publish() { +++ // Counter for number of tries before the package is "published" +++ let arc: Arc> = Arc::new(Mutex::new(0)); +++@@ -3016,7 +3017,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ /// A separate test is needed for package names with - or _ as they hit +++ /// the responder twice per cargo invocation. If that ever gets changed +++ /// this test will need to be changed accordingly. +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn wait_for_first_publish_underscore() { +++ // Counter for number of tries before the package is "published" +++ let arc: Arc> = Arc::new(Mutex::new(0)); +++@@ -3113,7 +3114,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ p.cargo("build").with_status(0).run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn wait_for_subsequent_publish() { +++ // Counter for number of tries before the package is "published" +++ let arc: Arc> = Arc::new(Mutex::new(0)); +++@@ -3206,7 +3207,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ p.cargo("check").with_status(0).run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn skip_wait_for_publish() { +++ // Intentionally using local registry so the crate never makes it to the index +++ let registry = registry::init(); +++@@ -3250,7 +3251,7 @@ See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn timeout_waiting_for_publish() { +++ // Publish doesn't happen within the timeout window. +++ let registry = registry::RegistryBuilder::new() +++@@ -3302,7 +3303,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn timeout_waiting_for_dependency_publish() { +++ // Publish doesn't happen within the timeout window. +++ let registry = registry::RegistryBuilder::new() +++@@ -3402,7 +3403,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn package_selection() { +++ let registry = registry::RegistryBuilder::new().http_api().build(); +++ let p = project() +++@@ -3516,7 +3517,7 @@ See https://github.com/rust-lang/cargo/issues/10948 for more information about t +++ .run(); +++ } +++ +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn wait_for_git_publish() { +++ // Slow publish to an index with a git index. +++ let registry = registry::RegistryBuilder::new() diff --cc debian/patches/cargo/c-2003-workaround-qemu-vfork-command-not-found.patch index 0000000000,0000000000,0000000000..d7b89a1b36 new file mode 100644 --- /dev/null +++ b/debian/patches/cargo/c-2003-workaround-qemu-vfork-command-not-found.patch @@@@ -1,0 -1,0 -1,0 +1,28 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 13 Jun 2024 11:16:38 +0200 +++Subject: c-2003-workaround-qemu-vfork-command-not-found +++ +++=================================================================== +++--- +++ src/tools/cargo/crates/cargo-test-macro/src/lib.rs | 8 ++++++++ +++ 1 file changed, 8 insertions(+) +++ +++diff --git a/src/tools/cargo/crates/cargo-test-macro/src/lib.rs b/src/tools/cargo/crates/cargo-test-macro/src/lib.rs +++index f974087..b45e8c3 100644 +++--- a/src/tools/cargo/crates/cargo-test-macro/src/lib.rs ++++++ b/src/tools/cargo/crates/cargo-test-macro/src/lib.rs +++@@ -291,6 +291,14 @@ fn check_command(command_path: &Path, args: &[&str]) -> bool { +++ } +++ }; +++ if !output.status.success() { ++++ // Debian specific patch, upstream wontfix: ++++ // qemu has a faulty vfork where it fails to fail if a command is not ++++ // found, with a unix_wait_status of 32512, or 0x7f00, 7f meaning ++++ // exit code 127. See https://github.com/rust-lang/rust/issues/90825 ++++ use std::os::unix::process::ExitStatusExt; ++++ if output.status.into_raw() == 0x7f00 { ++++ return false; ++++ } +++ panic!( +++ "expected command `{command_name}` to be runnable, got error {}:\n\ +++ stderr:{}\n\ diff --cc debian/patches/cargo/c-2200-workaround-x32-test.patch index 0000000000,0000000000,0000000000..3a169e8517 new file mode 100644 --- /dev/null +++ b/debian/patches/cargo/c-2200-workaround-x32-test.patch @@@@ -1,0 -1,0 -1,0 +1,22 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 13 Jun 2024 11:16:38 +0200 +++Subject: c-2200-workaround-x32-test +++ +++Bug: https://github.com/rust-lang/cargo/issues/10005 +++--- +++ src/tools/cargo/tests/testsuite/cfg.rs | 2 +- +++ 1 file changed, 1 insertion(+), 1 deletion(-) +++ +++diff --git a/src/tools/cargo/tests/testsuite/cfg.rs b/src/tools/cargo/tests/testsuite/cfg.rs +++index 9b5cd24..a4b5d1b 100644 +++--- a/src/tools/cargo/tests/testsuite/cfg.rs ++++++ b/src/tools/cargo/tests/testsuite/cfg.rs +++@@ -280,7 +280,7 @@ fn any_ok() { +++ +++ // https://github.com/rust-lang/cargo/issues/5313 +++ #[cargo_test] +++-#[cfg(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu"))] ++++#[cfg(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu", target_pointer_width = "64"))] +++ fn cfg_looks_at_rustflags_for_target() { +++ let p = project() +++ .file( diff --cc debian/patches/cargo/c-disable-fs-specific-test.patch index 0000000000,0000000000,0000000000..60ae016a1b new file mode 100644 --- /dev/null +++ b/debian/patches/cargo/c-disable-fs-specific-test.patch @@@@ -1,0 -1,0 -1,0 +1,22 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 13 Jun 2024 11:16:38 +0200 +++Subject: c-disable-fs-specific-test +++ +++=================================================================== +++--- +++ src/tools/cargo/tests/testsuite/metadata.rs | 2 +- +++ 1 file changed, 1 insertion(+), 1 deletion(-) +++ +++diff --git a/src/tools/cargo/tests/testsuite/metadata.rs b/src/tools/cargo/tests/testsuite/metadata.rs +++index 5c9015a..437cf5d 100644 +++--- a/src/tools/cargo/tests/testsuite/metadata.rs ++++++ b/src/tools/cargo/tests/testsuite/metadata.rs +++@@ -4297,7 +4297,7 @@ fn dep_kinds_workspace() { +++ // Creating non-utf8 path is an OS-specific pain, so let's run this only on +++ // linux, where arbitrary bytes work. +++ #[cfg(target_os = "linux")] +++-#[cargo_test] ++++#[allow(dead_code)] +++ fn cargo_metadata_non_utf8() { +++ use std::ffi::OsString; +++ use std::os::unix::ffi::OsStringExt; diff --cc debian/patches/cargo/d-0012-cargo-always-return-dev-channel.patch index 0000000000,0000000000,0000000000..bb6c6dd939 new file mode 100644 --- /dev/null +++ b/debian/patches/cargo/d-0012-cargo-always-return-dev-channel.patch @@@@ -1,0 -1,0 -1,0 +1,26 @@@@ +++From: Debian Rust Maintainers +++Date: Mon, 6 May 2024 10:25:32 +0200 +++Subject: d-0012-cargo-always-return-dev-channel +++ +++Last-Update: 2023-05-30 +++Forwarded: not-needed +++--- +++ src/tools/cargo/src/cargo/core/features.rs | 5 ++--- +++ 1 file changed, 2 insertions(+), 3 deletions(-) +++ +++diff --git a/src/tools/cargo/src/cargo/core/features.rs b/src/tools/cargo/src/cargo/core/features.rs +++index 4e17898..1a2a437 100644 +++--- a/src/tools/cargo/src/cargo/core/features.rs ++++++ b/src/tools/cargo/src/cargo/core/features.rs +++@@ -1388,9 +1388,8 @@ pub fn channel() -> String { +++ return "dev".to_string(); +++ } +++ } +++- crate::version() +++- .release_channel +++- .unwrap_or_else(|| String::from("dev")) ++++ // Debian: always return dev channel ++++ String::from("dev") +++ } +++ +++ /// Only for testing and developing. See ["Running with gitoxide as default git backend in tests"][1]. diff --cc debian/patches/prune/d-0000-ignore-removed-submodules.patch index 0000000000,0000000000,0000000000..e520b95f04 new file mode 100644 --- /dev/null +++ b/debian/patches/prune/d-0000-ignore-removed-submodules.patch @@@@ -1,0 -1,0 -1,0 +1,190 @@@@ +++From: Debian Rust Maintainers +++Date: Sat, 2 Oct 2021 01:07:59 +0100 +++Subject: d-0000-ignore-removed-submodules +++ +++Description: remove upstream parts that are not needed for the Debian build, in +++order to both reduce the orig tarball and the vendored crates within. +++ +++Forwarded: not-needed +++--- +++ Cargo.toml | 6 ------ +++ src/bootstrap/bootstrap.py | 4 ---- +++ src/bootstrap/src/core/builder/cargo.rs | 5 +---- +++ src/bootstrap/src/core/builder/mod.rs | 23 ----------------------- +++ src/build_helper/src/util.rs | 21 +-------------------- +++ 5 files changed, 2 insertions(+), 57 deletions(-) +++ +++diff --git a/Cargo.toml b/Cargo.toml +++index b773030..7d9b7ba 100644 +++--- a/Cargo.toml ++++++ b/Cargo.toml +++@@ -21,21 +21,15 @@ members = [ +++ "src/tools/tidy", +++ "src/tools/tier-check", +++ "src/tools/build-manifest", +++- "src/tools/remote-test-client", +++- "src/tools/remote-test-server", +++ "src/tools/rust-installer", +++ "src/tools/rustdoc", +++- "src/tools/rls", +++ "src/tools/rustfmt", +++- "src/tools/miri", +++- "src/tools/miri/cargo-miri", +++ "src/tools/rustdoc-themes", +++ "src/tools/unicode-table-generator", +++ "src/tools/jsondocck", +++ "src/tools/jsondoclint", +++ "src/tools/llvm-bitcode-linker", +++ "src/tools/html-checker", +++- "src/tools/bump-stage0", +++ "src/tools/replace-version-placeholder", +++ "src/tools/lld-wrapper", +++ "src/tools/collect-license-metadata", +++diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py +++index 535bdec..3726682 100644 +++--- a/src/bootstrap/bootstrap.py ++++++ b/src/bootstrap/bootstrap.py +++@@ -1129,10 +1129,6 @@ class RustBuild(object): +++ "-Zroot-dir=" + self.rust_root, +++ ] +++ args.extend("--verbose" for _ in range(self.verbose)) +++- if self.use_locked_deps: +++- args.append("--locked") +++- if self.use_vendored_sources: +++- args.append("--frozen") +++ if self.get_toml("metrics", "build"): +++ args.append("--features") +++ args.append("build-metrics") +++diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs +++index 432fbb8..a73e6cf 100644 +++--- a/src/bootstrap/src/core/builder/cargo.rs ++++++ b/src/bootstrap/src/core/builder/cargo.rs +++@@ -1140,10 +1140,7 @@ impl Builder<'_> { +++ } +++ } +++ +++- if self.config.locked_deps { +++- cargo.arg("--locked"); +++- } +++- if self.config.vendor || self.is_sudo { ++++ if self.is_sudo { +++ cargo.arg("--frozen"); +++ } +++ +++diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs +++index 30e42a5..579918d 100644 +++--- a/src/bootstrap/src/core/builder/mod.rs ++++++ b/src/bootstrap/src/core/builder/mod.rs +++@@ -841,26 +841,14 @@ impl<'a> Builder<'a> { +++ tool::Linkchecker, +++ tool::CargoTest, +++ tool::Compiletest, +++- tool::RemoteTestServer, +++- tool::RemoteTestClient, +++ tool::RustInstaller, +++ tool::Cargo, +++- tool::Rls, +++ tool::RustAnalyzer, +++ tool::RustAnalyzerProcMacroSrv, +++ tool::Rustdoc, +++ tool::Clippy, +++ tool::CargoClippy, +++- llvm::Llvm, +++- gcc::Gcc, +++- llvm::Sanitizers, +++ tool::Rustfmt, +++- tool::Miri, +++- tool::CargoMiri, +++- llvm::Lld, +++- llvm::Enzyme, +++- llvm::CrtBeginEnd, +++- tool::RustdocGUITest, +++ tool::OptimizedDist, +++ tool::CoverageDump, +++ tool::LlvmBitcodeLinker, +++@@ -901,10 +889,6 @@ impl<'a> Builder<'a> { +++ check::Rustdoc, +++ check::CodegenBackend, +++ check::Clippy, +++- check::Miri, +++- check::CargoMiri, +++- check::MiroptTestTools, +++- check::Rls, +++ check::Rustfmt, +++ check::RustAnalyzer, +++ check::TestFloatParse, +++@@ -958,8 +942,6 @@ impl<'a> Builder<'a> { +++ test::EmbeddedBook, +++ test::EditionGuide, +++ test::Rustfmt, +++- test::Miri, +++- test::CargoMiri, +++ test::Clippy, +++ test::CompiletestTest, +++ test::CrateRunMakeSupport, +++@@ -1000,7 +982,6 @@ impl<'a> Builder<'a> { +++ doc::CargoBook, +++ doc::Clippy, +++ doc::ClippyBook, +++- doc::Miri, +++ doc::EmbeddedBook, +++ doc::EditionGuide, +++ doc::StyleGuide, +++@@ -1023,11 +1004,9 @@ impl<'a> Builder<'a> { +++ dist::Analysis, +++ dist::Src, +++ dist::Cargo, +++- dist::Rls, +++ dist::RustAnalyzer, +++ dist::Rustfmt, +++ dist::Clippy, +++- dist::Miri, +++ dist::LlvmTools, +++ dist::LlvmBitcodeLinker, +++ dist::RustDev, +++@@ -1053,7 +1032,6 @@ impl<'a> Builder<'a> { +++ install::RustAnalyzer, +++ install::Rustfmt, +++ install::Clippy, +++- install::Miri, +++ install::LlvmTools, +++ install::Src, +++ ), +++@@ -1061,7 +1039,6 @@ impl<'a> Builder<'a> { +++ run::BuildManifest, +++ run::BumpStage0, +++ run::ReplaceVersionPlaceholder, +++- run::Miri, +++ run::CollectLicenseMetadata, +++ run::GenerateCopyright, +++ run::GenerateWindowsSys, +++diff --git a/src/build_helper/src/util.rs b/src/build_helper/src/util.rs +++index 72c05c4..3be35b7 100644 +++--- a/src/build_helper/src/util.rs ++++++ b/src/build_helper/src/util.rs +++@@ -52,24 +52,5 @@ pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> Result<(), ()> { +++ +++ /// Returns the submodule paths from the `.gitmodules` file in the given directory. +++ pub fn parse_gitmodules(target_dir: &Path) -> &[String] { +++- static SUBMODULES_PATHS: OnceLock> = OnceLock::new(); +++- let gitmodules = target_dir.join(".gitmodules"); +++- assert!(gitmodules.exists(), "'{}' file is missing.", gitmodules.display()); +++- +++- let init_submodules_paths = || { +++- let file = File::open(gitmodules).unwrap(); +++- +++- let mut submodules_paths = vec![]; +++- for line in BufReader::new(file).lines().map_while(Result::ok) { +++- let line = line.trim(); +++- if line.starts_with("path") { +++- let actual_path = line.split(' ').last().expect("Couldn't get value of path"); +++- submodules_paths.push(actual_path.to_owned()); +++- } +++- } +++- +++- submodules_paths +++- }; +++- +++- SUBMODULES_PATHS.get_or_init(|| init_submodules_paths()) ++++ return &[]; +++ } diff --cc debian/patches/prune/d-0001-pkg-config-no-special-snowflake.patch index 0000000000,0000000000,0000000000..b66fe2f542 new file mode 100644 --- /dev/null +++ b/debian/patches/prune/d-0001-pkg-config-no-special-snowflake.patch @@@@ -1,0 -1,0 -1,0 +1,97 @@@@ +++From: Debian Rust Maintainers +++Date: Sat, 2 Oct 2021 01:08:00 +0100 +++Subject: d-0001-pkg-config-no-special-snowflake +++ +++Description: always enable cross compilation via pkgconf, and set the right binary name. +++ +++Forwarded: not-needed +++--- +++ vendor/pkg-config-0.3.31/src/lib.rs | 26 +++++++++++--------------- +++ vendor/pkg-config-0.3.31/tests/test.rs | 2 -- +++ 2 files changed, 11 insertions(+), 17 deletions(-) +++ +++diff --git a/vendor/pkg-config-0.3.31/src/lib.rs b/vendor/pkg-config-0.3.31/src/lib.rs +++index db693fa..9ea4f56 100644 +++--- a/vendor/pkg-config-0.3.31/src/lib.rs ++++++ b/vendor/pkg-config-0.3.31/src/lib.rs +++@@ -150,11 +150,8 @@ pub enum Error { +++ /// Contains the name of the responsible environment variable. +++ EnvNoPkgConfig(String), +++ +++- /// Detected cross compilation without a custom sysroot. +++- /// +++- /// Ignore the error with `PKG_CONFIG_ALLOW_CROSS=1`, +++- /// which may let `pkg-config` select libraries +++- /// for the host's architecture instead of the target's. ++++ /// Cross compilation detected. Kept for compatibility; ++++ /// the Debian package never emits this. +++ CrossCompilation, +++ +++ /// Failed to run `pkg-config`. +++@@ -269,14 +266,6 @@ impl fmt::Display for Error { +++ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { +++ match *self { +++ Error::EnvNoPkgConfig(ref name) => write!(f, "Aborted because {} is set", name), +++- Error::CrossCompilation => f.write_str( +++- "pkg-config has not been configured to support cross-compilation.\n\ +++- \n\ +++- Install a sysroot for the target platform and configure it via\n\ +++- PKG_CONFIG_SYSROOT_DIR and PKG_CONFIG_PATH, or install a\n\ +++- cross-compiling wrapper for pkg-config and set it via\n\ +++- PKG_CONFIG environment variable.", +++- ), +++ Error::Command { +++ ref command, +++ ref cause, +++@@ -402,7 +391,7 @@ impl fmt::Display for Error { +++ )?; +++ format_output(output, f) +++ } +++- Error::__Nonexhaustive => panic!(), ++++ Error::CrossCompilation | Error::__Nonexhaustive => panic!(), +++ } +++ } +++ } +++@@ -596,6 +585,8 @@ impl Config { +++ if host == target { +++ return true; +++ } ++++ // always enable PKG_CONFIG_ALLOW_CROSS override in Debian ++++ return true; +++ +++ // pkg-config may not be aware of cross-compilation, and require +++ // a wrapper script that sets up platform-specific prefixes. +++@@ -653,7 +644,12 @@ impl Config { +++ } +++ +++ fn run(&self, name: &str, args: &[&str]) -> Result, Error> { +++- let pkg_config_exe = self.targeted_env_var("PKG_CONFIG"); ++++ let pkg_config_exe = self.targeted_env_var("PKG_CONFIG").or_else(|| { ++++ self.env_var_os("DEB_HOST_GNU_TYPE").map(|mut t| { ++++ t.push(OsString::from("-pkgconf")); ++++ t ++++ }) ++++ }); +++ let fallback_exe = if pkg_config_exe.is_none() { +++ Some(OsString::from("pkgconf")) +++ } else { +++diff --git a/vendor/pkg-config-0.3.31/tests/test.rs b/vendor/pkg-config-0.3.31/tests/test.rs +++index ef80fc7..dad738d 100644 +++--- a/vendor/pkg-config-0.3.31/tests/test.rs ++++++ b/vendor/pkg-config-0.3.31/tests/test.rs +++@@ -28,7 +28,6 @@ fn find(name: &str) -> Result { +++ pkg_config::probe_library(name) +++ } +++ +++-#[test] +++ fn cross_disabled() { +++ let _g = LOCK.lock(); +++ reset(); +++@@ -40,7 +39,6 @@ fn cross_disabled() { +++ } +++ } +++ +++-#[test] +++ fn cross_enabled() { +++ let _g = LOCK.lock(); +++ reset(); diff --cc debian/patches/prune/d-0002-mdbook-strip-embedded-libs.patch index 0000000000,0000000000,0000000000..66679f2db8 new file mode 100644 --- /dev/null +++ b/debian/patches/prune/d-0002-mdbook-strip-embedded-libs.patch @@@@ -1,0 -1,0 -1,0 +1,554 @@@@ +++From: Debian Rust Maintainers +++Date: Sat, 2 Oct 2021 01:08:00 +0100 +++Subject: d-0002-mdbook-strip-embedded-libs +++ +++Description: Use https://github.com/infinity0/mdBook/tree/debian to help you rebase +++the patch on top of a newer version. . Make sure the paths here match the ones +++in debian/rust-doc.links +++ +++Forwarded: not-needed +++--- +++ src/doc/rust-by-example/theme/index.hbs | 83 +--------------- +++ src/tools/linkchecker/main.rs | 28 +++++- +++ vendor/mdbook-0.4.43/src/book/init.rs | 19 ---- +++ .../src/renderer/html_handlebars/hbs_renderer.rs | 104 ++++----------------- +++ .../src/renderer/html_handlebars/search.rs | 2 - +++ vendor/mdbook-0.4.43/src/theme/index.hbs | 57 +---------- +++ vendor/mdbook-0.4.43/src/theme/mod.rs | 27 ------ +++ vendor/mdbook-0.4.43/src/theme/searcher/mod.rs | 2 - +++ vendor/mdbook-0.4.43/src/theme/toc.html.hbs | 3 +- +++ 9 files changed, 52 insertions(+), 273 deletions(-) +++ +++diff --git a/src/doc/rust-by-example/theme/index.hbs b/src/doc/rust-by-example/theme/index.hbs +++index 960f541..830fd29 100644 +++--- a/src/doc/rust-by-example/theme/index.hbs ++++++ b/src/doc/rust-by-example/theme/index.hbs +++@@ -33,10 +33,7 @@ +++ {{/if}} +++ +++ +++- +++- {{#if copy_fonts}} +++- +++- {{/if}} ++++ +++ +++ +++ +++@@ -50,7 +47,7 @@ +++ +++ {{#if mathjax_support}} +++ +++- ++++ +++ {{/if}} +++ +++ +++@@ -63,32 +60,6 @@ +++ +++ +++
+++- +++- +++- +++- +++- +++ +++ +++ +++@@ -296,54 +267,8 @@ +++ +++ {{/if}} +++ +++- {{#if google_analytics}} +++- +++- +++- {{/if}} +++- +++- {{#if playground_line_numbers}} +++- +++- {{/if}} +++- +++- {{#if playground_copyable}} +++- +++- {{/if}} +++- +++- {{#if playground_js}} +++- +++- +++- +++- +++- +++- {{/if}} +++- +++- {{#if search_js}} +++- +++- +++- +++- {{/if}} +++- +++- +++- +++- ++++ ++++ +++ +++ +++ {{#each additional_js}} +++diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs +++index 570b2c3..d39ed99 100644 +++--- a/src/tools/linkchecker/main.rs ++++++ b/src/tools/linkchecker/main.rs +++@@ -171,7 +171,17 @@ impl Checker { +++ for entry in t!(dir.read_dir()).map(|e| t!(e)) { +++ let path = entry.path(); +++ // Goes through symlinks +++- let metadata = t!(fs::metadata(&path)); ++++ let metadata = fs::metadata(&path); ++++ if let Err(err) = metadata { ++++ if let Ok(target) = fs::read_link(&path) { ++++ if target.starts_with("/usr/share") { ++++ // broken symlink to /usr/share, ok for our Debian build ++++ return; ++++ } ++++ } ++++ panic!("error at file {:?} while walking - {:?}", path, err) ++++ } ++++ let metadata = t!(metadata); +++ if metadata.is_dir() { +++ self.walk(&path, report); +++ } else { +++@@ -184,7 +194,15 @@ impl Checker { +++ fn check(&mut self, file: &Path, report: &mut Report) { +++ let (pretty_path, entry) = self.load_file(file, report); +++ let source = match entry { +++- FileEntry::Missing => panic!("missing file {:?} while walking", file), ++++ FileEntry::Missing => { ++++ if let Ok(target) = fs::read_link(&file) { ++++ if target.starts_with("/usr/share") { ++++ // broken symlink to /usr/share, ok for our Debian build ++++ return; ++++ } ++++ } ++++ panic!("missing file {:?} while walking", file) ++++ } +++ FileEntry::Dir => unreachable!("never with `check` path"), +++ FileEntry::OtherFile => return, +++ FileEntry::Redirect { .. } => return, +++@@ -273,6 +291,12 @@ impl Checker { +++ let (target_pretty_path, target_entry) = self.load_file(&path, report); +++ let (target_source, target_ids) = match target_entry { +++ FileEntry::Missing => { ++++ if let Ok(target) = fs::read_link(&path) { ++++ if target.starts_with("/usr/share") { ++++ // broken symlink to /usr/share, ok for our Debian build ++++ return; ++++ } ++++ } +++ if is_exception(file, &target_pretty_path) { +++ report.links_ignored_exception += 1; +++ } else { +++diff --git a/vendor/mdbook-0.4.43/src/book/init.rs b/vendor/mdbook-0.4.43/src/book/init.rs +++index faca1d0..c1a82a3 100644 +++--- a/vendor/mdbook-0.4.43/src/book/init.rs ++++++ b/vendor/mdbook-0.4.43/src/book/init.rs +++@@ -153,25 +153,6 @@ impl BookBuilder { +++ let mut js = File::create(themedir.join("book.js"))?; +++ js.write_all(theme::JS)?; +++ +++- let mut highlight_css = File::create(themedir.join("highlight.css"))?; +++- highlight_css.write_all(theme::HIGHLIGHT_CSS)?; +++- +++- let mut highlight_js = File::create(themedir.join("highlight.js"))?; +++- highlight_js.write_all(theme::HIGHLIGHT_JS)?; +++- +++- write_file(&themedir.join("fonts"), "fonts.css", theme::fonts::CSS)?; +++- for (file_name, contents) in theme::fonts::LICENSES { +++- write_file(&themedir, file_name, contents)?; +++- } +++- for (file_name, contents) in theme::fonts::OPEN_SANS.iter() { +++- write_file(&themedir, file_name, contents)?; +++- } +++- write_file( +++- &themedir, +++- theme::fonts::SOURCE_CODE_PRO.0, +++- theme::fonts::SOURCE_CODE_PRO.1, +++- )?; +++- +++ Ok(()) +++ } +++ +++diff --git a/vendor/mdbook-0.4.43/src/renderer/html_handlebars/hbs_renderer.rs b/vendor/mdbook-0.4.43/src/renderer/html_handlebars/hbs_renderer.rs +++index d0149fb..06ea0b4 100644 +++--- a/vendor/mdbook-0.4.43/src/renderer/html_handlebars/hbs_renderer.rs ++++++ b/vendor/mdbook-0.4.43/src/renderer/html_handlebars/hbs_renderer.rs +++@@ -3,13 +3,14 @@ use crate::config::{BookConfig, Code, Config, HtmlConfig, Playground, RustEditio +++ use crate::errors::*; +++ use crate::renderer::html_handlebars::helpers; +++ use crate::renderer::{RenderContext, Renderer}; +++-use crate::theme::{self, playground_editor, Theme}; ++++use crate::theme::{self, Theme}; +++ use crate::utils; +++ +++ use std::borrow::Cow; +++ use std::collections::BTreeMap; +++ use std::collections::HashMap; +++ use std::fs::{self, File}; ++++use std::os::unix::fs::symlink; +++ use std::path::{Path, PathBuf}; +++ +++ use crate::utils::fs::get_404_output_file; +++@@ -253,99 +254,28 @@ impl HtmlHandlebars { +++ if let Some(contents) = &theme.favicon_svg { +++ write_file(destination, "favicon.svg", contents)?; +++ } +++- write_file(destination, "highlight.css", &theme.highlight_css)?; +++ write_file(destination, "tomorrow-night.css", &theme.tomorrow_night_css)?; +++ write_file(destination, "ayu-highlight.css", &theme.ayu_highlight_css)?; +++- write_file(destination, "highlight.js", &theme.highlight_js)?; +++- write_file(destination, "clipboard.min.js", &theme.clipboard_js)?; +++- write_file( +++- destination, +++- "FontAwesome/css/font-awesome.css", +++- theme::FONT_AWESOME, ++++ symlink( ++++ "/usr/share/fonts-font-awesome/css/font-awesome.min.css", ++++ destination.join("css/font-awesome.min.css"), +++ )?; +++- write_file( +++- destination, +++- "FontAwesome/fonts/fontawesome-webfont.eot", +++- theme::FONT_AWESOME_EOT, ++++ symlink( ++++ "/usr/share/fonts-font-awesome/fonts", ++++ destination.join("fonts"), +++ )?; +++- write_file( +++- destination, +++- "FontAwesome/fonts/fontawesome-webfont.svg", +++- theme::FONT_AWESOME_SVG, ++++ symlink( ++++ "/usr/share/javascript/highlight.js/styles/atelier-dune-light.css", ++++ destination.join("highlight.css"), +++ )?; +++- write_file( +++- destination, +++- "FontAwesome/fonts/fontawesome-webfont.ttf", +++- theme::FONT_AWESOME_TTF, ++++ symlink( ++++ "/usr/share/javascript/highlight.js/highlight.js", ++++ destination.join("highlight.js"), +++ )?; +++- write_file( +++- destination, +++- "FontAwesome/fonts/fontawesome-webfont.woff", +++- theme::FONT_AWESOME_WOFF, +++- )?; +++- write_file( +++- destination, +++- "FontAwesome/fonts/fontawesome-webfont.woff2", +++- theme::FONT_AWESOME_WOFF2, +++- )?; +++- write_file( +++- destination, +++- "FontAwesome/fonts/FontAwesome.ttf", +++- theme::FONT_AWESOME_TTF, ++++ symlink( ++++ "/usr/share/javascript/mathjax/MathJax.js", ++++ destination.join("MathJax.js"), +++ )?; +++- // Don't copy the stock fonts if the user has specified their own fonts to use. +++- if html_config.copy_fonts && theme.fonts_css.is_none() { +++- write_file(destination, "fonts/fonts.css", theme::fonts::CSS)?; +++- for (file_name, contents) in theme::fonts::LICENSES.iter() { +++- write_file(destination, file_name, contents)?; +++- } +++- for (file_name, contents) in theme::fonts::OPEN_SANS.iter() { +++- write_file(destination, file_name, contents)?; +++- } +++- write_file( +++- destination, +++- theme::fonts::SOURCE_CODE_PRO.0, +++- theme::fonts::SOURCE_CODE_PRO.1, +++- )?; +++- } +++- if let Some(fonts_css) = &theme.fonts_css { +++- if !fonts_css.is_empty() { +++- write_file(destination, "fonts/fonts.css", fonts_css)?; +++- } +++- } +++- if !html_config.copy_fonts && theme.fonts_css.is_none() { +++- warn!( +++- "output.html.copy-fonts is deprecated.\n\ +++- This book appears to have copy-fonts=false in book.toml without a fonts.css file.\n\ +++- Add an empty `theme/fonts/fonts.css` file to squelch this warning." +++- ); +++- } +++- for font_file in &theme.font_files { +++- let contents = fs::read(font_file)?; +++- let filename = font_file.file_name().unwrap(); +++- let filename = Path::new("fonts").join(filename); +++- write_file(destination, filename, &contents)?; +++- } +++- +++- let playground_config = &html_config.playground; +++- +++- // Ace is a very large dependency, so only load it when requested +++- if playground_config.editable && playground_config.copy_js { +++- // Load the editor +++- write_file(destination, "editor.js", playground_editor::JS)?; +++- write_file(destination, "ace.js", playground_editor::ACE_JS)?; +++- write_file(destination, "mode-rust.js", playground_editor::MODE_RUST_JS)?; +++- write_file( +++- destination, +++- "theme-dawn.js", +++- playground_editor::THEME_DAWN_JS, +++- )?; +++- write_file( +++- destination, +++- "theme-tomorrow_night.js", +++- playground_editor::THEME_TOMORROW_NIGHT_JS, +++- )?; +++- } +++ +++ Ok(()) +++ } +++diff --git a/vendor/mdbook-0.4.43/src/renderer/html_handlebars/search.rs b/vendor/mdbook-0.4.43/src/renderer/html_handlebars/search.rs +++index c03eb4f..e25ec4a 100644 +++--- a/vendor/mdbook-0.4.43/src/renderer/html_handlebars/search.rs ++++++ b/vendor/mdbook-0.4.43/src/renderer/html_handlebars/search.rs +++@@ -53,8 +53,6 @@ pub fn create_files(search_config: &Search, destination: &Path, book: &Book) -> +++ format!("Object.assign(window.search, {index});").as_bytes(), +++ )?; +++ utils::fs::write_file(destination, "searcher.js", searcher::JS)?; +++- utils::fs::write_file(destination, "mark.min.js", searcher::MARK_JS)?; +++- utils::fs::write_file(destination, "elasticlunr.min.js", searcher::ELASTICLUNR_JS)?; +++ debug!("Copying search files ✓"); +++ } +++ +++diff --git a/vendor/mdbook-0.4.43/src/theme/index.hbs b/vendor/mdbook-0.4.43/src/theme/index.hbs +++index 7775f26..8fc5353 100644 +++--- a/vendor/mdbook-0.4.43/src/theme/index.hbs ++++++ b/vendor/mdbook-0.4.43/src/theme/index.hbs +++@@ -33,10 +33,7 @@ +++ {{/if}} +++ +++ +++- +++- {{#if copy_fonts}} +++- +++- {{/if}} ++++ +++ +++ +++ +++@@ -50,7 +47,7 @@ +++ +++ {{#if mathjax_support}} +++ +++- ++++ +++ {{/if}} +++ +++ +++@@ -248,54 +245,8 @@ +++ +++ {{/if}} +++ +++- {{#if google_analytics}} +++- +++- +++- {{/if}} +++- +++- {{#if playground_line_numbers}} +++- +++- {{/if}} +++- +++- {{#if playground_copyable}} +++- +++- {{/if}} +++- +++- {{#if playground_js}} +++- +++- +++- +++- +++- +++- {{/if}} +++- +++- {{#if search_js}} +++- +++- +++- +++- {{/if}} +++- +++- +++- +++- ++++ ++++ +++ +++ +++ {{#each additional_js}} +++diff --git a/vendor/mdbook-0.4.43/src/theme/mod.rs b/vendor/mdbook-0.4.43/src/theme/mod.rs +++index b173bd4..46a6902 100644 +++--- a/vendor/mdbook-0.4.43/src/theme/mod.rs ++++++ b/vendor/mdbook-0.4.43/src/theme/mod.rs +++@@ -1,9 +1,5 @@ +++ #![allow(missing_docs)] +++ +++-pub mod playground_editor; +++- +++-pub mod fonts; +++- +++ #[cfg(feature = "search")] +++ pub mod searcher; +++ +++@@ -26,19 +22,8 @@ pub static VARIABLES_CSS: &[u8] = include_bytes!("css/variables.css"); +++ pub static FAVICON_PNG: &[u8] = include_bytes!("favicon.png"); +++ pub static FAVICON_SVG: &[u8] = include_bytes!("favicon.svg"); +++ pub static JS: &[u8] = include_bytes!("book.js"); +++-pub static HIGHLIGHT_JS: &[u8] = include_bytes!("highlight.js"); +++ pub static TOMORROW_NIGHT_CSS: &[u8] = include_bytes!("tomorrow-night.css"); +++-pub static HIGHLIGHT_CSS: &[u8] = include_bytes!("highlight.css"); +++ pub static AYU_HIGHLIGHT_CSS: &[u8] = include_bytes!("ayu-highlight.css"); +++-pub static CLIPBOARD_JS: &[u8] = include_bytes!("clipboard.min.js"); +++-pub static FONT_AWESOME: &[u8] = include_bytes!("FontAwesome/css/font-awesome.min.css"); +++-pub static FONT_AWESOME_EOT: &[u8] = include_bytes!("FontAwesome/fonts/fontawesome-webfont.eot"); +++-pub static FONT_AWESOME_SVG: &[u8] = include_bytes!("FontAwesome/fonts/fontawesome-webfont.svg"); +++-pub static FONT_AWESOME_TTF: &[u8] = include_bytes!("FontAwesome/fonts/fontawesome-webfont.ttf"); +++-pub static FONT_AWESOME_WOFF: &[u8] = include_bytes!("FontAwesome/fonts/fontawesome-webfont.woff"); +++-pub static FONT_AWESOME_WOFF2: &[u8] = +++- include_bytes!("FontAwesome/fonts/fontawesome-webfont.woff2"); +++-pub static FONT_AWESOME_OTF: &[u8] = include_bytes!("FontAwesome/fonts/FontAwesome.otf"); +++ +++ /// The `Theme` struct should be used instead of the static variables because +++ /// the `new()` method will look if the user has a theme directory in their +++@@ -63,11 +48,8 @@ pub struct Theme { +++ pub favicon_png: Option>, +++ pub favicon_svg: Option>, +++ pub js: Vec, +++- pub highlight_css: Vec, +++ pub tomorrow_night_css: Vec, +++ pub ayu_highlight_css: Vec, +++- pub highlight_js: Vec, +++- pub clipboard_js: Vec, +++ } +++ +++ impl Theme { +++@@ -99,9 +81,6 @@ impl Theme { +++ theme_dir.join("css/variables.css"), +++ &mut theme.variables_css, +++ ), +++- (theme_dir.join("highlight.js"), &mut theme.highlight_js), +++- (theme_dir.join("clipboard.min.js"), &mut theme.clipboard_js), +++- (theme_dir.join("highlight.css"), &mut theme.highlight_css), +++ ( +++ theme_dir.join("tomorrow-night.css"), +++ &mut theme.tomorrow_night_css, +++@@ -191,11 +170,8 @@ impl Default for Theme { +++ favicon_png: Some(FAVICON_PNG.to_owned()), +++ favicon_svg: Some(FAVICON_SVG.to_owned()), +++ js: JS.to_owned(), +++- highlight_css: HIGHLIGHT_CSS.to_owned(), +++ tomorrow_night_css: TOMORROW_NIGHT_CSS.to_owned(), +++ ayu_highlight_css: AYU_HIGHLIGHT_CSS.to_owned(), +++- highlight_js: HIGHLIGHT_JS.to_owned(), +++- clipboard_js: CLIPBOARD_JS.to_owned(), +++ } +++ } +++ } +++@@ -284,11 +260,8 @@ mod tests { +++ favicon_png: Some(Vec::new()), +++ favicon_svg: Some(Vec::new()), +++ js: Vec::new(), +++- highlight_css: Vec::new(), +++ tomorrow_night_css: Vec::new(), +++ ayu_highlight_css: Vec::new(), +++- highlight_js: Vec::new(), +++- clipboard_js: Vec::new(), +++ }; +++ +++ assert_eq!(got, empty); +++diff --git a/vendor/mdbook-0.4.43/src/theme/searcher/mod.rs b/vendor/mdbook-0.4.43/src/theme/searcher/mod.rs +++index d5029db..59eda8a 100644 +++--- a/vendor/mdbook-0.4.43/src/theme/searcher/mod.rs ++++++ b/vendor/mdbook-0.4.43/src/theme/searcher/mod.rs +++@@ -2,5 +2,3 @@ +++ //! the "search" cargo feature is disabled. +++ +++ pub static JS: &[u8] = include_bytes!("searcher.js"); +++-pub static MARK_JS: &[u8] = include_bytes!("mark.min.js"); +++-pub static ELASTICLUNR_JS: &[u8] = include_bytes!("elasticlunr.min.js"); +++diff --git a/vendor/mdbook-0.4.43/src/theme/toc.html.hbs b/vendor/mdbook-0.4.43/src/theme/toc.html.hbs +++index f8fca87..4993db8 100644 +++--- a/vendor/mdbook-0.4.43/src/theme/toc.html.hbs ++++++ b/vendor/mdbook-0.4.43/src/theme/toc.html.hbs +++@@ -28,9 +28,8 @@ +++ +++ {{/if}} +++ +++- ++++ +++ {{#if copy_fonts}} +++- +++ {{/if}} +++ +++ {{#each additional_css}} diff --cc debian/patches/prune/d-0005-no-jemalloc.patch index 0000000000,0000000000,0000000000..cd0e946449 new file mode 100644 --- /dev/null +++ b/debian/patches/prune/d-0005-no-jemalloc.patch @@@@ -1,0 -1,0 -1,0 +1,74 @@@@ +++From: Debian Rust Maintainers +++Date: Sat, 2 Oct 2021 01:08:00 +0100 +++Subject: d-0005-no-jemalloc +++ +++Description: remove jemalloc-sys +++ +++Forwarded: not-needed +++--- +++ compiler/rustc/Cargo.toml | 6 ------ +++ src/tools/rust-analyzer/crates/profile/Cargo.toml | 2 -- +++ src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml | 4 ---- +++ 3 files changed, 12 deletions(-) +++ +++diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml +++index d24b630..2256524 100644 +++--- a/compiler/rustc/Cargo.toml ++++++ b/compiler/rustc/Cargo.toml +++@@ -20,14 +20,8 @@ rustc_smir = { path = "../rustc_smir" } +++ stable_mir = { path = "../stable_mir" } +++ # tidy-alphabetical-end +++ +++-[dependencies.tikv-jemalloc-sys] +++-version = "0.6.0" +++-optional = true +++-features = ['unprefixed_malloc_on_supported_platforms'] +++- +++ [features] +++ # tidy-alphabetical-start +++-jemalloc = ['dep:tikv-jemalloc-sys'] +++ llvm = ['rustc_driver_impl/llvm'] +++ max_level_info = ['rustc_driver_impl/max_level_info'] +++ rustc_randomized_layouts = ['rustc_driver_impl/rustc_randomized_layouts'] +++diff --git a/src/tools/rust-analyzer/crates/profile/Cargo.toml b/src/tools/rust-analyzer/crates/profile/Cargo.toml +++index 2e3413f..f823aa1 100644 +++--- a/src/tools/rust-analyzer/crates/profile/Cargo.toml ++++++ b/src/tools/rust-analyzer/crates/profile/Cargo.toml +++@@ -15,7 +15,6 @@ doctest = false +++ [dependencies] +++ cfg-if = "1.0.0" +++ libc.workspace = true +++-jemalloc-ctl = { version = "0.5.0", package = "tikv-jemalloc-ctl", optional = true } +++ +++ [target.'cfg(target_os = "linux")'.dependencies] +++ perf-event = "=0.4.7" +++@@ -25,7 +24,6 @@ windows-sys = { version = "0.52", features = ["Win32_System_Threading", "Win32_S +++ +++ [features] +++ cpu_profiler = [] +++-jemalloc = ["jemalloc-ctl"] +++ +++ # Uncomment to enable for the whole crate graph +++ # default = [ "cpu_profiler" ] +++diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++index fa9ff6b..ba1925d 100644 +++--- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml ++++++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++@@ -78,9 +78,6 @@ paths.workspace = true +++ [target.'cfg(windows)'.dependencies] +++ windows-sys = { version = "0.52", features = ["Win32_System_Threading"] } +++ +++-[target.'cfg(not(target_env = "msvc"))'.dependencies] +++-jemallocator = { version = "0.5.0", package = "tikv-jemallocator", optional = true } +++- +++ [dev-dependencies] +++ expect-test = "1.4.0" +++ xshell.workspace = true +++@@ -90,7 +87,6 @@ test-fixture.workspace = true +++ syntax-bridge.workspace = true +++ +++ [features] +++-jemalloc = ["jemallocator", "profile/jemalloc"] +++ force-always-assert = ["always-assert/force"] +++ sysroot-abi = [] +++ in-rust-tree = [ diff --cc debian/patches/prune/d-0006-no-mimalloc.patch index 0000000000,0000000000,0000000000..03edfb462e new file mode 100644 --- /dev/null +++ b/debian/patches/prune/d-0006-no-mimalloc.patch @@@@ -1,0 -1,0 -1,0 +1,23 @@@@ +++From: Debian Rust Maintainers +++Date: Sat, 11 Jan 2025 11:37:00 +0100 +++Subject: d-0006-no-mimalloc +++ +++Description: remove mimalloc(-sys) +++ +++Forwarded: not-needed +++--- +++ src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml | 1 - +++ 1 file changed, 1 deletion(-) +++ +++diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++index ba1925d..70a792b 100644 +++--- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml ++++++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++@@ -39,7 +39,6 @@ serde.workspace = true +++ serde_derive.workspace = true +++ tenthash = "0.4.0" +++ num_cpus = "1.15.0" +++-mimalloc = { version = "0.1.30", default-features = false, optional = true } +++ lsp-server.workspace = true +++ tracing.workspace = true +++ tracing-subscriber.workspace = true diff --cc debian/patches/prune/d-0007-no-tzdb.patch index 0000000000,0000000000,0000000000..6a55de2471 new file mode 100644 --- /dev/null +++ b/debian/patches/prune/d-0007-no-tzdb.patch @@@@ -1,0 -1,0 -1,0 +1,25 @@@@ +++From: Debian Rust Maintainers +++Date: Sat, 11 Jan 2025 11:37:00 +0100 +++Subject: d-0007-no-tzdb +++ +++Description: remove jiff-tzdb(-platform) +++ +++on Debian, we can just use the tzdata information.. +++ +++Forwarded: not-needed +++--- +++ vendor/jiff-0.1.13/Cargo.toml | 1 - +++ 1 file changed, 1 deletion(-) +++ +++diff --git a/vendor/jiff-0.1.13/Cargo.toml b/vendor/jiff-0.1.13/Cargo.toml +++index 7ff813b..43b6e66 100644 +++--- a/vendor/jiff-0.1.13/Cargo.toml ++++++ b/vendor/jiff-0.1.13/Cargo.toml +++@@ -122,7 +122,6 @@ alloc = [] +++ default = [ +++ "std", +++ "tz-system", +++- "tzdb-bundle-platform", +++ "tzdb-zoneinfo", +++ ] +++ js = [ diff --cc debian/patches/prune/d-0010-cargo-remove-vendored-c-crates.patch index 0000000000,0000000000,0000000000..c8a1e4a327 new file mode 100644 --- /dev/null +++ b/debian/patches/prune/d-0010-cargo-remove-vendored-c-crates.patch @@@@ -1,0 -1,0 -1,0 +1,38 @@@@ +++From: Debian Rust Maintainers +++Date: Mon, 6 May 2024 10:25:32 +0200 +++Subject: d-0010-cargo-remove-vendored-c-crates +++ +++Description: remove all vendoring features of crates normally shipping bundled +++C libs. that C code is stripped when repacking, so the features can't work +++anyway. +++ +++Forwarded: not-needed +++--- +++ src/tools/cargo/Cargo.toml | 6 ++---- +++ 1 file changed, 2 insertions(+), 4 deletions(-) +++ +++diff --git a/src/tools/cargo/Cargo.toml b/src/tools/cargo/Cargo.toml +++index 0a73f86..9898d05 100644 +++--- a/src/tools/cargo/Cargo.toml ++++++ b/src/tools/cargo/Cargo.toml +++@@ -80,7 +80,7 @@ proptest = "1.5.0" +++ pulldown-cmark = { version = "0.12.0", default-features = false, features = ["html"] } +++ rand = "0.8.5" +++ regex = "1.10.5" +++-rusqlite = { version = "0.32.0", features = ["bundled"] } ++++rusqlite = { version = "0.32.0" } +++ rustc-hash = "2.0.0" +++ rustc-stable-hash = "0.1.1" +++ rustfix = { version = "0.9.0", path = "crates/rustfix" } +++@@ -267,10 +267,8 @@ test = false +++ doc = false +++ +++ [features] +++-vendored-openssl = ["openssl/vendored"] +++-vendored-libgit2 = ["libgit2-sys/vendored"] ++++# Debian: removed vendoring flags +++ # This is primarily used by rust-lang/rust distributing cargo the executable. +++-all-static = ['vendored-openssl', 'curl/static-curl', 'curl/force-system-lib-on-osx', 'vendored-libgit2'] +++ +++ [lints] +++ workspace = true diff --cc debian/patches/prune/d-0011-cargo-remove-nghttp2.patch index 0000000000,0000000000,0000000000..5f8b87fc23 new file mode 100644 --- /dev/null +++ b/debian/patches/prune/d-0011-cargo-remove-nghttp2.patch @@@@ -1,0 -1,0 -1,0 +1,26 @@@@ +++From: Debian Rust Maintainers +++Date: Mon, 6 May 2024 10:25:32 +0200 +++Subject: d-0011-cargo-remove-nghttp2 +++ +++Description: remove dependency on libnghttp2-sys so it can be pruned. +++ +++Last-Update: 2023-05-17 +++ +++Forwarded: not-needed +++--- +++ vendor/curl-sys-0.4.78+curl-8.11.0/Cargo.toml | 2 +- +++ 1 file changed, 1 insertion(+), 1 deletion(-) +++ +++diff --git a/vendor/curl-sys-0.4.78+curl-8.11.0/Cargo.toml b/vendor/curl-sys-0.4.78+curl-8.11.0/Cargo.toml +++index 565a506..f78fab8 100644 +++--- a/vendor/curl-sys-0.4.78+curl-8.11.0/Cargo.toml ++++++ b/vendor/curl-sys-0.4.78+curl-8.11.0/Cargo.toml +++@@ -61,7 +61,7 @@ version = "0.3.3" +++ [features] +++ default = ["ssl"] +++ force-system-lib-on-osx = [] +++-http2 = ["libnghttp2-sys"] ++++http2 = [] +++ mesalink = [] +++ ntlm = [] +++ poll_7_68_0 = [] diff --cc debian/patches/prune/d-0020-remove-windows-dependencies.patch index 0000000000,0000000000,0000000000..4249c3ae3e new file mode 100644 --- /dev/null +++ b/debian/patches/prune/d-0020-remove-windows-dependencies.patch @@@@ -1,0 -1,0 -1,0 +1,515 @@@@ +++From: Debian Rust Maintainers +++Date: Mon, 6 May 2024 10:25:32 +0200 +++Subject: d-0020-remove-windows-dependencies +++ +++use something like +++ +++ find src compiler library -iname Cargo.toml -exec grep -H -n -e 'windows-sys' -e 'winapi' -e 'ntapi' -e 'wincon' -e 'winreg' -e 'windows' {} \; +++ +++to find and eliminate dependencies on windows-only crates when rebasing. +++ +++windows-bindgen and windows-metadata should not be removed, they are needed for +++the build and don't pull in windows-sys and friends. +++ +++Forwarded: not-needed +++ +++=================================================================== +++--- +++ compiler/rustc_codegen_ssa/Cargo.toml | 4 ---- +++ compiler/rustc_data_structures/Cargo.toml | 10 --------- +++ compiler/rustc_driver_impl/Cargo.toml | 6 ----- +++ compiler/rustc_errors/Cargo.toml | 8 ------- +++ compiler/rustc_session/Cargo.toml | 7 ------ +++ library/backtrace/Cargo.toml | 3 --- +++ library/backtrace/crates/as-if-std/Cargo.toml | 3 --- +++ src/bootstrap/Cargo.toml | 15 ------------- +++ src/tools/cargo/Cargo.toml | 26 ++++------------------ +++ .../cargo/crates/cargo-test-support/Cargo.toml | 3 --- +++ src/tools/cargo/crates/cargo-util/Cargo.toml | 7 ------ +++ src/tools/cargo/crates/home/Cargo.toml | 3 --- +++ .../cargo/credential/cargo-credential/Cargo.toml | 3 --- +++ src/tools/cargo/src/cargo/util/auth/mod.rs | 5 ----- +++ src/tools/compiletest/Cargo.toml | 10 --------- +++ src/tools/rust-analyzer/crates/profile/Cargo.toml | 3 --- +++ .../rust-analyzer/crates/rust-analyzer/Cargo.toml | 3 --- +++ src/tools/rust-analyzer/crates/stdx/Cargo.toml | 4 ---- +++ src/tools/rustc-perf/collector/Cargo.toml | 4 ---- +++ .../compile-benchmarks/cargo-0.60.0/Cargo.toml | 24 -------------------- +++ .../style-servo/components/gfx/Cargo.toml | 4 ---- +++ .../style-servo/components/style/Cargo.toml | 3 --- +++ .../native-tls-0.1.5/Cargo.toml | 4 +--- +++ .../example-compositor/compositor/Cargo.toml | 3 --- +++ .../webrender-2022/webrender/Cargo.toml | 3 --- +++ .../webrender-2022/wrench/Cargo.toml | 4 ---- +++ 26 files changed, 5 insertions(+), 167 deletions(-) +++ +++diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml +++index f0456e6..5d64044 100644 +++--- a/compiler/rustc_codegen_ssa/Cargo.toml ++++++ b/compiler/rustc_codegen_ssa/Cargo.toml +++@@ -57,7 +57,3 @@ libc = "0.2.50" +++ version = "0.36.2" +++ default-features = false +++ features = ["read_core", "elf", "macho", "pe", "xcoff", "unaligned", "archive", "write", "wasm"] +++- +++-[target.'cfg(windows)'.dependencies.windows] +++-version = "0.57.0" +++-features = ["Win32_Globalization"] +++diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml +++index c8ecddb..36486ca 100644 +++--- a/compiler/rustc_data_structures/Cargo.toml ++++++ b/compiler/rustc_data_structures/Cargo.toml +++@@ -31,16 +31,6 @@ tracing = "0.1" +++ [dependencies.parking_lot] +++ version = "0.12" +++ +++-[target.'cfg(windows)'.dependencies.windows] +++-version = "0.57.0" +++-features = [ +++- "Win32_Foundation", +++- "Win32_Storage_FileSystem", +++- "Win32_System_IO", +++- "Win32_System_ProcessStatus", +++- "Win32_System_Threading", +++-] +++- +++ [target.'cfg(unix)'.dependencies] +++ # tidy-alphabetical-start +++ libc = "0.2" +++diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml +++index 2f0fe64..0183ba6 100644 +++--- a/compiler/rustc_driver_impl/Cargo.toml ++++++ b/compiler/rustc_driver_impl/Cargo.toml +++@@ -58,12 +58,6 @@ tracing = { version = "0.1.35" } +++ libc = "0.2" +++ # tidy-alphabetical-end +++ +++-[target.'cfg(windows)'.dependencies.windows] +++-version = "0.57.0" +++-features = [ +++- "Win32_System_Diagnostics_Debug", +++-] +++- +++ [target.'cfg(not(target_family = "wasm"))'.dependencies] +++ # tidy-alphabetical-start +++ ctrlc = "3.4.4" +++diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml +++index 66b9adb..6ce19fb 100644 +++--- a/compiler/rustc_errors/Cargo.toml ++++++ b/compiler/rustc_errors/Cargo.toml +++@@ -29,11 +29,3 @@ termcolor = "1.2.0" +++ termize = "0.1.1" +++ tracing = "0.1" +++ # tidy-alphabetical-end +++- +++-[target.'cfg(windows)'.dependencies.windows] +++-version = "0.57.0" +++-features = [ +++- "Win32_Foundation", +++- "Win32_Security", +++- "Win32_System_Threading", +++-] +++diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml +++index e998369..14ca737 100644 +++--- a/compiler/rustc_session/Cargo.toml ++++++ b/compiler/rustc_session/Cargo.toml +++@@ -29,10 +29,3 @@ tracing = "0.1" +++ # tidy-alphabetical-start +++ libc = "0.2" +++ # tidy-alphabetical-end +++- +++-[target.'cfg(windows)'.dependencies.windows] +++-version = "0.57.0" +++-features = [ +++- "Win32_Foundation", +++- "Win32_System_LibraryLoader", +++-] +++diff --git a/library/backtrace/Cargo.toml b/library/backtrace/Cargo.toml +++index 27df474..5992036 100644 +++--- a/library/backtrace/Cargo.toml ++++++ b/library/backtrace/Cargo.toml +++@@ -38,9 +38,6 @@ cpp_demangle = { default-features = false, version = "0.4.0", optional = true, f +++ "alloc", +++ ] } +++ +++-[target.'cfg(windows)'.dependencies] +++-windows-targets = "0.52.6" +++- +++ [target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies] +++ miniz_oxide = { version = "0.8", default-features = false } +++ ruzstd = { version = "0.7.3", default-features = false, optional = true } +++diff --git a/library/backtrace/crates/as-if-std/Cargo.toml b/library/backtrace/crates/as-if-std/Cargo.toml +++index 092905f..bfb0700 100644 +++--- a/library/backtrace/crates/as-if-std/Cargo.toml ++++++ b/library/backtrace/crates/as-if-std/Cargo.toml +++@@ -27,9 +27,6 @@ default-features = false +++ optional = true +++ features = ['read_core', 'elf', 'macho', 'pe', 'xcoff', 'unaligned', 'archive'] +++ +++-[target.'cfg(windows)'.dependencies] +++-windows-targets = "0.52.6" +++- +++ [features] +++ default = ['backtrace'] +++ backtrace = ['addr2line', 'miniz_oxide', 'object', 'ruzstd'] +++diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml +++index d8775a6..3d16075 100644 +++--- a/src/bootstrap/Cargo.toml ++++++ b/src/bootstrap/Cargo.toml +++@@ -64,21 +64,6 @@ xz2 = "0.1" +++ # Dependencies needed by the build-metrics feature +++ sysinfo = { version = "0.33.0", default-features = false, optional = true, features = ["system"] } +++ +++-[target.'cfg(windows)'.dependencies.junction] +++-version = "1.0.0" +++- +++-[target.'cfg(windows)'.dependencies.windows] +++-version = "0.52" +++-features = [ +++- "Win32_Foundation", +++- "Win32_Security", +++- "Win32_System_Diagnostics_Debug", +++- "Win32_System_JobObjects", +++- "Win32_System_ProcessStatus", +++- "Win32_System_Threading", +++- "Win32_System_Time", +++-] +++- +++ [dev-dependencies] +++ pretty_assertions = "1.4" +++ +++diff --git a/src/tools/cargo/Cargo.toml b/src/tools/cargo/Cargo.toml +++index 9898d05..f18075e 100644 +++--- a/src/tools/cargo/Cargo.toml ++++++ b/src/tools/cargo/Cargo.toml +++@@ -2,7 +2,9 @@ +++ resolver = "2" +++ members = [ +++ "crates/*", +++- "credential/*", ++++ "credential/cargo-credential", ++++ "credential/cargo-credential-1password", ++++ "credential/cargo-credential-libsecret", +++ "benches/benchsuite", +++ "benches/capture", +++ ] +++@@ -29,8 +31,6 @@ bytesize = "1.3" +++ cargo = { path = "" } +++ cargo-credential = { version = "0.4.2", path = "credential/cargo-credential" } +++ cargo-credential-libsecret = { version = "0.4.7", path = "credential/cargo-credential-libsecret" } +++-cargo-credential-macos-keychain = { version = "0.4.7", path = "credential/cargo-credential-macos-keychain" } +++-cargo-credential-wincred = { version = "0.4.7", path = "credential/cargo-credential-wincred" } +++ cargo-platform = { path = "crates/cargo-platform", version = "0.2.0" } +++ cargo-test-macro = { version = "0.4.0", path = "crates/cargo-test-macro" } +++ cargo-test-support = { version = "0.7.0", path = "crates/cargo-test-support" } +++@@ -116,7 +116,6 @@ unicode-xid = "0.2.4" +++ url = "2.5.2" +++ varisat = "0.2.2" +++ walkdir = "2.5.0" +++-windows-sys = "0.59" +++ +++ [workspace.lints.rust] +++ rust_2018_idioms = "warn" # TODO: could this be removed? +++@@ -159,6 +158,7 @@ base64.workspace = true +++ blake3.workspace = true +++ bytesize.workspace = true +++ cargo-credential.workspace = true ++++cargo-credential-libsecret.workspace = true +++ cargo-platform.workspace = true +++ cargo-util-schemas.workspace = true +++ cargo-util.workspace = true +++@@ -229,27 +229,9 @@ libc.workspace = true +++ [target.'cfg(target_os = "linux")'.dependencies] +++ cargo-credential-libsecret.workspace = true +++ +++-[target.'cfg(target_os = "macos")'.dependencies] +++-cargo-credential-macos-keychain.workspace = true +++- +++ [target.'cfg(not(windows))'.dependencies] +++ openssl = { workspace = true, optional = true } +++ +++-[target.'cfg(windows)'.dependencies] +++-cargo-credential-wincred.workspace = true +++- +++-[target.'cfg(windows)'.dependencies.windows-sys] +++-workspace = true +++-features = [ +++- "Win32_Foundation", +++- "Win32_Security", +++- "Win32_Storage_FileSystem", +++- "Win32_System_IO", +++- "Win32_System_Console", +++- "Win32_System_JobObjects", +++- "Win32_System_Threading", +++-] +++- +++ [dev-dependencies] +++ annotate-snippets = { workspace = true, features = ["testing-colors"] } +++ cargo-test-support.workspace = true +++diff --git a/src/tools/cargo/crates/cargo-test-support/Cargo.toml b/src/tools/cargo/crates/cargo-test-support/Cargo.toml +++index 8c23a21..e75abb9 100644 +++--- a/src/tools/cargo/crates/cargo-test-support/Cargo.toml ++++++ b/src/tools/cargo/crates/cargo-test-support/Cargo.toml +++@@ -31,8 +31,5 @@ toml.workspace = true +++ url.workspace = true +++ walkdir.workspace = true +++ +++-[target.'cfg(windows)'.dependencies] +++-windows-sys = { workspace = true, features = ["Win32_Storage_FileSystem"] } +++- +++ [lints] +++ workspace = true +++diff --git a/src/tools/cargo/crates/cargo-util/Cargo.toml b/src/tools/cargo/crates/cargo-util/Cargo.toml +++index cf23406..0db9fc3 100644 +++--- a/src/tools/cargo/crates/cargo-util/Cargo.toml ++++++ b/src/tools/cargo/crates/cargo-util/Cargo.toml +++@@ -21,15 +21,8 @@ tempfile.workspace = true +++ tracing.workspace = true +++ walkdir.workspace = true +++ +++-[target.'cfg(target_os = "macos")'.dependencies] +++-core-foundation.workspace = true +++- +++ [target.'cfg(unix)'.dependencies] +++ libc.workspace = true +++ +++-[target.'cfg(windows)'.dependencies] +++-miow.workspace = true +++-windows-sys = { workspace = true, features = ["Win32_Storage_FileSystem", "Win32_Foundation", "Win32_System_Console"] } +++- +++ [lints] +++ workspace = true +++diff --git a/src/tools/cargo/crates/home/Cargo.toml b/src/tools/cargo/crates/home/Cargo.toml +++index 91742e5..0054cad 100644 +++--- a/src/tools/cargo/crates/home/Cargo.toml ++++++ b/src/tools/cargo/crates/home/Cargo.toml +++@@ -17,8 +17,5 @@ homepage.workspace = true +++ repository.workspace = true +++ description = "Shared definitions of home directories." +++ +++-[target.'cfg(windows)'.dependencies] +++-windows-sys = { workspace = true, features = ["Win32_Foundation", "Win32_UI_Shell", "Win32_System_Com"] } +++- +++ [lints] +++ workspace = true +++diff --git a/src/tools/cargo/credential/cargo-credential/Cargo.toml b/src/tools/cargo/credential/cargo-credential/Cargo.toml +++index 713fa41..5017448 100644 +++--- a/src/tools/cargo/credential/cargo-credential/Cargo.toml ++++++ b/src/tools/cargo/credential/cargo-credential/Cargo.toml +++@@ -18,9 +18,6 @@ time.workspace = true +++ [target.'cfg(unix)'.dependencies] +++ libc.workspace = true +++ +++-[target.'cfg(windows)'.dependencies] +++-windows-sys = { workspace = true, features = ["Win32_System_Console", "Win32_Foundation"] } +++- +++ [dev-dependencies] +++ snapbox = { workspace = true, features = ["examples"] } +++ +++diff --git a/src/tools/cargo/src/cargo/util/auth/mod.rs b/src/tools/cargo/src/cargo/util/auth/mod.rs +++index 2576b4b..9ab86e7 100644 +++--- a/src/tools/cargo/src/cargo/util/auth/mod.rs ++++++ b/src/tools/cargo/src/cargo/util/auth/mod.rs +++@@ -529,11 +529,6 @@ fn credential_action( +++ } +++ "cargo:paseto" => bail!("cargo:paseto requires -Zasymmetric-token"), +++ "cargo:token-from-stdout" => Box::new(BasicProcessCredential {}), +++- #[cfg(windows)] +++- "cargo:wincred" => Box::new(cargo_credential_wincred::WindowsCredential {}), +++- #[cfg(target_os = "macos")] +++- "cargo:macos-keychain" => Box::new(cargo_credential_macos_keychain::MacKeychain {}), +++- #[cfg(target_os = "linux")] +++ "cargo:libsecret" => Box::new(cargo_credential_libsecret::LibSecretCredential {}), +++ name if BUILT_IN_PROVIDERS.contains(&name) => { +++ Box::new(cargo_credential::UnsupportedCredential {}) +++diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml +++index 16cc1d2..7303972 100644 +++--- a/src/tools/compiletest/Cargo.toml ++++++ b/src/tools/compiletest/Cargo.toml +++@@ -29,13 +29,3 @@ home = "0.5.5" +++ +++ [target.'cfg(unix)'.dependencies] +++ libc = "0.2" +++- +++-[target.'cfg(windows)'.dependencies] +++-miow = "0.6" +++- +++-[target.'cfg(windows)'.dependencies.windows] +++-version = "0.57.0" +++-features = [ +++- "Win32_Foundation", +++- "Win32_System_Diagnostics_Debug", +++-] +++diff --git a/src/tools/rust-analyzer/crates/profile/Cargo.toml b/src/tools/rust-analyzer/crates/profile/Cargo.toml +++index f823aa1..c82566f 100644 +++--- a/src/tools/rust-analyzer/crates/profile/Cargo.toml ++++++ b/src/tools/rust-analyzer/crates/profile/Cargo.toml +++@@ -19,9 +19,6 @@ libc.workspace = true +++ [target.'cfg(target_os = "linux")'.dependencies] +++ perf-event = "=0.4.7" +++ +++-[target.'cfg(windows)'.dependencies] +++-windows-sys = { version = "0.52", features = ["Win32_System_Threading", "Win32_System_ProcessStatus"] } +++- +++ [features] +++ cpu_profiler = [] +++ +++diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++index 70a792b..7a1ecc5 100644 +++--- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml ++++++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++@@ -74,9 +74,6 @@ vfs-notify.workspace = true +++ vfs.workspace = true +++ paths.workspace = true +++ +++-[target.'cfg(windows)'.dependencies] +++-windows-sys = { version = "0.52", features = ["Win32_System_Threading"] } +++- +++ [dev-dependencies] +++ expect-test = "1.4.0" +++ xshell.workspace = true +++diff --git a/src/tools/rust-analyzer/crates/stdx/Cargo.toml b/src/tools/rust-analyzer/crates/stdx/Cargo.toml +++index bf0d6df..bfd04c9 100644 +++--- a/src/tools/rust-analyzer/crates/stdx/Cargo.toml ++++++ b/src/tools/rust-analyzer/crates/stdx/Cargo.toml +++@@ -21,10 +21,6 @@ crossbeam-channel.workspace = true +++ itertools.workspace = true +++ # Think twice before adding anything here +++ +++-[target.'cfg(windows)'.dependencies] +++-miow = "0.6.0" +++-windows-sys = { version = "0.52", features = ["Win32_Foundation"] } +++- +++ [features] +++ # Uncomment to enable for the whole crate graph +++ # default = [ "backtrace" ] +++diff --git a/src/tools/rustc-perf/collector/Cargo.toml b/src/tools/rustc-perf/collector/Cargo.toml +++index 9146a65..ffba6fa 100644 +++--- a/src/tools/rustc-perf/collector/Cargo.toml ++++++ b/src/tools/rustc-perf/collector/Cargo.toml +++@@ -45,10 +45,6 @@ analyzeme = "12.0.0" +++ +++ benchlib = { path = "benchlib" } +++ +++-[target.'cfg(windows)'.dependencies] +++-miow = "0.3" +++-windows-sys = { version = "0.45.0", features = ["Win32_Foundation"] } +++- +++ [features] +++ # Enable more precise Cachegrind profiles for runtime benchmarks. +++ # Requires a recent Valgrind to be installed. +++diff --git a/src/tools/rustc-perf/collector/compile-benchmarks/cargo-0.60.0/Cargo.toml b/src/tools/rustc-perf/collector/compile-benchmarks/cargo-0.60.0/Cargo.toml +++index 12ee1ee..a89f82f 100644 +++--- a/src/tools/rustc-perf/collector/compile-benchmarks/cargo-0.60.0/Cargo.toml ++++++ b/src/tools/rustc-perf/collector/compile-benchmarks/cargo-0.60.0/Cargo.toml +++@@ -209,28 +209,4 @@ deny-warnings = [] +++ pretty-env-logger = ["pretty_env_logger"] +++ vendored-openssl = ["openssl/vendored"] +++ +++-[target."cfg(windows)".dependencies.fwdansi] +++-version = "1.1.0" +++- +++-[target."cfg(windows)".dependencies.winapi] +++-version = "0.3" +++-features = [ +++- "basetsd", +++- "handleapi", +++- "jobapi", +++- "jobapi2", +++- "memoryapi", +++- "minwindef", +++- "ntdef", +++- "ntstatus", +++- "processenv", +++- "processthreadsapi", +++- "psapi", +++- "synchapi", +++- "winerror", +++- "winbase", +++- "wincon", +++- "winnt", +++-] +++- +++ [workspace] +++diff --git a/src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/gfx/Cargo.toml b/src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/gfx/Cargo.toml +++index 3d7aea1..57feefe 100644 +++--- a/src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/gfx/Cargo.toml ++++++ b/src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/gfx/Cargo.toml +++@@ -59,7 +59,3 @@ xml5ever = {version = "0.10"} +++ +++ [target.'cfg(any(target_feature = "sse2", target_feature = "neon"))'.dependencies] +++ simd = "0.2.0" +++- +++-[target.'cfg(target_os = "windows")'.dependencies] +++-dwrote = "0.4" +++-truetype = "0.26" +++diff --git a/src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/style/Cargo.toml b/src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/style/Cargo.toml +++index 23130d0..5f33889 100644 +++--- a/src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/style/Cargo.toml ++++++ b/src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/style/Cargo.toml +++@@ -77,9 +77,6 @@ time = "0.1" +++ unicode-bidi = "0.3" +++ unicode-segmentation = "1.0" +++ +++-[target.'cfg(windows)'.dependencies] +++-kernel32-sys = "0.2" +++- +++ [build-dependencies] +++ lazy_static = "0.2" +++ log = "0.3" +++diff --git a/src/tools/rustc-perf/collector/compile-benchmarks/tokio-webpush-simple/native-tls-0.1.5/Cargo.toml b/src/tools/rustc-perf/collector/compile-benchmarks/tokio-webpush-simple/native-tls-0.1.5/Cargo.toml +++index 38bd630e..6abd17c 100644 +++--- a/src/tools/rustc-perf/collector/compile-benchmarks/tokio-webpush-simple/native-tls-0.1.5/Cargo.toml ++++++ b/src/tools/rustc-perf/collector/compile-benchmarks/tokio-webpush-simple/native-tls-0.1.5/Cargo.toml +++@@ -33,7 +33,5 @@ version = "0.1.15" +++ +++ [target."cfg(any(target_os = \"macos\", target_os = \"ios\"))".dependencies.tempdir] +++ version = "0.3" +++-[target."cfg(target_os = \"windows\")".dependencies.schannel] +++-version = "0.1.7" +++ +++-[workspace] +++\ No newline at end of file ++++[workspace] +++diff --git a/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/example-compositor/compositor/Cargo.toml b/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/example-compositor/compositor/Cargo.toml +++index 4202332..2d35787 100644 +++--- a/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/example-compositor/compositor/Cargo.toml ++++++ b/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/example-compositor/compositor/Cargo.toml +++@@ -9,8 +9,5 @@ license = "MPL-2.0" +++ webrender = { path = "../../webrender" } +++ gleam = "0.13.1" +++ +++-[target.'cfg(windows)'.dependencies] +++-compositor-windows = { path = "../compositor-windows" } +++- +++ [target.'cfg(target_os = "linux")'.dependencies] +++ compositor-wayland = { path = "../compositor-wayland" } +++diff --git a/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/webrender/Cargo.toml b/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/webrender/Cargo.toml +++index ee727d4..ddc3c14 100644 +++--- a/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/webrender/Cargo.toml ++++++ b/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/webrender/Cargo.toml +++@@ -61,9 +61,6 @@ rand = "0.4" +++ freetype = { version = "0.7", default-features = false } +++ libc = "0.2" +++ +++-[target.'cfg(target_os = "windows")'.dependencies] +++-dwrote = "0.11" +++- +++ [target.'cfg(target_os = "macos")'.dependencies] +++ core-foundation = "0.9.2" +++ core-graphics = "0.22.3" +++diff --git a/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/wrench/Cargo.toml b/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/wrench/Cargo.toml +++index 04101b9..9b6e1e5 100644 +++--- a/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/wrench/Cargo.toml ++++++ b/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/wrench/Cargo.toml +++@@ -42,10 +42,6 @@ default = [ "env_logger" ] +++ headless = [ "osmesa-sys", "osmesa-src" ] +++ software = [ "swgl" ] +++ +++-[target.'cfg(target_os = "windows")'.dependencies] +++-dwrote = "0.11" +++-mozangle = { version = "0.3.2", features = ["egl"] } +++- +++ [target.'cfg(all(unix, not(target_os = "android")))'.dependencies] +++ font-loader = "0.11" +++ diff --cc debian/patches/prune/d-0021-vendor-remove-windows-dependencies.patch index 0000000000,0000000000,0000000000..7e42112e1a new file mode 100644 --- /dev/null +++ b/debian/patches/prune/d-0021-vendor-remove-windows-dependencies.patch @@@@ -1,0 -1,0 -1,0 +1,1275 @@@@ +++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= +++Date: Wed, 6 Sep 2023 13:23:24 -0600 +++Subject: d-0021-vendor-remove-windows-dependencies +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++use something like +++ +++ find vendor -iname Cargo.toml -exec grep -H -n -e 'schannel' -e 'windows-sys' -e 'winapi' -e 'ntapi' -e 'wincon' -e 'winreg' -e 'windows' -e 'winsplit' {} \; +++ +++to find dependencies on windows targets in vendored crates. you will likely +++need to remove some hunks from this patch after pruning dependencies, since +++hopefully a few of the crates patched during early rebasing are eliminated. +++ +++windows-bindgen and windows-metadata should not be removed, they are needed for +++the build and don't pull in windows-sys and friends. +++ +++Forwarded: not-needed +++ +++Signed-off-by: Fabian Grünbichler +++--- +++ vendor/android-tzdata-0.1.1/Cargo.toml | 1 + +++ vendor/anstream-0.6.18/Cargo.toml | 6 ---- +++ vendor/anstyle-query-1.1.2/Cargo.toml | 7 ---- +++ vendor/backtrace-0.3.71/Cargo.toml | 14 -------- +++ vendor/backtrace-0.3.73/Cargo.toml | 16 --------- +++ vendor/chrono-0.4.39/Cargo.toml | 9 ----- +++ vendor/colored-2.2.0/Cargo.toml | 7 ---- +++ vendor/console-0.15.10/Cargo.toml | 12 ------- +++ vendor/ctrlc-3.4.5/Cargo.toml | 18 ---------- +++ vendor/curl-0.4.47/Cargo.toml | 11 ------ +++ vendor/curl-sys-0.4.78+curl-8.11.0/Cargo.toml | 4 --- +++ vendor/dbus-0.9.7/Cargo.toml | 4 --- +++ vendor/dirs-sys-0.4.1/Cargo.toml | 9 ----- +++ vendor/dirs-sys-next-0.1.2/Cargo.toml | 3 -- +++ vendor/dlmalloc-0.2.7/Cargo.toml | 9 ----- +++ vendor/env_logger-0.11.6/Cargo.toml | 2 +- +++ vendor/errno-0.3.10/Cargo.toml | 7 ---- +++ vendor/fd-lock-4.0.2/Cargo.toml | 8 ----- +++ vendor/filetime-0.2.25/Cargo.toml | 7 ---- +++ vendor/gix-discover-0.37.0/Cargo.toml | 6 ---- +++ vendor/gix-path-0.10.13/Cargo.toml | 10 ------ +++ vendor/gix-sec-0.10.10/Cargo.toml | 10 ------ +++ vendor/home-0.5.11/Cargo.toml | 8 ----- +++ vendor/iana-time-zone-0.1.61/Cargo.toml | 3 -- +++ vendor/ignore-0.4.23/Cargo.toml | 3 -- +++ vendor/is-terminal-0.4.12/Cargo.toml | 11 ------ +++ vendor/is_executable-1.0.3/Cargo.toml | 4 --- +++ vendor/jiff-0.1.13/Cargo.toml | 10 ------ +++ vendor/libloading-0.8.6/Cargo.toml | 7 ---- +++ vendor/libssh2-sys-0.3.0/Cargo.toml | 8 ----- +++ vendor/mio-0.8.11/Cargo.toml | 12 ------- +++ vendor/notify-6.1.1/Cargo.toml | 11 ------ +++ vendor/nu-ansi-term-0.46.0/Cargo.toml | 10 ------ +++ vendor/nu-ansi-term-0.50.1/Cargo.toml | 10 ------ +++ vendor/onig-6.4.0/Cargo.toml | 3 -- +++ vendor/opener-0.5.2/Cargo.toml | 4 --- +++ vendor/opener-0.7.2/Cargo.toml | 12 ------- +++ vendor/os_info-3.8.2/Cargo.toml | 12 ------- +++ vendor/parking_lot_core-0.9.10/Cargo.toml | 3 -- +++ vendor/portable-atomic-1.10.0/Cargo.toml | 7 ---- +++ vendor/process-wrap-8.0.2/Cargo.toml | 11 ------ +++ vendor/rustix-0.38.42/Cargo.toml | 9 ----- +++ vendor/same-file-1.0.6/Cargo.toml | 2 -- +++ vendor/snapbox-0.6.20/Cargo.toml | 6 ---- +++ vendor/socket2-0.5.8/Cargo.toml | 10 ------ +++ vendor/stacker-0.1.17/Cargo.toml | 8 ----- +++ vendor/sysinfo-0.31.4/Cargo.toml | 47 -------------------------- +++ vendor/sysinfo-0.33.0/Cargo.toml | 48 --------------------------- +++ vendor/tempfile-3.14.0/Cargo.toml | 7 ---- +++ vendor/term-0.7.0/Cargo.toml | 6 ---- +++ vendor/termcolor-1.4.1/Cargo.toml | 3 -- +++ vendor/terminal_size-0.4.1/Cargo.toml | 6 ---- +++ vendor/termize-0.1.1/Cargo.toml | 3 -- +++ vendor/tokio-1.42.0/Cargo.toml | 21 ------------ +++ vendor/uuid-1.11.0/Cargo.toml | 1 - +++ vendor/walkdir-2.5.0/Cargo.toml | 3 -- +++ vendor/wasm-component-ld-0.5.11/Cargo.toml | 7 ---- +++ vendor/yansi-term-0.1.2/Cargo.toml | 3 -- +++ 58 files changed, 2 insertions(+), 517 deletions(-) +++ +++diff --git a/vendor/android-tzdata-0.1.1/Cargo.toml b/vendor/android-tzdata-0.1.1/Cargo.toml +++index 805128a..0682717 100644 +++--- a/vendor/android-tzdata-0.1.1/Cargo.toml ++++++ b/vendor/android-tzdata-0.1.1/Cargo.toml +++@@ -32,3 +32,4 @@ repository = "https://github.com/RumovZ/android-tzdata" +++ +++ [dev-dependencies.zip] +++ version = "0.6.4" ++++repository = "https://github.com/rust-cli/concolor" +++diff --git a/vendor/anstream-0.6.18/Cargo.toml b/vendor/anstream-0.6.18/Cargo.toml +++index a0b88d7..2a501f2 100644 +++--- a/vendor/anstream-0.6.18/Cargo.toml ++++++ b/vendor/anstream-0.6.18/Cargo.toml +++@@ -152,14 +152,8 @@ version = "0.2.0" +++ auto = ["dep:anstyle-query"] +++ default = [ +++ "auto", +++- "wincon", +++ ] +++ test = [] +++-wincon = ["dep:anstyle-wincon"] +++- +++-[target."cfg(windows)".dependencies.anstyle-wincon] +++-version = "3.0.5" +++-optional = true +++ +++ [lints.clippy] +++ bool_assert_comparison = "allow" +++diff --git a/vendor/anstyle-query-1.1.2/Cargo.toml b/vendor/anstyle-query-1.1.2/Cargo.toml +++index 8073b87..1431cec 100644 +++--- a/vendor/anstyle-query-1.1.2/Cargo.toml ++++++ b/vendor/anstyle-query-1.1.2/Cargo.toml +++@@ -92,13 +92,6 @@ path = "src/lib.rs" +++ name = "query" +++ path = "examples/query.rs" +++ +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.59.0" +++-features = [ +++- "Win32_System_Console", +++- "Win32_Foundation", +++-] +++- +++ [lints.clippy] +++ bool_assert_comparison = "allow" +++ branches_sharing_code = "allow" +++diff --git a/vendor/backtrace-0.3.71/Cargo.toml b/vendor/backtrace-0.3.71/Cargo.toml +++index 6ac3a6d..0749f23 100644 +++--- a/vendor/backtrace-0.3.71/Cargo.toml ++++++ b/vendor/backtrace-0.3.71/Cargo.toml +++@@ -105,16 +105,6 @@ serialize-serde = ["serde"] +++ std = [] +++ unix-backtrace = [] +++ verify-winapi = [ +++- "winapi/dbghelp", +++- "winapi/handleapi", +++- "winapi/libloaderapi", +++- "winapi/memoryapi", +++- "winapi/minwindef", +++- "winapi/processthreadsapi", +++- "winapi/synchapi", +++- "winapi/tlhelp32", +++- "winapi/winbase", +++- "winapi/winnt", +++ ] +++ +++ [target."cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))".dependencies.addr2line] +++@@ -141,7 +131,3 @@ features = [ +++ "archive", +++ ] +++ default-features = false +++- +++-[target."cfg(windows)".dependencies.winapi] +++-version = "0.3.9" +++-optional = true +++diff --git a/vendor/backtrace-0.3.73/Cargo.toml b/vendor/backtrace-0.3.73/Cargo.toml +++index 32ee718..78e4bee 100644 +++--- a/vendor/backtrace-0.3.73/Cargo.toml ++++++ b/vendor/backtrace-0.3.73/Cargo.toml +++@@ -121,18 +121,6 @@ serialize-serde = ["serde"] +++ std = [] +++ unix-backtrace = [] +++ verify-winapi = [ +++- "winapi/dbghelp", +++- "winapi/handleapi", +++- "winapi/libloaderapi", +++- "winapi/memoryapi", +++- "winapi/minwindef", +++- "winapi/processthreadsapi", +++- "winapi/synchapi", +++- "winapi/tlhelp32", +++- "winapi/winbase", +++- "winapi/winnt", +++- "winapi/winnls", +++- "winapi/stringapiset", +++ ] +++ +++ [target."cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))".dependencies.addr2line] +++@@ -160,9 +148,5 @@ features = [ +++ ] +++ default-features = false +++ +++-[target."cfg(windows)".dependencies.winapi] +++-version = "0.3.9" +++-optional = true +++- +++ [lints.rust] +++ unexpected_cfgs = "allow" +++diff --git a/vendor/chrono-0.4.39/Cargo.toml b/vendor/chrono-0.4.39/Cargo.toml +++index 6ccd2ac..70e45ba 100644 +++--- a/vendor/chrono-0.4.39/Cargo.toml ++++++ b/vendor/chrono-0.4.39/Cargo.toml +++@@ -107,7 +107,6 @@ version = "1" +++ __internal_bench = [] +++ alloc = [] +++ clock = [ +++- "winapi", +++ "iana-time-zone", +++ "android-tzdata", +++ "now", +++@@ -144,7 +143,6 @@ wasmbind = [ +++ "wasm-bindgen", +++ "js-sys", +++ ] +++-winapi = ["windows-targets"] +++ +++ [target.'cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))'.dependencies.js-sys] +++ version = "0.3" +++@@ -165,10 +163,3 @@ optional = true +++ version = "0.1.45" +++ features = ["fallback"] +++ optional = true +++- +++-[target."cfg(windows)".dependencies.windows-targets] +++-version = "0.52" +++-optional = true +++- +++-[target."cfg(windows)".dev-dependencies.windows-bindgen] +++-version = "0.58" +++diff --git a/vendor/colored-2.2.0/Cargo.toml b/vendor/colored-2.2.0/Cargo.toml +++index 500eb97..2e9ce71 100644 +++--- a/vendor/colored-2.2.0/Cargo.toml ++++++ b/vendor/colored-2.2.0/Cargo.toml +++@@ -80,10 +80,3 @@ version = "1" +++ +++ [features] +++ no-color = [] +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = ">=0.48,<=0.59" +++-features = [ +++- "Win32_Foundation", +++- "Win32_System_Console", +++-] +++diff --git a/vendor/console-0.15.10/Cargo.toml b/vendor/console-0.15.10/Cargo.toml +++index 0c96b8c..93a632f 100644 +++--- a/vendor/console-0.15.10/Cargo.toml ++++++ b/vendor/console-0.15.10/Cargo.toml +++@@ -92,15 +92,3 @@ default = [ +++ "ansi-parsing", +++ ] +++ windows-console-colors = ["ansi-parsing"] +++- +++-[target."cfg(windows)".dependencies.encode_unicode] +++-version = "1" +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.59" +++-features = [ +++- "Win32_Foundation", +++- "Win32_System_Console", +++- "Win32_Storage_FileSystem", +++- "Win32_UI_Input_KeyboardAndMouse", +++-] +++diff --git a/vendor/ctrlc-3.4.5/Cargo.toml b/vendor/ctrlc-3.4.5/Cargo.toml +++index c32a86c..3c1f918 100644 +++--- a/vendor/ctrlc-3.4.5/Cargo.toml ++++++ b/vendor/ctrlc-3.4.5/Cargo.toml +++@@ -56,23 +56,5 @@ features = [ +++ ] +++ default-features = false +++ +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.59" +++-features = [ +++- "Win32_Foundation", +++- "Win32_System_Threading", +++- "Win32_Security", +++- "Win32_System_Console", +++-] +++- +++-[target."cfg(windows)".dev-dependencies.windows-sys] +++-version = "0.59" +++-features = [ +++- "Win32_Storage_FileSystem", +++- "Win32_Foundation", +++- "Win32_System_IO", +++- "Win32_System_Console", +++-] +++- +++ [badges.maintenance] +++ status = "passively-maintained" +++diff --git a/vendor/curl-0.4.47/Cargo.toml b/vendor/curl-0.4.47/Cargo.toml +++index 580f431..7ac8e91 100644 +++--- a/vendor/curl-0.4.47/Cargo.toml ++++++ b/vendor/curl-0.4.47/Cargo.toml +++@@ -144,14 +144,3 @@ optional = true +++ [target.'cfg(all(unix, not(target_os = "macos")))'.dependencies.openssl-sys] +++ version = "0.9.64" +++ optional = true +++- +++-[target.'cfg(target_env = "msvc")'.dependencies.schannel] +++-version = "0.1.13" +++- +++-[target.'cfg(target_env = "msvc")'.dependencies.windows-sys] +++-version = "0.52" +++-features = [ +++- "Win32_Foundation", +++- "Win32_System_LibraryLoader", +++- "Win32_Security_Cryptography", +++-] +++diff --git a/vendor/curl-sys-0.4.78+curl-8.11.0/Cargo.toml b/vendor/curl-sys-0.4.78+curl-8.11.0/Cargo.toml +++index f78fab8..261659e 100644 +++--- a/vendor/curl-sys-0.4.78+curl-8.11.0/Cargo.toml ++++++ b/vendor/curl-sys-0.4.78+curl-8.11.0/Cargo.toml +++@@ -84,7 +84,3 @@ optional = true +++ +++ [target.'cfg(target_env = "msvc")'.build-dependencies.vcpkg] +++ version = "0.2" +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.52" +++-features = ["Win32_Networking_WinSock"] +++diff --git a/vendor/dbus-0.9.7/Cargo.toml b/vendor/dbus-0.9.7/Cargo.toml +++index d9f6d84..e04d90b 100644 +++--- a/vendor/dbus-0.9.7/Cargo.toml ++++++ b/vendor/dbus-0.9.7/Cargo.toml +++@@ -63,9 +63,5 @@ no-string-validation = [] +++ stdfd = [] +++ vendored = ["libdbus-sys/vendored"] +++ +++-[target."cfg(windows)".dependencies.winapi] +++-version = "0.3.0" +++-features = ["winsock2"] +++- +++ [badges.maintenance] +++ status = "actively-developed" +++diff --git a/vendor/dirs-sys-0.4.1/Cargo.toml b/vendor/dirs-sys-0.4.1/Cargo.toml +++index 4a992ae..86aec87 100644 +++--- a/vendor/dirs-sys-0.4.1/Cargo.toml ++++++ b/vendor/dirs-sys-0.4.1/Cargo.toml +++@@ -27,12 +27,3 @@ default-features = false +++ +++ [target."cfg(unix)".dependencies.libc] +++ version = "0.2" +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.48.0" +++-features = [ +++- "Win32_UI_Shell", +++- "Win32_Foundation", +++- "Win32_Globalization", +++- "Win32_System_Com", +++-] +++diff --git a/vendor/dirs-sys-next-0.1.2/Cargo.toml b/vendor/dirs-sys-next-0.1.2/Cargo.toml +++index e9d8d0c..acb2eb7 100644 +++--- a/vendor/dirs-sys-next-0.1.2/Cargo.toml ++++++ b/vendor/dirs-sys-next-0.1.2/Cargo.toml +++@@ -25,8 +25,5 @@ version = "0.4.0" +++ default-features = false +++ [target."cfg(unix)".dependencies.libc] +++ version = "0.2" +++-[target."cfg(windows)".dependencies.winapi] +++-version = "0.3" +++-features = ["knownfolders", "objbase", "shlobj", "winbase", "winerror"] +++ [badges.maintenance] +++ status = "as-is" +++diff --git a/vendor/dlmalloc-0.2.7/Cargo.toml b/vendor/dlmalloc-0.2.7/Cargo.toml +++index 8b4957e..a1aa2a1 100644 +++--- a/vendor/dlmalloc-0.2.7/Cargo.toml ++++++ b/vendor/dlmalloc-0.2.7/Cargo.toml +++@@ -77,12 +77,3 @@ rustc-dep-of-std = [ +++ [target.'cfg(all(unix, not(target_arch = "wasm32")))'.dependencies.libc] +++ version = "0.2" +++ default-features = false +++- +++-[target.'cfg(target_os = "windows")'.dependencies.windows-sys] +++-version = ">=0.52.0, <=0.59.*" +++-features = [ +++- "Win32_Foundation", +++- "Win32_System_Memory", +++- "Win32_System_Threading", +++- "Win32_System_SystemInformation", +++-] +++diff --git a/vendor/env_logger-0.11.6/Cargo.toml b/vendor/env_logger-0.11.6/Cargo.toml +++index e370a04..dce8b19 100644 +++--- a/vendor/env_logger-0.11.6/Cargo.toml ++++++ b/vendor/env_logger-0.11.6/Cargo.toml +++@@ -160,7 +160,7 @@ harness = false +++ +++ [dependencies.anstream] +++ version = "0.6.11" +++-features = ["wincon"] ++++features = [] +++ optional = true +++ default-features = false +++ +++diff --git a/vendor/errno-0.3.10/Cargo.toml b/vendor/errno-0.3.10/Cargo.toml +++index ad290a0..96d0da5 100644 +++--- a/vendor/errno-0.3.10/Cargo.toml ++++++ b/vendor/errno-0.3.10/Cargo.toml +++@@ -50,10 +50,3 @@ default-features = false +++ [target."cfg(unix)".dependencies.libc] +++ version = "0.2" +++ default-features = false +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = ">=0.52, <=0.59" +++-features = [ +++- "Win32_Foundation", +++- "Win32_System_Diagnostics_Debug", +++-] +++diff --git a/vendor/fd-lock-4.0.2/Cargo.toml b/vendor/fd-lock-4.0.2/Cargo.toml +++index 88826bc..fbf815d 100644 +++--- a/vendor/fd-lock-4.0.2/Cargo.toml ++++++ b/vendor/fd-lock-4.0.2/Cargo.toml +++@@ -43,11 +43,3 @@ version = "3.0.8" +++ [target."cfg(unix)".dependencies.rustix] +++ version = "0.38.0" +++ features = ["fs"] +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.52.0" +++-features = [ +++- "Win32_Foundation", +++- "Win32_Storage_FileSystem", +++- "Win32_System_IO", +++-] +++diff --git a/vendor/filetime-0.2.25/Cargo.toml b/vendor/filetime-0.2.25/Cargo.toml +++index d621d2c..2ea7805 100644 +++--- a/vendor/filetime-0.2.25/Cargo.toml ++++++ b/vendor/filetime-0.2.25/Cargo.toml +++@@ -47,10 +47,3 @@ version = "0.1.0" +++ +++ [target."cfg(unix)".dependencies.libc] +++ version = "0.2.27" +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.59.0" +++-features = [ +++- "Win32_Foundation", +++- "Win32_Storage_FileSystem", +++-] +++diff --git a/vendor/gix-discover-0.37.0/Cargo.toml b/vendor/gix-discover-0.37.0/Cargo.toml +++index 0fc281d..378120c 100644 +++--- a/vendor/gix-discover-0.37.0/Cargo.toml ++++++ b/vendor/gix-discover-0.37.0/Cargo.toml +++@@ -70,12 +70,6 @@ default-features = false +++ [target."cfg(any(unix, windows))".dev-dependencies.tempfile] +++ version = "3.2.0" +++ +++-[target.'cfg(target_os = "macos")'.dev-dependencies.defer] +++-version = "0.2.1" +++- +++-[target."cfg(windows)".dependencies.dunce] +++-version = "1.0.3" +++- +++ [lints.clippy] +++ bool_to_int_with_if = "allow" +++ borrow_as_ptr = "allow" +++diff --git a/vendor/gix-path-0.10.13/Cargo.toml b/vendor/gix-path-0.10.13/Cargo.toml +++index e849a4b..19eb266 100644 +++--- a/vendor/gix-path-0.10.13/Cargo.toml ++++++ b/vendor/gix-path-0.10.13/Cargo.toml +++@@ -55,16 +55,6 @@ default-features = false +++ [target.'cfg(not(target_family = "wasm"))'.dependencies.home] +++ version = "0.5.5" +++ +++-[target."cfg(windows)".dev-dependencies.known-folders] +++-version = "1.1.0" +++- +++-[target."cfg(windows)".dev-dependencies.windows] +++-version = "0.58.0" +++-features = ["Win32_System_Threading"] +++- +++-[target."cfg(windows)".dev-dependencies.winreg] +++-version = "0.52.0" +++- +++ [lints.clippy] +++ bool_to_int_with_if = "allow" +++ borrow_as_ptr = "allow" +++diff --git a/vendor/gix-sec-0.10.10/Cargo.toml b/vendor/gix-sec-0.10.10/Cargo.toml +++index 04a73e0..f299b05 100644 +++--- a/vendor/gix-sec-0.10.10/Cargo.toml ++++++ b/vendor/gix-sec-0.10.10/Cargo.toml +++@@ -69,16 +69,6 @@ version = "0.2.123" +++ [target."cfg(windows)".dependencies.gix-path] +++ version = "^0.10.13" +++ +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.52.0" +++-features = [ +++- "Win32_Foundation", +++- "Win32_Security_Authorization", +++- "Win32_Storage_FileSystem", +++- "Win32_System_Memory", +++- "Win32_System_Threading", +++-] +++- +++ [lints.clippy] +++ bool_to_int_with_if = "allow" +++ borrow_as_ptr = "allow" +++diff --git a/vendor/home-0.5.11/Cargo.toml b/vendor/home-0.5.11/Cargo.toml +++index dec1b26..6c857fc 100644 +++--- a/vendor/home-0.5.11/Cargo.toml ++++++ b/vendor/home-0.5.11/Cargo.toml +++@@ -39,14 +39,6 @@ repository = "https://github.com/rust-lang/cargo" +++ name = "home" +++ path = "src/lib.rs" +++ +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.59" +++-features = [ +++- "Win32_Foundation", +++- "Win32_UI_Shell", +++- "Win32_System_Com", +++-] +++- +++ [lints.clippy] +++ dbg_macro = "warn" +++ disallowed_methods = "warn" +++diff --git a/vendor/iana-time-zone-0.1.61/Cargo.toml b/vendor/iana-time-zone-0.1.61/Cargo.toml +++index 0181732..5aa5d04 100644 +++--- a/vendor/iana-time-zone-0.1.61/Cargo.toml ++++++ b/vendor/iana-time-zone-0.1.61/Cargo.toml +++@@ -69,6 +69,3 @@ version = "0.1.5" +++ +++ [target.'cfg(target_os = "haiku")'.dependencies.iana-time-zone-haiku] +++ version = "0.1.1" +++- +++-[target.'cfg(target_os = "windows")'.dependencies.windows-core] +++-version = ">=0.50, <=0.52" +++diff --git a/vendor/ignore-0.4.23/Cargo.toml b/vendor/ignore-0.4.23/Cargo.toml +++index 15384fe..74b3581 100644 +++--- a/vendor/ignore-0.4.23/Cargo.toml ++++++ b/vendor/ignore-0.4.23/Cargo.toml +++@@ -90,6 +90,3 @@ version = "0.5.8" +++ +++ [features] +++ simd-accel = [] +++- +++-[target."cfg(windows)".dependencies.winapi-util] +++-version = "0.1.2" +++diff --git a/vendor/is-terminal-0.4.12/Cargo.toml b/vendor/is-terminal-0.4.12/Cargo.toml +++index 98a8829..01ce09a 100644 +++--- a/vendor/is-terminal-0.4.12/Cargo.toml ++++++ b/vendor/is-terminal-0.4.12/Cargo.toml +++@@ -57,14 +57,3 @@ features = ["stdio"] +++ +++ [target."cfg(target_os = \"hermit\")".dependencies.hermit-abi] +++ version = "0.3.0" +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.52.0" +++-features = [ +++- "Win32_Foundation", +++- "Win32_Storage_FileSystem", +++- "Win32_System_Console", +++-] +++- +++-[target."cfg(windows)".dev-dependencies.tempfile] +++-version = "3" +++diff --git a/vendor/is_executable-1.0.3/Cargo.toml b/vendor/is_executable-1.0.3/Cargo.toml +++index 41f2f56..32747ea 100644 +++--- a/vendor/is_executable-1.0.3/Cargo.toml ++++++ b/vendor/is_executable-1.0.3/Cargo.toml +++@@ -43,9 +43,5 @@ path = "tests/tests.rs" +++ [dev-dependencies.diff] +++ version = "0.1.10" +++ +++-[target.'cfg(target_os = "windows")'.dependencies.winapi] +++-version = "0.3" +++-features = ["winbase"] +++- +++ [badges.travis-ci] +++ repository = "fitzgen/is_executable" +++diff --git a/vendor/jiff-0.1.13/Cargo.toml b/vendor/jiff-0.1.13/Cargo.toml +++index 43b6e66..5371d53 100644 +++--- a/vendor/jiff-0.1.13/Cargo.toml ++++++ b/vendor/jiff-0.1.13/Cargo.toml +++@@ -133,7 +133,6 @@ serde = ["dep:serde"] +++ std = ["alloc"] +++ tz-system = [ +++ "std", +++- "dep:windows-sys", +++ ] +++ tzdb-bundle-always = [ +++ "dep:jiff-tzdb", +++@@ -159,12 +158,3 @@ optional = true +++ +++ [target.'cfg(not(target_family = "wasm"))'.dev-dependencies.hifitime] +++ version = "3.9.0" +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = ">=0.52.0, <=0.59.*" +++-features = [ +++- "Win32_Foundation", +++- "Win32_System_Time", +++-] +++-optional = true +++-default-features = false +++diff --git a/vendor/libloading-0.8.6/Cargo.toml b/vendor/libloading-0.8.6/Cargo.toml +++index 338072a..712a40b 100644 +++--- a/vendor/libloading-0.8.6/Cargo.toml ++++++ b/vendor/libloading-0.8.6/Cargo.toml +++@@ -44,13 +44,6 @@ version = "1.1" +++ [target."cfg(unix)".dependencies.cfg-if] +++ version = "1" +++ +++-[target."cfg(windows)".dependencies.windows-targets] +++-version = ">=0.48, <0.53" +++- +++-[target."cfg(windows)".dev-dependencies.windows-sys] +++-version = ">=0.52,<0.59" +++-features = ["Win32_Foundation"] +++- +++ [lints.rust.unexpected_cfgs] +++ level = "warn" +++ priority = 0 +++diff --git a/vendor/libssh2-sys-0.3.0/Cargo.toml b/vendor/libssh2-sys-0.3.0/Cargo.toml +++index 45f4a71..516644c 100644 +++--- a/vendor/libssh2-sys-0.3.0/Cargo.toml ++++++ b/vendor/libssh2-sys-0.3.0/Cargo.toml +++@@ -43,16 +43,8 @@ version = "1.0.25" +++ version = "0.3.11" +++ +++ [features] +++-openssl-on-win32 = ["openssl-sys"] +++ vendored-openssl = ["openssl-sys/vendored"] +++ zlib-ng-compat = ["libz-sys/zlib-ng"] +++ +++-[target."cfg(target_env = \"msvc\")".build-dependencies.vcpkg] +++-version = "0.2" +++- +++ [target."cfg(unix)".dependencies.openssl-sys] +++ version = "0.9.35" +++- +++-[target."cfg(windows)".dependencies.openssl-sys] +++-version = "0.9.35" +++-optional = true +++diff --git a/vendor/mio-0.8.11/Cargo.toml b/vendor/mio-0.8.11/Cargo.toml +++index 5d112d9..1d30aa8 100644 +++--- a/vendor/mio-0.8.11/Cargo.toml ++++++ b/vendor/mio-0.8.11/Cargo.toml +++@@ -103,8 +103,6 @@ default = ["log"] +++ net = [] +++ os-ext = [ +++ "os-poll", +++- "windows-sys/Win32_System_Pipes", +++- "windows-sys/Win32_Security", +++ ] +++ os-poll = [] +++ +++@@ -116,13 +114,3 @@ version = "0.11.0" +++ +++ [target."cfg(unix)".dependencies.libc] +++ version = "0.2.149" +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.48" +++-features = [ +++- "Win32_Foundation", +++- "Win32_Networking_WinSock", +++- "Win32_Storage_FileSystem", +++- "Win32_System_IO", +++- "Win32_System_WindowsProgramming", +++-] +++diff --git a/vendor/notify-6.1.1/Cargo.toml b/vendor/notify-6.1.1/Cargo.toml +++index 34600c9..2a4612e 100644 +++--- a/vendor/notify-6.1.1/Cargo.toml ++++++ b/vendor/notify-6.1.1/Cargo.toml +++@@ -107,14 +107,3 @@ optional = true +++ version = "0.8" +++ features = ["os-ext"] +++ optional = true +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.48.0" +++-features = [ +++- "Win32_System_Threading", +++- "Win32_Foundation", +++- "Win32_Storage_FileSystem", +++- "Win32_Security", +++- "Win32_System_WindowsProgramming", +++- "Win32_System_IO", +++-] +++diff --git a/vendor/nu-ansi-term-0.46.0/Cargo.toml b/vendor/nu-ansi-term-0.46.0/Cargo.toml +++index 209e055..aa40f02 100644 +++--- a/vendor/nu-ansi-term-0.46.0/Cargo.toml ++++++ b/vendor/nu-ansi-term-0.46.0/Cargo.toml +++@@ -45,13 +45,3 @@ version = "1.0.39" +++ +++ [features] +++ derive_serde_style = ["serde"] +++- +++-[target."cfg(target_os=\"windows\")".dependencies.winapi] +++-version = "0.3.4" +++-features = [ +++- "consoleapi", +++- "errhandlingapi", +++- "fileapi", +++- "handleapi", +++- "processenv", +++-] +++diff --git a/vendor/nu-ansi-term-0.50.1/Cargo.toml b/vendor/nu-ansi-term-0.50.1/Cargo.toml +++index e491c19..e01f722 100644 +++--- a/vendor/nu-ansi-term-0.50.1/Cargo.toml ++++++ b/vendor/nu-ansi-term-0.50.1/Cargo.toml +++@@ -42,13 +42,3 @@ version = "1.0.94" +++ [features] +++ derive_serde_style = ["serde"] +++ gnu_legacy = [] +++- +++-[target."cfg(windows)".dependencies.windows] +++-version = "0.52.0" +++-features = [ +++- "Win32_Foundation", +++- "Win32_System_Console", +++- "Win32_Storage_FileSystem", +++- "Win32_Security", +++-] +++-package = "windows-sys" +++diff --git a/vendor/onig-6.4.0/Cargo.toml b/vendor/onig-6.4.0/Cargo.toml +++index 43e49e2..54b9a8b 100644 +++--- a/vendor/onig-6.4.0/Cargo.toml ++++++ b/vendor/onig-6.4.0/Cargo.toml +++@@ -44,6 +44,3 @@ generate = ["onig_sys/generate"] +++ posix-api = ["onig_sys/posix-api"] +++ print-debug = ["onig_sys/print-debug"] +++ std-pattern = [] +++- +++-[target."cfg(windows)".dependencies.libc] +++-version = "0.2" +++diff --git a/vendor/opener-0.5.2/Cargo.toml b/vendor/opener-0.5.2/Cargo.toml +++index 8d91b5e..2d7313b 100644 +++--- a/vendor/opener-0.5.2/Cargo.toml ++++++ b/vendor/opener-0.5.2/Cargo.toml +++@@ -32,10 +32,6 @@ version = "0.9" +++ [target."cfg(target_os = \"linux\")".dependencies.bstr] +++ version = "1" +++ +++-[target."cfg(windows)".dependencies.winapi] +++-version = "0.3" +++-features = ["shellapi"] +++- +++ [badges.appveyor] +++ branch = "master" +++ repository = "Seeker14491/opener" +++diff --git a/vendor/opener-0.7.2/Cargo.toml b/vendor/opener-0.7.2/Cargo.toml +++index 5639d3d..eff5c32 100644 +++--- a/vendor/opener-0.7.2/Cargo.toml ++++++ b/vendor/opener-0.7.2/Cargo.toml +++@@ -48,7 +48,6 @@ default = ["dbus-vendored"] +++ reveal = [ +++ "dep:url", +++ "dep:dbus", +++- "windows-sys/Win32_System_Com", +++ ] +++ +++ [target.'cfg(target_os = "linux")'.dependencies.bstr] +++@@ -62,16 +61,5 @@ optional = true +++ version = "2" +++ optional = true +++ +++-[target."cfg(windows)".dependencies.normpath] +++-version = "1" +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.59" +++-features = [ +++- "Win32_Foundation", +++- "Win32_UI_Shell", +++- "Win32_UI_WindowsAndMessaging", +++-] +++- +++ [badges.maintenance] +++ status = "passively-maintained" +++diff --git a/vendor/os_info-3.8.2/Cargo.toml b/vendor/os_info-3.8.2/Cargo.toml +++index 9aa2067..c1a79b8 100644 +++--- a/vendor/os_info-3.8.2/Cargo.toml ++++++ b/vendor/os_info-3.8.2/Cargo.toml +++@@ -48,15 +48,3 @@ version = "1" +++ +++ [features] +++ default = ["serde"] +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.52" +++-features = [ +++- "Win32_Foundation", +++- "Win32_System_LibraryLoader", +++- "Win32_System_Registry", +++- "Win32_System_SystemInformation", +++- "Win32_System_SystemServices", +++- "Win32_System_Threading", +++- "Win32_UI_WindowsAndMessaging", +++-] +++diff --git a/vendor/parking_lot_core-0.9.10/Cargo.toml b/vendor/parking_lot_core-0.9.10/Cargo.toml +++index 3111f2b..c7a53ca 100644 +++--- a/vendor/parking_lot_core-0.9.10/Cargo.toml ++++++ b/vendor/parking_lot_core-0.9.10/Cargo.toml +++@@ -61,6 +61,3 @@ version = "0.5" +++ +++ [target."cfg(unix)".dependencies.libc] +++ version = "0.2.95" +++- +++-[target."cfg(windows)".dependencies.windows-targets] +++-version = "0.52.0" +++diff --git a/vendor/portable-atomic-1.10.0/Cargo.toml b/vendor/portable-atomic-1.10.0/Cargo.toml +++index 7b520b7..c85bff2 100644 +++--- a/vendor/portable-atomic-1.10.0/Cargo.toml ++++++ b/vendor/portable-atomic-1.10.0/Cargo.toml +++@@ -98,13 +98,6 @@ unsafe-assume-single-core = [] +++ [target."cfg(unix)".dev-dependencies.libc] +++ version = "=0.2.163" +++ +++-[target."cfg(windows)".dev-dependencies.windows-sys] +++-version = "0.59" +++-features = [ +++- "Win32_Foundation", +++- "Win32_System_Threading", +++-] +++- +++ [lints.clippy] +++ all = "warn" +++ as_ptr_cast_mut = "warn" +++diff --git a/vendor/process-wrap-8.0.2/Cargo.toml b/vendor/process-wrap-8.0.2/Cargo.toml +++index d04598f..1f60c7e 100644 +++--- a/vendor/process-wrap-8.0.2/Cargo.toml ++++++ b/vendor/process-wrap-8.0.2/Cargo.toml +++@@ -73,8 +73,6 @@ features = [ +++ +++ [features] +++ creation-flags = [ +++- "dep:windows", +++- "windows/Win32_System_Threading", +++ ] +++ default = [ +++ "creation-flags", +++@@ -85,12 +83,6 @@ default = [ +++ "tracing", +++ ] +++ job-object = [ +++- "dep:windows", +++- "windows/Win32_Security", +++- "windows/Win32_System_Diagnostics_ToolHelp", +++- "windows/Win32_System_IO", +++- "windows/Win32_System_JobObjects", +++- "windows/Win32_System_Threading", +++ ] +++ kill-on-drop = [] +++ process-group = [] +++@@ -114,6 +106,3 @@ features = [ +++ optional = true +++ default-features = false +++ +++-[target."cfg(windows)".dependencies.windows] +++-version = "0.56.0" +++-optional = true +++diff --git a/vendor/rustix-0.38.42/Cargo.toml b/vendor/rustix-0.38.42/Cargo.toml +++index 580f185..46f2dbc 100644 +++--- a/vendor/rustix-0.38.42/Cargo.toml ++++++ b/vendor/rustix-0.38.42/Cargo.toml +++@@ -267,15 +267,6 @@ version = "0.3.10" +++ default-features = false +++ package = "errno" +++ +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = ">=0.52, <=0.59" +++-features = [ +++- "Win32_Foundation", +++- "Win32_Networking_WinSock", +++- "Win32_NetworkManagement_IpHelper", +++- "Win32_System_Threading", +++-] +++- +++ [lints.rust.unexpected_cfgs] +++ level = "warn" +++ priority = 0 +++diff --git a/vendor/same-file-1.0.6/Cargo.toml b/vendor/same-file-1.0.6/Cargo.toml +++index 4f66820..11ef472 100644 +++--- a/vendor/same-file-1.0.6/Cargo.toml ++++++ b/vendor/same-file-1.0.6/Cargo.toml +++@@ -25,5 +25,3 @@ license = "Unlicense/MIT" +++ repository = "https://github.com/BurntSushi/same-file" +++ [dev-dependencies.doc-comment] +++ version = "0.3" +++-[target."cfg(windows)".dependencies.winapi-util] +++-version = "0.1.1" +++diff --git a/vendor/snapbox-0.6.20/Cargo.toml b/vendor/snapbox-0.6.20/Cargo.toml +++index 4c54741..8ea990c 100644 +++--- a/vendor/snapbox-0.6.20/Cargo.toml ++++++ b/vendor/snapbox-0.6.20/Cargo.toml +++@@ -189,7 +189,6 @@ cmd = [ +++ "dep:os_pipe", +++ "dep:wait-timeout", +++ "dep:libc", +++- "dep:windows-sys", +++ ] +++ color = [ +++ "dep:anstream", +++@@ -231,11 +230,6 @@ term-svg = [ +++ version = "0.2.137" +++ optional = true +++ +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.59.0" +++-features = ["Win32_Foundation"] +++-optional = true +++- +++ [lints.clippy] +++ bool_assert_comparison = "allow" +++ branches_sharing_code = "allow" +++diff --git a/vendor/socket2-0.5.8/Cargo.toml b/vendor/socket2-0.5.8/Cargo.toml +++index 68d8eb7..ae363b0 100644 +++--- a/vendor/socket2-0.5.8/Cargo.toml ++++++ b/vendor/socket2-0.5.8/Cargo.toml +++@@ -85,13 +85,3 @@ all = [] +++ +++ [target."cfg(unix)".dependencies.libc] +++ version = "0.2.150" +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.52" +++-features = [ +++- "Win32_Foundation", +++- "Win32_Networking_WinSock", +++- "Win32_System_IO", +++- "Win32_System_Threading", +++- "Win32_System_WindowsProgramming", +++-] +++diff --git a/vendor/stacker-0.1.17/Cargo.toml b/vendor/stacker-0.1.17/Cargo.toml +++index 2ce65c2..f6d74c0 100644 +++--- a/vendor/stacker-0.1.17/Cargo.toml ++++++ b/vendor/stacker-0.1.17/Cargo.toml +++@@ -44,11 +44,3 @@ version = "0.1.7" +++ +++ [build-dependencies.cc] +++ version = "1.0.2" +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = ">=0.52.0, <0.60.0" +++-features = [ +++- "Win32_System_Memory", +++- "Win32_System_Threading", +++- "Win32_Foundation", +++-] +++diff --git a/vendor/sysinfo-0.31.4/Cargo.toml b/vendor/sysinfo-0.31.4/Cargo.toml +++index 97f5a7f..f09c18d 100644 +++--- a/vendor/sysinfo-0.31.4/Cargo.toml ++++++ b/vendor/sysinfo-0.31.4/Cargo.toml +++@@ -114,12 +114,6 @@ apple-app-store = ["apple-sandbox"] +++ apple-sandbox = [] +++ c-interface = ["default"] +++ component = [ +++- "windows/Win32_Foundation", +++- "windows/Win32_Security", +++- "windows/Win32_System_Com", +++- "windows/Win32_System_Rpc", +++- "windows/Win32_System_Variant", +++- "windows/Win32_System_Wmi", +++ ] +++ debug = ["libc/extra_traits"] +++ default = [ +++@@ -131,50 +125,17 @@ default = [ +++ "multithread", +++ ] +++ disk = [ +++- "windows/Win32_Foundation", +++- "windows/Win32_Storage_FileSystem", +++- "windows/Win32_Security", +++- "windows/Win32_System_IO", +++- "windows/Win32_System_Ioctl", +++- "windows/Win32_System_WindowsProgramming", +++ ] +++ linux-netdevs = [] +++ linux-tmpfs = [] +++ multithread = ["dep:rayon"] +++ network = [ +++- "windows/Win32_Foundation", +++- "windows/Win32_NetworkManagement_IpHelper", +++- "windows/Win32_NetworkManagement_Ndis", +++- "windows/Win32_Networking_WinSock", +++ ] +++ system = [ +++- "windows/Win32_Foundation", +++- "windows/Wdk_System_SystemInformation", +++- "windows/Wdk_System_SystemServices", +++- "windows/Wdk_System_Threading", +++- "windows/Win32_Security_Authorization", +++- "windows/Win32_System_Diagnostics_Debug", +++- "windows/Win32_System_Kernel", +++- "windows/Win32_System_Memory", +++- "windows/Win32_System_Performance", +++- "windows/Win32_System_Power", +++- "windows/Win32_System_ProcessStatus", +++- "windows/Win32_System_Registry", +++- "windows/Win32_System_RemoteDesktop", +++- "windows/Win32_System_SystemInformation", +++- "windows/Win32_System_SystemServices", +++- "windows/Win32_System_Threading", +++- "windows/Win32_UI_Shell", +++- "dep:ntapi", +++ "dep:memchr", +++ ] +++ unknown-ci = [] +++ user = [ +++- "windows/Win32_Foundation", +++- "windows/Win32_NetworkManagement_NetManagement", +++- "windows/Win32_Security", +++- "windows/Win32_Security_Authentication_Identity", +++- "windows/Win32_Security_Authorization", +++ ] +++ +++ [target.'cfg(all(target_os = "linux", not(target_os = "android")))'.dev-dependencies.tempfile] +++@@ -185,11 +146,3 @@ version = "0.8" +++ +++ [target.'cfg(not(any(target_os = "unknown", target_arch = "wasm32")))'.dependencies.libc] +++ version = "^0.2.153" +++- +++-[target."cfg(windows)".dependencies.ntapi] +++-version = "0.4" +++-optional = true +++- +++-[target."cfg(windows)".dependencies.windows] +++-version = ">=0.54, <=0.57" +++-optional = true +++diff --git a/vendor/sysinfo-0.33.0/Cargo.toml b/vendor/sysinfo-0.33.0/Cargo.toml +++index 6eebfa5..d9919f2 100644 +++--- a/vendor/sysinfo-0.33.0/Cargo.toml ++++++ b/vendor/sysinfo-0.33.0/Cargo.toml +++@@ -125,12 +125,6 @@ apple-app-store = ["apple-sandbox"] +++ apple-sandbox = [] +++ c-interface = ["default"] +++ component = [ +++- "windows/Win32_Foundation", +++- "windows/Win32_Security", +++- "windows/Win32_System_Com", +++- "windows/Win32_System_Rpc", +++- "windows/Win32_System_Variant", +++- "windows/Win32_System_Wmi", +++ ] +++ debug = ["libc/extra_traits"] +++ default = [ +++@@ -142,51 +136,17 @@ default = [ +++ "multithread", +++ ] +++ disk = [ +++- "windows/Win32_Foundation", +++- "windows/Win32_Storage_FileSystem", +++- "windows/Win32_Security", +++- "windows/Win32_System_IO", +++- "windows/Win32_System_Ioctl", +++- "windows/Win32_System_SystemServices", +++- "windows/Win32_System_WindowsProgramming", +++ ] +++ linux-netdevs = [] +++ linux-tmpfs = [] +++ multithread = ["dep:rayon"] +++ network = [ +++- "windows/Win32_Foundation", +++- "windows/Win32_NetworkManagement_IpHelper", +++- "windows/Win32_NetworkManagement_Ndis", +++- "windows/Win32_Networking_WinSock", +++ ] +++ system = [ +++- "windows/Win32_Foundation", +++- "windows/Wdk_System_SystemInformation", +++- "windows/Wdk_System_SystemServices", +++- "windows/Wdk_System_Threading", +++- "windows/Win32_Security_Authorization", +++- "windows/Win32_System_Diagnostics_Debug", +++- "windows/Win32_System_Kernel", +++- "windows/Win32_System_Memory", +++- "windows/Win32_System_Performance", +++- "windows/Win32_System_Power", +++- "windows/Win32_System_ProcessStatus", +++- "windows/Win32_System_Registry", +++- "windows/Win32_System_RemoteDesktop", +++- "windows/Win32_System_SystemInformation", +++- "windows/Win32_System_SystemServices", +++- "windows/Win32_System_Threading", +++- "windows/Win32_UI_Shell", +++- "dep:ntapi", +++ "dep:memchr", +++ ] +++ unknown-ci = [] +++ user = [ +++- "windows/Win32_Foundation", +++- "windows/Win32_NetworkManagement_NetManagement", +++- "windows/Win32_Security", +++- "windows/Win32_Security_Authentication_Identity", +++- "windows/Win32_Security_Authorization", +++ ] +++ +++ [target.'cfg(all(target_os = "linux", not(target_os = "android")))'.dev-dependencies.tempfile] +++@@ -197,11 +157,3 @@ version = "0.8.7" +++ +++ [target.'cfg(not(any(target_os = "unknown", target_arch = "wasm32")))'.dependencies.libc] +++ version = "^0.2.164" +++- +++-[target."cfg(windows)".dependencies.ntapi] +++-version = "0.4" +++-optional = true +++- +++-[target."cfg(windows)".dependencies.windows] +++-version = ">=0.54, <=0.57" +++-optional = true +++diff --git a/vendor/tempfile-3.14.0/Cargo.toml b/vendor/tempfile-3.14.0/Cargo.toml +++index 302880c..49c0634 100644 +++--- a/vendor/tempfile-3.14.0/Cargo.toml ++++++ b/vendor/tempfile-3.14.0/Cargo.toml +++@@ -81,10 +81,3 @@ nightly = [] +++ [target.'cfg(any(unix, target_os = "wasi"))'.dependencies.rustix] +++ version = "0.38.39" +++ features = ["fs"] +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = ">=0.52,<=0.59" +++-features = [ +++- "Win32_Storage_FileSystem", +++- "Win32_Foundation", +++-] +++diff --git a/vendor/term-0.7.0/Cargo.toml b/vendor/term-0.7.0/Cargo.toml +++index e89261e..ad5d62b 100644 +++--- a/vendor/term-0.7.0/Cargo.toml ++++++ b/vendor/term-0.7.0/Cargo.toml +++@@ -28,12 +28,6 @@ version = "2" +++ +++ [features] +++ default = [] +++-[target."cfg(windows)".dependencies.rustversion] +++-version = "1" +++- +++-[target."cfg(windows)".dependencies.winapi] +++-version = "0.3" +++-features = ["consoleapi", "wincon", "handleapi", "fileapi"] +++ [badges.appveyor] +++ repository = "Stebalien/term" +++ +++diff --git a/vendor/termcolor-1.4.1/Cargo.toml b/vendor/termcolor-1.4.1/Cargo.toml +++index f90eaca..d32db67 100644 +++--- a/vendor/termcolor-1.4.1/Cargo.toml ++++++ b/vendor/termcolor-1.4.1/Cargo.toml +++@@ -35,6 +35,3 @@ name = "termcolor" +++ bench = false +++ +++ [dev-dependencies] +++- +++-[target."cfg(windows)".dependencies.winapi-util] +++-version = "0.1.3" +++diff --git a/vendor/terminal_size-0.4.1/Cargo.toml b/vendor/terminal_size-0.4.1/Cargo.toml +++index 627f55f..66e689c 100644 +++--- a/vendor/terminal_size-0.4.1/Cargo.toml ++++++ b/vendor/terminal_size-0.4.1/Cargo.toml +++@@ -46,9 +46,3 @@ path = "examples/get_size.rs" +++ version = "0.38.0" +++ features = ["termios"] +++ +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.59.0" +++-features = [ +++- "Win32_Foundation", +++- "Win32_System_Console", +++-] +++diff --git a/vendor/termize-0.1.1/Cargo.toml b/vendor/termize-0.1.1/Cargo.toml +++index d248f4d..9bd9f37 100644 +++--- a/vendor/termize-0.1.1/Cargo.toml ++++++ b/vendor/termize-0.1.1/Cargo.toml +++@@ -49,8 +49,5 @@ rpath = false +++ [dependencies] +++ [target."cfg(unix)".dependencies.libc] +++ version = "0.2.66" +++-[target."cfg(windows)".dependencies.winapi] +++-version = "0.3.8" +++-features = ["handleapi", "processenv", "wincon", "winbase"] +++ [badges.cirrus-ci] +++ repository = "JohnTitor/termize" +++diff --git a/vendor/tokio-1.42.0/Cargo.toml b/vendor/tokio-1.42.0/Cargo.toml +++index 41a0faa..7f97e6c 100644 +++--- a/vendor/tokio-1.42.0/Cargo.toml ++++++ b/vendor/tokio-1.42.0/Cargo.toml +++@@ -703,11 +703,6 @@ net = [ +++ "mio/os-ext", +++ "mio/net", +++ "socket2", +++- "windows-sys/Win32_Foundation", +++- "windows-sys/Win32_Security", +++- "windows-sys/Win32_Storage_FileSystem", +++- "windows-sys/Win32_System_Pipes", +++- "windows-sys/Win32_System_SystemServices", +++ ] +++ process = [ +++ "bytes", +++@@ -716,9 +711,6 @@ process = [ +++ "mio/os-ext", +++ "mio/net", +++ "signal-hook-registry", +++- "windows-sys/Win32_Foundation", +++- "windows-sys/Win32_System_Threading", +++- "windows-sys/Win32_System_WindowsProgramming", +++ ] +++ rt = [] +++ rt-multi-thread = ["rt"] +++@@ -728,8 +720,6 @@ signal = [ +++ "mio/net", +++ "mio/os-ext", +++ "signal-hook-registry", +++- "windows-sys/Win32_Foundation", +++- "windows-sys/Win32_System_Console", +++ ] +++ sync = [] +++ test-util = [ +++@@ -798,14 +788,3 @@ features = [ +++ "socket", +++ ] +++ default-features = false +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.52" +++-optional = true +++- +++-[target."cfg(windows)".dev-dependencies.windows-sys] +++-version = "0.52" +++-features = [ +++- "Win32_Foundation", +++- "Win32_Security_Authorization", +++-] +++diff --git a/vendor/uuid-1.11.0/Cargo.toml b/vendor/uuid-1.11.0/Cargo.toml +++index 4355c0b..8d7065a 100644 +++--- a/vendor/uuid-1.11.0/Cargo.toml ++++++ b/vendor/uuid-1.11.0/Cargo.toml +++@@ -203,7 +203,6 @@ version = "0.3" +++ +++ [target.'cfg(target = "wasm32-unknown-unknown")'.dev-dependencies.wasm-bindgen] +++ version = "0.2" +++- +++ [badges.is-it-maintained-issue-resolution] +++ repository = "uuid-rs/uuid" +++ +++diff --git a/vendor/walkdir-2.5.0/Cargo.toml b/vendor/walkdir-2.5.0/Cargo.toml +++index 4fda2f4..1741677 100644 +++--- a/vendor/walkdir-2.5.0/Cargo.toml ++++++ b/vendor/walkdir-2.5.0/Cargo.toml +++@@ -39,9 +39,6 @@ version = "1.0.1" +++ [dev-dependencies.doc-comment] +++ version = "0.3" +++ +++-[target."cfg(windows)".dependencies.winapi-util] +++-version = "0.1.1" +++- +++ [badges.appveyor] +++ repository = "BurntSushi/walkdir" +++ +++diff --git a/vendor/wasm-component-ld-0.5.11/Cargo.toml b/vendor/wasm-component-ld-0.5.11/Cargo.toml +++index d03963f..3bc58f8 100644 +++--- a/vendor/wasm-component-ld-0.5.11/Cargo.toml ++++++ b/vendor/wasm-component-ld-0.5.11/Cargo.toml +++@@ -86,10 +86,3 @@ version = "0.219.0" +++ +++ [target."cfg(unix)".dependencies.libc] +++ version = "0.2" +++- +++-[target."cfg(windows)".dependencies.windows-sys] +++-version = "0.59" +++-features = ["Win32_Foundation"] +++- +++-[target."cfg(windows)".dependencies.winsplit] +++-version = "0.1" +++diff --git a/vendor/yansi-term-0.1.2/Cargo.toml b/vendor/yansi-term-0.1.2/Cargo.toml +++index 0317866..88ce8ef 100644 +++--- a/vendor/yansi-term-0.1.2/Cargo.toml ++++++ b/vendor/yansi-term-0.1.2/Cargo.toml +++@@ -36,9 +36,6 @@ version = "1.0" +++ +++ [features] +++ derive_serde_style = ["serde"] +++-[target."cfg(target_os=\"windows\")".dependencies.winapi] +++-version = "0.3.4" +++-features = ["consoleapi", "errhandlingapi", "fileapi", "handleapi", "processenv"] +++ [badges.maintenance] +++ status = "actively-developed" +++ diff --cc debian/patches/series index 0000000000,0000000000,0000000000..267a22d20f new file mode 100644 --- /dev/null +++ b/debian/patches/series @@@@ -1,0 -1,0 -1,0 +1,50 @@@@ +++cargo/c-2002_disable-net-tests.patch +++cargo/c-2003-workaround-qemu-vfork-command-not-found.patch +++cargo/c-2200-workaround-x32-test.patch +++cargo/c-disable-fs-specific-test.patch +++cargo/c-0003-tests-add-missing-cross-disabled-checks.patch +++cargo/d-0012-cargo-always-return-dev-channel.patch +++upstream/u-ignore-ppc-hangs.patch +++upstream/u-rustc-llvm-cross-flags.patch +++upstream/u-hurd-tests.patch +++upstream/d-ignore-test_arc_condvar_poison-ppc.patch +++upstream/d-disable-download-tests.patch +++prune/d-0000-ignore-removed-submodules.patch +++prune/d-0001-pkg-config-no-special-snowflake.patch +++prune/d-0002-mdbook-strip-embedded-libs.patch +++prune/d-0005-no-jemalloc.patch +++prune/d-0006-no-mimalloc.patch +++prune/d-0007-no-tzdb.patch +++prune/d-0010-cargo-remove-vendored-c-crates.patch +++prune/d-0011-cargo-remove-nghttp2.patch +++prune/d-0020-remove-windows-dependencies.patch +++prune/d-0021-vendor-remove-windows-dependencies.patch +++vendor/d-0003-cc-psm-rebuild-wasm32.patch +++build/d-bootstrap-rustflags.patch +++build/d-bootstrap-install-symlinks.patch +++build/d-bootstrap-disable-git.patch +++build/d-bootstrap-no-assume-tools.patch +++build/d-bootstrap-cargo-doc-paths.patch +++build/d-bootstrap-use-local-css.patch +++build/d-bootstrap-custom-debuginfo-path.patch +++build/d-bootstrap-permit-symlink-in-docs.patch +++build/d-test-ignore-avx-44056.patch +++behaviour/d-rust-gdb-paths.patch +++behaviour/d-rust-lldb-paths.patch +++behaviour/d-rustc-add-soname.patch +++behaviour/d-rustc-windows-ssp.patch +++behaviour/d-rustdoc-disable-embedded-fonts.patch +++ubuntu/ubuntu-disable-ppc64el-asm-tests.patch +++ubuntu/ubuntu-ignore-arm-doctest.patch +++vendor/onig_sys-use-system-lib.patch +++vendor/libz-sys-allow-cross-building.patch +++build/bootstrap-tests-disable-compiler-rt-optimizing.patch +++build/ignore-broken-debuginfo-tests.patch +++vendor/blake3-skip-embedded-C-code-use-pure-implementation.patch +++build/ci_rustc-disable-test-that-requires-upstream-git-repo.patch +++build/bootstrap-don-t-attempt-to-download-rustc-in-tests.patch +++behaviour/proc-macro-srv-make-usage-of-RTLD_DEEPBIND-portable.patch +++bootstrap/bootstrap-revert-cross-build-breaking-change.patch +++vendor/cargo-update-git2-bindings.patch +++vendor/gitoxide-backport-fix-for-CVE-2025-31130.patch +++upstream/RUSTSEC-2025-0024-sync-mpsc-prevent-double-free-on-Drop.patch diff --cc debian/patches/ubuntu/ubuntu-disable-ppc64el-asm-tests.patch index 0000000000,0000000000,0000000000..1f38fef727 new file mode 100644 --- /dev/null +++ b/debian/patches/ubuntu/ubuntu-disable-ppc64el-asm-tests.patch @@@@ -1,0 -1,0 -1,0 +1,44 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 13 Jun 2024 11:16:41 +0200 +++Subject: ubuntu-disable-ppc64el-asm-tests +++ +++Forwarded: not-needed +++--- +++ compiler/rustc_lint/src/builtin.rs | 5 ++++- +++ compiler/rustc_lint_defs/src/builtin.rs | 2 ++ +++ 2 files changed, 6 insertions(+), 1 deletion(-) +++ +++diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs +++index 6e82395..7577812 100644 +++--- a/compiler/rustc_lint/src/builtin.rs ++++++ b/compiler/rustc_lint/src/builtin.rs +++@@ -2750,7 +2750,10 @@ declare_lint! { +++ /// ### Example +++ /// +++ /// ```rust,compile_fail +++- /// # #![feature(asm_experimental_arch)] ++++ /// #![cfg_attr( ++++ /// not(any(target_arch = "powerpc64", target_arch = "s390x")), ++++ /// feature(asm_experimental_arch) ++++ /// )] +++ /// use std::arch::asm; +++ /// +++ /// fn main() { +++diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs +++index 2f23ab2..fa2585d 100644 +++--- a/compiler/rustc_lint_defs/src/builtin.rs ++++++ b/compiler/rustc_lint_defs/src/builtin.rs +++@@ -2927,11 +2927,13 @@ declare_lint! { +++ /// +++ /// use std::arch::naked_asm; +++ /// ++++ /// #[cfg(not(any(target_arch = "powerpc64", target_arch = "s390x")))] +++ /// #[naked] +++ /// pub fn default_abi() -> u32 { +++ /// unsafe { naked_asm!(""); } +++ /// } +++ /// ++++ /// #[cfg(not(any(target_arch = "powerpc64", target_arch = "s390x")))] +++ /// #[naked] +++ /// pub extern "Rust" fn rust_abi() -> u32 { +++ /// unsafe { naked_asm!(""); } diff --cc debian/patches/ubuntu/ubuntu-ignore-arm-doctest.patch index 0000000000,0000000000,0000000000..4249b18e6c new file mode 100644 --- /dev/null +++ b/debian/patches/ubuntu/ubuntu-ignore-arm-doctest.patch @@@@ -1,0 -1,0 -1,0 +1,48 @@@@ +++From: Simon Chopin +++Date: Thu, 13 Jun 2024 11:16:41 +0200 +++Subject: Disable the doctests for the instruction_set errors +++ +++Bug: https://github.com/rust-lang/rust/issues/83453 +++Last-Update: 2022-02-23 +++ +++The fix is as described in the upstream issue. +++--- +++ compiler/rustc_error_codes/src/error_codes/E0778.md | 4 ++-- +++ compiler/rustc_error_codes/src/error_codes/E0779.md | 2 +- +++ 2 files changed, 3 insertions(+), 3 deletions(-) +++ +++diff --git a/compiler/rustc_error_codes/src/error_codes/E0778.md b/compiler/rustc_error_codes/src/error_codes/E0778.md +++index 467362d..d5688c2 100644 +++--- a/compiler/rustc_error_codes/src/error_codes/E0778.md ++++++ b/compiler/rustc_error_codes/src/error_codes/E0778.md +++@@ -16,7 +16,7 @@ specified: +++ ``` +++ #![feature(isa_attribute)] +++ +++-#[cfg_attr(target_arch="arm", instruction_set(arm::a32))] ++++#[cfg_attr(all(target_arch="arm", target_os="none"), instruction_set(arm::a32))] +++ fn something() {} +++ ``` +++ +++@@ -25,7 +25,7 @@ or: +++ ``` +++ #![feature(isa_attribute)] +++ +++-#[cfg_attr(target_arch="arm", instruction_set(arm::t32))] ++++#[cfg_attr(all(target_arch="arm", target_os="none"), instruction_set(arm::t32))] +++ fn something() {} +++ ``` +++ +++diff --git a/compiler/rustc_error_codes/src/error_codes/E0779.md b/compiler/rustc_error_codes/src/error_codes/E0779.md +++index 146e20c..9d23322 100644 +++--- a/compiler/rustc_error_codes/src/error_codes/E0779.md ++++++ b/compiler/rustc_error_codes/src/error_codes/E0779.md +++@@ -21,7 +21,7 @@ error. Example: +++ ``` +++ #![feature(isa_attribute)] +++ +++-#[cfg_attr(target_arch="arm", instruction_set(arm::a32))] // ok! ++++#[cfg_attr(all(target_arch="arm", target_os="none"), instruction_set(arm::a32))] // ok! +++ pub fn something() {} +++ fn main() {} +++ ``` diff --cc debian/patches/upstream/RUSTSEC-2025-0024-sync-mpsc-prevent-double-free-on-Drop.patch index 0000000000,0000000000,0000000000..1557c25489 new file mode 100644 --- /dev/null +++ b/debian/patches/upstream/RUSTSEC-2025-0024-sync-mpsc-prevent-double-free-on-Drop.patch @@@@ -1,0 -1,0 -1,0 +1,42 @@@@ +++From: Petros Angelatos +++Date: Tue, 8 Apr 2025 22:37:25 +0300 +++Subject: RUSTSEC-2025-0024: sync::mpsc: prevent double free on `Drop` +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++This PR is fixing a regression introduced by #121646 that can lead to a +++double free when dropping the channel. +++ +++The details of the bug can be found in the corresponding crossbeam PR +++https://github.com/crossbeam-rs/crossbeam/pull/1187 +++ +++Signed-off-by: Petros Angelatos +++FG: cherry-pick from upstream b9e2ac5c7b1d6bb3b6f5fdfe0819eaf7e95bf7ff +++FG: drop test context +++Signed-off-by: Fabian Grünbichler +++--- +++ library/std/src/sync/mpmc/list.rs | 8 +++++++- +++ 1 file changed, 7 insertions(+), 1 deletion(-) +++ +++diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs +++index d88914f..66444af1 100644 +++--- a/library/std/src/sync/mpmc/list.rs ++++++ b/library/std/src/sync/mpmc/list.rs +++@@ -564,9 +564,15 @@ impl Channel { +++ // In that case, just wait until it gets initialized. +++ while block.is_null() { +++ backoff.spin_heavy(); +++- block = self.head.block.load(Ordering::Acquire); ++++ block = self.head.block.swap(ptr::null_mut(), Ordering::AcqRel); +++ } +++ } ++++ // After this point `head.block` is not modified again and it will be deallocated if it's ++++ // non-null. The `Drop` code of the channel, which runs after this function, also attempts ++++ // to deallocate `head.block` if it's non-null. Therefore this function must maintain the ++++ // invariant that if a deallocation of head.block is attemped then it must also be set to ++++ // NULL. Failing to do so will lead to the Drop code attempting a double free. For this ++++ // reason both reads above do an atomic swap instead of a simple atomic load. +++ +++ unsafe { +++ // Drop all messages between head and tail and deallocate the heap-allocated blocks. diff --cc debian/patches/upstream/d-disable-download-tests.patch index 0000000000,0000000000,0000000000..ba3eebed28 new file mode 100644 --- /dev/null +++ b/debian/patches/upstream/d-disable-download-tests.patch @@@@ -1,0 -1,0 -1,0 +1,23 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 13 Jun 2024 11:16:39 +0200 +++Subject: d-disable-download-tests +++ +++Forwarded: no +++--- +++ src/bootstrap/src/core/config/tests.rs | 3 +++ +++ 1 file changed, 3 insertions(+) +++ +++diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs +++index 24f932a..65381ca 100644 +++--- a/src/bootstrap/src/core/config/tests.rs ++++++ b/src/bootstrap/src/core/config/tests.rs +++@@ -56,6 +56,9 @@ fn download_ci_llvm() { +++ // - https://github.com/rust-lang/rust/pull/109162#issuecomment-1496782487 +++ #[test] +++ fn detect_src_and_out() { ++++ // Debian: this will attempt to download a toolchain ++++ return; ++++ +++ fn test(cfg: Config, build_dir: Option<&str>) { +++ // This will bring absolute form of `src/bootstrap` path +++ let current_dir = std::env::current_dir().unwrap(); diff --cc debian/patches/upstream/d-ignore-test_arc_condvar_poison-ppc.patch index 0000000000,0000000000,0000000000..455e6da96b new file mode 100644 --- /dev/null +++ b/debian/patches/upstream/d-ignore-test_arc_condvar_poison-ppc.patch @@@@ -1,0 -1,0 -1,0 +1,21 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 13 Jun 2024 11:16:39 +0200 +++Subject: d-ignore-test_arc_condvar_poison-ppc +++ +++Forwarded: no +++--- +++ library/std/src/sync/poison/mutex/tests.rs | 1 + +++ 1 file changed, 1 insertion(+) +++ +++diff --git a/library/std/src/sync/poison/mutex/tests.rs b/library/std/src/sync/poison/mutex/tests.rs +++index 395c8aa..e9a3ed5 100644 +++--- a/library/std/src/sync/poison/mutex/tests.rs ++++++ b/library/std/src/sync/poison/mutex/tests.rs +++@@ -260,6 +260,7 @@ fn test_mutex_arc_condvar() { +++ } +++ } +++ ++++#[cfg(not(target_arch = "powerpc"))] +++ #[test] +++ fn test_arc_condvar_poison() { +++ let packet = Packet(Arc::new((Mutex::new(1), Condvar::new()))); diff --cc debian/patches/upstream/u-hurd-tests.patch index 0000000000,0000000000,0000000000..110fd57e7a new file mode 100644 --- /dev/null +++ b/debian/patches/upstream/u-hurd-tests.patch @@@@ -1,0 -1,0 -1,0 +1,111 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 13 Jun 2024 11:16:39 +0200 +++Subject: compiletest: add ignore-hurd support and annotate some tests +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++These tests hang or make the box OOM +++ +++Forwarded: no +++ +++ +++Signed-off-by: Fabian Grünbichler +++--- +++ src/tools/compiletest/src/directive-list.rs | 1 + +++ src/tools/compiletest/src/header/tests.rs | 1 + +++ tests/crashes/115994.rs | 1 + +++ tests/run-make/long-linker-command-lines/foo.rs | 7 +++++++ +++ tests/ui/associated-consts/issue-93775.rs | 1 + +++ tests/ui/issues/issue-74564-if-expr-stack-overflow.rs | 1 + +++ tests/ui/threads-sendsync/mpsc_stress.rs | 1 + +++ 7 files changed, 13 insertions(+) +++ +++diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs +++index 01068af..7952c7a 100644 +++--- a/src/tools/compiletest/src/directive-list.rs ++++++ b/src/tools/compiletest/src/directive-list.rs +++@@ -58,6 +58,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ +++ "ignore-gnu", +++ "ignore-haiku", +++ "ignore-horizon", ++++ "ignore-hurd", +++ "ignore-i686-pc-windows-gnu", +++ "ignore-i686-pc-windows-msvc", +++ "ignore-illumos", +++diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs +++index 618b66d..5708375 100644 +++--- a/src/tools/compiletest/src/header/tests.rs ++++++ b/src/tools/compiletest/src/header/tests.rs +++@@ -332,6 +332,7 @@ fn ignore_target() { +++ assert!(check_ignore(&config, "//@ ignore-x86_64-unknown-linux-gnu")); +++ assert!(check_ignore(&config, "//@ ignore-x86_64")); +++ assert!(check_ignore(&config, "//@ ignore-linux")); ++++ assert!(check_ignore(&config, "//@ ignore-hurd")); +++ assert!(check_ignore(&config, "//@ ignore-unix")); +++ assert!(check_ignore(&config, "//@ ignore-gnu")); +++ assert!(check_ignore(&config, "//@ ignore-64bit")); +++diff --git a/tests/crashes/115994.rs b/tests/crashes/115994.rs +++index 23d1507..e0714e5 100644 +++--- a/tests/crashes/115994.rs ++++++ b/tests/crashes/115994.rs +++@@ -1,5 +1,6 @@ +++ //@ known-bug: #115994 +++ //@ compile-flags: -Cdebuginfo=2 --crate-type lib ++++//@ ignore-hurd +++ +++ // To prevent "overflow while adding drop-check rules". +++ use std::mem::ManuallyDrop; +++diff --git a/tests/run-make/long-linker-command-lines/foo.rs b/tests/run-make/long-linker-command-lines/foo.rs +++index 5b30c06..9ef0d5a 100644 +++--- a/tests/run-make/long-linker-command-lines/foo.rs ++++++ b/tests/run-make/long-linker-command-lines/foo.rs +++@@ -33,6 +33,13 @@ fn read_linker_args(path: &Path) -> String { +++ } +++ } +++ ++++#[cfg(target_os = "hurd")] ++++// Debian: test causes build to fail on hurd ++++fn main() { ++++ return; ++++} ++++ ++++#[cfg(not(target_os = "hurd"))] +++ fn main() { +++ let ok = PathBuf::from("ok"); +++ if env::var("YOU_ARE_A_LINKER").is_ok() { +++diff --git a/tests/ui/associated-consts/issue-93775.rs b/tests/ui/associated-consts/issue-93775.rs +++index 88e88b5..0981abc 100644 +++--- a/tests/ui/associated-consts/issue-93775.rs ++++++ b/tests/ui/associated-consts/issue-93775.rs +++@@ -4,6 +4,7 @@ +++ +++ //@ build-pass +++ // ignore-tidy-linelength ++++//@ ignore-hurd +++ +++ // Regression for #93775, needs build-pass to test it. +++ +++diff --git a/tests/ui/issues/issue-74564-if-expr-stack-overflow.rs b/tests/ui/issues/issue-74564-if-expr-stack-overflow.rs +++index c0ffed2..1e97353 100644 +++--- a/tests/ui/issues/issue-74564-if-expr-stack-overflow.rs ++++++ b/tests/ui/issues/issue-74564-if-expr-stack-overflow.rs +++@@ -1,5 +1,6 @@ +++ //@ build-pass +++ // ignore-tidy-filelength ++++//@ ignore-hurd +++ #![crate_type = "rlib"] +++ +++ fn banana(v: &str) -> u32 { +++diff --git a/tests/ui/threads-sendsync/mpsc_stress.rs b/tests/ui/threads-sendsync/mpsc_stress.rs +++index fe0b47f..77ce6d5 100644 +++--- a/tests/ui/threads-sendsync/mpsc_stress.rs ++++++ b/tests/ui/threads-sendsync/mpsc_stress.rs +++@@ -1,6 +1,7 @@ +++ //@ run-pass +++ //@ compile-flags:--test +++ //@ needs-threads ++++//@ ignore-hurd +++ +++ use std::sync::atomic::{AtomicUsize, Ordering}; +++ use std::sync::mpsc::{channel, RecvError, RecvTimeoutError, TryRecvError}; diff --cc debian/patches/upstream/u-ignore-ppc-hangs.patch index 0000000000,0000000000,0000000000..6c209101d0 new file mode 100644 --- /dev/null +++ b/debian/patches/upstream/u-ignore-ppc-hangs.patch @@@@ -1,0 -1,0 -1,0 +1,34 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 14 Jul 2022 13:17:37 +0200 +++Subject: u-ignore-ppc-hangs +++ +++Bug: https://github.com/rust-lang/rust/issues/89607 +++--- +++ library/alloc/tests/arc.rs | 1 + +++ library/alloc/tests/rc.rs | 1 + +++ 2 files changed, 2 insertions(+) +++ +++diff --git a/library/alloc/tests/arc.rs b/library/alloc/tests/arc.rs +++index a259c01..0ac0cbe 100644 +++--- a/library/alloc/tests/arc.rs ++++++ b/library/alloc/tests/arc.rs +++@@ -95,6 +95,7 @@ const SHARED_ITER_MAX: u16 = 100; +++ +++ fn assert_trusted_len(_: &I) {} +++ ++++#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))] +++ #[test] +++ fn shared_from_iter_normal() { +++ // Exercise the base implementation for non-`TrustedLen` iterators. +++diff --git a/library/alloc/tests/rc.rs b/library/alloc/tests/rc.rs +++index 451765d..363c29c 100644 +++--- a/library/alloc/tests/rc.rs ++++++ b/library/alloc/tests/rc.rs +++@@ -91,6 +91,7 @@ const SHARED_ITER_MAX: u16 = 100; +++ +++ fn assert_trusted_len(_: &I) {} +++ ++++#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))] +++ #[test] +++ fn shared_from_iter_normal() { +++ // Exercise the base implementation for non-`TrustedLen` iterators. diff --cc debian/patches/upstream/u-rustc-llvm-cross-flags.patch index 0000000000,0000000000,0000000000..9397e0269d new file mode 100644 --- /dev/null +++ b/debian/patches/upstream/u-rustc-llvm-cross-flags.patch @@@@ -1,0 -1,0 -1,0 +1,22 @@@@ +++From: Debian Rust Maintainers +++Date: Thu, 14 Jul 2022 13:17:37 +0200 +++Subject: u-rustc-llvm-cross-flags +++ +++=================================================================== +++--- +++ compiler/rustc_llvm/build.rs | 2 +- +++ 1 file changed, 1 insertion(+), 1 deletion(-) +++ +++diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs +++index d9d2829..bb6677e 100644 +++--- a/compiler/rustc_llvm/build.rs ++++++ b/compiler/rustc_llvm/build.rs +++@@ -328,7 +328,7 @@ fn main() { +++ if let Some(stripped) = lib.strip_prefix("-LIBPATH:") { +++ println!("cargo:rustc-link-search=native={}", stripped.replace(&host, &target)); +++ } else if let Some(stripped) = lib.strip_prefix("-L") { +++- println!("cargo:rustc-link-search=native={}", stripped.replace(&host, &target)); ++++ if stripped.contains(&host) { println!("cargo:rustc-link-search=native={}", stripped.replace(&host, &target)); } +++ } +++ } else if let Some(stripped) = lib.strip_prefix("-LIBPATH:") { +++ println!("cargo:rustc-link-search=native={stripped}"); diff --cc debian/patches/vendor/blake3-skip-embedded-C-code-use-pure-implementation.patch index 0000000000,0000000000,0000000000..7e0d6e306f new file mode 100644 --- /dev/null +++ b/debian/patches/vendor/blake3-skip-embedded-C-code-use-pure-implementation.patch @@@@ -1,0 -1,0 -1,0 +1,64 @@@@ +++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= +++Date: Sat, 30 Nov 2024 12:24:03 +0100 +++Subject: blake3: skip embedded C code, use pure implementation +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++Forwarded: not-needed +++ +++Signed-off-by: Fabian Grünbichler +++--- +++ vendor/blake3-1.5.5/Cargo.toml | 2 +- +++ vendor/blake3-1.5.5/build.rs | 18 ++++++++++++------ +++ 2 files changed, 13 insertions(+), 7 deletions(-) +++ +++diff --git a/vendor/blake3-1.5.5/Cargo.toml b/vendor/blake3-1.5.5/Cargo.toml +++index b30c1fd..2744571 100644 +++--- a/vendor/blake3-1.5.5/Cargo.toml ++++++ b/vendor/blake3-1.5.5/Cargo.toml +++@@ -110,7 +110,7 @@ version = "3.8.0" +++ version = "1.1.12" +++ +++ [features] +++-default = ["std"] ++++default = ["std", "pure"] +++ digest = ["dep:digest"] +++ mmap = [ +++ "std", +++diff --git a/vendor/blake3-1.5.5/build.rs b/vendor/blake3-1.5.5/build.rs +++index 57f72b7..952b864 100644 +++--- a/vendor/blake3-1.5.5/build.rs ++++++ b/vendor/blake3-1.5.5/build.rs +++@@ -275,7 +275,11 @@ fn main() -> Result<(), Box> { +++ } +++ +++ if is_x86_64() || is_x86_32() { +++- let support = c_compiler_support(); ++++ let support = if is_pure() { ++++ NoCompiler ++++ } else { ++++ c_compiler_support() ++++ }; +++ if is_x86_32() || should_prefer_intrinsics() || is_pure() || support == NoCompiler { +++ build_sse2_sse41_avx2_rust_intrinsics(); +++ } else { +++@@ -312,11 +316,13 @@ fn main() -> Result<(), Box> { +++ println!("cargo:rerun-if-env-changed=CFLAGS"); +++ +++ // Ditto for source files, though these shouldn't change as often. +++- for file in std::fs::read_dir("c")? { +++- println!( +++- "cargo:rerun-if-changed={}", +++- file?.path().to_str().expect("utf-8") +++- ); ++++ if !is_pure() { ++++ for file in std::fs::read_dir("c")? { ++++ println!( ++++ "cargo:rerun-if-changed={}", ++++ file?.path().to_str().expect("utf-8") ++++ ); ++++ } +++ } +++ +++ Ok(()) diff --cc debian/patches/vendor/cargo-update-git2-bindings.patch index 0000000000,0000000000,0000000000..10ec641507 new file mode 100644 --- /dev/null +++ b/debian/patches/vendor/cargo-update-git2-bindings.patch @@@@ -1,0 -1,0 -1,0 +1,39 @@@@ +++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= +++Date: Mon, 17 Mar 2025 06:53:14 +0100 +++Subject: cargo: update git2 bindings +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++to support libgit2 1.9 +++ +++ +++Signed-off-by: Fabian Grünbichler +++--- +++ src/tools/cargo/Cargo.toml | 6 +++--- +++ 1 file changed, 3 insertions(+), 3 deletions(-) +++ +++diff --git a/src/tools/cargo/Cargo.toml b/src/tools/cargo/Cargo.toml +++index f18075e..cec907e 100644 +++--- a/src/tools/cargo/Cargo.toml ++++++ b/src/tools/cargo/Cargo.toml +++@@ -47,8 +47,8 @@ curl = "0.4.46" +++ curl-sys = "0.4.73" +++ filetime = "0.2.23" +++ flate2 = { version = "1.0.30", default-features = false, features = ["zlib"] } +++-git2 = "0.19.0" +++-git2-curl = "0.20.0" ++++git2 = "0.20.0" ++++git2-curl = "0.21.0" +++ gix = { version = "0.69.1", default-features = false, features = ["blocking-http-transport-curl", "progress-tree", "parallel", "dirwalk"] } +++ glob = "0.3.1" +++ handlebars = { version = "6.0.0", features = ["dir_source"] } +++@@ -64,7 +64,7 @@ itertools = "0.13.0" +++ jobserver = "0.1.32" +++ lazycell = "1.3.0" +++ libc = "0.2.155" +++-libgit2-sys = "0.17.0" ++++libgit2-sys = "0.18.0" +++ libloading = "0.8.5" +++ memchr = "2.7.4" +++ miow = "0.6.0" diff --cc debian/patches/vendor/d-0003-cc-psm-rebuild-wasm32.patch index 0000000000,0000000000,0000000000..1440ab7b08 new file mode 100644 --- /dev/null +++ b/debian/patches/vendor/d-0003-cc-psm-rebuild-wasm32.patch @@@@ -1,0 -1,0 -1,0 +1,49 @@@@ +++From: Debian Rust Maintainers +++Date: Sat, 2 Oct 2021 01:08:00 +0100 +++Subject: d-0003-cc-psm-rebuild-wasm32 +++ +++Forwarded: not-needed +++--- +++ vendor/cc-1.2.0/src/lib.rs | 2 +- +++ vendor/psm-0.1.24/build.rs | 7 ++----- +++ 2 files changed, 3 insertions(+), 6 deletions(-) +++ +++diff --git a/vendor/cc-1.2.0/src/lib.rs b/vendor/cc-1.2.0/src/lib.rs +++index a0aaa30..202ff17 100644 +++--- a/vendor/cc-1.2.0/src/lib.rs ++++++ b/vendor/cc-1.2.0/src/lib.rs +++@@ -2623,7 +2623,7 @@ impl Build { +++ let (env, msvc, gnu, traditional, clang) = if self.cpp { +++ ("CXX", "cl.exe", "g++", "c++", "clang++") +++ } else { +++- ("CC", "cl.exe", "gcc", "cc", "clang") ++++ ("CC", "cl.exe", "gcc", "cc", "rust-clang") +++ }; +++ +++ // On historical Solaris systems, "cc" may have been Sun Studio, which +++diff --git a/vendor/psm-0.1.24/build.rs b/vendor/psm-0.1.24/build.rs +++index bc84149..a299ab5 100644 +++--- a/vendor/psm-0.1.24/build.rs ++++++ b/vendor/psm-0.1.24/build.rs +++@@ -51,7 +51,7 @@ fn find_assembly( +++ ("sparc", _, _, _) => Some(("src/arch/sparc_sysv.s", true)), +++ ("riscv32", _, _, _) => Some(("src/arch/riscv.s", true)), +++ ("riscv64", _, _, _) => Some(("src/arch/riscv64.s", true)), +++- ("wasm32", _, _, _) => Some(("src/arch/wasm32.o", true)), ++++ ("wasm32", _, _, _) => Some(("src/arch/wasm32.s", true)), +++ ("loongarch64", _, _, _) => Some(("src/arch/loongarch64.s", true)), +++ _ => None, +++ } +++@@ -99,11 +99,8 @@ fn main() { +++ cfg.define(&*format!("CFG_TARGET_ENV_{}", env), None); +++ } +++ +++- // For wasm targets we ship a precompiled `*.o` file so we just pass that +++- // directly to `ar` to assemble an archive. Otherwise we're actually +++- // compiling the source assembly file. +++ if asm.ends_with(".o") { +++- cfg.object(asm); ++++ panic!("Debian does not allow embedded object files in source code") +++ } else { +++ cfg.file(asm); +++ } diff --cc debian/patches/vendor/gitoxide-backport-fix-for-CVE-2025-31130.patch index 0000000000,0000000000,0000000000..cac068ddf1 new file mode 100644 --- /dev/null +++ b/debian/patches/vendor/gitoxide-backport-fix-for-CVE-2025-31130.patch @@@@ -1,0 -1,0 -1,0 +1,694 @@@@ +++From: Emily +++Date: Tue, 1 Apr 2025 21:55:16 +0100 +++Subject: gitoxide: backport fix for CVE-2025-31130 +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++fix feat!: detect SHA‐1 collision attacks +++ +++Fix [GHSA-2frx-2596-x5r6]. +++ +++[GHSA-2frx-2596-x5r6]: https://github.com/GitoxideLabs/gitoxide/security/advisories/GHSA-2frx-2596-x5r6 +++ +++This uses the `sha1-checked` crate from the RustCrypto project. It’s +++a pure Rust implementation, with no SIMD or assembly code. +++ +++The hashing implementation moves to `gix-hash`, as it no longer +++depends on any feature configuration. I wasn’t sure the ideal +++crate to put this in, but after checking reverse dependencies on +++crates.io, it seems like there’s essentially no user of `gix-hash` +++that wouldn’t be pulling in a hashing implementation anyway, so I +++think this is a fine and logical place for it to be. +++ +++A fallible API seems better than killing the process as Git does, +++since we’re in a library context and it would be bad if you could +++perform denial‐of‐service attacks on a server by sending it hash +++collisions. (Although there are probably cheaper ways to mount a +++denial‐of‐service attack.) +++ +++The new API also returns an `ObjectId` rather than `[u8; 20]`; the +++vast majority of `Hasher::digest()` users immediately convert the +++result to `ObjectId`, so this will help eliminate a lot of cruft +++across the tree. `ObjectId` also has nicer `Debug` and `Display` +++instances than `[u8; 20]`, and should theoretically make supporting +++the hash function transition easier, although I suspect further API +++changes will be required for that anyway. I wasn’t sure whether +++this would be a good change, as not every digest identifies an +++entry in the Git object database, but even many of the existing +++uses for non‐object digests across the tree used the `ObjectId` +++API anyway. Perhaps it would be best to have a separate non‐alias +++`Digest` type that `ObjectId` wraps, but this seems like the pragmatic +++choice for now that sticks with current practice. +++ +++The old API remains in this commit, as well as a temporary +++non‐fallible but `ObjectId`‐returning `Hasher::finalize()`, +++pending the migration of all in‐tree callers. +++ +++I named the module `gix_hash::hasher` since `gix_hash::hash` seemed +++like it would be confusing. This does mean that there is a function +++and module with the same name, which is permitted but perhaps a +++little strange. +++ +++Everything is re‐exported directly other than +++`gix_features::hash::Write`, which moves along with the I/O +++convenience functions into a new public submodule and becomes +++`gix_hash::hasher::io::Write`, as that seems like a clearer name +++to me, being akin to the `gix_hash::hasher` function but as an +++`std::io::Write` wrapper. +++ +++Raw hashing is somewhere around 0.25× to 0.65× the speed of the +++previous implementation, depending on the feature configuration +++and whether the CPU supports hardware‐accelerated hashing. (The +++more portable assembly in `sha1-asm` that doesn’t require the SHA +++instruction set doesn’t seem to speed things up that much; in fact, +++`sha1_smol` somehow regularly beats the assembly code used by `sha1` +++on my i9‐9880H MacBook Pro! Presumably this is why that path was +++removed in newer versions of the `sha1` crate.) +++ +++Performance on an end‐to‐end `gix no-repo pack verify` benchmark +++using pack files from the Linux kernel Git server measures around +++0.41× to 0.44× compared to the base commit on an M2 Max and a +++Ryzen 7 5800X, both of which have hardware instructions for SHA‐1 +++acceleration that the previous implementation uses but this one does +++not. On the i9‐9880H, it’s around 0.58× to 0.60× the speed; +++the slowdown is reduced by the older hardware’s lack of SHA‐1 +++instructions. +++ +++The `sha1collisiondetection` crate from the Sequoia PGP project, +++based on a modified C2Rust translation of the library used by Git, +++was also considered; although its raw hashing performance seems +++to measure around 1.12–1.15× the speed of `sha1-checked` on +++x86, it’s indistinguishable from noise on the end‐to‐end +++benchmark, and on an M2 Max `sha1-checked` is consistently +++around 1.03× the speed of `sha1collisiondetection` on that +++benchmark. The `sha1collisiondetection` crate has also had a +++soundness issue in the past due to the automatic C translation, +++whereas `sha1-checked` has only one trivial `unsafe` block. On the +++other hand, `sha1collisiondetection` is used by both Sequoia itself +++and the `gitoid` crate, whereas rPGP is the only major user of +++`sha1-checked`. I don’t think there’s a clear winner here. +++ +++The performance regression is very unfortunate, but the [SHAttered] +++attack demonstrated a collision back in 2017, and the 2020 [SHA‐1 is +++a Shambles] attack demonstrated a practical chosen‐prefix collision +++that broke the use of SHA‐1 in OpenPGP, costing $75k to perform, +++with an estimate of $45k to replicate at the time of publication and +++$11k for a classical collision. +++ +++[SHAttered]: https://shattered.io/ +++[SHA‐1 is a Shambles]: https://sha-mbles.github.io/ +++ +++Given the increase in GPU performance and production since then, +++that puts the Git object format squarely at risk. Git mitigated this +++attack in 2017; the algorithm is fairly general and detects all the +++existing public collisions. My understanding is that an entirely new +++cryptanalytic approach would be required to develop a collision attack +++for SHA‐1 that would not be detected with very high probability. +++ +++I believe that the speed penalty could be mitigated, although not +++fully eliminated, by implementing a version of the hardened SHA‐1 +++function that makes use of SIMD. For instance, the assembly code used +++by `openssl speed sha1` on my i9‐9880H measures around 830 MiB/s, +++compared to the winning 580 MiB/s of `sha1_smol`; adding collision +++detection support to that would surely incur a performance penalty, +++but it is likely that it could be much more competitive with +++the performance before this commit than the 310 MiB/s I get with +++`sha1-checked`. I haven’t been able to find any existing work on +++this; it seems that more or less everyone just uses the original +++C library that Git does, presumably because nothing except Git and +++OpenPGP is still relying on SHA‐1 anyway… +++ +++The performance will never compete with the >2 GiB/s that can +++be achieved with the x86 SHA instruction set extension, as the +++`SHA1RNDS4` instruction sadly runs four rounds at a time while the +++collision detection algorithm requires checks after every round, +++but I believe SIMD would still offer a significant improvement, +++and the AArch64 extension seems like it may be more flexible. +++ +++I know that these days the Git codebase has an additional faster +++unsafe API without these checks that it tries to carefully use only +++for operations that do not depend on hashing results for correctness +++or safety. I personally believe that’s not a terribly good idea, +++as it seems easy to misuse in a case where correctness actually does +++matter, but maybe that’s just my Rust safety bias talking. I think +++it would be better to focus on improving the performance of the safer +++algorithm, as I think that many of the operations where the performance +++penalty is the most painful are dealing with untrusted input anyway. +++ +++The `Hasher` struct gets a lot bigger; I don’t know if this is +++an issue or not, but if it is, it could potentially be boxed. +++ +++Closes: #585 +++ +++Backported from upstream, paths and context adapted and non-applicabable parts +++removed. +++Signed-off-by: Fabian Grünbichler +++--- +++ vendor/gix-features-0.39.1/Cargo.toml | 18 +-- +++ vendor/gix-features-0.39.1/src/hash.rs | 183 +------------------------------ +++ vendor/gix-hash-0.15.1/Cargo.toml | 8 ++ +++ vendor/gix-hash-0.15.1/src/hasher/io.rs | 138 +++++++++++++++++++++++ +++ vendor/gix-hash-0.15.1/src/hasher/mod.rs | 90 +++++++++++++++ +++ vendor/gix-hash-0.15.1/src/lib.rs | 5 + +++ 6 files changed, 250 insertions(+), 192 deletions(-) +++ create mode 100644 vendor/gix-hash-0.15.1/src/hasher/io.rs +++ create mode 100644 vendor/gix-hash-0.15.1/src/hasher/mod.rs +++ +++diff --git a/vendor/gix-features-0.39.1/Cargo.toml b/vendor/gix-features-0.39.1/Cargo.toml +++index 88ae0b8..1f7b2fb 100644 +++--- a/vendor/gix-features-0.39.1/Cargo.toml ++++++ b/vendor/gix-features-0.39.1/Cargo.toml +++@@ -91,14 +91,6 @@ default-features = false +++ version = "29.0.0" +++ optional = true +++ +++-[dependencies.sha1] +++-version = "0.10.0" +++-optional = true +++- +++-[dependencies.sha1_smol] +++-version = "1.0.0" +++-optional = true +++- +++ [dependencies.thiserror] +++ version = "2.0.0" +++ optional = true +++@@ -115,7 +107,7 @@ default-features = false +++ cache-efficiency-debug = [] +++ crc32 = ["dep:crc32fast"] +++ default = [] +++-fast-sha1 = ["dep:sha1"] ++++fast-sha1 = [] +++ fs-read-dir = ["dep:gix-utils"] +++ fs-walkdir-parallel = [ +++ "dep:jwalk", +++@@ -131,9 +123,10 @@ progress = ["prodash"] +++ progress-unit-bytes = [ +++ "dep:bytesize", +++ "prodash?/unit-bytes", ++++ "gix-hash/progress-unit-bytes", +++ ] +++ progress-unit-human-numbers = ["prodash?/unit-human"] +++-rustsha1 = ["dep:sha1_smol"] ++++rustsha1 = [] +++ tracing = ["gix-trace/tracing"] +++ tracing-detail = ["gix-trace/tracing-detail"] +++ walkdir = [ +++@@ -162,11 +155,6 @@ zlib-stock = [ +++ "flate2?/zlib", +++ ] +++ +++-[target.'cfg(all(any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64"), not(target_os = "windows")))'.dependencies.sha1] +++-version = "0.10.0" +++-features = ["asm"] +++-optional = true +++- +++ [target."cfg(unix)".dependencies.libc] +++ version = "0.2.119" +++ +++diff --git a/vendor/gix-features-0.39.1/src/hash.rs b/vendor/gix-features-0.39.1/src/hash.rs +++index eebc40f..719c579 100644 +++--- a/vendor/gix-features-0.39.1/src/hash.rs ++++++ b/vendor/gix-features-0.39.1/src/hash.rs +++@@ -1,54 +1,12 @@ +++ //! Hash functions and hash utilities +++-//! +++-//! With the `fast-sha1` feature, the `Sha1` hash type will use a more elaborate implementation utilizing hardware support +++-//! in case it is available. Otherwise the `rustsha1` feature should be set. `fast-sha1` will take precedence. +++-//! Otherwise, a minimal yet performant implementation is used instead for a decent trade-off between compile times and run-time performance. +++-#[cfg(all(feature = "rustsha1", not(feature = "fast-sha1")))] +++-mod _impl { +++- use super::Digest; +++- +++- /// A implementation of the Sha1 hash, which can be used once. +++- #[derive(Default, Clone)] +++- pub struct Sha1(sha1_smol::Sha1); +++- +++- impl Sha1 { +++- /// Digest the given `bytes`. +++- pub fn update(&mut self, bytes: &[u8]) { +++- self.0.update(bytes); +++- } +++- /// Finalize the hash and produce a digest. +++- pub fn digest(self) -> Digest { +++- self.0.digest().bytes() +++- } +++- } +++-} +++- +++-/// A hash-digest produced by a [`Hasher`] hash implementation. +++-#[cfg(any(feature = "fast-sha1", feature = "rustsha1"))] +++-pub type Digest = [u8; 20]; +++- +++-#[cfg(feature = "fast-sha1")] +++-mod _impl { +++- use sha1::Digest; +++- +++- /// A implementation of the Sha1 hash, which can be used once. +++- #[derive(Default, Clone)] +++- pub struct Sha1(sha1::Sha1); +++- +++- impl Sha1 { +++- /// Digest the given `bytes`. +++- pub fn update(&mut self, bytes: &[u8]) { +++- self.0.update(bytes); +++- } +++- /// Finalize the hash and produce a digest. +++- pub fn digest(self) -> super::Digest { +++- self.0.finalize().into() +++- } +++- } +++-} +++ ++++// TODO: Remove this. +++ #[cfg(any(feature = "rustsha1", feature = "fast-sha1"))] +++-pub use _impl::Sha1 as Hasher; ++++pub use gix_hash::hasher::{ ++++ hasher, ++++ io::{bytes, bytes_of_file, bytes_with_hasher, Write}, ++++ Digest, Hasher, ++++}; +++ +++ /// Compute a CRC32 hash from the given `bytes`, returning the CRC32 hash. +++ /// +++@@ -71,132 +29,3 @@ pub fn crc32(bytes: &[u8]) -> u32 { +++ h.update(bytes); +++ h.finalize() +++ } +++- +++-/// Produce a hasher suitable for the given kind of hash. +++-#[cfg(any(feature = "rustsha1", feature = "fast-sha1"))] +++-pub fn hasher(kind: gix_hash::Kind) -> Hasher { +++- match kind { +++- gix_hash::Kind::Sha1 => Hasher::default(), +++- } +++-} +++- +++-/// Compute the hash of `kind` for the bytes in the file at `path`, hashing only the first `num_bytes_from_start` +++-/// while initializing and calling `progress`. +++-/// +++-/// `num_bytes_from_start` is useful to avoid reading trailing hashes, which are never part of the hash itself, +++-/// denoting the amount of bytes to hash starting from the beginning of the file. +++-/// +++-/// # Note +++-/// +++-/// * Only available with the `gix-object` feature enabled due to usage of the [`gix_hash::Kind`] enum and the +++-/// [`gix_hash::ObjectId`] return value. +++-/// * [Interrupts][crate::interrupt] are supported. +++-#[cfg(all(feature = "progress", any(feature = "rustsha1", feature = "fast-sha1")))] +++-pub fn bytes_of_file( +++- path: &std::path::Path, +++- num_bytes_from_start: u64, +++- kind: gix_hash::Kind, +++- progress: &mut dyn crate::progress::Progress, +++- should_interrupt: &std::sync::atomic::AtomicBool, +++-) -> std::io::Result { +++- bytes( +++- &mut std::fs::File::open(path)?, +++- num_bytes_from_start, +++- kind, +++- progress, +++- should_interrupt, +++- ) +++-} +++- +++-/// Similar to [`bytes_of_file`], but operates on a stream of bytes. +++-#[cfg(all(feature = "progress", any(feature = "rustsha1", feature = "fast-sha1")))] +++-pub fn bytes( +++- read: &mut dyn std::io::Read, +++- num_bytes_from_start: u64, +++- kind: gix_hash::Kind, +++- progress: &mut dyn crate::progress::Progress, +++- should_interrupt: &std::sync::atomic::AtomicBool, +++-) -> std::io::Result { +++- bytes_with_hasher(read, num_bytes_from_start, hasher(kind), progress, should_interrupt) +++-} +++- +++-/// Similar to [`bytes()`], but takes a `hasher` instead of a hash kind. +++-#[cfg(all(feature = "progress", any(feature = "rustsha1", feature = "fast-sha1")))] +++-pub fn bytes_with_hasher( +++- read: &mut dyn std::io::Read, +++- num_bytes_from_start: u64, +++- mut hasher: Hasher, +++- progress: &mut dyn crate::progress::Progress, +++- should_interrupt: &std::sync::atomic::AtomicBool, +++-) -> std::io::Result { +++- let start = std::time::Instant::now(); +++- // init progress before the possibility for failure, as convenience in case people want to recover +++- progress.init( +++- Some(num_bytes_from_start as prodash::progress::Step), +++- crate::progress::bytes(), +++- ); +++- +++- const BUF_SIZE: usize = u16::MAX as usize; +++- let mut buf = [0u8; BUF_SIZE]; +++- let mut bytes_left = num_bytes_from_start; +++- +++- while bytes_left > 0 { +++- let out = &mut buf[..BUF_SIZE.min(bytes_left as usize)]; +++- read.read_exact(out)?; +++- bytes_left -= out.len() as u64; +++- progress.inc_by(out.len()); +++- hasher.update(out); +++- if should_interrupt.load(std::sync::atomic::Ordering::SeqCst) { +++- return Err(std::io::Error::new(std::io::ErrorKind::Other, "Interrupted")); +++- } +++- } +++- +++- let id = gix_hash::ObjectId::from(hasher.digest()); +++- progress.show_throughput(start); +++- Ok(id) +++-} +++- +++-#[cfg(any(feature = "rustsha1", feature = "fast-sha1"))] +++-mod write { +++- use crate::hash::Hasher; +++- +++- /// A utility to automatically generate a hash while writing into an inner writer. +++- pub struct Write { +++- /// The hash implementation. +++- pub hash: Hasher, +++- /// The inner writer. +++- pub inner: T, +++- } +++- +++- impl std::io::Write for Write +++- where +++- T: std::io::Write, +++- { +++- fn write(&mut self, buf: &[u8]) -> std::io::Result { +++- let written = self.inner.write(buf)?; +++- self.hash.update(&buf[..written]); +++- Ok(written) +++- } +++- +++- fn flush(&mut self) -> std::io::Result<()> { +++- self.inner.flush() +++- } +++- } +++- +++- impl Write +++- where +++- T: std::io::Write, +++- { +++- /// Create a new hash writer which hashes all bytes written to `inner` with a hash of `kind`. +++- pub fn new(inner: T, object_hash: gix_hash::Kind) -> Self { +++- match object_hash { +++- gix_hash::Kind::Sha1 => Write { +++- inner, +++- hash: Hasher::default(), +++- }, +++- } +++- } +++- } +++-} +++-#[cfg(any(feature = "rustsha1", feature = "fast-sha1"))] +++-pub use write::Write; +++diff --git a/vendor/gix-hash-0.15.1/Cargo.toml b/vendor/gix-hash-0.15.1/Cargo.toml +++index 6cb9fc8..a219070 100644 +++--- a/vendor/gix-hash-0.15.1/Cargo.toml ++++++ b/vendor/gix-hash-0.15.1/Cargo.toml +++@@ -46,18 +46,26 @@ optional = true +++ [dependencies.faster-hex] +++ version = "0.9.0" +++ ++++[dependencies.prodash] ++++version = "29" ++++ +++ [dependencies.serde] +++ version = "1.0.114" +++ features = ["derive"] +++ optional = true +++ default-features = false +++ ++++[dependencies.sha1-checked] ++++version = "0.10.0" ++++default-features = false ++++ +++ [dependencies.thiserror] +++ version = "2.0.0" +++ +++ [dev-dependencies] +++ +++ [features] ++++progress-unit-bytes = ["prodash/unit-bytes"] +++ serde = ["dep:serde"] +++ +++ [lints.clippy] +++diff --git a/vendor/gix-hash-0.15.1/src/hasher/io.rs b/vendor/gix-hash-0.15.1/src/hasher/io.rs +++new file mode 100644 +++index 0000000..ec582d9 +++--- /dev/null ++++++ b/vendor/gix-hash-0.15.1/src/hasher/io.rs +++@@ -0,0 +1,138 @@ ++++use crate::{hasher, Hasher}; ++++ ++++// Temporary, to avoid a circular dependency on `gix-features`. ++++/// ++++mod gix_features { ++++ /// ++++ pub mod progress { ++++ pub use prodash::{self, unit, Progress, Unit}; ++++ ++++ /// ++++ #[cfg(feature = "progress-unit-bytes")] ++++ pub fn bytes() -> Option { ++++ Some(unit::dynamic_and_mode( ++++ unit::Bytes, ++++ unit::display::Mode::with_throughput().and_percentage(), ++++ )) ++++ } ++++ ++++ /// ++++ #[cfg(not(feature = "progress-unit-bytes"))] ++++ pub fn bytes() -> Option { ++++ Some(unit::label_and_mode( ++++ "B", ++++ unit::display::Mode::with_throughput().and_percentage(), ++++ )) ++++ } ++++ } ++++} ++++ ++++/// Compute the hash of `kind` for the bytes in the file at `path`, hashing only the first `num_bytes_from_start` ++++/// while initializing and calling `progress`. ++++/// ++++/// `num_bytes_from_start` is useful to avoid reading trailing hashes, which are never part of the hash itself, ++++/// denoting the amount of bytes to hash starting from the beginning of the file. ++++/// ++++/// # Note ++++/// ++++/// * Interrupts are supported. ++++// TODO: Fix link to `gix_features::interrupt`. ++++pub fn bytes_of_file( ++++ path: &std::path::Path, ++++ num_bytes_from_start: u64, ++++ kind: crate::Kind, ++++ progress: &mut dyn gix_features::progress::Progress, ++++ should_interrupt: &std::sync::atomic::AtomicBool, ++++) -> std::io::Result { ++++ bytes( ++++ &mut std::fs::File::open(path)?, ++++ num_bytes_from_start, ++++ kind, ++++ progress, ++++ should_interrupt, ++++ ) ++++} ++++ ++++/// Similar to [`bytes_of_file`], but operates on a stream of bytes. ++++pub fn bytes( ++++ read: &mut dyn std::io::Read, ++++ num_bytes_from_start: u64, ++++ kind: crate::Kind, ++++ progress: &mut dyn gix_features::progress::Progress, ++++ should_interrupt: &std::sync::atomic::AtomicBool, ++++) -> std::io::Result { ++++ bytes_with_hasher(read, num_bytes_from_start, hasher(kind), progress, should_interrupt) ++++} ++++ ++++/// Similar to [`bytes()`], but takes a `hasher` instead of a hash kind. ++++pub fn bytes_with_hasher( ++++ read: &mut dyn std::io::Read, ++++ num_bytes_from_start: u64, ++++ mut hasher: Hasher, ++++ progress: &mut dyn gix_features::progress::Progress, ++++ should_interrupt: &std::sync::atomic::AtomicBool, ++++) -> std::io::Result { ++++ let start = std::time::Instant::now(); ++++ // init progress before the possibility for failure, as convenience in case people want to recover ++++ progress.init( ++++ Some(num_bytes_from_start as gix_features::progress::prodash::progress::Step), ++++ gix_features::progress::bytes(), ++++ ); ++++ ++++ const BUF_SIZE: usize = u16::MAX as usize; ++++ let mut buf = [0u8; BUF_SIZE]; ++++ let mut bytes_left = num_bytes_from_start; ++++ ++++ while bytes_left > 0 { ++++ let out = &mut buf[..BUF_SIZE.min(bytes_left as usize)]; ++++ read.read_exact(out)?; ++++ bytes_left -= out.len() as u64; ++++ progress.inc_by(out.len()); ++++ hasher.update(out); ++++ if should_interrupt.load(std::sync::atomic::Ordering::SeqCst) { ++++ return Err(std::io::Error::new(std::io::ErrorKind::Other, "Interrupted")); ++++ } ++++ } ++++ ++++ let id = crate::ObjectId::from(hasher.digest()); ++++ progress.show_throughput(start); ++++ Ok(id) ++++} ++++ ++++/// A utility to automatically generate a hash while writing into an inner writer. ++++pub struct Write { ++++ /// The hash implementation. ++++ pub hash: Hasher, ++++ /// The inner writer. ++++ pub inner: T, ++++} ++++ ++++impl std::io::Write for Write ++++where ++++ T: std::io::Write, ++++{ ++++ fn write(&mut self, buf: &[u8]) -> std::io::Result { ++++ let written = self.inner.write(buf)?; ++++ self.hash.update(&buf[..written]); ++++ Ok(written) ++++ } ++++ ++++ fn flush(&mut self) -> std::io::Result<()> { ++++ self.inner.flush() ++++ } ++++} ++++ ++++impl Write ++++where ++++ T: std::io::Write, ++++{ ++++ /// Create a new hash writer which hashes all bytes written to `inner` with a hash of `kind`. ++++ pub fn new(inner: T, object_hash: crate::Kind) -> Self { ++++ match object_hash { ++++ crate::Kind::Sha1 => Write { ++++ inner, ++++ hash: Hasher::default(), ++++ }, ++++ } ++++ } ++++} +++diff --git a/vendor/gix-hash-0.15.1/src/hasher/mod.rs b/vendor/gix-hash-0.15.1/src/hasher/mod.rs +++new file mode 100644 +++index 0000000..db4350b +++--- /dev/null ++++++ b/vendor/gix-hash-0.15.1/src/hasher/mod.rs +++@@ -0,0 +1,90 @@ ++++use sha1_checked::CollisionResult; ++++ ++++/// A hash-digest produced by a [`Hasher`] hash implementation. ++++pub type Digest = [u8; 20]; ++++ ++++/// The error returned by [`Hasher::try_finalize()`]. ++++#[derive(Debug, thiserror::Error)] ++++#[allow(missing_docs)] ++++pub enum Error { ++++ #[error("Detected SHA-1 collision attack with digest {digest}")] ++++ CollisionAttack { digest: crate::ObjectId }, ++++} ++++ ++++/// A implementation of the Sha1 hash, which can be used once. ++++/// ++++/// We use [`sha1_checked`] to implement the same collision detection ++++/// algorithm as Git. ++++#[derive(Clone)] ++++pub struct Hasher(sha1_checked::Sha1); ++++ ++++impl Default for Hasher { ++++ #[inline] ++++ fn default() -> Self { ++++ // This matches the configuration used by Git, which only uses ++++ // the collision detection to bail out, rather than computing ++++ // alternate “safe hashes” for inputs where a collision attack ++++ // was detected. ++++ Self(sha1_checked::Builder::default().safe_hash(false).build()) ++++ } ++++} ++++ ++++impl Hasher { ++++ /// Digest the given `bytes`. ++++ pub fn update(&mut self, bytes: &[u8]) { ++++ use sha1_checked::Digest; ++++ self.0.update(bytes); ++++ } ++++ ++++ /// Finalize the hash and produce an object ID. ++++ /// ++++ /// Returns [`Error`] if a collision attack is detected. ++++ #[inline] ++++ pub fn try_finalize(self) -> Result { ++++ match self.0.try_finalize() { ++++ CollisionResult::Ok(digest) => Ok(crate::ObjectId::Sha1(digest.into())), ++++ CollisionResult::Mitigated(_) => { ++++ // SAFETY: `CollisionResult::Mitigated` is only ++++ // returned when `safe_hash()` is on. `Hasher`’s field ++++ // is private, and we only construct it in the ++++ // `Default` instance, which turns `safe_hash()` off. ++++ // ++++ // As of Rust 1.84.1, the compiler can’t figure out ++++ // this function cannot panic without this. ++++ #[allow(unsafe_code)] ++++ unsafe { ++++ std::hint::unreachable_unchecked() ++++ } ++++ } ++++ CollisionResult::Collision(digest) => Err(Error::CollisionAttack { ++++ digest: crate::ObjectId::Sha1(digest.into()), ++++ }), ++++ } ++++ } ++++ ++++ /// Finalize the hash and produce an object ID. ++++ #[inline] ++++ pub fn finalize(self) -> crate::ObjectId { ++++ self.try_finalize().expect("Detected SHA-1 collision attack") ++++ } ++++ ++++ /// Finalize the hash and produce a digest. ++++ #[inline] ++++ pub fn digest(self) -> Digest { ++++ self.finalize() ++++ .as_slice() ++++ .try_into() ++++ .expect("SHA-1 object ID to be 20 bytes long") ++++ } ++++} ++++ ++++/// Produce a hasher suitable for the given kind of hash. ++++#[inline] ++++pub fn hasher(kind: crate::Kind) -> Hasher { ++++ match kind { ++++ crate::Kind::Sha1 => Hasher::default(), ++++ } ++++} ++++ ++++/// Hashing utilities for I/O operations. ++++pub mod io; +++diff --git a/vendor/gix-hash-0.15.1/src/lib.rs b/vendor/gix-hash-0.15.1/src/lib.rs +++index 20cb9c4..924681d 100644 +++--- a/vendor/gix-hash-0.15.1/src/lib.rs ++++++ b/vendor/gix-hash-0.15.1/src/lib.rs +++@@ -13,6 +13,11 @@ +++ mod borrowed; +++ pub use borrowed::{oid, Error}; +++ ++++/// Hash functions and hash utilities ++++pub mod hasher; ++++pub use hasher::io::{bytes, bytes_of_file, bytes_with_hasher}; ++++pub use hasher::{hasher, Hasher}; ++++ +++ mod object_id; +++ pub use object_id::{decode, ObjectId}; +++ diff --cc debian/patches/vendor/libz-sys-allow-cross-building.patch index 0000000000,0000000000,0000000000..407b3a1ed4 new file mode 100644 --- /dev/null +++ b/debian/patches/vendor/libz-sys-allow-cross-building.patch @@@@ -1,0 -1,0 -1,0 +1,32 @@@@ +++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= +++Date: Tue, 8 Oct 2024 12:58:44 +0200 +++Subject: libz-sys: allow cross-building +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++Signed-off-by: Fabian Grünbichler +++--- +++ vendor/libz-sys-1.1.20/build.rs | 8 +++----- +++ 1 file changed, 3 insertions(+), 5 deletions(-) +++ +++diff --git a/vendor/libz-sys-1.1.20/build.rs b/vendor/libz-sys-1.1.20/build.rs +++index cab160a..810084e 100644 +++--- a/vendor/libz-sys-1.1.20/build.rs ++++++ b/vendor/libz-sys-1.1.20/build.rs +++@@ -81,12 +81,10 @@ fn main() { +++ // +++ // Apple platforms have libz.1.dylib, and it's usually available even when +++ // cross compiling (via fat binary or in the target's Xcode SDK) ++++ // ++++ // Debian: allow cross-building! +++ let cross_compiling = target != host; +++- if target.contains("msvc") +++- || target.contains("pc-windows-gnu") +++- || want_static +++- || (cross_compiling && !target.contains("-apple-")) +++- { ++++ if target.contains("msvc") || target.contains("pc-windows-gnu") || want_static { +++ return build_zlib(&mut cfg, &target); +++ } +++ diff --cc debian/patches/vendor/onig_sys-use-system-lib.patch index 0000000000,0000000000,0000000000..ca5724ae86 new file mode 100644 --- /dev/null +++ b/debian/patches/vendor/onig_sys-use-system-lib.patch @@@@ -1,0 -1,0 -1,0 +1,25 @@@@ +++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= +++Date: Wed, 31 Jul 2024 10:29:04 +0200 +++Subject: onig_sys: use system lib +++MIME-Version: 1.0 +++Content-Type: text/plain; charset="utf-8" +++Content-Transfer-Encoding: 8bit +++ +++Signed-off-by: Fabian Grünbichler +++--- +++ vendor/onig_sys-69.8.1/build.rs | 2 +- +++ 1 file changed, 1 insertion(+), 1 deletion(-) +++ +++diff --git a/vendor/onig_sys-69.8.1/build.rs b/vendor/onig_sys-69.8.1/build.rs +++index 138e9d8..be1e128 100644 +++--- a/vendor/onig_sys-69.8.1/build.rs ++++++ b/vendor/onig_sys-69.8.1/build.rs +++@@ -219,7 +219,7 @@ fn bindgen_headers(path: &str) { +++ +++ pub fn main() { +++ let link_type = link_type_override(); +++- let require_pkg_config = env_var_bool("RUSTONIG_SYSTEM_LIBONIG").unwrap_or(false); ++++ let require_pkg_config = env_var_bool("RUSTONIG_SYSTEM_LIBONIG").unwrap_or(true); +++ +++ if require_pkg_config || link_type == Some(LinkType::Dynamic) { +++ let mut conf = Config::new(); diff --cc debian/prune-checksums index 0000000000,0000000000,0000000000..0c895cff44 new file mode 100755 --- /dev/null +++ b/debian/prune-checksums @@@@ -1,0 -1,0 -1,0 +1,47 @@@@ +++#!/usr/bin/python3 +++# Copyright: 2015-2017 The Debian Project +++# License: MIT or Apache-2.0 +++# +++# Helper to remove removed-files from .cargo-checksum +++# TODO: rewrite to perl and add to dh-cargo, maybe? +++ +++from collections import OrderedDict +++import argparse +++import json +++import os +++import sys +++ +++def prune_keep(cfile): +++ with open(cfile) as fp: +++ sums = json.load(fp, object_pairs_hook=OrderedDict) +++ +++ oldfiles = sums["files"] +++ newfiles = OrderedDict([entry for entry in oldfiles.items() if os.path.exists(entry[0])]) +++ sums["files"] = newfiles +++ +++ if len(oldfiles) == len(newfiles): +++ return +++ +++ with open(cfile, "w") as fp: +++ json.dump(sums, fp, separators=(',', ':')) +++ +++def prune(cfile): +++ with open(cfile, "r+") as fp: +++ sums = json.load(fp, object_pairs_hook=OrderedDict) +++ sums["files"] = {} +++ fp.seek(0) +++ json.dump(sums, fp, separators=(',', ':')) +++ fp.truncate() +++ +++if __name__ == "__main__": +++ parser = argparse.ArgumentParser() +++ parser.add_argument("-k", "--keep", action="store_true", help="keep " +++ "checksums of files that still exist, and assume they haven't changed.") +++ parser.add_argument('crates', nargs=argparse.REMAINDER, +++ help="crates whose checksums to prune. (default: ./)") +++ args = parser.parse_args(sys.argv[1:]) +++ crates = args.crates or ["."] +++ f = prune_keep if args.keep else prune +++ for c in crates: +++ cfile = os.path.join(c, ".cargo-checksum.json") if os.path.isdir(c) else c +++ f(cfile) diff --cc debian/prune-unused-deps index 0000000000,0000000000,0000000000..9faacf15b4 new file mode 100755 --- /dev/null +++ b/debian/prune-unused-deps @@@@ -1,0 -1,0 -1,0 +1,70 @@@@ +++#!/bin/bash +++# Run this script in an unpacked upstream tarball directory, and it will update +++# (i.e. overwrite) the "unused deps" part of Files-Excluded in d/copyright. +++ +++set -e +++ +++scriptdir=$(dirname "$(dirname "$(readlink -f "$0")")") +++had_config_toml=$(if test -e "$scriptdir/debian/config.toml"; then echo true; else echo false; fi) +++ +++( cd "$scriptdir" && debian/rules debian/config.toml ) +++cp "$scriptdir/debian/config.toml" config.toml +++ +++for i in "$scriptdir/debian/patches"/prune/d-00*.patch; do +++ "$scriptdir/debian/ensure-patch" -N "$i" +++done +++ +++# keep in sync with d/rules +++workspaces=". src/bootstrap library src/tools/rust-analyzer src/tools/cargo src/tools/rustbook" +++for ws in $workspaces; do +++ test -f "$ws/Cargo.lock.org" || cp "$ws/Cargo.lock" "$ws/Cargo.lock.orig" +++ rm -f "$ws/Cargo.lock" +++done +++ +++find vendor -name .cargo-checksum.json -execdir "$scriptdir/debian/prune-checksums" "{}" + +++ +++for ws in $workspaces; do +++ (cd "$ws" && cargo update --offline) +++done +++ +++needed_crates() { +++ for ws in $workspaces; do +++ cat "$ws/Cargo.lock"; +++ done \ +++ | sed -z -e 's/\nname = /name = /g' -e 's/\nversion = /version = /g' \ +++ | sed -ne 's/\[\[package\]\]name = "\(.*\)"version = "\(.*\)"/\1 \2/gp' +++} +++ +++ghetto_parse_cargo() { +++ cat "$1" \ +++ | tr '\n' '\t' \ +++ | sed -e 's/\t\[/\n[/g' \ +++ | perl -ne 'print if s/^\[(?:package|project)\].*\tname\s*=\s*"(.*?)".*\tversion\s*=\s*"(.*?)".*/\1 \2/g' +++} +++ +++pruned_paths() { +++ for i in vendor/*/Cargo.toml; do +++ pkgnamever= +++ pkgnamever=$(ghetto_parse_cargo "$i") +++ if [ -z "$pkgnamever" ]; then +++ echo >&2 "failed to parse: $i" +++ exit 1 +++ fi +++ echo "$pkgnamever $i" +++ done | grep -v -F -f <(needed_crates) | cut '-d ' -f3 | while read x; do +++ echo " $(dirname $x)" +++ done +++} +++ +++header='# DO NOT EDIT below, AUTOGENERATED' +++footer='# DO NOT EDIT above, AUTOGENERATED' +++{ +++echo "$header" +++pruned_paths +++echo "$footer" +++} > $scriptdir/debian/copyright.unused-deps +++ +++cd $scriptdir/debian +++sed -i -e "/^$header/,/^$footer/d" -e '/^# unused dependencies/rcopyright.unused-deps' copyright +++rm copyright.unused-deps +++$had_config_toml || rm "$scriptdir/debian/config.toml" diff --cc debian/rebase-patches.sh index 0000000000,0000000000,0000000000..cc1cd77625 new file mode 100755 --- /dev/null +++ b/debian/rebase-patches.sh @@@@ -1,0 -1,0 -1,0 +1,62 @@@@ +++#!/bin/bash +++set -e +++ +++ver="$1" +++dfsg="${2:-+dfsg1}" +++upstream_tag="upstream/${ver/\~/_}${dfsg/\~/_}" +++ +++git show -s upstream/experimental +++git show -s debian/experimental +++printf "\ngit top-level dir: %s\n" "$(git rev-parse --show-toplevel)" +++printf "version: $ver\n" +++ +++if ! git merge-base --is-ancestor upstream/experimental debian/experimental; then +++ echo >&2 "upstream/experimental is not an ancestor of debian/experimental" +++fi +++if git rev-parse "${upstream_tag}" 2>/dev/null >/dev/null; then +++ echo >&2 "tag already exists: ${upstream_tag}" +++fi +++ +++read -p "continue? [y/N] " x +++if [ "$x" != "y" ]; then exit 1; fi +++ +++cd "$(git rev-parse --show-toplevel)" +++git branch -f upstream/rebase-patches upstream/experimental +++git branch -f debian/rebase-patches debian/experimental +++git checkout debian/rebase-patches +++ +++gbp pq drop || true +++ +++read -p "import patches before upstream tarball? [Y/n]" x +++if [ "$x" != "n" ]; then +++ gbp pq import --no-patch-numbers +++ imported=1 +++fi +++ +++gbp import-orig "../rustc_${ver}${dfsg}.orig.tar.xz" \ +++ --upstream-branch=upstream/rebase-patches \ +++ --debian-branch=debian/rebase-patches \ +++ --no-sign-tags --no-pristine-tar --no-symlink-orig +++ +++if [ "$imported" == "" ]; then +++ gbp pq import --no-patch-numbers || ( git tag -d "${upstream_tag}" && false) +++fi +++ +++# rebase here +++echo "$0: Now manually rebase - run 'git rebase debian/rebase-patches'" +++echo "$0: There may be conflicts; follow the instructions that git tells you." +++echo "$0: When done, exit the child shell with ctrl-D" +++$SHELL +++ +++gbp pq export --no-patch-numbers +++git add debian/patches +++git commit -m "early-stage update of patches for ${ver}${dfsg}" +++git checkout . +++git rebase @~ --onto=debian/experimental +++git branch -f debian/experimental +++git checkout debian/experimental +++ +++# cleanup +++git tag -d "${upstream_tag}" || true +++git branch -D upstream/rebase-patches || true +++git branch -D debian/rebase-patches || true diff --cc debian/rules index 0000000000,0000000000,0000000000..7f8212bdf9 new file mode 100755 --- /dev/null +++ b/debian/rules @@@@ -1,0 -1,0 -1,0 +1,588 @@@@ +++#!/usr/bin/make -f +++# -*- makefile -*- +++ +++include /usr/share/dpkg/pkg-info.mk +++include /usr/share/dpkg/vendor.mk +++include /usr/share/dpkg/architecture.mk +++SED_VERSION_SHORT := sed -re 's/([^.]+)\.([^.]+)\..*/\1.\2/' +++RUST_VERSION := $(shell echo '$(DEB_VERSION_UPSTREAM)' | $(SED_VERSION_SHORT)) +++RUST_LONG_VERSION := $(shell echo '$(DEB_VERSION_UPSTREAM)' | sed -re 's/([^+]+).*/\1/') +++LIBSTD_PKG := libstd-rust-$(RUST_VERSION) +++# Sed expression that matches the "rustc" we have in our Build-Depends field +++SED_RUSTC_BUILDDEP := sed -ne "/^Build-Depends:/,/^[^[:space:]\#]/{/^ *rustc:native .*,/p}" debian/control +++# Version of /usr/bin/rustc +++LOCAL_RUST_VERSION := $(shell rustc --version --verbose | sed -ne 's/^release: //p') +++ +++include /usr/share/dpkg/buildflags.mk +++# needed for cross-compilation to avoid passing host CFLAGS to the BUILD +++# compiler +++export TARGET_CFLAGS = $(CFLAGS) +++export TARGET_CXXFLAGS = $(CXXFLAGS) +++export TARGET_CPPFLAGS = $(CPPFLAGS) +++export TARGET_LDFLAGS = $(LDFLAGS) +++unexport CFLAGS CXXFLAGS CPPFLAGS LDFLAGS +++export CARGO_HOME = $(CURDIR)/debian/cargo +++ +++# Defines DEB_*_RUST_TYPE triples +++include debian/architecture.mk +++# for dh_install substitution variable +++export DEB_HOST_RUST_TYPE +++ +++# for dh_install substitution variable +++export RUST_LONG_VERSION +++ +++DEB_DESTDIR := $(CURDIR)/debian/tmp +++ +++# Use system LLVM (comment out to use vendored LLVM) +++LLVM_VERSION = 19 +++OLD_LLVM_VERSION = 18 +++# Cargo-specific flags +++export LIBSSH2_SYS_USE_PKG_CONFIG=1 +++# Make it easier to test against a custom LLVM +++ifneq (,$(LLVM_DESTDIR)) +++LLVM_LIBRARY_PATH := $(LLVM_DESTDIR)/usr/lib/$(DEB_HOST_MULTIARCH):$(LLVM_DESTDIR)/usr/lib +++LD_LIBRARY_PATH := $(if $(LD_LIBRARY_PATH),$(LD_LIBRARY_PATH):$(LLVM_LIBRARY_PATH),$(LLVM_LIBRARY_PATH)) +++export LD_LIBRARY_PATH +++endif +++ +++# Required for profiler builtin +++CLANG_RT_ARCH := $(DEB_TARGET_GNU_CPU) +++ifeq (i386,$(DEB_TARGET_ARCH)) +++CLANG_RT_ARCH = i386 +++endif +++ifeq (armhf,$(DEB_TARGET_ARCH)) +++CLANG_RT_ARCH = armhf +++endif +++ +++ifneq (,$(filter $(DEB_TARGET_ARCH),sparc64 mips64el hurd-i386 hurd-amd64)) +++# sparc64: see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1061125 +++# mips64el: has profiler, but buggy atm (32-bit overflow in some counter?) +++CLANG_RT_ARCH = +++PROFILER = "false" +++PROFILER_PATH = "" +++else +++PROFILER = "true" +++PROFILER_PATH = profiler = \"/usr/lib/llvm-$(LLVM_VERSION)/lib/clang/$(LLVM_VERSION)/lib/linux/libclang_rt.profile-$(CLANG_RT_ARCH).a\" +++endif +++ +++ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) +++NJOBS := -j $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) +++endif +++RUSTBUILD_COMMON = RUST_BACKTRACE=1 python3 src/bootstrap/bootstrap.py +++RUSTBUILD = $(RUSTBUILD_COMMON) $(NJOBS) +++# force reproducibility +++RUSTBUILD_DOCS = $(RUSTBUILD_COMMON) -j1 +++RUSTBUILD_FLAGS = --stage 2 --config debian/config.toml --on-fail env +++# rust-tidy depends on lots of modules that we strip out of the build. +++# it also tries to access the network for some reason. so just disable it. +++RUSTBUILD_TEST = $(RUSTBUILD) test --no-fail-fast --exclude src/tools/tidy +++# To run a specific test, run something like: +++# $ debian/rules override_dh_auto_test-arch \ +++# RUSTBUILD_TEST_FLAGS="src/test/run-make --test-args extern-fn-struct" +++# See src/bootstrap/README.md for more options. +++RUSTBUILD_TEST_FLAGS = +++ +++# https://github.com/rust-lang/rust/issues/89744 +++# TODO: remove when we update cargo to 1.55 / 0.56 +++# upstream bug still exists and is under investigation, but is hidden by newer cargo +++export CARGO_PROFILE_RELEASE_BUILD_OVERRIDE_OPT_LEVEL=0 +++ +++update-version: +++ oldver=$(shell $(SED_RUSTC_BUILDDEP) | sed -ne 's/.*(<= \(.*\)).*/\1/gp' | $(SED_VERSION_SHORT)); \ +++ newver=$(RUST_VERSION); \ +++ debian/update-version.sh $$oldver $$newver $(RUST_LONG_VERSION) $(CARGO_NEW) +++ +++# Below we detect how we're supposed to bootstrap the stage0 compiler. See +++# README.Debian for more details of the cases described below. +++# +++PRECONFIGURE_CHECK = : +++HAVE_BINARY_TARBALL := $(shell ls -1 stage0/*/*$(DEB_HOST_RUST_TYPE)* 2>/dev/null | wc -l) +++DOWNLOAD_BOOTSTRAP := false +++# allow not using the binary tarball although it exists +++#ifneq (,$(filter $(DEB_HOST_ARCH), amd64 arm64 armhf i386 powerpc ppc64el s390x)) +++# HAVE_BINARY_TARBALL := 0 +++#endif +++ifeq (0,$(HAVE_BINARY_TARBALL)) +++ # Case A (Building from source): the extracted source tree does not include +++ # a bootstrapping tarball for the current architecture e.g. because the +++ # distro already has a rustc for this arch, or the uploader expects that +++ # this requirement be fulfilled in some other way. +++ # +++ # Case A-1: the builder did not select the "pkg.rustc.dlstage0" build profile. +++ # In this case, we use the distro's rustc - either the previous or current version. +++ ifeq (,$(findstring pkg.rustc.dlstage0,$(DEB_BUILD_PROFILES))) +++ # Make it easier to test against a custom rustc +++ ifneq (,$(RUST_DESTDIR)) +++ RUST_LIBRARY_PATH := $(RUST_DESTDIR)/usr/lib/$(DEB_HOST_MULTIARCH):$(RUST_DESTDIR)/usr/lib +++ LD_LIBRARY_PATH := $(if $(LD_LIBRARY_PATH),$(LD_LIBRARY_PATH):$(RUST_LIBRARY_PATH),$(RUST_LIBRARY_PATH)) +++ export LD_LIBRARY_PATH +++ endif +++ # +++ # Case A-2: the builder selected the "dlstage0" build profile. +++ # In this case, the rust build scripts will download a stage0 into stage0/ and use that. +++ # We don't need to do anything specific in this build file, so this case is empty. +++ else +++ DOWNLOAD_BOOTSTRAP := true +++ endif +++else +++ # Case B (Bootstrapping a new distro): the extracted source tree does +++ # include a bootstrapping tarball for the current architecture; see the +++ # `source_orig-stage0` target below on how to build this. +++ # +++ # In this case, we'll bootstrap from the stage0 given in that tarball. +++ # To ensure the uploader of the .dsc didn't make a mistake, we first check +++ # that rustc isn't a Build-Depends for the current architecture. +++ ifneq (,$(shell $(SED_RUSTC_BUILDDEP))) +++ ifeq (,$(shell $(SED_RUSTC_BUILDDEP) | grep '!$(DEB_HOST_ARCH)')) +++ PRECONFIGURE_CHECK = $(error found matches for stage0/*/*$(DEB_HOST_RUST_TYPE)*, \ +++ but rustc might be a Build-Depends for $(DEB_HOST_ARCH)) +++ endif +++ endif +++endif +++ +++BUILD_DOCS := true +++ifneq (,$(findstring nodoc,$(DEB_BUILD_PROFILES))) +++ BUILD_DOCS := false +++endif +++ifneq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS))) +++ BUILD_DOCS := false +++endif +++ +++BUILD_WASM := true +++WASM_TARGETS := "wasm32-unknown-unknown,wasm32-wasip1,wasm32-wasip2" +++ifneq (,$(findstring nowasm,$(DEB_BUILD_PROFILES))) +++ BUILD_WASM := false +++endif +++ +++WINDOWS_SUPPORT := amd64 i386 +++BUILD_WINDOWS := false +++ifneq (,$(findstring pkg.rustc.windows,$(DEB_BUILD_PROFILES))) +++ BUILD_WINDOWS := true +++endif +++ifeq (,$(filter $(DEB_HOST_ARCH), $(WINDOWS_SUPPORT))) +++ BUILD_WINDOWS := false +++else +++ ifeq (,$(filter $(DEB_BUILD_ARCH), $(WINDOWS_SUPPORT))) +++ ifeq (true,$(BUILD_WINDOWS)) +++ $(error cannot cross-compile from $(DEB_BUILD_ARCH) to $(DEB_HOST_ARCH) with "pkg.rustc.windows" in DEB_BUILD_PROFILES) +++ endif +++ endif +++ ifeq (i386,$(DEB_HOST_ARCH)) +++ WINDOWS_ARCH := i686 +++ else +++ WINDOWS_ARCH := x86_64 +++ endif +++endif +++# for dh_install substitution variable +++export WINDOWS_ARCH +++ +++MAKE_OPTIMISATIONS := true +++ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) +++ MAKE_OPTIMISATIONS := false +++endif +++ +++VERBOSITY_SUB := $(words $(filter terse,$(DEB_BUILD_OPTIONS))) +++VERBOSITY_ADD := $(words $(filter verbose,$(DEB_BUILD_OPTIONS))) +++VERBOSITY := $(shell expr 2 + $(VERBOSITY_ADD) - $(VERBOSITY_SUB)) +++ +++ifeq ($(shell test $(VERBOSITY) -ge 3; echo $$?),0) +++ export DH_VERBOSE=1 +++endif +++ +++ifeq ($(shell test $(VERBOSITY) -le 0; echo $$?),0) +++ export DH_QUIET=1 +++.SILENT: +++endif +++ +++# Build products or non-source files in src/, that shouldn't go in rust-src +++SRC_CLEAN = src/bootstrap/bootstrap.pyc \ +++ src/bootstrap/__pycache__ \ +++ src/etc/__pycache__/ +++ +++# Try to work around #933045 +++ifneq (,$(filter $(DEB_BUILD_ARCH), mips mipsel)) +++ SYSTEM_WORKAROUNDS += export MALLOC_ARENA_MAX=1; +++endif +++ +++%: +++ $(SYSTEM_WORKAROUNDS) dh $@ --parallel --with bash-completion +++ +++.PHONY: .dbg-windows +++.dbg-windows: +++ @echo host=$(DEB_BUILD_ARCH) target=$(DEB_HOST_ARCH) BUILD_WINDOWS=$(BUILD_WINDOWS) WINDOWS_ARCH=$(WINDOWS_ARCH) +++ +++.PHONY: build +++build: +++ $(SYSTEM_WORKAROUNDS) dh $@ --parallel --with bash-completion +++ +++override_dh_clean: +++ # Upstream contains a lot of these +++ dh_clean -XCargo.toml.orig +++ +++debian/config.toml: debian/config.toml.in debian/rules +++ u="$(DEB_VERSION_UPSTREAM)"; \ +++ if [ "$$u" != "$${u%~beta.*+dfsg*}" ]; then channel="beta"; \ +++ else channel="stable"; fi; \ +++ m4 -DRELEASE_CHANNEL="$$channel" \ +++ -DDEB_BUILD_RUST_TYPE="$(DEB_BUILD_RUST_TYPE)" \ +++ -DDEB_HOST_RUST_TYPE="$(DEB_HOST_RUST_TYPE)" \ +++ -DDEB_TARGET_RUST_TYPE="$(DEB_TARGET_RUST_TYPE)" \ +++ -DDEB_BUILD_GNU_TYPE="$(DEB_BUILD_GNU_TYPE)" \ +++ -DDEB_HOST_GNU_TYPE="$(DEB_HOST_GNU_TYPE)" \ +++ -DDEB_TARGET_GNU_TYPE="$(DEB_TARGET_GNU_TYPE)" \ +++ -DMAKE_OPTIMISATIONS="$(MAKE_OPTIMISATIONS)" \ +++ -DVERBOSITY="$(VERBOSITY)" \ +++ -DLLVM_DESTDIR="$(LLVM_DESTDIR)" \ +++ -DLLVM_VERSION="$(LLVM_VERSION)" \ +++ -DRUST_DESTDIR="$(RUST_DESTDIR)" \ +++ -DPROFILER="$(PROFILER)" \ +++ -DPROFILER_PATH="$(PROFILER_PATH)" \ +++ -DWINDOWS_ARCH="$(WINDOWS_ARCH)" \ +++ "$<" > "$@" +++ if $(DOWNLOAD_BOOTSTRAP) || [ $(HAVE_BINARY_TARBALL) != 0 ]; \ +++ then sed -i -e '/^rustc = /d' -e '/^cargo = /d' "$@"; fi +++# Work around low-memory (32-bit) architectures: https://github.com/rust-lang/rust/issues/45854 +++# otherwise they fail to mmap rustc_driver when building rustdoc in >1.60 +++ if [ $(DEB_BUILD_ARCH_BITS) = "32" ]; then \ +++ sed -i -e 's/^debuginfo-level = .*/debuginfo-level = 0/g' "$@"; \ +++ fi +++ +++check-no-old-llvm: +++ # fail the build if we have any instances of OLD_LLVM_VERSION in debian, except for debian/changelog +++ ! grep --color=always -i '\(clang\|ll\(..\|d\)\)-\?$(subst .,\.,$(OLD_LLVM_VERSION))' --exclude=changelog --exclude=copyright --exclude='*.patch' --exclude-dir='.debhelper' -R debian +++.PHONY: check-no-old-llvm +++ +++extra-vendor: +++ if [ -d extra ]; then \ +++ cd extra; \ +++ for c in *; do \ +++ if [ -e ../vendor/"$$c" ]; then \ +++ mv -v ../vendor/"$$c" ../vendor/"$$c".backup ; \ +++ fi ; \ +++ echo "adding extra vendored dependency '$$c'"; \ +++ cp -r ./"$$c" ../vendor/; \ +++ done; \ +++ fi +++ +++.PHONY: extra-vendor +++ +++debian/dh_auto_configure.stamp: debian/config.toml check-no-old-llvm extra-vendor +++ # fail the build if we accidentally vendored openssl, indicates we pulled in unnecessary dependencies +++ test ! -e vendor/openssl-src-* +++ # fail the build if our version contains ~exp and we are not releasing to experimental +++ v="$(DEB_VERSION)"; test "$$v" = "$${v%~exp*}" -o "$(DEB_DISTRIBUTION)" = "experimental" -o "$(DEB_DISTRIBUTION)" = "UNRELEASED" +++ $(PRECONFIGURE_CHECK) +++ if [ -d stage0 ]; then mkdir -p build && ln -sfT ../stage0 build/cache; fi +++ # work around #842634 +++ if test $$(grep "127.0.0.1\s*localhost" /etc/hosts | wc -l) -gt 1; then \ +++ debian/ensure-patch -N debian/patches-unused/d-test-host-duplicates.patch; fi +++ +++ # allow lock changes during build, but keep originals around in case we need them for rust-src +++ # keep in sync with d/prune-unused-deps +++ for ws in . src/bootstrap library src/tools/rust-analyzer src/tools/cargo src/tools/rustbook; do \ +++ if [ -f "$$ws/Cargo.lock" ]; then mv "$$ws/Cargo.lock" "$$ws/Cargo.lock.orig"; fi \ +++ done +++ # We patched some crates so have to rm the checksums +++ find vendor -name .cargo-checksum.json -execdir "$(CURDIR)/debian/prune-checksums" "{}" + +++ # Link against system liblzma, see https://github.com/alexcrichton/xz2-rs/issues/16 +++ for c in vendor/lzma-sys-*; do \ +++ echo 'fn main() { println!("cargo:rustc-link-lib=lzma"); }' > "$$c/build.rs"; \ +++ done +++ # We don't run ./configure because we use debian/config.toml directly +++ ln -sf debian/config.toml config.toml +++ touch "$@" +++ +++override_dh_auto_configure-arch: debian/dh_auto_configure.stamp +++override_dh_auto_configure-indep: debian/dh_auto_configure.stamp +++ifeq (true,$(BUILD_DOCS)) +++# Change config.toml now and not later, since that might trigger a rebuild +++ sed -i -e 's/^docs = false/docs = true/' debian/config.toml +++endif +++ +++override_dh_auto_clean: +++ $(RM) -rf build tmp debian/cargo_home config.stamp config.mk Makefile +++ $(RM) -rf $(TEST_LOG) debian/config.toml debian/*.stamp +++ $(RM) -rf $(SRC_CLEAN) config.toml +++ +++debian/dh_auto_build.stamp: +++ $(RUSTBUILD) build $(RUSTBUILD_FLAGS) +++ +++override_dh_auto_build-arch: debian/dh_auto_build.stamp +++ifeq (true,$(BUILD_WINDOWS)) +++ $(RUSTBUILD) build $(RUSTBUILD_FLAGS) \ +++ --host $(DEB_BUILD_RUST_TYPE) \ +++ --target $(WINDOWS_ARCH)-pc-windows-gnu \ +++ library/std +++endif +++ +++override_dh_auto_build-indep: debian/dh_auto_build.stamp +++ifeq (true,$(BUILD_WASM)) +++ $(RUSTBUILD) build $(RUSTBUILD_FLAGS) \ +++ --host $(DEB_BUILD_RUST_TYPE) \ +++ --target $(WASM_TARGETS) \ +++ library/std +++endif +++ifeq (true,$(BUILD_DOCS)) +++ $(RUSTBUILD_DOCS) doc $(RUSTBUILD_FLAGS) +++ $(RUSTBUILD_DOCS) doc $(RUSTBUILD_FLAGS) cargo # document cargo APIs +++endif +++ +++TEST_LOG = debian/rustc-tests.log +++# This is advertised as "5 tests failed" in README.Debian because our counting +++# method is imprecise and in practise we count some failures twice. +++# temporarily bumped from 8 to 10 to account for test output changes depending +++# on build path length, bump down again once 1.78 is imported +++FAILURES_ALLOWED = 10 +++ifneq (,$(filter $(DEB_BUILD_ARCH), armhf)) +++# temporarily bumped from 12 to 15, see above +++ FAILURES_ALLOWED = 15 +++endif +++ifneq (,$(filter $(DEB_BUILD_ARCH), armel mips mips64el)) +++ FAILURES_ALLOWED = 24 +++endif +++# workaround broken gdb 13.1 - revert to 24 once fixed +++# #1031946 / #1032785 +++ifneq (,$(filter $(DEB_BUILD_ARCH), mipsel)) +++ FAILURES_ALLOWED = 25 +++endif +++ifneq (,$(filter $(DEB_BUILD_ARCH), ppc64 s390x riscv64)) +++ FAILURES_ALLOWED = 40 +++endif +++ifneq (,$(filter $(DEB_BUILD_ARCH), loong64 powerpc powerpcspe sparc64 x32 hurd-i386 hurd-amd64)) +++ FAILURES_ALLOWED = 180 +++endif +++FAILED_TESTS = grep "FAILED\|^command did not execute successfully" $(TEST_LOG) | grep -v '^test result: FAILED' | grep -v 'FAILED (allowed)' +++# ignore debuginfo failures on armhf due to regression in GDB 11.2 +++# https://sourceware.org/bugzilla/show_bug.cgi?id=29272 +++ifneq (,$(filter $(DEB_BUILD_ARCH), armhf)) +++ FAILED_TESTS += | grep -v '^test \[debuginfo-gdb\] src/test/debuginfo/' +++endif +++override_dh_auto_test-arch: +++ # ensure that rustc_llvm is actually dynamically linked to libLLVM +++ set -e; find build/*/stage2/lib/rustlib/* -name '*rustc_llvm*.so' | \ +++ while read x; do \ +++ stat -c '%s %n' "$$x"; \ +++ objdump -p "$$x" | grep -q "NEEDED.*LLVM"; \ +++ test "$$(stat -c %s "$$x")" -lt 6000000; \ +++ done +++ifeq (, $(filter nocheck,$(DEB_BUILD_PROFILES))) +++ifeq (, $(filter nocheck,$(DEB_BUILD_OPTIONS))) +++ { $(RUSTBUILD_TEST) $(RUSTBUILD_FLAGS) $(RUSTBUILD_TEST_FLAGS); echo $$?; } | tee -a $(TEST_LOG) +++ # test that the log has at least 1 pass, to prevent e.g. #57709 +++ grep -l "^test .* \.\.\. ok$$" $(TEST_LOG) +++ echo "==== Debian rustc test report ===="; \ +++ echo "Specific test failures:"; \ +++ $(FAILED_TESTS); \ +++ num_failures=$$($(FAILED_TESTS) | wc -l); \ +++ exit_code=$$(tail -n1 $(TEST_LOG)); \ +++ echo "Summary: exit code $$exit_code, counted $$num_failures tests failed."; \ +++ echo -n "$(FAILURES_ALLOWED) maximum allowed. "; \ +++ if test "$$num_failures" -eq 0 -a "$$exit_code" -ne 0; then \ +++ echo "Aborting just in case, because we missed counting some test failures."; \ +++ echo "This could happen if we failed to build the tests, or if the testsuite runner is buggy."; \ +++ false; \ +++ elif test "$$num_failures" -le $(FAILURES_ALLOWED); then \ +++ echo "Continuing..."; \ +++ else \ +++ echo "Aborting the build."; \ +++ echo "Check the logs further above for details."; \ +++ false; \ +++ fi +++# don't continue if RUSTBUILD_TEST_FLAGS is non-empty +++ test -z "$(RUSTBUILD_TEST_FLAGS)" +++# don't run windows tests yet +++endif +++endif +++ +++override_dh_auto_test-indep: +++ifeq (, $(filter nocheck,$(DEB_BUILD_PROFILES))) +++ifeq (, $(filter nocheck,$(DEB_BUILD_OPTIONS))) +++ifeq (true,$(BUILD_WASM)) +++ # Ignore failures in these tests, but run them so we see what it's like +++ -PATH=$(CURDIR)/debian/bin:$(PATH) $(RUSTBUILD_TEST) $(RUSTBUILD_FLAGS) $(RUSTBUILD_TEST_FLAGS) \ +++ --host $(DEB_BUILD_RUST_TYPE) \ +++ --target $(WASM_TARGETS) \ +++ library/std +++endif +++ifeq (true,$(BUILD_DOCS)) +++ # Run all rules that test the docs, i.e. that depend on default:doc +++ $(RUSTBUILD_TEST) $(RUSTBUILD_FLAGS) src/tools/linkchecker +++endif +++ test -z "$(RUSTBUILD_TEST_FLAGS)" +++endif +++endif +++ +++run_rustbuild: +++ DESTDIR=$(DEB_DESTDIR) $(RUSTBUILD) $(X_CMD) $(RUSTBUILD_FLAGS) $(X_FLAGS) +++ +++override_dh_prep: +++ dh_prep +++ $(RM) -f debian/dh_auto_install.stamp +++ +++debian/dh_auto_install.stamp: +++ DESTDIR=$(DEB_DESTDIR) $(RUSTBUILD) install $(RUSTBUILD_FLAGS) +++ +++ mkdir -p $(DEB_DESTDIR)/usr/lib/$(DEB_HOST_MULTIARCH)/ +++ mv $(DEB_DESTDIR)/usr/lib/lib*.so $(DEB_DESTDIR)/usr/lib/$(DEB_HOST_MULTIARCH)/ +++ rm $(DEB_DESTDIR)/usr/lib/rustlib/$(DEB_HOST_RUST_TYPE)/lib/libstd-*.so +++ +++ # Replace duplicated compile-time/run-time dylibs with symlinks +++ @set -e; \ +++ for f in $(DEB_DESTDIR)/usr/lib/rustlib/$(DEB_HOST_RUST_TYPE)/lib/lib*.so; do \ +++ name=$${f##*/}; \ +++ if [ -f "$(DEB_DESTDIR)/usr/lib/$(DEB_HOST_MULTIARCH)/$$name" ]; then \ +++ echo "ln -sf ../../../$(DEB_HOST_MULTIARCH)/$$name $$f"; \ +++ ln -sf ../../../$(DEB_HOST_MULTIARCH)/$$name $$f; \ +++ fi; \ +++ done +++ +++ # Remove Cargo made package cache +++ rm -vf $(CURDIR)/debian/cargo/.package-cache +++ rm -vf $(CURDIR)/debian/cargo/.package-cache-mutate +++ rm -vf $(CURDIR)/debian/cargo/.global-cache +++ +++ touch "$@" +++ +++override_dh_auto_install-arch: debian/dh_auto_install.stamp +++ifeq (true,$(BUILD_WINDOWS)) +++ DESTDIR=$(DEB_DESTDIR) $(RUSTBUILD) install $(RUSTBUILD_FLAGS) \ +++ --host $(DEB_BUILD_RUST_TYPE) \ +++ --target $(WINDOWS_ARCH)-pc-windows-gnu \ +++ library/std +++endif +++ # Remove Cargo made package cache +++ rm -vf $(CURDIR)/debian/cargo/.package-cache +++ rm -vf $(CURDIR)/debian/cargo/.package-cache-mutate +++ rm -vf $(CURDIR)/debian/cargo/.global-cache +++ +++ +++override_dh_auto_install-indep: debian/dh_auto_install.stamp +++ifeq (true,$(BUILD_WASM)) +++ DESTDIR=$(DEB_DESTDIR) $(RUSTBUILD) install $(RUSTBUILD_FLAGS) \ +++ --host $(DEB_BUILD_RUST_TYPE) \ +++ --target $(WASM_TARGETS) \ +++ library/std +++endif +++ifeq (true,$(BUILD_DOCS)) +++ # Install Cargo docs +++ install -d $(DEB_DESTDIR)/usr/share/doc/cargo +++ cp -r $(CURDIR)/build/$(DEB_BUILD_RUST_TYPE)/compiler-doc $(DEB_DESTDIR)/usr/share/doc/cargo/reference +++ # Brute force to remove privacy-breach-logo lintian warning. +++ # We could have updated the upstream sources but it would complexify +++ # the rebase +++ @set -e; \ +++ find $(DEB_DESTDIR)/usr/share/doc/*/html -iname '*.html' | \ +++ while read file; do \ +++ topdir=$$(echo "$$file" | sed 's,^$(DEB_DESTDIR)/usr/share/doc/docs/html/,,; s,/[^/]*$$,/,; s,^[^/]*$$,,; s,[^/]\+/,../,g'); \ +++ sed -i \ +++ -e "s,https://\(doc\|www\).rust-lang.org/\(favicon.ico\|logos/rust-logo-32x32-blk.png\),$${topdir}rust-logo-32x32-blk.png," \ +++ -e 's,\([^,\1,g' \ +++ -e 's,\([^,\1,g' "$$file"; \ +++ done +++ find $(DEB_DESTDIR) \( -iname '*.html' -empty -o -name .lock -o -name '*.inc' \) -delete; +++ +++ # mv cargo book to cargo-docs +++ mv $(DEB_DESTDIR)/usr/share/doc/docs/html/cargo $(DEB_DESTDIR)/usr/share/doc/cargo/book +++endif +++ # Remove Cargo made package cache +++ rm -vf $(CURDIR)/debian/cargo/.package-cache +++ rm -vf $(CURDIR)/debian/cargo/.package-cache-mutate +++ rm -vf $(CURDIR)/debian/cargo/.global-cache +++ +++ +++override_dh_install-indep: +++ dh_install +++ $(RM) -rf $(SRC_CLEAN:%=debian/rust-src/usr/src/rustc-$(RUST_LONG_VERSION)/%) +++ +++ mv debian/rust-src/usr/src/rustc-$(RUST_LONG_VERSION)/library/Cargo.lock.orig \ +++ debian/rust-src/usr/src/rustc-$(RUST_LONG_VERSION)/library/Cargo.lock +++ # Get rid of lintian warnings +++ find debian/rust-src/usr/src/rustc-$(RUST_LONG_VERSION) -type f \ +++ \( -name .gitignore \ +++ -o -name 'LICENSE*' \ +++ -o -name 'LICENCE' \ +++ -o -name 'license' \ +++ -o -name 'COPYING*' \ +++ -o -name '.eslintrc.js' \ +++ \) -delete +++ # Remove files that autoload remote resources, caught by lintian +++ $(RM) -rf debian/rust-src/usr/src/rustc-*/vendor/cssparser-*/docs/*.html +++ $(RM) -rf debian/rust-src/usr/src/rustc-*/vendor/kuchiki-*/docs/*.html +++ $(RM) -rf debian/rust-src/usr/src/rustc-*/vendor/url-*/docs/*.html +++ $(RM) -rf debian/rust-src/usr/src/rustc-*/vendor/xz2-*/.gitmodules +++ +++override_dh_installchangelogs: +++ dh_installchangelogs RELEASES.md +++ +++override_dh_installdocs: +++ dh_installdocs -X.tex -X.aux -X.log -X.out -X.toc +++ +++override_dh_compress: +++ dh_compress -X.woff +++ +++# The below override is disabled on advice from #debian-devel, because: +++# - only shared libs get the "split dbgsym package" treatment by dh_strip; +++# static libs simply get their debuginfo discarded +++# - strip(1) sometimes breaks wasm libs +++# +++#override_dh_strip: +++# # Work around #35733, #468333 +++# find debian/libstd-rust-dev*/ -name '*.rlib' -execdir mv '{}' '{}.a' \; +++# # This is expected to print out lots of "File format unrecognized" warnings about +++# # rust.metadata.bin and *.deflate but the .o files inside the rlibs should be stripped +++# # Some files are still omitted because of #875780 however. +++# dh_strip -v +++# find debian/libstd-rust-dev*/ -name '*.rlib.a' -execdir sh -c 'mv "$$1" "$${1%.a}"' - '{}' \; +++ +++override_dh_dwz: +++ # otherwise rustc gets an empty multifile which lintian errors on, causing +++ # FTP auto-reject. this is a work-around, the lintian bug is #955752 +++ # double up the max entries count, else the build might fail.. +++ dh_dwz --no-dwz-multifile -- -L 100000000 +++ +++override_dh_makeshlibs: +++ dh_makeshlibs -V -N $(LIBSTD_PKG) +++ +++ # dh_makeshlibs doesn't support our "libfoo-version.so" naming +++ # structure, so we have to do this ourselves. +++ mkdir -p debian/$(LIBSTD_PKG)/DEBIAN +++ LC_ALL=C ls debian/$(LIBSTD_PKG)/usr/lib/$(DEB_HOST_MULTIARCH)/lib*.so | \ +++ sed -n 's,^.*/\(lib.*\)-\(.\+\)\.so$$,\1 \2,p' | \ +++ while read name version; do \ +++ echo "$$name $$version $(LIBSTD_PKG) (>= $(DEB_VERSION_UPSTREAM))"; \ +++ done > debian/$(LIBSTD_PKG)/DEBIAN/shlibs +++ +++override_dh_shlibdeps: +++ dh_shlibdeps -- -x$(LIBSTD_PKG) +++ +++QUILT_SPECIAL_SNOWFLAKE_RETURN_CODE = x=$$?; if [ $$x = 2 ]; then exit 0; else exit $$x; fi +++source_orig-stage0: +++ QUILT_PATCHES=debian/patches quilt push -aq; $(QUILT_SPECIAL_SNOWFLAKE_RETURN_CODE) +++ $(MAKE) -f debian/rules clean +++ debian/make_orig-stage0_tarball.sh +++ $(MAKE) -f debian/rules clean +++ QUILT_PATCHES=debian/patches quilt pop -aq; $(QUILT_SPECIAL_SNOWFLAKE_RETURN_CODE) +++ rm -rf .pc +++ +++get_beta_version = \ +++ u="$(DEB_VERSION_UPSTREAM)"; \ +++ if [ "$$u" != "$${u%~beta.*+dfsg*}" ]; then \ +++ newver=$(shell echo $(RUST_VERSION) | perl -lpe 's/(\d+)\.(\d+)/$$1 . "." . ($$2)/e'); \ +++ else \ +++ newver=$(shell echo $(RUST_VERSION) | perl -lpe 's/(\d+)\.(\d+)/$$1 . "." . ($$2+1)/e'); \ +++ fi +++ +++debian/watch-beta: debian/watch-beta.in debian/rules +++ set -e; $(get_beta_version); \ +++ m4 -DOLDVER="$$oldver" -DNEWVER="$$newver.0" "$<" > "$@" +++ +++source_orig-beta: debian/watch-beta +++ uscan $(USCAN_OPTS) $(if $(USCAN_DESTDIR),--destdir=$(USCAN_DESTDIR),) --verbose --watchfile "$<" +++ set -e; $(get_beta_version); \ +++ bd="$(if $(USCAN_DESTDIR),$(USCAN_DESTDIR),..)"; \ +++ tar xf $$bd/rustc-$$newver.0-beta.999-src.tar.xz rustc-beta-src/version; \ +++ bv="$$(sed -re 's/[0-9]+.[0-9]+.[0-9]+-beta.([0-9]+) \(.*\)/\1/g' rustc-beta-src/version)"; \ +++ bash -c 'shopt -s nullglob; for i in '"$$bd"'/rustc*beta.999*; do mv $$i $${i/beta.999/beta.'"$$bv"'}; done'; \ +++ rm -f rustc-beta-src/version; \ +++ rmdir -p rustc-beta-src; \ +++ echo "prepared rustc $$newver.0~beta.$$bv in $$bd" diff --cc debian/rust-analyzer.install index 0000000000,0000000000,0000000000..04b08d8a94 new file mode 100644 --- /dev/null +++ b/debian/rust-analyzer.install @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++usr/bin/rust-analyzer diff --cc debian/rust-clippy.install index 0000000000,0000000000,0000000000..cad917bfcb new file mode 100644 --- /dev/null +++ b/debian/rust-clippy.install @@@@ -1,0 -1,0 -1,0 +1,2 @@@@ +++usr/bin/clippy-driver +++usr/bin/cargo-clippy diff --cc debian/rust-doc.doc-base.book index 0000000000,0000000000,0000000000..80c3e08a89 new file mode 100644 --- /dev/null +++ b/debian/rust-doc.doc-base.book @@@@ -1,0 -1,0 -1,0 +1,13 @@@@ +++Document: rust-book +++Title: The Rust Programming Language +++Section: Programming/Rust +++Abstract: +++ This book will teach you about the Rust Programming Language. Rust is +++ a modern systems programming language focusing on safety and speed. It +++ accomplishes these goals by being memory safe without using garbage +++ collection. +++ +++Format: HTML +++Index: /usr/share/doc/rust-doc/html/book/index.html +++Files: /usr/share/doc/rust-doc/html/book/*.html +++ /usr/share/doc/rust-doc/html/book/*/*.html diff --cc debian/rust-doc.doc-base.reference index 0000000000,0000000000,0000000000..a538f8bcd8 new file mode 100644 --- /dev/null +++ b/debian/rust-doc.doc-base.reference @@@@ -1,0 -1,0 -1,0 +1,11 @@@@ +++Document: rust-reference +++Title: The Rust Reference +++Section: Programming/Rust +++Abstract: +++ This document is the primary reference for the Rust programming +++ language. +++ +++Format: HTML +++Index: /usr/share/doc/rust-doc/html/reference/index.html +++Files: /usr/share/doc/rust-doc/html/reference/*.html +++ /usr/share/doc/rust-doc/html/reference/*/*.html diff --cc debian/rust-doc.docs index 0000000000,0000000000,0000000000..7e9368dc9b new file mode 100644 --- /dev/null +++ b/debian/rust-doc.docs @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++debian/tmp/usr/share/doc/docs/html diff --cc debian/rust-doc.install index 0000000000,0000000000,0000000000..de6024b0c7 new file mode 100644 --- /dev/null +++ b/debian/rust-doc.install @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++debian/icons/rust-logo-32x32-blk.png usr/share/doc/rust-doc/html/ diff --cc debian/rust-gdb.install index 0000000000,0000000000,0000000000..7c1bf5d5dd new file mode 100644 --- /dev/null +++ b/debian/rust-gdb.install @@@@ -1,0 -1,0 -1,0 +1,5 @@@@ +++usr/bin/rust-gdb +++usr/bin/rust-gdbgui +++usr/lib/rustlib/etc/gdb_load_rust_pretty_printers.py +++usr/lib/rustlib/etc/gdb_lookup.py +++usr/lib/rustlib/etc/gdb_providers.py diff --cc debian/rust-gdb.links index 0000000000,0000000000,0000000000..51b82a4b7c new file mode 100644 --- /dev/null +++ b/debian/rust-gdb.links @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++usr/share/man/man1/gdb.1.gz usr/share/man/man1/rust-gdb.1.gz diff --cc debian/rust-lldb.install index 0000000000,0000000000,0000000000..8d5ff5192b new file mode 100644 --- /dev/null +++ b/debian/rust-lldb.install @@@@ -1,0 -1,0 -1,0 +1,4 @@@@ +++usr/bin/rust-lldb +++usr/lib/rustlib/etc/lldb_commands +++usr/lib/rustlib/etc/lldb_lookup.py +++usr/lib/rustlib/etc/lldb_providers.py diff --cc debian/rust-lldb.links index 0000000000,0000000000,0000000000..c5405b57c0 new file mode 100644 --- /dev/null +++ b/debian/rust-lldb.links @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++usr/share/man/man1/lldb-19.1.gz usr/share/man/man1/rust-lldb.1.gz diff --cc debian/rust-llvm.install index 0000000000,0000000000,0000000000..5a80ed18b5 new file mode 100644 --- /dev/null +++ b/debian/rust-llvm.install @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++usr/lib/rustlib/${env:DEB_HOST_RUST_TYPE}/bin/wasm-component-ld diff --cc debian/rust-llvm.links index 0000000000,0000000000,0000000000..6bb2c3a5eb new file mode 100644 --- /dev/null +++ b/debian/rust-llvm.links @@@@ -1,0 -1,0 -1,0 +1,14 @@@@ +++usr/bin/lld-19 usr/bin/rust-lld +++usr/bin/clang-19 usr/bin/rust-clang +++usr/bin/llvm-dwp-19 usr/bin/rust-llvm-dwp +++# for -Z gcc-ld=lld, see compiler/rustc_codegen_ssa/src/back/link.rs for logic +++usr/bin/rust-lld usr/lib/rustlib/${env:DEB_HOST_RUST_TYPE}/bin/gcc-ld/ld +++usr/bin/rust-lld usr/lib/rustlib/${env:DEB_HOST_RUST_TYPE}/bin/gcc-ld/ld64 +++ +++# instead of shipping the one copied by bootstrap, which would be for the wrong +++# architecture in case of a cross build anyway +++usr/bin/llvm-objcopy-19 usr/lib/rustlib/${env:DEB_HOST_RUST_TYPE}/bin/rust-objcopy +++ +++# For applications that use cargo-binutils, e.g. grcov +++usr/bin/llvm-profdata-19 usr/lib/rustlib/${env:DEB_HOST_RUST_TYPE}/bin/llvm-profdata +++usr/bin/llvm-cov-19 usr/lib/rustlib/${env:DEB_HOST_RUST_TYPE}/bin/llvm-cov diff --cc debian/rust-src.install index 0000000000,0000000000,0000000000..4f0a02cced new file mode 100644 --- /dev/null +++ b/debian/rust-src.install @@@@ -1,0 -1,0 -1,0 +1,16 @@@@ +++debian/patches usr/src/rustc-${env:RUST_LONG_VERSION}/debian +++# from src/bootstrap/dist.rs:370 onwards +++COPYRIGHT usr/src/rustc-${env:RUST_LONG_VERSION} +++LICENSE-APACHE usr/src/rustc-${env:RUST_LONG_VERSION} +++LICENSE-MIT usr/src/rustc-${env:RUST_LONG_VERSION} +++CONTRIBUTING.md usr/src/rustc-${env:RUST_LONG_VERSION} +++README.md usr/src/rustc-${env:RUST_LONG_VERSION} +++RELEASES.md usr/src/rustc-${env:RUST_LONG_VERSION} +++configure usr/src/rustc-${env:RUST_LONG_VERSION} +++x.py usr/src/rustc-${env:RUST_LONG_VERSION} +++config.example.toml usr/src/rustc-${env:RUST_LONG_VERSION} +++Cargo.toml usr/src/rustc-${env:RUST_LONG_VERSION} +++src usr/src/rustc-${env:RUST_LONG_VERSION} +++library usr/src/rustc-${env:RUST_LONG_VERSION} +++compiler usr/src/rustc-${env:RUST_LONG_VERSION} +++Cargo.lock usr/src/rustc-${env:RUST_LONG_VERSION} diff --cc debian/rust-src.links index 0000000000,0000000000,0000000000..c1b645bd85 new file mode 100644 --- /dev/null +++ b/debian/rust-src.links @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++usr/src/rustc-${env:RUST_LONG_VERSION} usr/lib/rustlib/src/rust diff --cc debian/rust-src.lintian-overrides index 0000000000,0000000000,0000000000..e9f7780795 new file mode 100644 --- /dev/null +++ b/debian/rust-src.lintian-overrides @@@@ -1,0 -1,0 -1,0 +1,16 @@@@ +++# False positives that change quite often, so just override with a wildcard +++rust-src binary: executable-not-elf-or-script [usr/src/rustc-*/*] +++rust-src binary: package-contains-eslint-config-file usr/src/rustc-*/src/librustdoc/html/static/.eslintrc.js +++rust-src binary: breakout-link usr/lib/rustlib/src/rust -> usr/src/rustc-* +++rust-src binary: embedded-javascript-library * [usr/src/rustc-*/*] +++rust-src binary: national-encoding [usr/src/rustc-*/*] +++ +++rust-src binary: duplicate-font-file * [usr/src/rustc-1.*.*/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/wrench/reftests/text/FreeSans.ttf] +++rust-src binary: duplicate-font-file * [usr/src/rustc-1.*.*/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/wrench/reftests/text/VeraBd.ttf] +++rust-src binary: package-contains-vcs-control-dir [usr/src/rustc-1.*.*/src/tools/cargo/tests/testsuite/cargo_init/mercurial_autodetect/in/.hg/] +++rust-src binary: package-contains-vcs-control-dir [usr/src/rustc-1.*.*/src/tools/cargo/tests/testsuite/cargo_init/simple_hg_ignore_exists/in/.hg/] +++rust-src binary: package-contains-vcs-control-file [usr/src/rustc-1.*.*/src/tools/cargo/tests/testsuite/cargo_init/mercurial_autodetect/out/.hgignore] +++rust-src binary: package-contains-vcs-control-file [usr/src/rustc-1.*.*/src/tools/cargo/tests/testsuite/cargo_init/simple_hg/out/.hgignore] +++rust-src binary: package-contains-vcs-control-file [usr/src/rustc-1.*.*/src/tools/cargo/tests/testsuite/cargo_init/simple_hg_ignore_exists/in/.hgignore] +++rust-src binary: package-contains-vcs-control-file [usr/src/rustc-1.*.*/src/tools/cargo/tests/testsuite/cargo_init/simple_hg_ignore_exists/out/.hgignore] +++rust-src binary: truetype-font-prohibits-installable-embedding (preview/print only) [usr/src/rustc-1.*.*/src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/wrench/reftests/text/VeraBd.ttf] diff --cc debian/rustc.install index 0000000000,0000000000,0000000000..10efe89df1 new file mode 100644 --- /dev/null +++ b/debian/rustc.install @@@@ -1,0 -1,0 -1,0 +1,6 @@@@ +++usr/bin/rustc +++usr/bin/rustdoc +++usr/lib/rustlib/etc/rust_types.py +++usr/libexec/rust-analyzer-proc-macro-srv +++debian/architecture.mk usr/share/rustc/ +++debian/wasi-node usr/share/rustc/bin/ diff --cc debian/rustc.lintian-overrides index 0000000000,0000000000,0000000000..b3d9d2daec new file mode 100644 --- /dev/null +++ b/debian/rustc.lintian-overrides @@@@ -1,0 -1,0 -1,0 +1,7 @@@@ +++# unofficial example script, no dependency needed +++rustc binary: missing-dep-for-interpreter /usr/bin/node (does not satisfy nodejs:any) [usr/share/rustc/bin/wasi-node] +++ +++# symlinks to other programs +++rustc binary: no-manual-page [usr/bin/rust-clang] +++rustc binary: no-manual-page [usr/bin/rust-lld] +++rustc binary: no-manual-page [usr/bin/rust-llvm-dwp] diff --cc debian/rustc.manpages index 0000000000,0000000000,0000000000..f153792b9d new file mode 100644 --- /dev/null +++ b/debian/rustc.manpages @@@@ -1,0 -1,0 -1,0 +1,3 @@@@ +++debian/tmp/usr/share/man/man1/rustc.1 +++debian/tmp/usr/share/man/man1/rustdoc.1 +++ diff --cc debian/rustfmt.install index 0000000000,0000000000,0000000000..e946f2db17 new file mode 100644 --- /dev/null +++ b/debian/rustfmt.install @@@@ -1,0 -1,0 -1,0 +1,2 @@@@ +++usr/bin/rustfmt +++usr/bin/cargo-fmt diff --cc debian/scripts/audit-vendor-source index 0000000000,0000000000,0000000000..08a46d8049 new file mode 100755 --- /dev/null +++ b/debian/scripts/audit-vendor-source @@@@ -1,0 -1,0 -1,0 +1,40 @@@@ +++#!/bin/sh +++# Audit Rust crate source for suspicious files in the current directory, that +++# shouldn't or can't be part of a Debian source package. +++# +++# NOTE: this overwrites & deletes files in the current directory!!! Make a +++# backup before running this script. +++# +++# Usage: $0 [] +++ +++set -e +++ +++whitelist="$1" +++filter_description="$2" +++shift 2 # everything else is args to suspicious-source +++ +++# Remove tiny files 4 bytes or less +++find . -size -4c -type f -delete +++# Remove non-suspicious files, warning on patterns that match nothing +++echo "Excluding (i.e. removing) whitelisted files..." +++grep -v '^#' "$whitelist" | xargs -I% sh -c 'rm -r ./% || true' +++echo "Checking for suspicious files..." +++# Remove cargo metadata files +++find . '(' -name '.cargo-checksum.json' -or -name '.cargo_vcs_info.json' ')' -delete +++# Strip comments & blank lines before testing rust source code - +++# some authors like to write really long comments +++find . -name '*.rs' -execdir sed -i -e '\,^\s*//,d' -e '/^\s*$/d' '{}' \; +++ +++# TODO: merge the -m stuff into suspicious-source(1). +++suspicious-source -v "$@" +++# The following shell snippet is a bit more strict than suspicious-source(1) +++find . -type f -exec file '{}' \; | \ +++ sed -e 's/\btext\b\(.*\), with very long lines/verylongtext\1/g' | \ +++ grep -v '\b\(text\|empty\)\b' || true +++ +++# Most C and JS code should be in their own package +++find . -name '*.c' -o -name '*.js' +++ +++echo "The above files (if any) seem suspicious, please audit them." +++echo "If good, add them to $whitelist." +++echo "If bad, add them to $filter_description." diff --cc debian/scripts/debian-cargo-vendor index 0000000000,0000000000,0000000000..6566b316d1 new file mode 100755 --- /dev/null +++ b/debian/scripts/debian-cargo-vendor @@@@ -1,0 -1,0 -1,0 +1,165 @@@@ +++#!/bin/bash +++# To run this, you need to first install cargo-lock. +++# +++# TODO: this script has a known bug in: if the Debian patches being applied, +++# changes the set of dependencies, then "cargo vendor" is not re-run in order +++# to pick up this new set of dependencies. This is manifested by an error +++# message like: "perhaps a crate was updated and forgotten to be re-vendored?" +++# +++set -e +++ +++SCRIPTDIR="$(dirname "$(readlink -f "$0")")" +++ +++not_needed() { +++ diff -ur packages-before packages-after | grep "^-- " | cut -d' ' -f2-3 +++} +++ +++ghetto_parse_cargo() { +++ cat "$1" \ +++ | tr '\n' '\t' \ +++ | sed -e 's/\t\[/\n[/g' \ +++ | perl -ne 'print if s/^\[(?:package|project)\].*\tname\s*=\s*"(.*?)".*\tversion\s*=\s*"(.*?)".*/\1 \2/g' +++} +++ +++pruned_paths() { +++ for i in vendor/*/Cargo.toml; do +++ pkgnamever= +++ pkgnamever=$(ghetto_parse_cargo "$i") +++ if [ -z "$pkgnamever" ]; then +++ echo >&2 "failed to parse: $i" +++ exit 1 +++ fi +++ echo "$pkgnamever $i" +++ done | grep -F -f <(not_needed) | cut '-d ' -f3 | while read x; do +++ echo " $(dirname $x)" +++ done +++} +++ +++crate_to_debcargo_conf() { +++ echo "$1" | sed -e 's/_/-/g' +++} +++ +++rm -rf vendor/ +++if [ -e "$CARGO_PRE_VENDOR" ]; then +++ "$CARGO_PRE_VENDOR" +++fi +++cargo vendor --verbose vendor/ +++mkdir -p .cargo +++cat >.cargo/config < packages-before +++cp Cargo.lock Cargo.lock.orig +++ +++if [ -d debcargo-conf ]; then ( cd debcargo-conf && git pull ); +++else git clone "${DEBCARGO_CONF:-https://salsa.debian.org/rust-team/debcargo-conf}"; fi +++ +++# keep applying patches, and drop to a subshell for manual fixing, until it succeeds +++while ! ( cd vendor +++x=true +++for i in *; do +++ debname=$(crate_to_debcargo_conf "$i") +++ cd $i +++ # if there is a d/rules then don't mess with it, it's too custom for this +++ # script to deal with - just use the upstream version. example: backtrace-sys +++ # TODO: deal with those better, especially backtrace-sys +++ if [ -e ../../debcargo-conf/src/$debname/debian/rules ]; then +++ echo >&2 "$0: the debcargo-conf for crate $i has a custom rules file, but applying patches anyway" +++ echo >&2 "$0: you may want to examine this situation more closely" +++ fi +++ if [ -d ../../debcargo-conf/src/$debname/debian/patches ]; then +++ echo >&2 "$0: patching $i" +++ mkdir -p debian +++ if [ ! -d debian/patches ]; then +++ cp -a -n "../../debcargo-conf/src/$debname/debian/patches" debian/ +++ fi +++ # first unapply any patches applied in the previous iteration +++ QUILT_PATCHES=debian/patches quilt pop -af +++ QUILT_PATCHES=debian/patches quilt push -a +++ case $? in +++ 0|2) true;; +++ *) echo >&2 "$0: patching $i failed <<<<<<<<<<<<<<<<<<<<<<<<" +++ QUILT_PATCHES=debian/patches quilt pop -af +++ x=false;; +++ esac +++ fi +++ if [ -f ../../debcargo-conf/src/$debname/debian/build.rs ]; then +++ echo >&2 "$0: overwriting build.rs with our custom one" +++ if [ ! -f build.rs.orig ]; then +++ cp -f build.rs build.rs.orig +++ fi +++ cp -f ../../debcargo-conf/src/$i/debian/build.rs build.rs +++ fi +++ cd .. +++done; $x ); do +++ echo >&2 "================================================================================" +++ echo >&2 "$0: You are now in a sub-shell!" +++ echo >&2 "$0: Fix the failed patches in debcargo-conf/, then exit the sub-shell by pressing ctrl-D ONCE." +++ echo >&2 "$0: If you need to abort this process, press ctrl-D then quickly ctrl-C." +++ if [ -f "${SRCDIR:-$PWD}/debian/debcargo-conf.patch" ]; then +++ echo >&2 "$0: Previous patch changes exist, to apply them run:" +++ echo >&2 " $ patch -d vendor -p2 < '${SRCDIR:-$PWD}/debian/debcargo-conf.patch'" +++ fi +++ echo >&2 "================================================================================" +++ bash || true +++ echo >&2 "$0: trying patches again..." +++done +++rm -rf vendor/*/.pc +++find vendor/*/debian/patches -name '*~' -delete || true +++cargo update +++cargo lock list > packages-after +++pruned_paths | while read x; do echo >&2 "$0: removing, because debcargo-conf patches makes it obsolete: $x"; rm -rf "$x"; done +++ +++# remove excluded files +++( cd vendor +++for i in *; do ( +++ debname=$(crate_to_debcargo_conf "$i") +++ shopt -s globstar # needed for double-glob to work in excludes +++ cd $i +++ if [ -e ../../debcargo-conf/src/$debname/debian/rules ]; then +++ echo >&2 "$0: the debcargo-conf for crate $i has a custom rules file, but applying excludes anyway" +++ echo >&2 "$0: you may want to examine this situation more closely" +++ fi +++ if grep -q excludes ../../debcargo-conf/src/$debname/debian/debcargo.toml 2>/dev/null; then +++ sed -nre 's/.*excludes\s*=\s*(\[[^]]*\]).*/\1/p' \ +++ ../../debcargo-conf/src/$i/debian/debcargo.toml \ +++ | python3 -c "import ast, sys; x=ast.literal_eval(sys.stdin.read()); print('\n'.join((i[:-3] if i.endswith('/**') else i) for i in x));" \ +++ | while read x; do echo >&2 "$0: removing, since it's excluded by debcargo-conf: vendor/$i/$x"; rm -rf $x; done +++ fi +++); done; ) +++ +++# TODO: rm special logic from debcargo and put into debcargo-conf instead +++echo >&2 "$0: removing winapi archives" +++rm -rf vendor/winapi-*-pc-windows-gnu/lib/*.a +++ +++echo >&2 "$0: pruning all checksums.." +++for i in vendor/*; do ${SCRIPTDIR}/prune-checksums "$i"; done +++ +++( cd vendor +++for i in *; do ( +++ cd $i +++ debname=$(crate_to_debcargo_conf "$i") +++ if [ -d debian/patches ]; then +++ rm -rf "../../debcargo-conf/src/$debname/debian/patches" +++ cp -a debian/patches "../../debcargo-conf/src/$debname/debian/" +++ fi +++); done; ) +++( cd debcargo-conf +++git add . +++if ! git diff --cached --quiet; then +++ git commit -m "Manual changes from debian-cargo-vendor" +++ git diff @~ > ../../debcargo-conf.patch || true +++ (cd ../.. ; echo >&2 "$0: backed up patch changes to $PWD/debcargo-conf.patch") +++ echo >&2 "$0: you should backport/merge them back into debcargo-conf.git" +++fi +++) +++ +++echo >&2 "$0: cleaning up..." +++rm -rf .cargo Cargo.lock debcargo-conf packages-before packages-after +++ +++echo >&2 "$0: restoring original Cargo.lock" +++mv Cargo.lock.orig Cargo.lock diff --cc debian/scripts/guess-crate-copyright index 0000000000,0000000000,0000000000..15f35f634c new file mode 100755 --- /dev/null +++ b/debian/scripts/guess-crate-copyright @@@@ -1,0 -1,0 -1,0 +1,45 @@@@ +++#!/usr/bin/python3 +++# Copyright: 2015-2017 The Debian Project +++# License: MIT or Apache-2.0 +++# +++# Guess the copyright of a cargo crate by looking at its git history. +++ +++import datetime +++import toml +++import os +++import subprocess +++import sys +++ +++this_year = datetime.datetime.now().year +++crates = sys.argv[1:] +++get_initial_commit = len(crates) == 1 +++ +++for crate in crates: +++ with open(os.path.join(crate, "Cargo.toml")) as fp: +++ data = toml.load(fp) +++ repo = data["package"].get("repository", None) +++ if get_initial_commit and repo: +++ output = subprocess.check_output( +++ """git clone -q --bare "%s" tmp.crate-copyright >&2 && +++cd tmp.crate-copyright && +++git log --format=%%cI --reverse | head -n1 | cut -b1-4 && +++git log --format=%%cI | head -n1 | cut -b1-4 && +++cd .. && +++rm -rf tmp.crate-copyright""" % repo, shell=True).decode("utf-8") +++ first_year, last_year = output.strip().split(maxsplit=2) +++ else: +++ first_year = "20XX" +++ last_year = this_year +++ +++ authors = data["package"].get("authors", ["UNKNOWN AUTHORS"]) +++ +++ print("""Files: {0} +++Copyright: {1} +++License: {2} +++Comment: see {3} +++""".format( +++ os.path.join(crate, "*"), +++ "\n ".join("%s-%s %s" % (first_year, last_year, a.replace(" <>", "")) for a in authors), +++ data["package"].get("license", "???").replace("/", " or "), +++ repo or "???" +++ )) diff --cc debian/scripts/prune-checksums index 0000000000,0000000000,0000000000..0c895cff44 new file mode 100755 --- /dev/null +++ b/debian/scripts/prune-checksums @@@@ -1,0 -1,0 -1,0 +1,47 @@@@ +++#!/usr/bin/python3 +++# Copyright: 2015-2017 The Debian Project +++# License: MIT or Apache-2.0 +++# +++# Helper to remove removed-files from .cargo-checksum +++# TODO: rewrite to perl and add to dh-cargo, maybe? +++ +++from collections import OrderedDict +++import argparse +++import json +++import os +++import sys +++ +++def prune_keep(cfile): +++ with open(cfile) as fp: +++ sums = json.load(fp, object_pairs_hook=OrderedDict) +++ +++ oldfiles = sums["files"] +++ newfiles = OrderedDict([entry for entry in oldfiles.items() if os.path.exists(entry[0])]) +++ sums["files"] = newfiles +++ +++ if len(oldfiles) == len(newfiles): +++ return +++ +++ with open(cfile, "w") as fp: +++ json.dump(sums, fp, separators=(',', ':')) +++ +++def prune(cfile): +++ with open(cfile, "r+") as fp: +++ sums = json.load(fp, object_pairs_hook=OrderedDict) +++ sums["files"] = {} +++ fp.seek(0) +++ json.dump(sums, fp, separators=(',', ':')) +++ fp.truncate() +++ +++if __name__ == "__main__": +++ parser = argparse.ArgumentParser() +++ parser.add_argument("-k", "--keep", action="store_true", help="keep " +++ "checksums of files that still exist, and assume they haven't changed.") +++ parser.add_argument('crates', nargs=argparse.REMAINDER, +++ help="crates whose checksums to prune. (default: ./)") +++ args = parser.parse_args(sys.argv[1:]) +++ crates = args.crates or ["."] +++ f = prune_keep if args.keep else prune +++ for c in crates: +++ cfile = os.path.join(c, ".cargo-checksum.json") if os.path.isdir(c) else c +++ f(cfile) diff --cc debian/scripts/repack-orig-tarball.sh index 0000000000,0000000000,0000000000..1b3b0a7f73 new file mode 100755 --- /dev/null +++ b/debian/scripts/repack-orig-tarball.sh @@@@ -1,0 -1,0 -1,0 +1,52 @@@@ +++#!/bin/bash +++ +++set -ex +++ +++if [[ -n "$1" ]]; then +++ ver="$1" +++fi +++ +++if [[ -z "$ver" ]]; then +++ echo '$ver must be set' +++ exit 1 +++fi +++ +++suffix="+dfsg1" +++if [[ -n "$2" ]]; then +++ suffix="$2" +++fi +++echo "Setting repack suffix to '$suffix'" +++ +++tarball=../"rustc-${ver/\~/-}-src.tar.xz" +++ +++echo "Looking up top-level dir in '$tarball'.." +++top="$(tar tf "$tarball" | head -n1)" +++ +++if [[ -z "$top" ]]; then +++ echo "Failed to extract top-level dir from '$tarball'" +++ exit 1 +++fi +++ +++echo "Top-level dir: '$top'" +++ +++grep-dctrl -n -F Files-Excluded -s Files-Excluded '' debian/copyright \ +++ | sed -r 's/^ +//; /^$/d' \ +++ | awk -v top="$top/" '/^\*/{print; next} {print top $$0}' \ +++ > "$tarball.excludes" +++ +++echo "Extracting tarball to '$top'" +++tar --exclude-from="$tarball.excludes" -xf "$tarball" +++ +++echo "Removing excludes file" +++rm -f "$tarball.excludes" +++ +++echo "Removing empty dirs" +++find "$top" -depth -type d -empty -print -delete +++ +++tar_options="--sort=name --owner=0 --group=0 --numeric-owner" +++origtxz="../rustc_$ver$suffix.orig.tar.xz" +++ +++echo "Repacking extracted tarball.." +++rm -f "$origtxz" +++tar $tar_options -cf - "$top" | xz -6 -T0 - > "$origtxz" +++ diff --cc debian/source/format index 0000000000,0000000000,0000000000..163aaf8d82 new file mode 100644 --- /dev/null +++ b/debian/source/format @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++3.0 (quilt) diff --cc debian/source/include-binaries index 0000000000,0000000000,0000000000..33bec95225 new file mode 100644 --- /dev/null +++ b/debian/source/include-binaries @@@@ -1,0 -1,0 -1,0 +1,6 @@@@ +++debian/icons/rust-logo-32x32-blk.png +++# if you are here because dpkg-source told you to "add stage0/rustc-** in d/source/include-binaries", +++# ignore that instruction and instead: +++# a) if you want to use the orig-stage0 for your next upload, then extract it into stage0/ +++# b) if you don't want to use it, then rename "../rustc_${version}.orig-stage0.tar.xz" to something else +++# see also d/source/options and d/source/local-options and #577113. diff --cc debian/source/lintian-overrides index 0000000000,0000000000,0000000000..56d8b9df3c new file mode 100644 --- /dev/null +++ b/debian/source/lintian-overrides @@@@ -1,0 -1,0 -1,0 +1,26 @@@@ +++# Test data +++rustc source: source-is-missing [src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/*.html] +++rustc source: source-is-missing [src/tools/rustc-perf/collector/compile-benchmarks/*] +++rustc source: source-is-missing [tests/rustdoc/decl-trailing-whitespace.declaration.html] +++rustc source: source-is-missing [tests/rustdoc/notable-trait/doc-notable_trait*.html] +++rustc source: source-is-missing [tests/rustdoc/notable-trait/spotlight*.html] +++rustc source: source-is-missing [vendor/html5ever-*/data/bench/*.html] +++rustc source: source-is-missing [vendor/minifier-*/tests/files/minified_main.js] +++ +++# these are not the license of any code here.. +++# old and new lintian output format.. +++rustc source: license-problem-json-evil *vendor/spdx-*/src/text/licenses/JSON* +++rustc source: license-problem-php-license *vendor/spdx-*/src/text/licenses/PHP-3.01* +++rustc source: license-problem-php-license *vendor/spdx-*/src/text/licenses/PHP-3.0* +++ +++# debian policy bug #649530, old and new formats +++rustc source: mismatched-override missing-license-paragraph-in-dep5-copyright mpl-2.0+ (*) +++rustc source: mismatched-override missing-license-paragraph-in-dep5-copyright debian/copyright mpl-2.0+ (*) [debian/source/lintian-overrides:*] +++rustc source: missing-license-paragraph-in-dep5-copyright mpl-2.0+ [debian/copyright:*] +++rustc source: missing-license-paragraph-in-dep5-copyright debian/copyright mpl-2.0+ (*) +++ +++# see d/copyright +++rustc source: source-contains-prebuilt-windows-binary [vendor/windows-bindgen-*/default/*.winmd] +++ +++# lintian is superfluous +++rustc source: superfluous-file-pattern debian/copyright * (*) diff --cc debian/source/options index 0000000000,0000000000,0000000000..8a8c93f546 new file mode 100644 --- /dev/null +++ b/debian/source/options @@@@ -1,0 -1,0 -1,0 +1,4 @@@@ +++# this helps to prevent accidentally including the orig-stage0 tarball in a non +++# orig-stage0 upload, after running `debian/rules source_orig-stage0`. +++# we can get rid of this after #577113 is fixed +++include-removal diff --cc debian/tests/control index 0000000000,0000000000,0000000000..38fbf8ed08 new file mode 100644 --- /dev/null +++ b/debian/tests/control @@@@ -1,0 -1,0 -1,0 +1,15 @@@@ +++#Test-Command: ./debian/rules build +++#Depends: @builddeps@ +++#Restrictions: rw-build-tree, allow-stderr +++# +++Tests: create-and-build-crate +++Restrictions: rw-build-tree, allow-stderr, needs-internet +++Depends: cargo, ca-certificates +++ +++Tests: create-and-build-wasm-wasip1-crate +++Restrictions: rw-build-tree, allow-stderr, needs-internet +++Depends: cargo, ca-certificates, libstd-rust-dev-wasm32, rust-llvm +++ +++Tests: create-and-build-wasm-wasip2-crate +++Restrictions: rw-build-tree, allow-stderr, needs-internet +++Depends: cargo, ca-certificates, libstd-rust-dev-wasm32, rust-llvm diff --cc debian/tests/create-and-build-crate index 0000000000,0000000000,0000000000..46cc2a0346 new file mode 100755 --- /dev/null +++ b/debian/tests/create-and-build-crate @@@@ -1,0 -1,0 -1,0 +1,39 @@@@ +++#!/bin/bash +++set -euo pipefail +++ +++tmpdir=$(mktemp -d) +++cd "$tmpdir" +++ +++cargo new hello +++cd hello +++ +++cat < src/main.rs +++use anyhow::Result; +++ +++fn main() -> Result<()> { +++ println!("Hello, World!"); +++ Ok(()) +++} +++ +++#[test] +++fn test() { +++ assert_eq!(1 + 1, 2); +++} +++EOF +++ +++cargo add 'anyhow@^1' +++cargo vendor +++ +++mkdir -p .cargo +++cat < .cargo/config.toml +++[source.crates-io] +++replace-with = "vendored-sources" +++ +++[source.vendored-sources] +++directory = "vendor" +++EOF +++ +++cargo check +++cargo build +++cargo test +++cargo run diff --cc debian/tests/create-and-build-wasm-wasip1-crate index 0000000000,0000000000,0000000000..bb81a4e6f7 new file mode 100755 --- /dev/null +++ b/debian/tests/create-and-build-wasm-wasip1-crate @@@@ -1,0 -1,0 -1,0 +1,37 @@@@ +++#!/bin/bash +++set -euo pipefail +++ +++tmpdir=$(mktemp -d) +++cd "$tmpdir" +++ +++cargo new hello +++cd hello +++ +++cat < src/main.rs +++use anyhow::Result; +++ +++fn main() -> Result<()> { +++ println!("Hello, World!"); +++ Ok(()) +++} +++ +++#[test] +++fn test() { +++ assert_eq!(1 + 1, 2); +++} +++EOF +++ +++cargo add 'anyhow@^1' +++cargo vendor +++ +++mkdir -p .cargo +++cat < .cargo/config.toml +++[source.crates-io] +++replace-with = "vendored-sources" +++ +++[source.vendored-sources] +++directory = "vendor" +++EOF +++ +++cargo check --target "wasm32-wasip1" +++cargo build --target "wasm32-wasip1" diff --cc debian/tests/create-and-build-wasm-wasip2-crate index 0000000000,0000000000,0000000000..904c516879 new file mode 100755 --- /dev/null +++ b/debian/tests/create-and-build-wasm-wasip2-crate @@@@ -1,0 -1,0 -1,0 +1,37 @@@@ +++#!/bin/bash +++set -euo pipefail +++ +++tmpdir=$(mktemp -d) +++cd "$tmpdir" +++ +++cargo new hello +++cd hello +++ +++cat < src/main.rs +++use anyhow::Result; +++ +++fn main() -> Result<()> { +++ println!("Hello, World!"); +++ Ok(()) +++} +++ +++#[test] +++fn test() { +++ assert_eq!(1 + 1, 2); +++} +++EOF +++ +++cargo add 'anyhow@^1' +++cargo vendor +++ +++mkdir -p .cargo +++cat < .cargo/config.toml +++[source.crates-io] +++replace-with = "vendored-sources" +++ +++[source.vendored-sources] +++directory = "vendor" +++EOF +++ +++cargo check --target "wasm32-wasip2" +++cargo build --target "wasm32-wasip2" diff --cc debian/update-version.sh index 0000000000,0000000000,0000000000..946c39e61e new file mode 100755 --- /dev/null +++ b/debian/update-version.sh @@@@ -1,0 -1,0 -1,0 +1,63 @@@@ +++#!/bin/bash +++# Don't run this directly, use "debian/rules update-version" instead +++ +++prev_stable() { +++local V=$1 +++python3 -c 'import sys; k=list(map(int,sys.argv[1].split("."))); k[1]-=1; print(".".join(map(str,k)))' "$V" +++} +++ +++update() { +++local ORIG=$1 NEW=$2 NEW_LONG=$3 +++ +++ORIG_M1=$(prev_stable $ORIG) +++NEW_M1=$(prev_stable $NEW) +++ORIG_R="${ORIG/./\\.}" # match a literal dot, otherwise this might sometimes match e.g. debhelper (>= 9.20141010) +++ +++WASI_CI="$(grep -Rl "^RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-.*" ../src/ci | head -n1)" +++WASI_SDK_VER="$(egrep -o '\bwasi-sdk-[0-9]+\b' "$WASI_CI" | head -n1)" +++ +++if [ -z "$WASI_SDK_VER" ]; then +++ echo >&2 "error: could not determine WASI_SDK version used by rustc upstream!" +++ exit 1 +++fi +++ +++WASI_TMP="$(mktemp -d)" +++git clone https://github.com/WebAssembly/wasi-sdk -b "$WASI_SDK_VER" "$WASI_TMP" +++WASI_COMMIT="$( (cd "$WASI_TMP" && git submodule status src/wasi-libc | sed -e 's/^-//' | egrep -o '^[0-9a-f]{7}') )" +++rm -rf "$WASI_TMP" +++ +++WASI_REGEX='wasi-libc \(([><=]+) 0.0~git([0-9]+).([0-9a-f]+)([~+]+)\)' +++ +++if [ -z "$WASI_COMMIT" -o "$(printf '%s\n' "$WASI_COMMIT" | wc -l)" != 1 ]; then +++ echo >&2 "error: could not determine unique WASI_COMMIT ($WASI_COMMIT), please figure it out from src/ci and update my logic" +++ exit 1 +++fi +++ +++WASI_COMMIT_OLD="$(sed -nre 's|.*'"${WASI_REGEX}"'.*|\3|gp' control | sort -u)" +++if [ -z "$WASI_COMMIT_OLD" -o "$(printf '%s\n' "$WASI_COMMIT_OLD" | wc -l)" != 1 ]; then +++ echo >&2 "error: could not determine unique WASI_COMMIT_OLD ($WASI_COMMIT_OLD), please figure it out from debian/control and update my logic" +++ exit 1 +++fi +++ +++sed -i -e "s|libstd-rust-${ORIG_R}|libstd-rust-$NEW|g" \ +++ -e "s|rustc:native\( *\)(<= [^)]*)|rustc:native\1(<= $NEW_LONG++)|g" \ +++ -e "s|rustc:native\( *\)(>= ${ORIG_M1/./\\.}|rustc:native\1(>= ${NEW_M1}|g" \ +++ -e "s|cargo:native\( *\)(>= ${ORIG_M1/./\\.}|cargo:native\1(>= ${NEW_M1}|g" \ +++ control +++ +++if [ "$WASI_COMMIT" != "$WASI_COMMIT_OLD" ]; then +++ sed -ri -e 's|'"${WASI_REGEX}"'|wasi-libc (\1 0.0~gitFIXME.'"${WASI_COMMIT}"'\4)|g' control +++ echo >&2 "note: the version of the wasi-libc Build-Depends has changed and needs to be FIXME with the correct date" +++ echo >&2 "please update that package, upload it to experimental, and supply the correct date in debian/control" +++fi +++ +++if [ "$NEW" != "$ORIG" ]; then +++git mv libstd-rust-$ORIG.install libstd-rust-$NEW.install +++git mv libstd-rust-$ORIG.triggers libstd-rust-$NEW.triggers +++git mv libstd-rust-$ORIG.lintian-overrides libstd-rust-$NEW.lintian-overrides +++fi +++sed -i -e "s|libstd-rust-${ORIG_R}|libstd-rust-$NEW|g" libstd-rust-$NEW.lintian-overrides +++} +++ +++cd $(dirname "$0") +++update "$@" diff --cc debian/upstream-tarball-unsuspicious.txt index 0000000000,0000000000,0000000000..00b5b8c3c4 new file mode 100644 --- /dev/null +++ b/debian/upstream-tarball-unsuspicious.txt @@@@ -1,0 -1,0 -1,0 +1,903 @@@@ +++## In this file we list false-positives of the check-orig-suspicious.sh script +++# so that they can be ignored. You should manually audit all of the files here +++# to confirm that they adhere to Debian Policy and the DFSG. In particular, if +++# you are blindly adding files here just to get the build to work, you are +++# probably Doing It Wrong. Ask in #debian-rust or the mailing list for pointers. +++ +++# False-positive, file(1) misidentifies mime type +++compiler/rustc_error_codes/src/error_codes/E0469.md +++src/doc/book/nostarch/chapter17.md +++src/doc/reference/src/crates-and-source-files.md +++src/doc/reference/src/items/extern-crates.md +++src/doc/reference/src/items/modules.md +++src/doc/reference/src/types-redirect.html +++src/tools/cargo/src/doc/src/reference/registries.md +++src/tools/clippy/book/src/lint_configuration.md +++tests/rustdoc-ui/doctest/auxiliary/relative-dir.md +++vendor/base64-*/src/lib.rs +++vendor/chrono-*/src/lib.rs +++vendor/crunchy-0.2.2/src/lib.rs +++vendor/fiat-crypto-*/src/p448_solinas_32.rs +++vendor/itertools-*/examples/iris.data +++vendor/minifier-*/src/js/tools.rs +++vendor/pasetors-*/src/footer.rs +++vendor/pasetors-*/src/version2.rs +++vendor/pasetors-*/src/version3.rs +++vendor/pasetors-*/src/version4.rs +++vendor/syn-2.*/src/gen/token.css +++vendor/term-*/src/terminfo/parser/names.rs +++vendor/wit-component-*/libdl.so +++ +++# False-positive, "verylongtext" but OK +++CONTRIBUTING.md +++README.md +++RELEASES.md +++compiler/rustc_baked_icu_data/src/data/mod.rs +++compiler/rustc_codegen_cranelift/docs/dwarf.md +++compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml +++compiler/rustc_codegen_gcc/Readme.md +++compiler/rustc_codegen_ssa/messages.ftl +++compiler/rustc_incremental/messages.ftl +++library/backtrace/src/windows_sys.rs +++library/core/src/ffi/c_*.md +++library/portable-simd/*.md +++library/std/src/sys/pal/sgx/abi/entry.S +++library/std/src/sys/pal/windows/c/windows_sys.rs +++library/stdarch/CONTRIBUTING.md +++library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++library/stdarch/crates/std_detect/README.md +++src/doc/*/CODE_OF_CONDUCT.md +++src/doc/book/first-edition/src/the-stack-and-the-heap.md +++src/doc/edition-guide/src/editions/index.md +++src/doc/edition-guide/src/rust-2018/index.md +++src/doc/edition-guide/src/rust-2021/disjoint-capture-in-closures.md +++src/doc/edition-guide/src/rust-2021/prelude.md +++src/doc/edition-guide/src/rust-2021/raw-lifetimes.md +++src/doc/edition-guide/src/rust-2024/*.md +++src/doc/embedded-book/src/*/*.md +++src/doc/nomicon/src/intro.md +++src/doc/reference/README.md +++src/doc/reference/docs/authoring.md +++src/doc/reference/docs/review-policy.md +++src/doc/reference/src/attributes/diagnostics.md +++src/doc/reference/src/conditional-compilation.md +++src/doc/reference/src/expressions/closure-expr.md +++src/doc/reference/src/inline-assembly.md +++src/doc/reference/src/introduction.md +++src/doc/reference/src/types/impl-trait.md +++src/doc/reference/src/unsafe-keyword.md +++src/doc/rust-by-example/src/flow_control/if_let.md +++src/doc/rust-by-example/src/std/arc.md +++src/doc/rust-by-example/src/trait/dyn.md +++src/doc/rust-by-example/src/unsafe/asm.md +++src/doc/rustc-dev-guide/src/*.md +++src/doc/rustc-dev-guide/src/*/*.md +++src/doc/rustc-dev-guide/src/borrow_check/region_inference/closure_constraints.md +++src/doc/rustc/src/instrument-coverage.md +++src/doc/rustc/src/lints/groups.md +++src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md +++src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md +++src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabihf.md +++src/doc/rustc/src/platform-support/unknown-uefi.md +++src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md +++src/doc/rustc/src/platform-support/wasm32v1-none.md +++src/doc/rustc/src/targets/known-issues.md +++src/doc/rustdoc/src/*.md +++src/doc/style-guide/src/nightly.md +++src/doc/unstable-book/src/*/*.md +++src/etc/completions/x.fish +++src/etc/completions/x.ps1 +++src/etc/completions/x.py.fish +++src/etc/completions/x.py.ps1 +++src/etc/completions/x.py.sh +++src/etc/completions/x.sh +++src/etc/third-party/README.txt +++src/librustdoc/html/highlight/fixtures/sample.html +++src/librustdoc/html/static/scrape-examples-help.md +++src/librustdoc/html/templates/page.html +++src/tools/cargo/crates/cargo-util-schemas/manifest.schema.json +++src/tools/cargo/src/cargo/sources/git/known_hosts.rs +++src/tools/cargo/src/doc/contrib/src/process/release.md +++src/tools/cargo/src/doc/src/guide/continuous-integration.md +++src/tools/cargo/src/doc/src/reference/features.md +++src/tools/cargo/src/doc/src/reference/semver.md +++src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs +++src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs +++src/tools/rust-analyzer/docs/dev/setup.md +++src/tools/rust-analyzer/docs/user/manual.adoc +++src/tools/rustc-perf/LICENSES/Apache-2.0.txt +++src/tools/rustc-perf/LICENSES/MIT.txt +++src/tools/rustc-perf/collector/src/compile/execute/etw_parser.rs +++src/tools/rustc-perf/docs/*.md +++src/tools/rustc-perf/triage/*.md +++src/tools/rustfmt/*.md +++tests/mir-opt/building/*.mir +++tests/rustdoc/inline_cross/assoc_item_trait_bounds.out*.html +++tests/rustdoc/notable-trait/doc-notable_trait*.html +++tests/rustdoc/notable-trait/spotlight-from-dependency.odd.html +++tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr +++tests/ui/parser/raw/too-many-hash.stderr +++vendor/*/*/*/LICENSE +++vendor/*/*/LICENSE +++vendor/*/CHANGELOG.md +++vendor/*/CODE_OF_CONDUCT.md +++vendor/*/CONTRIBUTORS.md +++vendor/*/COPYRIGHT +++vendor/*/Cargo.toml +++vendor/*/FAQ.md +++vendor/*/LICENSE +++vendor/*/LICENSE-* +++vendor/*/README.md +++vendor/*/Readme.md +++vendor/*/SPONSORS.md +++vendor/*/readme.md +++vendor/ammonia-*/src/lib.rs +++vendor/anstyle-parse-*/src/state/table.rs +++vendor/base64-*/RELEASE-NOTES.md +++vendor/base64ct-*/tests/proptests.proptest-regressions +++vendor/chrono-*/src/offset/local/tz_info/rule.rs +++vendor/chrono-*/src/offset/local/tz_info/timezone.rs +++vendor/core-foundation-sys-*/src/url.rs +++vendor/dbus-*/changes-in-0.7.md +++vendor/dbus-*/examples/argument_guide.md +++vendor/elliptic-curve-*/src/hash2curve/hash2field/expand_msg/xmd.rs +++vendor/elliptic-curve-*/src/hash2curve/hash2field/expand_msg/xof.rs +++vendor/elliptic-curve-*/src/jwk.rs +++vendor/encoding_rs-*/src/ascii.rs +++vendor/encoding_rs-*/src/utf_16.rs +++vendor/faster-hex-*/src/serde.rs +++vendor/fiat-crypto-*/src/p521_32.rs +++vendor/fiat-crypto-*/src/secp256k1_dettman_32.rs +++vendor/fiat-crypto-*/src/secp256k1_dettman_64.rs +++vendor/git2-*/src/cred.rs +++vendor/half-*/LICENSES/Apache-2.0.txt +++vendor/half-*/LICENSES/MIT.txt +++vendor/handlebars-*/src/lib.rs +++vendor/handlebars-*/src/render.rs +++vendor/handlebars-*/src/template.rs +++vendor/html-escape-*/src/decode/element/decode_impl.rs +++vendor/html-escape-*/src/encode/element/encode_impl.rs +++vendor/humansize-*/src/lib.rs +++vendor/icu_list-*/src/provider/serde_dfa.rs +++vendor/jiff-0.*/tests/tc39_262/span/round.rs +++vendor/kstring-*/benches/clone.rs +++vendor/lazy_static-*/src/lib.rs +++vendor/lexopt-0.*/DESIGN.md +++vendor/libdbus-sys-*/cross_compile.md +++vendor/maplit-*/README.rst +++vendor/mdbook-*/CONTRIBUTING.md +++vendor/nu-ansi-term-*/src/style.rs +++vendor/openssl-*/src/dh.rs +++vendor/openssl-sys-*/build/main.rs +++vendor/p384-*/src/arithmetic/hash2curve.rs +++vendor/pasetors-*/src/token.rs +++vendor/portable-atomic-*/build.rs +++vendor/portable-atomic-*/src/imp/atomic128/README.md +++vendor/portable-atomic-*/src/imp/interrupt/README.md +++vendor/portable-atomic-*/src/lib.rs +++vendor/portable-atomic-1.*/src/imp/atomic64/README.md +++vendor/pulldown-cmark-*/tests/suite/footnotes.rs +++vendor/pulldown-cmark-*/tests/suite/old_footnotes.rs +++vendor/rustc-demangle-*/src/legacy.rs +++vendor/spdx-expression-*/LICENSES/MIT.txt +++vendor/spdx-rs-*/LICENSE.txt +++vendor/spdx-rs-*/LICENSES/MIT.txt +++vendor/spdx-rs-*/src/models/file_information.rs +++vendor/spdx-rs-*/src/models/other_licensing_information_detected.rs +++vendor/spdx-rs-*/src/models/package_information.rs +++vendor/spki-*/tests/spki.rs +++vendor/stable_deref_trait-*/src/lib.rs +++vendor/syntect-*/src/html.rs +++vendor/syntect-*/src/parsing/parser.rs +++vendor/sysinfo-0.*/migration_guide.md +++vendor/tenthash-0.*/tests/test_vectors.rs +++vendor/tracing-subscriber-*/src/fmt/format/json.rs +++vendor/unicase-*/src/lib.rs +++vendor/unicode-normalization-*/src/stream_safe.rs +++vendor/vcpkg-*/notes.md +++vendor/web-sys-*/src/features/gen_SvgTextElement.rs +++vendor/web-sys-*/src/features/gen_SvgtSpanElement.rs +++vendor/windows-bindgen-*/src/rust/extensions/mod.rs +++vendor/windows-bindgen-*/src/tokens/mod.rs +++vendor/windows-bindgen-*/src/winmd/writer/tables.rs +++vendor/windows-metadata-*/src/lib.rs +++vendor/windows-metadata-*/src/reader.rs +++vendor/winnow-*/benches/contains_token.rs +++vendor/winnow-*/benches/iter.rs +++vendor/zerovec-*/src/map2d/map.rs +++ +++# False-positive, audit-vendor-source automatically flags JS/C files +++# The below ones are OK since they're actually part of rust's own source code +++# and are not "embedded libraries". +++src/ci/docker/scripts/qemu-bare-bones-addentropy.c +++src/ci/package-lock.json +++src/ci/package.json +++src/doc/book/*/ferris.js +++src/doc/book/ferris.js +++src/doc/reference/src/attributes-redirect.html +++src/doc/reference/theme/reference.js +++src/doc/rustc-dev-guide/mermaid-init.js +++src/librustdoc/html/static/.eslintrc.js +++src/librustdoc/html/static/js/*.js +++src/tools/cargo/src/cargo/core/compiler/timings.js +++src/tools/error_index_generator/*.js +++src/tools/rustc-perf/collector/compile-benchmarks/*/perf-config.json +++src/tools/rustc-perf/site/frontend/*.json +++src/tools/rustc-perf/site/frontend/.parcelrc +++src/tools/rustc-perf/site/frontend/.prettierrc.json +++src/tools/rustc-perf/site/frontend/src/*.ts +++src/tools/rustc-perf/site/frontend/src/*/*.ts +++src/tools/rustc-perf/site/frontend/src/*/*.vue +++src/tools/rustc-perf/site/frontend/src/*/*/*.ts +++src/tools/rustc-perf/site/frontend/src/*/*/*.vue +++src/tools/rustc-perf/site/frontend/src/*/*/*/*.ts +++src/tools/rustc-perf/site/frontend/src/*/*/*/*.vue +++src/tools/rustc-perf/site/frontend/src/*/*/*/*/*.ts +++src/tools/rustc-perf/site/frontend/src/*/*/*/*/*.vue +++src/tools/rustc-perf/site/frontend/src/*/*/*/*/*/*.ts +++src/tools/rustc-perf/site/frontend/src/*/*/*/*/*/*.vue +++src/tools/rustc-perf/site/frontend/static/schedule.js +++src/tools/rustdoc-gui/.eslintrc.js +++src/tools/rustdoc-gui/tester.js +++src/tools/rustdoc-js/.eslintrc.js +++src/tools/rustdoc-js/tester.js +++vendor/mdbook-0.*/src/theme/toc.js.hbs +++vendor/sysinfo-0.*/funding.json +++ +++# rustc-perf benchmark inputs +++src/tools/rustc-perf/collector/compile-benchmarks/cargo-*/src/cargo/core/compiler/timings.js +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/script/dom/bindings/codegen/ply/ply/lex.py +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/script/dom/bindings/codegen/ply/ply/yacc.py +++src/tools/rustc-perf/collector/compile-benchmarks/cargo-*/src/doc/src/guide/continuous-integration.md +++src/tools/rustc-perf/collector/compile-benchmarks/cargo-*/src/doc/src/images/*.png +++src/tools/rustc-perf/collector/compile-benchmarks/cargo-*/src/doc/src/images/*.svg +++src/tools/rustc-perf/collector/compile-benchmarks/cargo-*/src/doc/theme/favicon.png +++src/tools/rustc-perf/collector/compile-benchmarks/cargo-*/tests/testsuite/build_script.rs +++src/tools/rustc-perf/collector/compile-benchmarks/clap-*/src/derive.rs +++src/tools/rustc-perf/collector/compile-benchmarks/cranelift-codegen-*/src/isa/aarch64/inst/unwind/systemv.rs +++src/tools/rustc-perf/collector/compile-benchmarks/cranelift-codegen-*/src/isa/x64/lower.rs +++src/tools/rustc-perf/collector/compile-benchmarks/encoding/src/codec/simpchinese.rs +++src/tools/rustc-perf/collector/compile-benchmarks/encoding/src/codec/utf_16.rs +++src/tools/rustc-perf/collector/compile-benchmarks/encoding/src/examples/UTF-8-test.txt +++src/tools/rustc-perf/collector/compile-benchmarks/encoding/src/lib.rs +++src/tools/rustc-perf/collector/compile-benchmarks/encoding/src/types/lib.rs +++src/tools/rustc-perf/collector/compile-benchmarks/encoding/src/util.rs +++src/tools/rustc-perf/collector/compile-benchmarks/exa-*/xtests/outputs/dev_long.ansitxt +++src/tools/rustc-perf/collector/compile-benchmarks/html5ever-*/examples/capi/tokenize.c +++src/tools/rustc-perf/collector/compile-benchmarks/html5ever/README.md +++src/tools/rustc-perf/collector/compile-benchmarks/html5ever/data/bench/lipsum.html +++src/tools/rustc-perf/collector/compile-benchmarks/html5ever/data/bench/strong.html +++src/tools/rustc-perf/collector/compile-benchmarks/html5ever/data/entities.json +++src/tools/rustc-perf/collector/compile-benchmarks/regex-*/src/testdata/basic.dat +++src/tools/rustc-perf/collector/compile-benchmarks/regex-*/tests/crates_regex.rs +++src/tools/rustc-perf/collector/compile-benchmarks/regex-*/tests/fowler.rs +++src/tools/rustc-perf/collector/compile-benchmarks/regex-*/tests/suffix_reverse.rs +++src/tools/rustc-perf/collector/compile-benchmarks/regex-*/tests/unicode.rs +++src/tools/rustc-perf/collector/compile-benchmarks/regex/src/testdata/basic.dat +++src/tools/rustc-perf/collector/compile-benchmarks/ripgrep-*/benchsuite/runs/*/raw.csv +++src/tools/rustc-perf/collector/compile-benchmarks/ripgrep-*/tests/data/sherlock.* +++src/tools/rustc-perf/collector/compile-benchmarks/stm32f4-*/src/*/*.rs +++src/tools/rustc-perf/collector/compile-benchmarks/stm32f4-*/src/*/*/*.rs +++src/tools/rustc-perf/collector/compile-benchmarks/stm32f4-*/src/*/*/*/*.rs +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/1-b9b3e592dd-cherry-picked.patch +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/profile/trace-dump.js +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/style/attr.rs +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/style/counter_style/mod.rs +++src/tools/rustc-perf/collector/compile-benchmarks/regex/regex-capi/examples/iter.c +++src/tools/rustc-perf/collector/compile-benchmarks/regex/regex-capi/ctest/test.c +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/style/custom_properties.rs +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/style/font_face.rs +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/style/parser.rs +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/style/properties/Mako-0.9.1.zip +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/style/stylesheets/font_feature_values_rule.rs +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/style/values/specified/svg.rs +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/components/style_derive/cg.rs +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/rust-cssparser/src/macros.rs +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/rust-cssparser/src/nth.rs +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/rust-cssparser/src/parser.rs +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/rust-cssparser/src/tests.rs +++src/tools/rustc-perf/collector/compile-benchmarks/style-servo/rust-cssparser/src/tokenizer.rs +++src/tools/rustc-perf/collector/compile-benchmarks/syn-*/src/attr.rs +++src/tools/rustc-perf/collector/compile-benchmarks/syn-*/src/custom_punctuation.rs +++src/tools/rustc-perf/collector/compile-benchmarks/syn-*/src/group.rs +++src/tools/rustc-perf/collector/compile-benchmarks/syn-*/src/pat.rs +++src/tools/rustc-perf/collector/compile-benchmarks/syn-*/src/path.rs +++src/tools/rustc-perf/collector/compile-benchmarks/syn-*/src/punctuated.rs +++src/tools/rustc-perf/collector/compile-benchmarks/syn-*/src/stmt.rs +++src/tools/rustc-perf/collector/compile-benchmarks/syn-*/src/token.rs +++src/tools/rustc-perf/collector/compile-benchmarks/syn-*/src/ty.rs +++src/tools/rustc-perf/collector/compile-benchmarks/syn-*/tests/test_meta.rs +++src/tools/rustc-perf/collector/compile-benchmarks/syn/.travis.yml +++src/tools/rustc-perf/collector/compile-benchmarks/syn/synom/src/lib.rs +++src/tools/rustc-perf/collector/compile-benchmarks/tt-muncher/quote-*-modified/perf-config.json +++src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/webrender/res/Proggy.ttf +++src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/webrender/res/area-lut.tga +++src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/wrench/reftests/text/Ahem.ttf +++src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/wrench/reftests/text/FreeSans.ttf +++src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/wrench/reftests/text/Proggy.ttf +++src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/wrench/reftests/text/VeraBd.ttf +++src/tools/rustc-perf/collector/compile-benchmarks/wg-grammar/src/parse.rs +++src/tools/rustc-perf/collector/runtime-benchmarks/css/data/fb.css +++src/tools/rustc-perf/collector/runtime-benchmarks/data/nes15-NTSC.nes +++src/tools/rustc-perf/collector/runtime-benchmarks/data/sherlock.txt.gz +++src/tools/rustc-perf/collector/runtime-benchmarks/parsing/data/github-events.json +++src/tools/rustc-perf/collector/runtime-benchmarks/parsing/src/json.rs +++src/tools/rustc-perf/collector/runtime-benchmarks/svg/data/map.svg.gz +++src/tools/rustc-perf/collector/compile-benchmarks/*/Cargo.toml +++src/tools/rustc-perf/collector/compile-benchmarks/html5ever-*/data/bench/*.html +++src/tools/rustc-perf/collector/compile-benchmarks/unicode-normalization-*/src/stream_safe.rs +++src/tools/rustc-perf/collector/compile-benchmarks/piston-image/src/bmp/decoder.rs +++src/tools/rustc-perf/collector/compile-benchmarks/exa-*/xtests/outputs/*.ansitxt +++src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/webrender/src/profiler.rs +++src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/webrender/doc/*.md +++src/tools/rustc-perf/collector/compile-benchmarks/webrender-2022/wrench/reftests/*/*.png +++ +++# And these ones are actual helper files, not embedded bad code +++vendor/cc-1.*/src/detect_compiler_family.c +++vendor/libz-sys-*/src/smoke.c +++vendor/openssl-sys-*/build/expando.c +++vendor/sharded-slab-*/flake.lock +++vendor/wasm-bindgen-macro-*/src/worker.js +++ +++# Embedded libraries, justified in README.source +++vendor/dlmalloc-*/src/dlmalloc.c +++vendor/mdbook-*/src/theme/book.js +++vendor/mdbook-*/src/theme/searcher/searcher.js +++ +++# Trivial glue code for C <-> Rust +++library/backtrace/crates/line-tables-only/src/callback.c +++vendor/stacker-*/src/arch/windows.c +++ +++# False-positive, misc +++*/*/.github/actions/github-release/* +++compiler/rustc_codegen_gcc/target_specs/m68k-unknown-linux-gnu.json +++src/ci/github-actions/problem_matchers.json +++src/doc/book/listings/ch14-more-about-cargo/output-only-01-adder-crate/add/rustfmt-ignore +++src/doc/rustc-dev-guide/src/queries/example-0.counts.txt +++src/etc/rust_analyzer_settings.json +++src/tools/clippy/.remarkrc +++vendor/elasticlunr-rs-*/src/lang/*.rs +++vendor/git2-*/FUNDING.json +++vendor/plotters-*/src/style/colors/full_palette.rs +++ +++# False-positive, hand-editable small image +++src/doc/book/2018-edition/src/img/*.png +++src/doc/book/2018-edition/src/img/*.svg +++src/doc/book/2018-edition/src/img/ferris/*.svg +++src/doc/book/second-edition/src/img/*.png +++src/doc/book/second-edition/src/img/*.svg +++src/doc/book/src/img/*.png +++src/doc/book/src/img/*.svg +++src/doc/book/src/img/ferris/*.svg +++src/doc/book/tools/docx-to-md.xsl +++src/doc/embedded-book/src/assets/*.png +++src/doc/embedded-book/src/assets/*.svg +++src/doc/embedded-book/src/assets/f3.jpg +++src/doc/embedded-book/src/assets/verify.jpeg +++src/doc/nomicon/src/img/safeandunsafe.svg +++src/doc/rustc-dev-guide/src/img/*.png +++src/doc/rustc-dev-guide/src/queries/example-0.png +++src/doc/rustc/src/images/*.png +++src/doc/rustdoc/src/images/collapsed-long-item.png +++src/doc/rustdoc/src/images/collapsed-trait-impls.png +++src/etc/installer/gfx/ +++src/librustdoc/html/static/images/*.svg +++src/librustdoc/html/static/images/favicon-*.png +++src/tools/cargo/src/doc/src/images/Cargo-Logo-Small.png +++src/tools/cargo/src/doc/src/images/auth-level-acl.png +++src/tools/cargo/src/doc/src/images/build-info.png +++src/tools/cargo/src/doc/src/images/build-unit-time.png +++src/tools/cargo/src/doc/src/images/cargo-concurrency-over-time.png +++src/tools/cargo/src/doc/src/images/org-level-acl.png +++src/tools/cargo/src/doc/src/images/winapi-features.svg +++src/tools/cargo/src/doc/theme/favicon.png +++src/tools/rust-analyzer/assets/logo-*.svg +++src/tools/rustc-perf/site/frontend/static/favicon-32x32.png +++src/tools/rustc-perf/site/frontend/static/favicon.svg +++vendor/*/logo.png +++vendor/*/logo.svg +++vendor/color-eyre-*/pictures/custom_section.png +++vendor/color-eyre-*/pictures/full.png +++vendor/color-eyre-*/pictures/minimal.png +++vendor/color-eyre-*/pictures/short.png +++vendor/color-spantrace-*/pictures/full.png +++vendor/color-spantrace-*/pictures/minimal.png +++vendor/mdbook-*/src/theme/favicon.png +++vendor/mdbook-*/src/theme/favicon.svg +++vendor/petgraph-0.*/assets/*saurus*.png +++vendor/petgraph-0.*/assets/*saurus*.svg +++vendor/pretty_assertions-*/examples/*.png +++ +++# Example code +++vendor/annotate-snippets-*/examples/expected_type.svg +++vendor/annotate-snippets-*/examples/footer.svg +++vendor/annotate-snippets-*/examples/format.svg +++vendor/annotate-snippets-*/examples/multislice.svg +++vendor/html5ever-*/examples/capi/tokenize.c +++vendor/sysinfo-*/examples/simple.c +++ +++# Test data +++library/core/benches/str.rs +++library/core/tests/num/dec2flt/parse.rs +++library/portable-simd/crates/core_simd/tests/mask_ops_impl/*.rs +++library/portable-simd/crates/core_simd/webdriver.json +++library/std/src/sys/path/windows/tests.rs +++library/stdarch/crates/std_detect/src/detect/test_data/*.auxv +++library/stdarch/crates/stdarch-verify/x86-intel.xml +++library/stdarch/intrinsics_data/arm_intrinsics.json +++src/etc/test-float-parse/src/gen/spot_checks.rs +++src/librustdoc/html/render/write_shared/tests.rs +++src/tools/*/tests/*/*.stderr +++src/tools/cargo/benches/benchsuite/global-cache-tracker/global-cache-sample +++src/tools/cargo/benches/benchsuite/global-cache-tracker/random-sample +++src/tools/cargo/benches/workspaces/*.tgz +++src/tools/cargo/crates/mdman/tests/compare/expected/formatting.txt +++src/tools/cargo/crates/rustfix/tests/edge-cases/*.json +++src/tools/cargo/crates/rustfix/tests/everything/*.json +++src/tools/cargo/tests/testsuite/*.rs +++src/tools/cargo/tests/testsuite/cargo*/*/*.term.svg +++src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/out/Cargo.toml +++src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/out/Cargo.toml +++src/tools/cargo/tests/testsuite/lints/*/*.term.svg +++src/tools/clippy/tests/ui-internal/auxiliary/paths.rs +++src/tools/clippy/tests/ui-toml/*/*.stderr +++src/tools/clippy/tests/ui-toml/large_include_file/too_big.txt +++src/tools/clippy/tests/ui-toml/renamed_function_params/extend/clippy.toml +++src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed +++src/tools/rust-analyzer/bench_data/numerous_macro_rules +++src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_*.html +++src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/* +++src/tools/rust-analyzer/crates/project-model/test_data/*.json +++src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt +++src/tools/rust-analyzer/crates/syntax/test_data/reparse/fuzz-failures/0005.rs +++src/tools/rustc-perf/collector/compile-benchmarks/cargo-0.60.0/benches/workspaces/*.tgz +++src/tools/rustfmt/tests/source/*.rs +++src/tools/rustfmt/tests/source/*/*.rs +++src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_false.rs +++src/tools/rustfmt/tests/writemode/target/*.json +++src/tools/rustfmt/tests/writemode/target/*.xml +++tests/*/*.html +++tests/*/*.rs +++tests/*/*.stderr +++tests/*/*/*.js +++tests/*/*/*.json +++tests/*/*/*.rs +++tests/*/*/*.stderr +++tests/*/*/*.stdout +++tests/*/*/*/*.rs +++tests/auxiliary/rust_test_helpers.c +++tests/coverage/*.cov-map +++tests/coverage/*/*.cov-map +++tests/debuginfo/type-names.cdb.js +++tests/mir-opt/dataflow.main.maybe_init.borrowck.dot +++tests/run-make/*/*.c +++tests/run-make/libtest-junit/output-default.xml +++tests/run-make/libtest-junit/output-stdout-success.xml +++tests/run-make/wasm-exceptions-nostd/verify.mjs +++tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo.c +++tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c +++tests/rustdoc-gui/src/huge_logo/src/lib.rs +++tests/rustdoc-gui/src/scrape_examples/examples/check-many-*.rs +++tests/rustdoc-js-std/*.js +++tests/rustdoc-js/*.js +++tests/rustdoc-ui/show-coverage-json.stdout +++tests/ui/*/*/*.stderr +++tests/ui/async-await/async-closures/clone-closure.run.stdout +++tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg +++tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg +++tests/ui/diagnostic-flags/colored-session-opt-error.svg +++tests/ui/error-emitter/highlighting.svg +++tests/ui/error-emitter/highlighting.windows.svg +++tests/ui/error-emitter/multiline-multipart-suggestion.svg +++tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg +++tests/ui/error-emitter/multiline-removal-suggestion.svg +++tests/ui/error-emitter/unicode-output.svg +++tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg +++tests/ui/macros/not-utf8.bin +++tests/ui/suggestions/incorrect-variant-literal.svg +++tests/ui/traits/object/print_vtable_sizes.stdout +++vendor/annotate-snippets-*/tests/fixtures/no-color/strip_line_non_ws.toml +++vendor/basic-toml-*/tests/invalid-encoder/array-mixed-types-ints-and-floats.json +++vendor/basic-toml-*/tests/valid/*.json +++vendor/basic-toml-*/tests/valid/table-whitespace.toml +++vendor/borsh-1.5.1/tests/roundtrip/test_cow.rs +++vendor/bstr-*/src/unicode/fsm/*.dfa +++vendor/cargo_metadata*/tests/test_samples.rs +++vendor/chalk-solve-0.*/src/infer/test.rs +++vendor/content_inspector-*/testdata/* +++vendor/der-*/tests/examples/spki.der +++vendor/diff-*/tests/data/gitignores.chars.diff +++vendor/dissimilar-*/benches/*.txt +++vendor/elasticlunr-rs-*/tests/data/*.in.txt +++vendor/elasticlunr-rs-*/tests/searchindex_fixture_*.json +++vendor/elliptic-curve-*/tests/examples/*.der +++vendor/elliptic-curve-*/tests/examples/*.pem +++vendor/encoding_rs-*/src/test_data/euc_kr_in.txt +++vendor/encoding_rs-*/src/test_data/euc_kr_in_ref.txt +++vendor/flate2-*/examples/hello_world.txt.gz +++vendor/flate2-*/tests/*.gz +++vendor/flate2-*/tests/corrupt-gz-file.bin +++vendor/fluent-syntax-*/benches/parser.rs +++vendor/gsgdt-*/tests/*.json +++vendor/handlebars-*/tests/helper_with_space.rs +++vendor/hkdf-*/tests/data/*.blb +++vendor/hmac-*/tests/data/*.blb +++vendor/html5ever-*/data/bench/*.html +++vendor/html_parser-0.7.0/tests/snapshots/element__it_can_parse_script_with_content.snap +++vendor/icu_locid-*/benches/fixtures/*.json +++vendor/icu_locid-*/tests/fixtures/*.json +++vendor/icu_locid_transform-*/benches/fixtures/locales.json +++vendor/icu_locid_transform-*/benches/fixtures/uncanonicalized-locales.json +++vendor/icu_locid_transform-*/tests/fixtures/canonicalize.json +++vendor/icu_locid_transform-*/tests/fixtures/maximize.json +++vendor/icu_locid_transform-*/tests/fixtures/minimize.json +++vendor/icu_provider_adapters-*/tests/data/blob.postcard +++vendor/icu_provider_adapters-*/tests/data/langtest/*/*.json +++vendor/icu_provider_adapters-*/tests/data/langtest/*/*/*/*.json +++vendor/idna-*/tests/IdnaTest*.txt +++vendor/idna-*/tests/bad_punycode_tests.json +++vendor/idna-*/tests/punycode_tests.json +++vendor/im-rc-*/proptest-regressions/*.txt +++vendor/im-rc-*/proptest-regressions/*/*.txt +++vendor/im-rc-*/proptest-regressions/ord/map +++vendor/jiff-0.*/src/tz/snapshots/*.snap +++vendor/jiff-0.*/src/tz/testdata/*.tzif +++vendor/lsp-types-*/tests/tsc-unix.lsif +++vendor/md-5-*/tests/data/*.blb +++vendor/mdbook-*/test_book/src/individual/paragraph.md +++vendor/mdbook-*/test_book/src/individual/table.md +++vendor/mdbook-*/tests/searchindex_fixture.json +++vendor/minifier-*/tests/files/main.js +++vendor/minifier-*/tests/files/minified_main.js +++vendor/minifier-*/tests/files/test.json +++vendor/minimal-lexical-*/tests/parse_tests.rs +++vendor/minimal-lexical-*/tests/slow_tests.rs +++vendor/nix-*/test/test_kmod/hello_mod/hello.c +++vendor/openssl-*/test/* +++vendor/p384-*/src/test_vectors/data/wycheproof.blb +++vendor/pasetors-*/test_vectors/*.json +++vendor/pasetors-*/test_vectors/*/*.json +++vendor/pem-rfc7468-*/tests/examples/*.der +++vendor/pem-rfc7468-*/tests/examples/*.pem +++vendor/petgraph-0.*/tests/res/graph_*.txt +++vendor/pkcs8-*/tests/examples/*.der +++vendor/pkcs8-*/tests/examples/*.pem +++vendor/pkcs8-*/tests/private_key.rs +++vendor/proptest-*/proptest-regressions/test_runner/rng.txt +++vendor/proptest-*/src/regex-contrib/crates_regex.rs +++vendor/regex-*/record/compile-test/2023* +++vendor/regex-*/testdata/fowler/dat/basic.dat +++vendor/regex-*/tests/fuzz/testdata/* +++vendor/regex-1.*/tests/*.rs +++vendor/regex-automata-*/tests/gen/*/*.dfa +++vendor/regex-automata-0.1.10/data/fowler-tests/basic.dat +++vendor/regex-automata-0.1.10/data/tests/fowler/basic.dat +++vendor/regex-automata-0.2.0/tests/data/fowler/dat/basic.dat +++vendor/rinja_parser-0.*/benches/librustdoc/page.html +++vendor/rinja_parser-0.*/tests/comment-depth.txt +++vendor/rinja_parser-0.*/tests/filter-recursion.txt +++vendor/rinja_parser-0.*/tests/target-recursion.txt +++vendor/rinja_parser-0.*/tests/unary-recursion.txt +++vendor/rusqlite-*/test.csv +++vendor/rustc-demangle-*/src/lib.rs +++vendor/rustc-demangle-*/src/v0-large-test-symbols/early-recursion-limit +++vendor/ruzstd-0.7.*/test_fixtures/abc.txt.zst +++vendor/schemars-0.*/examples/*.schema.json +++vendor/schemars-0.*/tests/expected/*.json +++vendor/sec1-*/tests/examples/p256-priv.der +++vendor/sec1-*/tests/examples/p256-priv.pem +++vendor/serde_json-*/tests/lexical/parse.rs +++vendor/sha1-*/tests/data/sha1.blb +++vendor/sha2-*/tests/data/*.blb +++vendor/spki-*/tests/examples/*.der +++vendor/syntect-*/tests/public-api.txt +++vendor/tabled-*/tests/core/iter_table.rs +++vendor/tabled-*/tests/settings/colorization.rs +++vendor/tabled-*/tests/settings/padding_test.rs +++vendor/term-*/tests/data/* +++vendor/toml_edit-*/tests/fixtures/invalid/*/*.stderr +++vendor/toml_edit-*/tests/testsuite/invalid.rs +++vendor/unicode-ident-*/tests/fst/*.fst +++vendor/url-*/tests/*.json +++vendor/varisat-*/proptest-regressions/solver.txt +++vendor/vcpkg-*/test-data/no-status/installed/vcpkg/updates/* +++vendor/vcpkg-*/test-data/normalized/installed/vcpkg/updates/status +++vendor/walkdir-*/compare/nftw.c +++vendor/wast-*/tests/parse-fail/*.wat +++vendor/wast-*/tests/parse-fail/*.wat.err +++vendor/wit-component-*/tests/components/link-dl-openable-builtin-libdl-with-unused/component.wat +++vendor/wit-component-*/tests/interfaces/*.wat +++vendor/wit-parser-*/tests/ui/*.wit.json +++vendor/wit-parser-*/tests/ui/kinds-of-deps/deps/e.wasm +++vendor/wit-parser-0.219.*/tests/ui/parse-fail/conflicting-package.wit.result +++vendor/zip-*/tests/data/*.zip +++ +++# Compromise, ideally we'd autogenerate these +++# Should already by documented in debian/copyright +++compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs +++compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs +++compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs +++src/doc/rustc-dev-guide/src/mir/mir_*.svg +++src/librustdoc/html/static/css/normalize.css +++src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs +++vendor/icu_locid_transform_data-*/data/macros/fallback_likelysubtags_v1.rs.data +++vendor/icu_locid_transform_data-*/data/macros/fallback_parents_v1.rs.data +++vendor/icu_locid_transform_data-*/data/macros/fallback_supplement_co_v1.rs.data +++vendor/icu_locid_transform_data-*/data/macros/locid_transform_aliases_v2.rs.data +++vendor/icu_locid_transform_data-*/data/macros/locid_transform_likelysubtags_ext_v1.rs.data +++vendor/icu_locid_transform_data-*/data/macros/locid_transform_likelysubtags_l_v1.rs.data +++vendor/icu_locid_transform_data-*/data/macros/locid_transform_likelysubtags_sr_v1.rs.data +++vendor/icu_locid_transform_data-*/data/macros/locid_transform_script_dir_v1.rs.data +++vendor/icu_normalizer_data-1.*/data/macros/*.rs.data +++vendor/icu_properties_data-1.*/data/macros/*.rs.data +++vendor/linux-raw-sys-*/src/x86_64/general.rs +++vendor/pest_meta-*/src/grammar.rs +++vendor/regex-syntax-*/src/unicode_tables/*.rs +++vendor/syntect-5.2.0/assets/default.themedump +++vendor/syntect-5.2.0/assets/default_metadata.packdump +++vendor/syntect-5.2.0/assets/default_newlines.packdump +++vendor/syntect-5.2.0/assets/default_nonewlines.packdump +++vendor/ucd-parse-*/src/sentence_break.rs +++vendor/ucd-trie-*/src/general_category.rs +++vendor/unicode-normalization-*/src/tables.rs +++vendor/unicode-script-*/src/tables.rs +++vendor/unicode-segmentation-*/src/tables.rs +++vendor/wasi-*/src/lib_generated.rs +++vendor/wasi-preview1-component-adapter-provider-*/artefacts/wasi_snapshot_preview1.*.wasm +++vendor/windows-bindgen-*/default/*.winmd +++vendor/wit-component-*/tests/components/error-link-missing-symbols/error.txt +++ +++# Compromise, ideally we'd package these in their own package +++src/librustdoc/html/static/fonts/*.woff2 +++ +++# file brokenness (detected as Algol source code) +++vendor/protobuf-support-3.*/src/lexer/tokenizer.rs +++vendor/gix-validate-0.*/src/tag.rs +++vendor/handlebars-6.*/examples/block_helper_macro_let.rs +++vendor/handlebars-6.*/tests/block_context.rs +++vendor/handlebars-6.*/tests/whitespace.rs +++vendor/jiff-0.*/src/fmt/offset.rs +++vendor/schemars_derive-0.*/src/attr/schemars_to_serde.rs +++vendor/schemars_derive-0.*/src/lib.rs +++compiler/rustc_builtin_macros/src/global_allocator.rs +++compiler/rustc_codegen_gcc/build_system/src/utils.rs +++compiler/rustc_driver/src/lib.rs +++compiler/rustc_expand/src/mbe/quoted.rs +++compiler/rustc_infer/src/infer/freshen.rs +++compiler/rustc_macros/src/symbols/tests.rs +++compiler/rustc_type_ir/src/search_graph/mod.rs +++compiler/stable_mir/src/mir/visit.rs +++library/std/src/sys/pal/unix/process/process_unix.rs +++library/stdarch/crates/stdarch-verify/src/lib.rs +++src/librustdoc/html/markdown/tests.rs +++src/tools/cargo/crates/cargo-util-schemas/src/core/partial_version.rs +++src/tools/cargo/crates/cargo-util-schemas/src/manifest/rust_version.rs +++src/tools/cargo/crates/mdman/src/format/man.rs +++src/tools/cargo/crates/mdman/src/format/md.rs +++src/tools/cargo/crates/mdman/src/format/text.rs +++src/tools/cargo/crates/mdman/src/lib.rs +++src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++src/tools/compiletest/src/header/tests.rs +++src/tools/rust-analyzer/crates/cfg/src/tests.rs +++src/tools/rust-analyzer/crates/ide-assists/src/handlers/number_representation.rs +++src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs +++src/tools/rust-analyzer/crates/parser/src/lib.rs +++src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs +++src/tools/rust-analyzer/crates/ra-salsa/src/runtime.rs +++src/tools/rust-analyzer/crates/ra-salsa/src/runtime/local_state.rs +++src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs +++src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs +++src/tools/rustfmt/src/formatting.rs +++src/tools/rustfmt/src/lib.rs +++src/tools/rustfmt/src/parse/parser.rs +++src/tools/rustfmt/src/string.rs +++vendor/ahash-*/src/fallback_hash.rs +++vendor/ahash-*/src/hash_quality_test.rs +++vendor/ahash-*/src/lib.rs +++vendor/aho-corasick-*/src/ahocorasick.rs +++vendor/base16ct-*/benches/mod.rs +++vendor/base16ct-*/src/lower.rs +++vendor/base16ct-*/src/mixed.rs +++vendor/base16ct-*/src/upper.rs +++vendor/base64-*/src/decode.rs +++vendor/base64-*/src/encode.rs +++vendor/base64-*/src/engine/general_purpose/decode.rs +++vendor/base64ct-*/src/*.rs +++vendor/base64ct-*/tests/*.rs +++vendor/bitflags-*/src/tests/*.rs +++vendor/bitflags-*/src/traits.rs +++vendor/blake3-1.*/src/test.rs +++vendor/blake3-1.*/src/traits.rs +++vendor/block-buffer-*/tests/mod.rs +++vendor/camino-*/src/serde_impls.rs +++vendor/ciborium-*/tests/codec.rs +++vendor/clap*/src/derive.rs +++vendor/clap_derive-*/src/derives/args.rs +++vendor/clap_derive-*/src/derives/parser.rs +++vendor/clap_derive-*/src/derives/subcommand.rs +++vendor/clap_derive-*/src/derives/value_enum.rs +++vendor/color-print-proc-macro-*/src/format_args/mod.rs +++vendor/color-print-proc-macro-*/src/parse/color_tag.rs +++vendor/color-print-proc-macro-*/src/parse/util.rs +++vendor/compiler_builtins-*/libm/src/math/atan.rs +++vendor/datafrog-*/src/lib.rs +++vendor/dateparser-0.2.1/src/datetime.rs +++vendor/dateparser-0.2.1/src/timezone.rs +++vendor/digest-*/src/core_api/rt_variable.rs +++vendor/digest-*/src/core_api/wrapper.rs +++vendor/digest-*/src/dev.rs +++vendor/displaydoc-*/src/expand.rs +++vendor/ecdsa-*/src/der.rs +++vendor/ed25519-compact-*/src/sha512.rs +++vendor/env_logger-*/src/fmt/writer/mod.rs +++vendor/flate2-*/src/mem.rs +++vendor/flate2-*/src/zio.rs +++vendor/fst-*/src/raw/ops.rs +++vendor/futures-macro-*/src/lib.rs +++vendor/futures-macro-*/src/select.rs +++vendor/gimli*/src/read/aranges.rs +++vendor/gimli*/src/read/line.rs +++vendor/gimli*/src/read/loclists.rs +++vendor/gimli*/src/read/lookup.rs +++vendor/gimli*/src/read/rnglists.rs +++vendor/gimli*/src/read/unit.rs +++vendor/gix-config-*/src/file/init/mod.rs +++vendor/gix-config-*/src/parse/events.rs +++vendor/gix-config-*/src/parse/nom/mod.rs +++vendor/gix-date-*/src/parse.rs +++vendor/gix-discover-*/src/is.rs +++vendor/gix-features-*/src/parallel/mod.rs +++vendor/gix-features-*/src/parallel/reduce.rs +++vendor/gix-features-*/src/zlib/mod.rs +++vendor/gix-features-*/src/zlib/stream/inflate.rs +++vendor/gix-object-*/src/commit/ref_iter.rs +++vendor/gix-object-*/src/tag/ref_iter.rs +++vendor/gix-odb-*/src/store_impls/loose/find.rs +++vendor/gix-path-*/src/env/git/tests.rs +++vendor/gix-pathspec-*/src/lib.rs +++vendor/gix-pathspec-*/src/parse.rs +++vendor/gix-ref-*/src/store/packed/decode.rs +++vendor/gix-ref-*/src/store/packed/decode/tests.rs +++vendor/gix-revision-*/src/spec/parse/function.rs +++vendor/gix-url-*/src/lib.rs +++vendor/gix-url-*/src/parse.rs +++vendor/gix-validate-*/src/path.rs +++vendor/humansize-*/src/allocating.rs +++vendor/icu_locid-*/tests/langid.rs +++vendor/icu_locid-*/tests/locale.rs +++vendor/indoc-*/src/lib.rs +++vendor/libm-*/src/math/atan.rs +++vendor/lz4_flex-*/src/block/compress.rs +++vendor/lz4_flex-*/src/block/decompress_safe.rs +++vendor/lz4_flex-*/src/block/hashtable.rs +++vendor/miniz_oxide*/src/deflate/mod.rs +++vendor/miniz_oxide*/src/inflate/mod.rs +++vendor/nom-*/src/bits/complete.rs +++vendor/nom-*/src/bits/mod.rs +++vendor/nom-*/src/bits/streaming.rs +++vendor/nom-*/src/branch/mod.rs +++vendor/nom-*/src/branch/tests.rs +++vendor/nom-*/src/bytes/complete.rs +++vendor/nom-*/src/bytes/streaming.rs +++vendor/nom-*/src/character/complete.rs +++vendor/nom-*/src/character/streaming.rs +++vendor/nom-*/src/combinator/mod.rs +++vendor/nom-*/src/combinator/tests.rs +++vendor/nom-*/src/error.rs +++vendor/nom-*/src/internal.rs +++vendor/nom-*/src/multi/mod.rs +++vendor/nom-*/src/multi/tests.rs +++vendor/nom-*/src/number/complete.rs +++vendor/nom-*/src/number/streaming.rs +++vendor/nom-*/src/sequence/mod.rs +++vendor/nom-*/tests/css.rs +++vendor/nom-*/tests/issues.rs +++vendor/nom-*/tests/json.rs +++vendor/nom-*/tests/mp4.rs +++vendor/nom-*/tests/multiline.rs +++vendor/openssl-*/src/envelope.rs +++vendor/orion-*/src/test_framework/aead_interface.rs +++vendor/orion-*/src/test_framework/streamcipher_interface.rs +++vendor/os_info-*/src/matcher.rs +++vendor/pest-*/src/iterators/pair.rs +++vendor/pest-*/src/parser_state.rs +++vendor/pest-*/src/position.rs +++vendor/pest-*/src/span.rs +++vendor/pest-*/tests/calculator.rs +++vendor/pest_generator-*/src/generator.rs +++vendor/pest_generator-*/src/lib.rs +++vendor/proc-macro2-*/src/parse.rs +++vendor/pulldown-cmark-*/benches/html_rendering.rs +++vendor/pulldown-cmark-*/src/linklabel.rs +++vendor/pulldown-cmark-*/tests/lib.rs +++vendor/rayon-*/tests/sort-panic-safe.rs +++vendor/regex-*/src/regex/bytes.rs +++vendor/regex-automata-*/src/dfa/automaton.rs +++vendor/regex-automata-*/src/hybrid/dfa.rs +++vendor/regex-automata-*/src/meta/regex.rs +++vendor/regex-automata-*/src/regex.rs +++vendor/rinja-0.*/src/filters/mod.rs +++vendor/rinja-0.3.*/src/filters/builtin.rs +++vendor/rinja_parser-0.*/src/lib.rs +++vendor/rusqlite-*/src/util/sqlite_string.rs +++vendor/rustc-rayon-*/tests/sort-panic-safe.rs +++vendor/rustc_apfloat-*/src/lib.rs +++vendor/rustversion-*/src/attr.rs +++vendor/rustversion-*/src/expand.rs +++vendor/rustversion-*/src/lib.rs +++vendor/semver-*/src/parse.rs +++vendor/sha2-*/src/sha256.rs +++vendor/sha2-*/src/sha512.rs +++vendor/shell-words-*/src/lib.rs +++vendor/shlex-*/src/lib.rs +++vendor/syn-*/src/attr.rs +++vendor/syn-*/src/custom_punctuation.rs +++vendor/syn-*/src/data.rs +++vendor/syn-*/src/derive.rs +++vendor/syn-*/src/group.rs +++vendor/syn-*/src/meta.rs +++vendor/syn-*/src/pat.rs +++vendor/syn-*/src/path.rs +++vendor/syn-*/src/punctuated.rs +++vendor/syn-*/src/stmt.rs +++vendor/syn-*/src/token.rs +++vendor/syn-*/src/ty.rs +++vendor/syn-*/tests/test_meta.rs +++vendor/syntect-*/src/dumps.rs +++vendor/thiserror-impl-*/src/attr.rs +++vendor/thiserror-impl-*/src/expand.rs +++vendor/time-*/src/parsing/*.rs +++vendor/time-*/src/parsing/combinator/mod.rs +++vendor/time-*/src/parsing/combinator/rfc/*.rs +++vendor/time-*/src/primitive_date_time.rs +++vendor/toml_edit-*/src/parser/document.rs +++vendor/toml_edit-*/src/parser/key.rs +++vendor/toml_edit-*/src/parser/mod.rs +++vendor/toml_edit-*/src/parser/numbers.rs +++vendor/toml_edit-*/src/parser/strings.rs +++vendor/toml_edit-*/src/raw_string.rs +++vendor/toml_edit-*/tests/testsuite/parse.rs +++vendor/unic-langid-*/tests/langid.rs +++vendor/url-*/src/parser.rs +++vendor/utf-8-*/benches/from_utf8_lossy.rs +++vendor/utf-8-*/tests/unit.rs +++vendor/varisat-*/src/clause/alloc.rs +++vendor/varisat-*/src/solver.rs +++vendor/varisat-checker-*/src/lib.rs +++vendor/varisat-dimacs-*/src/lib.rs +++vendor/vec_mut_scan-*/src/lib.rs +++vendor/windows-bindgen-*/src/lib.rs +++vendor/windows-bindgen-*/src/rust/constants.rs +++vendor/winnow-*/benches/number.rs +++vendor/winnow-*/examples/css/parser.rs +++vendor/winnow-*/examples/http/parser.rs +++vendor/winnow-*/examples/http/parser_streaming.rs +++vendor/winnow-*/examples/json/parser.rs +++vendor/winnow-*/examples/json/parser_dispatch.rs +++vendor/winnow-*/examples/json/parser_partial.rs +++vendor/winnow-*/examples/ndjson/example.ndjson +++vendor/winnow-*/examples/ndjson/parser.rs +++vendor/winnow-*/src/ascii/mod.rs +++vendor/winnow-*/src/binary/bits/mod.rs +++vendor/winnow-*/src/binary/bits/tests.rs +++vendor/winnow-*/src/binary/mod.rs +++vendor/winnow-*/src/combinator/branch.rs +++vendor/winnow-*/src/combinator/core.rs +++vendor/winnow-*/src/combinator/multi.rs +++vendor/winnow-*/src/combinator/parser.rs +++vendor/winnow-*/src/combinator/sequence.rs +++vendor/winnow-*/src/combinator/tests.rs +++vendor/winnow-*/src/error.rs +++vendor/winnow-*/src/parser.rs +++vendor/winnow-*/src/token/mod.rs +++vendor/xz2-*/src/bufread.rs +++vendor/xz2-*/src/stream.rs +++vendor/yansi-*/tests/basic.rs +++ +++# file brokenness (detected als Dyalog APL transfer) +++vendor/clap-*/examples/demo.md +++vendor/clap-*/examples/tutorial_builder/*.md +++vendor/clap-*/examples/tutorial_derive/*.md diff --cc debian/upstream/signing-key.asc index 0000000000,0000000000,0000000000..93e2282c7a new file mode 100644 --- /dev/null +++ b/debian/upstream/signing-key.asc @@@@ -1,0 -1,0 -1,0 +1,86 @@@@ +++-----BEGIN PGP PUBLIC KEY BLOCK----- +++Version: GnuPG v1 +++ +++mQINBFJEwMkBEADlPACa2K7reD4x5zd8afKx75QYKmxqZwywRbgeICeD4bKiQoJZ +++dUjmn1LgrGaXuBMKXJQhyA34e/1YZel/8et+HPE5XpljBfNYXWbVocE1UMUTnFU9 +++CKXa4AhJ33f7we2/QmNRMUifw5adPwGMg4D8cDKXk02NdnqQlmFByv0vSaArR5kn +++gZKnLY6o0zZ9Buyy761Im/ShXqv4ATUgYiFc48z33G4j+BDmn0ryGr1aFdP58tHp +++gjWtLZs0iWeFNRDYDje6ODyu/MjOyuAWb2pYDH47Xu7XedMZzenH2TLM9yt/hyOV +++xReDPhvoGkaO8xqHioJMoPQi1gBjuBeewmFyTSPS4deASukhCFOcTsw/enzJagiS +++ZAq6Imehduke+peAL1z4PuRmzDPO2LPhVS7CDXtuKAYqUV2YakTq8MZUempVhw5n +++LqVaJ5/XiyOcv405PnkT25eIVVVghxAgyz6bOU/UMjGQYlkUxI7YZ9tdreLlFyPR +++OUL30E8q/aCd4PGJV24yJ1uit+yS8xjyUiMKm4J7oMP2XdBN98TUfLGw7SKeAxyU +++92BHlxg7yyPfI4TglsCzoSgEIV6xoGOVRRCYlGzSjUfz0bCMCclhTQRBkegKcjB3 +++sMTyG3SPZbjTlCqrFHy13e6hGl37Nhs8/MvXUysq2cluEISn5bivTKEeeQARAQAB +++tERSdXN0IExhbmd1YWdlIChUYWcgYW5kIFJlbGVhc2UgU2lnbmluZyBLZXkpIDxy +++dXN0LWtleUBydXN0LWxhbmcub3JnPokCOAQTAQIAIgUCUkTAyQIbAwYLCQgHAwIG +++FQgCCQoLBBYCAwECHgECF4AACgkQhauW5vob5f5fYQ//b1DWK1NSGx5nZ3zYZeHJ +++9mwGCftIaA2IRghAGrNf4Y8DaPqR+w1OdIegWn8kCoGfPfGAVW5XXJg+Oxk6QIaD +++2hJojBUrq1DALeCZVewzTVw6BN4DGuUexsc53a8DcY2Yk5WE3ll6UKq/YPiWiPNX +++9r8FE2MJwMABB6mWZLqJeg4RCrriBiCG26NZxGE7RTtPHyppoVxWKAFDiWyNdJ+3 +++UnjldWrT9xFqjqfXWw9Bhz8/EoaGeSSbMIAQDkQQpp1SWpljpgqvctZlc5fHhsG6 +++lmzW5RM4NG8OKvq3UrBihvgzwrIfoEDKpXbk3DXqaSs1o81NH5ftVWWbJp/ywM9Q +++uMC6n0YWiMZMQ1cFBy7tukpMkd+VPbPkiSwBhPkfZIzUAWd74nanN5SKBtcnymgJ ++++OJcxfZLiUkXRj0aUT1GLA9/7wnikhJI+RvwRfHBgrssXBKNPOfXGWajtIAmZc2t +++kR1E8zjBVLId7r5M8g52HKk+J+y5fVgJY91nxG0zf782JjtYuz9+knQd55JLFJCO +++hhbv3uRvhvkqgauHagR5X9vCMtcvqDseK7LXrRaOdOUDrK/Zg/abi5d+NIyZfEt/ +++ObFsv3idAIe/zpU6xa1nYNe3+Ixlb6mlZm3WCWGxWe+GvNW/kq36jZ/v/8pYMyVO +++p/kJqnf9y4dbufuYBg+RLqC5Ag0EUkTAyQEQANxy2tTSeRspfrpBk9+ju+KZ3zc4 +++umaIsEa5DxJ2zIKHywVAR67Um0K1YRG07/F5+tD9TIRkdx2pcmpjmSQzqdk3zqa9 +++2Zzeijjz2RNyBY8qYmyE08IncjTsFFB8OnvdXcsAgjCFmI1BKnePxrABL/2k8X18 +++aysPb0beWqQVsi5FsSpAHu6k1kaLKc+130x6Hf/YJAjeo+S7HeU5NeOz3zD+h5bA +++Q25qMiVHX3FwH7rFKZtFFog9Ogjzi0TkDKKxoeFKyADfIdteJWFjOlCI9KoIhfXq +++Et9JMnxApGqsJElJtfQjIdhMN4Lnep2WkudHAfwJ/412fe7wiW0rcBMvr/BlBGRY +++vM4sTgN058EwIuY9Qmc8RK4gbBf6GsfGNJjWozJ5XmXElmkQCAvbQFoAfi5TGfVb +++77QQrhrQlSpfIYrvfpvjYoqj618SbU6uBhzh758gLllmMB8LOhxWtq9eyn1rMWyR +++KL1fEkfvvMc78zP+Px6yDMa6UIez8jZXQ87Zou9EriLbzF4QfIYAqR9LUSMnLk6K +++o61tSFmFEDobC3tc1jkSg4zZe/wxskn96KOlmnxgMGO0vJ7ASrynoxEnQE8k3WwA ++++/YJDwboIR7zDwTy3Jw3mn1FgnH+c7Rb9h9geOzxKYINBFz5Hd0MKx7kZ1U6WobW +++KiYYxcCmoEeguSPHABEBAAGJAh8EGAECAAkFAlJEwMkCGwwACgkQhauW5vob5f7f +++FA//Ra+itJF4NsEyyhx4xYDOPq4uj0VWVjLdabDvFjQtbBLwIyh2bm8uO3AY4r/r +++rM5WWQ8oIXQ2vvXpAQO9g8iNlFez6OLzbfdSG80AG74pQqVVVyCQxD7FanB/KGge +++tAoOstFxaCAg4nxFlarMctFqOOXCFkylWl504JVIOvgbbbyj6I7qCUmbmqazBSMU +++K8c/Nz+FNu2Uf/lYWOeGogRSBgS0CVBcbmPUpnDHLxZWNXDWQOCxbhA1Uf58hcyu +++036kkiWHh2OGgJqlo2WIraPXx1cGw1Ey+U6exbtrZfE5kM9pZzRG7ZY83CXpYWMp +++kyVXNWmf9JcIWWBrXvJmMi0FDvtgg3Pt1tnoxqdilk6yhieFc8LqBn6CZgFUBk0t +++NSaWk3PsN0N6Ut8VXY6sai7MJ0Gih1gE1xadWj2zfZ9sLGyt2jZ6wK++U881YeXA +++ryaGKJ8sIs182hwQb4qN7eiUHzLtIh8oVBHo8Q4BJSat88E5/gOD6IQIpxc42iRL +++T+oNZw1hdwNyPOT1GMkkn86l3o7klwmQUWCPm6vl1aHp3omo+GHC63PpNFO5RncJ +++Ilo3aBKKmoE5lDSMGE8KFso5awTo9z9QnVPkRsk6qeBYit9xE3x3S+iwjcSg0nie +++aAkc0N00nc9V9jfPvt4z/5A5vjHh+NhFwH5h2vBJVPdsz6m5Ag0EVI9keAEQAL3R +++oVsHncJTmjHfBOV4JJsvCum4DuJDZ/rDdxauGcjMUWZaG338ZehnDqG1Yn/ys7zE +++aKYUmqyT+XP+M2IAQRTyxwlU1RsDlemQfWrESfZQCCmbnFScL0E7cBzy4xvtInQe +++UaFgJZ1BmxbzQrx+eBBdOTDv7RLnNVygRmMzmkDhxO1IGEu1+3ETIg/DxFE7VQY0 +++It/Ywz+nHu1o4Hemc/GdKxu9hcYvcRVc/Xhueq/zcIM96l0m+CFbs0HMKCj8dgMe +++Ng6pbbDjNM+cV+5BgpRdIpE2l9W7ImpbLihqcZt47J6oWt/RDRVoKOzRxjhULVyV +++2VP9ESr48HnbvxcpvUAEDCQUhsGpur4EKHFJ9AmQ4zf91gWLrDc6QmlACn9o9ARU +++fOV5aFsZI9ni1MJEInJTP37stz/uDECRie4LTL4O6P4Dkto8ROM2wzZq5CiRNfnT +++PP7ARfxlCkpg+gpLYRlxGUvRn6EeYwDtiMQJUQPfpGHSvThUlgDEsDrpp4SQSmdA +++CB+rvaRqCawWKoXs0In/9wylGorRUupeqGC0I0/rh+f5mayFvORzwy/4KK4QIEV9 +++aYTXTvSRl35MevfXU1Cumlaqle6SDkLr3ZnFQgJBqap0Y+Nmmz2HfO/pohsbtHPX +++92SN3dKqaoSBvzNGY5WT3CsqxDtik37kR3f9/DHpABEBAAGJBD4EGAECAAkFAlSP +++ZHgCGwICKQkQhauW5vob5f7BXSAEGQECAAYFAlSPZHgACgkQXLSpNHs7CdwemA/+ +++KFoGuFqU0uKT9qblN4ugRyil5itmTRVffl4tm5OoWkW8uDnu7Ue3vzdzy+9NV8X2 +++wRG835qjXijWP++AGuxgW6LB9nV5OWiKMCHOWnUjJQ6pNQMAgSN69QzkFXVF/q5f +++bkma9TgSbwjrVMyPzLSRwq7HsT3V02Qfr4cyq39QeILGy/NHW5z6LZnBy3BaVSd0 +++lGjCEc3yfH5OaB79na4W86WCV5n4IT7cojFM+LdL6P46RgmEtWSG3/CDjnJl6BLR +++WqatRNBWLIMKMpn+YvOOL9TwuP1xbqWr1vZ66wksm53NIDcWhptpp0KEuzbU0/Dt +++OltBhcX8tOmO36LrSadX9rwckSETCVYklmpAHNxPml011YNDThtBidvsicw1vZwR +++HsXn+txlL6RAIRN+J/Rw3uOiJAqN9Qgedpx2q+E15t8MiTg/FXtB9SysnskFT/BH +++z0USNKJUY0btZBw3eXWzUnZf59D8VW1M/9JwznCHAx0c9wy/gRDiwt9w4RoXryJD +++VAwZg8rwByjldoiThUJhkCYvJ0R3xH3kPnPlGXDW49E9R8C2umRC3cYOL4U9dOQ1 +++5hSlYydF5urFGCLIvodtE9q80uhpyt8L/5jj9tbwZWv6JLnfBquZSnCGqFZRfXlb +++Jphk9+CBQWwiZSRLZRzqQ4ffl4xyLuolx01PMaatkQbRaw/+JpgRNlurKQ0PsTrO +++8tztO/tpBBj/huc2DGkSwEWvkfWElS5RLDKdoMVs/j5CLYUJzZVikUJRm7m7b+OA +++P3W1nbDhuID+XV1CSBmGifQwpoPTys21stTIGLgznJrIfE5moFviOLqD/LrcYlsq +++CQg0yleu7SjOs//8dM3mC2FyLaE/dCZ8l2DCLhHw0+ynyRAvSK6aGCmZz6jMjmYF +++MXgiy7zESksMnVFMulIJJhR3eB0wx2GitibjY/ZhQ7tD3i0yy9ILR07dFz4pgkVM +++afxpVR7fmrMZ0t+yENd+9qzyAZs0ksxORoc2ze90SCx2jwEX/3K+m4I0hP2H/w5W +++gqdvuRLiqf+4BGW4zqWkLLlNIe/okt0r82SwHtDN0Ui1asmZTGj6sm8SXtwx+5cE +++38MttWqjDiibQOSthRVcETByRYM8KcjYSUCi4PoBc3NpDONkFbZm6XofR/f5mTcl +++2jDw6fIeVc4Hd1jBGajNzEqtneqqbdAkPQaLsuD2TMkQfTDJfE/IljwjrhDa9Mi+ +++odtnMWq8vlwOZZ24/8/BNK5qXuCYL67O7AJB4ZQ6BT+g4z96iRLbupzu/XJyXkQF +++rOY/Ghegvn7fDrnt2KC9MpgeFBXzUp+k5rzUdF8jbCx5apVjA1sWXB9Kh3L+DUwF +++Mve696B5tlHyc1KxjHR6w9GRsh4= +++=5FXw +++-----END PGP PUBLIC KEY BLOCK----- diff --cc debian/wasi-node index 0000000000,0000000000,0000000000..c1d5762758 new file mode 100755 --- /dev/null +++ b/debian/wasi-node @@@@ -1,0 -1,0 -1,0 +1,54 @@@@ +++#!/usr/bin/node --experimental-wasi-unstable-preview1 +++/// +++/// Simple WASI executor, adapted from the NodeJS WASI module API docs [1]. +++/// +++/// Usage: wasi-node [ .. ] +++/// +++/// Environment variables: +++/// +++/// WASI_NODE_PREOPENS - optional JSON file defining the application sandbox +++/// directory structure. See [1] for details. +++/// +++/// WASI_NODE_ENV - optional JSON file defining the application environment. +++/// If omitted then the process's POSIX environment is used; this may leak +++/// information. If a clean environment is required then set this to /dev/null +++/// or some other empty file. +++/// +++/// [1] https://nodejs.org/api/wasi.html +++ +++'use strict'; +++const fs = require('fs'); +++const { WASI } = require('wasi'); +++ +++// argv[0] is nodejs +++// argv[1] is this script +++var args = process.argv.slice(2); // inner argv includes cmd +++ +++if (!args[0]) { +++ console.warn(process.argv[1] + ": no command given"); +++ process.exit(1); +++} +++ +++var preopens = {}; +++var preopens_json = process.env["WASI_NODE_PREOPENS"]; +++if (preopens_json) { +++ var preopens_data = fs.readFileSync(preopens_json); +++ preopens = preopens_data.length ? JSON.parse(preopens_data) : {}; +++} +++ +++var env = process.env; +++var env_json = process.env["WASI_NODE_ENV"]; +++if (env_json) { +++ var env_data = fs.readFileSync(env_json); +++ env = env_data.length ? JSON.parse(env_data) : {}; +++} +++ +++const wasi = new WASI({ args: args, env: env, preopens: preopens }); +++const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; +++ +++(async () => { +++ const wasm = await WebAssembly.compile(fs.readFileSync(args[0])); +++ const instance = await WebAssembly.instantiate(wasm, importObject); +++ +++ wasi.start(instance); +++})(); diff --cc debian/watch index 0000000000,0000000000,0000000000..fe1cc1e51e new file mode 100644 --- /dev/null +++ b/debian/watch @@@@ -1,0 -1,0 -1,0 +1,18 @@@@ +++version=4 +++# if you need to download other versions replace the URL below with this one: +++# https://static.rust-lang.org/dist/channel-rust-$VERSION.toml +++# and also add searchmode=plain,\ +++# it's a bit slower to download, that's why we use the other one normally +++ +++opts="\ +++pgpsigurlmangle=s/$/.asc/,\ +++uversionmangle=s/(\d)[_.+-]?((beta|alpha)\.?\d*)$/$1~$2/,\ +++dversionmangle=s/\+dfsg\d*$//,\ +++downloadurlmangle=s/\.[gx]z/.xz/,\ +++filenamemangle=s/.*\/(.*)\.[gx]z(\..*)?/$1.xz$2/,\ +++repack,\ +++repacksuffix=+dfsg1,\ +++compression=xz,\ +++" \ +++ https://forge.rust-lang.org/infra/other-installation-methods.html \ +++ https://(?:.*/)rustc?-(\d[\d.]*(?:-[\w.]+)?)-src\.tar\.[gx]z diff --cc debian/watch-beta.in index 0000000000,0000000000,0000000000..5cd2aa66e8 new file mode 100644 --- /dev/null +++ b/debian/watch-beta.in @@@@ -1,0 -1,0 -1,0 +1,17 @@@@ +++version=4 +++# if you need to download other versions replace the URL below with this one: +++# https://static.rust-lang.org/dist/index.html +++# it's a bit slower to download, that's why we use the other one normally +++ +++opts="\ +++pgpsigurlmangle=s/$/.asc/,\ +++uversionmangle=s/.*/NEWVER~beta.999/,\ +++dversionmangle=s/\+dfsg\d*$//,\ +++downloadurlmangle=s/rustc-.*-(.*)\.[gx]z/rustc-beta-$1.xz/,\ +++filenamemangle=s/.*\/(.*)-[^-]*-(.*)\.[gx]z(\..*)?/$1-NEWVER-beta.999-$2.xz$3/,\ +++repack,\ +++repacksuffix=+dfsg1,\ +++compression=xz,\ +++" \ +++ https://forge.rust-lang.org/infra/other-installation-methods.html \ +++ (?:.*/)rustc?-(.*)-src\.tar\.[gx]z diff --cc extra/git2-curl/.cargo-checksum.json index 0000000000,0000000000,0000000000..d7d9bf1fff new file mode 100644 --- /dev/null +++ b/extra/git2-curl/.cargo-checksum.json @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++{"files":{"CHANGELOG.md":"433aae66b26ec1e1d867def155919cee89d831b0d14e5d20b9e80e1f11a20101","Cargo.toml":"49cac7eabb933177c492b5fa3a57813fb19e7471bb64d76777d172b81588738d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","src/lib.rs":"b1919f3ae4b6e4eba32fe74167ca13393baecccb04f986cdd4de71b122d48701","tests/all.rs":"5b48bca5608c533f4763f850a9b838cffe09e73e529261f16c331e10296f8e14"},"package":"be8dcabbc09ece4d30a9aa983d5804203b7e2f8054a171f792deff59b56d31fa"} diff --cc extra/git2-curl/CHANGELOG.md index 0000000000,0000000000,0000000000..1d51c646f7 new file mode 100644 --- /dev/null +++ b/extra/git2-curl/CHANGELOG.md @@@@ -1,0 -1,0 -1,0 +1,31 @@@@ +++# Changelog +++ +++## 0.20.0 - 2024-06-13 +++[0.19.0...0.20.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.19.0...git2-curl-0.20.0) +++ +++- Updated to [git2 0.19.0](../CHANGELOG.md#0190---2024-06-13) +++ +++## 0.19.0 - 2023-08-28 +++[0.18.0...0.19.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.18.0...git2-curl-0.19.0) +++ +++- Updated to [git2 0.18.0](../CHANGELOG.md#0180---2023-08-26) +++ +++## 0.18.0 - 2023-04-02 +++[0.17.0...0.18.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.17.0...git2-curl-0.18.0) +++ +++- Updated to [git2 0.17.0](../CHANGELOG.md#0170---2023-04-02) +++ +++## 0.17.0 - 2023-01-10 +++[0.16.0...0.17.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.16.0...git2-curl-0.17.0) +++ +++- Updated to [git2 0.16.0](../CHANGELOG.md#0160---2023-01-10) +++ +++## 0.16.0 - 2022-07-28 +++[0.15.0...0.16.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.15.0...git2-curl-0.16.0) +++ +++- Updated to [git2 0.15.0](../CHANGELOG.md#0150---2022-07-28) +++ +++## 0.15.0 - 2022-02-28 +++[0.14.1...0.15.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.14.1...git2-curl-0.15.0) +++ +++- Updated to [git2 0.14.0](../CHANGELOG.md#0140---2022-02-24) diff --cc extra/git2-curl/Cargo.toml index 0000000000,0000000000,0000000000..9313f18407 new file mode 100644 --- /dev/null +++ b/extra/git2-curl/Cargo.toml @@@@ -1,0 -1,0 -1,0 +1,74 @@@@ +++# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +++# +++# When uploading crates to the registry Cargo will automatically +++# "normalize" Cargo.toml files for maximal compatibility +++# with all versions of Cargo and also rewrite `path` dependencies +++# to registry (e.g., crates.io) dependencies. +++# +++# If you are reading this file be aware that the original Cargo.toml +++# will likely look very different (and much more reasonable). +++# See Cargo.toml.orig for the original contents. +++ +++[package] +++edition = "2018" +++name = "git2-curl" +++version = "0.21.0" +++authors = [ +++ "Josh Triplett ", +++ "Alex Crichton ", +++] +++build = false +++autolib = false +++autobins = false +++autoexamples = false +++autotests = false +++autobenches = false +++description = """ +++Backend for an HTTP transport in libgit2 powered by libcurl. +++ +++Intended to be used with the git2 crate. +++""" +++documentation = "https://docs.rs/git2-curl" +++readme = false +++license = "MIT OR Apache-2.0" +++repository = "https://github.com/rust-lang/git2-rs" +++ +++[lib] +++name = "git2_curl" +++path = "src/lib.rs" +++ +++[[test]] +++name = "all" +++path = "tests/all.rs" +++harness = false +++ +++[dependencies.curl] +++version = "0.4.33" +++ +++[dependencies.git2] +++version = "0.20" +++default-features = false +++ +++[dependencies.log] +++version = "0.4" +++ +++[dependencies.url] +++version = "2.0" +++ +++[dev-dependencies.civet] +++version = "0.11" +++ +++[dev-dependencies.conduit] +++version = "0.8" +++ +++[dev-dependencies.conduit-git-http-backend] +++version = "0.8" +++ +++[dev-dependencies.tempfile] +++version = "3.0" +++ +++[features] +++zlib-ng-compat = [ +++ "git2/zlib-ng-compat", +++ "curl/zlib-ng-compat", +++] diff --cc extra/git2-curl/LICENSE-APACHE index 0000000000,0000000000,0000000000..16fe87b06e new file mode 100644 --- /dev/null +++ b/extra/git2-curl/LICENSE-APACHE @@@@ -1,0 -1,0 -1,0 +1,201 @@@@ +++ Apache License +++ Version 2.0, January 2004 +++ http://www.apache.org/licenses/ +++ +++TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +++ +++1. Definitions. +++ +++ "License" shall mean the terms and conditions for use, reproduction, +++ and distribution as defined by Sections 1 through 9 of this document. +++ +++ "Licensor" shall mean the copyright owner or entity authorized by +++ the copyright owner that is granting the License. +++ +++ "Legal Entity" shall mean the union of the acting entity and all +++ other entities that control, are controlled by, or are under common +++ control with that entity. For the purposes of this definition, +++ "control" means (i) the power, direct or indirect, to cause the +++ direction or management of such entity, whether by contract or +++ otherwise, or (ii) ownership of fifty percent (50%) or more of the +++ outstanding shares, or (iii) beneficial ownership of such entity. +++ +++ "You" (or "Your") shall mean an individual or Legal Entity +++ exercising permissions granted by this License. +++ +++ "Source" form shall mean the preferred form for making modifications, +++ including but not limited to software source code, documentation +++ source, and configuration files. +++ +++ "Object" form shall mean any form resulting from mechanical +++ transformation or translation of a Source form, including but +++ not limited to compiled object code, generated documentation, +++ and conversions to other media types. +++ +++ "Work" shall mean the work of authorship, whether in Source or +++ Object form, made available under the License, as indicated by a +++ copyright notice that is included in or attached to the work +++ (an example is provided in the Appendix below). +++ +++ "Derivative Works" shall mean any work, whether in Source or Object +++ form, that is based on (or derived from) the Work and for which the +++ editorial revisions, annotations, elaborations, or other modifications +++ represent, as a whole, an original work of authorship. For the purposes +++ of this License, Derivative Works shall not include works that remain +++ separable from, or merely link (or bind by name) to the interfaces of, +++ the Work and Derivative Works thereof. +++ +++ "Contribution" shall mean any work of authorship, including +++ the original version of the Work and any modifications or additions +++ to that Work or Derivative Works thereof, that is intentionally +++ submitted to Licensor for inclusion in the Work by the copyright owner +++ or by an individual or Legal Entity authorized to submit on behalf of +++ the copyright owner. For the purposes of this definition, "submitted" +++ means any form of electronic, verbal, or written communication sent +++ to the Licensor or its representatives, including but not limited to +++ communication on electronic mailing lists, source code control systems, +++ and issue tracking systems that are managed by, or on behalf of, the +++ Licensor for the purpose of discussing and improving the Work, but +++ excluding communication that is conspicuously marked or otherwise +++ designated in writing by the copyright owner as "Not a Contribution." +++ +++ "Contributor" shall mean Licensor and any individual or Legal Entity +++ on behalf of whom a Contribution has been received by Licensor and +++ subsequently incorporated within the Work. +++ +++2. Grant of Copyright License. Subject to the terms and conditions of +++ this License, each Contributor hereby grants to You a perpetual, +++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable +++ copyright license to reproduce, prepare Derivative Works of, +++ publicly display, publicly perform, sublicense, and distribute the +++ Work and such Derivative Works in Source or Object form. +++ +++3. Grant of Patent License. Subject to the terms and conditions of +++ this License, each Contributor hereby grants to You a perpetual, +++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable +++ (except as stated in this section) patent license to make, have made, +++ use, offer to sell, sell, import, and otherwise transfer the Work, +++ where such license applies only to those patent claims licensable +++ by such Contributor that are necessarily infringed by their +++ Contribution(s) alone or by combination of their Contribution(s) +++ with the Work to which such Contribution(s) was submitted. If You +++ institute patent litigation against any entity (including a +++ cross-claim or counterclaim in a lawsuit) alleging that the Work +++ or a Contribution incorporated within the Work constitutes direct +++ or contributory patent infringement, then any patent licenses +++ granted to You under this License for that Work shall terminate +++ as of the date such litigation is filed. +++ +++4. Redistribution. You may reproduce and distribute copies of the +++ Work or Derivative Works thereof in any medium, with or without +++ modifications, and in Source or Object form, provided that You +++ meet the following conditions: +++ +++ (a) You must give any other recipients of the Work or +++ Derivative Works a copy of this License; and +++ +++ (b) You must cause any modified files to carry prominent notices +++ stating that You changed the files; and +++ +++ (c) You must retain, in the Source form of any Derivative Works +++ that You distribute, all copyright, patent, trademark, and +++ attribution notices from the Source form of the Work, +++ excluding those notices that do not pertain to any part of +++ the Derivative Works; and +++ +++ (d) If the Work includes a "NOTICE" text file as part of its +++ distribution, then any Derivative Works that You distribute must +++ include a readable copy of the attribution notices contained +++ within such NOTICE file, excluding those notices that do not +++ pertain to any part of the Derivative Works, in at least one +++ of the following places: within a NOTICE text file distributed +++ as part of the Derivative Works; within the Source form or +++ documentation, if provided along with the Derivative Works; or, +++ within a display generated by the Derivative Works, if and +++ wherever such third-party notices normally appear. The contents +++ of the NOTICE file are for informational purposes only and +++ do not modify the License. You may add Your own attribution +++ notices within Derivative Works that You distribute, alongside +++ or as an addendum to the NOTICE text from the Work, provided +++ that such additional attribution notices cannot be construed +++ as modifying the License. +++ +++ You may add Your own copyright statement to Your modifications and +++ may provide additional or different license terms and conditions +++ for use, reproduction, or distribution of Your modifications, or +++ for any such Derivative Works as a whole, provided Your use, +++ reproduction, and distribution of the Work otherwise complies with +++ the conditions stated in this License. +++ +++5. Submission of Contributions. Unless You explicitly state otherwise, +++ any Contribution intentionally submitted for inclusion in the Work +++ by You to the Licensor shall be under the terms and conditions of +++ this License, without any additional terms or conditions. +++ Notwithstanding the above, nothing herein shall supersede or modify +++ the terms of any separate license agreement you may have executed +++ with Licensor regarding such Contributions. +++ +++6. Trademarks. This License does not grant permission to use the trade +++ names, trademarks, service marks, or product names of the Licensor, +++ except as required for reasonable and customary use in describing the +++ origin of the Work and reproducing the content of the NOTICE file. +++ +++7. Disclaimer of Warranty. Unless required by applicable law or +++ agreed to in writing, Licensor provides the Work (and each +++ Contributor provides its Contributions) on an "AS IS" BASIS, +++ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +++ implied, including, without limitation, any warranties or conditions +++ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +++ PARTICULAR PURPOSE. You are solely responsible for determining the +++ appropriateness of using or redistributing the Work and assume any +++ risks associated with Your exercise of permissions under this License. +++ +++8. Limitation of Liability. In no event and under no legal theory, +++ whether in tort (including negligence), contract, or otherwise, +++ unless required by applicable law (such as deliberate and grossly +++ negligent acts) or agreed to in writing, shall any Contributor be +++ liable to You for damages, including any direct, indirect, special, +++ incidental, or consequential damages of any character arising as a +++ result of this License or out of the use or inability to use the +++ Work (including but not limited to damages for loss of goodwill, +++ work stoppage, computer failure or malfunction, or any and all +++ other commercial damages or losses), even if such Contributor +++ has been advised of the possibility of such damages. +++ +++9. Accepting Warranty or Additional Liability. While redistributing +++ the Work or Derivative Works thereof, You may choose to offer, +++ and charge a fee for, acceptance of support, warranty, indemnity, +++ or other liability obligations and/or rights consistent with this +++ License. However, in accepting such obligations, You may act only +++ on Your own behalf and on Your sole responsibility, not on behalf +++ of any other Contributor, and only if You agree to indemnify, +++ defend, and hold each Contributor harmless for any liability +++ incurred by, or claims asserted against, such Contributor by reason +++ of your accepting any such warranty or additional liability. +++ +++END OF TERMS AND CONDITIONS +++ +++APPENDIX: How to apply the Apache License to your work. +++ +++ To apply the Apache License to your work, attach the following +++ boilerplate notice, with the fields enclosed by brackets "[]" +++ replaced with your own identifying information. (Don't include +++ the brackets!) The text should be enclosed in the appropriate +++ comment syntax for the file format. We also recommend that a +++ file or class name and description of purpose be included on the +++ same "printed page" as the copyright notice for easier +++ identification within third-party archives. +++ +++Copyright [yyyy] [name of copyright owner] +++ +++Licensed under the Apache License, Version 2.0 (the "License"); +++you may not use this file except in compliance with the License. +++You may obtain a copy of the License at +++ +++ http://www.apache.org/licenses/LICENSE-2.0 +++ +++Unless required by applicable law or agreed to in writing, software +++distributed under the License is distributed on an "AS IS" BASIS, +++WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +++See the License for the specific language governing permissions and +++limitations under the License. diff --cc extra/git2-curl/LICENSE-MIT index 0000000000,0000000000,0000000000..39e0ed6602 new file mode 100644 --- /dev/null +++ b/extra/git2-curl/LICENSE-MIT @@@@ -1,0 -1,0 -1,0 +1,25 @@@@ +++Copyright (c) 2014 Alex Crichton +++ +++Permission is hereby granted, free of charge, to any +++person obtaining a copy of this software and associated +++documentation files (the "Software"), to deal in the +++Software without restriction, including without +++limitation the rights to use, copy, modify, merge, +++publish, distribute, sublicense, and/or sell copies of +++the Software, and to permit persons to whom the Software +++is furnished to do so, subject to the following +++conditions: +++ +++The above copyright notice and this permission notice +++shall be included in all copies or substantial portions +++of the Software. +++ +++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +++ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +++TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +++PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +++SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +++CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +++OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +++IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +++DEALINGS IN THE SOFTWARE. diff --cc extra/git2-curl/src/lib.rs index 0000000000,0000000000,0000000000..6fa4532772 new file mode 100644 --- /dev/null +++ b/extra/git2-curl/src/lib.rs @@@@ -1,0 -1,0 -1,0 +1,291 @@@@ +++//! A crate for using libcurl as a backend for HTTP git requests with git2-rs. +++//! +++//! This crate provides one public function, `register`, which will register +++//! a custom HTTP transport with libcurl for any HTTP requests made by libgit2. +++//! At this time the `register` function is unsafe for the same reasons that +++//! `git2::transport::register` is also unsafe. +++//! +++//! It is not recommended to use this crate wherever possible. The current +++//! libcurl backend used, `curl-rust`, only supports executing a request in one +++//! method call implying no streaming support. This consequently means that +++//! when a repository is cloned the entire contents of the repo are downloaded +++//! into memory, and *then* written off to disk by libgit2 afterwards. It +++//! should be possible to alleviate this problem in the future. +++//! +++//! > **NOTE**: At this time this crate likely does not support a `git push` +++//! > operation, only clones. +++ +++#![doc(html_root_url = "https://docs.rs/git2-curl/0.21")] +++#![deny(missing_docs)] +++#![warn(rust_2018_idioms)] +++#![cfg_attr(test, deny(warnings))] +++ +++use std::error; +++use std::io::prelude::*; +++use std::io::{self, Cursor}; +++use std::str; +++use std::sync::{Arc, Mutex, Once}; +++ +++use curl::easy::{Easy, List}; +++use git2::transport::SmartSubtransportStream; +++use git2::transport::{Service, SmartSubtransport, Transport}; +++use git2::Error; +++use log::{debug, info}; +++use url::Url; +++ +++struct CurlTransport { +++ handle: Arc>, +++ /// The URL of the remote server, e.g. `https://github.com/user/repo` +++ /// +++ /// This is an empty string until the first action is performed. +++ /// If there is an HTTP redirect, this will be updated with the new URL. +++ base_url: Arc>, +++} +++ +++struct CurlSubtransport { +++ handle: Arc>, +++ service: &'static str, +++ url_path: &'static str, +++ base_url: Arc>, +++ method: &'static str, +++ reader: Option>>, +++ sent_request: bool, +++} +++ +++/// Register the libcurl backend for HTTP requests made by libgit2. +++/// +++/// This function takes one parameter, a `handle`, which is used to perform all +++/// future HTTP requests. The handle can be previously configured with +++/// information such as proxies, SSL information, etc. +++/// +++/// This function is unsafe largely for the same reasons as +++/// `git2::transport::register`: +++/// +++/// * The function needs to be synchronized against all other creations of +++/// transport (any API calls to libgit2). +++/// * The function will leak `handle` as once registered it is not currently +++/// possible to unregister the backend. +++/// +++/// This function may be called concurrently, but only the first `handle` will +++/// be used. All others will be discarded. +++pub unsafe fn register(handle: Easy) { +++ static INIT: Once = Once::new(); +++ +++ let handle = Arc::new(Mutex::new(handle)); +++ let handle2 = handle.clone(); +++ INIT.call_once(move || { +++ git2::transport::register("http", move |remote| factory(remote, handle.clone())).unwrap(); +++ git2::transport::register("https", move |remote| factory(remote, handle2.clone())).unwrap(); +++ }); +++} +++ +++fn factory(remote: &git2::Remote<'_>, handle: Arc>) -> Result { +++ Transport::smart( +++ remote, +++ true, +++ CurlTransport { +++ handle: handle, +++ base_url: Arc::new(Mutex::new(String::new())), +++ }, +++ ) +++} +++ +++impl SmartSubtransport for CurlTransport { +++ fn action( +++ &self, +++ url: &str, +++ action: Service, +++ ) -> Result, Error> { +++ let mut base_url = self.base_url.lock().unwrap(); +++ if base_url.len() == 0 { +++ *base_url = url.to_string(); +++ } +++ let (service, path, method) = match action { +++ Service::UploadPackLs => ("upload-pack", "/info/refs?service=git-upload-pack", "GET"), +++ Service::UploadPack => ("upload-pack", "/git-upload-pack", "POST"), +++ Service::ReceivePackLs => { +++ ("receive-pack", "/info/refs?service=git-receive-pack", "GET") +++ } +++ Service::ReceivePack => ("receive-pack", "/git-receive-pack", "POST"), +++ }; +++ info!("action {} {}", service, path); +++ Ok(Box::new(CurlSubtransport { +++ handle: self.handle.clone(), +++ service: service, +++ url_path: path, +++ base_url: self.base_url.clone(), +++ method: method, +++ reader: None, +++ sent_request: false, +++ })) +++ } +++ +++ fn close(&self) -> Result<(), Error> { +++ Ok(()) // ... +++ } +++} +++ +++impl CurlSubtransport { +++ fn err>>(&self, err: E) -> io::Error { +++ io::Error::new(io::ErrorKind::Other, err) +++ } +++ +++ fn execute(&mut self, data: &[u8]) -> io::Result<()> { +++ if self.sent_request { +++ return Err(self.err("already sent HTTP request")); +++ } +++ let agent = format!("git/1.0 (git2-curl {})", env!("CARGO_PKG_VERSION")); +++ +++ // Parse our input URL to figure out the host +++ let url = format!("{}{}", self.base_url.lock().unwrap(), self.url_path); +++ let parsed = Url::parse(&url).map_err(|_| self.err("invalid url, failed to parse"))?; +++ let host = match parsed.host_str() { +++ Some(host) => host, +++ None => return Err(self.err("invalid url, did not have a host")), +++ }; +++ +++ // Prep the request +++ debug!("request to {}", url); +++ let mut h = self.handle.lock().unwrap(); +++ h.url(&url)?; +++ h.useragent(&agent)?; +++ h.follow_location(true)?; +++ match self.method { +++ "GET" => h.get(true)?, +++ "PUT" => h.put(true)?, +++ "POST" => h.post(true)?, +++ other => h.custom_request(other)?, +++ } +++ +++ let mut headers = List::new(); +++ headers.append(&format!("Host: {}", host))?; +++ if data.len() > 0 { +++ h.post_fields_copy(data)?; +++ headers.append(&format!( +++ "Accept: application/x-git-{}-result", +++ self.service +++ ))?; +++ headers.append(&format!( +++ "Content-Type: \ +++ application/x-git-{}-request", +++ self.service +++ ))?; +++ } else { +++ headers.append("Accept: */*")?; +++ } +++ headers.append("Expect:")?; +++ h.http_headers(headers)?; +++ +++ let mut content_type = None; +++ let mut data = Vec::new(); +++ { +++ let mut h = h.transfer(); +++ +++ // Look for the Content-Type header +++ h.header_function(|header| { +++ let header = match str::from_utf8(header) { +++ Ok(s) => s, +++ Err(..) => return true, +++ }; +++ let mut parts = header.splitn(2, ": "); +++ let name = parts.next().unwrap(); +++ let value = match parts.next() { +++ Some(value) => value, +++ None => return true, +++ }; +++ if name.eq_ignore_ascii_case("Content-Type") { +++ content_type = Some(value.trim().to_string()); +++ } +++ +++ true +++ })?; +++ +++ // Collect the request's response in-memory +++ h.write_function(|buf| { +++ data.extend_from_slice(buf); +++ Ok(buf.len()) +++ })?; +++ +++ // Send the request +++ h.perform()?; +++ } +++ +++ let code = h.response_code()?; +++ if code != 200 { +++ return Err(self.err( +++ &format!( +++ "failed to receive HTTP 200 response: \ +++ got {}", +++ code +++ )[..], +++ )); +++ } +++ +++ // Check returned headers +++ let expected = match self.method { +++ "GET" => format!("application/x-git-{}-advertisement", self.service), +++ _ => format!("application/x-git-{}-result", self.service), +++ }; +++ match content_type { +++ Some(ref content_type) if *content_type != expected => { +++ return Err(self.err( +++ &format!( +++ "expected a Content-Type header \ +++ with `{}` but found `{}`", +++ expected, content_type +++ )[..], +++ )) +++ } +++ Some(..) => {} +++ None => { +++ return Err(self.err( +++ &format!( +++ "expected a Content-Type header \ +++ with `{}` but didn't find one", +++ expected +++ )[..], +++ )) +++ } +++ } +++ +++ // Ok, time to read off some data. +++ let rdr = Cursor::new(data); +++ self.reader = Some(rdr); +++ +++ // If there was a redirect, update the `CurlTransport` with the new base. +++ if let Ok(Some(effective_url)) = h.effective_url() { +++ let new_base = if effective_url.ends_with(self.url_path) { +++ // Strip the action from the end. +++ &effective_url[..effective_url.len() - self.url_path.len()] +++ } else { +++ // I'm not sure if this code path makes sense, but it's what +++ // libgit does. +++ effective_url +++ }; +++ *self.base_url.lock().unwrap() = new_base.to_string(); +++ } +++ +++ Ok(()) +++ } +++} +++ +++impl Read for CurlSubtransport { +++ fn read(&mut self, buf: &mut [u8]) -> io::Result { +++ if self.reader.is_none() { +++ self.execute(&[])?; +++ } +++ self.reader.as_mut().unwrap().read(buf) +++ } +++} +++ +++impl Write for CurlSubtransport { +++ fn write(&mut self, data: &[u8]) -> io::Result { +++ if self.reader.is_none() { +++ self.execute(data)?; +++ } +++ Ok(data.len()) +++ } +++ fn flush(&mut self) -> io::Result<()> { +++ Ok(()) +++ } +++} diff --cc extra/git2-curl/tests/all.rs index 0000000000,0000000000,0000000000..c7f09dd40a new file mode 100644 --- /dev/null +++ b/extra/git2-curl/tests/all.rs @@@@ -1,0 -1,0 -1,0 +1,74 @@@@ +++use civet::{Config, Server}; +++use conduit_git_http_backend as git_backend; +++use std::fs::File; +++use std::path::Path; +++use tempfile::TempDir; +++ +++const PORT: u16 = 7848; +++ +++fn main() { +++ unsafe { +++ git2_curl::register(curl::easy::Easy::new()); +++ } +++ +++ // Spin up a server for git-http-backend +++ let td = TempDir::new().unwrap(); +++ let mut cfg = Config::new(); +++ cfg.port(PORT).threads(1); +++ let _a = Server::start(cfg, git_backend::Serve(td.path().to_path_buf())); +++ +++ // Prep a repo with one file called `foo` +++ let sig = git2::Signature::now("foo", "bar").unwrap(); +++ let r1 = git2::Repository::init(td.path()).unwrap(); +++ File::create(&td.path().join(".git").join("git-daemon-export-ok")).unwrap(); +++ { +++ let mut index = r1.index().unwrap(); +++ File::create(&td.path().join("foo")).unwrap(); +++ index.add_path(Path::new("foo")).unwrap(); +++ index.write().unwrap(); +++ let tree_id = index.write_tree().unwrap(); +++ r1.commit( +++ Some("HEAD"), +++ &sig, +++ &sig, +++ "test", +++ &r1.find_tree(tree_id).unwrap(), +++ &[], +++ ) +++ .unwrap(); +++ } +++ +++ // Clone through the git-http-backend +++ let td2 = TempDir::new().unwrap(); +++ let r = git2::Repository::clone(&format!("http://localhost:{}", PORT), td2.path()).unwrap(); +++ assert!(File::open(&td2.path().join("foo")).is_ok()); +++ { +++ File::create(&td.path().join("bar")).unwrap(); +++ let mut index = r1.index().unwrap(); +++ index.add_path(&Path::new("bar")).unwrap(); +++ index.write().unwrap(); +++ let tree_id = index.write_tree().unwrap(); +++ let parent = r1.head().ok().and_then(|h| h.target()).unwrap(); +++ let parent = r1.find_commit(parent).unwrap(); +++ r1.commit( +++ Some("HEAD"), +++ &sig, +++ &sig, +++ "test", +++ &r1.find_tree(tree_id).unwrap(), +++ &[&parent], +++ ) +++ .unwrap(); +++ } +++ +++ let mut remote = r.find_remote("origin").unwrap(); +++ remote +++ .fetch(&["refs/heads/*:refs/heads/*"], None, None) +++ .unwrap(); +++ let b = r.find_branch("master", git2::BranchType::Local).unwrap(); +++ let id = b.get().target().unwrap(); +++ let obj = r.find_object(id, None).unwrap(); +++ r.reset(&obj, git2::ResetType::Hard, None).unwrap(); +++ +++ assert!(File::open(&td2.path().join("bar")).is_ok()); +++} diff --cc extra/git2/.cargo-checksum.json index 0000000000,0000000000,0000000000..2a96f97e52 new file mode 100644 --- /dev/null +++ b/extra/git2/.cargo-checksum.json @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++{"files":{"CHANGELOG.md":"483ffa6c5a0e015fa4bb3376aebb1287274d9e7c0cc6a3f63b17451fd7f6092e","CONTRIBUTING.md":"6a996c629901ea1907887ef180f1bc034b31de05e26bf2b93ea61c066557fcd2","Cargo.lock":"1dc16599ba4edba4e0112bba53c4ae8f4d869b1f9e87b3abfbd7879e8c8d99d0","Cargo.toml":"e5aecc6fc09a347ddabc49fbae90e9207f68258cb2fc7e172c5c45a5c234b9f0","FUNDING.json":"c06c025744e060bc3dad39a052e15207fae3a7e31fc414af09b4e40e27778e79","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"8ef68e5e41b8960a67e612105cac7c65e2bde60494ac4f71c470826495129877","ci/publish.sh":"5b55345634baf7b0eb3aa3c84f44d1727a22a5197d0acd6f0312a47a1bfef889","examples/add.rs":"73ffbf602e48fced127415b8c2117df1e7c935bba212b6e360349550bed09afa","examples/blame.rs":"f6a8cff18376b407cc0bcb96f962df3845839cd59826f7ce8fdeb93daf277792","examples/cat-file.rs":"b7f7499d233fa1482d96e0988d49575b932025d99b9371acfed9d05b402682f7","examples/clone.rs":"0f50645cd7c31c370a6c8f9e7c15a9eca0ac214d69bffdd90c98933364f39c37","examples/diff.rs":"5b52278056b0c51c5e42a1ff96a80de34c7037ade01b49ac6a985d9f7a474c15","examples/fetch.rs":"f784e22534c71da2e8d30a59eba40d4b014cf1bf1a38cc4f0160a77a6dbbd334","examples/init.rs":"b9adb23a4bd950a2d3c3004d068c033b2bb8898d22608db16f695da48b54f293","examples/log.rs":"c6b622dcfbedb1e60cf6c41988daa74382da484506612834ea625f299741a1b4","examples/ls-remote.rs":"c21e3a4a661ce44e63aefeac680f27648e0ba3c895c9f0843557b25c20fc2390","examples/pull.rs":"f9ecf2b67170c48cc9f97133d3046578096f5d86beed7fc8d1f7ba0c906d59d5","examples/rev-list.rs":"28bfc6158ac782316dc06822a77d9952c70ea9ac2cafd3aa4809e88298b65ac8","examples/rev-parse.rs":"93e84d0e0211b68c49c397c4a55502f977b25fa0efbcff023b7f57f8f45be6e2","examples/status.rs":"f601427eb7f9b0dccee6e08dfd2b06b453a118f272c08ea0841e6a33896cac49","examples/tag.rs":"5cfb15225a1ae35b2490e01667a35deb50603293660344cb0210785568bdb4d2","src/apply.rs":"1ca5b0c06b96cd0af13dc322bf858e375a50f76d887c61052115ea8af2245847","src/attr.rs":"bc1957f495cf3aed4a663b50b43dd8deee6770ab259283673a883ac3c66908a7","src/blame.rs":"87cefd39c2bbb6fc7f9ecb549d44541f44ce61505a92368a93378b81df0b3c22","src/blob.rs":"7cb0326521dec9548a05c155283495c33f629678d9f7263e9de500c32052fb74","src/branch.rs":"1afa850c4c3a22531baddf5636bf55c9122a76b0d010e8392fbf04f1b76067ed","src/buf.rs":"d4d9795afc04eba6eb6a08c5dbcbc8e3e8341adc11701c65198d514f6cdfbac0","src/build.rs":"7e71b5821d8cfb86aa19bf3f7975c06a12e1589693f8de2ff10b332eb42714c6","src/call.rs":"e61e208050d3d17351da033a8fb48efbe2b7ef1ea0a1e81c98ad5df295162b5a","src/cert.rs":"6e8a78340cb8b3908977892d6d1723cebe70ff63819b28a63688e0fb4428b859","src/cherrypick.rs":"1ce882b6be825243d5551f11e1f48f53acc4aa52c4c5fb5510e69fd077a512bc","src/commit.rs":"a6bd389c2126e8646ac6b0544509e3016cd46450c9da686564cce710f0046b0c","src/config.rs":"c6d541117cceb6483b2bf43e3e9ea7575bf08a924e963ee89ee0cf1607b40516","src/cred.rs":"2b3578f37ecb442b363053028b64c70d99bf20f9a511e3de1fa58a383ff30849","src/describe.rs":"3adb68b3118bfa18c09f7ca767afa38d76e22130b1cebf20cc3b97c9a198957a","src/diff.rs":"8953973353edfc1a480dcb2fdeff256d668cdd90c2570563abb465ae6963d169","src/email.rs":"b95f32739a2adac55016e892d913fb4b03d10c0583569a613f6c13946238759d","src/error.rs":"06912d98095ec104b4bd416fcd8632422a2e78016f65a0bd07eb82eece473883","src/index.rs":"1f34cbc31ecb7d536f4138a2c4a35d9e24703c4d78575e4528c7bdf78c30e87c","src/indexer.rs":"c652d76bb2df02dc757ddeaa1395f022a61939d8ae08236f4f4369ab06c5511d","src/lib.rs":"96c40507a9339ac1150299d370045040a6bd416a063dfddf77174f2dfc8b68ad","src/mailmap.rs":"a034b1c86c8a8d4362939e2e2c1d0b1b2f5c71bac883b2b1b65b64078c70349e","src/mempack.rs":"8549f984360ac12868018e4f107a60386474c58cfb6c41993cbb0a820bd28908","src/merge.rs":"681f2f1e59cec49a8618a894e22645915e8f8a815a71d4ca7c6ab10fbdaeb919","src/message.rs":"ba445c543e2637b07c995ebc7a4f7b3c352061e2fecb83f9d95fce9c24f95d6c","src/note.rs":"55b286c3736833432d391184136f0fb0928e337990d1558166e2d998dc63f0dd","src/object.rs":"8b66f1c34570b37d204d0b3f626edbdd0baa7eb9734e3e444b72bf3e8fc46a27","src/odb.rs":"b3cd8696513b34fab005f6e37a05fc962f04ec40b35e2c89e6182aa63ea60625","src/oid.rs":"0f06937c0c4ac73024323a6cb119a8bd119f2b01054ed7e57a7b3fec6f346c6e","src/oid_array.rs":"4820657a5d4460a77a31fe0ba04c5575f6900a1767925a40464fadcacaf6a066","src/opts.rs":"3ee8746591c85a3257fd3ec74499c709174850a15e89d8df28b39c7e94f8cdfe","src/packbuilder.rs":"ea7acc367fee87e3a51e17e14fc64b44c3862b39054e17f0d38352b31325e26f","src/panic.rs":"62ef0684379f4cdebf9477e2f63c9f0ecc80fe608de2df32bca13ce0086249d6","src/patch.rs":"740fa2a29148605e3dac16f58fd603b408283cfe148b922fbe6b5a5d62f18db0","src/pathspec.rs":"54905396f243e254817bb017a8218f569a670c91346e21bb8ba2acf58ae9b943","src/proxy_options.rs":"cfa029317ae00a15074d4fd5de5d7c8da982459b915399c1d6010ddbee43ab28","src/push_update.rs":"1f10449f944b7000dcf6e242957adee0be5f45f8d458f2c83413293224cbbff7","src/rebase.rs":"179fc17e402d902300de8d37a65ceb0c29d6e8f4ba50cc8b7a7d8b09cfe9ef55","src/reference.rs":"87e4dad999f550050e25078157b2b413617698f10dcb844cdc2e4ea98b165271","src/reflog.rs":"b13ed72912f5375996b9ffb3a415371ae6c220de5a01226b13ca04fe97692f77","src/refspec.rs":"5107582963524fe9ff312a280232dba08d25be06fdf8f278c0bbfdbfa7a50402","src/remote.rs":"fc2d85a2fa80edff718bcb1397c625502ef1346af52803b1a61099444edcc527","src/remote_callbacks.rs":"cabd55a0e6d8aee101d1df7adae080e33872d816c7aed9e901304945139ae351","src/repo.rs":"df55248091999b9030225b1927a100315769d7cc488e4fcdb3b057126b37f45c","src/revert.rs":"b51dd98a9775e80dfd56b2fe13737e15baf64d3ac9c56546b2bbdfd53d1de7f9","src/revspec.rs":"29df0754775603ed1189bbe28f933f5851d50936eda380a57f175ec35496d637","src/revwalk.rs":"5b792871595ddd2bbc259de7d52174087ca34080c31fd907e23704001d7f4c61","src/signature.rs":"55c2ff56b05b8b48fa0b3a64a19557f49310749cc2100ec05f3216594b5dc4dc","src/stash.rs":"332cbec27ea7bff2f832173b7adfd3ed00e936022dc43797f31f06284bc1b93d","src/status.rs":"13712d5a07780fde16286fa897b965e2bf7881ed64468ebed1bbf9380f7c2a91","src/string_array.rs":"04501c0ca8440ec4460cc89a1c7f004dda027f8f0dc9b94a0f372a2391328d65","src/submodule.rs":"1d41cafa2523fdf4d8aae7d5dc38647c6062586d0ee1d91bc99be5d87ec6b2ee","src/tag.rs":"b7292fc74485950acfc484d4542d8a1bd135b957f0ad9c70e92762b805d73cd3","src/tagforeach.rs":"04ea7ff4072a270c5febaee8133ae93040eb81a139ed987238e0b500e9626c4c","src/test.rs":"cea22e72872aa7a875d1fc67390bd3c6d976719e0f2ad2a59d9954df78e0e7c2","src/time.rs":"7fd2bcdda9baf24c6292edd04be6112c83a57e8f9e566d6d219563ad98c12203","src/tracing.rs":"a08db58c46665280c9b364cde20d4e393d339e4920cd42d3da38cb8d1663f44e","src/transaction.rs":"6bb080f30646b5b3f22ac37f61945e58ce823944248e97fc58389cc8ca6c5895","src/transport.rs":"cec1afc572148833a5b43dc23252141d7dcb2b50246e01e86c67513d7b4a84ed","src/tree.rs":"a6996530d5feee417124ce7b27e69c20f7fc49cea7807ae4a96fe448578e4963","src/treebuilder.rs":"b04a16cd22e40f6c2e4d26d4ce343a2853e943474080e95b0e2250a5961e6c1d","src/util.rs":"f1089150444d090023d0eb31030c3e462f528a328f71165d70bc3434f8121078","src/version.rs":"bcc26c9dcc5bf872afd0741233f07981df0a4be28faeba9ad52eb437961eb30f","src/worktree.rs":"9690b76977ed44b8f8ea8b5530fae3a3b02f4bcbcb0826f4d74b2e3dff8bf76a","tests/add_extensions.rs":"af582f545b04ab475b7dcccbfc080876e643dc6d26ee3712347abeb19d4e1558","tests/get_extensions.rs":"9983f7ca5e117f74cbc55932f5478047b43087a4a83dc9324db9a62e6d3a298a","tests/global_state.rs":"c75947eca9718277da08722ca9a58d9b4154b36b1aca6453bb198238c17904ce","tests/remove_extensions.rs":"d267ffd5d2db7fe0c65b1940da5bc69d2ecc19d87f2955a7966f59a0e7a6879a"},"package":"3fda788993cc341f69012feba8bf45c0ba4f3291fcc08e214b4d5a7332d88aff"} diff --cc extra/git2/CHANGELOG.md index 0000000000,0000000000,0000000000..f76c3ba150 new file mode 100644 --- /dev/null +++ b/extra/git2/CHANGELOG.md @@@@ -1,0 -1,0 -1,0 +1,251 @@@@ +++# Changelog +++ +++## 0.19.0 - 2024-06-13 +++[0.18.3...0.19.0](https://github.com/rust-lang/git2-rs/compare/git2-0.18.3...git2-0.19.0) +++ +++### Added +++ +++- Added `opts` functions to control server timeouts (`get_server_connect_timeout_in_milliseconds`, `set_server_connect_timeout_in_milliseconds`, `get_server_timeout_in_milliseconds`, `set_server_timeout_in_milliseconds`), and add `ErrorCode::Timeout`. +++ [#1052](https://github.com/rust-lang/git2-rs/pull/1052) +++ +++### Changed +++ +++- ❗ Updated to libgit2 [1.8.1](https://github.com/libgit2/libgit2/releases/tag/v1.8.1) +++ [#1032](https://github.com/rust-lang/git2-rs/pull/1032) +++- Reduced size of the `Error` struct. +++ [#1053](https://github.com/rust-lang/git2-rs/pull/1053) +++ +++### Fixed +++ +++- Fixed some callbacks to relay the error from the callback to libgit2. +++ [#1043](https://github.com/rust-lang/git2-rs/pull/1043) +++ +++## 0.18.3 - 2024-03-18 +++[0.18.2...0.18.3](https://github.com/rust-lang/git2-rs/compare/git2-0.18.2...git2-0.18.3) +++ +++### Added +++ +++- Added `opts::` functions to get / set libgit2 mwindow options +++ [#1035](https://github.com/rust-lang/git2-rs/pull/1035) +++ +++ +++### Changed +++ +++- Updated examples to use clap instead of structopt +++ [#1007](https://github.com/rust-lang/git2-rs/pull/1007) +++ +++## 0.18.2 - 2024-02-06 +++[0.18.1...0.18.2](https://github.com/rust-lang/git2-rs/compare/git2-0.18.1...git2-0.18.2) +++ +++### Added +++ +++- Added `opts::set_ssl_cert_file` and `opts::set_ssl_cert_dir` for setting Certificate Authority file locations. +++ [#997](https://github.com/rust-lang/git2-rs/pull/997) +++- Added `TreeIter::nth` which makes jumping ahead in the iterator more efficient. +++ [#1004](https://github.com/rust-lang/git2-rs/pull/1004) +++- Added `Repository::find_commit_by_prefix` to find a commit by a shortened hash. +++ [#1011](https://github.com/rust-lang/git2-rs/pull/1011) +++- Added `Repository::find_tag_by_prefix` to find a tag by a shortened hash. +++ [#1015](https://github.com/rust-lang/git2-rs/pull/1015) +++- Added `Repository::find_object_by_prefix` to find an object by a shortened hash. +++ [#1014](https://github.com/rust-lang/git2-rs/pull/1014) +++ +++### Changed +++ +++- ❗ Updated to libgit2 [1.7.2](https://github.com/libgit2/libgit2/releases/tag/v1.7.2). +++ This fixes [CVE-2024-24575](https://github.com/libgit2/libgit2/security/advisories/GHSA-54mf-x2rh-hq9v) and [CVE-2024-24577](https://github.com/libgit2/libgit2/security/advisories/GHSA-j2v7-4f6v-gpg8). +++ [#1017](https://github.com/rust-lang/git2-rs/pull/1017) +++ +++## 0.18.1 - 2023-09-20 +++[0.18.0...0.18.1](https://github.com/rust-lang/git2-rs/compare/git2-0.18.0...git2-0.18.1) +++ +++### Added +++ +++- Added `FetchOptions::depth` to set the depth of a fetch or clone, adding support for shallow clones. +++ [#979](https://github.com/rust-lang/git2-rs/pull/979) +++ +++### Fixed +++ +++- Fixed an internal data type (`TreeWalkCbData`) to not assume it is a transparent type while casting. +++ [#989](https://github.com/rust-lang/git2-rs/pull/989) +++- Fixed so that `DiffPatchidOptions` and `StashSaveOptions` are publicly exported allowing the corresponding APIs to actually be used. +++ [#988](https://github.com/rust-lang/git2-rs/pull/988) +++ +++## 0.18.0 - 2023-08-28 +++[0.17.2...0.18.0](https://github.com/rust-lang/git2-rs/compare/0.17.2...git2-0.18.0) +++ +++### Added +++ +++- Added `Blame::blame_buffer` for getting blame data for a file that has been modified in memory. +++ [#981](https://github.com/rust-lang/git2-rs/pull/981) +++ +++### Changed +++ +++- Updated to libgit2 [1.7.0](https://github.com/libgit2/libgit2/releases/tag/v1.7.0). +++ [#968](https://github.com/rust-lang/git2-rs/pull/968) +++- Updated to libgit2 [1.7.1](https://github.com/libgit2/libgit2/releases/tag/v1.7.1). +++ [#982](https://github.com/rust-lang/git2-rs/pull/982) +++- Switched from bitflags 1.x to 2.1. This brings some small changes to types generated by bitflags. +++ [#973](https://github.com/rust-lang/git2-rs/pull/973) +++- Changed `Revwalk::with_hide_callback` to take a mutable reference to its callback to enforce type safety. +++ [#970](https://github.com/rust-lang/git2-rs/pull/970) +++- Implemented `FusedIterator` for many iterators that can support it. +++ [#955](https://github.com/rust-lang/git2-rs/pull/955) +++ +++### Fixed +++ +++- Fixed builds with cargo's `-Zminimal-versions`. +++ [#960](https://github.com/rust-lang/git2-rs/pull/960) +++ +++## 0.17.2 - 2023-05-27 +++[0.17.1...0.17.2](https://github.com/rust-lang/git2-rs/compare/0.17.1...0.17.2) +++ +++### Added +++- Added support for stashing with options (which can support partial stashing). +++ [#930](https://github.com/rust-lang/git2-rs/pull/930) +++ +++## 0.17.1 - 2023-04-13 +++[0.17.0...0.17.1](https://github.com/rust-lang/git2-rs/compare/0.17.0...0.17.1) +++ +++### Changed +++ +++- Updated to libgit2 [1.6.4](https://github.com/libgit2/libgit2/releases/tag/v1.6.4). +++ [#948](https://github.com/rust-lang/git2-rs/pull/948) +++ +++## 0.17.0 - 2023-04-02 +++[0.16.1...0.17.0](https://github.com/rust-lang/git2-rs/compare/0.16.1...0.17.0) +++ +++### Added +++ +++- Added `IntoIterator` implementation for `Statuses`. +++ [#880](https://github.com/rust-lang/git2-rs/pull/880) +++- Added `Reference::symbolic_set_target` +++ [#893](https://github.com/rust-lang/git2-rs/pull/893) +++- Added `Copy`, `Clone`, `Debug`, `PartialEq`, and `Eq` implementations for `AutotagOption` and `FetchPrune`. +++ [#889](https://github.com/rust-lang/git2-rs/pull/889) +++- Added `Eq` and `PartialEq` implementations for `Signature`. +++ [#890](https://github.com/rust-lang/git2-rs/pull/890) +++- Added `Repository::discover_path`. +++ [#883](https://github.com/rust-lang/git2-rs/pull/883) +++- Added `Submodule::repo_init`. +++ [#914](https://github.com/rust-lang/git2-rs/pull/914) +++- Added `Tag::is_valid_name`. +++ [#882](https://github.com/rust-lang/git2-rs/pull/882) +++- Added `Repository::set_head_bytes`. +++ [#931](https://github.com/rust-lang/git2-rs/pull/931) +++- Added the `Indexer` type which is a low-level API for storing and indexing pack files. +++ [#911](https://github.com/rust-lang/git2-rs/pull/911) +++- Added `Index::find_prefix`. +++ [#903](https://github.com/rust-lang/git2-rs/pull/903) +++- Added support for the deprecated group-writeable blob mode. This adds a new variant to `FileMode`. +++ [#887](https://github.com/rust-lang/git2-rs/pull/887) +++- Added `PushCallbacks::push_negotiation` callback and the corresponding `PushUpdate` type for getting receiving information about the updates to perform. +++ [#926](https://github.com/rust-lang/git2-rs/pull/926) +++ +++### Changed +++ +++- Updated to libgit2 [1.6.3](https://github.com/libgit2/libgit2/blob/main/docs/changelog.md#v163). +++ This brings in many changes, including better SSH host key support on Windows and better SSH host key algorithm negotiation. +++ 1.6.3 is now the minimum supported version. +++ [#935](https://github.com/rust-lang/git2-rs/pull/935) +++- Updated libssh2-sys from 0.2 to 0.3. +++ This brings in numerous changes, including SHA2 algorithm support with RSA. +++ [#919](https://github.com/rust-lang/git2-rs/pull/919) +++- Changed `RemoteCallbacks::credentials` callback error handler to correctly set the libgit2 error class. +++ [#918](https://github.com/rust-lang/git2-rs/pull/918) +++- `DiffOptions::flag` now takes a `git_diff_option_t` type. +++ [#935](https://github.com/rust-lang/git2-rs/pull/935) +++ +++ +++## 0.16.1 - 2023-01-20 +++[0.16.0...0.16.1](https://github.com/rust-lang/git2-rs/compare/0.16.0...0.16.1) +++ +++### Changed +++- Updated to [libgit2-sys 0.14.2+1.5.1](libgit2-sys/CHANGELOG.md#0142151---2023-01-20) +++ +++## 0.16.0 - 2023-01-10 +++[0.15.0...0.16.0](https://github.com/rust-lang/git2-rs/compare/0.15.0...0.16.0) +++ +++### Changed +++- Added ability to get the SSH host key and its type. +++ This includes an API breaking change to the `certificate_check` callback. +++ [#909](https://github.com/rust-lang/git2-rs/pull/909) +++- Updated to [libgit2-sys 0.14.1+1.5.0](libgit2-sys/CHANGELOG.md#0141150---2023-01-10) +++ +++## 0.15.0 - 2022-07-28 +++[0.14.4...0.15.0](https://github.com/rust-lang/git2-rs/compare/0.14.4...0.15.0) +++ +++### Added +++- Added `Repository::tag_annotation_create` binding `git_tag_annotation_create`. +++ [#845](https://github.com/rust-lang/git2-rs/pull/845) +++- Added the `Email` type which represents a patch in mbox format for sending via email. +++ Added the `EmailCreateOptions` struct to control formatting of the email. +++ Deprecates `Diff::format_email`, use `Email::from_diff` instead. +++ [#847](https://github.com/rust-lang/git2-rs/pull/847) +++- Added `ErrorCode::Owner` to map to the new `GIT_EOWNER` errors. +++ [#839](https://github.com/rust-lang/git2-rs/pull/839) +++- Added `opts::set_verify_owner_validation` to set whether or not ownership validation is performed. +++ [#839](https://github.com/rust-lang/git2-rs/pull/839) +++ +++### Changed +++- Updated to [libgit2-sys 0.14.0+1.5.0](libgit2-sys/CHANGELOG.md#0140150---2022-07-28) +++- Removed the `Iterator` implementation for `ConfigEntries` due to the unsound usage of the API which allowed values to be used after free. +++ Added `ConfigEntries::next` and `ConfigEntries::for_each` for iterating over all entries in a safe manor. +++ [#854](https://github.com/rust-lang/git2-rs/pull/854) +++ +++## 0.14.4 - 2022-05-19 +++[0.14.3...0.14.4](https://github.com/rust-lang/git2-rs/compare/0.14.3...0.14.4) +++ +++### Added +++- Added `Commit::body` and `Commit::body_bytes` for retrieving the commit message body. +++ [#835](https://github.com/rust-lang/git2-rs/pull/835) +++- Added `Tree::get_name_bytes` to handle non-UTF-8 entry names. +++ [#841](https://github.com/rust-lang/git2-rs/pull/841) +++ +++### Changed +++- Updated to [libgit2-sys 0.13.4+1.4.2](libgit2-sys/CHANGELOG.md#0134142---2022-05-10) +++ +++## 0.14.3 - 2022-04-27 +++[0.14.2...0.14.3](https://github.com/rust-lang/git2-rs/compare/0.14.2...0.14.3) +++ +++### Changed +++- Updated to [libgit2-sys 0.13.3+1.4.2](libgit2-sys/CHANGELOG.md#0133142---2022-04-27) +++ +++### Fixed +++- Fixed the lifetime of `Remote::create_detached`. +++ [#825](https://github.com/rust-lang/git2-rs/pull/825) +++ +++## 0.14.2 - 2022-03-10 +++[0.14.1...0.14.2](https://github.com/rust-lang/git2-rs/compare/0.14.1...0.14.2) +++ +++### Added +++- Added `Odb::exists_ext` to checks if an object database has an object, with extended flags. +++ [#818](https://github.com/rust-lang/git2-rs/pull/818) +++ +++### Changed +++- Updated to [libgit2-sys 0.13.2+1.4.2](libgit2-sys/CHANGELOG.md#0132142---2022-03-10) +++ +++## 0.14.1 - 2022-02-28 +++[0.14.0...0.14.1](https://github.com/rust-lang/git2-rs/compare/0.14.0...0.14.1) +++ +++### Changed +++- Updated to [libgit2-sys 0.13.1+1.4.2](libgit2-sys/CHANGELOG.md#0131142---2022-02-28) +++ +++## 0.14.0 - 2022-02-24 +++[0.13.25...0.14.0](https://github.com/rust-lang/git2-rs/compare/0.13.25...0.14.0) +++ +++### Added +++- Added `opts::get_extensions` and `opts::set_extensions` to support git extensions. +++ [#791](https://github.com/rust-lang/git2-rs/pull/791) +++- Added `PackBuilder::name` and `PackBuilder::name_bytes`. +++ [#806](https://github.com/rust-lang/git2-rs/pull/806) +++ - Deprecated `PackBuilder::hash`, use `PackBuilder::name` instead. +++- Added `FetchOptions::follow_redirects` and `PushOptions::follow_redirects`. +++ [#806](https://github.com/rust-lang/git2-rs/pull/806) +++- Added `StatusOptions::rename_threshold`. +++ [#806](https://github.com/rust-lang/git2-rs/pull/806) +++ +++### Changed +++- Updated to [libgit2-sys 0.13.0+1.4.1](libgit2-sys/CHANGELOG.md#0130141---2022-02-24) +++ [#806](https://github.com/rust-lang/git2-rs/pull/806) +++ [#811](https://github.com/rust-lang/git2-rs/pull/811) diff --cc extra/git2/CONTRIBUTING.md index 0000000000,0000000000,0000000000..c842f1eec5 new file mode 100644 --- /dev/null +++ b/extra/git2/CONTRIBUTING.md @@@@ -1,0 -1,0 -1,0 +1,63 @@@@ +++# Contributing +++ +++## Updating libgit2 +++ +++The following steps can be used to update libgit2: +++ +++1. Update the submodule. +++ There are several ways to go about this. +++ One way is to go to the `libgit2-sys/libgit2` directory and run `git fetch origin` to download the latest updates, and then check out a specific tag (such as `git checkout v1.4.1`). +++2. Update all the references to the version: +++ * Update [`libgit2-sys/build.rs`](https://github.com/rust-lang/git2-rs/blob/master/libgit2-sys/build.rs). +++ There is a version probe (search for `cfg.range_version`) which should be updated. +++ * Update the version in +++ [`libgit2-sys/Cargo.toml`](https://github.com/rust-lang/git2-rs/blob/master/libgit2-sys/Cargo.toml). +++ Update the metadata portion (the part after the `+`) to match libgit2. +++ Also bump the Cargo version (the part before the `+`), keeping in mind +++ if this will be a SemVer breaking change or not. +++ * Update the dependency version in [`Cargo.toml`](https://github.com/rust-lang/git2-rs/blob/master/Cargo.toml) to match the version in the last step (do not include the `+` metadata). +++ Also update the version of the `git2` crate itself so it will pick up the change to `libgit2-sys` (also keeping in mind if it is a SemVer breaking release). +++ * Update the version in [`README.md`](https://github.com/rust-lang/git2-rs/blob/master/README.md) if needed. +++ There are two places, the `Cargo.toml` example and the description of the libgit2 version it binds with. +++ * If there was a SemVer-breaking version bump for either library, also update the `html_root_url` attribute in the `lib.rs` of each library. +++3. Run tests. +++ `cargo test -p git2 -p git2-curl` is a good starting point. +++4. Run `systest`. +++ This will validate for any C-level API problems. +++ +++ `cargo run -p systest` +++ +++ The changelog at +++ can be helpful for seeing what has changed. +++ The project has recently started labeling API and ABI breaking changes with labels: +++ +++ Alternatively, running `git diff [PREV_VERSION]..[NEW_VERSION] --ignore-all-space -- include/` can provide an overview of changes made to the API. +++4. Once you have everything functional, publish a PR with the updates. +++ +++## Release process +++ +++Checklist for preparing for a release: +++ +++- Make sure the versions have been bumped and are pointing at what is expected. +++ - Version of `libgit2-sys` +++ - Version of `git2` +++ - Version of `git2-curl` +++ - `git2`'s dependency on `libgit2-sys` +++ - `git2-curl`'s dependency on `git2` +++ - The libgit2 version probe in `libgit2-sys/build.rs` +++ - Update the version in `README.md` +++ - Check the `html_root_url` values in the source code. +++- Update the change logs: +++ - [`CHANGELOG.md`](https://github.com/rust-lang/git2-rs/blob/master/CHANGELOG.md) +++ - [`libgit2-sys/CHANGELOG.md`](https://github.com/rust-lang/git2-rs/blob/master/libgit2-sys/CHANGELOG.md) +++ - [`git2-curl/CHANGELOG.md`](https://github.com/rust-lang/git2-rs/blob/master/git2-curl/CHANGELOG.md) +++ +++There is a GitHub workflow to handle publishing to crates.io and tagging the release. There are two different ways to run it: +++ +++- In the GitHub web UI: +++ 1. Go to (you can navigate here via the "Actions" tab at the top). +++ 2. Click the "Run workflow" drop-down on the right. +++ 3. Choose which crates to publish. It's OK to leave everything checked, it will skip if it is already published. Uncheck a crate if the version has been bumped in git, but you don't want to publish that particular one, yet. +++ 4. Click "Run workflow" +++- In the CLI: +++ 1. Run `gh workflow run publish.yml -R rust-lang/git2-rs` diff --cc extra/git2/Cargo.lock index 0000000000,0000000000,0000000000..e9fde354b6 new file mode 100644 --- /dev/null +++ b/extra/git2/Cargo.lock @@@@ -1,0 -1,0 -1,0 +1,842 @@@@ +++# This file is automatically @generated by Cargo. +++# It is not intended for manual editing. +++version = 4 +++ +++[[package]] +++name = "anstream" +++version = "0.6.18" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +++dependencies = [ +++ "anstyle", +++ "anstyle-parse", +++ "anstyle-query", +++ "anstyle-wincon", +++ "colorchoice", +++ "is_terminal_polyfill", +++ "utf8parse", +++] +++ +++[[package]] +++name = "anstyle" +++version = "1.0.10" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +++ +++[[package]] +++name = "anstyle-parse" +++version = "0.2.6" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +++dependencies = [ +++ "utf8parse", +++] +++ +++[[package]] +++name = "anstyle-query" +++version = "1.1.2" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +++dependencies = [ +++ "windows-sys", +++] +++ +++[[package]] +++name = "anstyle-wincon" +++version = "3.0.6" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +++dependencies = [ +++ "anstyle", +++ "windows-sys", +++] +++ +++[[package]] +++name = "bitflags" +++version = "2.6.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +++ +++[[package]] +++name = "cc" +++version = "1.2.7" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" +++dependencies = [ +++ "jobserver", +++ "libc", +++ "shlex", +++] +++ +++[[package]] +++name = "cfg-if" +++version = "1.0.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +++ +++[[package]] +++name = "clap" +++version = "4.5.23" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +++dependencies = [ +++ "clap_builder", +++ "clap_derive", +++] +++ +++[[package]] +++name = "clap_builder" +++version = "4.5.23" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +++dependencies = [ +++ "anstream", +++ "anstyle", +++ "clap_lex", +++ "strsim", +++] +++ +++[[package]] +++name = "clap_derive" +++version = "4.5.18" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +++dependencies = [ +++ "heck", +++ "proc-macro2", +++ "quote", +++ "syn", +++] +++ +++[[package]] +++name = "clap_lex" +++version = "0.7.4" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +++ +++[[package]] +++name = "cmake" +++version = "0.1.52" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" +++dependencies = [ +++ "cc", +++] +++ +++[[package]] +++name = "colorchoice" +++version = "1.0.3" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +++ +++[[package]] +++name = "deranged" +++version = "0.3.11" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +++dependencies = [ +++ "powerfmt", +++] +++ +++[[package]] +++name = "displaydoc" +++version = "0.2.5" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +++dependencies = [ +++ "proc-macro2", +++ "quote", +++ "syn", +++] +++ +++[[package]] +++name = "errno" +++version = "0.3.10" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +++dependencies = [ +++ "libc", +++ "windows-sys", +++] +++ +++[[package]] +++name = "fastrand" +++version = "2.3.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +++ +++[[package]] +++name = "form_urlencoded" +++version = "1.2.1" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +++dependencies = [ +++ "percent-encoding", +++] +++ +++[[package]] +++name = "getrandom" +++version = "0.2.15" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +++dependencies = [ +++ "cfg-if", +++ "libc", +++ "wasi", +++] +++ +++[[package]] +++name = "git2" +++version = "0.20.0" +++dependencies = [ +++ "bitflags", +++ "clap", +++ "libc", +++ "libgit2-sys", +++ "log", +++ "openssl-probe", +++ "openssl-sys", +++ "tempfile", +++ "time", +++ "url", +++] +++ +++[[package]] +++name = "heck" +++version = "0.5.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +++ +++[[package]] +++name = "icu_collections" +++version = "1.5.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +++dependencies = [ +++ "displaydoc", +++ "yoke", +++ "zerofrom", +++ "zerovec", +++] +++ +++[[package]] +++name = "icu_locid" +++version = "1.5.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +++dependencies = [ +++ "displaydoc", +++ "litemap", +++ "tinystr", +++ "writeable", +++ "zerovec", +++] +++ +++[[package]] +++name = "icu_locid_transform" +++version = "1.5.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +++dependencies = [ +++ "displaydoc", +++ "icu_locid", +++ "icu_locid_transform_data", +++ "icu_provider", +++ "tinystr", +++ "zerovec", +++] +++ +++[[package]] +++name = "icu_locid_transform_data" +++version = "1.5.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" +++ +++[[package]] +++name = "icu_normalizer" +++version = "1.5.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +++dependencies = [ +++ "displaydoc", +++ "icu_collections", +++ "icu_normalizer_data", +++ "icu_properties", +++ "icu_provider", +++ "smallvec", +++ "utf16_iter", +++ "utf8_iter", +++ "write16", +++ "zerovec", +++] +++ +++[[package]] +++name = "icu_normalizer_data" +++version = "1.5.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +++ +++[[package]] +++name = "icu_properties" +++version = "1.5.1" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +++dependencies = [ +++ "displaydoc", +++ "icu_collections", +++ "icu_locid_transform", +++ "icu_properties_data", +++ "icu_provider", +++ "tinystr", +++ "zerovec", +++] +++ +++[[package]] +++name = "icu_properties_data" +++version = "1.5.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +++ +++[[package]] +++name = "icu_provider" +++version = "1.5.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +++dependencies = [ +++ "displaydoc", +++ "icu_locid", +++ "icu_provider_macros", +++ "stable_deref_trait", +++ "tinystr", +++ "writeable", +++ "yoke", +++ "zerofrom", +++ "zerovec", +++] +++ +++[[package]] +++name = "icu_provider_macros" +++version = "1.5.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +++dependencies = [ +++ "proc-macro2", +++ "quote", +++ "syn", +++] +++ +++[[package]] +++name = "idna" +++version = "1.0.3" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +++dependencies = [ +++ "idna_adapter", +++ "smallvec", +++ "utf8_iter", +++] +++ +++[[package]] +++name = "idna_adapter" +++version = "1.2.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +++dependencies = [ +++ "icu_normalizer", +++ "icu_properties", +++] +++ +++[[package]] +++name = "is_terminal_polyfill" +++version = "1.70.1" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +++ +++[[package]] +++name = "itoa" +++version = "1.0.14" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +++ +++[[package]] +++name = "jobserver" +++version = "0.1.32" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +++dependencies = [ +++ "libc", +++] +++ +++[[package]] +++name = "libc" +++version = "0.2.169" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +++ +++[[package]] +++name = "libgit2-sys" +++version = "0.18.0+1.9.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "e1a117465e7e1597e8febea8bb0c410f1c7fb93b1e1cddf34363f8390367ffec" +++dependencies = [ +++ "cc", +++ "libc", +++ "libssh2-sys", +++ "libz-sys", +++ "openssl-sys", +++ "pkg-config", +++] +++ +++[[package]] +++name = "libssh2-sys" +++version = "0.3.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee" +++dependencies = [ +++ "cc", +++ "libc", +++ "libz-sys", +++ "openssl-sys", +++ "pkg-config", +++ "vcpkg", +++] +++ +++[[package]] +++name = "libz-sys" +++version = "1.1.20" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +++dependencies = [ +++ "cc", +++ "cmake", +++ "libc", +++ "pkg-config", +++ "vcpkg", +++] +++ +++[[package]] +++name = "linux-raw-sys" +++version = "0.4.14" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +++ +++[[package]] +++name = "litemap" +++version = "0.7.4" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" +++ +++[[package]] +++name = "log" +++version = "0.4.22" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +++ +++[[package]] +++name = "num-conv" +++version = "0.1.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +++ +++[[package]] +++name = "once_cell" +++version = "1.20.2" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +++ +++[[package]] +++name = "openssl-probe" +++version = "0.1.5" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +++ +++[[package]] +++name = "openssl-src" +++version = "300.4.1+3.4.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c" +++dependencies = [ +++ "cc", +++] +++ +++[[package]] +++name = "openssl-sys" +++version = "0.9.104" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +++dependencies = [ +++ "cc", +++ "libc", +++ "openssl-src", +++ "pkg-config", +++ "vcpkg", +++] +++ +++[[package]] +++name = "percent-encoding" +++version = "2.3.1" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +++ +++[[package]] +++name = "pkg-config" +++version = "0.3.31" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +++ +++[[package]] +++name = "powerfmt" +++version = "0.2.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +++ +++[[package]] +++name = "proc-macro2" +++version = "1.0.92" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +++dependencies = [ +++ "unicode-ident", +++] +++ +++[[package]] +++name = "quote" +++version = "1.0.38" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +++dependencies = [ +++ "proc-macro2", +++] +++ +++[[package]] +++name = "rustix" +++version = "0.38.42" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +++dependencies = [ +++ "bitflags", +++ "errno", +++ "libc", +++ "linux-raw-sys", +++ "windows-sys", +++] +++ +++[[package]] +++name = "serde" +++version = "1.0.217" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +++dependencies = [ +++ "serde_derive", +++] +++ +++[[package]] +++name = "serde_derive" +++version = "1.0.217" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +++dependencies = [ +++ "proc-macro2", +++ "quote", +++ "syn", +++] +++ +++[[package]] +++name = "shlex" +++version = "1.3.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +++ +++[[package]] +++name = "smallvec" +++version = "1.13.2" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +++ +++[[package]] +++name = "stable_deref_trait" +++version = "1.2.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +++ +++[[package]] +++name = "strsim" +++version = "0.11.1" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +++ +++[[package]] +++name = "syn" +++version = "2.0.94" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" +++dependencies = [ +++ "proc-macro2", +++ "quote", +++ "unicode-ident", +++] +++ +++[[package]] +++name = "synstructure" +++version = "0.13.1" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +++dependencies = [ +++ "proc-macro2", +++ "quote", +++ "syn", +++] +++ +++[[package]] +++name = "tempfile" +++version = "3.15.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" +++dependencies = [ +++ "cfg-if", +++ "fastrand", +++ "getrandom", +++ "once_cell", +++ "rustix", +++ "windows-sys", +++] +++ +++[[package]] +++name = "time" +++version = "0.3.37" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +++dependencies = [ +++ "deranged", +++ "itoa", +++ "num-conv", +++ "powerfmt", +++ "serde", +++ "time-core", +++ "time-macros", +++] +++ +++[[package]] +++name = "time-core" +++version = "0.1.2" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +++ +++[[package]] +++name = "time-macros" +++version = "0.2.19" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +++dependencies = [ +++ "num-conv", +++ "time-core", +++] +++ +++[[package]] +++name = "tinystr" +++version = "0.7.6" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +++dependencies = [ +++ "displaydoc", +++ "zerovec", +++] +++ +++[[package]] +++name = "unicode-ident" +++version = "1.0.14" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +++ +++[[package]] +++name = "url" +++version = "2.5.4" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +++dependencies = [ +++ "form_urlencoded", +++ "idna", +++ "percent-encoding", +++] +++ +++[[package]] +++name = "utf16_iter" +++version = "1.0.5" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" +++ +++[[package]] +++name = "utf8_iter" +++version = "1.0.4" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +++ +++[[package]] +++name = "utf8parse" +++version = "0.2.2" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +++ +++[[package]] +++name = "vcpkg" +++version = "0.2.15" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +++ +++[[package]] +++name = "wasi" +++version = "0.11.0+wasi-snapshot-preview1" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +++ +++[[package]] +++name = "windows-sys" +++version = "0.59.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +++dependencies = [ +++ "windows-targets", +++] +++ +++[[package]] +++name = "windows-targets" +++version = "0.52.6" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +++dependencies = [ +++ "windows_aarch64_gnullvm", +++ "windows_aarch64_msvc", +++ "windows_i686_gnu", +++ "windows_i686_gnullvm", +++ "windows_i686_msvc", +++ "windows_x86_64_gnu", +++ "windows_x86_64_gnullvm", +++ "windows_x86_64_msvc", +++] +++ +++[[package]] +++name = "windows_aarch64_gnullvm" +++version = "0.52.6" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +++ +++[[package]] +++name = "windows_aarch64_msvc" +++version = "0.52.6" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +++ +++[[package]] +++name = "windows_i686_gnu" +++version = "0.52.6" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +++ +++[[package]] +++name = "windows_i686_gnullvm" +++version = "0.52.6" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +++ +++[[package]] +++name = "windows_i686_msvc" +++version = "0.52.6" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +++ +++[[package]] +++name = "windows_x86_64_gnu" +++version = "0.52.6" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +++ +++[[package]] +++name = "windows_x86_64_gnullvm" +++version = "0.52.6" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +++ +++[[package]] +++name = "windows_x86_64_msvc" +++version = "0.52.6" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +++ +++[[package]] +++name = "write16" +++version = "1.0.0" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" +++ +++[[package]] +++name = "writeable" +++version = "0.5.5" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +++ +++[[package]] +++name = "yoke" +++version = "0.7.5" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +++dependencies = [ +++ "serde", +++ "stable_deref_trait", +++ "yoke-derive", +++ "zerofrom", +++] +++ +++[[package]] +++name = "yoke-derive" +++version = "0.7.5" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +++dependencies = [ +++ "proc-macro2", +++ "quote", +++ "syn", +++ "synstructure", +++] +++ +++[[package]] +++name = "zerofrom" +++version = "0.1.5" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +++dependencies = [ +++ "zerofrom-derive", +++] +++ +++[[package]] +++name = "zerofrom-derive" +++version = "0.1.5" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +++dependencies = [ +++ "proc-macro2", +++ "quote", +++ "syn", +++ "synstructure", +++] +++ +++[[package]] +++name = "zerovec" +++version = "0.10.4" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +++dependencies = [ +++ "yoke", +++ "zerofrom", +++ "zerovec-derive", +++] +++ +++[[package]] +++name = "zerovec-derive" +++version = "0.10.3" +++source = "registry+https://github.com/rust-lang/crates.io-index" +++checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +++dependencies = [ +++ "proc-macro2", +++ "quote", +++ "syn", +++] diff --cc extra/git2/Cargo.toml index 0000000000,0000000000,0000000000..edabcd9c75 new file mode 100644 --- /dev/null +++ b/extra/git2/Cargo.toml @@@@ -1,0 -1,0 -1,0 +1,165 @@@@ +++# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +++# +++# When uploading crates to the registry Cargo will automatically +++# "normalize" Cargo.toml files for maximal compatibility +++# with all versions of Cargo and also rewrite `path` dependencies +++# to registry (e.g., crates.io) dependencies. +++# +++# If you are reading this file be aware that the original Cargo.toml +++# will likely look very different (and much more reasonable). +++# See Cargo.toml.orig for the original contents. +++ +++[package] +++edition = "2018" +++name = "git2" +++version = "0.20.0" +++authors = [ +++ "Josh Triplett ", +++ "Alex Crichton ", +++] +++build = false +++autolib = false +++autobins = false +++autoexamples = false +++autotests = false +++autobenches = false +++description = """ +++Bindings to libgit2 for interoperating with git repositories. This library is +++both threadsafe and memory safe and allows both reading and writing git +++repositories. +++""" +++documentation = "https://docs.rs/git2" +++readme = "README.md" +++keywords = ["git"] +++categories = ["api-bindings"] +++license = "MIT OR Apache-2.0" +++repository = "https://github.com/rust-lang/git2-rs" +++ +++[lib] +++name = "git2" +++path = "src/lib.rs" +++ +++[[example]] +++name = "add" +++path = "examples/add.rs" +++ +++[[example]] +++name = "blame" +++path = "examples/blame.rs" +++ +++[[example]] +++name = "cat-file" +++path = "examples/cat-file.rs" +++ +++[[example]] +++name = "clone" +++path = "examples/clone.rs" +++ +++[[example]] +++name = "diff" +++path = "examples/diff.rs" +++ +++[[example]] +++name = "fetch" +++path = "examples/fetch.rs" +++ +++[[example]] +++name = "init" +++path = "examples/init.rs" +++ +++[[example]] +++name = "log" +++path = "examples/log.rs" +++ +++[[example]] +++name = "ls-remote" +++path = "examples/ls-remote.rs" +++ +++[[example]] +++name = "pull" +++path = "examples/pull.rs" +++ +++[[example]] +++name = "rev-list" +++path = "examples/rev-list.rs" +++ +++[[example]] +++name = "rev-parse" +++path = "examples/rev-parse.rs" +++ +++[[example]] +++name = "status" +++path = "examples/status.rs" +++ +++[[example]] +++name = "tag" +++path = "examples/tag.rs" +++ +++[[test]] +++name = "add_extensions" +++path = "tests/add_extensions.rs" +++ +++[[test]] +++name = "get_extensions" +++path = "tests/get_extensions.rs" +++ +++[[test]] +++name = "global_state" +++path = "tests/global_state.rs" +++ +++[[test]] +++name = "remove_extensions" +++path = "tests/remove_extensions.rs" +++ +++[dependencies.bitflags] +++version = "2.1.0" +++ +++[dependencies.libc] +++version = "0.2" +++ +++[dependencies.libgit2-sys] +++version = "0.18.0" +++ +++[dependencies.log] +++version = "0.4.8" +++ +++[dependencies.url] +++version = "2.0" +++ +++[dev-dependencies.clap] +++version = "4.4.13" +++features = ["derive"] +++ +++[dev-dependencies.tempfile] +++version = "3.1.0" +++ +++[dev-dependencies.time] +++version = "0.3.37" +++features = ["formatting"] +++ +++[features] +++default = [ +++ "ssh", +++ "https", +++] +++https = [ +++ "libgit2-sys/https", +++ "openssl-sys", +++ "openssl-probe", +++] +++ssh = ["libgit2-sys/ssh"] +++unstable = [] +++vendored-libgit2 = ["libgit2-sys/vendored"] +++vendored-openssl = [ +++ "openssl-sys/vendored", +++ "libgit2-sys/vendored-openssl", +++] +++zlib-ng-compat = ["libgit2-sys/zlib-ng-compat"] +++ +++[target.'cfg(all(unix, not(target_os = "macos")))'.dependencies.openssl-probe] +++version = "0.1" +++optional = true +++ +++[target.'cfg(all(unix, not(target_os = "macos")))'.dependencies.openssl-sys] +++version = "0.9.45" +++optional = true diff --cc extra/git2/FUNDING.json index 0000000000,0000000000,0000000000..480d41540c new file mode 100644 --- /dev/null +++ b/extra/git2/FUNDING.json @@@@ -1,0 -1,0 -1,0 +1,7 @@@@ +++{ +++ "drips": { +++ "ethereum": { +++ "ownedBy": "0x298f6e7CC02D6aa94E2b135f46F1761da7A44E58" +++ } +++ } +++} diff --cc extra/git2/LICENSE-APACHE index 0000000000,0000000000,0000000000..16fe87b06e new file mode 100644 --- /dev/null +++ b/extra/git2/LICENSE-APACHE @@@@ -1,0 -1,0 -1,0 +1,201 @@@@ +++ Apache License +++ Version 2.0, January 2004 +++ http://www.apache.org/licenses/ +++ +++TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +++ +++1. Definitions. +++ +++ "License" shall mean the terms and conditions for use, reproduction, +++ and distribution as defined by Sections 1 through 9 of this document. +++ +++ "Licensor" shall mean the copyright owner or entity authorized by +++ the copyright owner that is granting the License. +++ +++ "Legal Entity" shall mean the union of the acting entity and all +++ other entities that control, are controlled by, or are under common +++ control with that entity. For the purposes of this definition, +++ "control" means (i) the power, direct or indirect, to cause the +++ direction or management of such entity, whether by contract or +++ otherwise, or (ii) ownership of fifty percent (50%) or more of the +++ outstanding shares, or (iii) beneficial ownership of such entity. +++ +++ "You" (or "Your") shall mean an individual or Legal Entity +++ exercising permissions granted by this License. +++ +++ "Source" form shall mean the preferred form for making modifications, +++ including but not limited to software source code, documentation +++ source, and configuration files. +++ +++ "Object" form shall mean any form resulting from mechanical +++ transformation or translation of a Source form, including but +++ not limited to compiled object code, generated documentation, +++ and conversions to other media types. +++ +++ "Work" shall mean the work of authorship, whether in Source or +++ Object form, made available under the License, as indicated by a +++ copyright notice that is included in or attached to the work +++ (an example is provided in the Appendix below). +++ +++ "Derivative Works" shall mean any work, whether in Source or Object +++ form, that is based on (or derived from) the Work and for which the +++ editorial revisions, annotations, elaborations, or other modifications +++ represent, as a whole, an original work of authorship. For the purposes +++ of this License, Derivative Works shall not include works that remain +++ separable from, or merely link (or bind by name) to the interfaces of, +++ the Work and Derivative Works thereof. +++ +++ "Contribution" shall mean any work of authorship, including +++ the original version of the Work and any modifications or additions +++ to that Work or Derivative Works thereof, that is intentionally +++ submitted to Licensor for inclusion in the Work by the copyright owner +++ or by an individual or Legal Entity authorized to submit on behalf of +++ the copyright owner. For the purposes of this definition, "submitted" +++ means any form of electronic, verbal, or written communication sent +++ to the Licensor or its representatives, including but not limited to +++ communication on electronic mailing lists, source code control systems, +++ and issue tracking systems that are managed by, or on behalf of, the +++ Licensor for the purpose of discussing and improving the Work, but +++ excluding communication that is conspicuously marked or otherwise +++ designated in writing by the copyright owner as "Not a Contribution." +++ +++ "Contributor" shall mean Licensor and any individual or Legal Entity +++ on behalf of whom a Contribution has been received by Licensor and +++ subsequently incorporated within the Work. +++ +++2. Grant of Copyright License. Subject to the terms and conditions of +++ this License, each Contributor hereby grants to You a perpetual, +++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable +++ copyright license to reproduce, prepare Derivative Works of, +++ publicly display, publicly perform, sublicense, and distribute the +++ Work and such Derivative Works in Source or Object form. +++ +++3. Grant of Patent License. Subject to the terms and conditions of +++ this License, each Contributor hereby grants to You a perpetual, +++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable +++ (except as stated in this section) patent license to make, have made, +++ use, offer to sell, sell, import, and otherwise transfer the Work, +++ where such license applies only to those patent claims licensable +++ by such Contributor that are necessarily infringed by their +++ Contribution(s) alone or by combination of their Contribution(s) +++ with the Work to which such Contribution(s) was submitted. If You +++ institute patent litigation against any entity (including a +++ cross-claim or counterclaim in a lawsuit) alleging that the Work +++ or a Contribution incorporated within the Work constitutes direct +++ or contributory patent infringement, then any patent licenses +++ granted to You under this License for that Work shall terminate +++ as of the date such litigation is filed. +++ +++4. Redistribution. You may reproduce and distribute copies of the +++ Work or Derivative Works thereof in any medium, with or without +++ modifications, and in Source or Object form, provided that You +++ meet the following conditions: +++ +++ (a) You must give any other recipients of the Work or +++ Derivative Works a copy of this License; and +++ +++ (b) You must cause any modified files to carry prominent notices +++ stating that You changed the files; and +++ +++ (c) You must retain, in the Source form of any Derivative Works +++ that You distribute, all copyright, patent, trademark, and +++ attribution notices from the Source form of the Work, +++ excluding those notices that do not pertain to any part of +++ the Derivative Works; and +++ +++ (d) If the Work includes a "NOTICE" text file as part of its +++ distribution, then any Derivative Works that You distribute must +++ include a readable copy of the attribution notices contained +++ within such NOTICE file, excluding those notices that do not +++ pertain to any part of the Derivative Works, in at least one +++ of the following places: within a NOTICE text file distributed +++ as part of the Derivative Works; within the Source form or +++ documentation, if provided along with the Derivative Works; or, +++ within a display generated by the Derivative Works, if and +++ wherever such third-party notices normally appear. The contents +++ of the NOTICE file are for informational purposes only and +++ do not modify the License. You may add Your own attribution +++ notices within Derivative Works that You distribute, alongside +++ or as an addendum to the NOTICE text from the Work, provided +++ that such additional attribution notices cannot be construed +++ as modifying the License. +++ +++ You may add Your own copyright statement to Your modifications and +++ may provide additional or different license terms and conditions +++ for use, reproduction, or distribution of Your modifications, or +++ for any such Derivative Works as a whole, provided Your use, +++ reproduction, and distribution of the Work otherwise complies with +++ the conditions stated in this License. +++ +++5. Submission of Contributions. Unless You explicitly state otherwise, +++ any Contribution intentionally submitted for inclusion in the Work +++ by You to the Licensor shall be under the terms and conditions of +++ this License, without any additional terms or conditions. +++ Notwithstanding the above, nothing herein shall supersede or modify +++ the terms of any separate license agreement you may have executed +++ with Licensor regarding such Contributions. +++ +++6. Trademarks. This License does not grant permission to use the trade +++ names, trademarks, service marks, or product names of the Licensor, +++ except as required for reasonable and customary use in describing the +++ origin of the Work and reproducing the content of the NOTICE file. +++ +++7. Disclaimer of Warranty. Unless required by applicable law or +++ agreed to in writing, Licensor provides the Work (and each +++ Contributor provides its Contributions) on an "AS IS" BASIS, +++ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +++ implied, including, without limitation, any warranties or conditions +++ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +++ PARTICULAR PURPOSE. You are solely responsible for determining the +++ appropriateness of using or redistributing the Work and assume any +++ risks associated with Your exercise of permissions under this License. +++ +++8. Limitation of Liability. In no event and under no legal theory, +++ whether in tort (including negligence), contract, or otherwise, +++ unless required by applicable law (such as deliberate and grossly +++ negligent acts) or agreed to in writing, shall any Contributor be +++ liable to You for damages, including any direct, indirect, special, +++ incidental, or consequential damages of any character arising as a +++ result of this License or out of the use or inability to use the +++ Work (including but not limited to damages for loss of goodwill, +++ work stoppage, computer failure or malfunction, or any and all +++ other commercial damages or losses), even if such Contributor +++ has been advised of the possibility of such damages. +++ +++9. Accepting Warranty or Additional Liability. While redistributing +++ the Work or Derivative Works thereof, You may choose to offer, +++ and charge a fee for, acceptance of support, warranty, indemnity, +++ or other liability obligations and/or rights consistent with this +++ License. However, in accepting such obligations, You may act only +++ on Your own behalf and on Your sole responsibility, not on behalf +++ of any other Contributor, and only if You agree to indemnify, +++ defend, and hold each Contributor harmless for any liability +++ incurred by, or claims asserted against, such Contributor by reason +++ of your accepting any such warranty or additional liability. +++ +++END OF TERMS AND CONDITIONS +++ +++APPENDIX: How to apply the Apache License to your work. +++ +++ To apply the Apache License to your work, attach the following +++ boilerplate notice, with the fields enclosed by brackets "[]" +++ replaced with your own identifying information. (Don't include +++ the brackets!) The text should be enclosed in the appropriate +++ comment syntax for the file format. We also recommend that a +++ file or class name and description of purpose be included on the +++ same "printed page" as the copyright notice for easier +++ identification within third-party archives. +++ +++Copyright [yyyy] [name of copyright owner] +++ +++Licensed under the Apache License, Version 2.0 (the "License"); +++you may not use this file except in compliance with the License. +++You may obtain a copy of the License at +++ +++ http://www.apache.org/licenses/LICENSE-2.0 +++ +++Unless required by applicable law or agreed to in writing, software +++distributed under the License is distributed on an "AS IS" BASIS, +++WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +++See the License for the specific language governing permissions and +++limitations under the License. diff --cc extra/git2/LICENSE-MIT index 0000000000,0000000000,0000000000..39e0ed6602 new file mode 100644 --- /dev/null +++ b/extra/git2/LICENSE-MIT @@@@ -1,0 -1,0 -1,0 +1,25 @@@@ +++Copyright (c) 2014 Alex Crichton +++ +++Permission is hereby granted, free of charge, to any +++person obtaining a copy of this software and associated +++documentation files (the "Software"), to deal in the +++Software without restriction, including without +++limitation the rights to use, copy, modify, merge, +++publish, distribute, sublicense, and/or sell copies of +++the Software, and to permit persons to whom the Software +++is furnished to do so, subject to the following +++conditions: +++ +++The above copyright notice and this permission notice +++shall be included in all copies or substantial portions +++of the Software. +++ +++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +++ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +++TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +++PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +++SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +++CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +++OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +++IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +++DEALINGS IN THE SOFTWARE. diff --cc extra/git2/README.md index 0000000000,0000000000,0000000000..ae1c377da9 new file mode 100644 --- /dev/null +++ b/extra/git2/README.md @@@@ -1,0 -1,0 -1,0 +1,76 @@@@ +++# git2-rs +++ +++[Documentation](https://docs.rs/git2) +++ +++libgit2 bindings for Rust. +++ +++```toml +++[dependencies] +++git2 = "0.20.0" +++``` +++ +++## Rust version requirements +++ +++git2-rs works with stable Rust, and typically works with the most recent prior +++stable release as well. +++ +++## Version of libgit2 +++ +++Currently this library requires libgit2 1.9.0 (or newer patch versions). The +++source for libgit2 is included in the libgit2-sys crate so there's no need to +++pre-install the libgit2 library, the libgit2-sys crate will figure that and/or +++build that for you. On the other hand, if an appropriate version of `libgit2` +++is present, `git2` will attempt to dynamically link it. +++ +++To be more precise, the vendored `libgit2` is linked statically if two +++conditions both hold: +++ +++- The environment variable `LIBGIT2_NO_VENDOR=1` is **not** set +++- **and** either a) The Cargo feature `vendored-libgit2` is set or b) an +++ appropriate version of `libgit2` cannot be found on the system. +++ +++In particular, note that the environment variable overrides the Cargo feature. +++ +++## Building git2-rs +++ +++```sh +++$ git clone https://github.com/rust-lang/git2-rs +++$ cd git2-rs +++$ cargo build +++``` +++ +++### Automating Testing +++ +++Running tests and handling all of the associated edge cases on every commit +++proves tedious very quickly. To automate tests and handle proper stashing and +++unstashing of unstaged changes and thus avoid nasty surprises, use the +++pre-commit hook found [here][pre-commit-hook] and place it into the +++`.git/hooks/` with the name `pre-commit`. You may need to add execution +++permissions with `chmod +x`. +++ +++To skip tests on a simple commit or doc-fixes, use `git commit --no-verify`. +++ +++## Building on macOS 10.10+ +++ +++If the `ssh` feature is enabled (and it is by default) then this library depends +++on libssh2 which depends on OpenSSL. To get OpenSSL working follow the +++[`openssl` crate's instructions](https://github.com/sfackler/rust-openssl/blob/master/openssl/src/lib.rs#L31). +++ +++# License +++ +++This project is licensed under either of +++ +++ * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or +++ https://www.apache.org/licenses/LICENSE-2.0) +++ * MIT license ([LICENSE-MIT](LICENSE-MIT) or +++ https://opensource.org/licenses/MIT) +++ +++at your option. +++ +++### Contribution +++ +++Unless you explicitly state otherwise, any contribution intentionally submitted +++for inclusion in git2-rs by you, as defined in the Apache-2.0 license, shall be +++dual licensed as above, without any additional terms or conditions. +++ +++[pre-commit-hook]: https://gist.github.com/glfmn/0c5e9e2b41b48007ed3497d11e3dbbfa diff --cc extra/git2/ci/publish.sh index 0000000000,0000000000,0000000000..cfc084699c new file mode 100755 --- /dev/null +++ b/extra/git2/ci/publish.sh @@@@ -1,0 -1,0 -1,0 +1,46 @@@@ +++#!/bin/bash +++ +++set -e +++ +++function publish { +++ publish_this="$1" +++ crate_name="$2" +++ manifest="$3" +++ +++ if [ "$publish_this" != "true" ] +++ then +++ echo "Skipping $crate_name, publish not requested." +++ return +++ fi +++ +++ # Get the version from Cargo.toml +++ version=`sed -n -E 's/^version = "(.*)"/\1/p' $manifest` +++ +++ # Check crates.io if it is already published +++ set +e +++ output=`curl --fail --silent --head --location https://static.crates.io/crates/$crate_name/$version/download` +++ res="$?" +++ set -e +++ case $res in +++ 0) +++ echo "${crate_name}@${version} appears to already be published" +++ return +++ ;; +++ 22) ;; +++ *) +++ echo "Failed to check ${crate_name}@${version} res: $res" +++ echo "$output" +++ exit 1 +++ ;; +++ esac +++ +++ cargo publish --manifest-path $manifest --no-verify +++ +++ tag="${crate_name}-${version}" +++ git tag $tag +++ git push origin "$tag" +++} +++ +++publish $PUBLISH_LIBGIT2_SYS libgit2-sys libgit2-sys/Cargo.toml +++publish $PUBLISH_GIT2 git2 Cargo.toml +++publish $PUBLISH_GIT2_CURL git2-curl git2-curl/Cargo.toml diff --cc extra/git2/examples/add.rs index 0000000000,0000000000,0000000000..57c9bb10a9 new file mode 100644 --- /dev/null +++ b/extra/git2/examples/add.rs @@@@ -1,0 -1,0 -1,0 +1,81 @@@@ +++/* +++ * libgit2 "add" example - shows how to modify the index +++ * +++ * Written by the libgit2 contributors +++ * +++ * To the extent possible under law, the author(s) have dedicated all copyright +++ * and related and neighboring rights to this software to the public domain +++ * worldwide. This software is distributed without any warranty. +++ * +++ * You should have received a copy of the CC0 Public Domain Dedication along +++ * with this software. If not, see +++ * . +++ */ +++ +++#![deny(warnings)] +++#![allow(trivial_casts)] +++ +++use clap::Parser; +++use git2::Repository; +++use std::path::Path; +++ +++#[derive(Parser)] +++struct Args { +++ #[structopt(name = "spec")] +++ arg_spec: Vec, +++ #[structopt(name = "dry_run", short = 'n', long)] +++ /// dry run +++ flag_dry_run: bool, +++ #[structopt(name = "verbose", short, long)] +++ /// be verbose +++ flag_verbose: bool, +++ #[structopt(name = "update", short, long)] +++ /// update tracked files +++ flag_update: bool, +++} +++ +++fn run(args: &Args) -> Result<(), git2::Error> { +++ let repo = Repository::open(&Path::new("."))?; +++ let mut index = repo.index()?; +++ +++ let cb = &mut |path: &Path, _matched_spec: &[u8]| -> i32 { +++ let status = repo.status_file(path).unwrap(); +++ +++ let ret = if status.contains(git2::Status::WT_MODIFIED) +++ || status.contains(git2::Status::WT_NEW) +++ { +++ println!("add '{}'", path.display()); +++ 0 +++ } else { +++ 1 +++ }; +++ +++ if args.flag_dry_run { +++ 1 +++ } else { +++ ret +++ } +++ }; +++ let cb = if args.flag_verbose || args.flag_update { +++ Some(cb as &mut git2::IndexMatchedPath) +++ } else { +++ None +++ }; +++ +++ if args.flag_update { +++ index.update_all(args.arg_spec.iter(), cb)?; +++ } else { +++ index.add_all(args.arg_spec.iter(), git2::IndexAddOption::DEFAULT, cb)?; +++ } +++ +++ index.write()?; +++ Ok(()) +++} +++ +++fn main() { +++ let args = Args::parse(); +++ match run(&args) { +++ Ok(()) => {} +++ Err(e) => println!("error: {}", e), +++ } +++} diff --cc extra/git2/examples/blame.rs index 0000000000,0000000000,0000000000..202989b3f0 new file mode 100644 --- /dev/null +++ b/extra/git2/examples/blame.rs @@@@ -1,0 -1,0 -1,0 +1,104 @@@@ +++/* +++ * libgit2 "blame" example - shows how to use the blame API +++ * +++ * Written by the libgit2 contributors +++ * +++ * To the extent possible under law, the author(s) have dedicated all copyright +++ * and related and neighboring rights to this software to the public domain +++ * worldwide. This software is distributed without any warranty. +++ * +++ * You should have received a copy of the CC0 Public Domain Dedication along +++ * with this software. If not, see +++ * . +++ */ +++ +++#![deny(warnings)] +++ +++use clap::Parser; +++use git2::{BlameOptions, Repository}; +++use std::io::{BufRead, BufReader}; +++use std::path::Path; +++ +++#[derive(Parser)] +++#[allow(non_snake_case)] +++struct Args { +++ #[structopt(name = "path")] +++ arg_path: String, +++ #[structopt(name = "spec")] +++ arg_spec: Option, +++ #[structopt(short = 'M')] +++ /// find line moves within and across files +++ flag_M: bool, +++ #[structopt(short = 'C')] +++ /// find line copies within and across files +++ flag_C: bool, +++ #[structopt(short = 'F')] +++ /// follow only the first parent commits +++ flag_F: bool, +++} +++ +++fn run(args: &Args) -> Result<(), git2::Error> { +++ let repo = Repository::open(".")?; +++ let path = Path::new(&args.arg_path[..]); +++ +++ // Prepare our blame options +++ let mut opts = BlameOptions::new(); +++ opts.track_copies_same_commit_moves(args.flag_M) +++ .track_copies_same_commit_copies(args.flag_C) +++ .first_parent(args.flag_F); +++ +++ let mut commit_id = "HEAD".to_string(); +++ +++ // Parse spec +++ if let Some(spec) = args.arg_spec.as_ref() { +++ let revspec = repo.revparse(spec)?; +++ +++ let (oldest, newest) = if revspec.mode().contains(git2::RevparseMode::SINGLE) { +++ (None, revspec.from()) +++ } else if revspec.mode().contains(git2::RevparseMode::RANGE) { +++ (revspec.from(), revspec.to()) +++ } else { +++ (None, None) +++ }; +++ +++ if let Some(commit) = oldest { +++ opts.oldest_commit(commit.id()); +++ } +++ +++ if let Some(commit) = newest { +++ opts.newest_commit(commit.id()); +++ if !commit.id().is_zero() { +++ commit_id = format!("{}", commit.id()) +++ } +++ } +++ } +++ +++ let spec = format!("{}:{}", commit_id, path.display()); +++ let blame = repo.blame_file(path, Some(&mut opts))?; +++ let object = repo.revparse_single(&spec[..])?; +++ let blob = repo.find_blob(object.id())?; +++ let reader = BufReader::new(blob.content()); +++ +++ for (i, line) in reader.lines().enumerate() { +++ if let (Ok(line), Some(hunk)) = (line, blame.get_line(i + 1)) { +++ let sig = hunk.final_signature(); +++ println!( +++ "{} {} <{}> {}", +++ hunk.final_commit_id(), +++ String::from_utf8_lossy(sig.name_bytes()), +++ String::from_utf8_lossy(sig.email_bytes()), +++ line +++ ); +++ } +++ } +++ +++ Ok(()) +++} +++ +++fn main() { +++ let args = Args::parse(); +++ match run(&args) { +++ Ok(()) => {} +++ Err(e) => println!("error: {}", e), +++ } +++} diff --cc extra/git2/examples/cat-file.rs index 0000000000,0000000000,0000000000..6196b9bb9f new file mode 100644 --- /dev/null +++ b/extra/git2/examples/cat-file.rs @@@@ -1,0 -1,0 -1,0 +1,149 @@@@ +++/* +++ * libgit2 "cat-file" example - shows how to print data from the ODB +++ * +++ * Written by the libgit2 contributors +++ * +++ * To the extent possible under law, the author(s) have dedicated all copyright +++ * and related and neighboring rights to this software to the public domain +++ * worldwide. This software is distributed without any warranty. +++ * +++ * You should have received a copy of the CC0 Public Domain Dedication along +++ * with this software. If not, see +++ * . +++ */ +++ +++#![deny(warnings)] +++ +++use std::io::{self, Write}; +++ +++use clap::Parser; +++use git2::{Blob, Commit, ObjectType, Repository, Signature, Tag, Tree}; +++ +++#[derive(Parser)] +++struct Args { +++ #[structopt(name = "object")] +++ arg_object: String, +++ #[structopt(short = 't')] +++ /// show the object type +++ flag_t: bool, +++ #[structopt(short = 's')] +++ /// show the object size +++ flag_s: bool, +++ #[structopt(short = 'e')] +++ /// suppress all output +++ flag_e: bool, +++ #[structopt(short = 'p')] +++ /// pretty print the contents of the object +++ flag_p: bool, +++ #[structopt(name = "quiet", short, long)] +++ /// suppress output +++ flag_q: bool, +++ #[structopt(name = "verbose", short, long)] +++ flag_v: bool, +++ #[structopt(name = "dir", long = "git-dir")] +++ /// use the specified directory as the base directory +++ flag_git_dir: Option, +++} +++ +++fn run(args: &Args) -> Result<(), git2::Error> { +++ let path = args.flag_git_dir.as_ref().map(|s| &s[..]).unwrap_or("."); +++ let repo = Repository::open(path)?; +++ +++ let obj = repo.revparse_single(&args.arg_object)?; +++ if args.flag_v && !args.flag_q { +++ println!("{} {}\n--", obj.kind().unwrap().str(), obj.id()); +++ } +++ +++ if args.flag_t { +++ println!("{}", obj.kind().unwrap().str()); +++ } else if args.flag_s || args.flag_e { +++ /* ... */ +++ } else if args.flag_p { +++ match obj.kind() { +++ Some(ObjectType::Blob) => { +++ show_blob(obj.as_blob().unwrap()); +++ } +++ Some(ObjectType::Commit) => { +++ show_commit(obj.as_commit().unwrap()); +++ } +++ Some(ObjectType::Tag) => { +++ show_tag(obj.as_tag().unwrap()); +++ } +++ Some(ObjectType::Tree) => { +++ show_tree(obj.as_tree().unwrap()); +++ } +++ Some(ObjectType::Any) | None => println!("unknown {}", obj.id()), +++ } +++ } +++ Ok(()) +++} +++ +++fn show_blob(blob: &Blob) { +++ io::stdout().write_all(blob.content()).unwrap(); +++} +++ +++fn show_commit(commit: &Commit) { +++ println!("tree {}", commit.tree_id()); +++ for parent in commit.parent_ids() { +++ println!("parent {}", parent); +++ } +++ show_sig("author", Some(commit.author())); +++ show_sig("committer", Some(commit.committer())); +++ if let Some(msg) = commit.message() { +++ println!("\n{}", msg); +++ } +++} +++ +++fn show_tag(tag: &Tag) { +++ println!("object {}", tag.target_id()); +++ println!("type {}", tag.target_type().unwrap().str()); +++ println!("tag {}", tag.name().unwrap()); +++ show_sig("tagger", tag.tagger()); +++ +++ if let Some(msg) = tag.message() { +++ println!("\n{}", msg); +++ } +++} +++ +++fn show_tree(tree: &Tree) { +++ for entry in tree.iter() { +++ println!( +++ "{:06o} {} {}\t{}", +++ entry.filemode(), +++ entry.kind().unwrap().str(), +++ entry.id(), +++ entry.name().unwrap() +++ ); +++ } +++} +++ +++fn show_sig(header: &str, sig: Option) { +++ let sig = match sig { +++ Some(s) => s, +++ None => return, +++ }; +++ let offset = sig.when().offset_minutes(); +++ let (sign, offset) = if offset < 0 { +++ ('-', -offset) +++ } else { +++ ('+', offset) +++ }; +++ let (hours, minutes) = (offset / 60, offset % 60); +++ println!( +++ "{} {} {} {}{:02}{:02}", +++ header, +++ sig, +++ sig.when().seconds(), +++ sign, +++ hours, +++ minutes +++ ); +++} +++ +++fn main() { +++ let args = Args::parse(); +++ match run(&args) { +++ Ok(()) => {} +++ Err(e) => println!("error: {}", e), +++ } +++} diff --cc extra/git2/examples/clone.rs index 0000000000,0000000000,0000000000..f6d00b14b6 new file mode 100644 --- /dev/null +++ b/extra/git2/examples/clone.rs @@@@ -1,0 -1,0 -1,0 +1,126 @@@@ +++/* +++ * libgit2 "clone" example +++ * +++ * Written by the libgit2 contributors +++ * +++ * To the extent possible under law, the author(s) have dedicated all copyright +++ * and related and neighboring rights to this software to the public domain +++ * worldwide. This software is distributed without any warranty. +++ * +++ * You should have received a copy of the CC0 Public Domain Dedication along +++ * with this software. If not, see +++ * . +++ */ +++ +++#![deny(warnings)] +++ +++use clap::Parser; +++use git2::build::{CheckoutBuilder, RepoBuilder}; +++use git2::{FetchOptions, Progress, RemoteCallbacks}; +++use std::cell::RefCell; +++use std::io::{self, Write}; +++use std::path::{Path, PathBuf}; +++ +++#[derive(Parser)] +++struct Args { +++ #[structopt(name = "url")] +++ arg_url: String, +++ #[structopt(name = "path")] +++ arg_path: String, +++} +++ +++struct State { +++ progress: Option>, +++ total: usize, +++ current: usize, +++ path: Option, +++ newline: bool, +++} +++ +++fn print(state: &mut State) { +++ let stats = state.progress.as_ref().unwrap(); +++ let network_pct = (100 * stats.received_objects()) / stats.total_objects(); +++ let index_pct = (100 * stats.indexed_objects()) / stats.total_objects(); +++ let co_pct = if state.total > 0 { +++ (100 * state.current) / state.total +++ } else { +++ 0 +++ }; +++ let kbytes = stats.received_bytes() / 1024; +++ if stats.received_objects() == stats.total_objects() { +++ if !state.newline { +++ println!(); +++ state.newline = true; +++ } +++ print!( +++ "Resolving deltas {}/{}\r", +++ stats.indexed_deltas(), +++ stats.total_deltas() +++ ); +++ } else { +++ print!( +++ "net {:3}% ({:4} kb, {:5}/{:5}) / idx {:3}% ({:5}/{:5}) \ +++ / chk {:3}% ({:4}/{:4}) {}\r", +++ network_pct, +++ kbytes, +++ stats.received_objects(), +++ stats.total_objects(), +++ index_pct, +++ stats.indexed_objects(), +++ stats.total_objects(), +++ co_pct, +++ state.current, +++ state.total, +++ state +++ .path +++ .as_ref() +++ .map(|s| s.to_string_lossy().into_owned()) +++ .unwrap_or_default() +++ ) +++ } +++ io::stdout().flush().unwrap(); +++} +++ +++fn run(args: &Args) -> Result<(), git2::Error> { +++ let state = RefCell::new(State { +++ progress: None, +++ total: 0, +++ current: 0, +++ path: None, +++ newline: false, +++ }); +++ let mut cb = RemoteCallbacks::new(); +++ cb.transfer_progress(|stats| { +++ let mut state = state.borrow_mut(); +++ state.progress = Some(stats.to_owned()); +++ print(&mut *state); +++ true +++ }); +++ +++ let mut co = CheckoutBuilder::new(); +++ co.progress(|path, cur, total| { +++ let mut state = state.borrow_mut(); +++ state.path = path.map(|p| p.to_path_buf()); +++ state.current = cur; +++ state.total = total; +++ print(&mut *state); +++ }); +++ +++ let mut fo = FetchOptions::new(); +++ fo.remote_callbacks(cb); +++ RepoBuilder::new() +++ .fetch_options(fo) +++ .with_checkout(co) +++ .clone(&args.arg_url, Path::new(&args.arg_path))?; +++ println!(); +++ +++ Ok(()) +++} +++ +++fn main() { +++ let args = Args::parse(); +++ match run(&args) { +++ Ok(()) => {} +++ Err(e) => println!("error: {}", e), +++ } +++} diff --cc extra/git2/examples/diff.rs index 0000000000,0000000000,0000000000..7440149ba0 new file mode 100644 --- /dev/null +++ b/extra/git2/examples/diff.rs @@@@ -1,0 -1,0 -1,0 +1,368 @@@@ +++/* +++ * libgit2 "diff" example - shows how to use the diff API +++ * +++ * Written by the libgit2 contributors +++ * +++ * To the extent possible under law, the author(s) have dedicated all copyright +++ * and related and neighboring rights to this software to the public domain +++ * worldwide. This software is distributed without any warranty. +++ * +++ * You should have received a copy of the CC0 Public Domain Dedication along +++ * with this software. If not, see +++ * . +++ */ +++ +++#![deny(warnings)] +++ +++use clap::Parser; +++use git2::{Blob, Diff, DiffOptions, Error, Object, ObjectType, Oid, Repository}; +++use git2::{DiffDelta, DiffFindOptions, DiffFormat, DiffHunk, DiffLine}; +++use std::str; +++ +++#[derive(Parser)] +++#[allow(non_snake_case)] +++struct Args { +++ #[structopt(name = "from_oid")] +++ arg_from_oid: Option, +++ #[structopt(name = "to_oid")] +++ arg_to_oid: Option, +++ #[structopt(name = "blobs", long)] +++ /// treat from_oid and to_oid as blob ids +++ flag_blobs: bool, +++ #[structopt(name = "patch", short, long)] +++ /// show output in patch format +++ flag_patch: bool, +++ #[structopt(name = "cached", long)] +++ /// use staged changes as diff +++ flag_cached: bool, +++ #[structopt(name = "nocached", long)] +++ /// do not use staged changes +++ flag_nocached: bool, +++ #[structopt(name = "name-only", long)] +++ /// show only names of changed files +++ flag_name_only: bool, +++ #[structopt(name = "name-status", long)] +++ /// show only names and status changes +++ flag_name_status: bool, +++ #[structopt(name = "raw", long)] +++ /// generate the raw format +++ flag_raw: bool, +++ #[structopt(name = "format", long)] +++ /// specify format for stat summary +++ flag_format: Option, +++ #[structopt(name = "color", long)] +++ /// use color output +++ flag_color: bool, +++ #[structopt(name = "no-color", long)] +++ /// never use color output +++ flag_no_color: bool, +++ #[structopt(short = 'R')] +++ /// swap two inputs +++ flag_R: bool, +++ #[structopt(name = "text", short = 'a', long)] +++ /// treat all files as text +++ flag_text: bool, +++ #[structopt(name = "ignore-space-at-eol", long)] +++ /// ignore changes in whitespace at EOL +++ flag_ignore_space_at_eol: bool, +++ #[structopt(name = "ignore-space-change", short = 'b', long)] +++ /// ignore changes in amount of whitespace +++ flag_ignore_space_change: bool, +++ #[structopt(name = "ignore-all-space", short = 'w', long)] +++ /// ignore whitespace when comparing lines +++ flag_ignore_all_space: bool, +++ #[structopt(name = "ignored", long)] +++ /// show untracked files +++ flag_ignored: bool, +++ #[structopt(name = "untracked", long)] +++ /// generate diff using the patience algorithm +++ flag_untracked: bool, +++ #[structopt(name = "patience", long)] +++ /// show ignored files as well +++ flag_patience: bool, +++ #[structopt(name = "minimal", long)] +++ /// spend extra time to find smallest diff +++ flag_minimal: bool, +++ #[structopt(name = "stat", long)] +++ /// generate a diffstat +++ flag_stat: bool, +++ #[structopt(name = "numstat", long)] +++ /// similar to --stat, but more machine friendly +++ flag_numstat: bool, +++ #[structopt(name = "shortstat", long)] +++ /// only output last line of --stat +++ flag_shortstat: bool, +++ #[structopt(name = "summary", long)] +++ /// output condensed summary of header info +++ flag_summary: bool, +++ #[structopt(name = "find-renames", short = 'M', long)] +++ /// set threshold for finding renames (default 50) +++ flag_find_renames: Option, +++ #[structopt(name = "find-copies", short = 'C', long)] +++ /// set threshold for finding copies (default 50) +++ flag_find_copies: Option, +++ #[structopt(name = "find-copies-harder", long)] +++ /// inspect unmodified files for sources of copies +++ flag_find_copies_harder: bool, +++ #[structopt(name = "break_rewrites", short = 'B', long)] +++ /// break complete rewrite changes into pairs +++ flag_break_rewrites: bool, +++ #[structopt(name = "unified", short = 'U', long)] +++ /// lints of context to show +++ flag_unified: Option, +++ #[structopt(name = "inter-hunk-context", long)] +++ /// maximum lines of change between hunks +++ flag_inter_hunk_context: Option, +++ #[structopt(name = "abbrev", long)] +++ /// length to abbreviate commits to +++ flag_abbrev: Option, +++ #[structopt(name = "src-prefix", long)] +++ /// show given source prefix instead of 'a/' +++ flag_src_prefix: Option, +++ #[structopt(name = "dst-prefix", long)] +++ /// show given destination prefix instead of 'b/' +++ flag_dst_prefix: Option, +++ #[structopt(name = "path", long = "git-dir")] +++ /// path to git repository to use +++ flag_git_dir: Option, +++} +++ +++const RESET: &str = "\u{1b}[m"; +++const BOLD: &str = "\u{1b}[1m"; +++const RED: &str = "\u{1b}[31m"; +++const GREEN: &str = "\u{1b}[32m"; +++const CYAN: &str = "\u{1b}[36m"; +++ +++#[derive(PartialEq, Eq, Copy, Clone)] +++enum Cache { +++ Normal, +++ Only, +++ None, +++} +++ +++fn line_color(line: &DiffLine) -> Option<&'static str> { +++ match line.origin() { +++ '+' => Some(GREEN), +++ '-' => Some(RED), +++ '>' => Some(GREEN), +++ '<' => Some(RED), +++ 'F' => Some(BOLD), +++ 'H' => Some(CYAN), +++ _ => None, +++ } +++} +++ +++fn print_diff_line( +++ _delta: DiffDelta, +++ _hunk: Option, +++ line: DiffLine, +++ args: &Args, +++) -> bool { +++ if args.color() { +++ print!("{}", RESET); +++ if let Some(color) = line_color(&line) { +++ print!("{}", color); +++ } +++ } +++ match line.origin() { +++ '+' | '-' | ' ' => print!("{}", line.origin()), +++ _ => {} +++ } +++ print!("{}", str::from_utf8(line.content()).unwrap()); +++ true +++} +++ +++fn run(args: &Args) -> Result<(), Error> { +++ let path = args.flag_git_dir.as_ref().map(|s| &s[..]).unwrap_or("."); +++ let repo = Repository::open(path)?; +++ +++ // Prepare our diff options based on the arguments given +++ let mut opts = DiffOptions::new(); +++ opts.reverse(args.flag_R) +++ .force_text(args.flag_text) +++ .ignore_whitespace_eol(args.flag_ignore_space_at_eol) +++ .ignore_whitespace_change(args.flag_ignore_space_change) +++ .ignore_whitespace(args.flag_ignore_all_space) +++ .include_ignored(args.flag_ignored) +++ .include_untracked(args.flag_untracked) +++ .patience(args.flag_patience) +++ .minimal(args.flag_minimal); +++ if let Some(amt) = args.flag_unified { +++ opts.context_lines(amt); +++ } +++ if let Some(amt) = args.flag_inter_hunk_context { +++ opts.interhunk_lines(amt); +++ } +++ if let Some(amt) = args.flag_abbrev { +++ opts.id_abbrev(amt); +++ } +++ if let Some(ref s) = args.flag_src_prefix { +++ opts.old_prefix(&s); +++ } +++ if let Some(ref s) = args.flag_dst_prefix { +++ opts.new_prefix(&s); +++ } +++ if let Some("diff-index") = args.flag_format.as_ref().map(|s| &s[..]) { +++ opts.id_abbrev(40); +++ } +++ +++ if args.flag_blobs { +++ let b1 = resolve_blob(&repo, args.arg_from_oid.as_ref())?; +++ let b2 = resolve_blob(&repo, args.arg_to_oid.as_ref())?; +++ repo.diff_blobs( +++ b1.as_ref(), +++ None, +++ b2.as_ref(), +++ None, +++ Some(&mut opts), +++ None, +++ None, +++ None, +++ Some(&mut |d, h, l| print_diff_line(d, h, l, args)), +++ )?; +++ if args.color() { +++ print!("{}", RESET); +++ } +++ return Ok(()); +++ } +++ +++ // Prepare the diff to inspect +++ let t1 = tree_to_treeish(&repo, args.arg_from_oid.as_ref())?; +++ let t2 = tree_to_treeish(&repo, args.arg_to_oid.as_ref())?; +++ let head = tree_to_treeish(&repo, Some(&"HEAD".to_string()))?.unwrap(); +++ let mut diff = match (t1, t2, args.cache()) { +++ (Some(t1), Some(t2), _) => { +++ repo.diff_tree_to_tree(t1.as_tree(), t2.as_tree(), Some(&mut opts))? +++ } +++ (t1, None, Cache::None) => { +++ let t1 = t1.unwrap_or(head); +++ repo.diff_tree_to_workdir(t1.as_tree(), Some(&mut opts))? +++ } +++ (t1, None, Cache::Only) => { +++ let t1 = t1.unwrap_or(head); +++ repo.diff_tree_to_index(t1.as_tree(), None, Some(&mut opts))? +++ } +++ (Some(t1), None, _) => { +++ repo.diff_tree_to_workdir_with_index(t1.as_tree(), Some(&mut opts))? +++ } +++ (None, None, _) => repo.diff_index_to_workdir(None, Some(&mut opts))?, +++ (None, Some(_), _) => unreachable!(), +++ }; +++ +++ // Apply rename and copy detection if requested +++ if args.flag_break_rewrites +++ || args.flag_find_copies_harder +++ || args.flag_find_renames.is_some() +++ || args.flag_find_copies.is_some() +++ { +++ let mut opts = DiffFindOptions::new(); +++ if let Some(t) = args.flag_find_renames { +++ opts.rename_threshold(t); +++ opts.renames(true); +++ } +++ if let Some(t) = args.flag_find_copies { +++ opts.copy_threshold(t); +++ opts.copies(true); +++ } +++ opts.copies_from_unmodified(args.flag_find_copies_harder) +++ .rewrites(args.flag_break_rewrites); +++ diff.find_similar(Some(&mut opts))?; +++ } +++ +++ // Generate simple output +++ let stats = args.flag_stat | args.flag_numstat | args.flag_shortstat | args.flag_summary; +++ if stats { +++ print_stats(&diff, args)?; +++ } +++ if args.flag_patch || !stats { +++ diff.print(args.diff_format(), |d, h, l| print_diff_line(d, h, l, args))?; +++ if args.color() { +++ print!("{}", RESET); +++ } +++ } +++ +++ Ok(()) +++} +++ +++fn print_stats(diff: &Diff, args: &Args) -> Result<(), Error> { +++ let stats = diff.stats()?; +++ let mut format = git2::DiffStatsFormat::NONE; +++ if args.flag_stat { +++ format |= git2::DiffStatsFormat::FULL; +++ } +++ if args.flag_shortstat { +++ format |= git2::DiffStatsFormat::SHORT; +++ } +++ if args.flag_numstat { +++ format |= git2::DiffStatsFormat::NUMBER; +++ } +++ if args.flag_summary { +++ format |= git2::DiffStatsFormat::INCLUDE_SUMMARY; +++ } +++ let buf = stats.to_buf(format, 80)?; +++ print!("{}", str::from_utf8(&*buf).unwrap()); +++ Ok(()) +++} +++ +++fn tree_to_treeish<'a>( +++ repo: &'a Repository, +++ arg: Option<&String>, +++) -> Result>, Error> { +++ let arg = match arg { +++ Some(s) => s, +++ None => return Ok(None), +++ }; +++ let obj = repo.revparse_single(arg)?; +++ let tree = obj.peel(ObjectType::Tree)?; +++ Ok(Some(tree)) +++} +++ +++fn resolve_blob<'a>(repo: &'a Repository, arg: Option<&String>) -> Result>, Error> { +++ let arg = match arg { +++ Some(s) => Oid::from_str(s)?, +++ None => return Ok(None), +++ }; +++ repo.find_blob(arg).map(|b| Some(b)) +++} +++ +++impl Args { +++ fn cache(&self) -> Cache { +++ if self.flag_cached { +++ Cache::Only +++ } else if self.flag_nocached { +++ Cache::None +++ } else { +++ Cache::Normal +++ } +++ } +++ fn color(&self) -> bool { +++ self.flag_color && !self.flag_no_color +++ } +++ fn diff_format(&self) -> DiffFormat { +++ if self.flag_patch { +++ DiffFormat::Patch +++ } else if self.flag_name_only { +++ DiffFormat::NameOnly +++ } else if self.flag_name_status { +++ DiffFormat::NameStatus +++ } else if self.flag_raw { +++ DiffFormat::Raw +++ } else { +++ match self.flag_format.as_ref().map(|s| &s[..]) { +++ Some("name") => DiffFormat::NameOnly, +++ Some("name-status") => DiffFormat::NameStatus, +++ Some("raw") => DiffFormat::Raw, +++ Some("diff-index") => DiffFormat::Raw, +++ _ => DiffFormat::Patch, +++ } +++ } +++ } +++} +++ +++fn main() { +++ let args = Args::parse(); +++ match run(&args) { +++ Ok(()) => {} +++ Err(e) => println!("error: {}", e), +++ } +++} diff --cc extra/git2/examples/fetch.rs index 0000000000,0000000000,0000000000..af4aa98eb9 new file mode 100644 --- /dev/null +++ b/extra/git2/examples/fetch.rs @@@@ -1,0 -1,0 -1,0 +1,132 @@@@ +++/* +++ * libgit2 "fetch" example - shows how to fetch remote data +++ * +++ * Written by the libgit2 contributors +++ * +++ * To the extent possible under law, the author(s) have dedicated all copyright +++ * and related and neighboring rights to this software to the public domain +++ * worldwide. This software is distributed without any warranty. +++ * +++ * You should have received a copy of the CC0 Public Domain Dedication along +++ * with this software. If not, see +++ * . +++ */ +++ +++#![deny(warnings)] +++ +++use clap::Parser; +++use git2::{AutotagOption, FetchOptions, RemoteCallbacks, RemoteUpdateFlags, Repository}; +++use std::io::{self, Write}; +++use std::str; +++ +++#[derive(Parser)] +++struct Args { +++ #[structopt(name = "remote")] +++ arg_remote: Option, +++} +++ +++fn run(args: &Args) -> Result<(), git2::Error> { +++ let repo = Repository::open(".")?; +++ let remote = args.arg_remote.as_ref().map(|s| &s[..]).unwrap_or("origin"); +++ +++ // Figure out whether it's a named remote or a URL +++ println!("Fetching {} for repo", remote); +++ let mut cb = RemoteCallbacks::new(); +++ let mut remote = repo +++ .find_remote(remote) +++ .or_else(|_| repo.remote_anonymous(remote))?; +++ cb.sideband_progress(|data| { +++ print!("remote: {}", str::from_utf8(data).unwrap()); +++ io::stdout().flush().unwrap(); +++ true +++ }); +++ +++ // This callback gets called for each remote-tracking branch that gets +++ // updated. The message we output depends on whether it's a new one or an +++ // update. +++ cb.update_tips(|refname, a, b| { +++ if a.is_zero() { +++ println!("[new] {:20} {}", b, refname); +++ } else { +++ println!("[updated] {:10}..{:10} {}", a, b, refname); +++ } +++ true +++ }); +++ +++ // Here we show processed and total objects in the pack and the amount of +++ // received data. Most frontends will probably want to show a percentage and +++ // the download rate. +++ cb.transfer_progress(|stats| { +++ if stats.received_objects() == stats.total_objects() { +++ print!( +++ "Resolving deltas {}/{}\r", +++ stats.indexed_deltas(), +++ stats.total_deltas() +++ ); +++ } else if stats.total_objects() > 0 { +++ print!( +++ "Received {}/{} objects ({}) in {} bytes\r", +++ stats.received_objects(), +++ stats.total_objects(), +++ stats.indexed_objects(), +++ stats.received_bytes() +++ ); +++ } +++ io::stdout().flush().unwrap(); +++ true +++ }); +++ +++ // Download the packfile and index it. This function updates the amount of +++ // received data and the indexer stats which lets you inform the user about +++ // progress. +++ let mut fo = FetchOptions::new(); +++ fo.remote_callbacks(cb); +++ remote.download(&[] as &[&str], Some(&mut fo))?; +++ +++ { +++ // If there are local objects (we got a thin pack), then tell the user +++ // how many objects we saved from having to cross the network. +++ let stats = remote.stats(); +++ if stats.local_objects() > 0 { +++ println!( +++ "\rReceived {}/{} objects in {} bytes (used {} local \ +++ objects)", +++ stats.indexed_objects(), +++ stats.total_objects(), +++ stats.received_bytes(), +++ stats.local_objects() +++ ); +++ } else { +++ println!( +++ "\rReceived {}/{} objects in {} bytes", +++ stats.indexed_objects(), +++ stats.total_objects(), +++ stats.received_bytes() +++ ); +++ } +++ } +++ +++ // Disconnect the underlying connection to prevent from idling. +++ remote.disconnect()?; +++ +++ // Update the references in the remote's namespace to point to the right +++ // commits. This may be needed even if there was no packfile to download, +++ // which can happen e.g. when the branches have been changed but all the +++ // needed objects are available locally. +++ remote.update_tips( +++ None, +++ RemoteUpdateFlags::UPDATE_FETCHHEAD, +++ AutotagOption::Unspecified, +++ None, +++ )?; +++ +++ Ok(()) +++} +++ +++fn main() { +++ let args = Args::parse(); +++ match run(&args) { +++ Ok(()) => {} +++ Err(e) => println!("error: {}", e), +++ } +++} diff --cc extra/git2/examples/init.rs index 0000000000,0000000000,0000000000..3ae79082d7 new file mode 100644 --- /dev/null +++ b/extra/git2/examples/init.rs @@@@ -1,0 -1,0 -1,0 +1,145 @@@@ +++/* +++ * libgit2 "init" example - shows how to initialize a new repo (also includes how to do an initial commit) +++ * +++ * Written by the libgit2 contributors +++ * +++ * To the extent possible under law, the author(s) have dedicated all copyright +++ * and related and neighboring rights to this software to the public domain +++ * worldwide. This software is distributed without any warranty. +++ * +++ * You should have received a copy of the CC0 Public Domain Dedication along +++ * with this software. If not, see +++ * . +++ */ +++ +++#![deny(warnings)] +++ +++use clap::Parser; +++use git2::{Error, Repository, RepositoryInitMode, RepositoryInitOptions}; +++use std::path::{Path, PathBuf}; +++ +++#[derive(Parser)] +++struct Args { +++ #[structopt(name = "directory")] +++ arg_directory: String, +++ #[structopt(name = "quiet", short, long)] +++ /// don't print information to stdout +++ flag_quiet: bool, +++ #[structopt(name = "bare", long)] +++ /// initialize a new bare repository +++ flag_bare: bool, +++ #[structopt(name = "dir", long = "template")] +++ /// use as an initialization template +++ flag_template: Option, +++ #[structopt(name = "separate-git-dir", long)] +++ /// use as the .git directory +++ flag_separate_git_dir: Option, +++ #[structopt(name = "initial-commit", long)] +++ /// create an initial empty commit +++ flag_initial_commit: bool, +++ #[structopt(name = "perms", long = "shared")] +++ /// permissions to create the repository with +++ flag_shared: Option, +++} +++ +++fn run(args: &Args) -> Result<(), Error> { +++ let mut path = PathBuf::from(&args.arg_directory); +++ let repo = if !args.flag_bare +++ && args.flag_template.is_none() +++ && args.flag_shared.is_none() +++ && args.flag_separate_git_dir.is_none() +++ { +++ Repository::init(&path)? +++ } else { +++ let mut opts = RepositoryInitOptions::new(); +++ opts.bare(args.flag_bare); +++ if let Some(ref s) = args.flag_template { +++ opts.template_path(Path::new(s)); +++ } +++ +++ // If you specified a separate git directory, then initialize +++ // the repository at that path and use the second path as the +++ // working directory of the repository (with a git-link file) +++ if let Some(ref s) = args.flag_separate_git_dir { +++ opts.workdir_path(&path); +++ path = PathBuf::from(s); +++ } +++ +++ if let Some(ref s) = args.flag_shared { +++ opts.mode(parse_shared(s)?); +++ } +++ Repository::init_opts(&path, &opts)? +++ }; +++ +++ // Print a message to stdout like "git init" does +++ if !args.flag_quiet { +++ if args.flag_bare || args.flag_separate_git_dir.is_some() { +++ path = repo.path().to_path_buf(); +++ } else { +++ path = repo.workdir().unwrap().to_path_buf(); +++ } +++ println!("Initialized empty Git repository in {}", path.display()); +++ } +++ +++ if args.flag_initial_commit { +++ create_initial_commit(&repo)?; +++ println!("Created empty initial commit"); +++ } +++ +++ Ok(()) +++} +++ +++/// Unlike regular "git init", this example shows how to create an initial empty +++/// commit in the repository. This is the helper function that does that. +++fn create_initial_commit(repo: &Repository) -> Result<(), Error> { +++ // First use the config to initialize a commit signature for the user. +++ let sig = repo.signature()?; +++ +++ // Now let's create an empty tree for this commit +++ let tree_id = { +++ let mut index = repo.index()?; +++ +++ // Outside of this example, you could call index.add_path() +++ // here to put actual files into the index. For our purposes, we'll +++ // leave it empty for now. +++ +++ index.write_tree()? +++ }; +++ +++ let tree = repo.find_tree(tree_id)?; +++ +++ // Ready to create the initial commit. +++ // +++ // Normally creating a commit would involve looking up the current HEAD +++ // commit and making that be the parent of the initial commit, but here this +++ // is the first commit so there will be no parent. +++ repo.commit(Some("HEAD"), &sig, &sig, "Initial commit", &tree, &[])?; +++ +++ Ok(()) +++} +++ +++fn parse_shared(shared: &str) -> Result { +++ match shared { +++ "false" | "umask" => Ok(git2::RepositoryInitMode::SHARED_UMASK), +++ "true" | "group" => Ok(git2::RepositoryInitMode::SHARED_GROUP), +++ "all" | "world" => Ok(git2::RepositoryInitMode::SHARED_ALL), +++ _ => { +++ if shared.starts_with('0') { +++ match u32::from_str_radix(&shared[1..], 8).ok() { +++ Some(n) => Ok(RepositoryInitMode::from_bits_truncate(n)), +++ None => Err(Error::from_str("invalid octal value for --shared")), +++ } +++ } else { +++ Err(Error::from_str("unknown value for --shared")) +++ } +++ } +++ } +++} +++ +++fn main() { +++ let args = Args::parse(); +++ match run(&args) { +++ Ok(()) => {} +++ Err(e) => println!("error: {}", e), +++ } +++} diff --cc extra/git2/examples/log.rs index 0000000000,0000000000,0000000000..5f6fe0f210 new file mode 100644 --- /dev/null +++ b/extra/git2/examples/log.rs @@@@ -1,0 -1,0 -1,0 +1,303 @@@@ +++/* +++ * libgit2 "log" example - shows how to walk history and get commit info +++ * +++ * Written by the libgit2 contributors +++ * +++ * To the extent possible under law, the author(s) have dedicated all copyright +++ * and related and neighboring rights to this software to the public domain +++ * worldwide. This software is distributed without any warranty. +++ * +++ * You should have received a copy of the CC0 Public Domain Dedication along +++ * with this software. If not, see +++ * . +++ */ +++ +++#![deny(warnings)] +++ +++use clap::Parser; +++use git2::{Commit, DiffOptions, ObjectType, Repository, Signature, Time}; +++use git2::{DiffFormat, Error, Pathspec}; +++use std::str; +++ +++#[derive(Parser)] +++struct Args { +++ #[structopt(name = "topo-order", long)] +++ /// sort commits in topological order +++ flag_topo_order: bool, +++ #[structopt(name = "date-order", long)] +++ /// sort commits in date order +++ flag_date_order: bool, +++ #[structopt(name = "reverse", long)] +++ /// sort commits in reverse +++ flag_reverse: bool, +++ #[structopt(name = "author", long)] +++ /// author to sort by +++ flag_author: Option, +++ #[structopt(name = "committer", long)] +++ /// committer to sort by +++ flag_committer: Option, +++ #[structopt(name = "pat", long = "grep")] +++ /// pattern to filter commit messages by +++ flag_grep: Option, +++ #[structopt(name = "dir", long = "git-dir")] +++ /// alternative git directory to use +++ flag_git_dir: Option, +++ #[structopt(name = "skip", long)] +++ /// number of commits to skip +++ flag_skip: Option, +++ #[structopt(name = "max-count", short = 'n', long)] +++ /// maximum number of commits to show +++ flag_max_count: Option, +++ #[structopt(name = "merges", long)] +++ /// only show merge commits +++ flag_merges: bool, +++ #[structopt(name = "no-merges", long)] +++ /// don't show merge commits +++ flag_no_merges: bool, +++ #[structopt(name = "no-min-parents", long)] +++ /// don't require a minimum number of parents +++ flag_no_min_parents: bool, +++ #[structopt(name = "no-max-parents", long)] +++ /// don't require a maximum number of parents +++ flag_no_max_parents: bool, +++ #[structopt(name = "max-parents")] +++ /// specify a maximum number of parents for a commit +++ flag_max_parents: Option, +++ #[structopt(name = "min-parents")] +++ /// specify a minimum number of parents for a commit +++ flag_min_parents: Option, +++ #[structopt(name = "patch", long, short)] +++ /// show commit diff +++ flag_patch: bool, +++ #[structopt(name = "commit")] +++ arg_commit: Vec, +++ #[structopt(name = "spec", last = true)] +++ arg_spec: Vec, +++} +++ +++fn run(args: &Args) -> Result<(), Error> { +++ let path = args.flag_git_dir.as_ref().map(|s| &s[..]).unwrap_or("."); +++ let repo = Repository::open(path)?; +++ let mut revwalk = repo.revwalk()?; +++ +++ // Prepare the revwalk based on CLI parameters +++ let base = if args.flag_reverse { +++ git2::Sort::REVERSE +++ } else { +++ git2::Sort::NONE +++ }; +++ revwalk.set_sorting( +++ base | if args.flag_topo_order { +++ git2::Sort::TOPOLOGICAL +++ } else if args.flag_date_order { +++ git2::Sort::TIME +++ } else { +++ git2::Sort::NONE +++ }, +++ )?; +++ for commit in &args.arg_commit { +++ if commit.starts_with('^') { +++ let obj = repo.revparse_single(&commit[1..])?; +++ revwalk.hide(obj.id())?; +++ continue; +++ } +++ let revspec = repo.revparse(commit)?; +++ if revspec.mode().contains(git2::RevparseMode::SINGLE) { +++ revwalk.push(revspec.from().unwrap().id())?; +++ } else { +++ let from = revspec.from().unwrap().id(); +++ let to = revspec.to().unwrap().id(); +++ revwalk.push(to)?; +++ if revspec.mode().contains(git2::RevparseMode::MERGE_BASE) { +++ let base = repo.merge_base(from, to)?; +++ let o = repo.find_object(base, Some(ObjectType::Commit))?; +++ revwalk.push(o.id())?; +++ } +++ revwalk.hide(from)?; +++ } +++ } +++ if args.arg_commit.is_empty() { +++ revwalk.push_head()?; +++ } +++ +++ // Prepare our diff options and pathspec matcher +++ let (mut diffopts, mut diffopts2) = (DiffOptions::new(), DiffOptions::new()); +++ for spec in &args.arg_spec { +++ diffopts.pathspec(spec); +++ diffopts2.pathspec(spec); +++ } +++ let ps = Pathspec::new(args.arg_spec.iter())?; +++ +++ // Filter our revwalk based on the CLI parameters +++ macro_rules! filter_try { +++ ($e:expr) => { +++ match $e { +++ Ok(t) => t, +++ Err(e) => return Some(Err(e)), +++ } +++ }; +++ } +++ let revwalk = revwalk +++ .filter_map(|id| { +++ let id = filter_try!(id); +++ let commit = filter_try!(repo.find_commit(id)); +++ let parents = commit.parents().len(); +++ if parents < args.min_parents() { +++ return None; +++ } +++ if let Some(n) = args.max_parents() { +++ if parents >= n { +++ return None; +++ } +++ } +++ if !args.arg_spec.is_empty() { +++ match commit.parents().len() { +++ 0 => { +++ let tree = filter_try!(commit.tree()); +++ let flags = git2::PathspecFlags::NO_MATCH_ERROR; +++ if ps.match_tree(&tree, flags).is_err() { +++ return None; +++ } +++ } +++ _ => { +++ let m = commit.parents().all(|parent| { +++ match_with_parent(&repo, &commit, &parent, &mut diffopts) +++ .unwrap_or(false) +++ }); +++ if !m { +++ return None; +++ } +++ } +++ } +++ } +++ if !sig_matches(&commit.author(), &args.flag_author) { +++ return None; +++ } +++ if !sig_matches(&commit.committer(), &args.flag_committer) { +++ return None; +++ } +++ if !log_message_matches(commit.message(), &args.flag_grep) { +++ return None; +++ } +++ Some(Ok(commit)) +++ }) +++ .skip(args.flag_skip.unwrap_or(0)) +++ .take(args.flag_max_count.unwrap_or(!0)); +++ +++ // print! +++ for commit in revwalk { +++ let commit = commit?; +++ print_commit(&commit); +++ if !args.flag_patch || commit.parents().len() > 1 { +++ continue; +++ } +++ let a = if commit.parents().len() == 1 { +++ let parent = commit.parent(0)?; +++ Some(parent.tree()?) +++ } else { +++ None +++ }; +++ let b = commit.tree()?; +++ let diff = repo.diff_tree_to_tree(a.as_ref(), Some(&b), Some(&mut diffopts2))?; +++ diff.print(DiffFormat::Patch, |_delta, _hunk, line| { +++ match line.origin() { +++ ' ' | '+' | '-' => print!("{}", line.origin()), +++ _ => {} +++ } +++ print!("{}", str::from_utf8(line.content()).unwrap()); +++ true +++ })?; +++ } +++ +++ Ok(()) +++} +++ +++fn sig_matches(sig: &Signature, arg: &Option) -> bool { +++ match *arg { +++ Some(ref s) => { +++ sig.name().map(|n| n.contains(s)).unwrap_or(false) +++ || sig.email().map(|n| n.contains(s)).unwrap_or(false) +++ } +++ None => true, +++ } +++} +++ +++fn log_message_matches(msg: Option<&str>, grep: &Option) -> bool { +++ match (grep, msg) { +++ (&None, _) => true, +++ (&Some(_), None) => false, +++ (&Some(ref s), Some(msg)) => msg.contains(s), +++ } +++} +++ +++fn print_commit(commit: &Commit) { +++ println!("commit {}", commit.id()); +++ +++ if commit.parents().len() > 1 { +++ print!("Merge:"); +++ for id in commit.parent_ids() { +++ print!(" {:.8}", id); +++ } +++ println!(); +++ } +++ +++ let author = commit.author(); +++ println!("Author: {}", author); +++ print_time(&author.when(), "Date: "); +++ println!(); +++ +++ for line in String::from_utf8_lossy(commit.message_bytes()).lines() { +++ println!(" {}", line); +++ } +++ println!(); +++} +++ +++fn print_time(time: &Time, prefix: &str) { +++ let offset = time.offset_minutes(); +++ let (hours, minutes) = (offset / 60, offset % 60); +++ let dt = time::OffsetDateTime::from_unix_timestamp(time.seconds()).unwrap(); +++ let dto = dt.to_offset(time::UtcOffset::from_hms(hours as i8, minutes as i8, 0).unwrap()); +++ let format = time::format_description::parse("[weekday repr:short] [month repr:short] [day padding:space] [hour]:[minute]:[second] [year] [offset_hour sign:mandatory][offset_minute]") +++ .unwrap(); +++ let time_str = dto.format(&format).unwrap(); +++ +++ println!("{}{}", prefix, time_str); +++} +++ +++fn match_with_parent( +++ repo: &Repository, +++ commit: &Commit, +++ parent: &Commit, +++ opts: &mut DiffOptions, +++) -> Result { +++ let a = parent.tree()?; +++ let b = commit.tree()?; +++ let diff = repo.diff_tree_to_tree(Some(&a), Some(&b), Some(opts))?; +++ Ok(diff.deltas().len() > 0) +++} +++ +++impl Args { +++ fn min_parents(&self) -> usize { +++ if self.flag_no_min_parents { +++ return 0; +++ } +++ self.flag_min_parents +++ .unwrap_or(if self.flag_merges { 2 } else { 0 }) +++ } +++ +++ fn max_parents(&self) -> Option { +++ if self.flag_no_max_parents { +++ return None; +++ } +++ self.flag_max_parents +++ .or(if self.flag_no_merges { Some(1) } else { None }) +++ } +++} +++ +++fn main() { +++ let args = Args::parse(); +++ match run(&args) { +++ Ok(()) => {} +++ Err(e) => println!("error: {}", e), +++ } +++} diff --cc extra/git2/examples/ls-remote.rs index 0000000000,0000000000,0000000000..f88baaf906 new file mode 100644 --- /dev/null +++ b/extra/git2/examples/ls-remote.rs @@@@ -1,0 -1,0 -1,0 +1,51 @@@@ +++/* +++ * libgit2 "ls-remote" example +++ * +++ * Written by the libgit2 contributors +++ * +++ * To the extent possible under law, the author(s) have dedicated all copyright +++ * and related and neighboring rights to this software to the public domain +++ * worldwide. This software is distributed without any warranty. +++ * +++ * You should have received a copy of the CC0 Public Domain Dedication along +++ * with this software. If not, see +++ * . +++ */ +++ +++#![deny(warnings)] +++ +++use clap::Parser; +++use git2::{Direction, Repository}; +++ +++#[derive(Parser)] +++struct Args { +++ #[structopt(name = "remote")] +++ arg_remote: String, +++} +++ +++fn run(args: &Args) -> Result<(), git2::Error> { +++ let repo = Repository::open(".")?; +++ let remote = &args.arg_remote; +++ let mut remote = repo +++ .find_remote(remote) +++ .or_else(|_| repo.remote_anonymous(remote))?; +++ +++ // Connect to the remote and call the printing function for each of the +++ // remote references. +++ let connection = remote.connect_auth(Direction::Fetch, None, None)?; +++ +++ // Get the list of references on the remote and print out their name next to +++ // what they point to. +++ for head in connection.list()?.iter() { +++ println!("{}\t{}", head.oid(), head.name()); +++ } +++ Ok(()) +++} +++ +++fn main() { +++ let args = Args::parse(); +++ match run(&args) { +++ Ok(()) => {} +++ Err(e) => println!("error: {}", e), +++ } +++} diff --cc extra/git2/examples/pull.rs index 0000000000,0000000000,0000000000..27f461e546 new file mode 100644 --- /dev/null +++ b/extra/git2/examples/pull.rs @@@@ -1,0 -1,0 -1,0 +1,208 @@@@ +++/* +++ * libgit2 "pull" example - shows how to pull remote data into a local branch. +++ * +++ * Written by the libgit2 contributors +++ * +++ * To the extent possible under law, the author(s) have dedicated all copyright +++ * and related and neighboring rights to this software to the public domain +++ * worldwide. This software is distributed without any warranty. +++ * +++ * You should have received a copy of the CC0 Public Domain Dedication along +++ * with this software. If not, see +++ * . +++ */ +++ +++use clap::Parser; +++use git2::Repository; +++use std::io::{self, Write}; +++use std::str; +++ +++#[derive(Parser)] +++struct Args { +++ arg_remote: Option, +++ arg_branch: Option, +++} +++ +++fn do_fetch<'a>( +++ repo: &'a git2::Repository, +++ refs: &[&str], +++ remote: &'a mut git2::Remote, +++) -> Result, git2::Error> { +++ let mut cb = git2::RemoteCallbacks::new(); +++ +++ // Print out our transfer progress. +++ cb.transfer_progress(|stats| { +++ if stats.received_objects() == stats.total_objects() { +++ print!( +++ "Resolving deltas {}/{}\r", +++ stats.indexed_deltas(), +++ stats.total_deltas() +++ ); +++ } else if stats.total_objects() > 0 { +++ print!( +++ "Received {}/{} objects ({}) in {} bytes\r", +++ stats.received_objects(), +++ stats.total_objects(), +++ stats.indexed_objects(), +++ stats.received_bytes() +++ ); +++ } +++ io::stdout().flush().unwrap(); +++ true +++ }); +++ +++ let mut fo = git2::FetchOptions::new(); +++ fo.remote_callbacks(cb); +++ // Always fetch all tags. +++ // Perform a download and also update tips +++ fo.download_tags(git2::AutotagOption::All); +++ println!("Fetching {} for repo", remote.name().unwrap()); +++ remote.fetch(refs, Some(&mut fo), None)?; +++ +++ // If there are local objects (we got a thin pack), then tell the user +++ // how many objects we saved from having to cross the network. +++ let stats = remote.stats(); +++ if stats.local_objects() > 0 { +++ println!( +++ "\rReceived {}/{} objects in {} bytes (used {} local \ +++ objects)", +++ stats.indexed_objects(), +++ stats.total_objects(), +++ stats.received_bytes(), +++ stats.local_objects() +++ ); +++ } else { +++ println!( +++ "\rReceived {}/{} objects in {} bytes", +++ stats.indexed_objects(), +++ stats.total_objects(), +++ stats.received_bytes() +++ ); +++ } +++ +++ let fetch_head = repo.find_reference("FETCH_HEAD")?; +++ Ok(repo.reference_to_annotated_commit(&fetch_head)?) +++} +++ +++fn fast_forward( +++ repo: &Repository, +++ lb: &mut git2::Reference, +++ rc: &git2::AnnotatedCommit, +++) -> Result<(), git2::Error> { +++ let name = match lb.name() { +++ Some(s) => s.to_string(), +++ None => String::from_utf8_lossy(lb.name_bytes()).to_string(), +++ }; +++ let msg = format!("Fast-Forward: Setting {} to id: {}", name, rc.id()); +++ println!("{}", msg); +++ lb.set_target(rc.id(), &msg)?; +++ repo.set_head(&name)?; +++ repo.checkout_head(Some( +++ git2::build::CheckoutBuilder::default() +++ // For some reason the force is required to make the working directory actually get updated +++ // I suspect we should be adding some logic to handle dirty working directory states +++ // but this is just an example so maybe not. +++ .force(), +++ ))?; +++ Ok(()) +++} +++ +++fn normal_merge( +++ repo: &Repository, +++ local: &git2::AnnotatedCommit, +++ remote: &git2::AnnotatedCommit, +++) -> Result<(), git2::Error> { +++ let local_tree = repo.find_commit(local.id())?.tree()?; +++ let remote_tree = repo.find_commit(remote.id())?.tree()?; +++ let ancestor = repo +++ .find_commit(repo.merge_base(local.id(), remote.id())?)? +++ .tree()?; +++ let mut idx = repo.merge_trees(&ancestor, &local_tree, &remote_tree, None)?; +++ +++ if idx.has_conflicts() { +++ println!("Merge conflicts detected..."); +++ repo.checkout_index(Some(&mut idx), None)?; +++ return Ok(()); +++ } +++ let result_tree = repo.find_tree(idx.write_tree_to(repo)?)?; +++ // now create the merge commit +++ let msg = format!("Merge: {} into {}", remote.id(), local.id()); +++ let sig = repo.signature()?; +++ let local_commit = repo.find_commit(local.id())?; +++ let remote_commit = repo.find_commit(remote.id())?; +++ // Do our merge commit and set current branch head to that commit. +++ let _merge_commit = repo.commit( +++ Some("HEAD"), +++ &sig, +++ &sig, +++ &msg, +++ &result_tree, +++ &[&local_commit, &remote_commit], +++ )?; +++ // Set working tree to match head. +++ repo.checkout_head(None)?; +++ Ok(()) +++} +++ +++fn do_merge<'a>( +++ repo: &'a Repository, +++ remote_branch: &str, +++ fetch_commit: git2::AnnotatedCommit<'a>, +++) -> Result<(), git2::Error> { +++ // 1. do a merge analysis +++ let analysis = repo.merge_analysis(&[&fetch_commit])?; +++ +++ // 2. Do the appropriate merge +++ if analysis.0.is_fast_forward() { +++ println!("Doing a fast forward"); +++ // do a fast forward +++ let refname = format!("refs/heads/{}", remote_branch); +++ match repo.find_reference(&refname) { +++ Ok(mut r) => { +++ fast_forward(repo, &mut r, &fetch_commit)?; +++ } +++ Err(_) => { +++ // The branch doesn't exist so just set the reference to the +++ // commit directly. Usually this is because you are pulling +++ // into an empty repository. +++ repo.reference( +++ &refname, +++ fetch_commit.id(), +++ true, +++ &format!("Setting {} to {}", remote_branch, fetch_commit.id()), +++ )?; +++ repo.set_head(&refname)?; +++ repo.checkout_head(Some( +++ git2::build::CheckoutBuilder::default() +++ .allow_conflicts(true) +++ .conflict_style_merge(true) +++ .force(), +++ ))?; +++ } +++ }; +++ } else if analysis.0.is_normal() { +++ // do a normal merge +++ let head_commit = repo.reference_to_annotated_commit(&repo.head()?)?; +++ normal_merge(&repo, &head_commit, &fetch_commit)?; +++ } else { +++ println!("Nothing to do..."); +++ } +++ Ok(()) +++} +++ +++fn run(args: &Args) -> Result<(), git2::Error> { +++ let remote_name = args.arg_remote.as_ref().map(|s| &s[..]).unwrap_or("origin"); +++ let remote_branch = args.arg_branch.as_ref().map(|s| &s[..]).unwrap_or("master"); +++ let repo = Repository::open(".")?; +++ let mut remote = repo.find_remote(remote_name)?; +++ let fetch_commit = do_fetch(&repo, &[remote_branch], &mut remote)?; +++ do_merge(&repo, &remote_branch, fetch_commit) +++} +++ +++fn main() { +++ let args = Args::parse(); +++ match run(&args) { +++ Ok(()) => {} +++ Err(e) => println!("error: {}", e), +++ } +++} diff --cc extra/git2/examples/rev-list.rs index 0000000000,0000000000,0000000000..2eaed78e9a new file mode 100644 --- /dev/null +++ b/extra/git2/examples/rev-list.rs @@@@ -1,0 -1,0 -1,0 +1,105 @@@@ +++/* +++ * libgit2 "rev-list" example - shows how to transform a rev-spec into a list +++ * of commit ids +++ * +++ * Written by the libgit2 contributors +++ * +++ * To the extent possible under law, the author(s) have dedicated all copyright +++ * and related and neighboring rights to this software to the public domain +++ * worldwide. This software is distributed without any warranty. +++ * +++ * You should have received a copy of the CC0 Public Domain Dedication along +++ * with this software. If not, see +++ * . +++ */ +++ +++#![deny(warnings)] +++ +++use clap::Parser; +++use git2::{Error, Oid, Repository, Revwalk}; +++ +++#[derive(Parser)] +++struct Args { +++ #[structopt(name = "topo-order", long)] +++ /// sort commits in topological order +++ flag_topo_order: bool, +++ #[structopt(name = "date-order", long)] +++ /// sort commits in date order +++ flag_date_order: bool, +++ #[structopt(name = "reverse", long)] +++ /// sort commits in reverse +++ flag_reverse: bool, +++ #[structopt(name = "not")] +++ /// don't show +++ flag_not: Vec, +++ #[structopt(name = "spec", last = true)] +++ arg_spec: Vec, +++} +++ +++fn run(args: &Args) -> Result<(), git2::Error> { +++ let repo = Repository::open(".")?; +++ let mut revwalk = repo.revwalk()?; +++ +++ let base = if args.flag_reverse { +++ git2::Sort::REVERSE +++ } else { +++ git2::Sort::NONE +++ }; +++ revwalk.set_sorting( +++ base | if args.flag_topo_order { +++ git2::Sort::TOPOLOGICAL +++ } else if args.flag_date_order { +++ git2::Sort::TIME +++ } else { +++ git2::Sort::NONE +++ }, +++ )?; +++ +++ let specs = args +++ .flag_not +++ .iter() +++ .map(|s| (s, true)) +++ .chain(args.arg_spec.iter().map(|s| (s, false))) +++ .map(|(spec, hide)| { +++ if spec.starts_with('^') { +++ (&spec[1..], !hide) +++ } else { +++ (&spec[..], hide) +++ } +++ }); +++ for (spec, hide) in specs { +++ let id = if spec.contains("..") { +++ let revspec = repo.revparse(spec)?; +++ if revspec.mode().contains(git2::RevparseMode::MERGE_BASE) { +++ return Err(Error::from_str("merge bases not implemented")); +++ } +++ push(&mut revwalk, revspec.from().unwrap().id(), !hide)?; +++ revspec.to().unwrap().id() +++ } else { +++ repo.revparse_single(spec)?.id() +++ }; +++ push(&mut revwalk, id, hide)?; +++ } +++ +++ for id in revwalk { +++ let id = id?; +++ println!("{}", id); +++ } +++ Ok(()) +++} +++ +++fn push(revwalk: &mut Revwalk, id: Oid, hide: bool) -> Result<(), Error> { +++ if hide { +++ revwalk.hide(id) +++ } else { +++ revwalk.push(id) +++ } +++} +++ +++fn main() { +++ let args = Args::parse(); +++ match run(&args) { +++ Ok(()) => {} +++ Err(e) => println!("error: {}", e), +++ } +++} diff --cc extra/git2/examples/rev-parse.rs index 0000000000,0000000000,0000000000..8d3934ea8c new file mode 100644 --- /dev/null +++ b/extra/git2/examples/rev-parse.rs @@@@ -1,0 -1,0 -1,0 +1,60 @@@@ +++/* +++ * libgit2 "rev-parse" example - shows how to parse revspecs +++ * +++ * Written by the libgit2 contributors +++ * +++ * To the extent possible under law, the author(s) have dedicated all copyright +++ * and related and neighboring rights to this software to the public domain +++ * worldwide. This software is distributed without any warranty. +++ * +++ * You should have received a copy of the CC0 Public Domain Dedication along +++ * with this software. If not, see +++ * . +++ */ +++ +++#![deny(warnings)] +++ +++use clap::Parser; +++use git2::Repository; +++ +++#[derive(Parser)] +++struct Args { +++ #[structopt(name = "spec")] +++ arg_spec: String, +++ #[structopt(name = "dir", long = "git-dir")] +++ /// directory of the git repository to check +++ flag_git_dir: Option, +++} +++ +++fn run(args: &Args) -> Result<(), git2::Error> { +++ let path = args.flag_git_dir.as_ref().map(|s| &s[..]).unwrap_or("."); +++ let repo = Repository::open(path)?; +++ +++ let revspec = repo.revparse(&args.arg_spec)?; +++ +++ if revspec.mode().contains(git2::RevparseMode::SINGLE) { +++ println!("{}", revspec.from().unwrap().id()); +++ } else if revspec.mode().contains(git2::RevparseMode::RANGE) { +++ let to = revspec.to().unwrap(); +++ let from = revspec.from().unwrap(); +++ println!("{}", to.id()); +++ +++ if revspec.mode().contains(git2::RevparseMode::MERGE_BASE) { +++ let base = repo.merge_base(from.id(), to.id())?; +++ println!("{}", base); +++ } +++ +++ println!("^{}", from.id()); +++ } else { +++ return Err(git2::Error::from_str("invalid results from revparse")); +++ } +++ Ok(()) +++} +++ +++fn main() { +++ let args = Args::parse(); +++ match run(&args) { +++ Ok(()) => {} +++ Err(e) => println!("error: {}", e), +++ } +++} diff --cc extra/git2/examples/status.rs index 0000000000,0000000000,0000000000..0ed61711c8 new file mode 100644 --- /dev/null +++ b/extra/git2/examples/status.rs @@@@ -1,0 -1,0 -1,0 +1,441 @@@@ +++/* +++ * libgit2 "status" example - shows how to use the status APIs +++ * +++ * Written by the libgit2 contributors +++ * +++ * To the extent possible under law, the author(s) have dedicated all copyright +++ * and related and neighboring rights to this software to the public domain +++ * worldwide. This software is distributed without any warranty. +++ * +++ * You should have received a copy of the CC0 Public Domain Dedication along +++ * with this software. If not, see +++ * . +++ */ +++ +++#![deny(warnings)] +++ +++use clap::Parser; +++use git2::{Error, ErrorCode, Repository, StatusOptions, SubmoduleIgnore}; +++use std::str; +++use std::time::Duration; +++ +++#[derive(Parser)] +++struct Args { +++ arg_spec: Vec, +++ #[structopt(name = "long", long)] +++ /// show longer statuses (default) +++ _flag_long: bool, +++ /// show short statuses +++ #[structopt(name = "short", long)] +++ flag_short: bool, +++ #[structopt(name = "porcelain", long)] +++ /// ?? +++ flag_porcelain: bool, +++ #[structopt(name = "branch", short, long)] +++ /// show branch information +++ flag_branch: bool, +++ #[structopt(name = "z", short)] +++ /// ?? +++ flag_z: bool, +++ #[structopt(name = "ignored", long)] +++ /// show ignored files as well +++ flag_ignored: bool, +++ #[structopt(name = "opt-modules", long = "untracked-files")] +++ /// setting for showing untracked files [no|normal|all] +++ flag_untracked_files: Option, +++ #[structopt(name = "opt-files", long = "ignore-submodules")] +++ /// setting for ignoring submodules [all] +++ flag_ignore_submodules: Option, +++ #[structopt(name = "dir", long = "git-dir")] +++ /// git directory to analyze +++ flag_git_dir: Option, +++ #[structopt(name = "repeat", long)] +++ /// repeatedly show status, sleeping inbetween +++ flag_repeat: bool, +++ #[structopt(name = "list-submodules", long)] +++ /// show submodules +++ flag_list_submodules: bool, +++} +++ +++#[derive(Eq, PartialEq)] +++enum Format { +++ Long, +++ Short, +++ Porcelain, +++} +++ +++fn run(args: &Args) -> Result<(), Error> { +++ let path = args.flag_git_dir.clone().unwrap_or_else(|| ".".to_string()); +++ let repo = Repository::open(&path)?; +++ if repo.is_bare() { +++ return Err(Error::from_str("cannot report status on bare repository")); +++ } +++ +++ let mut opts = StatusOptions::new(); +++ opts.include_ignored(args.flag_ignored); +++ match args.flag_untracked_files.as_ref().map(|s| &s[..]) { +++ Some("no") => { +++ opts.include_untracked(false); +++ } +++ Some("normal") => { +++ opts.include_untracked(true); +++ } +++ Some("all") => { +++ opts.include_untracked(true).recurse_untracked_dirs(true); +++ } +++ Some(_) => return Err(Error::from_str("invalid untracked-files value")), +++ None => {} +++ } +++ match args.flag_ignore_submodules.as_ref().map(|s| &s[..]) { +++ Some("all") => { +++ opts.exclude_submodules(true); +++ } +++ Some(_) => return Err(Error::from_str("invalid ignore-submodules value")), +++ None => {} +++ } +++ opts.include_untracked(!args.flag_ignored); +++ for spec in &args.arg_spec { +++ opts.pathspec(spec); +++ } +++ +++ loop { +++ if args.flag_repeat { +++ println!("\u{1b}[H\u{1b}[2J"); +++ } +++ +++ let statuses = repo.statuses(Some(&mut opts))?; +++ +++ if args.flag_branch { +++ show_branch(&repo, &args.format())?; +++ } +++ if args.flag_list_submodules { +++ print_submodules(&repo)?; +++ } +++ +++ if args.format() == Format::Long { +++ print_long(&statuses); +++ } else { +++ print_short(&repo, &statuses); +++ } +++ +++ if args.flag_repeat { +++ std::thread::sleep(Duration::new(10, 0)); +++ } else { +++ return Ok(()); +++ } +++ } +++} +++ +++fn show_branch(repo: &Repository, format: &Format) -> Result<(), Error> { +++ let head = match repo.head() { +++ Ok(head) => Some(head), +++ Err(ref e) if e.code() == ErrorCode::UnbornBranch || e.code() == ErrorCode::NotFound => { +++ None +++ } +++ Err(e) => return Err(e), +++ }; +++ let head = head.as_ref().and_then(|h| h.shorthand()); +++ +++ if format == &Format::Long { +++ println!( +++ "# On branch {}", +++ head.unwrap_or("Not currently on any branch") +++ ); +++ } else { +++ println!("## {}", head.unwrap_or("HEAD (no branch)")); +++ } +++ Ok(()) +++} +++ +++fn print_submodules(repo: &Repository) -> Result<(), Error> { +++ let modules = repo.submodules()?; +++ println!("# Submodules"); +++ for sm in &modules { +++ println!( +++ "# - submodule '{}' at {}", +++ sm.name().unwrap(), +++ sm.path().display() +++ ); +++ } +++ Ok(()) +++} +++ +++// This function print out an output similar to git's status command in long +++// form, including the command-line hints. +++fn print_long(statuses: &git2::Statuses) { +++ let mut header = false; +++ let mut rm_in_workdir = false; +++ let mut changes_in_index = false; +++ let mut changed_in_workdir = false; +++ +++ // Print index changes +++ for entry in statuses +++ .iter() +++ .filter(|e| e.status() != git2::Status::CURRENT) +++ { +++ if entry.status().contains(git2::Status::WT_DELETED) { +++ rm_in_workdir = true; +++ } +++ let istatus = match entry.status() { +++ s if s.contains(git2::Status::INDEX_NEW) => "new file: ", +++ s if s.contains(git2::Status::INDEX_MODIFIED) => "modified: ", +++ s if s.contains(git2::Status::INDEX_DELETED) => "deleted: ", +++ s if s.contains(git2::Status::INDEX_RENAMED) => "renamed: ", +++ s if s.contains(git2::Status::INDEX_TYPECHANGE) => "typechange:", +++ _ => continue, +++ }; +++ if !header { +++ println!( +++ "\ +++# Changes to be committed: +++# (use \"git reset HEAD ...\" to unstage) +++#" +++ ); +++ header = true; +++ } +++ +++ let old_path = entry.head_to_index().unwrap().old_file().path(); +++ let new_path = entry.head_to_index().unwrap().new_file().path(); +++ match (old_path, new_path) { +++ (Some(old), Some(new)) if old != new => { +++ println!("#\t{} {} -> {}", istatus, old.display(), new.display()); +++ } +++ (old, new) => { +++ println!("#\t{} {}", istatus, old.or(new).unwrap().display()); +++ } +++ } +++ } +++ +++ if header { +++ changes_in_index = true; +++ println!("#"); +++ } +++ header = false; +++ +++ // Print workdir changes to tracked files +++ for entry in statuses.iter() { +++ // With `Status::OPT_INCLUDE_UNMODIFIED` (not used in this example) +++ // `index_to_workdir` may not be `None` even if there are no differences, +++ // in which case it will be a `Delta::Unmodified`. +++ if entry.status() == git2::Status::CURRENT || entry.index_to_workdir().is_none() { +++ continue; +++ } +++ +++ let istatus = match entry.status() { +++ s if s.contains(git2::Status::WT_MODIFIED) => "modified: ", +++ s if s.contains(git2::Status::WT_DELETED) => "deleted: ", +++ s if s.contains(git2::Status::WT_RENAMED) => "renamed: ", +++ s if s.contains(git2::Status::WT_TYPECHANGE) => "typechange:", +++ _ => continue, +++ }; +++ +++ if !header { +++ println!( +++ "\ +++# Changes not staged for commit: +++# (use \"git add{} ...\" to update what will be committed) +++# (use \"git checkout -- ...\" to discard changes in working directory) +++#\ +++ ", +++ if rm_in_workdir { "/rm" } else { "" } +++ ); +++ header = true; +++ } +++ +++ let old_path = entry.index_to_workdir().unwrap().old_file().path(); +++ let new_path = entry.index_to_workdir().unwrap().new_file().path(); +++ match (old_path, new_path) { +++ (Some(old), Some(new)) if old != new => { +++ println!("#\t{} {} -> {}", istatus, old.display(), new.display()); +++ } +++ (old, new) => { +++ println!("#\t{} {}", istatus, old.or(new).unwrap().display()); +++ } +++ } +++ } +++ +++ if header { +++ changed_in_workdir = true; +++ println!("#"); +++ } +++ header = false; +++ +++ // Print untracked files +++ for entry in statuses +++ .iter() +++ .filter(|e| e.status() == git2::Status::WT_NEW) +++ { +++ if !header { +++ println!( +++ "\ +++# Untracked files +++# (use \"git add ...\" to include in what will be committed) +++#" +++ ); +++ header = true; +++ } +++ let file = entry.index_to_workdir().unwrap().old_file().path().unwrap(); +++ println!("#\t{}", file.display()); +++ } +++ header = false; +++ +++ // Print ignored files +++ for entry in statuses +++ .iter() +++ .filter(|e| e.status() == git2::Status::IGNORED) +++ { +++ if !header { +++ println!( +++ "\ +++# Ignored files +++# (use \"git add -f ...\" to include in what will be committed) +++#" +++ ); +++ header = true; +++ } +++ let file = entry.index_to_workdir().unwrap().old_file().path().unwrap(); +++ println!("#\t{}", file.display()); +++ } +++ +++ if !changes_in_index && changed_in_workdir { +++ println!( +++ "no changes added to commit (use \"git add\" and/or \ +++ \"git commit -a\")" +++ ); +++ } +++} +++ +++// This version of the output prefixes each path with two status columns and +++// shows submodule status information. +++fn print_short(repo: &Repository, statuses: &git2::Statuses) { +++ for entry in statuses +++ .iter() +++ .filter(|e| e.status() != git2::Status::CURRENT) +++ { +++ let mut istatus = match entry.status() { +++ s if s.contains(git2::Status::INDEX_NEW) => 'A', +++ s if s.contains(git2::Status::INDEX_MODIFIED) => 'M', +++ s if s.contains(git2::Status::INDEX_DELETED) => 'D', +++ s if s.contains(git2::Status::INDEX_RENAMED) => 'R', +++ s if s.contains(git2::Status::INDEX_TYPECHANGE) => 'T', +++ _ => ' ', +++ }; +++ let mut wstatus = match entry.status() { +++ s if s.contains(git2::Status::WT_NEW) => { +++ if istatus == ' ' { +++ istatus = '?'; +++ } +++ '?' +++ } +++ s if s.contains(git2::Status::WT_MODIFIED) => 'M', +++ s if s.contains(git2::Status::WT_DELETED) => 'D', +++ s if s.contains(git2::Status::WT_RENAMED) => 'R', +++ s if s.contains(git2::Status::WT_TYPECHANGE) => 'T', +++ _ => ' ', +++ }; +++ +++ if entry.status().contains(git2::Status::IGNORED) { +++ istatus = '!'; +++ wstatus = '!'; +++ } +++ if istatus == '?' && wstatus == '?' { +++ continue; +++ } +++ let mut extra = ""; +++ +++ // A commit in a tree is how submodules are stored, so let's go take a +++ // look at its status. +++ // +++ // TODO: check for GIT_FILEMODE_COMMIT +++ let status = entry.index_to_workdir().and_then(|diff| { +++ let ignore = SubmoduleIgnore::Unspecified; +++ diff.new_file() +++ .path_bytes() +++ .and_then(|s| str::from_utf8(s).ok()) +++ .and_then(|name| repo.submodule_status(name, ignore).ok()) +++ }); +++ if let Some(status) = status { +++ if status.contains(git2::SubmoduleStatus::WD_MODIFIED) { +++ extra = " (new commits)"; +++ } else if status.contains(git2::SubmoduleStatus::WD_INDEX_MODIFIED) +++ || status.contains(git2::SubmoduleStatus::WD_WD_MODIFIED) +++ { +++ extra = " (modified content)"; +++ } else if status.contains(git2::SubmoduleStatus::WD_UNTRACKED) { +++ extra = " (untracked content)"; +++ } +++ } +++ +++ let (mut a, mut b, mut c) = (None, None, None); +++ if let Some(diff) = entry.head_to_index() { +++ a = diff.old_file().path(); +++ b = diff.new_file().path(); +++ } +++ if let Some(diff) = entry.index_to_workdir() { +++ a = a.or_else(|| diff.old_file().path()); +++ b = b.or_else(|| diff.old_file().path()); +++ c = diff.new_file().path(); +++ } +++ +++ match (istatus, wstatus) { +++ ('R', 'R') => println!( +++ "RR {} {} {}{}", +++ a.unwrap().display(), +++ b.unwrap().display(), +++ c.unwrap().display(), +++ extra +++ ), +++ ('R', w) => println!( +++ "R{} {} {}{}", +++ w, +++ a.unwrap().display(), +++ b.unwrap().display(), +++ extra +++ ), +++ (i, 'R') => println!( +++ "{}R {} {}{}", +++ i, +++ a.unwrap().display(), +++ c.unwrap().display(), +++ extra +++ ), +++ (i, w) => println!("{}{} {}{}", i, w, a.unwrap().display(), extra), +++ } +++ } +++ +++ for entry in statuses +++ .iter() +++ .filter(|e| e.status() == git2::Status::WT_NEW) +++ { +++ println!( +++ "?? {}", +++ entry +++ .index_to_workdir() +++ .unwrap() +++ .old_file() +++ .path() +++ .unwrap() +++ .display() +++ ); +++ } +++} +++ +++impl Args { +++ fn format(&self) -> Format { +++ if self.flag_short { +++ Format::Short +++ } else if self.flag_porcelain || self.flag_z { +++ Format::Porcelain +++ } else { +++ Format::Long +++ } +++ } +++} +++ +++fn main() { +++ let args = Args::parse(); +++ match run(&args) { +++ Ok(()) => {} +++ Err(e) => println!("error: {}", e), +++ } +++} diff --cc extra/git2/examples/tag.rs index 0000000000,0000000000,0000000000..5d2af02063 new file mode 100644 --- /dev/null +++ b/extra/git2/examples/tag.rs @@@@ -1,0 -1,0 -1,0 +1,127 @@@@ +++/* +++ * libgit2 "tag" example - shows how to list, create and delete tags +++ * +++ * Written by the libgit2 contributors +++ * +++ * To the extent possible under law, the author(s) have dedicated all copyright +++ * and related and neighboring rights to this software to the public domain +++ * worldwide. This software is distributed without any warranty. +++ * +++ * You should have received a copy of the CC0 Public Domain Dedication along +++ * with this software. If not, see +++ * . +++ */ +++ +++#![deny(warnings)] +++ +++use clap::Parser; +++use git2::{Commit, Error, Repository, Tag}; +++use std::str; +++ +++#[derive(Parser)] +++struct Args { +++ arg_tagname: Option, +++ arg_object: Option, +++ arg_pattern: Option, +++ #[structopt(name = "n", short)] +++ /// specify number of lines from the annotation to print +++ flag_n: Option, +++ #[structopt(name = "force", short, long)] +++ /// replace an existing tag with the given name +++ flag_force: bool, +++ #[structopt(name = "list", short, long)] +++ /// list tags with names matching the pattern given +++ flag_list: bool, +++ #[structopt(name = "tag", short, long = "delete")] +++ /// delete the tag specified +++ flag_delete: Option, +++ #[structopt(name = "msg", short, long = "message")] +++ /// message for a new tag +++ flag_message: Option, +++} +++ +++fn run(args: &Args) -> Result<(), Error> { +++ let repo = Repository::open(".")?; +++ +++ if let Some(ref name) = args.arg_tagname { +++ let target = args.arg_object.as_ref().map(|s| &s[..]).unwrap_or("HEAD"); +++ let obj = repo.revparse_single(target)?; +++ +++ if let Some(ref message) = args.flag_message { +++ let sig = repo.signature()?; +++ repo.tag(name, &obj, &sig, message, args.flag_force)?; +++ } else { +++ repo.tag_lightweight(name, &obj, args.flag_force)?; +++ } +++ } else if let Some(ref name) = args.flag_delete { +++ let obj = repo.revparse_single(name)?; +++ let id = obj.short_id()?; +++ repo.tag_delete(name)?; +++ println!( +++ "Deleted tag '{}' (was {})", +++ name, +++ str::from_utf8(&*id).unwrap() +++ ); +++ } else if args.flag_list { +++ let pattern = args.arg_pattern.as_ref().map(|s| &s[..]).unwrap_or("*"); +++ for name in repo.tag_names(Some(pattern))?.iter() { +++ let name = name.unwrap(); +++ let obj = repo.revparse_single(name)?; +++ +++ if let Some(tag) = obj.as_tag() { +++ print_tag(tag, args); +++ } else if let Some(commit) = obj.as_commit() { +++ print_commit(commit, name, args); +++ } else { +++ print_name(name); +++ } +++ } +++ } +++ Ok(()) +++} +++ +++fn print_tag(tag: &Tag, args: &Args) { +++ print!("{:<16}", tag.name().unwrap()); +++ if args.flag_n.is_some() { +++ print_list_lines(tag.message(), args); +++ } else { +++ println!(); +++ } +++} +++ +++fn print_commit(commit: &Commit, name: &str, args: &Args) { +++ print!("{:<16}", name); +++ if args.flag_n.is_some() { +++ print_list_lines(commit.message(), args); +++ } else { +++ println!(); +++ } +++} +++ +++fn print_name(name: &str) { +++ println!("{}", name); +++} +++ +++fn print_list_lines(message: Option<&str>, args: &Args) { +++ let message = match message { +++ Some(s) => s, +++ None => return, +++ }; +++ let mut lines = message.lines().filter(|l| !l.trim().is_empty()); +++ if let Some(first) = lines.next() { +++ print!("{}", first); +++ } +++ println!(); +++ +++ for line in lines.take(args.flag_n.unwrap_or(0) as usize) { +++ print!(" {}", line); +++ } +++} +++ +++fn main() { +++ let args = Args::parse(); +++ match run(&args) { +++ Ok(()) => {} +++ Err(e) => println!("error: {}", e), +++ } +++} diff --cc extra/git2/src/apply.rs index 0000000000,0000000000,0000000000..34dc811a01 new file mode 100644 --- /dev/null +++ b/extra/git2/src/apply.rs @@@@ -1,0 -1,0 -1,0 +1,208 @@@@ +++//! git_apply support +++//! see original: +++ +++use crate::{panic, raw, util::Binding, DiffDelta, DiffHunk}; +++use libc::c_int; +++use std::{ffi::c_void, mem}; +++ +++/// Possible application locations for git_apply +++/// see +++#[derive(Copy, Clone, Debug)] +++pub enum ApplyLocation { +++ /// Apply the patch to the workdir +++ WorkDir, +++ /// Apply the patch to the index +++ Index, +++ /// Apply the patch to both the working directory and the index +++ Both, +++} +++ +++impl Binding for ApplyLocation { +++ type Raw = raw::git_apply_location_t; +++ unsafe fn from_raw(raw: raw::git_apply_location_t) -> Self { +++ match raw { +++ raw::GIT_APPLY_LOCATION_WORKDIR => Self::WorkDir, +++ raw::GIT_APPLY_LOCATION_INDEX => Self::Index, +++ raw::GIT_APPLY_LOCATION_BOTH => Self::Both, +++ _ => panic!("Unknown git diff binary kind"), +++ } +++ } +++ fn raw(&self) -> raw::git_apply_location_t { +++ match *self { +++ Self::WorkDir => raw::GIT_APPLY_LOCATION_WORKDIR, +++ Self::Index => raw::GIT_APPLY_LOCATION_INDEX, +++ Self::Both => raw::GIT_APPLY_LOCATION_BOTH, +++ } +++ } +++} +++ +++/// Options to specify when applying a diff +++pub struct ApplyOptions<'cb> { +++ raw: raw::git_apply_options, +++ hunk_cb: Option>>, +++ delta_cb: Option>>, +++} +++ +++type HunkCB<'a> = dyn FnMut(Option>) -> bool + 'a; +++type DeltaCB<'a> = dyn FnMut(Option>) -> bool + 'a; +++ +++extern "C" fn delta_cb_c(delta: *const raw::git_diff_delta, data: *mut c_void) -> c_int { +++ panic::wrap(|| unsafe { +++ let delta = Binding::from_raw_opt(delta as *mut _); +++ +++ let payload = &mut *(data as *mut ApplyOptions<'_>); +++ let callback = match payload.delta_cb { +++ Some(ref mut c) => c, +++ None => return -1, +++ }; +++ +++ let apply = callback(delta); +++ if apply { +++ 0 +++ } else { +++ 1 +++ } +++ }) +++ .unwrap_or(-1) +++} +++ +++extern "C" fn hunk_cb_c(hunk: *const raw::git_diff_hunk, data: *mut c_void) -> c_int { +++ panic::wrap(|| unsafe { +++ let hunk = Binding::from_raw_opt(hunk); +++ +++ let payload = &mut *(data as *mut ApplyOptions<'_>); +++ let callback = match payload.hunk_cb { +++ Some(ref mut c) => c, +++ None => return -1, +++ }; +++ +++ let apply = callback(hunk); +++ if apply { +++ 0 +++ } else { +++ 1 +++ } +++ }) +++ .unwrap_or(-1) +++} +++ +++impl<'cb> ApplyOptions<'cb> { +++ /// Creates a new set of empty options (zeroed). +++ pub fn new() -> Self { +++ let mut opts = Self { +++ raw: unsafe { mem::zeroed() }, +++ hunk_cb: None, +++ delta_cb: None, +++ }; +++ assert_eq!( +++ unsafe { raw::git_apply_options_init(&mut opts.raw, raw::GIT_APPLY_OPTIONS_VERSION) }, +++ 0 +++ ); +++ opts +++ } +++ +++ fn flag(&mut self, opt: raw::git_apply_flags_t, val: bool) -> &mut Self { +++ let opt = opt as u32; +++ if val { +++ self.raw.flags |= opt; +++ } else { +++ self.raw.flags &= !opt; +++ } +++ self +++ } +++ +++ /// Don't actually make changes, just test that the patch applies. +++ pub fn check(&mut self, check: bool) -> &mut Self { +++ self.flag(raw::GIT_APPLY_CHECK, check) +++ } +++ +++ /// When applying a patch, callback that will be made per hunk. +++ pub fn hunk_callback(&mut self, cb: F) -> &mut Self +++ where +++ F: FnMut(Option>) -> bool + 'cb, +++ { +++ self.hunk_cb = Some(Box::new(cb) as Box>); +++ +++ self.raw.hunk_cb = Some(hunk_cb_c); +++ self.raw.payload = self as *mut _ as *mut _; +++ +++ self +++ } +++ +++ /// When applying a patch, callback that will be made per delta (file). +++ pub fn delta_callback(&mut self, cb: F) -> &mut Self +++ where +++ F: FnMut(Option>) -> bool + 'cb, +++ { +++ self.delta_cb = Some(Box::new(cb) as Box>); +++ +++ self.raw.delta_cb = Some(delta_cb_c); +++ self.raw.payload = self as *mut _ as *mut _; +++ +++ self +++ } +++ +++ /// Pointer to a raw git_stash_apply_options +++ pub unsafe fn raw(&mut self) -> *const raw::git_apply_options { +++ &self.raw as *const _ +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use super::*; +++ use std::{fs::File, io::Write, path::Path}; +++ +++ #[test] +++ fn smoke_test() { +++ let (_td, repo) = crate::test::repo_init(); +++ let diff = t!(repo.diff_tree_to_workdir(None, None)); +++ let mut count_hunks = 0; +++ let mut count_delta = 0; +++ { +++ let mut opts = ApplyOptions::new(); +++ opts.hunk_callback(|_hunk| { +++ count_hunks += 1; +++ true +++ }); +++ opts.delta_callback(|_delta| { +++ count_delta += 1; +++ true +++ }); +++ t!(repo.apply(&diff, ApplyLocation::Both, Some(&mut opts))); +++ } +++ assert_eq!(count_hunks, 0); +++ assert_eq!(count_delta, 0); +++ } +++ +++ #[test] +++ fn apply_hunks_and_delta() { +++ let file_path = Path::new("foo.txt"); +++ let (td, repo) = crate::test::repo_init(); +++ // create new file +++ t!(t!(File::create(&td.path().join(file_path))).write_all(b"bar")); +++ // stage the new file +++ t!(t!(repo.index()).add_path(file_path)); +++ // now change workdir version +++ t!(t!(File::create(&td.path().join(file_path))).write_all(b"foo\nbar")); +++ +++ let diff = t!(repo.diff_index_to_workdir(None, None)); +++ assert_eq!(diff.deltas().len(), 1); +++ let mut count_hunks = 0; +++ let mut count_delta = 0; +++ { +++ let mut opts = ApplyOptions::new(); +++ opts.hunk_callback(|_hunk| { +++ count_hunks += 1; +++ true +++ }); +++ opts.delta_callback(|_delta| { +++ count_delta += 1; +++ true +++ }); +++ t!(repo.apply(&diff, ApplyLocation::Index, Some(&mut opts))); +++ } +++ assert_eq!(count_delta, 1); +++ assert_eq!(count_hunks, 1); +++ } +++} diff --cc extra/git2/src/attr.rs index 0000000000,0000000000,0000000000..33b1d2d4af new file mode 100644 --- /dev/null +++ b/extra/git2/src/attr.rs @@@@ -1,0 -1,0 -1,0 +1,175 @@@@ +++use crate::raw; +++use std::ptr; +++use std::str; +++ +++/// All possible states of an attribute. +++/// +++/// This enum is used to interpret the value returned by +++/// [`Repository::get_attr`](crate::Repository::get_attr) and +++/// [`Repository::get_attr_bytes`](crate::Repository::get_attr_bytes). +++#[derive(Debug, Clone, Copy, Eq)] +++pub enum AttrValue<'string> { +++ /// The attribute is set to true. +++ True, +++ /// The attribute is unset (set to false). +++ False, +++ /// The attribute is set to a [valid UTF-8 string](prim@str). +++ String(&'string str), +++ /// The attribute is set to a string that might not be [valid UTF-8](prim@str). +++ Bytes(&'string [u8]), +++ /// The attribute is not specified. +++ Unspecified, +++} +++ +++macro_rules! from_value { +++ ($value:expr => $string:expr) => { +++ match unsafe { raw::git_attr_value($value.map_or(ptr::null(), |v| v.as_ptr().cast())) } { +++ raw::GIT_ATTR_VALUE_TRUE => Self::True, +++ raw::GIT_ATTR_VALUE_FALSE => Self::False, +++ raw::GIT_ATTR_VALUE_STRING => $string, +++ raw::GIT_ATTR_VALUE_UNSPECIFIED => Self::Unspecified, +++ _ => unreachable!(), +++ } +++ }; +++} +++ +++impl<'string> AttrValue<'string> { +++ /// Returns the state of an attribute by inspecting its [value](crate::Repository::get_attr) +++ /// by a [string](prim@str). +++ /// +++ /// This function always returns [`AttrValue::String`] and never returns [`AttrValue::Bytes`] +++ /// when the attribute is set to a string. +++ pub fn from_string(value: Option<&'string str>) -> Self { +++ from_value!(value => Self::String(value.unwrap())) +++ } +++ +++ /// Returns the state of an attribute by inspecting its [value](crate::Repository::get_attr_bytes) +++ /// by a [byte](u8) [slice]. +++ /// +++ /// This function will perform UTF-8 validation when the attribute is set to a string, returns +++ /// [`AttrValue::String`] if it's valid UTF-8 and [`AttrValue::Bytes`] otherwise. +++ pub fn from_bytes(value: Option<&'string [u8]>) -> Self { +++ let mut value = Self::always_bytes(value); +++ if let Self::Bytes(bytes) = value { +++ if let Ok(string) = str::from_utf8(bytes) { +++ value = Self::String(string); +++ } +++ } +++ value +++ } +++ +++ /// Returns the state of an attribute just like [`AttrValue::from_bytes`], but skips UTF-8 +++ /// validation and always returns [`AttrValue::Bytes`] when it's set to a string. +++ pub fn always_bytes(value: Option<&'string [u8]>) -> Self { +++ from_value!(value => Self::Bytes(value.unwrap())) +++ } +++} +++ +++/// Compare two [`AttrValue`]s. +++/// +++/// Note that this implementation does not differentiate between [`AttrValue::String`] and +++/// [`AttrValue::Bytes`]. +++impl PartialEq for AttrValue<'_> { +++ fn eq(&self, other: &AttrValue<'_>) -> bool { +++ match (self, other) { +++ (Self::True, AttrValue::True) +++ | (Self::False, AttrValue::False) +++ | (Self::Unspecified, AttrValue::Unspecified) => true, +++ (AttrValue::String(string), AttrValue::Bytes(bytes)) +++ | (AttrValue::Bytes(bytes), AttrValue::String(string)) => string.as_bytes() == *bytes, +++ (AttrValue::String(left), AttrValue::String(right)) => left == right, +++ (AttrValue::Bytes(left), AttrValue::Bytes(right)) => left == right, +++ _ => false, +++ } +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use super::AttrValue; +++ +++ macro_rules! test_attr_value { +++ ($function:ident, $variant:ident) => { +++ const ATTR_TRUE: &str = "[internal]__TRUE__"; +++ const ATTR_FALSE: &str = "[internal]__FALSE__"; +++ const ATTR_UNSET: &str = "[internal]__UNSET__"; +++ let as_bytes = AsRef::<[u8]>::as_ref; +++ // Use `matches!` here since the `PartialEq` implementation does not differentiate +++ // between `String` and `Bytes`. +++ assert!(matches!( +++ AttrValue::$function(Some(ATTR_TRUE.as_ref())), +++ AttrValue::$variant(s) if as_bytes(s) == ATTR_TRUE.as_bytes() +++ )); +++ assert!(matches!( +++ AttrValue::$function(Some(ATTR_FALSE.as_ref())), +++ AttrValue::$variant(s) if as_bytes(s) == ATTR_FALSE.as_bytes() +++ )); +++ assert!(matches!( +++ AttrValue::$function(Some(ATTR_UNSET.as_ref())), +++ AttrValue::$variant(s) if as_bytes(s) == ATTR_UNSET.as_bytes() +++ )); +++ assert!(matches!( +++ AttrValue::$function(Some("foo".as_ref())), +++ AttrValue::$variant(s) if as_bytes(s) == b"foo" +++ )); +++ assert!(matches!( +++ AttrValue::$function(Some("bar".as_ref())), +++ AttrValue::$variant(s) if as_bytes(s) == b"bar" +++ )); +++ assert_eq!(AttrValue::$function(None), AttrValue::Unspecified); +++ }; +++ } +++ +++ #[test] +++ fn attr_value_from_string() { +++ test_attr_value!(from_string, String); +++ } +++ +++ #[test] +++ fn attr_value_from_bytes() { +++ test_attr_value!(from_bytes, String); +++ assert!(matches!( +++ AttrValue::from_bytes(Some(&[0xff])), +++ AttrValue::Bytes(&[0xff]) +++ )); +++ assert!(matches!( +++ AttrValue::from_bytes(Some(b"\xffoobar")), +++ AttrValue::Bytes(b"\xffoobar") +++ )); +++ } +++ +++ #[test] +++ fn attr_value_always_bytes() { +++ test_attr_value!(always_bytes, Bytes); +++ assert!(matches!( +++ AttrValue::always_bytes(Some(&[0xff; 2])), +++ AttrValue::Bytes(&[0xff, 0xff]) +++ )); +++ assert!(matches!( +++ AttrValue::always_bytes(Some(b"\xffoo")), +++ AttrValue::Bytes(b"\xffoo") +++ )); +++ } +++ +++ #[test] +++ fn attr_value_partial_eq() { +++ assert_eq!(AttrValue::True, AttrValue::True); +++ assert_eq!(AttrValue::False, AttrValue::False); +++ assert_eq!(AttrValue::String("foo"), AttrValue::String("foo")); +++ assert_eq!(AttrValue::Bytes(b"foo"), AttrValue::Bytes(b"foo")); +++ assert_eq!(AttrValue::String("bar"), AttrValue::Bytes(b"bar")); +++ assert_eq!(AttrValue::Bytes(b"bar"), AttrValue::String("bar")); +++ assert_eq!(AttrValue::Unspecified, AttrValue::Unspecified); +++ assert_ne!(AttrValue::True, AttrValue::False); +++ assert_ne!(AttrValue::False, AttrValue::Unspecified); +++ assert_ne!(AttrValue::Unspecified, AttrValue::True); +++ assert_ne!(AttrValue::True, AttrValue::String("true")); +++ assert_ne!(AttrValue::Unspecified, AttrValue::Bytes(b"unspecified")); +++ assert_ne!(AttrValue::Bytes(b"false"), AttrValue::False); +++ assert_ne!(AttrValue::String("unspecified"), AttrValue::Unspecified); +++ assert_ne!(AttrValue::String("foo"), AttrValue::String("bar")); +++ assert_ne!(AttrValue::Bytes(b"foo"), AttrValue::Bytes(b"bar")); +++ assert_ne!(AttrValue::String("foo"), AttrValue::Bytes(b"bar")); +++ assert_ne!(AttrValue::Bytes(b"foo"), AttrValue::String("bar")); +++ } +++} diff --cc extra/git2/src/blame.rs index 0000000000,0000000000,0000000000..4bf41fed1e new file mode 100644 --- /dev/null +++ b/extra/git2/src/blame.rs @@@@ -1,0 -1,0 -1,0 +1,379 @@@@ +++use crate::util::{self, Binding}; +++use crate::{raw, signature, Error, Oid, Repository, Signature}; +++use libc::c_char; +++use std::iter::FusedIterator; +++use std::mem; +++use std::ops::Range; +++use std::path::Path; +++use std::{marker, ptr}; +++ +++/// Opaque structure to hold blame results. +++pub struct Blame<'repo> { +++ raw: *mut raw::git_blame, +++ _marker: marker::PhantomData<&'repo Repository>, +++} +++ +++/// Structure that represents a blame hunk. +++pub struct BlameHunk<'blame> { +++ raw: *mut raw::git_blame_hunk, +++ _marker: marker::PhantomData<&'blame raw::git_blame>, +++} +++ +++/// Blame options +++pub struct BlameOptions { +++ raw: raw::git_blame_options, +++} +++ +++/// An iterator over the hunks in a blame. +++pub struct BlameIter<'blame> { +++ range: Range, +++ blame: &'blame Blame<'blame>, +++} +++ +++impl<'repo> Blame<'repo> { +++ /// Get blame data for a file that has been modified in memory. +++ /// +++ /// Lines that differ between the buffer and the committed version are +++ /// marked as having a zero OID for their final_commit_id. +++ pub fn blame_buffer(&self, buffer: &[u8]) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ +++ unsafe { +++ try_call!(raw::git_blame_buffer( +++ &mut raw, +++ self.raw, +++ buffer.as_ptr() as *const c_char, +++ buffer.len() +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Gets the number of hunks that exist in the blame structure. +++ pub fn len(&self) -> usize { +++ unsafe { raw::git_blame_get_hunk_count(self.raw) as usize } +++ } +++ +++ /// Return `true` is there is no hunk in the blame structure. +++ pub fn is_empty(&self) -> bool { +++ self.len() == 0 +++ } +++ +++ /// Gets the blame hunk at the given index. +++ pub fn get_index(&self, index: usize) -> Option> { +++ unsafe { +++ let ptr = raw::git_blame_get_hunk_byindex(self.raw(), index as u32); +++ if ptr.is_null() { +++ None +++ } else { +++ Some(BlameHunk::from_raw_const(ptr)) +++ } +++ } +++ } +++ +++ /// Gets the hunk that relates to the given line number in the newest +++ /// commit. +++ pub fn get_line(&self, lineno: usize) -> Option> { +++ unsafe { +++ let ptr = raw::git_blame_get_hunk_byline(self.raw(), lineno); +++ if ptr.is_null() { +++ None +++ } else { +++ Some(BlameHunk::from_raw_const(ptr)) +++ } +++ } +++ } +++ +++ /// Returns an iterator over the hunks in this blame. +++ pub fn iter(&self) -> BlameIter<'_> { +++ BlameIter { +++ range: 0..self.len(), +++ blame: self, +++ } +++ } +++} +++ +++impl<'blame> BlameHunk<'blame> { +++ unsafe fn from_raw_const(raw: *const raw::git_blame_hunk) -> BlameHunk<'blame> { +++ BlameHunk { +++ raw: raw as *mut raw::git_blame_hunk, +++ _marker: marker::PhantomData, +++ } +++ } +++ +++ /// Returns OID of the commit where this line was last changed +++ pub fn final_commit_id(&self) -> Oid { +++ unsafe { Oid::from_raw(&(*self.raw).final_commit_id) } +++ } +++ +++ /// Returns signature of the commit. +++ pub fn final_signature(&self) -> Signature<'_> { +++ unsafe { signature::from_raw_const(self, (*self.raw).final_signature) } +++ } +++ +++ /// Returns line number where this hunk begins. +++ /// +++ /// Note that the start line is counting from 1. +++ pub fn final_start_line(&self) -> usize { +++ unsafe { (*self.raw).final_start_line_number } +++ } +++ +++ /// Returns the OID of the commit where this hunk was found. +++ /// +++ /// This will usually be the same as `final_commit_id`, +++ /// except when `BlameOptions::track_copies_any_commit_copies` has been +++ /// turned on +++ pub fn orig_commit_id(&self) -> Oid { +++ unsafe { Oid::from_raw(&(*self.raw).orig_commit_id) } +++ } +++ +++ /// Returns signature of the commit. +++ pub fn orig_signature(&self) -> Signature<'_> { +++ unsafe { signature::from_raw_const(self, (*self.raw).orig_signature) } +++ } +++ +++ /// Returns line number where this hunk begins. +++ /// +++ /// Note that the start line is counting from 1. +++ pub fn orig_start_line(&self) -> usize { +++ unsafe { (*self.raw).orig_start_line_number } +++ } +++ +++ /// Returns path to the file where this hunk originated. +++ /// +++ /// Note: `None` could be returned for non-unicode paths on Windows. +++ pub fn path(&self) -> Option<&Path> { +++ unsafe { +++ if let Some(bytes) = crate::opt_bytes(self, (*self.raw).orig_path) { +++ Some(util::bytes2path(bytes)) +++ } else { +++ None +++ } +++ } +++ } +++ +++ /// Tests whether this hunk has been tracked to a boundary commit +++ /// (the root, or the commit specified in git_blame_options.oldest_commit). +++ pub fn is_boundary(&self) -> bool { +++ unsafe { (*self.raw).boundary == 1 } +++ } +++ +++ /// Returns number of lines in this hunk. +++ pub fn lines_in_hunk(&self) -> usize { +++ unsafe { (*self.raw).lines_in_hunk as usize } +++ } +++} +++ +++impl Default for BlameOptions { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl BlameOptions { +++ /// Initialize options +++ pub fn new() -> BlameOptions { +++ unsafe { +++ let mut raw: raw::git_blame_options = mem::zeroed(); +++ assert_eq!( +++ raw::git_blame_init_options(&mut raw, raw::GIT_BLAME_OPTIONS_VERSION), +++ 0 +++ ); +++ +++ Binding::from_raw(&raw as *const _ as *mut _) +++ } +++ } +++ +++ fn flag(&mut self, opt: u32, val: bool) -> &mut BlameOptions { +++ if val { +++ self.raw.flags |= opt; +++ } else { +++ self.raw.flags &= !opt; +++ } +++ self +++ } +++ +++ /// Track lines that have moved within a file. +++ pub fn track_copies_same_file(&mut self, opt: bool) -> &mut BlameOptions { +++ self.flag(raw::GIT_BLAME_TRACK_COPIES_SAME_FILE, opt) +++ } +++ +++ /// Track lines that have moved across files in the same commit. +++ pub fn track_copies_same_commit_moves(&mut self, opt: bool) -> &mut BlameOptions { +++ self.flag(raw::GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES, opt) +++ } +++ +++ /// Track lines that have been copied from another file that exists +++ /// in the same commit. +++ pub fn track_copies_same_commit_copies(&mut self, opt: bool) -> &mut BlameOptions { +++ self.flag(raw::GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES, opt) +++ } +++ +++ /// Track lines that have been copied from another file that exists +++ /// in any commit. +++ pub fn track_copies_any_commit_copies(&mut self, opt: bool) -> &mut BlameOptions { +++ self.flag(raw::GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES, opt) +++ } +++ +++ /// Restrict the search of commits to those reachable following only +++ /// the first parents. +++ pub fn first_parent(&mut self, opt: bool) -> &mut BlameOptions { +++ self.flag(raw::GIT_BLAME_FIRST_PARENT, opt) +++ } +++ +++ /// Use mailmap file to map author and committer names and email addresses +++ /// to canonical real names and email addresses. The mailmap will be read +++ /// from the working directory, or HEAD in a bare repository. +++ pub fn use_mailmap(&mut self, opt: bool) -> &mut BlameOptions { +++ self.flag(raw::GIT_BLAME_USE_MAILMAP, opt) +++ } +++ +++ /// Ignore whitespace differences. +++ pub fn ignore_whitespace(&mut self, opt: bool) -> &mut BlameOptions { +++ self.flag(raw::GIT_BLAME_IGNORE_WHITESPACE, opt) +++ } +++ +++ /// Setter for the id of the newest commit to consider. +++ pub fn newest_commit(&mut self, id: Oid) -> &mut BlameOptions { +++ unsafe { +++ self.raw.newest_commit = *id.raw(); +++ } +++ self +++ } +++ +++ /// Setter for the id of the oldest commit to consider. +++ pub fn oldest_commit(&mut self, id: Oid) -> &mut BlameOptions { +++ unsafe { +++ self.raw.oldest_commit = *id.raw(); +++ } +++ self +++ } +++ +++ /// The first line in the file to blame. +++ pub fn min_line(&mut self, lineno: usize) -> &mut BlameOptions { +++ self.raw.min_line = lineno; +++ self +++ } +++ +++ /// The last line in the file to blame. +++ pub fn max_line(&mut self, lineno: usize) -> &mut BlameOptions { +++ self.raw.max_line = lineno; +++ self +++ } +++} +++ +++impl<'repo> Binding for Blame<'repo> { +++ type Raw = *mut raw::git_blame; +++ +++ unsafe fn from_raw(raw: *mut raw::git_blame) -> Blame<'repo> { +++ Blame { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ +++ fn raw(&self) -> *mut raw::git_blame { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for Blame<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_blame_free(self.raw) } +++ } +++} +++ +++impl<'blame> Binding for BlameHunk<'blame> { +++ type Raw = *mut raw::git_blame_hunk; +++ +++ unsafe fn from_raw(raw: *mut raw::git_blame_hunk) -> BlameHunk<'blame> { +++ BlameHunk { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ +++ fn raw(&self) -> *mut raw::git_blame_hunk { +++ self.raw +++ } +++} +++ +++impl Binding for BlameOptions { +++ type Raw = *mut raw::git_blame_options; +++ +++ unsafe fn from_raw(opts: *mut raw::git_blame_options) -> BlameOptions { +++ BlameOptions { raw: *opts } +++ } +++ +++ fn raw(&self) -> *mut raw::git_blame_options { +++ &self.raw as *const _ as *mut _ +++ } +++} +++ +++impl<'blame> Iterator for BlameIter<'blame> { +++ type Item = BlameHunk<'blame>; +++ fn next(&mut self) -> Option> { +++ self.range.next().and_then(|i| self.blame.get_index(i)) +++ } +++ +++ fn size_hint(&self) -> (usize, Option) { +++ self.range.size_hint() +++ } +++} +++ +++impl<'blame> DoubleEndedIterator for BlameIter<'blame> { +++ fn next_back(&mut self) -> Option> { +++ self.range.next_back().and_then(|i| self.blame.get_index(i)) +++ } +++} +++ +++impl<'blame> FusedIterator for BlameIter<'blame> {} +++ +++impl<'blame> ExactSizeIterator for BlameIter<'blame> {} +++ +++#[cfg(test)] +++mod tests { +++ use std::fs::{self, File}; +++ use std::path::Path; +++ +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut index = repo.index().unwrap(); +++ +++ let root = repo.workdir().unwrap(); +++ fs::create_dir(&root.join("foo")).unwrap(); +++ File::create(&root.join("foo/bar")).unwrap(); +++ index.add_path(Path::new("foo/bar")).unwrap(); +++ +++ let id = index.write_tree().unwrap(); +++ let tree = repo.find_tree(id).unwrap(); +++ let sig = repo.signature().unwrap(); +++ let id = repo.refname_to_id("HEAD").unwrap(); +++ let parent = repo.find_commit(id).unwrap(); +++ let commit = repo +++ .commit(Some("HEAD"), &sig, &sig, "commit", &tree, &[&parent]) +++ .unwrap(); +++ +++ let blame = repo.blame_file(Path::new("foo/bar"), None).unwrap(); +++ +++ assert_eq!(blame.len(), 1); +++ assert_eq!(blame.iter().count(), 1); +++ +++ let hunk = blame.get_index(0).unwrap(); +++ assert_eq!(hunk.final_commit_id(), commit); +++ assert_eq!(hunk.final_signature().name(), sig.name()); +++ assert_eq!(hunk.final_signature().email(), sig.email()); +++ assert_eq!(hunk.final_start_line(), 1); +++ assert_eq!(hunk.path(), Some(Path::new("foo/bar"))); +++ assert_eq!(hunk.lines_in_hunk(), 0); +++ assert!(!hunk.is_boundary()); +++ +++ let blame_buffer = blame.blame_buffer("\n".as_bytes()).unwrap(); +++ let line = blame_buffer.get_line(1).unwrap(); +++ +++ assert_eq!(blame_buffer.len(), 2); +++ assert_eq!(blame_buffer.iter().count(), 2); +++ assert!(line.final_commit_id().is_zero()); +++ } +++} diff --cc extra/git2/src/blob.rs index 0000000000,0000000000,0000000000..5c4a6ce6b8 new file mode 100644 --- /dev/null +++ b/extra/git2/src/blob.rs @@@@ -1,0 -1,0 -1,0 +1,208 @@@@ +++use std::io; +++use std::marker; +++use std::mem; +++use std::slice; +++ +++use crate::util::Binding; +++use crate::{raw, Error, Object, Oid}; +++ +++/// A structure to represent a git [blob][1] +++/// +++/// [1]: http://git-scm.com/book/en/Git-Internals-Git-Objects +++pub struct Blob<'repo> { +++ raw: *mut raw::git_blob, +++ _marker: marker::PhantomData>, +++} +++ +++impl<'repo> Blob<'repo> { +++ /// Get the id (SHA1) of a repository blob +++ pub fn id(&self) -> Oid { +++ unsafe { Binding::from_raw(raw::git_blob_id(&*self.raw)) } +++ } +++ +++ /// Determine if the blob content is most certainly binary or not. +++ pub fn is_binary(&self) -> bool { +++ unsafe { raw::git_blob_is_binary(&*self.raw) == 1 } +++ } +++ +++ /// Get the content of this blob. +++ pub fn content(&self) -> &[u8] { +++ unsafe { +++ let data = raw::git_blob_rawcontent(&*self.raw) as *const u8; +++ let len = raw::git_blob_rawsize(&*self.raw) as usize; +++ slice::from_raw_parts(data, len) +++ } +++ } +++ +++ /// Get the size in bytes of the contents of this blob. +++ pub fn size(&self) -> usize { +++ unsafe { raw::git_blob_rawsize(&*self.raw) as usize } +++ } +++ +++ /// Casts this Blob to be usable as an `Object` +++ pub fn as_object(&self) -> &Object<'repo> { +++ unsafe { &*(self as *const _ as *const Object<'repo>) } +++ } +++ +++ /// Consumes Blob to be returned as an `Object` +++ pub fn into_object(self) -> Object<'repo> { +++ assert_eq!(mem::size_of_val(&self), mem::size_of::>()); +++ unsafe { mem::transmute(self) } +++ } +++} +++ +++impl<'repo> Binding for Blob<'repo> { +++ type Raw = *mut raw::git_blob; +++ +++ unsafe fn from_raw(raw: *mut raw::git_blob) -> Blob<'repo> { +++ Blob { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_blob { +++ self.raw +++ } +++} +++ +++impl<'repo> std::fmt::Debug for Blob<'repo> { +++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +++ f.debug_struct("Blob").field("id", &self.id()).finish() +++ } +++} +++ +++impl<'repo> Clone for Blob<'repo> { +++ fn clone(&self) -> Self { +++ self.as_object().clone().into_blob().ok().unwrap() +++ } +++} +++ +++impl<'repo> Drop for Blob<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_blob_free(self.raw) } +++ } +++} +++ +++/// A structure to represent a git writestream for blobs +++pub struct BlobWriter<'repo> { +++ raw: *mut raw::git_writestream, +++ need_cleanup: bool, +++ _marker: marker::PhantomData>, +++} +++ +++impl<'repo> BlobWriter<'repo> { +++ /// Finalize blob writing stream and write the blob to the object db +++ pub fn commit(mut self) -> Result { +++ // After commit we already doesn't need cleanup on drop +++ self.need_cleanup = false; +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_blob_create_fromstream_commit(&mut raw, self.raw)); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++} +++ +++impl<'repo> Binding for BlobWriter<'repo> { +++ type Raw = *mut raw::git_writestream; +++ +++ unsafe fn from_raw(raw: *mut raw::git_writestream) -> BlobWriter<'repo> { +++ BlobWriter { +++ raw, +++ need_cleanup: true, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_writestream { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for BlobWriter<'repo> { +++ fn drop(&mut self) { +++ // We need cleanup in case the stream has not been committed +++ if self.need_cleanup { +++ unsafe { +++ if let Some(f) = (*self.raw).free { +++ f(self.raw) +++ } +++ } +++ } +++ } +++} +++ +++impl<'repo> io::Write for BlobWriter<'repo> { +++ fn write(&mut self, buf: &[u8]) -> io::Result { +++ unsafe { +++ if let Some(f) = (*self.raw).write { +++ let res = f(self.raw, buf.as_ptr() as *const _, buf.len()); +++ if res < 0 { +++ Err(io::Error::new(io::ErrorKind::Other, "Write error")) +++ } else { +++ Ok(buf.len()) +++ } +++ } else { +++ Err(io::Error::new(io::ErrorKind::Other, "no write callback")) +++ } +++ } +++ } +++ fn flush(&mut self) -> io::Result<()> { +++ Ok(()) +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::Repository; +++ use std::fs::File; +++ use std::io::prelude::*; +++ use std::path::Path; +++ use tempfile::TempDir; +++ +++ #[test] +++ fn buffer() { +++ let td = TempDir::new().unwrap(); +++ let repo = Repository::init(td.path()).unwrap(); +++ let id = repo.blob(&[5, 4, 6]).unwrap(); +++ let blob = repo.find_blob(id).unwrap(); +++ +++ assert_eq!(blob.id(), id); +++ assert_eq!(blob.size(), 3); +++ assert_eq!(blob.content(), [5, 4, 6]); +++ assert!(blob.is_binary()); +++ +++ repo.find_object(id, None).unwrap().as_blob().unwrap(); +++ repo.find_object(id, None) +++ .unwrap() +++ .into_blob() +++ .ok() +++ .unwrap(); +++ } +++ +++ #[test] +++ fn path() { +++ let td = TempDir::new().unwrap(); +++ let path = td.path().join("foo"); +++ File::create(&path).unwrap().write_all(&[7, 8, 9]).unwrap(); +++ let repo = Repository::init(td.path()).unwrap(); +++ let id = repo.blob_path(&path).unwrap(); +++ let blob = repo.find_blob(id).unwrap(); +++ assert_eq!(blob.content(), [7, 8, 9]); +++ blob.into_object(); +++ } +++ +++ #[test] +++ fn stream() { +++ let td = TempDir::new().unwrap(); +++ let repo = Repository::init(td.path()).unwrap(); +++ let mut ws = repo.blob_writer(Some(Path::new("foo"))).unwrap(); +++ let wl = ws.write(&[10, 11, 12]).unwrap(); +++ assert_eq!(wl, 3); +++ let id = ws.commit().unwrap(); +++ let blob = repo.find_blob(id).unwrap(); +++ assert_eq!(blob.content(), [10, 11, 12]); +++ blob.into_object(); +++ } +++} diff --cc extra/git2/src/branch.rs index 0000000000,0000000000,0000000000..e1eba99c2b new file mode 100644 --- /dev/null +++ b/extra/git2/src/branch.rs @@@@ -1,0 -1,0 -1,0 +1,197 @@@@ +++use std::ffi::CString; +++use std::marker; +++use std::ptr; +++use std::str; +++ +++use crate::util::Binding; +++use crate::{raw, BranchType, Error, Reference, References}; +++ +++/// A structure to represent a git [branch][1] +++/// +++/// A branch is currently just a wrapper to an underlying `Reference`. The +++/// reference can be accessed through the `get` and `into_reference` methods. +++/// +++/// [1]: http://git-scm.com/book/en/Git-Branching-What-a-Branch-Is +++pub struct Branch<'repo> { +++ inner: Reference<'repo>, +++} +++ +++/// An iterator over the branches inside of a repository. +++pub struct Branches<'repo> { +++ raw: *mut raw::git_branch_iterator, +++ _marker: marker::PhantomData>, +++} +++ +++impl<'repo> Branch<'repo> { +++ /// Creates Branch type from a Reference +++ pub fn wrap(reference: Reference<'_>) -> Branch<'_> { +++ Branch { inner: reference } +++ } +++ +++ /// Ensure the branch name is well-formed. +++ pub fn name_is_valid(name: &str) -> Result { +++ crate::init(); +++ let name = CString::new(name)?; +++ let mut valid: libc::c_int = 0; +++ unsafe { +++ try_call!(raw::git_branch_name_is_valid(&mut valid, name.as_ptr())); +++ } +++ Ok(valid == 1) +++ } +++ +++ /// Gain access to the reference that is this branch +++ pub fn get(&self) -> &Reference<'repo> { +++ &self.inner +++ } +++ +++ /// Gain mutable access to the reference that is this branch +++ pub fn get_mut(&mut self) -> &mut Reference<'repo> { +++ &mut self.inner +++ } +++ +++ /// Take ownership of the underlying reference. +++ pub fn into_reference(self) -> Reference<'repo> { +++ self.inner +++ } +++ +++ /// Delete an existing branch reference. +++ pub fn delete(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_branch_delete(self.get().raw())); +++ } +++ Ok(()) +++ } +++ +++ /// Determine if the current local branch is pointed at by HEAD. +++ pub fn is_head(&self) -> bool { +++ unsafe { raw::git_branch_is_head(&*self.get().raw()) == 1 } +++ } +++ +++ /// Move/rename an existing local branch reference. +++ pub fn rename(&mut self, new_branch_name: &str, force: bool) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ let new_branch_name = CString::new(new_branch_name)?; +++ unsafe { +++ try_call!(raw::git_branch_move( +++ &mut ret, +++ self.get().raw(), +++ new_branch_name, +++ force +++ )); +++ Ok(Branch::wrap(Binding::from_raw(ret))) +++ } +++ } +++ +++ /// Return the name of the given local or remote branch. +++ /// +++ /// May return `Ok(None)` if the name is not valid utf-8. +++ pub fn name(&self) -> Result, Error> { +++ self.name_bytes().map(|s| str::from_utf8(s).ok()) +++ } +++ +++ /// Return the name of the given local or remote branch. +++ pub fn name_bytes(&self) -> Result<&[u8], Error> { +++ let mut ret = ptr::null(); +++ unsafe { +++ try_call!(raw::git_branch_name(&mut ret, &*self.get().raw())); +++ Ok(crate::opt_bytes(self, ret).unwrap()) +++ } +++ } +++ +++ /// Return the reference supporting the remote tracking branch, given a +++ /// local branch reference. +++ pub fn upstream(&self) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_branch_upstream(&mut ret, &*self.get().raw())); +++ Ok(Branch::wrap(Binding::from_raw(ret))) +++ } +++ } +++ +++ /// Set the upstream configuration for a given local branch. +++ /// +++ /// If `None` is specified, then the upstream branch is unset. The name +++ /// provided is the name of the branch to set as upstream. +++ pub fn set_upstream(&mut self, upstream_name: Option<&str>) -> Result<(), Error> { +++ let upstream_name = crate::opt_cstr(upstream_name)?; +++ unsafe { +++ try_call!(raw::git_branch_set_upstream( +++ self.get().raw(), +++ upstream_name +++ )); +++ Ok(()) +++ } +++ } +++} +++ +++impl<'repo> Branches<'repo> { +++ /// Creates a new iterator from the raw pointer given. +++ /// +++ /// This function is unsafe as it is not guaranteed that `raw` is a valid +++ /// pointer. +++ pub unsafe fn from_raw(raw: *mut raw::git_branch_iterator) -> Branches<'repo> { +++ Branches { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++} +++ +++impl<'repo> Iterator for Branches<'repo> { +++ type Item = Result<(Branch<'repo>, BranchType), Error>; +++ fn next(&mut self) -> Option, BranchType), Error>> { +++ let mut ret = ptr::null_mut(); +++ let mut typ = raw::GIT_BRANCH_LOCAL; +++ unsafe { +++ try_call_iter!(raw::git_branch_next(&mut ret, &mut typ, self.raw)); +++ let typ = match typ { +++ raw::GIT_BRANCH_LOCAL => BranchType::Local, +++ raw::GIT_BRANCH_REMOTE => BranchType::Remote, +++ n => panic!("unexected branch type: {}", n), +++ }; +++ Some(Ok((Branch::wrap(Binding::from_raw(ret)), typ))) +++ } +++ } +++} +++ +++impl<'repo> Drop for Branches<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_branch_iterator_free(self.raw) } +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::{Branch, BranchType}; +++ +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ let head = repo.head().unwrap(); +++ let target = head.target().unwrap(); +++ let commit = repo.find_commit(target).unwrap(); +++ +++ let mut b1 = repo.branch("foo", &commit, false).unwrap(); +++ assert!(!b1.is_head()); +++ repo.branch("foo2", &commit, false).unwrap(); +++ +++ assert_eq!(repo.branches(None).unwrap().count(), 3); +++ repo.find_branch("foo", BranchType::Local).unwrap(); +++ let mut b1 = b1.rename("bar", false).unwrap(); +++ assert_eq!(b1.name().unwrap(), Some("bar")); +++ assert!(b1.upstream().is_err()); +++ b1.set_upstream(Some("main")).unwrap(); +++ b1.upstream().unwrap(); +++ b1.set_upstream(None).unwrap(); +++ +++ b1.delete().unwrap(); +++ } +++ +++ #[test] +++ fn name_is_valid() { +++ assert!(Branch::name_is_valid("foo").unwrap()); +++ assert!(!Branch::name_is_valid("").unwrap()); +++ assert!(!Branch::name_is_valid("with spaces").unwrap()); +++ assert!(!Branch::name_is_valid("~tilde").unwrap()); +++ } +++} diff --cc extra/git2/src/buf.rs index 0000000000,0000000000,0000000000..fd2bcbf96f new file mode 100644 --- /dev/null +++ b/extra/git2/src/buf.rs @@@@ -1,0 -1,0 -1,0 +1,71 @@@@ +++use std::ops::{Deref, DerefMut}; +++use std::ptr; +++use std::slice; +++use std::str; +++ +++use crate::raw; +++use crate::util::Binding; +++ +++/// A structure to wrap an intermediate buffer used by libgit2. +++/// +++/// A buffer can be thought of a `Vec`, but the `Vec` type is not used to +++/// avoid copying data back and forth. +++pub struct Buf { +++ raw: raw::git_buf, +++} +++ +++impl Default for Buf { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl Buf { +++ /// Creates a new empty buffer. +++ pub fn new() -> Buf { +++ crate::init(); +++ unsafe { +++ Binding::from_raw(&mut raw::git_buf { +++ ptr: ptr::null_mut(), +++ size: 0, +++ reserved: 0, +++ } as *mut _) +++ } +++ } +++ +++ /// Attempt to view this buffer as a string slice. +++ /// +++ /// Returns `None` if the buffer is not valid utf-8. +++ pub fn as_str(&self) -> Option<&str> { +++ str::from_utf8(&**self).ok() +++ } +++} +++ +++impl Deref for Buf { +++ type Target = [u8]; +++ fn deref(&self) -> &[u8] { +++ unsafe { slice::from_raw_parts(self.raw.ptr as *const u8, self.raw.size as usize) } +++ } +++} +++ +++impl DerefMut for Buf { +++ fn deref_mut(&mut self) -> &mut [u8] { +++ unsafe { slice::from_raw_parts_mut(self.raw.ptr as *mut u8, self.raw.size as usize) } +++ } +++} +++ +++impl Binding for Buf { +++ type Raw = *mut raw::git_buf; +++ unsafe fn from_raw(raw: *mut raw::git_buf) -> Buf { +++ Buf { raw: *raw } +++ } +++ fn raw(&self) -> *mut raw::git_buf { +++ &self.raw as *const _ as *mut _ +++ } +++} +++ +++impl Drop for Buf { +++ fn drop(&mut self) { +++ unsafe { raw::git_buf_dispose(&mut self.raw) } +++ } +++} diff --cc extra/git2/src/build.rs index 0000000000,0000000000,0000000000..4ac62439b7 new file mode 100644 --- /dev/null +++ b/extra/git2/src/build.rs @@@@ -1,0 -1,0 -1,0 +1,872 @@@@ +++//! Builder-pattern objects for configuration various git operations. +++ +++use libc::{c_char, c_int, c_uint, c_void, size_t}; +++use std::ffi::{CStr, CString}; +++use std::mem; +++use std::path::Path; +++use std::ptr; +++ +++use crate::util::{self, Binding}; +++use crate::{panic, raw, Error, FetchOptions, IntoCString, Oid, Repository, Tree}; +++use crate::{CheckoutNotificationType, DiffFile, FileMode, Remote}; +++ +++/// A builder struct which is used to build configuration for cloning a new git +++/// repository. +++/// +++/// # Example +++/// +++/// Cloning using SSH: +++/// +++/// ```no_run +++/// use git2::{Cred, Error, RemoteCallbacks}; +++/// use std::env; +++/// use std::path::Path; +++/// +++/// // Prepare callbacks. +++/// let mut callbacks = RemoteCallbacks::new(); +++/// callbacks.credentials(|_url, username_from_url, _allowed_types| { +++/// Cred::ssh_key( +++/// username_from_url.unwrap(), +++/// None, +++/// Path::new(&format!("{}/.ssh/id_rsa", env::var("HOME").unwrap())), +++/// None, +++/// ) +++/// }); +++/// +++/// // Prepare fetch options. +++/// let mut fo = git2::FetchOptions::new(); +++/// fo.remote_callbacks(callbacks); +++/// +++/// // Prepare builder. +++/// let mut builder = git2::build::RepoBuilder::new(); +++/// builder.fetch_options(fo); +++/// +++/// // Clone the project. +++/// builder.clone( +++/// "git@github.com:rust-lang/git2-rs.git", +++/// Path::new("/tmp/git2-rs"), +++/// ); +++/// ``` +++pub struct RepoBuilder<'cb> { +++ bare: bool, +++ branch: Option, +++ local: bool, +++ hardlinks: bool, +++ checkout: Option>, +++ fetch_opts: Option>, +++ clone_local: Option, +++ remote_create: Option>>, +++} +++ +++/// Type of callback passed to `RepoBuilder::remote_create`. +++/// +++/// The second and third arguments are the remote's name and the remote's URL. +++pub type RemoteCreate<'cb> = +++ dyn for<'a> FnMut(&'a Repository, &str, &str) -> Result, Error> + 'cb; +++ +++/// A builder struct for git tree updates. +++/// +++/// Paths passed to `remove` and `upsert` can be multi-component paths, i.e. they +++/// may contain slashes. +++/// +++/// This is a higher-level tree update facility. There is also [`TreeBuilder`] +++/// which is lower-level (and operates only on one level of the tree at a time). +++/// +++/// [`TreeBuilder`]: crate::TreeBuilder +++pub struct TreeUpdateBuilder { +++ updates: Vec, +++ paths: Vec, +++} +++ +++/// A builder struct for configuring checkouts of a repository. +++pub struct CheckoutBuilder<'cb> { +++ their_label: Option, +++ our_label: Option, +++ ancestor_label: Option, +++ target_dir: Option, +++ paths: Vec, +++ path_ptrs: Vec<*const c_char>, +++ file_perm: Option, +++ dir_perm: Option, +++ disable_filters: bool, +++ checkout_opts: u32, +++ progress: Option>>, +++ notify: Option>>, +++ notify_flags: CheckoutNotificationType, +++} +++ +++/// Checkout progress notification callback. +++/// +++/// The first argument is the path for the notification, the next is the number +++/// of completed steps so far, and the final is the total number of steps. +++pub type Progress<'a> = dyn FnMut(Option<&Path>, usize, usize) + 'a; +++ +++/// Checkout notifications callback. +++/// +++/// The first argument is the notification type, the next is the path for the +++/// the notification, followed by the baseline diff, target diff, and workdir diff. +++/// +++/// The callback must return a bool specifying whether the checkout should +++/// continue. +++pub type Notify<'a> = dyn FnMut( +++ CheckoutNotificationType, +++ Option<&Path>, +++ Option>, +++ Option>, +++ Option>, +++ ) -> bool +++ + 'a; +++ +++impl<'cb> Default for RepoBuilder<'cb> { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++/// Options that can be passed to `RepoBuilder::clone_local`. +++#[derive(Clone, Copy)] +++pub enum CloneLocal { +++ /// Auto-detect (default) +++ /// +++ /// Here libgit2 will bypass the git-aware transport for local paths, but +++ /// use a normal fetch for `file://` URLs. +++ Auto = raw::GIT_CLONE_LOCAL_AUTO as isize, +++ +++ /// Bypass the git-aware transport even for `file://` URLs. +++ Local = raw::GIT_CLONE_LOCAL as isize, +++ +++ /// Never bypass the git-aware transport +++ None = raw::GIT_CLONE_NO_LOCAL as isize, +++ +++ /// Bypass the git-aware transport, but don't try to use hardlinks. +++ NoLinks = raw::GIT_CLONE_LOCAL_NO_LINKS as isize, +++ +++ #[doc(hidden)] +++ __Nonexhaustive = 0xff, +++} +++ +++impl<'cb> RepoBuilder<'cb> { +++ /// Creates a new repository builder with all of the default configuration. +++ /// +++ /// When ready, the `clone()` method can be used to clone a new repository +++ /// using this configuration. +++ pub fn new() -> RepoBuilder<'cb> { +++ crate::init(); +++ RepoBuilder { +++ bare: false, +++ branch: None, +++ local: true, +++ clone_local: None, +++ hardlinks: true, +++ checkout: None, +++ fetch_opts: None, +++ remote_create: None, +++ } +++ } +++ +++ /// Indicate whether the repository will be cloned as a bare repository or +++ /// not. +++ pub fn bare(&mut self, bare: bool) -> &mut RepoBuilder<'cb> { +++ self.bare = bare; +++ self +++ } +++ +++ /// Specify the name of the branch to check out after the clone. +++ /// +++ /// If not specified, the remote's default branch will be used. +++ pub fn branch(&mut self, branch: &str) -> &mut RepoBuilder<'cb> { +++ self.branch = Some(CString::new(branch).unwrap()); +++ self +++ } +++ +++ /// Configures options for bypassing the git-aware transport on clone. +++ /// +++ /// Bypassing it means that instead of a fetch libgit2 will copy the object +++ /// database directory instead of figuring out what it needs, which is +++ /// faster. If possible, it will hardlink the files to save space. +++ pub fn clone_local(&mut self, clone_local: CloneLocal) -> &mut RepoBuilder<'cb> { +++ self.clone_local = Some(clone_local); +++ self +++ } +++ +++ /// Set the flag for bypassing the git aware transport mechanism for local +++ /// paths. +++ /// +++ /// If `true`, the git-aware transport will be bypassed for local paths. If +++ /// `false`, the git-aware transport will not be bypassed. +++ #[deprecated(note = "use `clone_local` instead")] +++ #[doc(hidden)] +++ pub fn local(&mut self, local: bool) -> &mut RepoBuilder<'cb> { +++ self.local = local; +++ self +++ } +++ +++ /// Set the flag for whether hardlinks are used when using a local git-aware +++ /// transport mechanism. +++ #[deprecated(note = "use `clone_local` instead")] +++ #[doc(hidden)] +++ pub fn hardlinks(&mut self, links: bool) -> &mut RepoBuilder<'cb> { +++ self.hardlinks = links; +++ self +++ } +++ +++ /// Configure the checkout which will be performed by consuming a checkout +++ /// builder. +++ pub fn with_checkout(&mut self, checkout: CheckoutBuilder<'cb>) -> &mut RepoBuilder<'cb> { +++ self.checkout = Some(checkout); +++ self +++ } +++ +++ /// Options which control the fetch, including callbacks. +++ /// +++ /// The callbacks are used for reporting fetch progress, and for acquiring +++ /// credentials in the event they are needed. +++ pub fn fetch_options(&mut self, fetch_opts: FetchOptions<'cb>) -> &mut RepoBuilder<'cb> { +++ self.fetch_opts = Some(fetch_opts); +++ self +++ } +++ +++ /// Configures a callback used to create the git remote, prior to its being +++ /// used to perform the clone operation. +++ pub fn remote_create(&mut self, f: F) -> &mut RepoBuilder<'cb> +++ where +++ F: for<'a> FnMut(&'a Repository, &str, &str) -> Result, Error> + 'cb, +++ { +++ self.remote_create = Some(Box::new(f)); +++ self +++ } +++ +++ /// Clone a remote repository. +++ /// +++ /// This will use the options configured so far to clone the specified URL +++ /// into the specified local path. +++ pub fn clone(&mut self, url: &str, into: &Path) -> Result { +++ let mut opts: raw::git_clone_options = unsafe { mem::zeroed() }; +++ unsafe { +++ try_call!(raw::git_clone_init_options( +++ &mut opts, +++ raw::GIT_CLONE_OPTIONS_VERSION +++ )); +++ } +++ opts.bare = self.bare as c_int; +++ opts.checkout_branch = self +++ .branch +++ .as_ref() +++ .map(|s| s.as_ptr()) +++ .unwrap_or(ptr::null()); +++ +++ if let Some(ref local) = self.clone_local { +++ opts.local = *local as raw::git_clone_local_t; +++ } else { +++ opts.local = match (self.local, self.hardlinks) { +++ (true, false) => raw::GIT_CLONE_LOCAL_NO_LINKS, +++ (false, _) => raw::GIT_CLONE_NO_LOCAL, +++ (true, _) => raw::GIT_CLONE_LOCAL_AUTO, +++ }; +++ } +++ +++ if let Some(ref mut cbs) = self.fetch_opts { +++ opts.fetch_opts = cbs.raw(); +++ } +++ +++ if let Some(ref mut c) = self.checkout { +++ unsafe { +++ c.configure(&mut opts.checkout_opts); +++ } +++ } +++ +++ if let Some(ref mut callback) = self.remote_create { +++ opts.remote_cb = Some(remote_create_cb); +++ opts.remote_cb_payload = callback as *mut _ as *mut _; +++ } +++ +++ let url = CString::new(url)?; +++ // Normal file path OK (does not need Windows conversion). +++ let into = into.into_c_string()?; +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_clone(&mut raw, url, into, &opts)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++} +++ +++extern "C" fn remote_create_cb( +++ out: *mut *mut raw::git_remote, +++ repo: *mut raw::git_repository, +++ name: *const c_char, +++ url: *const c_char, +++ payload: *mut c_void, +++) -> c_int { +++ unsafe { +++ let repo = Repository::from_raw(repo); +++ let code = panic::wrap(|| { +++ let name = CStr::from_ptr(name).to_str().unwrap(); +++ let url = CStr::from_ptr(url).to_str().unwrap(); +++ let f = payload as *mut Box>; +++ match (*f)(&repo, name, url) { +++ Ok(remote) => { +++ *out = crate::remote::remote_into_raw(remote); +++ 0 +++ } +++ Err(e) => e.raw_code(), +++ } +++ }); +++ mem::forget(repo); +++ code.unwrap_or(-1) +++ } +++} +++ +++impl<'cb> Default for CheckoutBuilder<'cb> { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl<'cb> CheckoutBuilder<'cb> { +++ /// Creates a new builder for checkouts with all of its default +++ /// configuration. +++ pub fn new() -> CheckoutBuilder<'cb> { +++ crate::init(); +++ CheckoutBuilder { +++ disable_filters: false, +++ dir_perm: None, +++ file_perm: None, +++ path_ptrs: Vec::new(), +++ paths: Vec::new(), +++ target_dir: None, +++ ancestor_label: None, +++ our_label: None, +++ their_label: None, +++ checkout_opts: raw::GIT_CHECKOUT_SAFE as u32, +++ progress: None, +++ notify: None, +++ notify_flags: CheckoutNotificationType::empty(), +++ } +++ } +++ +++ /// Indicate that this checkout should perform a dry run by checking for +++ /// conflicts but not make any actual changes. +++ pub fn dry_run(&mut self) -> &mut CheckoutBuilder<'cb> { +++ self.checkout_opts &= !((1 << 4) - 1); +++ self.checkout_opts |= raw::GIT_CHECKOUT_NONE as u32; +++ self +++ } +++ +++ /// Take any action necessary to get the working directory to match the +++ /// target including potentially discarding modified files. +++ pub fn force(&mut self) -> &mut CheckoutBuilder<'cb> { +++ self.checkout_opts &= !((1 << 4) - 1); +++ self.checkout_opts |= raw::GIT_CHECKOUT_FORCE as u32; +++ self +++ } +++ +++ /// Indicate that the checkout should be performed safely, allowing new +++ /// files to be created but not overwriting existing files or changes. +++ /// +++ /// This is the default. +++ pub fn safe(&mut self) -> &mut CheckoutBuilder<'cb> { +++ self.checkout_opts &= !((1 << 4) - 1); +++ self.checkout_opts |= raw::GIT_CHECKOUT_SAFE as u32; +++ self +++ } +++ +++ fn flag(&mut self, bit: raw::git_checkout_strategy_t, on: bool) -> &mut CheckoutBuilder<'cb> { +++ if on { +++ self.checkout_opts |= bit as u32; +++ } else { +++ self.checkout_opts &= !(bit as u32); +++ } +++ self +++ } +++ +++ /// In safe mode, create files that don't exist. +++ /// +++ /// Defaults to false. +++ pub fn recreate_missing(&mut self, allow: bool) -> &mut CheckoutBuilder<'cb> { +++ self.flag(raw::GIT_CHECKOUT_RECREATE_MISSING, allow) +++ } +++ +++ /// In safe mode, apply safe file updates even when there are conflicts +++ /// instead of canceling the checkout. +++ /// +++ /// Defaults to false. +++ pub fn allow_conflicts(&mut self, allow: bool) -> &mut CheckoutBuilder<'cb> { +++ self.flag(raw::GIT_CHECKOUT_ALLOW_CONFLICTS, allow) +++ } +++ +++ /// Remove untracked files from the working dir. +++ /// +++ /// Defaults to false. +++ pub fn remove_untracked(&mut self, remove: bool) -> &mut CheckoutBuilder<'cb> { +++ self.flag(raw::GIT_CHECKOUT_REMOVE_UNTRACKED, remove) +++ } +++ +++ /// Remove ignored files from the working dir. +++ /// +++ /// Defaults to false. +++ pub fn remove_ignored(&mut self, remove: bool) -> &mut CheckoutBuilder<'cb> { +++ self.flag(raw::GIT_CHECKOUT_REMOVE_IGNORED, remove) +++ } +++ +++ /// Only update the contents of files that already exist. +++ /// +++ /// If set, files will not be created or deleted. +++ /// +++ /// Defaults to false. +++ pub fn update_only(&mut self, update: bool) -> &mut CheckoutBuilder<'cb> { +++ self.flag(raw::GIT_CHECKOUT_UPDATE_ONLY, update) +++ } +++ +++ /// Prevents checkout from writing the updated files' information to the +++ /// index. +++ /// +++ /// Defaults to true. +++ pub fn update_index(&mut self, update: bool) -> &mut CheckoutBuilder<'cb> { +++ self.flag(raw::GIT_CHECKOUT_DONT_UPDATE_INDEX, !update) +++ } +++ +++ /// Indicate whether the index and git attributes should be refreshed from +++ /// disk before any operations. +++ /// +++ /// Defaults to true, +++ pub fn refresh(&mut self, refresh: bool) -> &mut CheckoutBuilder<'cb> { +++ self.flag(raw::GIT_CHECKOUT_NO_REFRESH, !refresh) +++ } +++ +++ /// Skip files with unmerged index entries. +++ /// +++ /// Defaults to false. +++ pub fn skip_unmerged(&mut self, skip: bool) -> &mut CheckoutBuilder<'cb> { +++ self.flag(raw::GIT_CHECKOUT_SKIP_UNMERGED, skip) +++ } +++ +++ /// Indicate whether the checkout should proceed on conflicts by using the +++ /// stage 2 version of the file ("ours"). +++ /// +++ /// Defaults to false. +++ pub fn use_ours(&mut self, ours: bool) -> &mut CheckoutBuilder<'cb> { +++ self.flag(raw::GIT_CHECKOUT_USE_OURS, ours) +++ } +++ +++ /// Indicate whether the checkout should proceed on conflicts by using the +++ /// stage 3 version of the file ("theirs"). +++ /// +++ /// Defaults to false. +++ pub fn use_theirs(&mut self, theirs: bool) -> &mut CheckoutBuilder<'cb> { +++ self.flag(raw::GIT_CHECKOUT_USE_THEIRS, theirs) +++ } +++ +++ /// Indicate whether ignored files should be overwritten during the checkout. +++ /// +++ /// Defaults to true. +++ pub fn overwrite_ignored(&mut self, overwrite: bool) -> &mut CheckoutBuilder<'cb> { +++ self.flag(raw::GIT_CHECKOUT_DONT_OVERWRITE_IGNORED, !overwrite) +++ } +++ +++ /// Indicate whether a normal merge file should be written for conflicts. +++ /// +++ /// Defaults to false. +++ pub fn conflict_style_merge(&mut self, on: bool) -> &mut CheckoutBuilder<'cb> { +++ self.flag(raw::GIT_CHECKOUT_CONFLICT_STYLE_MERGE, on) +++ } +++ +++ /// Specify for which notification types to invoke the notification +++ /// callback. +++ /// +++ /// Defaults to none. +++ pub fn notify_on( +++ &mut self, +++ notification_types: CheckoutNotificationType, +++ ) -> &mut CheckoutBuilder<'cb> { +++ self.notify_flags = notification_types; +++ self +++ } +++ +++ /// Indicates whether to include common ancestor data in diff3 format files +++ /// for conflicts. +++ /// +++ /// Defaults to false. +++ pub fn conflict_style_diff3(&mut self, on: bool) -> &mut CheckoutBuilder<'cb> { +++ self.flag(raw::GIT_CHECKOUT_CONFLICT_STYLE_DIFF3, on) +++ } +++ +++ /// Treat paths specified in [`CheckoutBuilder::path`] as exact file paths +++ /// instead of as pathspecs. +++ pub fn disable_pathspec_match(&mut self, on: bool) -> &mut CheckoutBuilder<'cb> { +++ self.flag(raw::GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH, on) +++ } +++ +++ /// Indicate whether to apply filters like CRLF conversion. +++ pub fn disable_filters(&mut self, disable: bool) -> &mut CheckoutBuilder<'cb> { +++ self.disable_filters = disable; +++ self +++ } +++ +++ /// Set the mode with which new directories are created. +++ /// +++ /// Default is 0755 +++ pub fn dir_perm(&mut self, perm: i32) -> &mut CheckoutBuilder<'cb> { +++ self.dir_perm = Some(perm); +++ self +++ } +++ +++ /// Set the mode with which new files are created. +++ /// +++ /// The default is 0644 or 0755 as dictated by the blob. +++ pub fn file_perm(&mut self, perm: i32) -> &mut CheckoutBuilder<'cb> { +++ self.file_perm = Some(perm); +++ self +++ } +++ +++ /// Add a path to be checked out. +++ /// +++ /// The path is a [pathspec] pattern, unless +++ /// [`CheckoutBuilder::disable_pathspec_match`] is set. +++ /// +++ /// If no paths are specified, then all files are checked out. Otherwise +++ /// only these specified paths are checked out. +++ /// +++ /// [pathspec]: https://git-scm.com/docs/gitglossary.html#Documentation/gitglossary.txt-aiddefpathspecapathspec +++ pub fn path(&mut self, path: T) -> &mut CheckoutBuilder<'cb> { +++ let path = util::cstring_to_repo_path(path).unwrap(); +++ self.path_ptrs.push(path.as_ptr()); +++ self.paths.push(path); +++ self +++ } +++ +++ /// Set the directory to check out to +++ pub fn target_dir(&mut self, dst: &Path) -> &mut CheckoutBuilder<'cb> { +++ // Normal file path OK (does not need Windows conversion). +++ self.target_dir = Some(dst.into_c_string().unwrap()); +++ self +++ } +++ +++ /// The name of the common ancestor side of conflicts +++ pub fn ancestor_label(&mut self, label: &str) -> &mut CheckoutBuilder<'cb> { +++ self.ancestor_label = Some(CString::new(label).unwrap()); +++ self +++ } +++ +++ /// The name of the common our side of conflicts +++ pub fn our_label(&mut self, label: &str) -> &mut CheckoutBuilder<'cb> { +++ self.our_label = Some(CString::new(label).unwrap()); +++ self +++ } +++ +++ /// The name of the common their side of conflicts +++ pub fn their_label(&mut self, label: &str) -> &mut CheckoutBuilder<'cb> { +++ self.their_label = Some(CString::new(label).unwrap()); +++ self +++ } +++ +++ /// Set a callback to receive notifications of checkout progress. +++ pub fn progress(&mut self, cb: F) -> &mut CheckoutBuilder<'cb> +++ where +++ F: FnMut(Option<&Path>, usize, usize) + 'cb, +++ { +++ self.progress = Some(Box::new(cb) as Box>); +++ self +++ } +++ +++ /// Set a callback to receive checkout notifications. +++ /// +++ /// Callbacks are invoked prior to modifying any files on disk. +++ /// Returning `false` from the callback will cancel the checkout. +++ pub fn notify(&mut self, cb: F) -> &mut CheckoutBuilder<'cb> +++ where +++ F: FnMut( +++ CheckoutNotificationType, +++ Option<&Path>, +++ Option>, +++ Option>, +++ Option>, +++ ) -> bool +++ + 'cb, +++ { +++ self.notify = Some(Box::new(cb) as Box>); +++ self +++ } +++ +++ /// Configure a raw checkout options based on this configuration. +++ /// +++ /// This method is unsafe as there is no guarantee that this structure will +++ /// outlive the provided checkout options. +++ pub unsafe fn configure(&mut self, opts: &mut raw::git_checkout_options) { +++ opts.version = raw::GIT_CHECKOUT_OPTIONS_VERSION; +++ opts.disable_filters = self.disable_filters as c_int; +++ opts.dir_mode = self.dir_perm.unwrap_or(0) as c_uint; +++ opts.file_mode = self.file_perm.unwrap_or(0) as c_uint; +++ +++ if !self.path_ptrs.is_empty() { +++ opts.paths.strings = self.path_ptrs.as_ptr() as *mut _; +++ opts.paths.count = self.path_ptrs.len() as size_t; +++ } +++ +++ if let Some(ref c) = self.target_dir { +++ opts.target_directory = c.as_ptr(); +++ } +++ if let Some(ref c) = self.ancestor_label { +++ opts.ancestor_label = c.as_ptr(); +++ } +++ if let Some(ref c) = self.our_label { +++ opts.our_label = c.as_ptr(); +++ } +++ if let Some(ref c) = self.their_label { +++ opts.their_label = c.as_ptr(); +++ } +++ if self.progress.is_some() { +++ opts.progress_cb = Some(progress_cb); +++ opts.progress_payload = self as *mut _ as *mut _; +++ } +++ if self.notify.is_some() { +++ opts.notify_cb = Some(notify_cb); +++ opts.notify_payload = self as *mut _ as *mut _; +++ opts.notify_flags = self.notify_flags.bits() as c_uint; +++ } +++ opts.checkout_strategy = self.checkout_opts as c_uint; +++ } +++} +++ +++extern "C" fn progress_cb( +++ path: *const c_char, +++ completed: size_t, +++ total: size_t, +++ data: *mut c_void, +++) { +++ panic::wrap(|| unsafe { +++ let payload = &mut *(data as *mut CheckoutBuilder<'_>); +++ let callback = match payload.progress { +++ Some(ref mut c) => c, +++ None => return, +++ }; +++ let path = if path.is_null() { +++ None +++ } else { +++ Some(util::bytes2path(CStr::from_ptr(path).to_bytes())) +++ }; +++ callback(path, completed as usize, total as usize) +++ }); +++} +++ +++extern "C" fn notify_cb( +++ why: raw::git_checkout_notify_t, +++ path: *const c_char, +++ baseline: *const raw::git_diff_file, +++ target: *const raw::git_diff_file, +++ workdir: *const raw::git_diff_file, +++ data: *mut c_void, +++) -> c_int { +++ // pack callback etc +++ panic::wrap(|| unsafe { +++ let payload = &mut *(data as *mut CheckoutBuilder<'_>); +++ let callback = match payload.notify { +++ Some(ref mut c) => c, +++ None => return 0, +++ }; +++ let path = if path.is_null() { +++ None +++ } else { +++ Some(util::bytes2path(CStr::from_ptr(path).to_bytes())) +++ }; +++ +++ let baseline = if baseline.is_null() { +++ None +++ } else { +++ Some(DiffFile::from_raw(baseline)) +++ }; +++ +++ let target = if target.is_null() { +++ None +++ } else { +++ Some(DiffFile::from_raw(target)) +++ }; +++ +++ let workdir = if workdir.is_null() { +++ None +++ } else { +++ Some(DiffFile::from_raw(workdir)) +++ }; +++ +++ let why = CheckoutNotificationType::from_bits_truncate(why as u32); +++ let keep_going = callback(why, path, baseline, target, workdir); +++ if keep_going { +++ 0 +++ } else { +++ 1 +++ } +++ }) +++ .unwrap_or(2) +++} +++ +++unsafe impl Send for TreeUpdateBuilder {} +++ +++impl Default for TreeUpdateBuilder { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl TreeUpdateBuilder { +++ /// Create a new empty series of updates. +++ pub fn new() -> Self { +++ Self { +++ updates: Vec::new(), +++ paths: Vec::new(), +++ } +++ } +++ +++ /// Add an update removing the specified `path` from a tree. +++ pub fn remove(&mut self, path: T) -> &mut Self { +++ let path = util::cstring_to_repo_path(path).unwrap(); +++ let path_ptr = path.as_ptr(); +++ self.paths.push(path); +++ self.updates.push(raw::git_tree_update { +++ action: raw::GIT_TREE_UPDATE_REMOVE, +++ id: raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }, +++ filemode: raw::GIT_FILEMODE_UNREADABLE, +++ path: path_ptr, +++ }); +++ self +++ } +++ +++ /// Add an update setting the specified `path` to a specific Oid, whether it currently exists +++ /// or not. +++ /// +++ /// Note that libgit2 does not support an upsert of a previously removed path, or an upsert +++ /// that changes the type of an object (such as from tree to blob or vice versa). +++ pub fn upsert(&mut self, path: T, id: Oid, filemode: FileMode) -> &mut Self { +++ let path = util::cstring_to_repo_path(path).unwrap(); +++ let path_ptr = path.as_ptr(); +++ self.paths.push(path); +++ self.updates.push(raw::git_tree_update { +++ action: raw::GIT_TREE_UPDATE_UPSERT, +++ id: unsafe { *id.raw() }, +++ filemode: u32::from(filemode) as raw::git_filemode_t, +++ path: path_ptr, +++ }); +++ self +++ } +++ +++ /// Create a new tree from the specified baseline and this series of updates. +++ /// +++ /// The baseline tree must exist in the specified repository. +++ pub fn create_updated(&mut self, repo: &Repository, baseline: &Tree<'_>) -> Result { +++ let mut ret = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_tree_create_updated( +++ &mut ret, +++ repo.raw(), +++ baseline.raw(), +++ self.updates.len(), +++ self.updates.as_ptr() +++ )); +++ Ok(Binding::from_raw(&ret as *const _)) +++ } +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use super::{CheckoutBuilder, RepoBuilder, TreeUpdateBuilder}; +++ use crate::{CheckoutNotificationType, FileMode, Repository}; +++ use std::fs; +++ use std::path::Path; +++ use tempfile::TempDir; +++ +++ #[test] +++ fn smoke() { +++ let r = RepoBuilder::new().clone("/path/to/nowhere", Path::new("foo")); +++ assert!(r.is_err()); +++ } +++ +++ #[test] +++ fn smoke2() { +++ let td = TempDir::new().unwrap(); +++ Repository::init_bare(&td.path().join("bare")).unwrap(); +++ let url = if cfg!(unix) { +++ format!("file://{}/bare", td.path().display()) +++ } else { +++ format!( +++ "file:///{}/bare", +++ td.path().display().to_string().replace("\\", "/") +++ ) +++ }; +++ +++ let dst = td.path().join("foo"); +++ RepoBuilder::new().clone(&url, &dst).unwrap(); +++ fs::remove_dir_all(&dst).unwrap(); +++ assert!(RepoBuilder::new().branch("foo").clone(&url, &dst).is_err()); +++ } +++ +++ #[test] +++ fn smoke_tree_create_updated() { +++ let (_tempdir, repo) = crate::test::repo_init(); +++ let (_, tree_id) = crate::test::commit(&repo); +++ let tree = t!(repo.find_tree(tree_id)); +++ assert!(tree.get_name("bar").is_none()); +++ let foo_id = tree.get_name("foo").unwrap().id(); +++ let tree2_id = t!(TreeUpdateBuilder::new() +++ .remove("foo") +++ .upsert("bar/baz", foo_id, FileMode::Blob) +++ .create_updated(&repo, &tree)); +++ let tree2 = t!(repo.find_tree(tree2_id)); +++ assert!(tree2.get_name("foo").is_none()); +++ let baz_id = tree2.get_path(Path::new("bar/baz")).unwrap().id(); +++ assert_eq!(foo_id, baz_id); +++ } +++ +++ /// Issue regression test #365 +++ #[test] +++ fn notify_callback() { +++ let td = TempDir::new().unwrap(); +++ let cd = TempDir::new().unwrap(); +++ +++ { +++ let mut opts = crate::RepositoryInitOptions::new(); +++ opts.initial_head("main"); +++ let repo = Repository::init_opts(&td.path(), &opts).unwrap(); +++ +++ let mut config = repo.config().unwrap(); +++ config.set_str("user.name", "name").unwrap(); +++ config.set_str("user.email", "email").unwrap(); +++ +++ let mut index = repo.index().unwrap(); +++ let p = Path::new(td.path()).join("file"); +++ println!("using path {:?}", p); +++ fs::File::create(&p).unwrap(); +++ index.add_path(&Path::new("file")).unwrap(); +++ let id = index.write_tree().unwrap(); +++ +++ let tree = repo.find_tree(id).unwrap(); +++ let sig = repo.signature().unwrap(); +++ repo.commit(Some("HEAD"), &sig, &sig, "initial", &tree, &[]) +++ .unwrap(); +++ } +++ +++ let repo = Repository::open_bare(&td.path().join(".git")).unwrap(); +++ let tree = repo +++ .revparse_single(&"main") +++ .unwrap() +++ .peel_to_tree() +++ .unwrap(); +++ let mut index = repo.index().unwrap(); +++ index.read_tree(&tree).unwrap(); +++ +++ let mut checkout_opts = CheckoutBuilder::new(); +++ checkout_opts.target_dir(&cd.path()); +++ checkout_opts.notify_on(CheckoutNotificationType::all()); +++ checkout_opts.notify(|_notif, _path, baseline, target, workdir| { +++ assert!(baseline.is_none()); +++ assert_eq!(target.unwrap().path(), Some(Path::new("file"))); +++ assert!(workdir.is_none()); +++ true +++ }); +++ repo.checkout_index(Some(&mut index), Some(&mut checkout_opts)) +++ .unwrap(); +++ } +++} diff --cc extra/git2/src/call.rs index 0000000000,0000000000,0000000000..9aa3ae667f new file mode 100644 --- /dev/null +++ b/extra/git2/src/call.rs @@@@ -1,0 -1,0 -1,0 +1,242 @@@@ +++#![macro_use] +++ +++use crate::Error; +++ +++macro_rules! call { +++ (raw::$p:ident ($($e:expr),*)) => ( +++ raw::$p($(crate::call::convert(&$e)),*) +++ ) +++} +++ +++macro_rules! try_call { +++ (raw::$p:ident ($($e:expr),*)) => ({ +++ match crate::call::c_try(raw::$p($(crate::call::convert(&$e)),*)) { +++ Ok(o) => o, +++ Err(e) => { crate::panic::check(); return Err(e) } +++ } +++ }) +++} +++ +++macro_rules! try_call_iter { +++ ($($f:tt)*) => { +++ match call!($($f)*) { +++ 0 => {} +++ raw::GIT_ITEROVER => return None, +++ e => return Some(Err(crate::call::last_error(e))) +++ } +++ } +++} +++ +++#[doc(hidden)] +++pub trait Convert { +++ fn convert(&self) -> T; +++} +++ +++pub fn convert>(u: &U) -> T { +++ u.convert() +++} +++ +++pub fn c_try(ret: libc::c_int) -> Result { +++ match ret { +++ n if n < 0 => Err(last_error(n)), +++ n => Ok(n), +++ } +++} +++ +++pub fn last_error(code: libc::c_int) -> Error { +++ Error::last_error(code) +++} +++ +++mod impls { +++ use std::ffi::CString; +++ use std::ptr; +++ +++ use crate::call::Convert; +++ use crate::{raw, BranchType, ConfigLevel, Direction, ObjectType, ResetType}; +++ use crate::{ +++ AutotagOption, DiffFormat, FetchPrune, FileFavor, SubmoduleIgnore, SubmoduleUpdate, +++ }; +++ +++ impl Convert for T { +++ fn convert(&self) -> T { +++ *self +++ } +++ } +++ +++ impl Convert for bool { +++ fn convert(&self) -> libc::c_int { +++ *self as libc::c_int +++ } +++ } +++ impl<'a, T> Convert<*const T> for &'a T { +++ fn convert(&self) -> *const T { +++ *self as *const T +++ } +++ } +++ impl<'a, T> Convert<*mut T> for &'a mut T { +++ fn convert(&self) -> *mut T { +++ &**self as *const T as *mut T +++ } +++ } +++ impl Convert<*const T> for *mut T { +++ fn convert(&self) -> *const T { +++ *self as *const T +++ } +++ } +++ +++ impl Convert<*const libc::c_char> for CString { +++ fn convert(&self) -> *const libc::c_char { +++ self.as_ptr() +++ } +++ } +++ +++ impl> Convert<*const T> for Option { +++ fn convert(&self) -> *const T { +++ self.as_ref().map(|s| s.convert()).unwrap_or(ptr::null()) +++ } +++ } +++ +++ impl> Convert<*mut T> for Option { +++ fn convert(&self) -> *mut T { +++ self.as_ref() +++ .map(|s| s.convert()) +++ .unwrap_or(ptr::null_mut()) +++ } +++ } +++ +++ impl Convert for ResetType { +++ fn convert(&self) -> raw::git_reset_t { +++ match *self { +++ ResetType::Soft => raw::GIT_RESET_SOFT, +++ ResetType::Hard => raw::GIT_RESET_HARD, +++ ResetType::Mixed => raw::GIT_RESET_MIXED, +++ } +++ } +++ } +++ +++ impl Convert for Direction { +++ fn convert(&self) -> raw::git_direction { +++ match *self { +++ Direction::Push => raw::GIT_DIRECTION_PUSH, +++ Direction::Fetch => raw::GIT_DIRECTION_FETCH, +++ } +++ } +++ } +++ +++ impl Convert for ObjectType { +++ fn convert(&self) -> raw::git_object_t { +++ match *self { +++ ObjectType::Any => raw::GIT_OBJECT_ANY, +++ ObjectType::Commit => raw::GIT_OBJECT_COMMIT, +++ ObjectType::Tree => raw::GIT_OBJECT_TREE, +++ ObjectType::Blob => raw::GIT_OBJECT_BLOB, +++ ObjectType::Tag => raw::GIT_OBJECT_TAG, +++ } +++ } +++ } +++ +++ impl Convert for Option { +++ fn convert(&self) -> raw::git_object_t { +++ self.unwrap_or(ObjectType::Any).convert() +++ } +++ } +++ +++ impl Convert for BranchType { +++ fn convert(&self) -> raw::git_branch_t { +++ match *self { +++ BranchType::Remote => raw::GIT_BRANCH_REMOTE, +++ BranchType::Local => raw::GIT_BRANCH_LOCAL, +++ } +++ } +++ } +++ +++ impl Convert for Option { +++ fn convert(&self) -> raw::git_branch_t { +++ self.map(|s| s.convert()).unwrap_or(raw::GIT_BRANCH_ALL) +++ } +++ } +++ +++ impl Convert for ConfigLevel { +++ fn convert(&self) -> raw::git_config_level_t { +++ match *self { +++ ConfigLevel::ProgramData => raw::GIT_CONFIG_LEVEL_PROGRAMDATA, +++ ConfigLevel::System => raw::GIT_CONFIG_LEVEL_SYSTEM, +++ ConfigLevel::XDG => raw::GIT_CONFIG_LEVEL_XDG, +++ ConfigLevel::Global => raw::GIT_CONFIG_LEVEL_GLOBAL, +++ ConfigLevel::Local => raw::GIT_CONFIG_LEVEL_LOCAL, +++ ConfigLevel::Worktree => raw::GIT_CONFIG_LEVEL_WORKTREE, +++ ConfigLevel::App => raw::GIT_CONFIG_LEVEL_APP, +++ ConfigLevel::Highest => raw::GIT_CONFIG_HIGHEST_LEVEL, +++ } +++ } +++ } +++ +++ impl Convert for DiffFormat { +++ fn convert(&self) -> raw::git_diff_format_t { +++ match *self { +++ DiffFormat::Patch => raw::GIT_DIFF_FORMAT_PATCH, +++ DiffFormat::PatchHeader => raw::GIT_DIFF_FORMAT_PATCH_HEADER, +++ DiffFormat::Raw => raw::GIT_DIFF_FORMAT_RAW, +++ DiffFormat::NameOnly => raw::GIT_DIFF_FORMAT_NAME_ONLY, +++ DiffFormat::NameStatus => raw::GIT_DIFF_FORMAT_NAME_STATUS, +++ DiffFormat::PatchId => raw::GIT_DIFF_FORMAT_PATCH_ID, +++ } +++ } +++ } +++ +++ impl Convert for FileFavor { +++ fn convert(&self) -> raw::git_merge_file_favor_t { +++ match *self { +++ FileFavor::Normal => raw::GIT_MERGE_FILE_FAVOR_NORMAL, +++ FileFavor::Ours => raw::GIT_MERGE_FILE_FAVOR_OURS, +++ FileFavor::Theirs => raw::GIT_MERGE_FILE_FAVOR_THEIRS, +++ FileFavor::Union => raw::GIT_MERGE_FILE_FAVOR_UNION, +++ } +++ } +++ } +++ +++ impl Convert for SubmoduleIgnore { +++ fn convert(&self) -> raw::git_submodule_ignore_t { +++ match *self { +++ SubmoduleIgnore::Unspecified => raw::GIT_SUBMODULE_IGNORE_UNSPECIFIED, +++ SubmoduleIgnore::None => raw::GIT_SUBMODULE_IGNORE_NONE, +++ SubmoduleIgnore::Untracked => raw::GIT_SUBMODULE_IGNORE_UNTRACKED, +++ SubmoduleIgnore::Dirty => raw::GIT_SUBMODULE_IGNORE_DIRTY, +++ SubmoduleIgnore::All => raw::GIT_SUBMODULE_IGNORE_ALL, +++ } +++ } +++ } +++ +++ impl Convert for SubmoduleUpdate { +++ fn convert(&self) -> raw::git_submodule_update_t { +++ match *self { +++ SubmoduleUpdate::Checkout => raw::GIT_SUBMODULE_UPDATE_CHECKOUT, +++ SubmoduleUpdate::Rebase => raw::GIT_SUBMODULE_UPDATE_REBASE, +++ SubmoduleUpdate::Merge => raw::GIT_SUBMODULE_UPDATE_MERGE, +++ SubmoduleUpdate::None => raw::GIT_SUBMODULE_UPDATE_NONE, +++ SubmoduleUpdate::Default => raw::GIT_SUBMODULE_UPDATE_DEFAULT, +++ } +++ } +++ } +++ +++ impl Convert for AutotagOption { +++ fn convert(&self) -> raw::git_remote_autotag_option_t { +++ match *self { +++ AutotagOption::Unspecified => raw::GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, +++ AutotagOption::None => raw::GIT_REMOTE_DOWNLOAD_TAGS_NONE, +++ AutotagOption::Auto => raw::GIT_REMOTE_DOWNLOAD_TAGS_AUTO, +++ AutotagOption::All => raw::GIT_REMOTE_DOWNLOAD_TAGS_ALL, +++ } +++ } +++ } +++ +++ impl Convert for FetchPrune { +++ fn convert(&self) -> raw::git_fetch_prune_t { +++ match *self { +++ FetchPrune::Unspecified => raw::GIT_FETCH_PRUNE_UNSPECIFIED, +++ FetchPrune::On => raw::GIT_FETCH_PRUNE, +++ FetchPrune::Off => raw::GIT_FETCH_NO_PRUNE, +++ } +++ } +++ } +++} diff --cc extra/git2/src/cert.rs index 0000000000,0000000000,0000000000..b232cc3ce8 new file mode 100644 --- /dev/null +++ b/extra/git2/src/cert.rs @@@@ -1,0 -1,0 -1,0 +1,191 @@@@ +++//! Certificate types which are passed to `CertificateCheck` in +++//! `RemoteCallbacks`. +++ +++use std::marker; +++use std::mem; +++use std::slice; +++ +++use crate::raw; +++use crate::util::Binding; +++ +++/// A certificate for a remote connection, viewable as one of `CertHostkey` or +++/// `CertX509` currently. +++pub struct Cert<'a> { +++ raw: *mut raw::git_cert, +++ _marker: marker::PhantomData<&'a raw::git_cert>, +++} +++ +++/// Hostkey information taken from libssh2 +++pub struct CertHostkey<'a> { +++ raw: *mut raw::git_cert_hostkey, +++ _marker: marker::PhantomData<&'a raw::git_cert>, +++} +++ +++/// X.509 certificate information +++pub struct CertX509<'a> { +++ raw: *mut raw::git_cert_x509, +++ _marker: marker::PhantomData<&'a raw::git_cert>, +++} +++ +++/// The SSH host key type. +++#[derive(Copy, Clone, Debug)] +++#[non_exhaustive] +++pub enum SshHostKeyType { +++ /// Unknown key type +++ Unknown = raw::GIT_CERT_SSH_RAW_TYPE_UNKNOWN as isize, +++ /// RSA key type +++ Rsa = raw::GIT_CERT_SSH_RAW_TYPE_RSA as isize, +++ /// DSS key type +++ Dss = raw::GIT_CERT_SSH_RAW_TYPE_DSS as isize, +++ /// ECDSA 256 key type +++ Ecdsa256 = raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_256 as isize, +++ /// ECDSA 384 key type +++ Ecdsa384 = raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_384 as isize, +++ /// ECDSA 521 key type +++ Ecdsa521 = raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_521 as isize, +++ /// ED25519 key type +++ Ed255219 = raw::GIT_CERT_SSH_RAW_TYPE_KEY_ED25519 as isize, +++} +++ +++impl SshHostKeyType { +++ /// The name of the key type as encoded in the known_hosts file. +++ pub fn name(&self) -> &'static str { +++ match self { +++ SshHostKeyType::Unknown => "unknown", +++ SshHostKeyType::Rsa => "ssh-rsa", +++ SshHostKeyType::Dss => "ssh-dss", +++ SshHostKeyType::Ecdsa256 => "ecdsa-sha2-nistp256", +++ SshHostKeyType::Ecdsa384 => "ecdsa-sha2-nistp384", +++ SshHostKeyType::Ecdsa521 => "ecdsa-sha2-nistp521", +++ SshHostKeyType::Ed255219 => "ssh-ed25519", +++ } +++ } +++ +++ /// A short name of the key type, the colloquial form used as a human-readable description. +++ pub fn short_name(&self) -> &'static str { +++ match self { +++ SshHostKeyType::Unknown => "Unknown", +++ SshHostKeyType::Rsa => "RSA", +++ SshHostKeyType::Dss => "DSA", +++ SshHostKeyType::Ecdsa256 => "ECDSA", +++ SshHostKeyType::Ecdsa384 => "ECDSA", +++ SshHostKeyType::Ecdsa521 => "ECDSA", +++ SshHostKeyType::Ed255219 => "ED25519", +++ } +++ } +++} +++ +++impl<'a> Cert<'a> { +++ /// Attempt to view this certificate as an SSH hostkey. +++ /// +++ /// Returns `None` if this is not actually an SSH hostkey. +++ pub fn as_hostkey(&self) -> Option<&CertHostkey<'a>> { +++ self.cast(raw::GIT_CERT_HOSTKEY_LIBSSH2) +++ } +++ +++ /// Attempt to view this certificate as an X.509 certificate. +++ /// +++ /// Returns `None` if this is not actually an X.509 certificate. +++ pub fn as_x509(&self) -> Option<&CertX509<'a>> { +++ self.cast(raw::GIT_CERT_X509) +++ } +++ +++ fn cast(&self, kind: raw::git_cert_t) -> Option<&T> { +++ assert_eq!(mem::size_of::>(), mem::size_of::()); +++ unsafe { +++ if kind == (*self.raw).cert_type { +++ Some(&*(self as *const Cert<'a> as *const T)) +++ } else { +++ None +++ } +++ } +++ } +++} +++ +++impl<'a> CertHostkey<'a> { +++ /// Returns the md5 hash of the hostkey, if available. +++ pub fn hash_md5(&self) -> Option<&[u8; 16]> { +++ unsafe { +++ if (*self.raw).kind as u32 & raw::GIT_CERT_SSH_MD5 as u32 == 0 { +++ None +++ } else { +++ Some(&(*self.raw).hash_md5) +++ } +++ } +++ } +++ +++ /// Returns the SHA-1 hash of the hostkey, if available. +++ pub fn hash_sha1(&self) -> Option<&[u8; 20]> { +++ unsafe { +++ if (*self.raw).kind as u32 & raw::GIT_CERT_SSH_SHA1 as u32 == 0 { +++ None +++ } else { +++ Some(&(*self.raw).hash_sha1) +++ } +++ } +++ } +++ +++ /// Returns the SHA-256 hash of the hostkey, if available. +++ pub fn hash_sha256(&self) -> Option<&[u8; 32]> { +++ unsafe { +++ if (*self.raw).kind as u32 & raw::GIT_CERT_SSH_SHA256 as u32 == 0 { +++ None +++ } else { +++ Some(&(*self.raw).hash_sha256) +++ } +++ } +++ } +++ +++ /// Returns the raw host key. +++ pub fn hostkey(&self) -> Option<&[u8]> { +++ unsafe { +++ if (*self.raw).kind & raw::GIT_CERT_SSH_RAW == 0 { +++ return None; +++ } +++ Some(slice::from_raw_parts( +++ (*self.raw).hostkey as *const u8, +++ (*self.raw).hostkey_len as usize, +++ )) +++ } +++ } +++ +++ /// Returns the type of the host key. +++ pub fn hostkey_type(&self) -> Option { +++ unsafe { +++ if (*self.raw).kind & raw::GIT_CERT_SSH_RAW == 0 { +++ return None; +++ } +++ let t = match (*self.raw).raw_type { +++ raw::GIT_CERT_SSH_RAW_TYPE_UNKNOWN => SshHostKeyType::Unknown, +++ raw::GIT_CERT_SSH_RAW_TYPE_RSA => SshHostKeyType::Rsa, +++ raw::GIT_CERT_SSH_RAW_TYPE_DSS => SshHostKeyType::Dss, +++ raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_256 => SshHostKeyType::Ecdsa256, +++ raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_384 => SshHostKeyType::Ecdsa384, +++ raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_521 => SshHostKeyType::Ecdsa521, +++ raw::GIT_CERT_SSH_RAW_TYPE_KEY_ED25519 => SshHostKeyType::Ed255219, +++ t => panic!("unexpected host key type {:?}", t), +++ }; +++ Some(t) +++ } +++ } +++} +++ +++impl<'a> CertX509<'a> { +++ /// Return the X.509 certificate data as a byte slice +++ pub fn data(&self) -> &[u8] { +++ unsafe { slice::from_raw_parts((*self.raw).data as *const u8, (*self.raw).len as usize) } +++ } +++} +++ +++impl<'a> Binding for Cert<'a> { +++ type Raw = *mut raw::git_cert; +++ unsafe fn from_raw(raw: *mut raw::git_cert) -> Cert<'a> { +++ Cert { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_cert { +++ self.raw +++ } +++} diff --cc extra/git2/src/cherrypick.rs index 0000000000,0000000000,0000000000..659b73089b new file mode 100644 --- /dev/null +++ b/extra/git2/src/cherrypick.rs @@@@ -1,0 -1,0 -1,0 +1,72 @@@@ +++use std::mem; +++ +++use crate::build::CheckoutBuilder; +++use crate::merge::MergeOptions; +++use crate::raw; +++use std::ptr; +++ +++/// Options to specify when cherry picking +++pub struct CherrypickOptions<'cb> { +++ mainline: u32, +++ checkout_builder: Option>, +++ merge_opts: Option, +++} +++ +++impl<'cb> CherrypickOptions<'cb> { +++ /// Creates a default set of cherrypick options +++ pub fn new() -> CherrypickOptions<'cb> { +++ CherrypickOptions { +++ mainline: 0, +++ checkout_builder: None, +++ merge_opts: None, +++ } +++ } +++ +++ /// Set the mainline value +++ /// +++ /// For merge commits, the "mainline" is treated as the parent. +++ pub fn mainline(&mut self, mainline: u32) -> &mut Self { +++ self.mainline = mainline; +++ self +++ } +++ +++ /// Set the checkout builder +++ pub fn checkout_builder(&mut self, cb: CheckoutBuilder<'cb>) -> &mut Self { +++ self.checkout_builder = Some(cb); +++ self +++ } +++ +++ /// Set the merge options +++ pub fn merge_opts(&mut self, merge_opts: MergeOptions) -> &mut Self { +++ self.merge_opts = Some(merge_opts); +++ self +++ } +++ +++ /// Obtain the raw struct +++ pub fn raw(&mut self) -> raw::git_cherrypick_options { +++ unsafe { +++ let mut checkout_opts: raw::git_checkout_options = mem::zeroed(); +++ raw::git_checkout_init_options(&mut checkout_opts, raw::GIT_CHECKOUT_OPTIONS_VERSION); +++ if let Some(ref mut cb) = self.checkout_builder { +++ cb.configure(&mut checkout_opts); +++ } +++ +++ let mut merge_opts: raw::git_merge_options = mem::zeroed(); +++ raw::git_merge_init_options(&mut merge_opts, raw::GIT_MERGE_OPTIONS_VERSION); +++ if let Some(ref opts) = self.merge_opts { +++ ptr::copy(opts.raw(), &mut merge_opts, 1); +++ } +++ +++ let mut cherrypick_opts: raw::git_cherrypick_options = mem::zeroed(); +++ raw::git_cherrypick_init_options( +++ &mut cherrypick_opts, +++ raw::GIT_CHERRYPICK_OPTIONS_VERSION, +++ ); +++ cherrypick_opts.mainline = self.mainline; +++ cherrypick_opts.checkout_opts = checkout_opts; +++ cherrypick_opts.merge_opts = merge_opts; +++ +++ cherrypick_opts +++ } +++ } +++} diff --cc extra/git2/src/commit.rs index 0000000000,0000000000,0000000000..7fef508096 new file mode 100644 --- /dev/null +++ b/extra/git2/src/commit.rs @@@@ -1,0 -1,0 -1,0 +1,472 @@@@ +++use std::iter::FusedIterator; +++use std::marker; +++use std::mem; +++use std::ops::Range; +++use std::ptr; +++use std::str; +++ +++use crate::util::Binding; +++use crate::{raw, signature, Buf, Error, IntoCString, Mailmap, Object, Oid, Signature, Time, Tree}; +++ +++/// A structure to represent a git [commit][1] +++/// +++/// [1]: http://git-scm.com/book/en/Git-Internals-Git-Objects +++pub struct Commit<'repo> { +++ raw: *mut raw::git_commit, +++ _marker: marker::PhantomData>, +++} +++ +++/// An iterator over the parent commits of a commit. +++/// +++/// Aborts iteration when a commit cannot be found +++pub struct Parents<'commit, 'repo> { +++ range: Range, +++ commit: &'commit Commit<'repo>, +++} +++ +++/// An iterator over the parent commits' ids of a commit. +++/// +++/// Aborts iteration when a commit cannot be found +++pub struct ParentIds<'commit> { +++ range: Range, +++ commit: &'commit Commit<'commit>, +++} +++ +++impl<'repo> Commit<'repo> { +++ /// Get the id (SHA1) of a repository commit +++ pub fn id(&self) -> Oid { +++ unsafe { Binding::from_raw(raw::git_commit_id(&*self.raw)) } +++ } +++ +++ /// Get the id of the tree pointed to by this commit. +++ /// +++ /// No attempts are made to fetch an object from the ODB. +++ pub fn tree_id(&self) -> Oid { +++ unsafe { Binding::from_raw(raw::git_commit_tree_id(&*self.raw)) } +++ } +++ +++ /// Get the tree pointed to by a commit. +++ pub fn tree(&self) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_commit_tree(&mut ret, &*self.raw)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Get access to the underlying raw pointer. +++ pub fn raw(&self) -> *mut raw::git_commit { +++ self.raw +++ } +++ +++ /// Get the full message of a commit. +++ /// +++ /// The returned message will be slightly prettified by removing any +++ /// potential leading newlines. +++ /// +++ /// `None` will be returned if the message is not valid utf-8 +++ pub fn message(&self) -> Option<&str> { +++ str::from_utf8(self.message_bytes()).ok() +++ } +++ +++ /// Get the full message of a commit as a byte slice. +++ /// +++ /// The returned message will be slightly prettified by removing any +++ /// potential leading newlines. +++ pub fn message_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, raw::git_commit_message(&*self.raw)).unwrap() } +++ } +++ +++ /// Get the encoding for the message of a commit, as a string representing a +++ /// standard encoding name. +++ /// +++ /// `None` will be returned if the encoding is not known +++ pub fn message_encoding(&self) -> Option<&str> { +++ let bytes = unsafe { crate::opt_bytes(self, raw::git_commit_message_encoding(&*self.raw)) }; +++ bytes.and_then(|b| str::from_utf8(b).ok()) +++ } +++ +++ /// Get the full raw message of a commit. +++ /// +++ /// `None` will be returned if the message is not valid utf-8 +++ pub fn message_raw(&self) -> Option<&str> { +++ str::from_utf8(self.message_raw_bytes()).ok() +++ } +++ +++ /// Get the full raw message of a commit. +++ pub fn message_raw_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, raw::git_commit_message_raw(&*self.raw)).unwrap() } +++ } +++ +++ /// Get the full raw text of the commit header. +++ /// +++ /// `None` will be returned if the message is not valid utf-8 +++ pub fn raw_header(&self) -> Option<&str> { +++ str::from_utf8(self.raw_header_bytes()).ok() +++ } +++ +++ /// Get an arbitrary header field. +++ pub fn header_field_bytes(&self, field: T) -> Result { +++ let buf = Buf::new(); +++ let raw_field = field.into_c_string()?; +++ unsafe { +++ try_call!(raw::git_commit_header_field( +++ buf.raw(), +++ &*self.raw, +++ raw_field +++ )); +++ } +++ Ok(buf) +++ } +++ +++ /// Get the full raw text of the commit header. +++ pub fn raw_header_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, raw::git_commit_raw_header(&*self.raw)).unwrap() } +++ } +++ +++ /// Get the short "summary" of the git commit message. +++ /// +++ /// The returned message is the summary of the commit, comprising the first +++ /// paragraph of the message with whitespace trimmed and squashed. +++ /// +++ /// `None` may be returned if an error occurs or if the summary is not valid +++ /// utf-8. +++ pub fn summary(&self) -> Option<&str> { +++ self.summary_bytes().and_then(|s| str::from_utf8(s).ok()) +++ } +++ +++ /// Get the short "summary" of the git commit message. +++ /// +++ /// The returned message is the summary of the commit, comprising the first +++ /// paragraph of the message with whitespace trimmed and squashed. +++ /// +++ /// `None` may be returned if an error occurs +++ pub fn summary_bytes(&self) -> Option<&[u8]> { +++ unsafe { crate::opt_bytes(self, raw::git_commit_summary(self.raw)) } +++ } +++ +++ /// Get the long "body" of the git commit message. +++ /// +++ /// The returned message is the body of the commit, comprising everything +++ /// but the first paragraph of the message. Leading and trailing whitespaces +++ /// are trimmed. +++ /// +++ /// `None` may be returned if an error occurs or if the summary is not valid +++ /// utf-8. +++ pub fn body(&self) -> Option<&str> { +++ self.body_bytes().and_then(|s| str::from_utf8(s).ok()) +++ } +++ +++ /// Get the long "body" of the git commit message. +++ /// +++ /// The returned message is the body of the commit, comprising everything +++ /// but the first paragraph of the message. Leading and trailing whitespaces +++ /// are trimmed. +++ /// +++ /// `None` may be returned if an error occurs. +++ pub fn body_bytes(&self) -> Option<&[u8]> { +++ unsafe { crate::opt_bytes(self, raw::git_commit_body(self.raw)) } +++ } +++ +++ /// Get the commit time (i.e. committer time) of a commit. +++ /// +++ /// The first element of the tuple is the time, in seconds, since the epoch. +++ /// The second element is the offset, in minutes, of the time zone of the +++ /// committer's preferred time zone. +++ pub fn time(&self) -> Time { +++ unsafe { +++ Time::new( +++ raw::git_commit_time(&*self.raw) as i64, +++ raw::git_commit_time_offset(&*self.raw) as i32, +++ ) +++ } +++ } +++ +++ /// Creates a new iterator over the parents of this commit. +++ pub fn parents<'a>(&'a self) -> Parents<'a, 'repo> { +++ Parents { +++ range: 0..self.parent_count(), +++ commit: self, +++ } +++ } +++ +++ /// Creates a new iterator over the parents of this commit. +++ pub fn parent_ids(&self) -> ParentIds<'_> { +++ ParentIds { +++ range: 0..self.parent_count(), +++ commit: self, +++ } +++ } +++ +++ /// Get the author of this commit. +++ pub fn author(&self) -> Signature<'_> { +++ unsafe { +++ let ptr = raw::git_commit_author(&*self.raw); +++ signature::from_raw_const(self, ptr) +++ } +++ } +++ +++ /// Get the author of this commit, using the mailmap to map names and email +++ /// addresses to canonical real names and email addresses. +++ pub fn author_with_mailmap(&self, mailmap: &Mailmap) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_commit_author_with_mailmap( +++ &mut ret, +++ &*self.raw, +++ &*mailmap.raw() +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Get the committer of this commit. +++ pub fn committer(&self) -> Signature<'_> { +++ unsafe { +++ let ptr = raw::git_commit_committer(&*self.raw); +++ signature::from_raw_const(self, ptr) +++ } +++ } +++ +++ /// Get the committer of this commit, using the mailmap to map names and email +++ /// addresses to canonical real names and email addresses. +++ pub fn committer_with_mailmap(&self, mailmap: &Mailmap) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_commit_committer_with_mailmap( +++ &mut ret, +++ &*self.raw, +++ &*mailmap.raw() +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Amend this existing commit with all non-`None` values +++ /// +++ /// This creates a new commit that is exactly the same as the old commit, +++ /// except that any non-`None` values will be updated. The new commit has +++ /// the same parents as the old commit. +++ /// +++ /// For information about `update_ref`, see [`Repository::commit`]. +++ /// +++ /// [`Repository::commit`]: struct.Repository.html#method.commit +++ pub fn amend( +++ &self, +++ update_ref: Option<&str>, +++ author: Option<&Signature<'_>>, +++ committer: Option<&Signature<'_>>, +++ message_encoding: Option<&str>, +++ message: Option<&str>, +++ tree: Option<&Tree<'repo>>, +++ ) -> Result { +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ let update_ref = crate::opt_cstr(update_ref)?; +++ let encoding = crate::opt_cstr(message_encoding)?; +++ let message = crate::opt_cstr(message)?; +++ unsafe { +++ try_call!(raw::git_commit_amend( +++ &mut raw, +++ self.raw(), +++ update_ref, +++ author.map(|s| s.raw()), +++ committer.map(|s| s.raw()), +++ encoding, +++ message, +++ tree.map(|t| t.raw()) +++ )); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++ +++ /// Get the number of parents of this commit. +++ /// +++ /// Use the `parents` iterator to return an iterator over all parents. +++ pub fn parent_count(&self) -> usize { +++ unsafe { raw::git_commit_parentcount(&*self.raw) as usize } +++ } +++ +++ /// Get the specified parent of the commit. +++ /// +++ /// Use the `parents` iterator to return an iterator over all parents. +++ pub fn parent(&self, i: usize) -> Result, Error> { +++ unsafe { +++ let mut raw = ptr::null_mut(); +++ try_call!(raw::git_commit_parent( +++ &mut raw, +++ &*self.raw, +++ i as libc::c_uint +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Get the specified parent id of the commit. +++ /// +++ /// This is different from `parent`, which will attempt to load the +++ /// parent commit from the ODB. +++ /// +++ /// Use the `parent_ids` iterator to return an iterator over all parents. +++ pub fn parent_id(&self, i: usize) -> Result { +++ unsafe { +++ let id = raw::git_commit_parent_id(self.raw, i as libc::c_uint); +++ if id.is_null() { +++ Err(Error::from_str("parent index out of bounds")) +++ } else { +++ Ok(Binding::from_raw(id)) +++ } +++ } +++ } +++ +++ /// Casts this Commit to be usable as an `Object` +++ pub fn as_object(&self) -> &Object<'repo> { +++ unsafe { &*(self as *const _ as *const Object<'repo>) } +++ } +++ +++ /// Consumes Commit to be returned as an `Object` +++ pub fn into_object(self) -> Object<'repo> { +++ assert_eq!(mem::size_of_val(&self), mem::size_of::>()); +++ unsafe { mem::transmute(self) } +++ } +++} +++ +++impl<'repo> Binding for Commit<'repo> { +++ type Raw = *mut raw::git_commit; +++ unsafe fn from_raw(raw: *mut raw::git_commit) -> Commit<'repo> { +++ Commit { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_commit { +++ self.raw +++ } +++} +++ +++impl<'repo> std::fmt::Debug for Commit<'repo> { +++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +++ let mut ds = f.debug_struct("Commit"); +++ ds.field("id", &self.id()); +++ if let Some(summary) = self.summary() { +++ ds.field("summary", &summary); +++ } +++ ds.finish() +++ } +++} +++ +++/// Aborts iteration when a commit cannot be found +++impl<'repo, 'commit> Iterator for Parents<'commit, 'repo> { +++ type Item = Commit<'repo>; +++ fn next(&mut self) -> Option> { +++ self.range.next().and_then(|i| self.commit.parent(i).ok()) +++ } +++ fn size_hint(&self) -> (usize, Option) { +++ self.range.size_hint() +++ } +++} +++ +++/// Aborts iteration when a commit cannot be found +++impl<'repo, 'commit> DoubleEndedIterator for Parents<'commit, 'repo> { +++ fn next_back(&mut self) -> Option> { +++ self.range +++ .next_back() +++ .and_then(|i| self.commit.parent(i).ok()) +++ } +++} +++ +++impl<'repo, 'commit> FusedIterator for Parents<'commit, 'repo> {} +++ +++impl<'repo, 'commit> ExactSizeIterator for Parents<'commit, 'repo> {} +++ +++/// Aborts iteration when a commit cannot be found +++impl<'commit> Iterator for ParentIds<'commit> { +++ type Item = Oid; +++ fn next(&mut self) -> Option { +++ self.range +++ .next() +++ .and_then(|i| self.commit.parent_id(i).ok()) +++ } +++ fn size_hint(&self) -> (usize, Option) { +++ self.range.size_hint() +++ } +++} +++ +++/// Aborts iteration when a commit cannot be found +++impl<'commit> DoubleEndedIterator for ParentIds<'commit> { +++ fn next_back(&mut self) -> Option { +++ self.range +++ .next_back() +++ .and_then(|i| self.commit.parent_id(i).ok()) +++ } +++} +++ +++impl<'commit> FusedIterator for ParentIds<'commit> {} +++ +++impl<'commit> ExactSizeIterator for ParentIds<'commit> {} +++ +++impl<'repo> Clone for Commit<'repo> { +++ fn clone(&self) -> Self { +++ self.as_object().clone().into_commit().ok().unwrap() +++ } +++} +++ +++impl<'repo> Drop for Commit<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_commit_free(self.raw) } +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ let head = repo.head().unwrap(); +++ let target = head.target().unwrap(); +++ let commit = repo.find_commit(target).unwrap(); +++ assert_eq!(commit.message(), Some("initial\n\nbody")); +++ assert_eq!(commit.body(), Some("body")); +++ assert_eq!(commit.id(), target); +++ commit.message_raw().unwrap(); +++ commit.raw_header().unwrap(); +++ commit.message_encoding(); +++ commit.summary().unwrap(); +++ commit.body().unwrap(); +++ commit.tree_id(); +++ commit.tree().unwrap(); +++ assert_eq!(commit.parents().count(), 0); +++ +++ let tree_header_bytes = commit.header_field_bytes("tree").unwrap(); +++ assert_eq!( +++ crate::Oid::from_str(tree_header_bytes.as_str().unwrap()).unwrap(), +++ commit.tree_id() +++ ); +++ assert_eq!(commit.author().name(), Some("name")); +++ assert_eq!(commit.author().email(), Some("email")); +++ assert_eq!(commit.committer().name(), Some("name")); +++ assert_eq!(commit.committer().email(), Some("email")); +++ +++ let sig = repo.signature().unwrap(); +++ let tree = repo.find_tree(commit.tree_id()).unwrap(); +++ let id = repo +++ .commit(Some("HEAD"), &sig, &sig, "bar", &tree, &[&commit]) +++ .unwrap(); +++ let head = repo.find_commit(id).unwrap(); +++ +++ let new_head = head +++ .amend(Some("HEAD"), None, None, None, Some("new message"), None) +++ .unwrap(); +++ let new_head = repo.find_commit(new_head).unwrap(); +++ assert_eq!(new_head.message(), Some("new message")); +++ new_head.into_object(); +++ +++ repo.find_object(target, None).unwrap().as_commit().unwrap(); +++ repo.find_object(target, None) +++ .unwrap() +++ .into_commit() +++ .ok() +++ .unwrap(); +++ } +++} diff --cc extra/git2/src/config.rs index 0000000000,0000000000,0000000000..9ba0a6da64 new file mode 100644 --- /dev/null +++ b/extra/git2/src/config.rs @@@@ -1,0 -1,0 -1,0 +1,782 @@@@ +++use std::ffi::CString; +++use std::marker; +++use std::path::{Path, PathBuf}; +++use std::ptr; +++use std::str; +++ +++use crate::util::{self, Binding}; +++use crate::{raw, Buf, ConfigLevel, Error, IntoCString}; +++ +++/// A structure representing a git configuration key/value store +++pub struct Config { +++ raw: *mut raw::git_config, +++} +++ +++/// A struct representing a certain entry owned by a `Config` instance. +++/// +++/// An entry has a name, a value, and a level it applies to. +++pub struct ConfigEntry<'cfg> { +++ raw: *mut raw::git_config_entry, +++ _marker: marker::PhantomData<&'cfg Config>, +++ owned: bool, +++} +++ +++/// An iterator over the `ConfigEntry` values of a `Config` structure. +++/// +++/// Due to lifetime restrictions, `ConfigEntries` does not implement the +++/// standard [`Iterator`] trait. It provides a [`next`] function which only +++/// allows access to one entry at a time. [`for_each`] is available as a +++/// convenience function. +++/// +++/// [`next`]: ConfigEntries::next +++/// [`for_each`]: ConfigEntries::for_each +++/// +++/// # Example +++/// +++/// ``` +++/// // Example of how to collect all entries. +++/// use git2::Config; +++/// +++/// let config = Config::new()?; +++/// let iter = config.entries(None)?; +++/// let mut entries = Vec::new(); +++/// iter +++/// .for_each(|entry| { +++/// let name = entry.name().unwrap().to_string(); +++/// let value = entry.value().unwrap_or("").to_string(); +++/// entries.push((name, value)) +++/// })?; +++/// for entry in &entries { +++/// println!("{} = {}", entry.0, entry.1); +++/// } +++/// # Ok::<(), git2::Error>(()) +++/// +++/// ``` +++pub struct ConfigEntries<'cfg> { +++ raw: *mut raw::git_config_iterator, +++ current: Option>, +++ _marker: marker::PhantomData<&'cfg Config>, +++} +++ +++impl Config { +++ /// Allocate a new configuration object +++ /// +++ /// This object is empty, so you have to add a file to it before you can do +++ /// anything with it. +++ pub fn new() -> Result { +++ crate::init(); +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_config_new(&mut raw)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Create a new config instance containing a single on-disk file +++ pub fn open(path: &Path) -> Result { +++ crate::init(); +++ let mut raw = ptr::null_mut(); +++ // Normal file path OK (does not need Windows conversion). +++ let path = path.into_c_string()?; +++ unsafe { +++ try_call!(raw::git_config_open_ondisk(&mut raw, path)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Open the global, XDG and system configuration files +++ /// +++ /// Utility wrapper that finds the global, XDG and system configuration +++ /// files and opens them into a single prioritized config object that can +++ /// be used when accessing default config data outside a repository. +++ pub fn open_default() -> Result { +++ crate::init(); +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_config_open_default(&mut raw)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Locate the path to the global configuration file +++ /// +++ /// The user or global configuration file is usually located in +++ /// `$HOME/.gitconfig`. +++ /// +++ /// This method will try to guess the full path to that file, if the file +++ /// exists. The returned path may be used on any method call to load +++ /// the global configuration file. +++ /// +++ /// This method will not guess the path to the XDG compatible config file +++ /// (`.config/git/config`). +++ pub fn find_global() -> Result { +++ crate::init(); +++ let buf = Buf::new(); +++ unsafe { +++ try_call!(raw::git_config_find_global(buf.raw())); +++ } +++ Ok(util::bytes2path(&buf).to_path_buf()) +++ } +++ +++ /// Locate the path to the system configuration file +++ /// +++ /// If /etc/gitconfig doesn't exist, it will look for `%PROGRAMFILES%` +++ pub fn find_system() -> Result { +++ crate::init(); +++ let buf = Buf::new(); +++ unsafe { +++ try_call!(raw::git_config_find_system(buf.raw())); +++ } +++ Ok(util::bytes2path(&buf).to_path_buf()) +++ } +++ +++ /// Locate the path to the global XDG compatible configuration file +++ /// +++ /// The XDG compatible configuration file is usually located in +++ /// `$HOME/.config/git/config`. +++ pub fn find_xdg() -> Result { +++ crate::init(); +++ let buf = Buf::new(); +++ unsafe { +++ try_call!(raw::git_config_find_xdg(buf.raw())); +++ } +++ Ok(util::bytes2path(&buf).to_path_buf()) +++ } +++ +++ /// Add an on-disk config file instance to an existing config +++ /// +++ /// The on-disk file pointed at by path will be opened and parsed; it's +++ /// expected to be a native Git config file following the default Git config +++ /// syntax (see man git-config). +++ /// +++ /// Further queries on this config object will access each of the config +++ /// file instances in order (instances with a higher priority level will be +++ /// accessed first). +++ pub fn add_file(&mut self, path: &Path, level: ConfigLevel, force: bool) -> Result<(), Error> { +++ // Normal file path OK (does not need Windows conversion). +++ let path = path.into_c_string()?; +++ unsafe { +++ try_call!(raw::git_config_add_file_ondisk( +++ self.raw, +++ path, +++ level, +++ ptr::null(), +++ force +++ )); +++ Ok(()) +++ } +++ } +++ +++ /// Delete a config variable from the config file with the highest level +++ /// (usually the local one). +++ pub fn remove(&mut self, name: &str) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_config_delete_entry(self.raw, name)); +++ Ok(()) +++ } +++ } +++ +++ /// Remove multivar config variables in the config file with the highest level (usually the +++ /// local one). +++ /// +++ /// The regular expression is applied case-sensitively on the value. +++ pub fn remove_multivar(&mut self, name: &str, regexp: &str) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ let regexp = CString::new(regexp)?; +++ unsafe { +++ try_call!(raw::git_config_delete_multivar(self.raw, name, regexp)); +++ } +++ Ok(()) +++ } +++ +++ /// Get the value of a boolean config variable. +++ /// +++ /// All config files will be looked into, in the order of their defined +++ /// level. A higher level means a higher priority. The first occurrence of +++ /// the variable will be returned here. +++ pub fn get_bool(&self, name: &str) -> Result { +++ let mut out = 0 as libc::c_int; +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_config_get_bool(&mut out, &*self.raw, name)); +++ } +++ Ok(out != 0) +++ } +++ +++ /// Get the value of an integer config variable. +++ /// +++ /// All config files will be looked into, in the order of their defined +++ /// level. A higher level means a higher priority. The first occurrence of +++ /// the variable will be returned here. +++ pub fn get_i32(&self, name: &str) -> Result { +++ let mut out = 0i32; +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_config_get_int32(&mut out, &*self.raw, name)); +++ } +++ Ok(out) +++ } +++ +++ /// Get the value of an integer config variable. +++ /// +++ /// All config files will be looked into, in the order of their defined +++ /// level. A higher level means a higher priority. The first occurrence of +++ /// the variable will be returned here. +++ pub fn get_i64(&self, name: &str) -> Result { +++ let mut out = 0i64; +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_config_get_int64(&mut out, &*self.raw, name)); +++ } +++ Ok(out) +++ } +++ +++ /// Get the value of a string config variable. +++ /// +++ /// This is the same as `get_bytes` except that it may return `Err` if +++ /// the bytes are not valid utf-8. +++ /// +++ /// For consistency reasons, this method can only be called on a [`snapshot`]. +++ /// An error will be returned otherwise. +++ /// +++ /// [`snapshot`]: `crate::Config::snapshot` +++ pub fn get_str(&self, name: &str) -> Result<&str, Error> { +++ str::from_utf8(self.get_bytes(name)?) +++ .map_err(|_| Error::from_str("configuration value is not valid utf8")) +++ } +++ +++ /// Get the value of a string config variable as a byte slice. +++ /// +++ /// For consistency reasons, this method can only be called on a [`snapshot`]. +++ /// An error will be returned otherwise. +++ /// +++ /// [`snapshot`]: `crate::Config::snapshot` +++ pub fn get_bytes(&self, name: &str) -> Result<&[u8], Error> { +++ let mut ret = ptr::null(); +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_config_get_string(&mut ret, &*self.raw, name)); +++ Ok(crate::opt_bytes(self, ret).unwrap()) +++ } +++ } +++ +++ /// Get the value of a string config variable as an owned string. +++ /// +++ /// All config files will be looked into, in the order of their +++ /// defined level. A higher level means a higher priority. The +++ /// first occurrence of the variable will be returned here. +++ /// +++ /// An error will be returned if the config value is not valid utf-8. +++ pub fn get_string(&self, name: &str) -> Result { +++ let ret = Buf::new(); +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_config_get_string_buf(ret.raw(), self.raw, name)); +++ } +++ str::from_utf8(&ret) +++ .map(|s| s.to_string()) +++ .map_err(|_| Error::from_str("configuration value is not valid utf8")) +++ } +++ +++ /// Get the value of a path config variable as an owned `PathBuf`. +++ /// +++ /// A leading '~' will be expanded to the global search path (which +++ /// defaults to the user's home directory but can be overridden via +++ /// [`raw::git_libgit2_opts`]. +++ /// +++ /// All config files will be looked into, in the order of their +++ /// defined level. A higher level means a higher priority. The +++ /// first occurrence of the variable will be returned here. +++ pub fn get_path(&self, name: &str) -> Result { +++ let ret = Buf::new(); +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_config_get_path(ret.raw(), self.raw, name)); +++ } +++ Ok(crate::util::bytes2path(&ret).to_path_buf()) +++ } +++ +++ /// Get the ConfigEntry for a config variable. +++ pub fn get_entry(&self, name: &str) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_config_get_entry(&mut ret, self.raw, name)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Iterate over all the config variables +++ /// +++ /// If `glob` is `Some`, then the iterator will only iterate over all +++ /// variables whose name matches the pattern. +++ /// +++ /// The regular expression is applied case-sensitively on the normalized form of +++ /// the variable name: the section and variable parts are lower-cased. The +++ /// subsection is left unchanged. +++ /// +++ /// Due to lifetime restrictions, the returned value does not implement +++ /// the standard [`Iterator`] trait. See [`ConfigEntries`] for more. +++ /// +++ /// # Example +++ /// +++ /// ``` +++ /// use git2::Config; +++ /// +++ /// let cfg = Config::new().unwrap(); +++ /// +++ /// let mut entries = cfg.entries(None).unwrap(); +++ /// while let Some(entry) = entries.next() { +++ /// let entry = entry.unwrap(); +++ /// println!("{} => {}", entry.name().unwrap(), entry.value().unwrap()); +++ /// } +++ /// ``` +++ pub fn entries(&self, glob: Option<&str>) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ match glob { +++ Some(s) => { +++ let s = CString::new(s)?; +++ try_call!(raw::git_config_iterator_glob_new(&mut ret, &*self.raw, s)); +++ } +++ None => { +++ try_call!(raw::git_config_iterator_new(&mut ret, &*self.raw)); +++ } +++ } +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Iterate over the values of a multivar +++ /// +++ /// If `regexp` is `Some`, then the iterator will only iterate over all +++ /// values which match the pattern. +++ /// +++ /// The regular expression is applied case-sensitively on the normalized form of +++ /// the variable name: the section and variable parts are lower-cased. The +++ /// subsection is left unchanged. +++ /// +++ /// Due to lifetime restrictions, the returned value does not implement +++ /// the standard [`Iterator`] trait. See [`ConfigEntries`] for more. +++ pub fn multivar(&self, name: &str, regexp: Option<&str>) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ let name = CString::new(name)?; +++ let regexp = regexp.map(CString::new).transpose()?; +++ unsafe { +++ try_call!(raw::git_config_multivar_iterator_new( +++ &mut ret, &*self.raw, name, regexp +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Open the global/XDG configuration file according to git's rules +++ /// +++ /// Git allows you to store your global configuration at `$HOME/.config` or +++ /// `$XDG_CONFIG_HOME/git/config`. For backwards compatibility, the XDG file +++ /// shouldn't be used unless the use has created it explicitly. With this +++ /// function you'll open the correct one to write to. +++ pub fn open_global(&mut self) -> Result { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_config_open_global(&mut raw, self.raw)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Build a single-level focused config object from a multi-level one. +++ /// +++ /// The returned config object can be used to perform get/set/delete +++ /// operations on a single specific level. +++ pub fn open_level(&self, level: ConfigLevel) -> Result { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_config_open_level(&mut raw, &*self.raw, level)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Set the value of a boolean config variable in the config file with the +++ /// highest level (usually the local one). +++ pub fn set_bool(&mut self, name: &str, value: bool) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_config_set_bool(self.raw, name, value)); +++ } +++ Ok(()) +++ } +++ +++ /// Set the value of an integer config variable in the config file with the +++ /// highest level (usually the local one). +++ pub fn set_i32(&mut self, name: &str, value: i32) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_config_set_int32(self.raw, name, value)); +++ } +++ Ok(()) +++ } +++ +++ /// Set the value of an integer config variable in the config file with the +++ /// highest level (usually the local one). +++ pub fn set_i64(&mut self, name: &str, value: i64) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_config_set_int64(self.raw, name, value)); +++ } +++ Ok(()) +++ } +++ +++ /// Set the value of an multivar config variable in the config file with the +++ /// highest level (usually the local one). +++ /// +++ /// The regular expression is applied case-sensitively on the value. +++ pub fn set_multivar(&mut self, name: &str, regexp: &str, value: &str) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ let regexp = CString::new(regexp)?; +++ let value = CString::new(value)?; +++ unsafe { +++ try_call!(raw::git_config_set_multivar(self.raw, name, regexp, value)); +++ } +++ Ok(()) +++ } +++ +++ /// Set the value of a string config variable in the config file with the +++ /// highest level (usually the local one). +++ pub fn set_str(&mut self, name: &str, value: &str) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ let value = CString::new(value)?; +++ unsafe { +++ try_call!(raw::git_config_set_string(self.raw, name, value)); +++ } +++ Ok(()) +++ } +++ +++ /// Create a snapshot of the configuration +++ /// +++ /// Create a snapshot of the current state of a configuration, which allows +++ /// you to look into a consistent view of the configuration for looking up +++ /// complex values (e.g. a remote, submodule). +++ pub fn snapshot(&mut self) -> Result { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_config_snapshot(&mut ret, self.raw)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Parse a string as a bool. +++ /// +++ /// Interprets "true", "yes", "on", 1, or any non-zero number as true. +++ /// Interprets "false", "no", "off", 0, or an empty string as false. +++ pub fn parse_bool(s: S) -> Result { +++ let s = s.into_c_string()?; +++ let mut out = 0; +++ crate::init(); +++ unsafe { +++ try_call!(raw::git_config_parse_bool(&mut out, s)); +++ } +++ Ok(out != 0) +++ } +++ +++ /// Parse a string as an i32; handles suffixes like k, M, or G, and +++ /// multiplies by the appropriate power of 1024. +++ pub fn parse_i32(s: S) -> Result { +++ let s = s.into_c_string()?; +++ let mut out = 0; +++ crate::init(); +++ unsafe { +++ try_call!(raw::git_config_parse_int32(&mut out, s)); +++ } +++ Ok(out) +++ } +++ +++ /// Parse a string as an i64; handles suffixes like k, M, or G, and +++ /// multiplies by the appropriate power of 1024. +++ pub fn parse_i64(s: S) -> Result { +++ let s = s.into_c_string()?; +++ let mut out = 0; +++ crate::init(); +++ unsafe { +++ try_call!(raw::git_config_parse_int64(&mut out, s)); +++ } +++ Ok(out) +++ } +++} +++ +++impl Binding for Config { +++ type Raw = *mut raw::git_config; +++ unsafe fn from_raw(raw: *mut raw::git_config) -> Config { +++ Config { raw } +++ } +++ fn raw(&self) -> *mut raw::git_config { +++ self.raw +++ } +++} +++ +++impl Drop for Config { +++ fn drop(&mut self) { +++ unsafe { raw::git_config_free(self.raw) } +++ } +++} +++ +++impl<'cfg> ConfigEntry<'cfg> { +++ /// Gets the name of this entry. +++ /// +++ /// May return `None` if the name is not valid utf-8 +++ pub fn name(&self) -> Option<&str> { +++ str::from_utf8(self.name_bytes()).ok() +++ } +++ +++ /// Gets the name of this entry as a byte slice. +++ pub fn name_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, (*self.raw).name).unwrap() } +++ } +++ +++ /// Gets the value of this entry. +++ /// +++ /// May return `None` if the value is not valid utf-8 +++ /// +++ /// # Panics +++ /// +++ /// Panics when no value is defined. +++ pub fn value(&self) -> Option<&str> { +++ str::from_utf8(self.value_bytes()).ok() +++ } +++ +++ /// Gets the value of this entry as a byte slice. +++ /// +++ /// # Panics +++ /// +++ /// Panics when no value is defined. +++ pub fn value_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, (*self.raw).value).unwrap() } +++ } +++ +++ /// Returns `true` when a value is defined otherwise `false`. +++ /// +++ /// No value defined is a short-hand to represent a Boolean `true`. +++ pub fn has_value(&self) -> bool { +++ unsafe { !(*self.raw).value.is_null() } +++ } +++ +++ /// Gets the configuration level of this entry. +++ pub fn level(&self) -> ConfigLevel { +++ unsafe { ConfigLevel::from_raw((*self.raw).level) } +++ } +++ +++ /// Depth of includes where this variable was found +++ pub fn include_depth(&self) -> u32 { +++ unsafe { (*self.raw).include_depth as u32 } +++ } +++} +++ +++impl<'cfg> Binding for ConfigEntry<'cfg> { +++ type Raw = *mut raw::git_config_entry; +++ +++ unsafe fn from_raw(raw: *mut raw::git_config_entry) -> ConfigEntry<'cfg> { +++ ConfigEntry { +++ raw, +++ _marker: marker::PhantomData, +++ owned: true, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_config_entry { +++ self.raw +++ } +++} +++ +++impl<'cfg> Binding for ConfigEntries<'cfg> { +++ type Raw = *mut raw::git_config_iterator; +++ +++ unsafe fn from_raw(raw: *mut raw::git_config_iterator) -> ConfigEntries<'cfg> { +++ ConfigEntries { +++ raw, +++ current: None, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_config_iterator { +++ self.raw +++ } +++} +++ +++impl<'cfg> ConfigEntries<'cfg> { +++ /// Advances the iterator and returns the next value. +++ /// +++ /// Returns `None` when iteration is finished. +++ pub fn next(&mut self) -> Option, Error>> { +++ let mut raw = ptr::null_mut(); +++ drop(self.current.take()); +++ unsafe { +++ try_call_iter!(raw::git_config_next(&mut raw, self.raw)); +++ let entry = ConfigEntry { +++ owned: false, +++ raw, +++ _marker: marker::PhantomData, +++ }; +++ self.current = Some(entry); +++ Some(Ok(self.current.as_ref().unwrap())) +++ } +++ } +++ +++ /// Calls the given closure for each remaining entry in the iterator. +++ pub fn for_each)>(mut self, mut f: F) -> Result<(), Error> { +++ while let Some(entry) = self.next() { +++ let entry = entry?; +++ f(entry); +++ } +++ Ok(()) +++ } +++} +++ +++impl<'cfg> Drop for ConfigEntries<'cfg> { +++ fn drop(&mut self) { +++ unsafe { raw::git_config_iterator_free(self.raw) } +++ } +++} +++ +++impl<'cfg> Drop for ConfigEntry<'cfg> { +++ fn drop(&mut self) { +++ if self.owned { +++ unsafe { raw::git_config_entry_free(self.raw) } +++ } +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use std::fs::File; +++ use tempfile::TempDir; +++ +++ use crate::Config; +++ +++ #[test] +++ fn smoke() { +++ let _cfg = Config::new().unwrap(); +++ let _ = Config::find_global(); +++ let _ = Config::find_system(); +++ let _ = Config::find_xdg(); +++ } +++ +++ #[test] +++ fn persisted() { +++ let td = TempDir::new().unwrap(); +++ let path = td.path().join("foo"); +++ File::create(&path).unwrap(); +++ +++ let mut cfg = Config::open(&path).unwrap(); +++ assert!(cfg.get_bool("foo.bar").is_err()); +++ cfg.set_bool("foo.k1", true).unwrap(); +++ cfg.set_i32("foo.k2", 1).unwrap(); +++ cfg.set_i64("foo.k3", 2).unwrap(); +++ cfg.set_str("foo.k4", "bar").unwrap(); +++ cfg.snapshot().unwrap(); +++ drop(cfg); +++ +++ let cfg = Config::open(&path).unwrap().snapshot().unwrap(); +++ assert_eq!(cfg.get_bool("foo.k1").unwrap(), true); +++ assert_eq!(cfg.get_i32("foo.k2").unwrap(), 1); +++ assert_eq!(cfg.get_i64("foo.k3").unwrap(), 2); +++ assert_eq!(cfg.get_str("foo.k4").unwrap(), "bar"); +++ +++ let mut entries = cfg.entries(None).unwrap(); +++ while let Some(entry) = entries.next() { +++ let entry = entry.unwrap(); +++ entry.name(); +++ entry.value(); +++ entry.level(); +++ } +++ } +++ +++ #[test] +++ fn multivar() { +++ let td = TempDir::new().unwrap(); +++ let path = td.path().join("foo"); +++ File::create(&path).unwrap(); +++ +++ let mut cfg = Config::open(&path).unwrap(); +++ cfg.set_multivar("foo.bar", "^$", "baz").unwrap(); +++ cfg.set_multivar("foo.bar", "^$", "qux").unwrap(); +++ cfg.set_multivar("foo.bar", "^$", "quux").unwrap(); +++ cfg.set_multivar("foo.baz", "^$", "oki").unwrap(); +++ +++ // `entries` filters by name +++ let mut entries: Vec = Vec::new(); +++ cfg.entries(Some("foo.bar")) +++ .unwrap() +++ .for_each(|entry| entries.push(entry.value().unwrap().to_string())) +++ .unwrap(); +++ entries.sort(); +++ assert_eq!(entries, ["baz", "quux", "qux"]); +++ +++ // which is the same as `multivar` without a regex +++ let mut multivals = Vec::new(); +++ cfg.multivar("foo.bar", None) +++ .unwrap() +++ .for_each(|entry| multivals.push(entry.value().unwrap().to_string())) +++ .unwrap(); +++ multivals.sort(); +++ assert_eq!(multivals, entries); +++ +++ // yet _with_ a regex, `multivar` filters by value +++ let mut quxish = Vec::new(); +++ cfg.multivar("foo.bar", Some("qu.*x")) +++ .unwrap() +++ .for_each(|entry| quxish.push(entry.value().unwrap().to_string())) +++ .unwrap(); +++ quxish.sort(); +++ assert_eq!(quxish, ["quux", "qux"]); +++ +++ cfg.remove_multivar("foo.bar", ".*").unwrap(); +++ +++ let count = |entries: super::ConfigEntries<'_>| -> usize { +++ let mut c = 0; +++ entries.for_each(|_| c += 1).unwrap(); +++ c +++ }; +++ +++ assert_eq!(count(cfg.entries(Some("foo.bar")).unwrap()), 0); +++ assert_eq!(count(cfg.multivar("foo.bar", None).unwrap()), 0); +++ } +++ +++ #[test] +++ fn parse() { +++ assert_eq!(Config::parse_bool("").unwrap(), false); +++ assert_eq!(Config::parse_bool("false").unwrap(), false); +++ assert_eq!(Config::parse_bool("no").unwrap(), false); +++ assert_eq!(Config::parse_bool("off").unwrap(), false); +++ assert_eq!(Config::parse_bool("0").unwrap(), false); +++ +++ assert_eq!(Config::parse_bool("true").unwrap(), true); +++ assert_eq!(Config::parse_bool("yes").unwrap(), true); +++ assert_eq!(Config::parse_bool("on").unwrap(), true); +++ assert_eq!(Config::parse_bool("1").unwrap(), true); +++ assert_eq!(Config::parse_bool("42").unwrap(), true); +++ +++ assert!(Config::parse_bool(" ").is_err()); +++ assert!(Config::parse_bool("some-string").is_err()); +++ assert!(Config::parse_bool("-").is_err()); +++ +++ assert_eq!(Config::parse_i32("0").unwrap(), 0); +++ assert_eq!(Config::parse_i32("1").unwrap(), 1); +++ assert_eq!(Config::parse_i32("100").unwrap(), 100); +++ assert_eq!(Config::parse_i32("-1").unwrap(), -1); +++ assert_eq!(Config::parse_i32("-100").unwrap(), -100); +++ assert_eq!(Config::parse_i32("1k").unwrap(), 1024); +++ assert_eq!(Config::parse_i32("4k").unwrap(), 4096); +++ assert_eq!(Config::parse_i32("1M").unwrap(), 1048576); +++ assert_eq!(Config::parse_i32("1G").unwrap(), 1024 * 1024 * 1024); +++ +++ assert_eq!(Config::parse_i64("0").unwrap(), 0); +++ assert_eq!(Config::parse_i64("1").unwrap(), 1); +++ assert_eq!(Config::parse_i64("100").unwrap(), 100); +++ assert_eq!(Config::parse_i64("-1").unwrap(), -1); +++ assert_eq!(Config::parse_i64("-100").unwrap(), -100); +++ assert_eq!(Config::parse_i64("1k").unwrap(), 1024); +++ assert_eq!(Config::parse_i64("4k").unwrap(), 4096); +++ assert_eq!(Config::parse_i64("1M").unwrap(), 1048576); +++ assert_eq!(Config::parse_i64("1G").unwrap(), 1024 * 1024 * 1024); +++ assert_eq!(Config::parse_i64("100G").unwrap(), 100 * 1024 * 1024 * 1024); +++ } +++} diff --cc extra/git2/src/cred.rs index 0000000000,0000000000,0000000000..b1f15cab13 new file mode 100644 --- /dev/null +++ b/extra/git2/src/cred.rs @@@@ -1,0 -1,0 -1,0 +1,725 @@@@ +++use log::{debug, trace}; +++use std::ffi::CString; +++use std::io::Write; +++use std::mem; +++use std::path::Path; +++use std::process::{Command, Stdio}; +++use std::ptr; +++ +++use crate::util::Binding; +++use crate::{raw, Config, Error, IntoCString}; +++ +++/// A structure to represent git credentials in libgit2. +++pub struct Cred { +++ raw: *mut raw::git_cred, +++} +++ +++/// Management of the gitcredentials(7) interface. +++pub struct CredentialHelper { +++ /// A public field representing the currently discovered username from +++ /// configuration. +++ pub username: Option, +++ protocol: Option, +++ host: Option, +++ port: Option, +++ path: Option, +++ url: String, +++ commands: Vec, +++} +++ +++impl Cred { +++ /// Create a "default" credential usable for Negotiate mechanisms like NTLM +++ /// or Kerberos authentication. +++ pub fn default() -> Result { +++ crate::init(); +++ let mut out = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_cred_default_new(&mut out)); +++ Ok(Binding::from_raw(out)) +++ } +++ } +++ +++ /// Create a new ssh key credential object used for querying an ssh-agent. +++ /// +++ /// The username specified is the username to authenticate. +++ pub fn ssh_key_from_agent(username: &str) -> Result { +++ crate::init(); +++ let mut out = ptr::null_mut(); +++ let username = CString::new(username)?; +++ unsafe { +++ try_call!(raw::git_cred_ssh_key_from_agent(&mut out, username)); +++ Ok(Binding::from_raw(out)) +++ } +++ } +++ +++ /// Create a new passphrase-protected ssh key credential object. +++ pub fn ssh_key( +++ username: &str, +++ publickey: Option<&Path>, +++ privatekey: &Path, +++ passphrase: Option<&str>, +++ ) -> Result { +++ crate::init(); +++ let username = CString::new(username)?; +++ let publickey = crate::opt_cstr(publickey)?; +++ let privatekey = privatekey.into_c_string()?; +++ let passphrase = crate::opt_cstr(passphrase)?; +++ let mut out = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_cred_ssh_key_new( +++ &mut out, username, publickey, privatekey, passphrase +++ )); +++ Ok(Binding::from_raw(out)) +++ } +++ } +++ +++ /// Create a new ssh key credential object reading the keys from memory. +++ pub fn ssh_key_from_memory( +++ username: &str, +++ publickey: Option<&str>, +++ privatekey: &str, +++ passphrase: Option<&str>, +++ ) -> Result { +++ crate::init(); +++ let username = CString::new(username)?; +++ let publickey = crate::opt_cstr(publickey)?; +++ let privatekey = CString::new(privatekey)?; +++ let passphrase = crate::opt_cstr(passphrase)?; +++ let mut out = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_cred_ssh_key_memory_new( +++ &mut out, username, publickey, privatekey, passphrase +++ )); +++ Ok(Binding::from_raw(out)) +++ } +++ } +++ +++ /// Create a new plain-text username and password credential object. +++ pub fn userpass_plaintext(username: &str, password: &str) -> Result { +++ crate::init(); +++ let username = CString::new(username)?; +++ let password = CString::new(password)?; +++ let mut out = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_cred_userpass_plaintext_new( +++ &mut out, username, password +++ )); +++ Ok(Binding::from_raw(out)) +++ } +++ } +++ +++ /// Attempt to read `credential.helper` according to gitcredentials(7) [1] +++ /// +++ /// This function will attempt to parse the user's `credential.helper` +++ /// configuration, invoke the necessary processes, and read off what the +++ /// username/password should be for a particular URL. +++ /// +++ /// The returned credential type will be a username/password credential if +++ /// successful. +++ /// +++ /// [1]: https://www.kernel.org/pub/software/scm/git/docs/gitcredentials.html +++ pub fn credential_helper( +++ config: &Config, +++ url: &str, +++ username: Option<&str>, +++ ) -> Result { +++ match CredentialHelper::new(url) +++ .config(config) +++ .username(username) +++ .execute() +++ { +++ Some((username, password)) => Cred::userpass_plaintext(&username, &password), +++ None => Err(Error::from_str( +++ "failed to acquire username/password \ +++ from local configuration", +++ )), +++ } +++ } +++ +++ /// Create a credential to specify a username. +++ /// +++ /// This is used with ssh authentication to query for the username if none is +++ /// specified in the URL. +++ pub fn username(username: &str) -> Result { +++ crate::init(); +++ let username = CString::new(username)?; +++ let mut out = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_cred_username_new(&mut out, username)); +++ Ok(Binding::from_raw(out)) +++ } +++ } +++ +++ /// Check whether a credential object contains username information. +++ pub fn has_username(&self) -> bool { +++ unsafe { raw::git_cred_has_username(self.raw) == 1 } +++ } +++ +++ /// Return the type of credentials that this object represents. +++ pub fn credtype(&self) -> raw::git_credtype_t { +++ unsafe { (*self.raw).credtype } +++ } +++ +++ /// Unwrap access to the underlying raw pointer, canceling the destructor +++ pub unsafe fn unwrap(mut self) -> *mut raw::git_cred { +++ mem::replace(&mut self.raw, ptr::null_mut()) +++ } +++} +++ +++impl Binding for Cred { +++ type Raw = *mut raw::git_cred; +++ +++ unsafe fn from_raw(raw: *mut raw::git_cred) -> Cred { +++ Cred { raw } +++ } +++ fn raw(&self) -> *mut raw::git_cred { +++ self.raw +++ } +++} +++ +++impl Drop for Cred { +++ fn drop(&mut self) { +++ if !self.raw.is_null() { +++ unsafe { +++ if let Some(f) = (*self.raw).free { +++ f(self.raw) +++ } +++ } +++ } +++ } +++} +++ +++impl CredentialHelper { +++ /// Create a new credential helper object which will be used to probe git's +++ /// local credential configuration. +++ /// +++ /// The URL specified is the namespace on which this will query credentials. +++ /// Invalid URLs are currently ignored. +++ pub fn new(url: &str) -> CredentialHelper { +++ let mut ret = CredentialHelper { +++ protocol: None, +++ host: None, +++ port: None, +++ path: None, +++ username: None, +++ url: url.to_string(), +++ commands: Vec::new(), +++ }; +++ +++ // Parse out the (protocol, host) if one is available +++ if let Ok(url) = url::Url::parse(url) { +++ if let Some(url::Host::Domain(s)) = url.host() { +++ ret.host = Some(s.to_string()); +++ } +++ ret.port = url.port(); +++ ret.protocol = Some(url.scheme().to_string()); +++ } +++ ret +++ } +++ +++ /// Set the username that this credential helper will query with. +++ /// +++ /// By default the username is `None`. +++ pub fn username(&mut self, username: Option<&str>) -> &mut CredentialHelper { +++ self.username = username.map(|s| s.to_string()); +++ self +++ } +++ +++ /// Query the specified configuration object to discover commands to +++ /// execute, usernames to query, etc. +++ pub fn config(&mut self, config: &Config) -> &mut CredentialHelper { +++ // Figure out the configured username/helper program. +++ // +++ // see http://git-scm.com/docs/gitcredentials.html#_configuration_options +++ if self.username.is_none() { +++ self.config_username(config); +++ } +++ self.config_helper(config); +++ self.config_use_http_path(config); +++ self +++ } +++ +++ // Configure the queried username from `config` +++ fn config_username(&mut self, config: &Config) { +++ let key = self.exact_key("username"); +++ self.username = config +++ .get_string(&key) +++ .ok() +++ .or_else(|| { +++ self.url_key("username") +++ .and_then(|s| config.get_string(&s).ok()) +++ }) +++ .or_else(|| config.get_string("credential.username").ok()) +++ } +++ +++ // Discover all `helper` directives from `config` +++ fn config_helper(&mut self, config: &Config) { +++ let exact = config.get_string(&self.exact_key("helper")); +++ self.add_command(exact.as_ref().ok().map(|s| &s[..])); +++ if let Some(key) = self.url_key("helper") { +++ let url = config.get_string(&key); +++ self.add_command(url.as_ref().ok().map(|s| &s[..])); +++ } +++ let global = config.get_string("credential.helper"); +++ self.add_command(global.as_ref().ok().map(|s| &s[..])); +++ } +++ +++ // Discover `useHttpPath` from `config` +++ fn config_use_http_path(&mut self, config: &Config) { +++ let mut use_http_path = false; +++ if let Some(value) = config.get_bool(&self.exact_key("useHttpPath")).ok() { +++ use_http_path = value; +++ } else if let Some(value) = self +++ .url_key("useHttpPath") +++ .and_then(|key| config.get_bool(&key).ok()) +++ { +++ use_http_path = value; +++ } else if let Some(value) = config.get_bool("credential.useHttpPath").ok() { +++ use_http_path = value; +++ } +++ +++ if use_http_path { +++ if let Ok(url) = url::Url::parse(&self.url) { +++ let path = url.path(); +++ // Url::parse always includes a leading slash for rooted URLs, while git does not. +++ self.path = Some(path.strip_prefix('/').unwrap_or(path).to_string()); +++ } +++ } +++ } +++ +++ // Add a `helper` configured command to the list of commands to execute. +++ // +++ // see https://www.kernel.org/pub/software/scm/git/docs/technical +++ // /api-credentials.html#_credential_helpers +++ fn add_command(&mut self, cmd: Option<&str>) { +++ let cmd = match cmd { +++ Some("") | None => return, +++ Some(s) => s, +++ }; +++ +++ if cmd.starts_with('!') { +++ self.commands.push(cmd[1..].to_string()); +++ } else if cmd.contains("/") || cmd.contains("\\") { +++ self.commands.push(cmd.to_string()); +++ } else { +++ self.commands.push(format!("git credential-{}", cmd)); +++ } +++ } +++ +++ fn exact_key(&self, name: &str) -> String { +++ format!("credential.{}.{}", self.url, name) +++ } +++ +++ fn url_key(&self, name: &str) -> Option { +++ match (&self.host, &self.protocol) { +++ (&Some(ref host), &Some(ref protocol)) => { +++ Some(format!("credential.{}://{}.{}", protocol, host, name)) +++ } +++ _ => None, +++ } +++ } +++ +++ /// Execute this helper, attempting to discover a username/password pair. +++ /// +++ /// All I/O errors are ignored, (to match git behavior), and this function +++ /// only succeeds if both a username and a password were found +++ pub fn execute(&self) -> Option<(String, String)> { +++ let mut username = self.username.clone(); +++ let mut password = None; +++ for cmd in &self.commands { +++ let (u, p) = self.execute_cmd(cmd, &username); +++ if u.is_some() && username.is_none() { +++ username = u; +++ } +++ if p.is_some() && password.is_none() { +++ password = p; +++ } +++ if username.is_some() && password.is_some() { +++ break; +++ } +++ } +++ +++ match (username, password) { +++ (Some(u), Some(p)) => Some((u, p)), +++ _ => None, +++ } +++ } +++ +++ // Execute the given `cmd`, providing the appropriate variables on stdin and +++ // then afterwards parsing the output into the username/password on stdout. +++ fn execute_cmd( +++ &self, +++ cmd: &str, +++ username: &Option, +++ ) -> (Option, Option) { +++ macro_rules! my_try( ($e:expr) => ( +++ match $e { +++ Ok(e) => e, +++ Err(e) => { +++ debug!("{} failed with {}", stringify!($e), e); +++ return (None, None) +++ } +++ } +++ ) ); +++ +++ // It looks like the `cmd` specification is typically bourne-shell-like +++ // syntax, so try that first. If that fails, though, we may be on a +++ // Windows machine for example where `sh` isn't actually available by +++ // default. Most credential helper configurations though are pretty +++ // simple (aka one or two space-separated strings) so also try to invoke +++ // the process directly. +++ // +++ // If that fails then it's up to the user to put `sh` in path and make +++ // sure it works. +++ let mut c = Command::new("sh"); +++ #[cfg(windows)] +++ { +++ use std::os::windows::process::CommandExt; +++ const CREATE_NO_WINDOW: u32 = 0x08000000; +++ c.creation_flags(CREATE_NO_WINDOW); +++ } +++ c.arg("-c") +++ .arg(&format!("{} get", cmd)) +++ .stdin(Stdio::piped()) +++ .stdout(Stdio::piped()) +++ .stderr(Stdio::piped()); +++ debug!("executing credential helper {:?}", c); +++ let mut p = match c.spawn() { +++ Ok(p) => p, +++ Err(e) => { +++ debug!("`sh` failed to spawn: {}", e); +++ let mut parts = cmd.split_whitespace(); +++ let mut c = Command::new(parts.next().unwrap()); +++ #[cfg(windows)] +++ { +++ use std::os::windows::process::CommandExt; +++ const CREATE_NO_WINDOW: u32 = 0x08000000; +++ c.creation_flags(CREATE_NO_WINDOW); +++ } +++ for arg in parts { +++ c.arg(arg); +++ } +++ c.arg("get") +++ .stdin(Stdio::piped()) +++ .stdout(Stdio::piped()) +++ .stderr(Stdio::piped()); +++ debug!("executing credential helper {:?}", c); +++ match c.spawn() { +++ Ok(p) => p, +++ Err(e) => { +++ debug!("fallback of {:?} failed with {}", cmd, e); +++ return (None, None); +++ } +++ } +++ } +++ }; +++ +++ // Ignore write errors as the command may not actually be listening for +++ // stdin +++ { +++ let stdin = p.stdin.as_mut().unwrap(); +++ if let Some(ref p) = self.protocol { +++ let _ = writeln!(stdin, "protocol={}", p); +++ } +++ if let Some(ref p) = self.host { +++ if let Some(ref p2) = self.port { +++ let _ = writeln!(stdin, "host={}:{}", p, p2); +++ } else { +++ let _ = writeln!(stdin, "host={}", p); +++ } +++ } +++ if let Some(ref p) = self.path { +++ let _ = writeln!(stdin, "path={}", p); +++ } +++ if let Some(ref p) = *username { +++ let _ = writeln!(stdin, "username={}", p); +++ } +++ } +++ let output = my_try!(p.wait_with_output()); +++ if !output.status.success() { +++ debug!( +++ "credential helper failed: {}\nstdout ---\n{}\nstderr ---\n{}", +++ output.status, +++ String::from_utf8_lossy(&output.stdout), +++ String::from_utf8_lossy(&output.stderr) +++ ); +++ return (None, None); +++ } +++ trace!( +++ "credential helper stderr ---\n{}", +++ String::from_utf8_lossy(&output.stderr) +++ ); +++ self.parse_output(output.stdout) +++ } +++ +++ // Parse the output of a command into the username/password found +++ fn parse_output(&self, output: Vec) -> (Option, Option) { +++ // Parse the output of the command, looking for username/password +++ let mut username = None; +++ let mut password = None; +++ for line in output.split(|t| *t == b'\n') { +++ let mut parts = line.splitn(2, |t| *t == b'='); +++ let key = parts.next().unwrap(); +++ let value = match parts.next() { +++ Some(s) => s, +++ None => { +++ trace!("ignoring output line: {}", String::from_utf8_lossy(line)); +++ continue; +++ } +++ }; +++ let value = match String::from_utf8(value.to_vec()) { +++ Ok(s) => s, +++ Err(..) => continue, +++ }; +++ match key { +++ b"username" => username = Some(value), +++ b"password" => password = Some(value), +++ _ => {} +++ } +++ } +++ (username, password) +++ } +++} +++ +++#[cfg(test)] +++mod test { +++ use std::env; +++ use std::fs::File; +++ use std::io::prelude::*; +++ use std::path::Path; +++ use tempfile::TempDir; +++ +++ use crate::{Config, ConfigLevel, Cred, CredentialHelper}; +++ +++ macro_rules! test_cfg( ($($k:expr => $v:expr),*) => ({ +++ let td = TempDir::new().unwrap(); +++ let mut cfg = Config::new().unwrap(); +++ cfg.add_file(&td.path().join("cfg"), ConfigLevel::App, false).unwrap(); +++ $(cfg.set_str($k, $v).unwrap();)* +++ cfg +++ }) ); +++ +++ #[test] +++ fn smoke() { +++ Cred::default().unwrap(); +++ } +++ +++ #[test] +++ fn credential_helper1() { +++ let cfg = test_cfg! { +++ "credential.helper" => "!f() { echo username=a; echo password=b; }; f" +++ }; +++ let (u, p) = CredentialHelper::new("https://example.com/foo/bar") +++ .config(&cfg) +++ .execute() +++ .unwrap(); +++ assert_eq!(u, "a"); +++ assert_eq!(p, "b"); +++ } +++ +++ #[test] +++ fn credential_helper2() { +++ let cfg = test_cfg! {}; +++ assert!(CredentialHelper::new("https://example.com/foo/bar") +++ .config(&cfg) +++ .execute() +++ .is_none()); +++ } +++ +++ #[test] +++ fn credential_helper3() { +++ let cfg = test_cfg! { +++ "credential.https://example.com.helper" => +++ "!f() { echo username=c; }; f", +++ "credential.helper" => "!f() { echo username=a; echo password=b; }; f" +++ }; +++ let (u, p) = CredentialHelper::new("https://example.com/foo/bar") +++ .config(&cfg) +++ .execute() +++ .unwrap(); +++ assert_eq!(u, "c"); +++ assert_eq!(p, "b"); +++ } +++ +++ #[test] +++ fn credential_helper4() { +++ if cfg!(windows) { +++ return; +++ } // shell scripts don't work on Windows +++ +++ let td = TempDir::new().unwrap(); +++ let path = td.path().join("script"); +++ File::create(&path) +++ .unwrap() +++ .write( +++ br"\ +++#!/bin/sh +++echo username=c +++", +++ ) +++ .unwrap(); +++ chmod(&path); +++ let cfg = test_cfg! { +++ "credential.https://example.com.helper" => +++ &path.display().to_string()[..], +++ "credential.helper" => "!f() { echo username=a; echo password=b; }; f" +++ }; +++ let (u, p) = CredentialHelper::new("https://example.com/foo/bar") +++ .config(&cfg) +++ .execute() +++ .unwrap(); +++ assert_eq!(u, "c"); +++ assert_eq!(p, "b"); +++ } +++ +++ #[test] +++ fn credential_helper5() { +++ if cfg!(windows) { +++ return; +++ } // shell scripts don't work on Windows +++ let td = TempDir::new().unwrap(); +++ let path = td.path().join("git-credential-script"); +++ File::create(&path) +++ .unwrap() +++ .write( +++ br"\ +++#!/bin/sh +++echo username=c +++", +++ ) +++ .unwrap(); +++ chmod(&path); +++ +++ let paths = env::var("PATH").unwrap(); +++ let paths = +++ env::split_paths(&paths).chain(path.parent().map(|p| p.to_path_buf()).into_iter()); +++ env::set_var("PATH", &env::join_paths(paths).unwrap()); +++ +++ let cfg = test_cfg! { +++ "credential.https://example.com.helper" => "script", +++ "credential.helper" => "!f() { echo username=a; echo password=b; }; f" +++ }; +++ let (u, p) = CredentialHelper::new("https://example.com/foo/bar") +++ .config(&cfg) +++ .execute() +++ .unwrap(); +++ assert_eq!(u, "c"); +++ assert_eq!(p, "b"); +++ } +++ +++ #[test] +++ fn credential_helper6() { +++ let cfg = test_cfg! { +++ "credential.helper" => "" +++ }; +++ assert!(CredentialHelper::new("https://example.com/foo/bar") +++ .config(&cfg) +++ .execute() +++ .is_none()); +++ } +++ +++ #[test] +++ fn credential_helper7() { +++ if cfg!(windows) { +++ return; +++ } // shell scripts don't work on Windows +++ let td = TempDir::new().unwrap(); +++ let path = td.path().join("script"); +++ File::create(&path) +++ .unwrap() +++ .write( +++ br"\ +++#!/bin/sh +++echo username=$1 +++echo password=$2 +++", +++ ) +++ .unwrap(); +++ chmod(&path); +++ let cfg = test_cfg! { +++ "credential.helper" => &format!("{} a b", path.display()) +++ }; +++ let (u, p) = CredentialHelper::new("https://example.com/foo/bar") +++ .config(&cfg) +++ .execute() +++ .unwrap(); +++ assert_eq!(u, "a"); +++ assert_eq!(p, "b"); +++ } +++ +++ #[test] +++ fn credential_helper8() { +++ let cfg = test_cfg! { +++ "credential.useHttpPath" => "true" +++ }; +++ let mut helper = CredentialHelper::new("https://example.com/foo/bar"); +++ helper.config(&cfg); +++ assert_eq!(helper.path.as_deref(), Some("foo/bar")); +++ } +++ +++ #[test] +++ fn credential_helper9() { +++ let cfg = test_cfg! { +++ "credential.helper" => "!f() { while read line; do eval $line; done; if [ \"$host\" = example.com:3000 ]; then echo username=a; echo password=b; fi; }; f" +++ }; +++ let (u, p) = CredentialHelper::new("https://example.com:3000/foo/bar") +++ .config(&cfg) +++ .execute() +++ .unwrap(); +++ assert_eq!(u, "a"); +++ assert_eq!(p, "b"); +++ } +++ +++ #[test] +++ #[cfg(feature = "ssh")] +++ fn ssh_key_from_memory() { +++ let cred = Cred::ssh_key_from_memory( +++ "test", +++ Some("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDByAO8uj+kXicj6C2ODMspgmUoVyl5eaw8vR6a1yEnFuJFzevabNlN6Ut+CPT3TRnYk5BW73pyXBtnSL2X95BOnbjMDXc4YIkgs3YYHWnxbqsD4Pj/RoGqhf+gwhOBtL0poh8tT8WqXZYxdJQKLQC7oBqf3ykCEYulE4oeRUmNh4IzEE+skD/zDkaJ+S1HRD8D8YCiTO01qQnSmoDFdmIZTi8MS8Cw+O/Qhym1271ThMlhD6PubSYJXfE6rVbE7A9RzH73A6MmKBlzK8VTb4SlNSrr/DOk+L0uq+wPkv+pm+D9WtxoqQ9yl6FaK1cPawa3+7yRNle3m+72KCtyMkQv"), +++ r#" +++ -----BEGIN RSA PRIVATE KEY----- +++ Proc-Type: 4,ENCRYPTED +++ DEK-Info: AES-128-CBC,818C7722D3B01F2161C2ACF6A5BBAAE8 +++ +++ 3Cht4QB3PcoQ0I55j1B3m2ZzIC/mrh+K5nQeA1Vy2GBTMyM7yqGHqTOv7qLhJscd +++ H+cB0Pm6yCr3lYuNrcKWOCUto+91P7ikyARruHVwyIxKdNx15uNulOzQJHQWNbA4 +++ RQHlhjON4atVo2FyJ6n+ujK6QiBg2PR5Vbbw/AtV6zBCFW3PhzDn+qqmHjpBFqj2 +++ vZUUe+MkDQcaF5J45XMHahhSdo/uKCDhfbylExp/+ACWkvxdPpsvcARM6X434ucD +++ aPY+4i0/JyLkdbm0GFN9/q3i53qf4kCBhojFl4AYJdGI0AzAgbdTXZ7EJHbAGZHS +++ os5K0oTwDVXMI0sSE2I/qHxaZZsDP1dOKq6di6SFPUp8liYimm7rNintRX88Gl2L +++ g1ko9abp/NlgD0YY/3mad+NNAISDL/YfXq2fklH3En3/7ZrOVZFKfZXwQwas5g+p +++ VQPKi3+ae74iOjLyuPDSc1ePmhUNYeP+9rLSc0wiaiHqls+2blPPDxAGMEo63kbz +++ YPVjdmuVX4VWnyEsfTxxJdFDYGSNh6rlrrO1RFrex7kJvpg5gTX4M/FT8TfCd7Hn +++ M6adXsLMqwu5tz8FuDmAtVdq8zdSrgZeAbpJ9D3EDOmZ70xz4XBL19ImxDp+Qqs2 +++ kQX7kobRzeeP2URfRoGr7XZikQWyQ2UASfPcQULY8R58QoZWWsQ4w51GZHg7TDnw +++ 1DRo/0OgkK7Gqf215nFmMpB4uyi58cq3WFwWQa1IqslkObpVgBQZcNZb/hKUYPGk +++ g4zehfIgAfCdnQHwZvQ6Fdzhcs3SZeO+zVyuiZN3Gsi9HU0/1vpAKiuuOzcG02vF +++ b6Y6hwsAA9yphF3atI+ARD4ZwXdDfzuGb3yJglMT3Fr/xuLwAvdchRo1spANKA0E +++ tT5okLrK0H4wnHvf2SniVVWRhmJis0lQo9LjGGwRIdsPpVnJSDvaISIVF+fHT90r +++ HvxN8zXI93x9jcPtwp7puQ1C7ehKJK10sZ71OLIZeuUgwt+5DRunqg6evPco9Go7 +++ UOGwcVhLY200KT+1k7zWzCS0yVQp2HRm6cxsZXAp4ClBSwIx15eIoLIrjZdJRjCq +++ COp6pZx1fnvJ9ERIvl5hon+Ty+renMcFKz2HmchC7egpcqIxW9Dsv6zjhHle6pxb +++ 37GaEKHF2KA3RN+dSV/K8n+C9Yent5tx5Y9a/pMcgRGtgu+G+nyFmkPKn5Zt39yX +++ qDpyM0LtbRVZPs+MgiqoGIwYc/ujoCq7GL38gezsBQoHaTt79yYBqCp6UR0LMuZ5 +++ f/7CtWqffgySfJ/0wjGidDAumDv8CK45AURpL/Z+tbFG3M9ar/LZz/Y6EyBcLtGY +++ Wwb4zs8zXIA0qHrjNTnPqHDvezziArYfgPjxCIHMZzms9Yn8+N02p39uIytqg434 +++ BAlCqZ7GYdDFfTpWIwX+segTK9ux0KdBqcQv+9Fwwjkq9KySnRKqNl7ZJcefFZJq +++ c6PA1iinZWBjuaO1HKx3PFulrl0bcpR9Kud1ZIyfnh5rwYN8UQkkcR/wZPla04TY +++ 8l5dq/LI/3G5sZXwUHKOcuQWTj7Saq7Q6gkKoMfqt0wC5bpZ1m17GHPoMz6GtX9O +++ -----END RSA PRIVATE KEY----- +++ "#, +++ Some("test123")); +++ assert!(cred.is_ok()); +++ } +++ +++ #[cfg(unix)] +++ fn chmod(path: &Path) { +++ use std::fs; +++ use std::os::unix::prelude::*; +++ let mut perms = fs::metadata(path).unwrap().permissions(); +++ perms.set_mode(0o755); +++ fs::set_permissions(path, perms).unwrap(); +++ } +++ #[cfg(windows)] +++ fn chmod(_path: &Path) {} +++} diff --cc extra/git2/src/describe.rs index 0000000000,0000000000,0000000000..cbaa1893b6 new file mode 100644 --- /dev/null +++ b/extra/git2/src/describe.rs @@@@ -1,0 -1,0 -1,0 +1,201 @@@@ +++use std::ffi::CString; +++use std::marker; +++use std::mem; +++use std::ptr; +++ +++use libc::{c_int, c_uint}; +++ +++use crate::util::Binding; +++use crate::{raw, Buf, Error, Repository}; +++ +++/// The result of a `describe` operation on either an `Describe` or a +++/// `Repository`. +++pub struct Describe<'repo> { +++ raw: *mut raw::git_describe_result, +++ _marker: marker::PhantomData<&'repo Repository>, +++} +++ +++/// Options which indicate how a `Describe` is created. +++pub struct DescribeOptions { +++ raw: raw::git_describe_options, +++ pattern: CString, +++} +++ +++/// Options which can be used to customize how a description is formatted. +++pub struct DescribeFormatOptions { +++ raw: raw::git_describe_format_options, +++ dirty_suffix: CString, +++} +++ +++impl<'repo> Describe<'repo> { +++ /// Prints this describe result, returning the result as a string. +++ pub fn format(&self, opts: Option<&DescribeFormatOptions>) -> Result { +++ let buf = Buf::new(); +++ let opts = opts.map(|o| &o.raw as *const _).unwrap_or(ptr::null()); +++ unsafe { +++ try_call!(raw::git_describe_format(buf.raw(), self.raw, opts)); +++ } +++ Ok(String::from_utf8(buf.to_vec()).unwrap()) +++ } +++} +++ +++impl<'repo> Binding for Describe<'repo> { +++ type Raw = *mut raw::git_describe_result; +++ +++ unsafe fn from_raw(raw: *mut raw::git_describe_result) -> Describe<'repo> { +++ Describe { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_describe_result { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for Describe<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_describe_result_free(self.raw) } +++ } +++} +++ +++impl Default for DescribeFormatOptions { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl DescribeFormatOptions { +++ /// Creates a new blank set of formatting options for a description. +++ pub fn new() -> DescribeFormatOptions { +++ let mut opts = DescribeFormatOptions { +++ raw: unsafe { mem::zeroed() }, +++ dirty_suffix: CString::new(Vec::new()).unwrap(), +++ }; +++ opts.raw.version = 1; +++ opts.raw.abbreviated_size = 7; +++ opts +++ } +++ +++ /// Sets the size of the abbreviated commit id to use. +++ /// +++ /// The value is the lower bound for the length of the abbreviated string, +++ /// and the default is 7. +++ pub fn abbreviated_size(&mut self, size: u32) -> &mut Self { +++ self.raw.abbreviated_size = size as c_uint; +++ self +++ } +++ +++ /// Sets whether or not the long format is used even when a shorter name +++ /// could be used. +++ pub fn always_use_long_format(&mut self, long: bool) -> &mut Self { +++ self.raw.always_use_long_format = long as c_int; +++ self +++ } +++ +++ /// If the workdir is dirty and this is set, this string will be appended to +++ /// the description string. +++ pub fn dirty_suffix(&mut self, suffix: &str) -> &mut Self { +++ self.dirty_suffix = CString::new(suffix).unwrap(); +++ self.raw.dirty_suffix = self.dirty_suffix.as_ptr(); +++ self +++ } +++} +++ +++impl Default for DescribeOptions { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl DescribeOptions { +++ /// Creates a new blank set of formatting options for a description. +++ pub fn new() -> DescribeOptions { +++ let mut opts = DescribeOptions { +++ raw: unsafe { mem::zeroed() }, +++ pattern: CString::new(Vec::new()).unwrap(), +++ }; +++ opts.raw.version = 1; +++ opts.raw.max_candidates_tags = 10; +++ opts +++ } +++ +++ #[allow(missing_docs)] +++ pub fn max_candidates_tags(&mut self, max: u32) -> &mut Self { +++ self.raw.max_candidates_tags = max as c_uint; +++ self +++ } +++ +++ /// Sets the reference lookup strategy +++ /// +++ /// This behaves like the `--tags` option to git-describe. +++ pub fn describe_tags(&mut self) -> &mut Self { +++ self.raw.describe_strategy = raw::GIT_DESCRIBE_TAGS as c_uint; +++ self +++ } +++ +++ /// Sets the reference lookup strategy +++ /// +++ /// This behaves like the `--all` option to git-describe. +++ pub fn describe_all(&mut self) -> &mut Self { +++ self.raw.describe_strategy = raw::GIT_DESCRIBE_ALL as c_uint; +++ self +++ } +++ +++ /// Indicates when calculating the distance from the matching tag or +++ /// reference whether to only walk down the first-parent ancestry. +++ pub fn only_follow_first_parent(&mut self, follow: bool) -> &mut Self { +++ self.raw.only_follow_first_parent = follow as c_int; +++ self +++ } +++ +++ /// If no matching tag or reference is found whether a describe option would +++ /// normally fail. This option indicates, however, that it will instead fall +++ /// back to showing the full id of the commit. +++ pub fn show_commit_oid_as_fallback(&mut self, show: bool) -> &mut Self { +++ self.raw.show_commit_oid_as_fallback = show as c_int; +++ self +++ } +++ +++ #[allow(missing_docs)] +++ pub fn pattern(&mut self, pattern: &str) -> &mut Self { +++ self.pattern = CString::new(pattern).unwrap(); +++ self.raw.pattern = self.pattern.as_ptr(); +++ self +++ } +++} +++ +++impl Binding for DescribeOptions { +++ type Raw = *mut raw::git_describe_options; +++ +++ unsafe fn from_raw(_raw: *mut raw::git_describe_options) -> DescribeOptions { +++ panic!("unimplemened") +++ } +++ fn raw(&self) -> *mut raw::git_describe_options { +++ &self.raw as *const _ as *mut _ +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::DescribeOptions; +++ +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ let head = t!(repo.head()).target().unwrap(); +++ +++ let d = t!(repo.describe(DescribeOptions::new().show_commit_oid_as_fallback(true))); +++ let id = head.to_string(); +++ assert_eq!(t!(d.format(None)), &id[..7]); +++ +++ let obj = t!(repo.find_object(head, None)); +++ let sig = t!(repo.signature()); +++ t!(repo.tag("foo", &obj, &sig, "message", true)); +++ let d = t!(repo.describe(&DescribeOptions::new())); +++ assert_eq!(t!(d.format(None)), "foo"); +++ +++ let d = t!(obj.describe(&DescribeOptions::new())); +++ assert_eq!(t!(d.format(None)), "foo"); +++ } +++} diff --cc extra/git2/src/diff.rs index 0000000000,0000000000,0000000000..3070550390 new file mode 100644 --- /dev/null +++ b/extra/git2/src/diff.rs @@@@ -1,0 -1,0 -1,0 +1,1863 @@@@ +++use libc::{c_char, c_int, c_void, size_t}; +++use std::ffi::CString; +++use std::iter::FusedIterator; +++use std::marker; +++use std::mem; +++use std::ops::Range; +++use std::path::Path; +++use std::ptr; +++use std::slice; +++ +++use crate::util::{self, Binding}; +++use crate::{panic, raw, Buf, Delta, DiffFormat, Error, FileMode, Oid, Repository}; +++use crate::{DiffFlags, DiffStatsFormat, IntoCString}; +++ +++/// The diff object that contains all individual file deltas. +++/// +++/// This is an opaque structure which will be allocated by one of the diff +++/// generator functions on the `Repository` structure (e.g. `diff_tree_to_tree` +++/// or other `diff_*` functions). +++pub struct Diff<'repo> { +++ raw: *mut raw::git_diff, +++ _marker: marker::PhantomData<&'repo Repository>, +++} +++ +++unsafe impl<'repo> Send for Diff<'repo> {} +++ +++/// Description of changes to one entry. +++pub struct DiffDelta<'a> { +++ raw: *mut raw::git_diff_delta, +++ _marker: marker::PhantomData<&'a raw::git_diff_delta>, +++} +++ +++/// Description of one side of a delta. +++/// +++/// Although this is called a "file" it could represent a file, a symbolic +++/// link, a submodule commit id, or even a tree (although that only happens if +++/// you are tracking type changes or ignored/untracked directories). +++pub struct DiffFile<'a> { +++ raw: *const raw::git_diff_file, +++ _marker: marker::PhantomData<&'a raw::git_diff_file>, +++} +++ +++/// Structure describing options about how the diff should be executed. +++pub struct DiffOptions { +++ pathspec: Vec, +++ pathspec_ptrs: Vec<*const c_char>, +++ old_prefix: Option, +++ new_prefix: Option, +++ raw: raw::git_diff_options, +++} +++ +++/// Control behavior of rename and copy detection +++pub struct DiffFindOptions { +++ raw: raw::git_diff_find_options, +++} +++ +++/// Control behavior of formatting emails +++pub struct DiffFormatEmailOptions { +++ raw: raw::git_diff_format_email_options, +++} +++ +++/// Control behavior of formatting emails +++pub struct DiffPatchidOptions { +++ raw: raw::git_diff_patchid_options, +++} +++ +++/// An iterator over the diffs in a delta +++pub struct Deltas<'diff> { +++ range: Range, +++ diff: &'diff Diff<'diff>, +++} +++ +++/// Structure describing a line (or data span) of a diff. +++pub struct DiffLine<'a> { +++ raw: *const raw::git_diff_line, +++ _marker: marker::PhantomData<&'a raw::git_diff_line>, +++} +++ +++/// Structure describing a hunk of a diff. +++pub struct DiffHunk<'a> { +++ raw: *const raw::git_diff_hunk, +++ _marker: marker::PhantomData<&'a raw::git_diff_hunk>, +++} +++ +++/// Structure describing a hunk of a diff. +++pub struct DiffStats { +++ raw: *mut raw::git_diff_stats, +++} +++ +++/// Structure describing the binary contents of a diff. +++pub struct DiffBinary<'a> { +++ raw: *const raw::git_diff_binary, +++ _marker: marker::PhantomData<&'a raw::git_diff_binary>, +++} +++ +++/// The contents of one of the files in a binary diff. +++pub struct DiffBinaryFile<'a> { +++ raw: *const raw::git_diff_binary_file, +++ _marker: marker::PhantomData<&'a raw::git_diff_binary_file>, +++} +++ +++/// When producing a binary diff, the binary data returned will be +++/// either the deflated full ("literal") contents of the file, or +++/// the deflated binary delta between the two sides (whichever is +++/// smaller). +++#[derive(Copy, Clone, Debug)] +++pub enum DiffBinaryKind { +++ /// There is no binary delta +++ None, +++ /// The binary data is the literal contents of the file +++ Literal, +++ /// The binary data is the delta from one side to the other +++ Delta, +++} +++ +++type PrintCb<'a> = dyn FnMut(DiffDelta<'_>, Option>, DiffLine<'_>) -> bool + 'a; +++ +++pub type FileCb<'a> = dyn FnMut(DiffDelta<'_>, f32) -> bool + 'a; +++pub type BinaryCb<'a> = dyn FnMut(DiffDelta<'_>, DiffBinary<'_>) -> bool + 'a; +++pub type HunkCb<'a> = dyn FnMut(DiffDelta<'_>, DiffHunk<'_>) -> bool + 'a; +++pub type LineCb<'a> = dyn FnMut(DiffDelta<'_>, Option>, DiffLine<'_>) -> bool + 'a; +++ +++pub struct DiffCallbacks<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h> { +++ pub file: Option<&'a mut FileCb<'b>>, +++ pub binary: Option<&'c mut BinaryCb<'d>>, +++ pub hunk: Option<&'e mut HunkCb<'f>>, +++ pub line: Option<&'g mut LineCb<'h>>, +++} +++ +++impl<'repo> Diff<'repo> { +++ /// Merge one diff into another. +++ /// +++ /// This merges items from the "from" list into the "self" list. The +++ /// resulting diff will have all items that appear in either list. +++ /// If an item appears in both lists, then it will be "merged" to appear +++ /// as if the old version was from the "onto" list and the new version +++ /// is from the "from" list (with the exception that if the item has a +++ /// pending DELETE in the middle, then it will show as deleted). +++ pub fn merge(&mut self, from: &Diff<'repo>) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_diff_merge(self.raw, &*from.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Returns an iterator over the deltas in this diff. +++ pub fn deltas(&self) -> Deltas<'_> { +++ let num_deltas = unsafe { raw::git_diff_num_deltas(&*self.raw) }; +++ Deltas { +++ range: 0..(num_deltas as usize), +++ diff: self, +++ } +++ } +++ +++ /// Return the diff delta for an entry in the diff list. +++ pub fn get_delta(&self, i: usize) -> Option> { +++ unsafe { +++ let ptr = raw::git_diff_get_delta(&*self.raw, i as size_t); +++ Binding::from_raw_opt(ptr as *mut _) +++ } +++ } +++ +++ /// Check if deltas are sorted case sensitively or insensitively. +++ pub fn is_sorted_icase(&self) -> bool { +++ unsafe { raw::git_diff_is_sorted_icase(&*self.raw) == 1 } +++ } +++ +++ /// Iterate over a diff generating formatted text output. +++ /// +++ /// Returning `false` from the callback will terminate the iteration and +++ /// return an error from this function. +++ pub fn print(&self, format: DiffFormat, mut cb: F) -> Result<(), Error> +++ where +++ F: FnMut(DiffDelta<'_>, Option>, DiffLine<'_>) -> bool, +++ { +++ let mut cb: &mut PrintCb<'_> = &mut cb; +++ let ptr = &mut cb as *mut _; +++ let print: raw::git_diff_line_cb = Some(print_cb); +++ unsafe { +++ try_call!(raw::git_diff_print(self.raw, format, print, ptr as *mut _)); +++ Ok(()) +++ } +++ } +++ +++ /// Loop over all deltas in a diff issuing callbacks. +++ /// +++ /// Returning `false` from any callback will terminate the iteration and +++ /// return an error from this function. +++ pub fn foreach( +++ &self, +++ file_cb: &mut FileCb<'_>, +++ binary_cb: Option<&mut BinaryCb<'_>>, +++ hunk_cb: Option<&mut HunkCb<'_>>, +++ line_cb: Option<&mut LineCb<'_>>, +++ ) -> Result<(), Error> { +++ let mut cbs = DiffCallbacks { +++ file: Some(file_cb), +++ binary: binary_cb, +++ hunk: hunk_cb, +++ line: line_cb, +++ }; +++ let ptr = &mut cbs as *mut _; +++ unsafe { +++ let binary_cb_c: raw::git_diff_binary_cb = if cbs.binary.is_some() { +++ Some(binary_cb_c) +++ } else { +++ None +++ }; +++ let hunk_cb_c: raw::git_diff_hunk_cb = if cbs.hunk.is_some() { +++ Some(hunk_cb_c) +++ } else { +++ None +++ }; +++ let line_cb_c: raw::git_diff_line_cb = if cbs.line.is_some() { +++ Some(line_cb_c) +++ } else { +++ None +++ }; +++ let file_cb: raw::git_diff_file_cb = Some(file_cb_c); +++ try_call!(raw::git_diff_foreach( +++ self.raw, +++ file_cb, +++ binary_cb_c, +++ hunk_cb_c, +++ line_cb_c, +++ ptr as *mut _ +++ )); +++ Ok(()) +++ } +++ } +++ +++ /// Accumulate diff statistics for all patches. +++ pub fn stats(&self) -> Result { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_diff_get_stats(&mut ret, self.raw)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Transform a diff marking file renames, copies, etc. +++ /// +++ /// This modifies a diff in place, replacing old entries that look like +++ /// renames or copies with new entries reflecting those changes. This also +++ /// will, if requested, break modified files into add/remove pairs if the +++ /// amount of change is above a threshold. +++ pub fn find_similar(&mut self, opts: Option<&mut DiffFindOptions>) -> Result<(), Error> { +++ let opts = opts.map(|opts| &opts.raw); +++ unsafe { +++ try_call!(raw::git_diff_find_similar(self.raw, opts)); +++ } +++ Ok(()) +++ } +++ +++ /// Create an e-mail ready patch from a diff. +++ /// +++ /// Matches the format created by `git format-patch` +++ #[doc(hidden)] +++ #[deprecated(note = "refactored to `Email::from_diff` to match upstream")] +++ pub fn format_email( +++ &mut self, +++ patch_no: usize, +++ total_patches: usize, +++ commit: &crate::Commit<'repo>, +++ opts: Option<&mut DiffFormatEmailOptions>, +++ ) -> Result { +++ assert!(patch_no > 0); +++ assert!(patch_no <= total_patches); +++ let mut default = DiffFormatEmailOptions::default(); +++ let raw_opts = opts.map_or(&mut default.raw, |opts| &mut opts.raw); +++ let summary = commit.summary_bytes().unwrap(); +++ let mut message = commit.message_bytes(); +++ assert!(message.starts_with(summary)); +++ message = &message[summary.len()..]; +++ raw_opts.patch_no = patch_no; +++ raw_opts.total_patches = total_patches; +++ let id = commit.id(); +++ raw_opts.id = id.raw(); +++ raw_opts.summary = summary.as_ptr() as *const _; +++ raw_opts.body = message.as_ptr() as *const _; +++ raw_opts.author = commit.author().raw(); +++ let buf = Buf::new(); +++ #[allow(deprecated)] +++ unsafe { +++ try_call!(raw::git_diff_format_email(buf.raw(), self.raw, &*raw_opts)); +++ } +++ Ok(buf) +++ } +++ +++ /// Create a patch ID from a diff. +++ pub fn patchid(&self, opts: Option<&mut DiffPatchidOptions>) -> Result { +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_diff_patchid( +++ &mut raw, +++ self.raw, +++ opts.map(|o| &mut o.raw) +++ )); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++ +++ // TODO: num_deltas_of_type, find_similar +++} +++impl Diff<'static> { +++ /// Read the contents of a git patch file into a `git_diff` object. +++ /// +++ /// The diff object produced is similar to the one that would be +++ /// produced if you actually produced it computationally by comparing +++ /// two trees, however there may be subtle differences. For example, +++ /// a patch file likely contains abbreviated object IDs, so the +++ /// object IDs parsed by this function will also be abbreviated. +++ pub fn from_buffer(buffer: &[u8]) -> Result, Error> { +++ crate::init(); +++ let mut diff: *mut raw::git_diff = std::ptr::null_mut(); +++ unsafe { +++ // NOTE: Doesn't depend on repo, so lifetime can be 'static +++ try_call!(raw::git_diff_from_buffer( +++ &mut diff, +++ buffer.as_ptr() as *const c_char, +++ buffer.len() +++ )); +++ Ok(Diff::from_raw(diff)) +++ } +++ } +++} +++ +++pub extern "C" fn print_cb( +++ delta: *const raw::git_diff_delta, +++ hunk: *const raw::git_diff_hunk, +++ line: *const raw::git_diff_line, +++ data: *mut c_void, +++) -> c_int { +++ unsafe { +++ let delta = Binding::from_raw(delta as *mut _); +++ let hunk = Binding::from_raw_opt(hunk); +++ let line = Binding::from_raw(line); +++ +++ let r = panic::wrap(|| { +++ let data = data as *mut &mut PrintCb<'_>; +++ (*data)(delta, hunk, line) +++ }); +++ if r == Some(true) { +++ raw::GIT_OK +++ } else { +++ raw::GIT_EUSER +++ } +++ } +++} +++ +++pub extern "C" fn file_cb_c( +++ delta: *const raw::git_diff_delta, +++ progress: f32, +++ data: *mut c_void, +++) -> c_int { +++ unsafe { +++ let delta = Binding::from_raw(delta as *mut _); +++ +++ let r = panic::wrap(|| { +++ let cbs = data as *mut DiffCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; +++ match (*cbs).file { +++ Some(ref mut cb) => cb(delta, progress), +++ None => false, +++ } +++ }); +++ if r == Some(true) { +++ raw::GIT_OK +++ } else { +++ raw::GIT_EUSER +++ } +++ } +++} +++ +++pub extern "C" fn binary_cb_c( +++ delta: *const raw::git_diff_delta, +++ binary: *const raw::git_diff_binary, +++ data: *mut c_void, +++) -> c_int { +++ unsafe { +++ let delta = Binding::from_raw(delta as *mut _); +++ let binary = Binding::from_raw(binary); +++ +++ let r = panic::wrap(|| { +++ let cbs = data as *mut DiffCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; +++ match (*cbs).binary { +++ Some(ref mut cb) => cb(delta, binary), +++ None => false, +++ } +++ }); +++ if r == Some(true) { +++ raw::GIT_OK +++ } else { +++ raw::GIT_EUSER +++ } +++ } +++} +++ +++pub extern "C" fn hunk_cb_c( +++ delta: *const raw::git_diff_delta, +++ hunk: *const raw::git_diff_hunk, +++ data: *mut c_void, +++) -> c_int { +++ unsafe { +++ let delta = Binding::from_raw(delta as *mut _); +++ let hunk = Binding::from_raw(hunk); +++ +++ let r = panic::wrap(|| { +++ let cbs = data as *mut DiffCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; +++ match (*cbs).hunk { +++ Some(ref mut cb) => cb(delta, hunk), +++ None => false, +++ } +++ }); +++ if r == Some(true) { +++ raw::GIT_OK +++ } else { +++ raw::GIT_EUSER +++ } +++ } +++} +++ +++pub extern "C" fn line_cb_c( +++ delta: *const raw::git_diff_delta, +++ hunk: *const raw::git_diff_hunk, +++ line: *const raw::git_diff_line, +++ data: *mut c_void, +++) -> c_int { +++ unsafe { +++ let delta = Binding::from_raw(delta as *mut _); +++ let hunk = Binding::from_raw_opt(hunk); +++ let line = Binding::from_raw(line); +++ +++ let r = panic::wrap(|| { +++ let cbs = data as *mut DiffCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; +++ match (*cbs).line { +++ Some(ref mut cb) => cb(delta, hunk, line), +++ None => false, +++ } +++ }); +++ if r == Some(true) { +++ raw::GIT_OK +++ } else { +++ raw::GIT_EUSER +++ } +++ } +++} +++ +++impl<'repo> Binding for Diff<'repo> { +++ type Raw = *mut raw::git_diff; +++ unsafe fn from_raw(raw: *mut raw::git_diff) -> Diff<'repo> { +++ Diff { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_diff { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for Diff<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_diff_free(self.raw) } +++ } +++} +++ +++impl<'a> DiffDelta<'a> { +++ /// Returns the flags on the delta. +++ /// +++ /// For more information, see `DiffFlags`'s documentation. +++ pub fn flags(&self) -> DiffFlags { +++ let flags = unsafe { (*self.raw).flags }; +++ let mut result = DiffFlags::empty(); +++ +++ #[cfg(target_env = "msvc")] +++ fn as_u32(flag: i32) -> u32 { +++ flag as u32 +++ } +++ #[cfg(not(target_env = "msvc"))] +++ fn as_u32(flag: u32) -> u32 { +++ flag +++ } +++ +++ if (flags & as_u32(raw::GIT_DIFF_FLAG_BINARY)) != 0 { +++ result |= DiffFlags::BINARY; +++ } +++ if (flags & as_u32(raw::GIT_DIFF_FLAG_NOT_BINARY)) != 0 { +++ result |= DiffFlags::NOT_BINARY; +++ } +++ if (flags & as_u32(raw::GIT_DIFF_FLAG_VALID_ID)) != 0 { +++ result |= DiffFlags::VALID_ID; +++ } +++ if (flags & as_u32(raw::GIT_DIFF_FLAG_EXISTS)) != 0 { +++ result |= DiffFlags::EXISTS; +++ } +++ result +++ } +++ +++ // TODO: expose when diffs are more exposed +++ // pub fn similarity(&self) -> u16 { +++ // unsafe { (*self.raw).similarity } +++ // } +++ +++ /// Returns the number of files in this delta. +++ pub fn nfiles(&self) -> u16 { +++ unsafe { (*self.raw).nfiles } +++ } +++ +++ /// Returns the status of this entry +++ /// +++ /// For more information, see `Delta`'s documentation +++ pub fn status(&self) -> Delta { +++ match unsafe { (*self.raw).status } { +++ raw::GIT_DELTA_UNMODIFIED => Delta::Unmodified, +++ raw::GIT_DELTA_ADDED => Delta::Added, +++ raw::GIT_DELTA_DELETED => Delta::Deleted, +++ raw::GIT_DELTA_MODIFIED => Delta::Modified, +++ raw::GIT_DELTA_RENAMED => Delta::Renamed, +++ raw::GIT_DELTA_COPIED => Delta::Copied, +++ raw::GIT_DELTA_IGNORED => Delta::Ignored, +++ raw::GIT_DELTA_UNTRACKED => Delta::Untracked, +++ raw::GIT_DELTA_TYPECHANGE => Delta::Typechange, +++ raw::GIT_DELTA_UNREADABLE => Delta::Unreadable, +++ raw::GIT_DELTA_CONFLICTED => Delta::Conflicted, +++ n => panic!("unknown diff status: {}", n), +++ } +++ } +++ +++ /// Return the file which represents the "from" side of the diff. +++ /// +++ /// What side this means depends on the function that was used to generate +++ /// the diff and will be documented on the function itself. +++ pub fn old_file(&self) -> DiffFile<'a> { +++ unsafe { Binding::from_raw(&(*self.raw).old_file as *const _) } +++ } +++ +++ /// Return the file which represents the "to" side of the diff. +++ /// +++ /// What side this means depends on the function that was used to generate +++ /// the diff and will be documented on the function itself. +++ pub fn new_file(&self) -> DiffFile<'a> { +++ unsafe { Binding::from_raw(&(*self.raw).new_file as *const _) } +++ } +++} +++ +++impl<'a> Binding for DiffDelta<'a> { +++ type Raw = *mut raw::git_diff_delta; +++ unsafe fn from_raw(raw: *mut raw::git_diff_delta) -> DiffDelta<'a> { +++ DiffDelta { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_diff_delta { +++ self.raw +++ } +++} +++ +++impl<'a> std::fmt::Debug for DiffDelta<'a> { +++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +++ f.debug_struct("DiffDelta") +++ .field("nfiles", &self.nfiles()) +++ .field("status", &self.status()) +++ .field("old_file", &self.old_file()) +++ .field("new_file", &self.new_file()) +++ .finish() +++ } +++} +++ +++impl<'a> DiffFile<'a> { +++ /// Returns the Oid of this item. +++ /// +++ /// If this entry represents an absent side of a diff (e.g. the `old_file` +++ /// of a `Added` delta), then the oid returned will be zeroes. +++ pub fn id(&self) -> Oid { +++ unsafe { Binding::from_raw(&(*self.raw).id as *const _) } +++ } +++ +++ /// Returns the path, in bytes, of the entry relative to the working +++ /// directory of the repository. +++ pub fn path_bytes(&self) -> Option<&'a [u8]> { +++ static FOO: () = (); +++ unsafe { crate::opt_bytes(&FOO, (*self.raw).path) } +++ } +++ +++ /// Returns the path of the entry relative to the working directory of the +++ /// repository. +++ pub fn path(&self) -> Option<&'a Path> { +++ self.path_bytes().map(util::bytes2path) +++ } +++ +++ /// Returns the size of this entry, in bytes +++ pub fn size(&self) -> u64 { +++ unsafe { (*self.raw).size as u64 } +++ } +++ +++ /// Returns `true` if file(s) are treated as binary data. +++ pub fn is_binary(&self) -> bool { +++ unsafe { (*self.raw).flags & raw::GIT_DIFF_FLAG_BINARY as u32 != 0 } +++ } +++ +++ /// Returns `true` if file(s) are treated as text data. +++ pub fn is_not_binary(&self) -> bool { +++ unsafe { (*self.raw).flags & raw::GIT_DIFF_FLAG_NOT_BINARY as u32 != 0 } +++ } +++ +++ /// Returns `true` if `id` value is known correct. +++ pub fn is_valid_id(&self) -> bool { +++ unsafe { (*self.raw).flags & raw::GIT_DIFF_FLAG_VALID_ID as u32 != 0 } +++ } +++ +++ /// Returns `true` if file exists at this side of the delta. +++ pub fn exists(&self) -> bool { +++ unsafe { (*self.raw).flags & raw::GIT_DIFF_FLAG_EXISTS as u32 != 0 } +++ } +++ +++ /// Returns file mode. +++ pub fn mode(&self) -> FileMode { +++ match unsafe { (*self.raw).mode.into() } { +++ raw::GIT_FILEMODE_UNREADABLE => FileMode::Unreadable, +++ raw::GIT_FILEMODE_TREE => FileMode::Tree, +++ raw::GIT_FILEMODE_BLOB => FileMode::Blob, +++ raw::GIT_FILEMODE_BLOB_GROUP_WRITABLE => FileMode::BlobGroupWritable, +++ raw::GIT_FILEMODE_BLOB_EXECUTABLE => FileMode::BlobExecutable, +++ raw::GIT_FILEMODE_LINK => FileMode::Link, +++ raw::GIT_FILEMODE_COMMIT => FileMode::Commit, +++ mode => panic!("unknown mode: {}", mode), +++ } +++ } +++} +++ +++impl<'a> Binding for DiffFile<'a> { +++ type Raw = *const raw::git_diff_file; +++ unsafe fn from_raw(raw: *const raw::git_diff_file) -> DiffFile<'a> { +++ DiffFile { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *const raw::git_diff_file { +++ self.raw +++ } +++} +++ +++impl<'a> std::fmt::Debug for DiffFile<'a> { +++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +++ let mut ds = f.debug_struct("DiffFile"); +++ ds.field("id", &self.id()); +++ if let Some(path_bytes) = &self.path_bytes() { +++ ds.field("path_bytes", path_bytes); +++ } +++ if let Some(path) = &self.path() { +++ ds.field("path", path); +++ } +++ ds.field("size", &self.size()).finish() +++ } +++} +++ +++impl Default for DiffOptions { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl DiffOptions { +++ /// Creates a new set of empty diff options. +++ /// +++ /// All flags and other options are defaulted to false or their otherwise +++ /// zero equivalents. +++ pub fn new() -> DiffOptions { +++ let mut opts = DiffOptions { +++ pathspec: Vec::new(), +++ pathspec_ptrs: Vec::new(), +++ raw: unsafe { mem::zeroed() }, +++ old_prefix: None, +++ new_prefix: None, +++ }; +++ assert_eq!(unsafe { raw::git_diff_init_options(&mut opts.raw, 1) }, 0); +++ opts +++ } +++ +++ fn flag(&mut self, opt: raw::git_diff_option_t, val: bool) -> &mut DiffOptions { +++ let opt = opt as u32; +++ if val { +++ self.raw.flags |= opt; +++ } else { +++ self.raw.flags &= !opt; +++ } +++ self +++ } +++ +++ /// Flag indicating whether the sides of the diff will be reversed. +++ pub fn reverse(&mut self, reverse: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_REVERSE, reverse) +++ } +++ +++ /// Flag indicating whether ignored files are included. +++ pub fn include_ignored(&mut self, include: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_INCLUDE_IGNORED, include) +++ } +++ +++ /// Flag indicating whether ignored directories are traversed deeply or not. +++ pub fn recurse_ignored_dirs(&mut self, recurse: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_RECURSE_IGNORED_DIRS, recurse) +++ } +++ +++ /// Flag indicating whether untracked files are in the diff +++ pub fn include_untracked(&mut self, include: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_INCLUDE_UNTRACKED, include) +++ } +++ +++ /// Flag indicating whether untracked directories are traversed deeply or +++ /// not. +++ pub fn recurse_untracked_dirs(&mut self, recurse: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_RECURSE_UNTRACKED_DIRS, recurse) +++ } +++ +++ /// Flag indicating whether unmodified files are in the diff. +++ pub fn include_unmodified(&mut self, include: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_INCLUDE_UNMODIFIED, include) +++ } +++ +++ /// If enabled, then Typechange delta records are generated. +++ pub fn include_typechange(&mut self, include: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_INCLUDE_TYPECHANGE, include) +++ } +++ +++ /// Event with `include_typechange`, the tree returned generally shows a +++ /// deleted blob. This flag correctly labels the tree transitions as a +++ /// typechange record with the `new_file`'s mode set to tree. +++ /// +++ /// Note that the tree SHA will not be available. +++ pub fn include_typechange_trees(&mut self, include: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_INCLUDE_TYPECHANGE_TREES, include) +++ } +++ +++ /// Flag indicating whether file mode changes are ignored. +++ pub fn ignore_filemode(&mut self, ignore: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_IGNORE_FILEMODE, ignore) +++ } +++ +++ /// Flag indicating whether all submodules should be treated as unmodified. +++ pub fn ignore_submodules(&mut self, ignore: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_IGNORE_SUBMODULES, ignore) +++ } +++ +++ /// Flag indicating whether case insensitive filenames should be used. +++ pub fn ignore_case(&mut self, ignore: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_IGNORE_CASE, ignore) +++ } +++ +++ /// If pathspecs are specified, this flag means that they should be applied +++ /// as an exact match instead of a fnmatch pattern. +++ pub fn disable_pathspec_match(&mut self, disable: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_DISABLE_PATHSPEC_MATCH, disable) +++ } +++ +++ /// Disable updating the `binary` flag in delta records. This is useful when +++ /// iterating over a diff if you don't need hunk and data callbacks and want +++ /// to avoid having to load a file completely. +++ pub fn skip_binary_check(&mut self, skip: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_SKIP_BINARY_CHECK, skip) +++ } +++ +++ /// When diff finds an untracked directory, to match the behavior of core +++ /// Git, it scans the contents for ignored and untracked files. If all +++ /// contents are ignored, then the directory is ignored; if any contents are +++ /// not ignored, then the directory is untracked. This is extra work that +++ /// may not matter in many cases. +++ /// +++ /// This flag turns off that scan and immediately labels an untracked +++ /// directory as untracked (changing the behavior to not match core git). +++ pub fn enable_fast_untracked_dirs(&mut self, enable: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS, enable) +++ } +++ +++ /// When diff finds a file in the working directory with stat information +++ /// different from the index, but the OID ends up being the same, write the +++ /// correct stat information into the index. Note: without this flag, diff +++ /// will always leave the index untouched. +++ pub fn update_index(&mut self, update: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_UPDATE_INDEX, update) +++ } +++ +++ /// Include unreadable files in the diff +++ pub fn include_unreadable(&mut self, include: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_INCLUDE_UNREADABLE, include) +++ } +++ +++ /// Include unreadable files in the diff as untracked files +++ pub fn include_unreadable_as_untracked(&mut self, include: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED, include) +++ } +++ +++ /// Treat all files as text, disabling binary attributes and detection. +++ pub fn force_text(&mut self, force: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_FORCE_TEXT, force) +++ } +++ +++ /// Treat all files as binary, disabling text diffs +++ pub fn force_binary(&mut self, force: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_FORCE_BINARY, force) +++ } +++ +++ /// Ignore all whitespace +++ pub fn ignore_whitespace(&mut self, ignore: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_IGNORE_WHITESPACE, ignore) +++ } +++ +++ /// Ignore changes in the amount of whitespace +++ pub fn ignore_whitespace_change(&mut self, ignore: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_IGNORE_WHITESPACE_CHANGE, ignore) +++ } +++ +++ /// Ignore whitespace at the end of line +++ pub fn ignore_whitespace_eol(&mut self, ignore: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_IGNORE_WHITESPACE_EOL, ignore) +++ } +++ +++ /// Ignore blank lines +++ pub fn ignore_blank_lines(&mut self, ignore: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_IGNORE_BLANK_LINES, ignore) +++ } +++ +++ /// When generating patch text, include the content of untracked files. +++ /// +++ /// This automatically turns on `include_untracked` but it does not turn on +++ /// `recurse_untracked_dirs`. Add that flag if you want the content of every +++ /// single untracked file. +++ pub fn show_untracked_content(&mut self, show: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_SHOW_UNTRACKED_CONTENT, show) +++ } +++ +++ /// When generating output, include the names of unmodified files if they +++ /// are included in the `Diff`. Normally these are skipped in the formats +++ /// that list files (e.g. name-only, name-status, raw). Even with this these +++ /// will not be included in the patch format. +++ pub fn show_unmodified(&mut self, show: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_SHOW_UNMODIFIED, show) +++ } +++ +++ /// Use the "patience diff" algorithm +++ pub fn patience(&mut self, patience: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_PATIENCE, patience) +++ } +++ +++ /// Take extra time to find the minimal diff +++ pub fn minimal(&mut self, minimal: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_MINIMAL, minimal) +++ } +++ +++ /// Include the necessary deflate/delta information so that `git-apply` can +++ /// apply given diff information to binary files. +++ pub fn show_binary(&mut self, show: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_SHOW_BINARY, show) +++ } +++ +++ /// Use a heuristic that takes indentation and whitespace into account +++ /// which generally can produce better diffs when dealing with ambiguous +++ /// diff hunks. +++ pub fn indent_heuristic(&mut self, heuristic: bool) -> &mut DiffOptions { +++ self.flag(raw::GIT_DIFF_INDENT_HEURISTIC, heuristic) +++ } +++ +++ /// Set the number of unchanged lines that define the boundary of a hunk +++ /// (and to display before and after). +++ /// +++ /// The default value for this is 3. +++ pub fn context_lines(&mut self, lines: u32) -> &mut DiffOptions { +++ self.raw.context_lines = lines; +++ self +++ } +++ +++ /// Set the maximum number of unchanged lines between hunk boundaries before +++ /// the hunks will be merged into one. +++ /// +++ /// The default value for this is 0. +++ pub fn interhunk_lines(&mut self, lines: u32) -> &mut DiffOptions { +++ self.raw.interhunk_lines = lines; +++ self +++ } +++ +++ /// The default value for this is `core.abbrev` or 7 if unset. +++ pub fn id_abbrev(&mut self, abbrev: u16) -> &mut DiffOptions { +++ self.raw.id_abbrev = abbrev; +++ self +++ } +++ +++ /// Maximum size (in bytes) above which a blob will be marked as binary +++ /// automatically. +++ /// +++ /// A negative value will disable this entirely. +++ /// +++ /// The default value for this is 512MB. +++ pub fn max_size(&mut self, size: i64) -> &mut DiffOptions { +++ self.raw.max_size = size as raw::git_off_t; +++ self +++ } +++ +++ /// The virtual "directory" to prefix old file names with in hunk headers. +++ /// +++ /// The default value for this is "a". +++ pub fn old_prefix(&mut self, t: T) -> &mut DiffOptions { +++ self.old_prefix = Some(t.into_c_string().unwrap()); +++ self +++ } +++ +++ /// The virtual "directory" to prefix new file names with in hunk headers. +++ /// +++ /// The default value for this is "b". +++ pub fn new_prefix(&mut self, t: T) -> &mut DiffOptions { +++ self.new_prefix = Some(t.into_c_string().unwrap()); +++ self +++ } +++ +++ /// Add to the array of paths/fnmatch patterns to constrain the diff. +++ pub fn pathspec(&mut self, pathspec: T) -> &mut DiffOptions { +++ let s = util::cstring_to_repo_path(pathspec).unwrap(); +++ self.pathspec_ptrs.push(s.as_ptr()); +++ self.pathspec.push(s); +++ self +++ } +++ +++ /// Acquire a pointer to the underlying raw options. +++ /// +++ /// This function is unsafe as the pointer is only valid so long as this +++ /// structure is not moved, modified, or used elsewhere. +++ pub unsafe fn raw(&mut self) -> *const raw::git_diff_options { +++ self.raw.old_prefix = self +++ .old_prefix +++ .as_ref() +++ .map(|s| s.as_ptr()) +++ .unwrap_or(ptr::null()); +++ self.raw.new_prefix = self +++ .new_prefix +++ .as_ref() +++ .map(|s| s.as_ptr()) +++ .unwrap_or(ptr::null()); +++ self.raw.pathspec.count = self.pathspec_ptrs.len() as size_t; +++ self.raw.pathspec.strings = self.pathspec_ptrs.as_ptr() as *mut _; +++ &self.raw as *const _ +++ } +++ +++ // TODO: expose ignore_submodules, notify_cb/notify_payload +++} +++ +++impl<'diff> Iterator for Deltas<'diff> { +++ type Item = DiffDelta<'diff>; +++ fn next(&mut self) -> Option> { +++ self.range.next().and_then(|i| self.diff.get_delta(i)) +++ } +++ fn size_hint(&self) -> (usize, Option) { +++ self.range.size_hint() +++ } +++} +++impl<'diff> DoubleEndedIterator for Deltas<'diff> { +++ fn next_back(&mut self) -> Option> { +++ self.range.next_back().and_then(|i| self.diff.get_delta(i)) +++ } +++} +++impl<'diff> FusedIterator for Deltas<'diff> {} +++ +++impl<'diff> ExactSizeIterator for Deltas<'diff> {} +++ +++/// Line origin constants. +++#[derive(Copy, Clone, Debug, PartialEq)] +++pub enum DiffLineType { +++ /// These values will be sent to `git_diff_line_cb` along with the line +++ Context, +++ /// +++ Addition, +++ /// +++ Deletion, +++ /// Both files have no LF at end +++ ContextEOFNL, +++ /// Old has no LF at end, new does +++ AddEOFNL, +++ /// Old has LF at end, new does not +++ DeleteEOFNL, +++ /// The following values will only be sent to a `git_diff_line_cb` when +++ /// the content of a diff is being formatted through `git_diff_print`. +++ FileHeader, +++ /// +++ HunkHeader, +++ /// For "Binary files x and y differ" +++ Binary, +++} +++ +++impl Binding for DiffLineType { +++ type Raw = raw::git_diff_line_t; +++ unsafe fn from_raw(raw: raw::git_diff_line_t) -> Self { +++ match raw { +++ raw::GIT_DIFF_LINE_CONTEXT => DiffLineType::Context, +++ raw::GIT_DIFF_LINE_ADDITION => DiffLineType::Addition, +++ raw::GIT_DIFF_LINE_DELETION => DiffLineType::Deletion, +++ raw::GIT_DIFF_LINE_CONTEXT_EOFNL => DiffLineType::ContextEOFNL, +++ raw::GIT_DIFF_LINE_ADD_EOFNL => DiffLineType::AddEOFNL, +++ raw::GIT_DIFF_LINE_DEL_EOFNL => DiffLineType::DeleteEOFNL, +++ raw::GIT_DIFF_LINE_FILE_HDR => DiffLineType::FileHeader, +++ raw::GIT_DIFF_LINE_HUNK_HDR => DiffLineType::HunkHeader, +++ raw::GIT_DIFF_LINE_BINARY => DiffLineType::Binary, +++ _ => panic!("Unknown git diff line type"), +++ } +++ } +++ fn raw(&self) -> raw::git_diff_line_t { +++ match *self { +++ DiffLineType::Context => raw::GIT_DIFF_LINE_CONTEXT, +++ DiffLineType::Addition => raw::GIT_DIFF_LINE_ADDITION, +++ DiffLineType::Deletion => raw::GIT_DIFF_LINE_DELETION, +++ DiffLineType::ContextEOFNL => raw::GIT_DIFF_LINE_CONTEXT_EOFNL, +++ DiffLineType::AddEOFNL => raw::GIT_DIFF_LINE_ADD_EOFNL, +++ DiffLineType::DeleteEOFNL => raw::GIT_DIFF_LINE_DEL_EOFNL, +++ DiffLineType::FileHeader => raw::GIT_DIFF_LINE_FILE_HDR, +++ DiffLineType::HunkHeader => raw::GIT_DIFF_LINE_HUNK_HDR, +++ DiffLineType::Binary => raw::GIT_DIFF_LINE_BINARY, +++ } +++ } +++} +++ +++impl<'a> DiffLine<'a> { +++ /// Line number in old file or `None` for added line +++ pub fn old_lineno(&self) -> Option { +++ match unsafe { (*self.raw).old_lineno } { +++ n if n < 0 => None, +++ n => Some(n as u32), +++ } +++ } +++ +++ /// Line number in new file or `None` for deleted line +++ pub fn new_lineno(&self) -> Option { +++ match unsafe { (*self.raw).new_lineno } { +++ n if n < 0 => None, +++ n => Some(n as u32), +++ } +++ } +++ +++ /// Number of newline characters in content +++ pub fn num_lines(&self) -> u32 { +++ unsafe { (*self.raw).num_lines as u32 } +++ } +++ +++ /// Offset in the original file to the content +++ pub fn content_offset(&self) -> i64 { +++ unsafe { (*self.raw).content_offset as i64 } +++ } +++ +++ /// Content of this line as bytes. +++ pub fn content(&self) -> &'a [u8] { +++ unsafe { +++ slice::from_raw_parts( +++ (*self.raw).content as *const u8, +++ (*self.raw).content_len as usize, +++ ) +++ } +++ } +++ +++ /// origin of this `DiffLine`. +++ /// +++ pub fn origin_value(&self) -> DiffLineType { +++ unsafe { Binding::from_raw((*self.raw).origin as raw::git_diff_line_t) } +++ } +++ +++ /// Sigil showing the origin of this `DiffLine`. +++ /// +++ /// * ` ` - Line context +++ /// * `+` - Line addition +++ /// * `-` - Line deletion +++ /// * `=` - Context (End of file) +++ /// * `>` - Add (End of file) +++ /// * `<` - Remove (End of file) +++ /// * `F` - File header +++ /// * `H` - Hunk header +++ /// * `B` - Line binary +++ pub fn origin(&self) -> char { +++ match unsafe { (*self.raw).origin as raw::git_diff_line_t } { +++ raw::GIT_DIFF_LINE_CONTEXT => ' ', +++ raw::GIT_DIFF_LINE_ADDITION => '+', +++ raw::GIT_DIFF_LINE_DELETION => '-', +++ raw::GIT_DIFF_LINE_CONTEXT_EOFNL => '=', +++ raw::GIT_DIFF_LINE_ADD_EOFNL => '>', +++ raw::GIT_DIFF_LINE_DEL_EOFNL => '<', +++ raw::GIT_DIFF_LINE_FILE_HDR => 'F', +++ raw::GIT_DIFF_LINE_HUNK_HDR => 'H', +++ raw::GIT_DIFF_LINE_BINARY => 'B', +++ _ => ' ', +++ } +++ } +++} +++ +++impl<'a> Binding for DiffLine<'a> { +++ type Raw = *const raw::git_diff_line; +++ unsafe fn from_raw(raw: *const raw::git_diff_line) -> DiffLine<'a> { +++ DiffLine { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *const raw::git_diff_line { +++ self.raw +++ } +++} +++ +++impl<'a> std::fmt::Debug for DiffLine<'a> { +++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +++ let mut ds = f.debug_struct("DiffLine"); +++ if let Some(old_lineno) = &self.old_lineno() { +++ ds.field("old_lineno", old_lineno); +++ } +++ if let Some(new_lineno) = &self.new_lineno() { +++ ds.field("new_lineno", new_lineno); +++ } +++ ds.field("num_lines", &self.num_lines()) +++ .field("content_offset", &self.content_offset()) +++ .field("content", &self.content()) +++ .field("origin", &self.origin()) +++ .finish() +++ } +++} +++ +++impl<'a> DiffHunk<'a> { +++ /// Starting line number in old_file +++ pub fn old_start(&self) -> u32 { +++ unsafe { (*self.raw).old_start as u32 } +++ } +++ +++ /// Number of lines in old_file +++ pub fn old_lines(&self) -> u32 { +++ unsafe { (*self.raw).old_lines as u32 } +++ } +++ +++ /// Starting line number in new_file +++ pub fn new_start(&self) -> u32 { +++ unsafe { (*self.raw).new_start as u32 } +++ } +++ +++ /// Number of lines in new_file +++ pub fn new_lines(&self) -> u32 { +++ unsafe { (*self.raw).new_lines as u32 } +++ } +++ +++ /// Header text +++ pub fn header(&self) -> &'a [u8] { +++ unsafe { +++ slice::from_raw_parts( +++ (*self.raw).header.as_ptr() as *const u8, +++ (*self.raw).header_len as usize, +++ ) +++ } +++ } +++} +++ +++impl<'a> Binding for DiffHunk<'a> { +++ type Raw = *const raw::git_diff_hunk; +++ unsafe fn from_raw(raw: *const raw::git_diff_hunk) -> DiffHunk<'a> { +++ DiffHunk { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *const raw::git_diff_hunk { +++ self.raw +++ } +++} +++ +++impl<'a> std::fmt::Debug for DiffHunk<'a> { +++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +++ f.debug_struct("DiffHunk") +++ .field("old_start", &self.old_start()) +++ .field("old_lines", &self.old_lines()) +++ .field("new_start", &self.new_start()) +++ .field("new_lines", &self.new_lines()) +++ .field("header", &self.header()) +++ .finish() +++ } +++} +++ +++impl DiffStats { +++ /// Get the total number of files changed in a diff. +++ pub fn files_changed(&self) -> usize { +++ unsafe { raw::git_diff_stats_files_changed(&*self.raw) as usize } +++ } +++ +++ /// Get the total number of insertions in a diff +++ pub fn insertions(&self) -> usize { +++ unsafe { raw::git_diff_stats_insertions(&*self.raw) as usize } +++ } +++ +++ /// Get the total number of deletions in a diff +++ pub fn deletions(&self) -> usize { +++ unsafe { raw::git_diff_stats_deletions(&*self.raw) as usize } +++ } +++ +++ /// Print diff statistics to a Buf +++ pub fn to_buf(&self, format: DiffStatsFormat, width: usize) -> Result { +++ let buf = Buf::new(); +++ unsafe { +++ try_call!(raw::git_diff_stats_to_buf( +++ buf.raw(), +++ self.raw, +++ format.bits(), +++ width as size_t +++ )); +++ } +++ Ok(buf) +++ } +++} +++ +++impl Binding for DiffStats { +++ type Raw = *mut raw::git_diff_stats; +++ +++ unsafe fn from_raw(raw: *mut raw::git_diff_stats) -> DiffStats { +++ DiffStats { raw } +++ } +++ fn raw(&self) -> *mut raw::git_diff_stats { +++ self.raw +++ } +++} +++ +++impl Drop for DiffStats { +++ fn drop(&mut self) { +++ unsafe { raw::git_diff_stats_free(self.raw) } +++ } +++} +++ +++impl std::fmt::Debug for DiffStats { +++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +++ f.debug_struct("DiffStats") +++ .field("files_changed", &self.files_changed()) +++ .field("insertions", &self.insertions()) +++ .field("deletions", &self.deletions()) +++ .finish() +++ } +++} +++ +++impl<'a> DiffBinary<'a> { +++ /// Returns whether there is data in this binary structure or not. +++ /// +++ /// If this is `true`, then this was produced and included binary content. +++ /// If this is `false` then this was generated knowing only that a binary +++ /// file changed but without providing the data, probably from a patch that +++ /// said `Binary files a/file.txt and b/file.txt differ`. +++ pub fn contains_data(&self) -> bool { +++ unsafe { (*self.raw).contains_data == 1 } +++ } +++ +++ /// The contents of the old file. +++ pub fn old_file(&self) -> DiffBinaryFile<'a> { +++ unsafe { Binding::from_raw(&(*self.raw).old_file as *const _) } +++ } +++ +++ /// The contents of the new file. +++ pub fn new_file(&self) -> DiffBinaryFile<'a> { +++ unsafe { Binding::from_raw(&(*self.raw).new_file as *const _) } +++ } +++} +++ +++impl<'a> Binding for DiffBinary<'a> { +++ type Raw = *const raw::git_diff_binary; +++ unsafe fn from_raw(raw: *const raw::git_diff_binary) -> DiffBinary<'a> { +++ DiffBinary { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *const raw::git_diff_binary { +++ self.raw +++ } +++} +++ +++impl<'a> DiffBinaryFile<'a> { +++ /// The type of binary data for this file +++ pub fn kind(&self) -> DiffBinaryKind { +++ unsafe { Binding::from_raw((*self.raw).kind) } +++ } +++ +++ /// The binary data, deflated +++ pub fn data(&self) -> &[u8] { +++ unsafe { +++ slice::from_raw_parts((*self.raw).data as *const u8, (*self.raw).datalen as usize) +++ } +++ } +++ +++ /// The length of the binary data after inflation +++ pub fn inflated_len(&self) -> usize { +++ unsafe { (*self.raw).inflatedlen as usize } +++ } +++} +++ +++impl<'a> Binding for DiffBinaryFile<'a> { +++ type Raw = *const raw::git_diff_binary_file; +++ unsafe fn from_raw(raw: *const raw::git_diff_binary_file) -> DiffBinaryFile<'a> { +++ DiffBinaryFile { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *const raw::git_diff_binary_file { +++ self.raw +++ } +++} +++ +++impl Binding for DiffBinaryKind { +++ type Raw = raw::git_diff_binary_t; +++ unsafe fn from_raw(raw: raw::git_diff_binary_t) -> DiffBinaryKind { +++ match raw { +++ raw::GIT_DIFF_BINARY_NONE => DiffBinaryKind::None, +++ raw::GIT_DIFF_BINARY_LITERAL => DiffBinaryKind::Literal, +++ raw::GIT_DIFF_BINARY_DELTA => DiffBinaryKind::Delta, +++ _ => panic!("Unknown git diff binary kind"), +++ } +++ } +++ fn raw(&self) -> raw::git_diff_binary_t { +++ match *self { +++ DiffBinaryKind::None => raw::GIT_DIFF_BINARY_NONE, +++ DiffBinaryKind::Literal => raw::GIT_DIFF_BINARY_LITERAL, +++ DiffBinaryKind::Delta => raw::GIT_DIFF_BINARY_DELTA, +++ } +++ } +++} +++ +++impl Default for DiffFindOptions { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl DiffFindOptions { +++ /// Creates a new set of empty diff find options. +++ /// +++ /// All flags and other options are defaulted to false or their otherwise +++ /// zero equivalents. +++ pub fn new() -> DiffFindOptions { +++ let mut opts = DiffFindOptions { +++ raw: unsafe { mem::zeroed() }, +++ }; +++ assert_eq!( +++ unsafe { raw::git_diff_find_init_options(&mut opts.raw, 1) }, +++ 0 +++ ); +++ opts +++ } +++ +++ fn flag(&mut self, opt: u32, val: bool) -> &mut DiffFindOptions { +++ if val { +++ self.raw.flags |= opt; +++ } else { +++ self.raw.flags &= !opt; +++ } +++ self +++ } +++ +++ /// Reset all flags back to their unset state, indicating that +++ /// `diff.renames` should be used instead. This is overridden once any flag +++ /// is set. +++ pub fn by_config(&mut self) -> &mut DiffFindOptions { +++ self.flag(0xffffffff, false) +++ } +++ +++ /// Look for renames? +++ pub fn renames(&mut self, find: bool) -> &mut DiffFindOptions { +++ self.flag(raw::GIT_DIFF_FIND_RENAMES, find) +++ } +++ +++ /// Consider old side of modified for renames? +++ pub fn renames_from_rewrites(&mut self, find: bool) -> &mut DiffFindOptions { +++ self.flag(raw::GIT_DIFF_FIND_RENAMES_FROM_REWRITES, find) +++ } +++ +++ /// Look for copies? +++ pub fn copies(&mut self, find: bool) -> &mut DiffFindOptions { +++ self.flag(raw::GIT_DIFF_FIND_COPIES, find) +++ } +++ +++ /// Consider unmodified as copy sources? +++ /// +++ /// For this to work correctly, use `include_unmodified` when the initial +++ /// diff is being generated. +++ pub fn copies_from_unmodified(&mut self, find: bool) -> &mut DiffFindOptions { +++ self.flag(raw::GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED, find) +++ } +++ +++ /// Mark significant rewrites for split. +++ pub fn rewrites(&mut self, find: bool) -> &mut DiffFindOptions { +++ self.flag(raw::GIT_DIFF_FIND_REWRITES, find) +++ } +++ +++ /// Actually split large rewrites into delete/add pairs +++ pub fn break_rewrites(&mut self, find: bool) -> &mut DiffFindOptions { +++ self.flag(raw::GIT_DIFF_BREAK_REWRITES, find) +++ } +++ +++ #[doc(hidden)] +++ pub fn break_rewries(&mut self, find: bool) -> &mut DiffFindOptions { +++ self.break_rewrites(find) +++ } +++ +++ /// Find renames/copies for untracked items in working directory. +++ /// +++ /// For this to work correctly use the `include_untracked` option when the +++ /// initial diff is being generated. +++ pub fn for_untracked(&mut self, find: bool) -> &mut DiffFindOptions { +++ self.flag(raw::GIT_DIFF_FIND_FOR_UNTRACKED, find) +++ } +++ +++ /// Turn on all finding features. +++ pub fn all(&mut self, find: bool) -> &mut DiffFindOptions { +++ self.flag(raw::GIT_DIFF_FIND_ALL, find) +++ } +++ +++ /// Measure similarity ignoring leading whitespace (default) +++ pub fn ignore_leading_whitespace(&mut self, ignore: bool) -> &mut DiffFindOptions { +++ self.flag(raw::GIT_DIFF_FIND_IGNORE_LEADING_WHITESPACE, ignore) +++ } +++ +++ /// Measure similarity ignoring all whitespace +++ pub fn ignore_whitespace(&mut self, ignore: bool) -> &mut DiffFindOptions { +++ self.flag(raw::GIT_DIFF_FIND_IGNORE_WHITESPACE, ignore) +++ } +++ +++ /// Measure similarity including all data +++ pub fn dont_ignore_whitespace(&mut self, dont: bool) -> &mut DiffFindOptions { +++ self.flag(raw::GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE, dont) +++ } +++ +++ /// Measure similarity only by comparing SHAs (fast and cheap) +++ pub fn exact_match_only(&mut self, exact: bool) -> &mut DiffFindOptions { +++ self.flag(raw::GIT_DIFF_FIND_EXACT_MATCH_ONLY, exact) +++ } +++ +++ /// Do not break rewrites unless they contribute to a rename. +++ /// +++ /// Normally, `break_rewrites` and `rewrites` will measure the +++ /// self-similarity of modified files and split the ones that have changed a +++ /// lot into a delete/add pair. Then the sides of that pair will be +++ /// considered candidates for rename and copy detection +++ /// +++ /// If you add this flag in and the split pair is not used for an actual +++ /// rename or copy, then the modified record will be restored to a regular +++ /// modified record instead of being split. +++ pub fn break_rewrites_for_renames_only(&mut self, b: bool) -> &mut DiffFindOptions { +++ self.flag(raw::GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY, b) +++ } +++ +++ /// Remove any unmodified deltas after find_similar is done. +++ /// +++ /// Using `copies_from_unmodified` to emulate the `--find-copies-harder` +++ /// behavior requires building a diff with the `include_unmodified` flag. If +++ /// you do not want unmodified records in the final result, pas this flag to +++ /// have them removed. +++ pub fn remove_unmodified(&mut self, remove: bool) -> &mut DiffFindOptions { +++ self.flag(raw::GIT_DIFF_FIND_REMOVE_UNMODIFIED, remove) +++ } +++ +++ /// Similarity to consider a file renamed (default 50) +++ pub fn rename_threshold(&mut self, thresh: u16) -> &mut DiffFindOptions { +++ self.raw.rename_threshold = thresh; +++ self +++ } +++ +++ /// Similarity of modified to be eligible rename source (default 50) +++ pub fn rename_from_rewrite_threshold(&mut self, thresh: u16) -> &mut DiffFindOptions { +++ self.raw.rename_from_rewrite_threshold = thresh; +++ self +++ } +++ +++ /// Similarity to consider a file copy (default 50) +++ pub fn copy_threshold(&mut self, thresh: u16) -> &mut DiffFindOptions { +++ self.raw.copy_threshold = thresh; +++ self +++ } +++ +++ /// Similarity to split modify into delete/add pair (default 60) +++ pub fn break_rewrite_threshold(&mut self, thresh: u16) -> &mut DiffFindOptions { +++ self.raw.break_rewrite_threshold = thresh; +++ self +++ } +++ +++ /// Maximum similarity sources to examine for a file (somewhat like +++ /// git-diff's `-l` option or `diff.renameLimit` config) +++ /// +++ /// Defaults to 200 +++ pub fn rename_limit(&mut self, limit: usize) -> &mut DiffFindOptions { +++ self.raw.rename_limit = limit as size_t; +++ self +++ } +++ +++ // TODO: expose git_diff_similarity_metric +++ +++ /// Acquire a pointer to the underlying raw options. +++ pub unsafe fn raw(&mut self) -> *const raw::git_diff_find_options { +++ &self.raw +++ } +++} +++ +++impl Default for DiffFormatEmailOptions { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl DiffFormatEmailOptions { +++ /// Creates a new set of email options, +++ /// initialized to the default values +++ pub fn new() -> Self { +++ let mut opts = DiffFormatEmailOptions { +++ raw: unsafe { mem::zeroed() }, +++ }; +++ assert_eq!( +++ unsafe { raw::git_diff_format_email_options_init(&mut opts.raw, 1) }, +++ 0 +++ ); +++ opts +++ } +++ +++ fn flag(&mut self, opt: u32, val: bool) -> &mut Self { +++ if val { +++ self.raw.flags |= opt; +++ } else { +++ self.raw.flags &= !opt; +++ } +++ self +++ } +++ +++ /// Exclude `[PATCH]` from the subject header +++ pub fn exclude_subject_patch_header(&mut self, should_exclude: bool) -> &mut Self { +++ self.flag( +++ raw::GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER, +++ should_exclude, +++ ) +++ } +++} +++ +++impl DiffPatchidOptions { +++ /// Creates a new set of patchid options, +++ /// initialized to the default values +++ pub fn new() -> Self { +++ let mut opts = DiffPatchidOptions { +++ raw: unsafe { mem::zeroed() }, +++ }; +++ assert_eq!( +++ unsafe { +++ raw::git_diff_patchid_options_init( +++ &mut opts.raw, +++ raw::GIT_DIFF_PATCHID_OPTIONS_VERSION, +++ ) +++ }, +++ 0 +++ ); +++ opts +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::{DiffLineType, DiffOptions, Oid, Signature, Time}; +++ use std::borrow::Borrow; +++ use std::fs::File; +++ use std::io::Write; +++ use std::path::Path; +++ +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ let diff = repo.diff_tree_to_workdir(None, None).unwrap(); +++ assert_eq!(diff.deltas().len(), 0); +++ let stats = diff.stats().unwrap(); +++ assert_eq!(stats.insertions(), 0); +++ assert_eq!(stats.deletions(), 0); +++ assert_eq!(stats.files_changed(), 0); +++ let patchid = diff.patchid(None).unwrap(); +++ assert_ne!(patchid, Oid::zero()); +++ } +++ +++ #[test] +++ fn foreach_smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ let diff = t!(repo.diff_tree_to_workdir(None, None)); +++ let mut count = 0; +++ t!(diff.foreach( +++ &mut |_file, _progress| { +++ count = count + 1; +++ true +++ }, +++ None, +++ None, +++ None +++ )); +++ assert_eq!(count, 0); +++ } +++ +++ #[test] +++ fn foreach_file_only() { +++ let path = Path::new("foo"); +++ let (td, repo) = crate::test::repo_init(); +++ t!(t!(File::create(&td.path().join(path))).write_all(b"bar")); +++ let mut opts = DiffOptions::new(); +++ opts.include_untracked(true); +++ let diff = t!(repo.diff_tree_to_workdir(None, Some(&mut opts))); +++ let mut count = 0; +++ let mut result = None; +++ t!(diff.foreach( +++ &mut |file, _progress| { +++ count = count + 1; +++ result = file.new_file().path().map(ToOwned::to_owned); +++ true +++ }, +++ None, +++ None, +++ None +++ )); +++ assert_eq!(result.as_ref().map(Borrow::borrow), Some(path)); +++ assert_eq!(count, 1); +++ } +++ +++ #[test] +++ fn foreach_file_and_hunk() { +++ let path = Path::new("foo"); +++ let (td, repo) = crate::test::repo_init(); +++ t!(t!(File::create(&td.path().join(path))).write_all(b"bar")); +++ let mut index = t!(repo.index()); +++ t!(index.add_path(path)); +++ let mut opts = DiffOptions::new(); +++ opts.include_untracked(true); +++ let diff = t!(repo.diff_tree_to_index(None, Some(&index), Some(&mut opts))); +++ let mut new_lines = 0; +++ t!(diff.foreach( +++ &mut |_file, _progress| { true }, +++ None, +++ Some(&mut |_file, hunk| { +++ new_lines = hunk.new_lines(); +++ true +++ }), +++ None +++ )); +++ assert_eq!(new_lines, 1); +++ } +++ +++ #[test] +++ fn foreach_all_callbacks() { +++ let fib = vec![0, 1, 1, 2, 3, 5, 8]; +++ // Verified with a node implementation of deflate, might be worth +++ // adding a deflate lib to do this inline here. +++ let deflated_fib = vec![120, 156, 99, 96, 100, 100, 98, 102, 229, 0, 0, 0, 53, 0, 21]; +++ let foo_path = Path::new("foo"); +++ let bin_path = Path::new("bin"); +++ let (td, repo) = crate::test::repo_init(); +++ t!(t!(File::create(&td.path().join(foo_path))).write_all(b"bar\n")); +++ t!(t!(File::create(&td.path().join(bin_path))).write_all(&fib)); +++ let mut index = t!(repo.index()); +++ t!(index.add_path(foo_path)); +++ t!(index.add_path(bin_path)); +++ let mut opts = DiffOptions::new(); +++ opts.include_untracked(true).show_binary(true); +++ let diff = t!(repo.diff_tree_to_index(None, Some(&index), Some(&mut opts))); +++ let mut bin_content = None; +++ let mut new_lines = 0; +++ let mut line_content = None; +++ t!(diff.foreach( +++ &mut |_file, _progress| { true }, +++ Some(&mut |_file, binary| { +++ bin_content = Some(binary.new_file().data().to_owned()); +++ true +++ }), +++ Some(&mut |_file, hunk| { +++ new_lines = hunk.new_lines(); +++ true +++ }), +++ Some(&mut |_file, _hunk, line| { +++ line_content = String::from_utf8(line.content().into()).ok(); +++ true +++ }) +++ )); +++ assert_eq!(bin_content, Some(deflated_fib)); +++ assert_eq!(new_lines, 1); +++ assert_eq!(line_content, Some("bar\n".to_string())); +++ } +++ +++ #[test] +++ fn format_email_simple() { +++ let (_td, repo) = crate::test::repo_init(); +++ const COMMIT_MESSAGE: &str = "Modify some content"; +++ const EXPECTED_EMAIL_START: &str = concat!( +++ "From f1234fb0588b6ed670779a34ba5c51ef962f285f Mon Sep 17 00:00:00 2001\n", +++ "From: Techcable \n", +++ "Date: Tue, 11 Jan 1972 17:46:40 +0000\n", +++ "Subject: [PATCH] Modify some content\n", +++ "\n", +++ "---\n", +++ " file1.txt | 8 +++++---\n", +++ " 1 file changed, 5 insertions(+), 3 deletions(-)\n", +++ "\n", +++ "diff --git a/file1.txt b/file1.txt\n", +++ "index 94aaae8..af8f41d 100644\n", +++ "--- a/file1.txt\n", +++ "+++ b/file1.txt\n", +++ "@@ -1,15 +1,17 @@\n", +++ " file1.txt\n", +++ " file1.txt\n", +++ "+_file1.txt_\n", +++ " file1.txt\n", +++ " file1.txt\n", +++ " file1.txt\n", +++ " file1.txt\n", +++ "+\n", +++ "+\n", +++ " file1.txt\n", +++ " file1.txt\n", +++ " file1.txt\n", +++ " file1.txt\n", +++ " file1.txt\n", +++ "-file1.txt\n", +++ "-file1.txt\n", +++ "-file1.txt\n", +++ "+_file1.txt_\n", +++ "+_file1.txt_\n", +++ " file1.txt\n", +++ "--\n" +++ ); +++ const ORIGINAL_FILE: &str = concat!( +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n" +++ ); +++ const UPDATED_FILE: &str = concat!( +++ "file1.txt\n", +++ "file1.txt\n", +++ "_file1.txt_\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "\n", +++ "\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "file1.txt\n", +++ "_file1.txt_\n", +++ "_file1.txt_\n", +++ "file1.txt\n" +++ ); +++ const FILE_MODE: i32 = 0o100644; +++ let original_file = repo.blob(ORIGINAL_FILE.as_bytes()).unwrap(); +++ let updated_file = repo.blob(UPDATED_FILE.as_bytes()).unwrap(); +++ let mut original_tree = repo.treebuilder(None).unwrap(); +++ original_tree +++ .insert("file1.txt", original_file, FILE_MODE) +++ .unwrap(); +++ let original_tree = original_tree.write().unwrap(); +++ let mut updated_tree = repo.treebuilder(None).unwrap(); +++ updated_tree +++ .insert("file1.txt", updated_file, FILE_MODE) +++ .unwrap(); +++ let updated_tree = updated_tree.write().unwrap(); +++ let time = Time::new(64_000_000, 0); +++ let author = Signature::new("Techcable", "dummy@dummy.org", &time).unwrap(); +++ let updated_commit = repo +++ .commit( +++ None, +++ &author, +++ &author, +++ COMMIT_MESSAGE, +++ &repo.find_tree(updated_tree).unwrap(), +++ &[], // NOTE: Have no parents to ensure stable hash +++ ) +++ .unwrap(); +++ let updated_commit = repo.find_commit(updated_commit).unwrap(); +++ let mut diff = repo +++ .diff_tree_to_tree( +++ Some(&repo.find_tree(original_tree).unwrap()), +++ Some(&repo.find_tree(updated_tree).unwrap()), +++ None, +++ ) +++ .unwrap(); +++ #[allow(deprecated)] +++ let actual_email = diff.format_email(1, 1, &updated_commit, None).unwrap(); +++ let actual_email = actual_email.as_str().unwrap(); +++ assert!( +++ actual_email.starts_with(EXPECTED_EMAIL_START), +++ "Unexpected email:\n{}", +++ actual_email +++ ); +++ let mut remaining_lines = actual_email[EXPECTED_EMAIL_START.len()..].lines(); +++ let version_line = remaining_lines.next(); +++ assert!( +++ version_line.unwrap().starts_with("libgit2"), +++ "Invalid version line: {:?}", +++ version_line +++ ); +++ while let Some(line) = remaining_lines.next() { +++ assert_eq!(line.trim(), "") +++ } +++ } +++ +++ #[test] +++ fn foreach_diff_line_origin_value() { +++ let foo_path = Path::new("foo"); +++ let (td, repo) = crate::test::repo_init(); +++ t!(t!(File::create(&td.path().join(foo_path))).write_all(b"bar\n")); +++ let mut index = t!(repo.index()); +++ t!(index.add_path(foo_path)); +++ let mut opts = DiffOptions::new(); +++ opts.include_untracked(true); +++ let diff = t!(repo.diff_tree_to_index(None, Some(&index), Some(&mut opts))); +++ let mut origin_values: Vec = Vec::new(); +++ t!(diff.foreach( +++ &mut |_file, _progress| { true }, +++ None, +++ None, +++ Some(&mut |_file, _hunk, line| { +++ origin_values.push(line.origin_value()); +++ true +++ }) +++ )); +++ assert_eq!(origin_values.len(), 1); +++ assert_eq!(origin_values[0], DiffLineType::Addition); +++ } +++ +++ #[test] +++ fn foreach_exits_with_euser() { +++ let foo_path = Path::new("foo"); +++ let bar_path = Path::new("foo"); +++ +++ let (td, repo) = crate::test::repo_init(); +++ t!(t!(File::create(&td.path().join(foo_path))).write_all(b"bar\n")); +++ +++ let mut index = t!(repo.index()); +++ t!(index.add_path(foo_path)); +++ t!(index.add_path(bar_path)); +++ +++ let mut opts = DiffOptions::new(); +++ opts.include_untracked(true); +++ let diff = t!(repo.diff_tree_to_index(None, Some(&index), Some(&mut opts))); +++ +++ let mut calls = 0; +++ let result = diff.foreach( +++ &mut |_file, _progress| { +++ calls += 1; +++ false +++ }, +++ None, +++ None, +++ None, +++ ); +++ +++ assert_eq!(result.unwrap_err().code(), crate::ErrorCode::User); +++ } +++} diff --cc extra/git2/src/email.rs index 0000000000,0000000000,0000000000..d3ebc03842 new file mode 100644 --- /dev/null +++ b/extra/git2/src/email.rs @@@@ -1,0 -1,0 -1,0 +1,183 @@@@ +++use std::ffi::CString; +++use std::{mem, ptr}; +++ +++use crate::util::Binding; +++use crate::{raw, Buf, Commit, DiffFindOptions, DiffOptions, Error, IntoCString}; +++use crate::{Diff, Oid, Signature}; +++ +++/// A structure to represent patch in mbox format for sending via email +++pub struct Email { +++ buf: Buf, +++} +++ +++/// Options for controlling the formatting of the generated e-mail. +++pub struct EmailCreateOptions { +++ diff_options: DiffOptions, +++ diff_find_options: DiffFindOptions, +++ subject_prefix: Option, +++ raw: raw::git_email_create_options, +++} +++ +++impl Default for EmailCreateOptions { +++ fn default() -> Self { +++ // Defaults options created in corresponding to `GIT_EMAIL_CREATE_OPTIONS_INIT` +++ let default_options = raw::git_email_create_options { +++ version: raw::GIT_EMAIL_CREATE_OPTIONS_VERSION, +++ flags: raw::GIT_EMAIL_CREATE_DEFAULT as u32, +++ diff_opts: unsafe { mem::zeroed() }, +++ diff_find_opts: unsafe { mem::zeroed() }, +++ subject_prefix: ptr::null(), +++ start_number: 1, +++ reroll_number: 0, +++ }; +++ let mut diff_options = DiffOptions::new(); +++ diff_options.show_binary(true).context_lines(3); +++ Self { +++ diff_options, +++ diff_find_options: DiffFindOptions::new(), +++ subject_prefix: None, +++ raw: default_options, +++ } +++ } +++} +++ +++impl EmailCreateOptions { +++ /// Creates a new set of email create options +++ /// +++ /// By default, options include rename detection and binary +++ /// diffs to match `git format-patch`. +++ pub fn new() -> Self { +++ Self::default() +++ } +++ +++ fn flag(&mut self, opt: raw::git_email_create_flags_t, val: bool) -> &mut Self { +++ let opt = opt as u32; +++ if val { +++ self.raw.flags |= opt; +++ } else { +++ self.raw.flags &= !opt; +++ } +++ self +++ } +++ +++ /// Flag indicating whether patch numbers are included in the subject prefix. +++ pub fn omit_numbers(&mut self, omit: bool) -> &mut Self { +++ self.flag(raw::GIT_EMAIL_CREATE_OMIT_NUMBERS, omit) +++ } +++ +++ /// Flag indicating whether numbers included in the subject prefix even when +++ /// the patch is for a single commit (1/1). +++ pub fn always_number(&mut self, always: bool) -> &mut Self { +++ self.flag(raw::GIT_EMAIL_CREATE_ALWAYS_NUMBER, always) +++ } +++ +++ /// Flag indicating whether rename or similarity detection are ignored. +++ pub fn ignore_renames(&mut self, ignore: bool) -> &mut Self { +++ self.flag(raw::GIT_EMAIL_CREATE_NO_RENAMES, ignore) +++ } +++ +++ /// Get mutable access to `DiffOptions` that are used for creating diffs. +++ pub fn diff_options(&mut self) -> &mut DiffOptions { +++ &mut self.diff_options +++ } +++ +++ /// Get mutable access to `DiffFindOptions` that are used for finding +++ /// similarities within diffs. +++ pub fn diff_find_options(&mut self) -> &mut DiffFindOptions { +++ &mut self.diff_find_options +++ } +++ +++ /// Set the subject prefix +++ /// +++ /// The default value for this is "PATCH". If set to an empty string ("") +++ /// then only the patch numbers will be shown in the prefix. +++ /// If the subject_prefix is empty and patch numbers are not being shown, +++ /// the prefix will be omitted entirely. +++ pub fn subject_prefix(&mut self, t: T) -> &mut Self { +++ self.subject_prefix = Some(t.into_c_string().unwrap()); +++ self +++ } +++ +++ /// Set the starting patch number; this cannot be 0. +++ /// +++ /// The default value for this is 1. +++ pub fn start_number(&mut self, number: usize) -> &mut Self { +++ self.raw.start_number = number; +++ self +++ } +++ +++ /// Set the "re-roll" number. +++ /// +++ /// The default value for this is 0 (no re-roll). +++ pub fn reroll_number(&mut self, number: usize) -> &mut Self { +++ self.raw.reroll_number = number; +++ self +++ } +++ +++ /// Acquire a pointer to the underlying raw options. +++ /// +++ /// This function is unsafe as the pointer is only valid so long as this +++ /// structure is not moved, modified, or used elsewhere. +++ unsafe fn raw(&mut self) -> *const raw::git_email_create_options { +++ self.raw.subject_prefix = self +++ .subject_prefix +++ .as_ref() +++ .map(|s| s.as_ptr()) +++ .unwrap_or(ptr::null()); +++ self.raw.diff_opts = ptr::read(self.diff_options.raw()); +++ self.raw.diff_find_opts = ptr::read(self.diff_find_options.raw()); +++ &self.raw as *const _ +++ } +++} +++ +++impl Email { +++ /// Returns a byte slice with stored e-mail patch in. `Email` could be +++ /// created by one of the `from_*` functions. +++ pub fn as_slice(&self) -> &[u8] { +++ &self.buf +++ } +++ +++ /// Create a diff for a commit in mbox format for sending via email. +++ pub fn from_diff( +++ diff: &Diff<'_>, +++ patch_idx: usize, +++ patch_count: usize, +++ commit_id: &Oid, +++ summary: T, +++ body: T, +++ author: &Signature<'_>, +++ opts: &mut EmailCreateOptions, +++ ) -> Result { +++ let buf = Buf::new(); +++ let summary = summary.into_c_string()?; +++ let body = body.into_c_string()?; +++ unsafe { +++ try_call!(raw::git_email_create_from_diff( +++ buf.raw(), +++ Binding::raw(diff), +++ patch_idx, +++ patch_count, +++ Binding::raw(commit_id), +++ summary.as_ptr(), +++ body.as_ptr(), +++ Binding::raw(author), +++ opts.raw() +++ )); +++ Ok(Self { buf }) +++ } +++ } +++ +++ /// Create a diff for a commit in mbox format for sending via email. +++ /// The commit must not be a merge commit. +++ pub fn from_commit(commit: &Commit<'_>, opts: &mut EmailCreateOptions) -> Result { +++ let buf = Buf::new(); +++ unsafe { +++ try_call!(raw::git_email_create_from_commit( +++ buf.raw(), +++ commit.raw(), +++ opts.raw() +++ )); +++ Ok(Self { buf }) +++ } +++ } +++} diff --cc extra/git2/src/error.rs index 0000000000,0000000000,0000000000..076667af98 new file mode 100644 --- /dev/null +++ b/extra/git2/src/error.rs @@@@ -1,0 -1,0 -1,0 +1,408 @@@@ +++use libc::c_int; +++use std::env::JoinPathsError; +++use std::error; +++use std::ffi::{CStr, CString, NulError}; +++use std::fmt; +++use std::str; +++ +++use crate::{raw, ErrorClass, ErrorCode}; +++ +++/// A structure to represent errors coming out of libgit2. +++#[derive(Debug, PartialEq)] +++pub struct Error { +++ code: c_int, +++ klass: c_int, +++ message: Box, +++} +++ +++impl Error { +++ /// Creates a new error. +++ /// +++ /// This is mainly intended for implementers of custom transports or +++ /// database backends, where it is desirable to propagate an [`Error`] +++ /// through `libgit2`. +++ pub fn new>(code: ErrorCode, class: ErrorClass, message: S) -> Self { +++ let mut err = Error::from_str(message.as_ref()); +++ err.set_code(code); +++ err.set_class(class); +++ err +++ } +++ +++ /// Returns the last error that happened with the code specified by `code`. +++ /// +++ /// The `code` argument typically comes from the return value of a function +++ /// call. This code will later be returned from the `code` function. +++ pub fn last_error(code: c_int) -> Error { +++ crate::init(); +++ unsafe { +++ // Note that whenever libgit2 returns an error any negative value +++ // indicates that an error happened. Auxiliary information is +++ // *usually* in `git_error_last` but unfortunately that's not always +++ // the case. Sometimes a negative error code is returned from +++ // libgit2 *without* calling `git_error_set` internally to configure +++ // the error. +++ // +++ // To handle this case and hopefully provide better error messages +++ // on our end we unconditionally call `git_error_clear` when we're done +++ // with an error. This is an attempt to clear it as aggressively as +++ // possible when we can to ensure that error information from one +++ // api invocation doesn't leak over to the next api invocation. +++ // +++ // Additionally if `git_error_last` returns null then we returned a +++ // canned error out. +++ let ptr = raw::git_error_last(); +++ let err = if ptr.is_null() { +++ let mut error = Error::from_str("an unknown git error occurred"); +++ error.code = code; +++ error +++ } else { +++ Error::from_raw(code, ptr) +++ }; +++ raw::git_error_clear(); +++ err +++ } +++ } +++ +++ unsafe fn from_raw(code: c_int, ptr: *const raw::git_error) -> Error { +++ let message = CStr::from_ptr((*ptr).message as *const _).to_bytes(); +++ let message = String::from_utf8_lossy(message).into_owned().into(); +++ Error { +++ code, +++ klass: (*ptr).klass, +++ message, +++ } +++ } +++ +++ /// Creates a new error from the given string as the error. +++ /// +++ /// The error returned will have the code `GIT_ERROR` and the class +++ /// `GIT_ERROR_NONE`. +++ pub fn from_str(s: &str) -> Error { +++ Error { +++ code: raw::GIT_ERROR as c_int, +++ klass: raw::GIT_ERROR_NONE as c_int, +++ message: s.into(), +++ } +++ } +++ +++ /// Return the error code associated with this error. +++ /// +++ /// An error code is intended to be programmatically actionable most of the +++ /// time. For example the code `GIT_EAGAIN` indicates that an error could be +++ /// fixed by trying again, while the code `GIT_ERROR` is more bland and +++ /// doesn't convey anything in particular. +++ pub fn code(&self) -> ErrorCode { +++ match self.raw_code() { +++ raw::GIT_OK => super::ErrorCode::GenericError, +++ raw::GIT_ERROR => super::ErrorCode::GenericError, +++ raw::GIT_ENOTFOUND => super::ErrorCode::NotFound, +++ raw::GIT_EEXISTS => super::ErrorCode::Exists, +++ raw::GIT_EAMBIGUOUS => super::ErrorCode::Ambiguous, +++ raw::GIT_EBUFS => super::ErrorCode::BufSize, +++ raw::GIT_EUSER => super::ErrorCode::User, +++ raw::GIT_EBAREREPO => super::ErrorCode::BareRepo, +++ raw::GIT_EUNBORNBRANCH => super::ErrorCode::UnbornBranch, +++ raw::GIT_EUNMERGED => super::ErrorCode::Unmerged, +++ raw::GIT_ENONFASTFORWARD => super::ErrorCode::NotFastForward, +++ raw::GIT_EINVALIDSPEC => super::ErrorCode::InvalidSpec, +++ raw::GIT_ECONFLICT => super::ErrorCode::Conflict, +++ raw::GIT_ELOCKED => super::ErrorCode::Locked, +++ raw::GIT_EMODIFIED => super::ErrorCode::Modified, +++ raw::GIT_PASSTHROUGH => super::ErrorCode::GenericError, +++ raw::GIT_ITEROVER => super::ErrorCode::GenericError, +++ raw::GIT_EAUTH => super::ErrorCode::Auth, +++ raw::GIT_ECERTIFICATE => super::ErrorCode::Certificate, +++ raw::GIT_EAPPLIED => super::ErrorCode::Applied, +++ raw::GIT_EPEEL => super::ErrorCode::Peel, +++ raw::GIT_EEOF => super::ErrorCode::Eof, +++ raw::GIT_EINVALID => super::ErrorCode::Invalid, +++ raw::GIT_EUNCOMMITTED => super::ErrorCode::Uncommitted, +++ raw::GIT_EDIRECTORY => super::ErrorCode::Directory, +++ raw::GIT_EMERGECONFLICT => super::ErrorCode::MergeConflict, +++ raw::GIT_EMISMATCH => super::ErrorCode::HashsumMismatch, +++ raw::GIT_EINDEXDIRTY => super::ErrorCode::IndexDirty, +++ raw::GIT_EAPPLYFAIL => super::ErrorCode::ApplyFail, +++ raw::GIT_EOWNER => super::ErrorCode::Owner, +++ raw::GIT_TIMEOUT => super::ErrorCode::Timeout, +++ _ => super::ErrorCode::GenericError, +++ } +++ } +++ +++ /// Modify the error code associated with this error. +++ /// +++ /// This is mainly intended to be used by implementers of custom transports +++ /// or database backends, and should be used with care. +++ pub fn set_code(&mut self, code: ErrorCode) { +++ self.code = match code { +++ ErrorCode::GenericError => raw::GIT_ERROR, +++ ErrorCode::NotFound => raw::GIT_ENOTFOUND, +++ ErrorCode::Exists => raw::GIT_EEXISTS, +++ ErrorCode::Ambiguous => raw::GIT_EAMBIGUOUS, +++ ErrorCode::BufSize => raw::GIT_EBUFS, +++ ErrorCode::User => raw::GIT_EUSER, +++ ErrorCode::BareRepo => raw::GIT_EBAREREPO, +++ ErrorCode::UnbornBranch => raw::GIT_EUNBORNBRANCH, +++ ErrorCode::Unmerged => raw::GIT_EUNMERGED, +++ ErrorCode::NotFastForward => raw::GIT_ENONFASTFORWARD, +++ ErrorCode::InvalidSpec => raw::GIT_EINVALIDSPEC, +++ ErrorCode::Conflict => raw::GIT_ECONFLICT, +++ ErrorCode::Locked => raw::GIT_ELOCKED, +++ ErrorCode::Modified => raw::GIT_EMODIFIED, +++ ErrorCode::Auth => raw::GIT_EAUTH, +++ ErrorCode::Certificate => raw::GIT_ECERTIFICATE, +++ ErrorCode::Applied => raw::GIT_EAPPLIED, +++ ErrorCode::Peel => raw::GIT_EPEEL, +++ ErrorCode::Eof => raw::GIT_EEOF, +++ ErrorCode::Invalid => raw::GIT_EINVALID, +++ ErrorCode::Uncommitted => raw::GIT_EUNCOMMITTED, +++ ErrorCode::Directory => raw::GIT_EDIRECTORY, +++ ErrorCode::MergeConflict => raw::GIT_EMERGECONFLICT, +++ ErrorCode::HashsumMismatch => raw::GIT_EMISMATCH, +++ ErrorCode::IndexDirty => raw::GIT_EINDEXDIRTY, +++ ErrorCode::ApplyFail => raw::GIT_EAPPLYFAIL, +++ ErrorCode::Owner => raw::GIT_EOWNER, +++ ErrorCode::Timeout => raw::GIT_TIMEOUT, +++ }; +++ } +++ +++ /// Return the error class associated with this error. +++ /// +++ /// Error classes are in general mostly just informative. For example the +++ /// class will show up in the error message but otherwise an error class is +++ /// typically not directly actionable. +++ pub fn class(&self) -> ErrorClass { +++ match self.raw_class() { +++ raw::GIT_ERROR_NONE => super::ErrorClass::None, +++ raw::GIT_ERROR_NOMEMORY => super::ErrorClass::NoMemory, +++ raw::GIT_ERROR_OS => super::ErrorClass::Os, +++ raw::GIT_ERROR_INVALID => super::ErrorClass::Invalid, +++ raw::GIT_ERROR_REFERENCE => super::ErrorClass::Reference, +++ raw::GIT_ERROR_ZLIB => super::ErrorClass::Zlib, +++ raw::GIT_ERROR_REPOSITORY => super::ErrorClass::Repository, +++ raw::GIT_ERROR_CONFIG => super::ErrorClass::Config, +++ raw::GIT_ERROR_REGEX => super::ErrorClass::Regex, +++ raw::GIT_ERROR_ODB => super::ErrorClass::Odb, +++ raw::GIT_ERROR_INDEX => super::ErrorClass::Index, +++ raw::GIT_ERROR_OBJECT => super::ErrorClass::Object, +++ raw::GIT_ERROR_NET => super::ErrorClass::Net, +++ raw::GIT_ERROR_TAG => super::ErrorClass::Tag, +++ raw::GIT_ERROR_TREE => super::ErrorClass::Tree, +++ raw::GIT_ERROR_INDEXER => super::ErrorClass::Indexer, +++ raw::GIT_ERROR_SSL => super::ErrorClass::Ssl, +++ raw::GIT_ERROR_SUBMODULE => super::ErrorClass::Submodule, +++ raw::GIT_ERROR_THREAD => super::ErrorClass::Thread, +++ raw::GIT_ERROR_STASH => super::ErrorClass::Stash, +++ raw::GIT_ERROR_CHECKOUT => super::ErrorClass::Checkout, +++ raw::GIT_ERROR_FETCHHEAD => super::ErrorClass::FetchHead, +++ raw::GIT_ERROR_MERGE => super::ErrorClass::Merge, +++ raw::GIT_ERROR_SSH => super::ErrorClass::Ssh, +++ raw::GIT_ERROR_FILTER => super::ErrorClass::Filter, +++ raw::GIT_ERROR_REVERT => super::ErrorClass::Revert, +++ raw::GIT_ERROR_CALLBACK => super::ErrorClass::Callback, +++ raw::GIT_ERROR_CHERRYPICK => super::ErrorClass::CherryPick, +++ raw::GIT_ERROR_DESCRIBE => super::ErrorClass::Describe, +++ raw::GIT_ERROR_REBASE => super::ErrorClass::Rebase, +++ raw::GIT_ERROR_FILESYSTEM => super::ErrorClass::Filesystem, +++ raw::GIT_ERROR_PATCH => super::ErrorClass::Patch, +++ raw::GIT_ERROR_WORKTREE => super::ErrorClass::Worktree, +++ raw::GIT_ERROR_SHA1 => super::ErrorClass::Sha1, +++ raw::GIT_ERROR_HTTP => super::ErrorClass::Http, +++ _ => super::ErrorClass::None, +++ } +++ } +++ +++ /// Modify the error class associated with this error. +++ /// +++ /// This is mainly intended to be used by implementers of custom transports +++ /// or database backends, and should be used with care. +++ pub fn set_class(&mut self, class: ErrorClass) { +++ self.klass = match class { +++ ErrorClass::None => raw::GIT_ERROR_NONE, +++ ErrorClass::NoMemory => raw::GIT_ERROR_NOMEMORY, +++ ErrorClass::Os => raw::GIT_ERROR_OS, +++ ErrorClass::Invalid => raw::GIT_ERROR_INVALID, +++ ErrorClass::Reference => raw::GIT_ERROR_REFERENCE, +++ ErrorClass::Zlib => raw::GIT_ERROR_ZLIB, +++ ErrorClass::Repository => raw::GIT_ERROR_REPOSITORY, +++ ErrorClass::Config => raw::GIT_ERROR_CONFIG, +++ ErrorClass::Regex => raw::GIT_ERROR_REGEX, +++ ErrorClass::Odb => raw::GIT_ERROR_ODB, +++ ErrorClass::Index => raw::GIT_ERROR_INDEX, +++ ErrorClass::Object => raw::GIT_ERROR_OBJECT, +++ ErrorClass::Net => raw::GIT_ERROR_NET, +++ ErrorClass::Tag => raw::GIT_ERROR_TAG, +++ ErrorClass::Tree => raw::GIT_ERROR_TREE, +++ ErrorClass::Indexer => raw::GIT_ERROR_INDEXER, +++ ErrorClass::Ssl => raw::GIT_ERROR_SSL, +++ ErrorClass::Submodule => raw::GIT_ERROR_SUBMODULE, +++ ErrorClass::Thread => raw::GIT_ERROR_THREAD, +++ ErrorClass::Stash => raw::GIT_ERROR_STASH, +++ ErrorClass::Checkout => raw::GIT_ERROR_CHECKOUT, +++ ErrorClass::FetchHead => raw::GIT_ERROR_FETCHHEAD, +++ ErrorClass::Merge => raw::GIT_ERROR_MERGE, +++ ErrorClass::Ssh => raw::GIT_ERROR_SSH, +++ ErrorClass::Filter => raw::GIT_ERROR_FILTER, +++ ErrorClass::Revert => raw::GIT_ERROR_REVERT, +++ ErrorClass::Callback => raw::GIT_ERROR_CALLBACK, +++ ErrorClass::CherryPick => raw::GIT_ERROR_CHERRYPICK, +++ ErrorClass::Describe => raw::GIT_ERROR_DESCRIBE, +++ ErrorClass::Rebase => raw::GIT_ERROR_REBASE, +++ ErrorClass::Filesystem => raw::GIT_ERROR_FILESYSTEM, +++ ErrorClass::Patch => raw::GIT_ERROR_PATCH, +++ ErrorClass::Worktree => raw::GIT_ERROR_WORKTREE, +++ ErrorClass::Sha1 => raw::GIT_ERROR_SHA1, +++ ErrorClass::Http => raw::GIT_ERROR_HTTP, +++ } as c_int; +++ } +++ +++ /// Return the raw error code associated with this error. +++ pub fn raw_code(&self) -> raw::git_error_code { +++ macro_rules! check( ($($e:ident,)*) => ( +++ $(if self.code == raw::$e as c_int { raw::$e }) else * +++ else { +++ raw::GIT_ERROR +++ } +++ ) ); +++ check!( +++ GIT_OK, +++ GIT_ERROR, +++ GIT_ENOTFOUND, +++ GIT_EEXISTS, +++ GIT_EAMBIGUOUS, +++ GIT_EBUFS, +++ GIT_EUSER, +++ GIT_EBAREREPO, +++ GIT_EUNBORNBRANCH, +++ GIT_EUNMERGED, +++ GIT_ENONFASTFORWARD, +++ GIT_EINVALIDSPEC, +++ GIT_ECONFLICT, +++ GIT_ELOCKED, +++ GIT_EMODIFIED, +++ GIT_EAUTH, +++ GIT_ECERTIFICATE, +++ GIT_EAPPLIED, +++ GIT_EPEEL, +++ GIT_EEOF, +++ GIT_EINVALID, +++ GIT_EUNCOMMITTED, +++ GIT_PASSTHROUGH, +++ GIT_ITEROVER, +++ GIT_RETRY, +++ GIT_EMISMATCH, +++ GIT_EINDEXDIRTY, +++ GIT_EAPPLYFAIL, +++ GIT_EOWNER, +++ GIT_TIMEOUT, +++ ) +++ } +++ +++ /// Return the raw error class associated with this error. +++ pub fn raw_class(&self) -> raw::git_error_t { +++ macro_rules! check( ($($e:ident,)*) => ( +++ $(if self.klass == raw::$e as c_int { raw::$e }) else * +++ else { +++ raw::GIT_ERROR_NONE +++ } +++ ) ); +++ check!( +++ GIT_ERROR_NONE, +++ GIT_ERROR_NOMEMORY, +++ GIT_ERROR_OS, +++ GIT_ERROR_INVALID, +++ GIT_ERROR_REFERENCE, +++ GIT_ERROR_ZLIB, +++ GIT_ERROR_REPOSITORY, +++ GIT_ERROR_CONFIG, +++ GIT_ERROR_REGEX, +++ GIT_ERROR_ODB, +++ GIT_ERROR_INDEX, +++ GIT_ERROR_OBJECT, +++ GIT_ERROR_NET, +++ GIT_ERROR_TAG, +++ GIT_ERROR_TREE, +++ GIT_ERROR_INDEXER, +++ GIT_ERROR_SSL, +++ GIT_ERROR_SUBMODULE, +++ GIT_ERROR_THREAD, +++ GIT_ERROR_STASH, +++ GIT_ERROR_CHECKOUT, +++ GIT_ERROR_FETCHHEAD, +++ GIT_ERROR_MERGE, +++ GIT_ERROR_SSH, +++ GIT_ERROR_FILTER, +++ GIT_ERROR_REVERT, +++ GIT_ERROR_CALLBACK, +++ GIT_ERROR_CHERRYPICK, +++ GIT_ERROR_DESCRIBE, +++ GIT_ERROR_REBASE, +++ GIT_ERROR_FILESYSTEM, +++ GIT_ERROR_PATCH, +++ GIT_ERROR_WORKTREE, +++ GIT_ERROR_SHA1, +++ GIT_ERROR_HTTP, +++ ) +++ } +++ +++ /// Return the message associated with this error +++ pub fn message(&self) -> &str { +++ &self.message +++ } +++ +++ /// A low-level convenience to call [`raw::git_error_set_str`] with the +++ /// information from this error. +++ /// +++ /// Returns the [`Error::raw_code`] value of this error, which is often +++ /// needed from a C callback. +++ pub(crate) unsafe fn raw_set_git_error(&self) -> raw::git_error_code { +++ let s = CString::new(self.message()).unwrap(); +++ raw::git_error_set_str(self.class() as c_int, s.as_ptr()); +++ self.raw_code() +++ } +++} +++ +++impl error::Error for Error {} +++ +++impl fmt::Display for Error { +++ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +++ write!(f, "{}", self.message)?; +++ match self.class() { +++ ErrorClass::None => {} +++ other => write!(f, "; class={:?} ({})", other, self.klass)?, +++ } +++ match self.code() { +++ ErrorCode::GenericError => {} +++ other => write!(f, "; code={:?} ({})", other, self.code)?, +++ } +++ Ok(()) +++ } +++} +++ +++impl From for Error { +++ fn from(_: NulError) -> Error { +++ Error::from_str( +++ "data contained a nul byte that could not be \ +++ represented as a string", +++ ) +++ } +++} +++ +++impl From for Error { +++ fn from(e: JoinPathsError) -> Error { +++ Error::from_str(&e.to_string()) +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::{ErrorClass, ErrorCode}; +++ +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ let err = repo.find_submodule("does_not_exist").err().unwrap(); +++ assert_eq!(err.code(), ErrorCode::NotFound); +++ assert_eq!(err.class(), ErrorClass::Submodule); +++ } +++} diff --cc extra/git2/src/index.rs index 0000000000,0000000000,0000000000..0291d3cb95 new file mode 100644 --- /dev/null +++ b/extra/git2/src/index.rs @@@@ -1,0 -1,0 -1,0 +1,929 @@@@ +++use std::ffi::{CStr, CString}; +++use std::marker; +++use std::ops::Range; +++use std::path::Path; +++use std::ptr; +++use std::slice; +++ +++use libc::{c_char, c_int, c_uint, c_void, size_t}; +++ +++use crate::util::{self, path_to_repo_path, Binding}; +++use crate::IntoCString; +++use crate::{panic, raw, Error, IndexAddOption, IndexTime, Oid, Repository, Tree}; +++ +++/// A structure to represent a git [index][1] +++/// +++/// [1]: http://git-scm.com/book/en/Git-Internals-Git-Objects +++pub struct Index { +++ raw: *mut raw::git_index, +++} +++ +++/// An iterator over the entries in an index +++pub struct IndexEntries<'index> { +++ range: Range, +++ index: &'index Index, +++} +++ +++/// An iterator over the conflicting entries in an index +++pub struct IndexConflicts<'index> { +++ conflict_iter: *mut raw::git_index_conflict_iterator, +++ _marker: marker::PhantomData<&'index Index>, +++} +++ +++/// A structure to represent the information returned when a conflict is detected in an index entry +++pub struct IndexConflict { +++ /// The ancestor index entry of the two conflicting index entries +++ pub ancestor: Option, +++ /// The index entry originating from the user's copy of the repository. +++ /// Its contents conflict with 'their' index entry +++ pub our: Option, +++ /// The index entry originating from the external repository. +++ /// Its contents conflict with 'our' index entry +++ pub their: Option, +++} +++ +++/// A callback function to filter index matches. +++/// +++/// Used by `Index::{add_all,remove_all,update_all}`. The first argument is the +++/// path, and the second is the pathspec that matched it. Return 0 to confirm +++/// the operation on the item, > 0 to skip the item, and < 0 to abort the scan. +++pub type IndexMatchedPath<'a> = dyn FnMut(&Path, &[u8]) -> i32 + 'a; +++ +++/// A structure to represent an entry or a file inside of an index. +++/// +++/// All fields of an entry are public for modification and inspection. This is +++/// also how a new index entry is created. +++#[allow(missing_docs)] +++#[derive(Debug)] +++pub struct IndexEntry { +++ pub ctime: IndexTime, +++ pub mtime: IndexTime, +++ pub dev: u32, +++ pub ino: u32, +++ pub mode: u32, +++ pub uid: u32, +++ pub gid: u32, +++ pub file_size: u32, +++ pub id: Oid, +++ pub flags: u16, +++ pub flags_extended: u16, +++ +++ /// The path of this index entry as a byte vector. Regardless of the +++ /// current platform, the directory separator is an ASCII forward slash +++ /// (`0x2F`). There are no terminating or internal NUL characters, and no +++ /// trailing slashes. Most of the time, paths will be valid utf-8 — but +++ /// not always. For more information on the path storage format, see +++ /// [these git docs][git-index-docs]. Note that libgit2 will take care of +++ /// handling the prefix compression mentioned there. +++ /// +++ /// [git-index-docs]: https://github.com/git/git/blob/a08a83db2bf27f015bec9a435f6d73e223c21c5e/Documentation/technical/index-format.txt#L107-L124 +++ /// +++ /// You can turn this value into a `std::ffi::CString` with +++ /// `CString::new(&entry.path[..]).unwrap()`. To turn a reference into a +++ /// `&std::path::Path`, see the `bytes2path()` function in the private, +++ /// internal `util` module in this crate’s source code. +++ pub path: Vec, +++} +++ +++impl Index { +++ /// Creates a new in-memory index. +++ /// +++ /// This index object cannot be read/written to the filesystem, but may be +++ /// used to perform in-memory index operations. +++ pub fn new() -> Result { +++ crate::init(); +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_index_new(&mut raw)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Create a new bare Git index object as a memory representation of the Git +++ /// index file in 'index_path', without a repository to back it. +++ /// +++ /// Since there is no ODB or working directory behind this index, any Index +++ /// methods which rely on these (e.g. add_path) will fail. +++ /// +++ /// If you need an index attached to a repository, use the `index()` method +++ /// on `Repository`. +++ pub fn open(index_path: &Path) -> Result { +++ crate::init(); +++ let mut raw = ptr::null_mut(); +++ // Normal file path OK (does not need Windows conversion). +++ let index_path = index_path.into_c_string()?; +++ unsafe { +++ try_call!(raw::git_index_open(&mut raw, index_path)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Get index on-disk version. +++ /// +++ /// Valid return values are 2, 3, or 4. If 3 is returned, an index +++ /// with version 2 may be written instead, if the extension data in +++ /// version 3 is not necessary. +++ pub fn version(&self) -> u32 { +++ unsafe { raw::git_index_version(self.raw) } +++ } +++ +++ /// Set index on-disk version. +++ /// +++ /// Valid values are 2, 3, or 4. If 2 is given, git_index_write may +++ /// write an index with version 3 instead, if necessary to accurately +++ /// represent the index. +++ pub fn set_version(&mut self, version: u32) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_index_set_version(self.raw, version)); +++ } +++ Ok(()) +++ } +++ +++ /// Add or update an index entry from an in-memory struct +++ /// +++ /// If a previous index entry exists that has the same path and stage as the +++ /// given 'source_entry', it will be replaced. Otherwise, the 'source_entry' +++ /// will be added. +++ pub fn add(&mut self, entry: &IndexEntry) -> Result<(), Error> { +++ let path = CString::new(&entry.path[..])?; +++ +++ // libgit2 encodes the length of the path in the lower bits of the +++ // `flags` entry, so mask those out and recalculate here to ensure we +++ // don't corrupt anything. +++ let mut flags = entry.flags & !raw::GIT_INDEX_ENTRY_NAMEMASK; +++ +++ if entry.path.len() < raw::GIT_INDEX_ENTRY_NAMEMASK as usize { +++ flags |= entry.path.len() as u16; +++ } else { +++ flags |= raw::GIT_INDEX_ENTRY_NAMEMASK; +++ } +++ +++ unsafe { +++ let raw = raw::git_index_entry { +++ dev: entry.dev, +++ ino: entry.ino, +++ mode: entry.mode, +++ uid: entry.uid, +++ gid: entry.gid, +++ file_size: entry.file_size, +++ id: *entry.id.raw(), +++ flags, +++ flags_extended: entry.flags_extended, +++ path: path.as_ptr(), +++ mtime: raw::git_index_time { +++ seconds: entry.mtime.seconds(), +++ nanoseconds: entry.mtime.nanoseconds(), +++ }, +++ ctime: raw::git_index_time { +++ seconds: entry.ctime.seconds(), +++ nanoseconds: entry.ctime.nanoseconds(), +++ }, +++ }; +++ try_call!(raw::git_index_add(self.raw, &raw)); +++ Ok(()) +++ } +++ } +++ +++ /// Add or update an index entry from a buffer in memory +++ /// +++ /// This method will create a blob in the repository that owns the index and +++ /// then add the index entry to the index. The path of the entry represents +++ /// the position of the blob relative to the repository's root folder. +++ /// +++ /// If a previous index entry exists that has the same path as the given +++ /// 'entry', it will be replaced. Otherwise, the 'entry' will be added. +++ /// The id and the file_size of the 'entry' are updated with the real value +++ /// of the blob. +++ /// +++ /// This forces the file to be added to the index, not looking at gitignore +++ /// rules. +++ /// +++ /// If this file currently is the result of a merge conflict, this file will +++ /// no longer be marked as conflicting. The data about the conflict will be +++ /// moved to the "resolve undo" (REUC) section. +++ pub fn add_frombuffer(&mut self, entry: &IndexEntry, data: &[u8]) -> Result<(), Error> { +++ let path = CString::new(&entry.path[..])?; +++ +++ // libgit2 encodes the length of the path in the lower bits of the +++ // `flags` entry, so mask those out and recalculate here to ensure we +++ // don't corrupt anything. +++ let mut flags = entry.flags & !raw::GIT_INDEX_ENTRY_NAMEMASK; +++ +++ if entry.path.len() < raw::GIT_INDEX_ENTRY_NAMEMASK as usize { +++ flags |= entry.path.len() as u16; +++ } else { +++ flags |= raw::GIT_INDEX_ENTRY_NAMEMASK; +++ } +++ +++ unsafe { +++ let raw = raw::git_index_entry { +++ dev: entry.dev, +++ ino: entry.ino, +++ mode: entry.mode, +++ uid: entry.uid, +++ gid: entry.gid, +++ file_size: entry.file_size, +++ id: *entry.id.raw(), +++ flags, +++ flags_extended: entry.flags_extended, +++ path: path.as_ptr(), +++ mtime: raw::git_index_time { +++ seconds: entry.mtime.seconds(), +++ nanoseconds: entry.mtime.nanoseconds(), +++ }, +++ ctime: raw::git_index_time { +++ seconds: entry.ctime.seconds(), +++ nanoseconds: entry.ctime.nanoseconds(), +++ }, +++ }; +++ +++ let ptr = data.as_ptr() as *const c_void; +++ let len = data.len() as size_t; +++ try_call!(raw::git_index_add_frombuffer(self.raw, &raw, ptr, len)); +++ Ok(()) +++ } +++ } +++ +++ /// Add or update an index entry from a file on disk +++ /// +++ /// The file path must be relative to the repository's working folder and +++ /// must be readable. +++ /// +++ /// This method will fail in bare index instances. +++ /// +++ /// This forces the file to be added to the index, not looking at gitignore +++ /// rules. +++ /// +++ /// If this file currently is the result of a merge conflict, this file will +++ /// no longer be marked as conflicting. The data about the conflict will be +++ /// moved to the "resolve undo" (REUC) section. +++ pub fn add_path(&mut self, path: &Path) -> Result<(), Error> { +++ let posix_path = path_to_repo_path(path)?; +++ unsafe { +++ try_call!(raw::git_index_add_bypath(self.raw, posix_path)); +++ Ok(()) +++ } +++ } +++ +++ /// Add or update index entries matching files in the working directory. +++ /// +++ /// This method will fail in bare index instances. +++ /// +++ /// The `pathspecs` are a list of file names or shell glob patterns that +++ /// will matched against files in the repository's working directory. Each +++ /// file that matches will be added to the index (either updating an +++ /// existing entry or adding a new entry). You can disable glob expansion +++ /// and force exact matching with the `AddDisablePathspecMatch` flag. +++ /// +++ /// Files that are ignored will be skipped (unlike `add_path`). If a file is +++ /// already tracked in the index, then it will be updated even if it is +++ /// ignored. Pass the `AddForce` flag to skip the checking of ignore rules. +++ /// +++ /// To emulate `git add -A` and generate an error if the pathspec contains +++ /// the exact path of an ignored file (when not using `AddForce`), add the +++ /// `AddCheckPathspec` flag. This checks that each entry in `pathspecs` +++ /// that is an exact match to a filename on disk is either not ignored or +++ /// already in the index. If this check fails, the function will return +++ /// an error. +++ /// +++ /// To emulate `git add -A` with the "dry-run" option, just use a callback +++ /// function that always returns a positive value. See below for details. +++ /// +++ /// If any files are currently the result of a merge conflict, those files +++ /// will no longer be marked as conflicting. The data about the conflicts +++ /// will be moved to the "resolve undo" (REUC) section. +++ /// +++ /// If you provide a callback function, it will be invoked on each matching +++ /// item in the working directory immediately before it is added to / +++ /// updated in the index. Returning zero will add the item to the index, +++ /// greater than zero will skip the item, and less than zero will abort the +++ /// scan an return an error to the caller. +++ /// +++ /// # Example +++ /// +++ /// Emulate `git add *`: +++ /// +++ /// ```no_run +++ /// use git2::{Index, IndexAddOption, Repository}; +++ /// +++ /// let repo = Repository::open("/path/to/a/repo").expect("failed to open"); +++ /// let mut index = repo.index().expect("cannot get the Index file"); +++ /// index.add_all(["*"].iter(), IndexAddOption::DEFAULT, None); +++ /// index.write(); +++ /// ``` +++ pub fn add_all( +++ &mut self, +++ pathspecs: I, +++ flag: IndexAddOption, +++ mut cb: Option<&mut IndexMatchedPath<'_>>, +++ ) -> Result<(), Error> +++ where +++ T: IntoCString, +++ I: IntoIterator, +++ { +++ let (_a, _b, raw_strarray) = crate::util::iter2cstrs_paths(pathspecs)?; +++ let ptr = cb.as_mut(); +++ let callback = ptr +++ .as_ref() +++ .map(|_| index_matched_path_cb as extern "C" fn(_, _, _) -> _); +++ unsafe { +++ try_call!(raw::git_index_add_all( +++ self.raw, +++ &raw_strarray, +++ flag.bits() as c_uint, +++ callback, +++ ptr.map(|p| p as *mut _).unwrap_or(ptr::null_mut()) as *mut c_void +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Clear the contents (all the entries) of an index object. +++ /// +++ /// This clears the index object in memory; changes must be explicitly +++ /// written to disk for them to take effect persistently via `write_*`. +++ pub fn clear(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_index_clear(self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Get the count of entries currently in the index +++ pub fn len(&self) -> usize { +++ unsafe { raw::git_index_entrycount(&*self.raw) as usize } +++ } +++ +++ /// Return `true` is there is no entry in the index +++ pub fn is_empty(&self) -> bool { +++ self.len() == 0 +++ } +++ +++ /// Get one of the entries in the index by its position. +++ pub fn get(&self, n: usize) -> Option { +++ unsafe { +++ let ptr = raw::git_index_get_byindex(self.raw, n as size_t); +++ if ptr.is_null() { +++ None +++ } else { +++ Some(Binding::from_raw(*ptr)) +++ } +++ } +++ } +++ +++ /// Get an iterator over the entries in this index. +++ pub fn iter(&self) -> IndexEntries<'_> { +++ IndexEntries { +++ range: 0..self.len(), +++ index: self, +++ } +++ } +++ +++ /// Get an iterator over the index entries that have conflicts +++ pub fn conflicts(&self) -> Result, Error> { +++ crate::init(); +++ let mut conflict_iter = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_index_conflict_iterator_new( +++ &mut conflict_iter, +++ self.raw +++ )); +++ Ok(Binding::from_raw(conflict_iter)) +++ } +++ } +++ +++ /// Get one of the entries in the index by its path. +++ pub fn get_path(&self, path: &Path, stage: i32) -> Option { +++ let path = path_to_repo_path(path).unwrap(); +++ unsafe { +++ let ptr = call!(raw::git_index_get_bypath(self.raw, path, stage as c_int)); +++ if ptr.is_null() { +++ None +++ } else { +++ Some(Binding::from_raw(*ptr)) +++ } +++ } +++ } +++ +++ /// Does this index have conflicts? +++ /// +++ /// Returns `true` if the index contains conflicts, `false` if it does not. +++ pub fn has_conflicts(&self) -> bool { +++ unsafe { raw::git_index_has_conflicts(self.raw) == 1 } +++ } +++ +++ /// Get the full path to the index file on disk. +++ /// +++ /// Returns `None` if this is an in-memory index. +++ pub fn path(&self) -> Option<&Path> { +++ unsafe { crate::opt_bytes(self, raw::git_index_path(&*self.raw)).map(util::bytes2path) } +++ } +++ +++ /// Update the contents of an existing index object in memory by reading +++ /// from the hard disk. +++ /// +++ /// If force is true, this performs a "hard" read that discards in-memory +++ /// changes and always reloads the on-disk index data. If there is no +++ /// on-disk version, the index will be cleared. +++ /// +++ /// If force is false, this does a "soft" read that reloads the index data +++ /// from disk only if it has changed since the last time it was loaded. +++ /// Purely in-memory index data will be untouched. Be aware: if there are +++ /// changes on disk, unwritten in-memory changes are discarded. +++ pub fn read(&mut self, force: bool) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_index_read(self.raw, force)); +++ } +++ Ok(()) +++ } +++ +++ /// Read a tree into the index file with stats +++ /// +++ /// The current index contents will be replaced by the specified tree. +++ pub fn read_tree(&mut self, tree: &Tree<'_>) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_index_read_tree(self.raw, &*tree.raw())); +++ } +++ Ok(()) +++ } +++ +++ /// Remove an entry from the index +++ pub fn remove(&mut self, path: &Path, stage: i32) -> Result<(), Error> { +++ let path = path_to_repo_path(path)?; +++ unsafe { +++ try_call!(raw::git_index_remove(self.raw, path, stage as c_int)); +++ } +++ Ok(()) +++ } +++ +++ /// Remove an index entry corresponding to a file on disk. +++ /// +++ /// The file path must be relative to the repository's working folder. It +++ /// may exist. +++ /// +++ /// If this file currently is the result of a merge conflict, this file will +++ /// no longer be marked as conflicting. The data about the conflict will be +++ /// moved to the "resolve undo" (REUC) section. +++ pub fn remove_path(&mut self, path: &Path) -> Result<(), Error> { +++ let path = path_to_repo_path(path)?; +++ unsafe { +++ try_call!(raw::git_index_remove_bypath(self.raw, path)); +++ } +++ Ok(()) +++ } +++ +++ /// Remove all entries from the index under a given directory. +++ pub fn remove_dir(&mut self, path: &Path, stage: i32) -> Result<(), Error> { +++ let path = path_to_repo_path(path)?; +++ unsafe { +++ try_call!(raw::git_index_remove_directory( +++ self.raw, +++ path, +++ stage as c_int +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Remove all matching index entries. +++ /// +++ /// If you provide a callback function, it will be invoked on each matching +++ /// item in the index immediately before it is removed. Return 0 to remove +++ /// the item, > 0 to skip the item, and < 0 to abort the scan. +++ pub fn remove_all( +++ &mut self, +++ pathspecs: I, +++ mut cb: Option<&mut IndexMatchedPath<'_>>, +++ ) -> Result<(), Error> +++ where +++ T: IntoCString, +++ I: IntoIterator, +++ { +++ let (_a, _b, raw_strarray) = crate::util::iter2cstrs_paths(pathspecs)?; +++ let ptr = cb.as_mut(); +++ let callback = ptr +++ .as_ref() +++ .map(|_| index_matched_path_cb as extern "C" fn(_, _, _) -> _); +++ unsafe { +++ try_call!(raw::git_index_remove_all( +++ self.raw, +++ &raw_strarray, +++ callback, +++ ptr.map(|p| p as *mut _).unwrap_or(ptr::null_mut()) as *mut c_void +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Update all index entries to match the working directory +++ /// +++ /// This method will fail in bare index instances. +++ /// +++ /// This scans the existing index entries and synchronizes them with the +++ /// working directory, deleting them if the corresponding working directory +++ /// file no longer exists otherwise updating the information (including +++ /// adding the latest version of file to the ODB if needed). +++ /// +++ /// If you provide a callback function, it will be invoked on each matching +++ /// item in the index immediately before it is updated (either refreshed or +++ /// removed depending on working directory state). Return 0 to proceed with +++ /// updating the item, > 0 to skip the item, and < 0 to abort the scan. +++ pub fn update_all( +++ &mut self, +++ pathspecs: I, +++ mut cb: Option<&mut IndexMatchedPath<'_>>, +++ ) -> Result<(), Error> +++ where +++ T: IntoCString, +++ I: IntoIterator, +++ { +++ let (_a, _b, raw_strarray) = crate::util::iter2cstrs_paths(pathspecs)?; +++ let ptr = cb.as_mut(); +++ let callback = ptr +++ .as_ref() +++ .map(|_| index_matched_path_cb as extern "C" fn(_, _, _) -> _); +++ unsafe { +++ try_call!(raw::git_index_update_all( +++ self.raw, +++ &raw_strarray, +++ callback, +++ ptr.map(|p| p as *mut _).unwrap_or(ptr::null_mut()) as *mut c_void +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Write an existing index object from memory back to disk using an atomic +++ /// file lock. +++ pub fn write(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_index_write(self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Write the index as a tree. +++ /// +++ /// This method will scan the index and write a representation of its +++ /// current state back to disk; it recursively creates tree objects for each +++ /// of the subtrees stored in the index, but only returns the OID of the +++ /// root tree. This is the OID that can be used e.g. to create a commit. +++ /// +++ /// The index instance cannot be bare, and needs to be associated to an +++ /// existing repository. +++ /// +++ /// The index must not contain any file in conflict. +++ pub fn write_tree(&mut self) -> Result { +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_index_write_tree(&mut raw, self.raw)); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++ +++ /// Write the index as a tree to the given repository +++ /// +++ /// This is the same as `write_tree` except that the destination repository +++ /// can be chosen. +++ pub fn write_tree_to(&mut self, repo: &Repository) -> Result { +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_index_write_tree_to(&mut raw, self.raw, repo.raw())); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++ +++ /// Find the first position of any entries matching a prefix. +++ /// +++ /// To find the first position of a path inside a given folder, suffix the prefix with a '/'. +++ pub fn find_prefix(&self, prefix: T) -> Result { +++ let mut at_pos: size_t = 0; +++ let entry_path = prefix.into_c_string()?; +++ unsafe { +++ try_call!(raw::git_index_find_prefix( +++ &mut at_pos, +++ self.raw, +++ entry_path +++ )); +++ Ok(at_pos) +++ } +++ } +++} +++ +++impl Binding for Index { +++ type Raw = *mut raw::git_index; +++ unsafe fn from_raw(raw: *mut raw::git_index) -> Index { +++ Index { raw } +++ } +++ fn raw(&self) -> *mut raw::git_index { +++ self.raw +++ } +++} +++ +++impl<'index> Binding for IndexConflicts<'index> { +++ type Raw = *mut raw::git_index_conflict_iterator; +++ +++ unsafe fn from_raw(raw: *mut raw::git_index_conflict_iterator) -> IndexConflicts<'index> { +++ IndexConflicts { +++ conflict_iter: raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_index_conflict_iterator { +++ self.conflict_iter +++ } +++} +++ +++extern "C" fn index_matched_path_cb( +++ path: *const c_char, +++ matched_pathspec: *const c_char, +++ payload: *mut c_void, +++) -> c_int { +++ unsafe { +++ let path = CStr::from_ptr(path).to_bytes(); +++ let matched_pathspec = CStr::from_ptr(matched_pathspec).to_bytes(); +++ +++ panic::wrap(|| { +++ let payload = payload as *mut &mut IndexMatchedPath<'_>; +++ (*payload)(util::bytes2path(path), matched_pathspec) as c_int +++ }) +++ .unwrap_or(-1) +++ } +++} +++ +++impl Drop for Index { +++ fn drop(&mut self) { +++ unsafe { raw::git_index_free(self.raw) } +++ } +++} +++ +++impl<'index> Drop for IndexConflicts<'index> { +++ fn drop(&mut self) { +++ unsafe { raw::git_index_conflict_iterator_free(self.conflict_iter) } +++ } +++} +++ +++impl<'index> Iterator for IndexEntries<'index> { +++ type Item = IndexEntry; +++ fn next(&mut self) -> Option { +++ self.range.next().map(|i| self.index.get(i).unwrap()) +++ } +++} +++ +++impl<'index> Iterator for IndexConflicts<'index> { +++ type Item = Result; +++ fn next(&mut self) -> Option> { +++ let mut ancestor = ptr::null(); +++ let mut our = ptr::null(); +++ let mut their = ptr::null(); +++ unsafe { +++ try_call_iter!(raw::git_index_conflict_next( +++ &mut ancestor, +++ &mut our, +++ &mut their, +++ self.conflict_iter +++ )); +++ Some(Ok(IndexConflict { +++ ancestor: match ancestor.is_null() { +++ false => Some(IndexEntry::from_raw(*ancestor)), +++ true => None, +++ }, +++ our: match our.is_null() { +++ false => Some(IndexEntry::from_raw(*our)), +++ true => None, +++ }, +++ their: match their.is_null() { +++ false => Some(IndexEntry::from_raw(*their)), +++ true => None, +++ }, +++ })) +++ } +++ } +++} +++ +++impl Binding for IndexEntry { +++ type Raw = raw::git_index_entry; +++ +++ unsafe fn from_raw(raw: raw::git_index_entry) -> IndexEntry { +++ let raw::git_index_entry { +++ ctime, +++ mtime, +++ dev, +++ ino, +++ mode, +++ uid, +++ gid, +++ file_size, +++ id, +++ flags, +++ flags_extended, +++ path, +++ } = raw; +++ +++ // libgit2 encodes the length of the path in the lower bits of `flags`, +++ // but if the length exceeds the number of bits then the path is +++ // nul-terminated. +++ let mut pathlen = (flags & raw::GIT_INDEX_ENTRY_NAMEMASK) as usize; +++ if pathlen == raw::GIT_INDEX_ENTRY_NAMEMASK as usize { +++ pathlen = CStr::from_ptr(path).to_bytes().len(); +++ } +++ +++ let path = slice::from_raw_parts(path as *const u8, pathlen); +++ +++ IndexEntry { +++ dev, +++ ino, +++ mode, +++ uid, +++ gid, +++ file_size, +++ id: Binding::from_raw(&id as *const _), +++ flags, +++ flags_extended, +++ path: path.to_vec(), +++ mtime: Binding::from_raw(mtime), +++ ctime: Binding::from_raw(ctime), +++ } +++ } +++ +++ fn raw(&self) -> raw::git_index_entry { +++ // not implemented, may require a CString in storage +++ panic!() +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use std::fs::{self, File}; +++ use std::path::Path; +++ use tempfile::TempDir; +++ +++ use crate::{ErrorCode, Index, IndexEntry, IndexTime, Oid, Repository, ResetType}; +++ +++ #[test] +++ fn smoke() { +++ let mut index = Index::new().unwrap(); +++ assert!(index.add_path(&Path::new(".")).is_err()); +++ index.clear().unwrap(); +++ assert_eq!(index.len(), 0); +++ assert!(index.get(0).is_none()); +++ assert!(index.path().is_none()); +++ assert!(index.read(true).is_err()); +++ } +++ +++ #[test] +++ fn smoke_from_repo() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut index = repo.index().unwrap(); +++ assert_eq!( +++ index.path().map(|s| s.to_path_buf()), +++ Some(repo.path().join("index")) +++ ); +++ Index::open(&repo.path().join("index")).unwrap(); +++ +++ index.clear().unwrap(); +++ index.read(true).unwrap(); +++ index.write().unwrap(); +++ index.write_tree().unwrap(); +++ index.write_tree_to(&repo).unwrap(); +++ } +++ +++ #[test] +++ fn add_all() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut index = repo.index().unwrap(); +++ +++ let root = repo.path().parent().unwrap(); +++ fs::create_dir(&root.join("foo")).unwrap(); +++ File::create(&root.join("foo/bar")).unwrap(); +++ let mut called = false; +++ index +++ .add_all( +++ ["foo"].iter(), +++ crate::IndexAddOption::DEFAULT, +++ Some(&mut |a: &Path, b: &[u8]| { +++ assert!(!called); +++ called = true; +++ assert_eq!(b, b"foo"); +++ assert_eq!(a, Path::new("foo/bar")); +++ 0 +++ }), +++ ) +++ .unwrap(); +++ assert!(called); +++ +++ called = false; +++ index +++ .remove_all( +++ ["."].iter(), +++ Some(&mut |a: &Path, b: &[u8]| { +++ assert!(!called); +++ called = true; +++ assert_eq!(b, b"."); +++ assert_eq!(a, Path::new("foo/bar")); +++ 0 +++ }), +++ ) +++ .unwrap(); +++ assert!(called); +++ } +++ +++ #[test] +++ fn smoke_add() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut index = repo.index().unwrap(); +++ +++ let root = repo.path().parent().unwrap(); +++ fs::create_dir(&root.join("foo")).unwrap(); +++ File::create(&root.join("foo/bar")).unwrap(); +++ index.add_path(Path::new("foo/bar")).unwrap(); +++ index.write().unwrap(); +++ assert_eq!(index.iter().count(), 1); +++ +++ // Make sure we can use this repo somewhere else now. +++ let id = index.write_tree().unwrap(); +++ let tree = repo.find_tree(id).unwrap(); +++ let sig = repo.signature().unwrap(); +++ let id = repo.refname_to_id("HEAD").unwrap(); +++ let parent = repo.find_commit(id).unwrap(); +++ let commit = repo +++ .commit(Some("HEAD"), &sig, &sig, "commit", &tree, &[&parent]) +++ .unwrap(); +++ let obj = repo.find_object(commit, None).unwrap(); +++ repo.reset(&obj, ResetType::Hard, None).unwrap(); +++ +++ let td2 = TempDir::new().unwrap(); +++ let url = crate::test::path2url(&root); +++ let repo = Repository::clone(&url, td2.path()).unwrap(); +++ let obj = repo.find_object(commit, None).unwrap(); +++ repo.reset(&obj, ResetType::Hard, None).unwrap(); +++ } +++ +++ #[test] +++ fn add_then_read() { +++ let mut index = Index::new().unwrap(); +++ let mut e = entry(); +++ e.path = b"foobar".to_vec(); +++ index.add(&e).unwrap(); +++ let e = index.get(0).unwrap(); +++ assert_eq!(e.path.len(), 6); +++ } +++ +++ #[test] +++ fn add_then_find() { +++ let mut index = Index::new().unwrap(); +++ let mut e = entry(); +++ e.path = b"foo/bar".to_vec(); +++ index.add(&e).unwrap(); +++ let mut e = entry(); +++ e.path = b"foo2/bar".to_vec(); +++ index.add(&e).unwrap(); +++ assert_eq!(index.get(0).unwrap().path, b"foo/bar"); +++ assert_eq!( +++ index.get_path(Path::new("foo/bar"), 0).unwrap().path, +++ b"foo/bar" +++ ); +++ assert_eq!(index.find_prefix(Path::new("foo2/")), Ok(1)); +++ assert_eq!( +++ index.find_prefix(Path::new("empty/")).unwrap_err().code(), +++ ErrorCode::NotFound +++ ); +++ } +++ +++ #[test] +++ fn add_frombuffer_then_read() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut index = repo.index().unwrap(); +++ +++ let mut e = entry(); +++ e.path = b"foobar".to_vec(); +++ let content = b"the contents"; +++ index.add_frombuffer(&e, content).unwrap(); +++ let e = index.get(0).unwrap(); +++ assert_eq!(e.path.len(), 6); +++ +++ let b = repo.find_blob(e.id).unwrap(); +++ assert_eq!(b.content(), content); +++ } +++ +++ fn entry() -> IndexEntry { +++ IndexEntry { +++ ctime: IndexTime::new(0, 0), +++ mtime: IndexTime::new(0, 0), +++ dev: 0, +++ ino: 0, +++ mode: 0o100644, +++ uid: 0, +++ gid: 0, +++ file_size: 0, +++ id: Oid::from_bytes(&[0; 20]).unwrap(), +++ flags: 0, +++ flags_extended: 0, +++ path: Vec::new(), +++ } +++ } +++} diff --cc extra/git2/src/indexer.rs index 0000000000,0000000000,0000000000..ddca5fa2d5 new file mode 100644 --- /dev/null +++ b/extra/git2/src/indexer.rs @@@@ -1,0 -1,0 -1,0 +1,252 @@@@ +++use std::ffi::CStr; +++use std::path::Path; +++use std::{io, marker, mem, ptr}; +++ +++use libc::c_void; +++ +++use crate::odb::{write_pack_progress_cb, OdbPackwriterCb}; +++use crate::util::Binding; +++use crate::{raw, Error, IntoCString, Odb}; +++ +++/// Struct representing the progress by an in-flight transfer. +++pub struct Progress<'a> { +++ pub(crate) raw: ProgressState, +++ pub(crate) _marker: marker::PhantomData<&'a raw::git_indexer_progress>, +++} +++ +++pub(crate) enum ProgressState { +++ Borrowed(*const raw::git_indexer_progress), +++ Owned(raw::git_indexer_progress), +++} +++ +++/// Callback to be invoked while indexing is in progress. +++/// +++/// This callback will be periodically called with updates to the progress of +++/// the indexing so far. The return value indicates whether the indexing or +++/// transfer should continue. A return value of `false` will cancel the +++/// indexing or transfer. +++/// +++/// * `progress` - the progress being made so far. +++pub type IndexerProgress<'a> = dyn FnMut(Progress<'_>) -> bool + 'a; +++ +++impl<'a> Progress<'a> { +++ /// Number of objects in the packfile being downloaded +++ pub fn total_objects(&self) -> usize { +++ unsafe { (*self.raw()).total_objects as usize } +++ } +++ /// Received objects that have been hashed +++ pub fn indexed_objects(&self) -> usize { +++ unsafe { (*self.raw()).indexed_objects as usize } +++ } +++ /// Objects which have been downloaded +++ pub fn received_objects(&self) -> usize { +++ unsafe { (*self.raw()).received_objects as usize } +++ } +++ /// Locally-available objects that have been injected in order to fix a thin +++ /// pack. +++ pub fn local_objects(&self) -> usize { +++ unsafe { (*self.raw()).local_objects as usize } +++ } +++ /// Number of deltas in the packfile being downloaded +++ pub fn total_deltas(&self) -> usize { +++ unsafe { (*self.raw()).total_deltas as usize } +++ } +++ /// Received deltas that have been hashed. +++ pub fn indexed_deltas(&self) -> usize { +++ unsafe { (*self.raw()).indexed_deltas as usize } +++ } +++ /// Size of the packfile received up to now +++ pub fn received_bytes(&self) -> usize { +++ unsafe { (*self.raw()).received_bytes as usize } +++ } +++ +++ /// Convert this to an owned version of `Progress`. +++ pub fn to_owned(&self) -> Progress<'static> { +++ Progress { +++ raw: ProgressState::Owned(unsafe { *self.raw() }), +++ _marker: marker::PhantomData, +++ } +++ } +++} +++ +++impl<'a> Binding for Progress<'a> { +++ type Raw = *const raw::git_indexer_progress; +++ unsafe fn from_raw(raw: *const raw::git_indexer_progress) -> Progress<'a> { +++ Progress { +++ raw: ProgressState::Borrowed(raw), +++ _marker: marker::PhantomData, +++ } +++ } +++ +++ fn raw(&self) -> *const raw::git_indexer_progress { +++ match self.raw { +++ ProgressState::Borrowed(raw) => raw, +++ ProgressState::Owned(ref raw) => raw as *const _, +++ } +++ } +++} +++ +++/// Callback to be invoked while a transfer is in progress. +++/// +++/// This callback will be periodically called with updates to the progress of +++/// the transfer so far. The return value indicates whether the transfer should +++/// continue. A return value of `false` will cancel the transfer. +++/// +++/// * `progress` - the progress being made so far. +++#[deprecated( +++ since = "0.11.0", +++ note = "renamed to `IndexerProgress` to match upstream" +++)] +++#[allow(dead_code)] +++pub type TransportProgress<'a> = IndexerProgress<'a>; +++ +++/// A stream to write and index a packfile +++/// +++/// This is equivalent to [`crate::OdbPackwriter`], but allows to store the pack +++/// and index at an arbitrary path. It also does not require access to an object +++/// database if, and only if, the pack file is self-contained (i.e. not "thin"). +++pub struct Indexer<'odb> { +++ raw: *mut raw::git_indexer, +++ progress: raw::git_indexer_progress, +++ progress_payload_ptr: *mut OdbPackwriterCb<'odb>, +++} +++ +++impl<'a> Indexer<'a> { +++ /// Create a new indexer +++ /// +++ /// The [`Odb`] is used to resolve base objects when fixing thin packs. It +++ /// can be `None` if no thin pack is expected, in which case missing bases +++ /// will result in an error. +++ /// +++ /// `mode` is the permissions to use for the output files, use `0` for defaults. +++ /// +++ /// If `verify` is `false`, the indexer will bypass object connectivity checks. +++ pub fn new(odb: Option<&Odb<'a>>, path: &Path, mode: u32, verify: bool) -> Result { +++ let path = path.into_c_string()?; +++ +++ let odb = odb.map(Binding::raw).unwrap_or_else(ptr::null_mut); +++ +++ let mut out = ptr::null_mut(); +++ let progress_cb: raw::git_indexer_progress_cb = Some(write_pack_progress_cb); +++ let progress_payload = Box::new(OdbPackwriterCb { cb: None }); +++ let progress_payload_ptr = Box::into_raw(progress_payload); +++ +++ unsafe { +++ let mut opts = mem::zeroed(); +++ try_call!(raw::git_indexer_options_init( +++ &mut opts, +++ raw::GIT_INDEXER_OPTIONS_VERSION +++ )); +++ opts.progress_cb = progress_cb; +++ opts.progress_cb_payload = progress_payload_ptr as *mut c_void; +++ opts.verify = verify.into(); +++ +++ try_call!(raw::git_indexer_new(&mut out, path, mode, odb, &mut opts)); +++ } +++ +++ Ok(Self { +++ raw: out, +++ progress: Default::default(), +++ progress_payload_ptr, +++ }) +++ } +++ +++ /// Finalize the pack and index +++ /// +++ /// Resolves any pending deltas and writes out the index file. The returned +++ /// string is the hexadecimal checksum of the packfile, which is also used +++ /// to name the pack and index files (`pack-.pack` and +++ /// `pack-.idx` respectively). +++ pub fn commit(mut self) -> Result { +++ unsafe { +++ try_call!(raw::git_indexer_commit(self.raw, &mut self.progress)); +++ +++ let name = CStr::from_ptr(raw::git_indexer_name(self.raw)); +++ Ok(name.to_str().expect("pack name not utf8").to_owned()) +++ } +++ } +++ +++ /// The callback through which progress is monitored. Be aware that this is +++ /// called inline, so performance may be affected. +++ pub fn progress(&mut self, cb: F) -> &mut Self +++ where +++ F: FnMut(Progress<'_>) -> bool + 'a, +++ { +++ let progress_payload = +++ unsafe { &mut *(self.progress_payload_ptr as *mut OdbPackwriterCb<'_>) }; +++ progress_payload.cb = Some(Box::new(cb) as Box>); +++ +++ self +++ } +++} +++ +++impl io::Write for Indexer<'_> { +++ fn write(&mut self, buf: &[u8]) -> io::Result { +++ unsafe { +++ let ptr = buf.as_ptr() as *mut c_void; +++ let len = buf.len(); +++ +++ let res = raw::git_indexer_append(self.raw, ptr, len, &mut self.progress); +++ if res < 0 { +++ Err(io::Error::new(io::ErrorKind::Other, Error::last_error(res))) +++ } else { +++ Ok(buf.len()) +++ } +++ } +++ } +++ +++ fn flush(&mut self) -> io::Result<()> { +++ Ok(()) +++ } +++} +++ +++impl Drop for Indexer<'_> { +++ fn drop(&mut self) { +++ unsafe { +++ raw::git_indexer_free(self.raw); +++ drop(Box::from_raw(self.progress_payload_ptr)) +++ } +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::{Buf, Indexer}; +++ use std::io::prelude::*; +++ +++ #[test] +++ fn indexer() { +++ let (_td, repo_source) = crate::test::repo_init(); +++ let (_td, repo_target) = crate::test::repo_init(); +++ +++ let mut progress_called = false; +++ +++ // Create an in-memory packfile +++ let mut builder = t!(repo_source.packbuilder()); +++ let mut buf = Buf::new(); +++ let (commit_source_id, _tree) = crate::test::commit(&repo_source); +++ t!(builder.insert_object(commit_source_id, None)); +++ t!(builder.write_buf(&mut buf)); +++ +++ // Write it to the standard location in the target repo, but via indexer +++ let odb = repo_source.odb().unwrap(); +++ let mut indexer = Indexer::new( +++ Some(&odb), +++ repo_target.path().join("objects").join("pack").as_path(), +++ 0o644, +++ true, +++ ) +++ .unwrap(); +++ indexer.progress(|_| { +++ progress_called = true; +++ true +++ }); +++ indexer.write(&buf).unwrap(); +++ indexer.commit().unwrap(); +++ +++ // Assert that target repo picks it up as valid +++ let commit_target = repo_target.find_commit(commit_source_id).unwrap(); +++ assert_eq!(commit_target.id(), commit_source_id); +++ assert!(progress_called); +++ } +++} diff --cc extra/git2/src/lib.rs index 0000000000,0000000000,0000000000..01c9a93517 new file mode 100644 --- /dev/null +++ b/extra/git2/src/lib.rs @@@@ -1,0 -1,0 -1,0 +1,1684 @@@@ +++//! # libgit2 bindings for Rust +++//! +++//! This library contains bindings to the [libgit2][1] C library which is used +++//! to manage git repositories. The library itself is a work in progress and is +++//! likely lacking some bindings here and there, so be warned. +++//! +++//! [1]: https://libgit2.github.com/ +++//! +++//! The git2-rs library strives to be as close to libgit2 as possible, but also +++//! strives to make using libgit2 as safe as possible. All resource management +++//! is automatic as well as adding strong types to all interfaces (including +++//! `Result`) +++//! +++//! ## Creating a `Repository` +++//! +++//! The `Repository` is the source from which almost all other objects in git-rs +++//! are spawned. A repository can be created through opening, initializing, or +++//! cloning. +++//! +++//! ### Initializing a new repository +++//! +++//! The `init` method will create a new repository, assuming one does not +++//! already exist. +++//! +++//! ```no_run +++//! # #![allow(unstable)] +++//! use git2::Repository; +++//! +++//! let repo = match Repository::init("/path/to/a/repo") { +++//! Ok(repo) => repo, +++//! Err(e) => panic!("failed to init: {}", e), +++//! }; +++//! ``` +++//! +++//! ### Opening an existing repository +++//! +++//! ```no_run +++//! # #![allow(unstable)] +++//! use git2::Repository; +++//! +++//! let repo = match Repository::open("/path/to/a/repo") { +++//! Ok(repo) => repo, +++//! Err(e) => panic!("failed to open: {}", e), +++//! }; +++//! ``` +++//! +++//! ### Cloning an existing repository +++//! +++//! ```no_run +++//! # #![allow(unstable)] +++//! use git2::Repository; +++//! +++//! let url = "https://github.com/alexcrichton/git2-rs"; +++//! let repo = match Repository::clone(url, "/path/to/a/repo") { +++//! Ok(repo) => repo, +++//! Err(e) => panic!("failed to clone: {}", e), +++//! }; +++//! ``` +++//! +++//! To clone using SSH, refer to [RepoBuilder](./build/struct.RepoBuilder.html). +++//! +++//! ## Working with a `Repository` +++//! +++//! All derivative objects, references, etc are attached to the lifetime of the +++//! source `Repository`, to ensure that they do not outlive the repository +++//! itself. +++ +++#![doc(html_root_url = "https://docs.rs/git2/0.20")] +++#![allow(trivial_numeric_casts, trivial_casts)] +++#![deny(missing_docs)] +++#![warn(rust_2018_idioms)] +++#![cfg_attr(test, deny(warnings))] +++ +++use bitflags::bitflags; +++use libgit2_sys as raw; +++ +++use std::ffi::{CStr, CString}; +++use std::fmt; +++use std::str; +++use std::sync::Once; +++ +++pub use crate::apply::{ApplyLocation, ApplyOptions}; +++pub use crate::attr::AttrValue; +++pub use crate::blame::{Blame, BlameHunk, BlameIter, BlameOptions}; +++pub use crate::blob::{Blob, BlobWriter}; +++pub use crate::branch::{Branch, Branches}; +++pub use crate::buf::Buf; +++pub use crate::cherrypick::CherrypickOptions; +++pub use crate::commit::{Commit, Parents}; +++pub use crate::config::{Config, ConfigEntries, ConfigEntry}; +++pub use crate::cred::{Cred, CredentialHelper}; +++pub use crate::describe::{Describe, DescribeFormatOptions, DescribeOptions}; +++pub use crate::diff::{Deltas, Diff, DiffDelta, DiffFile, DiffOptions}; +++pub use crate::diff::{DiffBinary, DiffBinaryFile, DiffBinaryKind, DiffPatchidOptions}; +++pub use crate::diff::{DiffFindOptions, DiffHunk, DiffLine, DiffLineType, DiffStats}; +++pub use crate::email::{Email, EmailCreateOptions}; +++pub use crate::error::Error; +++pub use crate::index::{ +++ Index, IndexConflict, IndexConflicts, IndexEntries, IndexEntry, IndexMatchedPath, +++}; +++pub use crate::indexer::{Indexer, IndexerProgress, Progress}; +++pub use crate::mailmap::Mailmap; +++pub use crate::mempack::Mempack; +++pub use crate::merge::{AnnotatedCommit, MergeOptions}; +++pub use crate::message::{ +++ message_prettify, message_trailers_bytes, message_trailers_strs, MessageTrailersBytes, +++ MessageTrailersBytesIterator, MessageTrailersStrs, MessageTrailersStrsIterator, +++ DEFAULT_COMMENT_CHAR, +++}; +++pub use crate::note::{Note, Notes}; +++pub use crate::object::Object; +++pub use crate::odb::{Odb, OdbObject, OdbPackwriter, OdbReader, OdbWriter}; +++pub use crate::oid::Oid; +++pub use crate::packbuilder::{PackBuilder, PackBuilderStage}; +++pub use crate::patch::Patch; +++pub use crate::pathspec::{Pathspec, PathspecFailedEntries, PathspecMatchList}; +++pub use crate::pathspec::{PathspecDiffEntries, PathspecEntries}; +++pub use crate::proxy_options::ProxyOptions; +++pub use crate::push_update::PushUpdate; +++pub use crate::rebase::{Rebase, RebaseOperation, RebaseOperationType, RebaseOptions}; +++pub use crate::reference::{Reference, ReferenceNames, References}; +++pub use crate::reflog::{Reflog, ReflogEntry, ReflogIter}; +++pub use crate::refspec::Refspec; +++pub use crate::remote::{ +++ FetchOptions, PushOptions, Refspecs, Remote, RemoteConnection, RemoteHead, RemoteRedirect, +++}; +++pub use crate::remote_callbacks::{CertificateCheckStatus, Credentials, RemoteCallbacks}; +++pub use crate::remote_callbacks::{TransportMessage, UpdateTips}; +++pub use crate::repo::{Repository, RepositoryInitOptions}; +++pub use crate::revert::RevertOptions; +++pub use crate::revspec::Revspec; +++pub use crate::revwalk::Revwalk; +++pub use crate::signature::Signature; +++pub use crate::stash::{StashApplyOptions, StashApplyProgressCb, StashCb, StashSaveOptions}; +++pub use crate::status::{StatusEntry, StatusIter, StatusOptions, StatusShow, Statuses}; +++pub use crate::submodule::{Submodule, SubmoduleUpdateOptions}; +++pub use crate::tag::Tag; +++pub use crate::time::{IndexTime, Time}; +++pub use crate::tracing::{trace_set, TraceLevel}; +++pub use crate::transaction::Transaction; +++pub use crate::tree::{Tree, TreeEntry, TreeIter, TreeWalkMode, TreeWalkResult}; +++pub use crate::treebuilder::TreeBuilder; +++pub use crate::util::IntoCString; +++pub use crate::version::Version; +++pub use crate::worktree::{Worktree, WorktreeAddOptions, WorktreeLockStatus, WorktreePruneOptions}; +++ +++// Create a convinience method on bitflag struct which checks the given flag +++macro_rules! is_bit_set { +++ ($name:ident, $flag:expr) => { +++ #[allow(missing_docs)] +++ pub fn $name(&self) -> bool { +++ self.intersects($flag) +++ } +++ }; +++} +++ +++/// An enumeration of possible errors that can happen when working with a git +++/// repository. +++// Note: We omit a few native error codes, as they are unlikely to be propagated +++// to the library user. Currently: +++// +++// * GIT_EPASSTHROUGH +++// * GIT_ITEROVER +++// * GIT_RETRY +++#[derive(PartialEq, Eq, Clone, Debug, Copy)] +++pub enum ErrorCode { +++ /// Generic error +++ GenericError, +++ /// Requested object could not be found +++ NotFound, +++ /// Object exists preventing operation +++ Exists, +++ /// More than one object matches +++ Ambiguous, +++ /// Output buffer too short to hold data +++ BufSize, +++ /// User-generated error +++ User, +++ /// Operation not allowed on bare repository +++ BareRepo, +++ /// HEAD refers to branch with no commits +++ UnbornBranch, +++ /// Merge in progress prevented operation +++ Unmerged, +++ /// Reference was not fast-forwardable +++ NotFastForward, +++ /// Name/ref spec was not in a valid format +++ InvalidSpec, +++ /// Checkout conflicts prevented operation +++ Conflict, +++ /// Lock file prevented operation +++ Locked, +++ /// Reference value does not match expected +++ Modified, +++ /// Authentication error +++ Auth, +++ /// Server certificate is invalid +++ Certificate, +++ /// Patch/merge has already been applied +++ Applied, +++ /// The requested peel operation is not possible +++ Peel, +++ /// Unexpected EOF +++ Eof, +++ /// Invalid operation or input +++ Invalid, +++ /// Uncommitted changes in index prevented operation +++ Uncommitted, +++ /// Operation was not valid for a directory +++ Directory, +++ /// A merge conflict exists and cannot continue +++ MergeConflict, +++ /// Hashsum mismatch in object +++ HashsumMismatch, +++ /// Unsaved changes in the index would be overwritten +++ IndexDirty, +++ /// Patch application failed +++ ApplyFail, +++ /// The object is not owned by the current user +++ Owner, +++ /// Timeout +++ Timeout, +++} +++ +++/// An enumeration of possible categories of things that can have +++/// errors when working with a git repository. +++#[derive(PartialEq, Eq, Clone, Debug, Copy)] +++pub enum ErrorClass { +++ /// Uncategorized +++ None, +++ /// Out of memory or insufficient allocated space +++ NoMemory, +++ /// Syscall or standard system library error +++ Os, +++ /// Invalid input +++ Invalid, +++ /// Error resolving or manipulating a reference +++ Reference, +++ /// ZLib failure +++ Zlib, +++ /// Bad repository state +++ Repository, +++ /// Bad configuration +++ Config, +++ /// Regex failure +++ Regex, +++ /// Bad object +++ Odb, +++ /// Invalid index data +++ Index, +++ /// Error creating or obtaining an object +++ Object, +++ /// Network error +++ Net, +++ /// Error manipulating a tag +++ Tag, +++ /// Invalid value in tree +++ Tree, +++ /// Hashing or packing error +++ Indexer, +++ /// Error from SSL +++ Ssl, +++ /// Error involving submodules +++ Submodule, +++ /// Threading error +++ Thread, +++ /// Error manipulating a stash +++ Stash, +++ /// Checkout failure +++ Checkout, +++ /// Invalid FETCH_HEAD +++ FetchHead, +++ /// Merge failure +++ Merge, +++ /// SSH failure +++ Ssh, +++ /// Error manipulating filters +++ Filter, +++ /// Error reverting commit +++ Revert, +++ /// Error from a user callback +++ Callback, +++ /// Error cherry-picking commit +++ CherryPick, +++ /// Can't describe object +++ Describe, +++ /// Error during rebase +++ Rebase, +++ /// Filesystem-related error +++ Filesystem, +++ /// Invalid patch data +++ Patch, +++ /// Error involving worktrees +++ Worktree, +++ /// Hash library error or SHA-1 collision +++ Sha1, +++ /// HTTP error +++ Http, +++} +++ +++/// A listing of the possible states that a repository can be in. +++#[derive(PartialEq, Eq, Clone, Debug, Copy)] +++#[allow(missing_docs)] +++pub enum RepositoryState { +++ Clean, +++ Merge, +++ Revert, +++ RevertSequence, +++ CherryPick, +++ CherryPickSequence, +++ Bisect, +++ Rebase, +++ RebaseInteractive, +++ RebaseMerge, +++ ApplyMailbox, +++ ApplyMailboxOrRebase, +++} +++ +++/// An enumeration of the possible directions for a remote. +++#[derive(Copy, Clone, Debug, PartialEq, Eq)] +++pub enum Direction { +++ /// Data will be fetched (read) from this remote. +++ Fetch, +++ /// Data will be pushed (written) to this remote. +++ Push, +++} +++ +++/// An enumeration of the operations that can be performed for the `reset` +++/// method on a `Repository`. +++#[derive(Copy, Clone, Debug, PartialEq, Eq)] +++pub enum ResetType { +++ /// Move the head to the given commit. +++ Soft, +++ /// Soft plus reset the index to the commit. +++ Mixed, +++ /// Mixed plus changes in the working tree are discarded. +++ Hard, +++} +++ +++/// An enumeration all possible kinds objects may have. +++#[derive(PartialEq, Eq, Copy, Clone, Debug)] +++pub enum ObjectType { +++ /// Any kind of git object +++ Any, +++ /// An object which corresponds to a git commit +++ Commit, +++ /// An object which corresponds to a git tree +++ Tree, +++ /// An object which corresponds to a git blob +++ Blob, +++ /// An object which corresponds to a git tag +++ Tag, +++} +++ +++/// An enumeration of all possible kinds of references. +++#[derive(PartialEq, Eq, Copy, Clone, Debug)] +++pub enum ReferenceType { +++ /// A reference which points at an object id. +++ Direct, +++ +++ /// A reference which points at another reference. +++ Symbolic, +++} +++ +++/// An enumeration for the possible types of branches +++#[derive(PartialEq, Eq, Debug, Copy, Clone)] +++pub enum BranchType { +++ /// A local branch not on a remote. +++ Local, +++ /// A branch for a remote. +++ Remote, +++} +++ +++/// An enumeration of the possible priority levels of a config file. +++/// +++/// The levels corresponding to the escalation logic (higher to lower) when +++/// searching for config entries. +++#[derive(PartialEq, Eq, Debug, Copy, Clone)] +++pub enum ConfigLevel { +++ /// System-wide on Windows, for compatibility with portable git +++ ProgramData = 1, +++ /// System-wide configuration file, e.g. /etc/gitconfig +++ System, +++ /// XDG-compatible configuration file, e.g. ~/.config/git/config +++ XDG, +++ /// User-specific configuration, e.g. ~/.gitconfig +++ Global, +++ /// Repository specific config, e.g. $PWD/.git/config +++ Local, +++ /// Worktree specific configuration file, e.g. $GIT_DIR/config.worktree +++ Worktree, +++ /// Application specific configuration file +++ App, +++ /// Highest level available +++ Highest = -1, +++} +++ +++/// Merge file favor options for `MergeOptions` instruct the file-level +++/// merging functionality how to deal with conflicting regions of the files. +++#[derive(PartialEq, Eq, Debug, Copy, Clone)] +++pub enum FileFavor { +++ /// When a region of a file is changed in both branches, a conflict will be +++ /// recorded in the index so that git_checkout can produce a merge file with +++ /// conflict markers in the working directory. This is the default. +++ Normal, +++ /// When a region of a file is changed in both branches, the file created +++ /// in the index will contain the "ours" side of any conflicting region. +++ /// The index will not record a conflict. +++ Ours, +++ /// When a region of a file is changed in both branches, the file created +++ /// in the index will contain the "theirs" side of any conflicting region. +++ /// The index will not record a conflict. +++ Theirs, +++ /// When a region of a file is changed in both branches, the file created +++ /// in the index will contain each unique line from each side, which has +++ /// the result of combining both files. The index will not record a conflict. +++ Union, +++} +++ +++bitflags! { +++ /// Orderings that may be specified for Revwalk iteration. +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct Sort: u32 { +++ /// Sort the repository contents in no particular ordering. +++ /// +++ /// This sorting is arbitrary, implementation-specific, and subject to +++ /// change at any time. This is the default sorting for new walkers. +++ const NONE = raw::GIT_SORT_NONE as u32; +++ +++ /// Sort the repository contents in topological order (children before +++ /// parents). +++ /// +++ /// This sorting mode can be combined with time sorting. +++ const TOPOLOGICAL = raw::GIT_SORT_TOPOLOGICAL as u32; +++ +++ /// Sort the repository contents by commit time. +++ /// +++ /// This sorting mode can be combined with topological sorting. +++ const TIME = raw::GIT_SORT_TIME as u32; +++ +++ /// Iterate through the repository contents in reverse order. +++ /// +++ /// This sorting mode can be combined with any others. +++ const REVERSE = raw::GIT_SORT_REVERSE as u32; +++ } +++} +++ +++impl Sort { +++ is_bit_set!(is_none, Sort::NONE); +++ is_bit_set!(is_topological, Sort::TOPOLOGICAL); +++ is_bit_set!(is_time, Sort::TIME); +++ is_bit_set!(is_reverse, Sort::REVERSE); +++} +++ +++bitflags! { +++ /// Types of credentials that can be requested by a credential callback. +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct CredentialType: u32 { +++ #[allow(missing_docs)] +++ const USER_PASS_PLAINTEXT = raw::GIT_CREDTYPE_USERPASS_PLAINTEXT as u32; +++ #[allow(missing_docs)] +++ const SSH_KEY = raw::GIT_CREDTYPE_SSH_KEY as u32; +++ #[allow(missing_docs)] +++ const SSH_MEMORY = raw::GIT_CREDTYPE_SSH_MEMORY as u32; +++ #[allow(missing_docs)] +++ const SSH_CUSTOM = raw::GIT_CREDTYPE_SSH_CUSTOM as u32; +++ #[allow(missing_docs)] +++ const DEFAULT = raw::GIT_CREDTYPE_DEFAULT as u32; +++ #[allow(missing_docs)] +++ const SSH_INTERACTIVE = raw::GIT_CREDTYPE_SSH_INTERACTIVE as u32; +++ #[allow(missing_docs)] +++ const USERNAME = raw::GIT_CREDTYPE_USERNAME as u32; +++ } +++} +++ +++impl CredentialType { +++ is_bit_set!(is_user_pass_plaintext, CredentialType::USER_PASS_PLAINTEXT); +++ is_bit_set!(is_ssh_key, CredentialType::SSH_KEY); +++ is_bit_set!(is_ssh_memory, CredentialType::SSH_MEMORY); +++ is_bit_set!(is_ssh_custom, CredentialType::SSH_CUSTOM); +++ is_bit_set!(is_default, CredentialType::DEFAULT); +++ is_bit_set!(is_ssh_interactive, CredentialType::SSH_INTERACTIVE); +++ is_bit_set!(is_username, CredentialType::USERNAME); +++} +++ +++impl Default for CredentialType { +++ fn default() -> Self { +++ CredentialType::DEFAULT +++ } +++} +++ +++bitflags! { +++ /// Flags for the `flags` field of an IndexEntry. +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct IndexEntryFlag: u16 { +++ /// Set when the `extended_flags` field is valid. +++ const EXTENDED = raw::GIT_INDEX_ENTRY_EXTENDED as u16; +++ /// "Assume valid" flag +++ const VALID = raw::GIT_INDEX_ENTRY_VALID as u16; +++ } +++} +++ +++impl IndexEntryFlag { +++ is_bit_set!(is_extended, IndexEntryFlag::EXTENDED); +++ is_bit_set!(is_valid, IndexEntryFlag::VALID); +++} +++ +++bitflags! { +++ /// Flags for the `extended_flags` field of an IndexEntry. +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct IndexEntryExtendedFlag: u16 { +++ /// An "intent to add" entry from "git add -N" +++ const INTENT_TO_ADD = raw::GIT_INDEX_ENTRY_INTENT_TO_ADD as u16; +++ /// Skip the associated worktree file, for sparse checkouts +++ const SKIP_WORKTREE = raw::GIT_INDEX_ENTRY_SKIP_WORKTREE as u16; +++ +++ #[allow(missing_docs)] +++ const UPTODATE = raw::GIT_INDEX_ENTRY_UPTODATE as u16; +++ } +++} +++ +++impl IndexEntryExtendedFlag { +++ is_bit_set!(is_intent_to_add, IndexEntryExtendedFlag::INTENT_TO_ADD); +++ is_bit_set!(is_skip_worktree, IndexEntryExtendedFlag::SKIP_WORKTREE); +++ is_bit_set!(is_up_to_date, IndexEntryExtendedFlag::UPTODATE); +++} +++ +++bitflags! { +++ /// Flags for APIs that add files matching pathspec +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct IndexAddOption: u32 { +++ #[allow(missing_docs)] +++ const DEFAULT = raw::GIT_INDEX_ADD_DEFAULT as u32; +++ #[allow(missing_docs)] +++ const FORCE = raw::GIT_INDEX_ADD_FORCE as u32; +++ #[allow(missing_docs)] +++ const DISABLE_PATHSPEC_MATCH = +++ raw::GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH as u32; +++ #[allow(missing_docs)] +++ const CHECK_PATHSPEC = raw::GIT_INDEX_ADD_CHECK_PATHSPEC as u32; +++ } +++} +++ +++impl IndexAddOption { +++ is_bit_set!(is_default, IndexAddOption::DEFAULT); +++ is_bit_set!(is_force, IndexAddOption::FORCE); +++ is_bit_set!( +++ is_disable_pathspec_match, +++ IndexAddOption::DISABLE_PATHSPEC_MATCH +++ ); +++ is_bit_set!(is_check_pathspec, IndexAddOption::CHECK_PATHSPEC); +++} +++ +++impl Default for IndexAddOption { +++ fn default() -> Self { +++ IndexAddOption::DEFAULT +++ } +++} +++ +++bitflags! { +++ /// Flags for `Repository::open_ext` +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct RepositoryOpenFlags: u32 { +++ /// Only open the specified path; don't walk upward searching. +++ const NO_SEARCH = raw::GIT_REPOSITORY_OPEN_NO_SEARCH as u32; +++ /// Search across filesystem boundaries. +++ const CROSS_FS = raw::GIT_REPOSITORY_OPEN_CROSS_FS as u32; +++ /// Force opening as bare repository, and defer loading its config. +++ const BARE = raw::GIT_REPOSITORY_OPEN_BARE as u32; +++ /// Don't try appending `/.git` to the specified repository path. +++ const NO_DOTGIT = raw::GIT_REPOSITORY_OPEN_NO_DOTGIT as u32; +++ /// Respect environment variables like `$GIT_DIR`. +++ const FROM_ENV = raw::GIT_REPOSITORY_OPEN_FROM_ENV as u32; +++ } +++} +++ +++impl RepositoryOpenFlags { +++ is_bit_set!(is_no_search, RepositoryOpenFlags::NO_SEARCH); +++ is_bit_set!(is_cross_fs, RepositoryOpenFlags::CROSS_FS); +++ is_bit_set!(is_bare, RepositoryOpenFlags::BARE); +++ is_bit_set!(is_no_dotgit, RepositoryOpenFlags::NO_DOTGIT); +++ is_bit_set!(is_from_env, RepositoryOpenFlags::FROM_ENV); +++} +++ +++bitflags! { +++ /// Flags for the return value of `Repository::revparse` +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct RevparseMode: u32 { +++ /// The spec targeted a single object +++ const SINGLE = raw::GIT_REVPARSE_SINGLE as u32; +++ /// The spec targeted a range of commits +++ const RANGE = raw::GIT_REVPARSE_RANGE as u32; +++ /// The spec used the `...` operator, which invokes special semantics. +++ const MERGE_BASE = raw::GIT_REVPARSE_MERGE_BASE as u32; +++ } +++} +++ +++impl RevparseMode { +++ is_bit_set!(is_no_single, RevparseMode::SINGLE); +++ is_bit_set!(is_range, RevparseMode::RANGE); +++ is_bit_set!(is_merge_base, RevparseMode::MERGE_BASE); +++} +++ +++bitflags! { +++ /// The results of `merge_analysis` indicating the merge opportunities. +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct MergeAnalysis: u32 { +++ /// No merge is possible. +++ const ANALYSIS_NONE = raw::GIT_MERGE_ANALYSIS_NONE as u32; +++ /// A "normal" merge; both HEAD and the given merge input have diverged +++ /// from their common ancestor. The divergent commits must be merged. +++ const ANALYSIS_NORMAL = raw::GIT_MERGE_ANALYSIS_NORMAL as u32; +++ /// All given merge inputs are reachable from HEAD, meaning the +++ /// repository is up-to-date and no merge needs to be performed. +++ const ANALYSIS_UP_TO_DATE = raw::GIT_MERGE_ANALYSIS_UP_TO_DATE as u32; +++ /// The given merge input is a fast-forward from HEAD and no merge +++ /// needs to be performed. Instead, the client can check out the +++ /// given merge input. +++ const ANALYSIS_FASTFORWARD = raw::GIT_MERGE_ANALYSIS_FASTFORWARD as u32; +++ /// The HEAD of the current repository is "unborn" and does not point to +++ /// a valid commit. No merge can be performed, but the caller may wish +++ /// to simply set HEAD to the target commit(s). +++ const ANALYSIS_UNBORN = raw::GIT_MERGE_ANALYSIS_UNBORN as u32; +++ } +++} +++ +++impl MergeAnalysis { +++ is_bit_set!(is_none, MergeAnalysis::ANALYSIS_NONE); +++ is_bit_set!(is_normal, MergeAnalysis::ANALYSIS_NORMAL); +++ is_bit_set!(is_up_to_date, MergeAnalysis::ANALYSIS_UP_TO_DATE); +++ is_bit_set!(is_fast_forward, MergeAnalysis::ANALYSIS_FASTFORWARD); +++ is_bit_set!(is_unborn, MergeAnalysis::ANALYSIS_UNBORN); +++} +++ +++bitflags! { +++ /// The user's stated preference for merges. +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct MergePreference: u32 { +++ /// No configuration was found that suggests a preferred behavior for +++ /// merge. +++ const NONE = raw::GIT_MERGE_PREFERENCE_NONE as u32; +++ /// There is a `merge.ff=false` configuration setting, suggesting that +++ /// the user does not want to allow a fast-forward merge. +++ const NO_FAST_FORWARD = raw::GIT_MERGE_PREFERENCE_NO_FASTFORWARD as u32; +++ /// There is a `merge.ff=only` configuration setting, suggesting that +++ /// the user only wants fast-forward merges. +++ const FASTFORWARD_ONLY = raw::GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY as u32; +++ } +++} +++ +++impl MergePreference { +++ is_bit_set!(is_none, MergePreference::NONE); +++ is_bit_set!(is_no_fast_forward, MergePreference::NO_FAST_FORWARD); +++ is_bit_set!(is_fastforward_only, MergePreference::FASTFORWARD_ONLY); +++} +++ +++bitflags! { +++ /// Flags controlling the behavior of ODB lookup operations +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct OdbLookupFlags: u32 { +++ /// Don't call `git_odb_refresh` if the lookup fails. Useful when doing +++ /// a batch of lookup operations for objects that may legitimately not +++ /// exist. When using this flag, you may wish to manually call +++ /// `git_odb_refresh` before processing a batch of objects. +++ const NO_REFRESH = raw::GIT_ODB_LOOKUP_NO_REFRESH as u32; +++ } +++} +++ +++bitflags! { +++ /// How to handle reference updates. +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct RemoteUpdateFlags: u32 { +++ /// Write the fetch results to FETCH_HEAD. +++ const UPDATE_FETCHHEAD = raw::GIT_REMOTE_UPDATE_FETCHHEAD as u32; +++ /// Report unchanged tips in the update_tips callback. +++ const REPORT_UNCHANGED = raw::GIT_REMOTE_UPDATE_REPORT_UNCHANGED as u32; +++ } +++} +++ +++#[cfg(test)] +++#[macro_use] +++mod test; +++#[macro_use] +++mod panic; +++mod attr; +++mod call; +++mod util; +++ +++pub mod build; +++pub mod cert; +++pub mod oid_array; +++pub mod opts; +++pub mod string_array; +++pub mod transport; +++ +++mod apply; +++mod blame; +++mod blob; +++mod branch; +++mod buf; +++mod cherrypick; +++mod commit; +++mod config; +++mod cred; +++mod describe; +++mod diff; +++mod email; +++mod error; +++mod index; +++mod indexer; +++mod mailmap; +++mod mempack; +++mod merge; +++mod message; +++mod note; +++mod object; +++mod odb; +++mod oid; +++mod packbuilder; +++mod patch; +++mod pathspec; +++mod proxy_options; +++mod push_update; +++mod rebase; +++mod reference; +++mod reflog; +++mod refspec; +++mod remote; +++mod remote_callbacks; +++mod repo; +++mod revert; +++mod revspec; +++mod revwalk; +++mod signature; +++mod stash; +++mod status; +++mod submodule; +++mod tag; +++mod tagforeach; +++mod time; +++mod tracing; +++mod transaction; +++mod tree; +++mod treebuilder; +++mod version; +++mod worktree; +++ +++fn init() { +++ static INIT: Once = Once::new(); +++ +++ INIT.call_once(|| { +++ openssl_env_init(); +++ }); +++ +++ raw::init(); +++} +++ +++#[cfg(all( +++ unix, +++ not(target_os = "macos"), +++ not(target_os = "ios"), +++ feature = "https" +++))] +++fn openssl_env_init() { +++ // Currently, libgit2 leverages OpenSSL for SSL support when cloning +++ // repositories over HTTPS. This means that we're picking up an OpenSSL +++ // dependency on non-Windows platforms (where it has its own HTTPS +++ // subsystem). As a result, we need to link to OpenSSL. +++ // +++ // Now actually *linking* to OpenSSL isn't so hard. We just need to make +++ // sure to use pkg-config to discover any relevant system dependencies for +++ // differences between distributions like CentOS and Ubuntu. The actual +++ // trickiness comes about when we start *distributing* the resulting +++ // binaries. Currently Cargo is distributed in binary form as nightlies, +++ // which means we're distributing a binary with OpenSSL linked in. +++ // +++ // For historical reasons, the Linux nightly builder is running a CentOS +++ // distribution in order to have as much ABI compatibility with other +++ // distributions as possible. Sadly, however, this compatibility does not +++ // extend to OpenSSL. Currently OpenSSL has two major versions, 0.9 and 1.0, +++ // which are incompatible (many ABI differences). The CentOS builder we +++ // build on has version 1.0, as do most distributions today. Some still have +++ // 0.9, however. This means that if we are to distribute the binaries built +++ // by the CentOS machine, we would only be compatible with OpenSSL 1.0 and +++ // we would fail to run (a dynamic linker error at runtime) on systems with +++ // only 9.8 installed (hopefully). +++ // +++ // But wait, the plot thickens! Apparently CentOS has dubbed their OpenSSL +++ // library as `libssl.so.10`, notably the `10` is included at the end. On +++ // the other hand Ubuntu, for example, only distributes `libssl.so`. This +++ // means that the binaries created at CentOS are hard-wired to probe for a +++ // file called `libssl.so.10` at runtime (using the LD_LIBRARY_PATH), which +++ // will not be found on ubuntu. The conclusion of this is that binaries +++ // built on CentOS cannot be distributed to Ubuntu and run successfully. +++ // +++ // There are a number of sneaky things we could do, including, but not +++ // limited to: +++ // +++ // 1. Create a shim program which runs "just before" cargo runs. The +++ // responsibility of this shim program would be to locate `libssl.so`, +++ // whatever it's called, on the current system, make sure there's a +++ // symlink *somewhere* called `libssl.so.10`, and then set up +++ // LD_LIBRARY_PATH and run the actual cargo. +++ // +++ // This approach definitely seems unconventional, and is borderline +++ // overkill for this problem. It's also dubious if we can find a +++ // libssl.so reliably on the target system. +++ // +++ // 2. Somehow re-work the CentOS installation so that the linked-against +++ // library is called libssl.so instead of libssl.so.10 +++ // +++ // The problem with this approach is that systems with 0.9 installed will +++ // start to silently fail, due to also having libraries called libssl.so +++ // (probably symlinked under a more appropriate version). +++ // +++ // 3. Compile Cargo against both OpenSSL 1.0 *and* OpenSSL 0.9, and +++ // distribute both. Also make sure that the linked-against name of the +++ // library is `libssl.so`. At runtime we determine which version is +++ // installed, and we then the appropriate binary. +++ // +++ // This approach clearly has drawbacks in terms of infrastructure and +++ // feasibility. +++ // +++ // 4. Build a nightly of Cargo for each distribution we'd like to support. +++ // You would then pick the appropriate Cargo nightly to install locally. +++ // +++ // So, with all this in mind, the decision was made to *statically* link +++ // OpenSSL. This solves any problem of relying on a downstream OpenSSL +++ // version being available. This does, however, open a can of worms related +++ // to security issues. It's generally a good idea to dynamically link +++ // OpenSSL as you'll get security updates over time without having to do +++ // anything (the system administrator will update the local openssl +++ // package). By statically linking, we're forfeiting this feature. +++ // +++ // The conclusion was made it is likely appropriate for the Cargo nightlies +++ // to statically link OpenSSL, but highly encourage distributions and +++ // packagers of Cargo to dynamically link OpenSSL. Packagers are targeting +++ // one system and are distributing to only that system, so none of the +++ // problems mentioned above would arise. +++ // +++ // In order to support this, a new package was made: openssl-static-sys. +++ // This package currently performs a fairly simple task: +++ // +++ // 1. Run pkg-config to discover where openssl is installed. +++ // 2. If openssl is installed in a nonstandard location, *and* static copies +++ // of the libraries are available, copy them to $OUT_DIR. +++ // +++ // This library will bring in libssl.a and libcrypto.a into the local build, +++ // allowing them to be picked up by this crate. This allows us to configure +++ // our own buildbots to have pkg-config point to these local pre-built +++ // copies of a static OpenSSL (with very few dependencies) while allowing +++ // most other builds of Cargo to naturally dynamically link OpenSSL. +++ // +++ // So in summary, if you're with me so far, we've statically linked OpenSSL +++ // to the Cargo binary (or any binary, for that matter) and we're ready to +++ // distribute it to *all* linux distributions. Remember that our original +++ // intent for openssl was for HTTPS support, which implies that we need some +++ // for of CA certificate store to validate certificates. This is normally +++ // installed in a standard system location. +++ // +++ // Unfortunately, as one might imagine, OpenSSL is configured for where this +++ // standard location is at *build time*, but it often varies widely +++ // per-system. Consequently, it was discovered that OpenSSL will respect the +++ // SSL_CERT_FILE and SSL_CERT_DIR environment variables in order to assist +++ // in discovering the location of this file (hurray!). +++ // +++ // So, finally getting to the point, this function solely exists to support +++ // our static builds of OpenSSL by probing for the "standard system +++ // location" of certificates and setting relevant environment variable to +++ // point to them. +++ // +++ // Ah, and as a final note, this is only a problem on Linux, not on OS X. On +++ // OS X the OpenSSL binaries are stable enough that we can just rely on +++ // dynamic linkage (plus they have some weird modifications to OpenSSL which +++ // means we wouldn't want to link statically). +++ openssl_probe::init_ssl_cert_env_vars(); +++} +++ +++#[cfg(any( +++ windows, +++ target_os = "macos", +++ target_os = "ios", +++ not(feature = "https") +++))] +++fn openssl_env_init() {} +++ +++unsafe fn opt_bytes<'a, T>(_anchor: &'a T, c: *const libc::c_char) -> Option<&'a [u8]> { +++ if c.is_null() { +++ None +++ } else { +++ Some(CStr::from_ptr(c).to_bytes()) +++ } +++} +++ +++fn opt_cstr(o: Option) -> Result, Error> { +++ match o { +++ Some(s) => s.into_c_string().map(Some), +++ None => Ok(None), +++ } +++} +++ +++impl ObjectType { +++ /// Convert an object type to its string representation. +++ pub fn str(&self) -> &'static str { +++ unsafe { +++ let ptr = call!(raw::git_object_type2string(*self)) as *const _; +++ let data = CStr::from_ptr(ptr).to_bytes(); +++ str::from_utf8(data).unwrap() +++ } +++ } +++ +++ /// Determine if the given git_object_t is a valid loose object type. +++ pub fn is_loose(&self) -> bool { +++ unsafe { call!(raw::git_object_typeisloose(*self)) == 1 } +++ } +++ +++ /// Convert a raw git_object_t to an ObjectType +++ pub fn from_raw(raw: raw::git_object_t) -> Option { +++ match raw { +++ raw::GIT_OBJECT_ANY => Some(ObjectType::Any), +++ raw::GIT_OBJECT_COMMIT => Some(ObjectType::Commit), +++ raw::GIT_OBJECT_TREE => Some(ObjectType::Tree), +++ raw::GIT_OBJECT_BLOB => Some(ObjectType::Blob), +++ raw::GIT_OBJECT_TAG => Some(ObjectType::Tag), +++ _ => None, +++ } +++ } +++ +++ /// Convert this kind into its raw representation +++ pub fn raw(&self) -> raw::git_object_t { +++ call::convert(self) +++ } +++ +++ /// Convert a string object type representation to its object type. +++ pub fn from_str(s: &str) -> Option { +++ let raw = unsafe { call!(raw::git_object_string2type(CString::new(s).unwrap())) }; +++ ObjectType::from_raw(raw) +++ } +++} +++ +++impl fmt::Display for ObjectType { +++ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +++ self.str().fmt(f) +++ } +++} +++ +++impl ReferenceType { +++ /// Convert an object type to its string representation. +++ pub fn str(&self) -> &'static str { +++ match self { +++ ReferenceType::Direct => "direct", +++ ReferenceType::Symbolic => "symbolic", +++ } +++ } +++ +++ /// Convert a raw git_reference_t to a ReferenceType. +++ pub fn from_raw(raw: raw::git_reference_t) -> Option { +++ match raw { +++ raw::GIT_REFERENCE_DIRECT => Some(ReferenceType::Direct), +++ raw::GIT_REFERENCE_SYMBOLIC => Some(ReferenceType::Symbolic), +++ _ => None, +++ } +++ } +++} +++ +++impl fmt::Display for ReferenceType { +++ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +++ self.str().fmt(f) +++ } +++} +++ +++impl ConfigLevel { +++ /// Converts a raw configuration level to a ConfigLevel +++ pub fn from_raw(raw: raw::git_config_level_t) -> ConfigLevel { +++ match raw { +++ raw::GIT_CONFIG_LEVEL_PROGRAMDATA => ConfigLevel::ProgramData, +++ raw::GIT_CONFIG_LEVEL_SYSTEM => ConfigLevel::System, +++ raw::GIT_CONFIG_LEVEL_XDG => ConfigLevel::XDG, +++ raw::GIT_CONFIG_LEVEL_GLOBAL => ConfigLevel::Global, +++ raw::GIT_CONFIG_LEVEL_LOCAL => ConfigLevel::Local, +++ raw::GIT_CONFIG_LEVEL_WORKTREE => ConfigLevel::Worktree, +++ raw::GIT_CONFIG_LEVEL_APP => ConfigLevel::App, +++ raw::GIT_CONFIG_HIGHEST_LEVEL => ConfigLevel::Highest, +++ n => panic!("unknown config level: {}", n), +++ } +++ } +++} +++ +++impl SubmoduleIgnore { +++ /// Converts a [`raw::git_submodule_ignore_t`] to a [`SubmoduleIgnore`] +++ pub fn from_raw(raw: raw::git_submodule_ignore_t) -> Self { +++ match raw { +++ raw::GIT_SUBMODULE_IGNORE_UNSPECIFIED => SubmoduleIgnore::Unspecified, +++ raw::GIT_SUBMODULE_IGNORE_NONE => SubmoduleIgnore::None, +++ raw::GIT_SUBMODULE_IGNORE_UNTRACKED => SubmoduleIgnore::Untracked, +++ raw::GIT_SUBMODULE_IGNORE_DIRTY => SubmoduleIgnore::Dirty, +++ raw::GIT_SUBMODULE_IGNORE_ALL => SubmoduleIgnore::All, +++ n => panic!("unknown submodule ignore rule: {}", n), +++ } +++ } +++} +++ +++impl SubmoduleUpdate { +++ /// Converts a [`raw::git_submodule_update_t`] to a [`SubmoduleUpdate`] +++ pub fn from_raw(raw: raw::git_submodule_update_t) -> Self { +++ match raw { +++ raw::GIT_SUBMODULE_UPDATE_CHECKOUT => SubmoduleUpdate::Checkout, +++ raw::GIT_SUBMODULE_UPDATE_REBASE => SubmoduleUpdate::Rebase, +++ raw::GIT_SUBMODULE_UPDATE_MERGE => SubmoduleUpdate::Merge, +++ raw::GIT_SUBMODULE_UPDATE_NONE => SubmoduleUpdate::None, +++ raw::GIT_SUBMODULE_UPDATE_DEFAULT => SubmoduleUpdate::Default, +++ n => panic!("unknown submodule update strategy: {}", n), +++ } +++ } +++} +++ +++bitflags! { +++ /// Status flags for a single file +++ /// +++ /// A combination of these values will be returned to indicate the status of +++ /// a file. Status compares the working directory, the index, and the +++ /// current HEAD of the repository. The `STATUS_INDEX_*` set of flags +++ /// represents the status of file in the index relative to the HEAD, and the +++ /// `STATUS_WT_*` set of flags represent the status of the file in the +++ /// working directory relative to the index. +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct Status: u32 { +++ #[allow(missing_docs)] +++ const CURRENT = raw::GIT_STATUS_CURRENT as u32; +++ +++ #[allow(missing_docs)] +++ const INDEX_NEW = raw::GIT_STATUS_INDEX_NEW as u32; +++ #[allow(missing_docs)] +++ const INDEX_MODIFIED = raw::GIT_STATUS_INDEX_MODIFIED as u32; +++ #[allow(missing_docs)] +++ const INDEX_DELETED = raw::GIT_STATUS_INDEX_DELETED as u32; +++ #[allow(missing_docs)] +++ const INDEX_RENAMED = raw::GIT_STATUS_INDEX_RENAMED as u32; +++ #[allow(missing_docs)] +++ const INDEX_TYPECHANGE = raw::GIT_STATUS_INDEX_TYPECHANGE as u32; +++ +++ #[allow(missing_docs)] +++ const WT_NEW = raw::GIT_STATUS_WT_NEW as u32; +++ #[allow(missing_docs)] +++ const WT_MODIFIED = raw::GIT_STATUS_WT_MODIFIED as u32; +++ #[allow(missing_docs)] +++ const WT_DELETED = raw::GIT_STATUS_WT_DELETED as u32; +++ #[allow(missing_docs)] +++ const WT_TYPECHANGE = raw::GIT_STATUS_WT_TYPECHANGE as u32; +++ #[allow(missing_docs)] +++ const WT_RENAMED = raw::GIT_STATUS_WT_RENAMED as u32; +++ +++ #[allow(missing_docs)] +++ const IGNORED = raw::GIT_STATUS_IGNORED as u32; +++ #[allow(missing_docs)] +++ const CONFLICTED = raw::GIT_STATUS_CONFLICTED as u32; +++ } +++} +++ +++impl Status { +++ is_bit_set!(is_index_new, Status::INDEX_NEW); +++ is_bit_set!(is_index_modified, Status::INDEX_MODIFIED); +++ is_bit_set!(is_index_deleted, Status::INDEX_DELETED); +++ is_bit_set!(is_index_renamed, Status::INDEX_RENAMED); +++ is_bit_set!(is_index_typechange, Status::INDEX_TYPECHANGE); +++ is_bit_set!(is_wt_new, Status::WT_NEW); +++ is_bit_set!(is_wt_modified, Status::WT_MODIFIED); +++ is_bit_set!(is_wt_deleted, Status::WT_DELETED); +++ is_bit_set!(is_wt_typechange, Status::WT_TYPECHANGE); +++ is_bit_set!(is_wt_renamed, Status::WT_RENAMED); +++ is_bit_set!(is_ignored, Status::IGNORED); +++ is_bit_set!(is_conflicted, Status::CONFLICTED); +++} +++ +++bitflags! { +++ /// Mode options for RepositoryInitOptions +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct RepositoryInitMode: u32 { +++ /// Use permissions configured by umask - the default +++ const SHARED_UMASK = raw::GIT_REPOSITORY_INIT_SHARED_UMASK as u32; +++ /// Use `--shared=group` behavior, chmod'ing the new repo to be +++ /// group writable and \"g+sx\" for sticky group assignment +++ const SHARED_GROUP = raw::GIT_REPOSITORY_INIT_SHARED_GROUP as u32; +++ /// Use `--shared=all` behavior, adding world readability. +++ const SHARED_ALL = raw::GIT_REPOSITORY_INIT_SHARED_ALL as u32; +++ } +++} +++ +++impl RepositoryInitMode { +++ is_bit_set!(is_shared_umask, RepositoryInitMode::SHARED_UMASK); +++ is_bit_set!(is_shared_group, RepositoryInitMode::SHARED_GROUP); +++ is_bit_set!(is_shared_all, RepositoryInitMode::SHARED_ALL); +++} +++ +++/// What type of change is described by a `DiffDelta`? +++#[derive(Copy, Clone, Debug, PartialEq, Eq)] +++pub enum Delta { +++ /// No changes +++ Unmodified, +++ /// Entry does not exist in old version +++ Added, +++ /// Entry does not exist in new version +++ Deleted, +++ /// Entry content changed between old and new +++ Modified, +++ /// Entry was renamed between old and new +++ Renamed, +++ /// Entry was copied from another old entry +++ Copied, +++ /// Entry is ignored item in workdir +++ Ignored, +++ /// Entry is untracked item in workdir +++ Untracked, +++ /// Type of entry changed between old and new +++ Typechange, +++ /// Entry is unreadable +++ Unreadable, +++ /// Entry in the index is conflicted +++ Conflicted, +++} +++ +++/// Valid modes for index and tree entries. +++#[derive(Copy, Clone, Debug, PartialEq, Eq)] +++pub enum FileMode { +++ /// Unreadable +++ Unreadable, +++ /// Tree +++ Tree, +++ /// Blob +++ Blob, +++ /// Group writable blob. Obsolete mode kept for compatibility reasons +++ BlobGroupWritable, +++ /// Blob executable +++ BlobExecutable, +++ /// Link +++ Link, +++ /// Commit +++ Commit, +++} +++ +++impl From for i32 { +++ fn from(mode: FileMode) -> i32 { +++ match mode { +++ FileMode::Unreadable => raw::GIT_FILEMODE_UNREADABLE as i32, +++ FileMode::Tree => raw::GIT_FILEMODE_TREE as i32, +++ FileMode::Blob => raw::GIT_FILEMODE_BLOB as i32, +++ FileMode::BlobGroupWritable => raw::GIT_FILEMODE_BLOB_GROUP_WRITABLE as i32, +++ FileMode::BlobExecutable => raw::GIT_FILEMODE_BLOB_EXECUTABLE as i32, +++ FileMode::Link => raw::GIT_FILEMODE_LINK as i32, +++ FileMode::Commit => raw::GIT_FILEMODE_COMMIT as i32, +++ } +++ } +++} +++ +++impl From for u32 { +++ fn from(mode: FileMode) -> u32 { +++ match mode { +++ FileMode::Unreadable => raw::GIT_FILEMODE_UNREADABLE as u32, +++ FileMode::Tree => raw::GIT_FILEMODE_TREE as u32, +++ FileMode::Blob => raw::GIT_FILEMODE_BLOB as u32, +++ FileMode::BlobGroupWritable => raw::GIT_FILEMODE_BLOB_GROUP_WRITABLE as u32, +++ FileMode::BlobExecutable => raw::GIT_FILEMODE_BLOB_EXECUTABLE as u32, +++ FileMode::Link => raw::GIT_FILEMODE_LINK as u32, +++ FileMode::Commit => raw::GIT_FILEMODE_COMMIT as u32, +++ } +++ } +++} +++ +++bitflags! { +++ /// Return codes for submodule status. +++ /// +++ /// A combination of these flags will be returned to describe the status of a +++ /// submodule. Depending on the "ignore" property of the submodule, some of +++ /// the flags may never be returned because they indicate changes that are +++ /// supposed to be ignored. +++ /// +++ /// Submodule info is contained in 4 places: the HEAD tree, the index, config +++ /// files (both .git/config and .gitmodules), and the working directory. Any +++ /// or all of those places might be missing information about the submodule +++ /// depending on what state the repo is in. We consider all four places to +++ /// build the combination of status flags. +++ /// +++ /// There are four values that are not really status, but give basic info +++ /// about what sources of submodule data are available. These will be +++ /// returned even if ignore is set to "ALL". +++ /// +++ /// * IN_HEAD - superproject head contains submodule +++ /// * IN_INDEX - superproject index contains submodule +++ /// * IN_CONFIG - superproject gitmodules has submodule +++ /// * IN_WD - superproject workdir has submodule +++ /// +++ /// The following values will be returned so long as ignore is not "ALL". +++ /// +++ /// * INDEX_ADDED - in index, not in head +++ /// * INDEX_DELETED - in head, not in index +++ /// * INDEX_MODIFIED - index and head don't match +++ /// * WD_UNINITIALIZED - workdir contains empty directory +++ /// * WD_ADDED - in workdir, not index +++ /// * WD_DELETED - in index, not workdir +++ /// * WD_MODIFIED - index and workdir head don't match +++ /// +++ /// The following can only be returned if ignore is "NONE" or "UNTRACKED". +++ /// +++ /// * WD_INDEX_MODIFIED - submodule workdir index is dirty +++ /// * WD_WD_MODIFIED - submodule workdir has modified files +++ /// +++ /// Lastly, the following will only be returned for ignore "NONE". +++ /// +++ /// * WD_UNTRACKED - workdir contains untracked files +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct SubmoduleStatus: u32 { +++ #[allow(missing_docs)] +++ const IN_HEAD = raw::GIT_SUBMODULE_STATUS_IN_HEAD as u32; +++ #[allow(missing_docs)] +++ const IN_INDEX = raw::GIT_SUBMODULE_STATUS_IN_INDEX as u32; +++ #[allow(missing_docs)] +++ const IN_CONFIG = raw::GIT_SUBMODULE_STATUS_IN_CONFIG as u32; +++ #[allow(missing_docs)] +++ const IN_WD = raw::GIT_SUBMODULE_STATUS_IN_WD as u32; +++ #[allow(missing_docs)] +++ const INDEX_ADDED = raw::GIT_SUBMODULE_STATUS_INDEX_ADDED as u32; +++ #[allow(missing_docs)] +++ const INDEX_DELETED = raw::GIT_SUBMODULE_STATUS_INDEX_DELETED as u32; +++ #[allow(missing_docs)] +++ const INDEX_MODIFIED = raw::GIT_SUBMODULE_STATUS_INDEX_MODIFIED as u32; +++ #[allow(missing_docs)] +++ const WD_UNINITIALIZED = +++ raw::GIT_SUBMODULE_STATUS_WD_UNINITIALIZED as u32; +++ #[allow(missing_docs)] +++ const WD_ADDED = raw::GIT_SUBMODULE_STATUS_WD_ADDED as u32; +++ #[allow(missing_docs)] +++ const WD_DELETED = raw::GIT_SUBMODULE_STATUS_WD_DELETED as u32; +++ #[allow(missing_docs)] +++ const WD_MODIFIED = raw::GIT_SUBMODULE_STATUS_WD_MODIFIED as u32; +++ #[allow(missing_docs)] +++ const WD_INDEX_MODIFIED = +++ raw::GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED as u32; +++ #[allow(missing_docs)] +++ const WD_WD_MODIFIED = raw::GIT_SUBMODULE_STATUS_WD_WD_MODIFIED as u32; +++ #[allow(missing_docs)] +++ const WD_UNTRACKED = raw::GIT_SUBMODULE_STATUS_WD_UNTRACKED as u32; +++ } +++} +++ +++impl SubmoduleStatus { +++ is_bit_set!(is_in_head, SubmoduleStatus::IN_HEAD); +++ is_bit_set!(is_in_index, SubmoduleStatus::IN_INDEX); +++ is_bit_set!(is_in_config, SubmoduleStatus::IN_CONFIG); +++ is_bit_set!(is_in_wd, SubmoduleStatus::IN_WD); +++ is_bit_set!(is_index_added, SubmoduleStatus::INDEX_ADDED); +++ is_bit_set!(is_index_deleted, SubmoduleStatus::INDEX_DELETED); +++ is_bit_set!(is_index_modified, SubmoduleStatus::INDEX_MODIFIED); +++ is_bit_set!(is_wd_uninitialized, SubmoduleStatus::WD_UNINITIALIZED); +++ is_bit_set!(is_wd_added, SubmoduleStatus::WD_ADDED); +++ is_bit_set!(is_wd_deleted, SubmoduleStatus::WD_DELETED); +++ is_bit_set!(is_wd_modified, SubmoduleStatus::WD_MODIFIED); +++ is_bit_set!(is_wd_wd_modified, SubmoduleStatus::WD_WD_MODIFIED); +++ is_bit_set!(is_wd_untracked, SubmoduleStatus::WD_UNTRACKED); +++} +++ +++/// Submodule ignore values +++/// +++/// These values represent settings for the `submodule.$name.ignore` +++/// configuration value which says how deeply to look at the working +++/// directory when getting the submodule status. +++#[derive(Copy, Clone, Debug, PartialEq, Eq)] +++pub enum SubmoduleIgnore { +++ /// Use the submodule's configuration +++ Unspecified, +++ /// Any change or untracked file is considered dirty +++ None, +++ /// Only dirty if tracked files have changed +++ Untracked, +++ /// Only dirty if HEAD has moved +++ Dirty, +++ /// Never dirty +++ All, +++} +++ +++/// Submodule update values +++/// +++/// These values represent settings for the `submodule.$name.update` +++/// configuration value which says how to handle `git submodule update` +++/// for this submodule. The value is usually set in the ".gitmodules" +++/// file and copied to ".git/config" when the submodule is initialized. +++#[derive(Copy, Clone, Debug, PartialEq, Eq)] +++pub enum SubmoduleUpdate { +++ /// The default; when a submodule is updated, checkout the new detached +++ /// HEAD to the submodule directory. +++ Checkout, +++ /// Update by rebasing the current checked out branch onto the commit from +++ /// the superproject. +++ Rebase, +++ /// Update by merging the commit in the superproject into the current +++ /// checkout out branch of the submodule. +++ Merge, +++ /// Do not update this submodule even when the commit in the superproject +++ /// is updated. +++ None, +++ /// Not used except as static initializer when we don't want any particular +++ /// update rule to be specified. +++ Default, +++} +++ +++bitflags! { +++ /// ... +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct PathspecFlags: u32 { +++ /// Use the default pathspec matching configuration. +++ const DEFAULT = raw::GIT_PATHSPEC_DEFAULT as u32; +++ /// Force matching to ignore case, otherwise matching will use native +++ /// case sensitivity of the platform filesystem. +++ const IGNORE_CASE = raw::GIT_PATHSPEC_IGNORE_CASE as u32; +++ /// Force case sensitive matches, otherwise match will use the native +++ /// case sensitivity of the platform filesystem. +++ const USE_CASE = raw::GIT_PATHSPEC_USE_CASE as u32; +++ /// Disable glob patterns and just use simple string comparison for +++ /// matching. +++ const NO_GLOB = raw::GIT_PATHSPEC_NO_GLOB as u32; +++ /// Means that match functions return the error code `NotFound` if no +++ /// matches are found. By default no matches is a success. +++ const NO_MATCH_ERROR = raw::GIT_PATHSPEC_NO_MATCH_ERROR as u32; +++ /// Means that the list returned should track which patterns matched +++ /// which files so that at the end of the match we can identify patterns +++ /// that did not match any files. +++ const FIND_FAILURES = raw::GIT_PATHSPEC_FIND_FAILURES as u32; +++ /// Means that the list returned does not need to keep the actual +++ /// matching filenames. Use this to just test if there were any matches +++ /// at all or in combination with `PATHSPEC_FAILURES` to validate a +++ /// pathspec. +++ const FAILURES_ONLY = raw::GIT_PATHSPEC_FAILURES_ONLY as u32; +++ } +++} +++ +++impl PathspecFlags { +++ is_bit_set!(is_default, PathspecFlags::DEFAULT); +++ is_bit_set!(is_ignore_case, PathspecFlags::IGNORE_CASE); +++ is_bit_set!(is_use_case, PathspecFlags::USE_CASE); +++ is_bit_set!(is_no_glob, PathspecFlags::NO_GLOB); +++ is_bit_set!(is_no_match_error, PathspecFlags::NO_MATCH_ERROR); +++ is_bit_set!(is_find_failures, PathspecFlags::FIND_FAILURES); +++ is_bit_set!(is_failures_only, PathspecFlags::FAILURES_ONLY); +++} +++ +++impl Default for PathspecFlags { +++ fn default() -> Self { +++ PathspecFlags::DEFAULT +++ } +++} +++ +++bitflags! { +++ /// Types of notifications emitted from checkouts. +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct CheckoutNotificationType: u32 { +++ /// Notification about a conflict. +++ const CONFLICT = raw::GIT_CHECKOUT_NOTIFY_CONFLICT as u32; +++ /// Notification about a dirty file. +++ const DIRTY = raw::GIT_CHECKOUT_NOTIFY_DIRTY as u32; +++ /// Notification about an updated file. +++ const UPDATED = raw::GIT_CHECKOUT_NOTIFY_UPDATED as u32; +++ /// Notification about an untracked file. +++ const UNTRACKED = raw::GIT_CHECKOUT_NOTIFY_UNTRACKED as u32; +++ /// Notification about an ignored file. +++ const IGNORED = raw::GIT_CHECKOUT_NOTIFY_IGNORED as u32; +++ } +++} +++ +++impl CheckoutNotificationType { +++ is_bit_set!(is_conflict, CheckoutNotificationType::CONFLICT); +++ is_bit_set!(is_dirty, CheckoutNotificationType::DIRTY); +++ is_bit_set!(is_updated, CheckoutNotificationType::UPDATED); +++ is_bit_set!(is_untracked, CheckoutNotificationType::UNTRACKED); +++ is_bit_set!(is_ignored, CheckoutNotificationType::IGNORED); +++} +++ +++/// Possible output formats for diff data +++#[derive(Copy, Clone, Debug, PartialEq, Eq)] +++pub enum DiffFormat { +++ /// full git diff +++ Patch, +++ /// just the headers of the patch +++ PatchHeader, +++ /// like git diff --raw +++ Raw, +++ /// like git diff --name-only +++ NameOnly, +++ /// like git diff --name-status +++ NameStatus, +++ /// git diff as used by git patch-id +++ PatchId, +++} +++ +++bitflags! { +++ /// Formatting options for diff stats +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct DiffStatsFormat: raw::git_diff_stats_format_t { +++ /// Don't generate any stats +++ const NONE = raw::GIT_DIFF_STATS_NONE; +++ /// Equivalent of `--stat` in git +++ const FULL = raw::GIT_DIFF_STATS_FULL; +++ /// Equivalent of `--shortstat` in git +++ const SHORT = raw::GIT_DIFF_STATS_SHORT; +++ /// Equivalent of `--numstat` in git +++ const NUMBER = raw::GIT_DIFF_STATS_NUMBER; +++ /// Extended header information such as creations, renames and mode +++ /// changes, equivalent of `--summary` in git +++ const INCLUDE_SUMMARY = raw::GIT_DIFF_STATS_INCLUDE_SUMMARY; +++ } +++} +++ +++impl DiffStatsFormat { +++ is_bit_set!(is_none, DiffStatsFormat::NONE); +++ is_bit_set!(is_full, DiffStatsFormat::FULL); +++ is_bit_set!(is_short, DiffStatsFormat::SHORT); +++ is_bit_set!(is_number, DiffStatsFormat::NUMBER); +++ is_bit_set!(is_include_summary, DiffStatsFormat::INCLUDE_SUMMARY); +++} +++ +++/// Automatic tag following options. +++#[derive(Copy, Clone, Debug, PartialEq, Eq)] +++pub enum AutotagOption { +++ /// Use the setting from the remote's configuration +++ Unspecified, +++ /// Ask the server for tags pointing to objects we're already downloading +++ Auto, +++ /// Don't ask for any tags beyond the refspecs +++ None, +++ /// Ask for all the tags +++ All, +++} +++ +++/// Configuration for how pruning is done on a fetch +++#[derive(Copy, Clone, Debug, PartialEq, Eq)] +++pub enum FetchPrune { +++ /// Use the setting from the configuration +++ Unspecified, +++ /// Force pruning on +++ On, +++ /// Force pruning off +++ Off, +++} +++ +++#[allow(missing_docs)] +++#[derive(Copy, Clone, Debug, PartialEq, Eq)] +++pub enum StashApplyProgress { +++ /// None +++ None, +++ /// Loading the stashed data from the object database +++ LoadingStash, +++ /// The stored index is being analyzed +++ AnalyzeIndex, +++ /// The modified files are being analyzed +++ AnalyzeModified, +++ /// The untracked and ignored files are being analyzed +++ AnalyzeUntracked, +++ /// The untracked files are being written to disk +++ CheckoutUntracked, +++ /// The modified files are being written to disk +++ CheckoutModified, +++ /// The stash was applied successfully +++ Done, +++} +++ +++bitflags! { +++ #[allow(missing_docs)] +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct StashApplyFlags: u32 { +++ #[allow(missing_docs)] +++ const DEFAULT = raw::GIT_STASH_APPLY_DEFAULT as u32; +++ /// Try to reinstate not only the working tree's changes, +++ /// but also the index's changes. +++ const REINSTATE_INDEX = raw::GIT_STASH_APPLY_REINSTATE_INDEX as u32; +++ } +++} +++ +++impl StashApplyFlags { +++ is_bit_set!(is_default, StashApplyFlags::DEFAULT); +++ is_bit_set!(is_reinstate_index, StashApplyFlags::REINSTATE_INDEX); +++} +++ +++impl Default for StashApplyFlags { +++ fn default() -> Self { +++ StashApplyFlags::DEFAULT +++ } +++} +++ +++bitflags! { +++ #[allow(missing_docs)] +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct StashFlags: u32 { +++ #[allow(missing_docs)] +++ const DEFAULT = raw::GIT_STASH_DEFAULT as u32; +++ /// All changes already added to the index are left intact in +++ /// the working directory +++ const KEEP_INDEX = raw::GIT_STASH_KEEP_INDEX as u32; +++ /// All untracked files are also stashed and then cleaned up +++ /// from the working directory +++ const INCLUDE_UNTRACKED = raw::GIT_STASH_INCLUDE_UNTRACKED as u32; +++ /// All ignored files are also stashed and then cleaned up from +++ /// the working directory +++ const INCLUDE_IGNORED = raw::GIT_STASH_INCLUDE_IGNORED as u32; +++ /// All changes in the index and working directory are left intact +++ const KEEP_ALL = raw::GIT_STASH_KEEP_ALL as u32; +++ } +++} +++ +++impl StashFlags { +++ is_bit_set!(is_default, StashFlags::DEFAULT); +++ is_bit_set!(is_keep_index, StashFlags::KEEP_INDEX); +++ is_bit_set!(is_include_untracked, StashFlags::INCLUDE_UNTRACKED); +++ is_bit_set!(is_include_ignored, StashFlags::INCLUDE_IGNORED); +++} +++ +++impl Default for StashFlags { +++ fn default() -> Self { +++ StashFlags::DEFAULT +++ } +++} +++ +++bitflags! { +++ #[allow(missing_docs)] +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct AttrCheckFlags: u32 { +++ /// Check the working directory, then the index. +++ const FILE_THEN_INDEX = raw::GIT_ATTR_CHECK_FILE_THEN_INDEX as u32; +++ /// Check the index, then the working directory. +++ const INDEX_THEN_FILE = raw::GIT_ATTR_CHECK_INDEX_THEN_FILE as u32; +++ /// Check the index only. +++ const INDEX_ONLY = raw::GIT_ATTR_CHECK_INDEX_ONLY as u32; +++ /// Do not use the system gitattributes file. +++ const NO_SYSTEM = raw::GIT_ATTR_CHECK_NO_SYSTEM as u32; +++ } +++} +++ +++impl Default for AttrCheckFlags { +++ fn default() -> Self { +++ AttrCheckFlags::FILE_THEN_INDEX +++ } +++} +++ +++bitflags! { +++ #[allow(missing_docs)] +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct DiffFlags: u32 { +++ /// File(s) treated as binary data. +++ const BINARY = raw::GIT_DIFF_FLAG_BINARY as u32; +++ /// File(s) treated as text data. +++ const NOT_BINARY = raw::GIT_DIFF_FLAG_NOT_BINARY as u32; +++ /// `id` value is known correct. +++ const VALID_ID = raw::GIT_DIFF_FLAG_VALID_ID as u32; +++ /// File exists at this side of the delta. +++ const EXISTS = raw::GIT_DIFF_FLAG_EXISTS as u32; +++ } +++} +++ +++impl DiffFlags { +++ is_bit_set!(is_binary, DiffFlags::BINARY); +++ is_bit_set!(is_not_binary, DiffFlags::NOT_BINARY); +++ is_bit_set!(has_valid_id, DiffFlags::VALID_ID); +++ is_bit_set!(exists, DiffFlags::EXISTS); +++} +++ +++bitflags! { +++ /// Options for [`Reference::normalize_name`]. +++ #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +++ pub struct ReferenceFormat: u32 { +++ /// No particular normalization. +++ const NORMAL = raw::GIT_REFERENCE_FORMAT_NORMAL as u32; +++ /// Control whether one-level refname are accepted (i.e., refnames that +++ /// do not contain multiple `/`-separated components). Those are +++ /// expected to be written only using uppercase letters and underscore +++ /// (e.g. `HEAD`, `FETCH_HEAD`). +++ const ALLOW_ONELEVEL = raw::GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL as u32; +++ /// Interpret the provided name as a reference pattern for a refspec (as +++ /// used with remote repositories). If this option is enabled, the name +++ /// is allowed to contain a single `*` in place of a full pathname +++ /// components (e.g., `foo/*/bar` but not `foo/bar*`). +++ const REFSPEC_PATTERN = raw::GIT_REFERENCE_FORMAT_REFSPEC_PATTERN as u32; +++ /// Interpret the name as part of a refspec in shorthand form so the +++ /// `ALLOW_ONELEVEL` naming rules aren't enforced and `main` becomes a +++ /// valid name. +++ const REFSPEC_SHORTHAND = raw::GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND as u32; +++ } +++} +++ +++impl ReferenceFormat { +++ is_bit_set!(is_allow_onelevel, ReferenceFormat::ALLOW_ONELEVEL); +++ is_bit_set!(is_refspec_pattern, ReferenceFormat::REFSPEC_PATTERN); +++ is_bit_set!(is_refspec_shorthand, ReferenceFormat::REFSPEC_SHORTHAND); +++} +++ +++impl Default for ReferenceFormat { +++ fn default() -> Self { +++ ReferenceFormat::NORMAL +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use super::{FileMode, ObjectType}; +++ +++ #[test] +++ fn convert() { +++ assert_eq!(ObjectType::Blob.str(), "blob"); +++ assert_eq!(ObjectType::from_str("blob"), Some(ObjectType::Blob)); +++ assert!(ObjectType::Blob.is_loose()); +++ } +++ +++ #[test] +++ fn convert_filemode() { +++ assert_eq!(i32::from(FileMode::Blob), 0o100644); +++ assert_eq!(i32::from(FileMode::BlobGroupWritable), 0o100664); +++ assert_eq!(i32::from(FileMode::BlobExecutable), 0o100755); +++ assert_eq!(u32::from(FileMode::Blob), 0o100644); +++ assert_eq!(u32::from(FileMode::BlobGroupWritable), 0o100664); +++ assert_eq!(u32::from(FileMode::BlobExecutable), 0o100755); +++ } +++ +++ #[test] +++ fn bitflags_partial_eq() { +++ use super::{ +++ AttrCheckFlags, CheckoutNotificationType, CredentialType, DiffFlags, DiffStatsFormat, +++ IndexAddOption, IndexEntryExtendedFlag, IndexEntryFlag, MergeAnalysis, MergePreference, +++ OdbLookupFlags, PathspecFlags, ReferenceFormat, RepositoryInitMode, +++ RepositoryOpenFlags, RevparseMode, Sort, StashApplyFlags, StashFlags, Status, +++ SubmoduleStatus, +++ }; +++ +++ assert_eq!( +++ AttrCheckFlags::FILE_THEN_INDEX, +++ AttrCheckFlags::FILE_THEN_INDEX +++ ); +++ assert_eq!( +++ CheckoutNotificationType::CONFLICT, +++ CheckoutNotificationType::CONFLICT +++ ); +++ assert_eq!( +++ CredentialType::USER_PASS_PLAINTEXT, +++ CredentialType::USER_PASS_PLAINTEXT +++ ); +++ assert_eq!(DiffFlags::BINARY, DiffFlags::BINARY); +++ assert_eq!( +++ DiffStatsFormat::INCLUDE_SUMMARY, +++ DiffStatsFormat::INCLUDE_SUMMARY +++ ); +++ assert_eq!( +++ IndexAddOption::CHECK_PATHSPEC, +++ IndexAddOption::CHECK_PATHSPEC +++ ); +++ assert_eq!( +++ IndexEntryExtendedFlag::INTENT_TO_ADD, +++ IndexEntryExtendedFlag::INTENT_TO_ADD +++ ); +++ assert_eq!(IndexEntryFlag::EXTENDED, IndexEntryFlag::EXTENDED); +++ assert_eq!( +++ MergeAnalysis::ANALYSIS_FASTFORWARD, +++ MergeAnalysis::ANALYSIS_FASTFORWARD +++ ); +++ assert_eq!( +++ MergePreference::FASTFORWARD_ONLY, +++ MergePreference::FASTFORWARD_ONLY +++ ); +++ assert_eq!(OdbLookupFlags::NO_REFRESH, OdbLookupFlags::NO_REFRESH); +++ assert_eq!(PathspecFlags::FAILURES_ONLY, PathspecFlags::FAILURES_ONLY); +++ assert_eq!( +++ ReferenceFormat::ALLOW_ONELEVEL, +++ ReferenceFormat::ALLOW_ONELEVEL +++ ); +++ assert_eq!( +++ RepositoryInitMode::SHARED_ALL, +++ RepositoryInitMode::SHARED_ALL +++ ); +++ assert_eq!(RepositoryOpenFlags::CROSS_FS, RepositoryOpenFlags::CROSS_FS); +++ assert_eq!(RevparseMode::RANGE, RevparseMode::RANGE); +++ assert_eq!(Sort::REVERSE, Sort::REVERSE); +++ assert_eq!( +++ StashApplyFlags::REINSTATE_INDEX, +++ StashApplyFlags::REINSTATE_INDEX +++ ); +++ assert_eq!(StashFlags::INCLUDE_IGNORED, StashFlags::INCLUDE_IGNORED); +++ assert_eq!(Status::WT_MODIFIED, Status::WT_MODIFIED); +++ assert_eq!(SubmoduleStatus::WD_ADDED, SubmoduleStatus::WD_ADDED); +++ } +++} diff --cc extra/git2/src/mailmap.rs index 0000000000,0000000000,0000000000..096b3227c7 new file mode 100644 --- /dev/null +++ b/extra/git2/src/mailmap.rs @@@@ -1,0 -1,0 -1,0 +1,134 @@@@ +++use std::ffi::CString; +++use std::ptr; +++ +++use crate::util::Binding; +++use crate::{raw, Error, Signature}; +++ +++/// A structure to represent a repository's .mailmap file. +++/// +++/// The representation cannot be written to disk. +++pub struct Mailmap { +++ raw: *mut raw::git_mailmap, +++} +++ +++impl Binding for Mailmap { +++ type Raw = *mut raw::git_mailmap; +++ +++ unsafe fn from_raw(ptr: *mut raw::git_mailmap) -> Mailmap { +++ Mailmap { raw: ptr } +++ } +++ +++ fn raw(&self) -> *mut raw::git_mailmap { +++ self.raw +++ } +++} +++ +++impl Drop for Mailmap { +++ fn drop(&mut self) { +++ unsafe { +++ raw::git_mailmap_free(self.raw); +++ } +++ } +++} +++ +++impl Mailmap { +++ /// Creates an empty, in-memory mailmap object. +++ pub fn new() -> Result { +++ crate::init(); +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_mailmap_new(&mut ret)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Creates an in-memory mailmap object representing the given buffer. +++ pub fn from_buffer(buf: &str) -> Result { +++ crate::init(); +++ let mut ret = ptr::null_mut(); +++ let len = buf.len(); +++ let buf = CString::new(buf)?; +++ unsafe { +++ try_call!(raw::git_mailmap_from_buffer(&mut ret, buf, len)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Adds a new entry to this in-memory mailmap object. +++ pub fn add_entry( +++ &mut self, +++ real_name: Option<&str>, +++ real_email: Option<&str>, +++ replace_name: Option<&str>, +++ replace_email: &str, +++ ) -> Result<(), Error> { +++ let real_name = crate::opt_cstr(real_name)?; +++ let real_email = crate::opt_cstr(real_email)?; +++ let replace_name = crate::opt_cstr(replace_name)?; +++ let replace_email = CString::new(replace_email)?; +++ unsafe { +++ try_call!(raw::git_mailmap_add_entry( +++ self.raw, +++ real_name, +++ real_email, +++ replace_name, +++ replace_email +++ )); +++ Ok(()) +++ } +++ } +++ +++ /// Resolves a signature to its real name and email address. +++ pub fn resolve_signature(&self, sig: &Signature<'_>) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_mailmap_resolve_signature( +++ &mut ret, +++ &*self.raw, +++ sig.raw() +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use super::*; +++ +++ #[test] +++ fn smoke() { +++ let sig_name = "name"; +++ let sig_email = "email"; +++ let sig = t!(Signature::now(sig_name, sig_email)); +++ +++ let mut mm = t!(Mailmap::new()); +++ +++ let mailmapped_sig = t!(mm.resolve_signature(&sig)); +++ assert_eq!(mailmapped_sig.name(), Some(sig_name)); +++ assert_eq!(mailmapped_sig.email(), Some(sig_email)); +++ +++ t!(mm.add_entry(None, None, None, sig_email)); +++ t!(mm.add_entry( +++ Some("real name"), +++ Some("real@email"), +++ Some(sig_name), +++ sig_email, +++ )); +++ +++ let mailmapped_sig = t!(mm.resolve_signature(&sig)); +++ assert_eq!(mailmapped_sig.name(), Some("real name")); +++ assert_eq!(mailmapped_sig.email(), Some("real@email")); +++ } +++ +++ #[test] +++ fn from_buffer() { +++ let buf = " "; +++ let mm = t!(Mailmap::from_buffer(&buf)); +++ +++ let sig = t!(Signature::now("name", "email")); +++ let mailmapped_sig = t!(mm.resolve_signature(&sig)); +++ assert_eq!(mailmapped_sig.name(), Some("name")); +++ assert_eq!(mailmapped_sig.email(), Some("prøper@emæil")); +++ } +++} diff --cc extra/git2/src/mempack.rs index 0000000000,0000000000,0000000000..a780707913 new file mode 100644 --- /dev/null +++ b/extra/git2/src/mempack.rs @@@@ -1,0 -1,0 -1,0 +1,49 @@@@ +++use std::marker; +++ +++use crate::util::Binding; +++use crate::{raw, Buf, Error, Odb, Repository}; +++ +++/// A structure to represent a mempack backend for the object database. The +++/// Mempack is bound to the Odb that it was created from, and cannot outlive +++/// that Odb. +++pub struct Mempack<'odb> { +++ raw: *mut raw::git_odb_backend, +++ _marker: marker::PhantomData<&'odb Odb<'odb>>, +++} +++ +++impl<'odb> Binding for Mempack<'odb> { +++ type Raw = *mut raw::git_odb_backend; +++ +++ unsafe fn from_raw(raw: *mut raw::git_odb_backend) -> Mempack<'odb> { +++ Mempack { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ +++ fn raw(&self) -> *mut raw::git_odb_backend { +++ self.raw +++ } +++} +++ +++// We don't need to implement `Drop` for Mempack because it is owned by the +++// odb to which it is attached, and that will take care of freeing the mempack +++// and associated memory. +++ +++impl<'odb> Mempack<'odb> { +++ /// Dumps the contents of the mempack into the provided buffer. +++ pub fn dump(&self, repo: &Repository, buf: &mut Buf) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_mempack_dump(buf.raw(), repo.raw(), self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Clears all data in the mempack. +++ pub fn reset(&self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_mempack_reset(self.raw)); +++ } +++ Ok(()) +++ } +++} diff --cc extra/git2/src/merge.rs index 0000000000,0000000000,0000000000..6bd30c10d1 new file mode 100644 --- /dev/null +++ b/extra/git2/src/merge.rs @@@@ -1,0 -1,0 -1,0 +1,194 @@@@ +++use libc::c_uint; +++use std::marker; +++use std::mem; +++use std::str; +++ +++use crate::call::Convert; +++use crate::util::Binding; +++use crate::{raw, Commit, FileFavor, Oid}; +++ +++/// A structure to represent an annotated commit, the input to merge and rebase. +++/// +++/// An annotated commit contains information about how it was looked up, which +++/// may be useful for functions like merge or rebase to provide context to the +++/// operation. +++pub struct AnnotatedCommit<'repo> { +++ raw: *mut raw::git_annotated_commit, +++ _marker: marker::PhantomData>, +++} +++ +++/// Options to specify when merging. +++pub struct MergeOptions { +++ raw: raw::git_merge_options, +++} +++ +++impl<'repo> AnnotatedCommit<'repo> { +++ /// Gets the commit ID that the given git_annotated_commit refers to +++ pub fn id(&self) -> Oid { +++ unsafe { Binding::from_raw(raw::git_annotated_commit_id(self.raw)) } +++ } +++ +++ /// Get the refname that the given git_annotated_commit refers to +++ /// +++ /// Returns None if it is not valid utf8 +++ pub fn refname(&self) -> Option<&str> { +++ str::from_utf8(self.refname_bytes()).ok() +++ } +++ +++ /// Get the refname that the given git_annotated_commit refers to. +++ pub fn refname_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, raw::git_annotated_commit_ref(&*self.raw)).unwrap() } +++ } +++} +++ +++impl Default for MergeOptions { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl MergeOptions { +++ /// Creates a default set of merge options. +++ pub fn new() -> MergeOptions { +++ let mut opts = MergeOptions { +++ raw: unsafe { mem::zeroed() }, +++ }; +++ assert_eq!(unsafe { raw::git_merge_init_options(&mut opts.raw, 1) }, 0); +++ opts +++ } +++ +++ fn flag(&mut self, opt: u32, val: bool) -> &mut MergeOptions { +++ if val { +++ self.raw.flags |= opt; +++ } else { +++ self.raw.flags &= !opt; +++ } +++ self +++ } +++ +++ /// Detect file renames +++ pub fn find_renames(&mut self, find: bool) -> &mut MergeOptions { +++ self.flag(raw::GIT_MERGE_FIND_RENAMES as u32, find) +++ } +++ +++ /// If a conflict occurs, exit immediately instead of attempting to continue +++ /// resolving conflicts +++ pub fn fail_on_conflict(&mut self, fail: bool) -> &mut MergeOptions { +++ self.flag(raw::GIT_MERGE_FAIL_ON_CONFLICT as u32, fail) +++ } +++ +++ /// Do not write the REUC extension on the generated index +++ pub fn skip_reuc(&mut self, skip: bool) -> &mut MergeOptions { +++ self.flag(raw::GIT_MERGE_FAIL_ON_CONFLICT as u32, skip) +++ } +++ +++ /// If the commits being merged have multiple merge bases, do not build a +++ /// recursive merge base (by merging the multiple merge bases), instead +++ /// simply use the first base. +++ pub fn no_recursive(&mut self, disable: bool) -> &mut MergeOptions { +++ self.flag(raw::GIT_MERGE_NO_RECURSIVE as u32, disable) +++ } +++ +++ /// Similarity to consider a file renamed (default 50) +++ pub fn rename_threshold(&mut self, thresh: u32) -> &mut MergeOptions { +++ self.raw.rename_threshold = thresh; +++ self +++ } +++ +++ /// Maximum similarity sources to examine for renames (default 200). +++ /// If the number of rename candidates (add / delete pairs) is greater +++ /// than this value, inexact rename detection is aborted. This setting +++ /// overrides the `merge.renameLimit` configuration value. +++ pub fn target_limit(&mut self, limit: u32) -> &mut MergeOptions { +++ self.raw.target_limit = limit as c_uint; +++ self +++ } +++ +++ /// Maximum number of times to merge common ancestors to build a +++ /// virtual merge base when faced with criss-cross merges. When +++ /// this limit is reached, the next ancestor will simply be used +++ /// instead of attempting to merge it. The default is unlimited. +++ pub fn recursion_limit(&mut self, limit: u32) -> &mut MergeOptions { +++ self.raw.recursion_limit = limit as c_uint; +++ self +++ } +++ +++ /// Specify a side to favor for resolving conflicts +++ pub fn file_favor(&mut self, favor: FileFavor) -> &mut MergeOptions { +++ self.raw.file_favor = favor.convert(); +++ self +++ } +++ +++ fn file_flag(&mut self, opt: u32, val: bool) -> &mut MergeOptions { +++ if val { +++ self.raw.file_flags |= opt; +++ } else { +++ self.raw.file_flags &= !opt; +++ } +++ self +++ } +++ +++ /// Create standard conflicted merge files +++ pub fn standard_style(&mut self, standard: bool) -> &mut MergeOptions { +++ self.file_flag(raw::GIT_MERGE_FILE_STYLE_MERGE as u32, standard) +++ } +++ +++ /// Create diff3-style file +++ pub fn diff3_style(&mut self, diff3: bool) -> &mut MergeOptions { +++ self.file_flag(raw::GIT_MERGE_FILE_STYLE_DIFF3 as u32, diff3) +++ } +++ +++ /// Condense non-alphanumeric regions for simplified diff file +++ pub fn simplify_alnum(&mut self, simplify: bool) -> &mut MergeOptions { +++ self.file_flag(raw::GIT_MERGE_FILE_SIMPLIFY_ALNUM as u32, simplify) +++ } +++ +++ /// Ignore all whitespace +++ pub fn ignore_whitespace(&mut self, ignore: bool) -> &mut MergeOptions { +++ self.file_flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE as u32, ignore) +++ } +++ +++ /// Ignore changes in amount of whitespace +++ pub fn ignore_whitespace_change(&mut self, ignore: bool) -> &mut MergeOptions { +++ self.file_flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE as u32, ignore) +++ } +++ +++ /// Ignore whitespace at end of line +++ pub fn ignore_whitespace_eol(&mut self, ignore: bool) -> &mut MergeOptions { +++ self.file_flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL as u32, ignore) +++ } +++ +++ /// Use the "patience diff" algorithm +++ pub fn patience(&mut self, patience: bool) -> &mut MergeOptions { +++ self.file_flag(raw::GIT_MERGE_FILE_DIFF_PATIENCE as u32, patience) +++ } +++ +++ /// Take extra time to find minimal diff +++ pub fn minimal(&mut self, minimal: bool) -> &mut MergeOptions { +++ self.file_flag(raw::GIT_MERGE_FILE_DIFF_MINIMAL as u32, minimal) +++ } +++ +++ /// Acquire a pointer to the underlying raw options. +++ pub unsafe fn raw(&self) -> *const raw::git_merge_options { +++ &self.raw as *const _ +++ } +++} +++ +++impl<'repo> Binding for AnnotatedCommit<'repo> { +++ type Raw = *mut raw::git_annotated_commit; +++ unsafe fn from_raw(raw: *mut raw::git_annotated_commit) -> AnnotatedCommit<'repo> { +++ AnnotatedCommit { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_annotated_commit { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for AnnotatedCommit<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_annotated_commit_free(self.raw) } +++ } +++} diff --cc extra/git2/src/message.rs index 0000000000,0000000000,0000000000..a7041da3ae new file mode 100644 --- /dev/null +++ b/extra/git2/src/message.rs @@@@ -1,0 -1,0 -1,0 +1,349 @@@@ +++use core::ops::Range; +++use std::ffi::CStr; +++use std::ffi::CString; +++use std::iter::FusedIterator; +++use std::ptr; +++ +++use libc::{c_char, c_int}; +++ +++use crate::util::Binding; +++use crate::{raw, Buf, Error, IntoCString}; +++ +++/// Clean up a message, removing extraneous whitespace, and ensure that the +++/// message ends with a newline. If `comment_char` is `Some`, also remove comment +++/// lines starting with that character. +++pub fn message_prettify( +++ message: T, +++ comment_char: Option, +++) -> Result { +++ _message_prettify(message.into_c_string()?, comment_char) +++} +++ +++fn _message_prettify(message: CString, comment_char: Option) -> Result { +++ let ret = Buf::new(); +++ unsafe { +++ try_call!(raw::git_message_prettify( +++ ret.raw(), +++ message, +++ comment_char.is_some() as c_int, +++ comment_char.unwrap_or(0) as c_char +++ )); +++ } +++ Ok(ret.as_str().unwrap().to_string()) +++} +++ +++/// The default comment character for `message_prettify` ('#') +++pub const DEFAULT_COMMENT_CHAR: Option = Some(b'#'); +++ +++/// Get the trailers for the given message. +++/// +++/// Use this function when you are dealing with a UTF-8-encoded message. +++pub fn message_trailers_strs(message: &str) -> Result { +++ _message_trailers(message.into_c_string()?).map(|res| MessageTrailersStrs(res)) +++} +++ +++/// Get the trailers for the given message. +++/// +++/// Use this function when the message might not be UTF-8-encoded, +++/// or if you want to handle the returned trailer key–value pairs +++/// as bytes. +++pub fn message_trailers_bytes(message: S) -> Result { +++ _message_trailers(message.into_c_string()?).map(|res| MessageTrailersBytes(res)) +++} +++ +++fn _message_trailers(message: CString) -> Result { +++ let ret = MessageTrailers::new(); +++ unsafe { +++ try_call!(raw::git_message_trailers(ret.raw(), message)); +++ } +++ Ok(ret) +++} +++ +++/// Collection of UTF-8-encoded trailers. +++/// +++/// Use `iter()` to get access to the values. +++pub struct MessageTrailersStrs(MessageTrailers); +++ +++impl MessageTrailersStrs { +++ /// Create a borrowed iterator. +++ pub fn iter(&self) -> MessageTrailersStrsIterator<'_> { +++ MessageTrailersStrsIterator(self.0.iter()) +++ } +++ /// The number of trailer key–value pairs. +++ pub fn len(&self) -> usize { +++ self.0.len() +++ } +++ /// Convert to the “bytes” variant. +++ pub fn to_bytes(self) -> MessageTrailersBytes { +++ MessageTrailersBytes(self.0) +++ } +++} +++ +++/// Collection of unencoded (bytes) trailers. +++/// +++/// Use `iter()` to get access to the values. +++pub struct MessageTrailersBytes(MessageTrailers); +++ +++impl MessageTrailersBytes { +++ /// Create a borrowed iterator. +++ pub fn iter(&self) -> MessageTrailersBytesIterator<'_> { +++ MessageTrailersBytesIterator(self.0.iter()) +++ } +++ /// The number of trailer key–value pairs. +++ pub fn len(&self) -> usize { +++ self.0.len() +++ } +++} +++ +++struct MessageTrailers { +++ raw: raw::git_message_trailer_array, +++} +++ +++impl MessageTrailers { +++ fn new() -> MessageTrailers { +++ crate::init(); +++ unsafe { +++ Binding::from_raw(&mut raw::git_message_trailer_array { +++ trailers: ptr::null_mut(), +++ count: 0, +++ _trailer_block: ptr::null_mut(), +++ } as *mut _) +++ } +++ } +++ fn iter(&self) -> MessageTrailersIterator<'_> { +++ MessageTrailersIterator { +++ trailers: self, +++ range: Range { +++ start: 0, +++ end: self.raw.count, +++ }, +++ } +++ } +++ fn len(&self) -> usize { +++ self.raw.count +++ } +++} +++ +++impl Drop for MessageTrailers { +++ fn drop(&mut self) { +++ unsafe { +++ raw::git_message_trailer_array_free(&mut self.raw); +++ } +++ } +++} +++ +++impl Binding for MessageTrailers { +++ type Raw = *mut raw::git_message_trailer_array; +++ unsafe fn from_raw(raw: *mut raw::git_message_trailer_array) -> MessageTrailers { +++ MessageTrailers { raw: *raw } +++ } +++ fn raw(&self) -> *mut raw::git_message_trailer_array { +++ &self.raw as *const _ as *mut _ +++ } +++} +++ +++struct MessageTrailersIterator<'a> { +++ trailers: &'a MessageTrailers, +++ range: Range, +++} +++ +++fn to_raw_tuple(trailers: &MessageTrailers, index: usize) -> (*const c_char, *const c_char) { +++ unsafe { +++ let addr = trailers.raw.trailers.wrapping_add(index); +++ ((*addr).key, (*addr).value) +++ } +++} +++ +++/// Borrowed iterator over the UTF-8-encoded trailers. +++pub struct MessageTrailersStrsIterator<'a>(MessageTrailersIterator<'a>); +++ +++impl<'pair> Iterator for MessageTrailersStrsIterator<'pair> { +++ type Item = (&'pair str, &'pair str); +++ +++ fn next(&mut self) -> Option { +++ self.0 +++ .range +++ .next() +++ .map(|index| to_str_tuple(&self.0.trailers, index)) +++ } +++ +++ fn size_hint(&self) -> (usize, Option) { +++ self.0.range.size_hint() +++ } +++} +++ +++impl FusedIterator for MessageTrailersStrsIterator<'_> {} +++ +++impl ExactSizeIterator for MessageTrailersStrsIterator<'_> { +++ fn len(&self) -> usize { +++ self.0.range.len() +++ } +++} +++ +++impl DoubleEndedIterator for MessageTrailersStrsIterator<'_> { +++ fn next_back(&mut self) -> Option { +++ self.0 +++ .range +++ .next_back() +++ .map(|index| to_str_tuple(&self.0.trailers, index)) +++ } +++} +++ +++fn to_str_tuple(trailers: &MessageTrailers, index: usize) -> (&str, &str) { +++ unsafe { +++ let (rkey, rvalue) = to_raw_tuple(&trailers, index); +++ let key = CStr::from_ptr(rkey).to_str().unwrap(); +++ let value = CStr::from_ptr(rvalue).to_str().unwrap(); +++ (key, value) +++ } +++} +++ +++/// Borrowed iterator over the raw (bytes) trailers. +++pub struct MessageTrailersBytesIterator<'a>(MessageTrailersIterator<'a>); +++ +++impl<'pair> Iterator for MessageTrailersBytesIterator<'pair> { +++ type Item = (&'pair [u8], &'pair [u8]); +++ +++ fn next(&mut self) -> Option { +++ self.0 +++ .range +++ .next() +++ .map(|index| to_bytes_tuple(&self.0.trailers, index)) +++ } +++ +++ fn size_hint(&self) -> (usize, Option) { +++ self.0.range.size_hint() +++ } +++} +++ +++impl FusedIterator for MessageTrailersBytesIterator<'_> {} +++ +++impl ExactSizeIterator for MessageTrailersBytesIterator<'_> { +++ fn len(&self) -> usize { +++ self.0.range.len() +++ } +++} +++ +++impl DoubleEndedIterator for MessageTrailersBytesIterator<'_> { +++ fn next_back(&mut self) -> Option { +++ self.0 +++ .range +++ .next_back() +++ .map(|index| to_bytes_tuple(&self.0.trailers, index)) +++ } +++} +++ +++fn to_bytes_tuple(trailers: &MessageTrailers, index: usize) -> (&[u8], &[u8]) { +++ unsafe { +++ let (rkey, rvalue) = to_raw_tuple(&trailers, index); +++ let key = CStr::from_ptr(rkey).to_bytes(); +++ let value = CStr::from_ptr(rvalue).to_bytes(); +++ (key, value) +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ +++ #[test] +++ fn prettify() { +++ use crate::{message_prettify, DEFAULT_COMMENT_CHAR}; +++ +++ // This does not attempt to duplicate the extensive tests for +++ // git_message_prettify in libgit2, just a few representative values to +++ // make sure the interface works as expected. +++ assert_eq!(message_prettify("1\n\n\n2", None).unwrap(), "1\n\n2\n"); +++ assert_eq!( +++ message_prettify("1\n\n\n2\n\n\n3", None).unwrap(), +++ "1\n\n2\n\n3\n" +++ ); +++ assert_eq!( +++ message_prettify("1\n# comment\n# more", None).unwrap(), +++ "1\n# comment\n# more\n" +++ ); +++ assert_eq!( +++ message_prettify("1\n# comment\n# more", DEFAULT_COMMENT_CHAR).unwrap(), +++ "1\n" +++ ); +++ assert_eq!( +++ message_prettify("1\n; comment\n; more", Some(';' as u8)).unwrap(), +++ "1\n" +++ ); +++ } +++ +++ #[test] +++ fn trailers() { +++ use crate::{message_trailers_bytes, message_trailers_strs, MessageTrailersStrs}; +++ use std::collections::HashMap; +++ +++ // no trailers +++ let message1 = " +++WHAT ARE WE HERE FOR +++ +++What are we here for? +++ +++Just to be eaten? +++"; +++ let expected: HashMap<&str, &str> = HashMap::new(); +++ assert_eq!(expected, to_map(&message_trailers_strs(message1).unwrap())); +++ +++ // standard PSA +++ let message2 = " +++Attention all +++ +++We are out of tomatoes. +++ +++Spoken-by: Major Turnips +++Transcribed-by: Seargant Persimmons +++Signed-off-by: Colonel Kale +++"; +++ let expected: HashMap<&str, &str> = vec![ +++ ("Spoken-by", "Major Turnips"), +++ ("Transcribed-by", "Seargant Persimmons"), +++ ("Signed-off-by", "Colonel Kale"), +++ ] +++ .into_iter() +++ .collect(); +++ assert_eq!(expected, to_map(&message_trailers_strs(message2).unwrap())); +++ +++ // ignore everything after `---` +++ let message3 = " +++The fate of Seargant Green-Peppers +++ +++Seargant Green-Peppers was killed by Caterpillar Battalion 44. +++ +++Signed-off-by: Colonel Kale +++--- +++I never liked that guy, anyway. +++ +++Opined-by: Corporal Garlic +++"; +++ let expected: HashMap<&str, &str> = vec![("Signed-off-by", "Colonel Kale")] +++ .into_iter() +++ .collect(); +++ assert_eq!(expected, to_map(&message_trailers_strs(message3).unwrap())); +++ +++ // Raw bytes message; not valid UTF-8 +++ // Source: https://stackoverflow.com/a/3886015/1725151 +++ let message4 = b" +++Be honest guys +++ +++Am I a malformed brussels sprout? +++ +++Signed-off-by: Lieutenant \xe2\x28\xa1prout +++"; +++ +++ let trailer = message_trailers_bytes(&message4[..]).unwrap(); +++ let expected = (&b"Signed-off-by"[..], &b"Lieutenant \xe2\x28\xa1prout"[..]); +++ let actual = trailer.iter().next().unwrap(); +++ assert_eq!(expected, actual); +++ +++ fn to_map(trailers: &MessageTrailersStrs) -> HashMap<&str, &str> { +++ let mut map = HashMap::with_capacity(trailers.len()); +++ for (key, value) in trailers.iter() { +++ map.insert(key, value); +++ } +++ map +++ } +++ } +++} diff --cc extra/git2/src/note.rs index 0000000000,0000000000,0000000000..50e5800fe7 new file mode 100644 --- /dev/null +++ b/extra/git2/src/note.rs @@@@ -1,0 -1,0 -1,0 +1,147 @@@@ +++use std::marker; +++use std::str; +++ +++use crate::util::Binding; +++use crate::{raw, signature, Error, Oid, Repository, Signature}; +++ +++/// A structure representing a [note][note] in git. +++/// +++/// [note]: http://alblue.bandlem.com/2011/11/git-tip-of-week-git-notes.html +++pub struct Note<'repo> { +++ raw: *mut raw::git_note, +++ +++ // Hmm, the current libgit2 version does not have this inside of it, but +++ // perhaps it's a good idea to keep it around? Can always remove it later I +++ // suppose... +++ _marker: marker::PhantomData<&'repo Repository>, +++} +++ +++/// An iterator over all of the notes within a repository. +++pub struct Notes<'repo> { +++ raw: *mut raw::git_note_iterator, +++ _marker: marker::PhantomData<&'repo Repository>, +++} +++ +++impl<'repo> Note<'repo> { +++ /// Get the note author +++ pub fn author(&self) -> Signature<'_> { +++ unsafe { signature::from_raw_const(self, raw::git_note_author(&*self.raw)) } +++ } +++ +++ /// Get the note committer +++ pub fn committer(&self) -> Signature<'_> { +++ unsafe { signature::from_raw_const(self, raw::git_note_committer(&*self.raw)) } +++ } +++ +++ /// Get the note message, in bytes. +++ pub fn message_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, raw::git_note_message(&*self.raw)).unwrap() } +++ } +++ +++ /// Get the note message as a string, returning `None` if it is not UTF-8. +++ pub fn message(&self) -> Option<&str> { +++ str::from_utf8(self.message_bytes()).ok() +++ } +++ +++ /// Get the note object's id +++ pub fn id(&self) -> Oid { +++ unsafe { Binding::from_raw(raw::git_note_id(&*self.raw)) } +++ } +++} +++ +++impl<'repo> Binding for Note<'repo> { +++ type Raw = *mut raw::git_note; +++ unsafe fn from_raw(raw: *mut raw::git_note) -> Note<'repo> { +++ Note { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_note { +++ self.raw +++ } +++} +++ +++impl<'repo> std::fmt::Debug for Note<'repo> { +++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +++ f.debug_struct("Note").field("id", &self.id()).finish() +++ } +++} +++ +++impl<'repo> Drop for Note<'repo> { +++ fn drop(&mut self) { +++ unsafe { +++ raw::git_note_free(self.raw); +++ } +++ } +++} +++ +++impl<'repo> Binding for Notes<'repo> { +++ type Raw = *mut raw::git_note_iterator; +++ unsafe fn from_raw(raw: *mut raw::git_note_iterator) -> Notes<'repo> { +++ Notes { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_note_iterator { +++ self.raw +++ } +++} +++ +++impl<'repo> Iterator for Notes<'repo> { +++ type Item = Result<(Oid, Oid), Error>; +++ fn next(&mut self) -> Option> { +++ let mut note_id = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ let mut annotated_id = note_id; +++ unsafe { +++ try_call_iter!(raw::git_note_next( +++ &mut note_id, +++ &mut annotated_id, +++ self.raw +++ )); +++ Some(Ok(( +++ Binding::from_raw(¬e_id as *const _), +++ Binding::from_raw(&annotated_id as *const _), +++ ))) +++ } +++ } +++} +++ +++impl<'repo> Drop for Notes<'repo> { +++ fn drop(&mut self) { +++ unsafe { +++ raw::git_note_iterator_free(self.raw); +++ } +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ assert!(repo.notes(None).is_err()); +++ +++ let sig = repo.signature().unwrap(); +++ let head = repo.head().unwrap().target().unwrap(); +++ let note = repo.note(&sig, &sig, None, head, "foo", false).unwrap(); +++ assert_eq!(repo.notes(None).unwrap().count(), 1); +++ +++ let note_obj = repo.find_note(None, head).unwrap(); +++ assert_eq!(note_obj.id(), note); +++ assert_eq!(note_obj.message(), Some("foo")); +++ +++ let (a, b) = repo.notes(None).unwrap().next().unwrap().unwrap(); +++ assert_eq!(a, note); +++ assert_eq!(b, head); +++ +++ assert_eq!(repo.note_default_ref().unwrap(), "refs/notes/commits"); +++ +++ assert_eq!(sig.name(), note_obj.author().name()); +++ assert_eq!(sig.name(), note_obj.committer().name()); +++ assert!(sig.when() == note_obj.committer().when()); +++ } +++} diff --cc extra/git2/src/object.rs index 0000000000,0000000000,0000000000..fcae0066cb new file mode 100644 --- /dev/null +++ b/extra/git2/src/object.rs @@@@ -1,0 -1,0 -1,0 +1,248 @@@@ +++use std::marker; +++use std::mem; +++use std::ptr; +++ +++use crate::util::Binding; +++use crate::{raw, Blob, Buf, Commit, Error, ObjectType, Oid, Repository, Tag, Tree}; +++use crate::{Describe, DescribeOptions}; +++ +++/// A structure to represent a git [object][1] +++/// +++/// [1]: http://git-scm.com/book/en/Git-Internals-Git-Objects +++pub struct Object<'repo> { +++ raw: *mut raw::git_object, +++ _marker: marker::PhantomData<&'repo Repository>, +++} +++ +++impl<'repo> Object<'repo> { +++ /// Get the id (SHA1) of a repository object +++ pub fn id(&self) -> Oid { +++ unsafe { Binding::from_raw(raw::git_object_id(&*self.raw)) } +++ } +++ +++ /// Get the object type of an object. +++ /// +++ /// If the type is unknown, then `None` is returned. +++ pub fn kind(&self) -> Option { +++ ObjectType::from_raw(unsafe { raw::git_object_type(&*self.raw) }) +++ } +++ +++ /// Recursively peel an object until an object of the specified type is met. +++ /// +++ /// If you pass `Any` as the target type, then the object will be +++ /// peeled until the type changes (e.g. a tag will be chased until the +++ /// referenced object is no longer a tag). +++ pub fn peel(&self, kind: ObjectType) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_object_peel(&mut raw, &*self.raw(), kind)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Recursively peel an object until a blob is found +++ pub fn peel_to_blob(&self) -> Result, Error> { +++ self.peel(ObjectType::Blob) +++ .map(|o| o.cast_or_panic(ObjectType::Blob)) +++ } +++ +++ /// Recursively peel an object until a commit is found +++ pub fn peel_to_commit(&self) -> Result, Error> { +++ self.peel(ObjectType::Commit) +++ .map(|o| o.cast_or_panic(ObjectType::Commit)) +++ } +++ +++ /// Recursively peel an object until a tag is found +++ pub fn peel_to_tag(&self) -> Result, Error> { +++ self.peel(ObjectType::Tag) +++ .map(|o| o.cast_or_panic(ObjectType::Tag)) +++ } +++ +++ /// Recursively peel an object until a tree is found +++ pub fn peel_to_tree(&self) -> Result, Error> { +++ self.peel(ObjectType::Tree) +++ .map(|o| o.cast_or_panic(ObjectType::Tree)) +++ } +++ +++ /// Get a short abbreviated OID string for the object +++ /// +++ /// This starts at the "core.abbrev" length (default 7 characters) and +++ /// iteratively extends to a longer string if that length is ambiguous. The +++ /// result will be unambiguous (at least until new objects are added to the +++ /// repository). +++ pub fn short_id(&self) -> Result { +++ unsafe { +++ let buf = Buf::new(); +++ try_call!(raw::git_object_short_id(buf.raw(), &*self.raw())); +++ Ok(buf) +++ } +++ } +++ +++ /// Attempt to view this object as a commit. +++ /// +++ /// Returns `None` if the object is not actually a commit. +++ pub fn as_commit(&self) -> Option<&Commit<'repo>> { +++ self.cast(ObjectType::Commit) +++ } +++ +++ /// Attempt to consume this object and return a commit. +++ /// +++ /// Returns `Err(self)` if this object is not actually a commit. +++ pub fn into_commit(self) -> Result, Object<'repo>> { +++ self.cast_into(ObjectType::Commit) +++ } +++ +++ /// Attempt to view this object as a tag. +++ /// +++ /// Returns `None` if the object is not actually a tag. +++ pub fn as_tag(&self) -> Option<&Tag<'repo>> { +++ self.cast(ObjectType::Tag) +++ } +++ +++ /// Attempt to consume this object and return a tag. +++ /// +++ /// Returns `Err(self)` if this object is not actually a tag. +++ pub fn into_tag(self) -> Result, Object<'repo>> { +++ self.cast_into(ObjectType::Tag) +++ } +++ +++ /// Attempt to view this object as a tree. +++ /// +++ /// Returns `None` if the object is not actually a tree. +++ pub fn as_tree(&self) -> Option<&Tree<'repo>> { +++ self.cast(ObjectType::Tree) +++ } +++ +++ /// Attempt to consume this object and return a tree. +++ /// +++ /// Returns `Err(self)` if this object is not actually a tree. +++ pub fn into_tree(self) -> Result, Object<'repo>> { +++ self.cast_into(ObjectType::Tree) +++ } +++ +++ /// Attempt to view this object as a blob. +++ /// +++ /// Returns `None` if the object is not actually a blob. +++ pub fn as_blob(&self) -> Option<&Blob<'repo>> { +++ self.cast(ObjectType::Blob) +++ } +++ +++ /// Attempt to consume this object and return a blob. +++ /// +++ /// Returns `Err(self)` if this object is not actually a blob. +++ pub fn into_blob(self) -> Result, Object<'repo>> { +++ self.cast_into(ObjectType::Blob) +++ } +++ +++ /// Describes a commit +++ /// +++ /// Performs a describe operation on this commitish object. +++ pub fn describe(&self, opts: &DescribeOptions) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_describe_commit(&mut ret, self.raw, opts.raw())); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ fn cast(&self, kind: ObjectType) -> Option<&T> { +++ assert_eq!(mem::size_of::>(), mem::size_of::()); +++ if self.kind() == Some(kind) { +++ unsafe { Some(&*(self as *const _ as *const T)) } +++ } else { +++ None +++ } +++ } +++ +++ fn cast_into(self, kind: ObjectType) -> Result> { +++ assert_eq!(mem::size_of_val(&self), mem::size_of::()); +++ if self.kind() == Some(kind) { +++ Ok(unsafe { +++ let other = ptr::read(&self as *const _ as *const T); +++ mem::forget(self); +++ other +++ }) +++ } else { +++ Err(self) +++ } +++ } +++} +++ +++/// This trait is useful to export cast_or_panic into crate but not outside +++pub trait CastOrPanic { +++ fn cast_or_panic(self, kind: ObjectType) -> T; +++} +++ +++impl<'repo> CastOrPanic for Object<'repo> { +++ fn cast_or_panic(self, kind: ObjectType) -> T { +++ assert_eq!(mem::size_of_val(&self), mem::size_of::()); +++ if self.kind() == Some(kind) { +++ unsafe { +++ let other = ptr::read(&self as *const _ as *const T); +++ mem::forget(self); +++ other +++ } +++ } else { +++ let buf; +++ let akind = match self.kind() { +++ Some(akind) => akind.str(), +++ None => { +++ buf = format!("unknown ({})", unsafe { raw::git_object_type(&*self.raw) }); +++ &buf +++ } +++ }; +++ panic!( +++ "Expected object {} to be {} but it is {}", +++ self.id(), +++ kind.str(), +++ akind +++ ) +++ } +++ } +++} +++ +++impl<'repo> Clone for Object<'repo> { +++ fn clone(&self) -> Object<'repo> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ let rc = raw::git_object_dup(&mut raw, self.raw); +++ assert_eq!(rc, 0); +++ Binding::from_raw(raw) +++ } +++ } +++} +++ +++impl<'repo> std::fmt::Debug for Object<'repo> { +++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +++ let mut ds = f.debug_struct("Object"); +++ match self.kind() { +++ Some(kind) => ds.field("kind", &kind), +++ None => ds.field( +++ "kind", +++ &format!("Unknow ({})", unsafe { raw::git_object_type(&*self.raw) }), +++ ), +++ }; +++ ds.field("id", &self.id()); +++ ds.finish() +++ } +++} +++ +++impl<'repo> Binding for Object<'repo> { +++ type Raw = *mut raw::git_object; +++ +++ unsafe fn from_raw(raw: *mut raw::git_object) -> Object<'repo> { +++ Object { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_object { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for Object<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_object_free(self.raw) } +++ } +++} diff --cc extra/git2/src/odb.rs index 0000000000,0000000000,0000000000..2019908c48 new file mode 100644 --- /dev/null +++ b/extra/git2/src/odb.rs @@@@ -1,0 -1,0 -1,0 +1,770 @@@@ +++use std::io; +++use std::marker; +++use std::ptr; +++use std::slice; +++ +++use std::ffi::CString; +++ +++use libc::{c_char, c_int, c_uint, c_void, size_t}; +++ +++use crate::panic; +++use crate::util::Binding; +++use crate::{ +++ raw, Error, IndexerProgress, Mempack, Object, ObjectType, OdbLookupFlags, Oid, Progress, +++}; +++ +++/// A structure to represent a git object database +++pub struct Odb<'repo> { +++ raw: *mut raw::git_odb, +++ _marker: marker::PhantomData>, +++} +++ +++// `git_odb` uses locking and atomics internally. +++unsafe impl<'repo> Send for Odb<'repo> {} +++unsafe impl<'repo> Sync for Odb<'repo> {} +++ +++impl<'repo> Binding for Odb<'repo> { +++ type Raw = *mut raw::git_odb; +++ +++ unsafe fn from_raw(raw: *mut raw::git_odb) -> Odb<'repo> { +++ Odb { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_odb { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for Odb<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_odb_free(self.raw) } +++ } +++} +++ +++impl<'repo> Odb<'repo> { +++ /// Creates an object database without any backends. +++ pub fn new<'a>() -> Result, Error> { +++ crate::init(); +++ unsafe { +++ let mut out = ptr::null_mut(); +++ try_call!(raw::git_odb_new(&mut out)); +++ Ok(Odb::from_raw(out)) +++ } +++ } +++ +++ /// Create object database reading stream. +++ /// +++ /// Note that most backends do not support streaming reads because they store their objects as compressed/delta'ed blobs. +++ /// If the backend does not support streaming reads, use the `read` method instead. +++ pub fn reader(&self, oid: Oid) -> Result<(OdbReader<'_>, usize, ObjectType), Error> { +++ let mut out = ptr::null_mut(); +++ let mut size = 0usize; +++ let mut otype: raw::git_object_t = ObjectType::Any.raw(); +++ unsafe { +++ try_call!(raw::git_odb_open_rstream( +++ &mut out, +++ &mut size, +++ &mut otype, +++ self.raw, +++ oid.raw() +++ )); +++ Ok(( +++ OdbReader::from_raw(out), +++ size, +++ ObjectType::from_raw(otype).unwrap(), +++ )) +++ } +++ } +++ +++ /// Create object database writing stream. +++ /// +++ /// The type and final length of the object must be specified when opening the stream. +++ /// If the backend does not support streaming writes, use the `write` method instead. +++ pub fn writer(&self, size: usize, obj_type: ObjectType) -> Result, Error> { +++ let mut out = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_odb_open_wstream( +++ &mut out, +++ self.raw, +++ size as raw::git_object_size_t, +++ obj_type.raw() +++ )); +++ Ok(OdbWriter::from_raw(out)) +++ } +++ } +++ +++ /// Iterate over all objects in the object database.s +++ pub fn foreach(&self, mut callback: C) -> Result<(), Error> +++ where +++ C: FnMut(&Oid) -> bool, +++ { +++ unsafe { +++ let mut data = ForeachCbData { +++ callback: &mut callback, +++ }; +++ let cb: raw::git_odb_foreach_cb = Some(foreach_cb); +++ try_call!(raw::git_odb_foreach( +++ self.raw(), +++ cb, +++ &mut data as *mut _ as *mut _ +++ )); +++ Ok(()) +++ } +++ } +++ +++ /// Read an object from the database. +++ pub fn read(&self, oid: Oid) -> Result, Error> { +++ let mut out = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_odb_read(&mut out, self.raw, oid.raw())); +++ Ok(OdbObject::from_raw(out)) +++ } +++ } +++ +++ /// Reads the header of an object from the database +++ /// without reading the full content. +++ pub fn read_header(&self, oid: Oid) -> Result<(usize, ObjectType), Error> { +++ let mut size: usize = 0; +++ let mut kind_id: i32 = ObjectType::Any.raw(); +++ +++ unsafe { +++ try_call!(raw::git_odb_read_header( +++ &mut size as *mut size_t, +++ &mut kind_id as *mut raw::git_object_t, +++ self.raw, +++ oid.raw() +++ )); +++ +++ Ok((size, ObjectType::from_raw(kind_id).unwrap())) +++ } +++ } +++ +++ /// Write an object to the database. +++ pub fn write(&self, kind: ObjectType, data: &[u8]) -> Result { +++ unsafe { +++ let mut out = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ try_call!(raw::git_odb_write( +++ &mut out, +++ self.raw, +++ data.as_ptr() as *const c_void, +++ data.len(), +++ kind.raw() +++ )); +++ Ok(Oid::from_raw(&mut out)) +++ } +++ } +++ +++ /// Create stream for writing a pack file to the ODB +++ pub fn packwriter(&self) -> Result, Error> { +++ let mut out = ptr::null_mut(); +++ let progress_cb: raw::git_indexer_progress_cb = Some(write_pack_progress_cb); +++ let progress_payload = Box::new(OdbPackwriterCb { cb: None }); +++ let progress_payload_ptr = Box::into_raw(progress_payload); +++ +++ unsafe { +++ try_call!(raw::git_odb_write_pack( +++ &mut out, +++ self.raw, +++ progress_cb, +++ progress_payload_ptr as *mut c_void +++ )); +++ } +++ +++ Ok(OdbPackwriter { +++ raw: out, +++ progress: Default::default(), +++ progress_payload_ptr, +++ }) +++ } +++ +++ /// Checks if the object database has an object. +++ pub fn exists(&self, oid: Oid) -> bool { +++ unsafe { raw::git_odb_exists(self.raw, oid.raw()) != 0 } +++ } +++ +++ /// Checks if the object database has an object, with extended flags. +++ pub fn exists_ext(&self, oid: Oid, flags: OdbLookupFlags) -> bool { +++ unsafe { raw::git_odb_exists_ext(self.raw, oid.raw(), flags.bits() as c_uint) != 0 } +++ } +++ +++ /// Potentially finds an object that starts with the given prefix. +++ pub fn exists_prefix(&self, short_oid: Oid, len: usize) -> Result { +++ unsafe { +++ let mut out = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ try_call!(raw::git_odb_exists_prefix( +++ &mut out, +++ self.raw, +++ short_oid.raw(), +++ len +++ )); +++ Ok(Oid::from_raw(&out)) +++ } +++ } +++ +++ /// Refresh the object database. +++ /// This should never be needed, and is +++ /// provided purely for convenience. +++ /// The object database will automatically +++ /// refresh when an object is not found when +++ /// requested. +++ pub fn refresh(&self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_odb_refresh(self.raw)); +++ Ok(()) +++ } +++ } +++ +++ /// Adds an alternate disk backend to the object database. +++ pub fn add_disk_alternate(&self, path: &str) -> Result<(), Error> { +++ unsafe { +++ let path = CString::new(path)?; +++ try_call!(raw::git_odb_add_disk_alternate(self.raw, path)); +++ Ok(()) +++ } +++ } +++ +++ /// Create a new mempack backend, and add it to this odb with the given +++ /// priority. Higher values give the backend higher precedence. The default +++ /// loose and pack backends have priorities 1 and 2 respectively (hard-coded +++ /// in libgit2). A reference to the new mempack backend is returned on +++ /// success. The lifetime of the backend must be contained within the +++ /// lifetime of this odb, since deletion of the odb will also result in +++ /// deletion of the mempack backend. +++ /// +++ /// Here is an example that fails to compile because it tries to hold the +++ /// mempack reference beyond the Odb's lifetime: +++ /// +++ /// ```compile_fail +++ /// use git2::Odb; +++ /// let mempack = { +++ /// let odb = Odb::new().unwrap(); +++ /// odb.add_new_mempack_backend(1000).unwrap() +++ /// }; +++ /// ``` +++ pub fn add_new_mempack_backend<'odb>( +++ &'odb self, +++ priority: i32, +++ ) -> Result, Error> { +++ unsafe { +++ let mut mempack = ptr::null_mut(); +++ // The mempack backend object in libgit2 is only ever freed by an +++ // odb that has the backend in its list. So to avoid potentially +++ // leaking the mempack backend, this API ensures that the backend +++ // is added to the odb before returning it. The lifetime of the +++ // mempack is also bound to the lifetime of the odb, so that users +++ // can't end up with a dangling reference to a mempack object that +++ // was actually freed when the odb was destroyed. +++ try_call!(raw::git_mempack_new(&mut mempack)); +++ try_call!(raw::git_odb_add_backend( +++ self.raw, +++ mempack, +++ priority as c_int +++ )); +++ Ok(Mempack::from_raw(mempack)) +++ } +++ } +++} +++ +++/// An object from the Object Database. +++pub struct OdbObject<'a> { +++ raw: *mut raw::git_odb_object, +++ _marker: marker::PhantomData>, +++} +++ +++impl<'a> Binding for OdbObject<'a> { +++ type Raw = *mut raw::git_odb_object; +++ +++ unsafe fn from_raw(raw: *mut raw::git_odb_object) -> OdbObject<'a> { +++ OdbObject { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ +++ fn raw(&self) -> *mut raw::git_odb_object { +++ self.raw +++ } +++} +++ +++impl<'a> Drop for OdbObject<'a> { +++ fn drop(&mut self) { +++ unsafe { raw::git_odb_object_free(self.raw) } +++ } +++} +++ +++impl<'a> OdbObject<'a> { +++ /// Get the object type. +++ pub fn kind(&self) -> ObjectType { +++ unsafe { ObjectType::from_raw(raw::git_odb_object_type(self.raw)).unwrap() } +++ } +++ +++ /// Get the object size. +++ pub fn len(&self) -> usize { +++ unsafe { raw::git_odb_object_size(self.raw) } +++ } +++ +++ /// Get the object data. +++ pub fn data(&self) -> &[u8] { +++ unsafe { +++ let size = self.len(); +++ let ptr: *const u8 = raw::git_odb_object_data(self.raw) as *const u8; +++ let buffer = slice::from_raw_parts(ptr, size); +++ return buffer; +++ } +++ } +++ +++ /// Get the object id. +++ pub fn id(&self) -> Oid { +++ unsafe { Oid::from_raw(raw::git_odb_object_id(self.raw)) } +++ } +++} +++ +++/// A structure to represent a git ODB rstream +++pub struct OdbReader<'repo> { +++ raw: *mut raw::git_odb_stream, +++ _marker: marker::PhantomData>, +++} +++ +++// `git_odb_stream` is not thread-safe internally, so it can't use `Sync`, but moving it to another +++// thread and continuing to read will work. +++unsafe impl<'repo> Send for OdbReader<'repo> {} +++ +++impl<'repo> Binding for OdbReader<'repo> { +++ type Raw = *mut raw::git_odb_stream; +++ +++ unsafe fn from_raw(raw: *mut raw::git_odb_stream) -> OdbReader<'repo> { +++ OdbReader { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_odb_stream { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for OdbReader<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_odb_stream_free(self.raw) } +++ } +++} +++ +++impl<'repo> io::Read for OdbReader<'repo> { +++ fn read(&mut self, buf: &mut [u8]) -> io::Result { +++ unsafe { +++ let ptr = buf.as_ptr() as *mut c_char; +++ let len = buf.len(); +++ let res = raw::git_odb_stream_read(self.raw, ptr, len); +++ if res < 0 { +++ Err(io::Error::new(io::ErrorKind::Other, "Read error")) +++ } else { +++ Ok(res as _) +++ } +++ } +++ } +++} +++ +++/// A structure to represent a git ODB wstream +++pub struct OdbWriter<'repo> { +++ raw: *mut raw::git_odb_stream, +++ _marker: marker::PhantomData>, +++} +++ +++// `git_odb_stream` is not thread-safe internally, so it can't use `Sync`, but moving it to another +++// thread and continuing to write will work. +++unsafe impl<'repo> Send for OdbWriter<'repo> {} +++ +++impl<'repo> OdbWriter<'repo> { +++ /// Finish writing to an ODB stream +++ /// +++ /// This method can be used to finalize writing object to the database and get an identifier. +++ /// The object will take its final name and will be available to the odb. +++ /// This method will fail if the total number of received bytes differs from the size declared with odb_writer() +++ /// Attempting write after finishing will be ignored. +++ pub fn finalize(&mut self) -> Result { +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_odb_stream_finalize_write(&mut raw, self.raw)); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++} +++ +++impl<'repo> Binding for OdbWriter<'repo> { +++ type Raw = *mut raw::git_odb_stream; +++ +++ unsafe fn from_raw(raw: *mut raw::git_odb_stream) -> OdbWriter<'repo> { +++ OdbWriter { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_odb_stream { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for OdbWriter<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_odb_stream_free(self.raw) } +++ } +++} +++ +++impl<'repo> io::Write for OdbWriter<'repo> { +++ fn write(&mut self, buf: &[u8]) -> io::Result { +++ unsafe { +++ let ptr = buf.as_ptr() as *const c_char; +++ let len = buf.len(); +++ let res = raw::git_odb_stream_write(self.raw, ptr, len); +++ if res < 0 { +++ Err(io::Error::new(io::ErrorKind::Other, "Write error")) +++ } else { +++ Ok(buf.len()) +++ } +++ } +++ } +++ fn flush(&mut self) -> io::Result<()> { +++ Ok(()) +++ } +++} +++ +++pub(crate) struct OdbPackwriterCb<'repo> { +++ pub(crate) cb: Option>>, +++} +++ +++/// A stream to write a packfile to the ODB +++pub struct OdbPackwriter<'repo> { +++ raw: *mut raw::git_odb_writepack, +++ progress: raw::git_indexer_progress, +++ progress_payload_ptr: *mut OdbPackwriterCb<'repo>, +++} +++ +++impl<'repo> OdbPackwriter<'repo> { +++ /// Finish writing the packfile +++ pub fn commit(&mut self) -> Result { +++ unsafe { +++ let writepack = &*self.raw; +++ let res = match writepack.commit { +++ Some(commit) => commit(self.raw, &mut self.progress), +++ None => -1, +++ }; +++ +++ if res < 0 { +++ Err(Error::last_error(res)) +++ } else { +++ Ok(res) +++ } +++ } +++ } +++ +++ /// The callback through which progress is monitored. Be aware that this is +++ /// called inline, so performance may be affected. +++ pub fn progress(&mut self, cb: F) -> &mut OdbPackwriter<'repo> +++ where +++ F: FnMut(Progress<'_>) -> bool + 'repo, +++ { +++ let progress_payload = +++ unsafe { &mut *(self.progress_payload_ptr as *mut OdbPackwriterCb<'_>) }; +++ +++ progress_payload.cb = Some(Box::new(cb) as Box>); +++ self +++ } +++} +++ +++impl<'repo> io::Write for OdbPackwriter<'repo> { +++ fn write(&mut self, buf: &[u8]) -> io::Result { +++ unsafe { +++ let ptr = buf.as_ptr() as *mut c_void; +++ let len = buf.len(); +++ +++ let writepack = &*self.raw; +++ let res = match writepack.append { +++ Some(append) => append(self.raw, ptr, len, &mut self.progress), +++ None => -1, +++ }; +++ +++ if res < 0 { +++ Err(io::Error::new(io::ErrorKind::Other, "Write error")) +++ } else { +++ Ok(buf.len()) +++ } +++ } +++ } +++ fn flush(&mut self) -> io::Result<()> { +++ Ok(()) +++ } +++} +++ +++impl<'repo> Drop for OdbPackwriter<'repo> { +++ fn drop(&mut self) { +++ unsafe { +++ let writepack = &*self.raw; +++ match writepack.free { +++ Some(free) => free(self.raw), +++ None => (), +++ }; +++ +++ drop(Box::from_raw(self.progress_payload_ptr)); +++ } +++ } +++} +++ +++pub type ForeachCb<'a> = dyn FnMut(&Oid) -> bool + 'a; +++ +++struct ForeachCbData<'a> { +++ pub callback: &'a mut ForeachCb<'a>, +++} +++ +++extern "C" fn foreach_cb(id: *const raw::git_oid, payload: *mut c_void) -> c_int { +++ panic::wrap(|| unsafe { +++ let data = &mut *(payload as *mut ForeachCbData<'_>); +++ let res = { +++ let callback = &mut data.callback; +++ callback(&Binding::from_raw(id)) +++ }; +++ +++ if res { +++ 0 +++ } else { +++ 1 +++ } +++ }) +++ .unwrap_or(1) +++} +++ +++pub(crate) extern "C" fn write_pack_progress_cb( +++ stats: *const raw::git_indexer_progress, +++ payload: *mut c_void, +++) -> c_int { +++ let ok = panic::wrap(|| unsafe { +++ let payload = &mut *(payload as *mut OdbPackwriterCb<'_>); +++ +++ let callback = match payload.cb { +++ Some(ref mut cb) => cb, +++ None => return true, +++ }; +++ +++ let progress: Progress<'_> = Binding::from_raw(stats); +++ callback(progress) +++ }); +++ if ok == Some(true) { +++ 0 +++ } else { +++ -1 +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::{Buf, ObjectType, Oid, Repository}; +++ use std::io::prelude::*; +++ use tempfile::TempDir; +++ +++ #[test] +++ fn read() { +++ let td = TempDir::new().unwrap(); +++ let repo = Repository::init(td.path()).unwrap(); +++ let dat = [4, 3, 5, 6, 9]; +++ let id = repo.blob(&dat).unwrap(); +++ let db = repo.odb().unwrap(); +++ let obj = db.read(id).unwrap(); +++ let data = obj.data(); +++ let size = obj.len(); +++ assert_eq!(size, 5); +++ assert_eq!(dat, data); +++ assert_eq!(id, obj.id()); +++ } +++ +++ #[test] +++ fn read_header() { +++ let td = TempDir::new().unwrap(); +++ let repo = Repository::init(td.path()).unwrap(); +++ let dat = [4, 3, 5, 6, 9]; +++ let id = repo.blob(&dat).unwrap(); +++ let db = repo.odb().unwrap(); +++ let (size, kind) = db.read_header(id).unwrap(); +++ +++ assert_eq!(size, 5); +++ assert_eq!(kind, ObjectType::Blob); +++ } +++ +++ #[test] +++ fn write() { +++ let td = TempDir::new().unwrap(); +++ let repo = Repository::init(td.path()).unwrap(); +++ let dat = [4, 3, 5, 6, 9]; +++ let db = repo.odb().unwrap(); +++ let id = db.write(ObjectType::Blob, &dat).unwrap(); +++ let blob = repo.find_blob(id).unwrap(); +++ assert_eq!(blob.content(), dat); +++ } +++ +++ #[test] +++ fn writer() { +++ let td = TempDir::new().unwrap(); +++ let repo = Repository::init(td.path()).unwrap(); +++ let dat = [4, 3, 5, 6, 9]; +++ let db = repo.odb().unwrap(); +++ let mut ws = db.writer(dat.len(), ObjectType::Blob).unwrap(); +++ let wl = ws.write(&dat[0..3]).unwrap(); +++ assert_eq!(wl, 3); +++ let wl = ws.write(&dat[3..5]).unwrap(); +++ assert_eq!(wl, 2); +++ let id = ws.finalize().unwrap(); +++ let blob = repo.find_blob(id).unwrap(); +++ assert_eq!(blob.content(), dat); +++ } +++ +++ #[test] +++ fn exists() { +++ let td = TempDir::new().unwrap(); +++ let repo = Repository::init(td.path()).unwrap(); +++ let dat = [4, 3, 5, 6, 9]; +++ let db = repo.odb().unwrap(); +++ let id = db.write(ObjectType::Blob, &dat).unwrap(); +++ assert!(db.exists(id)); +++ } +++ +++ #[test] +++ fn exists_prefix() { +++ let td = TempDir::new().unwrap(); +++ let repo = Repository::init(td.path()).unwrap(); +++ let dat = [4, 3, 5, 6, 9]; +++ let db = repo.odb().unwrap(); +++ let id = db.write(ObjectType::Blob, &dat).unwrap(); +++ let id_prefix_str = &id.to_string()[0..10]; +++ let id_prefix = Oid::from_str(id_prefix_str).unwrap(); +++ let found_oid = db.exists_prefix(id_prefix, 10).unwrap(); +++ assert_eq!(found_oid, id); +++ } +++ +++ #[test] +++ fn packwriter() { +++ let (_td, repo_source) = crate::test::repo_init(); +++ let (_td, repo_target) = crate::test::repo_init(); +++ let mut builder = t!(repo_source.packbuilder()); +++ let mut buf = Buf::new(); +++ let (commit_source_id, _tree) = crate::test::commit(&repo_source); +++ t!(builder.insert_object(commit_source_id, None)); +++ t!(builder.write_buf(&mut buf)); +++ let db = repo_target.odb().unwrap(); +++ let mut packwriter = db.packwriter().unwrap(); +++ packwriter.write(&buf).unwrap(); +++ packwriter.commit().unwrap(); +++ let commit_target = repo_target.find_commit(commit_source_id).unwrap(); +++ assert_eq!(commit_target.id(), commit_source_id); +++ } +++ +++ #[test] +++ fn packwriter_progress() { +++ let mut progress_called = false; +++ { +++ let (_td, repo_source) = crate::test::repo_init(); +++ let (_td, repo_target) = crate::test::repo_init(); +++ let mut builder = t!(repo_source.packbuilder()); +++ let mut buf = Buf::new(); +++ let (commit_source_id, _tree) = crate::test::commit(&repo_source); +++ t!(builder.insert_object(commit_source_id, None)); +++ t!(builder.write_buf(&mut buf)); +++ let db = repo_target.odb().unwrap(); +++ let mut packwriter = db.packwriter().unwrap(); +++ packwriter.progress(|_| { +++ progress_called = true; +++ true +++ }); +++ packwriter.write(&buf).unwrap(); +++ packwriter.commit().unwrap(); +++ } +++ assert_eq!(progress_called, true); +++ } +++ +++ #[test] +++ fn write_with_mempack() { +++ use crate::{Buf, ResetType}; +++ use std::io::Write; +++ use std::path::Path; +++ +++ // Create a repo, add a mempack backend +++ let (_td, repo) = crate::test::repo_init(); +++ let odb = repo.odb().unwrap(); +++ let mempack = odb.add_new_mempack_backend(1000).unwrap(); +++ +++ // Sanity check that foo doesn't exist initially +++ let foo_file = Path::new(repo.workdir().unwrap()).join("foo"); +++ assert!(!foo_file.exists()); +++ +++ // Make a commit that adds foo. This writes new stuff into the mempack +++ // backend. +++ let (oid1, _id) = crate::test::commit(&repo); +++ let commit1 = repo.find_commit(oid1).unwrap(); +++ t!(repo.reset(commit1.as_object(), ResetType::Hard, None)); +++ assert!(foo_file.exists()); +++ +++ // Dump the mempack modifications into a buf, and reset it. This "erases" +++ // commit-related objects from the repository. Ensure the commit appears +++ // to have become invalid, by checking for failure in `reset --hard`. +++ let mut buf = Buf::new(); +++ mempack.dump(&repo, &mut buf).unwrap(); +++ mempack.reset().unwrap(); +++ assert!(repo +++ .reset(commit1.as_object(), ResetType::Hard, None) +++ .is_err()); +++ +++ // Write the buf into a packfile in the repo. This brings back the +++ // missing objects, and we verify everything is good again. +++ let mut packwriter = odb.packwriter().unwrap(); +++ packwriter.write(&buf).unwrap(); +++ packwriter.commit().unwrap(); +++ t!(repo.reset(commit1.as_object(), ResetType::Hard, None)); +++ assert!(foo_file.exists()); +++ } +++ +++ #[test] +++ fn stream_read() { +++ // Test for read impl of OdbReader. +++ const FOO_TEXT: &[u8] = b"this is a test"; +++ let (_td, repo) = crate::test::repo_init(); +++ let p = repo.path().parent().unwrap().join("foo"); +++ std::fs::write(&p, FOO_TEXT).unwrap(); +++ let mut index = repo.index().unwrap(); +++ index.add_path(std::path::Path::new("foo")).unwrap(); +++ let tree_id = index.write_tree().unwrap(); +++ let tree = repo.find_tree(tree_id).unwrap(); +++ let sig = repo.signature().unwrap(); +++ let head_id = repo.refname_to_id("HEAD").unwrap(); +++ let parent = repo.find_commit(head_id).unwrap(); +++ let _commit = repo +++ .commit(Some("HEAD"), &sig, &sig, "commit", &tree, &[&parent]) +++ .unwrap(); +++ +++ // Try reading from a commit object. +++ let odb = repo.odb().unwrap(); +++ let oid = repo.refname_to_id("HEAD").unwrap(); +++ let (mut reader, size, ty) = odb.reader(oid).unwrap(); +++ assert!(ty == ObjectType::Commit); +++ let mut x = [0; 10000]; +++ let r = reader.read(&mut x).unwrap(); +++ assert!(r == size); +++ +++ // Try reading from a blob. This assumes it is a loose object (packed +++ // objects can't read). +++ let commit = repo.find_commit(oid).unwrap(); +++ let tree = commit.tree().unwrap(); +++ let entry = tree.get_name("foo").unwrap(); +++ let (mut reader, size, ty) = odb.reader(entry.id()).unwrap(); +++ assert_eq!(size, FOO_TEXT.len()); +++ assert!(ty == ObjectType::Blob); +++ let mut x = [0; 10000]; +++ let r = reader.read(&mut x).unwrap(); +++ assert_eq!(r, 14); +++ assert_eq!(&x[..FOO_TEXT.len()], FOO_TEXT); +++ } +++} diff --cc extra/git2/src/oid.rs index 0000000000,0000000000,0000000000..35516cb181 new file mode 100644 --- /dev/null +++ b/extra/git2/src/oid.rs @@@@ -1,0 -1,0 -1,0 +1,258 @@@@ +++use std::cmp::Ordering; +++use std::fmt; +++use std::hash::{Hash, Hasher}; +++use std::path::Path; +++use std::str; +++ +++use crate::{raw, Error, IntoCString, ObjectType}; +++ +++use crate::util::{c_cmp_to_ordering, Binding}; +++ +++/// Unique identity of any object (commit, tree, blob, tag). +++#[derive(Copy, Clone)] +++#[repr(C)] +++pub struct Oid { +++ raw: raw::git_oid, +++} +++ +++impl Oid { +++ /// Parse a hex-formatted object id into an Oid structure. +++ /// +++ /// # Errors +++ /// +++ /// Returns an error if the string is empty, is longer than 40 hex +++ /// characters, or contains any non-hex characters. +++ pub fn from_str(s: &str) -> Result { +++ crate::init(); +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_oid_fromstrn( +++ &mut raw, +++ s.as_bytes().as_ptr() as *const libc::c_char, +++ s.len() as libc::size_t +++ )); +++ } +++ Ok(Oid { raw }) +++ } +++ +++ /// Parse a raw object id into an Oid structure. +++ /// +++ /// If the array given is not 20 bytes in length, an error is returned. +++ pub fn from_bytes(bytes: &[u8]) -> Result { +++ crate::init(); +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ if bytes.len() != raw::GIT_OID_RAWSZ { +++ Err(Error::from_str("raw byte array must be 20 bytes")) +++ } else { +++ unsafe { +++ try_call!(raw::git_oid_fromraw(&mut raw, bytes.as_ptr())); +++ } +++ Ok(Oid { raw }) +++ } +++ } +++ +++ /// Creates an all zero Oid structure. +++ pub fn zero() -> Oid { +++ let out = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ Oid { raw: out } +++ } +++ +++ /// Hashes the provided data as an object of the provided type, and returns +++ /// an Oid corresponding to the result. This does not store the object +++ /// inside any object database or repository. +++ pub fn hash_object(kind: ObjectType, bytes: &[u8]) -> Result { +++ crate::init(); +++ +++ let mut out = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_odb_hash( +++ &mut out, +++ bytes.as_ptr() as *const libc::c_void, +++ bytes.len(), +++ kind.raw() +++ )); +++ } +++ +++ Ok(Oid { raw: out }) +++ } +++ +++ /// Hashes the content of the provided file as an object of the provided type, +++ /// and returns an Oid corresponding to the result. This does not store the object +++ /// inside any object database or repository. +++ pub fn hash_file>(kind: ObjectType, path: P) -> Result { +++ crate::init(); +++ +++ // Normal file path OK (does not need Windows conversion). +++ let rpath = path.as_ref().into_c_string()?; +++ +++ let mut out = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_odb_hashfile(&mut out, rpath, kind.raw())); +++ } +++ +++ Ok(Oid { raw: out }) +++ } +++ +++ /// View this OID as a byte-slice 20 bytes in length. +++ pub fn as_bytes(&self) -> &[u8] { +++ &self.raw.id +++ } +++ +++ /// Test if this OID is all zeros. +++ pub fn is_zero(&self) -> bool { +++ unsafe { raw::git_oid_iszero(&self.raw) == 1 } +++ } +++} +++ +++impl Binding for Oid { +++ type Raw = *const raw::git_oid; +++ +++ unsafe fn from_raw(oid: *const raw::git_oid) -> Oid { +++ Oid { raw: *oid } +++ } +++ fn raw(&self) -> *const raw::git_oid { +++ &self.raw as *const _ +++ } +++} +++ +++impl fmt::Debug for Oid { +++ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +++ fmt::Display::fmt(self, f) +++ } +++} +++ +++impl fmt::Display for Oid { +++ /// Hex-encode this Oid into a formatter. +++ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +++ let mut dst = [0u8; raw::GIT_OID_HEXSZ + 1]; +++ unsafe { +++ raw::git_oid_tostr( +++ dst.as_mut_ptr() as *mut libc::c_char, +++ dst.len() as libc::size_t, +++ &self.raw, +++ ); +++ } +++ let s = &dst[..dst.iter().position(|&a| a == 0).unwrap()]; +++ str::from_utf8(s).unwrap().fmt(f) +++ } +++} +++ +++impl str::FromStr for Oid { +++ type Err = Error; +++ +++ /// Parse a hex-formatted object id into an Oid structure. +++ /// +++ /// # Errors +++ /// +++ /// Returns an error if the string is empty, is longer than 40 hex +++ /// characters, or contains any non-hex characters. +++ fn from_str(s: &str) -> Result { +++ Oid::from_str(s) +++ } +++} +++ +++impl PartialEq for Oid { +++ fn eq(&self, other: &Oid) -> bool { +++ unsafe { raw::git_oid_equal(&self.raw, &other.raw) != 0 } +++ } +++} +++impl Eq for Oid {} +++ +++impl PartialOrd for Oid { +++ fn partial_cmp(&self, other: &Oid) -> Option { +++ Some(self.cmp(other)) +++ } +++} +++ +++impl Ord for Oid { +++ fn cmp(&self, other: &Oid) -> Ordering { +++ c_cmp_to_ordering(unsafe { raw::git_oid_cmp(&self.raw, &other.raw) }) +++ } +++} +++ +++impl Hash for Oid { +++ fn hash(&self, into: &mut H) { +++ self.raw.id.hash(into) +++ } +++} +++ +++impl AsRef<[u8]> for Oid { +++ fn as_ref(&self) -> &[u8] { +++ self.as_bytes() +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use std::fs::File; +++ use std::io::prelude::*; +++ +++ use super::Error; +++ use super::Oid; +++ use crate::ObjectType; +++ use tempfile::TempDir; +++ +++ #[test] +++ fn conversions() { +++ assert!(Oid::from_str("foo").is_err()); +++ assert!(Oid::from_str("decbf2be529ab6557d5429922251e5ee36519817").is_ok()); +++ assert!(Oid::from_bytes(b"foo").is_err()); +++ assert!(Oid::from_bytes(b"00000000000000000000").is_ok()); +++ } +++ +++ #[test] +++ fn comparisons() -> Result<(), Error> { +++ assert_eq!(Oid::from_str("decbf2b")?, Oid::from_str("decbf2b")?); +++ assert!(Oid::from_str("decbf2b")? <= Oid::from_str("decbf2b")?); +++ assert!(Oid::from_str("decbf2b")? >= Oid::from_str("decbf2b")?); +++ { +++ let o = Oid::from_str("decbf2b")?; +++ assert_eq!(o, o); +++ assert!(o <= o); +++ assert!(o >= o); +++ } +++ assert_eq!( +++ Oid::from_str("decbf2b")?, +++ Oid::from_str("decbf2b000000000000000000000000000000000")? +++ ); +++ assert!( +++ Oid::from_bytes(b"00000000000000000000")? < Oid::from_bytes(b"00000000000000000001")? +++ ); +++ assert!(Oid::from_bytes(b"00000000000000000000")? < Oid::from_str("decbf2b")?); +++ assert_eq!( +++ Oid::from_bytes(b"00000000000000000000")?, +++ Oid::from_str("3030303030303030303030303030303030303030")? +++ ); +++ Ok(()) +++ } +++ +++ #[test] +++ fn zero_is_zero() { +++ assert!(Oid::zero().is_zero()); +++ } +++ +++ #[test] +++ fn hash_object() { +++ let bytes = "Hello".as_bytes(); +++ assert!(Oid::hash_object(ObjectType::Blob, bytes).is_ok()); +++ } +++ +++ #[test] +++ fn hash_file() { +++ let td = TempDir::new().unwrap(); +++ let path = td.path().join("hello.txt"); +++ let mut file = File::create(&path).unwrap(); +++ file.write_all("Hello".as_bytes()).unwrap(); +++ assert!(Oid::hash_file(ObjectType::Blob, &path).is_ok()); +++ } +++} diff --cc extra/git2/src/oid_array.rs index 0000000000,0000000000,0000000000..0d87ce9954 new file mode 100644 --- /dev/null +++ b/extra/git2/src/oid_array.rs @@@@ -1,0 -1,0 -1,0 +1,52 @@@@ +++//! Bindings to libgit2's raw `git_oidarray` type +++ +++use std::ops::Deref; +++ +++use crate::oid::Oid; +++use crate::raw; +++use crate::util::Binding; +++use std::mem; +++use std::slice; +++ +++/// An oid array structure used by libgit2 +++/// +++/// Some APIs return arrays of OIDs which originate from libgit2. This +++/// wrapper type behaves a little like `Vec<&Oid>` but does so without copying +++/// the underlying Oids until necessary. +++pub struct OidArray { +++ raw: raw::git_oidarray, +++} +++ +++impl Deref for OidArray { +++ type Target = [Oid]; +++ +++ fn deref(&self) -> &[Oid] { +++ unsafe { +++ debug_assert_eq!(mem::size_of::(), mem::size_of_val(&*self.raw.ids)); +++ +++ slice::from_raw_parts(self.raw.ids as *const Oid, self.raw.count as usize) +++ } +++ } +++} +++ +++impl Binding for OidArray { +++ type Raw = raw::git_oidarray; +++ unsafe fn from_raw(raw: raw::git_oidarray) -> OidArray { +++ OidArray { raw } +++ } +++ fn raw(&self) -> raw::git_oidarray { +++ self.raw +++ } +++} +++ +++impl<'repo> std::fmt::Debug for OidArray { +++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +++ f.debug_tuple("OidArray").field(&self.deref()).finish() +++ } +++} +++ +++impl Drop for OidArray { +++ fn drop(&mut self) { +++ unsafe { raw::git_oidarray_free(&mut self.raw) } +++ } +++} diff --cc extra/git2/src/opts.rs index 0000000000,0000000000,0000000000..ab63661023 new file mode 100644 --- /dev/null +++ b/extra/git2/src/opts.rs @@@@ -1,0 -1,0 -1,0 +1,465 @@@@ +++//! Bindings to libgit2's git_libgit2_opts function. +++ +++use std::ffi::CString; +++use std::ptr; +++ +++use crate::string_array::StringArray; +++use crate::util::Binding; +++use crate::{raw, Buf, ConfigLevel, Error, IntoCString}; +++ +++/// Set the search path for a level of config data. The search path applied to +++/// shared attributes and ignore files, too. +++/// +++/// `level` must be one of [`ConfigLevel::System`], [`ConfigLevel::Global`], +++/// [`ConfigLevel::XDG`], [`ConfigLevel::ProgramData`]. +++/// +++/// `path` lists directories delimited by `GIT_PATH_LIST_SEPARATOR`. +++/// Use magic path `$PATH` to include the old value of the path +++/// (if you want to prepend or append, for instance). +++/// +++/// This function is unsafe as it mutates the global state but cannot guarantee +++/// thread-safety. It needs to be externally synchronized with calls to access +++/// the global state. +++pub unsafe fn set_search_path

(level: ConfigLevel, path: P) -> Result<(), Error> +++where +++ P: IntoCString, +++{ +++ crate::init(); +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_SET_SEARCH_PATH as libc::c_int, +++ level as libc::c_int, +++ path.into_c_string()?.as_ptr() +++ )); +++ Ok(()) +++} +++ +++/// Reset the search path for a given level of config data to the default +++/// (generally based on environment variables). +++/// +++/// `level` must be one of [`ConfigLevel::System`], [`ConfigLevel::Global`], +++/// [`ConfigLevel::XDG`], [`ConfigLevel::ProgramData`]. +++/// +++/// This function is unsafe as it mutates the global state but cannot guarantee +++/// thread-safety. It needs to be externally synchronized with calls to access +++/// the global state. +++pub unsafe fn reset_search_path(level: ConfigLevel) -> Result<(), Error> { +++ crate::init(); +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_SET_SEARCH_PATH as libc::c_int, +++ level as libc::c_int, +++ core::ptr::null::() +++ )); +++ Ok(()) +++} +++ +++/// Get the search path for a given level of config data. +++/// +++/// `level` must be one of [`ConfigLevel::System`], [`ConfigLevel::Global`], +++/// [`ConfigLevel::XDG`], [`ConfigLevel::ProgramData`]. +++/// +++/// This function is unsafe as it mutates the global state but cannot guarantee +++/// thread-safety. It needs to be externally synchronized with calls to access +++/// the global state. +++pub unsafe fn get_search_path(level: ConfigLevel) -> Result { +++ crate::init(); +++ let buf = Buf::new(); +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_GET_SEARCH_PATH as libc::c_int, +++ level as libc::c_int, +++ buf.raw() as *const _ +++ )); +++ buf.into_c_string() +++} +++ +++/// Controls whether or not libgit2 will cache loaded objects. Enabled by +++/// default, but disabling this can improve performance and memory usage if +++/// loading a large number of objects that will not be referenced again. +++/// Disabling this will cause repository objects to clear their caches when next +++/// accessed. +++pub fn enable_caching(enabled: bool) { +++ crate::init(); +++ let error = unsafe { +++ raw::git_libgit2_opts( +++ raw::GIT_OPT_ENABLE_CACHING as libc::c_int, +++ enabled as libc::c_int, +++ ) +++ }; +++ // This function cannot actually fail, but the function has an error return +++ // for other options that can. +++ debug_assert!(error >= 0); +++} +++ +++/// Controls whether or not libgit2 will verify when writing an object that all +++/// objects it references are valid. Enabled by default, but disabling this can +++/// significantly improve performance, at the cost of potentially allowing the +++/// creation of objects that reference invalid objects (due to programming +++/// error or repository corruption). +++pub fn strict_object_creation(enabled: bool) { +++ crate::init(); +++ let error = unsafe { +++ raw::git_libgit2_opts( +++ raw::GIT_OPT_ENABLE_STRICT_OBJECT_CREATION as libc::c_int, +++ enabled as libc::c_int, +++ ) +++ }; +++ // This function cannot actually fail, but the function has an error return +++ // for other options that can. +++ debug_assert!(error >= 0); +++} +++ +++/// Controls whether or not libgit2 will verify that objects loaded have the +++/// expected hash. Enabled by default, but disabling this can significantly +++/// improve performance, at the cost of relying on repository integrity +++/// without checking it. +++pub fn strict_hash_verification(enabled: bool) { +++ crate::init(); +++ let error = unsafe { +++ raw::git_libgit2_opts( +++ raw::GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION as libc::c_int, +++ enabled as libc::c_int, +++ ) +++ }; +++ // This function cannot actually fail, but the function has an error return +++ // for other options that can. +++ debug_assert!(error >= 0); +++} +++ +++/// Returns the list of git extensions that are supported. This is the list of +++/// built-in extensions supported by libgit2 and custom extensions that have +++/// been added with [`set_extensions`]. Extensions that have been negated will +++/// not be returned. +++/// +++/// # Safety +++/// +++/// libgit2 stores user extensions in a static variable. +++/// This function is effectively reading a `static mut` and should be treated as such +++pub unsafe fn get_extensions() -> Result { +++ crate::init(); +++ +++ let mut extensions = raw::git_strarray { +++ strings: ptr::null_mut(), +++ count: 0, +++ }; +++ +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_GET_EXTENSIONS as libc::c_int, +++ &mut extensions +++ )); +++ +++ Ok(StringArray::from_raw(extensions)) +++} +++ +++/// Set that the given git extensions are supported by the caller. Extensions +++/// supported by libgit2 may be negated by prefixing them with a `!`. +++/// For example: setting extensions to `[ "!noop", "newext" ]` indicates that +++/// the caller does not want to support repositories with the `noop` extension +++/// but does want to support repositories with the `newext` extension. +++/// +++/// # Safety +++/// +++/// libgit2 stores user extensions in a static variable. +++/// This function is effectively modifying a `static mut` and should be treated as such +++pub unsafe fn set_extensions(extensions: &[E]) -> Result<(), Error> +++where +++ for<'x> &'x E: IntoCString, +++{ +++ crate::init(); +++ +++ let extensions = extensions +++ .iter() +++ .map(|e| e.into_c_string()) +++ .collect::, _>>()?; +++ +++ let extension_ptrs = extensions.iter().map(|e| e.as_ptr()).collect::>(); +++ +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_SET_EXTENSIONS as libc::c_int, +++ extension_ptrs.as_ptr(), +++ extension_ptrs.len() as libc::size_t +++ )); +++ +++ Ok(()) +++} +++ +++/// Set whether or not to verify ownership before performing a repository. +++/// Enabled by default, but disabling this can lead to code execution vulnerabilities. +++pub unsafe fn set_verify_owner_validation(enabled: bool) -> Result<(), Error> { +++ crate::init(); +++ let error = raw::git_libgit2_opts( +++ raw::GIT_OPT_SET_OWNER_VALIDATION as libc::c_int, +++ enabled as libc::c_int, +++ ); +++ // This function cannot actually fail, but the function has an error return +++ // for other options that can. +++ debug_assert!(error >= 0); +++ Ok(()) +++} +++ +++/// Set the SSL certificate-authority location to `file`. `file` is the location +++/// of a file containing several certificates concatenated together. +++pub unsafe fn set_ssl_cert_file

(file: P) -> Result<(), Error> +++where +++ P: IntoCString, +++{ +++ crate::init(); +++ +++ unsafe { +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_SET_SSL_CERT_LOCATIONS as libc::c_int, +++ file.into_c_string()?.as_ptr(), +++ core::ptr::null::() +++ )); +++ } +++ +++ Ok(()) +++} +++ +++/// Set the SSL certificate-authority location to `path`. `path` is the location +++/// of a directory holding several certificates, one per file. +++pub unsafe fn set_ssl_cert_dir

(path: P) -> Result<(), Error> +++where +++ P: IntoCString, +++{ +++ crate::init(); +++ +++ unsafe { +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_SET_SSL_CERT_LOCATIONS as libc::c_int, +++ core::ptr::null::(), +++ path.into_c_string()?.as_ptr() +++ )); +++ } +++ +++ Ok(()) +++} +++ +++/// Get the maximum mmap window size +++/// +++/// # Safety +++/// This function is reading a C global without synchronization, so it is not +++/// thread safe, and should only be called before any thread is spawned. +++pub unsafe fn get_mwindow_size() -> Result { +++ crate::init(); +++ +++ let mut size = 0; +++ +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_GET_MWINDOW_SIZE as libc::c_int, +++ &mut size +++ )); +++ +++ Ok(size) +++} +++ +++/// Set the maximum mmap window size +++/// +++/// # Safety +++/// This function is modifying a C global without synchronization, so it is not +++/// thread safe, and should only be called before any thread is spawned. +++pub unsafe fn set_mwindow_size(size: libc::size_t) -> Result<(), Error> { +++ crate::init(); +++ +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_SET_MWINDOW_SIZE as libc::c_int, +++ size +++ )); +++ +++ Ok(()) +++} +++ +++/// Get the maximum memory that will be mapped in total by the library +++/// +++/// # Safety +++/// This function is reading a C global without synchronization, so it is not +++/// thread safe, and should only be called before any thread is spawned. +++pub unsafe fn get_mwindow_mapped_limit() -> Result { +++ crate::init(); +++ +++ let mut limit = 0; +++ +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_GET_MWINDOW_MAPPED_LIMIT as libc::c_int, +++ &mut limit +++ )); +++ +++ Ok(limit) +++} +++ +++/// Set the maximum amount of memory that can be mapped at any time +++/// by the library. +++/// +++/// # Safety +++/// This function is modifying a C global without synchronization, so it is not +++/// thread safe, and should only be called before any thread is spawned. +++pub unsafe fn set_mwindow_mapped_limit(limit: libc::size_t) -> Result<(), Error> { +++ crate::init(); +++ +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_SET_MWINDOW_MAPPED_LIMIT as libc::c_int, +++ limit +++ )); +++ +++ Ok(()) +++} +++ +++/// Get the maximum number of files that will be mapped at any time by the +++/// library. +++/// +++/// # Safety +++/// This function is reading a C global without synchronization, so it is not +++/// thread safe, and should only be called before any thread is spawned. +++pub unsafe fn get_mwindow_file_limit() -> Result { +++ crate::init(); +++ +++ let mut limit = 0; +++ +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_GET_MWINDOW_FILE_LIMIT as libc::c_int, +++ &mut limit +++ )); +++ +++ Ok(limit) +++} +++ +++/// Set the maximum number of files that can be mapped at any time +++/// by the library. The default (0) is unlimited. +++/// +++/// # Safety +++/// This function is modifying a C global without synchronization, so it is not +++/// thread safe, and should only be called before any thread is spawned. +++pub unsafe fn set_mwindow_file_limit(limit: libc::size_t) -> Result<(), Error> { +++ crate::init(); +++ +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_SET_MWINDOW_FILE_LIMIT as libc::c_int, +++ limit +++ )); +++ +++ Ok(()) +++} +++ +++/// Get server connect timeout in milliseconds +++/// +++/// # Safety +++/// This function is modifying a C global without synchronization, so it is not +++/// thread safe, and should only be called before any thread is spawned. +++pub unsafe fn get_server_connect_timeout_in_milliseconds() -> Result { +++ crate::init(); +++ +++ let mut server_connect_timeout = 0; +++ +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_GET_SERVER_CONNECT_TIMEOUT as libc::c_int, +++ &mut server_connect_timeout +++ )); +++ +++ Ok(server_connect_timeout) +++} +++ +++/// Set server connect timeout in milliseconds +++/// +++/// # Safety +++/// This function is modifying a C global without synchronization, so it is not +++/// thread safe, and should only be called before any thread is spawned. +++pub unsafe fn set_server_connect_timeout_in_milliseconds( +++ timeout: libc::c_int, +++) -> Result<(), Error> { +++ crate::init(); +++ +++ let error = raw::git_libgit2_opts( +++ raw::GIT_OPT_SET_SERVER_CONNECT_TIMEOUT as libc::c_int, +++ timeout, +++ ); +++ // This function cannot actually fail, but the function has an error return +++ // for other options that can. +++ debug_assert!(error >= 0); +++ +++ Ok(()) +++} +++ +++/// Get server timeout in milliseconds +++/// +++/// # Safety +++/// This function is modifying a C global without synchronization, so it is not +++/// thread safe, and should only be called before any thread is spawned. +++pub unsafe fn get_server_timeout_in_milliseconds() -> Result { +++ crate::init(); +++ +++ let mut server_timeout = 0; +++ +++ try_call!(raw::git_libgit2_opts( +++ raw::GIT_OPT_GET_SERVER_TIMEOUT as libc::c_int, +++ &mut server_timeout +++ )); +++ +++ Ok(server_timeout) +++} +++ +++/// Set server timeout in milliseconds +++/// +++/// # Safety +++/// This function is modifying a C global without synchronization, so it is not +++/// thread safe, and should only be called before any thread is spawned. +++pub unsafe fn set_server_timeout_in_milliseconds(timeout: libc::c_int) -> Result<(), Error> { +++ crate::init(); +++ +++ let error = raw::git_libgit2_opts( +++ raw::GIT_OPT_SET_SERVER_TIMEOUT as libc::c_int, +++ timeout as libc::c_int, +++ ); +++ // This function cannot actually fail, but the function has an error return +++ // for other options that can. +++ debug_assert!(error >= 0); +++ +++ Ok(()) +++} +++ +++#[cfg(test)] +++mod test { +++ use super::*; +++ +++ #[test] +++ fn smoke() { +++ strict_hash_verification(false); +++ } +++ +++ #[test] +++ fn mwindow_size() { +++ unsafe { +++ assert!(set_mwindow_size(1024).is_ok()); +++ assert!(get_mwindow_size().unwrap() == 1024); +++ } +++ } +++ +++ #[test] +++ fn mwindow_mapped_limit() { +++ unsafe { +++ assert!(set_mwindow_mapped_limit(1024).is_ok()); +++ assert!(get_mwindow_mapped_limit().unwrap() == 1024); +++ } +++ } +++ +++ #[test] +++ fn mwindow_file_limit() { +++ unsafe { +++ assert!(set_mwindow_file_limit(1024).is_ok()); +++ assert!(get_mwindow_file_limit().unwrap() == 1024); +++ } +++ } +++ +++ #[test] +++ fn server_connect_timeout() { +++ unsafe { +++ assert!(set_server_connect_timeout_in_milliseconds(5000).is_ok()); +++ assert!(get_server_connect_timeout_in_milliseconds().unwrap() == 5000); +++ } +++ } +++ +++ #[test] +++ fn server_timeout() { +++ unsafe { +++ assert!(set_server_timeout_in_milliseconds(10_000).is_ok()); +++ assert!(get_server_timeout_in_milliseconds().unwrap() == 10_000); +++ } +++ } +++} diff --cc extra/git2/src/packbuilder.rs index 0000000000,0000000000,0000000000..de47bbce32 new file mode 100644 --- /dev/null +++ b/extra/git2/src/packbuilder.rs @@@@ -1,0 -1,0 -1,0 +1,503 @@@@ +++use libc::{c_int, c_uint, c_void, size_t}; +++use std::marker; +++use std::path::Path; +++use std::ptr; +++use std::slice; +++use std::str; +++ +++use crate::odb::{write_pack_progress_cb, OdbPackwriterCb}; +++use crate::util::Binding; +++use crate::IntoCString; +++use crate::{panic, raw, Buf, Error, Oid, Repository, Revwalk}; +++ +++#[derive(PartialEq, Eq, Clone, Debug, Copy)] +++/// Stages that are reported by the `PackBuilder` progress callback. +++pub enum PackBuilderStage { +++ /// Adding objects to the pack +++ AddingObjects, +++ /// Deltafication of the pack +++ Deltafication, +++} +++ +++pub type ProgressCb<'a> = dyn FnMut(PackBuilderStage, u32, u32) -> bool + 'a; +++pub type ForEachCb<'a> = dyn FnMut(&[u8]) -> bool + 'a; +++ +++/// A builder for creating a packfile +++pub struct PackBuilder<'repo> { +++ raw: *mut raw::git_packbuilder, +++ _progress: Option>>>, +++ _marker: marker::PhantomData<&'repo Repository>, +++} +++ +++impl<'repo> PackBuilder<'repo> { +++ /// Insert a single object. For an optimal pack it's mandatory to insert +++ /// objects in recency order, commits followed by trees and blobs. +++ pub fn insert_object(&mut self, id: Oid, name: Option<&str>) -> Result<(), Error> { +++ let name = crate::opt_cstr(name)?; +++ unsafe { +++ try_call!(raw::git_packbuilder_insert(self.raw, id.raw(), name)); +++ } +++ Ok(()) +++ } +++ +++ /// Insert a root tree object. This will add the tree as well as all +++ /// referenced trees and blobs. +++ pub fn insert_tree(&mut self, id: Oid) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_packbuilder_insert_tree(self.raw, id.raw())); +++ } +++ Ok(()) +++ } +++ +++ /// Insert a commit object. This will add a commit as well as the completed +++ /// referenced tree. +++ pub fn insert_commit(&mut self, id: Oid) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_packbuilder_insert_commit(self.raw, id.raw())); +++ } +++ Ok(()) +++ } +++ +++ /// Insert objects as given by the walk. Those commits and all objects they +++ /// reference will be inserted into the packbuilder. +++ pub fn insert_walk(&mut self, walk: &mut Revwalk<'_>) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_packbuilder_insert_walk(self.raw, walk.raw())); +++ } +++ Ok(()) +++ } +++ +++ /// Recursively insert an object and its referenced objects. Insert the +++ /// object as well as any object it references. +++ pub fn insert_recursive(&mut self, id: Oid, name: Option<&str>) -> Result<(), Error> { +++ let name = crate::opt_cstr(name)?; +++ unsafe { +++ try_call!(raw::git_packbuilder_insert_recur(self.raw, id.raw(), name)); +++ } +++ Ok(()) +++ } +++ +++ /// Write the contents of the packfile to an in-memory buffer. The contents +++ /// of the buffer will become a valid packfile, even though there will be +++ /// no attached index. +++ pub fn write_buf(&mut self, buf: &mut Buf) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_packbuilder_write_buf(buf.raw(), self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Write the new pack and corresponding index file to path. +++ /// To set a progress callback, use `set_progress_callback` before calling this method. +++ pub fn write(&mut self, path: &Path, mode: u32) -> Result<(), Error> { +++ let path = path.into_c_string()?; +++ let progress_cb: raw::git_indexer_progress_cb = Some(write_pack_progress_cb); +++ let progress_payload = Box::new(OdbPackwriterCb { cb: None }); +++ let progress_payload_ptr = Box::into_raw(progress_payload); +++ +++ unsafe { +++ try_call!(raw::git_packbuilder_write( +++ self.raw, +++ path, +++ mode, +++ progress_cb, +++ progress_payload_ptr as *mut _ +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Create the new pack and pass each object to the callback. +++ pub fn foreach(&mut self, mut cb: F) -> Result<(), Error> +++ where +++ F: FnMut(&[u8]) -> bool, +++ { +++ let mut cb = &mut cb as &mut ForEachCb<'_>; +++ let ptr = &mut cb as *mut _; +++ let foreach: raw::git_packbuilder_foreach_cb = Some(foreach_c); +++ unsafe { +++ try_call!(raw::git_packbuilder_foreach( +++ self.raw, +++ foreach, +++ ptr as *mut _ +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// `progress` will be called with progress information during pack +++ /// building. Be aware that this is called inline with pack building +++ /// operations, so performance may be affected. +++ /// +++ /// There can only be one progress callback attached, this will replace any +++ /// existing one. See `unset_progress_callback` to remove the current +++ /// progress callback without attaching a new one. +++ pub fn set_progress_callback(&mut self, progress: F) -> Result<(), Error> +++ where +++ F: FnMut(PackBuilderStage, u32, u32) -> bool + 'repo, +++ { +++ let mut progress = Box::new(Box::new(progress) as Box>); +++ let ptr = &mut *progress as *mut _; +++ let progress_c: raw::git_packbuilder_progress = Some(progress_c); +++ unsafe { +++ try_call!(raw::git_packbuilder_set_callbacks( +++ self.raw, +++ progress_c, +++ ptr as *mut _ +++ )); +++ } +++ self._progress = Some(progress); +++ Ok(()) +++ } +++ +++ /// Remove the current progress callback. See `set_progress_callback` to +++ /// set the progress callback. +++ pub fn unset_progress_callback(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_packbuilder_set_callbacks( +++ self.raw, +++ None, +++ ptr::null_mut() +++ )); +++ self._progress = None; +++ } +++ Ok(()) +++ } +++ +++ /// Set the number of threads to be used. +++ /// +++ /// Returns the number of threads to be used. +++ pub fn set_threads(&mut self, threads: u32) -> u32 { +++ unsafe { raw::git_packbuilder_set_threads(self.raw, threads) } +++ } +++ +++ /// Get the total number of objects the packbuilder will write out. +++ pub fn object_count(&self) -> usize { +++ unsafe { raw::git_packbuilder_object_count(self.raw) } +++ } +++ +++ /// Get the number of objects the packbuilder has already written out. +++ pub fn written(&self) -> usize { +++ unsafe { raw::git_packbuilder_written(self.raw) } +++ } +++ +++ /// Get the packfile's hash. A packfile's name is derived from the sorted +++ /// hashing of all object names. This is only correct after the packfile +++ /// has been written. +++ #[deprecated = "use `name()` to retrieve the filename"] +++ #[allow(deprecated)] +++ pub fn hash(&self) -> Option { +++ if self.object_count() == 0 { +++ unsafe { Some(Binding::from_raw(raw::git_packbuilder_hash(self.raw))) } +++ } else { +++ None +++ } +++ } +++ +++ /// Get the unique name for the resulting packfile. +++ /// +++ /// The packfile's name is derived from the packfile's content. This is only +++ /// correct after the packfile has been written. +++ /// +++ /// Returns `None` if the packfile has not been written or if the name is +++ /// not valid utf-8. +++ pub fn name(&self) -> Option<&str> { +++ self.name_bytes().and_then(|s| str::from_utf8(s).ok()) +++ } +++ +++ /// Get the unique name for the resulting packfile, in bytes. +++ /// +++ /// The packfile's name is derived from the packfile's content. This is only +++ /// correct after the packfile has been written. +++ pub fn name_bytes(&self) -> Option<&[u8]> { +++ unsafe { crate::opt_bytes(self, raw::git_packbuilder_name(self.raw)) } +++ } +++} +++ +++impl<'repo> Binding for PackBuilder<'repo> { +++ type Raw = *mut raw::git_packbuilder; +++ unsafe fn from_raw(ptr: *mut raw::git_packbuilder) -> PackBuilder<'repo> { +++ PackBuilder { +++ raw: ptr, +++ _progress: None, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_packbuilder { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for PackBuilder<'repo> { +++ fn drop(&mut self) { +++ unsafe { +++ raw::git_packbuilder_set_callbacks(self.raw, None, ptr::null_mut()); +++ raw::git_packbuilder_free(self.raw); +++ } +++ } +++} +++ +++impl Binding for PackBuilderStage { +++ type Raw = raw::git_packbuilder_stage_t; +++ unsafe fn from_raw(raw: raw::git_packbuilder_stage_t) -> PackBuilderStage { +++ match raw { +++ raw::GIT_PACKBUILDER_ADDING_OBJECTS => PackBuilderStage::AddingObjects, +++ raw::GIT_PACKBUILDER_DELTAFICATION => PackBuilderStage::Deltafication, +++ _ => panic!("Unknown git diff binary kind"), +++ } +++ } +++ fn raw(&self) -> raw::git_packbuilder_stage_t { +++ match *self { +++ PackBuilderStage::AddingObjects => raw::GIT_PACKBUILDER_ADDING_OBJECTS, +++ PackBuilderStage::Deltafication => raw::GIT_PACKBUILDER_DELTAFICATION, +++ } +++ } +++} +++ +++extern "C" fn foreach_c(buf: *const c_void, size: size_t, data: *mut c_void) -> c_int { +++ unsafe { +++ let buf = slice::from_raw_parts(buf as *const u8, size as usize); +++ +++ let r = panic::wrap(|| { +++ let data = data as *mut &mut ForEachCb<'_>; +++ (*data)(buf) +++ }); +++ if r == Some(true) { +++ 0 +++ } else { +++ -1 +++ } +++ } +++} +++ +++extern "C" fn progress_c( +++ stage: raw::git_packbuilder_stage_t, +++ current: c_uint, +++ total: c_uint, +++ data: *mut c_void, +++) -> c_int { +++ unsafe { +++ let stage = Binding::from_raw(stage); +++ +++ let r = panic::wrap(|| { +++ let data = data as *mut Box>; +++ (*data)(stage, current, total) +++ }); +++ if r == Some(true) { +++ 0 +++ } else { +++ -1 +++ } +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::{Buf, Oid}; +++ +++ // hash of a packfile constructed without any objects in it +++ const EMPTY_PACKFILE_OID: &str = "029d08823bd8a8eab510ad6ac75c823cfd3ed31e"; +++ +++ fn pack_header(len: u8) -> Vec { +++ [].iter() +++ .chain(b"PACK") // signature +++ .chain(&[0, 0, 0, 2]) // version number +++ .chain(&[0, 0, 0, len]) // number of objects +++ .cloned() +++ .collect::>() +++ } +++ +++ fn empty_pack_header() -> Vec { +++ pack_header(0) +++ .iter() +++ .chain(&[ +++ 0x02, 0x9d, 0x08, 0x82, 0x3b, // ^ +++ 0xd8, 0xa8, 0xea, 0xb5, 0x10, // | SHA-1 of the zero +++ 0xad, 0x6a, 0xc7, 0x5c, 0x82, // | object pack header +++ 0x3c, 0xfd, 0x3e, 0xd3, 0x1e, +++ ]) // v +++ .cloned() +++ .collect::>() +++ } +++ +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ let _builder = t!(repo.packbuilder()); +++ } +++ +++ #[test] +++ fn smoke_write_buf() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut builder = t!(repo.packbuilder()); +++ let mut buf = Buf::new(); +++ t!(builder.write_buf(&mut buf)); +++ #[allow(deprecated)] +++ { +++ assert!(builder.hash().unwrap().is_zero()); +++ } +++ assert!(builder.name().is_none()); +++ assert_eq!(&*buf, &*empty_pack_header()); +++ } +++ +++ #[test] +++ fn smoke_write() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut builder = t!(repo.packbuilder()); +++ t!(builder.write(repo.path(), 0)); +++ #[allow(deprecated)] +++ { +++ assert!(builder.hash().unwrap() == Oid::from_str(EMPTY_PACKFILE_OID).unwrap()); +++ } +++ assert!(builder.name().unwrap() == EMPTY_PACKFILE_OID); +++ } +++ +++ #[test] +++ fn smoke_foreach() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut builder = t!(repo.packbuilder()); +++ let mut buf = Vec::::new(); +++ t!(builder.foreach(|bytes| { +++ buf.extend(bytes); +++ true +++ })); +++ assert_eq!(&*buf, &*empty_pack_header()); +++ } +++ +++ #[test] +++ fn insert_write_buf() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut builder = t!(repo.packbuilder()); +++ let mut buf = Buf::new(); +++ let (commit, _tree) = crate::test::commit(&repo); +++ t!(builder.insert_object(commit, None)); +++ assert_eq!(builder.object_count(), 1); +++ t!(builder.write_buf(&mut buf)); +++ // Just check that the correct number of objects are written +++ assert_eq!(&buf[0..12], &*pack_header(1)); +++ } +++ +++ #[test] +++ fn insert_tree_write_buf() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut builder = t!(repo.packbuilder()); +++ let mut buf = Buf::new(); +++ let (_commit, tree) = crate::test::commit(&repo); +++ // will insert the tree itself and the blob, 2 objects +++ t!(builder.insert_tree(tree)); +++ assert_eq!(builder.object_count(), 2); +++ t!(builder.write_buf(&mut buf)); +++ // Just check that the correct number of objects are written +++ assert_eq!(&buf[0..12], &*pack_header(2)); +++ } +++ +++ #[test] +++ fn insert_commit_write_buf() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut builder = t!(repo.packbuilder()); +++ let mut buf = Buf::new(); +++ let (commit, _tree) = crate::test::commit(&repo); +++ // will insert the commit, its tree and the blob, 3 objects +++ t!(builder.insert_commit(commit)); +++ assert_eq!(builder.object_count(), 3); +++ t!(builder.write_buf(&mut buf)); +++ // Just check that the correct number of objects are written +++ assert_eq!(&buf[0..12], &*pack_header(3)); +++ } +++ +++ #[test] +++ fn insert_write() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut builder = t!(repo.packbuilder()); +++ let (commit, _tree) = crate::test::commit(&repo); +++ t!(builder.insert_object(commit, None)); +++ assert_eq!(builder.object_count(), 1); +++ t!(builder.write(repo.path(), 0)); +++ t!(repo.find_commit(commit)); +++ } +++ +++ #[test] +++ fn insert_tree_write() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut builder = t!(repo.packbuilder()); +++ let (_commit, tree) = crate::test::commit(&repo); +++ // will insert the tree itself and the blob, 2 objects +++ t!(builder.insert_tree(tree)); +++ assert_eq!(builder.object_count(), 2); +++ t!(builder.write(repo.path(), 0)); +++ t!(repo.find_tree(tree)); +++ } +++ +++ #[test] +++ fn insert_commit_write() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut builder = t!(repo.packbuilder()); +++ let (commit, _tree) = crate::test::commit(&repo); +++ // will insert the commit, its tree and the blob, 3 objects +++ t!(builder.insert_commit(commit)); +++ assert_eq!(builder.object_count(), 3); +++ t!(builder.write(repo.path(), 0)); +++ t!(repo.find_commit(commit)); +++ } +++ +++ #[test] +++ fn progress_callback() { +++ let mut progress_called = false; +++ { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut builder = t!(repo.packbuilder()); +++ let (commit, _tree) = crate::test::commit(&repo); +++ t!(builder.set_progress_callback(|_, _, _| { +++ progress_called = true; +++ true +++ })); +++ t!(builder.insert_commit(commit)); +++ t!(builder.write_buf(&mut Buf::new())); +++ } +++ assert_eq!(progress_called, true); +++ } +++ +++ #[test] +++ fn clear_progress_callback() { +++ let mut progress_called = false; +++ { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut builder = t!(repo.packbuilder()); +++ let (commit, _tree) = crate::test::commit(&repo); +++ t!(builder.set_progress_callback(|_, _, _| { +++ progress_called = true; +++ true +++ })); +++ t!(builder.unset_progress_callback()); +++ t!(builder.insert_commit(commit)); +++ t!(builder.write_buf(&mut Buf::new())); +++ } +++ assert_eq!(progress_called, false); +++ } +++ +++ #[test] +++ fn progress_callback_with_write() { +++ let mut progress_called = false; +++ { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut builder = t!(repo.packbuilder()); +++ let (commit, _tree) = crate::test::commit(&repo); +++ t!(builder.set_progress_callback(|_, _, _| { +++ progress_called = true; +++ true +++ })); +++ t!(builder.insert_commit(commit)); +++ t!(builder.write(repo.path(), 0)); +++ } +++ assert_eq!(progress_called, true); +++ } +++ +++ #[test] +++ fn set_threads() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut builder = t!(repo.packbuilder()); +++ let used = builder.set_threads(4); +++ // Will be 1 if not compiled with threading. +++ assert!(used == 1 || used == 4); +++ } +++} diff --cc extra/git2/src/panic.rs index 0000000000,0000000000,0000000000..3e1b208bc7 new file mode 100644 --- /dev/null +++ b/extra/git2/src/panic.rs @@@@ -1,0 -1,0 -1,0 +1,33 @@@@ +++use std::any::Any; +++use std::cell::RefCell; +++ +++thread_local!(static LAST_ERROR: RefCell>> = { +++ RefCell::new(None) +++}); +++ +++pub fn wrap T + std::panic::UnwindSafe>(f: F) -> Option { +++ use std::panic; +++ if LAST_ERROR.with(|slot| slot.borrow().is_some()) { +++ return None; +++ } +++ match panic::catch_unwind(f) { +++ Ok(ret) => Some(ret), +++ Err(e) => { +++ LAST_ERROR.with(move |slot| { +++ *slot.borrow_mut() = Some(e); +++ }); +++ None +++ } +++ } +++} +++ +++pub fn check() { +++ let err = LAST_ERROR.with(|slot| slot.borrow_mut().take()); +++ if let Some(err) = err { +++ std::panic::resume_unwind(err); +++ } +++} +++ +++pub fn panicked() -> bool { +++ LAST_ERROR.with(|slot| slot.borrow().is_some()) +++} diff --cc extra/git2/src/patch.rs index 0000000000,0000000000,0000000000..67b84c0f0a new file mode 100644 --- /dev/null +++ b/extra/git2/src/patch.rs @@@@ -1,0 -1,0 -1,0 +1,235 @@@@ +++use libc::{c_int, c_void}; +++use std::marker::PhantomData; +++use std::path::Path; +++use std::ptr; +++ +++use crate::diff::{print_cb, LineCb}; +++use crate::util::{into_opt_c_string, Binding}; +++use crate::{raw, Blob, Buf, Diff, DiffDelta, DiffHunk, DiffLine, DiffOptions, Error}; +++ +++/// A structure representing the text changes in a single diff delta. +++/// +++/// This is an opaque structure. +++pub struct Patch<'buffers> { +++ raw: *mut raw::git_patch, +++ buffers: PhantomData<&'buffers ()>, +++} +++ +++unsafe impl<'buffers> Send for Patch<'buffers> {} +++ +++impl<'buffers> Binding for Patch<'buffers> { +++ type Raw = *mut raw::git_patch; +++ unsafe fn from_raw(raw: Self::Raw) -> Self { +++ Patch { +++ raw, +++ buffers: PhantomData, +++ } +++ } +++ fn raw(&self) -> Self::Raw { +++ self.raw +++ } +++} +++ +++impl<'buffers> Drop for Patch<'buffers> { +++ fn drop(&mut self) { +++ unsafe { raw::git_patch_free(self.raw) } +++ } +++} +++ +++impl<'buffers> Patch<'buffers> { +++ /// Return a Patch for one file in a Diff. +++ /// +++ /// Returns Ok(None) for an unchanged or binary file. +++ pub fn from_diff(diff: &Diff<'buffers>, idx: usize) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_patch_from_diff(&mut ret, diff.raw(), idx)); +++ Ok(Binding::from_raw_opt(ret)) +++ } +++ } +++ +++ /// Generate a Patch by diffing two blobs. +++ pub fn from_blobs( +++ old_blob: &Blob<'buffers>, +++ old_path: Option<&Path>, +++ new_blob: &Blob<'buffers>, +++ new_path: Option<&Path>, +++ opts: Option<&mut DiffOptions>, +++ ) -> Result { +++ let mut ret = ptr::null_mut(); +++ let old_path = into_opt_c_string(old_path)?; +++ let new_path = into_opt_c_string(new_path)?; +++ unsafe { +++ try_call!(raw::git_patch_from_blobs( +++ &mut ret, +++ old_blob.raw(), +++ old_path, +++ new_blob.raw(), +++ new_path, +++ opts.map(|s| s.raw()) +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Generate a Patch by diffing a blob and a buffer. +++ pub fn from_blob_and_buffer( +++ old_blob: &Blob<'buffers>, +++ old_path: Option<&Path>, +++ new_buffer: &'buffers [u8], +++ new_path: Option<&Path>, +++ opts: Option<&mut DiffOptions>, +++ ) -> Result { +++ let mut ret = ptr::null_mut(); +++ let old_path = into_opt_c_string(old_path)?; +++ let new_path = into_opt_c_string(new_path)?; +++ unsafe { +++ try_call!(raw::git_patch_from_blob_and_buffer( +++ &mut ret, +++ old_blob.raw(), +++ old_path, +++ new_buffer.as_ptr() as *const c_void, +++ new_buffer.len(), +++ new_path, +++ opts.map(|s| s.raw()) +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Generate a Patch by diffing two buffers. +++ pub fn from_buffers( +++ old_buffer: &'buffers [u8], +++ old_path: Option<&Path>, +++ new_buffer: &'buffers [u8], +++ new_path: Option<&Path>, +++ opts: Option<&mut DiffOptions>, +++ ) -> Result { +++ crate::init(); +++ let mut ret = ptr::null_mut(); +++ let old_path = into_opt_c_string(old_path)?; +++ let new_path = into_opt_c_string(new_path)?; +++ unsafe { +++ try_call!(raw::git_patch_from_buffers( +++ &mut ret, +++ old_buffer.as_ptr() as *const c_void, +++ old_buffer.len(), +++ old_path, +++ new_buffer.as_ptr() as *const c_void, +++ new_buffer.len(), +++ new_path, +++ opts.map(|s| s.raw()) +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Get the DiffDelta associated with the Patch. +++ pub fn delta(&self) -> DiffDelta<'buffers> { +++ unsafe { Binding::from_raw(raw::git_patch_get_delta(self.raw) as *mut _) } +++ } +++ +++ /// Get the number of hunks in the Patch. +++ pub fn num_hunks(&self) -> usize { +++ unsafe { raw::git_patch_num_hunks(self.raw) } +++ } +++ +++ /// Get the number of lines of context, additions, and deletions in the Patch. +++ pub fn line_stats(&self) -> Result<(usize, usize, usize), Error> { +++ let mut context = 0; +++ let mut additions = 0; +++ let mut deletions = 0; +++ unsafe { +++ try_call!(raw::git_patch_line_stats( +++ &mut context, +++ &mut additions, +++ &mut deletions, +++ self.raw +++ )); +++ } +++ Ok((context, additions, deletions)) +++ } +++ +++ /// Get a DiffHunk and its total line count from the Patch. +++ pub fn hunk(&self, hunk_idx: usize) -> Result<(DiffHunk<'buffers>, usize), Error> { +++ let mut ret = ptr::null(); +++ let mut lines = 0; +++ unsafe { +++ try_call!(raw::git_patch_get_hunk( +++ &mut ret, &mut lines, self.raw, hunk_idx +++ )); +++ Ok((Binding::from_raw(ret), lines)) +++ } +++ } +++ +++ /// Get the number of lines in a hunk. +++ pub fn num_lines_in_hunk(&self, hunk_idx: usize) -> Result { +++ unsafe { Ok(try_call!(raw::git_patch_num_lines_in_hunk(self.raw, hunk_idx)) as usize) } +++ } +++ +++ /// Get a DiffLine from a hunk of the Patch. +++ pub fn line_in_hunk( +++ &self, +++ hunk_idx: usize, +++ line_of_hunk: usize, +++ ) -> Result, Error> { +++ let mut ret = ptr::null(); +++ unsafe { +++ try_call!(raw::git_patch_get_line_in_hunk( +++ &mut ret, +++ self.raw, +++ hunk_idx, +++ line_of_hunk +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Get the size of a Patch's diff data in bytes. +++ pub fn size( +++ &self, +++ include_context: bool, +++ include_hunk_headers: bool, +++ include_file_headers: bool, +++ ) -> usize { +++ unsafe { +++ raw::git_patch_size( +++ self.raw, +++ include_context as c_int, +++ include_hunk_headers as c_int, +++ include_file_headers as c_int, +++ ) +++ } +++ } +++ +++ /// Print the Patch to text via a callback. +++ pub fn print(&mut self, mut line_cb: &mut LineCb<'_>) -> Result<(), Error> { +++ let ptr = &mut line_cb as *mut _ as *mut c_void; +++ unsafe { +++ let cb: raw::git_diff_line_cb = Some(print_cb); +++ try_call!(raw::git_patch_print(self.raw, cb, ptr)); +++ Ok(()) +++ } +++ } +++ +++ /// Get the Patch text as a Buf. +++ pub fn to_buf(&mut self) -> Result { +++ let buf = Buf::new(); +++ unsafe { +++ try_call!(raw::git_patch_to_buf(buf.raw(), self.raw)); +++ } +++ Ok(buf) +++ } +++} +++ +++impl<'buffers> std::fmt::Debug for Patch<'buffers> { +++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +++ let mut ds = f.debug_struct("Patch"); +++ ds.field("delta", &self.delta()) +++ .field("num_hunks", &self.num_hunks()); +++ if let Ok(line_stats) = &self.line_stats() { +++ ds.field("line_stats", line_stats); +++ } +++ ds.finish() +++ } +++} diff --cc extra/git2/src/pathspec.rs index 0000000000,0000000000,0000000000..16850dc210 new file mode 100644 --- /dev/null +++ b/extra/git2/src/pathspec.rs @@@@ -1,0 -1,0 -1,0 +1,368 @@@@ +++use libc::size_t; +++use std::iter::FusedIterator; +++use std::marker; +++use std::ops::Range; +++use std::path::Path; +++use std::ptr; +++ +++use crate::util::{path_to_repo_path, Binding}; +++use crate::{raw, Diff, DiffDelta, Error, Index, IntoCString, PathspecFlags, Repository, Tree}; +++ +++/// Structure representing a compiled pathspec used for matching against various +++/// structures. +++pub struct Pathspec { +++ raw: *mut raw::git_pathspec, +++} +++ +++/// List of filenames matching a pathspec. +++pub struct PathspecMatchList<'ps> { +++ raw: *mut raw::git_pathspec_match_list, +++ _marker: marker::PhantomData<&'ps Pathspec>, +++} +++ +++/// Iterator over the matched paths in a pathspec. +++pub struct PathspecEntries<'list> { +++ range: Range, +++ list: &'list PathspecMatchList<'list>, +++} +++ +++/// Iterator over the matching diff deltas. +++pub struct PathspecDiffEntries<'list> { +++ range: Range, +++ list: &'list PathspecMatchList<'list>, +++} +++ +++/// Iterator over the failed list of pathspec items that did not match. +++pub struct PathspecFailedEntries<'list> { +++ range: Range, +++ list: &'list PathspecMatchList<'list>, +++} +++ +++impl Pathspec { +++ /// Creates a new pathspec from a list of specs to match against. +++ pub fn new(specs: I) -> Result +++ where +++ T: IntoCString, +++ I: IntoIterator, +++ { +++ crate::init(); +++ let (_a, _b, arr) = crate::util::iter2cstrs_paths(specs)?; +++ unsafe { +++ let mut ret = ptr::null_mut(); +++ try_call!(raw::git_pathspec_new(&mut ret, &arr)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Match a pathspec against files in a diff. +++ /// +++ /// The list returned contains the list of all matched filenames (unless you +++ /// pass `PATHSPEC_FAILURES_ONLY` in the flags) and may also contain the +++ /// list of pathspecs with no match if the `PATHSPEC_FIND_FAILURES` flag is +++ /// specified. +++ pub fn match_diff( +++ &self, +++ diff: &Diff<'_>, +++ flags: PathspecFlags, +++ ) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_pathspec_match_diff( +++ &mut ret, +++ diff.raw(), +++ flags.bits(), +++ self.raw +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Match a pathspec against files in a tree. +++ /// +++ /// The list returned contains the list of all matched filenames (unless you +++ /// pass `PATHSPEC_FAILURES_ONLY` in the flags) and may also contain the +++ /// list of pathspecs with no match if the `PATHSPEC_FIND_FAILURES` flag is +++ /// specified. +++ pub fn match_tree( +++ &self, +++ tree: &Tree<'_>, +++ flags: PathspecFlags, +++ ) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_pathspec_match_tree( +++ &mut ret, +++ tree.raw(), +++ flags.bits(), +++ self.raw +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// This matches the pathspec against the files in the repository index. +++ /// +++ /// The list returned contains the list of all matched filenames (unless you +++ /// pass `PATHSPEC_FAILURES_ONLY` in the flags) and may also contain the +++ /// list of pathspecs with no match if the `PATHSPEC_FIND_FAILURES` flag is +++ /// specified. +++ pub fn match_index( +++ &self, +++ index: &Index, +++ flags: PathspecFlags, +++ ) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_pathspec_match_index( +++ &mut ret, +++ index.raw(), +++ flags.bits(), +++ self.raw +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Match a pathspec against the working directory of a repository. +++ /// +++ /// This matches the pathspec against the current files in the working +++ /// directory of the repository. It is an error to invoke this on a bare +++ /// repo. This handles git ignores (i.e. ignored files will not be +++ /// considered to match the pathspec unless the file is tracked in the +++ /// index). +++ /// +++ /// The list returned contains the list of all matched filenames (unless you +++ /// pass `PATHSPEC_FAILURES_ONLY` in the flags) and may also contain the +++ /// list of pathspecs with no match if the `PATHSPEC_FIND_FAILURES` flag is +++ /// specified. +++ pub fn match_workdir( +++ &self, +++ repo: &Repository, +++ flags: PathspecFlags, +++ ) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_pathspec_match_workdir( +++ &mut ret, +++ repo.raw(), +++ flags.bits(), +++ self.raw +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Try to match a path against a pathspec +++ /// +++ /// Unlike most of the other pathspec matching functions, this will not fall +++ /// back on the native case-sensitivity for your platform. You must +++ /// explicitly pass flags to control case sensitivity or else this will fall +++ /// back on being case sensitive. +++ pub fn matches_path(&self, path: &Path, flags: PathspecFlags) -> bool { +++ let path = path_to_repo_path(path).unwrap(); +++ unsafe { raw::git_pathspec_matches_path(&*self.raw, flags.bits(), path.as_ptr()) == 1 } +++ } +++} +++ +++impl Binding for Pathspec { +++ type Raw = *mut raw::git_pathspec; +++ +++ unsafe fn from_raw(raw: *mut raw::git_pathspec) -> Pathspec { +++ Pathspec { raw } +++ } +++ fn raw(&self) -> *mut raw::git_pathspec { +++ self.raw +++ } +++} +++ +++impl Drop for Pathspec { +++ fn drop(&mut self) { +++ unsafe { raw::git_pathspec_free(self.raw) } +++ } +++} +++ +++impl<'ps> PathspecMatchList<'ps> { +++ fn entrycount(&self) -> usize { +++ unsafe { raw::git_pathspec_match_list_entrycount(&*self.raw) as usize } +++ } +++ +++ fn failed_entrycount(&self) -> usize { +++ unsafe { raw::git_pathspec_match_list_failed_entrycount(&*self.raw) as usize } +++ } +++ +++ /// Returns an iterator over the matching filenames in this list. +++ pub fn entries(&self) -> PathspecEntries<'_> { +++ let n = self.entrycount(); +++ let n = if n > 0 && self.entry(0).is_none() { +++ 0 +++ } else { +++ n +++ }; +++ PathspecEntries { +++ range: 0..n, +++ list: self, +++ } +++ } +++ +++ /// Get a matching filename by position. +++ /// +++ /// If this list was generated from a diff, then the return value will +++ /// always be `None. +++ pub fn entry(&self, i: usize) -> Option<&[u8]> { +++ unsafe { +++ let ptr = raw::git_pathspec_match_list_entry(&*self.raw, i as size_t); +++ crate::opt_bytes(self, ptr) +++ } +++ } +++ +++ /// Returns an iterator over the matching diff entries in this list. +++ pub fn diff_entries(&self) -> PathspecDiffEntries<'_> { +++ let n = self.entrycount(); +++ let n = if n > 0 && self.diff_entry(0).is_none() { +++ 0 +++ } else { +++ n +++ }; +++ PathspecDiffEntries { +++ range: 0..n, +++ list: self, +++ } +++ } +++ +++ /// Get a matching diff delta by position. +++ /// +++ /// If the list was not generated from a diff, then the return value will +++ /// always be `None`. +++ pub fn diff_entry(&self, i: usize) -> Option> { +++ unsafe { +++ let ptr = raw::git_pathspec_match_list_diff_entry(&*self.raw, i as size_t); +++ Binding::from_raw_opt(ptr as *mut _) +++ } +++ } +++ +++ /// Returns an iterator over the non-matching entries in this list. +++ pub fn failed_entries(&self) -> PathspecFailedEntries<'_> { +++ let n = self.failed_entrycount(); +++ let n = if n > 0 && self.failed_entry(0).is_none() { +++ 0 +++ } else { +++ n +++ }; +++ PathspecFailedEntries { +++ range: 0..n, +++ list: self, +++ } +++ } +++ +++ /// Get an original pathspec string that had no matches. +++ pub fn failed_entry(&self, i: usize) -> Option<&[u8]> { +++ unsafe { +++ let ptr = raw::git_pathspec_match_list_failed_entry(&*self.raw, i as size_t); +++ crate::opt_bytes(self, ptr) +++ } +++ } +++} +++ +++impl<'ps> Binding for PathspecMatchList<'ps> { +++ type Raw = *mut raw::git_pathspec_match_list; +++ +++ unsafe fn from_raw(raw: *mut raw::git_pathspec_match_list) -> PathspecMatchList<'ps> { +++ PathspecMatchList { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_pathspec_match_list { +++ self.raw +++ } +++} +++ +++impl<'ps> Drop for PathspecMatchList<'ps> { +++ fn drop(&mut self) { +++ unsafe { raw::git_pathspec_match_list_free(self.raw) } +++ } +++} +++ +++impl<'list> Iterator for PathspecEntries<'list> { +++ type Item = &'list [u8]; +++ fn next(&mut self) -> Option<&'list [u8]> { +++ self.range.next().and_then(|i| self.list.entry(i)) +++ } +++ fn size_hint(&self) -> (usize, Option) { +++ self.range.size_hint() +++ } +++} +++impl<'list> DoubleEndedIterator for PathspecEntries<'list> { +++ fn next_back(&mut self) -> Option<&'list [u8]> { +++ self.range.next_back().and_then(|i| self.list.entry(i)) +++ } +++} +++impl<'list> FusedIterator for PathspecEntries<'list> {} +++impl<'list> ExactSizeIterator for PathspecEntries<'list> {} +++ +++impl<'list> Iterator for PathspecDiffEntries<'list> { +++ type Item = DiffDelta<'list>; +++ fn next(&mut self) -> Option> { +++ self.range.next().and_then(|i| self.list.diff_entry(i)) +++ } +++ fn size_hint(&self) -> (usize, Option) { +++ self.range.size_hint() +++ } +++} +++impl<'list> DoubleEndedIterator for PathspecDiffEntries<'list> { +++ fn next_back(&mut self) -> Option> { +++ self.range.next_back().and_then(|i| self.list.diff_entry(i)) +++ } +++} +++impl<'list> FusedIterator for PathspecDiffEntries<'list> {} +++impl<'list> ExactSizeIterator for PathspecDiffEntries<'list> {} +++ +++impl<'list> Iterator for PathspecFailedEntries<'list> { +++ type Item = &'list [u8]; +++ fn next(&mut self) -> Option<&'list [u8]> { +++ self.range.next().and_then(|i| self.list.failed_entry(i)) +++ } +++ fn size_hint(&self) -> (usize, Option) { +++ self.range.size_hint() +++ } +++} +++impl<'list> DoubleEndedIterator for PathspecFailedEntries<'list> { +++ fn next_back(&mut self) -> Option<&'list [u8]> { +++ self.range +++ .next_back() +++ .and_then(|i| self.list.failed_entry(i)) +++ } +++} +++impl<'list> FusedIterator for PathspecFailedEntries<'list> {} +++impl<'list> ExactSizeIterator for PathspecFailedEntries<'list> {} +++ +++#[cfg(test)] +++mod tests { +++ use super::Pathspec; +++ use crate::PathspecFlags; +++ use std::fs::File; +++ use std::path::Path; +++ +++ #[test] +++ fn smoke() { +++ let ps = Pathspec::new(["a"].iter()).unwrap(); +++ assert!(ps.matches_path(Path::new("a"), PathspecFlags::DEFAULT)); +++ assert!(ps.matches_path(Path::new("a/b"), PathspecFlags::DEFAULT)); +++ assert!(!ps.matches_path(Path::new("b"), PathspecFlags::DEFAULT)); +++ assert!(!ps.matches_path(Path::new("ab/c"), PathspecFlags::DEFAULT)); +++ +++ let (td, repo) = crate::test::repo_init(); +++ let list = ps.match_workdir(&repo, PathspecFlags::DEFAULT).unwrap(); +++ assert_eq!(list.entries().len(), 0); +++ assert_eq!(list.diff_entries().len(), 0); +++ assert_eq!(list.failed_entries().len(), 0); +++ +++ File::create(&td.path().join("a")).unwrap(); +++ +++ let list = ps +++ .match_workdir(&repo, crate::PathspecFlags::FIND_FAILURES) +++ .unwrap(); +++ assert_eq!(list.entries().len(), 1); +++ assert_eq!(list.entries().next(), Some("a".as_bytes())); +++ } +++} diff --cc extra/git2/src/proxy_options.rs index 0000000000,0000000000,0000000000..b19ba3a527 new file mode 100644 --- /dev/null +++ b/extra/git2/src/proxy_options.rs @@@@ -1,0 -1,0 -1,0 +1,56 @@@@ +++use std::ffi::CString; +++use std::marker; +++use std::ptr; +++ +++use crate::raw; +++use crate::util::Binding; +++ +++/// Options which can be specified to various fetch operations. +++#[derive(Default)] +++pub struct ProxyOptions<'a> { +++ url: Option, +++ proxy_kind: raw::git_proxy_t, +++ _marker: marker::PhantomData<&'a i32>, +++} +++ +++impl<'a> ProxyOptions<'a> { +++ /// Creates a new set of proxy options ready to be configured. +++ pub fn new() -> ProxyOptions<'a> { +++ Default::default() +++ } +++ +++ /// Try to auto-detect the proxy from the git configuration. +++ /// +++ /// Note that this will override `url` specified before. +++ pub fn auto(&mut self) -> &mut Self { +++ self.proxy_kind = raw::GIT_PROXY_AUTO; +++ self +++ } +++ +++ /// Specify the exact URL of the proxy to use. +++ /// +++ /// Note that this will override `auto` specified before. +++ pub fn url(&mut self, url: &str) -> &mut Self { +++ self.proxy_kind = raw::GIT_PROXY_SPECIFIED; +++ self.url = Some(CString::new(url).unwrap()); +++ self +++ } +++} +++ +++impl<'a> Binding for ProxyOptions<'a> { +++ type Raw = raw::git_proxy_options; +++ unsafe fn from_raw(_raw: raw::git_proxy_options) -> ProxyOptions<'a> { +++ panic!("can't create proxy from raw options") +++ } +++ +++ fn raw(&self) -> raw::git_proxy_options { +++ raw::git_proxy_options { +++ version: raw::GIT_PROXY_OPTIONS_VERSION, +++ kind: self.proxy_kind, +++ url: self.url.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null()), +++ credentials: None, +++ certificate_check: None, +++ payload: ptr::null_mut(), +++ } +++ } +++} diff --cc extra/git2/src/push_update.rs index 0000000000,0000000000,0000000000..97bebb1921 new file mode 100644 --- /dev/null +++ b/extra/git2/src/push_update.rs @@@@ -1,0 -1,0 -1,0 +1,55 @@@@ +++use crate::util::Binding; +++use crate::{raw, Oid}; +++use std::marker; +++use std::str; +++ +++/// Represents an update which will be performed on the remote during push. +++pub struct PushUpdate<'a> { +++ raw: *const raw::git_push_update, +++ _marker: marker::PhantomData<&'a raw::git_push_update>, +++} +++ +++impl<'a> Binding for PushUpdate<'a> { +++ type Raw = *const raw::git_push_update; +++ unsafe fn from_raw(raw: *const raw::git_push_update) -> PushUpdate<'a> { +++ PushUpdate { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> Self::Raw { +++ self.raw +++ } +++} +++ +++impl PushUpdate<'_> { +++ /// Returns the source name of the reference as a byte slice. +++ pub fn src_refname_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, (*self.raw).src_refname).unwrap() } +++ } +++ +++ /// Returns the source name of the reference, or None if it is not valid UTF-8. +++ pub fn src_refname(&self) -> Option<&str> { +++ str::from_utf8(self.src_refname_bytes()).ok() +++ } +++ +++ /// Returns the name of the reference to update on the server as a byte slice. +++ pub fn dst_refname_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, (*self.raw).dst_refname).unwrap() } +++ } +++ +++ /// Returns the name of the reference to update on the server, or None if it is not valid UTF-8. +++ pub fn dst_refname(&self) -> Option<&str> { +++ str::from_utf8(self.dst_refname_bytes()).ok() +++ } +++ +++ /// Returns the current target of the reference. +++ pub fn src(&self) -> Oid { +++ unsafe { Binding::from_raw(&(*self.raw).src as *const _) } +++ } +++ +++ /// Returns the new target for the reference. +++ pub fn dst(&self) -> Oid { +++ unsafe { Binding::from_raw(&(*self.raw).dst as *const _) } +++ } +++} diff --cc extra/git2/src/rebase.rs index 0000000000,0000000000,0000000000..2bf8fe3e8a new file mode 100644 --- /dev/null +++ b/extra/git2/src/rebase.rs @@@@ -1,0 -1,0 -1,0 +1,441 @@@@ +++use std::ffi::CString; +++use std::{marker, mem, ptr, str}; +++ +++use crate::build::CheckoutBuilder; +++use crate::util::Binding; +++use crate::{raw, Error, Index, MergeOptions, Oid, Signature}; +++ +++/// Rebase options +++/// +++/// Use to tell the rebase machinery how to operate. +++pub struct RebaseOptions<'cb> { +++ raw: raw::git_rebase_options, +++ rewrite_notes_ref: Option, +++ merge_options: Option, +++ checkout_options: Option>, +++} +++ +++impl<'cb> Default for RebaseOptions<'cb> { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl<'cb> RebaseOptions<'cb> { +++ /// Creates a new default set of rebase options. +++ pub fn new() -> RebaseOptions<'cb> { +++ let mut opts = RebaseOptions { +++ raw: unsafe { mem::zeroed() }, +++ rewrite_notes_ref: None, +++ merge_options: None, +++ checkout_options: None, +++ }; +++ assert_eq!(unsafe { raw::git_rebase_init_options(&mut opts.raw, 1) }, 0); +++ opts +++ } +++ +++ /// Used by `Repository::rebase`, this will instruct other clients working on this +++ /// rebase that you want a quiet rebase experience, which they may choose to +++ /// provide in an application-specific manner. This has no effect upon +++ /// libgit2 directly, but is provided for interoperability between Git +++ /// tools. +++ pub fn quiet(&mut self, quiet: bool) -> &mut RebaseOptions<'cb> { +++ self.raw.quiet = quiet as i32; +++ self +++ } +++ +++ /// Used by `Repository::rebase`, this will begin an in-memory rebase, +++ /// which will allow callers to step through the rebase operations and +++ /// commit the rebased changes, but will not rewind HEAD or update the +++ /// repository to be in a rebasing state. This will not interfere with +++ /// the working directory (if there is one). +++ pub fn inmemory(&mut self, inmemory: bool) -> &mut RebaseOptions<'cb> { +++ self.raw.inmemory = inmemory as i32; +++ self +++ } +++ +++ /// Used by `finish()`, this is the name of the notes reference +++ /// used to rewrite notes for rebased commits when finishing the rebase; +++ /// if NULL, the contents of the configuration option `notes.rewriteRef` +++ /// is examined, unless the configuration option `notes.rewrite.rebase` +++ /// is set to false. If `notes.rewriteRef` is also NULL, notes will +++ /// not be rewritten. +++ pub fn rewrite_notes_ref(&mut self, rewrite_notes_ref: &str) -> &mut RebaseOptions<'cb> { +++ self.rewrite_notes_ref = Some(CString::new(rewrite_notes_ref).unwrap()); +++ self +++ } +++ +++ /// Options to control how trees are merged during `next()`. +++ pub fn merge_options(&mut self, opts: MergeOptions) -> &mut RebaseOptions<'cb> { +++ self.merge_options = Some(opts); +++ self +++ } +++ +++ /// Options to control how files are written during `Repository::rebase`, +++ /// `next()` and `abort()`. Note that a minimum strategy of +++ /// `GIT_CHECKOUT_SAFE` is defaulted in `init` and `next`, and a minimum +++ /// strategy of `GIT_CHECKOUT_FORCE` is defaulted in `abort` to match git +++ /// semantics. +++ pub fn checkout_options(&mut self, opts: CheckoutBuilder<'cb>) -> &mut RebaseOptions<'cb> { +++ self.checkout_options = Some(opts); +++ self +++ } +++ +++ /// Acquire a pointer to the underlying raw options. +++ pub fn raw(&mut self) -> *const raw::git_rebase_options { +++ unsafe { +++ if let Some(opts) = self.merge_options.as_mut().take() { +++ ptr::copy_nonoverlapping(opts.raw(), &mut self.raw.merge_options, 1); +++ } +++ if let Some(opts) = self.checkout_options.as_mut() { +++ opts.configure(&mut self.raw.checkout_options); +++ } +++ self.raw.rewrite_notes_ref = self +++ .rewrite_notes_ref +++ .as_ref() +++ .map(|s| s.as_ptr()) +++ .unwrap_or(ptr::null()); +++ } +++ &self.raw +++ } +++} +++ +++/// Representation of a rebase +++pub struct Rebase<'repo> { +++ raw: *mut raw::git_rebase, +++ _marker: marker::PhantomData<&'repo raw::git_rebase>, +++} +++ +++impl<'repo> Rebase<'repo> { +++ /// Gets the count of rebase operations that are to be applied. +++ pub fn len(&self) -> usize { +++ unsafe { raw::git_rebase_operation_entrycount(self.raw) } +++ } +++ +++ /// Gets the original `HEAD` ref name for merge rebases. +++ pub fn orig_head_name(&self) -> Option<&str> { +++ let name_bytes = +++ unsafe { crate::opt_bytes(self, raw::git_rebase_orig_head_name(self.raw)) }; +++ name_bytes.and_then(|s| str::from_utf8(s).ok()) +++ } +++ +++ /// Gets the original HEAD id for merge rebases. +++ pub fn orig_head_id(&self) -> Option { +++ unsafe { Oid::from_raw_opt(raw::git_rebase_orig_head_id(self.raw)) } +++ } +++ +++ /// Gets the rebase operation specified by the given index. +++ pub fn nth(&mut self, n: usize) -> Option> { +++ unsafe { +++ let op = raw::git_rebase_operation_byindex(self.raw, n); +++ if op.is_null() { +++ None +++ } else { +++ Some(RebaseOperation::from_raw(op)) +++ } +++ } +++ } +++ +++ /// Gets the index of the rebase operation that is currently being applied. +++ /// If the first operation has not yet been applied (because you have called +++ /// `init` but not yet `next`) then this returns None. +++ pub fn operation_current(&mut self) -> Option { +++ let cur = unsafe { raw::git_rebase_operation_current(self.raw) }; +++ if cur == raw::GIT_REBASE_NO_OPERATION { +++ None +++ } else { +++ Some(cur) +++ } +++ } +++ +++ /// Gets the index produced by the last operation, which is the result of +++ /// `next()` and which will be committed by the next invocation of +++ /// `commit()`. This is useful for resolving conflicts in an in-memory +++ /// rebase before committing them. +++ /// +++ /// This is only applicable for in-memory rebases; for rebases within a +++ /// working directory, the changes were applied to the repository's index. +++ pub fn inmemory_index(&mut self) -> Result { +++ let mut idx = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_rebase_inmemory_index(&mut idx, self.raw)); +++ Ok(Binding::from_raw(idx)) +++ } +++ } +++ +++ /// Commits the current patch. You must have resolved any conflicts that +++ /// were introduced during the patch application from the `git_rebase_next` +++ /// invocation. To keep the author and message from the original commit leave +++ /// them as None +++ pub fn commit( +++ &mut self, +++ author: Option<&Signature<'_>>, +++ committer: &Signature<'_>, +++ message: Option<&str>, +++ ) -> Result { +++ let mut id: raw::git_oid = unsafe { mem::zeroed() }; +++ let message = crate::opt_cstr(message)?; +++ unsafe { +++ try_call!(raw::git_rebase_commit( +++ &mut id, +++ self.raw, +++ author.map(|a| a.raw()), +++ committer.raw(), +++ ptr::null(), +++ message +++ )); +++ Ok(Binding::from_raw(&id as *const _)) +++ } +++ } +++ +++ /// Aborts a rebase that is currently in progress, resetting the repository +++ /// and working directory to their state before rebase began. +++ pub fn abort(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_rebase_abort(self.raw)); +++ } +++ +++ Ok(()) +++ } +++ +++ /// Finishes a rebase that is currently in progress once all patches have +++ /// been applied. +++ pub fn finish(&mut self, signature: Option<&Signature<'_>>) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_rebase_finish(self.raw, signature.map(|s| s.raw()))); +++ } +++ +++ Ok(()) +++ } +++} +++ +++impl<'rebase> Iterator for Rebase<'rebase> { +++ type Item = Result, Error>; +++ +++ /// Performs the next rebase operation and returns the information about it. +++ /// If the operation is one that applies a patch (which is any operation except +++ /// GitRebaseOperation::Exec) then the patch will be applied and the index and +++ /// working directory will be updated with the changes. If there are conflicts, +++ /// you will need to address those before committing the changes. +++ fn next(&mut self) -> Option, Error>> { +++ let mut out = ptr::null_mut(); +++ unsafe { +++ try_call_iter!(raw::git_rebase_next(&mut out, self.raw)); +++ Some(Ok(RebaseOperation::from_raw(out))) +++ } +++ } +++} +++ +++impl<'repo> Binding for Rebase<'repo> { +++ type Raw = *mut raw::git_rebase; +++ unsafe fn from_raw(raw: *mut raw::git_rebase) -> Rebase<'repo> { +++ Rebase { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_rebase { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for Rebase<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_rebase_free(self.raw) } +++ } +++} +++ +++/// A rebase operation +++/// +++/// Describes a single instruction/operation to be performed during the +++/// rebase. +++#[derive(Debug, PartialEq)] +++pub enum RebaseOperationType { +++ /// The given commit is to be cherry-picked. The client should commit the +++ /// changes and continue if there are no conflicts. +++ Pick, +++ +++ /// The given commit is to be cherry-picked, but the client should prompt +++ /// the user to provide an updated commit message. +++ Reword, +++ +++ /// The given commit is to be cherry-picked, but the client should stop to +++ /// allow the user to edit the changes before committing them. +++ Edit, +++ +++ /// The given commit is to be squashed into the previous commit. The commit +++ /// message will be merged with the previous message. +++ Squash, +++ +++ /// The given commit is to be squashed into the previous commit. The commit +++ /// message from this commit will be discarded. +++ Fixup, +++ +++ /// No commit will be cherry-picked. The client should run the given command +++ /// and (if successful) continue. +++ Exec, +++} +++ +++impl RebaseOperationType { +++ /// Convert from the int into an enum. Returns None if invalid. +++ pub fn from_raw(raw: raw::git_rebase_operation_t) -> Option { +++ match raw { +++ raw::GIT_REBASE_OPERATION_PICK => Some(RebaseOperationType::Pick), +++ raw::GIT_REBASE_OPERATION_REWORD => Some(RebaseOperationType::Reword), +++ raw::GIT_REBASE_OPERATION_EDIT => Some(RebaseOperationType::Edit), +++ raw::GIT_REBASE_OPERATION_SQUASH => Some(RebaseOperationType::Squash), +++ raw::GIT_REBASE_OPERATION_FIXUP => Some(RebaseOperationType::Fixup), +++ raw::GIT_REBASE_OPERATION_EXEC => Some(RebaseOperationType::Exec), +++ _ => None, +++ } +++ } +++} +++ +++/// A rebase operation +++/// +++/// Describes a single instruction/operation to be performed during the +++/// rebase. +++#[derive(Debug)] +++pub struct RebaseOperation<'rebase> { +++ raw: *const raw::git_rebase_operation, +++ _marker: marker::PhantomData>, +++} +++ +++impl<'rebase> RebaseOperation<'rebase> { +++ /// The type of rebase operation +++ pub fn kind(&self) -> Option { +++ unsafe { RebaseOperationType::from_raw((*self.raw).kind) } +++ } +++ +++ /// The commit ID being cherry-picked. This will be populated for all +++ /// operations except those of type `GIT_REBASE_OPERATION_EXEC`. +++ pub fn id(&self) -> Oid { +++ unsafe { Binding::from_raw(&(*self.raw).id as *const _) } +++ } +++ +++ ///The executable the user has requested be run. This will only +++ /// be populated for operations of type RebaseOperationType::Exec +++ pub fn exec(&self) -> Option<&str> { +++ unsafe { str::from_utf8(crate::opt_bytes(self, (*self.raw).exec).unwrap()).ok() } +++ } +++} +++ +++impl<'rebase> Binding for RebaseOperation<'rebase> { +++ type Raw = *const raw::git_rebase_operation; +++ unsafe fn from_raw(raw: *const raw::git_rebase_operation) -> RebaseOperation<'rebase> { +++ RebaseOperation { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *const raw::git_rebase_operation { +++ self.raw +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::{RebaseOperationType, RebaseOptions, Signature}; +++ use std::{fs, path}; +++ +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ let head_target = repo.head().unwrap().target().unwrap(); +++ let tip = repo.find_commit(head_target).unwrap(); +++ let sig = tip.author(); +++ let tree = tip.tree().unwrap(); +++ +++ // We just want to see the iteration work so we can create commits with +++ // no changes +++ let c1 = repo +++ .commit(Some("refs/heads/main"), &sig, &sig, "foo", &tree, &[&tip]) +++ .unwrap(); +++ let c1 = repo.find_commit(c1).unwrap(); +++ let c2 = repo +++ .commit(Some("refs/heads/main"), &sig, &sig, "foo", &tree, &[&c1]) +++ .unwrap(); +++ +++ let head = repo.find_reference("refs/heads/main").unwrap(); +++ let branch = repo.reference_to_annotated_commit(&head).unwrap(); +++ let upstream = repo.find_annotated_commit(tip.id()).unwrap(); +++ let mut rebase = repo +++ .rebase(Some(&branch), Some(&upstream), None, None) +++ .unwrap(); +++ +++ assert_eq!(Some("refs/heads/main"), rebase.orig_head_name()); +++ assert_eq!(Some(c2), rebase.orig_head_id()); +++ +++ assert_eq!(rebase.len(), 2); +++ { +++ let op = rebase.next().unwrap().unwrap(); +++ assert_eq!(op.kind(), Some(RebaseOperationType::Pick)); +++ assert_eq!(op.id(), c1.id()); +++ } +++ { +++ let op = rebase.next().unwrap().unwrap(); +++ assert_eq!(op.kind(), Some(RebaseOperationType::Pick)); +++ assert_eq!(op.id(), c2); +++ } +++ { +++ let op = rebase.next(); +++ assert!(op.is_none()); +++ } +++ } +++ +++ #[test] +++ fn keeping_original_author_msg() { +++ let (td, repo) = crate::test::repo_init(); +++ let head_target = repo.head().unwrap().target().unwrap(); +++ let tip = repo.find_commit(head_target).unwrap(); +++ let sig = Signature::now("testname", "testemail").unwrap(); +++ let mut index = repo.index().unwrap(); +++ +++ fs::File::create(td.path().join("file_a")).unwrap(); +++ index.add_path(path::Path::new("file_a")).unwrap(); +++ index.write().unwrap(); +++ let tree_id_a = index.write_tree().unwrap(); +++ let tree_a = repo.find_tree(tree_id_a).unwrap(); +++ let c1 = repo +++ .commit(Some("refs/heads/main"), &sig, &sig, "A", &tree_a, &[&tip]) +++ .unwrap(); +++ let c1 = repo.find_commit(c1).unwrap(); +++ +++ fs::File::create(td.path().join("file_b")).unwrap(); +++ index.add_path(path::Path::new("file_b")).unwrap(); +++ index.write().unwrap(); +++ let tree_id_b = index.write_tree().unwrap(); +++ let tree_b = repo.find_tree(tree_id_b).unwrap(); +++ let c2 = repo +++ .commit(Some("refs/heads/main"), &sig, &sig, "B", &tree_b, &[&c1]) +++ .unwrap(); +++ +++ let branch = repo.find_annotated_commit(c2).unwrap(); +++ let upstream = repo.find_annotated_commit(tip.id()).unwrap(); +++ let mut opts: RebaseOptions<'_> = Default::default(); +++ let mut rebase = repo +++ .rebase(Some(&branch), Some(&upstream), None, Some(&mut opts)) +++ .unwrap(); +++ +++ assert_eq!(rebase.len(), 2); +++ +++ { +++ rebase.next().unwrap().unwrap(); +++ let id = rebase.commit(None, &sig, None).unwrap(); +++ let commit = repo.find_commit(id).unwrap(); +++ assert_eq!(commit.message(), Some("A")); +++ assert_eq!(commit.author().name(), Some("testname")); +++ assert_eq!(commit.author().email(), Some("testemail")); +++ } +++ +++ { +++ rebase.next().unwrap().unwrap(); +++ let id = rebase.commit(None, &sig, None).unwrap(); +++ let commit = repo.find_commit(id).unwrap(); +++ assert_eq!(commit.message(), Some("B")); +++ assert_eq!(commit.author().name(), Some("testname")); +++ assert_eq!(commit.author().email(), Some("testemail")); +++ } +++ rebase.finish(None).unwrap(); +++ } +++} diff --cc extra/git2/src/reference.rs index 0000000000,0000000000,0000000000..0af845d7c5 new file mode 100644 --- /dev/null +++ b/extra/git2/src/reference.rs @@@@ -1,0 -1,0 -1,0 +1,592 @@@@ +++use std::cmp::Ordering; +++use std::ffi::CString; +++use std::marker; +++use std::mem; +++use std::ptr; +++use std::str; +++ +++use crate::object::CastOrPanic; +++use crate::util::{c_cmp_to_ordering, Binding}; +++use crate::{ +++ call, raw, Blob, Commit, Error, Object, ObjectType, Oid, ReferenceFormat, ReferenceType, +++ Repository, Tag, Tree, +++}; +++ +++// Not in the public header files (yet?), but a hard limit used by libgit2 +++// internally +++const GIT_REFNAME_MAX: usize = 1024; +++ +++/// This is used to logically indicate that a [`raw::git_reference`] or +++/// [`raw::git_reference_iterator`] holds a reference to [`raw::git_refdb`]. +++/// It is not necessary to have a wrapper like this in the +++/// [`marker::PhantomData`], since all that matters is that it is tied to the +++/// lifetime of the [`Repository`], but this helps distinguish the actual +++/// references involved. +++struct Refdb<'repo>(#[allow(dead_code)] &'repo Repository); +++ +++/// A structure to represent a git [reference][1]. +++/// +++/// [1]: http://git-scm.com/book/en/Git-Internals-Git-References +++pub struct Reference<'repo> { +++ raw: *mut raw::git_reference, +++ _marker: marker::PhantomData>, +++} +++ +++/// An iterator over the references in a repository. +++pub struct References<'repo> { +++ raw: *mut raw::git_reference_iterator, +++ _marker: marker::PhantomData>, +++} +++ +++/// An iterator over the names of references in a repository. +++pub struct ReferenceNames<'repo, 'references> { +++ inner: &'references mut References<'repo>, +++} +++ +++impl<'repo> Reference<'repo> { +++ /// Ensure the reference name is well-formed. +++ /// +++ /// Validation is performed as if [`ReferenceFormat::ALLOW_ONELEVEL`] +++ /// was given to [`Reference::normalize_name`]. No normalization is +++ /// performed, however. +++ /// +++ /// ```rust +++ /// use git2::Reference; +++ /// +++ /// assert!(Reference::is_valid_name("HEAD")); +++ /// assert!(Reference::is_valid_name("refs/heads/main")); +++ /// +++ /// // But: +++ /// assert!(!Reference::is_valid_name("main")); +++ /// assert!(!Reference::is_valid_name("refs/heads/*")); +++ /// assert!(!Reference::is_valid_name("foo//bar")); +++ /// ``` +++ /// +++ /// [`ReferenceFormat::ALLOW_ONELEVEL`]: +++ /// struct.ReferenceFormat#associatedconstant.ALLOW_ONELEVEL +++ /// [`Reference::normalize_name`]: struct.Reference#method.normalize_name +++ pub fn is_valid_name(refname: &str) -> bool { +++ crate::init(); +++ let refname = CString::new(refname).unwrap(); +++ let mut valid: libc::c_int = 0; +++ unsafe { +++ call::c_try(raw::git_reference_name_is_valid( +++ &mut valid, +++ refname.as_ptr(), +++ )) +++ .unwrap(); +++ } +++ valid == 1 +++ } +++ +++ /// Normalize reference name and check validity. +++ /// +++ /// This will normalize the reference name by collapsing runs of adjacent +++ /// slashes between name components into a single slash. It also validates +++ /// the name according to the following rules: +++ /// +++ /// 1. If [`ReferenceFormat::ALLOW_ONELEVEL`] is given, the name may +++ /// contain only capital letters and underscores, and must begin and end +++ /// with a letter. (e.g. "HEAD", "ORIG_HEAD"). +++ /// 2. The flag [`ReferenceFormat::REFSPEC_SHORTHAND`] has an effect +++ /// only when combined with [`ReferenceFormat::ALLOW_ONELEVEL`]. If +++ /// it is given, "shorthand" branch names (i.e. those not prefixed by +++ /// `refs/`, but consisting of a single word without `/` separators) +++ /// become valid. For example, "main" would be accepted. +++ /// 3. If [`ReferenceFormat::REFSPEC_PATTERN`] is given, the name may +++ /// contain a single `*` in place of a full pathname component (e.g. +++ /// `foo/*/bar`, `foo/bar*`). +++ /// 4. Names prefixed with "refs/" can be almost anything. You must avoid +++ /// the characters '~', '^', ':', '\\', '?', '[', and '*', and the +++ /// sequences ".." and "@{" which have special meaning to revparse. +++ /// +++ /// If the reference passes validation, it is returned in normalized form, +++ /// otherwise an [`Error`] with [`ErrorCode::InvalidSpec`] is returned. +++ /// +++ /// ```rust +++ /// use git2::{Reference, ReferenceFormat}; +++ /// +++ /// assert_eq!( +++ /// Reference::normalize_name( +++ /// "foo//bar", +++ /// ReferenceFormat::NORMAL +++ /// ) +++ /// .unwrap(), +++ /// "foo/bar".to_owned() +++ /// ); +++ /// +++ /// assert_eq!( +++ /// Reference::normalize_name( +++ /// "HEAD", +++ /// ReferenceFormat::ALLOW_ONELEVEL +++ /// ) +++ /// .unwrap(), +++ /// "HEAD".to_owned() +++ /// ); +++ /// +++ /// assert_eq!( +++ /// Reference::normalize_name( +++ /// "refs/heads/*", +++ /// ReferenceFormat::REFSPEC_PATTERN +++ /// ) +++ /// .unwrap(), +++ /// "refs/heads/*".to_owned() +++ /// ); +++ /// +++ /// assert_eq!( +++ /// Reference::normalize_name( +++ /// "main", +++ /// ReferenceFormat::ALLOW_ONELEVEL | ReferenceFormat::REFSPEC_SHORTHAND +++ /// ) +++ /// .unwrap(), +++ /// "main".to_owned() +++ /// ); +++ /// ``` +++ /// +++ /// [`ReferenceFormat::ALLOW_ONELEVEL`]: +++ /// struct.ReferenceFormat#associatedconstant.ALLOW_ONELEVEL +++ /// [`ReferenceFormat::REFSPEC_SHORTHAND`]: +++ /// struct.ReferenceFormat#associatedconstant.REFSPEC_SHORTHAND +++ /// [`ReferenceFormat::REFSPEC_PATTERN`]: +++ /// struct.ReferenceFormat#associatedconstant.REFSPEC_PATTERN +++ /// [`Error`]: struct.Error +++ /// [`ErrorCode::InvalidSpec`]: enum.ErrorCode#variant.InvalidSpec +++ pub fn normalize_name(refname: &str, flags: ReferenceFormat) -> Result { +++ crate::init(); +++ let mut dst = [0u8; GIT_REFNAME_MAX]; +++ let refname = CString::new(refname)?; +++ unsafe { +++ try_call!(raw::git_reference_normalize_name( +++ dst.as_mut_ptr() as *mut libc::c_char, +++ dst.len() as libc::size_t, +++ refname, +++ flags.bits() +++ )); +++ let s = &dst[..dst.iter().position(|&a| a == 0).unwrap()]; +++ Ok(str::from_utf8(s).unwrap().to_owned()) +++ } +++ } +++ +++ /// Get access to the underlying raw pointer. +++ pub fn raw(&self) -> *mut raw::git_reference { +++ self.raw +++ } +++ +++ /// Delete an existing reference. +++ /// +++ /// This method works for both direct and symbolic references. The reference +++ /// will be immediately removed on disk. +++ /// +++ /// This function will return an error if the reference has changed from the +++ /// time it was looked up. +++ pub fn delete(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_reference_delete(self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Check if a reference is a local branch. +++ pub fn is_branch(&self) -> bool { +++ unsafe { raw::git_reference_is_branch(&*self.raw) == 1 } +++ } +++ +++ /// Check if a reference is a note. +++ pub fn is_note(&self) -> bool { +++ unsafe { raw::git_reference_is_note(&*self.raw) == 1 } +++ } +++ +++ /// Check if a reference is a remote tracking branch +++ pub fn is_remote(&self) -> bool { +++ unsafe { raw::git_reference_is_remote(&*self.raw) == 1 } +++ } +++ +++ /// Check if a reference is a tag +++ pub fn is_tag(&self) -> bool { +++ unsafe { raw::git_reference_is_tag(&*self.raw) == 1 } +++ } +++ +++ /// Get the reference type of a reference. +++ /// +++ /// If the type is unknown, then `None` is returned. +++ pub fn kind(&self) -> Option { +++ ReferenceType::from_raw(unsafe { raw::git_reference_type(&*self.raw) }) +++ } +++ +++ /// Get the full name of a reference. +++ /// +++ /// Returns `None` if the name is not valid utf-8. +++ pub fn name(&self) -> Option<&str> { +++ str::from_utf8(self.name_bytes()).ok() +++ } +++ +++ /// Get the full name of a reference. +++ pub fn name_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, raw::git_reference_name(&*self.raw)).unwrap() } +++ } +++ +++ /// Get the full shorthand of a reference. +++ /// +++ /// This will transform the reference name into a name "human-readable" +++ /// version. If no shortname is appropriate, it will return the full name. +++ /// +++ /// Returns `None` if the shorthand is not valid utf-8. +++ pub fn shorthand(&self) -> Option<&str> { +++ str::from_utf8(self.shorthand_bytes()).ok() +++ } +++ +++ /// Get the full shorthand of a reference. +++ pub fn shorthand_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, raw::git_reference_shorthand(&*self.raw)).unwrap() } +++ } +++ +++ /// Get the OID pointed to by a direct reference. +++ /// +++ /// Only available if the reference is direct (i.e. an object id reference, +++ /// not a symbolic one). +++ pub fn target(&self) -> Option { +++ unsafe { Binding::from_raw_opt(raw::git_reference_target(&*self.raw)) } +++ } +++ +++ /// Return the peeled OID target of this reference. +++ /// +++ /// This peeled OID only applies to direct references that point to a hard +++ /// Tag object: it is the result of peeling such Tag. +++ pub fn target_peel(&self) -> Option { +++ unsafe { Binding::from_raw_opt(raw::git_reference_target_peel(&*self.raw)) } +++ } +++ +++ /// Get full name to the reference pointed to by a symbolic reference. +++ /// +++ /// May return `None` if the reference is either not symbolic or not a +++ /// valid utf-8 string. +++ pub fn symbolic_target(&self) -> Option<&str> { +++ self.symbolic_target_bytes() +++ .and_then(|s| str::from_utf8(s).ok()) +++ } +++ +++ /// Get full name to the reference pointed to by a symbolic reference. +++ /// +++ /// Only available if the reference is symbolic. +++ pub fn symbolic_target_bytes(&self) -> Option<&[u8]> { +++ unsafe { crate::opt_bytes(self, raw::git_reference_symbolic_target(&*self.raw)) } +++ } +++ +++ /// Resolve a symbolic reference to a direct reference. +++ /// +++ /// This method iteratively peels a symbolic reference until it resolves to +++ /// a direct reference to an OID. +++ /// +++ /// If a direct reference is passed as an argument, a copy of that +++ /// reference is returned. +++ pub fn resolve(&self) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_reference_resolve(&mut raw, &*self.raw)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Peel a reference to an object +++ /// +++ /// This method recursively peels the reference until it reaches +++ /// an object of the specified type. +++ pub fn peel(&self, kind: ObjectType) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_reference_peel(&mut raw, self.raw, kind)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Peel a reference to a blob +++ /// +++ /// This method recursively peels the reference until it reaches +++ /// a blob. +++ pub fn peel_to_blob(&self) -> Result, Error> { +++ Ok(self.peel(ObjectType::Blob)?.cast_or_panic(ObjectType::Blob)) +++ } +++ +++ /// Peel a reference to a commit +++ /// +++ /// This method recursively peels the reference until it reaches +++ /// a commit. +++ pub fn peel_to_commit(&self) -> Result, Error> { +++ Ok(self +++ .peel(ObjectType::Commit)? +++ .cast_or_panic(ObjectType::Commit)) +++ } +++ +++ /// Peel a reference to a tree +++ /// +++ /// This method recursively peels the reference until it reaches +++ /// a tree. +++ pub fn peel_to_tree(&self) -> Result, Error> { +++ Ok(self.peel(ObjectType::Tree)?.cast_or_panic(ObjectType::Tree)) +++ } +++ +++ /// Peel a reference to a tag +++ /// +++ /// This method recursively peels the reference until it reaches +++ /// a tag. +++ pub fn peel_to_tag(&self) -> Result, Error> { +++ Ok(self.peel(ObjectType::Tag)?.cast_or_panic(ObjectType::Tag)) +++ } +++ +++ /// Rename an existing reference. +++ /// +++ /// This method works for both direct and symbolic references. +++ /// +++ /// If the force flag is not enabled, and there's already a reference with +++ /// the given name, the renaming will fail. +++ pub fn rename( +++ &mut self, +++ new_name: &str, +++ force: bool, +++ msg: &str, +++ ) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ let new_name = CString::new(new_name)?; +++ let msg = CString::new(msg)?; +++ unsafe { +++ try_call!(raw::git_reference_rename( +++ &mut raw, self.raw, new_name, force, msg +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Conditionally create a new reference with the same name as the given +++ /// reference but a different OID target. The reference must be a direct +++ /// reference, otherwise this will fail. +++ /// +++ /// The new reference will be written to disk, overwriting the given +++ /// reference. +++ pub fn set_target(&mut self, id: Oid, reflog_msg: &str) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ let msg = CString::new(reflog_msg)?; +++ unsafe { +++ try_call!(raw::git_reference_set_target( +++ &mut raw, +++ self.raw, +++ id.raw(), +++ msg +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Create a new reference with the same name as the given reference but a +++ /// different symbolic target. The reference must be a symbolic reference, +++ /// otherwise this will fail. +++ /// +++ /// The new reference will be written to disk, overwriting the given +++ /// reference. +++ /// +++ /// The target name will be checked for validity. See +++ /// [`Repository::reference_symbolic`] for rules about valid names. +++ /// +++ /// The message for the reflog will be ignored if the reference does not +++ /// belong in the standard set (HEAD, branches and remote-tracking +++ /// branches) and it does not have a reflog. +++ pub fn symbolic_set_target( +++ &mut self, +++ target: &str, +++ reflog_msg: &str, +++ ) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ let target = CString::new(target)?; +++ let msg = CString::new(reflog_msg)?; +++ unsafe { +++ try_call!(raw::git_reference_symbolic_set_target( +++ &mut raw, self.raw, target, msg +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++} +++ +++impl<'repo> PartialOrd for Reference<'repo> { +++ fn partial_cmp(&self, other: &Reference<'repo>) -> Option { +++ Some(self.cmp(other)) +++ } +++} +++ +++impl<'repo> Ord for Reference<'repo> { +++ fn cmp(&self, other: &Reference<'repo>) -> Ordering { +++ c_cmp_to_ordering(unsafe { raw::git_reference_cmp(&*self.raw, &*other.raw) }) +++ } +++} +++ +++impl<'repo> PartialEq for Reference<'repo> { +++ fn eq(&self, other: &Reference<'repo>) -> bool { +++ self.cmp(other) == Ordering::Equal +++ } +++} +++ +++impl<'repo> Eq for Reference<'repo> {} +++ +++impl<'repo> Binding for Reference<'repo> { +++ type Raw = *mut raw::git_reference; +++ unsafe fn from_raw(raw: *mut raw::git_reference) -> Reference<'repo> { +++ Reference { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_reference { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for Reference<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_reference_free(self.raw) } +++ } +++} +++ +++impl<'repo> References<'repo> { +++ /// Consumes a `References` iterator to create an iterator over just the +++ /// name of some references. +++ /// +++ /// This is more efficient if only the names are desired of references as +++ /// the references themselves don't have to be allocated and deallocated. +++ /// +++ /// The returned iterator will yield strings as opposed to a `Reference`. +++ pub fn names<'a>(&'a mut self) -> ReferenceNames<'repo, 'a> { +++ ReferenceNames { inner: self } +++ } +++} +++ +++impl<'repo> Binding for References<'repo> { +++ type Raw = *mut raw::git_reference_iterator; +++ unsafe fn from_raw(raw: *mut raw::git_reference_iterator) -> References<'repo> { +++ References { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_reference_iterator { +++ self.raw +++ } +++} +++ +++impl<'repo> Iterator for References<'repo> { +++ type Item = Result, Error>; +++ fn next(&mut self) -> Option, Error>> { +++ let mut out = ptr::null_mut(); +++ unsafe { +++ try_call_iter!(raw::git_reference_next(&mut out, self.raw)); +++ Some(Ok(Binding::from_raw(out))) +++ } +++ } +++} +++ +++impl<'repo> Drop for References<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_reference_iterator_free(self.raw) } +++ } +++} +++ +++impl<'repo, 'references> Iterator for ReferenceNames<'repo, 'references> { +++ type Item = Result<&'references str, Error>; +++ fn next(&mut self) -> Option> { +++ let mut out = ptr::null(); +++ unsafe { +++ try_call_iter!(raw::git_reference_next_name(&mut out, self.inner.raw)); +++ let bytes = crate::opt_bytes(self, out).unwrap(); +++ let s = str::from_utf8(bytes).unwrap(); +++ Some(Ok(mem::transmute::<&str, &'references str>(s))) +++ } +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::{ObjectType, Reference, ReferenceType}; +++ +++ #[test] +++ fn is_valid_name() { +++ assert!(Reference::is_valid_name("refs/foo")); +++ assert!(!Reference::is_valid_name("foo")); +++ assert!(Reference::is_valid_name("FOO_BAR")); +++ +++ assert!(!Reference::is_valid_name("foo")); +++ assert!(!Reference::is_valid_name("_FOO_BAR")); +++ } +++ +++ #[test] +++ #[should_panic] +++ fn is_valid_name_for_invalid_ref() { +++ Reference::is_valid_name("ab\012"); +++ } +++ +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut head = repo.head().unwrap(); +++ assert!(head.is_branch()); +++ assert!(!head.is_remote()); +++ assert!(!head.is_tag()); +++ assert!(!head.is_note()); +++ +++ // HEAD is a symbolic reference but git_repository_head resolves it +++ // so it is a GIT_REFERENCE_DIRECT. +++ assert_eq!(head.kind().unwrap(), ReferenceType::Direct); +++ +++ assert!(head == repo.head().unwrap()); +++ assert_eq!(head.name(), Some("refs/heads/main")); +++ +++ assert!(head == repo.find_reference("refs/heads/main").unwrap()); +++ assert_eq!( +++ repo.refname_to_id("refs/heads/main").unwrap(), +++ head.target().unwrap() +++ ); +++ +++ assert!(head.symbolic_target().is_none()); +++ assert!(head.target_peel().is_none()); +++ +++ assert_eq!(head.shorthand(), Some("main")); +++ assert!(head.resolve().unwrap() == head); +++ +++ let mut tag1 = repo +++ .reference("refs/tags/tag1", head.target().unwrap(), false, "test") +++ .unwrap(); +++ assert!(tag1.is_tag()); +++ assert_eq!(tag1.kind().unwrap(), ReferenceType::Direct); +++ +++ let peeled_commit = tag1.peel(ObjectType::Commit).unwrap(); +++ assert_eq!(ObjectType::Commit, peeled_commit.kind().unwrap()); +++ assert_eq!(tag1.target().unwrap(), peeled_commit.id()); +++ +++ tag1.delete().unwrap(); +++ +++ let mut sym1 = repo +++ .reference_symbolic("refs/tags/tag1", "refs/heads/main", false, "test") +++ .unwrap(); +++ assert_eq!(sym1.kind().unwrap(), ReferenceType::Symbolic); +++ let mut sym2 = repo +++ .reference_symbolic("refs/tags/tag2", "refs/heads/main", false, "test") +++ .unwrap() +++ .symbolic_set_target("refs/tags/tag1", "test") +++ .unwrap(); +++ assert_eq!(sym2.kind().unwrap(), ReferenceType::Symbolic); +++ assert_eq!(sym2.symbolic_target().unwrap(), "refs/tags/tag1"); +++ sym2.delete().unwrap(); +++ sym1.delete().unwrap(); +++ +++ { +++ assert!(repo.references().unwrap().count() == 1); +++ assert!(repo.references().unwrap().next().unwrap().unwrap() == head); +++ let mut names = repo.references().unwrap(); +++ let mut names = names.names(); +++ assert_eq!(names.next().unwrap().unwrap(), "refs/heads/main"); +++ assert!(names.next().is_none()); +++ assert!(repo.references_glob("foo").unwrap().count() == 0); +++ assert!(repo.references_glob("refs/heads/*").unwrap().count() == 1); +++ } +++ +++ let mut head = head.rename("refs/foo", true, "test").unwrap(); +++ head.delete().unwrap(); +++ } +++} diff --cc extra/git2/src/reflog.rs index 0000000000,0000000000,0000000000..bbd2140ab2 new file mode 100644 --- /dev/null +++ b/extra/git2/src/reflog.rs @@@@ -1,0 -1,0 -1,0 +1,196 @@@@ +++use libc::size_t; +++use std::iter::FusedIterator; +++use std::marker; +++use std::ops::Range; +++use std::str; +++ +++use crate::util::Binding; +++use crate::{raw, signature, Error, Oid, Signature}; +++ +++/// A reference log of a git repository. +++pub struct Reflog { +++ raw: *mut raw::git_reflog, +++} +++ +++/// An entry inside the reflog of a repository +++pub struct ReflogEntry<'reflog> { +++ raw: *const raw::git_reflog_entry, +++ _marker: marker::PhantomData<&'reflog Reflog>, +++} +++ +++/// An iterator over the entries inside of a reflog. +++pub struct ReflogIter<'reflog> { +++ range: Range, +++ reflog: &'reflog Reflog, +++} +++ +++impl Reflog { +++ /// Add a new entry to the in-memory reflog. +++ pub fn append( +++ &mut self, +++ new_oid: Oid, +++ committer: &Signature<'_>, +++ msg: Option<&str>, +++ ) -> Result<(), Error> { +++ let msg = crate::opt_cstr(msg)?; +++ unsafe { +++ try_call!(raw::git_reflog_append( +++ self.raw, +++ new_oid.raw(), +++ committer.raw(), +++ msg +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Remove an entry from the reflog by its index +++ /// +++ /// To ensure there's no gap in the log history, set rewrite_previous_entry +++ /// param value to `true`. When deleting entry n, member old_oid of entry +++ /// n-1 (if any) will be updated with the value of member new_oid of entry +++ /// n+1. +++ pub fn remove(&mut self, i: usize, rewrite_previous_entry: bool) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_reflog_drop( +++ self.raw, +++ i as size_t, +++ rewrite_previous_entry +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Lookup an entry by its index +++ /// +++ /// Requesting the reflog entry with an index of 0 (zero) will return the +++ /// most recently created entry. +++ pub fn get(&self, i: usize) -> Option> { +++ unsafe { +++ let ptr = raw::git_reflog_entry_byindex(self.raw, i as size_t); +++ Binding::from_raw_opt(ptr) +++ } +++ } +++ +++ /// Get the number of log entries in a reflog +++ pub fn len(&self) -> usize { +++ unsafe { raw::git_reflog_entrycount(self.raw) as usize } +++ } +++ +++ /// Return `true ` is there is no log entry in a reflog +++ pub fn is_empty(&self) -> bool { +++ self.len() == 0 +++ } +++ +++ /// Get an iterator to all entries inside of this reflog +++ pub fn iter(&self) -> ReflogIter<'_> { +++ ReflogIter { +++ range: 0..self.len(), +++ reflog: self, +++ } +++ } +++ +++ /// Write an existing in-memory reflog object back to disk using an atomic +++ /// file lock. +++ pub fn write(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_reflog_write(self.raw)); +++ } +++ Ok(()) +++ } +++} +++ +++impl Binding for Reflog { +++ type Raw = *mut raw::git_reflog; +++ +++ unsafe fn from_raw(raw: *mut raw::git_reflog) -> Reflog { +++ Reflog { raw } +++ } +++ fn raw(&self) -> *mut raw::git_reflog { +++ self.raw +++ } +++} +++ +++impl Drop for Reflog { +++ fn drop(&mut self) { +++ unsafe { raw::git_reflog_free(self.raw) } +++ } +++} +++ +++impl<'reflog> ReflogEntry<'reflog> { +++ /// Get the committer of this entry +++ pub fn committer(&self) -> Signature<'_> { +++ unsafe { +++ let ptr = raw::git_reflog_entry_committer(self.raw); +++ signature::from_raw_const(self, ptr) +++ } +++ } +++ +++ /// Get the new oid +++ pub fn id_new(&self) -> Oid { +++ unsafe { Binding::from_raw(raw::git_reflog_entry_id_new(self.raw)) } +++ } +++ +++ /// Get the old oid +++ pub fn id_old(&self) -> Oid { +++ unsafe { Binding::from_raw(raw::git_reflog_entry_id_old(self.raw)) } +++ } +++ +++ /// Get the log message, returning `None` on invalid UTF-8. +++ pub fn message(&self) -> Option<&str> { +++ self.message_bytes().and_then(|s| str::from_utf8(s).ok()) +++ } +++ +++ /// Get the log message as a byte array. +++ pub fn message_bytes(&self) -> Option<&[u8]> { +++ unsafe { crate::opt_bytes(self, raw::git_reflog_entry_message(self.raw)) } +++ } +++} +++ +++impl<'reflog> Binding for ReflogEntry<'reflog> { +++ type Raw = *const raw::git_reflog_entry; +++ +++ unsafe fn from_raw(raw: *const raw::git_reflog_entry) -> ReflogEntry<'reflog> { +++ ReflogEntry { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *const raw::git_reflog_entry { +++ self.raw +++ } +++} +++ +++impl<'reflog> Iterator for ReflogIter<'reflog> { +++ type Item = ReflogEntry<'reflog>; +++ fn next(&mut self) -> Option> { +++ self.range.next().and_then(|i| self.reflog.get(i)) +++ } +++ fn size_hint(&self) -> (usize, Option) { +++ self.range.size_hint() +++ } +++} +++impl<'reflog> DoubleEndedIterator for ReflogIter<'reflog> { +++ fn next_back(&mut self) -> Option> { +++ self.range.next_back().and_then(|i| self.reflog.get(i)) +++ } +++} +++impl<'reflog> FusedIterator for ReflogIter<'reflog> {} +++impl<'reflog> ExactSizeIterator for ReflogIter<'reflog> {} +++ +++#[cfg(test)] +++mod tests { +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ let mut reflog = repo.reflog("HEAD").unwrap(); +++ assert_eq!(reflog.iter().len(), 1); +++ reflog.write().unwrap(); +++ +++ let entry = reflog.iter().next().unwrap(); +++ assert!(entry.message().is_some()); +++ +++ repo.reflog_rename("HEAD", "refs/heads/foo").unwrap(); +++ repo.reflog_delete("refs/heads/foo").unwrap(); +++ } +++} diff --cc extra/git2/src/refspec.rs index 0000000000,0000000000,0000000000..3f62e991c7 new file mode 100644 --- /dev/null +++ b/extra/git2/src/refspec.rs @@@@ -1,0 -1,0 -1,0 +1,122 @@@@ +++use std::ffi::CString; +++use std::marker; +++use std::str; +++ +++use crate::util::Binding; +++use crate::{raw, Buf, Direction, Error}; +++ +++/// A structure to represent a git [refspec][1]. +++/// +++/// Refspecs are currently mainly accessed/created through a `Remote`. +++/// +++/// [1]: http://git-scm.com/book/en/Git-Internals-The-Refspec +++pub struct Refspec<'remote> { +++ raw: *const raw::git_refspec, +++ _marker: marker::PhantomData<&'remote raw::git_remote>, +++} +++ +++impl<'remote> Refspec<'remote> { +++ /// Get the refspec's direction. +++ pub fn direction(&self) -> Direction { +++ match unsafe { raw::git_refspec_direction(self.raw) } { +++ raw::GIT_DIRECTION_FETCH => Direction::Fetch, +++ raw::GIT_DIRECTION_PUSH => Direction::Push, +++ n => panic!("unknown refspec direction: {}", n), +++ } +++ } +++ +++ /// Get the destination specifier. +++ /// +++ /// If the destination is not utf-8, None is returned. +++ pub fn dst(&self) -> Option<&str> { +++ str::from_utf8(self.dst_bytes()).ok() +++ } +++ +++ /// Get the destination specifier, in bytes. +++ pub fn dst_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, raw::git_refspec_dst(self.raw)).unwrap() } +++ } +++ +++ /// Check if a refspec's destination descriptor matches a reference +++ pub fn dst_matches(&self, refname: &str) -> bool { +++ let refname = CString::new(refname).unwrap(); +++ unsafe { raw::git_refspec_dst_matches(self.raw, refname.as_ptr()) == 1 } +++ } +++ +++ /// Get the source specifier. +++ /// +++ /// If the source is not utf-8, None is returned. +++ pub fn src(&self) -> Option<&str> { +++ str::from_utf8(self.src_bytes()).ok() +++ } +++ +++ /// Get the source specifier, in bytes. +++ pub fn src_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, raw::git_refspec_src(self.raw)).unwrap() } +++ } +++ +++ /// Check if a refspec's source descriptor matches a reference +++ pub fn src_matches(&self, refname: &str) -> bool { +++ let refname = CString::new(refname).unwrap(); +++ unsafe { raw::git_refspec_src_matches(self.raw, refname.as_ptr()) == 1 } +++ } +++ +++ /// Get the force update setting. +++ pub fn is_force(&self) -> bool { +++ unsafe { raw::git_refspec_force(self.raw) == 1 } +++ } +++ +++ /// Get the refspec's string. +++ /// +++ /// Returns None if the string is not valid utf8. +++ pub fn str(&self) -> Option<&str> { +++ str::from_utf8(self.bytes()).ok() +++ } +++ +++ /// Get the refspec's string as a byte array +++ pub fn bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, raw::git_refspec_string(self.raw)).unwrap() } +++ } +++ +++ /// Transform a reference to its target following the refspec's rules +++ pub fn transform(&self, name: &str) -> Result { +++ let name = CString::new(name).unwrap(); +++ unsafe { +++ let buf = Buf::new(); +++ try_call!(raw::git_refspec_transform( +++ buf.raw(), +++ self.raw, +++ name.as_ptr() +++ )); +++ Ok(buf) +++ } +++ } +++ +++ /// Transform a target reference to its source reference following the refspec's rules +++ pub fn rtransform(&self, name: &str) -> Result { +++ let name = CString::new(name).unwrap(); +++ unsafe { +++ let buf = Buf::new(); +++ try_call!(raw::git_refspec_rtransform( +++ buf.raw(), +++ self.raw, +++ name.as_ptr() +++ )); +++ Ok(buf) +++ } +++ } +++} +++ +++impl<'remote> Binding for Refspec<'remote> { +++ type Raw = *const raw::git_refspec; +++ +++ unsafe fn from_raw(raw: *const raw::git_refspec) -> Refspec<'remote> { +++ Refspec { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *const raw::git_refspec { +++ self.raw +++ } +++} diff --cc extra/git2/src/remote.rs index 0000000000,0000000000,0000000000..13c275ae2e new file mode 100644 --- /dev/null +++ b/extra/git2/src/remote.rs @@@@ -1,0 -1,0 -1,0 +1,1168 @@@@ +++use raw::git_strarray; +++use std::iter::FusedIterator; +++use std::marker; +++use std::mem; +++use std::ops::Range; +++use std::os::raw::c_uint; +++use std::ptr; +++use std::slice; +++use std::str; +++use std::{ffi::CString, os::raw::c_char}; +++ +++use crate::string_array::StringArray; +++use crate::util::Binding; +++use crate::{call, raw, Buf, Direction, Error, FetchPrune, Oid, ProxyOptions, Refspec}; +++use crate::{AutotagOption, Progress, RemoteCallbacks, RemoteUpdateFlags, Repository}; +++ +++/// A structure representing a [remote][1] of a git repository. +++/// +++/// [1]: http://git-scm.com/book/en/Git-Basics-Working-with-Remotes +++/// +++/// The lifetime is the lifetime of the repository that it is attached to. The +++/// remote is used to manage fetches and pushes as well as refspecs. +++pub struct Remote<'repo> { +++ raw: *mut raw::git_remote, +++ _marker: marker::PhantomData<&'repo Repository>, +++} +++ +++/// An iterator over the refspecs that a remote contains. +++pub struct Refspecs<'remote> { +++ range: Range, +++ remote: &'remote Remote<'remote>, +++} +++ +++/// Description of a reference advertised by a remote server, given out on calls +++/// to `list`. +++pub struct RemoteHead<'remote> { +++ raw: *const raw::git_remote_head, +++ _marker: marker::PhantomData<&'remote str>, +++} +++ +++/// Options which can be specified to various fetch operations. +++pub struct FetchOptions<'cb> { +++ callbacks: Option>, +++ depth: i32, +++ proxy: Option>, +++ prune: FetchPrune, +++ update_flags: RemoteUpdateFlags, +++ download_tags: AutotagOption, +++ follow_redirects: RemoteRedirect, +++ custom_headers: Vec, +++ custom_headers_ptrs: Vec<*const c_char>, +++} +++ +++/// Options to control the behavior of a git push. +++pub struct PushOptions<'cb> { +++ callbacks: Option>, +++ proxy: Option>, +++ pb_parallelism: u32, +++ follow_redirects: RemoteRedirect, +++ custom_headers: Vec, +++ custom_headers_ptrs: Vec<*const c_char>, +++ remote_push_options: Vec, +++ remote_push_options_ptrs: Vec<*const c_char>, +++} +++ +++/// Holds callbacks for a connection to a `Remote`. Disconnects when dropped +++pub struct RemoteConnection<'repo, 'connection, 'cb> { +++ _callbacks: Box>, +++ _proxy: ProxyOptions<'cb>, +++ remote: &'connection mut Remote<'repo>, +++} +++ +++/// Remote redirection settings; whether redirects to another host are +++/// permitted. +++/// +++/// By default, git will follow a redirect on the initial request +++/// (`/info/refs`), but not subsequent requests. +++pub enum RemoteRedirect { +++ /// Do not follow any off-site redirects at any stage of the fetch or push. +++ None, +++ /// Allow off-site redirects only upon the initial request. This is the +++ /// default. +++ Initial, +++ /// Allow redirects at any stage in the fetch or push. +++ All, +++} +++ +++pub fn remote_into_raw(remote: Remote<'_>) -> *mut raw::git_remote { +++ let ret = remote.raw; +++ mem::forget(remote); +++ ret +++} +++ +++impl<'repo> Remote<'repo> { +++ /// Ensure the remote name is well-formed. +++ pub fn is_valid_name(remote_name: &str) -> bool { +++ crate::init(); +++ let remote_name = CString::new(remote_name).unwrap(); +++ let mut valid: libc::c_int = 0; +++ unsafe { +++ call::c_try(raw::git_remote_name_is_valid( +++ &mut valid, +++ remote_name.as_ptr(), +++ )) +++ .unwrap(); +++ } +++ valid == 1 +++ } +++ +++ /// Create a detached remote +++ /// +++ /// Create a remote with the given URL in-memory. You can use this +++ /// when you have a URL instead of a remote's name. +++ /// Contrasted with an anonymous remote, a detached remote will not +++ /// consider any repo configuration values. +++ pub fn create_detached>>(url: S) -> Result, Error> { +++ crate::init(); +++ let mut ret = ptr::null_mut(); +++ let url = CString::new(url)?; +++ unsafe { +++ try_call!(raw::git_remote_create_detached(&mut ret, url)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Get the remote's name. +++ /// +++ /// Returns `None` if this remote has not yet been named or if the name is +++ /// not valid utf-8 +++ pub fn name(&self) -> Option<&str> { +++ self.name_bytes().and_then(|s| str::from_utf8(s).ok()) +++ } +++ +++ /// Get the remote's name, in bytes. +++ /// +++ /// Returns `None` if this remote has not yet been named +++ pub fn name_bytes(&self) -> Option<&[u8]> { +++ unsafe { crate::opt_bytes(self, raw::git_remote_name(&*self.raw)) } +++ } +++ +++ /// Get the remote's URL. +++ /// +++ /// Returns `None` if the URL is not valid utf-8 +++ pub fn url(&self) -> Option<&str> { +++ str::from_utf8(self.url_bytes()).ok() +++ } +++ +++ /// Get the remote's URL as a byte array. +++ pub fn url_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, raw::git_remote_url(&*self.raw)).unwrap() } +++ } +++ +++ /// Get the remote's pushurl. +++ /// +++ /// Returns `None` if the pushurl is not valid utf-8 +++ pub fn pushurl(&self) -> Option<&str> { +++ self.pushurl_bytes().and_then(|s| str::from_utf8(s).ok()) +++ } +++ +++ /// Get the remote's pushurl as a byte array. +++ pub fn pushurl_bytes(&self) -> Option<&[u8]> { +++ unsafe { crate::opt_bytes(self, raw::git_remote_pushurl(&*self.raw)) } +++ } +++ +++ /// Get the remote's default branch. +++ /// +++ /// The remote (or more exactly its transport) must have connected to the +++ /// remote repository. This default branch is available as soon as the +++ /// connection to the remote is initiated and it remains available after +++ /// disconnecting. +++ pub fn default_branch(&self) -> Result { +++ unsafe { +++ let buf = Buf::new(); +++ try_call!(raw::git_remote_default_branch(buf.raw(), self.raw)); +++ Ok(buf) +++ } +++ } +++ +++ /// Open a connection to a remote. +++ pub fn connect(&mut self, dir: Direction) -> Result<(), Error> { +++ // TODO: can callbacks be exposed safely? +++ unsafe { +++ try_call!(raw::git_remote_connect( +++ self.raw, +++ dir, +++ ptr::null(), +++ ptr::null(), +++ ptr::null() +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Open a connection to a remote with callbacks and proxy settings +++ /// +++ /// Returns a `RemoteConnection` that will disconnect once dropped +++ pub fn connect_auth<'connection, 'cb>( +++ &'connection mut self, +++ dir: Direction, +++ cb: Option>, +++ proxy_options: Option>, +++ ) -> Result, Error> { +++ let cb = Box::new(cb.unwrap_or_else(RemoteCallbacks::new)); +++ let proxy_options = proxy_options.unwrap_or_else(ProxyOptions::new); +++ unsafe { +++ try_call!(raw::git_remote_connect( +++ self.raw, +++ dir, +++ &cb.raw(), +++ &proxy_options.raw(), +++ ptr::null() +++ )); +++ } +++ +++ Ok(RemoteConnection { +++ _callbacks: cb, +++ _proxy: proxy_options, +++ remote: self, +++ }) +++ } +++ +++ /// Check whether the remote is connected +++ pub fn connected(&mut self) -> bool { +++ unsafe { raw::git_remote_connected(self.raw) == 1 } +++ } +++ +++ /// Disconnect from the remote +++ pub fn disconnect(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_remote_disconnect(self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Download and index the packfile +++ /// +++ /// Connect to the remote if it hasn't been done yet, negotiate with the +++ /// remote git which objects are missing, download and index the packfile. +++ /// +++ /// The .idx file will be created and both it and the packfile with be +++ /// renamed to their final name. +++ /// +++ /// The `specs` argument is a list of refspecs to use for this negotiation +++ /// and download. Use an empty array to use the base refspecs. +++ pub fn download + crate::IntoCString + Clone>( +++ &mut self, +++ specs: &[Str], +++ opts: Option<&mut FetchOptions<'_>>, +++ ) -> Result<(), Error> { +++ let (_a, _b, arr) = crate::util::iter2cstrs(specs.iter())?; +++ let raw = opts.map(|o| o.raw()); +++ unsafe { +++ try_call!(raw::git_remote_download(self.raw, &arr, raw.as_ref())); +++ } +++ Ok(()) +++ } +++ +++ /// Cancel the operation +++ /// +++ /// At certain points in its operation, the network code checks whether the +++ /// operation has been canceled and if so stops the operation. +++ pub fn stop(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_remote_stop(self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Get the number of refspecs for a remote +++ pub fn refspecs(&self) -> Refspecs<'_> { +++ let cnt = unsafe { raw::git_remote_refspec_count(&*self.raw) as usize }; +++ Refspecs { +++ range: 0..cnt, +++ remote: self, +++ } +++ } +++ +++ /// Get the `nth` refspec from this remote. +++ /// +++ /// The `refspecs` iterator can be used to iterate over all refspecs. +++ pub fn get_refspec(&self, i: usize) -> Option> { +++ unsafe { +++ let ptr = raw::git_remote_get_refspec(&*self.raw, i as libc::size_t); +++ Binding::from_raw_opt(ptr) +++ } +++ } +++ +++ /// Download new data and update tips +++ /// +++ /// Convenience function to connect to a remote, download the data, +++ /// disconnect and update the remote-tracking branches. +++ /// +++ /// # Examples +++ /// +++ /// Example of functionality similar to `git fetch origin main`: +++ /// +++ /// ```no_run +++ /// fn fetch_origin_main(repo: git2::Repository) -> Result<(), git2::Error> { +++ /// repo.find_remote("origin")?.fetch(&["main"], None, None) +++ /// } +++ /// +++ /// let repo = git2::Repository::discover("rust").unwrap(); +++ /// fetch_origin_main(repo).unwrap(); +++ /// ``` +++ pub fn fetch + crate::IntoCString + Clone>( +++ &mut self, +++ refspecs: &[Str], +++ opts: Option<&mut FetchOptions<'_>>, +++ reflog_msg: Option<&str>, +++ ) -> Result<(), Error> { +++ let (_a, _b, arr) = crate::util::iter2cstrs(refspecs.iter())?; +++ let msg = crate::opt_cstr(reflog_msg)?; +++ let raw = opts.map(|o| o.raw()); +++ unsafe { +++ try_call!(raw::git_remote_fetch(self.raw, &arr, raw.as_ref(), msg)); +++ } +++ Ok(()) +++ } +++ +++ /// Update the tips to the new state +++ pub fn update_tips( +++ &mut self, +++ callbacks: Option<&mut RemoteCallbacks<'_>>, +++ update_flags: RemoteUpdateFlags, +++ download_tags: AutotagOption, +++ msg: Option<&str>, +++ ) -> Result<(), Error> { +++ let msg = crate::opt_cstr(msg)?; +++ let cbs = callbacks.map(|cb| cb.raw()); +++ unsafe { +++ try_call!(raw::git_remote_update_tips( +++ self.raw, +++ cbs.as_ref(), +++ update_flags.bits() as c_uint, +++ download_tags, +++ msg +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Perform a push +++ /// +++ /// Perform all the steps for a push. If no refspecs are passed then the +++ /// configured refspecs will be used. +++ /// +++ /// Note that you'll likely want to use `RemoteCallbacks` and set +++ /// `push_update_reference` to test whether all the references were pushed +++ /// successfully. +++ pub fn push + crate::IntoCString + Clone>( +++ &mut self, +++ refspecs: &[Str], +++ opts: Option<&mut PushOptions<'_>>, +++ ) -> Result<(), Error> { +++ let (_a, _b, arr) = crate::util::iter2cstrs(refspecs.iter())?; +++ let raw = opts.map(|o| o.raw()); +++ unsafe { +++ try_call!(raw::git_remote_push(self.raw, &arr, raw.as_ref())); +++ } +++ Ok(()) +++ } +++ +++ /// Get the statistics structure that is filled in by the fetch operation. +++ pub fn stats(&self) -> Progress<'_> { +++ unsafe { Binding::from_raw(raw::git_remote_stats(self.raw)) } +++ } +++ +++ /// Get the remote repository's reference advertisement list. +++ /// +++ /// Get the list of references with which the server responds to a new +++ /// connection. +++ /// +++ /// The remote (or more exactly its transport) must have connected to the +++ /// remote repository. This list is available as soon as the connection to +++ /// the remote is initiated and it remains available after disconnecting. +++ pub fn list(&self) -> Result<&[RemoteHead<'_>], Error> { +++ let mut size = 0; +++ let mut base = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_remote_ls(&mut base, &mut size, self.raw)); +++ assert_eq!( +++ mem::size_of::>(), +++ mem::size_of::<*const raw::git_remote_head>() +++ ); +++ let slice = slice::from_raw_parts(base as *const _, size as usize); +++ Ok(mem::transmute::< +++ &[*const raw::git_remote_head], +++ &[RemoteHead<'_>], +++ >(slice)) +++ } +++ } +++ +++ /// Prune tracking refs that are no longer present on remote +++ pub fn prune(&mut self, callbacks: Option>) -> Result<(), Error> { +++ let cbs = Box::new(callbacks.unwrap_or_else(RemoteCallbacks::new)); +++ unsafe { +++ try_call!(raw::git_remote_prune(self.raw, &cbs.raw())); +++ } +++ Ok(()) +++ } +++ +++ /// Get the remote's list of fetch refspecs +++ pub fn fetch_refspecs(&self) -> Result { +++ unsafe { +++ let mut raw: raw::git_strarray = mem::zeroed(); +++ try_call!(raw::git_remote_get_fetch_refspecs(&mut raw, self.raw)); +++ Ok(StringArray::from_raw(raw)) +++ } +++ } +++ +++ /// Get the remote's list of push refspecs +++ pub fn push_refspecs(&self) -> Result { +++ unsafe { +++ let mut raw: raw::git_strarray = mem::zeroed(); +++ try_call!(raw::git_remote_get_push_refspecs(&mut raw, self.raw)); +++ Ok(StringArray::from_raw(raw)) +++ } +++ } +++} +++ +++impl<'repo> Clone for Remote<'repo> { +++ fn clone(&self) -> Remote<'repo> { +++ let mut ret = ptr::null_mut(); +++ let rc = unsafe { call!(raw::git_remote_dup(&mut ret, self.raw)) }; +++ assert_eq!(rc, 0); +++ Remote { +++ raw: ret, +++ _marker: marker::PhantomData, +++ } +++ } +++} +++ +++impl<'repo> Binding for Remote<'repo> { +++ type Raw = *mut raw::git_remote; +++ +++ unsafe fn from_raw(raw: *mut raw::git_remote) -> Remote<'repo> { +++ Remote { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_remote { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for Remote<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_remote_free(self.raw) } +++ } +++} +++ +++impl<'repo> Iterator for Refspecs<'repo> { +++ type Item = Refspec<'repo>; +++ fn next(&mut self) -> Option> { +++ self.range.next().and_then(|i| self.remote.get_refspec(i)) +++ } +++ fn size_hint(&self) -> (usize, Option) { +++ self.range.size_hint() +++ } +++} +++impl<'repo> DoubleEndedIterator for Refspecs<'repo> { +++ fn next_back(&mut self) -> Option> { +++ self.range +++ .next_back() +++ .and_then(|i| self.remote.get_refspec(i)) +++ } +++} +++impl<'repo> FusedIterator for Refspecs<'repo> {} +++impl<'repo> ExactSizeIterator for Refspecs<'repo> {} +++ +++#[allow(missing_docs)] // not documented in libgit2 :( +++impl<'remote> RemoteHead<'remote> { +++ /// Flag if this is available locally. +++ pub fn is_local(&self) -> bool { +++ unsafe { (*self.raw).local != 0 } +++ } +++ +++ pub fn oid(&self) -> Oid { +++ unsafe { Binding::from_raw(&(*self.raw).oid as *const _) } +++ } +++ pub fn loid(&self) -> Oid { +++ unsafe { Binding::from_raw(&(*self.raw).loid as *const _) } +++ } +++ +++ pub fn name(&self) -> &str { +++ let b = unsafe { crate::opt_bytes(self, (*self.raw).name).unwrap() }; +++ str::from_utf8(b).unwrap() +++ } +++ +++ pub fn symref_target(&self) -> Option<&str> { +++ let b = unsafe { crate::opt_bytes(self, (*self.raw).symref_target) }; +++ b.map(|b| str::from_utf8(b).unwrap()) +++ } +++} +++ +++impl<'cb> Default for FetchOptions<'cb> { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl<'cb> FetchOptions<'cb> { +++ /// Creates a new blank set of fetch options +++ pub fn new() -> FetchOptions<'cb> { +++ FetchOptions { +++ callbacks: None, +++ proxy: None, +++ prune: FetchPrune::Unspecified, +++ update_flags: RemoteUpdateFlags::UPDATE_FETCHHEAD, +++ download_tags: AutotagOption::Unspecified, +++ follow_redirects: RemoteRedirect::Initial, +++ custom_headers: Vec::new(), +++ custom_headers_ptrs: Vec::new(), +++ depth: 0, // Not limited depth +++ } +++ } +++ +++ /// Set the callbacks to use for the fetch operation. +++ pub fn remote_callbacks(&mut self, cbs: RemoteCallbacks<'cb>) -> &mut Self { +++ self.callbacks = Some(cbs); +++ self +++ } +++ +++ /// Set the proxy options to use for the fetch operation. +++ pub fn proxy_options(&mut self, opts: ProxyOptions<'cb>) -> &mut Self { +++ self.proxy = Some(opts); +++ self +++ } +++ +++ /// Set whether to perform a prune after the fetch. +++ pub fn prune(&mut self, prune: FetchPrune) -> &mut Self { +++ self.prune = prune; +++ self +++ } +++ +++ /// Set whether to write the results to FETCH_HEAD. +++ /// +++ /// Defaults to `true`. +++ pub fn update_fetchhead(&mut self, update: bool) -> &mut Self { +++ self.update_flags +++ .set(RemoteUpdateFlags::UPDATE_FETCHHEAD, update); +++ self +++ } +++ +++ /// Set whether to report unchanged tips in the update_tips callback. +++ /// +++ /// Defaults to `false`. +++ pub fn report_unchanged(&mut self, update: bool) -> &mut Self { +++ self.update_flags +++ .set(RemoteUpdateFlags::REPORT_UNCHANGED, update); +++ self +++ } +++ +++ /// Set fetch depth, a value less or equal to 0 is interpreted as pull +++ /// everything (effectively the same as not declaring a limit depth). +++ +++ // FIXME(blyxyas): We currently don't have a test for shallow functions +++ // because libgit2 doesn't support local shallow clones. +++ // https://github.com/rust-lang/git2-rs/pull/979#issuecomment-1716299900 +++ pub fn depth(&mut self, depth: i32) -> &mut Self { +++ self.depth = depth.max(0); +++ self +++ } +++ +++ /// Set how to behave regarding tags on the remote, such as auto-downloading +++ /// tags for objects we're downloading or downloading all of them. +++ /// +++ /// The default is to auto-follow tags. +++ pub fn download_tags(&mut self, opt: AutotagOption) -> &mut Self { +++ self.download_tags = opt; +++ self +++ } +++ +++ /// Set remote redirection settings; whether redirects to another host are +++ /// permitted. +++ /// +++ /// By default, git will follow a redirect on the initial request +++ /// (`/info/refs`), but not subsequent requests. +++ pub fn follow_redirects(&mut self, redirect: RemoteRedirect) -> &mut Self { +++ self.follow_redirects = redirect; +++ self +++ } +++ +++ /// Set extra headers for this fetch operation. +++ pub fn custom_headers(&mut self, custom_headers: &[&str]) -> &mut Self { +++ self.custom_headers = custom_headers +++ .iter() +++ .map(|&s| CString::new(s).unwrap()) +++ .collect(); +++ self.custom_headers_ptrs = self.custom_headers.iter().map(|s| s.as_ptr()).collect(); +++ self +++ } +++} +++ +++impl<'cb> Binding for FetchOptions<'cb> { +++ type Raw = raw::git_fetch_options; +++ +++ unsafe fn from_raw(_raw: raw::git_fetch_options) -> FetchOptions<'cb> { +++ panic!("unimplemented"); +++ } +++ fn raw(&self) -> raw::git_fetch_options { +++ raw::git_fetch_options { +++ version: 1, +++ callbacks: self +++ .callbacks +++ .as_ref() +++ .map(|m| m.raw()) +++ .unwrap_or_else(|| RemoteCallbacks::new().raw()), +++ proxy_opts: self +++ .proxy +++ .as_ref() +++ .map(|m| m.raw()) +++ .unwrap_or_else(|| ProxyOptions::new().raw()), +++ prune: crate::call::convert(&self.prune), +++ // `update_fetchhead` is an incorrectly named option which contains both +++ // the `UPDATE_FETCHHEAD` and `REPORT_UNCHANGED` flags. +++ // See https://github.com/libgit2/libgit2/pull/6806 +++ update_fetchhead: self.update_flags.bits() as c_uint, +++ download_tags: crate::call::convert(&self.download_tags), +++ depth: self.depth, +++ follow_redirects: self.follow_redirects.raw(), +++ custom_headers: git_strarray { +++ count: self.custom_headers_ptrs.len(), +++ strings: self.custom_headers_ptrs.as_ptr() as *mut _, +++ }, +++ } +++ } +++} +++ +++impl<'cb> Default for PushOptions<'cb> { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl<'cb> PushOptions<'cb> { +++ /// Creates a new blank set of push options +++ pub fn new() -> PushOptions<'cb> { +++ PushOptions { +++ callbacks: None, +++ proxy: None, +++ pb_parallelism: 1, +++ follow_redirects: RemoteRedirect::Initial, +++ custom_headers: Vec::new(), +++ custom_headers_ptrs: Vec::new(), +++ remote_push_options: Vec::new(), +++ remote_push_options_ptrs: Vec::new(), +++ } +++ } +++ +++ /// Set the callbacks to use for the push operation. +++ pub fn remote_callbacks(&mut self, cbs: RemoteCallbacks<'cb>) -> &mut Self { +++ self.callbacks = Some(cbs); +++ self +++ } +++ +++ /// Set the proxy options to use for the push operation. +++ pub fn proxy_options(&mut self, opts: ProxyOptions<'cb>) -> &mut Self { +++ self.proxy = Some(opts); +++ self +++ } +++ +++ /// If the transport being used to push to the remote requires the creation +++ /// of a pack file, this controls the number of worker threads used by the +++ /// packbuilder when creating that pack file to be sent to the remote. +++ /// +++ /// if set to 0 the packbuilder will auto-detect the number of threads to +++ /// create, and the default value is 1. +++ pub fn packbuilder_parallelism(&mut self, parallel: u32) -> &mut Self { +++ self.pb_parallelism = parallel; +++ self +++ } +++ +++ /// Set remote redirection settings; whether redirects to another host are +++ /// permitted. +++ /// +++ /// By default, git will follow a redirect on the initial request +++ /// (`/info/refs`), but not subsequent requests. +++ pub fn follow_redirects(&mut self, redirect: RemoteRedirect) -> &mut Self { +++ self.follow_redirects = redirect; +++ self +++ } +++ +++ /// Set extra headers for this push operation. +++ pub fn custom_headers(&mut self, custom_headers: &[&str]) -> &mut Self { +++ self.custom_headers = custom_headers +++ .iter() +++ .map(|&s| CString::new(s).unwrap()) +++ .collect(); +++ self.custom_headers_ptrs = self.custom_headers.iter().map(|s| s.as_ptr()).collect(); +++ self +++ } +++ +++ /// Set "push options" to deliver to the remote. +++ pub fn remote_push_options(&mut self, remote_push_options: &[&str]) -> &mut Self { +++ self.remote_push_options = remote_push_options +++ .iter() +++ .map(|&s| CString::new(s).unwrap()) +++ .collect(); +++ self.remote_push_options_ptrs = self +++ .remote_push_options +++ .iter() +++ .map(|s| s.as_ptr()) +++ .collect(); +++ self +++ } +++} +++ +++impl<'cb> Binding for PushOptions<'cb> { +++ type Raw = raw::git_push_options; +++ +++ unsafe fn from_raw(_raw: raw::git_push_options) -> PushOptions<'cb> { +++ panic!("unimplemented"); +++ } +++ fn raw(&self) -> raw::git_push_options { +++ raw::git_push_options { +++ version: 1, +++ callbacks: self +++ .callbacks +++ .as_ref() +++ .map(|m| m.raw()) +++ .unwrap_or_else(|| RemoteCallbacks::new().raw()), +++ proxy_opts: self +++ .proxy +++ .as_ref() +++ .map(|m| m.raw()) +++ .unwrap_or_else(|| ProxyOptions::new().raw()), +++ pb_parallelism: self.pb_parallelism as libc::c_uint, +++ follow_redirects: self.follow_redirects.raw(), +++ custom_headers: git_strarray { +++ count: self.custom_headers_ptrs.len(), +++ strings: self.custom_headers_ptrs.as_ptr() as *mut _, +++ }, +++ remote_push_options: git_strarray { +++ count: self.remote_push_options.len(), +++ strings: self.remote_push_options_ptrs.as_ptr() as *mut _, +++ }, +++ } +++ } +++} +++ +++impl<'repo, 'connection, 'cb> RemoteConnection<'repo, 'connection, 'cb> { +++ /// Check whether the remote is (still) connected +++ pub fn connected(&mut self) -> bool { +++ self.remote.connected() +++ } +++ +++ /// Get the remote repository's reference advertisement list. +++ /// +++ /// This list is available as soon as the connection to +++ /// the remote is initiated and it remains available after disconnecting. +++ pub fn list(&self) -> Result<&[RemoteHead<'_>], Error> { +++ self.remote.list() +++ } +++ +++ /// Get the remote's default branch. +++ /// +++ /// This default branch is available as soon as the connection to the remote +++ /// is initiated and it remains available after disconnecting. +++ pub fn default_branch(&self) -> Result { +++ self.remote.default_branch() +++ } +++ +++ /// access remote bound to this connection +++ pub fn remote(&mut self) -> &mut Remote<'repo> { +++ self.remote +++ } +++} +++ +++impl<'repo, 'connection, 'cb> Drop for RemoteConnection<'repo, 'connection, 'cb> { +++ fn drop(&mut self) { +++ drop(self.remote.disconnect()); +++ } +++} +++ +++impl Default for RemoteRedirect { +++ fn default() -> Self { +++ RemoteRedirect::Initial +++ } +++} +++ +++impl RemoteRedirect { +++ fn raw(&self) -> raw::git_remote_redirect_t { +++ match self { +++ RemoteRedirect::None => raw::GIT_REMOTE_REDIRECT_NONE, +++ RemoteRedirect::Initial => raw::GIT_REMOTE_REDIRECT_INITIAL, +++ RemoteRedirect::All => raw::GIT_REMOTE_REDIRECT_ALL, +++ } +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::{AutotagOption, PushOptions, RemoteUpdateFlags}; +++ use crate::{Direction, FetchOptions, Remote, RemoteCallbacks, Repository}; +++ use std::cell::Cell; +++ use tempfile::TempDir; +++ +++ #[test] +++ fn smoke() { +++ let (td, repo) = crate::test::repo_init(); +++ t!(repo.remote("origin", "/path/to/nowhere")); +++ drop(repo); +++ +++ let repo = t!(Repository::init(td.path())); +++ let mut origin = t!(repo.find_remote("origin")); +++ assert_eq!(origin.name(), Some("origin")); +++ assert_eq!(origin.url(), Some("/path/to/nowhere")); +++ assert_eq!(origin.pushurl(), None); +++ +++ t!(repo.remote_set_url("origin", "/path/to/elsewhere")); +++ t!(repo.remote_set_pushurl("origin", Some("/path/to/elsewhere"))); +++ +++ let stats = origin.stats(); +++ assert_eq!(stats.total_objects(), 0); +++ +++ t!(origin.stop()); +++ } +++ +++ #[test] +++ fn create_remote() { +++ let td = TempDir::new().unwrap(); +++ let remote = td.path().join("remote"); +++ Repository::init_bare(&remote).unwrap(); +++ +++ let (_td, repo) = crate::test::repo_init(); +++ let url = if cfg!(unix) { +++ format!("file://{}", remote.display()) +++ } else { +++ format!( +++ "file:///{}", +++ remote.display().to_string().replace("\\", "/") +++ ) +++ }; +++ +++ let mut origin = repo.remote("origin", &url).unwrap(); +++ assert_eq!(origin.name(), Some("origin")); +++ assert_eq!(origin.url(), Some(&url[..])); +++ assert_eq!(origin.pushurl(), None); +++ +++ { +++ let mut specs = origin.refspecs(); +++ let spec = specs.next().unwrap(); +++ assert!(specs.next().is_none()); +++ assert_eq!(spec.str(), Some("+refs/heads/*:refs/remotes/origin/*")); +++ assert_eq!(spec.dst(), Some("refs/remotes/origin/*")); +++ assert_eq!(spec.src(), Some("refs/heads/*")); +++ assert!(spec.is_force()); +++ } +++ assert!(origin.refspecs().next_back().is_some()); +++ { +++ let remotes = repo.remotes().unwrap(); +++ assert_eq!(remotes.len(), 1); +++ assert_eq!(remotes.get(0), Some("origin")); +++ assert_eq!(remotes.iter().count(), 1); +++ assert_eq!(remotes.iter().next().unwrap(), Some("origin")); +++ } +++ +++ origin.connect(Direction::Push).unwrap(); +++ assert!(origin.connected()); +++ origin.disconnect().unwrap(); +++ +++ origin.connect(Direction::Fetch).unwrap(); +++ assert!(origin.connected()); +++ origin.download(&[] as &[&str], None).unwrap(); +++ origin.disconnect().unwrap(); +++ +++ { +++ let mut connection = origin.connect_auth(Direction::Push, None, None).unwrap(); +++ assert!(connection.connected()); +++ } +++ assert!(!origin.connected()); +++ +++ { +++ let mut connection = origin.connect_auth(Direction::Fetch, None, None).unwrap(); +++ assert!(connection.connected()); +++ } +++ assert!(!origin.connected()); +++ +++ origin.fetch(&[] as &[&str], None, None).unwrap(); +++ origin.fetch(&[] as &[&str], None, Some("foo")).unwrap(); +++ origin +++ .update_tips( +++ None, +++ RemoteUpdateFlags::UPDATE_FETCHHEAD, +++ AutotagOption::Unspecified, +++ None, +++ ) +++ .unwrap(); +++ origin +++ .update_tips( +++ None, +++ RemoteUpdateFlags::UPDATE_FETCHHEAD, +++ AutotagOption::All, +++ Some("foo"), +++ ) +++ .unwrap(); +++ +++ t!(repo.remote_add_fetch("origin", "foo")); +++ t!(repo.remote_add_fetch("origin", "bar")); +++ } +++ +++ #[test] +++ fn rename_remote() { +++ let (_td, repo) = crate::test::repo_init(); +++ repo.remote("origin", "foo").unwrap(); +++ drop(repo.remote_rename("origin", "foo")); +++ drop(repo.remote_delete("foo")); +++ } +++ +++ #[test] +++ fn create_remote_anonymous() { +++ let td = TempDir::new().unwrap(); +++ let repo = Repository::init(td.path()).unwrap(); +++ +++ let origin = repo.remote_anonymous("/path/to/nowhere").unwrap(); +++ assert_eq!(origin.name(), None); +++ drop(origin.clone()); +++ } +++ +++ #[test] +++ fn is_valid_name() { +++ assert!(Remote::is_valid_name("foobar")); +++ assert!(!Remote::is_valid_name("\x01")); +++ } +++ +++ #[test] +++ #[should_panic] +++ fn is_valid_name_for_invalid_remote() { +++ Remote::is_valid_name("ab\012"); +++ } +++ +++ #[test] +++ fn transfer_cb() { +++ let (td, _repo) = crate::test::repo_init(); +++ let td2 = TempDir::new().unwrap(); +++ let url = crate::test::path2url(&td.path()); +++ +++ let repo = Repository::init(td2.path()).unwrap(); +++ let progress_hit = Cell::new(false); +++ { +++ let mut callbacks = RemoteCallbacks::new(); +++ let mut origin = repo.remote("origin", &url).unwrap(); +++ +++ callbacks.transfer_progress(|_progress| { +++ progress_hit.set(true); +++ true +++ }); +++ origin +++ .fetch( +++ &[] as &[&str], +++ Some(FetchOptions::new().remote_callbacks(callbacks)), +++ None, +++ ) +++ .unwrap(); +++ +++ let list = t!(origin.list()); +++ assert_eq!(list.len(), 2); +++ assert_eq!(list[0].name(), "HEAD"); +++ assert!(!list[0].is_local()); +++ assert_eq!(list[1].name(), "refs/heads/main"); +++ assert!(!list[1].is_local()); +++ } +++ assert!(progress_hit.get()); +++ } +++ +++ /// This test is meant to assure that the callbacks provided to connect will not cause +++ /// segfaults +++ #[test] +++ fn connect_list() { +++ let (td, _repo) = crate::test::repo_init(); +++ let td2 = TempDir::new().unwrap(); +++ let url = crate::test::path2url(&td.path()); +++ +++ let repo = Repository::init(td2.path()).unwrap(); +++ let mut callbacks = RemoteCallbacks::new(); +++ callbacks.sideband_progress(|_progress| { +++ // no-op +++ true +++ }); +++ +++ let mut origin = repo.remote("origin", &url).unwrap(); +++ +++ { +++ let mut connection = origin +++ .connect_auth(Direction::Fetch, Some(callbacks), None) +++ .unwrap(); +++ assert!(connection.connected()); +++ +++ let list = t!(connection.list()); +++ assert_eq!(list.len(), 2); +++ assert_eq!(list[0].name(), "HEAD"); +++ assert!(!list[0].is_local()); +++ assert_eq!(list[1].name(), "refs/heads/main"); +++ assert!(!list[1].is_local()); +++ } +++ assert!(!origin.connected()); +++ } +++ +++ #[test] +++ fn push() { +++ let (_td, repo) = crate::test::repo_init(); +++ let td2 = TempDir::new().unwrap(); +++ let td3 = TempDir::new().unwrap(); +++ let url = crate::test::path2url(&td2.path()); +++ +++ let mut opts = crate::RepositoryInitOptions::new(); +++ opts.bare(true); +++ opts.initial_head("main"); +++ Repository::init_opts(td2.path(), &opts).unwrap(); +++ // git push +++ let mut remote = repo.remote("origin", &url).unwrap(); +++ let mut updated = false; +++ { +++ let mut callbacks = RemoteCallbacks::new(); +++ callbacks.push_update_reference(|refname, status| { +++ updated = true; +++ assert_eq!(refname, "refs/heads/main"); +++ assert_eq!(status, None); +++ Ok(()) +++ }); +++ let mut options = PushOptions::new(); +++ options.remote_callbacks(callbacks); +++ remote +++ .push(&["refs/heads/main"], Some(&mut options)) +++ .unwrap(); +++ } +++ assert!(updated); +++ +++ let repo = Repository::clone(&url, td3.path()).unwrap(); +++ let commit = repo.head().unwrap().target().unwrap(); +++ let commit = repo.find_commit(commit).unwrap(); +++ assert_eq!(commit.message(), Some("initial\n\nbody")); +++ } +++ +++ #[test] +++ fn prune() { +++ let (td, remote_repo) = crate::test::repo_init(); +++ let oid = remote_repo.head().unwrap().target().unwrap(); +++ let commit = remote_repo.find_commit(oid).unwrap(); +++ remote_repo.branch("stale", &commit, true).unwrap(); +++ +++ let td2 = TempDir::new().unwrap(); +++ let url = crate::test::path2url(&td.path()); +++ let repo = Repository::clone(&url, &td2).unwrap(); +++ +++ fn assert_branch_count(repo: &Repository, count: usize) { +++ assert_eq!( +++ repo.branches(Some(crate::BranchType::Remote)) +++ .unwrap() +++ .filter(|b| b.as_ref().unwrap().0.name().unwrap() == Some("origin/stale")) +++ .count(), +++ count, +++ ); +++ } +++ +++ assert_branch_count(&repo, 1); +++ +++ // delete `stale` branch on remote repo +++ let mut stale_branch = remote_repo +++ .find_branch("stale", crate::BranchType::Local) +++ .unwrap(); +++ stale_branch.delete().unwrap(); +++ +++ // prune +++ let mut remote = repo.find_remote("origin").unwrap(); +++ remote.connect(Direction::Push).unwrap(); +++ let mut callbacks = RemoteCallbacks::new(); +++ callbacks.update_tips(|refname, _a, b| { +++ assert_eq!(refname, "refs/remotes/origin/stale"); +++ assert!(b.is_zero()); +++ true +++ }); +++ remote.prune(Some(callbacks)).unwrap(); +++ assert_branch_count(&repo, 0); +++ } +++ +++ #[test] +++ fn push_negotiation() { +++ let (_td, repo) = crate::test::repo_init(); +++ let oid = repo.head().unwrap().target().unwrap(); +++ +++ let td2 = TempDir::new().unwrap(); +++ let url = crate::test::path2url(td2.path()); +++ let mut opts = crate::RepositoryInitOptions::new(); +++ opts.bare(true); +++ opts.initial_head("main"); +++ let remote_repo = Repository::init_opts(td2.path(), &opts).unwrap(); +++ +++ // reject pushing a branch +++ let mut remote = repo.remote("origin", &url).unwrap(); +++ let mut updated = false; +++ { +++ let mut callbacks = RemoteCallbacks::new(); +++ callbacks.push_negotiation(|updates| { +++ assert!(!updated); +++ updated = true; +++ assert_eq!(updates.len(), 1); +++ let u = &updates[0]; +++ assert_eq!(u.src_refname().unwrap(), "refs/heads/main"); +++ assert!(u.src().is_zero()); +++ assert_eq!(u.dst_refname().unwrap(), "refs/heads/main"); +++ assert_eq!(u.dst(), oid); +++ Err(crate::Error::from_str("rejected")) +++ }); +++ let mut options = PushOptions::new(); +++ options.remote_callbacks(callbacks); +++ assert!(remote +++ .push(&["refs/heads/main"], Some(&mut options)) +++ .is_err()); +++ } +++ assert!(updated); +++ assert_eq!(remote_repo.branches(None).unwrap().count(), 0); +++ +++ // push 3 branches +++ let commit = repo.find_commit(oid).unwrap(); +++ repo.branch("new1", &commit, true).unwrap(); +++ repo.branch("new2", &commit, true).unwrap(); +++ let mut flag = 0; +++ updated = false; +++ { +++ let mut callbacks = RemoteCallbacks::new(); +++ callbacks.push_negotiation(|updates| { +++ assert!(!updated); +++ updated = true; +++ assert_eq!(updates.len(), 3); +++ for u in updates { +++ assert!(u.src().is_zero()); +++ assert_eq!(u.dst(), oid); +++ let src_name = u.src_refname().unwrap(); +++ let dst_name = u.dst_refname().unwrap(); +++ match src_name { +++ "refs/heads/main" => { +++ assert_eq!(dst_name, src_name); +++ flag |= 1; +++ } +++ "refs/heads/new1" => { +++ assert_eq!(dst_name, "refs/heads/dev1"); +++ flag |= 2; +++ } +++ "refs/heads/new2" => { +++ assert_eq!(dst_name, "refs/heads/dev2"); +++ flag |= 4; +++ } +++ _ => panic!("unexpected refname: {}", src_name), +++ } +++ } +++ Ok(()) +++ }); +++ let mut options = PushOptions::new(); +++ options.remote_callbacks(callbacks); +++ remote +++ .push( +++ &[ +++ "refs/heads/main", +++ "refs/heads/new1:refs/heads/dev1", +++ "refs/heads/new2:refs/heads/dev2", +++ ], +++ Some(&mut options), +++ ) +++ .unwrap(); +++ } +++ assert!(updated); +++ assert_eq!(flag, 7); +++ assert_eq!(remote_repo.branches(None).unwrap().count(), 3); +++ } +++} diff --cc extra/git2/src/remote_callbacks.rs index 0000000000,0000000000,0000000000..2df2e7b015 new file mode 100644 --- /dev/null +++ b/extra/git2/src/remote_callbacks.rs @@@@ -1,0 -1,0 -1,0 +1,526 @@@@ +++use libc::{c_char, c_int, c_uint, c_void, size_t}; +++use std::ffi::CStr; +++use std::mem; +++use std::ptr; +++use std::slice; +++use std::str; +++ +++use crate::cert::Cert; +++use crate::util::Binding; +++use crate::{ +++ panic, raw, Cred, CredentialType, Error, IndexerProgress, Oid, PackBuilderStage, Progress, +++ PushUpdate, +++}; +++ +++/// A structure to contain the callbacks which are invoked when a repository is +++/// being updated or downloaded. +++/// +++/// These callbacks are used to manage facilities such as authentication, +++/// transfer progress, etc. +++pub struct RemoteCallbacks<'a> { +++ push_progress: Option>>, +++ progress: Option>>, +++ pack_progress: Option>>, +++ credentials: Option>>, +++ sideband_progress: Option>>, +++ update_tips: Option>>, +++ certificate_check: Option>>, +++ push_update_reference: Option>>, +++ push_negotiation: Option>>, +++} +++ +++/// Callback used to acquire credentials for when a remote is fetched. +++/// +++/// * `url` - the resource for which the credentials are required. +++/// * `username_from_url` - the username that was embedded in the URL, or `None` +++/// if it was not included. +++/// * `allowed_types` - a bitmask stating which cred types are OK to return. +++pub type Credentials<'a> = +++ dyn FnMut(&str, Option<&str>, CredentialType) -> Result + 'a; +++ +++/// Callback for receiving messages delivered by the transport. +++/// +++/// The return value indicates whether the network operation should continue. +++pub type TransportMessage<'a> = dyn FnMut(&[u8]) -> bool + 'a; +++ +++/// Callback for whenever a reference is updated locally. +++pub type UpdateTips<'a> = dyn FnMut(&str, Oid, Oid) -> bool + 'a; +++ +++/// Callback for a custom certificate check. +++/// +++/// The first argument is the certificate received on the connection. +++/// Certificates are typically either an SSH or X509 certificate. +++/// +++/// The second argument is the hostname for the connection is passed as the last +++/// argument. +++pub type CertificateCheck<'a> = +++ dyn FnMut(&Cert<'_>, &str) -> Result + 'a; +++ +++/// The return value for the [`RemoteCallbacks::certificate_check`] callback. +++pub enum CertificateCheckStatus { +++ /// Indicates that the certificate should be accepted. +++ CertificateOk, +++ /// Indicates that the certificate callback is neither accepting nor +++ /// rejecting the certificate. The result of the certificate checks +++ /// built-in to libgit2 will be used instead. +++ CertificatePassthrough, +++} +++ +++/// Callback for each updated reference on push. +++/// +++/// The first argument here is the `refname` of the reference, and the second is +++/// the status message sent by a server. If the status is `Some` then the update +++/// was rejected by the remote server with a reason why. +++pub type PushUpdateReference<'a> = dyn FnMut(&str, Option<&str>) -> Result<(), Error> + 'a; +++ +++/// Callback for push transfer progress +++/// +++/// Parameters: +++/// * current +++/// * total +++/// * bytes +++pub type PushTransferProgress<'a> = dyn FnMut(usize, usize, usize) + 'a; +++ +++/// Callback for pack progress +++/// +++/// Be aware that this is called inline with pack building operations, +++/// so performance may be affected. +++/// +++/// Parameters: +++/// * stage +++/// * current +++/// * total +++pub type PackProgress<'a> = dyn FnMut(PackBuilderStage, usize, usize) + 'a; +++ +++/// The callback is called once between the negotiation step and the upload. +++/// +++/// The argument is a slice containing the updates which will be sent as +++/// commands to the destination. +++/// +++/// The push is cancelled if an error is returned. +++pub type PushNegotiation<'a> = dyn FnMut(&[PushUpdate<'_>]) -> Result<(), Error> + 'a; +++ +++impl<'a> Default for RemoteCallbacks<'a> { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl<'a> RemoteCallbacks<'a> { +++ /// Creates a new set of empty callbacks +++ pub fn new() -> RemoteCallbacks<'a> { +++ RemoteCallbacks { +++ credentials: None, +++ progress: None, +++ pack_progress: None, +++ sideband_progress: None, +++ update_tips: None, +++ certificate_check: None, +++ push_update_reference: None, +++ push_progress: None, +++ push_negotiation: None, +++ } +++ } +++ +++ /// The callback through which to fetch credentials if required. +++ /// +++ /// # Example +++ /// +++ /// Prepare a callback to authenticate using the `$HOME/.ssh/id_rsa` SSH key, and +++ /// extracting the username from the URL (i.e. git@github.com:rust-lang/git2-rs.git): +++ /// +++ /// ```no_run +++ /// use git2::{Cred, RemoteCallbacks}; +++ /// use std::env; +++ /// +++ /// let mut callbacks = RemoteCallbacks::new(); +++ /// callbacks.credentials(|_url, username_from_url, _allowed_types| { +++ /// Cred::ssh_key( +++ /// username_from_url.unwrap(), +++ /// None, +++ /// std::path::Path::new(&format!("{}/.ssh/id_rsa", env::var("HOME").unwrap())), +++ /// None, +++ /// ) +++ /// }); +++ /// ``` +++ pub fn credentials(&mut self, cb: F) -> &mut RemoteCallbacks<'a> +++ where +++ F: FnMut(&str, Option<&str>, CredentialType) -> Result + 'a, +++ { +++ self.credentials = Some(Box::new(cb) as Box>); +++ self +++ } +++ +++ /// The callback through which progress is monitored. +++ pub fn transfer_progress(&mut self, cb: F) -> &mut RemoteCallbacks<'a> +++ where +++ F: FnMut(Progress<'_>) -> bool + 'a, +++ { +++ self.progress = Some(Box::new(cb) as Box>); +++ self +++ } +++ +++ /// Textual progress from the remote. +++ /// +++ /// Text sent over the progress side-band will be passed to this function +++ /// (this is the 'counting objects' output). +++ pub fn sideband_progress(&mut self, cb: F) -> &mut RemoteCallbacks<'a> +++ where +++ F: FnMut(&[u8]) -> bool + 'a, +++ { +++ self.sideband_progress = Some(Box::new(cb) as Box>); +++ self +++ } +++ +++ /// Each time a reference is updated locally, the callback will be called +++ /// with information about it. +++ pub fn update_tips(&mut self, cb: F) -> &mut RemoteCallbacks<'a> +++ where +++ F: FnMut(&str, Oid, Oid) -> bool + 'a, +++ { +++ self.update_tips = Some(Box::new(cb) as Box>); +++ self +++ } +++ +++ /// If certificate verification fails, then this callback will be invoked to +++ /// let the caller make the final decision of whether to allow the +++ /// connection to proceed. +++ pub fn certificate_check(&mut self, cb: F) -> &mut RemoteCallbacks<'a> +++ where +++ F: FnMut(&Cert<'_>, &str) -> Result + 'a, +++ { +++ self.certificate_check = Some(Box::new(cb) as Box>); +++ self +++ } +++ +++ /// Set a callback to get invoked for each updated reference on a push. +++ /// +++ /// The first argument to the callback is the name of the reference and the +++ /// second is a status message sent by the server. If the status is `Some` +++ /// then the push was rejected. +++ pub fn push_update_reference(&mut self, cb: F) -> &mut RemoteCallbacks<'a> +++ where +++ F: FnMut(&str, Option<&str>) -> Result<(), Error> + 'a, +++ { +++ self.push_update_reference = Some(Box::new(cb) as Box>); +++ self +++ } +++ +++ /// The callback through which progress of push transfer is monitored +++ /// +++ /// Parameters: +++ /// * current +++ /// * total +++ /// * bytes +++ pub fn push_transfer_progress(&mut self, cb: F) -> &mut RemoteCallbacks<'a> +++ where +++ F: FnMut(usize, usize, usize) + 'a, +++ { +++ self.push_progress = Some(Box::new(cb) as Box>); +++ self +++ } +++ +++ /// Function to call with progress information during pack building. +++ /// +++ /// Be aware that this is called inline with pack building operations, +++ /// so performance may be affected. +++ /// +++ /// Parameters: +++ /// * stage +++ /// * current +++ /// * total +++ pub fn pack_progress(&mut self, cb: F) -> &mut RemoteCallbacks<'a> +++ where +++ F: FnMut(PackBuilderStage, usize, usize) + 'a, +++ { +++ self.pack_progress = Some(Box::new(cb) as Box>); +++ self +++ } +++ +++ /// The callback is called once between the negotiation step and the upload. +++ /// +++ /// The argument to the callback is a slice containing the updates which +++ /// will be sent as commands to the destination. +++ /// +++ /// The push is cancelled if the callback returns an error. +++ pub fn push_negotiation(&mut self, cb: F) -> &mut RemoteCallbacks<'a> +++ where +++ F: FnMut(&[PushUpdate<'_>]) -> Result<(), Error> + 'a, +++ { +++ self.push_negotiation = Some(Box::new(cb) as Box>); +++ self +++ } +++} +++ +++impl<'a> Binding for RemoteCallbacks<'a> { +++ type Raw = raw::git_remote_callbacks; +++ unsafe fn from_raw(_raw: raw::git_remote_callbacks) -> RemoteCallbacks<'a> { +++ panic!("unimplemented"); +++ } +++ +++ fn raw(&self) -> raw::git_remote_callbacks { +++ unsafe { +++ let mut callbacks: raw::git_remote_callbacks = mem::zeroed(); +++ assert_eq!( +++ raw::git_remote_init_callbacks(&mut callbacks, raw::GIT_REMOTE_CALLBACKS_VERSION), +++ 0 +++ ); +++ if self.progress.is_some() { +++ callbacks.transfer_progress = Some(transfer_progress_cb); +++ } +++ if self.credentials.is_some() { +++ callbacks.credentials = Some(credentials_cb); +++ } +++ if self.sideband_progress.is_some() { +++ callbacks.sideband_progress = Some(sideband_progress_cb); +++ } +++ if self.certificate_check.is_some() { +++ callbacks.certificate_check = Some(certificate_check_cb); +++ } +++ if self.push_update_reference.is_some() { +++ callbacks.push_update_reference = Some(push_update_reference_cb); +++ } +++ if self.push_progress.is_some() { +++ callbacks.push_transfer_progress = Some(push_transfer_progress_cb); +++ } +++ if self.pack_progress.is_some() { +++ callbacks.pack_progress = Some(pack_progress_cb); +++ } +++ if self.update_tips.is_some() { +++ let f: extern "C" fn( +++ *const c_char, +++ *const raw::git_oid, +++ *const raw::git_oid, +++ *mut c_void, +++ ) -> c_int = update_tips_cb; +++ callbacks.update_tips = Some(f); +++ } +++ if self.push_negotiation.is_some() { +++ callbacks.push_negotiation = Some(push_negotiation_cb); +++ } +++ callbacks.payload = self as *const _ as *mut _; +++ callbacks +++ } +++ } +++} +++ +++extern "C" fn credentials_cb( +++ ret: *mut *mut raw::git_cred, +++ url: *const c_char, +++ username_from_url: *const c_char, +++ allowed_types: c_uint, +++ payload: *mut c_void, +++) -> c_int { +++ unsafe { +++ let ok = panic::wrap(|| { +++ let payload = &mut *(payload as *mut RemoteCallbacks<'_>); +++ let callback = payload +++ .credentials +++ .as_mut() +++ .ok_or(raw::GIT_PASSTHROUGH as c_int)?; +++ *ret = ptr::null_mut(); +++ let url = str::from_utf8(CStr::from_ptr(url).to_bytes()) +++ .map_err(|_| raw::GIT_PASSTHROUGH as c_int)?; +++ let username_from_url = match crate::opt_bytes(&url, username_from_url) { +++ Some(username) => { +++ Some(str::from_utf8(username).map_err(|_| raw::GIT_PASSTHROUGH as c_int)?) +++ } +++ None => None, +++ }; +++ +++ let cred_type = CredentialType::from_bits_truncate(allowed_types as u32); +++ +++ callback(url, username_from_url, cred_type).map_err(|e| e.raw_set_git_error()) +++ }); +++ match ok { +++ Some(Ok(cred)) => { +++ // Turns out it's a memory safety issue if we pass through any +++ // and all credentials into libgit2 +++ if allowed_types & (cred.credtype() as c_uint) != 0 { +++ *ret = cred.unwrap(); +++ 0 +++ } else { +++ raw::GIT_PASSTHROUGH as c_int +++ } +++ } +++ Some(Err(e)) => e, +++ None => -1, +++ } +++ } +++} +++ +++extern "C" fn transfer_progress_cb( +++ stats: *const raw::git_indexer_progress, +++ payload: *mut c_void, +++) -> c_int { +++ let ok = panic::wrap(|| unsafe { +++ let payload = &mut *(payload as *mut RemoteCallbacks<'_>); +++ let callback = match payload.progress { +++ Some(ref mut c) => c, +++ None => return true, +++ }; +++ let progress = Binding::from_raw(stats); +++ callback(progress) +++ }); +++ if ok == Some(true) { +++ 0 +++ } else { +++ -1 +++ } +++} +++ +++extern "C" fn sideband_progress_cb(str: *const c_char, len: c_int, payload: *mut c_void) -> c_int { +++ let ok = panic::wrap(|| unsafe { +++ let payload = &mut *(payload as *mut RemoteCallbacks<'_>); +++ let callback = match payload.sideband_progress { +++ Some(ref mut c) => c, +++ None => return true, +++ }; +++ let buf = slice::from_raw_parts(str as *const u8, len as usize); +++ callback(buf) +++ }); +++ if ok == Some(true) { +++ 0 +++ } else { +++ -1 +++ } +++} +++ +++extern "C" fn update_tips_cb( +++ refname: *const c_char, +++ a: *const raw::git_oid, +++ b: *const raw::git_oid, +++ data: *mut c_void, +++) -> c_int { +++ let ok = panic::wrap(|| unsafe { +++ let payload = &mut *(data as *mut RemoteCallbacks<'_>); +++ let callback = match payload.update_tips { +++ Some(ref mut c) => c, +++ None => return true, +++ }; +++ let refname = str::from_utf8(CStr::from_ptr(refname).to_bytes()).unwrap(); +++ let a = Binding::from_raw(a); +++ let b = Binding::from_raw(b); +++ callback(refname, a, b) +++ }); +++ if ok == Some(true) { +++ 0 +++ } else { +++ -1 +++ } +++} +++ +++extern "C" fn certificate_check_cb( +++ cert: *mut raw::git_cert, +++ _valid: c_int, +++ hostname: *const c_char, +++ data: *mut c_void, +++) -> c_int { +++ let ok = panic::wrap(|| unsafe { +++ let payload = &mut *(data as *mut RemoteCallbacks<'_>); +++ let callback = match payload.certificate_check { +++ Some(ref mut c) => c, +++ None => return Ok(CertificateCheckStatus::CertificatePassthrough), +++ }; +++ let cert = Binding::from_raw(cert); +++ let hostname = str::from_utf8(CStr::from_ptr(hostname).to_bytes()).unwrap(); +++ callback(&cert, hostname) +++ }); +++ match ok { +++ Some(Ok(CertificateCheckStatus::CertificateOk)) => 0, +++ Some(Ok(CertificateCheckStatus::CertificatePassthrough)) => raw::GIT_PASSTHROUGH as c_int, +++ Some(Err(e)) => unsafe { e.raw_set_git_error() }, +++ None => { +++ // Panic. The *should* get resumed by some future call to check(). +++ -1 +++ } +++ } +++} +++ +++extern "C" fn push_update_reference_cb( +++ refname: *const c_char, +++ status: *const c_char, +++ data: *mut c_void, +++) -> c_int { +++ panic::wrap(|| unsafe { +++ let payload = &mut *(data as *mut RemoteCallbacks<'_>); +++ let callback = match payload.push_update_reference { +++ Some(ref mut c) => c, +++ None => return 0, +++ }; +++ let refname = str::from_utf8(CStr::from_ptr(refname).to_bytes()).unwrap(); +++ let status = if status.is_null() { +++ None +++ } else { +++ Some(str::from_utf8(CStr::from_ptr(status).to_bytes()).unwrap()) +++ }; +++ match callback(refname, status) { +++ Ok(()) => 0, +++ Err(e) => e.raw_set_git_error(), +++ } +++ }) +++ .unwrap_or(-1) +++} +++ +++extern "C" fn push_transfer_progress_cb( +++ progress: c_uint, +++ total: c_uint, +++ bytes: size_t, +++ data: *mut c_void, +++) -> c_int { +++ panic::wrap(|| unsafe { +++ let payload = &mut *(data as *mut RemoteCallbacks<'_>); +++ let callback = match payload.push_progress { +++ Some(ref mut c) => c, +++ None => return 0, +++ }; +++ +++ callback(progress as usize, total as usize, bytes as usize); +++ +++ 0 +++ }) +++ .unwrap_or(-1) +++} +++ +++extern "C" fn pack_progress_cb( +++ stage: raw::git_packbuilder_stage_t, +++ current: c_uint, +++ total: c_uint, +++ data: *mut c_void, +++) -> c_int { +++ panic::wrap(|| unsafe { +++ let payload = &mut *(data as *mut RemoteCallbacks<'_>); +++ let callback = match payload.pack_progress { +++ Some(ref mut c) => c, +++ None => return 0, +++ }; +++ +++ let stage = Binding::from_raw(stage); +++ +++ callback(stage, current as usize, total as usize); +++ +++ 0 +++ }) +++ .unwrap_or(-1) +++} +++ +++extern "C" fn push_negotiation_cb( +++ updates: *mut *const raw::git_push_update, +++ len: size_t, +++ payload: *mut c_void, +++) -> c_int { +++ panic::wrap(|| unsafe { +++ let payload = &mut *(payload as *mut RemoteCallbacks<'_>); +++ let callback = match payload.push_negotiation { +++ Some(ref mut c) => c, +++ None => return 0, +++ }; +++ +++ let updates = slice::from_raw_parts(updates as *mut PushUpdate<'_>, len); +++ match callback(updates) { +++ Ok(()) => 0, +++ Err(e) => e.raw_set_git_error(), +++ } +++ }) +++ .unwrap_or(-1) +++} diff --cc extra/git2/src/repo.rs index 0000000000,0000000000,0000000000..074955f623 new file mode 100644 --- /dev/null +++ b/extra/git2/src/repo.rs @@@@ -1,0 -1,0 -1,0 +1,4390 @@@@ +++use libc::{c_char, c_int, c_uint, c_void, size_t}; +++use std::env; +++use std::ffi::{CStr, CString, OsStr}; +++use std::mem; +++use std::path::{Path, PathBuf}; +++use std::ptr; +++use std::str; +++ +++use crate::build::{CheckoutBuilder, RepoBuilder}; +++use crate::diff::{ +++ binary_cb_c, file_cb_c, hunk_cb_c, line_cb_c, BinaryCb, DiffCallbacks, FileCb, HunkCb, LineCb, +++}; +++use crate::oid_array::OidArray; +++use crate::stash::{stash_cb, StashApplyOptions, StashCbData, StashSaveOptions}; +++use crate::string_array::StringArray; +++use crate::tagforeach::{tag_foreach_cb, TagForeachCB, TagForeachData}; +++use crate::util::{self, path_to_repo_path, Binding}; +++use crate::worktree::{Worktree, WorktreeAddOptions}; +++use crate::CherrypickOptions; +++use crate::RevertOptions; +++use crate::{mailmap::Mailmap, panic}; +++use crate::{ +++ raw, AttrCheckFlags, Buf, Error, Object, Remote, RepositoryOpenFlags, RepositoryState, Revspec, +++ StashFlags, +++}; +++use crate::{ +++ AnnotatedCommit, MergeAnalysis, MergeOptions, MergePreference, SubmoduleIgnore, +++ SubmoduleStatus, SubmoduleUpdate, +++}; +++use crate::{ApplyLocation, ApplyOptions, Rebase, RebaseOptions}; +++use crate::{Blame, BlameOptions, Reference, References, ResetType, Signature, Submodule}; +++use crate::{Blob, BlobWriter, Branch, BranchType, Branches, Commit, Config, Index, Oid, Tree}; +++use crate::{Describe, IntoCString, Reflog, RepositoryInitMode, RevparseMode}; +++use crate::{DescribeOptions, Diff, DiffOptions, Odb, PackBuilder, TreeBuilder}; +++use crate::{Note, Notes, ObjectType, Revwalk, Status, StatusOptions, Statuses, Tag, Transaction}; +++ +++type MergeheadForeachCb<'a> = dyn FnMut(&Oid) -> bool + 'a; +++type FetchheadForeachCb<'a> = dyn FnMut(&str, &[u8], &Oid, bool) -> bool + 'a; +++ +++struct FetchheadForeachCbData<'a> { +++ callback: &'a mut FetchheadForeachCb<'a>, +++} +++ +++struct MergeheadForeachCbData<'a> { +++ callback: &'a mut MergeheadForeachCb<'a>, +++} +++ +++extern "C" fn mergehead_foreach_cb(oid: *const raw::git_oid, payload: *mut c_void) -> c_int { +++ panic::wrap(|| unsafe { +++ let data = &mut *(payload as *mut MergeheadForeachCbData<'_>); +++ let res = { +++ let callback = &mut data.callback; +++ callback(&Binding::from_raw(oid)) +++ }; +++ +++ if res { +++ 0 +++ } else { +++ 1 +++ } +++ }) +++ .unwrap_or(1) +++} +++ +++extern "C" fn fetchhead_foreach_cb( +++ ref_name: *const c_char, +++ remote_url: *const c_char, +++ oid: *const raw::git_oid, +++ is_merge: c_uint, +++ payload: *mut c_void, +++) -> c_int { +++ panic::wrap(|| unsafe { +++ let data = &mut *(payload as *mut FetchheadForeachCbData<'_>); +++ let res = { +++ let callback = &mut data.callback; +++ +++ assert!(!ref_name.is_null()); +++ assert!(!remote_url.is_null()); +++ assert!(!oid.is_null()); +++ +++ let ref_name = str::from_utf8(CStr::from_ptr(ref_name).to_bytes()).unwrap(); +++ let remote_url = CStr::from_ptr(remote_url).to_bytes(); +++ let oid = Binding::from_raw(oid); +++ let is_merge = is_merge == 1; +++ +++ callback(&ref_name, remote_url, &oid, is_merge) +++ }; +++ +++ if res { +++ 0 +++ } else { +++ 1 +++ } +++ }) +++ .unwrap_or(1) +++} +++ +++/// An owned git repository, representing all state associated with the +++/// underlying filesystem. +++/// +++/// This structure corresponds to a `git_repository` in libgit2. Many other +++/// types in git2-rs are derivative from this structure and are attached to its +++/// lifetime. +++/// +++/// When a repository goes out of scope it is freed in memory but not deleted +++/// from the filesystem. +++pub struct Repository { +++ raw: *mut raw::git_repository, +++} +++ +++// It is the current belief that a `Repository` can be sent among threads, or +++// even shared among threads in a mutex. +++unsafe impl Send for Repository {} +++ +++/// Options which can be used to configure how a repository is initialized +++pub struct RepositoryInitOptions { +++ flags: u32, +++ mode: u32, +++ workdir_path: Option, +++ description: Option, +++ template_path: Option, +++ initial_head: Option, +++ origin_url: Option, +++} +++ +++impl Repository { +++ /// Attempt to open an already-existing repository at `path`. +++ /// +++ /// The path can point to either a normal or bare repository. +++ pub fn open>(path: P) -> Result { +++ crate::init(); +++ // Normal file path OK (does not need Windows conversion). +++ let path = path.as_ref().into_c_string()?; +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_repository_open(&mut ret, path)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Attempt to open an already-existing bare repository at `path`. +++ /// +++ /// The path can point to only a bare repository. +++ pub fn open_bare>(path: P) -> Result { +++ crate::init(); +++ // Normal file path OK (does not need Windows conversion). +++ let path = path.as_ref().into_c_string()?; +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_repository_open_bare(&mut ret, path)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Find and open an existing repository, respecting git environment +++ /// variables. This acts like `open_ext` with the +++ /// [FROM_ENV](RepositoryOpenFlags::FROM_ENV) flag, but additionally respects `$GIT_DIR`. +++ /// With `$GIT_DIR` unset, this will search for a repository starting in +++ /// the current directory. +++ pub fn open_from_env() -> Result { +++ crate::init(); +++ let mut ret = ptr::null_mut(); +++ let flags = raw::GIT_REPOSITORY_OPEN_FROM_ENV; +++ unsafe { +++ try_call!(raw::git_repository_open_ext( +++ &mut ret, +++ ptr::null(), +++ flags as c_uint, +++ ptr::null() +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Find and open an existing repository, with additional options. +++ /// +++ /// If flags contains [NO_SEARCH](RepositoryOpenFlags::NO_SEARCH), the path must point +++ /// directly to a repository; otherwise, this may point to a subdirectory +++ /// of a repository, and `open_ext` will search up through parent +++ /// directories. +++ /// +++ /// If flags contains [CROSS_FS](RepositoryOpenFlags::CROSS_FS), the search through parent +++ /// directories will not cross a filesystem boundary (detected when the +++ /// stat st_dev field changes). +++ /// +++ /// If flags contains [BARE](RepositoryOpenFlags::BARE), force opening the repository as +++ /// bare even if it isn't, ignoring any working directory, and defer +++ /// loading the repository configuration for performance. +++ /// +++ /// If flags contains [NO_DOTGIT](RepositoryOpenFlags::NO_DOTGIT), don't try appending +++ /// `/.git` to `path`. +++ /// +++ /// If flags contains [FROM_ENV](RepositoryOpenFlags::FROM_ENV), `open_ext` will ignore +++ /// other flags and `ceiling_dirs`, and respect the same environment +++ /// variables git does. Note, however, that `path` overrides `$GIT_DIR`; to +++ /// respect `$GIT_DIR` as well, use `open_from_env`. +++ /// +++ /// ceiling_dirs specifies a list of paths that the search through parent +++ /// directories will stop before entering. Use the functions in std::env +++ /// to construct or manipulate such a path list. (You can use `&[] as +++ /// &[&std::ffi::OsStr]` as an argument if there are no ceiling +++ /// directories.) +++ pub fn open_ext( +++ path: P, +++ flags: RepositoryOpenFlags, +++ ceiling_dirs: I, +++ ) -> Result +++ where +++ P: AsRef, +++ O: AsRef, +++ I: IntoIterator, +++ { +++ crate::init(); +++ // Normal file path OK (does not need Windows conversion). +++ let path = path.as_ref().into_c_string()?; +++ let ceiling_dirs_os = env::join_paths(ceiling_dirs)?; +++ let ceiling_dirs = ceiling_dirs_os.into_c_string()?; +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_repository_open_ext( +++ &mut ret, +++ path, +++ flags.bits() as c_uint, +++ ceiling_dirs +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Attempt to open an already-existing repository from a worktree. +++ pub fn open_from_worktree(worktree: &Worktree) -> Result { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_repository_open_from_worktree( +++ &mut ret, +++ worktree.raw() +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Attempt to open an already-existing repository at or above `path` +++ /// +++ /// This starts at `path` and looks up the filesystem hierarchy +++ /// until it finds a repository. +++ pub fn discover>(path: P) -> Result { +++ // TODO: this diverges significantly from the libgit2 API +++ crate::init(); +++ let buf = Buf::new(); +++ // Normal file path OK (does not need Windows conversion). +++ let path = path.as_ref().into_c_string()?; +++ unsafe { +++ try_call!(raw::git_repository_discover( +++ buf.raw(), +++ path, +++ 1, +++ ptr::null() +++ )); +++ } +++ Repository::open(util::bytes2path(&*buf)) +++ } +++ +++ /// Attempt to find the path to a git repo for a given path +++ /// +++ /// This starts at `path` and looks up the filesystem hierarchy +++ /// until it finds a repository, stopping if it finds a member of ceiling_dirs +++ pub fn discover_path, I, O>(path: P, ceiling_dirs: I) -> Result +++ where +++ O: AsRef, +++ I: IntoIterator, +++ { +++ crate::init(); +++ let buf = Buf::new(); +++ // Normal file path OK (does not need Windows conversion). +++ let path = path.as_ref().into_c_string()?; +++ let ceiling_dirs_os = env::join_paths(ceiling_dirs)?; +++ let ceiling_dirs = ceiling_dirs_os.into_c_string()?; +++ unsafe { +++ try_call!(raw::git_repository_discover( +++ buf.raw(), +++ path, +++ 1, +++ ceiling_dirs +++ )); +++ } +++ +++ Ok(util::bytes2path(&*buf).to_path_buf()) +++ } +++ +++ /// Creates a new repository in the specified folder. +++ /// +++ /// This by default will create any necessary directories to create the +++ /// repository, and it will read any user-specified templates when creating +++ /// the repository. This behavior can be configured through `init_opts`. +++ pub fn init>(path: P) -> Result { +++ Repository::init_opts(path, &RepositoryInitOptions::new()) +++ } +++ +++ /// Creates a new `--bare` repository in the specified folder. +++ /// +++ /// The folder must exist prior to invoking this function. +++ pub fn init_bare>(path: P) -> Result { +++ Repository::init_opts(path, RepositoryInitOptions::new().bare(true)) +++ } +++ +++ /// Creates a new repository in the specified folder with the given options. +++ /// +++ /// See `RepositoryInitOptions` struct for more information. +++ pub fn init_opts>( +++ path: P, +++ opts: &RepositoryInitOptions, +++ ) -> Result { +++ crate::init(); +++ // Normal file path OK (does not need Windows conversion). +++ let path = path.as_ref().into_c_string()?; +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ let mut opts = opts.raw(); +++ try_call!(raw::git_repository_init_ext(&mut ret, path, &mut opts)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Clone a remote repository. +++ /// +++ /// See the `RepoBuilder` struct for more information. This function will +++ /// delegate to a fresh `RepoBuilder` +++ pub fn clone>(url: &str, into: P) -> Result { +++ crate::init(); +++ RepoBuilder::new().clone(url, into.as_ref()) +++ } +++ +++ /// Clone a remote repository, initialize and update its submodules +++ /// recursively. +++ /// +++ /// This is similar to `git clone --recursive`. +++ pub fn clone_recurse>(url: &str, into: P) -> Result { +++ let repo = Repository::clone(url, into)?; +++ repo.update_submodules()?; +++ Ok(repo) +++ } +++ +++ /// Attempt to wrap an object database as a repository. +++ pub fn from_odb(odb: Odb<'_>) -> Result { +++ crate::init(); +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_repository_wrap_odb(&mut ret, odb.raw())); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Update submodules recursively. +++ /// +++ /// Uninitialized submodules will be initialized. +++ fn update_submodules(&self) -> Result<(), Error> { +++ fn add_subrepos(repo: &Repository, list: &mut Vec) -> Result<(), Error> { +++ for mut subm in repo.submodules()? { +++ subm.update(true, None)?; +++ list.push(subm.open()?); +++ } +++ Ok(()) +++ } +++ +++ let mut repos = Vec::new(); +++ add_subrepos(self, &mut repos)?; +++ while let Some(repo) = repos.pop() { +++ add_subrepos(&repo, &mut repos)?; +++ } +++ Ok(()) +++ } +++ +++ /// Execute a rev-parse operation against the `spec` listed. +++ /// +++ /// The resulting revision specification is returned, or an error is +++ /// returned if one occurs. +++ pub fn revparse(&self, spec: &str) -> Result, Error> { +++ let mut raw = raw::git_revspec { +++ from: ptr::null_mut(), +++ to: ptr::null_mut(), +++ flags: 0, +++ }; +++ let spec = CString::new(spec)?; +++ unsafe { +++ try_call!(raw::git_revparse(&mut raw, self.raw, spec)); +++ let to = Binding::from_raw_opt(raw.to); +++ let from = Binding::from_raw_opt(raw.from); +++ let mode = RevparseMode::from_bits_truncate(raw.flags as u32); +++ Ok(Revspec::from_objects(from, to, mode)) +++ } +++ } +++ +++ /// Find a single object, as specified by a revision string. +++ pub fn revparse_single(&self, spec: &str) -> Result, Error> { +++ let spec = CString::new(spec)?; +++ let mut obj = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_revparse_single(&mut obj, self.raw, spec)); +++ assert!(!obj.is_null()); +++ Ok(Binding::from_raw(obj)) +++ } +++ } +++ +++ /// Find a single object and intermediate reference by a revision string. +++ /// +++ /// See `man gitrevisions`, or +++ /// for +++ /// information on the syntax accepted. +++ /// +++ /// In some cases (`@{<-n>}` or `@{upstream}`), the expression +++ /// may point to an intermediate reference. When such expressions are being +++ /// passed in, this intermediate reference is returned. +++ pub fn revparse_ext(&self, spec: &str) -> Result<(Object<'_>, Option>), Error> { +++ let spec = CString::new(spec)?; +++ let mut git_obj = ptr::null_mut(); +++ let mut git_ref = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_revparse_ext( +++ &mut git_obj, +++ &mut git_ref, +++ self.raw, +++ spec +++ )); +++ assert!(!git_obj.is_null()); +++ Ok((Binding::from_raw(git_obj), Binding::from_raw_opt(git_ref))) +++ } +++ } +++ +++ /// Tests whether this repository is a bare repository or not. +++ pub fn is_bare(&self) -> bool { +++ unsafe { raw::git_repository_is_bare(self.raw) == 1 } +++ } +++ +++ /// Tests whether this repository is a shallow clone. +++ pub fn is_shallow(&self) -> bool { +++ unsafe { raw::git_repository_is_shallow(self.raw) == 1 } +++ } +++ +++ /// Tests whether this repository is a worktree. +++ pub fn is_worktree(&self) -> bool { +++ unsafe { raw::git_repository_is_worktree(self.raw) == 1 } +++ } +++ +++ /// Tests whether this repository is empty. +++ pub fn is_empty(&self) -> Result { +++ let empty = unsafe { try_call!(raw::git_repository_is_empty(self.raw)) }; +++ Ok(empty == 1) +++ } +++ +++ /// Returns the path to the `.git` folder for normal repositories or the +++ /// repository itself for bare repositories. +++ pub fn path(&self) -> &Path { +++ unsafe { +++ let ptr = raw::git_repository_path(self.raw); +++ util::bytes2path(crate::opt_bytes(self, ptr).unwrap()) +++ } +++ } +++ +++ /// Returns the path of the shared common directory for this repository. +++ /// +++ /// If the repository is bare, it is the root directory for the repository. +++ /// If the repository is a worktree, it is the parent repo's gitdir. +++ /// Otherwise, it is the gitdir. +++ pub fn commondir(&self) -> &Path { +++ unsafe { +++ let ptr = raw::git_repository_commondir(self.raw); +++ util::bytes2path(crate::opt_bytes(self, ptr).unwrap()) +++ } +++ } +++ +++ /// Returns the current state of this repository +++ pub fn state(&self) -> RepositoryState { +++ let state = unsafe { raw::git_repository_state(self.raw) }; +++ macro_rules! check( ($($raw:ident => $real:ident),*) => ( +++ $(if state == raw::$raw as c_int { +++ super::RepositoryState::$real +++ }) else * +++ else { +++ panic!("unknown repository state: {}", state) +++ } +++ ) ); +++ +++ check!( +++ GIT_REPOSITORY_STATE_NONE => Clean, +++ GIT_REPOSITORY_STATE_MERGE => Merge, +++ GIT_REPOSITORY_STATE_REVERT => Revert, +++ GIT_REPOSITORY_STATE_REVERT_SEQUENCE => RevertSequence, +++ GIT_REPOSITORY_STATE_CHERRYPICK => CherryPick, +++ GIT_REPOSITORY_STATE_CHERRYPICK_SEQUENCE => CherryPickSequence, +++ GIT_REPOSITORY_STATE_BISECT => Bisect, +++ GIT_REPOSITORY_STATE_REBASE => Rebase, +++ GIT_REPOSITORY_STATE_REBASE_INTERACTIVE => RebaseInteractive, +++ GIT_REPOSITORY_STATE_REBASE_MERGE => RebaseMerge, +++ GIT_REPOSITORY_STATE_APPLY_MAILBOX => ApplyMailbox, +++ GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE => ApplyMailboxOrRebase +++ ) +++ } +++ +++ /// Get the path of the working directory for this repository. +++ /// +++ /// If this repository is bare, then `None` is returned. +++ pub fn workdir(&self) -> Option<&Path> { +++ unsafe { +++ let ptr = raw::git_repository_workdir(self.raw); +++ if ptr.is_null() { +++ None +++ } else { +++ Some(util::bytes2path(CStr::from_ptr(ptr).to_bytes())) +++ } +++ } +++ } +++ +++ /// Set the path to the working directory for this repository. +++ /// +++ /// If `update_link` is true, create/update the gitlink file in the workdir +++ /// and set config "core.worktree" (if workdir is not the parent of the .git +++ /// directory). +++ pub fn set_workdir(&self, path: &Path, update_gitlink: bool) -> Result<(), Error> { +++ // Normal file path OK (does not need Windows conversion). +++ let path = path.into_c_string()?; +++ unsafe { +++ try_call!(raw::git_repository_set_workdir( +++ self.raw(), +++ path, +++ update_gitlink +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Get the currently active namespace for this repository. +++ /// +++ /// If there is no namespace, or the namespace is not a valid utf8 string, +++ /// `None` is returned. +++ pub fn namespace(&self) -> Option<&str> { +++ self.namespace_bytes().and_then(|s| str::from_utf8(s).ok()) +++ } +++ +++ /// Get the currently active namespace for this repository as a byte array. +++ /// +++ /// If there is no namespace, `None` is returned. +++ pub fn namespace_bytes(&self) -> Option<&[u8]> { +++ unsafe { crate::opt_bytes(self, raw::git_repository_get_namespace(self.raw)) } +++ } +++ +++ /// Set the active namespace for this repository. +++ pub fn set_namespace(&self, namespace: &str) -> Result<(), Error> { +++ self.set_namespace_bytes(namespace.as_bytes()) +++ } +++ +++ /// Set the active namespace for this repository as a byte array. +++ pub fn set_namespace_bytes(&self, namespace: &[u8]) -> Result<(), Error> { +++ unsafe { +++ let namespace = CString::new(namespace)?; +++ try_call!(raw::git_repository_set_namespace(self.raw, namespace)); +++ Ok(()) +++ } +++ } +++ +++ /// Remove the active namespace for this repository. +++ pub fn remove_namespace(&self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_repository_set_namespace(self.raw, ptr::null())); +++ Ok(()) +++ } +++ } +++ +++ /// Retrieves the Git merge message. +++ /// Remember to remove the message when finished. +++ pub fn message(&self) -> Result { +++ unsafe { +++ let buf = Buf::new(); +++ try_call!(raw::git_repository_message(buf.raw(), self.raw)); +++ Ok(str::from_utf8(&buf).unwrap().to_string()) +++ } +++ } +++ +++ /// Remove the Git merge message. +++ pub fn remove_message(&self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_repository_message_remove(self.raw)); +++ Ok(()) +++ } +++ } +++ +++ /// List all remotes for a given repository +++ pub fn remotes(&self) -> Result { +++ let mut arr = raw::git_strarray { +++ strings: ptr::null_mut(), +++ count: 0, +++ }; +++ unsafe { +++ try_call!(raw::git_remote_list(&mut arr, self.raw)); +++ Ok(Binding::from_raw(arr)) +++ } +++ } +++ +++ /// Get the information for a particular remote +++ pub fn find_remote(&self, name: &str) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_remote_lookup(&mut ret, self.raw, name)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Add a remote with the default fetch refspec to the repository's +++ /// configuration. +++ pub fn remote(&self, name: &str, url: &str) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ let name = CString::new(name)?; +++ let url = CString::new(url)?; +++ unsafe { +++ try_call!(raw::git_remote_create(&mut ret, self.raw, name, url)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Add a remote with the provided fetch refspec to the repository's +++ /// configuration. +++ pub fn remote_with_fetch( +++ &self, +++ name: &str, +++ url: &str, +++ fetch: &str, +++ ) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ let name = CString::new(name)?; +++ let url = CString::new(url)?; +++ let fetch = CString::new(fetch)?; +++ unsafe { +++ try_call!(raw::git_remote_create_with_fetchspec( +++ &mut ret, self.raw, name, url, fetch +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Create an anonymous remote +++ /// +++ /// Create a remote with the given URL and refspec in memory. You can use +++ /// this when you have a URL instead of a remote's name. Note that anonymous +++ /// remotes cannot be converted to persisted remotes. +++ pub fn remote_anonymous(&self, url: &str) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ let url = CString::new(url)?; +++ unsafe { +++ try_call!(raw::git_remote_create_anonymous(&mut ret, self.raw, url)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Give a remote a new name +++ /// +++ /// All remote-tracking branches and configuration settings for the remote +++ /// are updated. +++ /// +++ /// A temporary in-memory remote cannot be given a name with this method. +++ /// +++ /// No loaded instances of the remote with the old name will change their +++ /// name or their list of refspecs. +++ /// +++ /// The returned array of strings is a list of the non-default refspecs +++ /// which cannot be renamed and are returned for further processing by the +++ /// caller. +++ pub fn remote_rename(&self, name: &str, new_name: &str) -> Result { +++ let name = CString::new(name)?; +++ let new_name = CString::new(new_name)?; +++ let mut problems = raw::git_strarray { +++ count: 0, +++ strings: ptr::null_mut(), +++ }; +++ unsafe { +++ try_call!(raw::git_remote_rename( +++ &mut problems, +++ self.raw, +++ name, +++ new_name +++ )); +++ Ok(Binding::from_raw(problems)) +++ } +++ } +++ +++ /// Delete an existing persisted remote. +++ /// +++ /// All remote-tracking branches and configuration settings for the remote +++ /// will be removed. +++ pub fn remote_delete(&self, name: &str) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_remote_delete(self.raw, name)); +++ } +++ Ok(()) +++ } +++ +++ /// Add a fetch refspec to the remote's configuration +++ /// +++ /// Add the given refspec to the fetch list in the configuration. No loaded +++ /// remote instances will be affected. +++ pub fn remote_add_fetch(&self, name: &str, spec: &str) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ let spec = CString::new(spec)?; +++ unsafe { +++ try_call!(raw::git_remote_add_fetch(self.raw, name, spec)); +++ } +++ Ok(()) +++ } +++ +++ /// Add a push refspec to the remote's configuration. +++ /// +++ /// Add the given refspec to the push list in the configuration. No +++ /// loaded remote instances will be affected. +++ pub fn remote_add_push(&self, name: &str, spec: &str) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ let spec = CString::new(spec)?; +++ unsafe { +++ try_call!(raw::git_remote_add_push(self.raw, name, spec)); +++ } +++ Ok(()) +++ } +++ +++ /// Set the remote's URL in the configuration +++ /// +++ /// Remote objects already in memory will not be affected. This assumes +++ /// the common case of a single-url remote and will otherwise return an +++ /// error. +++ pub fn remote_set_url(&self, name: &str, url: &str) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ let url = CString::new(url)?; +++ unsafe { +++ try_call!(raw::git_remote_set_url(self.raw, name, url)); +++ } +++ Ok(()) +++ } +++ +++ /// Set the remote's URL for pushing in the configuration. +++ /// +++ /// Remote objects already in memory will not be affected. This assumes +++ /// the common case of a single-url remote and will otherwise return an +++ /// error. +++ /// +++ /// `None` indicates that it should be cleared. +++ pub fn remote_set_pushurl(&self, name: &str, pushurl: Option<&str>) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ let pushurl = crate::opt_cstr(pushurl)?; +++ unsafe { +++ try_call!(raw::git_remote_set_pushurl(self.raw, name, pushurl)); +++ } +++ Ok(()) +++ } +++ +++ /// Sets the current head to the specified object and optionally resets +++ /// the index and working tree to match. +++ /// +++ /// A soft reset means the head will be moved to the commit. +++ /// +++ /// A mixed reset will trigger a soft reset, plus the index will be +++ /// replaced with the content of the commit tree. +++ /// +++ /// A hard reset will trigger a mixed reset and the working directory will +++ /// be replaced with the content of the index. (Untracked and ignored files +++ /// will be left alone, however.) +++ /// +++ /// The `target` is a commit-ish to which the head should be moved to. The +++ /// object can either be a commit or a tag, but tags must be dereferenceable +++ /// to a commit. +++ /// +++ /// The `checkout` options will only be used for a hard reset. +++ pub fn reset( +++ &self, +++ target: &Object<'_>, +++ kind: ResetType, +++ checkout: Option<&mut CheckoutBuilder<'_>>, +++ ) -> Result<(), Error> { +++ unsafe { +++ let mut opts: raw::git_checkout_options = mem::zeroed(); +++ try_call!(raw::git_checkout_init_options( +++ &mut opts, +++ raw::GIT_CHECKOUT_OPTIONS_VERSION +++ )); +++ let opts = checkout.map(|c| { +++ c.configure(&mut opts); +++ &mut opts +++ }); +++ try_call!(raw::git_reset(self.raw, target.raw(), kind, opts)); +++ } +++ Ok(()) +++ } +++ +++ /// Updates some entries in the index from the target commit tree. +++ /// +++ /// The scope of the updated entries is determined by the paths being +++ /// in the iterator provided. +++ /// +++ /// Passing a `None` target will result in removing entries in the index +++ /// matching the provided pathspecs. +++ pub fn reset_default(&self, target: Option<&Object<'_>>, paths: I) -> Result<(), Error> +++ where +++ T: IntoCString, +++ I: IntoIterator, +++ { +++ let (_a, _b, mut arr) = crate::util::iter2cstrs_paths(paths)?; +++ let target = target.map(|t| t.raw()); +++ unsafe { +++ try_call!(raw::git_reset_default(self.raw, target, &mut arr)); +++ } +++ Ok(()) +++ } +++ +++ /// Retrieve and resolve the reference pointed at by HEAD. +++ pub fn head(&self) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_repository_head(&mut ret, self.raw)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Make the repository HEAD point to the specified reference. +++ /// +++ /// If the provided reference points to a tree or a blob, the HEAD is +++ /// unaltered and an error is returned. +++ /// +++ /// If the provided reference points to a branch, the HEAD will point to +++ /// that branch, staying attached, or become attached if it isn't yet. If +++ /// the branch doesn't exist yet, no error will be returned. The HEAD will +++ /// then be attached to an unborn branch. +++ /// +++ /// Otherwise, the HEAD will be detached and will directly point to the +++ /// commit. +++ pub fn set_head(&self, refname: &str) -> Result<(), Error> { +++ self.set_head_bytes(refname.as_bytes()) +++ } +++ +++ /// Make the repository HEAD point to the specified reference as a byte array. +++ /// +++ /// If the provided reference points to a tree or a blob, the HEAD is +++ /// unaltered and an error is returned. +++ /// +++ /// If the provided reference points to a branch, the HEAD will point to +++ /// that branch, staying attached, or become attached if it isn't yet. If +++ /// the branch doesn't exist yet, no error will be returned. The HEAD will +++ /// then be attached to an unborn branch. +++ /// +++ /// Otherwise, the HEAD will be detached and will directly point to the +++ /// commit. +++ pub fn set_head_bytes(&self, refname: &[u8]) -> Result<(), Error> { +++ let refname = CString::new(refname)?; +++ unsafe { +++ try_call!(raw::git_repository_set_head(self.raw, refname)); +++ } +++ Ok(()) +++ } +++ +++ /// Determines whether the repository HEAD is detached. +++ pub fn head_detached(&self) -> Result { +++ unsafe { +++ let value = raw::git_repository_head_detached(self.raw); +++ match value { +++ 0 => Ok(false), +++ 1 => Ok(true), +++ _ => Err(Error::last_error(value)), +++ } +++ } +++ } +++ +++ /// Make the repository HEAD directly point to the commit. +++ /// +++ /// If the provided commitish cannot be found in the repository, the HEAD +++ /// is unaltered and an error is returned. +++ /// +++ /// If the provided commitish cannot be peeled into a commit, the HEAD is +++ /// unaltered and an error is returned. +++ /// +++ /// Otherwise, the HEAD will eventually be detached and will directly point +++ /// to the peeled commit. +++ pub fn set_head_detached(&self, commitish: Oid) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_repository_set_head_detached( +++ self.raw, +++ commitish.raw() +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Make the repository HEAD directly point to the commit. +++ /// +++ /// If the provided commitish cannot be found in the repository, the HEAD +++ /// is unaltered and an error is returned. +++ /// If the provided commitish cannot be peeled into a commit, the HEAD is +++ /// unaltered and an error is returned. +++ /// Otherwise, the HEAD will eventually be detached and will directly point +++ /// to the peeled commit. +++ pub fn set_head_detached_from_annotated( +++ &self, +++ commitish: AnnotatedCommit<'_>, +++ ) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_repository_set_head_detached_from_annotated( +++ self.raw, +++ commitish.raw() +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Create an iterator for the repo's references +++ pub fn references(&self) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_reference_iterator_new(&mut ret, self.raw)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Create an iterator for the repo's references that match the specified +++ /// glob +++ pub fn references_glob(&self, glob: &str) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ let glob = CString::new(glob)?; +++ unsafe { +++ try_call!(raw::git_reference_iterator_glob_new( +++ &mut ret, self.raw, glob +++ )); +++ +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Load all submodules for this repository and return them. +++ pub fn submodules(&self) -> Result>, Error> { +++ struct Data<'a, 'b> { +++ repo: &'b Repository, +++ ret: &'a mut Vec>, +++ } +++ let mut ret = Vec::new(); +++ +++ unsafe { +++ let mut data = Data { +++ repo: self, +++ ret: &mut ret, +++ }; +++ let cb: raw::git_submodule_cb = Some(append); +++ try_call!(raw::git_submodule_foreach( +++ self.raw, +++ cb, +++ &mut data as *mut _ as *mut c_void +++ )); +++ } +++ +++ return Ok(ret); +++ +++ extern "C" fn append( +++ _repo: *mut raw::git_submodule, +++ name: *const c_char, +++ data: *mut c_void, +++ ) -> c_int { +++ unsafe { +++ let data = &mut *(data as *mut Data<'_, '_>); +++ let mut raw = ptr::null_mut(); +++ let rc = raw::git_submodule_lookup(&mut raw, data.repo.raw(), name); +++ assert_eq!(rc, 0); +++ data.ret.push(Binding::from_raw(raw)); +++ } +++ 0 +++ } +++ } +++ +++ /// Gather file status information and populate the returned structure. +++ /// +++ /// Note that if a pathspec is given in the options to filter the +++ /// status, then the results from rename detection (if you enable it) may +++ /// not be accurate. To do rename detection properly, this must be called +++ /// with no pathspec so that all files can be considered. +++ pub fn statuses(&self, options: Option<&mut StatusOptions>) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_status_list_new( +++ &mut ret, +++ self.raw, +++ options.map(|s| s.raw()).unwrap_or(ptr::null()) +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Test if the ignore rules apply to a given file. +++ /// +++ /// This function checks the ignore rules to see if they would apply to the +++ /// given file. This indicates if the file would be ignored regardless of +++ /// whether the file is already in the index or committed to the repository. +++ /// +++ /// One way to think of this is if you were to do "git add ." on the +++ /// directory containing the file, would it be added or not? +++ pub fn status_should_ignore(&self, path: &Path) -> Result { +++ let mut ret = 0 as c_int; +++ let path = util::cstring_to_repo_path(path)?; +++ unsafe { +++ try_call!(raw::git_status_should_ignore(&mut ret, self.raw, path)); +++ } +++ Ok(ret != 0) +++ } +++ +++ /// Get file status for a single file. +++ /// +++ /// This tries to get status for the filename that you give. If no files +++ /// match that name (in either the HEAD, index, or working directory), this +++ /// returns NotFound. +++ /// +++ /// If the name matches multiple files (for example, if the path names a +++ /// directory or if running on a case- insensitive filesystem and yet the +++ /// HEAD has two entries that both match the path), then this returns +++ /// Ambiguous because it cannot give correct results. +++ /// +++ /// This does not do any sort of rename detection. Renames require a set of +++ /// targets and because of the path filtering, there is not enough +++ /// information to check renames correctly. To check file status with rename +++ /// detection, there is no choice but to do a full `statuses` and scan +++ /// through looking for the path that you are interested in. +++ pub fn status_file(&self, path: &Path) -> Result { +++ let mut ret = 0 as c_uint; +++ let path = path_to_repo_path(path)?; +++ unsafe { +++ try_call!(raw::git_status_file(&mut ret, self.raw, path)); +++ } +++ Ok(Status::from_bits_truncate(ret as u32)) +++ } +++ +++ /// Create an iterator which loops over the requested branches. +++ pub fn branches(&self, filter: Option) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_branch_iterator_new(&mut raw, self.raw(), filter)); +++ Ok(Branches::from_raw(raw)) +++ } +++ } +++ +++ /// Get the Index file for this repository. +++ /// +++ /// If a custom index has not been set, the default index for the repository +++ /// will be returned (the one located in .git/index). +++ /// +++ /// **Caution**: If the [`Repository`] of this index is dropped, then this +++ /// [`Index`] will become detached, and most methods on it will fail. See +++ /// [`Index::open`]. Be sure the repository has a binding such as a local +++ /// variable to keep it alive at least as long as the index. +++ pub fn index(&self) -> Result { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_repository_index(&mut raw, self.raw())); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Set the Index file for this repository. +++ pub fn set_index(&self, index: &mut Index) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_repository_set_index(self.raw(), index.raw())); +++ } +++ Ok(()) +++ } +++ +++ /// Get the configuration file for this repository. +++ /// +++ /// If a configuration file has not been set, the default config set for the +++ /// repository will be returned, including global and system configurations +++ /// (if they are available). +++ pub fn config(&self) -> Result { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_repository_config(&mut raw, self.raw())); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Get the value of a git attribute for a path as a string. +++ /// +++ /// This function will return a special string if the attribute is set to a special value. +++ /// Interpreting the special string is discouraged. You should always use +++ /// [`AttrValue::from_string`](crate::AttrValue::from_string) to interpret the return value +++ /// and avoid the special string. +++ /// +++ /// As such, the return type of this function will probably be changed in the next major version +++ /// to prevent interpreting the returned string without checking whether it's special. +++ pub fn get_attr( +++ &self, +++ path: &Path, +++ name: &str, +++ flags: AttrCheckFlags, +++ ) -> Result, Error> { +++ Ok(self +++ .get_attr_bytes(path, name, flags)? +++ .and_then(|a| str::from_utf8(a).ok())) +++ } +++ +++ /// Get the value of a git attribute for a path as a byte slice. +++ /// +++ /// This function will return a special byte slice if the attribute is set to a special value. +++ /// Interpreting the special byte slice is discouraged. You should always use +++ /// [`AttrValue::from_bytes`](crate::AttrValue::from_bytes) to interpret the return value and +++ /// avoid the special string. +++ /// +++ /// As such, the return type of this function will probably be changed in the next major version +++ /// to prevent interpreting the returned byte slice without checking whether it's special. +++ pub fn get_attr_bytes( +++ &self, +++ path: &Path, +++ name: &str, +++ flags: AttrCheckFlags, +++ ) -> Result, Error> { +++ let mut ret = ptr::null(); +++ let path = util::cstring_to_repo_path(path)?; +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_attr_get( +++ &mut ret, +++ self.raw(), +++ flags.bits(), +++ path, +++ name +++ )); +++ Ok(crate::opt_bytes(self, ret)) +++ } +++ } +++ +++ /// Write an in-memory buffer to the ODB as a blob. +++ /// +++ /// The Oid returned can in turn be passed to `find_blob` to get a handle to +++ /// the blob. +++ pub fn blob(&self, data: &[u8]) -> Result { +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ let ptr = data.as_ptr() as *const c_void; +++ let len = data.len() as size_t; +++ try_call!(raw::git_blob_create_frombuffer( +++ &mut raw, +++ self.raw(), +++ ptr, +++ len +++ )); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++ +++ /// Read a file from the filesystem and write its content to the Object +++ /// Database as a loose blob +++ /// +++ /// The Oid returned can in turn be passed to `find_blob` to get a handle to +++ /// the blob. +++ pub fn blob_path(&self, path: &Path) -> Result { +++ // Normal file path OK (does not need Windows conversion). +++ let path = path.into_c_string()?; +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_blob_create_fromdisk(&mut raw, self.raw(), path)); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++ +++ /// Create a stream to write blob +++ /// +++ /// This function may need to buffer the data on disk and will in general +++ /// not be the right choice if you know the size of the data to write. +++ /// +++ /// Use `BlobWriter::commit()` to commit the write to the object db +++ /// and get the object id. +++ /// +++ /// If the `hintpath` parameter is filled, it will be used to determine +++ /// what git filters should be applied to the object before it is written +++ /// to the object database. +++ pub fn blob_writer(&self, hintpath: Option<&Path>) -> Result, Error> { +++ let path_str = match hintpath { +++ Some(path) => Some(path.into_c_string()?), +++ None => None, +++ }; +++ let path = match path_str { +++ Some(ref path) => path.as_ptr(), +++ None => ptr::null(), +++ }; +++ let mut out = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_blob_create_fromstream(&mut out, self.raw(), path)); +++ Ok(BlobWriter::from_raw(out)) +++ } +++ } +++ +++ /// Lookup a reference to one of the objects in a repository. +++ pub fn find_blob(&self, oid: Oid) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_blob_lookup(&mut raw, self.raw(), oid.raw())); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Get the object database for this repository +++ pub fn odb(&self) -> Result, Error> { +++ let mut odb = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_repository_odb(&mut odb, self.raw())); +++ Ok(Odb::from_raw(odb)) +++ } +++ } +++ +++ /// Override the object database for this repository +++ pub fn set_odb(&self, odb: &Odb<'_>) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_repository_set_odb(self.raw(), odb.raw())); +++ } +++ Ok(()) +++ } +++ +++ /// Create a new branch pointing at a target commit +++ /// +++ /// A new direct reference will be created pointing to this target commit. +++ /// If `force` is true and a reference already exists with the given name, +++ /// it'll be replaced. +++ pub fn branch( +++ &self, +++ branch_name: &str, +++ target: &Commit<'_>, +++ force: bool, +++ ) -> Result, Error> { +++ let branch_name = CString::new(branch_name)?; +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_branch_create( +++ &mut raw, +++ self.raw(), +++ branch_name, +++ target.raw(), +++ force +++ )); +++ Ok(Branch::wrap(Binding::from_raw(raw))) +++ } +++ } +++ +++ /// Create a new branch pointing at a target commit +++ /// +++ /// This behaves like `Repository::branch()` but takes +++ /// an annotated commit, which lets you specify which +++ /// extended SHA syntax string was specified by a user, +++ /// allowing for more exact reflog messages. +++ /// +++ /// See the documentation for `Repository::branch()` +++ pub fn branch_from_annotated_commit( +++ &self, +++ branch_name: &str, +++ target: &AnnotatedCommit<'_>, +++ force: bool, +++ ) -> Result, Error> { +++ let branch_name = CString::new(branch_name)?; +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_branch_create_from_annotated( +++ &mut raw, +++ self.raw(), +++ branch_name, +++ target.raw(), +++ force +++ )); +++ Ok(Branch::wrap(Binding::from_raw(raw))) +++ } +++ } +++ +++ /// Lookup a branch by its name in a repository. +++ pub fn find_branch(&self, name: &str, branch_type: BranchType) -> Result, Error> { +++ let name = CString::new(name)?; +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_branch_lookup( +++ &mut ret, +++ self.raw(), +++ name, +++ branch_type +++ )); +++ Ok(Branch::wrap(Binding::from_raw(ret))) +++ } +++ } +++ +++ /// Create new commit in the repository +++ /// +++ /// If the `update_ref` is not `None`, name of the reference that will be +++ /// updated to point to this commit. If the reference is not direct, it will +++ /// be resolved to a direct reference. Use "HEAD" to update the HEAD of the +++ /// current branch and make it point to this commit. If the reference +++ /// doesn't exist yet, it will be created. If it does exist, the first +++ /// parent must be the tip of this branch. +++ pub fn commit( +++ &self, +++ update_ref: Option<&str>, +++ author: &Signature<'_>, +++ committer: &Signature<'_>, +++ message: &str, +++ tree: &Tree<'_>, +++ parents: &[&Commit<'_>], +++ ) -> Result { +++ let update_ref = crate::opt_cstr(update_ref)?; +++ let mut parent_ptrs = parents +++ .iter() +++ .map(|p| p.raw() as *const raw::git_commit) +++ .collect::>(); +++ let message = CString::new(message)?; +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_commit_create( +++ &mut raw, +++ self.raw(), +++ update_ref, +++ author.raw(), +++ committer.raw(), +++ ptr::null(), +++ message, +++ tree.raw(), +++ parents.len() as size_t, +++ parent_ptrs.as_mut_ptr() +++ )); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++ +++ /// Create a commit object and return that as a Buf. +++ /// +++ /// That can be converted to a string like this `str::from_utf8(&buf).unwrap().to_string()`. +++ /// And that string can be passed to the `commit_signed` function, +++ /// the arguments behave the same as in the `commit` function. +++ pub fn commit_create_buffer( +++ &self, +++ author: &Signature<'_>, +++ committer: &Signature<'_>, +++ message: &str, +++ tree: &Tree<'_>, +++ parents: &[&Commit<'_>], +++ ) -> Result { +++ let mut parent_ptrs = parents +++ .iter() +++ .map(|p| p.raw() as *const raw::git_commit) +++ .collect::>(); +++ let message = CString::new(message)?; +++ let buf = Buf::new(); +++ unsafe { +++ try_call!(raw::git_commit_create_buffer( +++ buf.raw(), +++ self.raw(), +++ author.raw(), +++ committer.raw(), +++ ptr::null(), +++ message, +++ tree.raw(), +++ parents.len() as size_t, +++ parent_ptrs.as_mut_ptr() +++ )); +++ Ok(buf) +++ } +++ } +++ +++ /// Create a commit object from the given buffer and signature +++ /// +++ /// Given the unsigned commit object's contents, its signature and the +++ /// header field in which to store the signature, attach the signature to +++ /// the commit and write it into the given repository. +++ /// +++ /// Use `None` in `signature_field` to use the default of `gpgsig`, which is +++ /// almost certainly what you want. +++ /// +++ /// Returns the resulting (signed) commit id. +++ pub fn commit_signed( +++ &self, +++ commit_content: &str, +++ signature: &str, +++ signature_field: Option<&str>, +++ ) -> Result { +++ let commit_content = CString::new(commit_content)?; +++ let signature = CString::new(signature)?; +++ let signature_field = crate::opt_cstr(signature_field)?; +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_commit_create_with_signature( +++ &mut raw, +++ self.raw(), +++ commit_content, +++ signature, +++ signature_field +++ )); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++ +++ /// Extract the signature from a commit +++ /// +++ /// Returns a tuple containing the signature in the first value and the +++ /// signed data in the second. +++ pub fn extract_signature( +++ &self, +++ commit_id: &Oid, +++ signature_field: Option<&str>, +++ ) -> Result<(Buf, Buf), Error> { +++ let signature_field = crate::opt_cstr(signature_field)?; +++ let signature = Buf::new(); +++ let content = Buf::new(); +++ unsafe { +++ try_call!(raw::git_commit_extract_signature( +++ signature.raw(), +++ content.raw(), +++ self.raw(), +++ commit_id.raw() as *mut _, +++ signature_field +++ )); +++ Ok((signature, content)) +++ } +++ } +++ +++ /// Lookup a reference to one of the commits in a repository. +++ pub fn find_commit(&self, oid: Oid) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_commit_lookup(&mut raw, self.raw(), oid.raw())); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Lookup a reference to one of the commits in a repository by short hash. +++ pub fn find_commit_by_prefix(&self, prefix_hash: &str) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_commit_lookup_prefix( +++ &mut raw, +++ self.raw(), +++ Oid::from_str(prefix_hash)?.raw(), +++ prefix_hash.len() +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Creates an `AnnotatedCommit` from the given commit id. +++ pub fn find_annotated_commit(&self, id: Oid) -> Result, Error> { +++ unsafe { +++ let mut raw = ptr::null_mut(); +++ try_call!(raw::git_annotated_commit_lookup( +++ &mut raw, +++ self.raw(), +++ id.raw() +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Lookup a reference to one of the objects in a repository. +++ pub fn find_object(&self, oid: Oid, kind: Option) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_object_lookup( +++ &mut raw, +++ self.raw(), +++ oid.raw(), +++ kind +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Lookup a reference to one of the objects by id prefix in a repository. +++ pub fn find_object_by_prefix( +++ &self, +++ prefix_hash: &str, +++ kind: Option, +++ ) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_object_lookup_prefix( +++ &mut raw, +++ self.raw(), +++ Oid::from_str(prefix_hash)?.raw(), +++ prefix_hash.len(), +++ kind +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Create a new direct reference. +++ /// +++ /// This function will return an error if a reference already exists with +++ /// the given name unless force is true, in which case it will be +++ /// overwritten. +++ pub fn reference( +++ &self, +++ name: &str, +++ id: Oid, +++ force: bool, +++ log_message: &str, +++ ) -> Result, Error> { +++ let name = CString::new(name)?; +++ let log_message = CString::new(log_message)?; +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_reference_create( +++ &mut raw, +++ self.raw(), +++ name, +++ id.raw(), +++ force, +++ log_message +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Conditionally create new direct reference. +++ /// +++ /// A direct reference (also called an object id reference) refers directly +++ /// to a specific object id (a.k.a. OID or SHA) in the repository. The id +++ /// permanently refers to the object (although the reference itself can be +++ /// moved). For example, in libgit2 the direct ref "refs/tags/v0.17.0" +++ /// refers to OID 5b9fac39d8a76b9139667c26a63e6b3f204b3977. +++ /// +++ /// The direct reference will be created in the repository and written to +++ /// the disk. +++ /// +++ /// Valid reference names must follow one of two patterns: +++ /// +++ /// 1. Top-level names must contain only capital letters and underscores, +++ /// and must begin and end with a letter. (e.g. "HEAD", "ORIG_HEAD"). +++ /// 2. Names prefixed with "refs/" can be almost anything. You must avoid +++ /// the characters `~`, `^`, `:`, `\\`, `?`, `[`, and `*`, and the +++ /// sequences ".." and "@{" which have special meaning to revparse. +++ /// +++ /// This function will return an error if a reference already exists with +++ /// the given name unless `force` is true, in which case it will be +++ /// overwritten. +++ /// +++ /// The message for the reflog will be ignored if the reference does not +++ /// belong in the standard set (HEAD, branches and remote-tracking +++ /// branches) and it does not have a reflog. +++ /// +++ /// It will return GIT_EMODIFIED if the reference's value at the time of +++ /// updating does not match the one passed through `current_id` (i.e. if the +++ /// ref has changed since the user read it). +++ pub fn reference_matching( +++ &self, +++ name: &str, +++ id: Oid, +++ force: bool, +++ current_id: Oid, +++ log_message: &str, +++ ) -> Result, Error> { +++ let name = CString::new(name)?; +++ let log_message = CString::new(log_message)?; +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_reference_create_matching( +++ &mut raw, +++ self.raw(), +++ name, +++ id.raw(), +++ force, +++ current_id.raw(), +++ log_message +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Create a new symbolic reference. +++ /// +++ /// A symbolic reference is a reference name that refers to another +++ /// reference name. If the other name moves, the symbolic name will move, +++ /// too. As a simple example, the "HEAD" reference might refer to +++ /// "refs/heads/master" while on the "master" branch of a repository. +++ /// +++ /// Valid reference names must follow one of two patterns: +++ /// +++ /// 1. Top-level names must contain only capital letters and underscores, +++ /// and must begin and end with a letter. (e.g. "HEAD", "ORIG_HEAD"). +++ /// 2. Names prefixed with "refs/" can be almost anything. You must avoid +++ /// the characters '~', '^', ':', '\\', '?', '[', and '*', and the +++ /// sequences ".." and "@{" which have special meaning to revparse. +++ /// +++ /// This function will return an error if a reference already exists with +++ /// the given name unless force is true, in which case it will be +++ /// overwritten. +++ pub fn reference_symbolic( +++ &self, +++ name: &str, +++ target: &str, +++ force: bool, +++ log_message: &str, +++ ) -> Result, Error> { +++ let name = CString::new(name)?; +++ let target = CString::new(target)?; +++ let log_message = CString::new(log_message)?; +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_reference_symbolic_create( +++ &mut raw, +++ self.raw(), +++ name, +++ target, +++ force, +++ log_message +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Create a new symbolic reference. +++ /// +++ /// This function will return an error if a reference already exists with +++ /// the given name unless force is true, in which case it will be +++ /// overwritten. +++ /// +++ /// It will return GIT_EMODIFIED if the reference's value at the time of +++ /// updating does not match the one passed through current_value (i.e. if +++ /// the ref has changed since the user read it). +++ pub fn reference_symbolic_matching( +++ &self, +++ name: &str, +++ target: &str, +++ force: bool, +++ current_value: &str, +++ log_message: &str, +++ ) -> Result, Error> { +++ let name = CString::new(name)?; +++ let target = CString::new(target)?; +++ let current_value = CString::new(current_value)?; +++ let log_message = CString::new(log_message)?; +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_reference_symbolic_create_matching( +++ &mut raw, +++ self.raw(), +++ name, +++ target, +++ force, +++ current_value, +++ log_message +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Lookup a reference to one of the objects in a repository. +++ pub fn find_reference(&self, name: &str) -> Result, Error> { +++ let name = CString::new(name)?; +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_reference_lookup(&mut raw, self.raw(), name)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Lookup a reference to one of the objects in a repository. +++ /// `Repository::find_reference` with teeth; give the method your reference in +++ /// human-readable format e.g. 'main' instead of 'refs/heads/main', and it +++ /// will do-what-you-mean, returning the `Reference`. +++ pub fn resolve_reference_from_short_name(&self, refname: &str) -> Result, Error> { +++ let refname = CString::new(refname)?; +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_reference_dwim(&mut raw, self.raw(), refname)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Lookup a reference by name and resolve immediately to OID. +++ /// +++ /// This function provides a quick way to resolve a reference name straight +++ /// through to the object id that it refers to. This avoids having to +++ /// allocate or free any `Reference` objects for simple situations. +++ pub fn refname_to_id(&self, name: &str) -> Result { +++ let name = CString::new(name)?; +++ let mut ret = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_reference_name_to_id(&mut ret, self.raw(), name)); +++ Ok(Binding::from_raw(&ret as *const _)) +++ } +++ } +++ +++ /// Creates a git_annotated_commit from the given reference. +++ pub fn reference_to_annotated_commit( +++ &self, +++ reference: &Reference<'_>, +++ ) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_annotated_commit_from_ref( +++ &mut ret, +++ self.raw(), +++ reference.raw() +++ )); +++ Ok(AnnotatedCommit::from_raw(ret)) +++ } +++ } +++ +++ /// Creates a git_annotated_commit from FETCH_HEAD. +++ pub fn annotated_commit_from_fetchhead( +++ &self, +++ branch_name: &str, +++ remote_url: &str, +++ id: &Oid, +++ ) -> Result, Error> { +++ let branch_name = CString::new(branch_name)?; +++ let remote_url = CString::new(remote_url)?; +++ +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_annotated_commit_from_fetchhead( +++ &mut ret, +++ self.raw(), +++ branch_name, +++ remote_url, +++ id.raw() +++ )); +++ Ok(AnnotatedCommit::from_raw(ret)) +++ } +++ } +++ +++ /// Create a new action signature with default user and now timestamp. +++ /// +++ /// This looks up the user.name and user.email from the configuration and +++ /// uses the current time as the timestamp, and creates a new signature +++ /// based on that information. It will return `NotFound` if either the +++ /// user.name or user.email are not set. +++ pub fn signature(&self) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_signature_default(&mut ret, self.raw())); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Set up a new git submodule for checkout. +++ /// +++ /// This does "git submodule add" up to the fetch and checkout of the +++ /// submodule contents. It preps a new submodule, creates an entry in +++ /// `.gitmodules` and creates an empty initialized repository either at the +++ /// given path in the working directory or in `.git/modules` with a gitlink +++ /// from the working directory to the new repo. +++ /// +++ /// To fully emulate "git submodule add" call this function, then `open()` +++ /// the submodule repo and perform the clone step as needed. Lastly, call +++ /// `add_finalize()` to wrap up adding the new submodule and `.gitmodules` +++ /// to the index to be ready to commit. +++ pub fn submodule( +++ &self, +++ url: &str, +++ path: &Path, +++ use_gitlink: bool, +++ ) -> Result, Error> { +++ let url = CString::new(url)?; +++ let path = path_to_repo_path(path)?; +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_submodule_add_setup( +++ &mut raw, +++ self.raw(), +++ url, +++ path, +++ use_gitlink +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Lookup submodule information by name or path. +++ /// +++ /// Given either the submodule name or path (they are usually the same), +++ /// this returns a structure describing the submodule. +++ pub fn find_submodule(&self, name: &str) -> Result, Error> { +++ let name = CString::new(name)?; +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_submodule_lookup(&mut raw, self.raw(), name)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Get the status for a submodule. +++ /// +++ /// This looks at a submodule and tries to determine the status. It +++ /// will return a combination of the `SubmoduleStatus` values. +++ pub fn submodule_status( +++ &self, +++ name: &str, +++ ignore: SubmoduleIgnore, +++ ) -> Result { +++ let mut ret = 0; +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_submodule_status(&mut ret, self.raw, name, ignore)); +++ } +++ Ok(SubmoduleStatus::from_bits_truncate(ret as u32)) +++ } +++ +++ /// Set the ignore rule for the submodule in the configuration +++ /// +++ /// This does not affect any currently-loaded instances. +++ pub fn submodule_set_ignore( +++ &mut self, +++ name: &str, +++ ignore: SubmoduleIgnore, +++ ) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_submodule_set_ignore(self.raw(), name, ignore)); +++ } +++ Ok(()) +++ } +++ +++ /// Set the update rule for the submodule in the configuration +++ /// +++ /// This setting won't affect any existing instances. +++ pub fn submodule_set_update( +++ &mut self, +++ name: &str, +++ update: SubmoduleUpdate, +++ ) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_submodule_set_update(self.raw(), name, update)); +++ } +++ Ok(()) +++ } +++ +++ /// Set the URL for the submodule in the configuration +++ /// +++ /// After calling this, you may wish to call [`Submodule::sync`] to write +++ /// the changes to the checked out submodule repository. +++ pub fn submodule_set_url(&mut self, name: &str, url: &str) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ let url = CString::new(url)?; +++ unsafe { +++ try_call!(raw::git_submodule_set_url(self.raw(), name, url)); +++ } +++ Ok(()) +++ } +++ +++ /// Set the branch for the submodule in the configuration +++ /// +++ /// After calling this, you may wish to call [`Submodule::sync`] to write +++ /// the changes to the checked out submodule repository. +++ pub fn submodule_set_branch(&mut self, name: &str, branch_name: &str) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ let branch_name = CString::new(branch_name)?; +++ unsafe { +++ try_call!(raw::git_submodule_set_branch(self.raw(), name, branch_name)); +++ } +++ Ok(()) +++ } +++ +++ /// Lookup a reference to one of the objects in a repository. +++ pub fn find_tree(&self, oid: Oid) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_tree_lookup(&mut raw, self.raw(), oid.raw())); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Create a new TreeBuilder, optionally initialized with the +++ /// entries of the given Tree. +++ /// +++ /// The tree builder can be used to create or modify trees in memory and +++ /// write them as tree objects to the database. +++ pub fn treebuilder(&self, tree: Option<&Tree<'_>>) -> Result, Error> { +++ unsafe { +++ let mut ret = ptr::null_mut(); +++ let tree = match tree { +++ Some(tree) => tree.raw(), +++ None => ptr::null_mut(), +++ }; +++ try_call!(raw::git_treebuilder_new(&mut ret, self.raw, tree)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Create a new tag in the repository from an object +++ /// +++ /// A new reference will also be created pointing to this tag object. If +++ /// `force` is true and a reference already exists with the given name, +++ /// it'll be replaced. +++ /// +++ /// The message will not be cleaned up. +++ /// +++ /// The tag name will be checked for validity. You must avoid the characters +++ /// '~', '^', ':', ' \ ', '?', '[', and '*', and the sequences ".." and " @ +++ /// {" which have special meaning to revparse. +++ pub fn tag( +++ &self, +++ name: &str, +++ target: &Object<'_>, +++ tagger: &Signature<'_>, +++ message: &str, +++ force: bool, +++ ) -> Result { +++ let name = CString::new(name)?; +++ let message = CString::new(message)?; +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_tag_create( +++ &mut raw, +++ self.raw, +++ name, +++ target.raw(), +++ tagger.raw(), +++ message, +++ force +++ )); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++ +++ /// Create a new tag in the repository from an object without creating a reference. +++ /// +++ /// The message will not be cleaned up. +++ /// +++ /// The tag name will be checked for validity. You must avoid the characters +++ /// '~', '^', ':', ' \ ', '?', '[', and '*', and the sequences ".." and " @ +++ /// {" which have special meaning to revparse. +++ pub fn tag_annotation_create( +++ &self, +++ name: &str, +++ target: &Object<'_>, +++ tagger: &Signature<'_>, +++ message: &str, +++ ) -> Result { +++ let name = CString::new(name)?; +++ let message = CString::new(message)?; +++ let mut raw_oid = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_tag_annotation_create( +++ &mut raw_oid, +++ self.raw, +++ name, +++ target.raw(), +++ tagger.raw(), +++ message +++ )); +++ Ok(Binding::from_raw(&raw_oid as *const _)) +++ } +++ } +++ +++ /// Create a new lightweight tag pointing at a target object +++ /// +++ /// A new direct reference will be created pointing to this target object. +++ /// If force is true and a reference already exists with the given name, +++ /// it'll be replaced. +++ pub fn tag_lightweight( +++ &self, +++ name: &str, +++ target: &Object<'_>, +++ force: bool, +++ ) -> Result { +++ let name = CString::new(name)?; +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_tag_create_lightweight( +++ &mut raw, +++ self.raw, +++ name, +++ target.raw(), +++ force +++ )); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++ +++ /// Lookup a tag object from the repository. +++ pub fn find_tag(&self, id: Oid) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_tag_lookup(&mut raw, self.raw, id.raw())); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Lookup a tag object by prefix hash from the repository. +++ pub fn find_tag_by_prefix(&self, prefix_hash: &str) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_tag_lookup_prefix( +++ &mut raw, +++ self.raw, +++ Oid::from_str(prefix_hash)?.raw(), +++ prefix_hash.len() +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Delete an existing tag reference. +++ /// +++ /// The tag name will be checked for validity, see `tag` for some rules +++ /// about valid names. +++ pub fn tag_delete(&self, name: &str) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_tag_delete(self.raw, name)); +++ Ok(()) +++ } +++ } +++ +++ /// Get a list with all the tags in the repository. +++ /// +++ /// An optional fnmatch pattern can also be specified. +++ pub fn tag_names(&self, pattern: Option<&str>) -> Result { +++ let mut arr = raw::git_strarray { +++ strings: ptr::null_mut(), +++ count: 0, +++ }; +++ unsafe { +++ match pattern { +++ Some(s) => { +++ let s = CString::new(s)?; +++ try_call!(raw::git_tag_list_match(&mut arr, s, self.raw)); +++ } +++ None => { +++ try_call!(raw::git_tag_list(&mut arr, self.raw)); +++ } +++ } +++ Ok(Binding::from_raw(arr)) +++ } +++ } +++ +++ /// iterate over all tags calling `cb` on each. +++ /// the callback is provided the tag id and name +++ pub fn tag_foreach(&self, cb: T) -> Result<(), Error> +++ where +++ T: FnMut(Oid, &[u8]) -> bool, +++ { +++ let mut data = TagForeachData { +++ cb: Box::new(cb) as TagForeachCB<'_>, +++ }; +++ +++ unsafe { +++ raw::git_tag_foreach( +++ self.raw, +++ Some(tag_foreach_cb), +++ (&mut data) as *mut _ as *mut _, +++ ); +++ } +++ Ok(()) +++ } +++ +++ /// Updates files in the index and the working tree to match the content of +++ /// the commit pointed at by HEAD. +++ pub fn checkout_head(&self, opts: Option<&mut CheckoutBuilder<'_>>) -> Result<(), Error> { +++ unsafe { +++ let mut raw_opts = mem::zeroed(); +++ try_call!(raw::git_checkout_init_options( +++ &mut raw_opts, +++ raw::GIT_CHECKOUT_OPTIONS_VERSION +++ )); +++ if let Some(c) = opts { +++ c.configure(&mut raw_opts); +++ } +++ +++ try_call!(raw::git_checkout_head(self.raw, &raw_opts)); +++ } +++ Ok(()) +++ } +++ +++ /// Updates files in the working tree to match the content of the index. +++ /// +++ /// If the index is `None`, the repository's index will be used. +++ pub fn checkout_index( +++ &self, +++ index: Option<&mut Index>, +++ opts: Option<&mut CheckoutBuilder<'_>>, +++ ) -> Result<(), Error> { +++ unsafe { +++ let mut raw_opts = mem::zeroed(); +++ try_call!(raw::git_checkout_init_options( +++ &mut raw_opts, +++ raw::GIT_CHECKOUT_OPTIONS_VERSION +++ )); +++ if let Some(c) = opts { +++ c.configure(&mut raw_opts); +++ } +++ +++ try_call!(raw::git_checkout_index( +++ self.raw, +++ index.map(|i| &mut *i.raw()), +++ &raw_opts +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Updates files in the index and working tree to match the content of the +++ /// tree pointed at by the treeish. +++ pub fn checkout_tree( +++ &self, +++ treeish: &Object<'_>, +++ opts: Option<&mut CheckoutBuilder<'_>>, +++ ) -> Result<(), Error> { +++ unsafe { +++ let mut raw_opts = mem::zeroed(); +++ try_call!(raw::git_checkout_init_options( +++ &mut raw_opts, +++ raw::GIT_CHECKOUT_OPTIONS_VERSION +++ )); +++ if let Some(c) = opts { +++ c.configure(&mut raw_opts); +++ } +++ +++ try_call!(raw::git_checkout_tree(self.raw, &*treeish.raw(), &raw_opts)); +++ } +++ Ok(()) +++ } +++ +++ /// Merges the given commit(s) into HEAD, writing the results into the +++ /// working directory. Any changes are staged for commit and any conflicts +++ /// are written to the index. Callers should inspect the repository's index +++ /// after this completes, resolve any conflicts and prepare a commit. +++ /// +++ /// For compatibility with git, the repository is put into a merging state. +++ /// Once the commit is done (or if the user wishes to abort), you should +++ /// clear this state by calling cleanup_state(). +++ pub fn merge( +++ &self, +++ annotated_commits: &[&AnnotatedCommit<'_>], +++ merge_opts: Option<&mut MergeOptions>, +++ checkout_opts: Option<&mut CheckoutBuilder<'_>>, +++ ) -> Result<(), Error> { +++ unsafe { +++ let mut raw_checkout_opts = mem::zeroed(); +++ try_call!(raw::git_checkout_init_options( +++ &mut raw_checkout_opts, +++ raw::GIT_CHECKOUT_OPTIONS_VERSION +++ )); +++ if let Some(c) = checkout_opts { +++ c.configure(&mut raw_checkout_opts); +++ } +++ +++ let mut commit_ptrs = annotated_commits +++ .iter() +++ .map(|c| c.raw() as *const raw::git_annotated_commit) +++ .collect::>(); +++ +++ try_call!(raw::git_merge( +++ self.raw, +++ commit_ptrs.as_mut_ptr(), +++ annotated_commits.len() as size_t, +++ merge_opts.map(|o| o.raw()).unwrap_or(ptr::null()), +++ &raw_checkout_opts +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Merge two commits, producing an index that reflects the result of +++ /// the merge. The index may be written as-is to the working directory or +++ /// checked out. If the index is to be converted to a tree, the caller +++ /// should resolve any conflicts that arose as part of the merge. +++ pub fn merge_commits( +++ &self, +++ our_commit: &Commit<'_>, +++ their_commit: &Commit<'_>, +++ opts: Option<&MergeOptions>, +++ ) -> Result { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_merge_commits( +++ &mut raw, +++ self.raw, +++ our_commit.raw(), +++ their_commit.raw(), +++ opts.map(|o| o.raw()) +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Merge two trees, producing an index that reflects the result of +++ /// the merge. The index may be written as-is to the working directory or +++ /// checked out. If the index is to be converted to a tree, the caller +++ /// should resolve any conflicts that arose as part of the merge. +++ pub fn merge_trees( +++ &self, +++ ancestor_tree: &Tree<'_>, +++ our_tree: &Tree<'_>, +++ their_tree: &Tree<'_>, +++ opts: Option<&MergeOptions>, +++ ) -> Result { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_merge_trees( +++ &mut raw, +++ self.raw, +++ ancestor_tree.raw(), +++ our_tree.raw(), +++ their_tree.raw(), +++ opts.map(|o| o.raw()) +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Remove all the metadata associated with an ongoing command like merge, +++ /// revert, cherry-pick, etc. For example: MERGE_HEAD, MERGE_MSG, etc. +++ pub fn cleanup_state(&self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_repository_state_cleanup(self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Analyzes the given branch(es) and determines the opportunities for +++ /// merging them into the HEAD of the repository. +++ pub fn merge_analysis( +++ &self, +++ their_heads: &[&AnnotatedCommit<'_>], +++ ) -> Result<(MergeAnalysis, MergePreference), Error> { +++ unsafe { +++ let mut raw_merge_analysis = 0 as raw::git_merge_analysis_t; +++ let mut raw_merge_preference = 0 as raw::git_merge_preference_t; +++ let mut their_heads = their_heads +++ .iter() +++ .map(|v| v.raw() as *const _) +++ .collect::>(); +++ try_call!(raw::git_merge_analysis( +++ &mut raw_merge_analysis, +++ &mut raw_merge_preference, +++ self.raw, +++ their_heads.as_mut_ptr() as *mut _, +++ their_heads.len() +++ )); +++ Ok(( +++ MergeAnalysis::from_bits_truncate(raw_merge_analysis as u32), +++ MergePreference::from_bits_truncate(raw_merge_preference as u32), +++ )) +++ } +++ } +++ +++ /// Analyzes the given branch(es) and determines the opportunities for +++ /// merging them into a reference. +++ pub fn merge_analysis_for_ref( +++ &self, +++ our_ref: &Reference<'_>, +++ their_heads: &[&AnnotatedCommit<'_>], +++ ) -> Result<(MergeAnalysis, MergePreference), Error> { +++ unsafe { +++ let mut raw_merge_analysis = 0 as raw::git_merge_analysis_t; +++ let mut raw_merge_preference = 0 as raw::git_merge_preference_t; +++ let mut their_heads = their_heads +++ .iter() +++ .map(|v| v.raw() as *const _) +++ .collect::>(); +++ try_call!(raw::git_merge_analysis_for_ref( +++ &mut raw_merge_analysis, +++ &mut raw_merge_preference, +++ self.raw, +++ our_ref.raw(), +++ their_heads.as_mut_ptr() as *mut _, +++ their_heads.len() +++ )); +++ Ok(( +++ MergeAnalysis::from_bits_truncate(raw_merge_analysis as u32), +++ MergePreference::from_bits_truncate(raw_merge_preference as u32), +++ )) +++ } +++ } +++ +++ /// Initializes a rebase operation to rebase the changes in `branch` +++ /// relative to `upstream` onto another branch. To begin the rebase process, +++ /// call `next()`. +++ pub fn rebase( +++ &self, +++ branch: Option<&AnnotatedCommit<'_>>, +++ upstream: Option<&AnnotatedCommit<'_>>, +++ onto: Option<&AnnotatedCommit<'_>>, +++ opts: Option<&mut RebaseOptions<'_>>, +++ ) -> Result, Error> { +++ let mut rebase: *mut raw::git_rebase = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_rebase_init( +++ &mut rebase, +++ self.raw(), +++ branch.map(|c| c.raw()), +++ upstream.map(|c| c.raw()), +++ onto.map(|c| c.raw()), +++ opts.map(|o| o.raw()).unwrap_or(ptr::null()) +++ )); +++ +++ Ok(Rebase::from_raw(rebase)) +++ } +++ } +++ +++ /// Opens an existing rebase that was previously started by either an +++ /// invocation of `rebase()` or by another client. +++ pub fn open_rebase(&self, opts: Option<&mut RebaseOptions<'_>>) -> Result, Error> { +++ let mut rebase: *mut raw::git_rebase = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_rebase_open( +++ &mut rebase, +++ self.raw(), +++ opts.map(|o| o.raw()).unwrap_or(ptr::null()) +++ )); +++ Ok(Rebase::from_raw(rebase)) +++ } +++ } +++ +++ /// Add a note for an object +++ /// +++ /// The `notes_ref` argument is the canonical name of the reference to use, +++ /// defaulting to "refs/notes/commits". If `force` is specified then +++ /// previous notes are overwritten. +++ pub fn note( +++ &self, +++ author: &Signature<'_>, +++ committer: &Signature<'_>, +++ notes_ref: Option<&str>, +++ oid: Oid, +++ note: &str, +++ force: bool, +++ ) -> Result { +++ let notes_ref = crate::opt_cstr(notes_ref)?; +++ let note = CString::new(note)?; +++ let mut ret = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_note_create( +++ &mut ret, +++ self.raw, +++ notes_ref, +++ author.raw(), +++ committer.raw(), +++ oid.raw(), +++ note, +++ force +++ )); +++ Ok(Binding::from_raw(&ret as *const _)) +++ } +++ } +++ +++ /// Get the default notes reference for this repository +++ pub fn note_default_ref(&self) -> Result { +++ let ret = Buf::new(); +++ unsafe { +++ try_call!(raw::git_note_default_ref(ret.raw(), self.raw)); +++ } +++ Ok(str::from_utf8(&ret).unwrap().to_string()) +++ } +++ +++ /// Creates a new iterator for notes in this repository. +++ /// +++ /// The `notes_ref` argument is the canonical name of the reference to use, +++ /// defaulting to "refs/notes/commits". +++ /// +++ /// The iterator returned yields pairs of (Oid, Oid) where the first element +++ /// is the id of the note and the second id is the id the note is +++ /// annotating. +++ pub fn notes(&self, notes_ref: Option<&str>) -> Result, Error> { +++ let notes_ref = crate::opt_cstr(notes_ref)?; +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_note_iterator_new(&mut ret, self.raw, notes_ref)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Read the note for an object. +++ /// +++ /// The `notes_ref` argument is the canonical name of the reference to use, +++ /// defaulting to "refs/notes/commits". +++ /// +++ /// The id specified is the Oid of the git object to read the note from. +++ pub fn find_note(&self, notes_ref: Option<&str>, id: Oid) -> Result, Error> { +++ let notes_ref = crate::opt_cstr(notes_ref)?; +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_note_read(&mut ret, self.raw, notes_ref, id.raw())); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Remove the note for an object. +++ /// +++ /// The `notes_ref` argument is the canonical name of the reference to use, +++ /// defaulting to "refs/notes/commits". +++ /// +++ /// The id specified is the Oid of the git object to remove the note from. +++ pub fn note_delete( +++ &self, +++ id: Oid, +++ notes_ref: Option<&str>, +++ author: &Signature<'_>, +++ committer: &Signature<'_>, +++ ) -> Result<(), Error> { +++ let notes_ref = crate::opt_cstr(notes_ref)?; +++ unsafe { +++ try_call!(raw::git_note_remove( +++ self.raw, +++ notes_ref, +++ author.raw(), +++ committer.raw(), +++ id.raw() +++ )); +++ Ok(()) +++ } +++ } +++ +++ /// Create a revwalk that can be used to traverse the commit graph. +++ pub fn revwalk(&self) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_revwalk_new(&mut raw, self.raw())); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Get the blame for a single file. +++ pub fn blame_file( +++ &self, +++ path: &Path, +++ opts: Option<&mut BlameOptions>, +++ ) -> Result, Error> { +++ let path = path_to_repo_path(path)?; +++ let mut raw = ptr::null_mut(); +++ +++ unsafe { +++ try_call!(raw::git_blame_file( +++ &mut raw, +++ self.raw(), +++ path, +++ opts.map(|s| s.raw()) +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Find a merge base between two commits +++ pub fn merge_base(&self, one: Oid, two: Oid) -> Result { +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_merge_base( +++ &mut raw, +++ self.raw, +++ one.raw(), +++ two.raw() +++ )); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++ +++ /// Find a merge base given a list of commits +++ /// +++ /// This behaves similar to [`git merge-base`](https://git-scm.com/docs/git-merge-base#_discussion). +++ /// Given three commits `a`, `b`, and `c`, `merge_base_many(&[a, b, c])` +++ /// will compute a hypothetical commit `m`, which is a merge between `b` +++ /// and `c`. +++ /// +++ /// For example, with the following topology: +++ /// ```text +++ /// o---o---o---o---C +++ /// / +++ /// / o---o---o---B +++ /// / / +++ /// ---2---1---o---o---o---A +++ /// ``` +++ /// +++ /// the result of `merge_base_many(&[a, b, c])` is 1. This is because the +++ /// equivalent topology with a merge commit `m` between `b` and `c` would +++ /// is: +++ /// ```text +++ /// o---o---o---o---o +++ /// / \ +++ /// / o---o---o---o---M +++ /// / / +++ /// ---2---1---o---o---o---A +++ /// ``` +++ /// +++ /// and the result of `merge_base_many(&[a, m])` is 1. +++ /// +++ /// --- +++ /// +++ /// If you're looking to recieve the common merge base between all the +++ /// given commits, use [`Self::merge_base_octopus`]. +++ pub fn merge_base_many(&self, oids: &[Oid]) -> Result { +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ +++ unsafe { +++ try_call!(raw::git_merge_base_many( +++ &mut raw, +++ self.raw, +++ oids.len() as size_t, +++ oids.as_ptr() as *const raw::git_oid +++ )); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++ +++ /// Find a common merge base between all given a list of commits +++ pub fn merge_base_octopus(&self, oids: &[Oid]) -> Result { +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ +++ unsafe { +++ try_call!(raw::git_merge_base_octopus( +++ &mut raw, +++ self.raw, +++ oids.len() as size_t, +++ oids.as_ptr() as *const raw::git_oid +++ )); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++ +++ /// Find all merge bases between two commits +++ pub fn merge_bases(&self, one: Oid, two: Oid) -> Result { +++ let mut arr = raw::git_oidarray { +++ ids: ptr::null_mut(), +++ count: 0, +++ }; +++ unsafe { +++ try_call!(raw::git_merge_bases( +++ &mut arr, +++ self.raw, +++ one.raw(), +++ two.raw() +++ )); +++ Ok(Binding::from_raw(arr)) +++ } +++ } +++ +++ /// Find all merge bases given a list of commits +++ pub fn merge_bases_many(&self, oids: &[Oid]) -> Result { +++ let mut arr = raw::git_oidarray { +++ ids: ptr::null_mut(), +++ count: 0, +++ }; +++ unsafe { +++ try_call!(raw::git_merge_bases_many( +++ &mut arr, +++ self.raw, +++ oids.len() as size_t, +++ oids.as_ptr() as *const raw::git_oid +++ )); +++ Ok(Binding::from_raw(arr)) +++ } +++ } +++ +++ /// Count the number of unique commits between two commit objects +++ /// +++ /// There is no need for branches containing the commits to have any +++ /// upstream relationship, but it helps to think of one as a branch and the +++ /// other as its upstream, the ahead and behind values will be what git +++ /// would report for the branches. +++ pub fn graph_ahead_behind(&self, local: Oid, upstream: Oid) -> Result<(usize, usize), Error> { +++ unsafe { +++ let mut ahead: size_t = 0; +++ let mut behind: size_t = 0; +++ try_call!(raw::git_graph_ahead_behind( +++ &mut ahead, +++ &mut behind, +++ self.raw(), +++ local.raw(), +++ upstream.raw() +++ )); +++ Ok((ahead as usize, behind as usize)) +++ } +++ } +++ +++ /// Determine if a commit is the descendant of another commit +++ /// +++ /// Note that a commit is not considered a descendant of itself, in contrast +++ /// to `git merge-base --is-ancestor`. +++ pub fn graph_descendant_of(&self, commit: Oid, ancestor: Oid) -> Result { +++ unsafe { +++ let rv = try_call!(raw::git_graph_descendant_of( +++ self.raw(), +++ commit.raw(), +++ ancestor.raw() +++ )); +++ Ok(rv != 0) +++ } +++ } +++ +++ /// Read the reflog for the given reference +++ /// +++ /// If there is no reflog file for the given reference yet, an empty reflog +++ /// object will be returned. +++ pub fn reflog(&self, name: &str) -> Result { +++ let name = CString::new(name)?; +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_reflog_read(&mut ret, self.raw, name)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Delete the reflog for the given reference +++ pub fn reflog_delete(&self, name: &str) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_reflog_delete(self.raw, name)); +++ } +++ Ok(()) +++ } +++ +++ /// Rename a reflog +++ /// +++ /// The reflog to be renamed is expected to already exist. +++ pub fn reflog_rename(&self, old_name: &str, new_name: &str) -> Result<(), Error> { +++ let old_name = CString::new(old_name)?; +++ let new_name = CString::new(new_name)?; +++ unsafe { +++ try_call!(raw::git_reflog_rename(self.raw, old_name, new_name)); +++ } +++ Ok(()) +++ } +++ +++ /// Check if the given reference has a reflog. +++ pub fn reference_has_log(&self, name: &str) -> Result { +++ let name = CString::new(name)?; +++ let ret = unsafe { try_call!(raw::git_reference_has_log(self.raw, name)) }; +++ Ok(ret != 0) +++ } +++ +++ /// Ensure that the given reference has a reflog. +++ pub fn reference_ensure_log(&self, name: &str) -> Result<(), Error> { +++ let name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_reference_ensure_log(self.raw, name)); +++ } +++ Ok(()) +++ } +++ +++ /// Describes a commit +++ /// +++ /// Performs a describe operation on the current commit and the worktree. +++ /// After performing a describe on HEAD, a status is run and description is +++ /// considered to be dirty if there are. +++ pub fn describe(&self, opts: &DescribeOptions) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_describe_workdir(&mut ret, self.raw, opts.raw())); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Directly run a diff on two blobs. +++ /// +++ /// Compared to a file, a blob lacks some contextual information. As such, the +++ /// `DiffFile` given to the callback will have some fake data; i.e. mode will be +++ /// 0 and path will be `None`. +++ /// +++ /// `None` is allowed for either `old_blob` or `new_blob` and will be treated +++ /// as an empty blob, with the oid set to zero in the `DiffFile`. Passing `None` +++ /// for both blobs is a noop; no callbacks will be made at all. +++ /// +++ /// We do run a binary content check on the blob content and if either blob looks +++ /// like binary data, the `DiffFile` binary attribute will be set to 1 and no call to +++ /// the `hunk_cb` nor `line_cb` will be made (unless you set the `force_text` +++ /// option). +++ pub fn diff_blobs( +++ &self, +++ old_blob: Option<&Blob<'_>>, +++ old_as_path: Option<&str>, +++ new_blob: Option<&Blob<'_>>, +++ new_as_path: Option<&str>, +++ opts: Option<&mut DiffOptions>, +++ file_cb: Option<&mut FileCb<'_>>, +++ binary_cb: Option<&mut BinaryCb<'_>>, +++ hunk_cb: Option<&mut HunkCb<'_>>, +++ line_cb: Option<&mut LineCb<'_>>, +++ ) -> Result<(), Error> { +++ let old_as_path = crate::opt_cstr(old_as_path)?; +++ let new_as_path = crate::opt_cstr(new_as_path)?; +++ let mut cbs = DiffCallbacks { +++ file: file_cb, +++ binary: binary_cb, +++ hunk: hunk_cb, +++ line: line_cb, +++ }; +++ let ptr = &mut cbs as *mut _; +++ unsafe { +++ let file_cb_c: raw::git_diff_file_cb = if cbs.file.is_some() { +++ Some(file_cb_c) +++ } else { +++ None +++ }; +++ let binary_cb_c: raw::git_diff_binary_cb = if cbs.binary.is_some() { +++ Some(binary_cb_c) +++ } else { +++ None +++ }; +++ let hunk_cb_c: raw::git_diff_hunk_cb = if cbs.hunk.is_some() { +++ Some(hunk_cb_c) +++ } else { +++ None +++ }; +++ let line_cb_c: raw::git_diff_line_cb = if cbs.line.is_some() { +++ Some(line_cb_c) +++ } else { +++ None +++ }; +++ try_call!(raw::git_diff_blobs( +++ old_blob.map(|s| s.raw()), +++ old_as_path, +++ new_blob.map(|s| s.raw()), +++ new_as_path, +++ opts.map(|s| s.raw()), +++ file_cb_c, +++ binary_cb_c, +++ hunk_cb_c, +++ line_cb_c, +++ ptr as *mut _ +++ )); +++ Ok(()) +++ } +++ } +++ +++ /// Create a diff with the difference between two tree objects. +++ /// +++ /// This is equivalent to `git diff ` +++ /// +++ /// The first tree will be used for the "old_file" side of the delta and the +++ /// second tree will be used for the "new_file" side of the delta. You can +++ /// pass `None` to indicate an empty tree, although it is an error to pass +++ /// `None` for both the `old_tree` and `new_tree`. +++ pub fn diff_tree_to_tree( +++ &self, +++ old_tree: Option<&Tree<'_>>, +++ new_tree: Option<&Tree<'_>>, +++ opts: Option<&mut DiffOptions>, +++ ) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_diff_tree_to_tree( +++ &mut ret, +++ self.raw(), +++ old_tree.map(|s| s.raw()), +++ new_tree.map(|s| s.raw()), +++ opts.map(|s| s.raw()) +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Create a diff between a tree and repository index. +++ /// +++ /// This is equivalent to `git diff --cached ` or if you pass +++ /// the HEAD tree, then like `git diff --cached`. +++ /// +++ /// The tree you pass will be used for the "old_file" side of the delta, and +++ /// the index will be used for the "new_file" side of the delta. +++ /// +++ /// If you pass `None` for the index, then the existing index of the `repo` +++ /// will be used. In this case, the index will be refreshed from disk +++ /// (if it has changed) before the diff is generated. +++ /// +++ /// If the tree is `None`, then it is considered an empty tree. +++ pub fn diff_tree_to_index( +++ &self, +++ old_tree: Option<&Tree<'_>>, +++ index: Option<&Index>, +++ opts: Option<&mut DiffOptions>, +++ ) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_diff_tree_to_index( +++ &mut ret, +++ self.raw(), +++ old_tree.map(|s| s.raw()), +++ index.map(|s| s.raw()), +++ opts.map(|s| s.raw()) +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Create a diff between two index objects. +++ /// +++ /// The first index will be used for the "old_file" side of the delta, and +++ /// the second index will be used for the "new_file" side of the delta. +++ pub fn diff_index_to_index( +++ &self, +++ old_index: &Index, +++ new_index: &Index, +++ opts: Option<&mut DiffOptions>, +++ ) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_diff_index_to_index( +++ &mut ret, +++ self.raw(), +++ old_index.raw(), +++ new_index.raw(), +++ opts.map(|s| s.raw()) +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Create a diff between the repository index and the workdir directory. +++ /// +++ /// This matches the `git diff` command. See the note below on +++ /// `tree_to_workdir` for a discussion of the difference between +++ /// `git diff` and `git diff HEAD` and how to emulate a `git diff ` +++ /// using libgit2. +++ /// +++ /// The index will be used for the "old_file" side of the delta, and the +++ /// working directory will be used for the "new_file" side of the delta. +++ /// +++ /// If you pass `None` for the index, then the existing index of the `repo` +++ /// will be used. In this case, the index will be refreshed from disk +++ /// (if it has changed) before the diff is generated. +++ pub fn diff_index_to_workdir( +++ &self, +++ index: Option<&Index>, +++ opts: Option<&mut DiffOptions>, +++ ) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_diff_index_to_workdir( +++ &mut ret, +++ self.raw(), +++ index.map(|s| s.raw()), +++ opts.map(|s| s.raw()) +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Create a diff between a tree and the working directory. +++ /// +++ /// The tree you provide will be used for the "old_file" side of the delta, +++ /// and the working directory will be used for the "new_file" side. +++ /// +++ /// This is not the same as `git diff ` or `git diff-index +++ /// `. Those commands use information from the index, whereas this +++ /// function strictly returns the differences between the tree and the files +++ /// in the working directory, regardless of the state of the index. Use +++ /// `tree_to_workdir_with_index` to emulate those commands. +++ /// +++ /// To see difference between this and `tree_to_workdir_with_index`, +++ /// consider the example of a staged file deletion where the file has then +++ /// been put back into the working dir and further modified. The +++ /// tree-to-workdir diff for that file is 'modified', but `git diff` would +++ /// show status 'deleted' since there is a staged delete. +++ /// +++ /// If `None` is passed for `tree`, then an empty tree is used. +++ pub fn diff_tree_to_workdir( +++ &self, +++ old_tree: Option<&Tree<'_>>, +++ opts: Option<&mut DiffOptions>, +++ ) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_diff_tree_to_workdir( +++ &mut ret, +++ self.raw(), +++ old_tree.map(|s| s.raw()), +++ opts.map(|s| s.raw()) +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Create a diff between a tree and the working directory using index data +++ /// to account for staged deletes, tracked files, etc. +++ /// +++ /// This emulates `git diff ` by diffing the tree to the index and +++ /// the index to the working directory and blending the results into a +++ /// single diff that includes staged deleted, etc. +++ pub fn diff_tree_to_workdir_with_index( +++ &self, +++ old_tree: Option<&Tree<'_>>, +++ opts: Option<&mut DiffOptions>, +++ ) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_diff_tree_to_workdir_with_index( +++ &mut ret, +++ self.raw(), +++ old_tree.map(|s| s.raw()), +++ opts.map(|s| s.raw()) +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Create a PackBuilder +++ pub fn packbuilder(&self) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_packbuilder_new(&mut ret, self.raw())); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Save the local modifications to a new stash. +++ pub fn stash_save( +++ &mut self, +++ stasher: &Signature<'_>, +++ message: &str, +++ flags: Option, +++ ) -> Result { +++ self.stash_save2(stasher, Some(message), flags) +++ } +++ +++ /// Save the local modifications to a new stash. +++ /// unlike `stash_save` it allows to pass a null `message` +++ pub fn stash_save2( +++ &mut self, +++ stasher: &Signature<'_>, +++ message: Option<&str>, +++ flags: Option, +++ ) -> Result { +++ unsafe { +++ let mut raw_oid = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ let message = crate::opt_cstr(message)?; +++ let flags = flags.unwrap_or_else(StashFlags::empty); +++ try_call!(raw::git_stash_save( +++ &mut raw_oid, +++ self.raw(), +++ stasher.raw(), +++ message, +++ flags.bits() as c_uint +++ )); +++ Ok(Binding::from_raw(&raw_oid as *const _)) +++ } +++ } +++ +++ /// Like `stash_save` but with more options like selective statshing via path patterns. +++ pub fn stash_save_ext( +++ &mut self, +++ opts: Option<&mut StashSaveOptions<'_>>, +++ ) -> Result { +++ unsafe { +++ let mut raw_oid = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ let opts = opts.map(|opts| opts.raw()); +++ try_call!(raw::git_stash_save_with_opts( +++ &mut raw_oid, +++ self.raw(), +++ opts +++ )); +++ Ok(Binding::from_raw(&raw_oid as *const _)) +++ } +++ } +++ +++ /// Apply a single stashed state from the stash list. +++ pub fn stash_apply( +++ &mut self, +++ index: usize, +++ opts: Option<&mut StashApplyOptions<'_>>, +++ ) -> Result<(), Error> { +++ unsafe { +++ let opts = opts.map(|opts| opts.raw()); +++ try_call!(raw::git_stash_apply(self.raw(), index, opts)); +++ Ok(()) +++ } +++ } +++ +++ /// Loop over all the stashed states and issue a callback for each one. +++ /// +++ /// Return `true` to continue iterating or `false` to stop. +++ pub fn stash_foreach(&mut self, mut callback: C) -> Result<(), Error> +++ where +++ C: FnMut(usize, &str, &Oid) -> bool, +++ { +++ unsafe { +++ let mut data = StashCbData { +++ callback: &mut callback, +++ }; +++ let cb: raw::git_stash_cb = Some(stash_cb); +++ try_call!(raw::git_stash_foreach( +++ self.raw(), +++ cb, +++ &mut data as *mut _ as *mut _ +++ )); +++ Ok(()) +++ } +++ } +++ +++ /// Remove a single stashed state from the stash list. +++ pub fn stash_drop(&mut self, index: usize) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_stash_drop(self.raw(), index)); +++ Ok(()) +++ } +++ } +++ +++ /// Apply a single stashed state from the stash list and remove it from the list if successful. +++ pub fn stash_pop( +++ &mut self, +++ index: usize, +++ opts: Option<&mut StashApplyOptions<'_>>, +++ ) -> Result<(), Error> { +++ unsafe { +++ let opts = opts.map(|opts| opts.raw()); +++ try_call!(raw::git_stash_pop(self.raw(), index, opts)); +++ Ok(()) +++ } +++ } +++ +++ /// Add ignore rules for a repository. +++ /// +++ /// The format of the rules is the same one of the .gitignore file. +++ pub fn add_ignore_rule(&self, rules: &str) -> Result<(), Error> { +++ let rules = CString::new(rules)?; +++ unsafe { +++ try_call!(raw::git_ignore_add_rule(self.raw, rules)); +++ } +++ Ok(()) +++ } +++ +++ /// Clear ignore rules that were explicitly added. +++ pub fn clear_ignore_rules(&self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_ignore_clear_internal_rules(self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Test if the ignore rules apply to a given path. +++ pub fn is_path_ignored>(&self, path: P) -> Result { +++ let path = util::cstring_to_repo_path(path.as_ref())?; +++ let mut ignored: c_int = 0; +++ unsafe { +++ try_call!(raw::git_ignore_path_is_ignored( +++ &mut ignored, +++ self.raw, +++ path +++ )); +++ } +++ Ok(ignored == 1) +++ } +++ +++ /// Perform a cherrypick +++ pub fn cherrypick( +++ &self, +++ commit: &Commit<'_>, +++ options: Option<&mut CherrypickOptions<'_>>, +++ ) -> Result<(), Error> { +++ let raw_opts = options.map(|o| o.raw()); +++ let ptr_raw_opts = match raw_opts.as_ref() { +++ Some(v) => v, +++ None => std::ptr::null(), +++ }; +++ unsafe { +++ try_call!(raw::git_cherrypick(self.raw(), commit.raw(), ptr_raw_opts)); +++ +++ Ok(()) +++ } +++ } +++ +++ /// Create an index of uncommitted changes, representing the result of +++ /// cherry-picking. +++ pub fn cherrypick_commit( +++ &self, +++ cherrypick_commit: &Commit<'_>, +++ our_commit: &Commit<'_>, +++ mainline: u32, +++ options: Option<&MergeOptions>, +++ ) -> Result { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_cherrypick_commit( +++ &mut ret, +++ self.raw(), +++ cherrypick_commit.raw(), +++ our_commit.raw(), +++ mainline, +++ options.map(|o| o.raw()) +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Find the remote name of a remote-tracking branch +++ pub fn branch_remote_name(&self, refname: &str) -> Result { +++ let refname = CString::new(refname)?; +++ unsafe { +++ let buf = Buf::new(); +++ try_call!(raw::git_branch_remote_name(buf.raw(), self.raw, refname)); +++ Ok(buf) +++ } +++ } +++ +++ /// Retrieves the name of the reference supporting the remote tracking branch, +++ /// given the name of a local branch reference. +++ pub fn branch_upstream_name(&self, refname: &str) -> Result { +++ let refname = CString::new(refname)?; +++ unsafe { +++ let buf = Buf::new(); +++ try_call!(raw::git_branch_upstream_name(buf.raw(), self.raw, refname)); +++ Ok(buf) +++ } +++ } +++ +++ /// Retrieve the name of the upstream remote of a local branch. +++ /// +++ /// `refname` must be in the form `refs/heads/{branch_name}` +++ pub fn branch_upstream_remote(&self, refname: &str) -> Result { +++ let refname = CString::new(refname)?; +++ unsafe { +++ let buf = Buf::new(); +++ try_call!(raw::git_branch_upstream_remote( +++ buf.raw(), +++ self.raw, +++ refname +++ )); +++ Ok(buf) +++ } +++ } +++ +++ /// Apply a Diff to the given repo, making changes directly in the working directory, the index, or both. +++ pub fn apply( +++ &self, +++ diff: &Diff<'_>, +++ location: ApplyLocation, +++ options: Option<&mut ApplyOptions<'_>>, +++ ) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_apply( +++ self.raw, +++ diff.raw(), +++ location.raw(), +++ options.map(|s| s.raw()).unwrap_or(ptr::null()) +++ )); +++ +++ Ok(()) +++ } +++ } +++ +++ /// Apply a Diff to the provided tree, and return the resulting Index. +++ pub fn apply_to_tree( +++ &self, +++ tree: &Tree<'_>, +++ diff: &Diff<'_>, +++ options: Option<&mut ApplyOptions<'_>>, +++ ) -> Result { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_apply_to_tree( +++ &mut ret, +++ self.raw, +++ tree.raw(), +++ diff.raw(), +++ options.map(|s| s.raw()).unwrap_or(ptr::null()) +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Reverts the given commit, producing changes in the index and working directory. +++ pub fn revert( +++ &self, +++ commit: &Commit<'_>, +++ options: Option<&mut RevertOptions<'_>>, +++ ) -> Result<(), Error> { +++ let raw_opts = options.map(|o| o.raw()); +++ let ptr_raw_opts = match raw_opts.as_ref() { +++ Some(v) => v, +++ None => 0 as *const _, +++ }; +++ unsafe { +++ try_call!(raw::git_revert(self.raw(), commit.raw(), ptr_raw_opts)); +++ Ok(()) +++ } +++ } +++ +++ /// Reverts the given commit against the given "our" commit, +++ /// producing an index that reflects the result of the revert. +++ pub fn revert_commit( +++ &self, +++ revert_commit: &Commit<'_>, +++ our_commit: &Commit<'_>, +++ mainline: u32, +++ options: Option<&MergeOptions>, +++ ) -> Result { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_revert_commit( +++ &mut ret, +++ self.raw(), +++ revert_commit.raw(), +++ our_commit.raw(), +++ mainline, +++ options.map(|o| o.raw()) +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Lists all the worktrees for the repository +++ pub fn worktrees(&self) -> Result { +++ let mut arr = raw::git_strarray { +++ strings: ptr::null_mut(), +++ count: 0, +++ }; +++ unsafe { +++ try_call!(raw::git_worktree_list(&mut arr, self.raw)); +++ Ok(Binding::from_raw(arr)) +++ } +++ } +++ +++ /// Opens a worktree by name for the given repository +++ /// +++ /// This can open any worktree that the worktrees method returns. +++ pub fn find_worktree(&self, name: &str) -> Result { +++ let mut raw = ptr::null_mut(); +++ let raw_name = CString::new(name)?; +++ unsafe { +++ try_call!(raw::git_worktree_lookup(&mut raw, self.raw, raw_name)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Creates a new worktree for the repository +++ pub fn worktree<'a>( +++ &'a self, +++ name: &str, +++ path: &Path, +++ opts: Option<&WorktreeAddOptions<'a>>, +++ ) -> Result { +++ let mut raw = ptr::null_mut(); +++ let raw_name = CString::new(name)?; +++ let raw_path = path.into_c_string()?; +++ +++ unsafe { +++ try_call!(raw::git_worktree_add( +++ &mut raw, +++ self.raw, +++ raw_name, +++ raw_path, +++ opts.map(|o| o.raw()) +++ )); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Create a new transaction +++ pub fn transaction<'a>(&'a self) -> Result, Error> { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_transaction_new(&mut raw, self.raw)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Gets this repository's mailmap. +++ pub fn mailmap(&self) -> Result { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_mailmap_from_repository(&mut ret, self.raw)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// If a merge is in progress, invoke 'callback' for each commit ID in the +++ /// MERGE_HEAD file. +++ pub fn mergehead_foreach(&mut self, mut callback: C) -> Result<(), Error> +++ where +++ C: FnMut(&Oid) -> bool, +++ { +++ unsafe { +++ let mut data = MergeheadForeachCbData { +++ callback: &mut callback, +++ }; +++ let cb: raw::git_repository_mergehead_foreach_cb = Some(mergehead_foreach_cb); +++ try_call!(raw::git_repository_mergehead_foreach( +++ self.raw(), +++ cb, +++ &mut data as *mut _ as *mut _ +++ )); +++ Ok(()) +++ } +++ } +++ +++ /// Invoke 'callback' for each entry in the given FETCH_HEAD file. +++ /// +++ /// `callback` will be called with with following arguments: +++ /// +++ /// - `&str`: the reference name +++ /// - `&[u8]`: the remote URL +++ /// - `&Oid`: the reference target OID +++ /// - `bool`: was the reference the result of a merge +++ pub fn fetchhead_foreach(&self, mut callback: C) -> Result<(), Error> +++ where +++ C: FnMut(&str, &[u8], &Oid, bool) -> bool, +++ { +++ unsafe { +++ let mut data = FetchheadForeachCbData { +++ callback: &mut callback, +++ }; +++ let cb: raw::git_repository_fetchhead_foreach_cb = Some(fetchhead_foreach_cb); +++ try_call!(raw::git_repository_fetchhead_foreach( +++ self.raw(), +++ cb, +++ &mut data as *mut _ as *mut _ +++ )); +++ Ok(()) +++ } +++ } +++} +++ +++impl Binding for Repository { +++ type Raw = *mut raw::git_repository; +++ unsafe fn from_raw(ptr: *mut raw::git_repository) -> Repository { +++ Repository { raw: ptr } +++ } +++ fn raw(&self) -> *mut raw::git_repository { +++ self.raw +++ } +++} +++ +++impl Drop for Repository { +++ fn drop(&mut self) { +++ unsafe { raw::git_repository_free(self.raw) } +++ } +++} +++ +++impl RepositoryInitOptions { +++ /// Creates a default set of initialization options. +++ /// +++ /// By default this will set flags for creating all necessary directories +++ /// and initializing a directory from the user-configured templates path. +++ pub fn new() -> RepositoryInitOptions { +++ RepositoryInitOptions { +++ flags: raw::GIT_REPOSITORY_INIT_MKDIR as u32 +++ | raw::GIT_REPOSITORY_INIT_MKPATH as u32 +++ | raw::GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE as u32, +++ mode: 0, +++ workdir_path: None, +++ description: None, +++ template_path: None, +++ initial_head: None, +++ origin_url: None, +++ } +++ } +++ +++ /// Create a bare repository with no working directory. +++ /// +++ /// Defaults to false. +++ pub fn bare(&mut self, bare: bool) -> &mut RepositoryInitOptions { +++ self.flag(raw::GIT_REPOSITORY_INIT_BARE, bare) +++ } +++ +++ /// Return an error if the repository path appears to already be a git +++ /// repository. +++ /// +++ /// Defaults to false. +++ pub fn no_reinit(&mut self, enabled: bool) -> &mut RepositoryInitOptions { +++ self.flag(raw::GIT_REPOSITORY_INIT_NO_REINIT, enabled) +++ } +++ +++ /// Normally a '/.git/' will be appended to the repo path for non-bare repos +++ /// (if it is not already there), but passing this flag prevents that +++ /// behavior. +++ /// +++ /// Defaults to false. +++ pub fn no_dotgit_dir(&mut self, enabled: bool) -> &mut RepositoryInitOptions { +++ self.flag(raw::GIT_REPOSITORY_INIT_NO_DOTGIT_DIR, enabled) +++ } +++ +++ /// Make the repo path (and workdir path) as needed. The ".git" directory +++ /// will always be created regardless of this flag. +++ /// +++ /// Defaults to true. +++ pub fn mkdir(&mut self, enabled: bool) -> &mut RepositoryInitOptions { +++ self.flag(raw::GIT_REPOSITORY_INIT_MKDIR, enabled) +++ } +++ +++ /// Recursively make all components of the repo and workdir path as +++ /// necessary. +++ /// +++ /// Defaults to true. +++ pub fn mkpath(&mut self, enabled: bool) -> &mut RepositoryInitOptions { +++ self.flag(raw::GIT_REPOSITORY_INIT_MKPATH, enabled) +++ } +++ +++ /// Set to one of the `RepositoryInit` constants, or a custom value. +++ pub fn mode(&mut self, mode: RepositoryInitMode) -> &mut RepositoryInitOptions { +++ self.mode = mode.bits(); +++ self +++ } +++ +++ /// Enable or disable using external templates. +++ /// +++ /// If enabled, then the `template_path` option will be queried first, then +++ /// `init.templatedir` from the global config, and finally +++ /// `/usr/share/git-core-templates` will be used (if it exists). +++ /// +++ /// Defaults to true. +++ pub fn external_template(&mut self, enabled: bool) -> &mut RepositoryInitOptions { +++ self.flag(raw::GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE, enabled) +++ } +++ +++ fn flag( +++ &mut self, +++ flag: raw::git_repository_init_flag_t, +++ on: bool, +++ ) -> &mut RepositoryInitOptions { +++ if on { +++ self.flags |= flag as u32; +++ } else { +++ self.flags &= !(flag as u32); +++ } +++ self +++ } +++ +++ /// The path to the working directory. +++ /// +++ /// If this is a relative path it will be evaluated relative to the repo +++ /// path. If this is not the "natural" working directory, a .git gitlink +++ /// file will be created here linking to the repo path. +++ pub fn workdir_path(&mut self, path: &Path) -> &mut RepositoryInitOptions { +++ // Normal file path OK (does not need Windows conversion). +++ self.workdir_path = Some(path.into_c_string().unwrap()); +++ self +++ } +++ +++ /// If set, this will be used to initialize the "description" file in the +++ /// repository instead of using the template content. +++ pub fn description(&mut self, desc: &str) -> &mut RepositoryInitOptions { +++ self.description = Some(CString::new(desc).unwrap()); +++ self +++ } +++ +++ /// When the `external_template` option is set, this is the first location +++ /// to check for the template directory. +++ /// +++ /// If this is not configured, then the default locations will be searched +++ /// instead. +++ pub fn template_path(&mut self, path: &Path) -> &mut RepositoryInitOptions { +++ // Normal file path OK (does not need Windows conversion). +++ self.template_path = Some(path.into_c_string().unwrap()); +++ self +++ } +++ +++ /// The name of the head to point HEAD at. +++ /// +++ /// If not configured, this will be taken from your git configuration. +++ /// If this begins with `refs/` it will be used verbatim; +++ /// otherwise `refs/heads/` will be prefixed +++ pub fn initial_head(&mut self, head: &str) -> &mut RepositoryInitOptions { +++ self.initial_head = Some(CString::new(head).unwrap()); +++ self +++ } +++ +++ /// If set, then after the rest of the repository initialization is +++ /// completed an `origin` remote will be added pointing to this URL. +++ pub fn origin_url(&mut self, url: &str) -> &mut RepositoryInitOptions { +++ self.origin_url = Some(CString::new(url).unwrap()); +++ self +++ } +++ +++ /// Creates a set of raw init options to be used with +++ /// `git_repository_init_ext`. +++ /// +++ /// This method is unsafe as the returned value may have pointers to the +++ /// interior of this structure. +++ pub unsafe fn raw(&self) -> raw::git_repository_init_options { +++ let mut opts = mem::zeroed(); +++ assert_eq!( +++ raw::git_repository_init_init_options( +++ &mut opts, +++ raw::GIT_REPOSITORY_INIT_OPTIONS_VERSION +++ ), +++ 0 +++ ); +++ opts.flags = self.flags; +++ opts.mode = self.mode; +++ opts.workdir_path = crate::call::convert(&self.workdir_path); +++ opts.description = crate::call::convert(&self.description); +++ opts.template_path = crate::call::convert(&self.template_path); +++ opts.initial_head = crate::call::convert(&self.initial_head); +++ opts.origin_url = crate::call::convert(&self.origin_url); +++ opts +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::build::CheckoutBuilder; +++ use crate::CherrypickOptions; +++ use crate::{ +++ ObjectType, Oid, Repository, ResetType, Signature, SubmoduleIgnore, SubmoduleUpdate, +++ }; +++ use std::ffi::OsStr; +++ use std::fs; +++ use std::path::Path; +++ use tempfile::TempDir; +++ +++ #[test] +++ fn smoke_init() { +++ let td = TempDir::new().unwrap(); +++ let path = td.path(); +++ +++ let repo = Repository::init(path).unwrap(); +++ assert!(!repo.is_bare()); +++ } +++ +++ #[test] +++ fn smoke_init_bare() { +++ let td = TempDir::new().unwrap(); +++ let path = td.path(); +++ +++ let repo = Repository::init_bare(path).unwrap(); +++ assert!(repo.is_bare()); +++ assert!(repo.namespace().is_none()); +++ } +++ +++ #[test] +++ fn smoke_open() { +++ let td = TempDir::new().unwrap(); +++ let path = td.path(); +++ Repository::init(td.path()).unwrap(); +++ let repo = Repository::open(path).unwrap(); +++ assert!(!repo.is_bare()); +++ assert!(!repo.is_shallow()); +++ assert!(repo.is_empty().unwrap()); +++ assert_eq!( +++ crate::test::realpath(&repo.path()).unwrap(), +++ crate::test::realpath(&td.path().join(".git/")).unwrap() +++ ); +++ assert_eq!(repo.state(), crate::RepositoryState::Clean); +++ } +++ +++ #[test] +++ fn smoke_open_bare() { +++ let td = TempDir::new().unwrap(); +++ let path = td.path(); +++ Repository::init_bare(td.path()).unwrap(); +++ +++ let repo = Repository::open(path).unwrap(); +++ assert!(repo.is_bare()); +++ assert_eq!( +++ crate::test::realpath(&repo.path()).unwrap(), +++ crate::test::realpath(&td.path().join("")).unwrap() +++ ); +++ } +++ +++ #[test] +++ fn smoke_checkout() { +++ let (_td, repo) = crate::test::repo_init(); +++ repo.checkout_head(None).unwrap(); +++ } +++ +++ #[test] +++ fn smoke_revparse() { +++ let (_td, repo) = crate::test::repo_init(); +++ let rev = repo.revparse("HEAD").unwrap(); +++ assert!(rev.to().is_none()); +++ let from = rev.from().unwrap(); +++ assert!(rev.from().is_some()); +++ +++ assert_eq!(repo.revparse_single("HEAD").unwrap().id(), from.id()); +++ let obj = repo.find_object(from.id(), None).unwrap().clone(); +++ obj.peel(ObjectType::Any).unwrap(); +++ obj.short_id().unwrap(); +++ repo.reset(&obj, ResetType::Hard, None).unwrap(); +++ let mut opts = CheckoutBuilder::new(); +++ t!(repo.reset(&obj, ResetType::Soft, Some(&mut opts))); +++ } +++ +++ #[test] +++ fn makes_dirs() { +++ let td = TempDir::new().unwrap(); +++ Repository::init(&td.path().join("a/b/c/d")).unwrap(); +++ } +++ +++ #[test] +++ fn smoke_discover() { +++ let td = TempDir::new().unwrap(); +++ let subdir = td.path().join("subdi"); +++ fs::create_dir(&subdir).unwrap(); +++ Repository::init_bare(td.path()).unwrap(); +++ let repo = Repository::discover(&subdir).unwrap(); +++ assert_eq!( +++ crate::test::realpath(&repo.path()).unwrap(), +++ crate::test::realpath(&td.path().join("")).unwrap() +++ ); +++ } +++ +++ #[test] +++ fn smoke_discover_path() { +++ let td = TempDir::new().unwrap(); +++ let subdir = td.path().join("subdi"); +++ fs::create_dir(&subdir).unwrap(); +++ Repository::init_bare(td.path()).unwrap(); +++ let path = Repository::discover_path(&subdir, &[] as &[&OsStr]).unwrap(); +++ assert_eq!( +++ crate::test::realpath(&path).unwrap(), +++ crate::test::realpath(&td.path().join("")).unwrap() +++ ); +++ } +++ +++ #[test] +++ fn smoke_discover_path_ceiling_dir() { +++ let td = TempDir::new().unwrap(); +++ let subdir = td.path().join("subdi"); +++ fs::create_dir(&subdir).unwrap(); +++ let ceilingdir = subdir.join("ceiling"); +++ fs::create_dir(&ceilingdir).unwrap(); +++ let testdir = ceilingdir.join("testdi"); +++ fs::create_dir(&testdir).unwrap(); +++ Repository::init_bare(td.path()).unwrap(); +++ let path = Repository::discover_path(&testdir, &[ceilingdir.as_os_str()]); +++ +++ assert!(path.is_err()); +++ } +++ +++ #[test] +++ fn smoke_open_ext() { +++ let td = TempDir::new().unwrap(); +++ let subdir = td.path().join("subdir"); +++ fs::create_dir(&subdir).unwrap(); +++ Repository::init(td.path()).unwrap(); +++ +++ let repo = Repository::open_ext( +++ &subdir, +++ crate::RepositoryOpenFlags::empty(), +++ &[] as &[&OsStr], +++ ) +++ .unwrap(); +++ assert!(!repo.is_bare()); +++ assert_eq!( +++ crate::test::realpath(&repo.path()).unwrap(), +++ crate::test::realpath(&td.path().join(".git")).unwrap() +++ ); +++ +++ let repo = +++ Repository::open_ext(&subdir, crate::RepositoryOpenFlags::BARE, &[] as &[&OsStr]) +++ .unwrap(); +++ assert!(repo.is_bare()); +++ assert_eq!( +++ crate::test::realpath(&repo.path()).unwrap(), +++ crate::test::realpath(&td.path().join(".git")).unwrap() +++ ); +++ +++ let err = Repository::open_ext( +++ &subdir, +++ crate::RepositoryOpenFlags::NO_SEARCH, +++ &[] as &[&OsStr], +++ ) +++ .err() +++ .unwrap(); +++ assert_eq!(err.code(), crate::ErrorCode::NotFound); +++ +++ assert!( +++ Repository::open_ext(&subdir, crate::RepositoryOpenFlags::empty(), &[&subdir]).is_ok() +++ ); +++ } +++ +++ fn graph_repo_init() -> (TempDir, Repository) { +++ let (_td, repo) = crate::test::repo_init(); +++ { +++ let head = repo.head().unwrap().target().unwrap(); +++ let head = repo.find_commit(head).unwrap(); +++ +++ let mut index = repo.index().unwrap(); +++ let id = index.write_tree().unwrap(); +++ +++ let tree = repo.find_tree(id).unwrap(); +++ let sig = repo.signature().unwrap(); +++ repo.commit(Some("HEAD"), &sig, &sig, "second", &tree, &[&head]) +++ .unwrap(); +++ } +++ (_td, repo) +++ } +++ +++ #[test] +++ fn smoke_graph_ahead_behind() { +++ let (_td, repo) = graph_repo_init(); +++ let head = repo.head().unwrap().target().unwrap(); +++ let head = repo.find_commit(head).unwrap(); +++ let head_id = head.id(); +++ let head_parent_id = head.parent(0).unwrap().id(); +++ let (ahead, behind) = repo.graph_ahead_behind(head_id, head_parent_id).unwrap(); +++ assert_eq!(ahead, 1); +++ assert_eq!(behind, 0); +++ let (ahead, behind) = repo.graph_ahead_behind(head_parent_id, head_id).unwrap(); +++ assert_eq!(ahead, 0); +++ assert_eq!(behind, 1); +++ } +++ +++ #[test] +++ fn smoke_graph_descendant_of() { +++ let (_td, repo) = graph_repo_init(); +++ let head = repo.head().unwrap().target().unwrap(); +++ let head = repo.find_commit(head).unwrap(); +++ let head_id = head.id(); +++ let head_parent_id = head.parent(0).unwrap().id(); +++ assert!(repo.graph_descendant_of(head_id, head_parent_id).unwrap()); +++ assert!(!repo.graph_descendant_of(head_parent_id, head_id).unwrap()); +++ } +++ +++ #[test] +++ fn smoke_reference_has_log_ensure_log() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ assert_eq!(repo.reference_has_log("HEAD").unwrap(), true); +++ assert_eq!(repo.reference_has_log("refs/heads/main").unwrap(), true); +++ assert_eq!(repo.reference_has_log("NOT_HEAD").unwrap(), false); +++ let main_oid = repo.revparse_single("main").unwrap().id(); +++ assert!(repo +++ .reference("NOT_HEAD", main_oid, false, "creating a new branch") +++ .is_ok()); +++ assert_eq!(repo.reference_has_log("NOT_HEAD").unwrap(), false); +++ assert!(repo.reference_ensure_log("NOT_HEAD").is_ok()); +++ assert_eq!(repo.reference_has_log("NOT_HEAD").unwrap(), true); +++ } +++ +++ #[test] +++ fn smoke_set_head() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ assert!(repo.set_head("refs/heads/does-not-exist").is_ok()); +++ assert!(repo.head().is_err()); +++ +++ assert!(repo.set_head("refs/heads/main").is_ok()); +++ assert!(repo.head().is_ok()); +++ +++ assert!(repo.set_head("*").is_err()); +++ } +++ +++ #[test] +++ fn smoke_set_head_bytes() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ assert!(repo.set_head_bytes(b"refs/heads/does-not-exist").is_ok()); +++ assert!(repo.head().is_err()); +++ +++ assert!(repo.set_head_bytes(b"refs/heads/main").is_ok()); +++ assert!(repo.head().is_ok()); +++ +++ assert!(repo.set_head_bytes(b"*").is_err()); +++ } +++ +++ #[test] +++ fn smoke_set_head_detached() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ let void_oid = Oid::from_bytes(b"00000000000000000000").unwrap(); +++ assert!(repo.set_head_detached(void_oid).is_err()); +++ +++ let main_oid = repo.revparse_single("main").unwrap().id(); +++ assert!(repo.set_head_detached(main_oid).is_ok()); +++ assert_eq!(repo.head().unwrap().target().unwrap(), main_oid); +++ } +++ +++ #[test] +++ fn smoke_find_object_by_prefix() { +++ let (_td, repo) = crate::test::repo_init(); +++ let head = repo.head().unwrap().target().unwrap(); +++ let head = repo.find_commit(head).unwrap(); +++ let head_id = head.id(); +++ let head_prefix = &head_id.to_string()[..7]; +++ let obj = repo.find_object_by_prefix(head_prefix, None).unwrap(); +++ assert_eq!(obj.id(), head_id); +++ } +++ +++ /// create the following: +++ /// /---o4 +++ /// /---o3 +++ /// o1---o2 +++ #[test] +++ fn smoke_merge_base() { +++ let (_td, repo) = graph_repo_init(); +++ let sig = repo.signature().unwrap(); +++ +++ // let oid1 = head +++ let oid1 = repo.head().unwrap().target().unwrap(); +++ let commit1 = repo.find_commit(oid1).unwrap(); +++ println!("created oid1 {:?}", oid1); +++ +++ repo.branch("branch_a", &commit1, true).unwrap(); +++ repo.branch("branch_b", &commit1, true).unwrap(); +++ repo.branch("branch_c", &commit1, true).unwrap(); +++ +++ // create commit oid2 on branch_a +++ let mut index = repo.index().unwrap(); +++ let p = Path::new(repo.workdir().unwrap()).join("file_a"); +++ println!("using path {:?}", p); +++ fs::File::create(&p).unwrap(); +++ index.add_path(Path::new("file_a")).unwrap(); +++ let id_a = index.write_tree().unwrap(); +++ let tree_a = repo.find_tree(id_a).unwrap(); +++ let oid2 = repo +++ .commit( +++ Some("refs/heads/branch_a"), +++ &sig, +++ &sig, +++ "commit 2", +++ &tree_a, +++ &[&commit1], +++ ) +++ .unwrap(); +++ repo.find_commit(oid2).unwrap(); +++ println!("created oid2 {:?}", oid2); +++ +++ t!(repo.reset(commit1.as_object(), ResetType::Hard, None)); +++ +++ // create commit oid3 on branch_b +++ let mut index = repo.index().unwrap(); +++ let p = Path::new(repo.workdir().unwrap()).join("file_b"); +++ fs::File::create(&p).unwrap(); +++ index.add_path(Path::new("file_b")).unwrap(); +++ let id_b = index.write_tree().unwrap(); +++ let tree_b = repo.find_tree(id_b).unwrap(); +++ let oid3 = repo +++ .commit( +++ Some("refs/heads/branch_b"), +++ &sig, +++ &sig, +++ "commit 3", +++ &tree_b, +++ &[&commit1], +++ ) +++ .unwrap(); +++ repo.find_commit(oid3).unwrap(); +++ println!("created oid3 {:?}", oid3); +++ +++ t!(repo.reset(commit1.as_object(), ResetType::Hard, None)); +++ +++ // create commit oid4 on branch_c +++ let mut index = repo.index().unwrap(); +++ let p = Path::new(repo.workdir().unwrap()).join("file_c"); +++ fs::File::create(&p).unwrap(); +++ index.add_path(Path::new("file_c")).unwrap(); +++ let id_c = index.write_tree().unwrap(); +++ let tree_c = repo.find_tree(id_c).unwrap(); +++ let oid4 = repo +++ .commit( +++ Some("refs/heads/branch_c"), +++ &sig, +++ &sig, +++ "commit 3", +++ &tree_c, +++ &[&commit1], +++ ) +++ .unwrap(); +++ repo.find_commit(oid4).unwrap(); +++ println!("created oid4 {:?}", oid4); +++ +++ // the merge base of (oid2,oid3) should be oid1 +++ let merge_base = repo.merge_base(oid2, oid3).unwrap(); +++ assert_eq!(merge_base, oid1); +++ +++ // the merge base of (oid2,oid3,oid4) should be oid1 +++ let merge_base = repo.merge_base_many(&[oid2, oid3, oid4]).unwrap(); +++ assert_eq!(merge_base, oid1); +++ +++ // the octopus merge base of (oid2,oid3,oid4) should be oid1 +++ let merge_base = repo.merge_base_octopus(&[oid2, oid3, oid4]).unwrap(); +++ assert_eq!(merge_base, oid1); +++ } +++ +++ /// create an octopus: +++ /// /---o2-o4 +++ /// o1 X +++ /// \---o3-o5 +++ /// and checks that the merge bases of (o4,o5) are (o2,o3) +++ #[test] +++ fn smoke_merge_bases() { +++ let (_td, repo) = graph_repo_init(); +++ let sig = repo.signature().unwrap(); +++ +++ // let oid1 = head +++ let oid1 = repo.head().unwrap().target().unwrap(); +++ let commit1 = repo.find_commit(oid1).unwrap(); +++ println!("created oid1 {:?}", oid1); +++ +++ repo.branch("branch_a", &commit1, true).unwrap(); +++ repo.branch("branch_b", &commit1, true).unwrap(); +++ +++ // create commit oid2 on branchA +++ let mut index = repo.index().unwrap(); +++ let p = Path::new(repo.workdir().unwrap()).join("file_a"); +++ println!("using path {:?}", p); +++ fs::File::create(&p).unwrap(); +++ index.add_path(Path::new("file_a")).unwrap(); +++ let id_a = index.write_tree().unwrap(); +++ let tree_a = repo.find_tree(id_a).unwrap(); +++ let oid2 = repo +++ .commit( +++ Some("refs/heads/branch_a"), +++ &sig, +++ &sig, +++ "commit 2", +++ &tree_a, +++ &[&commit1], +++ ) +++ .unwrap(); +++ let commit2 = repo.find_commit(oid2).unwrap(); +++ println!("created oid2 {:?}", oid2); +++ +++ t!(repo.reset(commit1.as_object(), ResetType::Hard, None)); +++ +++ // create commit oid3 on branchB +++ let mut index = repo.index().unwrap(); +++ let p = Path::new(repo.workdir().unwrap()).join("file_b"); +++ fs::File::create(&p).unwrap(); +++ index.add_path(Path::new("file_b")).unwrap(); +++ let id_b = index.write_tree().unwrap(); +++ let tree_b = repo.find_tree(id_b).unwrap(); +++ let oid3 = repo +++ .commit( +++ Some("refs/heads/branch_b"), +++ &sig, +++ &sig, +++ "commit 3", +++ &tree_b, +++ &[&commit1], +++ ) +++ .unwrap(); +++ let commit3 = repo.find_commit(oid3).unwrap(); +++ println!("created oid3 {:?}", oid3); +++ +++ // create merge commit oid4 on branchA with parents oid2 and oid3 +++ //let mut index4 = repo.merge_commits(&commit2, &commit3, None).unwrap(); +++ repo.set_head("refs/heads/branch_a").unwrap(); +++ repo.checkout_head(None).unwrap(); +++ let oid4 = repo +++ .commit( +++ Some("refs/heads/branch_a"), +++ &sig, +++ &sig, +++ "commit 4", +++ &tree_a, +++ &[&commit2, &commit3], +++ ) +++ .unwrap(); +++ //index4.write_tree_to(&repo).unwrap(); +++ println!("created oid4 {:?}", oid4); +++ +++ // create merge commit oid5 on branchB with parents oid2 and oid3 +++ //let mut index5 = repo.merge_commits(&commit3, &commit2, None).unwrap(); +++ repo.set_head("refs/heads/branch_b").unwrap(); +++ repo.checkout_head(None).unwrap(); +++ let oid5 = repo +++ .commit( +++ Some("refs/heads/branch_b"), +++ &sig, +++ &sig, +++ "commit 5", +++ &tree_a, +++ &[&commit3, &commit2], +++ ) +++ .unwrap(); +++ //index5.write_tree_to(&repo).unwrap(); +++ println!("created oid5 {:?}", oid5); +++ +++ // merge bases of (oid4,oid5) should be (oid2,oid3) +++ let merge_bases = repo.merge_bases(oid4, oid5).unwrap(); +++ let mut found_oid2 = false; +++ let mut found_oid3 = false; +++ for mg in merge_bases.iter() { +++ println!("found merge base {:?}", mg); +++ if mg == &oid2 { +++ found_oid2 = true; +++ } else if mg == &oid3 { +++ found_oid3 = true; +++ } else { +++ assert!(false); +++ } +++ } +++ assert!(found_oid2); +++ assert!(found_oid3); +++ assert_eq!(merge_bases.len(), 2); +++ +++ // merge bases of (oid4,oid5) should be (oid2,oid3) +++ let merge_bases = repo.merge_bases_many(&[oid4, oid5]).unwrap(); +++ let mut found_oid2 = false; +++ let mut found_oid3 = false; +++ for mg in merge_bases.iter() { +++ println!("found merge base {:?}", mg); +++ if mg == &oid2 { +++ found_oid2 = true; +++ } else if mg == &oid3 { +++ found_oid3 = true; +++ } else { +++ assert!(false); +++ } +++ } +++ assert!(found_oid2); +++ assert!(found_oid3); +++ assert_eq!(merge_bases.len(), 2); +++ } +++ +++ #[test] +++ fn smoke_revparse_ext() { +++ let (_td, repo) = graph_repo_init(); +++ +++ { +++ let short_refname = "main"; +++ let expected_refname = "refs/heads/main"; +++ let (obj, reference) = repo.revparse_ext(short_refname).unwrap(); +++ let expected_obj = repo.revparse_single(expected_refname).unwrap(); +++ assert_eq!(obj.id(), expected_obj.id()); +++ assert_eq!(reference.unwrap().name().unwrap(), expected_refname); +++ } +++ { +++ let missing_refname = "refs/heads/does-not-exist"; +++ assert!(repo.revparse_ext(missing_refname).is_err()); +++ } +++ { +++ let (_obj, reference) = repo.revparse_ext("HEAD^").unwrap(); +++ assert!(reference.is_none()); +++ } +++ } +++ +++ #[test] +++ fn smoke_is_path_ignored() { +++ let (_td, repo) = graph_repo_init(); +++ +++ assert!(!repo.is_path_ignored(Path::new("foo")).unwrap()); +++ +++ let _ = repo.add_ignore_rule("/foo"); +++ assert!(repo.is_path_ignored(Path::new("foo")).unwrap()); +++ if cfg!(windows) { +++ assert!(repo.is_path_ignored(Path::new("foo\\thing")).unwrap()); +++ } +++ +++ let _ = repo.clear_ignore_rules(); +++ assert!(!repo.is_path_ignored(Path::new("foo")).unwrap()); +++ if cfg!(windows) { +++ assert!(!repo.is_path_ignored(Path::new("foo\\thing")).unwrap()); +++ } +++ } +++ +++ #[test] +++ fn smoke_cherrypick() { +++ let (_td, repo) = crate::test::repo_init(); +++ let sig = repo.signature().unwrap(); +++ +++ let oid1 = repo.head().unwrap().target().unwrap(); +++ let commit1 = repo.find_commit(oid1).unwrap(); +++ +++ repo.branch("branch_a", &commit1, true).unwrap(); +++ +++ // Add 2 commits on top of the initial one in branch_a +++ let mut index = repo.index().unwrap(); +++ let p1 = Path::new(repo.workdir().unwrap()).join("file_c"); +++ fs::File::create(&p1).unwrap(); +++ index.add_path(Path::new("file_c")).unwrap(); +++ let id = index.write_tree().unwrap(); +++ let tree_c = repo.find_tree(id).unwrap(); +++ let oid2 = repo +++ .commit( +++ Some("refs/heads/branch_a"), +++ &sig, +++ &sig, +++ "commit 2", +++ &tree_c, +++ &[&commit1], +++ ) +++ .unwrap(); +++ let commit2 = repo.find_commit(oid2).unwrap(); +++ println!("created oid2 {:?}", oid2); +++ assert!(p1.exists()); +++ +++ let mut index = repo.index().unwrap(); +++ let p2 = Path::new(repo.workdir().unwrap()).join("file_d"); +++ fs::File::create(&p2).unwrap(); +++ index.add_path(Path::new("file_d")).unwrap(); +++ let id = index.write_tree().unwrap(); +++ let tree_d = repo.find_tree(id).unwrap(); +++ let oid3 = repo +++ .commit( +++ Some("refs/heads/branch_a"), +++ &sig, +++ &sig, +++ "commit 3", +++ &tree_d, +++ &[&commit2], +++ ) +++ .unwrap(); +++ let commit3 = repo.find_commit(oid3).unwrap(); +++ println!("created oid3 {:?}", oid3); +++ assert!(p1.exists()); +++ assert!(p2.exists()); +++ +++ // cherry-pick commit3 on top of commit1 in branch b +++ repo.reset(commit1.as_object(), ResetType::Hard, None) +++ .unwrap(); +++ let mut cherrypick_opts = CherrypickOptions::new(); +++ repo.cherrypick(&commit3, Some(&mut cherrypick_opts)) +++ .unwrap(); +++ let id = repo.index().unwrap().write_tree().unwrap(); +++ let tree_d = repo.find_tree(id).unwrap(); +++ let oid4 = repo +++ .commit(Some("HEAD"), &sig, &sig, "commit 4", &tree_d, &[&commit1]) +++ .unwrap(); +++ let commit4 = repo.find_commit(oid4).unwrap(); +++ // should have file from commit3, but not the file from commit2 +++ assert_eq!(commit4.parent(0).unwrap().id(), commit1.id()); +++ assert!(!p1.exists()); +++ assert!(p2.exists()); +++ } +++ +++ #[test] +++ fn smoke_revert() { +++ let (_td, repo) = crate::test::repo_init(); +++ let foo_file = Path::new(repo.workdir().unwrap()).join("foo"); +++ assert!(!foo_file.exists()); +++ +++ let (oid1, _id) = crate::test::commit(&repo); +++ let commit1 = repo.find_commit(oid1).unwrap(); +++ t!(repo.reset(commit1.as_object(), ResetType::Hard, None)); +++ assert!(foo_file.exists()); +++ +++ repo.revert(&commit1, None).unwrap(); +++ let id = repo.index().unwrap().write_tree().unwrap(); +++ let tree2 = repo.find_tree(id).unwrap(); +++ let sig = repo.signature().unwrap(); +++ repo.commit(Some("HEAD"), &sig, &sig, "commit 1", &tree2, &[&commit1]) +++ .unwrap(); +++ // reverting once removes `foo` file +++ assert!(!foo_file.exists()); +++ +++ let oid2 = repo.head().unwrap().target().unwrap(); +++ let commit2 = repo.find_commit(oid2).unwrap(); +++ repo.revert(&commit2, None).unwrap(); +++ let id = repo.index().unwrap().write_tree().unwrap(); +++ let tree3 = repo.find_tree(id).unwrap(); +++ repo.commit(Some("HEAD"), &sig, &sig, "commit 2", &tree3, &[&commit2]) +++ .unwrap(); +++ // reverting twice restores `foo` file +++ assert!(foo_file.exists()); +++ } +++ +++ #[test] +++ fn smoke_config_write_and_read() { +++ let (td, repo) = crate::test::repo_init(); +++ +++ let mut config = repo.config().unwrap(); +++ +++ config.set_bool("commit.gpgsign", false).unwrap(); +++ +++ let c = fs::read_to_string(td.path().join(".git").join("config")).unwrap(); +++ +++ assert!(c.contains("[commit]")); +++ assert!(c.contains("gpgsign = false")); +++ +++ let config = repo.config().unwrap(); +++ +++ assert!(!config.get_bool("commit.gpgsign").unwrap()); +++ } +++ +++ #[test] +++ fn smoke_merge_analysis_for_ref() -> Result<(), crate::Error> { +++ let (_td, repo) = graph_repo_init(); +++ +++ // Set up this repo state: +++ // * second (their-branch) +++ // * initial (HEAD -> main) +++ // +++ // We expect that their-branch can be fast-forward merged into main. +++ +++ // git checkout --detach HEAD +++ let head_commit = repo.head()?.peel_to_commit()?; +++ repo.set_head_detached(head_commit.id())?; +++ +++ // git branch their-branch HEAD +++ let their_branch = repo.branch("their-branch", &head_commit, false)?; +++ +++ // git branch -f main HEAD~ +++ let mut parents_iter = head_commit.parents(); +++ let parent = parents_iter.next().unwrap(); +++ assert!(parents_iter.next().is_none()); +++ +++ let main = repo.branch("main", &parent, true)?; +++ +++ // git checkout main +++ repo.set_head(main.get().name().expect("should be utf-8"))?; +++ +++ let (merge_analysis, _merge_preference) = repo.merge_analysis_for_ref( +++ main.get(), +++ &[&repo.reference_to_annotated_commit(their_branch.get())?], +++ )?; +++ +++ assert!(merge_analysis.contains(crate::MergeAnalysis::ANALYSIS_FASTFORWARD)); +++ +++ Ok(()) +++ } +++ +++ #[test] +++ fn smoke_submodule_set() -> Result<(), crate::Error> { +++ let (td1, _repo) = crate::test::repo_init(); +++ let (td2, mut repo2) = crate::test::repo_init(); +++ let url = crate::test::path2url(td1.path()); +++ let name = "bar"; +++ { +++ let mut s = repo2.submodule(&url, Path::new(name), true)?; +++ fs::remove_dir_all(td2.path().join("bar")).unwrap(); +++ Repository::clone(&url, td2.path().join("bar"))?; +++ s.add_to_index(false)?; +++ s.add_finalize()?; +++ } +++ +++ // update strategy +++ repo2.submodule_set_update(name, SubmoduleUpdate::None)?; +++ assert!(matches!( +++ repo2.find_submodule(name)?.update_strategy(), +++ SubmoduleUpdate::None +++ )); +++ repo2.submodule_set_update(name, SubmoduleUpdate::Rebase)?; +++ assert!(matches!( +++ repo2.find_submodule(name)?.update_strategy(), +++ SubmoduleUpdate::Rebase +++ )); +++ +++ // ignore rule +++ repo2.submodule_set_ignore(name, SubmoduleIgnore::Untracked)?; +++ assert!(matches!( +++ repo2.find_submodule(name)?.ignore_rule(), +++ SubmoduleIgnore::Untracked +++ )); +++ repo2.submodule_set_ignore(name, SubmoduleIgnore::Dirty)?; +++ assert!(matches!( +++ repo2.find_submodule(name)?.ignore_rule(), +++ SubmoduleIgnore::Dirty +++ )); +++ +++ // url +++ repo2.submodule_set_url(name, "fake-url")?; +++ assert_eq!(repo2.find_submodule(name)?.url(), Some("fake-url")); +++ +++ // branch +++ repo2.submodule_set_branch(name, "fake-branch")?; +++ assert_eq!(repo2.find_submodule(name)?.branch(), Some("fake-branch")); +++ +++ Ok(()) +++ } +++ +++ #[test] +++ fn smoke_mailmap_from_repository() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ let commit = { +++ let head = t!(repo.head()).target().unwrap(); +++ t!(repo.find_commit(head)) +++ }; +++ +++ // This is our baseline for HEAD. +++ let author = commit.author(); +++ let committer = commit.committer(); +++ assert_eq!(author.name(), Some("name")); +++ assert_eq!(author.email(), Some("email")); +++ assert_eq!(committer.name(), Some("name")); +++ assert_eq!(committer.email(), Some("email")); +++ +++ // There is no .mailmap file in the test repo so all signature identities are equal. +++ let mailmap = t!(repo.mailmap()); +++ let mailmapped_author = t!(commit.author_with_mailmap(&mailmap)); +++ let mailmapped_committer = t!(commit.committer_with_mailmap(&mailmap)); +++ assert_eq!(mailmapped_author.name(), author.name()); +++ assert_eq!(mailmapped_author.email(), author.email()); +++ assert_eq!(mailmapped_committer.name(), committer.name()); +++ assert_eq!(mailmapped_committer.email(), committer.email()); +++ +++ let commit = { +++ // - Add a .mailmap file to the repository. +++ // - Commit with a signature identity different from the author's. +++ // - Include entries for both author and committer to prove we call +++ // the right raw functions. +++ let mailmap_file = Path::new(".mailmap"); +++ let p = Path::new(repo.workdir().unwrap()).join(&mailmap_file); +++ t!(fs::write( +++ p, +++ r#" +++Author Name name +++Committer Name "#, +++ )); +++ let mut index = t!(repo.index()); +++ t!(index.add_path(&mailmap_file)); +++ let id_mailmap = t!(index.write_tree()); +++ let tree_mailmap = t!(repo.find_tree(id_mailmap)); +++ +++ let head = t!(repo.commit( +++ Some("HEAD"), +++ &author, +++ t!(&Signature::now("committer", "committer@email")), +++ "Add mailmap", +++ &tree_mailmap, +++ &[&commit], +++ )); +++ t!(repo.find_commit(head)) +++ }; +++ +++ // Sanity check that we're working with the right commit and that its +++ // author and committer identities differ. +++ let author = commit.author(); +++ let committer = commit.committer(); +++ assert_ne!(author.name(), committer.name()); +++ assert_ne!(author.email(), committer.email()); +++ assert_eq!(author.name(), Some("name")); +++ assert_eq!(author.email(), Some("email")); +++ assert_eq!(committer.name(), Some("committer")); +++ assert_eq!(committer.email(), Some("committer@email")); +++ +++ // Fetch the newly added .mailmap from the repository. +++ let mailmap = t!(repo.mailmap()); +++ let mailmapped_author = t!(commit.author_with_mailmap(&mailmap)); +++ let mailmapped_committer = t!(commit.committer_with_mailmap(&mailmap)); +++ +++ let mm_resolve_author = t!(mailmap.resolve_signature(&author)); +++ let mm_resolve_committer = t!(mailmap.resolve_signature(&committer)); +++ +++ // Mailmap Signature lifetime is independent of Commit lifetime. +++ drop(author); +++ drop(committer); +++ drop(commit); +++ +++ // author_with_mailmap() + committer_with_mailmap() work +++ assert_eq!(mailmapped_author.name(), Some("Author Name")); +++ assert_eq!(mailmapped_author.email(), Some("author.proper@email")); +++ assert_eq!(mailmapped_committer.name(), Some("Committer Name")); +++ assert_eq!(mailmapped_committer.email(), Some("committer.proper@email")); +++ +++ // resolve_signature() works +++ assert_eq!(mm_resolve_author.email(), mailmapped_author.email()); +++ assert_eq!(mm_resolve_committer.email(), mailmapped_committer.email()); +++ } +++ +++ #[test] +++ fn smoke_find_tag_by_prefix() { +++ let (_td, repo) = crate::test::repo_init(); +++ let head = repo.head().unwrap(); +++ let tag_oid = repo +++ .tag( +++ "tag", +++ &repo +++ .find_object(head.peel_to_commit().unwrap().id(), None) +++ .unwrap(), +++ &repo.signature().unwrap(), +++ "message", +++ false, +++ ) +++ .unwrap(); +++ let tag = repo.find_tag(tag_oid).unwrap(); +++ let found_tag = repo +++ .find_tag_by_prefix(&tag.id().to_string()[0..7]) +++ .unwrap(); +++ assert_eq!(tag.id(), found_tag.id()); +++ } +++ +++ #[test] +++ fn smoke_commondir() { +++ let (td, repo) = crate::test::repo_init(); +++ assert_eq!( +++ crate::test::realpath(repo.path()).unwrap(), +++ crate::test::realpath(repo.commondir()).unwrap() +++ ); +++ +++ let worktree = repo +++ .worktree("test", &td.path().join("worktree"), None) +++ .unwrap(); +++ let worktree_repo = Repository::open_from_worktree(&worktree).unwrap(); +++ assert_eq!( +++ crate::test::realpath(repo.path()).unwrap(), +++ crate::test::realpath(worktree_repo.commondir()).unwrap() +++ ); +++ } +++} diff --cc extra/git2/src/revert.rs index 0000000000,0000000000,0000000000..55d702600e new file mode 100644 --- /dev/null +++ b/extra/git2/src/revert.rs @@@@ -1,0 -1,0 -1,0 +1,69 @@@@ +++use std::mem; +++ +++use crate::build::CheckoutBuilder; +++use crate::merge::MergeOptions; +++use crate::raw; +++use std::ptr; +++ +++/// Options to specify when reverting +++pub struct RevertOptions<'cb> { +++ mainline: u32, +++ checkout_builder: Option>, +++ merge_opts: Option, +++} +++ +++impl<'cb> RevertOptions<'cb> { +++ /// Creates a default set of revert options +++ pub fn new() -> RevertOptions<'cb> { +++ RevertOptions { +++ mainline: 0, +++ checkout_builder: None, +++ merge_opts: None, +++ } +++ } +++ +++ /// Set the mainline value +++ /// +++ /// For merge commits, the "mainline" is treated as the parent. +++ pub fn mainline(&mut self, mainline: u32) -> &mut Self { +++ self.mainline = mainline; +++ self +++ } +++ +++ /// Set the checkout builder +++ pub fn checkout_builder(&mut self, cb: CheckoutBuilder<'cb>) -> &mut Self { +++ self.checkout_builder = Some(cb); +++ self +++ } +++ +++ /// Set the merge options +++ pub fn merge_opts(&mut self, merge_opts: MergeOptions) -> &mut Self { +++ self.merge_opts = Some(merge_opts); +++ self +++ } +++ +++ /// Obtain the raw struct +++ pub fn raw(&mut self) -> raw::git_revert_options { +++ unsafe { +++ let mut checkout_opts: raw::git_checkout_options = mem::zeroed(); +++ raw::git_checkout_init_options(&mut checkout_opts, raw::GIT_CHECKOUT_OPTIONS_VERSION); +++ if let Some(ref mut cb) = self.checkout_builder { +++ cb.configure(&mut checkout_opts); +++ } +++ +++ let mut merge_opts: raw::git_merge_options = mem::zeroed(); +++ raw::git_merge_init_options(&mut merge_opts, raw::GIT_MERGE_OPTIONS_VERSION); +++ if let Some(ref opts) = self.merge_opts { +++ ptr::copy(opts.raw(), &mut merge_opts, 1); +++ } +++ +++ let mut revert_opts: raw::git_revert_options = mem::zeroed(); +++ raw::git_revert_options_init(&mut revert_opts, raw::GIT_REVERT_OPTIONS_VERSION); +++ revert_opts.mainline = self.mainline; +++ revert_opts.checkout_opts = checkout_opts; +++ revert_opts.merge_opts = merge_opts; +++ +++ revert_opts +++ } +++ } +++} diff --cc extra/git2/src/revspec.rs index 0000000000,0000000000,0000000000..d2e08670af new file mode 100644 --- /dev/null +++ b/extra/git2/src/revspec.rs @@@@ -1,0 -1,0 -1,0 +1,34 @@@@ +++use crate::{Object, RevparseMode}; +++ +++/// A revspec represents a range of revisions within a repository. +++pub struct Revspec<'repo> { +++ from: Option>, +++ to: Option>, +++ mode: RevparseMode, +++} +++ +++impl<'repo> Revspec<'repo> { +++ /// Assembles a new revspec from the from/to components. +++ pub fn from_objects( +++ from: Option>, +++ to: Option>, +++ mode: RevparseMode, +++ ) -> Revspec<'repo> { +++ Revspec { from, to, mode } +++ } +++ +++ /// Access the `from` range of this revspec. +++ pub fn from(&self) -> Option<&Object<'repo>> { +++ self.from.as_ref() +++ } +++ +++ /// Access the `to` range of this revspec. +++ pub fn to(&self) -> Option<&Object<'repo>> { +++ self.to.as_ref() +++ } +++ +++ /// Returns the intent of the revspec. +++ pub fn mode(&self) -> RevparseMode { +++ self.mode +++ } +++} diff --cc extra/git2/src/revwalk.rs index 0000000000,0000000000,0000000000..7837f00d63 new file mode 100644 --- /dev/null +++ b/extra/git2/src/revwalk.rs @@@@ -1,0 -1,0 -1,0 +1,316 @@@@ +++use libc::{c_int, c_uint, c_void}; +++use std::ffi::CString; +++use std::marker; +++ +++use crate::util::Binding; +++use crate::{panic, raw, Error, Oid, Repository, Sort}; +++ +++/// A revwalk allows traversal of the commit graph defined by including one or +++/// more leaves and excluding one or more roots. +++pub struct Revwalk<'repo> { +++ raw: *mut raw::git_revwalk, +++ _marker: marker::PhantomData<&'repo Repository>, +++} +++ +++/// A `Revwalk` with an associated "hide callback", see `with_hide_callback` +++pub struct RevwalkWithHideCb<'repo, 'cb, C> +++where +++ C: FnMut(Oid) -> bool, +++{ +++ revwalk: Revwalk<'repo>, +++ _marker: marker::PhantomData<&'cb C>, +++} +++ +++extern "C" fn revwalk_hide_cb(commit_id: *const raw::git_oid, payload: *mut c_void) -> c_int +++where +++ C: FnMut(Oid) -> bool, +++{ +++ panic::wrap(|| unsafe { +++ let hide_cb = payload as *mut C; +++ if (*hide_cb)(Oid::from_raw(commit_id)) { +++ 1 +++ } else { +++ 0 +++ } +++ }) +++ .unwrap_or(-1) +++} +++ +++impl<'repo, 'cb, C: FnMut(Oid) -> bool> RevwalkWithHideCb<'repo, 'cb, C> { +++ /// Consumes the `RevwalkWithHideCb` and returns the contained `Revwalk`. +++ /// +++ /// Note that this will reset the `Revwalk`. +++ pub fn into_inner(mut self) -> Result, Error> { +++ self.revwalk.reset()?; +++ Ok(self.revwalk) +++ } +++} +++ +++impl<'repo> Revwalk<'repo> { +++ /// Reset a revwalk to allow re-configuring it. +++ /// +++ /// The revwalk is automatically reset when iteration of its commits +++ /// completes. +++ pub fn reset(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_revwalk_reset(self.raw())); +++ } +++ Ok(()) +++ } +++ +++ /// Set the order in which commits are visited. +++ pub fn set_sorting(&mut self, sort_mode: Sort) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_revwalk_sorting( +++ self.raw(), +++ sort_mode.bits() as c_uint +++ )); +++ } +++ Ok(()) +++ } +++ +++ /// Simplify the history by first-parent +++ /// +++ /// No parents other than the first for each commit will be enqueued. +++ pub fn simplify_first_parent(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_revwalk_simplify_first_parent(self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Mark a commit to start traversal from. +++ /// +++ /// The given OID must belong to a commitish on the walked repository. +++ /// +++ /// The given commit will be used as one of the roots when starting the +++ /// revision walk. At least one commit must be pushed onto the walker before +++ /// a walk can be started. +++ pub fn push(&mut self, oid: Oid) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_revwalk_push(self.raw(), oid.raw())); +++ } +++ Ok(()) +++ } +++ +++ /// Push the repository's HEAD +++ /// +++ /// For more information, see `push`. +++ pub fn push_head(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_revwalk_push_head(self.raw())); +++ } +++ Ok(()) +++ } +++ +++ /// Push matching references +++ /// +++ /// The OIDs pointed to by the references that match the given glob pattern +++ /// will be pushed to the revision walker. +++ /// +++ /// A leading 'refs/' is implied if not present as well as a trailing `/ \ +++ /// *` if the glob lacks '?', ' \ *' or '['. +++ /// +++ /// Any references matching this glob which do not point to a commitish +++ /// will be ignored. +++ pub fn push_glob(&mut self, glob: &str) -> Result<(), Error> { +++ let glob = CString::new(glob)?; +++ unsafe { +++ try_call!(raw::git_revwalk_push_glob(self.raw, glob)); +++ } +++ Ok(()) +++ } +++ +++ /// Push and hide the respective endpoints of the given range. +++ /// +++ /// The range should be of the form `..` where each +++ /// `` is in the form accepted by `revparse_single`. The left-hand +++ /// commit will be hidden and the right-hand commit pushed. +++ pub fn push_range(&mut self, range: &str) -> Result<(), Error> { +++ let range = CString::new(range)?; +++ unsafe { +++ try_call!(raw::git_revwalk_push_range(self.raw, range)); +++ } +++ Ok(()) +++ } +++ +++ /// Push the OID pointed to by a reference +++ /// +++ /// The reference must point to a commitish. +++ pub fn push_ref(&mut self, reference: &str) -> Result<(), Error> { +++ let reference = CString::new(reference)?; +++ unsafe { +++ try_call!(raw::git_revwalk_push_ref(self.raw, reference)); +++ } +++ Ok(()) +++ } +++ +++ /// Mark a commit as not of interest to this revwalk. +++ pub fn hide(&mut self, oid: Oid) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_revwalk_hide(self.raw(), oid.raw())); +++ } +++ Ok(()) +++ } +++ +++ /// Hide all commits for which the callback returns true from +++ /// the walk. +++ pub fn with_hide_callback<'cb, C>( +++ self, +++ callback: &'cb mut C, +++ ) -> Result, Error> +++ where +++ C: FnMut(Oid) -> bool, +++ { +++ let r = RevwalkWithHideCb { +++ revwalk: self, +++ _marker: marker::PhantomData, +++ }; +++ unsafe { +++ raw::git_revwalk_add_hide_cb( +++ r.revwalk.raw(), +++ Some(revwalk_hide_cb::), +++ callback as *mut _ as *mut c_void, +++ ); +++ }; +++ Ok(r) +++ } +++ +++ /// Hide the repository's HEAD +++ /// +++ /// For more information, see `hide`. +++ pub fn hide_head(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_revwalk_hide_head(self.raw())); +++ } +++ Ok(()) +++ } +++ +++ /// Hide matching references. +++ /// +++ /// The OIDs pointed to by the references that match the given glob pattern +++ /// and their ancestors will be hidden from the output on the revision walk. +++ /// +++ /// A leading 'refs/' is implied if not present as well as a trailing `/ \ +++ /// *` if the glob lacks '?', ' \ *' or '['. +++ /// +++ /// Any references matching this glob which do not point to a commitish +++ /// will be ignored. +++ pub fn hide_glob(&mut self, glob: &str) -> Result<(), Error> { +++ let glob = CString::new(glob)?; +++ unsafe { +++ try_call!(raw::git_revwalk_hide_glob(self.raw, glob)); +++ } +++ Ok(()) +++ } +++ +++ /// Hide the OID pointed to by a reference. +++ /// +++ /// The reference must point to a commitish. +++ pub fn hide_ref(&mut self, reference: &str) -> Result<(), Error> { +++ let reference = CString::new(reference)?; +++ unsafe { +++ try_call!(raw::git_revwalk_hide_ref(self.raw, reference)); +++ } +++ Ok(()) +++ } +++} +++ +++impl<'repo> Binding for Revwalk<'repo> { +++ type Raw = *mut raw::git_revwalk; +++ unsafe fn from_raw(raw: *mut raw::git_revwalk) -> Revwalk<'repo> { +++ Revwalk { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_revwalk { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for Revwalk<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_revwalk_free(self.raw) } +++ } +++} +++ +++impl<'repo> Iterator for Revwalk<'repo> { +++ type Item = Result; +++ fn next(&mut self) -> Option> { +++ let mut out: raw::git_oid = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call_iter!(raw::git_revwalk_next(&mut out, self.raw())); +++ Some(Ok(Binding::from_raw(&out as *const _))) +++ } +++ } +++} +++ +++impl<'repo, 'cb, C: FnMut(Oid) -> bool> Iterator for RevwalkWithHideCb<'repo, 'cb, C> { +++ type Item = Result; +++ fn next(&mut self) -> Option> { +++ let out = self.revwalk.next(); +++ crate::panic::check(); +++ out +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ let head = repo.head().unwrap(); +++ let target = head.target().unwrap(); +++ +++ let mut walk = repo.revwalk().unwrap(); +++ walk.push(target).unwrap(); +++ +++ let oids: Vec = walk.by_ref().collect::, _>>().unwrap(); +++ +++ assert_eq!(oids.len(), 1); +++ assert_eq!(oids[0], target); +++ +++ walk.reset().unwrap(); +++ walk.push_head().unwrap(); +++ assert_eq!(walk.by_ref().count(), 1); +++ +++ walk.reset().unwrap(); +++ walk.push_head().unwrap(); +++ walk.hide_head().unwrap(); +++ assert_eq!(walk.by_ref().count(), 0); +++ } +++ +++ #[test] +++ fn smoke_hide_cb() { +++ let (_td, repo) = crate::test::repo_init(); +++ let head = repo.head().unwrap(); +++ let target = head.target().unwrap(); +++ +++ let mut walk = repo.revwalk().unwrap(); +++ walk.push(target).unwrap(); +++ +++ let oids: Vec = walk.by_ref().collect::, _>>().unwrap(); +++ +++ assert_eq!(oids.len(), 1); +++ assert_eq!(oids[0], target); +++ +++ walk.reset().unwrap(); +++ walk.push_head().unwrap(); +++ assert_eq!(walk.by_ref().count(), 1); +++ +++ walk.reset().unwrap(); +++ walk.push_head().unwrap(); +++ +++ let mut hide_cb = |oid| oid == target; +++ let mut walk = walk.with_hide_callback(&mut hide_cb).unwrap(); +++ +++ assert_eq!(walk.by_ref().count(), 0); +++ +++ let mut walk = walk.into_inner().unwrap(); +++ walk.push_head().unwrap(); +++ assert_eq!(walk.by_ref().count(), 1); +++ } +++} diff --cc extra/git2/src/signature.rs index 0000000000,0000000000,0000000000..7c9ffb3933 new file mode 100644 --- /dev/null +++ b/extra/git2/src/signature.rs @@@@ -1,0 -1,0 -1,0 +1,188 @@@@ +++use std::ffi::CString; +++use std::fmt; +++use std::marker; +++use std::mem; +++use std::ptr; +++use std::str; +++ +++use crate::util::Binding; +++use crate::{raw, Error, Time}; +++ +++/// A Signature is used to indicate authorship of various actions throughout the +++/// library. +++/// +++/// Signatures contain a name, email, and timestamp. All fields can be specified +++/// with `new` while the `now` constructor omits the timestamp. The +++/// [`Repository::signature`] method can be used to create a default signature +++/// with name and email values read from the configuration. +++/// +++/// [`Repository::signature`]: struct.Repository.html#method.signature +++pub struct Signature<'a> { +++ raw: *mut raw::git_signature, +++ _marker: marker::PhantomData<&'a str>, +++ owned: bool, +++} +++ +++impl<'a> Signature<'a> { +++ /// Create a new action signature with a timestamp of 'now'. +++ /// +++ /// See `new` for more information +++ pub fn now(name: &str, email: &str) -> Result, Error> { +++ crate::init(); +++ let mut ret = ptr::null_mut(); +++ let name = CString::new(name)?; +++ let email = CString::new(email)?; +++ unsafe { +++ try_call!(raw::git_signature_now(&mut ret, name, email)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Create a new action signature. +++ /// +++ /// The `time` specified is in seconds since the epoch, and the `offset` is +++ /// the time zone offset in minutes. +++ /// +++ /// Returns error if either `name` or `email` contain angle brackets. +++ pub fn new(name: &str, email: &str, time: &Time) -> Result, Error> { +++ crate::init(); +++ let mut ret = ptr::null_mut(); +++ let name = CString::new(name)?; +++ let email = CString::new(email)?; +++ unsafe { +++ try_call!(raw::git_signature_new( +++ &mut ret, +++ name, +++ email, +++ time.seconds() as raw::git_time_t, +++ time.offset_minutes() as libc::c_int +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Gets the name on the signature. +++ /// +++ /// Returns `None` if the name is not valid utf-8 +++ pub fn name(&self) -> Option<&str> { +++ str::from_utf8(self.name_bytes()).ok() +++ } +++ +++ /// Gets the name on the signature as a byte slice. +++ pub fn name_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, (*self.raw).name).unwrap() } +++ } +++ +++ /// Gets the email on the signature. +++ /// +++ /// Returns `None` if the email is not valid utf-8 +++ pub fn email(&self) -> Option<&str> { +++ str::from_utf8(self.email_bytes()).ok() +++ } +++ +++ /// Gets the email on the signature as a byte slice. +++ pub fn email_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, (*self.raw).email).unwrap() } +++ } +++ +++ /// Get the `when` of this signature. +++ pub fn when(&self) -> Time { +++ unsafe { Binding::from_raw((*self.raw).when) } +++ } +++ +++ /// Convert a signature of any lifetime into an owned signature with a +++ /// static lifetime. +++ pub fn to_owned(&self) -> Signature<'static> { +++ unsafe { +++ let me = mem::transmute::<&Signature<'a>, &Signature<'static>>(self); +++ me.clone() +++ } +++ } +++} +++ +++impl<'a> Binding for Signature<'a> { +++ type Raw = *mut raw::git_signature; +++ unsafe fn from_raw(raw: *mut raw::git_signature) -> Signature<'a> { +++ Signature { +++ raw, +++ _marker: marker::PhantomData, +++ owned: true, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_signature { +++ self.raw +++ } +++} +++ +++/// Creates a new signature from the give raw pointer, tied to the lifetime +++/// of the given object. +++/// +++/// This function is unsafe as there is no guarantee that `raw` is valid for +++/// `'a` nor if it's a valid pointer. +++pub unsafe fn from_raw_const<'b, T>(_lt: &'b T, raw: *const raw::git_signature) -> Signature<'b> { +++ Signature { +++ raw: raw as *mut raw::git_signature, +++ _marker: marker::PhantomData, +++ owned: false, +++ } +++} +++ +++impl Clone for Signature<'static> { +++ fn clone(&self) -> Signature<'static> { +++ // TODO: can this be defined for 'a and just do a plain old copy if the +++ // lifetime isn't static? +++ let mut raw = ptr::null_mut(); +++ let rc = unsafe { raw::git_signature_dup(&mut raw, &*self.raw) }; +++ assert_eq!(rc, 0); +++ unsafe { Binding::from_raw(raw) } +++ } +++} +++ +++impl<'a> Drop for Signature<'a> { +++ fn drop(&mut self) { +++ if self.owned { +++ unsafe { raw::git_signature_free(self.raw) } +++ } +++ } +++} +++ +++impl<'a> fmt::Display for Signature<'a> { +++ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +++ write!( +++ f, +++ "{} <{}>", +++ String::from_utf8_lossy(self.name_bytes()), +++ String::from_utf8_lossy(self.email_bytes()) +++ ) +++ } +++} +++ +++impl PartialEq for Signature<'_> { +++ fn eq(&self, other: &Self) -> bool { +++ self.when() == other.when() +++ && self.email_bytes() == other.email_bytes() +++ && self.name_bytes() == other.name_bytes() +++ } +++} +++ +++impl Eq for Signature<'_> {} +++ +++#[cfg(test)] +++mod tests { +++ use crate::{Signature, Time}; +++ +++ #[test] +++ fn smoke() { +++ Signature::new("foo", "bar", &Time::new(89, 0)).unwrap(); +++ Signature::now("foo", "bar").unwrap(); +++ assert!(Signature::new("", "bar", &Time::new(89, 0)).is_err()); +++ assert!(Signature::now("", "bar").is_err()); +++ +++ let s = Signature::now("foo", "bar").unwrap(); +++ assert_eq!(s.name(), Some("foo")); +++ assert_eq!(s.email(), Some("bar")); +++ +++ drop(s.clone()); +++ drop(s.to_owned()); +++ } +++} diff --cc extra/git2/src/stash.rs index 0000000000,0000000000,0000000000..ea898e46ba new file mode 100644 --- /dev/null +++ b/extra/git2/src/stash.rs @@@@ -1,0 -1,0 -1,0 +1,348 @@@@ +++use crate::build::CheckoutBuilder; +++use crate::util::{self, Binding}; +++use crate::{panic, raw, IntoCString, Oid, Signature, StashApplyProgress, StashFlags}; +++use libc::{c_char, c_int, c_void, size_t}; +++use std::ffi::{c_uint, CStr, CString}; +++use std::mem; +++ +++/// Stash application options structure +++pub struct StashSaveOptions<'a> { +++ message: Option, +++ flags: Option, +++ stasher: Signature<'a>, +++ pathspec: Vec, +++ pathspec_ptrs: Vec<*const c_char>, +++ raw_opts: raw::git_stash_save_options, +++} +++ +++impl<'a> StashSaveOptions<'a> { +++ /// Creates a default +++ pub fn new(stasher: Signature<'a>) -> Self { +++ let mut opts = Self { +++ message: None, +++ flags: None, +++ stasher, +++ pathspec: Vec::new(), +++ pathspec_ptrs: Vec::new(), +++ raw_opts: unsafe { mem::zeroed() }, +++ }; +++ assert_eq!( +++ unsafe { +++ raw::git_stash_save_options_init( +++ &mut opts.raw_opts, +++ raw::GIT_STASH_SAVE_OPTIONS_VERSION, +++ ) +++ }, +++ 0 +++ ); +++ opts +++ } +++ +++ /// Customize optional `flags` field +++ pub fn flags(&mut self, flags: Option) -> &mut Self { +++ self.flags = flags; +++ self +++ } +++ +++ /// Add to the array of paths patterns to build the stash. +++ pub fn pathspec(&mut self, pathspec: T) -> &mut Self { +++ let s = util::cstring_to_repo_path(pathspec).unwrap(); +++ self.pathspec_ptrs.push(s.as_ptr()); +++ self.pathspec.push(s); +++ self +++ } +++ +++ /// Acquire a pointer to the underlying raw options. +++ /// +++ /// This function is unsafe as the pointer is only valid so long as this +++ /// structure is not moved, modified, or used elsewhere. +++ pub unsafe fn raw(&mut self) -> *const raw::git_stash_save_options { +++ self.raw_opts.flags = self.flags.unwrap_or_else(StashFlags::empty).bits() as c_uint; +++ self.raw_opts.message = crate::call::convert(&self.message); +++ self.raw_opts.paths.count = self.pathspec_ptrs.len() as size_t; +++ self.raw_opts.paths.strings = self.pathspec_ptrs.as_ptr() as *mut _; +++ self.raw_opts.stasher = self.stasher.raw(); +++ +++ &self.raw_opts as *const _ +++ } +++} +++ +++/// Stash application progress notification function. +++/// +++/// Return `true` to continue processing, or `false` to +++/// abort the stash application. +++// FIXME: This probably should have been pub(crate) since it is not used anywhere. +++pub type StashApplyProgressCb<'a> = dyn FnMut(StashApplyProgress) -> bool + 'a; +++ +++/// This is a callback function you can provide to iterate over all the +++/// stashed states that will be invoked per entry. +++// FIXME: This probably should have been pub(crate) since it is not used anywhere. +++pub type StashCb<'a> = dyn FnMut(usize, &str, &Oid) -> bool + 'a; +++ +++/// Stash application options structure +++pub struct StashApplyOptions<'cb> { +++ progress: Option>>, +++ checkout_options: Option>, +++ raw_opts: raw::git_stash_apply_options, +++} +++ +++impl<'cb> Default for StashApplyOptions<'cb> { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl<'cb> StashApplyOptions<'cb> { +++ /// Creates a default set of merge options. +++ pub fn new() -> StashApplyOptions<'cb> { +++ let mut opts = StashApplyOptions { +++ progress: None, +++ checkout_options: None, +++ raw_opts: unsafe { mem::zeroed() }, +++ }; +++ assert_eq!( +++ unsafe { raw::git_stash_apply_init_options(&mut opts.raw_opts, 1) }, +++ 0 +++ ); +++ opts +++ } +++ +++ /// Set stash application flag to GIT_STASH_APPLY_REINSTATE_INDEX +++ pub fn reinstantiate_index(&mut self) -> &mut StashApplyOptions<'cb> { +++ self.raw_opts.flags = raw::GIT_STASH_APPLY_REINSTATE_INDEX as u32; +++ self +++ } +++ +++ /// Options to use when writing files to the working directory +++ pub fn checkout_options(&mut self, opts: CheckoutBuilder<'cb>) -> &mut StashApplyOptions<'cb> { +++ self.checkout_options = Some(opts); +++ self +++ } +++ +++ /// Optional callback to notify the consumer of application progress. +++ /// +++ /// Return `true` to continue processing, or `false` to +++ /// abort the stash application. +++ pub fn progress_cb(&mut self, callback: C) -> &mut StashApplyOptions<'cb> +++ where +++ C: FnMut(StashApplyProgress) -> bool + 'cb, +++ { +++ self.progress = Some(Box::new(callback) as Box>); +++ self.raw_opts.progress_cb = Some(stash_apply_progress_cb); +++ self.raw_opts.progress_payload = self as *mut _ as *mut _; +++ self +++ } +++ +++ /// Pointer to a raw git_stash_apply_options +++ pub fn raw(&mut self) -> &raw::git_stash_apply_options { +++ unsafe { +++ if let Some(opts) = self.checkout_options.as_mut() { +++ opts.configure(&mut self.raw_opts.checkout_options); +++ } +++ } +++ &self.raw_opts +++ } +++} +++ +++pub(crate) struct StashCbData<'a> { +++ pub callback: &'a mut StashCb<'a>, +++} +++ +++pub(crate) extern "C" fn stash_cb( +++ index: size_t, +++ message: *const c_char, +++ stash_id: *const raw::git_oid, +++ payload: *mut c_void, +++) -> c_int { +++ panic::wrap(|| unsafe { +++ let data = &mut *(payload as *mut StashCbData<'_>); +++ let res = { +++ let callback = &mut data.callback; +++ callback( +++ index, +++ CStr::from_ptr(message).to_str().unwrap(), +++ &Binding::from_raw(stash_id), +++ ) +++ }; +++ +++ if res { +++ 0 +++ } else { +++ 1 +++ } +++ }) +++ .unwrap_or(1) +++} +++ +++fn convert_progress(progress: raw::git_stash_apply_progress_t) -> StashApplyProgress { +++ match progress { +++ raw::GIT_STASH_APPLY_PROGRESS_NONE => StashApplyProgress::None, +++ raw::GIT_STASH_APPLY_PROGRESS_LOADING_STASH => StashApplyProgress::LoadingStash, +++ raw::GIT_STASH_APPLY_PROGRESS_ANALYZE_INDEX => StashApplyProgress::AnalyzeIndex, +++ raw::GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED => StashApplyProgress::AnalyzeModified, +++ raw::GIT_STASH_APPLY_PROGRESS_ANALYZE_UNTRACKED => StashApplyProgress::AnalyzeUntracked, +++ raw::GIT_STASH_APPLY_PROGRESS_CHECKOUT_UNTRACKED => StashApplyProgress::CheckoutUntracked, +++ raw::GIT_STASH_APPLY_PROGRESS_CHECKOUT_MODIFIED => StashApplyProgress::CheckoutModified, +++ raw::GIT_STASH_APPLY_PROGRESS_DONE => StashApplyProgress::Done, +++ +++ _ => StashApplyProgress::None, +++ } +++} +++ +++extern "C" fn stash_apply_progress_cb( +++ progress: raw::git_stash_apply_progress_t, +++ payload: *mut c_void, +++) -> c_int { +++ panic::wrap(|| unsafe { +++ let options = &mut *(payload as *mut StashApplyOptions<'_>); +++ let res = { +++ let callback = options.progress.as_mut().unwrap(); +++ callback(convert_progress(progress)) +++ }; +++ +++ if res { +++ 0 +++ } else { +++ -1 +++ } +++ }) +++ .unwrap_or(-1) +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::stash::{StashApplyOptions, StashSaveOptions}; +++ use crate::test::repo_init; +++ use crate::{IndexAddOption, Repository, StashFlags, Status}; +++ use std::fs; +++ use std::path::{Path, PathBuf}; +++ +++ fn make_stash(next: C) +++ where +++ C: FnOnce(&mut Repository), +++ { +++ let (_td, mut repo) = repo_init(); +++ let signature = repo.signature().unwrap(); +++ +++ let p = Path::new(repo.workdir().unwrap()).join("file_b.txt"); +++ println!("using path {:?}", p); +++ +++ fs::write(&p, "data".as_bytes()).unwrap(); +++ +++ let rel_p = Path::new("file_b.txt"); +++ assert!(repo.status_file(&rel_p).unwrap() == Status::WT_NEW); +++ +++ repo.stash_save(&signature, "msg1", Some(StashFlags::INCLUDE_UNTRACKED)) +++ .unwrap(); +++ +++ assert!(repo.status_file(&rel_p).is_err()); +++ +++ let mut count = 0; +++ repo.stash_foreach(|index, name, _oid| { +++ count += 1; +++ assert!(index == 0); +++ assert!(name == "On main: msg1"); +++ true +++ }) +++ .unwrap(); +++ +++ assert!(count == 1); +++ next(&mut repo); +++ } +++ +++ fn count_stash(repo: &mut Repository) -> usize { +++ let mut count = 0; +++ repo.stash_foreach(|_, _, _| { +++ count += 1; +++ true +++ }) +++ .unwrap(); +++ count +++ } +++ +++ #[test] +++ fn smoke_stash_save_drop() { +++ make_stash(|repo| { +++ repo.stash_drop(0).unwrap(); +++ assert!(count_stash(repo) == 0) +++ }) +++ } +++ +++ #[test] +++ fn smoke_stash_save_pop() { +++ make_stash(|repo| { +++ repo.stash_pop(0, None).unwrap(); +++ assert!(count_stash(repo) == 0) +++ }) +++ } +++ +++ #[test] +++ fn smoke_stash_save_apply() { +++ make_stash(|repo| { +++ let mut options = StashApplyOptions::new(); +++ options.progress_cb(|progress| { +++ println!("{:?}", progress); +++ true +++ }); +++ +++ repo.stash_apply(0, Some(&mut options)).unwrap(); +++ assert!(count_stash(repo) == 1) +++ }) +++ } +++ +++ #[test] +++ fn test_stash_save2_msg_none() { +++ let (_td, mut repo) = repo_init(); +++ let signature = repo.signature().unwrap(); +++ +++ let p = Path::new(repo.workdir().unwrap()).join("file_b.txt"); +++ +++ fs::write(&p, "data".as_bytes()).unwrap(); +++ +++ repo.stash_save2(&signature, None, Some(StashFlags::INCLUDE_UNTRACKED)) +++ .unwrap(); +++ +++ let mut stash_name = String::new(); +++ repo.stash_foreach(|index, name, _oid| { +++ assert_eq!(index, 0); +++ stash_name = name.to_string(); +++ true +++ }) +++ .unwrap(); +++ +++ assert!(stash_name.starts_with("WIP on main:")); +++ } +++ +++ fn create_file(r: &Repository, name: &str, data: &str) -> PathBuf { +++ let p = Path::new(r.workdir().unwrap()).join(name); +++ fs::write(&p, data).unwrap(); +++ p +++ } +++ +++ #[test] +++ fn test_stash_save_ext() { +++ let (_td, mut repo) = repo_init(); +++ let signature = repo.signature().unwrap(); +++ +++ create_file(&repo, "file_a", "foo"); +++ create_file(&repo, "file_b", "foo"); +++ +++ let mut index = repo.index().unwrap(); +++ index +++ .add_all(["*"].iter(), IndexAddOption::DEFAULT, None) +++ .unwrap(); +++ index.write().unwrap(); +++ +++ assert_eq!(repo.statuses(None).unwrap().len(), 2); +++ +++ let mut opt = StashSaveOptions::new(signature); +++ opt.pathspec("file_a"); +++ repo.stash_save_ext(Some(&mut opt)).unwrap(); +++ +++ assert_eq!(repo.statuses(None).unwrap().len(), 0); +++ +++ repo.stash_pop(0, None).unwrap(); +++ +++ assert_eq!(repo.statuses(None).unwrap().len(), 1); +++ } +++} diff --cc extra/git2/src/status.rs index 0000000000,0000000000,0000000000..a5a8cffd39 new file mode 100644 --- /dev/null +++ b/extra/git2/src/status.rs @@@@ -1,0 -1,0 -1,0 +1,435 @@@@ +++use libc::{c_char, c_uint, size_t}; +++use std::ffi::CString; +++use std::iter::FusedIterator; +++use std::marker; +++use std::mem; +++use std::ops::Range; +++use std::str; +++ +++use crate::util::{self, Binding}; +++use crate::{raw, DiffDelta, IntoCString, Repository, Status}; +++ +++/// Options that can be provided to `repo.statuses()` to control how the status +++/// information is gathered. +++pub struct StatusOptions { +++ raw: raw::git_status_options, +++ pathspec: Vec, +++ ptrs: Vec<*const c_char>, +++} +++ +++/// Enumeration of possible methods of what can be shown through a status +++/// operation. +++#[derive(Copy, Clone)] +++pub enum StatusShow { +++ /// Only gives status based on HEAD to index comparison, not looking at +++ /// working directory changes. +++ Index, +++ +++ /// Only gives status based on index to working directory comparison, not +++ /// comparing the index to the HEAD. +++ Workdir, +++ +++ /// The default, this roughly matches `git status --porcelain` regarding +++ /// which files are included and in what order. +++ IndexAndWorkdir, +++} +++ +++/// A container for a list of status information about a repository. +++/// +++/// Each instance appears as if it were a collection, having a length and +++/// allowing indexing, as well as providing an iterator. +++pub struct Statuses<'repo> { +++ raw: *mut raw::git_status_list, +++ +++ // Hm, not currently present, but can't hurt? +++ _marker: marker::PhantomData<&'repo Repository>, +++} +++ +++/// An iterator over the statuses in a `Statuses` instance. +++pub struct StatusIter<'statuses> { +++ statuses: &'statuses Statuses<'statuses>, +++ range: Range, +++} +++ +++/// A structure representing an entry in the `Statuses` structure. +++/// +++/// Instances are created through the `.iter()` method or the `.get()` method. +++pub struct StatusEntry<'statuses> { +++ raw: *const raw::git_status_entry, +++ _marker: marker::PhantomData<&'statuses DiffDelta<'statuses>>, +++} +++ +++impl Default for StatusOptions { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++impl StatusOptions { +++ /// Creates a new blank set of status options. +++ pub fn new() -> StatusOptions { +++ unsafe { +++ let mut raw = mem::zeroed(); +++ let r = raw::git_status_init_options(&mut raw, raw::GIT_STATUS_OPTIONS_VERSION); +++ assert_eq!(r, 0); +++ StatusOptions { +++ raw, +++ pathspec: Vec::new(), +++ ptrs: Vec::new(), +++ } +++ } +++ } +++ +++ /// Select the files on which to report status. +++ /// +++ /// The default, if unspecified, is to show the index and the working +++ /// directory. +++ pub fn show(&mut self, show: StatusShow) -> &mut StatusOptions { +++ self.raw.show = match show { +++ StatusShow::Index => raw::GIT_STATUS_SHOW_INDEX_ONLY, +++ StatusShow::Workdir => raw::GIT_STATUS_SHOW_WORKDIR_ONLY, +++ StatusShow::IndexAndWorkdir => raw::GIT_STATUS_SHOW_INDEX_AND_WORKDIR, +++ }; +++ self +++ } +++ +++ /// Add a path pattern to match (using fnmatch-style matching). +++ /// +++ /// If the `disable_pathspec_match` option is given, then this is a literal +++ /// path to match. If this is not called, then there will be no patterns to +++ /// match and the entire directory will be used. +++ pub fn pathspec(&mut self, pathspec: T) -> &mut StatusOptions { +++ let s = util::cstring_to_repo_path(pathspec).unwrap(); +++ self.ptrs.push(s.as_ptr()); +++ self.pathspec.push(s); +++ self +++ } +++ +++ fn flag(&mut self, flag: raw::git_status_opt_t, val: bool) -> &mut StatusOptions { +++ if val { +++ self.raw.flags |= flag as c_uint; +++ } else { +++ self.raw.flags &= !(flag as c_uint); +++ } +++ self +++ } +++ +++ /// Flag whether untracked files will be included. +++ /// +++ /// Untracked files will only be included if the workdir files are included +++ /// in the status "show" option. +++ pub fn include_untracked(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_INCLUDE_UNTRACKED, include) +++ } +++ +++ /// Flag whether ignored files will be included. +++ /// +++ /// The files will only be included if the workdir files are included +++ /// in the status "show" option. +++ pub fn include_ignored(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_INCLUDE_IGNORED, include) +++ } +++ +++ /// Flag to include unmodified files. +++ pub fn include_unmodified(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_INCLUDE_UNMODIFIED, include) +++ } +++ +++ /// Flag that submodules should be skipped. +++ /// +++ /// This only applies if there are no pending typechanges to the submodule +++ /// (either from or to another type). +++ pub fn exclude_submodules(&mut self, exclude: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_EXCLUDE_SUBMODULES, exclude) +++ } +++ +++ /// Flag that all files in untracked directories should be included. +++ /// +++ /// Normally if an entire directory is new then just the top-level directory +++ /// is included (with a trailing slash on the entry name). +++ pub fn recurse_untracked_dirs(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS, include) +++ } +++ +++ /// Indicates that the given paths should be treated as literals paths, note +++ /// patterns. +++ pub fn disable_pathspec_match(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH, include) +++ } +++ +++ /// Indicates that the contents of ignored directories should be included in +++ /// the status. +++ pub fn recurse_ignored_dirs(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_RECURSE_IGNORED_DIRS, include) +++ } +++ +++ /// Indicates that rename detection should be processed between the head. +++ pub fn renames_head_to_index(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX, include) +++ } +++ +++ /// Indicates that rename detection should be run between the index and the +++ /// working directory. +++ pub fn renames_index_to_workdir(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR, include) +++ } +++ +++ /// Override the native case sensitivity for the file system and force the +++ /// output to be in case sensitive order. +++ pub fn sort_case_sensitively(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_SORT_CASE_SENSITIVELY, include) +++ } +++ +++ /// Override the native case sensitivity for the file system and force the +++ /// output to be in case-insensitive order. +++ pub fn sort_case_insensitively(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY, include) +++ } +++ +++ /// Indicates that rename detection should include rewritten files. +++ pub fn renames_from_rewrites(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_RENAMES_FROM_REWRITES, include) +++ } +++ +++ /// Bypasses the default status behavior of doing a "soft" index reload. +++ pub fn no_refresh(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_NO_REFRESH, include) +++ } +++ +++ /// Refresh the stat cache in the index for files are unchanged but have +++ /// out of date stat information in the index. +++ /// +++ /// This will result in less work being done on subsequent calls to fetching +++ /// the status. +++ pub fn update_index(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_UPDATE_INDEX, include) +++ } +++ +++ // erm... +++ #[allow(missing_docs)] +++ pub fn include_unreadable(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_INCLUDE_UNREADABLE, include) +++ } +++ +++ // erm... +++ #[allow(missing_docs)] +++ pub fn include_unreadable_as_untracked(&mut self, include: bool) -> &mut StatusOptions { +++ self.flag(raw::GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED, include) +++ } +++ +++ /// Set threshold above which similar files will be considered renames. +++ /// +++ /// This is equivalent to the `-M` option. Defaults to 50. +++ pub fn rename_threshold(&mut self, threshold: u16) -> &mut StatusOptions { +++ self.raw.rename_threshold = threshold; +++ self +++ } +++ +++ /// Get a pointer to the inner list of status options. +++ /// +++ /// This function is unsafe as the returned structure has interior pointers +++ /// and may no longer be valid if these options continue to be mutated. +++ pub unsafe fn raw(&mut self) -> *const raw::git_status_options { +++ self.raw.pathspec.strings = self.ptrs.as_ptr() as *mut _; +++ self.raw.pathspec.count = self.ptrs.len() as size_t; +++ &self.raw +++ } +++} +++ +++impl<'repo> Statuses<'repo> { +++ /// Gets a status entry from this list at the specified index. +++ /// +++ /// Returns `None` if the index is out of bounds. +++ pub fn get(&self, index: usize) -> Option> { +++ unsafe { +++ let p = raw::git_status_byindex(self.raw, index as size_t); +++ Binding::from_raw_opt(p) +++ } +++ } +++ +++ /// Gets the count of status entries in this list. +++ /// +++ /// If there are no changes in status (according to the options given +++ /// when the status list was created), this should return 0. +++ pub fn len(&self) -> usize { +++ unsafe { raw::git_status_list_entrycount(self.raw) as usize } +++ } +++ +++ /// Return `true` if there is no status entry in this list. +++ pub fn is_empty(&self) -> bool { +++ self.len() == 0 +++ } +++ +++ /// Returns an iterator over the statuses in this list. +++ pub fn iter(&self) -> StatusIter<'_> { +++ StatusIter { +++ statuses: self, +++ range: 0..self.len(), +++ } +++ } +++} +++ +++impl<'repo> Binding for Statuses<'repo> { +++ type Raw = *mut raw::git_status_list; +++ unsafe fn from_raw(raw: *mut raw::git_status_list) -> Statuses<'repo> { +++ Statuses { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_status_list { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for Statuses<'repo> { +++ fn drop(&mut self) { +++ unsafe { +++ raw::git_status_list_free(self.raw); +++ } +++ } +++} +++ +++impl<'a> Iterator for StatusIter<'a> { +++ type Item = StatusEntry<'a>; +++ fn next(&mut self) -> Option> { +++ self.range.next().and_then(|i| self.statuses.get(i)) +++ } +++ fn size_hint(&self) -> (usize, Option) { +++ self.range.size_hint() +++ } +++} +++impl<'a> DoubleEndedIterator for StatusIter<'a> { +++ fn next_back(&mut self) -> Option> { +++ self.range.next_back().and_then(|i| self.statuses.get(i)) +++ } +++} +++impl<'a> FusedIterator for StatusIter<'a> {} +++impl<'a> ExactSizeIterator for StatusIter<'a> {} +++ +++impl<'a> IntoIterator for &'a Statuses<'a> { +++ type Item = StatusEntry<'a>; +++ type IntoIter = StatusIter<'a>; +++ fn into_iter(self) -> Self::IntoIter { +++ self.iter() +++ } +++} +++ +++impl<'statuses> StatusEntry<'statuses> { +++ /// Access the bytes for this entry's corresponding pathname +++ pub fn path_bytes(&self) -> &[u8] { +++ unsafe { +++ if (*self.raw).head_to_index.is_null() { +++ crate::opt_bytes(self, (*(*self.raw).index_to_workdir).old_file.path) +++ } else { +++ crate::opt_bytes(self, (*(*self.raw).head_to_index).old_file.path) +++ } +++ .unwrap() +++ } +++ } +++ +++ /// Access this entry's path name as a string. +++ /// +++ /// Returns `None` if the path is not valid utf-8. +++ pub fn path(&self) -> Option<&str> { +++ str::from_utf8(self.path_bytes()).ok() +++ } +++ +++ /// Access the status flags for this file +++ pub fn status(&self) -> Status { +++ Status::from_bits_truncate(unsafe { (*self.raw).status as u32 }) +++ } +++ +++ /// Access detailed information about the differences between the file in +++ /// HEAD and the file in the index. +++ pub fn head_to_index(&self) -> Option> { +++ unsafe { Binding::from_raw_opt((*self.raw).head_to_index) } +++ } +++ +++ /// Access detailed information about the differences between the file in +++ /// the index and the file in the working directory. +++ pub fn index_to_workdir(&self) -> Option> { +++ unsafe { Binding::from_raw_opt((*self.raw).index_to_workdir) } +++ } +++} +++ +++impl<'statuses> Binding for StatusEntry<'statuses> { +++ type Raw = *const raw::git_status_entry; +++ +++ unsafe fn from_raw(raw: *const raw::git_status_entry) -> StatusEntry<'statuses> { +++ StatusEntry { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *const raw::git_status_entry { +++ self.raw +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use super::StatusOptions; +++ use std::fs::File; +++ use std::io::prelude::*; +++ use std::path::Path; +++ +++ #[test] +++ fn smoke() { +++ let (td, repo) = crate::test::repo_init(); +++ assert_eq!(repo.statuses(None).unwrap().len(), 0); +++ File::create(&td.path().join("foo")).unwrap(); +++ let statuses = repo.statuses(None).unwrap(); +++ assert_eq!(statuses.iter().count(), 1); +++ let status = statuses.iter().next().unwrap(); +++ assert_eq!(status.path(), Some("foo")); +++ assert!(status.status().contains(crate::Status::WT_NEW)); +++ assert!(!status.status().contains(crate::Status::INDEX_NEW)); +++ assert!(status.head_to_index().is_none()); +++ let diff = status.index_to_workdir().unwrap(); +++ assert_eq!(diff.old_file().path_bytes().unwrap(), b"foo"); +++ assert_eq!(diff.new_file().path_bytes().unwrap(), b"foo"); +++ } +++ +++ #[test] +++ fn filter() { +++ let (td, repo) = crate::test::repo_init(); +++ t!(File::create(&td.path().join("foo"))); +++ t!(File::create(&td.path().join("bar"))); +++ let mut opts = StatusOptions::new(); +++ opts.include_untracked(true).pathspec("foo"); +++ +++ let statuses = t!(repo.statuses(Some(&mut opts))); +++ assert_eq!(statuses.iter().count(), 1); +++ let status = statuses.iter().next().unwrap(); +++ assert_eq!(status.path(), Some("foo")); +++ } +++ +++ #[test] +++ fn gitignore() { +++ let (td, repo) = crate::test::repo_init(); +++ t!(t!(File::create(td.path().join(".gitignore"))).write_all(b"foo\n")); +++ assert!(!t!(repo.status_should_ignore(Path::new("bar")))); +++ assert!(t!(repo.status_should_ignore(Path::new("foo")))); +++ } +++ +++ #[test] +++ fn status_file() { +++ let (td, repo) = crate::test::repo_init(); +++ assert!(repo.status_file(Path::new("foo")).is_err()); +++ if cfg!(windows) { +++ assert!(repo.status_file(Path::new("bar\\foo.txt")).is_err()); +++ } +++ t!(File::create(td.path().join("foo"))); +++ if cfg!(windows) { +++ t!(::std::fs::create_dir_all(td.path().join("bar"))); +++ t!(File::create(td.path().join("bar").join("foo.txt"))); +++ } +++ let status = t!(repo.status_file(Path::new("foo"))); +++ assert!(status.contains(crate::Status::WT_NEW)); +++ if cfg!(windows) { +++ let status = t!(repo.status_file(Path::new("bar\\foo.txt"))); +++ assert!(status.contains(crate::Status::WT_NEW)); +++ } +++ } +++} diff --cc extra/git2/src/string_array.rs index 0000000000,0000000000,0000000000..c77ccdab96 new file mode 100644 --- /dev/null +++ b/extra/git2/src/string_array.rs @@@@ -1,0 -1,0 -1,0 +1,136 @@@@ +++//! Bindings to libgit2's raw `git_strarray` type +++ +++use std::iter::FusedIterator; +++use std::ops::Range; +++use std::str; +++ +++use crate::raw; +++use crate::util::Binding; +++ +++/// A string array structure used by libgit2 +++/// +++/// Some APIs return arrays of strings which originate from libgit2. This +++/// wrapper type behaves a little like `Vec<&str>` but does so without copying +++/// the underlying strings until necessary. +++pub struct StringArray { +++ raw: raw::git_strarray, +++} +++ +++/// A forward iterator over the strings of an array, casted to `&str`. +++pub struct Iter<'a> { +++ range: Range, +++ arr: &'a StringArray, +++} +++ +++/// A forward iterator over the strings of an array, casted to `&[u8]`. +++pub struct IterBytes<'a> { +++ range: Range, +++ arr: &'a StringArray, +++} +++ +++impl StringArray { +++ /// Returns None if the i'th string is not utf8 or if i is out of bounds. +++ pub fn get(&self, i: usize) -> Option<&str> { +++ self.get_bytes(i).and_then(|s| str::from_utf8(s).ok()) +++ } +++ +++ /// Returns None if `i` is out of bounds. +++ pub fn get_bytes(&self, i: usize) -> Option<&[u8]> { +++ if i < self.raw.count as usize { +++ unsafe { +++ let ptr = *self.raw.strings.add(i) as *const _; +++ Some(crate::opt_bytes(self, ptr).unwrap()) +++ } +++ } else { +++ None +++ } +++ } +++ +++ /// Returns an iterator over the strings contained within this array. +++ /// +++ /// The iterator yields `Option<&str>` as it is unknown whether the contents +++ /// are utf-8 or not. +++ pub fn iter(&self) -> Iter<'_> { +++ Iter { +++ range: 0..self.len(), +++ arr: self, +++ } +++ } +++ +++ /// Returns an iterator over the strings contained within this array, +++ /// yielding byte slices. +++ pub fn iter_bytes(&self) -> IterBytes<'_> { +++ IterBytes { +++ range: 0..self.len(), +++ arr: self, +++ } +++ } +++ +++ /// Returns the number of strings in this array. +++ pub fn len(&self) -> usize { +++ self.raw.count as usize +++ } +++ +++ /// Return `true` if this array is empty. +++ pub fn is_empty(&self) -> bool { +++ self.len() == 0 +++ } +++} +++ +++impl Binding for StringArray { +++ type Raw = raw::git_strarray; +++ unsafe fn from_raw(raw: raw::git_strarray) -> StringArray { +++ StringArray { raw } +++ } +++ fn raw(&self) -> raw::git_strarray { +++ self.raw +++ } +++} +++ +++impl<'a> IntoIterator for &'a StringArray { +++ type Item = Option<&'a str>; +++ type IntoIter = Iter<'a>; +++ fn into_iter(self) -> Self::IntoIter { +++ self.iter() +++ } +++} +++ +++impl<'a> Iterator for Iter<'a> { +++ type Item = Option<&'a str>; +++ fn next(&mut self) -> Option> { +++ self.range.next().map(|i| self.arr.get(i)) +++ } +++ fn size_hint(&self) -> (usize, Option) { +++ self.range.size_hint() +++ } +++} +++impl<'a> DoubleEndedIterator for Iter<'a> { +++ fn next_back(&mut self) -> Option> { +++ self.range.next_back().map(|i| self.arr.get(i)) +++ } +++} +++impl<'a> FusedIterator for Iter<'a> {} +++impl<'a> ExactSizeIterator for Iter<'a> {} +++ +++impl<'a> Iterator for IterBytes<'a> { +++ type Item = &'a [u8]; +++ fn next(&mut self) -> Option<&'a [u8]> { +++ self.range.next().and_then(|i| self.arr.get_bytes(i)) +++ } +++ fn size_hint(&self) -> (usize, Option) { +++ self.range.size_hint() +++ } +++} +++impl<'a> DoubleEndedIterator for IterBytes<'a> { +++ fn next_back(&mut self) -> Option<&'a [u8]> { +++ self.range.next_back().and_then(|i| self.arr.get_bytes(i)) +++ } +++} +++impl<'a> FusedIterator for IterBytes<'a> {} +++impl<'a> ExactSizeIterator for IterBytes<'a> {} +++ +++impl Drop for StringArray { +++ fn drop(&mut self) { +++ unsafe { raw::git_strarray_free(&mut self.raw) } +++ } +++} diff --cc extra/git2/src/submodule.rs index 0000000000,0000000000,0000000000..06a6359400 new file mode 100644 --- /dev/null +++ b/extra/git2/src/submodule.rs @@@@ -1,0 -1,0 -1,0 +1,471 @@@@ +++use std::marker; +++use std::mem; +++use std::os::raw::c_int; +++use std::path::Path; +++use std::ptr; +++use std::str; +++ +++use crate::util::{self, Binding}; +++use crate::{build::CheckoutBuilder, SubmoduleIgnore, SubmoduleUpdate}; +++use crate::{raw, Error, FetchOptions, Oid, Repository}; +++ +++/// A structure to represent a git [submodule][1] +++/// +++/// [1]: http://git-scm.com/book/en/Git-Tools-Submodules +++pub struct Submodule<'repo> { +++ raw: *mut raw::git_submodule, +++ _marker: marker::PhantomData<&'repo Repository>, +++} +++ +++impl<'repo> Submodule<'repo> { +++ /// Get the submodule's branch. +++ /// +++ /// Returns `None` if the branch is not valid utf-8 or if the branch is not +++ /// yet available. +++ pub fn branch(&self) -> Option<&str> { +++ self.branch_bytes().and_then(|s| str::from_utf8(s).ok()) +++ } +++ +++ /// Get the branch for the submodule. +++ /// +++ /// Returns `None` if the branch is not yet available. +++ pub fn branch_bytes(&self) -> Option<&[u8]> { +++ unsafe { crate::opt_bytes(self, raw::git_submodule_branch(self.raw)) } +++ } +++ +++ /// Perform the clone step for a newly created submodule. +++ /// +++ /// This performs the necessary `git_clone` to setup a newly-created submodule. +++ pub fn clone( +++ &mut self, +++ opts: Option<&mut SubmoduleUpdateOptions<'_>>, +++ ) -> Result { +++ unsafe { +++ let raw_opts = opts.map(|o| o.raw()); +++ let mut raw_repo = ptr::null_mut(); +++ try_call!(raw::git_submodule_clone( +++ &mut raw_repo, +++ self.raw, +++ raw_opts.as_ref() +++ )); +++ Ok(Binding::from_raw(raw_repo)) +++ } +++ } +++ +++ /// Get the submodule's URL. +++ /// +++ /// Returns `None` if the URL is not valid utf-8 or if the URL isn't present +++ pub fn url(&self) -> Option<&str> { +++ self.opt_url_bytes().and_then(|b| str::from_utf8(b).ok()) +++ } +++ +++ /// Get the URL for the submodule. +++ #[doc(hidden)] +++ #[deprecated(note = "renamed to `opt_url_bytes`")] +++ pub fn url_bytes(&self) -> &[u8] { +++ self.opt_url_bytes().unwrap() +++ } +++ +++ /// Get the URL for the submodule. +++ /// +++ /// Returns `None` if the URL isn't present +++ // TODO: delete this method and fix the signature of `url_bytes` on next +++ // major version bump +++ pub fn opt_url_bytes(&self) -> Option<&[u8]> { +++ unsafe { crate::opt_bytes(self, raw::git_submodule_url(self.raw)) } +++ } +++ +++ /// Get the submodule's name. +++ /// +++ /// Returns `None` if the name is not valid utf-8 +++ pub fn name(&self) -> Option<&str> { +++ str::from_utf8(self.name_bytes()).ok() +++ } +++ +++ /// Get the name for the submodule. +++ pub fn name_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, raw::git_submodule_name(self.raw)).unwrap() } +++ } +++ +++ /// Get the path for the submodule. +++ pub fn path(&self) -> &Path { +++ util::bytes2path(unsafe { +++ crate::opt_bytes(self, raw::git_submodule_path(self.raw)).unwrap() +++ }) +++ } +++ +++ /// Get the OID for the submodule in the current HEAD tree. +++ pub fn head_id(&self) -> Option { +++ unsafe { Binding::from_raw_opt(raw::git_submodule_head_id(self.raw)) } +++ } +++ +++ /// Get the OID for the submodule in the index. +++ pub fn index_id(&self) -> Option { +++ unsafe { Binding::from_raw_opt(raw::git_submodule_index_id(self.raw)) } +++ } +++ +++ /// Get the OID for the submodule in the current working directory. +++ /// +++ /// This returns the OID that corresponds to looking up 'HEAD' in the +++ /// checked out submodule. If there are pending changes in the index or +++ /// anything else, this won't notice that. +++ pub fn workdir_id(&self) -> Option { +++ unsafe { Binding::from_raw_opt(raw::git_submodule_wd_id(self.raw)) } +++ } +++ +++ /// Get the ignore rule that will be used for the submodule. +++ pub fn ignore_rule(&self) -> SubmoduleIgnore { +++ SubmoduleIgnore::from_raw(unsafe { raw::git_submodule_ignore(self.raw) }) +++ } +++ +++ /// Get the update rule that will be used for the submodule. +++ pub fn update_strategy(&self) -> SubmoduleUpdate { +++ SubmoduleUpdate::from_raw(unsafe { raw::git_submodule_update_strategy(self.raw) }) +++ } +++ +++ /// Copy submodule info into ".git/config" file. +++ /// +++ /// Just like "git submodule init", this copies information about the +++ /// submodule into ".git/config". You can use the accessor functions above +++ /// to alter the in-memory git_submodule object and control what is written +++ /// to the config, overriding what is in .gitmodules. +++ /// +++ /// By default, existing entries will not be overwritten, but passing `true` +++ /// for `overwrite` forces them to be updated. +++ pub fn init(&mut self, overwrite: bool) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_submodule_init(self.raw, overwrite)); +++ } +++ Ok(()) +++ } +++ +++ /// Set up the subrepository for a submodule in preparation for clone. +++ /// +++ /// This function can be called to init and set up a submodule repository +++ /// from a submodule in preparation to clone it from its remote. +++ +++ /// use_gitlink: Should the workdir contain a gitlink to the repo in +++ /// .git/modules vs. repo directly in workdir. +++ pub fn repo_init(&mut self, use_gitlink: bool) -> Result { +++ unsafe { +++ let mut raw_repo = ptr::null_mut(); +++ try_call!(raw::git_submodule_repo_init( +++ &mut raw_repo, +++ self.raw, +++ use_gitlink +++ )); +++ Ok(Binding::from_raw(raw_repo)) +++ } +++ } +++ +++ /// Open the repository for a submodule. +++ /// +++ /// This will only work if the submodule is checked out into the working +++ /// directory. +++ pub fn open(&self) -> Result { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_submodule_open(&mut raw, self.raw)); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Reread submodule info from config, index, and HEAD. +++ /// +++ /// Call this to reread cached submodule information for this submodule if +++ /// you have reason to believe that it has changed. +++ /// +++ /// If `force` is `true`, then data will be reloaded even if it doesn't seem +++ /// out of date +++ pub fn reload(&mut self, force: bool) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_submodule_reload(self.raw, force)); +++ } +++ Ok(()) +++ } +++ +++ /// Copy submodule remote info into submodule repo. +++ /// +++ /// This copies the information about the submodules URL into the checked +++ /// out submodule config, acting like "git submodule sync". This is useful +++ /// if you have altered the URL for the submodule (or it has been altered +++ /// by a fetch of upstream changes) and you need to update your local repo. +++ pub fn sync(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_submodule_sync(self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Add current submodule HEAD commit to index of superproject. +++ /// +++ /// If `write_index` is true, then the index file will be immediately +++ /// written. Otherwise you must explicitly call `write()` on an `Index` +++ /// later on. +++ pub fn add_to_index(&mut self, write_index: bool) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_submodule_add_to_index(self.raw, write_index)); +++ } +++ Ok(()) +++ } +++ +++ /// Resolve the setup of a new git submodule. +++ /// +++ /// This should be called on a submodule once you have called add setup and +++ /// done the clone of the submodule. This adds the .gitmodules file and the +++ /// newly cloned submodule to the index to be ready to be committed (but +++ /// doesn't actually do the commit). +++ pub fn add_finalize(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_submodule_add_finalize(self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Update submodule. +++ /// +++ /// This will clone a missing submodule and check out the subrepository to +++ /// the commit specified in the index of the containing repository. If +++ /// the submodule repository doesn't contain the target commit, then the +++ /// submodule is fetched using the fetch options supplied in `opts`. +++ /// +++ /// `init` indicates if the submodule should be initialized first if it has +++ /// not been initialized yet. +++ pub fn update( +++ &mut self, +++ init: bool, +++ opts: Option<&mut SubmoduleUpdateOptions<'_>>, +++ ) -> Result<(), Error> { +++ unsafe { +++ let mut raw_opts = opts.map(|o| o.raw()); +++ try_call!(raw::git_submodule_update( +++ self.raw, +++ init as c_int, +++ raw_opts.as_mut().map_or(ptr::null_mut(), |o| o) +++ )); +++ } +++ Ok(()) +++ } +++} +++ +++impl<'repo> Binding for Submodule<'repo> { +++ type Raw = *mut raw::git_submodule; +++ unsafe fn from_raw(raw: *mut raw::git_submodule) -> Submodule<'repo> { +++ Submodule { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_submodule { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for Submodule<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_submodule_free(self.raw) } +++ } +++} +++ +++/// Options to update a submodule. +++pub struct SubmoduleUpdateOptions<'cb> { +++ checkout_builder: CheckoutBuilder<'cb>, +++ fetch_opts: FetchOptions<'cb>, +++ allow_fetch: bool, +++} +++ +++impl<'cb> SubmoduleUpdateOptions<'cb> { +++ /// Return default options. +++ pub fn new() -> Self { +++ SubmoduleUpdateOptions { +++ checkout_builder: CheckoutBuilder::new(), +++ fetch_opts: FetchOptions::new(), +++ allow_fetch: true, +++ } +++ } +++ +++ unsafe fn raw(&mut self) -> raw::git_submodule_update_options { +++ let mut checkout_opts: raw::git_checkout_options = mem::zeroed(); +++ let init_res = +++ raw::git_checkout_init_options(&mut checkout_opts, raw::GIT_CHECKOUT_OPTIONS_VERSION); +++ assert_eq!(0, init_res); +++ self.checkout_builder.configure(&mut checkout_opts); +++ let opts = raw::git_submodule_update_options { +++ version: raw::GIT_SUBMODULE_UPDATE_OPTIONS_VERSION, +++ checkout_opts, +++ fetch_opts: self.fetch_opts.raw(), +++ allow_fetch: self.allow_fetch as c_int, +++ }; +++ opts +++ } +++ +++ /// Set checkout options. +++ pub fn checkout(&mut self, opts: CheckoutBuilder<'cb>) -> &mut Self { +++ self.checkout_builder = opts; +++ self +++ } +++ +++ /// Set fetch options and allow fetching. +++ pub fn fetch(&mut self, opts: FetchOptions<'cb>) -> &mut Self { +++ self.fetch_opts = opts; +++ self.allow_fetch = true; +++ self +++ } +++ +++ /// Allow or disallow fetching. +++ pub fn allow_fetch(&mut self, b: bool) -> &mut Self { +++ self.allow_fetch = b; +++ self +++ } +++} +++ +++impl<'cb> Default for SubmoduleUpdateOptions<'cb> { +++ fn default() -> Self { +++ Self::new() +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use std::fs; +++ use std::path::Path; +++ use tempfile::TempDir; +++ use url::Url; +++ +++ use crate::Repository; +++ use crate::SubmoduleUpdateOptions; +++ +++ #[test] +++ fn smoke() { +++ let td = TempDir::new().unwrap(); +++ let repo = Repository::init(td.path()).unwrap(); +++ let mut s1 = repo +++ .submodule("/path/to/nowhere", Path::new("foo"), true) +++ .unwrap(); +++ s1.init(false).unwrap(); +++ s1.sync().unwrap(); +++ +++ let s2 = repo +++ .submodule("/path/to/nowhere", Path::new("bar"), true) +++ .unwrap(); +++ drop((s1, s2)); +++ +++ let mut submodules = repo.submodules().unwrap(); +++ assert_eq!(submodules.len(), 2); +++ let mut s = submodules.remove(0); +++ assert_eq!(s.name(), Some("bar")); +++ assert_eq!(s.url(), Some("/path/to/nowhere")); +++ assert_eq!(s.branch(), None); +++ assert!(s.head_id().is_none()); +++ assert!(s.index_id().is_none()); +++ assert!(s.workdir_id().is_none()); +++ +++ repo.find_submodule("bar").unwrap(); +++ s.open().unwrap(); +++ assert!(s.path() == Path::new("bar")); +++ s.reload(true).unwrap(); +++ } +++ +++ #[test] +++ fn add_a_submodule() { +++ let (_td, repo1) = crate::test::repo_init(); +++ let (td, repo2) = crate::test::repo_init(); +++ +++ let url = Url::from_file_path(&repo1.workdir().unwrap()).unwrap(); +++ let mut s = repo2 +++ .submodule(&url.to_string(), Path::new("bar"), true) +++ .unwrap(); +++ t!(fs::remove_dir_all(td.path().join("bar"))); +++ t!(Repository::clone(&url.to_string(), td.path().join("bar"))); +++ t!(s.add_to_index(false)); +++ t!(s.add_finalize()); +++ } +++ +++ #[test] +++ fn update_submodule() { +++ // ----------------------------------- +++ // Same as `add_a_submodule()` +++ let (_td, repo1) = crate::test::repo_init(); +++ let (td, repo2) = crate::test::repo_init(); +++ +++ let url = Url::from_file_path(&repo1.workdir().unwrap()).unwrap(); +++ let mut s = repo2 +++ .submodule(&url.to_string(), Path::new("bar"), true) +++ .unwrap(); +++ t!(fs::remove_dir_all(td.path().join("bar"))); +++ t!(Repository::clone(&url.to_string(), td.path().join("bar"))); +++ t!(s.add_to_index(false)); +++ t!(s.add_finalize()); +++ // ----------------------------------- +++ +++ // Attempt to update submodule +++ let submodules = t!(repo1.submodules()); +++ for mut submodule in submodules { +++ let mut submodule_options = SubmoduleUpdateOptions::new(); +++ let init = true; +++ let opts = Some(&mut submodule_options); +++ +++ t!(submodule.update(init, opts)); +++ } +++ } +++ +++ #[test] +++ fn clone_submodule() { +++ // ----------------------------------- +++ // Same as `add_a_submodule()` +++ let (_td, repo1) = crate::test::repo_init(); +++ let (_td, repo2) = crate::test::repo_init(); +++ let (_td, parent) = crate::test::repo_init(); +++ +++ let url1 = Url::from_file_path(&repo1.workdir().unwrap()).unwrap(); +++ let url2 = Url::from_file_path(&repo2.workdir().unwrap()).unwrap(); +++ let mut s1 = parent +++ .submodule(&url1.to_string(), Path::new("bar"), true) +++ .unwrap(); +++ let mut s2 = parent +++ .submodule(&url2.to_string(), Path::new("bar2"), true) +++ .unwrap(); +++ // ----------------------------------- +++ +++ t!(s1.clone(Some(&mut SubmoduleUpdateOptions::default()))); +++ t!(s2.clone(None)); +++ } +++ +++ #[test] +++ fn repo_init_submodule() { +++ // ----------------------------------- +++ // Same as `clone_submodule()` +++ let (_td, child) = crate::test::repo_init(); +++ let (_td, parent) = crate::test::repo_init(); +++ +++ let url_child = Url::from_file_path(&child.workdir().unwrap()).unwrap(); +++ let url_parent = Url::from_file_path(&parent.workdir().unwrap()).unwrap(); +++ let mut sub = parent +++ .submodule(&url_child.to_string(), Path::new("bar"), true) +++ .unwrap(); +++ +++ // ----------------------------------- +++ // Let's commit the submodule for later clone +++ t!(sub.clone(None)); +++ t!(sub.add_to_index(true)); +++ t!(sub.add_finalize()); +++ +++ crate::test::commit(&parent); +++ +++ // Clone the parent to init its submodules +++ let td = TempDir::new().unwrap(); +++ let new_parent = Repository::clone(&url_parent.to_string(), &td).unwrap(); +++ +++ let mut submodules = new_parent.submodules().unwrap(); +++ let child = submodules.first_mut().unwrap(); +++ +++ // First init child +++ t!(child.init(false)); +++ assert_eq!(child.url().unwrap(), url_child.as_str()); +++ +++ // open() is not possible before initializing the repo +++ assert!(child.open().is_err()); +++ t!(child.repo_init(true)); +++ assert!(child.open().is_ok()); +++ } +++} diff --cc extra/git2/src/tag.rs index 0000000000,0000000000,0000000000..6986c7c160 new file mode 100644 --- /dev/null +++ b/extra/git2/src/tag.rs @@@@ -1,0 -1,0 -1,0 +1,234 @@@@ +++use std::ffi::CString; +++use std::marker; +++use std::mem; +++use std::ptr; +++use std::str; +++ +++use crate::util::Binding; +++use crate::{call, raw, signature, Error, Object, ObjectType, Oid, Signature}; +++ +++/// A structure to represent a git [tag][1] +++/// +++/// [1]: http://git-scm.com/book/en/Git-Basics-Tagging +++pub struct Tag<'repo> { +++ raw: *mut raw::git_tag, +++ _marker: marker::PhantomData>, +++} +++ +++impl<'repo> Tag<'repo> { +++ /// Determine whether a tag name is valid, meaning that (when prefixed with refs/tags/) that +++ /// it is a valid reference name, and that any additional tag name restrictions are imposed +++ /// (eg, it cannot start with a -). +++ pub fn is_valid_name(tag_name: &str) -> bool { +++ crate::init(); +++ let tag_name = CString::new(tag_name).unwrap(); +++ let mut valid: libc::c_int = 0; +++ unsafe { +++ call::c_try(raw::git_tag_name_is_valid(&mut valid, tag_name.as_ptr())).unwrap(); +++ } +++ valid == 1 +++ } +++ +++ /// Get the id (SHA1) of a repository tag +++ pub fn id(&self) -> Oid { +++ unsafe { Binding::from_raw(raw::git_tag_id(&*self.raw)) } +++ } +++ +++ /// Get the message of a tag +++ /// +++ /// Returns None if there is no message or if it is not valid utf8 +++ pub fn message(&self) -> Option<&str> { +++ self.message_bytes().and_then(|s| str::from_utf8(s).ok()) +++ } +++ +++ /// Get the message of a tag +++ /// +++ /// Returns None if there is no message +++ pub fn message_bytes(&self) -> Option<&[u8]> { +++ unsafe { crate::opt_bytes(self, raw::git_tag_message(&*self.raw)) } +++ } +++ +++ /// Get the name of a tag +++ /// +++ /// Returns None if it is not valid utf8 +++ pub fn name(&self) -> Option<&str> { +++ str::from_utf8(self.name_bytes()).ok() +++ } +++ +++ /// Get the name of a tag +++ pub fn name_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, raw::git_tag_name(&*self.raw)).unwrap() } +++ } +++ +++ /// Recursively peel a tag until a non tag git_object is found +++ pub fn peel(&self) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_tag_peel(&mut ret, &*self.raw)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Get the tagger (author) of a tag +++ /// +++ /// If the author is unspecified, then `None` is returned. +++ pub fn tagger(&self) -> Option> { +++ unsafe { +++ let ptr = raw::git_tag_tagger(&*self.raw); +++ if ptr.is_null() { +++ None +++ } else { +++ Some(signature::from_raw_const(self, ptr)) +++ } +++ } +++ } +++ +++ /// Get the tagged object of a tag +++ /// +++ /// This method performs a repository lookup for the given object and +++ /// returns it +++ pub fn target(&self) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_tag_target(&mut ret, &*self.raw)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Get the OID of the tagged object of a tag +++ pub fn target_id(&self) -> Oid { +++ unsafe { Binding::from_raw(raw::git_tag_target_id(&*self.raw)) } +++ } +++ +++ /// Get the ObjectType of the tagged object of a tag +++ pub fn target_type(&self) -> Option { +++ unsafe { ObjectType::from_raw(raw::git_tag_target_type(&*self.raw)) } +++ } +++ +++ /// Casts this Tag to be usable as an `Object` +++ pub fn as_object(&self) -> &Object<'repo> { +++ unsafe { &*(self as *const _ as *const Object<'repo>) } +++ } +++ +++ /// Consumes Tag to be returned as an `Object` +++ pub fn into_object(self) -> Object<'repo> { +++ assert_eq!(mem::size_of_val(&self), mem::size_of::>()); +++ unsafe { mem::transmute(self) } +++ } +++} +++ +++impl<'repo> std::fmt::Debug for Tag<'repo> { +++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +++ let mut ds = f.debug_struct("Tag"); +++ if let Some(name) = self.name() { +++ ds.field("name", &name); +++ } +++ ds.field("id", &self.id()); +++ ds.finish() +++ } +++} +++ +++impl<'repo> Binding for Tag<'repo> { +++ type Raw = *mut raw::git_tag; +++ unsafe fn from_raw(raw: *mut raw::git_tag) -> Tag<'repo> { +++ Tag { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_tag { +++ self.raw +++ } +++} +++ +++impl<'repo> Clone for Tag<'repo> { +++ fn clone(&self) -> Self { +++ self.as_object().clone().into_tag().ok().unwrap() +++ } +++} +++ +++impl<'repo> Drop for Tag<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_tag_free(self.raw) } +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::Tag; +++ +++ // Reference -- https://git-scm.com/docs/git-check-ref-format +++ #[test] +++ fn name_is_valid() { +++ assert_eq!(Tag::is_valid_name("blah_blah"), true); +++ assert_eq!(Tag::is_valid_name("v1.2.3"), true); +++ assert_eq!(Tag::is_valid_name("my/tag"), true); +++ assert_eq!(Tag::is_valid_name("@"), true); +++ +++ assert_eq!(Tag::is_valid_name("-foo"), false); +++ assert_eq!(Tag::is_valid_name("foo:bar"), false); +++ assert_eq!(Tag::is_valid_name("foo^bar"), false); +++ assert_eq!(Tag::is_valid_name("foo."), false); +++ assert_eq!(Tag::is_valid_name("@{"), false); +++ assert_eq!(Tag::is_valid_name("as\\cd"), false); +++ } +++ +++ #[test] +++ #[should_panic] +++ fn is_valid_name_for_invalid_tag() { +++ Tag::is_valid_name("ab\012"); +++ } +++ +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ let head = repo.head().unwrap(); +++ let id = head.target().unwrap(); +++ assert!(repo.find_tag(id).is_err()); +++ +++ let obj = repo.find_object(id, None).unwrap(); +++ let sig = repo.signature().unwrap(); +++ let tag_id = repo.tag("foo", &obj, &sig, "msg", false).unwrap(); +++ let tag = repo.find_tag(tag_id).unwrap(); +++ assert_eq!(tag.id(), tag_id); +++ +++ let tags = repo.tag_names(None).unwrap(); +++ assert_eq!(tags.len(), 1); +++ assert_eq!(tags.get(0), Some("foo")); +++ +++ assert_eq!(tag.name(), Some("foo")); +++ assert_eq!(tag.message(), Some("msg")); +++ assert_eq!(tag.peel().unwrap().id(), obj.id()); +++ assert_eq!(tag.target_id(), obj.id()); +++ assert_eq!(tag.target_type(), Some(crate::ObjectType::Commit)); +++ +++ assert_eq!(tag.tagger().unwrap().name(), sig.name()); +++ tag.target().unwrap(); +++ tag.into_object(); +++ +++ repo.find_object(tag_id, None).unwrap().as_tag().unwrap(); +++ repo.find_object(tag_id, None) +++ .unwrap() +++ .into_tag() +++ .ok() +++ .unwrap(); +++ +++ repo.tag_delete("foo").unwrap(); +++ } +++ +++ #[test] +++ fn lite() { +++ let (_td, repo) = crate::test::repo_init(); +++ let head = t!(repo.head()); +++ let id = head.target().unwrap(); +++ let obj = t!(repo.find_object(id, None)); +++ let tag_id = t!(repo.tag_lightweight("foo", &obj, false)); +++ assert!(repo.find_tag(tag_id).is_err()); +++ assert_eq!(t!(repo.refname_to_id("refs/tags/foo")), id); +++ +++ let tags = t!(repo.tag_names(Some("f*"))); +++ assert_eq!(tags.len(), 1); +++ let tags = t!(repo.tag_names(Some("b*"))); +++ assert_eq!(tags.len(), 0); +++ } +++} diff --cc extra/git2/src/tagforeach.rs index 0000000000,0000000000,0000000000..425eea5a48 new file mode 100644 --- /dev/null +++ b/extra/git2/src/tagforeach.rs @@@@ -1,0 -1,0 -1,0 +1,69 @@@@ +++//! git_tag_foreach support +++//! see original: +++ +++use crate::{panic, raw, util::Binding, Oid}; +++use libc::{c_char, c_int}; +++use raw::git_oid; +++use std::ffi::{c_void, CStr}; +++ +++/// boxed callback type +++pub(crate) type TagForeachCB<'a> = Box bool + 'a>; +++ +++/// helper type to be able to pass callback to payload +++pub(crate) struct TagForeachData<'a> { +++ /// callback +++ pub(crate) cb: TagForeachCB<'a>, +++} +++ +++/// c callback forwarding to rust callback inside `TagForeachData` +++/// see original: +++pub(crate) extern "C" fn tag_foreach_cb( +++ name: *const c_char, +++ oid: *mut git_oid, +++ payload: *mut c_void, +++) -> c_int { +++ panic::wrap(|| unsafe { +++ let id: Oid = Binding::from_raw(oid as *const _); +++ +++ let name = CStr::from_ptr(name); +++ let name = name.to_bytes(); +++ +++ let payload = &mut *(payload as *mut TagForeachData<'_>); +++ let cb = &mut payload.cb; +++ +++ let res = cb(id, name); +++ +++ if res { +++ 0 +++ } else { +++ -1 +++ } +++ }) +++ .unwrap_or(-1) +++} +++ +++#[cfg(test)] +++mod tests { +++ +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ let head = repo.head().unwrap(); +++ let id = head.target().unwrap(); +++ assert!(repo.find_tag(id).is_err()); +++ +++ let obj = repo.find_object(id, None).unwrap(); +++ let sig = repo.signature().unwrap(); +++ let tag_id = repo.tag("foo", &obj, &sig, "msg", false).unwrap(); +++ +++ let mut tags = Vec::new(); +++ repo.tag_foreach(|id, name| { +++ tags.push((id, String::from_utf8(name.into()).unwrap())); +++ true +++ }) +++ .unwrap(); +++ +++ assert_eq!(tags[0].0, tag_id); +++ assert_eq!(tags[0].1, "refs/tags/foo"); +++ } +++} diff --cc extra/git2/src/test.rs index 0000000000,0000000000,0000000000..57a590f519 new file mode 100644 --- /dev/null +++ b/extra/git2/src/test.rs @@@@ -1,0 -1,0 -1,0 +1,89 @@@@ +++use std::fs::File; +++use std::io; +++use std::path::{Path, PathBuf}; +++#[cfg(unix)] +++use std::ptr; +++use tempfile::TempDir; +++use url::Url; +++ +++use crate::{Branch, Oid, Repository, RepositoryInitOptions}; +++ +++macro_rules! t { +++ ($e:expr) => { +++ match $e { +++ Ok(e) => e, +++ Err(e) => panic!("{} failed with {}", stringify!($e), e), +++ } +++ }; +++} +++ +++pub fn repo_init() -> (TempDir, Repository) { +++ let td = TempDir::new().unwrap(); +++ let mut opts = RepositoryInitOptions::new(); +++ opts.initial_head("main"); +++ let repo = Repository::init_opts(td.path(), &opts).unwrap(); +++ { +++ let mut config = repo.config().unwrap(); +++ config.set_str("user.name", "name").unwrap(); +++ config.set_str("user.email", "email").unwrap(); +++ let mut index = repo.index().unwrap(); +++ let id = index.write_tree().unwrap(); +++ +++ let tree = repo.find_tree(id).unwrap(); +++ let sig = repo.signature().unwrap(); +++ repo.commit(Some("HEAD"), &sig, &sig, "initial\n\nbody", &tree, &[]) +++ .unwrap(); +++ } +++ (td, repo) +++} +++ +++pub fn commit(repo: &Repository) -> (Oid, Oid) { +++ let mut index = t!(repo.index()); +++ let root = repo.path().parent().unwrap(); +++ t!(File::create(&root.join("foo"))); +++ t!(index.add_path(Path::new("foo"))); +++ +++ let tree_id = t!(index.write_tree()); +++ let tree = t!(repo.find_tree(tree_id)); +++ let sig = t!(repo.signature()); +++ let head_id = t!(repo.refname_to_id("HEAD")); +++ let parent = t!(repo.find_commit(head_id)); +++ let commit = t!(repo.commit(Some("HEAD"), &sig, &sig, "commit", &tree, &[&parent])); +++ (commit, tree_id) +++} +++ +++pub fn path2url(path: &Path) -> String { +++ Url::from_file_path(path).unwrap().to_string() +++} +++ +++pub fn worktrees_env_init(repo: &Repository) -> (TempDir, Branch<'_>) { +++ let oid = repo.head().unwrap().target().unwrap(); +++ let commit = repo.find_commit(oid).unwrap(); +++ let branch = repo.branch("wt-branch", &commit, true).unwrap(); +++ let wtdir = TempDir::new().unwrap(); +++ (wtdir, branch) +++} +++ +++#[cfg(windows)] +++pub fn realpath(original: &Path) -> io::Result { +++ Ok(original.canonicalize()?.to_path_buf()) +++} +++#[cfg(unix)] +++pub fn realpath(original: &Path) -> io::Result { +++ use libc::c_char; +++ use std::ffi::{CStr, CString, OsString}; +++ use std::os::unix::prelude::*; +++ extern "C" { +++ fn realpath(name: *const c_char, resolved: *mut c_char) -> *mut c_char; +++ } +++ unsafe { +++ let cstr = CString::new(original.as_os_str().as_bytes())?; +++ let ptr = realpath(cstr.as_ptr(), ptr::null_mut()); +++ if ptr.is_null() { +++ return Err(io::Error::last_os_error()); +++ } +++ let bytes = CStr::from_ptr(ptr).to_bytes().to_vec(); +++ libc::free(ptr as *mut _); +++ Ok(PathBuf::from(OsString::from_vec(bytes))) +++ } +++} diff --cc extra/git2/src/time.rs index 0000000000,0000000000,0000000000..46b5bd3f94 new file mode 100644 --- /dev/null +++ b/extra/git2/src/time.rs @@@@ -1,0 -1,0 -1,0 +1,127 @@@@ +++use std::cmp::Ordering; +++ +++use libc::{c_char, c_int}; +++ +++use crate::raw; +++use crate::util::Binding; +++ +++/// Time in a signature +++#[derive(Copy, Clone, Debug, Eq, PartialEq)] +++pub struct Time { +++ raw: raw::git_time, +++} +++ +++/// Time structure used in a git index entry. +++#[derive(Copy, Clone, Debug, Eq, PartialEq)] +++pub struct IndexTime { +++ raw: raw::git_index_time, +++} +++ +++impl Time { +++ /// Creates a new time structure from its components. +++ pub fn new(time: i64, offset: i32) -> Time { +++ unsafe { +++ Binding::from_raw(raw::git_time { +++ time: time as raw::git_time_t, +++ offset: offset as c_int, +++ sign: if offset < 0 { '-' } else { '+' } as c_char, +++ }) +++ } +++ } +++ +++ /// Return the time, in seconds, from epoch +++ pub fn seconds(&self) -> i64 { +++ self.raw.time as i64 +++ } +++ +++ /// Return the timezone offset, in minutes +++ pub fn offset_minutes(&self) -> i32 { +++ self.raw.offset as i32 +++ } +++ +++ /// Return whether the offset was positive or negative. Primarily useful +++ /// in case the offset is specified as a negative zero. +++ pub fn sign(&self) -> char { +++ self.raw.sign as u8 as char +++ } +++} +++ +++impl PartialOrd for Time { +++ fn partial_cmp(&self, other: &Time) -> Option { +++ Some(self.cmp(other)) +++ } +++} +++ +++impl Ord for Time { +++ fn cmp(&self, other: &Time) -> Ordering { +++ (self.raw.time, self.raw.offset).cmp(&(other.raw.time, other.raw.offset)) +++ } +++} +++ +++impl Binding for Time { +++ type Raw = raw::git_time; +++ unsafe fn from_raw(raw: raw::git_time) -> Time { +++ Time { raw } +++ } +++ fn raw(&self) -> raw::git_time { +++ self.raw +++ } +++} +++ +++impl IndexTime { +++ /// Creates a new time structure from its components. +++ pub fn new(seconds: i32, nanoseconds: u32) -> IndexTime { +++ unsafe { +++ Binding::from_raw(raw::git_index_time { +++ seconds, +++ nanoseconds, +++ }) +++ } +++ } +++ +++ /// Returns the number of seconds in the second component of this time. +++ pub fn seconds(&self) -> i32 { +++ self.raw.seconds +++ } +++ /// Returns the nanosecond component of this time. +++ pub fn nanoseconds(&self) -> u32 { +++ self.raw.nanoseconds +++ } +++} +++ +++impl Binding for IndexTime { +++ type Raw = raw::git_index_time; +++ unsafe fn from_raw(raw: raw::git_index_time) -> IndexTime { +++ IndexTime { raw } +++ } +++ fn raw(&self) -> raw::git_index_time { +++ self.raw +++ } +++} +++ +++impl PartialOrd for IndexTime { +++ fn partial_cmp(&self, other: &IndexTime) -> Option { +++ Some(self.cmp(other)) +++ } +++} +++ +++impl Ord for IndexTime { +++ fn cmp(&self, other: &IndexTime) -> Ordering { +++ let me = (self.raw.seconds, self.raw.nanoseconds); +++ let other = (other.raw.seconds, other.raw.nanoseconds); +++ me.cmp(&other) +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::Time; +++ +++ #[test] +++ fn smoke() { +++ assert_eq!(Time::new(1608839587, -300).seconds(), 1608839587); +++ assert_eq!(Time::new(1608839587, -300).offset_minutes(), -300); +++ assert_eq!(Time::new(1608839587, -300).sign(), '-'); +++ assert_eq!(Time::new(1608839587, 300).sign(), '+'); +++ } +++} diff --cc extra/git2/src/tracing.rs index 0000000000,0000000000,0000000000..9872571dd3 new file mode 100644 --- /dev/null +++ b/extra/git2/src/tracing.rs @@@@ -1,0 -1,0 -1,0 +1,140 @@@@ +++use std::{ +++ ffi::CStr, +++ sync::atomic::{AtomicPtr, Ordering}, +++}; +++ +++use libc::{c_char, c_int}; +++ +++use crate::{panic, raw, util::Binding, Error}; +++ +++/// Available tracing levels. When tracing is set to a particular level, +++/// callers will be provided tracing at the given level and all lower levels. +++#[derive(Copy, Clone, Debug)] +++pub enum TraceLevel { +++ /// No tracing will be performed. +++ None, +++ +++ /// Severe errors that may impact the program's execution +++ Fatal, +++ +++ /// Errors that do not impact the program's execution +++ Error, +++ +++ /// Warnings that suggest abnormal data +++ Warn, +++ +++ /// Informational messages about program execution +++ Info, +++ +++ /// Detailed data that allows for debugging +++ Debug, +++ +++ /// Exceptionally detailed debugging data +++ Trace, +++} +++ +++impl Binding for TraceLevel { +++ type Raw = raw::git_trace_level_t; +++ unsafe fn from_raw(raw: raw::git_trace_level_t) -> Self { +++ match raw { +++ raw::GIT_TRACE_NONE => Self::None, +++ raw::GIT_TRACE_FATAL => Self::Fatal, +++ raw::GIT_TRACE_ERROR => Self::Error, +++ raw::GIT_TRACE_WARN => Self::Warn, +++ raw::GIT_TRACE_INFO => Self::Info, +++ raw::GIT_TRACE_DEBUG => Self::Debug, +++ raw::GIT_TRACE_TRACE => Self::Trace, +++ _ => panic!("Unknown git trace level"), +++ } +++ } +++ fn raw(&self) -> raw::git_trace_level_t { +++ match *self { +++ Self::None => raw::GIT_TRACE_NONE, +++ Self::Fatal => raw::GIT_TRACE_FATAL, +++ Self::Error => raw::GIT_TRACE_ERROR, +++ Self::Warn => raw::GIT_TRACE_WARN, +++ Self::Info => raw::GIT_TRACE_INFO, +++ Self::Debug => raw::GIT_TRACE_DEBUG, +++ Self::Trace => raw::GIT_TRACE_TRACE, +++ } +++ } +++} +++ +++/// Callback type used to pass tracing events to the subscriber. +++/// see `trace_set` to register a subscriber. +++pub type TracingCb = fn(TraceLevel, &[u8]); +++ +++/// Use an atomic pointer to store the global tracing subscriber function. +++static CALLBACK: AtomicPtr<()> = AtomicPtr::new(std::ptr::null_mut()); +++ +++/// Set the global subscriber called when libgit2 produces a tracing message. +++pub fn trace_set(level: TraceLevel, cb: TracingCb) -> Result<(), Error> { +++ // Store the callback in the global atomic. +++ CALLBACK.store(cb as *mut (), Ordering::SeqCst); +++ +++ // git_trace_set returns 0 if there was no error. +++ let return_code: c_int = unsafe { raw::git_trace_set(level.raw(), Some(tracing_cb_c)) }; +++ +++ if return_code != 0 { +++ Err(Error::last_error(return_code)) +++ } else { +++ Ok(()) +++ } +++} +++ +++/// The tracing callback we pass to libgit2 (C ABI compatible). +++extern "C" fn tracing_cb_c(level: raw::git_trace_level_t, msg: *const c_char) { +++ // Load the callback function pointer from the global atomic. +++ let cb: *mut () = CALLBACK.load(Ordering::SeqCst); +++ +++ // Transmute the callback pointer into the function pointer we know it to be. +++ // +++ // SAFETY: We only ever set the callback pointer with something cast from a TracingCb +++ // so transmuting back to a TracingCb is safe. This is notably not an integer-to-pointer +++ // transmute as described in the mem::transmute documentation and is in-line with the +++ // example in that documentation for casing between *const () to fn pointers. +++ let cb: TracingCb = unsafe { std::mem::transmute(cb) }; +++ +++ // If libgit2 passes us a message that is null, drop it and do not pass it to the callback. +++ // This is to avoid ever exposing rust code to a null ref, which would be Undefined Behavior. +++ if msg.is_null() { +++ return; +++ } +++ +++ // Convert the message from a *const c_char to a &[u8] and pass it to the callback. +++ // +++ // SAFETY: We've just checked that the pointer is not null. The other safety requirements are left to +++ // libgit2 to enforce -- namely that it gives us a valid, nul-terminated, C string, that that string exists +++ // entirely in one allocation, that the string will not be mutated once passed to us, and that the nul-terminator is +++ // within isize::MAX bytes from the given pointers data address. +++ let msg: &CStr = unsafe { CStr::from_ptr(msg) }; +++ +++ // Convert from a CStr to &[u8] to pass to the rust code callback. +++ let msg: &[u8] = CStr::to_bytes(msg); +++ +++ // Do the remaining part of this function in a panic wrapper, to catch any panics it produces. +++ panic::wrap(|| { +++ // Convert the raw trace level into a type we can pass to the rust callback fn. +++ // +++ // SAFETY: Currently the implementation of this function (above) may panic, but is only marked as unsafe to match +++ // the trait definition, thus we can consider this call safe. +++ let level: TraceLevel = unsafe { Binding::from_raw(level) }; +++ +++ // Call the user-supplied callback (which may panic). +++ (cb)(level, msg); +++ }); +++} +++ +++#[cfg(test)] +++mod tests { +++ use super::TraceLevel; +++ +++ // Test that using the above function to set a tracing callback doesn't panic. +++ #[test] +++ fn smoke() { +++ super::trace_set(TraceLevel::Trace, |level, msg| { +++ dbg!(level, msg); +++ }) +++ .expect("libgit2 can set global trace callback"); +++ } +++} diff --cc extra/git2/src/transaction.rs index 0000000000,0000000000,0000000000..4f661f1d48 new file mode 100644 --- /dev/null +++ b/extra/git2/src/transaction.rs @@@@ -1,0 -1,0 -1,0 +1,285 @@@@ +++use std::ffi::CString; +++use std::marker; +++ +++use crate::{raw, util::Binding, Error, Oid, Reflog, Repository, Signature}; +++ +++/// A structure representing a transactional update of a repository's references. +++/// +++/// Transactions work by locking loose refs for as long as the [`Transaction`] +++/// is held, and committing all changes to disk when [`Transaction::commit`] is +++/// called. Note that committing is not atomic: if an operation fails, the +++/// transaction aborts, but previous successful operations are not rolled back. +++pub struct Transaction<'repo> { +++ raw: *mut raw::git_transaction, +++ _marker: marker::PhantomData<&'repo Repository>, +++} +++ +++impl Drop for Transaction<'_> { +++ fn drop(&mut self) { +++ unsafe { raw::git_transaction_free(self.raw) } +++ } +++} +++ +++impl<'repo> Binding for Transaction<'repo> { +++ type Raw = *mut raw::git_transaction; +++ +++ unsafe fn from_raw(ptr: *mut raw::git_transaction) -> Transaction<'repo> { +++ Transaction { +++ raw: ptr, +++ _marker: marker::PhantomData, +++ } +++ } +++ +++ fn raw(&self) -> *mut raw::git_transaction { +++ self.raw +++ } +++} +++ +++impl<'repo> Transaction<'repo> { +++ /// Lock the specified reference by name. +++ pub fn lock_ref(&mut self, refname: &str) -> Result<(), Error> { +++ let refname = CString::new(refname).unwrap(); +++ unsafe { +++ try_call!(raw::git_transaction_lock_ref(self.raw, refname)); +++ } +++ +++ Ok(()) +++ } +++ +++ /// Set the target of the specified reference. +++ /// +++ /// The reference must have been locked via `lock_ref`. +++ /// +++ /// If `reflog_signature` is `None`, the [`Signature`] is read from the +++ /// repository config. +++ pub fn set_target( +++ &mut self, +++ refname: &str, +++ target: Oid, +++ reflog_signature: Option<&Signature<'_>>, +++ reflog_message: &str, +++ ) -> Result<(), Error> { +++ let refname = CString::new(refname).unwrap(); +++ let reflog_message = CString::new(reflog_message).unwrap(); +++ unsafe { +++ try_call!(raw::git_transaction_set_target( +++ self.raw, +++ refname, +++ target.raw(), +++ reflog_signature.map(|s| s.raw()), +++ reflog_message +++ )); +++ } +++ +++ Ok(()) +++ } +++ +++ /// Set the target of the specified symbolic reference. +++ /// +++ /// The reference must have been locked via `lock_ref`. +++ /// +++ /// If `reflog_signature` is `None`, the [`Signature`] is read from the +++ /// repository config. +++ pub fn set_symbolic_target( +++ &mut self, +++ refname: &str, +++ target: &str, +++ reflog_signature: Option<&Signature<'_>>, +++ reflog_message: &str, +++ ) -> Result<(), Error> { +++ let refname = CString::new(refname).unwrap(); +++ let target = CString::new(target).unwrap(); +++ let reflog_message = CString::new(reflog_message).unwrap(); +++ unsafe { +++ try_call!(raw::git_transaction_set_symbolic_target( +++ self.raw, +++ refname, +++ target, +++ reflog_signature.map(|s| s.raw()), +++ reflog_message +++ )); +++ } +++ +++ Ok(()) +++ } +++ +++ /// Add a [`Reflog`] to the transaction. +++ /// +++ /// This commit the in-memory [`Reflog`] to disk when the transaction commits. +++ /// Note that atomicity is **not* guaranteed: if the transaction fails to +++ /// modify `refname`, the reflog may still have been committed to disk. +++ /// +++ /// If this is combined with setting the target, that update won't be +++ /// written to the log (i.e. the `reflog_signature` and `reflog_message` +++ /// parameters will be ignored). +++ pub fn set_reflog(&mut self, refname: &str, reflog: Reflog) -> Result<(), Error> { +++ let refname = CString::new(refname).unwrap(); +++ unsafe { +++ try_call!(raw::git_transaction_set_reflog( +++ self.raw, +++ refname, +++ reflog.raw() +++ )); +++ } +++ +++ Ok(()) +++ } +++ +++ /// Remove a reference. +++ /// +++ /// The reference must have been locked via `lock_ref`. +++ pub fn remove(&mut self, refname: &str) -> Result<(), Error> { +++ let refname = CString::new(refname).unwrap(); +++ unsafe { +++ try_call!(raw::git_transaction_remove(self.raw, refname)); +++ } +++ +++ Ok(()) +++ } +++ +++ /// Commit the changes from the transaction. +++ /// +++ /// The updates will be made one by one, and the first failure will stop the +++ /// processing. +++ pub fn commit(self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_transaction_commit(self.raw)); +++ } +++ Ok(()) +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::{Error, ErrorClass, ErrorCode, Oid, Repository}; +++ +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ let mut tx = t!(repo.transaction()); +++ +++ t!(tx.lock_ref("refs/heads/main")); +++ t!(tx.lock_ref("refs/heads/next")); +++ +++ t!(tx.set_target("refs/heads/main", Oid::zero(), None, "set main to zero")); +++ t!(tx.set_symbolic_target( +++ "refs/heads/next", +++ "refs/heads/main", +++ None, +++ "set next to main", +++ )); +++ +++ t!(tx.commit()); +++ +++ assert_eq!(repo.refname_to_id("refs/heads/main").unwrap(), Oid::zero()); +++ assert_eq!( +++ repo.find_reference("refs/heads/next") +++ .unwrap() +++ .symbolic_target() +++ .unwrap(), +++ "refs/heads/main" +++ ); +++ } +++ +++ #[test] +++ fn locks_same_repo_handle() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ let mut tx1 = t!(repo.transaction()); +++ t!(tx1.lock_ref("refs/heads/seen")); +++ +++ let mut tx2 = t!(repo.transaction()); +++ assert!(matches!(tx2.lock_ref("refs/heads/seen"), Err(e) if e.code() == ErrorCode::Locked)) +++ } +++ +++ #[test] +++ fn locks_across_repo_handles() { +++ let (td, repo1) = crate::test::repo_init(); +++ let repo2 = t!(Repository::open(&td)); +++ +++ let mut tx1 = t!(repo1.transaction()); +++ t!(tx1.lock_ref("refs/heads/seen")); +++ +++ let mut tx2 = t!(repo2.transaction()); +++ assert!(matches!(tx2.lock_ref("refs/heads/seen"), Err(e) if e.code() == ErrorCode::Locked)) +++ } +++ +++ #[test] +++ fn drop_unlocks() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ let mut tx = t!(repo.transaction()); +++ t!(tx.lock_ref("refs/heads/seen")); +++ drop(tx); +++ +++ let mut tx2 = t!(repo.transaction()); +++ t!(tx2.lock_ref("refs/heads/seen")) +++ } +++ +++ #[test] +++ fn commit_unlocks() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ let mut tx = t!(repo.transaction()); +++ t!(tx.lock_ref("refs/heads/seen")); +++ t!(tx.commit()); +++ +++ let mut tx2 = t!(repo.transaction()); +++ t!(tx2.lock_ref("refs/heads/seen")); +++ } +++ +++ #[test] +++ fn prevents_non_transactional_updates() { +++ let (_td, repo) = crate::test::repo_init(); +++ let head = t!(repo.refname_to_id("HEAD")); +++ +++ let mut tx = t!(repo.transaction()); +++ t!(tx.lock_ref("refs/heads/seen")); +++ +++ assert!(matches!( +++ repo.reference("refs/heads/seen", head, true, "competing with lock"), +++ Err(e) if e.code() == ErrorCode::Locked +++ )); +++ } +++ +++ #[test] +++ fn remove() { +++ let (_td, repo) = crate::test::repo_init(); +++ let head = t!(repo.refname_to_id("HEAD")); +++ let next = "refs/heads/next"; +++ +++ t!(repo.reference( +++ next, +++ head, +++ true, +++ "refs/heads/next@{0}: branch: Created from HEAD" +++ )); +++ +++ { +++ let mut tx = t!(repo.transaction()); +++ t!(tx.lock_ref(next)); +++ t!(tx.remove(next)); +++ t!(tx.commit()); +++ } +++ assert!(matches!(repo.refname_to_id(next), Err(e) if e.code() == ErrorCode::NotFound)) +++ } +++ +++ #[test] +++ fn must_lock_ref() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ // 🤷 +++ fn is_not_locked_err(e: &Error) -> bool { +++ e.code() == ErrorCode::NotFound +++ && e.class() == ErrorClass::Reference +++ && e.message() == "the specified reference is not locked" +++ } +++ +++ let mut tx = t!(repo.transaction()); +++ assert!(matches!( +++ tx.set_target("refs/heads/main", Oid::zero(), None, "set main to zero"), +++ Err(e) if is_not_locked_err(&e) +++ )) +++ } +++} diff --cc extra/git2/src/transport.rs index 0000000000,0000000000,0000000000..b1ca3f8b80 new file mode 100644 --- /dev/null +++ b/extra/git2/src/transport.rs @@@@ -1,0 -1,0 -1,0 +1,421 @@@@ +++//! Interfaces for adding custom transports to libgit2 +++ +++use libc::{c_char, c_int, c_uint, c_void, size_t}; +++use std::ffi::{CStr, CString}; +++use std::io; +++use std::io::prelude::*; +++use std::mem; +++use std::ptr; +++use std::slice; +++use std::str; +++ +++use crate::util::Binding; +++use crate::{panic, raw, Error, Remote}; +++ +++/// A transport is a structure which knows how to transfer data to and from a +++/// remote. +++/// +++/// This transport is a representation of the raw transport underneath it, which +++/// is similar to a trait object in Rust. +++#[allow(missing_copy_implementations)] +++pub struct Transport { +++ raw: *mut raw::git_transport, +++ owned: bool, +++} +++ +++/// Interface used by smart transports. +++/// +++/// The full-fledged definition of transports has to deal with lots of +++/// nitty-gritty details of the git protocol, but "smart transports" largely +++/// only need to deal with read() and write() of data over a channel. +++/// +++/// A smart subtransport is contained within an instance of a smart transport +++/// and is delegated to in order to actually conduct network activity to push or +++/// pull data from a remote. +++pub trait SmartSubtransport: Send + 'static { +++ /// Indicates that this subtransport will be performing the specified action +++ /// on the specified URL. +++ /// +++ /// This function is responsible for making any network connections and +++ /// returns a stream which can be read and written from in order to +++ /// negotiate the git protocol. +++ fn action(&self, url: &str, action: Service) +++ -> Result, Error>; +++ +++ /// Terminates a connection with the remote. +++ /// +++ /// Each subtransport is guaranteed a call to close() between calls to +++ /// action(), except for the following two natural progressions of actions +++ /// against a constant URL. +++ /// +++ /// 1. UploadPackLs -> UploadPack +++ /// 2. ReceivePackLs -> ReceivePack +++ fn close(&self) -> Result<(), Error>; +++} +++ +++/// Actions that a smart transport can ask a subtransport to perform +++#[derive(Copy, Clone, PartialEq, Debug)] +++#[allow(missing_docs)] +++pub enum Service { +++ UploadPackLs, +++ UploadPack, +++ ReceivePackLs, +++ ReceivePack, +++} +++ +++/// An instance of a stream over which a smart transport will communicate with a +++/// remote. +++/// +++/// Currently this only requires the standard `Read` and `Write` traits. This +++/// trait also does not need to be implemented manually as long as the `Read` +++/// and `Write` traits are implemented. +++pub trait SmartSubtransportStream: Read + Write + Send + 'static {} +++ +++impl SmartSubtransportStream for T {} +++ +++type TransportFactory = dyn Fn(&Remote<'_>) -> Result + Send + Sync + 'static; +++ +++/// Boxed data payload used for registering new transports. +++/// +++/// Currently only contains a field which knows how to create transports. +++struct TransportData { +++ factory: Box, +++} +++ +++/// Instance of a `git_smart_subtransport`, must use `#[repr(C)]` to ensure that +++/// the C fields come first. +++#[repr(C)] +++struct RawSmartSubtransport { +++ raw: raw::git_smart_subtransport, +++ stream: Option<*mut raw::git_smart_subtransport_stream>, +++ rpc: bool, +++ obj: Box, +++} +++ +++/// Instance of a `git_smart_subtransport_stream`, must use `#[repr(C)]` to +++/// ensure that the C fields come first. +++#[repr(C)] +++struct RawSmartSubtransportStream { +++ raw: raw::git_smart_subtransport_stream, +++ obj: Box, +++} +++ +++/// Add a custom transport definition, to be used in addition to the built-in +++/// set of transports that come with libgit2. +++/// +++/// This function is unsafe as it needs to be externally synchronized with calls +++/// to creation of other transports. +++pub unsafe fn register(prefix: &str, factory: F) -> Result<(), Error> +++where +++ F: Fn(&Remote<'_>) -> Result + Send + Sync + 'static, +++{ +++ crate::init(); +++ let mut data = Box::new(TransportData { +++ factory: Box::new(factory), +++ }); +++ let prefix = CString::new(prefix)?; +++ let datap = (&mut *data) as *mut TransportData as *mut c_void; +++ let factory: raw::git_transport_cb = Some(transport_factory); +++ try_call!(raw::git_transport_register(prefix, factory, datap)); +++ mem::forget(data); +++ Ok(()) +++} +++ +++impl Transport { +++ /// Creates a new transport which will use the "smart" transport protocol +++ /// for transferring data. +++ /// +++ /// A smart transport requires a *subtransport* over which data is actually +++ /// communicated, but this subtransport largely just needs to be able to +++ /// read() and write(). The subtransport provided will be used to make +++ /// connections which can then be read/written from. +++ /// +++ /// The `rpc` argument is `true` if the protocol is stateless, false +++ /// otherwise. For example `http://` is stateless but `git://` is not. +++ pub fn smart(remote: &Remote<'_>, rpc: bool, subtransport: S) -> Result +++ where +++ S: SmartSubtransport, +++ { +++ let mut ret = ptr::null_mut(); +++ +++ let mut raw = Box::new(RawSmartSubtransport { +++ raw: raw::git_smart_subtransport { +++ action: Some(subtransport_action), +++ close: Some(subtransport_close), +++ free: Some(subtransport_free), +++ }, +++ stream: None, +++ rpc, +++ obj: Box::new(subtransport), +++ }); +++ let mut defn = raw::git_smart_subtransport_definition { +++ callback: Some(smart_factory), +++ rpc: rpc as c_uint, +++ param: &mut *raw as *mut _ as *mut _, +++ }; +++ +++ // Currently there's no way to pass a payload via the +++ // git_smart_subtransport_definition structure, but it's only used as a +++ // configuration for the initial creation of the smart transport (verified +++ // by reading the current code, hopefully it doesn't change!). +++ // +++ // We, however, need some state (gotta pass in our +++ // `RawSmartSubtransport`). This also means that this block must be +++ // entirely synchronized with a lock (boo!) +++ unsafe { +++ try_call!(raw::git_transport_smart( +++ &mut ret, +++ remote.raw(), +++ &mut defn as *mut _ as *mut _ +++ )); +++ mem::forget(raw); // ownership transport to `ret` +++ } +++ return Ok(Transport { +++ raw: ret, +++ owned: true, +++ }); +++ +++ extern "C" fn smart_factory( +++ out: *mut *mut raw::git_smart_subtransport, +++ _owner: *mut raw::git_transport, +++ ptr: *mut c_void, +++ ) -> c_int { +++ unsafe { +++ *out = ptr as *mut raw::git_smart_subtransport; +++ 0 +++ } +++ } +++ } +++} +++ +++impl Drop for Transport { +++ fn drop(&mut self) { +++ if self.owned { +++ unsafe { (*self.raw).free.unwrap()(self.raw) } +++ } +++ } +++} +++ +++// callback used by register() to create new transports +++extern "C" fn transport_factory( +++ out: *mut *mut raw::git_transport, +++ owner: *mut raw::git_remote, +++ param: *mut c_void, +++) -> c_int { +++ struct Bomb<'a> { +++ remote: Option>, +++ } +++ impl<'a> Drop for Bomb<'a> { +++ fn drop(&mut self) { +++ // TODO: maybe a method instead? +++ mem::forget(self.remote.take()); +++ } +++ } +++ +++ panic::wrap(|| unsafe { +++ let remote = Bomb { +++ remote: Some(Binding::from_raw(owner)), +++ }; +++ let data = &mut *(param as *mut TransportData); +++ match (data.factory)(remote.remote.as_ref().unwrap()) { +++ Ok(mut transport) => { +++ *out = transport.raw; +++ transport.owned = false; +++ 0 +++ } +++ Err(e) => e.raw_code() as c_int, +++ } +++ }) +++ .unwrap_or(-1) +++} +++ +++// callback used by smart transports to delegate an action to a +++// `SmartSubtransport` trait object. +++extern "C" fn subtransport_action( +++ stream: *mut *mut raw::git_smart_subtransport_stream, +++ raw_transport: *mut raw::git_smart_subtransport, +++ url: *const c_char, +++ action: raw::git_smart_service_t, +++) -> c_int { +++ panic::wrap(|| unsafe { +++ let url = CStr::from_ptr(url).to_bytes(); +++ let url = match str::from_utf8(url).ok() { +++ Some(s) => s, +++ None => return -1, +++ }; +++ let action = match action { +++ raw::GIT_SERVICE_UPLOADPACK_LS => Service::UploadPackLs, +++ raw::GIT_SERVICE_UPLOADPACK => Service::UploadPack, +++ raw::GIT_SERVICE_RECEIVEPACK_LS => Service::ReceivePackLs, +++ raw::GIT_SERVICE_RECEIVEPACK => Service::ReceivePack, +++ n => panic!("unknown action: {}", n), +++ }; +++ +++ let transport = &mut *(raw_transport as *mut RawSmartSubtransport); +++ // Note: we only need to generate if rpc is on. Else, for receive-pack and upload-pack +++ // libgit2 reuses the stream generated for receive-pack-ls or upload-pack-ls. +++ let generate_stream = +++ transport.rpc || action == Service::UploadPackLs || action == Service::ReceivePackLs; +++ if generate_stream { +++ let obj = match transport.obj.action(url, action) { +++ Ok(s) => s, +++ Err(e) => return e.raw_set_git_error(), +++ }; +++ *stream = mem::transmute(Box::new(RawSmartSubtransportStream { +++ raw: raw::git_smart_subtransport_stream { +++ subtransport: raw_transport, +++ read: Some(stream_read), +++ write: Some(stream_write), +++ free: Some(stream_free), +++ }, +++ obj, +++ })); +++ transport.stream = Some(*stream); +++ } else { +++ if transport.stream.is_none() { +++ return -1; +++ } +++ *stream = transport.stream.unwrap(); +++ } +++ 0 +++ }) +++ .unwrap_or(-1) +++} +++ +++// callback used by smart transports to close a `SmartSubtransport` trait +++// object. +++extern "C" fn subtransport_close(transport: *mut raw::git_smart_subtransport) -> c_int { +++ let ret = panic::wrap(|| unsafe { +++ let transport = &mut *(transport as *mut RawSmartSubtransport); +++ transport.obj.close() +++ }); +++ match ret { +++ Some(Ok(())) => 0, +++ Some(Err(e)) => e.raw_code() as c_int, +++ None => -1, +++ } +++} +++ +++// callback used by smart transports to free a `SmartSubtransport` trait +++// object. +++extern "C" fn subtransport_free(transport: *mut raw::git_smart_subtransport) { +++ let _ = panic::wrap(|| unsafe { +++ mem::transmute::<_, Box>(transport); +++ }); +++} +++ +++// callback used by smart transports to read from a `SmartSubtransportStream` +++// object. +++extern "C" fn stream_read( +++ stream: *mut raw::git_smart_subtransport_stream, +++ buffer: *mut c_char, +++ buf_size: size_t, +++ bytes_read: *mut size_t, +++) -> c_int { +++ let ret = panic::wrap(|| unsafe { +++ let transport = &mut *(stream as *mut RawSmartSubtransportStream); +++ let buf = slice::from_raw_parts_mut(buffer as *mut u8, buf_size as usize); +++ match transport.obj.read(buf) { +++ Ok(n) => { +++ *bytes_read = n as size_t; +++ Ok(n) +++ } +++ e => e, +++ } +++ }); +++ match ret { +++ Some(Ok(_)) => 0, +++ Some(Err(e)) => unsafe { +++ set_err_io(&e); +++ -2 +++ }, +++ None => -1, +++ } +++} +++ +++// callback used by smart transports to write to a `SmartSubtransportStream` +++// object. +++extern "C" fn stream_write( +++ stream: *mut raw::git_smart_subtransport_stream, +++ buffer: *const c_char, +++ len: size_t, +++) -> c_int { +++ let ret = panic::wrap(|| unsafe { +++ let transport = &mut *(stream as *mut RawSmartSubtransportStream); +++ let buf = slice::from_raw_parts(buffer as *const u8, len as usize); +++ transport.obj.write_all(buf) +++ }); +++ match ret { +++ Some(Ok(())) => 0, +++ Some(Err(e)) => unsafe { +++ set_err_io(&e); +++ -2 +++ }, +++ None => -1, +++ } +++} +++ +++unsafe fn set_err_io(e: &io::Error) { +++ let s = CString::new(e.to_string()).unwrap(); +++ raw::git_error_set_str(raw::GIT_ERROR_NET as c_int, s.as_ptr()); +++} +++ +++// callback used by smart transports to free a `SmartSubtransportStream` +++// object. +++extern "C" fn stream_free(stream: *mut raw::git_smart_subtransport_stream) { +++ let _ = panic::wrap(|| unsafe { +++ mem::transmute::<_, Box>(stream); +++ }); +++} +++ +++#[cfg(test)] +++mod tests { +++ use super::*; +++ use crate::{ErrorClass, ErrorCode}; +++ use std::sync::Once; +++ +++ struct DummyTransport; +++ +++ // in lieu of lazy_static +++ fn dummy_error() -> Error { +++ Error::new(ErrorCode::Ambiguous, ErrorClass::Net, "bleh") +++ } +++ +++ impl SmartSubtransport for DummyTransport { +++ fn action( +++ &self, +++ _url: &str, +++ _service: Service, +++ ) -> Result, Error> { +++ Err(dummy_error()) +++ } +++ +++ fn close(&self) -> Result<(), Error> { +++ Ok(()) +++ } +++ } +++ +++ #[test] +++ fn transport_error_propagates() { +++ static INIT: Once = Once::new(); +++ +++ unsafe { +++ INIT.call_once(|| { +++ register("dummy", move |remote| { +++ Transport::smart(&remote, true, DummyTransport) +++ }) +++ .unwrap(); +++ }) +++ } +++ +++ let (_td, repo) = crate::test::repo_init(); +++ t!(repo.remote("origin", "dummy://ball")); +++ +++ let mut origin = t!(repo.find_remote("origin")); +++ +++ match origin.fetch(&["main"], None, None) { +++ Ok(()) => unreachable!(), +++ Err(e) => assert_eq!(e, dummy_error()), +++ } +++ } +++} diff --cc extra/git2/src/tree.rs index 0000000000,0000000000,0000000000..e683257436 new file mode 100644 --- /dev/null +++ b/extra/git2/src/tree.rs @@@@ -1,0 -1,0 -1,0 +1,617 @@@@ +++use libc::{c_char, c_int, c_void}; +++use std::cmp::Ordering; +++use std::ffi::{CStr, CString}; +++use std::iter::FusedIterator; +++use std::marker; +++use std::mem; +++use std::ops::Range; +++use std::path::Path; +++use std::ptr; +++use std::str; +++ +++use crate::util::{c_cmp_to_ordering, path_to_repo_path, Binding}; +++use crate::{panic, raw, Error, Object, ObjectType, Oid, Repository}; +++ +++/// A structure to represent a git [tree][1] +++/// +++/// [1]: http://git-scm.com/book/en/Git-Internals-Git-Objects +++pub struct Tree<'repo> { +++ raw: *mut raw::git_tree, +++ _marker: marker::PhantomData>, +++} +++ +++/// A structure representing an entry inside of a tree. An entry is borrowed +++/// from a tree. +++pub struct TreeEntry<'tree> { +++ raw: *mut raw::git_tree_entry, +++ owned: bool, +++ _marker: marker::PhantomData<&'tree raw::git_tree_entry>, +++} +++ +++/// An iterator over the entries in a tree. +++pub struct TreeIter<'tree> { +++ range: Range, +++ tree: &'tree Tree<'tree>, +++} +++ +++/// A binary indicator of whether a tree walk should be performed in pre-order +++/// or post-order. +++#[derive(Clone, Copy)] +++pub enum TreeWalkMode { +++ /// Runs the traversal in pre-order. +++ PreOrder = 0, +++ /// Runs the traversal in post-order. +++ PostOrder = 1, +++} +++ +++/// Possible return codes for tree walking callback functions. +++#[repr(i32)] +++pub enum TreeWalkResult { +++ /// Continue with the traversal as normal. +++ Ok = 0, +++ /// Skip the current node (in pre-order mode). +++ Skip = 1, +++ /// Completely stop the traversal. +++ Abort = raw::GIT_EUSER, +++} +++ +++impl Into for TreeWalkResult { +++ fn into(self) -> i32 { +++ self as i32 +++ } +++} +++ +++impl Into for TreeWalkMode { +++ #[cfg(target_env = "msvc")] +++ fn into(self) -> raw::git_treewalk_mode { +++ self as i32 +++ } +++ #[cfg(not(target_env = "msvc"))] +++ fn into(self) -> raw::git_treewalk_mode { +++ self as u32 +++ } +++} +++ +++impl<'repo> Tree<'repo> { +++ /// Get the id (SHA1) of a repository object +++ pub fn id(&self) -> Oid { +++ unsafe { Binding::from_raw(raw::git_tree_id(&*self.raw)) } +++ } +++ +++ /// Get the number of entries listed in this tree. +++ pub fn len(&self) -> usize { +++ unsafe { raw::git_tree_entrycount(&*self.raw) as usize } +++ } +++ +++ /// Return `true` if there is not entry +++ pub fn is_empty(&self) -> bool { +++ self.len() == 0 +++ } +++ +++ /// Returns an iterator over the entries in this tree. +++ pub fn iter(&self) -> TreeIter<'_> { +++ TreeIter { +++ range: 0..self.len(), +++ tree: self, +++ } +++ } +++ +++ /// Traverse the entries in a tree and its subtrees in post or pre-order. +++ /// The callback function will be run on each node of the tree that's +++ /// walked. The return code of this function will determine how the walk +++ /// continues. +++ /// +++ /// libgit2 requires that the callback be an integer, where 0 indicates a +++ /// successful visit, 1 skips the node, and -1 aborts the traversal completely. +++ /// You may opt to use the enum [`TreeWalkResult`] instead. +++ /// +++ /// ```ignore +++ /// let mut ct = 0; +++ /// tree.walk(TreeWalkMode::PreOrder, |_, entry| { +++ /// assert_eq!(entry.name(), Some("foo")); +++ /// ct += 1; +++ /// TreeWalkResult::Ok +++ /// }).unwrap(); +++ /// assert_eq!(ct, 1); +++ /// ``` +++ /// +++ /// See [libgit2 documentation][1] for more information. +++ /// +++ /// [1]: https://libgit2.org/libgit2/#HEAD/group/tree/git_tree_walk +++ pub fn walk(&self, mode: TreeWalkMode, mut callback: C) -> Result<(), Error> +++ where +++ C: FnMut(&str, &TreeEntry<'_>) -> T, +++ T: Into, +++ { +++ unsafe { +++ let mut data = TreeWalkCbData { +++ callback: &mut callback, +++ }; +++ try_call!(raw::git_tree_walk( +++ self.raw(), +++ mode as raw::git_treewalk_mode, +++ treewalk_cb::, +++ &mut data as *mut _ as *mut c_void +++ )); +++ Ok(()) +++ } +++ } +++ +++ /// Lookup a tree entry by SHA value. +++ pub fn get_id(&self, id: Oid) -> Option> { +++ unsafe { +++ let ptr = raw::git_tree_entry_byid(&*self.raw(), &*id.raw()); +++ if ptr.is_null() { +++ None +++ } else { +++ Some(entry_from_raw_const(ptr)) +++ } +++ } +++ } +++ +++ /// Lookup a tree entry by its position in the tree +++ pub fn get(&self, n: usize) -> Option> { +++ unsafe { +++ let ptr = raw::git_tree_entry_byindex(&*self.raw(), n as libc::size_t); +++ if ptr.is_null() { +++ None +++ } else { +++ Some(entry_from_raw_const(ptr)) +++ } +++ } +++ } +++ +++ /// Lookup a tree entry by its filename +++ pub fn get_name(&self, filename: &str) -> Option> { +++ self.get_name_bytes(filename.as_bytes()) +++ } +++ +++ /// Lookup a tree entry by its filename, specified as bytes. +++ /// +++ /// This allows for non-UTF-8 filenames. +++ pub fn get_name_bytes(&self, filename: &[u8]) -> Option> { +++ let filename = CString::new(filename).unwrap(); +++ unsafe { +++ let ptr = call!(raw::git_tree_entry_byname(&*self.raw(), filename)); +++ if ptr.is_null() { +++ None +++ } else { +++ Some(entry_from_raw_const(ptr)) +++ } +++ } +++ } +++ +++ /// Retrieve a tree entry contained in a tree or in any of its subtrees, +++ /// given its relative path. +++ pub fn get_path(&self, path: &Path) -> Result, Error> { +++ let path = path_to_repo_path(path)?; +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_tree_entry_bypath(&mut ret, &*self.raw(), path)); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Casts this Tree to be usable as an `Object` +++ pub fn as_object(&self) -> &Object<'repo> { +++ unsafe { &*(self as *const _ as *const Object<'repo>) } +++ } +++ +++ /// Consumes this Tree to be returned as an `Object` +++ pub fn into_object(self) -> Object<'repo> { +++ assert_eq!(mem::size_of_val(&self), mem::size_of::>()); +++ unsafe { mem::transmute(self) } +++ } +++} +++ +++type TreeWalkCb<'a, T> = dyn FnMut(&str, &TreeEntry<'_>) -> T + 'a; +++ +++struct TreeWalkCbData<'a, T> { +++ callback: &'a mut TreeWalkCb<'a, T>, +++} +++ +++extern "C" fn treewalk_cb>( +++ root: *const c_char, +++ entry: *const raw::git_tree_entry, +++ payload: *mut c_void, +++) -> c_int { +++ match panic::wrap(|| unsafe { +++ let root = match CStr::from_ptr(root).to_str() { +++ Ok(value) => value, +++ _ => return -1, +++ }; +++ let entry = entry_from_raw_const(entry); +++ let payload = &mut *(payload as *mut TreeWalkCbData<'_, T>); +++ let callback = &mut payload.callback; +++ callback(root, &entry).into() +++ }) { +++ Some(value) => value, +++ None => -1, +++ } +++} +++ +++impl<'repo> Binding for Tree<'repo> { +++ type Raw = *mut raw::git_tree; +++ +++ unsafe fn from_raw(raw: *mut raw::git_tree) -> Tree<'repo> { +++ Tree { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_tree { +++ self.raw +++ } +++} +++ +++impl<'repo> std::fmt::Debug for Tree<'repo> { +++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +++ f.debug_struct("Tree").field("id", &self.id()).finish() +++ } +++} +++ +++impl<'repo> Clone for Tree<'repo> { +++ fn clone(&self) -> Self { +++ self.as_object().clone().into_tree().ok().unwrap() +++ } +++} +++ +++impl<'repo> Drop for Tree<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_tree_free(self.raw) } +++ } +++} +++ +++impl<'repo, 'iter> IntoIterator for &'iter Tree<'repo> { +++ type Item = TreeEntry<'iter>; +++ type IntoIter = TreeIter<'iter>; +++ fn into_iter(self) -> Self::IntoIter { +++ self.iter() +++ } +++} +++ +++/// Create a new tree entry from the raw pointer provided. +++/// +++/// The lifetime of the entry is tied to the tree provided and the function +++/// is unsafe because the validity of the pointer cannot be guaranteed. +++pub unsafe fn entry_from_raw_const<'tree>(raw: *const raw::git_tree_entry) -> TreeEntry<'tree> { +++ TreeEntry { +++ raw: raw as *mut raw::git_tree_entry, +++ owned: false, +++ _marker: marker::PhantomData, +++ } +++} +++ +++impl<'tree> TreeEntry<'tree> { +++ /// Get the id of the object pointed by the entry +++ pub fn id(&self) -> Oid { +++ unsafe { Binding::from_raw(raw::git_tree_entry_id(&*self.raw)) } +++ } +++ +++ /// Get the filename of a tree entry +++ /// +++ /// Returns `None` if the name is not valid utf-8 +++ pub fn name(&self) -> Option<&str> { +++ str::from_utf8(self.name_bytes()).ok() +++ } +++ +++ /// Get the filename of a tree entry +++ pub fn name_bytes(&self) -> &[u8] { +++ unsafe { crate::opt_bytes(self, raw::git_tree_entry_name(&*self.raw())).unwrap() } +++ } +++ +++ /// Convert a tree entry to the object it points to. +++ pub fn to_object<'a>(&self, repo: &'a Repository) -> Result, Error> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_tree_entry_to_object( +++ &mut ret, +++ repo.raw(), +++ &*self.raw() +++ )); +++ Ok(Binding::from_raw(ret)) +++ } +++ } +++ +++ /// Get the type of the object pointed by the entry +++ pub fn kind(&self) -> Option { +++ ObjectType::from_raw(unsafe { raw::git_tree_entry_type(&*self.raw) }) +++ } +++ +++ /// Get the UNIX file attributes of a tree entry +++ pub fn filemode(&self) -> i32 { +++ unsafe { raw::git_tree_entry_filemode(&*self.raw) as i32 } +++ } +++ +++ /// Get the raw UNIX file attributes of a tree entry +++ pub fn filemode_raw(&self) -> i32 { +++ unsafe { raw::git_tree_entry_filemode_raw(&*self.raw) as i32 } +++ } +++ +++ /// Convert this entry of any lifetime into an owned signature with a static +++ /// lifetime. +++ /// +++ /// This will use the `Clone::clone` implementation under the hood. +++ pub fn to_owned(&self) -> TreeEntry<'static> { +++ unsafe { +++ let me = mem::transmute::<&TreeEntry<'tree>, &TreeEntry<'static>>(self); +++ me.clone() +++ } +++ } +++} +++ +++impl<'a> Binding for TreeEntry<'a> { +++ type Raw = *mut raw::git_tree_entry; +++ unsafe fn from_raw(raw: *mut raw::git_tree_entry) -> TreeEntry<'a> { +++ TreeEntry { +++ raw, +++ owned: true, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_tree_entry { +++ self.raw +++ } +++} +++ +++impl<'a> Clone for TreeEntry<'a> { +++ fn clone(&self) -> TreeEntry<'a> { +++ let mut ret = ptr::null_mut(); +++ unsafe { +++ assert_eq!(raw::git_tree_entry_dup(&mut ret, &*self.raw()), 0); +++ Binding::from_raw(ret) +++ } +++ } +++} +++ +++impl<'a> PartialOrd for TreeEntry<'a> { +++ fn partial_cmp(&self, other: &TreeEntry<'a>) -> Option { +++ Some(self.cmp(other)) +++ } +++} +++impl<'a> Ord for TreeEntry<'a> { +++ fn cmp(&self, other: &TreeEntry<'a>) -> Ordering { +++ c_cmp_to_ordering(unsafe { raw::git_tree_entry_cmp(&*self.raw(), &*other.raw()) }) +++ } +++} +++ +++impl<'a> PartialEq for TreeEntry<'a> { +++ fn eq(&self, other: &TreeEntry<'a>) -> bool { +++ self.cmp(other) == Ordering::Equal +++ } +++} +++impl<'a> Eq for TreeEntry<'a> {} +++ +++impl<'a> Drop for TreeEntry<'a> { +++ fn drop(&mut self) { +++ if self.owned { +++ unsafe { raw::git_tree_entry_free(self.raw) } +++ } +++ } +++} +++ +++impl<'tree> Iterator for TreeIter<'tree> { +++ type Item = TreeEntry<'tree>; +++ fn next(&mut self) -> Option> { +++ self.range.next().and_then(|i| self.tree.get(i)) +++ } +++ fn size_hint(&self) -> (usize, Option) { +++ self.range.size_hint() +++ } +++ fn nth(&mut self, n: usize) -> Option> { +++ self.range.nth(n).and_then(|i| self.tree.get(i)) +++ } +++} +++impl<'tree> DoubleEndedIterator for TreeIter<'tree> { +++ fn next_back(&mut self) -> Option> { +++ self.range.next_back().and_then(|i| self.tree.get(i)) +++ } +++} +++impl<'tree> FusedIterator for TreeIter<'tree> {} +++impl<'tree> ExactSizeIterator for TreeIter<'tree> {} +++ +++#[cfg(test)] +++mod tests { +++ use super::{TreeWalkMode, TreeWalkResult}; +++ use crate::{Object, ObjectType, Repository, Tree, TreeEntry}; +++ use std::fs::File; +++ use std::io::prelude::*; +++ use std::path::Path; +++ use tempfile::TempDir; +++ +++ pub struct TestTreeIter<'a> { +++ entries: Vec>, +++ repo: &'a Repository, +++ } +++ +++ impl<'a> Iterator for TestTreeIter<'a> { +++ type Item = TreeEntry<'a>; +++ +++ fn next(&mut self) -> Option> { +++ if self.entries.is_empty() { +++ None +++ } else { +++ let entry = self.entries.remove(0); +++ +++ match entry.kind() { +++ Some(ObjectType::Tree) => { +++ let obj: Object<'a> = entry.to_object(self.repo).unwrap(); +++ +++ let tree: &Tree<'a> = obj.as_tree().unwrap(); +++ +++ for entry in tree.iter() { +++ self.entries.push(entry.to_owned()); +++ } +++ } +++ _ => {} +++ } +++ +++ Some(entry) +++ } +++ } +++ } +++ +++ fn tree_iter<'repo>(tree: &Tree<'repo>, repo: &'repo Repository) -> TestTreeIter<'repo> { +++ let mut initial = vec![]; +++ +++ for entry in tree.iter() { +++ initial.push(entry.to_owned()); +++ } +++ +++ TestTreeIter { +++ entries: initial, +++ repo: repo, +++ } +++ } +++ +++ #[test] +++ fn smoke_tree_iter() { +++ let (td, repo) = crate::test::repo_init(); +++ +++ setup_repo(&td, &repo); +++ +++ let head = repo.head().unwrap(); +++ let target = head.target().unwrap(); +++ let commit = repo.find_commit(target).unwrap(); +++ +++ let tree = repo.find_tree(commit.tree_id()).unwrap(); +++ assert_eq!(tree.id(), commit.tree_id()); +++ assert_eq!(tree.len(), 8); +++ +++ for entry in tree_iter(&tree, &repo) { +++ println!("iter entry {:?}", entry.name()); +++ } +++ } +++ +++ #[test] +++ fn smoke_tree_nth() { +++ let (td, repo) = crate::test::repo_init(); +++ +++ setup_repo(&td, &repo); +++ +++ let head = repo.head().unwrap(); +++ let target = head.target().unwrap(); +++ let commit = repo.find_commit(target).unwrap(); +++ +++ let tree = repo.find_tree(commit.tree_id()).unwrap(); +++ assert_eq!(tree.id(), commit.tree_id()); +++ assert_eq!(tree.len(), 8); +++ let mut it = tree.iter(); +++ let e = it.nth(4).unwrap(); +++ assert_eq!(e.name(), Some("f4")); +++ } +++ +++ fn setup_repo(td: &TempDir, repo: &Repository) { +++ let mut index = repo.index().unwrap(); +++ for n in 0..8 { +++ let name = format!("f{n}"); +++ File::create(&td.path().join(&name)) +++ .unwrap() +++ .write_all(name.as_bytes()) +++ .unwrap(); +++ index.add_path(Path::new(&name)).unwrap(); +++ } +++ let id = index.write_tree().unwrap(); +++ let sig = repo.signature().unwrap(); +++ let tree = repo.find_tree(id).unwrap(); +++ let parent = repo +++ .find_commit(repo.head().unwrap().target().unwrap()) +++ .unwrap(); +++ repo.commit( +++ Some("HEAD"), +++ &sig, +++ &sig, +++ "another commit", +++ &tree, +++ &[&parent], +++ ) +++ .unwrap(); +++ } +++ +++ #[test] +++ fn smoke() { +++ let (td, repo) = crate::test::repo_init(); +++ +++ setup_repo(&td, &repo); +++ +++ let head = repo.head().unwrap(); +++ let target = head.target().unwrap(); +++ let commit = repo.find_commit(target).unwrap(); +++ +++ let tree = repo.find_tree(commit.tree_id()).unwrap(); +++ assert_eq!(tree.id(), commit.tree_id()); +++ assert_eq!(tree.len(), 8); +++ { +++ let e0 = tree.get(0).unwrap(); +++ assert!(e0 == tree.get_id(e0.id()).unwrap()); +++ assert!(e0 == tree.get_name("f0").unwrap()); +++ assert!(e0 == tree.get_name_bytes(b"f0").unwrap()); +++ assert!(e0 == tree.get_path(Path::new("f0")).unwrap()); +++ assert_eq!(e0.name(), Some("f0")); +++ e0.to_object(&repo).unwrap(); +++ +++ let e1 = tree.get(1).unwrap(); +++ assert!(e1 == tree.get_id(e1.id()).unwrap()); +++ assert!(e1 == tree.get_name("f1").unwrap()); +++ assert!(e1 == tree.get_name_bytes(b"f1").unwrap()); +++ assert!(e1 == tree.get_path(Path::new("f1")).unwrap()); +++ assert_eq!(e1.name(), Some("f1")); +++ e1.to_object(&repo).unwrap(); +++ } +++ tree.into_object(); +++ +++ repo.find_object(commit.tree_id(), None) +++ .unwrap() +++ .as_tree() +++ .unwrap(); +++ repo.find_object(commit.tree_id(), None) +++ .unwrap() +++ .into_tree() +++ .ok() +++ .unwrap(); +++ } +++ +++ #[test] +++ fn tree_walk() { +++ let (td, repo) = crate::test::repo_init(); +++ +++ setup_repo(&td, &repo); +++ +++ let head = repo.head().unwrap(); +++ let target = head.target().unwrap(); +++ let commit = repo.find_commit(target).unwrap(); +++ let tree = repo.find_tree(commit.tree_id()).unwrap(); +++ +++ let mut ct = 0; +++ tree.walk(TreeWalkMode::PreOrder, |_, entry| { +++ assert_eq!(entry.name(), Some(format!("f{ct}").as_str())); +++ ct += 1; +++ 0 +++ }) +++ .unwrap(); +++ assert_eq!(ct, 8); +++ +++ let mut ct = 0; +++ tree.walk(TreeWalkMode::PreOrder, |_, entry| { +++ assert_eq!(entry.name(), Some(format!("f{ct}").as_str())); +++ ct += 1; +++ TreeWalkResult::Ok +++ }) +++ .unwrap(); +++ assert_eq!(ct, 8); +++ } +++ +++ #[test] +++ fn tree_walk_error() { +++ let (td, repo) = crate::test::repo_init(); +++ +++ setup_repo(&td, &repo); +++ +++ let head = repo.head().unwrap(); +++ let target = head.target().unwrap(); +++ let commit = repo.find_commit(target).unwrap(); +++ let tree = repo.find_tree(commit.tree_id()).unwrap(); +++ let e = tree.walk(TreeWalkMode::PreOrder, |_, _| -1).unwrap_err(); +++ assert_eq!(e.class(), crate::ErrorClass::Callback); +++ } +++} diff --cc extra/git2/src/treebuilder.rs index 0000000000,0000000000,0000000000..1548a048cf new file mode 100644 --- /dev/null +++ b/extra/git2/src/treebuilder.rs @@@@ -1,0 -1,0 -1,0 +1,234 @@@@ +++use std::marker; +++use std::ptr; +++ +++use libc::{c_int, c_void}; +++ +++use crate::util::{Binding, IntoCString}; +++use crate::{panic, raw, tree, Error, Oid, Repository, TreeEntry}; +++ +++/// Constructor for in-memory trees (low-level) +++/// +++/// You probably want to use [`build::TreeUpdateBuilder`] instead. +++/// +++/// This is the more raw of the two tree update facilities. It +++/// handles only one level of a nested tree structure at a time. Each +++/// path passed to `insert` etc. must be a single component. +++/// +++/// [`build::TreeUpdateBuilder`]: crate::build::TreeUpdateBuilder +++pub struct TreeBuilder<'repo> { +++ raw: *mut raw::git_treebuilder, +++ _marker: marker::PhantomData<&'repo Repository>, +++} +++ +++impl<'repo> TreeBuilder<'repo> { +++ /// Clear all the entries in the builder +++ pub fn clear(&mut self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_treebuilder_clear(self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Get the number of entries +++ pub fn len(&self) -> usize { +++ unsafe { raw::git_treebuilder_entrycount(self.raw) as usize } +++ } +++ +++ /// Return `true` if there is no entry +++ pub fn is_empty(&self) -> bool { +++ self.len() == 0 +++ } +++ +++ /// Get en entry from the builder from its filename +++ pub fn get

(&self, filename: P) -> Result>, Error> +++ where +++ P: IntoCString, +++ { +++ let filename = filename.into_c_string()?; +++ unsafe { +++ let ret = raw::git_treebuilder_get(self.raw, filename.as_ptr()); +++ if ret.is_null() { +++ Ok(None) +++ } else { +++ Ok(Some(tree::entry_from_raw_const(ret))) +++ } +++ } +++ } +++ +++ /// Add or update an entry in the builder +++ /// +++ /// No attempt is made to ensure that the provided Oid points to +++ /// an object of a reasonable type (or any object at all). +++ /// +++ /// The mode given must be one of 0o040000, 0o100644, 0o100755, 0o120000 or +++ /// 0o160000 currently. +++ pub fn insert( +++ &mut self, +++ filename: P, +++ oid: Oid, +++ filemode: i32, +++ ) -> Result, Error> { +++ let filename = filename.into_c_string()?; +++ let filemode = filemode as raw::git_filemode_t; +++ +++ let mut ret = ptr::null(); +++ unsafe { +++ try_call!(raw::git_treebuilder_insert( +++ &mut ret, +++ self.raw, +++ filename, +++ oid.raw(), +++ filemode +++ )); +++ Ok(tree::entry_from_raw_const(ret)) +++ } +++ } +++ +++ /// Remove an entry from the builder by its filename +++ pub fn remove(&mut self, filename: P) -> Result<(), Error> { +++ let filename = filename.into_c_string()?; +++ unsafe { +++ try_call!(raw::git_treebuilder_remove(self.raw, filename)); +++ } +++ Ok(()) +++ } +++ +++ /// Selectively remove entries from the tree +++ /// +++ /// Values for which the filter returns `true` will be kept. Note +++ /// that this behavior is different from the libgit2 C interface. +++ pub fn filter(&mut self, mut filter: F) -> Result<(), Error> +++ where +++ F: FnMut(&TreeEntry<'_>) -> bool, +++ { +++ let mut cb: &mut FilterCb<'_> = &mut filter; +++ let ptr = &mut cb as *mut _; +++ let cb: raw::git_treebuilder_filter_cb = Some(filter_cb); +++ unsafe { +++ try_call!(raw::git_treebuilder_filter(self.raw, cb, ptr as *mut _)); +++ panic::check(); +++ } +++ Ok(()) +++ } +++ +++ /// Write the contents of the TreeBuilder as a Tree object and +++ /// return its Oid +++ pub fn write(&self) -> Result { +++ let mut raw = raw::git_oid { +++ id: [0; raw::GIT_OID_RAWSZ], +++ }; +++ unsafe { +++ try_call!(raw::git_treebuilder_write(&mut raw, self.raw())); +++ Ok(Binding::from_raw(&raw as *const _)) +++ } +++ } +++} +++ +++type FilterCb<'a> = dyn FnMut(&TreeEntry<'_>) -> bool + 'a; +++ +++extern "C" fn filter_cb(entry: *const raw::git_tree_entry, payload: *mut c_void) -> c_int { +++ let ret = panic::wrap(|| unsafe { +++ // There's no way to return early from git_treebuilder_filter. +++ if panic::panicked() { +++ true +++ } else { +++ let entry = tree::entry_from_raw_const(entry); +++ let payload = payload as *mut &mut FilterCb<'_>; +++ (*payload)(&entry) +++ } +++ }); +++ if ret == Some(false) { +++ 1 +++ } else { +++ 0 +++ } +++} +++ +++impl<'repo> Binding for TreeBuilder<'repo> { +++ type Raw = *mut raw::git_treebuilder; +++ +++ unsafe fn from_raw(raw: *mut raw::git_treebuilder) -> TreeBuilder<'repo> { +++ TreeBuilder { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ fn raw(&self) -> *mut raw::git_treebuilder { +++ self.raw +++ } +++} +++ +++impl<'repo> Drop for TreeBuilder<'repo> { +++ fn drop(&mut self) { +++ unsafe { raw::git_treebuilder_free(self.raw) } +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::ObjectType; +++ +++ #[test] +++ fn smoke() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ let mut builder = repo.treebuilder(None).unwrap(); +++ assert_eq!(builder.len(), 0); +++ let blob = repo.blob(b"data").unwrap(); +++ { +++ let entry = builder.insert("a", blob, 0o100644).unwrap(); +++ assert_eq!(entry.kind(), Some(ObjectType::Blob)); +++ } +++ builder.insert("b", blob, 0o100644).unwrap(); +++ assert_eq!(builder.len(), 2); +++ builder.remove("a").unwrap(); +++ assert_eq!(builder.len(), 1); +++ assert_eq!(builder.get("b").unwrap().unwrap().id(), blob); +++ builder.clear().unwrap(); +++ assert_eq!(builder.len(), 0); +++ } +++ +++ #[test] +++ fn write() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ let mut builder = repo.treebuilder(None).unwrap(); +++ let data = repo.blob(b"data").unwrap(); +++ builder.insert("name", data, 0o100644).unwrap(); +++ let tree = builder.write().unwrap(); +++ let tree = repo.find_tree(tree).unwrap(); +++ let entry = tree.get(0).unwrap(); +++ assert_eq!(entry.name(), Some("name")); +++ let blob = entry.to_object(&repo).unwrap(); +++ let blob = blob.as_blob().unwrap(); +++ assert_eq!(blob.content(), b"data"); +++ +++ let builder = repo.treebuilder(Some(&tree)).unwrap(); +++ assert_eq!(builder.len(), 1); +++ } +++ +++ #[test] +++ fn filter() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ let mut builder = repo.treebuilder(None).unwrap(); +++ let blob = repo.blob(b"data").unwrap(); +++ let tree = { +++ let head = repo.head().unwrap().peel(ObjectType::Commit).unwrap(); +++ let head = head.as_commit().unwrap(); +++ head.tree_id() +++ }; +++ builder.insert("blob", blob, 0o100644).unwrap(); +++ builder.insert("dir", tree, 0o040000).unwrap(); +++ builder.insert("dir2", tree, 0o040000).unwrap(); +++ +++ builder.filter(|_| true).unwrap(); +++ assert_eq!(builder.len(), 3); +++ builder +++ .filter(|e| e.kind().unwrap() != ObjectType::Blob) +++ .unwrap(); +++ assert_eq!(builder.len(), 2); +++ builder.filter(|_| false).unwrap(); +++ assert_eq!(builder.len(), 0); +++ } +++} diff --cc extra/git2/src/util.rs index 0000000000,0000000000,0000000000..4065492f76 new file mode 100644 --- /dev/null +++ b/extra/git2/src/util.rs @@@@ -1,0 -1,0 -1,0 +1,341 @@@@ +++use libc::{c_char, c_int, size_t}; +++use std::cmp::Ordering; +++use std::ffi::{CString, OsStr, OsString}; +++use std::path::{Component, Path, PathBuf}; +++ +++use crate::{raw, Error}; +++ +++#[doc(hidden)] +++pub trait IsNull { +++ fn is_ptr_null(&self) -> bool; +++} +++impl IsNull for *const T { +++ fn is_ptr_null(&self) -> bool { +++ self.is_null() +++ } +++} +++impl IsNull for *mut T { +++ fn is_ptr_null(&self) -> bool { +++ self.is_null() +++ } +++} +++ +++#[doc(hidden)] +++pub trait Binding: Sized { +++ type Raw; +++ +++ unsafe fn from_raw(raw: Self::Raw) -> Self; +++ fn raw(&self) -> Self::Raw; +++ +++ unsafe fn from_raw_opt(raw: T) -> Option +++ where +++ T: Copy + IsNull, +++ Self: Binding, +++ { +++ if raw.is_ptr_null() { +++ None +++ } else { +++ Some(Binding::from_raw(raw)) +++ } +++ } +++} +++ +++/// Converts an iterator of repo paths into a git2-compatible array of cstrings. +++/// +++/// Only use this for repo-relative paths or pathspecs. +++/// +++/// See `iter2cstrs` for more details. +++pub fn iter2cstrs_paths( +++ iter: I, +++) -> Result<(Vec, Vec<*const c_char>, raw::git_strarray), Error> +++where +++ T: IntoCString, +++ I: IntoIterator, +++{ +++ let cstrs = iter +++ .into_iter() +++ .map(|i| fixup_windows_path(i.into_c_string()?)) +++ .collect::, _>>()?; +++ iter2cstrs(cstrs) +++} +++ +++/// Converts an iterator of things into a git array of c-strings. +++/// +++/// Returns a tuple `(cstrings, pointers, git_strarray)`. The first two values +++/// should not be dropped before `git_strarray`. +++pub fn iter2cstrs( +++ iter: I, +++) -> Result<(Vec, Vec<*const c_char>, raw::git_strarray), Error> +++where +++ T: IntoCString, +++ I: IntoIterator, +++{ +++ let cstrs = iter +++ .into_iter() +++ .map(|i| i.into_c_string()) +++ .collect::, _>>()?; +++ let ptrs = cstrs.iter().map(|i| i.as_ptr()).collect::>(); +++ let raw = raw::git_strarray { +++ strings: ptrs.as_ptr() as *mut _, +++ count: ptrs.len() as size_t, +++ }; +++ Ok((cstrs, ptrs, raw)) +++} +++ +++#[cfg(unix)] +++pub fn bytes2path(b: &[u8]) -> &Path { +++ use std::os::unix::prelude::*; +++ Path::new(OsStr::from_bytes(b)) +++} +++#[cfg(windows)] +++pub fn bytes2path(b: &[u8]) -> &Path { +++ use std::str; +++ Path::new(str::from_utf8(b).unwrap()) +++} +++ +++/// A class of types that can be converted to C strings. +++/// +++/// These types are represented internally as byte slices and it is quite rare +++/// for them to contain an interior 0 byte. +++pub trait IntoCString { +++ /// Consume this container, converting it into a CString +++ fn into_c_string(self) -> Result; +++} +++ +++impl<'a, T: IntoCString + Clone> IntoCString for &'a T { +++ fn into_c_string(self) -> Result { +++ self.clone().into_c_string() +++ } +++} +++ +++impl<'a> IntoCString for &'a str { +++ fn into_c_string(self) -> Result { +++ Ok(CString::new(self)?) +++ } +++} +++ +++impl IntoCString for String { +++ fn into_c_string(self) -> Result { +++ Ok(CString::new(self.into_bytes())?) +++ } +++} +++ +++impl IntoCString for CString { +++ fn into_c_string(self) -> Result { +++ Ok(self) +++ } +++} +++ +++impl<'a> IntoCString for &'a Path { +++ fn into_c_string(self) -> Result { +++ let s: &OsStr = self.as_ref(); +++ s.into_c_string() +++ } +++} +++ +++impl IntoCString for PathBuf { +++ fn into_c_string(self) -> Result { +++ let s: OsString = self.into(); +++ s.into_c_string() +++ } +++} +++ +++impl<'a> IntoCString for &'a OsStr { +++ fn into_c_string(self) -> Result { +++ self.to_os_string().into_c_string() +++ } +++} +++ +++impl IntoCString for OsString { +++ #[cfg(unix)] +++ fn into_c_string(self) -> Result { +++ use std::os::unix::prelude::*; +++ let s: &OsStr = self.as_ref(); +++ Ok(CString::new(s.as_bytes())?) +++ } +++ #[cfg(windows)] +++ fn into_c_string(self) -> Result { +++ match self.to_str() { +++ Some(s) => s.into_c_string(), +++ None => Err(Error::from_str( +++ "only valid unicode paths are accepted on windows", +++ )), +++ } +++ } +++} +++ +++impl<'a> IntoCString for &'a [u8] { +++ fn into_c_string(self) -> Result { +++ Ok(CString::new(self)?) +++ } +++} +++ +++impl IntoCString for Vec { +++ fn into_c_string(self) -> Result { +++ Ok(CString::new(self)?) +++ } +++} +++ +++pub fn into_opt_c_string(opt_s: Option) -> Result, Error> +++where +++ S: IntoCString, +++{ +++ match opt_s { +++ None => Ok(None), +++ Some(s) => Ok(Some(s.into_c_string()?)), +++ } +++} +++ +++pub fn c_cmp_to_ordering(cmp: c_int) -> Ordering { +++ match cmp { +++ 0 => Ordering::Equal, +++ n if n < 0 => Ordering::Less, +++ _ => Ordering::Greater, +++ } +++} +++ +++/// Converts a path to a CString that is usable by the libgit2 API. +++/// +++/// Checks if it is a relative path. +++/// +++/// On Windows, this also requires the path to be valid Unicode, and translates +++/// back slashes to forward slashes. +++pub fn path_to_repo_path(path: &Path) -> Result { +++ macro_rules! err { +++ ($msg:literal, $path:expr) => { +++ return Err(Error::from_str(&format!($msg, $path.display()))) +++ }; +++ } +++ match path.components().next() { +++ None => return Err(Error::from_str("repo path should not be empty")), +++ Some(Component::Prefix(_)) => err!( +++ "repo path `{}` should be relative, not a windows prefix", +++ path +++ ), +++ Some(Component::RootDir) => err!("repo path `{}` should be relative", path), +++ Some(Component::CurDir) => err!("repo path `{}` should not start with `.`", path), +++ Some(Component::ParentDir) => err!("repo path `{}` should not start with `..`", path), +++ Some(Component::Normal(_)) => {} +++ } +++ #[cfg(windows)] +++ { +++ match path.to_str() { +++ None => { +++ return Err(Error::from_str( +++ "only valid unicode paths are accepted on windows", +++ )) +++ } +++ Some(s) => return fixup_windows_path(s), +++ } +++ } +++ #[cfg(not(windows))] +++ { +++ path.into_c_string() +++ } +++} +++ +++pub fn cstring_to_repo_path(path: T) -> Result { +++ fixup_windows_path(path.into_c_string()?) +++} +++ +++#[cfg(windows)] +++fn fixup_windows_path>>(path: P) -> Result { +++ let mut bytes: Vec = path.into(); +++ for i in 0..bytes.len() { +++ if bytes[i] == b'\\' { +++ bytes[i] = b'/'; +++ } +++ } +++ Ok(CString::new(bytes)?) +++} +++ +++#[cfg(not(windows))] +++fn fixup_windows_path(path: CString) -> Result { +++ Ok(path) +++} +++ +++#[cfg(test)] +++mod tests { +++ use super::*; +++ +++ macro_rules! assert_err { +++ ($path:expr, $msg:expr) => { +++ match path_to_repo_path(Path::new($path)) { +++ Ok(_) => panic!("expected `{}` to err", $path), +++ Err(e) => assert_eq!(e.message(), $msg), +++ } +++ }; +++ } +++ +++ macro_rules! assert_repo_path_ok { +++ ($path:expr) => { +++ assert_repo_path_ok!($path, $path) +++ }; +++ ($path:expr, $expect:expr) => { +++ assert_eq!( +++ path_to_repo_path(Path::new($path)), +++ Ok(CString::new($expect).unwrap()) +++ ); +++ }; +++ } +++ +++ #[test] +++ #[cfg(windows)] +++ fn path_to_repo_path_translate() { +++ assert_repo_path_ok!("foo"); +++ assert_repo_path_ok!("foo/bar"); +++ assert_repo_path_ok!(r"foo\bar", "foo/bar"); +++ assert_repo_path_ok!(r"foo\bar\", "foo/bar/"); +++ } +++ +++ #[test] +++ fn path_to_repo_path_no_weird() { +++ assert_err!("", "repo path should not be empty"); +++ assert_err!("./foo", "repo path `./foo` should not start with `.`"); +++ assert_err!("../foo", "repo path `../foo` should not start with `..`"); +++ } +++ +++ #[test] +++ #[cfg(not(windows))] +++ fn path_to_repo_path_no_absolute() { +++ assert_err!("/", "repo path `/` should be relative"); +++ assert_repo_path_ok!("foo/bar"); +++ } +++ +++ #[test] +++ #[cfg(windows)] +++ fn path_to_repo_path_no_absolute() { +++ assert_err!( +++ r"c:", +++ r"repo path `c:` should be relative, not a windows prefix" +++ ); +++ assert_err!( +++ r"c:\", +++ r"repo path `c:\` should be relative, not a windows prefix" +++ ); +++ assert_err!( +++ r"c:temp", +++ r"repo path `c:temp` should be relative, not a windows prefix" +++ ); +++ assert_err!( +++ r"\\?\UNC\a\b\c", +++ r"repo path `\\?\UNC\a\b\c` should be relative, not a windows prefix" +++ ); +++ assert_err!( +++ r"\\?\c:\foo", +++ r"repo path `\\?\c:\foo` should be relative, not a windows prefix" +++ ); +++ assert_err!( +++ r"\\.\COM42", +++ r"repo path `\\.\COM42` should be relative, not a windows prefix" +++ ); +++ assert_err!( +++ r"\\a\b", +++ r"repo path `\\a\b` should be relative, not a windows prefix" +++ ); +++ assert_err!(r"\", r"repo path `\` should be relative"); +++ assert_err!(r"/", r"repo path `/` should be relative"); +++ assert_err!(r"\foo", r"repo path `\foo` should be relative"); +++ assert_err!(r"/foo", r"repo path `/foo` should be relative"); +++ } +++} diff --cc extra/git2/src/version.rs index 0000000000,0000000000,0000000000..b5dd4fb123 new file mode 100644 --- /dev/null +++ b/extra/git2/src/version.rs @@@@ -1,0 -1,0 -1,0 +1,95 @@@@ +++use crate::raw; +++use libc::c_int; +++use std::fmt; +++ +++/// Version information about libgit2 and the capabilities it supports. +++pub struct Version { +++ major: c_int, +++ minor: c_int, +++ rev: c_int, +++ features: c_int, +++} +++ +++macro_rules! flag_test { +++ ($features:expr, $flag:expr) => { +++ ($features as u32 & $flag as u32) != 0 +++ }; +++} +++ +++impl Version { +++ /// Returns a [`Version`] which provides information about libgit2. +++ pub fn get() -> Version { +++ let mut v = Version { +++ major: 0, +++ minor: 0, +++ rev: 0, +++ features: 0, +++ }; +++ unsafe { +++ raw::git_libgit2_version(&mut v.major, &mut v.minor, &mut v.rev); +++ v.features = raw::git_libgit2_features(); +++ } +++ v +++ } +++ +++ /// Returns the version of libgit2. +++ /// +++ /// The return value is a tuple of `(major, minor, rev)` +++ pub fn libgit2_version(&self) -> (u32, u32, u32) { +++ (self.major as u32, self.minor as u32, self.rev as u32) +++ } +++ +++ /// Returns the version of the libgit2-sys crate. +++ pub fn crate_version(&self) -> &'static str { +++ env!("CARGO_PKG_VERSION") +++ } +++ +++ /// Returns true if this was built with the vendored version of libgit2. +++ pub fn vendored(&self) -> bool { +++ raw::vendored() +++ } +++ +++ /// Returns true if libgit2 was built thread-aware and can be safely used +++ /// from multiple threads. +++ pub fn threads(&self) -> bool { +++ flag_test!(self.features, raw::GIT_FEATURE_THREADS) +++ } +++ +++ /// Returns true if libgit2 was built with and linked against a TLS implementation. +++ /// +++ /// Custom TLS streams may still be added by the user to support HTTPS +++ /// regardless of this. +++ pub fn https(&self) -> bool { +++ flag_test!(self.features, raw::GIT_FEATURE_HTTPS) +++ } +++ +++ /// Returns true if libgit2 was built with and linked against libssh2. +++ /// +++ /// A custom transport may still be added by the user to support libssh2 +++ /// regardless of this. +++ pub fn ssh(&self) -> bool { +++ flag_test!(self.features, raw::GIT_FEATURE_SSH) +++ } +++ +++ /// Returns true if libgit2 was built with support for sub-second +++ /// resolution in file modification times. +++ pub fn nsec(&self) -> bool { +++ flag_test!(self.features, raw::GIT_FEATURE_NSEC) +++ } +++} +++ +++impl fmt::Debug for Version { +++ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { +++ let mut f = f.debug_struct("Version"); +++ f.field("major", &self.major) +++ .field("minor", &self.minor) +++ .field("rev", &self.rev) +++ .field("crate_version", &self.crate_version()) +++ .field("vendored", &self.vendored()) +++ .field("threads", &self.threads()) +++ .field("https", &self.https()) +++ .field("ssh", &self.ssh()) +++ .field("nsec", &self.nsec()); +++ f.finish() +++ } +++} diff --cc extra/git2/src/worktree.rs index 0000000000,0000000000,0000000000..fc32902db1 new file mode 100644 --- /dev/null +++ b/extra/git2/src/worktree.rs @@@@ -1,0 -1,0 -1,0 +1,337 @@@@ +++use crate::buf::Buf; +++use crate::reference::Reference; +++use crate::repo::Repository; +++use crate::util::{self, Binding}; +++use crate::{raw, Error}; +++use std::os::raw::c_int; +++use std::path::Path; +++use std::ptr; +++use std::str; +++use std::{marker, mem}; +++ +++/// An owned git worktree +++/// +++/// This structure corresponds to a `git_worktree` in libgit2. +++// +++pub struct Worktree { +++ raw: *mut raw::git_worktree, +++} +++ +++/// Options which can be used to configure how a worktree is initialized +++pub struct WorktreeAddOptions<'a> { +++ raw: raw::git_worktree_add_options, +++ _marker: marker::PhantomData>, +++} +++ +++/// Options to configure how worktree pruning is performed +++pub struct WorktreePruneOptions { +++ raw: raw::git_worktree_prune_options, +++} +++ +++/// Lock Status of a worktree +++#[derive(PartialEq, Debug)] +++pub enum WorktreeLockStatus { +++ /// Worktree is Unlocked +++ Unlocked, +++ /// Worktree is locked with the optional message +++ Locked(Option), +++} +++ +++impl Worktree { +++ /// Open a worktree of a the repository +++ /// +++ /// If a repository is not the main tree but a worktree, this +++ /// function will look up the worktree inside the parent +++ /// repository and create a new `git_worktree` structure. +++ pub fn open_from_repository(repo: &Repository) -> Result { +++ let mut raw = ptr::null_mut(); +++ unsafe { +++ try_call!(raw::git_worktree_open_from_repository(&mut raw, repo.raw())); +++ Ok(Binding::from_raw(raw)) +++ } +++ } +++ +++ /// Retrieves the name of the worktree +++ /// +++ /// This is the name that can be passed to repo::Repository::find_worktree +++ /// to reopen the worktree. This is also the name that would appear in the +++ /// list returned by repo::Repository::worktrees +++ pub fn name(&self) -> Option<&str> { +++ unsafe { +++ crate::opt_bytes(self, raw::git_worktree_name(self.raw)) +++ .and_then(|s| str::from_utf8(s).ok()) +++ } +++ } +++ +++ /// Retrieves the path to the worktree +++ /// +++ /// This is the path to the top-level of the source and not the path to the +++ /// .git file within the worktree. This path can be passed to +++ /// repo::Repository::open. +++ pub fn path(&self) -> &Path { +++ unsafe { +++ util::bytes2path(crate::opt_bytes(self, raw::git_worktree_path(self.raw)).unwrap()) +++ } +++ } +++ +++ /// Validates the worktree +++ /// +++ /// This checks that it still exists on the +++ /// filesystem and that the metadata is correct +++ pub fn validate(&self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_worktree_validate(self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Locks the worktree +++ pub fn lock(&self, reason: Option<&str>) -> Result<(), Error> { +++ let reason = crate::opt_cstr(reason)?; +++ unsafe { +++ try_call!(raw::git_worktree_lock(self.raw, reason)); +++ } +++ Ok(()) +++ } +++ +++ /// Unlocks the worktree +++ pub fn unlock(&self) -> Result<(), Error> { +++ unsafe { +++ try_call!(raw::git_worktree_unlock(self.raw)); +++ } +++ Ok(()) +++ } +++ +++ /// Checks if worktree is locked +++ pub fn is_locked(&self) -> Result { +++ let buf = Buf::new(); +++ unsafe { +++ match try_call!(raw::git_worktree_is_locked(buf.raw(), self.raw)) { +++ 0 => Ok(WorktreeLockStatus::Unlocked), +++ _ => { +++ let v = buf.to_vec(); +++ Ok(WorktreeLockStatus::Locked(match v.len() { +++ 0 => None, +++ _ => Some(String::from_utf8(v).unwrap()), +++ })) +++ } +++ } +++ } +++ } +++ +++ /// Prunes the worktree +++ pub fn prune(&self, opts: Option<&mut WorktreePruneOptions>) -> Result<(), Error> { +++ // When successful the worktree should be removed however the backing structure +++ // of the git_worktree should still be valid. +++ unsafe { +++ try_call!(raw::git_worktree_prune(self.raw, opts.map(|o| o.raw()))); +++ } +++ Ok(()) +++ } +++ +++ /// Checks if the worktree is prunable +++ pub fn is_prunable(&self, opts: Option<&mut WorktreePruneOptions>) -> Result { +++ unsafe { +++ let rv = try_call!(raw::git_worktree_is_prunable( +++ self.raw, +++ opts.map(|o| o.raw()) +++ )); +++ Ok(rv != 0) +++ } +++ } +++} +++ +++impl<'a> WorktreeAddOptions<'a> { +++ /// Creates a default set of add options. +++ /// +++ /// By default this will not lock the worktree +++ pub fn new() -> WorktreeAddOptions<'a> { +++ unsafe { +++ let mut raw = mem::zeroed(); +++ assert_eq!( +++ raw::git_worktree_add_options_init(&mut raw, raw::GIT_WORKTREE_ADD_OPTIONS_VERSION), +++ 0 +++ ); +++ WorktreeAddOptions { +++ raw, +++ _marker: marker::PhantomData, +++ } +++ } +++ } +++ +++ /// If enabled, this will cause the newly added worktree to be locked +++ pub fn lock(&mut self, enabled: bool) -> &mut WorktreeAddOptions<'a> { +++ self.raw.lock = enabled as c_int; +++ self +++ } +++ +++ /// If enabled, this will checkout the existing branch matching the worktree name. +++ pub fn checkout_existing(&mut self, enabled: bool) -> &mut WorktreeAddOptions<'a> { +++ self.raw.checkout_existing = enabled as c_int; +++ self +++ } +++ +++ /// reference to use for the new worktree HEAD +++ pub fn reference( +++ &mut self, +++ reference: Option<&'a Reference<'_>>, +++ ) -> &mut WorktreeAddOptions<'a> { +++ self.raw.reference = if let Some(reference) = reference { +++ reference.raw() +++ } else { +++ ptr::null_mut() +++ }; +++ self +++ } +++ +++ /// Get a set of raw add options to be used with `git_worktree_add` +++ pub fn raw(&self) -> *const raw::git_worktree_add_options { +++ &self.raw +++ } +++} +++ +++impl WorktreePruneOptions { +++ /// Creates a default set of pruning options +++ /// +++ /// By defaults this will prune only worktrees that are no longer valid +++ /// unlocked and not checked out +++ pub fn new() -> WorktreePruneOptions { +++ unsafe { +++ let mut raw = mem::zeroed(); +++ assert_eq!( +++ raw::git_worktree_prune_options_init( +++ &mut raw, +++ raw::GIT_WORKTREE_PRUNE_OPTIONS_VERSION +++ ), +++ 0 +++ ); +++ WorktreePruneOptions { raw } +++ } +++ } +++ +++ /// Controls whether valid (still existing on the filesystem) worktrees +++ /// will be pruned +++ /// +++ /// Defaults to false +++ pub fn valid(&mut self, valid: bool) -> &mut WorktreePruneOptions { +++ self.flag(raw::GIT_WORKTREE_PRUNE_VALID, valid) +++ } +++ +++ /// Controls whether locked worktrees will be pruned +++ /// +++ /// Defaults to false +++ pub fn locked(&mut self, locked: bool) -> &mut WorktreePruneOptions { +++ self.flag(raw::GIT_WORKTREE_PRUNE_LOCKED, locked) +++ } +++ +++ /// Controls whether the actual working tree on the filesystem is recursively removed +++ /// +++ /// Defaults to false +++ pub fn working_tree(&mut self, working_tree: bool) -> &mut WorktreePruneOptions { +++ self.flag(raw::GIT_WORKTREE_PRUNE_WORKING_TREE, working_tree) +++ } +++ +++ fn flag(&mut self, flag: raw::git_worktree_prune_t, on: bool) -> &mut WorktreePruneOptions { +++ if on { +++ self.raw.flags |= flag as u32; +++ } else { +++ self.raw.flags &= !(flag as u32); +++ } +++ self +++ } +++ +++ /// Get a set of raw prune options to be used with `git_worktree_prune` +++ pub fn raw(&mut self) -> *mut raw::git_worktree_prune_options { +++ &mut self.raw +++ } +++} +++ +++impl Binding for Worktree { +++ type Raw = *mut raw::git_worktree; +++ unsafe fn from_raw(ptr: *mut raw::git_worktree) -> Worktree { +++ Worktree { raw: ptr } +++ } +++ fn raw(&self) -> *mut raw::git_worktree { +++ self.raw +++ } +++} +++ +++impl Drop for Worktree { +++ fn drop(&mut self) { +++ unsafe { raw::git_worktree_free(self.raw) } +++ } +++} +++ +++#[cfg(test)] +++mod tests { +++ use crate::WorktreeAddOptions; +++ use crate::WorktreeLockStatus; +++ +++ use tempfile::TempDir; +++ +++ #[test] +++ fn smoke_add_no_ref() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ let wtdir = TempDir::new().unwrap(); +++ let wt_path = wtdir.path().join("tree-no-ref-dir"); +++ let opts = WorktreeAddOptions::new(); +++ +++ let wt = repo.worktree("tree-no-ref", &wt_path, Some(&opts)).unwrap(); +++ assert_eq!(wt.name(), Some("tree-no-ref")); +++ assert_eq!( +++ wt.path().canonicalize().unwrap(), +++ wt_path.canonicalize().unwrap() +++ ); +++ let status = wt.is_locked().unwrap(); +++ assert_eq!(status, WorktreeLockStatus::Unlocked); +++ } +++ +++ #[test] +++ fn smoke_add_locked() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ let wtdir = TempDir::new().unwrap(); +++ let wt_path = wtdir.path().join("locked-tree"); +++ let mut opts = WorktreeAddOptions::new(); +++ opts.lock(true); +++ +++ let wt = repo.worktree("locked-tree", &wt_path, Some(&opts)).unwrap(); +++ // shouldn't be able to lock a worktree that was created locked +++ assert!(wt.lock(Some("my reason")).is_err()); +++ assert_eq!(wt.name(), Some("locked-tree")); +++ assert_eq!( +++ wt.path().canonicalize().unwrap(), +++ wt_path.canonicalize().unwrap() +++ ); +++ assert_eq!(wt.is_locked().unwrap(), WorktreeLockStatus::Locked(None)); +++ assert!(wt.unlock().is_ok()); +++ assert!(wt.lock(Some("my reason")).is_ok()); +++ assert_eq!( +++ wt.is_locked().unwrap(), +++ WorktreeLockStatus::Locked(Some("my reason".to_string())) +++ ); +++ } +++ +++ #[test] +++ fn smoke_add_from_branch() { +++ let (_td, repo) = crate::test::repo_init(); +++ +++ let (wt_top, branch) = crate::test::worktrees_env_init(&repo); +++ let wt_path = wt_top.path().join("test"); +++ let mut opts = WorktreeAddOptions::new(); +++ let reference = branch.into_reference(); +++ opts.reference(Some(&reference)); +++ +++ let wt = repo +++ .worktree("test-worktree", &wt_path, Some(&opts)) +++ .unwrap(); +++ assert_eq!(wt.name(), Some("test-worktree")); +++ assert_eq!( +++ wt.path().canonicalize().unwrap(), +++ wt_path.canonicalize().unwrap() +++ ); +++ let status = wt.is_locked().unwrap(); +++ assert_eq!(status, WorktreeLockStatus::Unlocked); +++ } +++} diff --cc extra/git2/tests/add_extensions.rs index 0000000000,0000000000,0000000000..d49c33cf79 new file mode 100644 --- /dev/null +++ b/extra/git2/tests/add_extensions.rs @@@@ -1,0 -1,0 -1,0 +1,30 @@@@ +++//! Test for `set_extensions`, which writes a global state maintained by libgit2 +++ +++use git2::opts::{get_extensions, set_extensions}; +++use git2::Error; +++ +++#[test] +++fn test_add_extensions() -> Result<(), Error> { +++ unsafe { +++ set_extensions(&["custom"])?; +++ } +++ +++ let extensions = unsafe { get_extensions() }?; +++ let extensions: Vec<_> = extensions.iter().collect(); +++ +++ assert_eq!( +++ extensions, +++ [ +++ Some("custom"), +++ Some("noop"), +++ // The objectformat extension was added in 1.6 +++ Some("objectformat"), +++ // The preciousobjects extension was added in 1.9 +++ Some("preciousobjects"), +++ // The worktreeconfig extension was added in 1.8 +++ Some("worktreeconfig") +++ ] +++ ); +++ +++ Ok(()) +++} diff --cc extra/git2/tests/get_extensions.rs index 0000000000,0000000000,0000000000..2ac362d0ba new file mode 100644 --- /dev/null +++ b/extra/git2/tests/get_extensions.rs @@@@ -1,0 -1,0 -1,0 +1,25 @@@@ +++//! Test for `get_extensions`, which reads a global state maintained by libgit2 +++ +++use git2::opts::get_extensions; +++use git2::Error; +++ +++#[test] +++fn test_get_extensions() -> Result<(), Error> { +++ let extensions = unsafe { get_extensions() }?; +++ let extensions: Vec<_> = extensions.iter().collect(); +++ +++ assert_eq!( +++ extensions, +++ [ +++ Some("noop"), +++ // The objectformat extension was added in 1.6 +++ Some("objectformat"), +++ // The preciousobjects extension was added in 1.9 +++ Some("preciousobjects"), +++ // The worktreeconfig extension was added in 1.8 +++ Some("worktreeconfig") +++ ] +++ ); +++ +++ Ok(()) +++} diff --cc extra/git2/tests/global_state.rs index 0000000000,0000000000,0000000000..192acdbd3a new file mode 100644 --- /dev/null +++ b/extra/git2/tests/global_state.rs @@@@ -1,0 -1,0 -1,0 +1,47 @@@@ +++//! Test for some global state set up by libgit2's `git_libgit2_init` function +++//! that need to be synchronized within a single process. +++ +++use git2::opts; +++use git2::{ConfigLevel, IntoCString}; +++ +++// Test for mutating configuration file search path which is set during +++// initialization in libgit2's `git_sysdir_global_init` function. +++#[test] +++fn search_path() -> Result<(), Box> { +++ use std::env::join_paths; +++ +++ let path = "fake_path"; +++ let original = unsafe { opts::get_search_path(ConfigLevel::Global) }; +++ assert_ne!(original, Ok(path.into_c_string()?)); +++ +++ // Set +++ unsafe { +++ opts::set_search_path(ConfigLevel::Global, &path)?; +++ } +++ assert_eq!( +++ unsafe { opts::get_search_path(ConfigLevel::Global) }, +++ Ok(path.into_c_string()?) +++ ); +++ +++ // Append +++ let paths = join_paths(["$PATH", path].iter())?; +++ let expected_paths = join_paths([path, path].iter())?.into_c_string()?; +++ unsafe { +++ opts::set_search_path(ConfigLevel::Global, paths)?; +++ } +++ assert_eq!( +++ unsafe { opts::get_search_path(ConfigLevel::Global) }, +++ Ok(expected_paths) +++ ); +++ +++ // Reset +++ unsafe { +++ opts::reset_search_path(ConfigLevel::Global)?; +++ } +++ assert_eq!( +++ unsafe { opts::get_search_path(ConfigLevel::Global) }, +++ original +++ ); +++ +++ Ok(()) +++} diff --cc extra/git2/tests/remove_extensions.rs index 0000000000,0000000000,0000000000..3e54b427b7 new file mode 100644 --- /dev/null +++ b/extra/git2/tests/remove_extensions.rs @@@@ -1,0 -1,0 -1,0 +1,26 @@@@ +++//! Test for `set_extensions`, which writes a global state maintained by libgit2 +++ +++use git2::opts::{get_extensions, set_extensions}; +++use git2::Error; +++ +++#[test] +++fn test_remove_extensions() -> Result<(), Error> { +++ unsafe { +++ set_extensions(&[ +++ "custom", +++ "!ignore", +++ "!noop", +++ "!objectformat", +++ "!preciousobjects", +++ "!worktreeconfig", +++ "other", +++ ])?; +++ } +++ +++ let extensions = unsafe { get_extensions() }?; +++ let extensions: Vec<_> = extensions.iter().collect(); +++ +++ assert_eq!(extensions, [Some("custom"), Some("other")]); +++ +++ Ok(()) +++} diff --cc extra/libgit2-sys/.cargo-checksum.json index 0000000000,0000000000,0000000000..9dcb7dee6b new file mode 100644 --- /dev/null +++ b/extra/libgit2-sys/.cargo-checksum.json @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++{"files":{"CHANGELOG.md":"239e09ac517677e56e328552756812f3450e678976f64d2d9c826d2de1939f02","Cargo.toml":"2c4902c9fdc45b8be7ac49aba35880a65832957644922938e9d3797ff8d9344e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","build.rs":"0ecd9d34196f254bedcbbf7181c4e495aa1a8f6766a7baf3d6a73678fd73eee6","lib.rs":"d3654c08b1b9b020374df8d10b13f4624b0a71b004f927ecc2e54835e0f36383","libgit2/AUTHORS":"56a6299291549dcd4d247dc78329e367df2e509336f6457b50946af55ec37a33","libgit2/CMakeLists.txt":"bf5daee877bca7801a8a20d8b7ecee4f78128e094acdf2d0b352229260edc39f","libgit2/COPYING":"e3712465634e97cfd850822a4eb5ac7d2f8a10f753189366d5a2060046f28288","libgit2/FUNDING.json":"cadc5a95ab8b3065020b9db155081c5949110bc70ba2d68fa74e7b98fb212fc0","libgit2/README.md":"b95462dd7737099aa1f5db59c19cc04bbf4ce9c8e11bd4a6b29d1f6687707385","libgit2/SECURITY.md":"991b73e51ce6f6036351fd00d7cfb3918e8cb884acee446712948e9f25c50ce3","libgit2/api.docurium":"c77dc54504945864b3270877a9ddcabe85d6d1a742c07232f6faf847958c0dd2","libgit2/cmake/AddCFlagIfSupported.cmake":"4be37a9752e3859c9ab8525f365fcb4392d1e5135ea222795c304b42dcf11b13","libgit2/cmake/AddClarTest.cmake":"022f6d1a498bead384338fd1b17ddcf72ce18d6ce54b6c0298ee3ea61c0d63ea","libgit2/cmake/CheckPrototypeDefinitionSafe.cmake":"24781f975f8d49cd044c07cf010050593317e66575ea1002b4b896e8b96bb45f","libgit2/cmake/DefaultCFlags.cmake":"a2b5a645f29bb3be74aea7bf5f5d83a77f68d3190363e83b43f9ba70a41c5963","libgit2/cmake/EnableWarnings.cmake":"f5690cb37a672c92696f618890da93d44eaa07f3cdad9a3515bb08125909ac0f","libgit2/cmake/ExperimentalFeatures.cmake":"5722077113489154402f9ba758aff0e351c47887110e1ec2bb7da3ca50f63652","libgit2/cmake/FindCoreFoundation.cmake":"5f71227384a4914df198dc7766b6b8474942730a16c22de0c987c9548808f1c6","libgit2/cmake/FindGSSAPI.cmake":"6704673fcbc0c94c02395a3e4fd96f41fbe0111397f0f06dd9a912d11c1ddb91","libgit2/cmake/FindGSSFramework.cmake":"136f3282657cd83aa5a9ea4a3d11ffd14d839e637c6e2669aa5f0c0eb9d9daab","libgit2/cmake/FindHTTP_Parser.cmake":"ca1d95edef14b1e05449d45dcbdd93c386025c408cbf27a00cb4af4ab0d62a7f","libgit2/cmake/FindIntlIconv.cmake":"75a64438565daa580681a4b856046debbdb38f52abe4db8b689192e5209f53e4","libgit2/cmake/FindLLHTTP.cmake":"08e5b8c62230535abf9f8eeac76ce60e254956b1318c5303b30b0bffc9565bdb","libgit2/cmake/FindLibSSH2.cmake":"0cfe918a5d00dbceeae55ffeb5546f8c5595eb48558c2e9584561db17f29b91f","libgit2/cmake/FindPCRE.cmake":"2b1e7b45cf0410320e706573ecce75b8be4eeda6b9b4fa19893a248c57096a71","libgit2/cmake/FindPCRE2.cmake":"d8045c217a1856963badd52548406cab2881d2ae304608d6b40bd77bcb590f0e","libgit2/cmake/FindPkgLibraries.cmake":"e50a58f9d39ed58d5bfc39e6f18066b436cf92ccabd6683fed4f30cee9689627","libgit2/cmake/FindSecurity.cmake":"1c16ac77018f28efac83cd848c130d5127c22999dc48efe44bc8ee9b501deb29","libgit2/cmake/FindStatNsec.cmake":"4b3bb2337ce205580703704a2725eba085044810d54a0e0cc5680b6f71eb494f","libgit2/cmake/Findfutimens.cmake":"281fa0a75648482e3b13841d92db2c5332147fa8c7f96afe7ee11eae77a6bfd3","libgit2/cmake/FindmbedTLS.cmake":"23d2c96094b525b7a333427776cf51f0a1466a70d9358af48c8d851e20ebad64","libgit2/cmake/IdeSplitSources.cmake":"0c1725438bac95a6c56627408b81017a88748944b0ff83cc45c0824421e3aeee","libgit2/cmake/PkgBuildConfig.cmake":"fdf17c32ee3621b671695f29a1373f4e2d05606dad03a658a751e94a37385f91","libgit2/cmake/SanitizeBool.cmake":"6d93d776331f1cc9d4052ed53731789d6e141bba9ac8681dba70a80abb2cdc00","libgit2/cmake/SelectGSSAPI.cmake":"fdd233669f3d426adf1a773e021e2761e56f49d073a2af56652b230ddc4d949e","libgit2/cmake/SelectHTTPParser.cmake":"c083d30eaa75b7fa5d6dd2c71b6b0207f62264abc7b10fa63ee3f1657810e9b6","libgit2/cmake/SelectHTTPSBackend.cmake":"bb62b26210aaf9cec0f745aee9fccccfbd751f6d78ecdf009d3e62064966033b","libgit2/cmake/SelectHashes.cmake":"d146e3544637032d3afb1d2d8b282ddfead8d882241244f9dffb70e074e708aa","libgit2/cmake/SelectRegex.cmake":"b3e6fd581fd93a0e5e52c18ebb7ffc08b50bce8f97507e3bcfc32e49523dc709","libgit2/cmake/SelectSSH.cmake":"41fa2238d92a33da0b59d16d4cd71c02311fc3ab276d3b66057ec750f79b768f","libgit2/cmake/SelectXdiff.cmake":"aede153b2634f2485d3717896d453b0f87cf26873ea02e89cc5aa31106ecd6c4","libgit2/cmake/SelectZlib.cmake":"b95582c741f759625ac8590e7728c00693397d9813bd41ec97aec889a63a5f19","libgit2/deps/chromium-zlib/CMakeLists.txt":"f8c70a5cede31712527ba84f3eb0c0a8319cbf7643c6afb63c1fdfbed1e757d7","libgit2/deps/llhttp/CMakeLists.txt":"1d96268d8a4ca2cbf0f40b0211e66c4c046badf51ffc8e80a4f074b72b965752","libgit2/deps/llhttp/LICENSE-MIT":"ebca854e0134cd256d673627c20499f42577eb74bacf08b9f25b626a73c91277","libgit2/deps/llhttp/api.c":"97f40be464a6d72731673f8f0dca19f5f54feec6bbbdcce0646d1d85b64084be","libgit2/deps/llhttp/http.c":"a1f2b23168f8e9b5bfa464c89027d3ca259fc649ae3d7e72bfff997d1aeb5d72","libgit2/deps/llhttp/llhttp.c":"d853660d90a48b370fc3aac5fd9ae664a79860522fbac9cf5c40f70e40af03c1","libgit2/deps/llhttp/llhttp.h":"066ec0eea575a2dddad32ab9ca39b2805b69b32187ed78e1231cfee24b786f3c","libgit2/deps/ntlmclient/CMakeLists.txt":"25fc0e36038a920f14bb7b439b8f1317a33a32666a9d1e9e993183d68c90cb54","libgit2/deps/ntlmclient/compat.h":"f27a8e91c75ed75a71140c597548b43fae19b28eda1a09ab28e367a196bdad84","libgit2/deps/ntlmclient/crypt.h":"38647af40b21a8baf2c2e73e80ff631718b7fb0db51b0c2079d4bc85793a2032","libgit2/deps/ntlmclient/crypt_builtin_md4.c":"2a18370c597317819359886a54062820048a0621d4e38b89e9a5e5760c69777e","libgit2/deps/ntlmclient/crypt_commoncrypto.c":"c00d8ab310df82c32f51ac11ed02ba69cb4a13a56d0848e8bfd8b928ecb60c0c","libgit2/deps/ntlmclient/crypt_commoncrypto.h":"55a6fe82280421e5fd61f20be1938cc92efef1a211147072790eecc91eb87e6f","libgit2/deps/ntlmclient/crypt_mbedtls.c":"1c2e053e86b4e706a40654b2cdd5e027c022cd9590a508068ccc173db15ee1f4","libgit2/deps/ntlmclient/crypt_mbedtls.h":"d10c8dee39844ad68a6f408d4134300b984279da9dfb9c7ff070a7065e5ecc26","libgit2/deps/ntlmclient/crypt_openssl.c":"528baa27ff9e538a855a812071158ee28d3792565c670d7034dcb05f9d7a67db","libgit2/deps/ntlmclient/crypt_openssl.h":"8c87194b5fd0220f4b40ec5ddaed151c8a189a157ed3b3ab3595f5358cf4a62d","libgit2/deps/ntlmclient/ntlm.c":"adf2d486d8c5a22227e5f1b67da2f81021c2df9c85512c18b67f26121f6c465e","libgit2/deps/ntlmclient/ntlm.h":"5328219af7251999ea78a2d2d648a6d98943af7ace5fbce0d8cb5ad4b0bb4c60","libgit2/deps/ntlmclient/ntlmclient.h":"fa223a164392f53822703c80dfb1299d3483bab3b9ad02fec1058a0f50a55eca","libgit2/deps/ntlmclient/unicode.h":"ddb0cbb25cca1a2f413865070fd47c354f87caf66f868022dd288b90fe93711d","libgit2/deps/ntlmclient/unicode_builtin.c":"639717b403f73b8c16de91456360e78343da62721c242555033f65e36ed3e3ee","libgit2/deps/ntlmclient/unicode_builtin.h":"fb1674d49fc240f33d8120fea10504021a61f69967d933ed386d57d0b267127a","libgit2/deps/ntlmclient/unicode_iconv.c":"9e04ea305d04ac91b4c302ffcb06a4f8b8aa6dd8167a28e3dce6b37c5aa35a01","libgit2/deps/ntlmclient/unicode_iconv.h":"7dd5cfe97dbbbcec94f3e1dcd6edf51785f6eb5510ef96607fce45ce1cc818a3","libgit2/deps/ntlmclient/utf8.h":"8f7396ce0f4e6a4288982bf9a98aced8621bb8997aba77510fe87431de1165b6","libgit2/deps/ntlmclient/util.c":"94ec747cd810c90ccc966688d89ef8dbfb91e41aea2f665a13db5fa18ac26443","libgit2/deps/ntlmclient/util.h":"2eed4228416cd6286500c966ed5fbaa2bba7d548b75dfff254a4e45feda85cdb","libgit2/deps/pcre/CMakeLists.txt":"8dd12e8681df34e4755194e937b1d733380d97ac28b448941c872e71f4959029","libgit2/deps/pcre/COPYING":"17abe1dbb92b21ab173cf9757dd57b0b15cd8d863b2ccdef635fdbef03077fb0","libgit2/deps/pcre/LICENCE":"51b3dea44f63338b84b9c97b3d793826a8397309068cf9379a423216ab8ea5b2","libgit2/deps/pcre/cmake/COPYING-CMAKE-SCRIPTS":"46cde7dc11e64c78d650b4851b88f6704b4665ff60f22a1caf68ceb15e217e5b","libgit2/deps/pcre/cmake/FindEditline.cmake":"44788ac3e7c8c4b4da3e5e0f467c7ee49de7ba9e1c13024dcf1e2501f8fe9684","libgit2/deps/pcre/cmake/FindPackageHandleStandardArgs.cmake":"aa3ef1f1c8742da54813aab0ac58c71edd1e58cd3b6b157b856bfd525adc2e5d","libgit2/deps/pcre/cmake/FindReadline.cmake":"055e1df8bd29e6837d8ebb8c15dd5dcb28c88e23aabda8538b76a249dff829b0","libgit2/deps/pcre/config.h.in":"480e3e1a1eea810516e59f19375575e83f62980d20b9cfc990ecf8e8cb17f79f","libgit2/deps/pcre/pcre.h":"a0cf7c5c7659779e198e31d856fc3d2cbeb73b0caed8d8a95a1b15ce1af28880","libgit2/deps/pcre/pcre_byte_order.c":"4030a1156da8690352226b5de2c9c5f52cc6955409e4a7ab9ba4d6b223e74b3c","libgit2/deps/pcre/pcre_chartables.c":"3386fd60b4a4175a7baf474223522540abd6e006e8507a04d3485f84973424ae","libgit2/deps/pcre/pcre_compile.c":"d0493e6abaa2108a3edf3469052f3f93818699aec21f5ddde03f0e406f2ff9ae","libgit2/deps/pcre/pcre_config.c":"fb9e1e766291b2b4b3066ecfd0795db398762b9597fb2af23cc784617984609e","libgit2/deps/pcre/pcre_dfa_exec.c":"1cbf3a680388110bddff833983d3653630eedf6e6e9d9e656a737e3b85de9dd0","libgit2/deps/pcre/pcre_exec.c":"2cc612c9d8020aae0339f292cf28a268838a9ab90658cdff06b5f3ee914e4fcf","libgit2/deps/pcre/pcre_fullinfo.c":"a84fc4cb4d22b2ddfcd4d0f0a0ff333cc9f623e1fbf2a7c90623a212e0bde54d","libgit2/deps/pcre/pcre_get.c":"c93ded768f96cc392f911776e6d993b565114936e08247dfa79080b35dada4e7","libgit2/deps/pcre/pcre_globals.c":"8b2fda23b42715eff2f01188c4911dd8453868ff77fccfe34b99126aa775fa5d","libgit2/deps/pcre/pcre_internal.h":"f713de1fa2c20b5414f6746c80d10878ab48c9186462b074c5bb6a74a822fa80","libgit2/deps/pcre/pcre_jit_compile.c":"76ed39027b25f2bdab581c0bb12b95fa3659baa53c81e10f8f17819d6255199b","libgit2/deps/pcre/pcre_maketables.c":"8564fab861c7eb4037ffcd53fda789a747a30c4a462f460a5ef824f534fb06dc","libgit2/deps/pcre/pcre_newline.c":"3163ed2193fa74d8cc9e1db2bba672bcebf8efe85c2465cc0aefda51966bd929","libgit2/deps/pcre/pcre_ord2utf8.c":"fa926e32ae8d6e5610c500e7b6971a5149765a1881f798b18904a0a88bf549de","libgit2/deps/pcre/pcre_printint.c":"71751d151efbe935e9d8bbf58bbe143d617b34acd13d1bf237330c7c7736c422","libgit2/deps/pcre/pcre_refcount.c":"0dd8b7273243545fdafab585890fa12e210cf526030eb6b877325ce89250fa39","libgit2/deps/pcre/pcre_string_utils.c":"b83225f9cf2658654d6a0af01199050f6fb36d903041b33cd4d0c06e762b66df","libgit2/deps/pcre/pcre_study.c":"f5285714b59af9503dacff268cb37ab4944fbdf74a78c5a7b9bc49043a00ba40","libgit2/deps/pcre/pcre_tables.c":"fcdd9f705a7a1640ae5e5e5b7148761fc5e82896d84b1a287dd7e55b8b87eb15","libgit2/deps/pcre/pcre_ucd.c":"b35ad7e532f52c5fb1f4ab1d48f5d80618abff2a115099220d95cd13ac64c346","libgit2/deps/pcre/pcre_valid_utf8.c":"4265abf04c03acba9ea90351da662eb89aaed79e7eef03329ccf030ef28ef907","libgit2/deps/pcre/pcre_version.c":"5bb67c3373a934a2d9263ba9f9fe3cd79e381e6aed8507e5319202330bc5275e","libgit2/deps/pcre/pcre_xclass.c":"b2c3b2c7600e18e562a333df017ee35c69233e9427b866726d944122a9560e28","libgit2/deps/pcre/pcreposix.c":"49e996bbf43cb2d4acec350410ab40f811a9fefe21fc68004c6182a8da884aba","libgit2/deps/pcre/pcreposix.h":"85a6a09b806d8506e5710e9862b6716b2b88761abe0d05aeda5071257537d9c3","libgit2/deps/pcre/ucp.h":"ea98e4eb999d8e777f2ba709e68b5aff7108a4eaa169f4eefa4510056551b724","libgit2/deps/winhttp/CMakeLists.txt":"e9012f9e9812df5a744551a9b57982fe8c8ffbdd3ddf41a8d96e58546fcb72c6","libgit2/deps/winhttp/COPYING.GPL":"d9a8038088df84fde493fa33a0f1e537252eeb9642122aa4b862690197152813","libgit2/deps/winhttp/COPYING.LGPL":"dc626520dcd53a22f727af3ee42c770e56c97a64fe3adb063799d8ab032fe551","libgit2/deps/winhttp/urlmon.h":"6cdb0f5ce5f0aea2daefc44c4806697ed31ad759f8baa18fb38a5b220ddc7d7f","libgit2/deps/winhttp/winhttp.def":"89601b95ac2515619426ea52ca093fac1a16ef0bfb5586c1385a028947ab6513","libgit2/deps/winhttp/winhttp.h":"a51828d65b1b260a727f596c41cf3257cac2ef6cfebb11726234fd7ccb1537f6","libgit2/deps/winhttp/winhttp64.def":"7cd0bc8dd2c06d288c241d175da06146e940c28d7201fb63de8a75730d09fcd4","libgit2/deps/xdiff/CMakeLists.txt":"566633d8b9bf4674f8b13605c8c77f42cf0e29e1ec82bede60a1559c092837fe","libgit2/deps/xdiff/git-xdiff.h":"8c39998f8a58de5b9401f3f5b12fc8b4dbc5cb3314a1ee3ce00da3b9339ef723","libgit2/deps/xdiff/xdiff.h":"6459a65d5e0f910f6bdcba30cd5332a58fbb75118acb5757f5596bd22c00a6cb","libgit2/deps/xdiff/xdiffi.c":"89c9015af166c491be55d2ed75de5be2475c3e6c9a657697c838c77da42d8958","libgit2/deps/xdiff/xdiffi.h":"89917373f37fab79ec7da56e6829c2bf05962ab1fb9e9e4f0950adbb31265614","libgit2/deps/xdiff/xemit.c":"e31c12a09dff4a9dca32166d2eee915b80294b408e86012f72f03528f69a4282","libgit2/deps/xdiff/xemit.h":"0a8c569eec74bb4d6e8b7b9a50b457532550800e0566cbba6d185974613a2e6c","libgit2/deps/xdiff/xhistogram.c":"74bc7e7b8926418d20d2772fe8aa5c3f4c525530305c09cfe81712c80ee92890","libgit2/deps/xdiff/xinclude.h":"cd17076d3909d1750044114719daa2acc0ee4b53afd9c2f3864cdba453f5f0fa","libgit2/deps/xdiff/xmacros.h":"f6db27fb8b3c39fbfa1b06bf7a1af45bec4b125614147353fc98798aa89c0bf2","libgit2/deps/xdiff/xmerge.c":"6741b89ba5ad54aaf4c2adecc03f5b7b60d5b9aeff30fc7546be15c26572c252","libgit2/deps/xdiff/xpatience.c":"ff098106ced16724ffe55d4a371af314fedf356576d5ae2c3ed4e617938152ea","libgit2/deps/xdiff/xprepare.c":"44ade0e142a1dc1bd3b9cb25ef4df415213f1f85cf2a43580af25c297bc7c6da","libgit2/deps/xdiff/xprepare.h":"4945e8fffe620cd4d687c12618d1a4b2aa95a7a8097abf3e5e341abf96c76e1b","libgit2/deps/xdiff/xtypes.h":"3336d046bf60e0dc99f3686dfe9ecf098456f0aebe96486be5d1cd64b5d9cefa","libgit2/deps/xdiff/xutils.c":"82ea4546497bd7212ff445537b58a9c64dcae297b839c2fa9b374aa40cd5c862","libgit2/deps/xdiff/xutils.h":"383027bd378a757ec1a96f2825976f817a066b6468774ef703b35c9e1c75ed73","libgit2/deps/zlib/CMakeLists.txt":"bb881a0b24a2800ceb8a624c5165d80e7e8fd451b3bb40f8a73790b188ea6144","libgit2/deps/zlib/LICENSE":"845efc77857d485d91fb3e0b884aaa929368c717ae8186b66fe1ed2495753243","libgit2/deps/zlib/adler32.c":"9cd1443a24ff2a3053961695bd432035c58347386a420d3388232376ebabe211","libgit2/deps/zlib/crc32.c":"8fd16f0a7714d51c89c2eb37eb98ec15e8a4dc57ba343e7b7398b19144039fda","libgit2/deps/zlib/crc32.h":"9a2223575183ac2ee8a247f20bf3ac066e8bd0140369556bdbdffc777435749e","libgit2/deps/zlib/deflate.c":"3b956337350f94c34987750f785587ef33d9c89ceaebb7c2afb189c956360cbe","libgit2/deps/zlib/deflate.h":"48baf016326d8d5e3e32ac8153cc7e22f854b8e6834830b167b998a7fb1e7989","libgit2/deps/zlib/gzguts.h":"716fa648aca1bb06c219d7b97ad4846d8479206143bc39557bfd8283f5783e04","libgit2/deps/zlib/infback.c":"62df9a6dd3eef126f1d81d0ad7a534504610dec44482b0a472b61c93cbab6554","libgit2/deps/zlib/inffast.c":"e6ef64ce5dc0a4cd5c7ad08ceeb2b2a698b8447f6bd156057caeb2edab68c0cb","libgit2/deps/zlib/inffast.h":"05cc5dc9ff1da7b8b52a4bd8bda0d8a5c236a2f39efe84b941516ea13857e6c5","libgit2/deps/zlib/inffixed.h":"237ba710f090e432b62ebf963bee8b302867e9691406b2d3f8ee89ee7bfef9b0","libgit2/deps/zlib/inflate.c":"34c998ce0037c0537c04b03b276f680b945f9b2c9d1e01b287605bd6879f7fd2","libgit2/deps/zlib/inflate.h":"e8d4a51b07694bf48cb91979c19974cf6a5ab0b8a09d26ec0d14df349230673e","libgit2/deps/zlib/inftrees.c":"5d4f335221d2dc76f17abd2577d92c2d7baf68fa6d7f23373b360830493d1563","libgit2/deps/zlib/inftrees.h":"0a0fcaf2ae2fae57426bdc06637270e9bba974f35202cadbdba479d946e6409d","libgit2/deps/zlib/trees.c":"f63c68c16c05fcd196050529d1a0e7657960e4136b9987d90a6ac3e58a964b0f","libgit2/deps/zlib/trees.h":"bb0a9d3ca88ee00c81adb7c636e73b97085f6ef1b52d6d58edbe2b6dc3adeb4d","libgit2/deps/zlib/zconf.h":"f5134250a67d57459234b63858f0d9d3ef8dcc48e9e1028d3f4fdcf6eae677ae","libgit2/deps/zlib/zlib.h":"8a5579af72ea4f427ff00a4150f0ccb3fc5c1e4379f726e101133b1ab9fc600c","libgit2/deps/zlib/zutil.c":"8ced40d8c88588811edd2bdb35b7439983d5e1f8e9e32b8a3b244731f3c317b7","libgit2/deps/zlib/zutil.h":"dddb2dc7a1dc339ecf2c8e089b366f08bb731c0839c7110240d17ce731bb4fea","libgit2/git.git-authors":"807ee76d5d1f87f87bb4deff8196b7854530521ebe52bde5d52b9e2bb82a75e4","libgit2/include/git2.h":"04b93d6a4dac32d661a56c3ca222ba62e8896f8148774ed52565d631ebf8d0e0","libgit2/include/git2/annotated_commit.h":"db6ae80abe996c772311f8f922c95107e5da2d34e3cfb7eb5516614b011d56ee","libgit2/include/git2/apply.h":"ffb13a162ad33bfa60840c4062669d8e752c6eb2f16b02ec5ef01e4a2f3ef8b2","libgit2/include/git2/attr.h":"781cdbcb3e11892c9df464d3750689edf17063136d1e674b8c5dbce22da1097b","libgit2/include/git2/blame.h":"2e7000a338de982a120716175b8e3e5d82270e9d0108d67c3bfb32b8b54c9c3d","libgit2/include/git2/blob.h":"6f8b1da0fcffd5f8a5c40a51704397741b820981d49d363990f0526145ef3992","libgit2/include/git2/branch.h":"b9644e8e34610f59b749091e883360dc33ca83a911fe99bca8200337d4221d05","libgit2/include/git2/buffer.h":"6a137704c0ba3e1fb332a4a432923b1ad32e392c36bfb38141f951b814bd6523","libgit2/include/git2/cert.h":"c41d6db041e351994433588643498bee37ac660f345c7ae1d7dbd7da105f01a9","libgit2/include/git2/checkout.h":"98378b75321206229ca5cf8e171a4ed666e586f4b94e7e8968da57305bb83207","libgit2/include/git2/cherrypick.h":"733fd3e446ca33212921c34c067e489d0ffd91531db8b84e99a5108e726db1c6","libgit2/include/git2/clone.h":"3cf212c27bbdd1680bbf8af8008a2114d9d5e029350c0e0a7e22272a3e9b1814","libgit2/include/git2/commit.h":"561667b10a97bec70c5a267e55692c212c763dec8bd86f8e5a4fafa169b495d9","libgit2/include/git2/common.h":"f96f0ea4a8dd71b8ba25180428fa8080a34284d6a796ab0edb4ae07ef536d2ae","libgit2/include/git2/config.h":"7e239b766b6772de63081dbe20342e916b223ea445f57631fb6e732b714111ba","libgit2/include/git2/cred_helpers.h":"4478aa5e3f82cd754333311939c3c0d5deeff7be636f68e03a7f5b1c5f4bf73b","libgit2/include/git2/credential.h":"9066b84291e63c78bc69ccf46b3197a530bbd7fd82507e8d3d4a70237d56e88f","libgit2/include/git2/credential_helpers.h":"98e54a11f950e0451a692f1a989199a0d6f7de28684fe9a1e6c0dd67561465fb","libgit2/include/git2/deprecated.h":"c77395e0d38172997a15f484c2d00e9ab5a18730ab401ad0e535e85edb5f880f","libgit2/include/git2/describe.h":"2f63fec11bc7f70ed11f7a66eaa1c58e8a2554ca274be5d97727d4fc62e3347b","libgit2/include/git2/diff.h":"4bbcd6c341919c6605c7905be3dacd40da901b8328d0b9e5beeb9acfc9cdf463","libgit2/include/git2/email.h":"1872a47a91d43979c6edc4f17154f30d8e9ed0516a30682718bf15b9845a6e04","libgit2/include/git2/errors.h":"c68d33d2d41bf595ef7544c6dd2af4c5ffccc8fea8b5a7379a3cb084df451ca0","libgit2/include/git2/experimental.h":"11218571e33eaced42fc23331994179c25faaa6bb918a75087afea89d07ae3f0","libgit2/include/git2/filter.h":"920e19f75f4fdcc2eb08601e0611df3b22e701f473d4ad7dc513f60b968a3a69","libgit2/include/git2/global.h":"377aab0df9a552b93c8deca8e7bbc34d14e8662b9b6846107d8c60bf5b136f31","libgit2/include/git2/graph.h":"99a947707841139b90ff0c67668af8dce107e6af8ce985b73b6829b3f9b8884f","libgit2/include/git2/ignore.h":"381176cddebdda0e1568773903f11dd795abd5b7a2cecc8ddccc058d3268488e","libgit2/include/git2/index.h":"58e392fa587b9a68e8c0fdeecb33250aa4e246e7d08be906457e98834848b2d3","libgit2/include/git2/indexer.h":"07a15611b6d3149a81ada7dd45ac9dd1e3866d062a17e557d42c690c058373d7","libgit2/include/git2/mailmap.h":"25df25bf0291ef856c5807f2cd352607e9329b3da2bd80b3fca507967dbce266","libgit2/include/git2/merge.h":"952034c1ede3c0ebbc9ca95123e22f10a63edad2e5f58722d68c4547d93839bc","libgit2/include/git2/message.h":"770606ab6c9fcdc58a863bb541b262c113c3d5b516e13a1225dac1c913c1ca0c","libgit2/include/git2/net.h":"1e7c746f12540b1073f0c0159c12336fa83e532f40a5e2851702d303cbea138b","libgit2/include/git2/notes.h":"76968a7990cc7d85df09e98d5604d64be64d77f399c45067e1f6b9b08dff1518","libgit2/include/git2/object.h":"0547af2fd02aa756e94b3ad682434ddcfe430224b563273be506135b0b1c9107","libgit2/include/git2/odb.h":"49ef671eb0a06b2e421e75d2e952583014925deb0098e170b108a808eed86046","libgit2/include/git2/odb_backend.h":"ce8aa6a659e9b0b3d6cff7042a7ddce1ef1610ee608a671423c60715335ef2f9","libgit2/include/git2/oid.h":"3040665c20c1119635a8ecc528b19342d907adca4b6d5673b2f088e108e218fb","libgit2/include/git2/oidarray.h":"8d8b1f317c7cc78195ffc20d75b92960792ce08286f3cd80db4d1323e9f7a590","libgit2/include/git2/pack.h":"8da6a48d1ed248e725e2ba641d5f0a0c024ce45d5ac8768d9b7967aad8cb3fb3","libgit2/include/git2/patch.h":"6a549b6821dcb147761a1596203c12fdb4abbd6038aee94f8a23525593bc652e","libgit2/include/git2/pathspec.h":"28c479d635aaf55007d026ead6336ef4043c4005d0d2a20eb78b61f27bbc0768","libgit2/include/git2/proxy.h":"960651fc189fa6b5ebede460dd33df12e2072a35edcdb65ff207554194eef3db","libgit2/include/git2/rebase.h":"11eabd700cedbd186453e8e1874d836b85386106fdb614e0c7496a697c73b2a3","libgit2/include/git2/refdb.h":"c2785560d893133745efd344fa853660f0cd0d15e25dda56373d98d0f00fd73e","libgit2/include/git2/reflog.h":"fe4c09ecc76d4515cdfe810e144ae2df6d9d142f37f88e72e6488950b08325f1","libgit2/include/git2/refs.h":"c7e315fcb44045195a0163c7b2644e39a0d8a2901648025317e7e627de199a8e","libgit2/include/git2/refspec.h":"5ee144d4e5a15f0f3f2db0d827f0be5ee77bf20a6aff88a4bd383221d6354473","libgit2/include/git2/remote.h":"c565e65e5477aa9a373783e9ff0a508e46b54811e14f0855da7745fbe3716a07","libgit2/include/git2/repository.h":"947f01e699aad61723a517ef0802bbef6750efaadc71f0db54f14ee6fc2e1e05","libgit2/include/git2/reset.h":"a117417c2d07e9d3325dad337c4463e66db837505a27a35bd606fb8e2bc4ab51","libgit2/include/git2/revert.h":"28b4f1d47c2a59a5190efe742dc5754c3cbe62138dd258412ae99b34dd1551e8","libgit2/include/git2/revparse.h":"8fc12d979a3bf00c3bf736d767921cd78ae8d890bdc603d9bb143c2d8ef62154","libgit2/include/git2/revwalk.h":"d7edf83b9cbfa7ae6dd9c7a2685df718873b99bb1d599749a538dcee818e0027","libgit2/include/git2/signature.h":"07a715960dad62424fcad3b6902b00de237867e52b47b049adc60a2647f09d65","libgit2/include/git2/stash.h":"c9955a519348a335afa2af3b12e5683a35c6f8f40689b3139a25bc1d46ed002f","libgit2/include/git2/status.h":"a7821a0c23b8645e02bf5a98c312e1b180dd69efa41d22561429700fdcc80cc3","libgit2/include/git2/stdint.h":"051a031fc8a0845c7951fa154b7efeb5a6252669856bb33a71d5ceeebb9d5406","libgit2/include/git2/strarray.h":"fee029c468fb4d5b55a2c7664494275a2d9a8dc9d4d0bfde69b8dfbdf86ff1bf","libgit2/include/git2/submodule.h":"3b8d3488a7367dbe310baeaf9536f4adcb94dcfcf53916c72cc79a561d4abfc3","libgit2/include/git2/sys/alloc.h":"fba245b560edc88b371c841a898aa588b043fb9f165b0c71c1355104fd6d2416","libgit2/include/git2/sys/commit.h":"d34bc09c34953177487aa987b11d92ae486d17a6e5ca7caaec935ebf949f6fdd","libgit2/include/git2/sys/commit_graph.h":"602a79d8502f4461e924ee6655e55db01c90919ba3581f30d6d6a1a723f7de34","libgit2/include/git2/sys/config.h":"cc8010d313368f7a5c599b6dea8ab90c8a35e54fa19d8e19d208e8e509922199","libgit2/include/git2/sys/cred.h":"b2ea956401c5554f26cec0f428dd9d0d9661d1ef3d9368769b415193df98ed1a","libgit2/include/git2/sys/credential.h":"c7b9d66f19c7b28134f7c00b1e1c6ac8d0694e2a921d0219492d33c03b8873fd","libgit2/include/git2/sys/diff.h":"b4e9d4e4d47c3071d1d21f8e44613f3c457e3d9d36972d5b19a6df6ed7543d09","libgit2/include/git2/sys/email.h":"505654bfa9d46c8dbdb75631b44fc430808a767529905460311a597912c201f4","libgit2/include/git2/sys/errors.h":"f9f08dcc38782986a8e4078ffa9023d449e4f8fb118ed6847195b4aeea6ae11e","libgit2/include/git2/sys/filter.h":"0508bf325e3035bfa28692231495292999ccb1ad4e3f977726287b615e76ad84","libgit2/include/git2/sys/hashsig.h":"184e8124f282ab80909212ed25c62f04b5547b03c8df15141f999bb052b9f20c","libgit2/include/git2/sys/index.h":"a491832bac3948bfa19962f7bb1bc96e74dd2590a45afd7196284ace94f8727b","libgit2/include/git2/sys/mempack.h":"3f902801f8dfd587abb000cf62b9af76f0b2e8da75dbb6f23660472bbeb8c265","libgit2/include/git2/sys/merge.h":"c901a5bba256e2cc7f4965555e43d3a34adc491d89d95d9ec37fd84c16afa4f5","libgit2/include/git2/sys/midx.h":"63754c3c51a5924bc191c4f02262b0962990610382c5ff741891c58b166efbc1","libgit2/include/git2/sys/odb_backend.h":"29c2aa4efc79d3dd8818dfbfb4b7381556d64a282dac1021c9189af5de709792","libgit2/include/git2/sys/openssl.h":"e94117488e34bf5b0b32ec75c934f5d8fd56ef991a22d221b84c631f9336f85a","libgit2/include/git2/sys/path.h":"ecf909282490bc331e81996f37356f45f99bfb1c255383ce062dfdb961e08ae8","libgit2/include/git2/sys/refdb_backend.h":"c90fa95e6d0fa09c697748d7996c51b3f168719c409bb052c18ff169ce9910a0","libgit2/include/git2/sys/refs.h":"64bf32e8e5174ef4d65050a940b8153e62126d40da59c5b4b6becb0382d85cdf","libgit2/include/git2/sys/remote.h":"cdc4bafbdd64d4fe23be24b54fa12957f48d0d3da092f2e6f8ff9e36c37e3801","libgit2/include/git2/sys/repository.h":"322b056f5d5d259f01c35c6a8455f2898e2f547b8a914c93ca2df032f807ebf4","libgit2/include/git2/sys/stream.h":"f740ce0c770740a66abab39932eb876fb95962d881e3b80ba6e5fbba47dc088d","libgit2/include/git2/sys/transport.h":"1c2eb079df00942b22693cec746bb45636a36e468078f358f5b845a71a1afc16","libgit2/include/git2/tag.h":"a032086d2aa97c02858904e96918cff8a1a47ad7df054e421259f9006830f02f","libgit2/include/git2/trace.h":"c7fee0bc30268081aa1cef033bb38e37179b09eb07afea9fec8e63529ebe85b3","libgit2/include/git2/transaction.h":"55602cc816a57436aba35438a32f4d534d04bb31afdf751cdd5c2db61b1b4644","libgit2/include/git2/transport.h":"a6b3f6b26c0c1640c5e88fd161e5cf4574e9c3cd9b2c22ac61045e2c63faebfe","libgit2/include/git2/tree.h":"129542fdaa60301ced5150afe2b43a4649d654159ba6a152f608d00f852c0d28","libgit2/include/git2/types.h":"48c399475b08a7296b754eaf62664512c425252da8dcc9f9bff9460c4072d989","libgit2/include/git2/version.h":"ebf5569dd3023d8c8e62695881fdfe69f0ca6ba062bc677b997cfcf8ea0d8188","libgit2/include/git2/worktree.h":"b74eae1f0f41140112578dd48602ac5cb73759f0e7847a2a1987665c6d8ea6a0","libgit2/package.json":"4fda7dd425626617c3118e25f02f5a9b9f4be2f17d33cef22cd23d5022f7ae3a","libgit2/script/api-docs/README.md":"9b7048890c4d1204532a4de94c17aa0f661442581aee9de79ad8d5eb99eb1103","libgit2/script/api-docs/api-generator.js":"6bae0247a550ebcb811b2b478f5e4c53bd5e5579adff6f07ab73fea1fc3cf806","libgit2/script/api-docs/docs-generator.js":"38894fc8cc204d974f76ac4b45a852a17bc81558fd84d4c9c8d6269b783f8374","libgit2/script/api-docs/generate":"ecdc102048da88c20b827fb25a0ebc8167e381db01e76b510c9468a59c56d1c9","libgit2/script/api-docs/package-lock.json":"6e50e118eef2d19ebd0cb1086948701d46795f6360dbbd2aa10a6fc1145e1e11","libgit2/script/api-docs/package.json":"82672c5dd592b4106165a2afd1a1e1bfcac10043eeba649368ca613991a8e01a","libgit2/script/api-docs/search-generator.js":"b9536113c7df568c460110284fc2435e091eb73e0e8ed24c141ea5eea6b88a0e","libgit2/script/backport.sh":"6ef93a8c4a15ef74d2639638db3b24d20a76fc31faa53b1c34b07e3759c78fe6","libgit2/script/leaks.sh":"62532838555750cfdbff91709c40b1c1356e399238fc29379a45802922530a51","libgit2/script/release.py":"28a113a377422d7aebab4ce25c672f134ccb8a81cbbcece4d6af4354c44c4711","libgit2/script/sanitizers.supp":"8ac23fc907490c5ba1dd641f97201878e195c3bec0c1f224a9a4dda1fbd1f5b9","libgit2/script/thread-sanitizer.supp":"6497c98a2c0c83d867b0d88c36095a609731e7f6f4ad5a73dfe5287d6f2ba0d2","libgit2/script/user_model.c":"073e0b631f2d50af9c326dc009c626dfb9d31707d36bc61396ad9960160652bf","libgit2/script/user_nodefs.h":"4287333a6d7484a5a5796e6deadea53ec1ef587e4c571351e3fab61cf8badb45","libgit2/script/valgrind.sh":"beb7ccea1140bd25684216aefcb7ab44ff42fa9a4d0376ec18f47060d84688c5","libgit2/script/valgrind.supp":"03369931efdcbf06380b0deebba763014f2b0d8296325c07442b44dac6a0c7e7","libgit2/src/CMakeLists.txt":"7db897128511c4646ccd2e7e657e000483d506d7c0806233d66ba5007cfce7ea","libgit2/src/README.md":"acfbe0a4ed6cd7d806b30582cde06b871fe2b16f5a9eec3af717ff819030c6d3","libgit2/src/cli/CMakeLists.txt":"87d87cb6440f0efe0341d16dedb754a460364a8715f0c40e8594ffc2ac9c06fc","libgit2/src/cli/README.md":"84ea472e6be8c7e14558749a6b9207b8acf45ce78ce2278a525813d6c66c09d8","libgit2/src/cli/cmd.c":"1b7ec8535865b00b3fa705c9afc141f013696da493c63bce065a8070572b7d56","libgit2/src/cli/cmd.h":"3167f21423f29220c77e754509c45697cf14683b78a9686e61d18a5848852d93","libgit2/src/cli/cmd_blame.c":"bf413b163796058d86ec3ddf9a416bedaf6beb913a57e6748727b54668aa8f2d","libgit2/src/cli/cmd_cat_file.c":"9dede87d869a3cab92ad6ec80131c7c1949479bf20e4990aa72808e065553602","libgit2/src/cli/cmd_clone.c":"70b26aeb066f5e45f475fbdca2658dca59755cba7b960547712c058f79339a92","libgit2/src/cli/cmd_config.c":"143388bfcc4e0daba623f74fda0fa340d78b43fd2eb9e862fd3ef1cc5fa72a27","libgit2/src/cli/cmd_hash_object.c":"c001187712655693fb3eca074e1e62cb2871c872087bebc8e47ee25abcc3235e","libgit2/src/cli/cmd_help.c":"686da2d4e168a84d69c8a252a5cb48b7376fd26c1d4b979bc687a38dd60892e1","libgit2/src/cli/cmd_index_pack.c":"3285f0fabf2c136eca8b1d3d25efe8ae12e5b39da6953379a229d3dee3bff473","libgit2/src/cli/cmd_init.c":"3ae629e46362a9e1e5ce18661e14752bf7a0d8277c002991a1d7e76d15090c1e","libgit2/src/cli/common.c":"82a815a6fad27a231c8f7370d84c94ba4dbb6287b601a1ceb077ee80e9861560","libgit2/src/cli/common.h":"126bd9b643f68209cfa0fc0c77125bf81a14ba18e677d6fca604d0458b1c54b5","libgit2/src/cli/error.h":"ebd8eadd5527dc381acbd08c45aab5a21e2d4d2beff0a4baf462389b1cb0aeab","libgit2/src/cli/main.c":"a66f33d50fe852e901080476e79a42c29cf9d0eda9238c20f417e9054448ef5a","libgit2/src/cli/opt.c":"025483e0666aaa8158241ee0b4c06b632e3d10e2e60ccd4e0cf137629fe3b53d","libgit2/src/cli/opt.h":"f56c0a3e1b624b695083a3b88b8cba2f2c0c80871bd447cff1bb18ce4af14d4d","libgit2/src/cli/opt_usage.c":"f2065d08e19f46aad0b9ba8eb336297fbddd89b7bd3ca990d565fe92925815b7","libgit2/src/cli/opt_usage.h":"7369f7f69e9ada3da113d861ed000d235adb3d2d335284bdc9a6036fd51ed726","libgit2/src/cli/progress.c":"29944809d3c1ec31bd0891ac6b15697d227ebaf371099b07736f52e3f5b5a59e","libgit2/src/cli/progress.h":"c3027b4e1e4ca439009e2b692ad5702966de62c6a84a58ccb9844ea22b4496d5","libgit2/src/cli/sighandler.h":"4ebd5db9e9368f8001bffd2e43f8cd7e2ba7428d0a56eea8255c1d1252c50d88","libgit2/src/cli/unix/sighandler.c":"76509f4c00d99fdb9fdc275a5be2ab0e45964340a865d723a7359e094df9b674","libgit2/src/cli/win32/precompiled.c":"4dff04101bd64b95c8f708d1accd1bedc39e95a263444290f796c63f4734d4cd","libgit2/src/cli/win32/precompiled.h":"0e580ecd400170374b474681c84817c8d70e416fb97f22d027be1d9698a63341","libgit2/src/cli/win32/sighandler.c":"56027bdf1bb5232f9bcb619ebfa56bcf3477122a86e592eabb8c0f1503ea93dd","libgit2/src/libgit2/CMakeLists.txt":"179602152cb83f3460eafb13e8e29bc8850346add521db11d60b0903f845f424","libgit2/src/libgit2/annotated_commit.c":"9672606a57bd3ba7e94872182187d0850a7e298528765b493358ae9f40c3af70","libgit2/src/libgit2/annotated_commit.h":"fa0d7abeb786002f70a764b0f08efbcd4b4d6133ed7d0e184d39c60a93df0e62","libgit2/src/libgit2/apply.c":"05adc90b841a2d440bb081dbab5485631d8dab994ac634bec4bc229a7d30c282","libgit2/src/libgit2/apply.h":"4b3cccfd8030ab006fe78a89bd6ded5e1d89f7122630da6efa792c1a5b6874ae","libgit2/src/libgit2/attr.c":"32969883dc55dbb71b08c75231c7266e75f24245cfd8b5b10dbcc5f11cf2e455","libgit2/src/libgit2/attr.h":"c940426d88f00d1510d2698897d5fd1b9270d91ec0c86a7df10b9d07f598171e","libgit2/src/libgit2/attr_file.c":"2011d17d836f990158c9e8e67a47823e69f2eab336fc3aab4a43f44dd2419d91","libgit2/src/libgit2/attr_file.h":"9240f1de4e650472dd3389eaef2e2b28e84041fe33d96dc4cfc8a4763406bd94","libgit2/src/libgit2/attrcache.c":"38f1c7dd23ca0caff8d513309504962d2d7dd49d3a86403e9b76c0be4d262b5d","libgit2/src/libgit2/attrcache.h":"71ece32af260911e20212d046b198af3a02bc68897c0b98d5ed9421f0f90e12c","libgit2/src/libgit2/blame.c":"d11bb0c374424ac31d6c24bf148185341631af219c482c195e2231f89ba491c6","libgit2/src/libgit2/blame.h":"f4bc967c877560bb56a5f297454c7f3f60437cabfd430fedcbb9993ee3e6494e","libgit2/src/libgit2/blame_git.c":"eb0045fb97386393986037a8e4a6ee1840ddc1da915e807e32666c981f0f2e18","libgit2/src/libgit2/blame_git.h":"9b813f16b93512d27d93648e53d1438d5b931024701273b5976c1da41868e286","libgit2/src/libgit2/blob.c":"5dba150f29f75e92dd68ac92736342fe751b5e0d2fcd724523a93dbf5561ddf8","libgit2/src/libgit2/blob.h":"0d8836e7d5d286e1f5c37e342ae83b4543930c4c07de652e8eaf431e4c760ae1","libgit2/src/libgit2/branch.c":"e615d2eb9a2853bf496204aacf1fe8d89f1dea31d328a5a0342a9e0aacbc2a8d","libgit2/src/libgit2/branch.h":"a7512fb6c578721a8d0c47a250fee9ddbbd08fa5c53460420d8158d39511e042","libgit2/src/libgit2/buf.c":"491511777e2c68cbbb6e350e469da80fd240286d71b953230e688b920474ae27","libgit2/src/libgit2/buf.h":"4ed1bd58f01790c6b8505b9ce3f1cca443e8952c64611a36516d9c5d1cb96ac2","libgit2/src/libgit2/cache.c":"f1b58f140ae2cdcc6b3172591a6fd1731b22ba5561d5f651cc6daa2297bcad03","libgit2/src/libgit2/cache.h":"14ef07936091acd0c058ace1ae7a9c0d69b262239a9932432bb36b97ad44ca5d","libgit2/src/libgit2/checkout.c":"8fc768f21766267523b0ad6d09a73e256878ab9118c9c7e3c21d8e2fab83adc7","libgit2/src/libgit2/checkout.h":"86cd4012dc0bf97df74fe49140ac2b686e472d5a930ae69d537b23cbfd2f1b3e","libgit2/src/libgit2/cherrypick.c":"d8370d2ff8abe50b9a4083079eb47955787c35bd62d00fb598736610897aed32","libgit2/src/libgit2/clone.c":"8d7d12fea4ab54c2d24da94e00bd63bb140160125b4e6154c43a957e6639811e","libgit2/src/libgit2/clone.h":"780109b39b33c44122aed97d58c4d86f85b136e6c865b2e82c9601e308ed5533","libgit2/src/libgit2/commit.c":"ab095f9ffddaf8036df852c523893a86eea9e0ee1fd28e22ce7cbff9f9373a18","libgit2/src/libgit2/commit.h":"1cd14919ffd28c7625fd0cff5a8e7d9250c5ff74370393484c92615aeadfd497","libgit2/src/libgit2/commit_graph.c":"93c808473a199cd9c45b912b46af091eb3913d877a7d310005edf177c145d4a0","libgit2/src/libgit2/commit_graph.h":"6911f4c532336cfce7dcbd359a85ba3d22a0a3e68c66d6e6e08088f784dcf079","libgit2/src/libgit2/commit_list.c":"398a42dec95f6257d3cb8d06fe93986a162a2fdc184d1592c6ae9159b3d1329d","libgit2/src/libgit2/commit_list.h":"cc616cd4e8206a95c6368d7c4f317855b09dfe324638f999e8f2ecb6db3c720a","libgit2/src/libgit2/common.h":"6c3fb69d1dd0a3656b76dccbae2f2ae11d67675c3695cf0de4521daa422c28ae","libgit2/src/libgit2/config.c":"3bd7e316d37585238c806d26430fd54cf5f0cff50720b418d1c526e0fca0c071","libgit2/src/libgit2/config.cmake.in":"02042970005b621d49b62945230242bb46eb56502fa948806287baa19f70b98b","libgit2/src/libgit2/config.h":"3322700eebb0ff80f7d81e84894ea50f47f517de9826e784dd48e7d89481134b","libgit2/src/libgit2/config_backend.h":"5573f855a3cfd354538bf117465e37d167fee4e5df35ec4cb091e675732026ef","libgit2/src/libgit2/config_cache.c":"628d762865d701eeb9658706b5414be2366155812a60cad1da5a888ec44125d5","libgit2/src/libgit2/config_file.c":"df8498bfa7de04f7a76b6be8e5f007b1826f3d9870f7749ecf70f85028b6e216","libgit2/src/libgit2/config_list.c":"7d2036e72f515235f62091c6acce48351c59c88da4375de59f043818c8d99e98","libgit2/src/libgit2/config_list.h":"ef65fd05e8ebd3e52a1559cbe2354af4b0ed15355152678c60dd751d5be9c247","libgit2/src/libgit2/config_mem.c":"58fb549a3064776d40e4765d44fa5149d7f1d6bb3645b7a2fa40ed5296d6cf61","libgit2/src/libgit2/config_parse.c":"3f0923957f5f1b01f3d90244792d8eadbe2d2c4ef5ec1c2154f1745c7b6b6352","libgit2/src/libgit2/config_parse.h":"ed2e0138e13fc0115fba047c80687eb20778984bb2ee13c261ae69893e11e5a9","libgit2/src/libgit2/config_snapshot.c":"80eb0c23f4b8b0fc09bd7eec351f8099293c53c1b4f44fd81098b17da648931f","libgit2/src/libgit2/crlf.c":"2b5a392b269eb2af132f790a7764271dfd8523c47d18ac0f2d9fca1bd631363e","libgit2/src/libgit2/delta.c":"3e5d84b81f8fa3b752f75e0853a548ec3863ac3f1070bf99a9367bf6ae8ab87c","libgit2/src/libgit2/delta.h":"c757526292144083a0e96e7ab259080e83158e28c4819c4fa8bc2523aec12a59","libgit2/src/libgit2/describe.c":"f1a16c9c2e5f74752e1526a41f42c78ee4904b62245e0380a9d36e04d4dfcf56","libgit2/src/libgit2/diff.c":"41cb8c28752d133277f2448d7ac3968690cae653f93e7fd6cc173b3424682edf","libgit2/src/libgit2/diff.h":"6756796efbe24bc502dd337a9bb64de256d24a07e814254cf87808a753cc1cd5","libgit2/src/libgit2/diff_driver.c":"330b8718034a6a8fffae4ace4a4988a57b630474a208a08be57913acd6c50761","libgit2/src/libgit2/diff_driver.h":"f628f60d2679dd45dc7270fc0e8fcb271b4286cc1b13dcd0eab80df1d98be1b0","libgit2/src/libgit2/diff_file.c":"9d6033a915d9c4050d19f3f6d0f1e34e93650f00908cc247c0d2c512d506a248","libgit2/src/libgit2/diff_file.h":"f19e2a17d089591596325cfede708846c8df05a711e349ff84394db4af560c1c","libgit2/src/libgit2/diff_generate.c":"9a6fb642c4d624bb8d91ac2ed62ebe4becfb1015ee6783e32472aed53ca080c2","libgit2/src/libgit2/diff_generate.h":"a856792a6febd862984ac01bd41f998a848a60cd5d72b4c04a94099d3ffc5c6b","libgit2/src/libgit2/diff_parse.c":"5d7801826eb978de9f668a0350c783bedc408b2eb8b0a0176fc66d5d8d8bd062","libgit2/src/libgit2/diff_parse.h":"8902d9ba9102f10898c14d0a41a8d5823450527266908cbbb06e676309e23f56","libgit2/src/libgit2/diff_print.c":"0ffa654c7544f160c0887078091a5f2f255b8a9840be1df99a5009305cc2a0f0","libgit2/src/libgit2/diff_stats.c":"63e5e55d9f59992927409b3fafbb2c203a4098e84b0b747617e1a53a327384ba","libgit2/src/libgit2/diff_stats.h":"4ce359d523ffa03df7c0592ec0b905dd693054b44f62c4d1a91af464ace119dd","libgit2/src/libgit2/diff_tform.c":"dc65829e9abfccbaabedddf04ce84e42e34cf7968c8bde42e137fa3b7752e67e","libgit2/src/libgit2/diff_tform.h":"a4a7433036cefffaa9d968ff45244afb4957313cd9c28980cc102f172f9eaf5a","libgit2/src/libgit2/diff_xdiff.c":"6980509ccc58b82b36c0ea42e319c402a19002bbe59c2c4ad5e7accec4cfec44","libgit2/src/libgit2/diff_xdiff.h":"90cd3845e8da92354752904547ec9e53cee328f9cb2fb43e554e7d7047f6e182","libgit2/src/libgit2/email.c":"faf57f6ee54c8d27463a0a01703f2e4f746b56d3851d38e897ed5b06d3d134f3","libgit2/src/libgit2/email.h":"6b4a9dfb85b367e3423c2967f9cc257cf498fb9dd973c4400cea2be183065d2b","libgit2/src/libgit2/experimental.h.in":"9675b72f4b942cb66c2d1bb2c39e2d8f3c2c7ec562c456c5fa3ffc3119e0d900","libgit2/src/libgit2/fetch.c":"151943586ce55f9d0e654220d6b7cf07f940cf5961c21d4543ba7f6531f0b9e0","libgit2/src/libgit2/fetch.h":"e133482c55b6245e18cb64cf9b4f0afd308202c4a56e315631ba2a2cbc7f9f03","libgit2/src/libgit2/fetchhead.c":"ae489ea30536a2fb55dd24e69c3d0f4488d8967f783c0997e8b0db7377171122","libgit2/src/libgit2/fetchhead.h":"65681769629f670afcf739d582bb7ae90f702f0c6085de3f26b79fb3293d1dc7","libgit2/src/libgit2/filter.c":"703a2fed473ffc81b8a1c1f99ef294a40068bd9342c74190a25b31d6404d4e73","libgit2/src/libgit2/filter.h":"b716cb38e4af7b9adca4e9b1538eb546ebf15f279906561fa8fa504bcc62ed24","libgit2/src/libgit2/git2.rc":"28d3ec420d917a93ec62ec83f5fb8a4bfa988c4a42409ce9a2fc4aa241029fd5","libgit2/src/libgit2/grafts.c":"e2d6347db7e82258f50594e727e8855df5c5e5d2cafdce2c6b5fafffe99bcc71","libgit2/src/libgit2/grafts.h":"d77692a9dfddeee0754e80add4a7f435a20f75dfe75a03e40e584731ad01e2e9","libgit2/src/libgit2/graph.c":"929811ed381a0ef69f1181b09a61b8e08398c49bc16b8bbdb926585a675fe384","libgit2/src/libgit2/hashmap_oid.h":"a297bf7971f2461c09853775a1bd5320be7b4c228ca8c480e9e7eaa242c7666e","libgit2/src/libgit2/hashsig.c":"fbe29bf41024a9bf9b556756a23bea451d1ca2aced680fe666d24b651a719a7a","libgit2/src/libgit2/ident.c":"5c14c2e3bc8899244018645089cc2ee0e3786bd538434cffebc25532500eecee","libgit2/src/libgit2/ignore.c":"0e5be19897672f9815879010a3331e6a3f0cbdc2261a0c7cc9953c6f88ff81a6","libgit2/src/libgit2/ignore.h":"131aa84f9e474111db0f03797969e99493e67ef287cf8801606a889765e96ece","libgit2/src/libgit2/index.c":"a524e6d8c90522b1e75e11b9d7f914d66c0ac090e2a54684db3c2686581ca730","libgit2/src/libgit2/index.h":"a8769ffb64f8347f6a33c2a5679ffadeb95fc85df2403d4151fb313e4995c520","libgit2/src/libgit2/index_map.c":"9c47ad9f6b75812ec18b96a37c3dad104c4abde464236cb0310526b73cba2201","libgit2/src/libgit2/index_map.h":"799ef3dc0f4c99b8f126397481f6ba0b11904d9f25b6f6cf62826f97a8eb80b7","libgit2/src/libgit2/indexer.c":"fdc1463b01b76f7d594ae0cf6a5383296ee3158b653e9da71b46aa73e00ed8e7","libgit2/src/libgit2/indexer.h":"bd32fd65a3a7c6014e3e9846477b060033102c8c7baeb097506074f99c50a434","libgit2/src/libgit2/iterator.c":"5f579f125f16242c9dda2a28110760eb6dc6df424fcdc73a88442cb1b340f7a6","libgit2/src/libgit2/iterator.h":"5b2e297b9746a37110b2113a878564e3d46705735e500ad7e77bdca9541e85ff","libgit2/src/libgit2/libgit2.c":"a633bc64d5788f829d7f248bc1523781aa788bad1883e76b9bd4c807d2fc413f","libgit2/src/libgit2/mailmap.c":"fd2035a692293ca3111f115cc6dfa0974d7a26139790c3103d244d146cd62585","libgit2/src/libgit2/mailmap.h":"edd8723b4c861c855708f2d7f9ed5e37cbb7523534349b0f69258a3557b93b36","libgit2/src/libgit2/merge.c":"8775ea5fe68db1824ce0f04a516760d6d44c438f680b1057c66a98ab174b2285","libgit2/src/libgit2/merge.h":"ee2d6ebc3328e33115a69f60f0323be4fcf7a586a6308d76b5d6b6451a2e06dc","libgit2/src/libgit2/merge_driver.c":"42e8d0bac2100b9dd3b8f73ef2118db360f3680e884f8594f37af25471e37fb5","libgit2/src/libgit2/merge_driver.h":"4f56c2965330a5cb08b9f26d6b83dc4e15fced9419540d2d793f2e75049bc121","libgit2/src/libgit2/merge_file.c":"11e61c5320eec5290d76efc3b808e08de722cdff6f12612ca76983bbc6f8848b","libgit2/src/libgit2/message.c":"12b4d518b4f77b20d76e6b7062f56ddc7a7a666ee97f7f33909c9010ca3b5b0f","libgit2/src/libgit2/midx.c":"ad3c612a22ef17a4efd58d52e98ba5489afa6ce41c87f727e46a4e0c4e6a4869","libgit2/src/libgit2/midx.h":"e120c7c79d150095fc32add058bc82e3a7403cfaa84ca4d32994031d353194a5","libgit2/src/libgit2/mwindow.c":"4ca1ada058b4b1e7cee34ded71bf9ce2fbc9f087d7c65dde448ee03ee2a22191","libgit2/src/libgit2/mwindow.h":"2f11d808807b9eabf99f8f70309f51b216f1b127d4f6559b238bab20541ed8a4","libgit2/src/libgit2/notes.c":"974285fadfff6caa5bd79a903689853de9cd2bbc3ab55ecce74bb5c845a6c38a","libgit2/src/libgit2/notes.h":"650f92bbf875ab194b9e1d041f06fb8332bf5f402ea49cde528a81d2eac05694","libgit2/src/libgit2/object.c":"13de0bc0d5bf6ba0bd3c0a354e51b1e26a51824865b0b01551412af46db19be5","libgit2/src/libgit2/object.h":"b0b160cf112a26d4edafd937ba016e8a54f5654184b622e5c6b0a42e7ef461fa","libgit2/src/libgit2/object_api.c":"ac963762a903ea36adb20f0d4317388159c23828a6e26e9a1b1333b7a9fa1317","libgit2/src/libgit2/odb.c":"fbce4561920638766219299ae55167805f1d7d496bacf6032f643647ceada77e","libgit2/src/libgit2/odb.h":"505d85dd41198f41da28cad298eb880e4a671d281756de0d8205b53ab40f1106","libgit2/src/libgit2/odb_loose.c":"01e99c92d96eee62de939acd4c8027df7e574b0fe6a6bab09e8befa12f6e27b8","libgit2/src/libgit2/odb_mempack.c":"f5ecbf377f03b7cce05912ef6704739ce080b896b7f6c6fe2059c46aad96bd1c","libgit2/src/libgit2/odb_pack.c":"c66bf4e1d9d5be5608d0076853c3a8826843f56aa69c63f0c34108e6970f4d69","libgit2/src/libgit2/oid.c":"5a7db6c5b20fdc47ae1016052abf8bd858ebd11df8aab47f0cb2143a905c69ba","libgit2/src/libgit2/oid.h":"ab449b781a4c818a38325729780263c70359ce4b8eecd13ccf3d21e21eb60005","libgit2/src/libgit2/oidarray.c":"97eb0acabdaded7927caaa15b4e46571a8ed5e76423a5e6f9a6134f3fae4a86d","libgit2/src/libgit2/oidarray.h":"c109a93dab1485df8adc272db24be0bb6e07f849002dce2c55ce3e03ea138c76","libgit2/src/libgit2/pack-objects.c":"69012808e14777b49bc7d29e4b3a3f5c86df87c29b010ec645da40f3f318dd25","libgit2/src/libgit2/pack-objects.h":"9a833982603d33402224574dae2d840b5d2ef8d56b878d9090ce3e7f6721dfd5","libgit2/src/libgit2/pack.c":"ab8d2431d1e531d9ef848f845b5bacaf1da039f8893f80a191b782380ecef550","libgit2/src/libgit2/pack.h":"fa11f85657130b655b94ae6bb00811c1a5aa0162deafc4de3eb887f7df380e43","libgit2/src/libgit2/parse.c":"ae1738e409c0844d74cd054623195727a725505de8e3284d12f3d3c9e98f3f0d","libgit2/src/libgit2/parse.h":"45b8d736b9b103a6971b3dc3d95e0300a0384c9a62a6916000e1cc149b5294d1","libgit2/src/libgit2/patch.c":"48eceeb2b8fd25f24f830f7abda25853f4ede673b38698b671a9aac8d84562ad","libgit2/src/libgit2/patch.h":"05d7a5336612380fb4850aea817750a163fdf9dfbf5845cb81e9e2246d2619fc","libgit2/src/libgit2/patch_generate.c":"b64154b5b9b0ea69c90e119a47a24c18122055c53926eb6b437f9b59d383d450","libgit2/src/libgit2/patch_generate.h":"c83a9d70e860b13940f70140199ee40e8cad310350a764e726672ed7133e2999","libgit2/src/libgit2/patch_parse.c":"b068961f082fc5906c6658171f37b895e55c429594e58dfddf28072278fe9bf2","libgit2/src/libgit2/patch_parse.h":"6883a184830f4c59427177eba5462d27737706a1be899db35423c5ad9d6c8c4a","libgit2/src/libgit2/path.c":"c009cf85bbc8ca3ffdeb5cdc62362e368ef211612ad550bdc6dceabe988d6f16","libgit2/src/libgit2/path.h":"e5a2b8a9f717ebeafde09b3fb0330eac85c9d52213f334fedebaffefbe3575cb","libgit2/src/libgit2/pathspec.c":"b3e851575462400cc55e2d0e911c88f8e60c7c7b696920015c57329bb76d1d93","libgit2/src/libgit2/pathspec.h":"ab2ba851d4cd815aa25a910b792102230224ef7bb079879277d77f2984fe64cd","libgit2/src/libgit2/proxy.c":"2e979107904bc593f4d0a4a911a20efbf0956ab3441e21b10eff8661c8c7fc2a","libgit2/src/libgit2/proxy.h":"3758a64bea3691eb59a3c4d0bc70f7e1660b2a7f52e33513b03e9d7dc02bb617","libgit2/src/libgit2/push.c":"0c592ecedb5bc419df01e3650e4719c608f4d61321ae40ae845d6f204da22edd","libgit2/src/libgit2/push.h":"e7e9b90154bdfc624cd43e41f955ad4824567d5bf2b9589dd052f181f23d350d","libgit2/src/libgit2/reader.c":"d3d41922e7935be996d33ade27b471512a9e35f3f0468c6dfe5a6fe679751e9b","libgit2/src/libgit2/reader.h":"de0410d529d888feb13a8db4221e4d73f3575e3c815e6bb4ab9a4caf4d822e32","libgit2/src/libgit2/rebase.c":"1afe5afc9b1f9e4508109422a441ac970903c82a9ca708d297536e4467dbff63","libgit2/src/libgit2/refdb.c":"40cd4c55b0d0296bfa674541fb16936cb7c5a785be9afdbfca5e96b54adb7424","libgit2/src/libgit2/refdb.h":"ad8127049a89e43f49ffed64e82ee343e7c8acee31f7cb900b555193667cb99a","libgit2/src/libgit2/refdb_fs.c":"6ef130be842461dca3acf9082c408de3144ebe7cfa041b7de18af3d2914a2a81","libgit2/src/libgit2/reflog.c":"30b898d5c35265d1624ce947a27ad956fa6406e8446f26186d061af522157b12","libgit2/src/libgit2/reflog.h":"cb143a995aeefee11d3da15b4e6547f269d671645fd9b1c786abb8fb2276119d","libgit2/src/libgit2/refs.c":"e394dbdbef8a494a442dd1867e1e2dd53fe682988a02ac77edfd058a96af8606","libgit2/src/libgit2/refs.h":"a6fa957bcbf3116bbba96259db1fcd7c6dabd3cd0f556f723e8ddd77d01b02a0","libgit2/src/libgit2/refspec.c":"72d5238dd530fd0a77d7989ff80e465a2e2bc3a2347d0447ad77d1619d8a81b7","libgit2/src/libgit2/refspec.h":"80c4e67c0a3078ac8902ed294327f37948a10af7123d397c90bc58f3d98205af","libgit2/src/libgit2/remote.c":"39551c4a4edb9b42ff63c3e2973a7dae8fd4866b6fd2af17874e1baea9debf41","libgit2/src/libgit2/remote.h":"0746f3f51138a42234eec42ae5cfa417c05b641c514103b407fe602e2837d7b4","libgit2/src/libgit2/repo_template.h":"bec227c595d193802723f81765487da76beaffafae40ec05b76a4db7de153c01","libgit2/src/libgit2/repository.c":"2d7ce5f5914816dd369c5336ee0e19fb11d7a0b9c3223696006344b26e133852","libgit2/src/libgit2/repository.h":"bb743b720936fe2c0e6b4e7f76e23e86df97b5629f9293c4a8a8f5954bd4c63d","libgit2/src/libgit2/reset.c":"415f1163f1348ac033cdd45feb27097c8a698047b678b94ff1656899248948b8","libgit2/src/libgit2/revert.c":"5fb9db8b9d79a21a260967215ed02c88b49897db88cdeaef3dc292b72ae643f1","libgit2/src/libgit2/revparse.c":"0768bb468d0f39247df5fb269bcd80eff5d8818cd9efa999e8bc03d982ae8bd0","libgit2/src/libgit2/revwalk.c":"9b264bf60344cf5b5386e17cc1262b2088518f5e0baba2bcd6a22a92bc6fde4e","libgit2/src/libgit2/revwalk.h":"b79fb6a2b90b708cc8f4f951e7128eae01cb30d91c84ebc0b5539958c1e20ddc","libgit2/src/libgit2/settings.c":"ced3f9b63888f2ae93fa226ec795f2958ef9f1069658849f90984076ddfcddf5","libgit2/src/libgit2/settings.h":"be6c7b556e30b676f45f6653e1b0311958ce58f03f54cab39ba2b0c30838be54","libgit2/src/libgit2/signature.c":"188116fbc3b74e206516525d39ded34bacb4a58e3b7fa107072f1ac58f2e4342","libgit2/src/libgit2/signature.h":"612835d2c5067740534d2c26664b8e38fcae2db3b4d7c584c248bedb8bca399d","libgit2/src/libgit2/stash.c":"00bb03f18903f844618ce2a7bf8e3eb82374d387919af9994e0d3c5f381d92c3","libgit2/src/libgit2/status.c":"b864b001ad0ab0057f90cea2f0d947555700580e826eccb910a2b889a8555fd0","libgit2/src/libgit2/status.h":"68ed612f65430563ad5b3f50973b360f583c5865e54c9b9298eb082d441c4e79","libgit2/src/libgit2/strarray.c":"94987bed6dad5529d2020d2be626b3c99cc93df1b71e081388eeb267518716b7","libgit2/src/libgit2/strarray.h":"a406e07d6100e223cf1faa06ec8cb1e451bba75bfb081cc4d2fc737a6d35243a","libgit2/src/libgit2/stream.h":"a7755d211e19ea4a29d7d6151f71efd92bb92906d1668960e076ced663961784","libgit2/src/libgit2/streams/mbedtls.c":"940f300bbcde4f133cdb6185d793f39060f50db772ac4f6d0e273e44684cbd54","libgit2/src/libgit2/streams/mbedtls.h":"4aab96dac336790b4b172a7f355eb3fa6db35d31765edfa6524c581c10896ec3","libgit2/src/libgit2/streams/openssl.c":"9f123ff490757e23cdc5b93119d79507ed90edb64ce9257635ad69676c0df4b7","libgit2/src/libgit2/streams/openssl.h":"39379d387e6b07bb83f6ec5602da4ca7bb7218c85c1f18ce61ed3353ce3c4d7c","libgit2/src/libgit2/streams/openssl_dynamic.c":"3ea7fbd6f938f63a08563d953deb2a61c1fc1afca0dfffdf7f470b478b112eb4","libgit2/src/libgit2/streams/openssl_dynamic.h":"51b1485e838f06146553dd7894c90d9be6d80211ee29a72ed018553ce10b96e5","libgit2/src/libgit2/streams/openssl_legacy.c":"1c0643b0ea8cdd9d2f37dda38d777dc6aa6d3af8c631671f413da53b62470066","libgit2/src/libgit2/streams/openssl_legacy.h":"5a0f3da348dd5fb0cf4ddf7b9f65234bb5cf7017dfb084e5aad48e8d33d818a3","libgit2/src/libgit2/streams/registry.c":"079e2c8807d0cab10ab4363599e8a82e31042ba5ba2802cb52cdca0afad8222c","libgit2/src/libgit2/streams/registry.h":"42a887dd1fff029efa00a04a4e8716905149d3639a6881dc53254170cb8e18be","libgit2/src/libgit2/streams/schannel.c":"5bb78d33ef0be34431bf525384b7a7c0ebab3b7a13a68023ff6b83534e68ce5c","libgit2/src/libgit2/streams/schannel.h":"34eb7f2a0f56c80fef790cad5d50916cf9222494ccd7ccb129132cbbb9a66aa7","libgit2/src/libgit2/streams/socket.c":"5e595d05c71967de79b9e516ec9664e10e51067b89c9a7478253d61084f2fc16","libgit2/src/libgit2/streams/socket.h":"59cd164dec6960d8af55859b0d1504b29c2b29f489618fb57f81e57ed3de9ad2","libgit2/src/libgit2/streams/stransport.c":"7c2d6640ac8e16db85f1ad2e048fc66578a9451a66d4740007dbcec95fe28be5","libgit2/src/libgit2/streams/stransport.h":"01c4555417713c415de10ea16222d44cd9c0c0db4ad5d7e3d5e9863d62f49eb4","libgit2/src/libgit2/streams/tls.c":"3da24376a8e7e077e8aeefbb5c13e9e75444334f802185b3d2dfb3eb7d6be47b","libgit2/src/libgit2/streams/tls.h":"c989f0a996ba7a11f8732336da77266905ebbc371e5e5969955d096ae16b64ad","libgit2/src/libgit2/submodule.c":"6a54c3b701cf0cd28bff1abf2d7fcc074351e72254a0b519d5ff80af3cc4c4a7","libgit2/src/libgit2/submodule.h":"1d4bab3a0268fe2bbbb6fd4e6524727f2868923d3ce8341b3486a0b32707483b","libgit2/src/libgit2/sysdir.c":"bc7368efe6db818f64a8d8b4178455da7b8f8e28b157dc99ed95b094d3e0170f","libgit2/src/libgit2/sysdir.h":"a46088fb2ab6cfa011708576800e982123e9dcf6dbcffbae1ea1cb578ab0c8c5","libgit2/src/libgit2/tag.c":"52b5c50844db1ac4cd34fb802886d99f58f73bdd349c93208b85587d986059b3","libgit2/src/libgit2/tag.h":"9a1c517ed65f7f8576bd03aef9093d911d0dcb9a6d3e62510e38d3a52972cee9","libgit2/src/libgit2/trace.c":"f2e5041c5e688cf4e2c8ccc024ffa6a9c06b894cacfd1f967edfb5e11b513ce5","libgit2/src/libgit2/trace.h":"dc582e64181bbd55683b5afa6b400c9729a8daff22571c0ace7a3aada3b179bf","libgit2/src/libgit2/trailer.c":"6db9292ec295e18dd8b5afa9d02ecc61057a2c97017dcc64701c9768fb9d524f","libgit2/src/libgit2/transaction.c":"7d7a158835fb7b999c40cd990cd1973d44b92ea4f43534cb2a558ae56df5c0bb","libgit2/src/libgit2/transaction.h":"9f713178b226fa474dda766104e4387aa4c23d35938724b374eaf35bb8399919","libgit2/src/libgit2/transport.c":"0bf1b0fba69ed2594267833db264c210911324ce0cbed149a5b8bc1adb32cb5a","libgit2/src/libgit2/transports/auth.c":"e208690ebdec130e9737530a57835df13f5344906fbd9391aed1f665d3821458","libgit2/src/libgit2/transports/auth.h":"db03c74c487403b291248c7be2be837e673d6fddb6867a1782a6a86b3da8d410","libgit2/src/libgit2/transports/auth_gssapi.c":"b572e5aabdc25c1f98f0eac6e558196d2f8bac51cba8c5541cd778b8e84f6d1d","libgit2/src/libgit2/transports/auth_negotiate.h":"9b0b1046193596bf5dbac17eaf94e51ee8f67882f7af8fa099d323cccceda0d1","libgit2/src/libgit2/transports/auth_ntlm.h":"2eab6b8e47b975afbaf721437ddf05d238cad3d80be98ba6d38861bc476f2ab5","libgit2/src/libgit2/transports/auth_ntlmclient.c":"75488a8b39303f0d34a82fc653be8dafc66148e4b064b269f2736d4c189ffd37","libgit2/src/libgit2/transports/auth_sspi.c":"69e78e40d30c16a6d51d23344153113c8b9d4803bcff5c87b65dfedf2d21be93","libgit2/src/libgit2/transports/credential.c":"480f5e35438cf567fecbaa6ae4819725b6c90664f1a1bca20ab2e9718a6f5cd3","libgit2/src/libgit2/transports/credential_helpers.c":"e6ce81166b05d5f66c74c24086ec2025758ced7d8b85b041e190c2dab57e181b","libgit2/src/libgit2/transports/git.c":"723302003d7e77f7a659ac9e9f67c222c4875e5a251afb56c0d3feb52657511a","libgit2/src/libgit2/transports/http.c":"5ae353a7ec87004ce3c195506d7a8ffc8ff93720c3507047b76887a45aa38c1e","libgit2/src/libgit2/transports/http.h":"94e51b28d536bede476bc74b08acef383736e5c2b728459b5fc29760c3da96c1","libgit2/src/libgit2/transports/httpclient.c":"799b5b4806c89bafed2fd1f3d3203df43c7544c83d3e6d01b6e01b0d68d9565b","libgit2/src/libgit2/transports/httpclient.h":"8977ed1e072bd38ee12a42f31907696e0f69c8fcd1a4ed828f9fe7f2ac6903f1","libgit2/src/libgit2/transports/httpparser.c":"eabcf32232ad130c00bfbfb9fb0da4a1d2430459b25d894b53e534c2e6626f0e","libgit2/src/libgit2/transports/httpparser.h":"ee5a08ba448744f5f6dc5738ca43668afbe908d78a5dac2ab9cdae5e9f8024af","libgit2/src/libgit2/transports/local.c":"c0b77a798f73c96a40ae52dfed051a3c34d2b5b7d20b7005d04629f92bbc85c9","libgit2/src/libgit2/transports/smart.c":"28649d6972aec5f2a19343749a316fc6dbf5ef2e6ce26ce183b385c55cd789c2","libgit2/src/libgit2/transports/smart.h":"e1b33350076338b2eb37b0e08fee522893d7ab1fc592743c99c4c0e810542a21","libgit2/src/libgit2/transports/smart_pkt.c":"5be6fedfe4583503b9a0455c49d4fedb25261a85d04ee6824a844c1916652aba","libgit2/src/libgit2/transports/smart_protocol.c":"85beac2c67f766863e701083b4aae3c747b56e23fcf72b70c297845f7503fb7d","libgit2/src/libgit2/transports/ssh.c":"deb2355ef48566d3075df8652f2e6ca1c20331a1a5b62229925a4e89cd0b469e","libgit2/src/libgit2/transports/ssh_exec.c":"b5264b515dbbcf47e5ede81fcd40345a81d423c4d67b8215544f04724db93714","libgit2/src/libgit2/transports/ssh_exec.h":"2774dca45f7267272d4b5e354cee69f464ea323c580dd638313a55ef96718dbb","libgit2/src/libgit2/transports/ssh_libssh2.c":"6fe6117d0109f639d1b371941d113e7d771b26fdf43401fc626654b83fc51d83","libgit2/src/libgit2/transports/ssh_libssh2.h":"cb3202d3ae34a06b380f1778e13c32b40fb86a3113c11ac40f43229fbd304b97","libgit2/src/libgit2/transports/winhttp.c":"6410ba0a7dfe430e58505b643ab017a29a002ce2d886262a340103599b130e88","libgit2/src/libgit2/tree-cache.c":"c99ea22ab8fc2bfc85b762c1792f9a377da757a292ea245d74e444da189d7cde","libgit2/src/libgit2/tree-cache.h":"81ee821b7d1a95b6beb1dbb2e2f51ad7339ecdb97ad99abe4fd35b9be0f7e54e","libgit2/src/libgit2/tree.c":"0754361f28e01c019ab604c82f5b01ed20560d0efbdb01ef8b71ad729ad5fa5d","libgit2/src/libgit2/tree.h":"f2f3be4c1dad7ba9b69aa43543e8463f05dddc25f270f26f7f65011e02cfd1cd","libgit2/src/libgit2/userdiff.h":"f623acbe67ce809a21541d0d665536f68df9e0ed8a4aa4556cbffd070960fc88","libgit2/src/libgit2/worktree.c":"4bfb0f4432168363189af0e828ae2d64cbc064afc2a1b2cbe11ad7947d57eac9","libgit2/src/libgit2/worktree.h":"6962d0da3dc1ff1e967672fcbe84b8b09807924521e5d113df811ebee8e02664","libgit2/src/util/CMakeLists.txt":"b701235a39f8d750fe129677c22672c615c3ceb70e5e86d70b3d2632370d0048","libgit2/src/util/alloc.c":"d647f270fdcaec18eef23a64adeb2b73ea89e4cbe2d06b7205cd999cdc24dd42","libgit2/src/util/alloc.h":"71bb23ad8325f9c90b9bd5cc2e33c29d6f30c7f6e69f12df049e621a75d5b921","libgit2/src/util/allocators/debugalloc.c":"f3f30085a454bedc2d632dd938e8e986d0cef82475377cc27aabce24055c9c8b","libgit2/src/util/allocators/debugalloc.h":"22971098ded1e5bfcce6d24ece72ac64e62eadcbf5f096b5d3b4255c8cef3f54","libgit2/src/util/allocators/failalloc.c":"a5954443a6b20bee10ac45e5cbd6318a033ed8db05b225957bb4d02c387fc54f","libgit2/src/util/allocators/failalloc.h":"c4d7fe2b71894ccfe0571e779a6e00c11f0e4ae53de98492499f75e92ce72f6b","libgit2/src/util/allocators/stdalloc.c":"b7c180ffdb52e8c5bf5000b7e6fa66f68ecbdd4bddaaa9e56eab3ba416aead70","libgit2/src/util/allocators/stdalloc.h":"e140c3b240622f36d7eeea232dd41711fa2c01e8b557a9d3393a5c2b416a5891","libgit2/src/util/allocators/win32_leakcheck.c":"4f7a15ba2fdf29d739214e466c928adc31ffbc0f07b40036a94979126ef1feb0","libgit2/src/util/allocators/win32_leakcheck.h":"1de31b13678ea2dcdae5177f5cb1b7d2d7560ff4069b8f77f07501bec4979913","libgit2/src/util/array.h":"80c16c10150bab526850fc06c363cff4d4319ddd3627f7ad768d86d689c86fbb","libgit2/src/util/assert_safe.h":"0f2b8fa61e0dedbedbc6299618b98bc2c60dd78c386f2b9b8f7b8d747a2daf78","libgit2/src/util/bitvec.h":"281444c865be87104cff9c1b3998877a67bfd92af4b0e5b9b034fd48f6569f7a","libgit2/src/util/cc-compat.h":"c4807cd6963c470be476b3b2dd52b29b93a202db509540710ea32d81f6fb24de","libgit2/src/util/ctype_compat.h":"03fc885c9e4bd4a1b7b994d86702be50bba1889e3a6c47ab985c0d38005ec8b9","libgit2/src/util/date.c":"4324e7b1cdeb8364b7760f0f112fd89281095b9e2e67b77fd321907aa6ffb9c9","libgit2/src/util/date.h":"3d99d9140365e84dfb1240f14fec29dc5600728c94287616eecec02505dc3bce","libgit2/src/util/errors.c":"ffabe99d635d8dbbd6fcae5bcdf18dff990fcbf370af0e8e0f17b62227cc279e","libgit2/src/util/errors.h":"ccf61cde1b16ecdc843d9b5a0eba2e18deb15bab5d0877f1d9103b95cbc08216","libgit2/src/util/filebuf.c":"5ee4b7e2adae5ccf2b751851af8cde8762c473154dda4203fba2bf8080fbcfde","libgit2/src/util/filebuf.h":"f98eada1c23529ddf9a942c252abd5310a8e1e965c72b21d082a2a58cd552786","libgit2/src/util/fs_path.c":"f00858c426c4d680a6868af30386a1df99c27d45db5ddb975c1f11e79d50a547","libgit2/src/util/fs_path.h":"0a2fb2eff8adacc9985b1474592dfa50410b045d4ae81815ff43086a82f7cc35","libgit2/src/util/futils.c":"c8d225d2f335745fb9d4236b8c29055fbe0249fe23ef5c3d313162bb397a744b","libgit2/src/util/futils.h":"1e5d989463ea53e2cea0677ca2bbc975692fc61259a0566c111a65c3f4d7a038","libgit2/src/util/git2_features.h.in":"5fd9c7d8bd78459d7028011d3714f21344e8cf764a9e58ca34389dbc1b8a4b69","libgit2/src/util/git2_util.h":"f88550b3c5f9e1380714693ad0865c6f5e91b2ddd66f8ebf3889ae87fcd4fd31","libgit2/src/util/hash.c":"0c88b789d33f29229471a9dfba3da0a989214a08a8ea727582d81e7118c561ea","libgit2/src/util/hash.h":"6fc0c22c0a1ee5a26ef29c8512c951db23f440dad2b7a31403abc214d1d7447b","libgit2/src/util/hash/builtin.c":"fe213c6a61b923cbd3acd6e55322f4d60c531617f3b9d5d281d2050c6e0a9524","libgit2/src/util/hash/builtin.h":"bbf1ce668c7d38412a5c7351b41da31352f5eba696ed453daaf442e97c225f00","libgit2/src/util/hash/collisiondetect.c":"50be16f2b8736ca61bbe657751a0e66b847affd6030a582f3366c27659e5d245","libgit2/src/util/hash/collisiondetect.h":"21d7b15068a89ed1537a6cdb5d1a3b78e5bb3bba318839579f9b20aa796518b6","libgit2/src/util/hash/common_crypto.c":"241d19fef0e60f08189405bb8ef3426438505bea0752ac57f10db06be6dc8dcb","libgit2/src/util/hash/common_crypto.h":"5b89841130c9d4b09cf90ff25874cec68d18df3f4883ad74b15c408bbaf77b9f","libgit2/src/util/hash/mbedtls.c":"97b33e8b549e9b1da4ae558db570679feed0f91e504b339e4be697084c721343","libgit2/src/util/hash/mbedtls.h":"42dc9f2db495d9440f0ec5dcca33b28395be7bce55d2560c33cc3a4c474623cc","libgit2/src/util/hash/openssl.c":"6bffa802f0c6d3f9e89c0c048011db663c630933a4805b5be3fb348d68516893","libgit2/src/util/hash/openssl.h":"d20fe2ff5a8ea2023ce1e6db742743b17aea02e5bd83eddb241d71242603c5b3","libgit2/src/util/hash/rfc6234/sha.h":"137fbf064d7168c033551d8302bce635721cceb9423b8d4bd5182afbaec12af7","libgit2/src/util/hash/rfc6234/sha224-256.c":"b01cf69e8bdb01a83465ec0d6551633d97c96307406d1595887aeea3f5512136","libgit2/src/util/hash/sha.h":"11683cd719ff7185a248d06c7caddb2e6fceb1d49f4f03f349215bf13d0c3963","libgit2/src/util/hash/sha1dc/sha1.c":"fa40cc0830d58d340eb8942499181de72fd4cb4ad4c1d1216755b0367499661a","libgit2/src/util/hash/sha1dc/sha1.h":"78f97f092c20329d1fa8d9a8cbb3d53bb90be19cbc49f1917605a9ddf520de83","libgit2/src/util/hash/sha1dc/ubc_check.c":"7b0db83569ba82965dc0d16e51e9ad85167cdfdab343f9a02c2c475bfdd93956","libgit2/src/util/hash/sha1dc/ubc_check.h":"4a140693701da167b4709c4c1b330800a0c29f2a065d0d819567a27b3171a09f","libgit2/src/util/hash/win32.c":"fed73763276bc187e2f109eb4aff19653e5fc4fb092066a3be8fd02c9e3cb77b","libgit2/src/util/hash/win32.h":"43b90e70705dcfc28cd19b1ca2ef206a364db60af390d3dd73a8ec13d2a79e69","libgit2/src/util/hashmap.h":"bff15bebd2e7a995de36de1c7115f466be3074017f000601570d60f5fa357e02","libgit2/src/util/hashmap_str.h":"202f61cebe12bbde1858cb449abb736c6029d1d2cda528fb4ba00d8a0fa13618","libgit2/src/util/integer.h":"78c97ef23562d2bb46648272683186cd5b2e4671bb808745a0f08118ab73e3c5","libgit2/src/util/map.h":"f678e1aab0799a95a2152aa6cf6ef6b306eb783ba2a6b2b0e3df147e5596a917","libgit2/src/util/net.c":"422191d20e04f17a1fc20d41b35b4c353b0e72db448defeac1acf393c12229bc","libgit2/src/util/net.h":"72adee72e7ff998874869e71015728bc2849a2767bcc8a7cced64fdadf575609","libgit2/src/util/pool.c":"519fb7489c80b4abb2b842123f46d723088ad0bb11647448189601f242dda7ed","libgit2/src/util/pool.h":"3c19d4a3cfe5c97bebb3669c00ab4df1e999bac22b96e35dbe5a6db7066ead07","libgit2/src/util/posix.c":"a36bc1f5a1af765f383865666d2eaabf0347810e6b4cf39af538b26ea5cac17d","libgit2/src/util/posix.h":"a7f36bda0c34725cd657844e61d0e08367beb9c8088bdd8fd59efa6c221f7490","libgit2/src/util/pqueue.c":"d5cd8f6c5639b50898fe0f9354dbb29de1a0be1d20c879242c8423907466c7c2","libgit2/src/util/pqueue.h":"6fb6944e1d5200ddb837e24356e419f03586d5947193ff929c3a5980dc228161","libgit2/src/util/process.h":"b0477c92e923549f8587f631c4f5e965906711228425503f9d91d447f4aa7063","libgit2/src/util/rand.c":"1b374bc351c569dd3ee4566fed5dcb605563436ddaf3917dcb734375e2f0d08e","libgit2/src/util/rand.h":"102ce327cbbd6dcb9bdbe4c35addc7efa0095f335873860b06d85c4a070ebeac","libgit2/src/util/regexp.c":"2871d762d7b02224505309845e57c44e66e7e4db112d4cf91c4f9ec5b4b7faf5","libgit2/src/util/regexp.h":"855b271c6c8f5e1f3e5dc6648e9364d0448b2a9c1bc72cc3de0d1742e2905b32","libgit2/src/util/runtime.c":"b287e2f3d0a686b77736b725a86b8d6bea904b93c2f987513c608663b818a1d9","libgit2/src/util/runtime.h":"9aac7e20b2b879c49a423ef537bb0f51b8371c24503281b283b1fb74a8944f49","libgit2/src/util/sortedcache.c":"1c628c9b96899091117dcbaf81e4dfb048b6cff88ef58d855bbdccba423ac86e","libgit2/src/util/sortedcache.h":"e3255937db47e162df9c290cce9aef6030cc9d6ebb14128c568f97f52ba242d1","libgit2/src/util/staticstr.h":"d9d6abc1dd70f297f8c51ce23a52d8c62d43b306d05779d42a5bc1703eb11a36","libgit2/src/util/str.c":"cc41608f2c8e140929ea480170932f2cce61a2dd3e1199b3371d2ceb8d14a4e3","libgit2/src/util/str.h":"5c26b120517aa1b05ab78af401fa0e1f5848498100bc4204ca9f361451efec2c","libgit2/src/util/strlist.c":"5fd9b8d72068af3b7732e6e9a02bf84000748e6e50b24025a2a477c12d5824ef","libgit2/src/util/strlist.h":"1c3dfeb8e5e28e829a27dee01053500dbc32aea1f6c427953d7a53706f7a1eef","libgit2/src/util/strnlen.h":"27e73ccbe8be7c5bac1d022bf59f2458cc2998d0222e7658a687e02f89fcfd17","libgit2/src/util/thread.c":"6d741eabfe3739f6183e1d65935405f9fc457622d5b21978d4affdf6084e4fde","libgit2/src/util/thread.h":"a837c87234498a6d036fcbb84cddb4e9c28f73dac2f5572d0dbd2719330f2158","libgit2/src/util/tsort.c":"d1dee30457c185e86bc47efecc5417459aefeabe7cfaf8aebe5eb2239296ee20","libgit2/src/util/unix/map.c":"1606c6c48126c72040f985492b6e6bd7b5df27d384f6f5bea9c35118ef7bb2de","libgit2/src/util/unix/posix.h":"b6619fc5059c0759e2904cde66d879bfb0918567f5235026f0c2d7875a3d517e","libgit2/src/util/unix/process.c":"71641f263642687cf01b02b1b636282e89f2595038a47e63b9bdc872fec2d368","libgit2/src/util/unix/pthread.h":"c716daa88e2e7ef2a2df23591a6061965dc11d77ed5fe1863d367a2b738a9fb0","libgit2/src/util/unix/realpath.c":"41f2f5e03d021d2c981b325f7806e97669280fbcd944903eeab902095554c046","libgit2/src/util/utf8.c":"6cbf514d854524883a85a781e5e2a9003d71793fb2cd527795d26c972831a8ef","libgit2/src/util/utf8.h":"ca0239005ee004df1b2593aa727036a82f1ce3953000c3acf712b2639acd9206","libgit2/src/util/util.c":"35791b9a91e04008448360145c389374fa21296d8c90a99f9b41edf14794fc1c","libgit2/src/util/util.h":"07936486b65a55bcc6075eaf53984467a0edfe3d278af64a73f115f32d401a77","libgit2/src/util/varint.c":"f93c5ba3498ac04d98ba13d3a320263892452356f797c4091411e5833dfe82f2","libgit2/src/util/varint.h":"b429d5e8b69d579cc6dab5e12ab4acf904c66947b41ca5372dfc3e327e59f533","libgit2/src/util/vector.c":"438ce226d81796d0ac72fe5bd0427c6cefc98ed45dcbf1ecae5a56795ce4fec4","libgit2/src/util/vector.h":"345d074375a69c0111d44d493aa627fb297fdfad1f305b69f276eb9eab585e5b","libgit2/src/util/wildmatch.c":"0102685757a40046a5fdee4be5be784989a84d3b4be9160d48120c4485c37133","libgit2/src/util/wildmatch.h":"7d59454a8271f810622ccfebb26c8408bd85f64c99d4411028e8482ab2c333d0","libgit2/src/util/win32/dir.c":"a0490ab8fe3be9213093afca1923a0fc472d368f2907ab23a86bb392520359cc","libgit2/src/util/win32/dir.h":"7835a64f082860bee53530a381fe9d6917be39f0d756562e8306dfd78154d3f7","libgit2/src/util/win32/error.c":"78d4147c74ea5f040fc01add6d8f216be3593bf589814bb2a4748efea89d97be","libgit2/src/util/win32/error.h":"44175c12d291bdf80df65a41cf669708c252ec04c8e084c41777c7a0b53569d1","libgit2/src/util/win32/map.c":"6ce9c0a15df639d1d5b334685eeef03698b3ed006924e60b67461336fd7afc20","libgit2/src/util/win32/mingw-compat.h":"f7b0c7e9dd7147e8930782cdf54ce4be385172966dd1e27435446f38cd2f6d68","libgit2/src/util/win32/msvc-compat.h":"36e4c9515a8d53e70f78794826700c4a5472235aef703ac439308dd005e31454","libgit2/src/util/win32/path_w32.c":"9b1fbfe3907f3030dd065d2dea16d3ea534f5aed8c44d2709a8feeb0f93bcac8","libgit2/src/util/win32/path_w32.h":"de01a65de67423157b23202bcba550f4ed1d5de2ac0e06a4f2ae8177aa4319ba","libgit2/src/util/win32/posix.h":"4dd2fc1529fc7e625180b649b9212d83462c654e47ba799fa62353aed5f60e14","libgit2/src/util/win32/posix_w32.c":"4cb0cf6500dfb19ed11feb47e013e2ae06b0a04464a8e8ff27e3282e5a7b3fbd","libgit2/src/util/win32/precompiled.c":"4dff04101bd64b95c8f708d1accd1bedc39e95a263444290f796c63f4734d4cd","libgit2/src/util/win32/precompiled.h":"3f763f472fbf822314807b91ee9a2f88fe7f2fbcd165ee4e57f3f90e2715f14c","libgit2/src/util/win32/process.c":"b3e0cb393c876bee28a1ad794c4fd9a7c3d0bc022b12227d01ff9b5bab6afb5f","libgit2/src/util/win32/reparse.h":"ba254a97aba283930306f39f73e297d5eb30350276b3dd86deecbf10b4094c97","libgit2/src/util/win32/thread.c":"bce98dd6a635b66d811fab98b943ec448751a8b55c7261732277ca2804862fb9","libgit2/src/util/win32/thread.h":"8141cdc5c89901c2259a64c8f070950f69d4b742ed743ee1c520fd47b5b6948c","libgit2/src/util/win32/utf-conv.c":"7fc663799ef1f595c8438ddb5945aa71e9cf3b47ba2f626f017845af5eca7cdf","libgit2/src/util/win32/utf-conv.h":"61b3a452d6e79d03e5087885442a05c561a36ef5468575502c98bafb74a71cd7","libgit2/src/util/win32/version.h":"d9d9546728ee78923ba7ea1c16c000d44450ca80f8c0c3268bf58fa9966ba38f","libgit2/src/util/win32/w32_buffer.c":"1099be7c74b5bb265614787be285505e18dcaf71412607d8ec108639762a5b8d","libgit2/src/util/win32/w32_buffer.h":"a11005a0f3b2ecb3220ea9cdfd1df4b61d90f10e0e68ed2716b2f9502f2fa8f7","libgit2/src/util/win32/w32_common.h":"214cd67bcbdf89bb7effb78ee50c60b0504319117984c1a990f8301cffd78e0d","libgit2/src/util/win32/w32_leakcheck.c":"844ae1c7a959c8f181b45cc49a6f34262d03510f7748b6be7a159d7fd5c5e56d","libgit2/src/util/win32/w32_leakcheck.h":"cace8320ae9e8ef1d5b4836905a2d318e9e2a536ad3e232393e5f42b428554e7","libgit2/src/util/win32/w32_util.c":"27d9669fd679dc4d739c1a898028be6d154abe41f47ba7298c487956587e1c82","libgit2/src/util/win32/w32_util.h":"f052487c469e5ba2fd327e55db1721e8f3f8d8947872ac63c6a3591fe7768853","libgit2/src/util/win32/win32-compat.h":"5ea7b1837a159d66a89365ee2bf3724b32579a6a78d94b0b205d44c8697a8e6f","libgit2/src/util/zstream.c":"51e507d17742366b91e6f427a48b566b52013f06502c3f05fbd6f5120b3d6afb","libgit2/src/util/zstream.h":"daa41460cf0ed019ef62a1936fb18626e8abac2b9a05061b6a377d4ab74a4cc5"},"package":"e1a117465e7e1597e8febea8bb0c410f1c7fb93b1e1cddf34363f8390367ffec"} diff --cc extra/libgit2-sys/CHANGELOG.md index 0000000000,0000000000,0000000000..02f82b00d7 new file mode 100644 --- /dev/null +++ b/extra/libgit2-sys/CHANGELOG.md @@@@ -1,0 -1,0 -1,0 +1,194 @@@@ +++# Changelog +++ +++## 0.17.0+1.8.1 - 2024-06-13 +++[0.16.2...0.17.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.16.2+1.7.2...libgit2-sys-0.17.0+1.8.1) +++ +++### Changed +++ +++- ❗ Updated to libgit2 [1.8.1](https://github.com/libgit2/libgit2/releases/tag/v1.8.1) +++ [#1032](https://github.com/rust-lang/git2-rs/pull/1032) +++ +++## 0.16.2+1.7.2 - 2024-02-06 +++[0.16.1...0.16.2](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.16.1+1.7.1...libgit2-sys-0.16.2+1.7.2) +++ +++### Added +++ +++- Added binding for `git_commit_lookup_prefix`. +++ [#1011](https://github.com/rust-lang/git2-rs/pull/1011) +++- Added binding for `git_object_lookup_prefix`. +++ [#1014](https://github.com/rust-lang/git2-rs/pull/1014) +++ +++### Changed +++ +++- ❗ Updated to libgit2 [1.7.2](https://github.com/libgit2/libgit2/releases/tag/v1.7.2). +++ This fixes [CVE-2024-24575](https://github.com/libgit2/libgit2/security/advisories/GHSA-54mf-x2rh-hq9v) and [CVE-2024-24577](https://github.com/libgit2/libgit2/security/advisories/GHSA-j2v7-4f6v-gpg8). +++ [#1017](https://github.com/rust-lang/git2-rs/pull/1017) +++ +++## 0.16.1+1.7.1 - 2023-08-28 +++[0.16.0...0.16.1](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.16.0+1.7.1...libgit2-sys-0.16.1+1.7.1) +++ +++### Fixed +++ +++- Fixed publish of 0.16.0 missing the libgit2 submodule. +++ +++## 0.16.0+1.7.1 - 2023-08-28 +++[0.15.2...0.16.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.15.2+1.6.4...libgit2-sys-0.16.0+1.7.1) +++ +++### Added +++ +++- Added LIBGIT2_NO_VENDOR environment variable to force using the system libgit2. +++ [#966](https://github.com/rust-lang/git2-rs/pull/966) +++- Added binding for `git_blame_buffer`. +++ [#981](https://github.com/rust-lang/git2-rs/pull/981) +++ +++### Changed +++ +++- Updated to libgit2 [1.7.0](https://github.com/libgit2/libgit2/releases/tag/v1.7.0). +++ [#968](https://github.com/rust-lang/git2-rs/pull/968) +++- Updated to libgit2 [1.7.1](https://github.com/libgit2/libgit2/releases/tag/v1.7.1). +++ [#982](https://github.com/rust-lang/git2-rs/pull/982) +++ +++### Fixed +++ +++- Fixed builds with cargo's `-Zminimal-versions`. +++ [#960](https://github.com/rust-lang/git2-rs/pull/960) +++ +++ +++## 0.15.2+1.6.4 - 2023-05-27 +++[0.15.1...0.15.2](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.15.1+1.6.4...libgit2-sys-0.15.2+1.6.4) +++ +++### Added +++ +++- Added bindings for stash options. +++ [#930](https://github.com/rust-lang/git2-rs/pull/930) +++ +++## 0.15.1+1.6.4 - 2023-04-13 +++[0.15.0...0.15.1](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.15.0+1.6.3...libgit2-sys-0.15.1+1.6.4) +++ +++### Changed +++ +++- Updated to libgit2 [1.6.4](https://github.com/libgit2/libgit2/releases/tag/v1.6.4). +++ This brings in a minor fix on Windows when the ProgramData directory does not exist. +++ [#948](https://github.com/rust-lang/git2-rs/pull/948) +++ +++## 0.15.0+1.6.3 - 2023-04-02 +++[0.14.2...0.15.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.14.2+1.5.1...libgit2-sys-0.15.0+1.6.3) +++ +++### Added +++ +++- Added bindings for `git_remote_name_is_valid`, `git_reference_name_is_valid`, and `git_tag_name_is_valid`. +++ [#882](https://github.com/rust-lang/git2-rs/pull/882) +++- Added bindings for `git_indexer` support. +++ [#911](https://github.com/rust-lang/git2-rs/pull/911) +++- Added bindings for `git_index_find_prefix`. +++ [#903](https://github.com/rust-lang/git2-rs/pull/903) +++- Added support for the deprecated group-writeable blob file mode. +++ [#887](https://github.com/rust-lang/git2-rs/pull/887) +++ +++### Changed +++ +++- Updated libssh2-sys from 0.2 to 0.3. +++ This brings in numerous changes, including SHA2 algorithm support with RSA. +++ [#919](https://github.com/rust-lang/git2-rs/pull/919) +++- Updated to libgit2 [1.6.3](https://github.com/libgit2/libgit2/blob/main/docs/changelog.md#v163). +++ This brings in many changes, including better SSH host key support on Windows and better SSH host key algorithm negotiation. +++ 1.6.3 is now the minimum supported version. +++ [#935](https://github.com/rust-lang/git2-rs/pull/935) +++- The `GIT_DIFF_` constants have been changed to be a `git_diff_option_t` type. +++ [#935](https://github.com/rust-lang/git2-rs/pull/935) +++ +++### Fixed +++ +++- Fixed the rerun-if-changed build script support on Windows. This is only relevant for those working within the git2-rs source tree. +++ [#916](https://github.com/rust-lang/git2-rs/pull/916) +++ +++## 0.14.2+1.5.1 - 2023-01-20 +++[0.14.1...0.14.2](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.14.1+1.5.0...libgit2-sys-0.14.2+1.5.1) +++ +++### Changed +++- Updated the bundled libgit2 to [1.5.1](https://github.com/libgit2/libgit2/releases/tag/v1.5.1). +++ [a233483a3952d6112653be86fb5ce65267e3d5ac](https://github.com/rust-lang/git2-rs/commit/a233483a3952d6112653be86fb5ce65267e3d5ac) +++ - Changes: [fbea439d4b6fc91c6b619d01b85ab3b7746e4c19...42e5db98b963ae503229c63e44e06e439df50e56](https://github.com/libgit2/libgit2/compare/fbea439d4b6fc91c6b619d01b85ab3b7746e4c19...42e5db98b963ae503229c63e44e06e439df50e56): +++ - Fixes [GHSA-8643-3wh5-rmjq](https://github.com/libgit2/libgit2/security/advisories/GHSA-8643-3wh5-rmjq) to validate SSH host keys. +++ - The supported libgit2 system library range is 1.5.1 to less than 1.6.0 or 1.4.5 to less than 1.5.0, which should include this fix. +++ +++## 0.13.5+1.4.5 - 2023-01-20 +++[0.13.4...0.13.5](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.13.4+1.4.2...libgit2-sys-0.13.5+1.4.5) +++ +++### Changed +++- Updated the bundled libgit2 to [1.4.5](https://github.com/libgit2/libgit2/releases/tag/v1.4.5). +++ - Changes: [2a0d0bd19b5d13e2ab7f3780e094404828cbb9a7...cd6f679af401eda1f172402006ef8265f8bd58ea](https://github.com/libgit2/libgit2/compare/2a0d0bd19b5d13e2ab7f3780e094404828cbb9a7...cd6f679af401eda1f172402006ef8265f8bd58ea): +++ - Fixes [GHSA-8643-3wh5-rmjq](https://github.com/libgit2/libgit2/security/advisories/GHSA-8643-3wh5-rmjq) to validate SSH host keys. +++ - The supported libgit2 system library range is 1.4.5 to less than 1.5.0. +++ +++## 0.14.1+1.5.0 - 2023-01-10 +++[0.14.0...0.14.1](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.14.0+1.5.0...libgit2-sys-0.14.1+1.5.0) +++ +++### Added +++- Added variants to `git_cert_ssh_raw_type_t`. +++ [#909](https://github.com/rust-lang/git2-rs/pull/909) +++ +++## 0.14.0+1.5.0 - 2022-07-28 +++[0.13.4...0.14.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.13.4+1.4.2...libgit2-sys-0.14.0+1.5.0) +++ +++### Added +++- Added bindings for ownership validation. +++ [#839](https://github.com/rust-lang/git2-rs/pull/839) +++ +++### Changed +++ +++- Updated the bundled libgit2 to [1.5.0](https://github.com/libgit2/libgit2/releases/tag/v1.5.0). +++ [#839](https://github.com/rust-lang/git2-rs/pull/839) +++ [#858](https://github.com/rust-lang/git2-rs/pull/858) +++ - Changes: [2a0d0bd19b5d13e2ab7f3780e094404828cbb9a7...fbea439d4b6fc91c6b619d01b85ab3b7746e4c19](https://github.com/libgit2/libgit2/compare/2a0d0bd19b5d13e2ab7f3780e094404828cbb9a7...fbea439d4b6fc91c6b619d01b85ab3b7746e4c19): +++ - The supported libgit2 system library range is 1.4.4 to less than 1.6.0. +++ - Fixes [CVE 2022-24765](https://github.com/libgit2/libgit2/releases/tag/v1.4.3). +++ +++## 0.13.4+1.4.2 - 2022-05-10 +++[0.13.3...0.13.4](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.13.3+1.4.2...libgit2-sys-0.13.4+1.4.2) +++ +++### Added +++- Added bindings for `git_commit_body` +++ [#835](https://github.com/rust-lang/git2-rs/pull/835) +++ +++## 0.13.3+1.4.2 - 2022-04-27 +++[0.13.2...0.13.3](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.13.2+1.4.2...libgit2-sys-0.13.3+1.4.2) +++ +++### Changed +++- Updated the bundled libgit2 to 1.5.0-alpha. +++ [#822](https://github.com/rust-lang/git2-rs/pull/822) +++ - Changes: [182d0d1ee933de46bf0b5a6ec269bafa77aba9a2...2a0d0bd19b5d13e2ab7f3780e094404828cbb9a7](https://github.com/libgit2/libgit2/compare/182d0d1ee933de46bf0b5a6ec269bafa77aba9a2...2a0d0bd19b5d13e2ab7f3780e094404828cbb9a7) +++- Changed the pkg-config probe to restrict linking against a version of a system-installed libgit2 to a version less than 1.5.0. +++ Previously it would allow any version above 1.4.0 which could pick up an API-breaking version. +++ [#817](https://github.com/rust-lang/git2-rs/pull/817) +++- When using pkg-config to locate libgit2, the system lib dirs are no longer added to the search path. +++ [#831](https://github.com/rust-lang/git2-rs/pull/831) +++- When using the `zlib-ng-compat` Cargo feature, `libssh2-sys` is no longer automatically included unless you also enable the `ssh` feature. +++ [#833](https://github.com/rust-lang/git2-rs/pull/833) +++ +++## 0.13.2+1.4.2 - 2022-03-10 +++[0.13.1...0.13.2](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.13.1+1.4.2...libgit2-sys-0.13.2+1.4.2) +++ +++### Added +++- Added bindings for `git_odb_exists_ext`. +++ [#818](https://github.com/rust-lang/git2-rs/pull/818) +++ +++## 0.13.1+1.4.2 - 2022-02-28 +++[0.13.0...0.13.1](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.13.0+1.4.1...libgit2-sys-0.13.1+1.4.2) +++ +++### Changed +++- Updated the bundled libgit2 to [1.4.2](https://github.com/libgit2/libgit2/releases/tag/v1.4.2). +++ [#815](https://github.com/rust-lang/git2-rs/pull/815) +++ - Changes: [fdd15bcfca6b2ec4b7ecad1aa11a396cb15bd064...182d0d1ee933de46bf0b5a6ec269bafa77aba9a2](https://github.com/libgit2/libgit2/compare/fdd15bcfca6b2ec4b7ecad1aa11a396cb15bd064...182d0d1ee933de46bf0b5a6ec269bafa77aba9a2). +++ +++## 0.13.0+1.4.1 - 2022-02-24 +++[0.12.26...0.13.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.12.26+1.3.0...libgit2-sys-0.13.0+1.4.1) +++ +++### Changed +++- Changed libgit2-sys to use the presence of the `src` directory instead of `.git` to determine if it has a git submodule that needs updating. +++ [#801](https://github.com/rust-lang/git2-rs/pull/801) +++- Updated the bundled libgit2 to [1.4.1](https://github.com/libgit2/libgit2/releases/tag/v1.4.1) (see also [1.4.0](https://github.com/libgit2/libgit2/releases/tag/v1.4.0)) +++ [#806](https://github.com/rust-lang/git2-rs/pull/806) +++ [#811](https://github.com/rust-lang/git2-rs/pull/811) +++ - Changes: [b7bad55e4bb0a285b073ba5e02b01d3f522fc95d...fdd15bcfca6b2ec4b7ecad1aa11a396cb15bd064](https://github.com/libgit2/libgit2/compare/b7bad55e4bb0a285b073ba5e02b01d3f522fc95d...fdd15bcfca6b2ec4b7ecad1aa11a396cb15bd064) +++ - The supported libgit2 system library range is 1.4.0 or greater. diff --cc extra/libgit2-sys/Cargo.toml index 0000000000,0000000000,0000000000..f6ca04789e new file mode 100644 --- /dev/null +++ b/extra/libgit2-sys/Cargo.toml @@@@ -1,0 -1,0 -1,0 +1,74 @@@@ +++# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +++# +++# When uploading crates to the registry Cargo will automatically +++# "normalize" Cargo.toml files for maximal compatibility +++# with all versions of Cargo and also rewrite `path` dependencies +++# to registry (e.g., crates.io) dependencies. +++# +++# If you are reading this file be aware that the original Cargo.toml +++# will likely look very different (and much more reasonable). +++# See Cargo.toml.orig for the original contents. +++ +++[package] +++edition = "2018" +++name = "libgit2-sys" +++version = "0.18.0+1.9.0" +++authors = [ +++ "Josh Triplett ", +++ "Alex Crichton ", +++] +++build = "build.rs" +++links = "git2" +++exclude = [ +++ "libgit2/ci/*", +++ "libgit2/docs/*", +++ "libgit2/examples/*", +++ "libgit2/fuzzers/*", +++ "libgit2/tests/*", +++] +++autolib = false +++autobins = false +++autoexamples = false +++autotests = false +++autobenches = false +++description = "Native bindings to the libgit2 library" +++readme = false +++license = "MIT OR Apache-2.0" +++repository = "https://github.com/rust-lang/git2-rs" +++ +++[lib] +++name = "libgit2_sys" +++path = "lib.rs" +++ +++[dependencies.libc] +++version = "0.2" +++ +++[dependencies.libssh2-sys] +++version = "0.3.0" +++optional = true +++ +++[dependencies.libz-sys] +++version = "1.1.0" +++features = ["libc"] +++default-features = false +++ +++[build-dependencies.cc] +++version = "1.0.43" +++features = ["parallel"] +++ +++[build-dependencies.pkg-config] +++version = "0.3.15" +++ +++[features] +++https = ["openssl-sys"] +++ssh = ["libssh2-sys"] +++vendored = [] +++vendored-openssl = ["openssl-sys/vendored"] +++zlib-ng-compat = [ +++ "libz-sys/zlib-ng", +++ "libssh2-sys?/zlib-ng-compat", +++] +++ +++[target."cfg(unix)".dependencies.openssl-sys] +++version = "0.9.45" +++optional = true diff --cc extra/libgit2-sys/LICENSE-APACHE index 0000000000,0000000000,0000000000..16fe87b06e new file mode 100644 --- /dev/null +++ b/extra/libgit2-sys/LICENSE-APACHE @@@@ -1,0 -1,0 -1,0 +1,201 @@@@ +++ Apache License +++ Version 2.0, January 2004 +++ http://www.apache.org/licenses/ +++ +++TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +++ +++1. Definitions. +++ +++ "License" shall mean the terms and conditions for use, reproduction, +++ and distribution as defined by Sections 1 through 9 of this document. +++ +++ "Licensor" shall mean the copyright owner or entity authorized by +++ the copyright owner that is granting the License. +++ +++ "Legal Entity" shall mean the union of the acting entity and all +++ other entities that control, are controlled by, or are under common +++ control with that entity. For the purposes of this definition, +++ "control" means (i) the power, direct or indirect, to cause the +++ direction or management of such entity, whether by contract or +++ otherwise, or (ii) ownership of fifty percent (50%) or more of the +++ outstanding shares, or (iii) beneficial ownership of such entity. +++ +++ "You" (or "Your") shall mean an individual or Legal Entity +++ exercising permissions granted by this License. +++ +++ "Source" form shall mean the preferred form for making modifications, +++ including but not limited to software source code, documentation +++ source, and configuration files. +++ +++ "Object" form shall mean any form resulting from mechanical +++ transformation or translation of a Source form, including but +++ not limited to compiled object code, generated documentation, +++ and conversions to other media types. +++ +++ "Work" shall mean the work of authorship, whether in Source or +++ Object form, made available under the License, as indicated by a +++ copyright notice that is included in or attached to the work +++ (an example is provided in the Appendix below). +++ +++ "Derivative Works" shall mean any work, whether in Source or Object +++ form, that is based on (or derived from) the Work and for which the +++ editorial revisions, annotations, elaborations, or other modifications +++ represent, as a whole, an original work of authorship. For the purposes +++ of this License, Derivative Works shall not include works that remain +++ separable from, or merely link (or bind by name) to the interfaces of, +++ the Work and Derivative Works thereof. +++ +++ "Contribution" shall mean any work of authorship, including +++ the original version of the Work and any modifications or additions +++ to that Work or Derivative Works thereof, that is intentionally +++ submitted to Licensor for inclusion in the Work by the copyright owner +++ or by an individual or Legal Entity authorized to submit on behalf of +++ the copyright owner. For the purposes of this definition, "submitted" +++ means any form of electronic, verbal, or written communication sent +++ to the Licensor or its representatives, including but not limited to +++ communication on electronic mailing lists, source code control systems, +++ and issue tracking systems that are managed by, or on behalf of, the +++ Licensor for the purpose of discussing and improving the Work, but +++ excluding communication that is conspicuously marked or otherwise +++ designated in writing by the copyright owner as "Not a Contribution." +++ +++ "Contributor" shall mean Licensor and any individual or Legal Entity +++ on behalf of whom a Contribution has been received by Licensor and +++ subsequently incorporated within the Work. +++ +++2. Grant of Copyright License. Subject to the terms and conditions of +++ this License, each Contributor hereby grants to You a perpetual, +++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable +++ copyright license to reproduce, prepare Derivative Works of, +++ publicly display, publicly perform, sublicense, and distribute the +++ Work and such Derivative Works in Source or Object form. +++ +++3. Grant of Patent License. Subject to the terms and conditions of +++ this License, each Contributor hereby grants to You a perpetual, +++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable +++ (except as stated in this section) patent license to make, have made, +++ use, offer to sell, sell, import, and otherwise transfer the Work, +++ where such license applies only to those patent claims licensable +++ by such Contributor that are necessarily infringed by their +++ Contribution(s) alone or by combination of their Contribution(s) +++ with the Work to which such Contribution(s) was submitted. If You +++ institute patent litigation against any entity (including a +++ cross-claim or counterclaim in a lawsuit) alleging that the Work +++ or a Contribution incorporated within the Work constitutes direct +++ or contributory patent infringement, then any patent licenses +++ granted to You under this License for that Work shall terminate +++ as of the date such litigation is filed. +++ +++4. Redistribution. You may reproduce and distribute copies of the +++ Work or Derivative Works thereof in any medium, with or without +++ modifications, and in Source or Object form, provided that You +++ meet the following conditions: +++ +++ (a) You must give any other recipients of the Work or +++ Derivative Works a copy of this License; and +++ +++ (b) You must cause any modified files to carry prominent notices +++ stating that You changed the files; and +++ +++ (c) You must retain, in the Source form of any Derivative Works +++ that You distribute, all copyright, patent, trademark, and +++ attribution notices from the Source form of the Work, +++ excluding those notices that do not pertain to any part of +++ the Derivative Works; and +++ +++ (d) If the Work includes a "NOTICE" text file as part of its +++ distribution, then any Derivative Works that You distribute must +++ include a readable copy of the attribution notices contained +++ within such NOTICE file, excluding those notices that do not +++ pertain to any part of the Derivative Works, in at least one +++ of the following places: within a NOTICE text file distributed +++ as part of the Derivative Works; within the Source form or +++ documentation, if provided along with the Derivative Works; or, +++ within a display generated by the Derivative Works, if and +++ wherever such third-party notices normally appear. The contents +++ of the NOTICE file are for informational purposes only and +++ do not modify the License. You may add Your own attribution +++ notices within Derivative Works that You distribute, alongside +++ or as an addendum to the NOTICE text from the Work, provided +++ that such additional attribution notices cannot be construed +++ as modifying the License. +++ +++ You may add Your own copyright statement to Your modifications and +++ may provide additional or different license terms and conditions +++ for use, reproduction, or distribution of Your modifications, or +++ for any such Derivative Works as a whole, provided Your use, +++ reproduction, and distribution of the Work otherwise complies with +++ the conditions stated in this License. +++ +++5. Submission of Contributions. Unless You explicitly state otherwise, +++ any Contribution intentionally submitted for inclusion in the Work +++ by You to the Licensor shall be under the terms and conditions of +++ this License, without any additional terms or conditions. +++ Notwithstanding the above, nothing herein shall supersede or modify +++ the terms of any separate license agreement you may have executed +++ with Licensor regarding such Contributions. +++ +++6. Trademarks. This License does not grant permission to use the trade +++ names, trademarks, service marks, or product names of the Licensor, +++ except as required for reasonable and customary use in describing the +++ origin of the Work and reproducing the content of the NOTICE file. +++ +++7. Disclaimer of Warranty. Unless required by applicable law or +++ agreed to in writing, Licensor provides the Work (and each +++ Contributor provides its Contributions) on an "AS IS" BASIS, +++ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +++ implied, including, without limitation, any warranties or conditions +++ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +++ PARTICULAR PURPOSE. You are solely responsible for determining the +++ appropriateness of using or redistributing the Work and assume any +++ risks associated with Your exercise of permissions under this License. +++ +++8. Limitation of Liability. In no event and under no legal theory, +++ whether in tort (including negligence), contract, or otherwise, +++ unless required by applicable law (such as deliberate and grossly +++ negligent acts) or agreed to in writing, shall any Contributor be +++ liable to You for damages, including any direct, indirect, special, +++ incidental, or consequential damages of any character arising as a +++ result of this License or out of the use or inability to use the +++ Work (including but not limited to damages for loss of goodwill, +++ work stoppage, computer failure or malfunction, or any and all +++ other commercial damages or losses), even if such Contributor +++ has been advised of the possibility of such damages. +++ +++9. Accepting Warranty or Additional Liability. While redistributing +++ the Work or Derivative Works thereof, You may choose to offer, +++ and charge a fee for, acceptance of support, warranty, indemnity, +++ or other liability obligations and/or rights consistent with this +++ License. However, in accepting such obligations, You may act only +++ on Your own behalf and on Your sole responsibility, not on behalf +++ of any other Contributor, and only if You agree to indemnify, +++ defend, and hold each Contributor harmless for any liability +++ incurred by, or claims asserted against, such Contributor by reason +++ of your accepting any such warranty or additional liability. +++ +++END OF TERMS AND CONDITIONS +++ +++APPENDIX: How to apply the Apache License to your work. +++ +++ To apply the Apache License to your work, attach the following +++ boilerplate notice, with the fields enclosed by brackets "[]" +++ replaced with your own identifying information. (Don't include +++ the brackets!) The text should be enclosed in the appropriate +++ comment syntax for the file format. We also recommend that a +++ file or class name and description of purpose be included on the +++ same "printed page" as the copyright notice for easier +++ identification within third-party archives. +++ +++Copyright [yyyy] [name of copyright owner] +++ +++Licensed under the Apache License, Version 2.0 (the "License"); +++you may not use this file except in compliance with the License. +++You may obtain a copy of the License at +++ +++ http://www.apache.org/licenses/LICENSE-2.0 +++ +++Unless required by applicable law or agreed to in writing, software +++distributed under the License is distributed on an "AS IS" BASIS, +++WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +++See the License for the specific language governing permissions and +++limitations under the License. diff --cc extra/libgit2-sys/LICENSE-MIT index 0000000000,0000000000,0000000000..39e0ed6602 new file mode 100644 --- /dev/null +++ b/extra/libgit2-sys/LICENSE-MIT @@@@ -1,0 -1,0 -1,0 +1,25 @@@@ +++Copyright (c) 2014 Alex Crichton +++ +++Permission is hereby granted, free of charge, to any +++person obtaining a copy of this software and associated +++documentation files (the "Software"), to deal in the +++Software without restriction, including without +++limitation the rights to use, copy, modify, merge, +++publish, distribute, sublicense, and/or sell copies of +++the Software, and to permit persons to whom the Software +++is furnished to do so, subject to the following +++conditions: +++ +++The above copyright notice and this permission notice +++shall be included in all copies or substantial portions +++of the Software. +++ +++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +++ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +++TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +++PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +++SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +++CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +++OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +++IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +++DEALINGS IN THE SOFTWARE. diff --cc extra/libgit2-sys/build.rs index 0000000000,0000000000,0000000000..77cd4eac64 new file mode 100644 --- /dev/null +++ b/extra/libgit2-sys/build.rs @@@@ -1,0 -1,0 -1,0 +1,301 @@@@ +++use std::env; +++use std::fs; +++use std::io; +++use std::path::{Path, PathBuf}; +++use std::process::Command; +++ +++/// Tries to use system libgit2 and emits necessary build script instructions. +++fn try_system_libgit2() -> Result { +++ let mut cfg = pkg_config::Config::new(); +++ match cfg.range_version("1.9.0".."1.10.0").probe("libgit2") { +++ Ok(lib) => { +++ for include in &lib.include_paths { +++ println!("cargo:root={}", include.display()); +++ } +++ Ok(lib) +++ } +++ Err(e) => { +++ println!("cargo:warning=failed to probe system libgit2: {e}"); +++ Err(e) +++ } +++ } +++} +++ +++fn main() { +++ println!( +++ "cargo:rustc-check-cfg=cfg(\ +++ libgit2_vendored,\ +++ )" +++ ); +++ +++ let https = env::var("CARGO_FEATURE_HTTPS").is_ok(); +++ let ssh = env::var("CARGO_FEATURE_SSH").is_ok(); +++ let vendored = env::var("CARGO_FEATURE_VENDORED").is_ok(); +++ let zlib_ng_compat = env::var("CARGO_FEATURE_ZLIB_NG_COMPAT").is_ok(); +++ +++ // Specify `LIBGIT2_NO_VENDOR` to force to use system libgit2. +++ // Due to the additive nature of Cargo features, if some crate in the +++ // dependency graph activates `vendored` feature, there is no way to revert +++ // it back. This env var serves as a workaround for this purpose. +++ println!("cargo:rerun-if-env-changed=LIBGIT2_NO_VENDOR"); +++ let forced_no_vendor = env::var_os("LIBGIT2_NO_VENDOR").map_or(false, |s| s != "0"); +++ +++ if forced_no_vendor { +++ if try_system_libgit2().is_err() { +++ panic!( +++ "\ +++The environment variable `LIBGIT2_NO_VENDOR` has been set but no compatible system libgit2 could be found. +++The build is now aborting. To disable, unset the variable or use `LIBGIT2_NO_VENDOR=0`. +++", +++ ); +++ } +++ +++ // We've reached here, implying we're using system libgit2. +++ return; +++ } +++ +++ // To use zlib-ng in zlib-compat mode, we have to build libgit2 ourselves. +++ let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat; +++ if try_to_use_system_libgit2 && try_system_libgit2().is_ok() { +++ // using system libgit2 has worked +++ return; +++ } +++ +++ println!("cargo:rustc-cfg=libgit2_vendored"); +++ +++ if !Path::new("libgit2/src").exists() { +++ let _ = Command::new("git") +++ .args(&["submodule", "update", "--init", "libgit2"]) +++ .status(); +++ } +++ +++ let target = env::var("TARGET").unwrap(); +++ let windows = target.contains("windows"); +++ let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap()); +++ let include = dst.join("include"); +++ let mut cfg = cc::Build::new(); +++ fs::create_dir_all(&include).unwrap(); +++ +++ // Copy over all header files +++ cp_r("libgit2/include", &include); +++ +++ cfg.include(&include) +++ .include("libgit2/src/libgit2") +++ .include("libgit2/src/util") +++ .out_dir(dst.join("build")) +++ .warnings(false); +++ +++ // Include all cross-platform C files +++ add_c_files(&mut cfg, "libgit2/src/libgit2"); +++ add_c_files(&mut cfg, "libgit2/src/util"); +++ +++ // These are activated by features, but they're all unconditionally always +++ // compiled apparently and have internal #define's to make sure they're +++ // compiled correctly. +++ add_c_files(&mut cfg, "libgit2/src/libgit2/transports"); +++ add_c_files(&mut cfg, "libgit2/src/libgit2/streams"); +++ +++ // Always use bundled HTTP parser (llhttp) for now +++ cfg.include("libgit2/deps/llhttp"); +++ add_c_files(&mut cfg, "libgit2/deps/llhttp"); +++ +++ // external/system xdiff is not yet supported +++ cfg.include("libgit2/deps/xdiff"); +++ add_c_files(&mut cfg, "libgit2/deps/xdiff"); +++ +++ // Use the included PCRE regex backend. +++ // +++ // Ideally these defines would be specific to the pcre files (or placed in +++ // a config.h), but since libgit2 already has a config.h used for other +++ // reasons, just define on the command-line for everything. Perhaps there +++ // is some way with cc to have different instructions per-file? +++ cfg.define("GIT_REGEX_BUILTIN", "1") +++ .include("libgit2/deps/pcre") +++ .define("HAVE_STDINT_H", Some("1")) +++ .define("HAVE_MEMMOVE", Some("1")) +++ .define("NO_RECURSE", Some("1")) +++ .define("NEWLINE", Some("10")) +++ .define("POSIX_MALLOC_THRESHOLD", Some("10")) +++ .define("LINK_SIZE", Some("2")) +++ .define("PARENS_NEST_LIMIT", Some("250")) +++ .define("MATCH_LIMIT", Some("10000000")) +++ .define("MATCH_LIMIT_RECURSION", Some("MATCH_LIMIT")) +++ .define("MAX_NAME_SIZE", Some("32")) +++ .define("MAX_NAME_COUNT", Some("10000")); +++ // "no symbols" warning on pcre_string_utils.c is because it is only used +++ // when when COMPILE_PCRE8 is not defined, which is the default. +++ add_c_files(&mut cfg, "libgit2/deps/pcre"); +++ +++ cfg.file("libgit2/src/util/allocators/failalloc.c"); +++ cfg.file("libgit2/src/util/allocators/stdalloc.c"); +++ +++ if windows { +++ add_c_files(&mut cfg, "libgit2/src/util/win32"); +++ cfg.define("STRSAFE_NO_DEPRECATE", None); +++ cfg.define("WIN32", None); +++ cfg.define("_WIN32_WINNT", Some("0x0600")); +++ +++ // libgit2's build system claims that forks like mingw-w64 of MinGW +++ // still want this define to use C99 stdio functions automatically. +++ // Apparently libgit2 breaks at runtime if this isn't here? Who knows! +++ if target.contains("gnu") { +++ cfg.define("__USE_MINGW_ANSI_STDIO", "1"); +++ } +++ } else { +++ add_c_files(&mut cfg, "libgit2/src/util/unix"); +++ cfg.flag("-fvisibility=hidden"); +++ } +++ if target.contains("solaris") || target.contains("illumos") { +++ cfg.define("_POSIX_C_SOURCE", "200112L"); +++ cfg.define("__EXTENSIONS__", None); +++ } +++ +++ let mut features = String::new(); +++ +++ features.push_str("#ifndef INCLUDE_features_h\n"); +++ features.push_str("#define INCLUDE_features_h\n"); +++ features.push_str("#define GIT_THREADS 1\n"); +++ features.push_str("#define GIT_TRACE 1\n"); +++ features.push_str("#define GIT_HTTPPARSER_BUILTIN 1\n"); +++ +++ if !target.contains("android") { +++ features.push_str("#define GIT_USE_NSEC 1\n"); +++ } +++ +++ if windows { +++ features.push_str("#define GIT_IO_WSAPOLL 1\n"); +++ } else { +++ // Should we fallback to `select` as more systems have that? +++ features.push_str("#define GIT_IO_POLL 1\n"); +++ features.push_str("#define GIT_IO_SELECT 1\n"); +++ } +++ +++ if target.contains("apple") { +++ features.push_str("#define GIT_USE_STAT_MTIMESPEC 1\n"); +++ } else { +++ features.push_str("#define GIT_USE_STAT_MTIM 1\n"); +++ } +++ +++ if env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap() == "32" { +++ features.push_str("#define GIT_ARCH_32 1\n"); +++ } else { +++ features.push_str("#define GIT_ARCH_64 1\n"); +++ } +++ +++ if ssh { +++ if let Some(path) = env::var_os("DEP_SSH2_INCLUDE") { +++ cfg.include(path); +++ } +++ features.push_str("#define GIT_SSH 1\n"); +++ features.push_str("#define GIT_SSH_LIBSSH2 1\n"); +++ features.push_str("#define GIT_SSH_LIBSSH2_MEMORY_CREDENTIALS 1\n"); +++ } +++ if https { +++ features.push_str("#define GIT_HTTPS 1\n"); +++ +++ if windows { +++ features.push_str("#define GIT_WINHTTP 1\n"); +++ } else if target.contains("apple") { +++ features.push_str("#define GIT_SECURE_TRANSPORT 1\n"); +++ } else { +++ features.push_str("#define GIT_OPENSSL 1\n"); +++ if let Some(path) = env::var_os("DEP_OPENSSL_INCLUDE") { +++ cfg.include(path); +++ } +++ } +++ } +++ +++ // Use the CollisionDetection SHA1 implementation. +++ features.push_str("#define GIT_SHA1_COLLISIONDETECT 1\n"); +++ cfg.define("SHA1DC_NO_STANDARD_INCLUDES", "1"); +++ cfg.define("SHA1DC_CUSTOM_INCLUDE_SHA1_C", "\"common.h\""); +++ cfg.define("SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C", "\"common.h\""); +++ cfg.file("libgit2/src/util/hash/collisiondetect.c"); +++ cfg.file("libgit2/src/util/hash/sha1dc/sha1.c"); +++ cfg.file("libgit2/src/util/hash/sha1dc/ubc_check.c"); +++ +++ if https { +++ if windows { +++ features.push_str("#define GIT_SHA256_WIN32 1\n"); +++ cfg.file("libgit2/src/util/hash/win32.c"); +++ } else if target.contains("apple") { +++ features.push_str("#define GIT_SHA256_COMMON_CRYPTO 1\n"); +++ cfg.file("libgit2/src/util/hash/common_crypto.c"); +++ } else { +++ features.push_str("#define GIT_SHA256_OPENSSL 1\n"); +++ cfg.file("libgit2/src/util/hash/openssl.c"); +++ } +++ } else { +++ features.push_str("#define GIT_SHA256_BUILTIN 1\n"); +++ cfg.file("libgit2/src/util/hash/builtin.c"); +++ cfg.file("libgit2/src/util/hash/rfc6234/sha224-256.c"); +++ } +++ +++ if let Some(path) = env::var_os("DEP_Z_INCLUDE") { +++ cfg.include(path); +++ } +++ +++ if target.contains("apple") { +++ features.push_str("#define GIT_USE_ICONV 1\n"); +++ } +++ +++ features.push_str("#endif\n"); +++ fs::write(include.join("git2_features.h"), features).unwrap(); +++ +++ cfg.compile("git2"); +++ +++ println!("cargo:root={}", dst.display()); +++ +++ if target.contains("windows") { +++ println!("cargo:rustc-link-lib=winhttp"); +++ println!("cargo:rustc-link-lib=rpcrt4"); +++ println!("cargo:rustc-link-lib=ole32"); +++ println!("cargo:rustc-link-lib=crypt32"); +++ println!("cargo:rustc-link-lib=secur32"); +++ } +++ +++ if target.contains("apple") { +++ println!("cargo:rustc-link-lib=iconv"); +++ println!("cargo:rustc-link-lib=framework=Security"); +++ println!("cargo:rustc-link-lib=framework=CoreFoundation"); +++ } +++ +++ println!("cargo:rerun-if-changed=libgit2/include"); +++ println!("cargo:rerun-if-changed=libgit2/src"); +++ println!("cargo:rerun-if-changed=libgit2/deps"); +++} +++ +++fn cp_r(from: impl AsRef, to: impl AsRef) { +++ for e in from.as_ref().read_dir().unwrap() { +++ let e = e.unwrap(); +++ let from = e.path(); +++ let to = to.as_ref().join(e.file_name()); +++ if e.file_type().unwrap().is_dir() { +++ fs::create_dir_all(&to).unwrap(); +++ cp_r(&from, &to); +++ } else { +++ println!("{} => {}", from.display(), to.display()); +++ fs::copy(&from, &to).unwrap(); +++ } +++ } +++} +++ +++fn add_c_files(build: &mut cc::Build, path: impl AsRef) { +++ let path = path.as_ref(); +++ if !path.exists() { +++ panic!("Path {} does not exist", path.display()); +++ } +++ // sort the C files to ensure a deterministic build for reproducible builds +++ let dir = path.read_dir().unwrap(); +++ let mut paths = dir.collect::>>().unwrap(); +++ paths.sort_by_key(|e| e.path()); +++ +++ for e in paths { +++ let path = e.path(); +++ if e.file_type().unwrap().is_dir() { +++ // skip dirs for now +++ } else if path.extension().and_then(|s| s.to_str()) == Some("c") { +++ build.file(&path); +++ } +++ } +++} diff --cc extra/libgit2-sys/lib.rs index 0000000000,0000000000,0000000000..bf0f107755 new file mode 100644 --- /dev/null +++ b/extra/libgit2-sys/lib.rs @@@@ -1,0 -1,0 -1,0 +1,4367 @@@@ +++#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.18")] +++#![allow(non_camel_case_types, unused_extern_crates)] +++ +++// This is required to link libz when libssh2-sys is not included. +++extern crate libz_sys as libz; +++ +++use libc::{c_char, c_int, c_uchar, c_uint, c_void, size_t}; +++#[cfg(feature = "ssh")] +++use libssh2_sys as libssh2; +++use std::ffi::CStr; +++ +++pub const GIT_OID_RAWSZ: usize = 20; +++pub const GIT_OID_HEXSZ: usize = GIT_OID_RAWSZ * 2; +++pub const GIT_CLONE_OPTIONS_VERSION: c_uint = 1; +++pub const GIT_STASH_APPLY_OPTIONS_VERSION: c_uint = 1; +++pub const GIT_CHECKOUT_OPTIONS_VERSION: c_uint = 1; +++pub const GIT_MERGE_OPTIONS_VERSION: c_uint = 1; +++pub const GIT_REMOTE_CALLBACKS_VERSION: c_uint = 1; +++pub const GIT_STATUS_OPTIONS_VERSION: c_uint = 1; +++pub const GIT_BLAME_OPTIONS_VERSION: c_uint = 1; +++pub const GIT_PROXY_OPTIONS_VERSION: c_uint = 1; +++pub const GIT_SUBMODULE_UPDATE_OPTIONS_VERSION: c_uint = 1; +++pub const GIT_ODB_BACKEND_VERSION: c_uint = 1; +++pub const GIT_REFDB_BACKEND_VERSION: c_uint = 1; +++pub const GIT_CHERRYPICK_OPTIONS_VERSION: c_uint = 1; +++pub const GIT_APPLY_OPTIONS_VERSION: c_uint = 1; +++pub const GIT_REVERT_OPTIONS_VERSION: c_uint = 1; +++pub const GIT_INDEXER_OPTIONS_VERSION: c_uint = 1; +++ +++macro_rules! git_enum { +++ (pub enum $name:ident { $($variants:tt)* }) => { +++ #[cfg(target_env = "msvc")] +++ pub type $name = i32; +++ #[cfg(not(target_env = "msvc"))] +++ pub type $name = u32; +++ git_enum!(gen, $name, 0, $($variants)*); +++ }; +++ (pub enum $name:ident: $t:ty { $($variants:tt)* }) => { +++ pub type $name = $t; +++ git_enum!(gen, $name, 0, $($variants)*); +++ }; +++ (gen, $name:ident, $val:expr, $variant:ident, $($rest:tt)*) => { +++ pub const $variant: $name = $val; +++ git_enum!(gen, $name, $val+1, $($rest)*); +++ }; +++ (gen, $name:ident, $val:expr, $variant:ident = $e:expr, $($rest:tt)*) => { +++ pub const $variant: $name = $e; +++ git_enum!(gen, $name, $e+1, $($rest)*); +++ }; +++ (gen, $name:ident, $val:expr, ) => {} +++} +++ +++pub enum git_blob {} +++pub enum git_branch_iterator {} +++pub enum git_blame {} +++pub enum git_commit {} +++pub enum git_config {} +++pub enum git_config_iterator {} +++pub enum git_index {} +++pub enum git_index_conflict_iterator {} +++pub enum git_object {} +++pub enum git_reference {} +++pub enum git_reference_iterator {} +++pub enum git_annotated_commit {} +++pub enum git_refdb {} +++pub enum git_refspec {} +++pub enum git_remote {} +++pub enum git_repository {} +++pub enum git_revwalk {} +++pub enum git_submodule {} +++pub enum git_tag {} +++pub enum git_tree {} +++pub enum git_tree_entry {} +++pub enum git_treebuilder {} +++pub enum git_push {} +++pub enum git_note {} +++pub enum git_note_iterator {} +++pub enum git_status_list {} +++pub enum git_pathspec {} +++pub enum git_pathspec_match_list {} +++pub enum git_diff {} +++pub enum git_diff_stats {} +++pub enum git_patch {} +++pub enum git_rebase {} +++pub enum git_reflog {} +++pub enum git_reflog_entry {} +++pub enum git_describe_result {} +++pub enum git_packbuilder {} +++pub enum git_odb {} +++pub enum git_odb_stream {} +++pub enum git_odb_object {} +++pub enum git_worktree {} +++pub enum git_transaction {} +++pub enum git_mailmap {} +++pub enum git_indexer {} +++ +++#[repr(C)] +++pub struct git_revspec { +++ pub from: *mut git_object, +++ pub to: *mut git_object, +++ pub flags: c_uint, +++} +++ +++#[repr(C)] +++pub struct git_error { +++ pub message: *mut c_char, +++ pub klass: c_int, +++} +++ +++#[repr(C)] +++#[derive(Copy, Clone)] +++pub struct git_oid { +++ pub id: [u8; GIT_OID_RAWSZ], +++} +++ +++#[repr(C)] +++#[derive(Copy)] +++pub struct git_strarray { +++ pub strings: *mut *mut c_char, +++ pub count: size_t, +++} +++impl Clone for git_strarray { +++ fn clone(&self) -> git_strarray { +++ *self +++ } +++} +++ +++#[repr(C)] +++#[derive(Copy)] +++pub struct git_oidarray { +++ pub ids: *mut git_oid, +++ pub count: size_t, +++} +++impl Clone for git_oidarray { +++ fn clone(&self) -> git_oidarray { +++ *self +++ } +++} +++ +++#[repr(C)] +++pub struct git_signature { +++ pub name: *mut c_char, +++ pub email: *mut c_char, +++ pub when: git_time, +++} +++ +++#[repr(C)] +++#[derive(Copy, Clone, Debug, Eq, PartialEq)] +++pub struct git_time { +++ pub time: git_time_t, +++ pub offset: c_int, +++ pub sign: c_char, +++} +++ +++pub type git_off_t = i64; +++pub type git_time_t = i64; +++pub type git_object_size_t = u64; +++ +++git_enum! { +++ pub enum git_revparse_mode_t { +++ GIT_REVPARSE_SINGLE = 1 << 0, +++ GIT_REVPARSE_RANGE = 1 << 1, +++ GIT_REVPARSE_MERGE_BASE = 1 << 2, +++ } +++} +++ +++git_enum! { +++ pub enum git_error_code: c_int { +++ GIT_OK = 0, +++ +++ GIT_ERROR = -1, +++ GIT_ENOTFOUND = -3, +++ GIT_EEXISTS = -4, +++ GIT_EAMBIGUOUS = -5, +++ GIT_EBUFS = -6, +++ GIT_EUSER = -7, +++ GIT_EBAREREPO = -8, +++ GIT_EUNBORNBRANCH = -9, +++ GIT_EUNMERGED = -10, +++ GIT_ENONFASTFORWARD = -11, +++ GIT_EINVALIDSPEC = -12, +++ GIT_ECONFLICT = -13, +++ GIT_ELOCKED = -14, +++ GIT_EMODIFIED = -15, +++ GIT_EAUTH = -16, +++ GIT_ECERTIFICATE = -17, +++ GIT_EAPPLIED = -18, +++ GIT_EPEEL = -19, +++ GIT_EEOF = -20, +++ GIT_EINVALID = -21, +++ GIT_EUNCOMMITTED = -22, +++ GIT_EDIRECTORY = -23, +++ GIT_EMERGECONFLICT = -24, +++ GIT_PASSTHROUGH = -30, +++ GIT_ITEROVER = -31, +++ GIT_RETRY = -32, +++ GIT_EMISMATCH = -33, +++ GIT_EINDEXDIRTY = -34, +++ GIT_EAPPLYFAIL = -35, +++ GIT_EOWNER = -36, +++ GIT_TIMEOUT = -37, +++ GIT_EUNCHANGED = -38, +++ GIT_ENOTSUPPORTED = -39, +++ GIT_EREADONLY = -40, +++ } +++} +++ +++git_enum! { +++ pub enum git_error_t { +++ GIT_ERROR_NONE = 0, +++ GIT_ERROR_NOMEMORY, +++ GIT_ERROR_OS, +++ GIT_ERROR_INVALID, +++ GIT_ERROR_REFERENCE, +++ GIT_ERROR_ZLIB, +++ GIT_ERROR_REPOSITORY, +++ GIT_ERROR_CONFIG, +++ GIT_ERROR_REGEX, +++ GIT_ERROR_ODB, +++ GIT_ERROR_INDEX, +++ GIT_ERROR_OBJECT, +++ GIT_ERROR_NET, +++ GIT_ERROR_TAG, +++ GIT_ERROR_TREE, +++ GIT_ERROR_INDEXER, +++ GIT_ERROR_SSL, +++ GIT_ERROR_SUBMODULE, +++ GIT_ERROR_THREAD, +++ GIT_ERROR_STASH, +++ GIT_ERROR_CHECKOUT, +++ GIT_ERROR_FETCHHEAD, +++ GIT_ERROR_MERGE, +++ GIT_ERROR_SSH, +++ GIT_ERROR_FILTER, +++ GIT_ERROR_REVERT, +++ GIT_ERROR_CALLBACK, +++ GIT_ERROR_CHERRYPICK, +++ GIT_ERROR_DESCRIBE, +++ GIT_ERROR_REBASE, +++ GIT_ERROR_FILESYSTEM, +++ GIT_ERROR_PATCH, +++ GIT_ERROR_WORKTREE, +++ GIT_ERROR_SHA1, +++ GIT_ERROR_HTTP, +++ } +++} +++ +++git_enum! { +++ pub enum git_repository_state_t { +++ GIT_REPOSITORY_STATE_NONE, +++ GIT_REPOSITORY_STATE_MERGE, +++ GIT_REPOSITORY_STATE_REVERT, +++ GIT_REPOSITORY_STATE_REVERT_SEQUENCE, +++ GIT_REPOSITORY_STATE_CHERRYPICK, +++ GIT_REPOSITORY_STATE_CHERRYPICK_SEQUENCE, +++ GIT_REPOSITORY_STATE_BISECT, +++ GIT_REPOSITORY_STATE_REBASE, +++ GIT_REPOSITORY_STATE_REBASE_INTERACTIVE, +++ GIT_REPOSITORY_STATE_REBASE_MERGE, +++ GIT_REPOSITORY_STATE_APPLY_MAILBOX, +++ GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE, +++ } +++} +++ +++git_enum! { +++ pub enum git_direction { +++ GIT_DIRECTION_FETCH, +++ GIT_DIRECTION_PUSH, +++ } +++} +++ +++#[repr(C)] +++pub struct git_clone_options { +++ pub version: c_uint, +++ pub checkout_opts: git_checkout_options, +++ pub fetch_opts: git_fetch_options, +++ pub bare: c_int, +++ pub local: git_clone_local_t, +++ pub checkout_branch: *const c_char, +++ pub repository_cb: git_repository_create_cb, +++ pub repository_cb_payload: *mut c_void, +++ pub remote_cb: git_remote_create_cb, +++ pub remote_cb_payload: *mut c_void, +++} +++ +++git_enum! { +++ pub enum git_clone_local_t { +++ GIT_CLONE_LOCAL_AUTO, +++ GIT_CLONE_LOCAL, +++ GIT_CLONE_NO_LOCAL, +++ GIT_CLONE_LOCAL_NO_LINKS, +++ } +++} +++ +++#[repr(C)] +++pub struct git_checkout_options { +++ pub version: c_uint, +++ pub checkout_strategy: c_uint, +++ pub disable_filters: c_int, +++ pub dir_mode: c_uint, +++ pub file_mode: c_uint, +++ pub file_open_flags: c_int, +++ pub notify_flags: c_uint, +++ pub notify_cb: git_checkout_notify_cb, +++ pub notify_payload: *mut c_void, +++ pub progress_cb: git_checkout_progress_cb, +++ pub progress_payload: *mut c_void, +++ pub paths: git_strarray, +++ pub baseline: *mut git_tree, +++ pub baseline_index: *mut git_index, +++ pub target_directory: *const c_char, +++ pub ancestor_label: *const c_char, +++ pub our_label: *const c_char, +++ pub their_label: *const c_char, +++ pub perfdata_cb: git_checkout_perfdata_cb, +++ pub perfdata_payload: *mut c_void, +++} +++ +++pub type git_checkout_notify_cb = Option< +++ extern "C" fn( +++ git_checkout_notify_t, +++ *const c_char, +++ *const git_diff_file, +++ *const git_diff_file, +++ *const git_diff_file, +++ *mut c_void, +++ ) -> c_int, +++>; +++pub type git_checkout_progress_cb = +++ Option; +++ +++pub type git_checkout_perfdata_cb = +++ Option; +++ +++#[repr(C)] +++pub struct git_checkout_perfdata { +++ pub mkdir_calls: size_t, +++ pub stat_calls: size_t, +++ pub chmod_calls: size_t, +++} +++ +++#[repr(C)] +++#[derive(Copy, Clone, Default)] +++pub struct git_indexer_progress { +++ pub total_objects: c_uint, +++ pub indexed_objects: c_uint, +++ pub received_objects: c_uint, +++ pub local_objects: c_uint, +++ pub total_deltas: c_uint, +++ pub indexed_deltas: c_uint, +++ pub received_bytes: size_t, +++} +++ +++pub type git_indexer_progress_cb = +++ Option c_int>; +++ +++#[deprecated( +++ since = "0.10.0", +++ note = "renamed to `git_indexer_progress` to match upstream" +++)] +++pub type git_transfer_progress = git_indexer_progress; +++ +++#[repr(C)] +++pub struct git_indexer_options { +++ pub version: c_uint, +++ pub progress_cb: git_indexer_progress_cb, +++ pub progress_cb_payload: *mut c_void, +++ pub verify: c_uchar, +++} +++ +++pub type git_remote_ready_cb = Option c_int>; +++ +++git_enum! { +++ pub enum git_remote_update_flags { +++ GIT_REMOTE_UPDATE_FETCHHEAD = 1 << 0, +++ GIT_REMOTE_UPDATE_REPORT_UNCHANGED = 1 << 1, +++ } +++} +++ +++#[repr(C)] +++pub struct git_remote_callbacks { +++ pub version: c_uint, +++ pub sideband_progress: git_transport_message_cb, +++ pub completion: Option c_int>, +++ pub credentials: git_cred_acquire_cb, +++ pub certificate_check: git_transport_certificate_check_cb, +++ pub transfer_progress: git_indexer_progress_cb, +++ pub update_tips: +++ Option c_int>, +++ pub pack_progress: git_packbuilder_progress, +++ pub push_transfer_progress: git_push_transfer_progress, +++ pub push_update_reference: git_push_update_reference_cb, +++ pub push_negotiation: git_push_negotiation, +++ pub transport: git_transport_cb, +++ pub remote_ready: git_remote_ready_cb, +++ pub payload: *mut c_void, +++ pub resolve_url: git_url_resolve_cb, +++ pub update_refs: Option< +++ extern "C" fn( +++ *const c_char, +++ *const git_oid, +++ *const git_oid, +++ *mut git_refspec, +++ *mut c_void, +++ ) -> c_int, +++ >, +++} +++ +++#[repr(C)] +++pub struct git_fetch_options { +++ pub version: c_int, +++ pub callbacks: git_remote_callbacks, +++ pub prune: git_fetch_prune_t, +++ pub update_fetchhead: c_uint, +++ pub download_tags: git_remote_autotag_option_t, +++ pub proxy_opts: git_proxy_options, +++ pub depth: c_int, +++ pub follow_redirects: git_remote_redirect_t, +++ pub custom_headers: git_strarray, +++} +++ +++#[repr(C)] +++pub struct git_fetch_negotiation { +++ refs: *const *const git_remote_head, +++ refs_len: size_t, +++ shallow_roots: *mut git_oid, +++ shallow_roots_len: size_t, +++ depth: c_int, +++} +++ +++git_enum! { +++ pub enum git_remote_autotag_option_t { +++ GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, +++ GIT_REMOTE_DOWNLOAD_TAGS_AUTO, +++ GIT_REMOTE_DOWNLOAD_TAGS_NONE, +++ GIT_REMOTE_DOWNLOAD_TAGS_ALL, +++ } +++} +++ +++git_enum! { +++ pub enum git_fetch_prune_t { +++ GIT_FETCH_PRUNE_UNSPECIFIED, +++ GIT_FETCH_PRUNE, +++ GIT_FETCH_NO_PRUNE, +++ } +++} +++ +++git_enum! { +++ pub enum git_remote_completion_type { +++ GIT_REMOTE_COMPLETION_DOWNLOAD, +++ GIT_REMOTE_COMPLETION_INDEXING, +++ GIT_REMOTE_COMPLETION_ERROR, +++ } +++} +++ +++pub type git_transport_message_cb = +++ Option c_int>; +++pub type git_cred_acquire_cb = Option< +++ extern "C" fn(*mut *mut git_cred, *const c_char, *const c_char, c_uint, *mut c_void) -> c_int, +++>; +++pub type git_transfer_progress_cb = +++ Option c_int>; +++pub type git_packbuilder_progress = +++ Option c_int>; +++pub type git_push_transfer_progress = +++ Option c_int>; +++pub type git_transport_certificate_check_cb = +++ Option c_int>; +++pub type git_push_negotiation = +++ Option c_int>; +++ +++pub type git_push_update_reference_cb = +++ Option c_int>; +++pub type git_url_resolve_cb = +++ Option c_int>; +++ +++#[repr(C)] +++pub struct git_push_update { +++ pub src_refname: *mut c_char, +++ pub dst_refname: *mut c_char, +++ pub src: git_oid, +++ pub dst: git_oid, +++} +++ +++git_enum! { +++ pub enum git_cert_t { +++ GIT_CERT_NONE, +++ GIT_CERT_X509, +++ GIT_CERT_HOSTKEY_LIBSSH2, +++ GIT_CERT_STRARRAY, +++ } +++} +++ +++#[repr(C)] +++pub struct git_cert { +++ pub cert_type: git_cert_t, +++} +++ +++#[repr(C)] +++pub struct git_cert_hostkey { +++ pub parent: git_cert, +++ pub kind: git_cert_ssh_t, +++ pub hash_md5: [u8; 16], +++ pub hash_sha1: [u8; 20], +++ pub hash_sha256: [u8; 32], +++ pub raw_type: git_cert_ssh_raw_type_t, +++ pub hostkey: *const c_char, +++ pub hostkey_len: size_t, +++} +++ +++#[repr(C)] +++pub struct git_cert_x509 { +++ pub parent: git_cert, +++ pub data: *mut c_void, +++ pub len: size_t, +++} +++ +++git_enum! { +++ pub enum git_cert_ssh_t { +++ GIT_CERT_SSH_MD5 = 1 << 0, +++ GIT_CERT_SSH_SHA1 = 1 << 1, +++ GIT_CERT_SSH_SHA256 = 1 << 2, +++ GIT_CERT_SSH_RAW = 1 << 3, +++ } +++} +++ +++git_enum! { +++ pub enum git_cert_ssh_raw_type_t { +++ GIT_CERT_SSH_RAW_TYPE_UNKNOWN = 0, +++ GIT_CERT_SSH_RAW_TYPE_RSA = 1, +++ GIT_CERT_SSH_RAW_TYPE_DSS = 2, +++ GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_256 = 3, +++ GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_384 = 4, +++ GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_521 = 5, +++ GIT_CERT_SSH_RAW_TYPE_KEY_ED25519 = 6, +++ } +++} +++ +++git_enum! { +++ pub enum git_diff_flag_t { +++ GIT_DIFF_FLAG_BINARY = 1 << 0, +++ GIT_DIFF_FLAG_NOT_BINARY = 1 << 1, +++ GIT_DIFF_FLAG_VALID_ID = 1 << 2, +++ GIT_DIFF_FLAG_EXISTS = 1 << 3, +++ } +++} +++ +++#[repr(C)] +++pub struct git_diff_file { +++ pub id: git_oid, +++ pub path: *const c_char, +++ pub size: git_object_size_t, +++ pub flags: u32, +++ pub mode: u16, +++ pub id_abbrev: u16, +++} +++ +++pub type git_repository_create_cb = +++ Option c_int>; +++pub type git_remote_create_cb = Option< +++ extern "C" fn( +++ *mut *mut git_remote, +++ *mut git_repository, +++ *const c_char, +++ *const c_char, +++ *mut c_void, +++ ) -> c_int, +++>; +++ +++git_enum! { +++ pub enum git_checkout_notify_t { +++ GIT_CHECKOUT_NOTIFY_NONE = 0, +++ GIT_CHECKOUT_NOTIFY_CONFLICT = 1 << 0, +++ GIT_CHECKOUT_NOTIFY_DIRTY = 1 << 1, +++ GIT_CHECKOUT_NOTIFY_UPDATED = 1 << 2, +++ GIT_CHECKOUT_NOTIFY_UNTRACKED = 1 << 3, +++ GIT_CHECKOUT_NOTIFY_IGNORED = 1 << 4, +++ +++ GIT_CHECKOUT_NOTIFY_ALL = 0x0FFFF, +++ } +++} +++ +++git_enum! { +++ pub enum git_status_t { +++ GIT_STATUS_CURRENT = 0, +++ +++ GIT_STATUS_INDEX_NEW = 1 << 0, +++ GIT_STATUS_INDEX_MODIFIED = 1 << 1, +++ GIT_STATUS_INDEX_DELETED = 1 << 2, +++ GIT_STATUS_INDEX_RENAMED = 1 << 3, +++ GIT_STATUS_INDEX_TYPECHANGE = 1 << 4, +++ +++ GIT_STATUS_WT_NEW = 1 << 7, +++ GIT_STATUS_WT_MODIFIED = 1 << 8, +++ GIT_STATUS_WT_DELETED = 1 << 9, +++ GIT_STATUS_WT_TYPECHANGE = 1 << 10, +++ GIT_STATUS_WT_RENAMED = 1 << 11, +++ GIT_STATUS_WT_UNREADABLE = 1 << 12, +++ +++ GIT_STATUS_IGNORED = 1 << 14, +++ GIT_STATUS_CONFLICTED = 1 << 15, +++ } +++} +++ +++git_enum! { +++ pub enum git_status_opt_t { +++ GIT_STATUS_OPT_INCLUDE_UNTRACKED = 1 << 0, +++ GIT_STATUS_OPT_INCLUDE_IGNORED = 1 << 1, +++ GIT_STATUS_OPT_INCLUDE_UNMODIFIED = 1 << 2, +++ GIT_STATUS_OPT_EXCLUDE_SUBMODULES = 1 << 3, +++ GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS = 1 << 4, +++ GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH = 1 << 5, +++ GIT_STATUS_OPT_RECURSE_IGNORED_DIRS = 1 << 6, +++ GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX = 1 << 7, +++ GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR = 1 << 8, +++ GIT_STATUS_OPT_SORT_CASE_SENSITIVELY = 1 << 9, +++ GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY = 1 << 10, +++ +++ GIT_STATUS_OPT_RENAMES_FROM_REWRITES = 1 << 11, +++ GIT_STATUS_OPT_NO_REFRESH = 1 << 12, +++ GIT_STATUS_OPT_UPDATE_INDEX = 1 << 13, +++ GIT_STATUS_OPT_INCLUDE_UNREADABLE = 1 << 14, +++ GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED = 1 << 15, +++ } +++} +++ +++git_enum! { +++ pub enum git_status_show_t { +++ GIT_STATUS_SHOW_INDEX_AND_WORKDIR = 0, +++ GIT_STATUS_SHOW_INDEX_ONLY = 1, +++ GIT_STATUS_SHOW_WORKDIR_ONLY = 2, +++ } +++} +++ +++git_enum! { +++ pub enum git_delta_t { +++ GIT_DELTA_UNMODIFIED, +++ GIT_DELTA_ADDED, +++ GIT_DELTA_DELETED, +++ GIT_DELTA_MODIFIED, +++ GIT_DELTA_RENAMED, +++ GIT_DELTA_COPIED, +++ GIT_DELTA_IGNORED, +++ GIT_DELTA_UNTRACKED, +++ GIT_DELTA_TYPECHANGE, +++ GIT_DELTA_UNREADABLE, +++ GIT_DELTA_CONFLICTED, +++ } +++} +++ +++#[repr(C)] +++pub struct git_status_options { +++ pub version: c_uint, +++ pub show: git_status_show_t, +++ pub flags: c_uint, +++ pub pathspec: git_strarray, +++ pub baseline: *mut git_tree, +++ pub rename_threshold: u16, +++} +++ +++#[repr(C)] +++pub struct git_diff_delta { +++ pub status: git_delta_t, +++ pub flags: u32, +++ pub similarity: u16, +++ pub nfiles: u16, +++ pub old_file: git_diff_file, +++ pub new_file: git_diff_file, +++} +++ +++#[repr(C)] +++pub struct git_status_entry { +++ pub status: git_status_t, +++ pub head_to_index: *mut git_diff_delta, +++ pub index_to_workdir: *mut git_diff_delta, +++} +++ +++git_enum! { +++ pub enum git_checkout_strategy_t { +++ GIT_CHECKOUT_SAFE = 0, +++ GIT_CHECKOUT_FORCE = 1 << 1, +++ GIT_CHECKOUT_RECREATE_MISSING = 1 << 2, +++ GIT_CHECKOUT_ALLOW_CONFLICTS = 1 << 4, +++ GIT_CHECKOUT_REMOVE_UNTRACKED = 1 << 5, +++ GIT_CHECKOUT_REMOVE_IGNORED = 1 << 6, +++ GIT_CHECKOUT_UPDATE_ONLY = 1 << 7, +++ GIT_CHECKOUT_DONT_UPDATE_INDEX = 1 << 8, +++ GIT_CHECKOUT_NO_REFRESH = 1 << 9, +++ GIT_CHECKOUT_SKIP_UNMERGED = 1 << 10, +++ GIT_CHECKOUT_USE_OURS = 1 << 11, +++ GIT_CHECKOUT_USE_THEIRS = 1 << 12, +++ GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH = 1 << 13, +++ GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES = 1 << 18, +++ GIT_CHECKOUT_DONT_OVERWRITE_IGNORED = 1 << 19, +++ GIT_CHECKOUT_CONFLICT_STYLE_MERGE = 1 << 20, +++ GIT_CHECKOUT_CONFLICT_STYLE_DIFF3 = 1 << 21, +++ GIT_CHECKOUT_NONE = 1 << 30, +++ +++ GIT_CHECKOUT_UPDATE_SUBMODULES = 1 << 16, +++ GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED = 1 << 17, +++ } +++} +++ +++git_enum! { +++ pub enum git_reset_t { +++ GIT_RESET_SOFT = 1, +++ GIT_RESET_MIXED = 2, +++ GIT_RESET_HARD = 3, +++ } +++} +++ +++git_enum! { +++ pub enum git_object_t: c_int { +++ GIT_OBJECT_ANY = -2, +++ GIT_OBJECT_INVALID = -1, +++ GIT_OBJECT_COMMIT = 1, +++ GIT_OBJECT_TREE = 2, +++ GIT_OBJECT_BLOB = 3, +++ GIT_OBJECT_TAG = 4, +++ GIT_OBJECT_OFS_DELTA = 6, +++ GIT_OBJECT_REF_DELTA = 7, +++ } +++} +++ +++git_enum! { +++ pub enum git_reference_t { +++ GIT_REFERENCE_INVALID = 0, +++ GIT_REFERENCE_DIRECT = 1, +++ GIT_REFERENCE_SYMBOLIC = 2, +++ GIT_REFERENCE_ALL = GIT_REFERENCE_DIRECT | GIT_REFERENCE_SYMBOLIC, +++ } +++} +++ +++git_enum! { +++ pub enum git_filemode_t { +++ GIT_FILEMODE_UNREADABLE = 0o000000, +++ GIT_FILEMODE_TREE = 0o040000, +++ GIT_FILEMODE_BLOB = 0o100644, +++ GIT_FILEMODE_BLOB_GROUP_WRITABLE = 0o100664, +++ GIT_FILEMODE_BLOB_EXECUTABLE = 0o100755, +++ GIT_FILEMODE_LINK = 0o120000, +++ GIT_FILEMODE_COMMIT = 0o160000, +++ } +++} +++ +++git_enum! { +++ pub enum git_treewalk_mode { +++ GIT_TREEWALK_PRE = 0, +++ GIT_TREEWALK_POST = 1, +++ } +++} +++ +++pub type git_treewalk_cb = +++ extern "C" fn(*const c_char, *const git_tree_entry, *mut c_void) -> c_int; +++pub type git_treebuilder_filter_cb = +++ Option c_int>; +++ +++pub type git_revwalk_hide_cb = Option c_int>; +++ +++git_enum! { +++ pub enum git_tree_update_t { +++ GIT_TREE_UPDATE_UPSERT = 0, +++ GIT_TREE_UPDATE_REMOVE = 1, +++ } +++} +++ +++#[repr(C)] +++pub struct git_tree_update { +++ pub action: git_tree_update_t, +++ pub id: git_oid, +++ pub filemode: git_filemode_t, +++ pub path: *const c_char, +++} +++ +++#[repr(C)] +++#[derive(Copy, Clone)] +++pub struct git_buf { +++ pub ptr: *mut c_char, +++ pub reserved: size_t, +++ pub size: size_t, +++} +++ +++git_enum! { +++ pub enum git_branch_t { +++ GIT_BRANCH_LOCAL = 1, +++ GIT_BRANCH_REMOTE = 2, +++ GIT_BRANCH_ALL = GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE, +++ } +++} +++ +++pub const GIT_BLAME_NORMAL: u32 = 0; +++pub const GIT_BLAME_TRACK_COPIES_SAME_FILE: u32 = 1 << 0; +++pub const GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES: u32 = 1 << 1; +++pub const GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES: u32 = 1 << 2; +++pub const GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES: u32 = 1 << 3; +++pub const GIT_BLAME_FIRST_PARENT: u32 = 1 << 4; +++pub const GIT_BLAME_USE_MAILMAP: u32 = 1 << 5; +++pub const GIT_BLAME_IGNORE_WHITESPACE: u32 = 1 << 6; +++ +++#[repr(C)] +++#[derive(Copy, Clone)] +++pub struct git_blame_options { +++ pub version: c_uint, +++ +++ pub flags: u32, +++ pub min_match_characters: u16, +++ pub newest_commit: git_oid, +++ pub oldest_commit: git_oid, +++ pub min_line: usize, +++ pub max_line: usize, +++} +++ +++#[repr(C)] +++#[derive(Copy, Clone)] +++pub struct git_blame_hunk { +++ pub lines_in_hunk: usize, +++ pub final_commit_id: git_oid, +++ pub final_start_line_number: usize, +++ pub final_signature: *mut git_signature, +++ pub final_committer: *mut git_signature, +++ pub orig_commit_id: git_oid, +++ pub orig_path: *const c_char, +++ pub orig_start_line_number: usize, +++ pub orig_signature: *mut git_signature, +++ pub orig_committer: *mut git_signature, +++ pub summary: *const c_char, +++ pub boundary: c_char, +++} +++ +++pub type git_index_matched_path_cb = +++ Option c_int>; +++ +++git_enum! { +++ pub enum git_index_entry_extended_flag_t { +++ GIT_INDEX_ENTRY_INTENT_TO_ADD = 1 << 13, +++ GIT_INDEX_ENTRY_SKIP_WORKTREE = 1 << 14, +++ +++ GIT_INDEX_ENTRY_UPTODATE = 1 << 2, +++ } +++} +++ +++git_enum! { +++ pub enum git_index_entry_flag_t { +++ GIT_INDEX_ENTRY_EXTENDED = 0x4000, +++ GIT_INDEX_ENTRY_VALID = 0x8000, +++ } +++} +++ +++#[repr(C)] +++#[derive(Copy, Clone)] +++pub struct git_index_entry { +++ pub ctime: git_index_time, +++ pub mtime: git_index_time, +++ pub dev: u32, +++ pub ino: u32, +++ pub mode: u32, +++ pub uid: u32, +++ pub gid: u32, +++ pub file_size: u32, +++ pub id: git_oid, +++ pub flags: u16, +++ pub flags_extended: u16, +++ pub path: *const c_char, +++} +++ +++pub const GIT_INDEX_ENTRY_NAMEMASK: u16 = 0xfff; +++pub const GIT_INDEX_ENTRY_STAGEMASK: u16 = 0x3000; +++pub const GIT_INDEX_ENTRY_STAGESHIFT: u16 = 12; +++ +++#[repr(C)] +++#[derive(Copy, Clone, Debug, Eq, PartialEq)] +++pub struct git_index_time { +++ pub seconds: i32, +++ pub nanoseconds: u32, +++} +++ +++#[repr(C)] +++pub struct git_config_entry { +++ pub name: *const c_char, +++ pub value: *const c_char, +++ pub backend_type: *const c_char, +++ pub origin_path: *const c_char, +++ pub include_depth: c_uint, +++ pub level: git_config_level_t, +++} +++ +++git_enum! { +++ pub enum git_config_level_t: c_int { +++ GIT_CONFIG_LEVEL_PROGRAMDATA = 1, +++ GIT_CONFIG_LEVEL_SYSTEM = 2, +++ GIT_CONFIG_LEVEL_XDG = 3, +++ GIT_CONFIG_LEVEL_GLOBAL = 4, +++ GIT_CONFIG_LEVEL_LOCAL = 5, +++ GIT_CONFIG_LEVEL_WORKTREE = 6, +++ GIT_CONFIG_LEVEL_APP = 7, +++ GIT_CONFIG_HIGHEST_LEVEL = -1, +++ } +++} +++ +++git_enum! { +++ pub enum git_submodule_update_t { +++ GIT_SUBMODULE_UPDATE_CHECKOUT = 1, +++ GIT_SUBMODULE_UPDATE_REBASE = 2, +++ GIT_SUBMODULE_UPDATE_MERGE = 3, +++ GIT_SUBMODULE_UPDATE_NONE = 4, +++ GIT_SUBMODULE_UPDATE_DEFAULT = 0, +++ } +++} +++ +++git_enum! { +++ pub enum git_submodule_ignore_t: c_int { +++ GIT_SUBMODULE_IGNORE_UNSPECIFIED = -1, +++ +++ GIT_SUBMODULE_IGNORE_NONE = 1, +++ GIT_SUBMODULE_IGNORE_UNTRACKED = 2, +++ GIT_SUBMODULE_IGNORE_DIRTY = 3, +++ GIT_SUBMODULE_IGNORE_ALL = 4, +++ } +++} +++ +++pub type git_submodule_cb = +++ Option c_int>; +++ +++#[repr(C)] +++pub struct git_submodule_update_options { +++ pub version: c_uint, +++ pub checkout_opts: git_checkout_options, +++ pub fetch_opts: git_fetch_options, +++ pub allow_fetch: c_int, +++} +++ +++#[repr(C)] +++pub struct git_writestream { +++ pub write: Option c_int>, +++ pub close: Option c_int>, +++ pub free: Option, +++} +++ +++git_enum! { +++ pub enum git_attr_value_t { +++ GIT_ATTR_VALUE_UNSPECIFIED = 0, +++ GIT_ATTR_VALUE_TRUE, +++ GIT_ATTR_VALUE_FALSE, +++ GIT_ATTR_VALUE_STRING, +++ } +++} +++ +++pub const GIT_ATTR_CHECK_FILE_THEN_INDEX: u32 = 0; +++pub const GIT_ATTR_CHECK_INDEX_THEN_FILE: u32 = 1; +++pub const GIT_ATTR_CHECK_INDEX_ONLY: u32 = 2; +++pub const GIT_ATTR_CHECK_NO_SYSTEM: u32 = 1 << 2; +++pub const GIT_ATTR_CHECK_INCLUDE_HEAD: u32 = 1 << 3; +++ +++#[repr(C)] +++pub struct git_cred { +++ pub credtype: git_credtype_t, +++ pub free: Option, +++} +++ +++git_enum! { +++ pub enum git_credtype_t { +++ GIT_CREDTYPE_USERPASS_PLAINTEXT = 1 << 0, +++ GIT_CREDTYPE_SSH_KEY = 1 << 1, +++ GIT_CREDTYPE_SSH_CUSTOM = 1 << 2, +++ GIT_CREDTYPE_DEFAULT = 1 << 3, +++ GIT_CREDTYPE_SSH_INTERACTIVE = 1 << 4, +++ GIT_CREDTYPE_USERNAME = 1 << 5, +++ GIT_CREDTYPE_SSH_MEMORY = 1 << 6, +++ } +++} +++ +++pub type git_cred_ssh_interactive_callback = Option< +++ extern "C" fn( +++ name: *const c_char, +++ name_len: c_int, +++ instruction: *const c_char, +++ instruction_len: c_int, +++ num_prompts: c_int, +++ prompts: *const LIBSSH2_USERAUTH_KBDINT_PROMPT, +++ responses: *mut LIBSSH2_USERAUTH_KBDINT_RESPONSE, +++ abstrakt: *mut *mut c_void, +++ ), +++>; +++ +++pub type git_cred_sign_callback = Option< +++ extern "C" fn( +++ session: *mut LIBSSH2_SESSION, +++ sig: *mut *mut c_uchar, +++ sig_len: *mut size_t, +++ data: *const c_uchar, +++ data_len: size_t, +++ abstrakt: *mut *mut c_void, +++ ), +++>; +++ +++pub enum LIBSSH2_SESSION {} +++pub enum LIBSSH2_USERAUTH_KBDINT_PROMPT {} +++pub enum LIBSSH2_USERAUTH_KBDINT_RESPONSE {} +++ +++#[repr(C)] +++pub struct git_push_options { +++ pub version: c_uint, +++ pub pb_parallelism: c_uint, +++ pub callbacks: git_remote_callbacks, +++ pub proxy_opts: git_proxy_options, +++ pub follow_redirects: git_remote_redirect_t, +++ pub custom_headers: git_strarray, +++ pub remote_push_options: git_strarray, +++} +++ +++pub type git_tag_foreach_cb = +++ Option c_int>; +++ +++git_enum! { +++ pub enum git_index_add_option_t { +++ GIT_INDEX_ADD_DEFAULT = 0, +++ GIT_INDEX_ADD_FORCE = 1 << 0, +++ GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH = 1 << 1, +++ GIT_INDEX_ADD_CHECK_PATHSPEC = 1 << 2, +++ } +++} +++ +++git_enum! { +++ pub enum git_repository_open_flag_t { +++ GIT_REPOSITORY_OPEN_NO_SEARCH = 1 << 0, +++ GIT_REPOSITORY_OPEN_CROSS_FS = 1 << 1, +++ GIT_REPOSITORY_OPEN_BARE = 1 << 2, +++ GIT_REPOSITORY_OPEN_NO_DOTGIT = 1 << 3, +++ GIT_REPOSITORY_OPEN_FROM_ENV = 1 << 4, +++ } +++} +++ +++#[repr(C)] +++pub struct git_repository_init_options { +++ pub version: c_uint, +++ pub flags: u32, +++ pub mode: u32, +++ pub workdir_path: *const c_char, +++ pub description: *const c_char, +++ pub template_path: *const c_char, +++ pub initial_head: *const c_char, +++ pub origin_url: *const c_char, +++} +++ +++pub const GIT_REPOSITORY_INIT_OPTIONS_VERSION: c_uint = 1; +++ +++git_enum! { +++ pub enum git_repository_init_flag_t { +++ GIT_REPOSITORY_INIT_BARE = 1 << 0, +++ GIT_REPOSITORY_INIT_NO_REINIT = 1 << 1, +++ GIT_REPOSITORY_INIT_NO_DOTGIT_DIR = 1 << 2, +++ GIT_REPOSITORY_INIT_MKDIR = 1 << 3, +++ GIT_REPOSITORY_INIT_MKPATH = 1 << 4, +++ GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE = 1 << 5, +++ } +++} +++ +++git_enum! { +++ pub enum git_repository_init_mode_t { +++ GIT_REPOSITORY_INIT_SHARED_UMASK = 0, +++ GIT_REPOSITORY_INIT_SHARED_GROUP = 0o002775, +++ GIT_REPOSITORY_INIT_SHARED_ALL = 0o002777, +++ } +++} +++ +++git_enum! { +++ pub enum git_sort_t { +++ GIT_SORT_NONE = 0, +++ GIT_SORT_TOPOLOGICAL = 1 << 0, +++ GIT_SORT_TIME = 1 << 1, +++ GIT_SORT_REVERSE = 1 << 2, +++ } +++} +++ +++git_enum! { +++ pub enum git_submodule_status_t { +++ GIT_SUBMODULE_STATUS_IN_HEAD = 1 << 0, +++ GIT_SUBMODULE_STATUS_IN_INDEX = 1 << 1, +++ GIT_SUBMODULE_STATUS_IN_CONFIG = 1 << 2, +++ GIT_SUBMODULE_STATUS_IN_WD = 1 << 3, +++ GIT_SUBMODULE_STATUS_INDEX_ADDED = 1 << 4, +++ GIT_SUBMODULE_STATUS_INDEX_DELETED = 1 << 5, +++ GIT_SUBMODULE_STATUS_INDEX_MODIFIED = 1 << 6, +++ GIT_SUBMODULE_STATUS_WD_UNINITIALIZED = 1 << 7, +++ GIT_SUBMODULE_STATUS_WD_ADDED = 1 << 8, +++ GIT_SUBMODULE_STATUS_WD_DELETED = 1 << 9, +++ GIT_SUBMODULE_STATUS_WD_MODIFIED = 1 << 10, +++ GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED = 1 << 11, +++ GIT_SUBMODULE_STATUS_WD_WD_MODIFIED = 1 << 12, +++ GIT_SUBMODULE_STATUS_WD_UNTRACKED = 1 << 13, +++ } +++} +++ +++#[repr(C)] +++pub struct git_remote_head { +++ pub local: c_int, +++ pub oid: git_oid, +++ pub loid: git_oid, +++ pub name: *mut c_char, +++ pub symref_target: *mut c_char, +++} +++ +++git_enum! { +++ pub enum git_pathspec_flag_t { +++ GIT_PATHSPEC_DEFAULT = 0, +++ GIT_PATHSPEC_IGNORE_CASE = 1 << 0, +++ GIT_PATHSPEC_USE_CASE = 1 << 1, +++ GIT_PATHSPEC_NO_GLOB = 1 << 2, +++ GIT_PATHSPEC_NO_MATCH_ERROR = 1 << 3, +++ GIT_PATHSPEC_FIND_FAILURES = 1 << 4, +++ GIT_PATHSPEC_FAILURES_ONLY = 1 << 5, +++ } +++} +++ +++pub type git_diff_file_cb = Option c_int>; +++pub type git_diff_hunk_cb = +++ Option c_int>; +++pub type git_diff_line_cb = Option< +++ extern "C" fn( +++ *const git_diff_delta, +++ *const git_diff_hunk, +++ *const git_diff_line, +++ *mut c_void, +++ ) -> c_int, +++>; +++pub type git_diff_binary_cb = +++ Option c_int>; +++ +++#[repr(C)] +++pub struct git_diff_hunk { +++ pub old_start: c_int, +++ pub old_lines: c_int, +++ pub new_start: c_int, +++ pub new_lines: c_int, +++ pub header_len: size_t, +++ pub header: [c_char; 128], +++} +++ +++git_enum! { +++ pub enum git_diff_line_t { +++ GIT_DIFF_LINE_CONTEXT = b' ' as git_diff_line_t, +++ GIT_DIFF_LINE_ADDITION = b'+' as git_diff_line_t, +++ GIT_DIFF_LINE_DELETION = b'-' as git_diff_line_t, +++ GIT_DIFF_LINE_CONTEXT_EOFNL = b'=' as git_diff_line_t, +++ GIT_DIFF_LINE_ADD_EOFNL = b'>' as git_diff_line_t, +++ GIT_DIFF_LINE_DEL_EOFNL = b'<' as git_diff_line_t, +++ GIT_DIFF_LINE_FILE_HDR = b'F' as git_diff_line_t, +++ GIT_DIFF_LINE_HUNK_HDR = b'H' as git_diff_line_t, +++ GIT_DIFF_LINE_BINARY = b'B' as git_diff_line_t, +++ } +++} +++ +++#[repr(C)] +++pub struct git_diff_line { +++ pub origin: c_char, +++ pub old_lineno: c_int, +++ pub new_lineno: c_int, +++ pub num_lines: c_int, +++ pub content_len: size_t, +++ pub content_offset: git_off_t, +++ pub content: *const c_char, +++} +++ +++#[repr(C)] +++pub struct git_diff_options { +++ pub version: c_uint, +++ pub flags: u32, +++ pub ignore_submodules: git_submodule_ignore_t, +++ pub pathspec: git_strarray, +++ pub notify_cb: git_diff_notify_cb, +++ pub progress_cb: git_diff_progress_cb, +++ pub payload: *mut c_void, +++ pub context_lines: u32, +++ pub interhunk_lines: u32, +++ pub oid_type: git_oid_t, +++ pub id_abbrev: u16, +++ pub max_size: git_off_t, +++ pub old_prefix: *const c_char, +++ pub new_prefix: *const c_char, +++} +++ +++git_enum! { +++ pub enum git_oid_t { +++ GIT_OID_SHA1 = 1, +++ // SHA256 is still experimental so we are not going to enable it. +++ /* GIT_OID_SHA256 = 2, */ +++ } +++} +++ +++git_enum! { +++ pub enum git_diff_format_t { +++ GIT_DIFF_FORMAT_PATCH = 1, +++ GIT_DIFF_FORMAT_PATCH_HEADER = 2, +++ GIT_DIFF_FORMAT_RAW = 3, +++ GIT_DIFF_FORMAT_NAME_ONLY = 4, +++ GIT_DIFF_FORMAT_NAME_STATUS = 5, +++ GIT_DIFF_FORMAT_PATCH_ID = 6, +++ } +++} +++ +++git_enum! { +++ pub enum git_diff_stats_format_t { +++ GIT_DIFF_STATS_NONE = 0, +++ GIT_DIFF_STATS_FULL = 1 << 0, +++ GIT_DIFF_STATS_SHORT = 1 << 1, +++ GIT_DIFF_STATS_NUMBER = 1 << 2, +++ GIT_DIFF_STATS_INCLUDE_SUMMARY = 1 << 3, +++ } +++} +++ +++pub type git_diff_notify_cb = Option< +++ extern "C" fn(*const git_diff, *const git_diff_delta, *const c_char, *mut c_void) -> c_int, +++>; +++ +++pub type git_diff_progress_cb = +++ Option c_int>; +++ +++git_enum! { +++ pub enum git_diff_option_t { +++ GIT_DIFF_NORMAL = 0, +++ GIT_DIFF_REVERSE = 1 << 0, +++ GIT_DIFF_INCLUDE_IGNORED = 1 << 1, +++ GIT_DIFF_RECURSE_IGNORED_DIRS = 1 << 2, +++ GIT_DIFF_INCLUDE_UNTRACKED = 1 << 3, +++ GIT_DIFF_RECURSE_UNTRACKED_DIRS = 1 << 4, +++ GIT_DIFF_INCLUDE_UNMODIFIED = 1 << 5, +++ GIT_DIFF_INCLUDE_TYPECHANGE = 1 << 6, +++ GIT_DIFF_INCLUDE_TYPECHANGE_TREES = 1 << 7, +++ GIT_DIFF_IGNORE_FILEMODE = 1 << 8, +++ GIT_DIFF_IGNORE_SUBMODULES = 1 << 9, +++ GIT_DIFF_IGNORE_CASE = 1 << 10, +++ GIT_DIFF_DISABLE_PATHSPEC_MATCH = 1 << 12, +++ GIT_DIFF_SKIP_BINARY_CHECK = 1 << 13, +++ GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS = 1 << 14, +++ GIT_DIFF_UPDATE_INDEX = 1 << 15, +++ GIT_DIFF_INCLUDE_UNREADABLE = 1 << 16, +++ GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED = 1 << 17, +++ GIT_DIFF_INDENT_HEURISTIC = 1 << 18, +++ GIT_DIFF_IGNORE_BLANK_LINES = 1 << 19, +++ GIT_DIFF_FORCE_TEXT = 1 << 20, +++ GIT_DIFF_FORCE_BINARY = 1 << 21, +++ GIT_DIFF_IGNORE_WHITESPACE = 1 << 22, +++ GIT_DIFF_IGNORE_WHITESPACE_CHANGE = 1 << 23, +++ GIT_DIFF_IGNORE_WHITESPACE_EOL = 1 << 24, +++ GIT_DIFF_SHOW_UNTRACKED_CONTENT = 1 << 25, +++ GIT_DIFF_SHOW_UNMODIFIED = 1 << 26, +++ GIT_DIFF_PATIENCE = 1 << 28, +++ GIT_DIFF_MINIMAL = 1 << 29, +++ GIT_DIFF_SHOW_BINARY = 1 << 30, +++ } +++} +++ +++#[repr(C)] +++pub struct git_diff_find_options { +++ pub version: c_uint, +++ pub flags: u32, +++ pub rename_threshold: u16, +++ pub rename_from_rewrite_threshold: u16, +++ pub copy_threshold: u16, +++ pub break_rewrite_threshold: u16, +++ pub rename_limit: size_t, +++ pub metric: *mut git_diff_similarity_metric, +++} +++ +++#[repr(C)] +++pub struct git_diff_similarity_metric { +++ pub file_signature: Option< +++ extern "C" fn(*mut *mut c_void, *const git_diff_file, *const c_char, *mut c_void) -> c_int, +++ >, +++ pub buffer_signature: Option< +++ extern "C" fn( +++ *mut *mut c_void, +++ *const git_diff_file, +++ *const c_char, +++ size_t, +++ *mut c_void, +++ ) -> c_int, +++ >, +++ pub free_signature: Option, +++ pub similarity: +++ Option c_int>, +++ pub payload: *mut c_void, +++} +++ +++pub const GIT_DIFF_FIND_OPTIONS_VERSION: c_uint = 1; +++ +++pub const GIT_DIFF_FIND_BY_CONFIG: u32 = 0; +++pub const GIT_DIFF_FIND_RENAMES: u32 = 1 << 0; +++pub const GIT_DIFF_FIND_RENAMES_FROM_REWRITES: u32 = 1 << 1; +++pub const GIT_DIFF_FIND_COPIES: u32 = 1 << 2; +++pub const GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED: u32 = 1 << 3; +++pub const GIT_DIFF_FIND_REWRITES: u32 = 1 << 4; +++pub const GIT_DIFF_BREAK_REWRITES: u32 = 1 << 5; +++pub const GIT_DIFF_FIND_AND_BREAK_REWRITES: u32 = GIT_DIFF_FIND_REWRITES | GIT_DIFF_BREAK_REWRITES; +++pub const GIT_DIFF_FIND_FOR_UNTRACKED: u32 = 1 << 6; +++pub const GIT_DIFF_FIND_ALL: u32 = 0x0ff; +++pub const GIT_DIFF_FIND_IGNORE_LEADING_WHITESPACE: u32 = 0; +++pub const GIT_DIFF_FIND_IGNORE_WHITESPACE: u32 = 1 << 12; +++pub const GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE: u32 = 1 << 13; +++pub const GIT_DIFF_FIND_EXACT_MATCH_ONLY: u32 = 1 << 14; +++pub const GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY: u32 = 1 << 15; +++pub const GIT_DIFF_FIND_REMOVE_UNMODIFIED: u32 = 1 << 16; +++ +++#[repr(C)] +++pub struct git_diff_format_email_options { +++ pub version: c_uint, +++ pub flags: u32, +++ pub patch_no: usize, +++ pub total_patches: usize, +++ pub id: *const git_oid, +++ pub summary: *const c_char, +++ pub body: *const c_char, +++ pub author: *const git_signature, +++} +++ +++pub const GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION: c_uint = 1; +++ +++pub const GIT_DIFF_FORMAT_EMAIL_NONE: u32 = 0; +++pub const GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER: u32 = 1 << 0; +++ +++#[repr(C)] +++pub struct git_diff_patchid_options { +++ pub version: c_uint, +++} +++ +++pub const GIT_DIFF_PATCHID_OPTIONS_VERSION: c_uint = 1; +++ +++#[repr(C)] +++pub struct git_diff_binary { +++ pub contains_data: c_uint, +++ pub old_file: git_diff_binary_file, +++ pub new_file: git_diff_binary_file, +++} +++ +++#[repr(C)] +++pub struct git_diff_binary_file { +++ pub kind: git_diff_binary_t, +++ pub data: *const c_char, +++ pub datalen: size_t, +++ pub inflatedlen: size_t, +++} +++ +++git_enum! { +++ pub enum git_diff_binary_t { +++ GIT_DIFF_BINARY_NONE, +++ GIT_DIFF_BINARY_LITERAL, +++ GIT_DIFF_BINARY_DELTA, +++ } +++} +++ +++#[repr(C)] +++pub struct git_merge_options { +++ pub version: c_uint, +++ pub flags: u32, +++ pub rename_threshold: c_uint, +++ pub target_limit: c_uint, +++ pub metric: *mut git_diff_similarity_metric, +++ pub recursion_limit: c_uint, +++ pub default_driver: *const c_char, +++ pub file_favor: git_merge_file_favor_t, +++ pub file_flags: u32, +++} +++ +++git_enum! { +++ pub enum git_merge_flag_t { +++ GIT_MERGE_FIND_RENAMES = 1 << 0, +++ GIT_MERGE_FAIL_ON_CONFLICT = 1 << 1, +++ GIT_MERGE_SKIP_REUC = 1 << 2, +++ GIT_MERGE_NO_RECURSIVE = 1 << 3, +++ } +++} +++ +++git_enum! { +++ pub enum git_merge_file_favor_t { +++ GIT_MERGE_FILE_FAVOR_NORMAL = 0, +++ GIT_MERGE_FILE_FAVOR_OURS = 1, +++ GIT_MERGE_FILE_FAVOR_THEIRS = 2, +++ GIT_MERGE_FILE_FAVOR_UNION = 3, +++ } +++} +++ +++git_enum! { +++ pub enum git_merge_file_flag_t { +++ GIT_MERGE_FILE_DEFAULT = 0, +++ GIT_MERGE_FILE_STYLE_MERGE = 1 << 0, +++ GIT_MERGE_FILE_STYLE_DIFF3 = 1 << 1, +++ GIT_MERGE_FILE_SIMPLIFY_ALNUM = 1 << 2, +++ GIT_MERGE_FILE_IGNORE_WHITESPACE = 1 << 3, +++ GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE = 1 << 4, +++ GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL = 1 << 5, +++ GIT_MERGE_FILE_DIFF_PATIENCE = 1 << 6, +++ GIT_MERGE_FILE_DIFF_MINIMAL = 1 << 7, +++ } +++} +++ +++git_enum! { +++ pub enum git_merge_analysis_t { +++ GIT_MERGE_ANALYSIS_NONE = 0, +++ GIT_MERGE_ANALYSIS_NORMAL = 1 << 0, +++ GIT_MERGE_ANALYSIS_UP_TO_DATE = 1 << 1, +++ GIT_MERGE_ANALYSIS_FASTFORWARD = 1 << 2, +++ GIT_MERGE_ANALYSIS_UNBORN = 1 << 3, +++ } +++} +++ +++git_enum! { +++ pub enum git_merge_preference_t { +++ GIT_MERGE_PREFERENCE_NONE = 0, +++ GIT_MERGE_PREFERENCE_NO_FASTFORWARD = 1 << 0, +++ GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY = 1 << 1, +++ } +++} +++ +++pub type git_transport_cb = Option< +++ extern "C" fn( +++ out: *mut *mut git_transport, +++ owner: *mut git_remote, +++ param: *mut c_void, +++ ) -> c_int, +++>; +++ +++#[repr(C)] +++pub struct git_transport { +++ pub version: c_uint, +++ pub connect: Option< +++ extern "C" fn( +++ transport: *mut git_transport, +++ url: *const c_char, +++ direction: c_int, +++ connect_opts: *const git_remote_connect_options, +++ ) -> c_int, +++ >, +++ pub set_connect_opts: Option< +++ extern "C" fn( +++ transport: *mut git_transport, +++ connect_opts: *const git_remote_connect_options, +++ ) -> c_int, +++ >, +++ pub capabilities: +++ Option c_int>, +++ pub ls: Option< +++ extern "C" fn( +++ out: *mut *mut *const git_remote_head, +++ size: *mut size_t, +++ transport: *mut git_transport, +++ ) -> c_int, +++ >, +++ pub push: Option c_int>, +++ pub negotiate_fetch: Option< +++ extern "C" fn( +++ transport: *mut git_transport, +++ repo: *mut git_repository, +++ fetch_data: *const git_fetch_negotiation, +++ ) -> c_int, +++ >, +++ pub shallow_roots: +++ Option c_int>, +++ pub download_pack: Option< +++ extern "C" fn( +++ transport: *mut git_transport, +++ repo: *mut git_repository, +++ stats: *mut git_indexer_progress, +++ ) -> c_int, +++ >, +++ pub is_connected: Option c_int>, +++ pub cancel: Option, +++ pub close: Option c_int>, +++ pub free: Option, +++} +++ +++#[repr(C)] +++pub struct git_remote_connect_options { +++ pub version: c_uint, +++ pub callbacks: git_remote_callbacks, +++ pub proxy_opts: git_proxy_options, +++ pub follow_redirects: git_remote_redirect_t, +++ pub custom_headers: git_strarray, +++} +++ +++git_enum! { +++ pub enum git_remote_redirect_t { +++ GIT_REMOTE_REDIRECT_NONE = 1 << 0, +++ GIT_REMOTE_REDIRECT_INITIAL = 1 << 1, +++ GIT_REMOTE_REDIRECT_ALL = 1 << 2, +++ } +++} +++ +++#[repr(C)] +++pub struct git_odb_backend { +++ pub version: c_uint, +++ pub odb: *mut git_odb, +++ pub read: Option< +++ extern "C" fn( +++ *mut *mut c_void, +++ *mut size_t, +++ *mut git_object_t, +++ *mut git_odb_backend, +++ *const git_oid, +++ ) -> c_int, +++ >, +++ +++ pub read_prefix: Option< +++ extern "C" fn( +++ *mut git_oid, +++ *mut *mut c_void, +++ *mut size_t, +++ *mut git_object_t, +++ *mut git_odb_backend, +++ *const git_oid, +++ size_t, +++ ) -> c_int, +++ >, +++ pub read_header: Option< +++ extern "C" fn( +++ *mut size_t, +++ *mut git_object_t, +++ *mut git_odb_backend, +++ *const git_oid, +++ ) -> c_int, +++ >, +++ +++ pub write: Option< +++ extern "C" fn( +++ *mut git_odb_backend, +++ *const git_oid, +++ *const c_void, +++ size_t, +++ git_object_t, +++ ) -> c_int, +++ >, +++ +++ pub writestream: Option< +++ extern "C" fn( +++ *mut *mut git_odb_stream, +++ *mut git_odb_backend, +++ git_object_size_t, +++ git_object_t, +++ ) -> c_int, +++ >, +++ +++ pub readstream: Option< +++ extern "C" fn( +++ *mut *mut git_odb_stream, +++ *mut size_t, +++ *mut git_object_t, +++ *mut git_odb_backend, +++ *const git_oid, +++ ) -> c_int, +++ >, +++ +++ pub exists: Option c_int>, +++ +++ pub exists_prefix: +++ Option c_int>, +++ +++ pub refresh: Option c_int>, +++ +++ pub foreach: +++ Option c_int>, +++ +++ pub writepack: Option< +++ extern "C" fn( +++ *mut *mut git_odb_writepack, +++ *mut git_odb_backend, +++ *mut git_odb, +++ git_indexer_progress_cb, +++ *mut c_void, +++ ) -> c_int, +++ >, +++ +++ pub writemidx: Option c_int>, +++ +++ pub freshen: Option c_int>, +++ +++ pub free: Option, +++} +++ +++git_enum! { +++ pub enum git_odb_lookup_flags_t { +++ GIT_ODB_LOOKUP_NO_REFRESH = 1 << 0, +++ } +++} +++ +++#[repr(C)] +++pub struct git_odb_writepack { +++ pub backend: *mut git_odb_backend, +++ +++ pub append: Option< +++ extern "C" fn( +++ *mut git_odb_writepack, +++ *const c_void, +++ size_t, +++ *mut git_indexer_progress, +++ ) -> c_int, +++ >, +++ +++ pub commit: +++ Option c_int>, +++ +++ pub free: Option, +++} +++ +++#[repr(C)] +++pub struct git_refdb_backend { +++ pub version: c_uint, +++ pub exists: Option c_int>, +++ pub lookup: Option< +++ extern "C" fn(*mut *mut git_reference, *mut git_refdb_backend, *const c_char) -> c_int, +++ >, +++ pub iterator: Option< +++ extern "C" fn( +++ *mut *mut git_reference_iterator, +++ *mut git_refdb_backend, +++ *const c_char, +++ ) -> c_int, +++ >, +++ pub write: Option< +++ extern "C" fn( +++ *mut git_refdb_backend, +++ *const git_reference, +++ c_int, +++ *const git_signature, +++ *const c_char, +++ *const git_oid, +++ *const c_char, +++ ) -> c_int, +++ >, +++ pub rename: Option< +++ extern "C" fn( +++ *mut *mut git_reference, +++ *mut git_refdb_backend, +++ *const c_char, +++ *const c_char, +++ c_int, +++ *const git_signature, +++ *const c_char, +++ ) -> c_int, +++ >, +++ pub del: Option< +++ extern "C" fn( +++ *mut git_refdb_backend, +++ *const c_char, +++ *const git_oid, +++ *const c_char, +++ ) -> c_int, +++ >, +++ pub compress: Option c_int>, +++ pub has_log: Option c_int>, +++ pub ensure_log: Option c_int>, +++ pub free: Option, +++ pub reflog_read: +++ Option c_int>, +++ pub reflog_write: Option c_int>, +++ pub reflog_rename: +++ Option c_int>, +++ pub reflog_delete: Option c_int>, +++ pub lock: +++ Option c_int>, +++ pub unlock: Option< +++ extern "C" fn( +++ *mut git_refdb_backend, +++ *mut c_void, +++ c_int, +++ c_int, +++ *const git_reference, +++ *const git_signature, +++ *const c_char, +++ ) -> c_int, +++ >, +++} +++ +++#[repr(C)] +++pub struct git_proxy_options { +++ pub version: c_uint, +++ pub kind: git_proxy_t, +++ pub url: *const c_char, +++ pub credentials: git_cred_acquire_cb, +++ pub certificate_check: git_transport_certificate_check_cb, +++ pub payload: *mut c_void, +++} +++ +++git_enum! { +++ pub enum git_proxy_t { +++ GIT_PROXY_NONE = 0, +++ GIT_PROXY_AUTO = 1, +++ GIT_PROXY_SPECIFIED = 2, +++ } +++} +++ +++git_enum! { +++ pub enum git_smart_service_t { +++ GIT_SERVICE_UPLOADPACK_LS = 1, +++ GIT_SERVICE_UPLOADPACK = 2, +++ GIT_SERVICE_RECEIVEPACK_LS = 3, +++ GIT_SERVICE_RECEIVEPACK = 4, +++ } +++} +++ +++#[repr(C)] +++pub struct git_smart_subtransport_stream { +++ pub subtransport: *mut git_smart_subtransport, +++ pub read: Option< +++ extern "C" fn( +++ *mut git_smart_subtransport_stream, +++ *mut c_char, +++ size_t, +++ *mut size_t, +++ ) -> c_int, +++ >, +++ pub write: +++ Option c_int>, +++ pub free: Option, +++} +++ +++#[repr(C)] +++pub struct git_smart_subtransport { +++ pub action: Option< +++ extern "C" fn( +++ *mut *mut git_smart_subtransport_stream, +++ *mut git_smart_subtransport, +++ *const c_char, +++ git_smart_service_t, +++ ) -> c_int, +++ >, +++ pub close: Option c_int>, +++ pub free: Option, +++} +++ +++pub type git_smart_subtransport_cb = Option< +++ extern "C" fn(*mut *mut git_smart_subtransport, *mut git_transport, *mut c_void) -> c_int, +++>; +++ +++#[repr(C)] +++pub struct git_smart_subtransport_definition { +++ pub callback: git_smart_subtransport_cb, +++ pub rpc: c_uint, +++ pub param: *mut c_void, +++} +++ +++#[repr(C)] +++pub struct git_describe_options { +++ pub version: c_uint, +++ pub max_candidates_tags: c_uint, +++ pub describe_strategy: c_uint, +++ pub pattern: *const c_char, +++ pub only_follow_first_parent: c_int, +++ pub show_commit_oid_as_fallback: c_int, +++} +++ +++git_enum! { +++ pub enum git_describe_strategy_t { +++ GIT_DESCRIBE_DEFAULT, +++ GIT_DESCRIBE_TAGS, +++ GIT_DESCRIBE_ALL, +++ } +++} +++ +++#[repr(C)] +++pub struct git_describe_format_options { +++ pub version: c_uint, +++ pub abbreviated_size: c_uint, +++ pub always_use_long_format: c_int, +++ pub dirty_suffix: *const c_char, +++} +++ +++git_enum! { +++ pub enum git_packbuilder_stage_t { +++ GIT_PACKBUILDER_ADDING_OBJECTS, +++ GIT_PACKBUILDER_DELTAFICATION, +++ } +++} +++ +++git_enum! { +++ pub enum git_stash_flags { +++ GIT_STASH_DEFAULT = 0, +++ GIT_STASH_KEEP_INDEX = 1 << 0, +++ GIT_STASH_INCLUDE_UNTRACKED = 1 << 1, +++ GIT_STASH_INCLUDE_IGNORED = 1 << 2, +++ GIT_STASH_KEEP_ALL = 1 << 3, +++ } +++} +++ +++git_enum! { +++ pub enum git_stash_apply_flags { +++ GIT_STASH_APPLY_DEFAULT = 0, +++ GIT_STASH_APPLY_REINSTATE_INDEX = 1 << 0, +++ } +++} +++ +++git_enum! { +++ pub enum git_stash_apply_progress_t { +++ GIT_STASH_APPLY_PROGRESS_NONE = 0, +++ GIT_STASH_APPLY_PROGRESS_LOADING_STASH, +++ GIT_STASH_APPLY_PROGRESS_ANALYZE_INDEX, +++ GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED, +++ GIT_STASH_APPLY_PROGRESS_ANALYZE_UNTRACKED, +++ GIT_STASH_APPLY_PROGRESS_CHECKOUT_UNTRACKED, +++ GIT_STASH_APPLY_PROGRESS_CHECKOUT_MODIFIED, +++ GIT_STASH_APPLY_PROGRESS_DONE, +++ } +++} +++ +++#[repr(C)] +++pub struct git_stash_save_options { +++ pub version: c_uint, +++ pub flags: u32, +++ pub stasher: *const git_signature, +++ pub message: *const c_char, +++ pub paths: git_strarray, +++} +++ +++pub const GIT_STASH_SAVE_OPTIONS_VERSION: c_uint = 1; +++ +++#[repr(C)] +++pub struct git_stash_apply_options { +++ pub version: c_uint, +++ pub flags: u32, +++ pub checkout_options: git_checkout_options, +++ pub progress_cb: git_stash_apply_progress_cb, +++ pub progress_payload: *mut c_void, +++} +++ +++pub type git_stash_apply_progress_cb = +++ Option c_int>; +++ +++pub type git_stash_cb = Option< +++ extern "C" fn( +++ index: size_t, +++ message: *const c_char, +++ stash_id: *const git_oid, +++ payload: *mut c_void, +++ ) -> c_int, +++>; +++ +++pub type git_packbuilder_foreach_cb = +++ Option c_int>; +++ +++pub type git_odb_foreach_cb = +++ Option c_int>; +++ +++pub type git_commit_signing_cb = Option< +++ extern "C" fn( +++ signature: *mut git_buf, +++ signature_field: *mut git_buf, +++ commit_content: *const c_char, +++ payload: *mut c_void, +++ ) -> c_int, +++>; +++ +++pub type git_commit_create_cb = Option< +++ extern "C" fn( +++ *mut git_oid, +++ *const git_signature, +++ *const git_signature, +++ *const c_char, +++ *const c_char, +++ *const git_tree, +++ usize, +++ *const git_commit, +++ *mut c_void, +++ ) -> c_int, +++>; +++ +++pub const GIT_REBASE_NO_OPERATION: usize = usize::max_value(); +++ +++#[repr(C)] +++pub struct git_rebase_options { +++ pub version: c_uint, +++ pub quiet: c_int, +++ pub inmemory: c_int, +++ pub rewrite_notes_ref: *const c_char, +++ pub merge_options: git_merge_options, +++ pub checkout_options: git_checkout_options, +++ pub commit_create_cb: git_commit_create_cb, +++ pub signing_cb: git_commit_signing_cb, +++ pub payload: *mut c_void, +++} +++ +++git_enum! { +++ pub enum git_rebase_operation_t { +++ GIT_REBASE_OPERATION_PICK = 0, +++ GIT_REBASE_OPERATION_REWORD, +++ GIT_REBASE_OPERATION_EDIT, +++ GIT_REBASE_OPERATION_SQUASH, +++ GIT_REBASE_OPERATION_FIXUP, +++ GIT_REBASE_OPERATION_EXEC, +++ } +++} +++ +++#[repr(C)] +++pub struct git_rebase_operation { +++ pub kind: git_rebase_operation_t, +++ pub id: git_oid, +++ pub exec: *const c_char, +++} +++ +++#[repr(C)] +++pub struct git_cherrypick_options { +++ pub version: c_uint, +++ pub mainline: c_uint, +++ pub merge_opts: git_merge_options, +++ pub checkout_opts: git_checkout_options, +++} +++ +++pub type git_revert_options = git_cherrypick_options; +++ +++pub type git_apply_delta_cb = +++ Option c_int>; +++ +++pub type git_apply_hunk_cb = +++ Option c_int>; +++ +++git_enum! { +++ pub enum git_apply_flags_t { +++ GIT_APPLY_CHECK = 1<<0, +++ } +++} +++ +++#[repr(C)] +++pub struct git_apply_options { +++ pub version: c_uint, +++ pub delta_cb: git_apply_delta_cb, +++ pub hunk_cb: git_apply_hunk_cb, +++ pub payload: *mut c_void, +++ pub flags: u32, +++} +++ +++git_enum! { +++ pub enum git_apply_location_t { +++ GIT_APPLY_LOCATION_WORKDIR = 0, +++ GIT_APPLY_LOCATION_INDEX = 1, +++ GIT_APPLY_LOCATION_BOTH = 2, +++ } +++} +++ +++git_enum! { +++ pub enum git_libgit2_opt_t { +++ GIT_OPT_GET_MWINDOW_SIZE = 0, +++ GIT_OPT_SET_MWINDOW_SIZE, +++ GIT_OPT_GET_MWINDOW_MAPPED_LIMIT, +++ GIT_OPT_SET_MWINDOW_MAPPED_LIMIT, +++ GIT_OPT_GET_SEARCH_PATH, +++ GIT_OPT_SET_SEARCH_PATH, +++ GIT_OPT_SET_CACHE_OBJECT_LIMIT, +++ GIT_OPT_SET_CACHE_MAX_SIZE, +++ GIT_OPT_ENABLE_CACHING, +++ GIT_OPT_GET_CACHED_MEMORY, +++ GIT_OPT_GET_TEMPLATE_PATH, +++ GIT_OPT_SET_TEMPLATE_PATH, +++ GIT_OPT_SET_SSL_CERT_LOCATIONS, +++ GIT_OPT_SET_USER_AGENT, +++ GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, +++ GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, +++ GIT_OPT_SET_SSL_CIPHERS, +++ GIT_OPT_GET_USER_AGENT, +++ GIT_OPT_ENABLE_OFS_DELTA, +++ GIT_OPT_ENABLE_FSYNC_GITDIR, +++ GIT_OPT_GET_WINDOWS_SHAREMODE, +++ GIT_OPT_SET_WINDOWS_SHAREMODE, +++ GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, +++ GIT_OPT_SET_ALLOCATOR, +++ GIT_OPT_ENABLE_UNSAVED_INDEX_SAFETY, +++ GIT_OPT_GET_PACK_MAX_OBJECTS, +++ GIT_OPT_SET_PACK_MAX_OBJECTS, +++ GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS, +++ GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE, +++ GIT_OPT_GET_MWINDOW_FILE_LIMIT, +++ GIT_OPT_SET_MWINDOW_FILE_LIMIT, +++ GIT_OPT_SET_ODB_PACKED_PRIORITY, +++ GIT_OPT_SET_ODB_LOOSE_PRIORITY, +++ GIT_OPT_GET_EXTENSIONS, +++ GIT_OPT_SET_EXTENSIONS, +++ GIT_OPT_GET_OWNER_VALIDATION, +++ GIT_OPT_SET_OWNER_VALIDATION, +++ GIT_OPT_GET_HOMEDIR, +++ GIT_OPT_SET_HOMEDIR, +++ GIT_OPT_SET_SERVER_CONNECT_TIMEOUT, +++ GIT_OPT_GET_SERVER_CONNECT_TIMEOUT, +++ GIT_OPT_SET_SERVER_TIMEOUT, +++ GIT_OPT_GET_SERVER_TIMEOUT, +++ GIT_OPT_SET_USER_AGENT_PRODUCT, +++ GIT_OPT_GET_USER_AGENT_PRODUCT, +++ } +++} +++ +++git_enum! { +++ pub enum git_reference_format_t { +++ GIT_REFERENCE_FORMAT_NORMAL = 0, +++ GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL = 1 << 0, +++ GIT_REFERENCE_FORMAT_REFSPEC_PATTERN = 1 << 1, +++ GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND = 1 << 2, +++ } +++} +++ +++#[repr(C)] +++pub struct git_worktree_add_options { +++ pub version: c_uint, +++ pub lock: c_int, +++ pub checkout_existing: c_int, +++ pub reference: *mut git_reference, +++ pub checkout_options: git_checkout_options, +++} +++ +++pub const GIT_WORKTREE_ADD_OPTIONS_VERSION: c_uint = 1; +++ +++git_enum! { +++ pub enum git_worktree_prune_t { +++ /* Prune working tree even if working tree is valid */ +++ GIT_WORKTREE_PRUNE_VALID = 1 << 0, +++ /* Prune working tree even if it is locked */ +++ GIT_WORKTREE_PRUNE_LOCKED = 1 << 1, +++ /* Prune checked out working tree */ +++ GIT_WORKTREE_PRUNE_WORKING_TREE = 1 << 2, +++ } +++} +++ +++#[repr(C)] +++pub struct git_worktree_prune_options { +++ pub version: c_uint, +++ pub flags: u32, +++} +++ +++pub const GIT_WORKTREE_PRUNE_OPTIONS_VERSION: c_uint = 1; +++ +++pub type git_repository_mergehead_foreach_cb = +++ Option c_int>; +++ +++pub type git_repository_fetchhead_foreach_cb = Option< +++ extern "C" fn(*const c_char, *const c_char, *const git_oid, c_uint, *mut c_void) -> c_int, +++>; +++ +++git_enum! { +++ pub enum git_trace_level_t { +++ /* No tracing will be performed. */ +++ GIT_TRACE_NONE = 0, +++ +++ /* Severe errors that may impact the program's execution */ +++ GIT_TRACE_FATAL = 1, +++ +++ /* Errors that do not impact the program's execution */ +++ GIT_TRACE_ERROR = 2, +++ +++ /* Warnings that suggest abnormal data */ +++ GIT_TRACE_WARN = 3, +++ +++ /* Informational messages about program execution */ +++ GIT_TRACE_INFO = 4, +++ +++ /* Detailed data that allows for debugging */ +++ GIT_TRACE_DEBUG = 5, +++ +++ /* Exceptionally detailed debugging data */ +++ GIT_TRACE_TRACE = 6, +++ } +++} +++ +++pub type git_trace_cb = Option; +++ +++git_enum! { +++ pub enum git_feature_t { +++ GIT_FEATURE_THREADS = 1 << 0, +++ GIT_FEATURE_HTTPS = 1 << 1, +++ GIT_FEATURE_SSH = 1 << 2, +++ GIT_FEATURE_NSEC = 1 << 3, +++ } +++} +++ +++#[repr(C)] +++pub struct git_message_trailer { +++ pub key: *const c_char, +++ pub value: *const c_char, +++} +++ +++#[repr(C)] +++#[derive(Copy, Clone)] +++pub struct git_message_trailer_array { +++ pub trailers: *mut git_message_trailer, +++ pub count: size_t, +++ pub _trailer_block: *mut c_char, +++} +++ +++#[repr(C)] +++pub struct git_email_create_options { +++ pub version: c_uint, +++ pub flags: u32, +++ pub diff_opts: git_diff_options, +++ pub diff_find_opts: git_diff_find_options, +++ pub subject_prefix: *const c_char, +++ pub start_number: usize, +++ pub reroll_number: usize, +++} +++ +++pub const GIT_EMAIL_CREATE_OPTIONS_VERSION: c_uint = 1; +++ +++git_enum! { +++ pub enum git_email_create_flags_t { +++ GIT_EMAIL_CREATE_DEFAULT = 0, +++ GIT_EMAIL_CREATE_OMIT_NUMBERS = 1 << 0, +++ GIT_EMAIL_CREATE_ALWAYS_NUMBER = 1 << 1, +++ GIT_EMAIL_CREATE_NO_RENAMES = 1 << 2, +++ } +++} +++ +++extern "C" { +++ // threads +++ pub fn git_libgit2_init() -> c_int; +++ pub fn git_libgit2_shutdown() -> c_int; +++ +++ // repository +++ pub fn git_repository_new(out: *mut *mut git_repository) -> c_int; +++ pub fn git_repository_free(repo: *mut git_repository); +++ pub fn git_repository_open(repo: *mut *mut git_repository, path: *const c_char) -> c_int; +++ pub fn git_repository_open_bare(repo: *mut *mut git_repository, path: *const c_char) -> c_int; +++ pub fn git_repository_open_ext( +++ repo: *mut *mut git_repository, +++ path: *const c_char, +++ flags: c_uint, +++ ceiling_dirs: *const c_char, +++ ) -> c_int; +++ pub fn git_repository_open_from_worktree( +++ repo: *mut *mut git_repository, +++ worktree: *mut git_worktree, +++ ) -> c_int; +++ pub fn git_repository_wrap_odb(repo: *mut *mut git_repository, odb: *mut git_odb) -> c_int; +++ pub fn git_repository_init( +++ repo: *mut *mut git_repository, +++ path: *const c_char, +++ is_bare: c_uint, +++ ) -> c_int; +++ pub fn git_repository_init_ext( +++ out: *mut *mut git_repository, +++ repo_path: *const c_char, +++ opts: *mut git_repository_init_options, +++ ) -> c_int; +++ pub fn git_repository_init_init_options( +++ opts: *mut git_repository_init_options, +++ version: c_uint, +++ ) -> c_int; +++ pub fn git_repository_get_namespace(repo: *mut git_repository) -> *const c_char; +++ pub fn git_repository_set_namespace( +++ repo: *mut git_repository, +++ namespace: *const c_char, +++ ) -> c_int; +++ pub fn git_repository_head(out: *mut *mut git_reference, repo: *mut git_repository) -> c_int; +++ pub fn git_repository_set_head(repo: *mut git_repository, refname: *const c_char) -> c_int; +++ +++ pub fn git_repository_head_detached(repo: *mut git_repository) -> c_int; +++ pub fn git_repository_set_head_detached( +++ repo: *mut git_repository, +++ commitish: *const git_oid, +++ ) -> c_int; +++ pub fn git_repository_set_head_detached_from_annotated( +++ repo: *mut git_repository, +++ commitish: *const git_annotated_commit, +++ ) -> c_int; +++ pub fn git_repository_set_bare(repo: *mut git_repository) -> c_int; +++ pub fn git_repository_is_worktree(repo: *const git_repository) -> c_int; +++ pub fn git_repository_is_bare(repo: *const git_repository) -> c_int; +++ pub fn git_repository_is_empty(repo: *mut git_repository) -> c_int; +++ pub fn git_repository_is_shallow(repo: *mut git_repository) -> c_int; +++ pub fn git_repository_path(repo: *const git_repository) -> *const c_char; +++ pub fn git_repository_commondir(repo: *const git_repository) -> *const c_char; +++ pub fn git_repository_state(repo: *mut git_repository) -> c_int; +++ pub fn git_repository_workdir(repo: *const git_repository) -> *const c_char; +++ pub fn git_repository_set_workdir( +++ repo: *mut git_repository, +++ workdir: *const c_char, +++ update_gitlink: c_int, +++ ) -> c_int; +++ pub fn git_repository_index(out: *mut *mut git_index, repo: *mut git_repository) -> c_int; +++ pub fn git_repository_set_index(repo: *mut git_repository, index: *mut git_index) -> c_int; +++ +++ pub fn git_repository_message(buf: *mut git_buf, repo: *mut git_repository) -> c_int; +++ +++ pub fn git_repository_message_remove(repo: *mut git_repository) -> c_int; +++ pub fn git_repository_config(out: *mut *mut git_config, repo: *mut git_repository) -> c_int; +++ pub fn git_repository_set_config(repo: *mut git_repository, config: *mut git_config) -> c_int; +++ pub fn git_repository_config_snapshot( +++ out: *mut *mut git_config, +++ repo: *mut git_repository, +++ ) -> c_int; +++ pub fn git_repository_discover( +++ out: *mut git_buf, +++ start_path: *const c_char, +++ across_fs: c_int, +++ ceiling_dirs: *const c_char, +++ ) -> c_int; +++ pub fn git_repository_set_odb(repo: *mut git_repository, odb: *mut git_odb) -> c_int; +++ +++ pub fn git_repository_refdb(out: *mut *mut git_refdb, repo: *mut git_repository) -> c_int; +++ pub fn git_repository_set_refdb(repo: *mut git_repository, refdb: *mut git_refdb) -> c_int; +++ +++ pub fn git_repository_reinit_filesystem( +++ repo: *mut git_repository, +++ recurse_submodules: c_int, +++ ) -> c_int; +++ pub fn git_repository_mergehead_foreach( +++ repo: *mut git_repository, +++ callback: git_repository_mergehead_foreach_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_repository_fetchhead_foreach( +++ repo: *mut git_repository, +++ callback: git_repository_fetchhead_foreach_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_ignore_add_rule(repo: *mut git_repository, rules: *const c_char) -> c_int; +++ pub fn git_ignore_clear_internal_rules(repo: *mut git_repository) -> c_int; +++ pub fn git_ignore_path_is_ignored( +++ ignored: *mut c_int, +++ repo: *mut git_repository, +++ path: *const c_char, +++ ) -> c_int; +++ +++ // revparse +++ pub fn git_revparse( +++ revspec: *mut git_revspec, +++ repo: *mut git_repository, +++ spec: *const c_char, +++ ) -> c_int; +++ pub fn git_revparse_single( +++ out: *mut *mut git_object, +++ repo: *mut git_repository, +++ spec: *const c_char, +++ ) -> c_int; +++ pub fn git_revparse_ext( +++ object_out: *mut *mut git_object, +++ reference_out: *mut *mut git_reference, +++ repo: *mut git_repository, +++ spec: *const c_char, +++ ) -> c_int; +++ +++ // object +++ pub fn git_object_dup(dest: *mut *mut git_object, source: *mut git_object) -> c_int; +++ pub fn git_object_id(obj: *const git_object) -> *const git_oid; +++ pub fn git_object_free(object: *mut git_object); +++ pub fn git_object_lookup( +++ dest: *mut *mut git_object, +++ repo: *mut git_repository, +++ id: *const git_oid, +++ kind: git_object_t, +++ ) -> c_int; +++ pub fn git_object_lookup_prefix( +++ dest: *mut *mut git_object, +++ repo: *mut git_repository, +++ id: *const git_oid, +++ len: size_t, +++ kind: git_object_t, +++ ) -> c_int; +++ pub fn git_object_type(obj: *const git_object) -> git_object_t; +++ pub fn git_object_peel( +++ peeled: *mut *mut git_object, +++ object: *const git_object, +++ target_type: git_object_t, +++ ) -> c_int; +++ pub fn git_object_short_id(out: *mut git_buf, obj: *const git_object) -> c_int; +++ pub fn git_object_type2string(kind: git_object_t) -> *const c_char; +++ pub fn git_object_string2type(s: *const c_char) -> git_object_t; +++ pub fn git_object_typeisloose(kind: git_object_t) -> c_int; +++ +++ // oid +++ pub fn git_oid_fromraw(out: *mut git_oid, raw: *const c_uchar) -> c_int; +++ pub fn git_oid_fromstrn(out: *mut git_oid, str: *const c_char, len: size_t) -> c_int; +++ pub fn git_oid_tostr(out: *mut c_char, n: size_t, id: *const git_oid) -> *mut c_char; +++ pub fn git_oid_cmp(a: *const git_oid, b: *const git_oid) -> c_int; +++ pub fn git_oid_equal(a: *const git_oid, b: *const git_oid) -> c_int; +++ pub fn git_oid_streq(id: *const git_oid, str: *const c_char) -> c_int; +++ pub fn git_oid_iszero(id: *const git_oid) -> c_int; +++ +++ // error +++ pub fn git_error_last() -> *const git_error; +++ pub fn git_error_clear(); +++ pub fn git_error_set_str(error_class: c_int, string: *const c_char) -> c_int; +++ +++ // remote +++ pub fn git_remote_create( +++ out: *mut *mut git_remote, +++ repo: *mut git_repository, +++ name: *const c_char, +++ url: *const c_char, +++ ) -> c_int; +++ pub fn git_remote_create_with_fetchspec( +++ out: *mut *mut git_remote, +++ repo: *mut git_repository, +++ name: *const c_char, +++ url: *const c_char, +++ fetch: *const c_char, +++ ) -> c_int; +++ pub fn git_remote_lookup( +++ out: *mut *mut git_remote, +++ repo: *mut git_repository, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_remote_create_anonymous( +++ out: *mut *mut git_remote, +++ repo: *mut git_repository, +++ url: *const c_char, +++ ) -> c_int; +++ pub fn git_remote_create_detached(out: *mut *mut git_remote, url: *const c_char) -> c_int; +++ pub fn git_remote_delete(repo: *mut git_repository, name: *const c_char) -> c_int; +++ pub fn git_remote_free(remote: *mut git_remote); +++ pub fn git_remote_name(remote: *const git_remote) -> *const c_char; +++ pub fn git_remote_pushurl(remote: *const git_remote) -> *const c_char; +++ pub fn git_remote_refspec_count(remote: *const git_remote) -> size_t; +++ pub fn git_remote_url(remote: *const git_remote) -> *const c_char; +++ pub fn git_remote_connect( +++ remote: *mut git_remote, +++ dir: git_direction, +++ callbacks: *const git_remote_callbacks, +++ proxy_opts: *const git_proxy_options, +++ custom_headers: *const git_strarray, +++ ) -> c_int; +++ pub fn git_remote_connected(remote: *const git_remote) -> c_int; +++ pub fn git_remote_disconnect(remote: *mut git_remote) -> c_int; +++ pub fn git_remote_add_fetch( +++ repo: *mut git_repository, +++ remote: *const c_char, +++ refspec: *const c_char, +++ ) -> c_int; +++ pub fn git_remote_add_push( +++ repo: *mut git_repository, +++ remote: *const c_char, +++ refspec: *const c_char, +++ ) -> c_int; +++ pub fn git_remote_download( +++ remote: *mut git_remote, +++ refspecs: *const git_strarray, +++ opts: *const git_fetch_options, +++ ) -> c_int; +++ pub fn git_remote_stop(remote: *mut git_remote) -> c_int; +++ pub fn git_remote_dup(dest: *mut *mut git_remote, source: *mut git_remote) -> c_int; +++ pub fn git_remote_get_fetch_refspecs( +++ array: *mut git_strarray, +++ remote: *const git_remote, +++ ) -> c_int; +++ pub fn git_remote_get_push_refspecs( +++ array: *mut git_strarray, +++ remote: *const git_remote, +++ ) -> c_int; +++ pub fn git_remote_get_refspec(remote: *const git_remote, n: size_t) -> *const git_refspec; +++ pub fn git_remote_is_valid_name(remote_name: *const c_char) -> c_int; +++ pub fn git_remote_name_is_valid(valid: *mut c_int, remote_name: *const c_char) -> c_int; +++ pub fn git_remote_list(out: *mut git_strarray, repo: *mut git_repository) -> c_int; +++ pub fn git_remote_rename( +++ problems: *mut git_strarray, +++ repo: *mut git_repository, +++ name: *const c_char, +++ new_name: *const c_char, +++ ) -> c_int; +++ pub fn git_remote_fetch( +++ remote: *mut git_remote, +++ refspecs: *const git_strarray, +++ opts: *const git_fetch_options, +++ reflog_message: *const c_char, +++ ) -> c_int; +++ pub fn git_remote_push( +++ remote: *mut git_remote, +++ refspecs: *const git_strarray, +++ opts: *const git_push_options, +++ ) -> c_int; +++ pub fn git_remote_update_tips( +++ remote: *mut git_remote, +++ callbacks: *const git_remote_callbacks, +++ update_flags: c_uint, +++ download_tags: git_remote_autotag_option_t, +++ reflog_message: *const c_char, +++ ) -> c_int; +++ pub fn git_remote_set_url( +++ repo: *mut git_repository, +++ remote: *const c_char, +++ url: *const c_char, +++ ) -> c_int; +++ pub fn git_remote_set_pushurl( +++ repo: *mut git_repository, +++ remote: *const c_char, +++ pushurl: *const c_char, +++ ) -> c_int; +++ pub fn git_remote_init_callbacks(opts: *mut git_remote_callbacks, version: c_uint) -> c_int; +++ pub fn git_fetch_init_options(opts: *mut git_fetch_options, version: c_uint) -> c_int; +++ pub fn git_remote_stats(remote: *mut git_remote) -> *const git_indexer_progress; +++ pub fn git_remote_ls( +++ out: *mut *mut *const git_remote_head, +++ size: *mut size_t, +++ remote: *mut git_remote, +++ ) -> c_int; +++ pub fn git_remote_set_autotag( +++ repo: *mut git_repository, +++ remote: *const c_char, +++ value: git_remote_autotag_option_t, +++ ) -> c_int; +++ pub fn git_remote_prune( +++ remote: *mut git_remote, +++ callbacks: *const git_remote_callbacks, +++ ) -> c_int; +++ pub fn git_remote_default_branch(out: *mut git_buf, remote: *mut git_remote) -> c_int; +++ +++ // refspec +++ pub fn git_refspec_direction(spec: *const git_refspec) -> git_direction; +++ pub fn git_refspec_dst(spec: *const git_refspec) -> *const c_char; +++ pub fn git_refspec_dst_matches(spec: *const git_refspec, refname: *const c_char) -> c_int; +++ pub fn git_refspec_src(spec: *const git_refspec) -> *const c_char; +++ pub fn git_refspec_src_matches(spec: *const git_refspec, refname: *const c_char) -> c_int; +++ pub fn git_refspec_force(spec: *const git_refspec) -> c_int; +++ pub fn git_refspec_string(spec: *const git_refspec) -> *const c_char; +++ pub fn git_refspec_transform( +++ out: *mut git_buf, +++ spec: *const git_refspec, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_refspec_rtransform( +++ out: *mut git_buf, +++ spec: *const git_refspec, +++ name: *const c_char, +++ ) -> c_int; +++ +++ // strarray +++ pub fn git_strarray_free(array: *mut git_strarray); +++ +++ // oidarray +++ pub fn git_oidarray_free(array: *mut git_oidarray); +++ +++ // signature +++ pub fn git_signature_default(out: *mut *mut git_signature, repo: *mut git_repository) -> c_int; +++ pub fn git_signature_free(sig: *mut git_signature); +++ pub fn git_signature_new( +++ out: *mut *mut git_signature, +++ name: *const c_char, +++ email: *const c_char, +++ time: git_time_t, +++ offset: c_int, +++ ) -> c_int; +++ pub fn git_signature_now( +++ out: *mut *mut git_signature, +++ name: *const c_char, +++ email: *const c_char, +++ ) -> c_int; +++ pub fn git_signature_dup(dest: *mut *mut git_signature, sig: *const git_signature) -> c_int; +++ +++ // status +++ pub fn git_status_list_new( +++ out: *mut *mut git_status_list, +++ repo: *mut git_repository, +++ options: *const git_status_options, +++ ) -> c_int; +++ pub fn git_status_list_entrycount(list: *mut git_status_list) -> size_t; +++ pub fn git_status_byindex( +++ statuslist: *mut git_status_list, +++ idx: size_t, +++ ) -> *const git_status_entry; +++ pub fn git_status_list_free(list: *mut git_status_list); +++ pub fn git_status_init_options(opts: *mut git_status_options, version: c_uint) -> c_int; +++ pub fn git_status_file( +++ status_flags: *mut c_uint, +++ repo: *mut git_repository, +++ path: *const c_char, +++ ) -> c_int; +++ pub fn git_status_should_ignore( +++ ignored: *mut c_int, +++ repo: *mut git_repository, +++ path: *const c_char, +++ ) -> c_int; +++ +++ // clone +++ pub fn git_clone( +++ out: *mut *mut git_repository, +++ url: *const c_char, +++ local_path: *const c_char, +++ options: *const git_clone_options, +++ ) -> c_int; +++ pub fn git_clone_init_options(opts: *mut git_clone_options, version: c_uint) -> c_int; +++ +++ // reset +++ pub fn git_reset( +++ repo: *mut git_repository, +++ target: *const git_object, +++ reset_type: git_reset_t, +++ checkout_opts: *const git_checkout_options, +++ ) -> c_int; +++ pub fn git_reset_default( +++ repo: *mut git_repository, +++ target: *const git_object, +++ pathspecs: *const git_strarray, +++ ) -> c_int; +++ +++ // reference +++ pub fn git_reference_cmp(ref1: *const git_reference, ref2: *const git_reference) -> c_int; +++ pub fn git_reference_delete(r: *mut git_reference) -> c_int; +++ pub fn git_reference_free(r: *mut git_reference); +++ pub fn git_reference_is_branch(r: *const git_reference) -> c_int; +++ pub fn git_reference_is_note(r: *const git_reference) -> c_int; +++ pub fn git_reference_is_remote(r: *const git_reference) -> c_int; +++ pub fn git_reference_is_tag(r: *const git_reference) -> c_int; +++ pub fn git_reference_is_valid_name(name: *const c_char) -> c_int; +++ pub fn git_reference_name_is_valid(valid: *mut c_int, refname: *const c_char) -> c_int; +++ pub fn git_reference_lookup( +++ out: *mut *mut git_reference, +++ repo: *mut git_repository, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_reference_dwim( +++ out: *mut *mut git_reference, +++ repo: *mut git_repository, +++ refname: *const c_char, +++ ) -> c_int; +++ pub fn git_reference_name(r: *const git_reference) -> *const c_char; +++ pub fn git_reference_name_to_id( +++ out: *mut git_oid, +++ repo: *mut git_repository, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_reference_peel( +++ out: *mut *mut git_object, +++ r: *const git_reference, +++ otype: git_object_t, +++ ) -> c_int; +++ pub fn git_reference_rename( +++ new_ref: *mut *mut git_reference, +++ r: *mut git_reference, +++ new_name: *const c_char, +++ force: c_int, +++ log_message: *const c_char, +++ ) -> c_int; +++ pub fn git_reference_resolve(out: *mut *mut git_reference, r: *const git_reference) -> c_int; +++ pub fn git_reference_shorthand(r: *const git_reference) -> *const c_char; +++ pub fn git_reference_symbolic_target(r: *const git_reference) -> *const c_char; +++ pub fn git_reference_target(r: *const git_reference) -> *const git_oid; +++ pub fn git_reference_target_peel(r: *const git_reference) -> *const git_oid; +++ pub fn git_reference_set_target( +++ out: *mut *mut git_reference, +++ r: *mut git_reference, +++ id: *const git_oid, +++ log_message: *const c_char, +++ ) -> c_int; +++ pub fn git_reference_symbolic_set_target( +++ out: *mut *mut git_reference, +++ r: *mut git_reference, +++ target: *const c_char, +++ log_message: *const c_char, +++ ) -> c_int; +++ pub fn git_reference_type(r: *const git_reference) -> git_reference_t; +++ pub fn git_reference_iterator_new( +++ out: *mut *mut git_reference_iterator, +++ repo: *mut git_repository, +++ ) -> c_int; +++ pub fn git_reference_iterator_glob_new( +++ out: *mut *mut git_reference_iterator, +++ repo: *mut git_repository, +++ glob: *const c_char, +++ ) -> c_int; +++ pub fn git_reference_iterator_free(iter: *mut git_reference_iterator); +++ pub fn git_reference_next( +++ out: *mut *mut git_reference, +++ iter: *mut git_reference_iterator, +++ ) -> c_int; +++ pub fn git_reference_next_name( +++ out: *mut *const c_char, +++ iter: *mut git_reference_iterator, +++ ) -> c_int; +++ pub fn git_reference_create( +++ out: *mut *mut git_reference, +++ repo: *mut git_repository, +++ name: *const c_char, +++ id: *const git_oid, +++ force: c_int, +++ log_message: *const c_char, +++ ) -> c_int; +++ pub fn git_reference_symbolic_create( +++ out: *mut *mut git_reference, +++ repo: *mut git_repository, +++ name: *const c_char, +++ target: *const c_char, +++ force: c_int, +++ log_message: *const c_char, +++ ) -> c_int; +++ pub fn git_reference_create_matching( +++ out: *mut *mut git_reference, +++ repo: *mut git_repository, +++ name: *const c_char, +++ id: *const git_oid, +++ force: c_int, +++ current_id: *const git_oid, +++ log_message: *const c_char, +++ ) -> c_int; +++ pub fn git_reference_symbolic_create_matching( +++ out: *mut *mut git_reference, +++ repo: *mut git_repository, +++ name: *const c_char, +++ target: *const c_char, +++ force: c_int, +++ current_id: *const c_char, +++ log_message: *const c_char, +++ ) -> c_int; +++ pub fn git_reference_has_log(repo: *mut git_repository, name: *const c_char) -> c_int; +++ pub fn git_reference_ensure_log(repo: *mut git_repository, name: *const c_char) -> c_int; +++ pub fn git_reference_normalize_name( +++ buffer_out: *mut c_char, +++ buffer_size: size_t, +++ name: *const c_char, +++ flags: u32, +++ ) -> c_int; +++ +++ // stash +++ pub fn git_stash_save( +++ out: *mut git_oid, +++ repo: *mut git_repository, +++ stasher: *const git_signature, +++ message: *const c_char, +++ flags: c_uint, +++ ) -> c_int; +++ +++ pub fn git_stash_save_options_init(opts: *mut git_stash_save_options, version: c_uint) +++ -> c_int; +++ +++ pub fn git_stash_save_with_opts( +++ out: *mut git_oid, +++ repo: *mut git_repository, +++ options: *const git_stash_save_options, +++ ) -> c_int; +++ +++ pub fn git_stash_apply_init_options( +++ opts: *mut git_stash_apply_options, +++ version: c_uint, +++ ) -> c_int; +++ +++ pub fn git_stash_apply( +++ repo: *mut git_repository, +++ index: size_t, +++ options: *const git_stash_apply_options, +++ ) -> c_int; +++ +++ pub fn git_stash_foreach( +++ repo: *mut git_repository, +++ callback: git_stash_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ +++ pub fn git_stash_drop(repo: *mut git_repository, index: size_t) -> c_int; +++ +++ pub fn git_stash_pop( +++ repo: *mut git_repository, +++ index: size_t, +++ options: *const git_stash_apply_options, +++ ) -> c_int; +++ +++ // submodules +++ pub fn git_submodule_add_finalize(submodule: *mut git_submodule) -> c_int; +++ pub fn git_submodule_add_setup( +++ submodule: *mut *mut git_submodule, +++ repo: *mut git_repository, +++ url: *const c_char, +++ path: *const c_char, +++ use_gitlink: c_int, +++ ) -> c_int; +++ pub fn git_submodule_add_to_index(submodule: *mut git_submodule, write_index: c_int) -> c_int; +++ pub fn git_submodule_branch(submodule: *mut git_submodule) -> *const c_char; +++ pub fn git_submodule_clone( +++ repo: *mut *mut git_repository, +++ submodule: *mut git_submodule, +++ opts: *const git_submodule_update_options, +++ ) -> c_int; +++ pub fn git_submodule_foreach( +++ repo: *mut git_repository, +++ callback: git_submodule_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_submodule_free(submodule: *mut git_submodule); +++ pub fn git_submodule_head_id(submodule: *mut git_submodule) -> *const git_oid; +++ pub fn git_submodule_ignore(submodule: *mut git_submodule) -> git_submodule_ignore_t; +++ pub fn git_submodule_index_id(submodule: *mut git_submodule) -> *const git_oid; +++ pub fn git_submodule_init(submodule: *mut git_submodule, overwrite: c_int) -> c_int; +++ pub fn git_submodule_repo_init( +++ repo: *mut *mut git_repository, +++ submodule: *const git_submodule, +++ use_gitlink: c_int, +++ ) -> c_int; +++ pub fn git_submodule_location(status: *mut c_uint, submodule: *mut git_submodule) -> c_int; +++ pub fn git_submodule_lookup( +++ out: *mut *mut git_submodule, +++ repo: *mut git_repository, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_submodule_name(submodule: *mut git_submodule) -> *const c_char; +++ pub fn git_submodule_open( +++ repo: *mut *mut git_repository, +++ submodule: *mut git_submodule, +++ ) -> c_int; +++ pub fn git_submodule_path(submodule: *mut git_submodule) -> *const c_char; +++ pub fn git_submodule_reload(submodule: *mut git_submodule, force: c_int) -> c_int; +++ pub fn git_submodule_set_ignore( +++ repo: *mut git_repository, +++ name: *const c_char, +++ ignore: git_submodule_ignore_t, +++ ) -> c_int; +++ pub fn git_submodule_set_update( +++ repo: *mut git_repository, +++ name: *const c_char, +++ update: git_submodule_update_t, +++ ) -> c_int; +++ pub fn git_submodule_set_url( +++ repo: *mut git_repository, +++ name: *const c_char, +++ url: *const c_char, +++ ) -> c_int; +++ pub fn git_submodule_sync(submodule: *mut git_submodule) -> c_int; +++ pub fn git_submodule_update_strategy(submodule: *mut git_submodule) -> git_submodule_update_t; +++ pub fn git_submodule_update( +++ submodule: *mut git_submodule, +++ init: c_int, +++ options: *mut git_submodule_update_options, +++ ) -> c_int; +++ pub fn git_submodule_update_init_options( +++ options: *mut git_submodule_update_options, +++ version: c_uint, +++ ) -> c_int; +++ pub fn git_submodule_url(submodule: *mut git_submodule) -> *const c_char; +++ pub fn git_submodule_wd_id(submodule: *mut git_submodule) -> *const git_oid; +++ pub fn git_submodule_status( +++ status: *mut c_uint, +++ repo: *mut git_repository, +++ name: *const c_char, +++ ignore: git_submodule_ignore_t, +++ ) -> c_int; +++ pub fn git_submodule_set_branch( +++ repo: *mut git_repository, +++ name: *const c_char, +++ branch: *const c_char, +++ ) -> c_int; +++ +++ // blob +++ pub fn git_blob_free(blob: *mut git_blob); +++ pub fn git_blob_id(blob: *const git_blob) -> *const git_oid; +++ pub fn git_blob_is_binary(blob: *const git_blob) -> c_int; +++ pub fn git_blob_lookup( +++ blob: *mut *mut git_blob, +++ repo: *mut git_repository, +++ id: *const git_oid, +++ ) -> c_int; +++ pub fn git_blob_lookup_prefix( +++ blob: *mut *mut git_blob, +++ repo: *mut git_repository, +++ id: *const git_oid, +++ len: size_t, +++ ) -> c_int; +++ pub fn git_blob_rawcontent(blob: *const git_blob) -> *const c_void; +++ pub fn git_blob_rawsize(blob: *const git_blob) -> git_object_size_t; +++ pub fn git_blob_create_frombuffer( +++ id: *mut git_oid, +++ repo: *mut git_repository, +++ buffer: *const c_void, +++ len: size_t, +++ ) -> c_int; +++ pub fn git_blob_create_fromdisk( +++ id: *mut git_oid, +++ repo: *mut git_repository, +++ path: *const c_char, +++ ) -> c_int; +++ pub fn git_blob_create_fromworkdir( +++ id: *mut git_oid, +++ repo: *mut git_repository, +++ relative_path: *const c_char, +++ ) -> c_int; +++ pub fn git_blob_create_fromstream( +++ out: *mut *mut git_writestream, +++ repo: *mut git_repository, +++ hintpath: *const c_char, +++ ) -> c_int; +++ pub fn git_blob_create_fromstream_commit( +++ id: *mut git_oid, +++ stream: *mut git_writestream, +++ ) -> c_int; +++ +++ // tree +++ pub fn git_tree_entry_byid(tree: *const git_tree, id: *const git_oid) -> *const git_tree_entry; +++ pub fn git_tree_entry_byindex(tree: *const git_tree, idx: size_t) -> *const git_tree_entry; +++ pub fn git_tree_entry_byname( +++ tree: *const git_tree, +++ filename: *const c_char, +++ ) -> *const git_tree_entry; +++ pub fn git_tree_entry_bypath( +++ out: *mut *mut git_tree_entry, +++ tree: *const git_tree, +++ filename: *const c_char, +++ ) -> c_int; +++ pub fn git_tree_entry_cmp(e1: *const git_tree_entry, e2: *const git_tree_entry) -> c_int; +++ pub fn git_tree_entry_dup(dest: *mut *mut git_tree_entry, src: *const git_tree_entry) -> c_int; +++ pub fn git_tree_entry_filemode(entry: *const git_tree_entry) -> git_filemode_t; +++ pub fn git_tree_entry_filemode_raw(entry: *const git_tree_entry) -> git_filemode_t; +++ pub fn git_tree_entry_free(entry: *mut git_tree_entry); +++ pub fn git_tree_entry_id(entry: *const git_tree_entry) -> *const git_oid; +++ pub fn git_tree_entry_name(entry: *const git_tree_entry) -> *const c_char; +++ pub fn git_tree_entry_to_object( +++ out: *mut *mut git_object, +++ repo: *mut git_repository, +++ entry: *const git_tree_entry, +++ ) -> c_int; +++ pub fn git_tree_entry_type(entry: *const git_tree_entry) -> git_object_t; +++ pub fn git_tree_entrycount(tree: *const git_tree) -> size_t; +++ pub fn git_tree_free(tree: *mut git_tree); +++ pub fn git_tree_id(tree: *const git_tree) -> *const git_oid; +++ pub fn git_tree_lookup( +++ tree: *mut *mut git_tree, +++ repo: *mut git_repository, +++ id: *const git_oid, +++ ) -> c_int; +++ pub fn git_tree_walk( +++ tree: *const git_tree, +++ mode: git_treewalk_mode, +++ callback: git_treewalk_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_tree_create_updated( +++ out: *mut git_oid, +++ repo: *mut git_repository, +++ baseline: *mut git_tree, +++ nupdates: usize, +++ updates: *const git_tree_update, +++ ) -> c_int; +++ +++ // treebuilder +++ pub fn git_treebuilder_new( +++ out: *mut *mut git_treebuilder, +++ repo: *mut git_repository, +++ source: *const git_tree, +++ ) -> c_int; +++ pub fn git_treebuilder_clear(bld: *mut git_treebuilder) -> c_int; +++ pub fn git_treebuilder_entrycount(bld: *mut git_treebuilder) -> size_t; +++ pub fn git_treebuilder_free(bld: *mut git_treebuilder); +++ pub fn git_treebuilder_get( +++ bld: *mut git_treebuilder, +++ filename: *const c_char, +++ ) -> *const git_tree_entry; +++ pub fn git_treebuilder_insert( +++ out: *mut *const git_tree_entry, +++ bld: *mut git_treebuilder, +++ filename: *const c_char, +++ id: *const git_oid, +++ filemode: git_filemode_t, +++ ) -> c_int; +++ pub fn git_treebuilder_remove(bld: *mut git_treebuilder, filename: *const c_char) -> c_int; +++ pub fn git_treebuilder_filter( +++ bld: *mut git_treebuilder, +++ filter: git_treebuilder_filter_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_treebuilder_write(id: *mut git_oid, bld: *mut git_treebuilder) -> c_int; +++ +++ // buf +++ pub fn git_buf_dispose(buffer: *mut git_buf); +++ pub fn git_buf_grow(buffer: *mut git_buf, target_size: size_t) -> c_int; +++ pub fn git_buf_set(buffer: *mut git_buf, data: *const c_void, datalen: size_t) -> c_int; +++ +++ // commit +++ pub fn git_commit_author(commit: *const git_commit) -> *const git_signature; +++ pub fn git_commit_author_with_mailmap( +++ out: *mut *mut git_signature, +++ commit: *const git_commit, +++ mailmap: *const git_mailmap, +++ ) -> c_int; +++ pub fn git_commit_committer(commit: *const git_commit) -> *const git_signature; +++ pub fn git_commit_committer_with_mailmap( +++ out: *mut *mut git_signature, +++ commit: *const git_commit, +++ mailmap: *const git_mailmap, +++ ) -> c_int; +++ pub fn git_commit_free(commit: *mut git_commit); +++ pub fn git_commit_id(commit: *const git_commit) -> *const git_oid; +++ pub fn git_commit_lookup( +++ commit: *mut *mut git_commit, +++ repo: *mut git_repository, +++ id: *const git_oid, +++ ) -> c_int; +++ pub fn git_commit_lookup_prefix( +++ commit: *mut *mut git_commit, +++ repo: *mut git_repository, +++ id: *const git_oid, +++ len: size_t, +++ ) -> c_int; +++ pub fn git_commit_message(commit: *const git_commit) -> *const c_char; +++ pub fn git_commit_message_encoding(commit: *const git_commit) -> *const c_char; +++ pub fn git_commit_message_raw(commit: *const git_commit) -> *const c_char; +++ pub fn git_commit_nth_gen_ancestor( +++ commit: *mut *mut git_commit, +++ commit: *const git_commit, +++ n: c_uint, +++ ) -> c_int; +++ pub fn git_commit_parent( +++ out: *mut *mut git_commit, +++ commit: *const git_commit, +++ n: c_uint, +++ ) -> c_int; +++ pub fn git_commit_parent_id(commit: *const git_commit, n: c_uint) -> *const git_oid; +++ pub fn git_commit_parentcount(commit: *const git_commit) -> c_uint; +++ pub fn git_commit_raw_header(commit: *const git_commit) -> *const c_char; +++ pub fn git_commit_summary(commit: *mut git_commit) -> *const c_char; +++ pub fn git_commit_body(commit: *mut git_commit) -> *const c_char; +++ pub fn git_commit_time(commit: *const git_commit) -> git_time_t; +++ pub fn git_commit_time_offset(commit: *const git_commit) -> c_int; +++ pub fn git_commit_tree(tree_out: *mut *mut git_tree, commit: *const git_commit) -> c_int; +++ pub fn git_commit_tree_id(commit: *const git_commit) -> *const git_oid; +++ pub fn git_commit_amend( +++ id: *mut git_oid, +++ commit_to_amend: *const git_commit, +++ update_ref: *const c_char, +++ author: *const git_signature, +++ committer: *const git_signature, +++ message_encoding: *const c_char, +++ message: *const c_char, +++ tree: *const git_tree, +++ ) -> c_int; +++ pub fn git_commit_create( +++ id: *mut git_oid, +++ repo: *mut git_repository, +++ update_ref: *const c_char, +++ author: *const git_signature, +++ committer: *const git_signature, +++ message_encoding: *const c_char, +++ message: *const c_char, +++ tree: *const git_tree, +++ parent_count: size_t, +++ parents: *mut *const git_commit, +++ ) -> c_int; +++ pub fn git_commit_create_buffer( +++ out: *mut git_buf, +++ repo: *mut git_repository, +++ author: *const git_signature, +++ committer: *const git_signature, +++ message_encoding: *const c_char, +++ message: *const c_char, +++ tree: *const git_tree, +++ parent_count: size_t, +++ parents: *mut *const git_commit, +++ ) -> c_int; +++ pub fn git_commit_header_field( +++ out: *mut git_buf, +++ commit: *const git_commit, +++ field: *const c_char, +++ ) -> c_int; +++ pub fn git_annotated_commit_lookup( +++ out: *mut *mut git_annotated_commit, +++ repo: *mut git_repository, +++ id: *const git_oid, +++ ) -> c_int; +++ pub fn git_commit_create_with_signature( +++ id: *mut git_oid, +++ repo: *mut git_repository, +++ commit_content: *const c_char, +++ signature: *const c_char, +++ signature_field: *const c_char, +++ ) -> c_int; +++ pub fn git_commit_extract_signature( +++ signature: *mut git_buf, +++ signed_data: *mut git_buf, +++ repo: *mut git_repository, +++ commit_id: *mut git_oid, +++ field: *const c_char, +++ ) -> c_int; +++ +++ // branch +++ pub fn git_branch_create( +++ out: *mut *mut git_reference, +++ repo: *mut git_repository, +++ branch_name: *const c_char, +++ target: *const git_commit, +++ force: c_int, +++ ) -> c_int; +++ pub fn git_branch_create_from_annotated( +++ ref_out: *mut *mut git_reference, +++ repository: *mut git_repository, +++ branch_name: *const c_char, +++ commit: *const git_annotated_commit, +++ force: c_int, +++ ) -> c_int; +++ pub fn git_branch_delete(branch: *mut git_reference) -> c_int; +++ pub fn git_branch_is_head(branch: *const git_reference) -> c_int; +++ pub fn git_branch_iterator_free(iter: *mut git_branch_iterator); +++ pub fn git_branch_iterator_new( +++ iter: *mut *mut git_branch_iterator, +++ repo: *mut git_repository, +++ list_flags: git_branch_t, +++ ) -> c_int; +++ pub fn git_branch_lookup( +++ out: *mut *mut git_reference, +++ repo: *mut git_repository, +++ branch_name: *const c_char, +++ branch_type: git_branch_t, +++ ) -> c_int; +++ pub fn git_branch_move( +++ out: *mut *mut git_reference, +++ branch: *mut git_reference, +++ new_branch_name: *const c_char, +++ force: c_int, +++ ) -> c_int; +++ pub fn git_branch_name(out: *mut *const c_char, branch: *const git_reference) -> c_int; +++ pub fn git_branch_name_is_valid(valid: *mut c_int, name: *const c_char) -> c_int; +++ pub fn git_branch_remote_name( +++ out: *mut git_buf, +++ repo: *mut git_repository, +++ refname: *const c_char, +++ ) -> c_int; +++ pub fn git_branch_next( +++ out: *mut *mut git_reference, +++ out_type: *mut git_branch_t, +++ iter: *mut git_branch_iterator, +++ ) -> c_int; +++ pub fn git_branch_set_upstream( +++ branch: *mut git_reference, +++ upstream_name: *const c_char, +++ ) -> c_int; +++ pub fn git_branch_upstream(out: *mut *mut git_reference, branch: *const git_reference) +++ -> c_int; +++ pub fn git_branch_upstream_name( +++ out: *mut git_buf, +++ repo: *mut git_repository, +++ refname: *const c_char, +++ ) -> c_int; +++ pub fn git_branch_upstream_remote( +++ out: *mut git_buf, +++ repo: *mut git_repository, +++ refname: *const c_char, +++ ) -> c_int; +++ +++ // index +++ pub fn git_index_version(index: *mut git_index) -> c_uint; +++ pub fn git_index_set_version(index: *mut git_index, version: c_uint) -> c_int; +++ pub fn git_index_add(index: *mut git_index, entry: *const git_index_entry) -> c_int; +++ pub fn git_index_add_all( +++ index: *mut git_index, +++ pathspec: *const git_strarray, +++ flags: c_uint, +++ callback: git_index_matched_path_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_index_add_bypath(index: *mut git_index, path: *const c_char) -> c_int; +++ pub fn git_index_add_frombuffer( +++ index: *mut git_index, +++ entry: *const git_index_entry, +++ buffer: *const c_void, +++ len: size_t, +++ ) -> c_int; +++ pub fn git_index_conflict_add( +++ index: *mut git_index, +++ ancestor_entry: *const git_index_entry, +++ our_entry: *const git_index_entry, +++ their_entry: *const git_index_entry, +++ ) -> c_int; +++ pub fn git_index_conflict_remove(index: *mut git_index, path: *const c_char) -> c_int; +++ pub fn git_index_conflict_get( +++ ancestor_out: *mut *const git_index_entry, +++ our_out: *mut *const git_index_entry, +++ their_out: *mut *const git_index_entry, +++ index: *mut git_index, +++ path: *const c_char, +++ ) -> c_int; +++ pub fn git_index_conflict_iterator_new( +++ iter: *mut *mut git_index_conflict_iterator, +++ index: *mut git_index, +++ ) -> c_int; +++ pub fn git_index_conflict_next( +++ ancestor_out: *mut *const git_index_entry, +++ our_out: *mut *const git_index_entry, +++ their_out: *mut *const git_index_entry, +++ iter: *mut git_index_conflict_iterator, +++ ) -> c_int; +++ pub fn git_index_conflict_iterator_free(iter: *mut git_index_conflict_iterator); +++ pub fn git_index_clear(index: *mut git_index) -> c_int; +++ pub fn git_index_entry_stage(entry: *const git_index_entry) -> c_int; +++ pub fn git_index_entrycount(entry: *const git_index) -> size_t; +++ pub fn git_index_find(at_pos: *mut size_t, index: *mut git_index, path: *const c_char) +++ -> c_int; +++ pub fn git_index_find_prefix( +++ at_pos: *mut size_t, +++ index: *mut git_index, +++ prefix: *const c_char, +++ ) -> c_int; +++ pub fn git_index_free(index: *mut git_index); +++ pub fn git_index_get_byindex(index: *mut git_index, n: size_t) -> *const git_index_entry; +++ pub fn git_index_get_bypath( +++ index: *mut git_index, +++ path: *const c_char, +++ stage: c_int, +++ ) -> *const git_index_entry; +++ pub fn git_index_has_conflicts(index: *const git_index) -> c_int; +++ pub fn git_index_new(index: *mut *mut git_index) -> c_int; +++ pub fn git_index_open(index: *mut *mut git_index, index_path: *const c_char) -> c_int; +++ pub fn git_index_path(index: *const git_index) -> *const c_char; +++ pub fn git_index_read(index: *mut git_index, force: c_int) -> c_int; +++ pub fn git_index_read_tree(index: *mut git_index, tree: *const git_tree) -> c_int; +++ pub fn git_index_remove(index: *mut git_index, path: *const c_char, stage: c_int) -> c_int; +++ pub fn git_index_remove_all( +++ index: *mut git_index, +++ pathspec: *const git_strarray, +++ callback: git_index_matched_path_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_index_remove_bypath(index: *mut git_index, path: *const c_char) -> c_int; +++ pub fn git_index_remove_directory( +++ index: *mut git_index, +++ dir: *const c_char, +++ stage: c_int, +++ ) -> c_int; +++ pub fn git_index_update_all( +++ index: *mut git_index, +++ pathspec: *const git_strarray, +++ callback: git_index_matched_path_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_index_write(index: *mut git_index) -> c_int; +++ pub fn git_index_write_tree(out: *mut git_oid, index: *mut git_index) -> c_int; +++ pub fn git_index_write_tree_to( +++ out: *mut git_oid, +++ index: *mut git_index, +++ repo: *mut git_repository, +++ ) -> c_int; +++ +++ // config +++ pub fn git_config_add_file_ondisk( +++ cfg: *mut git_config, +++ path: *const c_char, +++ level: git_config_level_t, +++ repo: *const git_repository, +++ force: c_int, +++ ) -> c_int; +++ pub fn git_config_delete_entry(cfg: *mut git_config, name: *const c_char) -> c_int; +++ pub fn git_config_delete_multivar( +++ cfg: *mut git_config, +++ name: *const c_char, +++ regexp: *const c_char, +++ ) -> c_int; +++ pub fn git_config_find_programdata(out: *mut git_buf) -> c_int; +++ pub fn git_config_find_global(out: *mut git_buf) -> c_int; +++ pub fn git_config_find_system(out: *mut git_buf) -> c_int; +++ pub fn git_config_find_xdg(out: *mut git_buf) -> c_int; +++ pub fn git_config_free(cfg: *mut git_config); +++ pub fn git_config_get_bool( +++ out: *mut c_int, +++ cfg: *const git_config, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_config_get_entry( +++ out: *mut *mut git_config_entry, +++ cfg: *const git_config, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_config_get_int32( +++ out: *mut i32, +++ cfg: *const git_config, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_config_get_int64( +++ out: *mut i64, +++ cfg: *const git_config, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_config_get_string( +++ out: *mut *const c_char, +++ cfg: *const git_config, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_config_get_string_buf( +++ out: *mut git_buf, +++ cfg: *const git_config, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_config_get_path( +++ out: *mut git_buf, +++ cfg: *const git_config, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_config_iterator_free(iter: *mut git_config_iterator); +++ pub fn git_config_iterator_glob_new( +++ out: *mut *mut git_config_iterator, +++ cfg: *const git_config, +++ regexp: *const c_char, +++ ) -> c_int; +++ pub fn git_config_iterator_new( +++ out: *mut *mut git_config_iterator, +++ cfg: *const git_config, +++ ) -> c_int; +++ pub fn git_config_new(out: *mut *mut git_config) -> c_int; +++ pub fn git_config_next( +++ entry: *mut *mut git_config_entry, +++ iter: *mut git_config_iterator, +++ ) -> c_int; +++ pub fn git_config_open_default(out: *mut *mut git_config) -> c_int; +++ pub fn git_config_open_global(out: *mut *mut git_config, config: *mut git_config) -> c_int; +++ pub fn git_config_open_level( +++ out: *mut *mut git_config, +++ parent: *const git_config, +++ level: git_config_level_t, +++ ) -> c_int; +++ pub fn git_config_open_ondisk(out: *mut *mut git_config, path: *const c_char) -> c_int; +++ pub fn git_config_parse_bool(out: *mut c_int, value: *const c_char) -> c_int; +++ pub fn git_config_parse_int32(out: *mut i32, value: *const c_char) -> c_int; +++ pub fn git_config_parse_int64(out: *mut i64, value: *const c_char) -> c_int; +++ pub fn git_config_set_bool(cfg: *mut git_config, name: *const c_char, value: c_int) -> c_int; +++ pub fn git_config_set_int32(cfg: *mut git_config, name: *const c_char, value: i32) -> c_int; +++ pub fn git_config_set_int64(cfg: *mut git_config, name: *const c_char, value: i64) -> c_int; +++ pub fn git_config_set_multivar( +++ cfg: *mut git_config, +++ name: *const c_char, +++ regexp: *const c_char, +++ value: *const c_char, +++ ) -> c_int; +++ pub fn git_config_set_string( +++ cfg: *mut git_config, +++ name: *const c_char, +++ value: *const c_char, +++ ) -> c_int; +++ pub fn git_config_snapshot(out: *mut *mut git_config, config: *mut git_config) -> c_int; +++ pub fn git_config_entry_free(entry: *mut git_config_entry); +++ pub fn git_config_multivar_iterator_new( +++ out: *mut *mut git_config_iterator, +++ cfg: *const git_config, +++ name: *const c_char, +++ regexp: *const c_char, +++ ) -> c_int; +++ +++ // attr +++ pub fn git_attr_get( +++ value_out: *mut *const c_char, +++ repo: *mut git_repository, +++ flags: u32, +++ path: *const c_char, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_attr_value(value: *const c_char) -> git_attr_value_t; +++ +++ // cred +++ pub fn git_cred_default_new(out: *mut *mut git_cred) -> c_int; +++ pub fn git_cred_has_username(cred: *mut git_cred) -> c_int; +++ pub fn git_cred_ssh_custom_new( +++ out: *mut *mut git_cred, +++ username: *const c_char, +++ publickey: *const c_char, +++ publickey_len: size_t, +++ sign_callback: git_cred_sign_callback, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_cred_ssh_interactive_new( +++ out: *mut *mut git_cred, +++ username: *const c_char, +++ prompt_callback: git_cred_ssh_interactive_callback, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_cred_ssh_key_from_agent(out: *mut *mut git_cred, username: *const c_char) -> c_int; +++ pub fn git_cred_ssh_key_new( +++ out: *mut *mut git_cred, +++ username: *const c_char, +++ publickey: *const c_char, +++ privatekey: *const c_char, +++ passphrase: *const c_char, +++ ) -> c_int; +++ pub fn git_cred_ssh_key_memory_new( +++ out: *mut *mut git_cred, +++ username: *const c_char, +++ publickey: *const c_char, +++ privatekey: *const c_char, +++ passphrase: *const c_char, +++ ) -> c_int; +++ pub fn git_cred_userpass( +++ cred: *mut *mut git_cred, +++ url: *const c_char, +++ user_from_url: *const c_char, +++ allowed_types: c_uint, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_cred_userpass_plaintext_new( +++ out: *mut *mut git_cred, +++ username: *const c_char, +++ password: *const c_char, +++ ) -> c_int; +++ pub fn git_cred_username_new(cred: *mut *mut git_cred, username: *const c_char) -> c_int; +++ +++ // tags +++ pub fn git_tag_annotation_create( +++ oid: *mut git_oid, +++ repo: *mut git_repository, +++ tag_name: *const c_char, +++ target: *const git_object, +++ tagger: *const git_signature, +++ message: *const c_char, +++ ) -> c_int; +++ pub fn git_tag_create( +++ oid: *mut git_oid, +++ repo: *mut git_repository, +++ tag_name: *const c_char, +++ target: *const git_object, +++ tagger: *const git_signature, +++ message: *const c_char, +++ force: c_int, +++ ) -> c_int; +++ pub fn git_tag_create_frombuffer( +++ oid: *mut git_oid, +++ repo: *mut git_repository, +++ buffer: *const c_char, +++ force: c_int, +++ ) -> c_int; +++ pub fn git_tag_create_lightweight( +++ oid: *mut git_oid, +++ repo: *mut git_repository, +++ tag_name: *const c_char, +++ target: *const git_object, +++ force: c_int, +++ ) -> c_int; +++ pub fn git_tag_delete(repo: *mut git_repository, tag_name: *const c_char) -> c_int; +++ pub fn git_tag_foreach( +++ repo: *mut git_repository, +++ callback: git_tag_foreach_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_tag_free(tag: *mut git_tag); +++ pub fn git_tag_id(tag: *const git_tag) -> *const git_oid; +++ pub fn git_tag_list(tag_names: *mut git_strarray, repo: *mut git_repository) -> c_int; +++ pub fn git_tag_list_match( +++ tag_names: *mut git_strarray, +++ pattern: *const c_char, +++ repo: *mut git_repository, +++ ) -> c_int; +++ pub fn git_tag_lookup( +++ out: *mut *mut git_tag, +++ repo: *mut git_repository, +++ id: *const git_oid, +++ ) -> c_int; +++ pub fn git_tag_lookup_prefix( +++ out: *mut *mut git_tag, +++ repo: *mut git_repository, +++ id: *const git_oid, +++ len: size_t, +++ ) -> c_int; +++ pub fn git_tag_message(tag: *const git_tag) -> *const c_char; +++ pub fn git_tag_name(tag: *const git_tag) -> *const c_char; +++ pub fn git_tag_peel(tag_target_out: *mut *mut git_object, tag: *const git_tag) -> c_int; +++ pub fn git_tag_tagger(tag: *const git_tag) -> *const git_signature; +++ pub fn git_tag_target(target_out: *mut *mut git_object, tag: *const git_tag) -> c_int; +++ pub fn git_tag_target_id(tag: *const git_tag) -> *const git_oid; +++ pub fn git_tag_target_type(tag: *const git_tag) -> git_object_t; +++ pub fn git_tag_name_is_valid(valid: *mut c_int, tag_name: *const c_char) -> c_int; +++ +++ // checkout +++ pub fn git_checkout_head(repo: *mut git_repository, opts: *const git_checkout_options) +++ -> c_int; +++ pub fn git_checkout_index( +++ repo: *mut git_repository, +++ index: *mut git_index, +++ opts: *const git_checkout_options, +++ ) -> c_int; +++ pub fn git_checkout_tree( +++ repo: *mut git_repository, +++ treeish: *const git_object, +++ opts: *const git_checkout_options, +++ ) -> c_int; +++ pub fn git_checkout_init_options(opts: *mut git_checkout_options, version: c_uint) -> c_int; +++ +++ // merge +++ pub fn git_annotated_commit_id(commit: *const git_annotated_commit) -> *const git_oid; +++ pub fn git_annotated_commit_ref(commit: *const git_annotated_commit) -> *const c_char; +++ pub fn git_annotated_commit_from_ref( +++ out: *mut *mut git_annotated_commit, +++ repo: *mut git_repository, +++ reference: *const git_reference, +++ ) -> c_int; +++ pub fn git_annotated_commit_from_fetchhead( +++ out: *mut *mut git_annotated_commit, +++ repo: *mut git_repository, +++ branch_name: *const c_char, +++ remote_url: *const c_char, +++ oid: *const git_oid, +++ ) -> c_int; +++ pub fn git_annotated_commit_free(commit: *mut git_annotated_commit); +++ pub fn git_merge_init_options(opts: *mut git_merge_options, version: c_uint) -> c_int; +++ pub fn git_merge( +++ repo: *mut git_repository, +++ their_heads: *mut *const git_annotated_commit, +++ len: size_t, +++ merge_opts: *const git_merge_options, +++ checkout_opts: *const git_checkout_options, +++ ) -> c_int; +++ pub fn git_merge_commits( +++ out: *mut *mut git_index, +++ repo: *mut git_repository, +++ our_commit: *const git_commit, +++ their_commit: *const git_commit, +++ opts: *const git_merge_options, +++ ) -> c_int; +++ pub fn git_merge_trees( +++ out: *mut *mut git_index, +++ repo: *mut git_repository, +++ ancestor_tree: *const git_tree, +++ our_tree: *const git_tree, +++ their_tree: *const git_tree, +++ opts: *const git_merge_options, +++ ) -> c_int; +++ pub fn git_repository_state_cleanup(repo: *mut git_repository) -> c_int; +++ +++ // merge analysis +++ +++ pub fn git_merge_analysis( +++ analysis_out: *mut git_merge_analysis_t, +++ pref_out: *mut git_merge_preference_t, +++ repo: *mut git_repository, +++ their_heads: *mut *const git_annotated_commit, +++ their_heads_len: usize, +++ ) -> c_int; +++ +++ pub fn git_merge_analysis_for_ref( +++ analysis_out: *mut git_merge_analysis_t, +++ pref_out: *mut git_merge_preference_t, +++ repo: *mut git_repository, +++ git_reference: *mut git_reference, +++ their_heads: *mut *const git_annotated_commit, +++ their_heads_len: usize, +++ ) -> c_int; +++ +++ // notes +++ pub fn git_note_author(note: *const git_note) -> *const git_signature; +++ pub fn git_note_committer(note: *const git_note) -> *const git_signature; +++ pub fn git_note_create( +++ out: *mut git_oid, +++ repo: *mut git_repository, +++ notes_ref: *const c_char, +++ author: *const git_signature, +++ committer: *const git_signature, +++ oid: *const git_oid, +++ note: *const c_char, +++ force: c_int, +++ ) -> c_int; +++ pub fn git_note_default_ref(out: *mut git_buf, repo: *mut git_repository) -> c_int; +++ pub fn git_note_free(note: *mut git_note); +++ pub fn git_note_id(note: *const git_note) -> *const git_oid; +++ pub fn git_note_iterator_free(it: *mut git_note_iterator); +++ pub fn git_note_iterator_new( +++ out: *mut *mut git_note_iterator, +++ repo: *mut git_repository, +++ notes_ref: *const c_char, +++ ) -> c_int; +++ pub fn git_note_message(note: *const git_note) -> *const c_char; +++ pub fn git_note_next( +++ note_id: *mut git_oid, +++ annotated_id: *mut git_oid, +++ it: *mut git_note_iterator, +++ ) -> c_int; +++ pub fn git_note_read( +++ out: *mut *mut git_note, +++ repo: *mut git_repository, +++ notes_ref: *const c_char, +++ oid: *const git_oid, +++ ) -> c_int; +++ pub fn git_note_remove( +++ repo: *mut git_repository, +++ notes_ref: *const c_char, +++ author: *const git_signature, +++ committer: *const git_signature, +++ oid: *const git_oid, +++ ) -> c_int; +++ +++ // blame +++ pub fn git_blame_buffer( +++ out: *mut *mut git_blame, +++ reference: *mut git_blame, +++ buffer: *const c_char, +++ buffer_len: size_t, +++ ) -> c_int; +++ pub fn git_blame_file( +++ out: *mut *mut git_blame, +++ repo: *mut git_repository, +++ path: *const c_char, +++ options: *mut git_blame_options, +++ ) -> c_int; +++ pub fn git_blame_free(blame: *mut git_blame); +++ +++ pub fn git_blame_init_options(opts: *mut git_blame_options, version: c_uint) -> c_int; +++ pub fn git_blame_get_hunk_count(blame: *mut git_blame) -> u32; +++ +++ pub fn git_blame_get_hunk_byline(blame: *mut git_blame, lineno: usize) +++ -> *const git_blame_hunk; +++ pub fn git_blame_get_hunk_byindex(blame: *mut git_blame, index: u32) -> *const git_blame_hunk; +++ +++ // revwalk +++ pub fn git_revwalk_new(out: *mut *mut git_revwalk, repo: *mut git_repository) -> c_int; +++ pub fn git_revwalk_free(walk: *mut git_revwalk); +++ +++ pub fn git_revwalk_reset(walk: *mut git_revwalk) -> c_int; +++ +++ pub fn git_revwalk_sorting(walk: *mut git_revwalk, sort_mode: c_uint) -> c_int; +++ +++ pub fn git_revwalk_push_head(walk: *mut git_revwalk) -> c_int; +++ pub fn git_revwalk_push(walk: *mut git_revwalk, oid: *const git_oid) -> c_int; +++ pub fn git_revwalk_push_ref(walk: *mut git_revwalk, refname: *const c_char) -> c_int; +++ pub fn git_revwalk_push_glob(walk: *mut git_revwalk, glob: *const c_char) -> c_int; +++ pub fn git_revwalk_push_range(walk: *mut git_revwalk, range: *const c_char) -> c_int; +++ pub fn git_revwalk_simplify_first_parent(walk: *mut git_revwalk) -> c_int; +++ +++ pub fn git_revwalk_hide_head(walk: *mut git_revwalk) -> c_int; +++ pub fn git_revwalk_hide(walk: *mut git_revwalk, oid: *const git_oid) -> c_int; +++ pub fn git_revwalk_hide_ref(walk: *mut git_revwalk, refname: *const c_char) -> c_int; +++ pub fn git_revwalk_hide_glob(walk: *mut git_revwalk, refname: *const c_char) -> c_int; +++ pub fn git_revwalk_add_hide_cb( +++ walk: *mut git_revwalk, +++ hide_cb: git_revwalk_hide_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ +++ pub fn git_revwalk_next(out: *mut git_oid, walk: *mut git_revwalk) -> c_int; +++ +++ // merge +++ pub fn git_merge_base( +++ out: *mut git_oid, +++ repo: *mut git_repository, +++ one: *const git_oid, +++ two: *const git_oid, +++ ) -> c_int; +++ +++ pub fn git_merge_base_many( +++ out: *mut git_oid, +++ repo: *mut git_repository, +++ length: size_t, +++ input_array: *const git_oid, +++ ) -> c_int; +++ +++ pub fn git_merge_base_octopus( +++ out: *mut git_oid, +++ repo: *mut git_repository, +++ length: size_t, +++ input_array: *const git_oid, +++ ) -> c_int; +++ +++ pub fn git_merge_bases( +++ out: *mut git_oidarray, +++ repo: *mut git_repository, +++ one: *const git_oid, +++ two: *const git_oid, +++ ) -> c_int; +++ +++ pub fn git_merge_bases_many( +++ out: *mut git_oidarray, +++ repo: *mut git_repository, +++ length: size_t, +++ input_array: *const git_oid, +++ ) -> c_int; +++ +++ // pathspec +++ pub fn git_pathspec_free(ps: *mut git_pathspec); +++ pub fn git_pathspec_match_diff( +++ out: *mut *mut git_pathspec_match_list, +++ diff: *mut git_diff, +++ flags: u32, +++ ps: *mut git_pathspec, +++ ) -> c_int; +++ pub fn git_pathspec_match_index( +++ out: *mut *mut git_pathspec_match_list, +++ index: *mut git_index, +++ flags: u32, +++ ps: *mut git_pathspec, +++ ) -> c_int; +++ pub fn git_pathspec_match_list_diff_entry( +++ m: *const git_pathspec_match_list, +++ pos: size_t, +++ ) -> *const git_diff_delta; +++ pub fn git_pathspec_match_list_entry( +++ m: *const git_pathspec_match_list, +++ pos: size_t, +++ ) -> *const c_char; +++ pub fn git_pathspec_match_list_entrycount(m: *const git_pathspec_match_list) -> size_t; +++ pub fn git_pathspec_match_list_failed_entry( +++ m: *const git_pathspec_match_list, +++ pos: size_t, +++ ) -> *const c_char; +++ pub fn git_pathspec_match_list_failed_entrycount(m: *const git_pathspec_match_list) -> size_t; +++ pub fn git_pathspec_match_list_free(m: *mut git_pathspec_match_list); +++ pub fn git_pathspec_match_tree( +++ out: *mut *mut git_pathspec_match_list, +++ tree: *mut git_tree, +++ flags: u32, +++ ps: *mut git_pathspec, +++ ) -> c_int; +++ pub fn git_pathspec_match_workdir( +++ out: *mut *mut git_pathspec_match_list, +++ repo: *mut git_repository, +++ flags: u32, +++ ps: *mut git_pathspec, +++ ) -> c_int; +++ pub fn git_pathspec_matches_path( +++ ps: *const git_pathspec, +++ flags: u32, +++ path: *const c_char, +++ ) -> c_int; +++ pub fn git_pathspec_new(out: *mut *mut git_pathspec, pathspec: *const git_strarray) -> c_int; +++ +++ // diff +++ pub fn git_diff_blob_to_buffer( +++ old_blob: *const git_blob, +++ old_as_path: *const c_char, +++ buffer: *const c_char, +++ buffer_len: size_t, +++ buffer_as_path: *const c_char, +++ options: *const git_diff_options, +++ file_cb: git_diff_file_cb, +++ binary_cb: git_diff_binary_cb, +++ hunk_cb: git_diff_hunk_cb, +++ line_cb: git_diff_line_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_diff_blobs( +++ old_blob: *const git_blob, +++ old_as_path: *const c_char, +++ new_blob: *const git_blob, +++ new_as_path: *const c_char, +++ options: *const git_diff_options, +++ file_cb: git_diff_file_cb, +++ binary_cb: git_diff_binary_cb, +++ hunk_cb: git_diff_hunk_cb, +++ line_cb: git_diff_line_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_diff_buffers( +++ old_buffer: *const c_void, +++ old_len: size_t, +++ old_as_path: *const c_char, +++ new_buffer: *const c_void, +++ new_len: size_t, +++ new_as_path: *const c_char, +++ options: *const git_diff_options, +++ file_cb: git_diff_file_cb, +++ binary_cb: git_diff_binary_cb, +++ hunk_cb: git_diff_hunk_cb, +++ line_cb: git_diff_line_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_diff_from_buffer( +++ diff: *mut *mut git_diff, +++ content: *const c_char, +++ content_len: size_t, +++ ) -> c_int; +++ pub fn git_diff_find_similar( +++ diff: *mut git_diff, +++ options: *const git_diff_find_options, +++ ) -> c_int; +++ pub fn git_diff_find_init_options(opts: *mut git_diff_find_options, version: c_uint) -> c_int; +++ pub fn git_diff_foreach( +++ diff: *mut git_diff, +++ file_cb: git_diff_file_cb, +++ binary_cb: git_diff_binary_cb, +++ hunk_cb: git_diff_hunk_cb, +++ line_cb: git_diff_line_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_diff_free(diff: *mut git_diff); +++ pub fn git_diff_get_delta(diff: *const git_diff, idx: size_t) -> *const git_diff_delta; +++ pub fn git_diff_get_stats(out: *mut *mut git_diff_stats, diff: *mut git_diff) -> c_int; +++ pub fn git_diff_index_to_index( +++ diff: *mut *mut git_diff, +++ repo: *mut git_repository, +++ old_index: *mut git_index, +++ new_index: *mut git_index, +++ opts: *const git_diff_options, +++ ) -> c_int; +++ pub fn git_diff_index_to_workdir( +++ diff: *mut *mut git_diff, +++ repo: *mut git_repository, +++ index: *mut git_index, +++ opts: *const git_diff_options, +++ ) -> c_int; +++ pub fn git_diff_init_options(opts: *mut git_diff_options, version: c_uint) -> c_int; +++ pub fn git_diff_is_sorted_icase(diff: *const git_diff) -> c_int; +++ pub fn git_diff_merge(onto: *mut git_diff, from: *const git_diff) -> c_int; +++ pub fn git_diff_num_deltas(diff: *const git_diff) -> size_t; +++ pub fn git_diff_num_deltas_of_type(diff: *const git_diff, delta: git_delta_t) -> size_t; +++ pub fn git_diff_print( +++ diff: *mut git_diff, +++ format: git_diff_format_t, +++ print_cb: git_diff_line_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_diff_stats_deletions(stats: *const git_diff_stats) -> size_t; +++ pub fn git_diff_stats_files_changed(stats: *const git_diff_stats) -> size_t; +++ pub fn git_diff_stats_free(stats: *mut git_diff_stats); +++ pub fn git_diff_stats_insertions(stats: *const git_diff_stats) -> size_t; +++ pub fn git_diff_stats_to_buf( +++ out: *mut git_buf, +++ stats: *const git_diff_stats, +++ format: git_diff_stats_format_t, +++ width: size_t, +++ ) -> c_int; +++ pub fn git_diff_status_char(status: git_delta_t) -> c_char; +++ pub fn git_diff_tree_to_index( +++ diff: *mut *mut git_diff, +++ repo: *mut git_repository, +++ old_tree: *mut git_tree, +++ index: *mut git_index, +++ opts: *const git_diff_options, +++ ) -> c_int; +++ pub fn git_diff_tree_to_tree( +++ diff: *mut *mut git_diff, +++ repo: *mut git_repository, +++ old_tree: *mut git_tree, +++ new_tree: *mut git_tree, +++ opts: *const git_diff_options, +++ ) -> c_int; +++ pub fn git_diff_tree_to_workdir( +++ diff: *mut *mut git_diff, +++ repo: *mut git_repository, +++ old_tree: *mut git_tree, +++ opts: *const git_diff_options, +++ ) -> c_int; +++ pub fn git_diff_tree_to_workdir_with_index( +++ diff: *mut *mut git_diff, +++ repo: *mut git_repository, +++ old_tree: *mut git_tree, +++ opts: *const git_diff_options, +++ ) -> c_int; +++ +++ pub fn git_graph_ahead_behind( +++ ahead: *mut size_t, +++ behind: *mut size_t, +++ repo: *mut git_repository, +++ local: *const git_oid, +++ upstream: *const git_oid, +++ ) -> c_int; +++ +++ pub fn git_graph_descendant_of( +++ repo: *mut git_repository, +++ commit: *const git_oid, +++ ancestor: *const git_oid, +++ ) -> c_int; +++ +++ pub fn git_diff_format_email( +++ out: *mut git_buf, +++ diff: *mut git_diff, +++ opts: *const git_diff_format_email_options, +++ ) -> c_int; +++ pub fn git_diff_format_email_options_init( +++ opts: *mut git_diff_format_email_options, +++ version: c_uint, +++ ) -> c_int; +++ +++ pub fn git_diff_patchid( +++ out: *mut git_oid, +++ diff: *mut git_diff, +++ opts: *mut git_diff_patchid_options, +++ ) -> c_int; +++ pub fn git_diff_patchid_options_init( +++ opts: *mut git_diff_patchid_options, +++ version: c_uint, +++ ) -> c_int; +++ +++ // patch +++ pub fn git_patch_from_diff(out: *mut *mut git_patch, diff: *mut git_diff, idx: size_t) +++ -> c_int; +++ pub fn git_patch_from_blobs( +++ out: *mut *mut git_patch, +++ old_blob: *const git_blob, +++ old_as_path: *const c_char, +++ new_blob: *const git_blob, +++ new_as_path: *const c_char, +++ opts: *const git_diff_options, +++ ) -> c_int; +++ pub fn git_patch_from_blob_and_buffer( +++ out: *mut *mut git_patch, +++ old_blob: *const git_blob, +++ old_as_path: *const c_char, +++ buffer: *const c_void, +++ buffer_len: size_t, +++ buffer_as_path: *const c_char, +++ opts: *const git_diff_options, +++ ) -> c_int; +++ pub fn git_patch_from_buffers( +++ out: *mut *mut git_patch, +++ old_buffer: *const c_void, +++ old_len: size_t, +++ old_as_path: *const c_char, +++ new_buffer: *const c_void, +++ new_len: size_t, +++ new_as_path: *const c_char, +++ opts: *const git_diff_options, +++ ) -> c_int; +++ pub fn git_patch_free(patch: *mut git_patch); +++ pub fn git_patch_get_delta(patch: *const git_patch) -> *const git_diff_delta; +++ pub fn git_patch_num_hunks(patch: *const git_patch) -> size_t; +++ pub fn git_patch_line_stats( +++ total_context: *mut size_t, +++ total_additions: *mut size_t, +++ total_deletions: *mut size_t, +++ patch: *const git_patch, +++ ) -> c_int; +++ pub fn git_patch_get_hunk( +++ out: *mut *const git_diff_hunk, +++ lines_in_hunk: *mut size_t, +++ patch: *mut git_patch, +++ hunk_idx: size_t, +++ ) -> c_int; +++ pub fn git_patch_num_lines_in_hunk(patch: *const git_patch, hunk_idx: size_t) -> c_int; +++ pub fn git_patch_get_line_in_hunk( +++ out: *mut *const git_diff_line, +++ patch: *mut git_patch, +++ hunk_idx: size_t, +++ line_of_hunk: size_t, +++ ) -> c_int; +++ pub fn git_patch_size( +++ patch: *mut git_patch, +++ include_context: c_int, +++ include_hunk_headers: c_int, +++ include_file_headers: c_int, +++ ) -> size_t; +++ pub fn git_patch_print( +++ patch: *mut git_patch, +++ print_cb: git_diff_line_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_patch_to_buf(buf: *mut git_buf, patch: *mut git_patch) -> c_int; +++ +++ // reflog +++ pub fn git_reflog_append( +++ reflog: *mut git_reflog, +++ id: *const git_oid, +++ committer: *const git_signature, +++ msg: *const c_char, +++ ) -> c_int; +++ pub fn git_reflog_delete(repo: *mut git_repository, name: *const c_char) -> c_int; +++ pub fn git_reflog_drop( +++ reflog: *mut git_reflog, +++ idx: size_t, +++ rewrite_previous_entry: c_int, +++ ) -> c_int; +++ pub fn git_reflog_entry_byindex( +++ reflog: *const git_reflog, +++ idx: size_t, +++ ) -> *const git_reflog_entry; +++ pub fn git_reflog_entry_committer(entry: *const git_reflog_entry) -> *const git_signature; +++ pub fn git_reflog_entry_id_new(entry: *const git_reflog_entry) -> *const git_oid; +++ pub fn git_reflog_entry_id_old(entry: *const git_reflog_entry) -> *const git_oid; +++ pub fn git_reflog_entry_message(entry: *const git_reflog_entry) -> *const c_char; +++ pub fn git_reflog_entrycount(reflog: *mut git_reflog) -> size_t; +++ pub fn git_reflog_free(reflog: *mut git_reflog); +++ pub fn git_reflog_read( +++ out: *mut *mut git_reflog, +++ repo: *mut git_repository, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_reflog_rename( +++ repo: *mut git_repository, +++ old_name: *const c_char, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_reflog_write(reflog: *mut git_reflog) -> c_int; +++ +++ // transport +++ pub fn git_transport_register( +++ prefix: *const c_char, +++ cb: git_transport_cb, +++ param: *mut c_void, +++ ) -> c_int; +++ pub fn git_transport_unregister(prefix: *const c_char) -> c_int; +++ pub fn git_transport_smart( +++ out: *mut *mut git_transport, +++ owner: *mut git_remote, +++ payload: *mut c_void, +++ ) -> c_int; +++ +++ // describe +++ pub fn git_describe_commit( +++ result: *mut *mut git_describe_result, +++ object: *mut git_object, +++ opts: *mut git_describe_options, +++ ) -> c_int; +++ pub fn git_describe_format( +++ buf: *mut git_buf, +++ result: *const git_describe_result, +++ opts: *const git_describe_format_options, +++ ) -> c_int; +++ pub fn git_describe_result_free(result: *mut git_describe_result); +++ pub fn git_describe_workdir( +++ out: *mut *mut git_describe_result, +++ repo: *mut git_repository, +++ opts: *mut git_describe_options, +++ ) -> c_int; +++ +++ // message +++ pub fn git_message_prettify( +++ out: *mut git_buf, +++ message: *const c_char, +++ strip_comments: c_int, +++ comment_char: c_char, +++ ) -> c_int; +++ +++ pub fn git_message_trailers( +++ out: *mut git_message_trailer_array, +++ message: *const c_char, +++ ) -> c_int; +++ +++ pub fn git_message_trailer_array_free(trailer: *mut git_message_trailer_array); +++ +++ // packbuilder +++ pub fn git_packbuilder_new(out: *mut *mut git_packbuilder, repo: *mut git_repository) -> c_int; +++ pub fn git_packbuilder_set_threads(pb: *mut git_packbuilder, n: c_uint) -> c_uint; +++ pub fn git_packbuilder_insert( +++ pb: *mut git_packbuilder, +++ id: *const git_oid, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_packbuilder_insert_tree(pb: *mut git_packbuilder, id: *const git_oid) -> c_int; +++ pub fn git_packbuilder_insert_commit(pb: *mut git_packbuilder, id: *const git_oid) -> c_int; +++ pub fn git_packbuilder_insert_walk(pb: *mut git_packbuilder, walk: *mut git_revwalk) -> c_int; +++ pub fn git_packbuilder_insert_recur( +++ pb: *mut git_packbuilder, +++ id: *const git_oid, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_packbuilder_write_buf(buf: *mut git_buf, pb: *mut git_packbuilder) -> c_int; +++ pub fn git_packbuilder_write( +++ pb: *mut git_packbuilder, +++ path: *const c_char, +++ mode: c_uint, +++ progress_cb: git_indexer_progress_cb, +++ progress_cb_payload: *mut c_void, +++ ) -> c_int; +++ #[deprecated = "use `git_packbuilder_name` to retrieve the filename"] +++ pub fn git_packbuilder_hash(pb: *mut git_packbuilder) -> *const git_oid; +++ pub fn git_packbuilder_name(pb: *mut git_packbuilder) -> *const c_char; +++ pub fn git_packbuilder_foreach( +++ pb: *mut git_packbuilder, +++ cb: git_packbuilder_foreach_cb, +++ payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_packbuilder_object_count(pb: *mut git_packbuilder) -> size_t; +++ pub fn git_packbuilder_written(pb: *mut git_packbuilder) -> size_t; +++ pub fn git_packbuilder_set_callbacks( +++ pb: *mut git_packbuilder, +++ progress_cb: git_packbuilder_progress, +++ progress_cb_payload: *mut c_void, +++ ) -> c_int; +++ pub fn git_packbuilder_free(pb: *mut git_packbuilder); +++ +++ // indexer +++ pub fn git_indexer_new( +++ out: *mut *mut git_indexer, +++ path: *const c_char, +++ mode: c_uint, +++ odb: *mut git_odb, +++ opts: *mut git_indexer_options, +++ ) -> c_int; +++ pub fn git_indexer_append( +++ idx: *mut git_indexer, +++ data: *const c_void, +++ size: size_t, +++ stats: *mut git_indexer_progress, +++ ) -> c_int; +++ pub fn git_indexer_commit(idx: *mut git_indexer, stats: *mut git_indexer_progress) -> c_int; +++ #[deprecated = "use `git_indexer_name` to retrieve the filename"] +++ pub fn git_indexer_hash(idx: *const git_indexer) -> *const git_oid; +++ pub fn git_indexer_name(idx: *const git_indexer) -> *const c_char; +++ pub fn git_indexer_free(idx: *mut git_indexer); +++ +++ pub fn git_indexer_options_init(opts: *mut git_indexer_options, version: c_uint) -> c_int; +++ +++ // odb +++ pub fn git_repository_odb(out: *mut *mut git_odb, repo: *mut git_repository) -> c_int; +++ pub fn git_odb_new(db: *mut *mut git_odb) -> c_int; +++ pub fn git_odb_free(db: *mut git_odb); +++ pub fn git_odb_open_rstream( +++ out: *mut *mut git_odb_stream, +++ len: *mut size_t, +++ otype: *mut git_object_t, +++ db: *mut git_odb, +++ oid: *const git_oid, +++ ) -> c_int; +++ pub fn git_odb_stream_read( +++ stream: *mut git_odb_stream, +++ buffer: *mut c_char, +++ len: size_t, +++ ) -> c_int; +++ pub fn git_odb_open_wstream( +++ out: *mut *mut git_odb_stream, +++ db: *mut git_odb, +++ size: git_object_size_t, +++ obj_type: git_object_t, +++ ) -> c_int; +++ pub fn git_odb_stream_write( +++ stream: *mut git_odb_stream, +++ buffer: *const c_char, +++ len: size_t, +++ ) -> c_int; +++ pub fn git_odb_stream_finalize_write(id: *mut git_oid, stream: *mut git_odb_stream) -> c_int; +++ pub fn git_odb_stream_free(stream: *mut git_odb_stream); +++ pub fn git_odb_foreach(db: *mut git_odb, cb: git_odb_foreach_cb, payload: *mut c_void) +++ -> c_int; +++ +++ pub fn git_odb_read( +++ out: *mut *mut git_odb_object, +++ odb: *mut git_odb, +++ oid: *const git_oid, +++ ) -> c_int; +++ +++ pub fn git_odb_read_header( +++ len_out: *mut size_t, +++ type_out: *mut git_object_t, +++ odb: *mut git_odb, +++ oid: *const git_oid, +++ ) -> c_int; +++ +++ pub fn git_odb_write( +++ out: *mut git_oid, +++ odb: *mut git_odb, +++ data: *const c_void, +++ len: size_t, +++ otype: git_object_t, +++ ) -> c_int; +++ +++ pub fn git_odb_write_pack( +++ out: *mut *mut git_odb_writepack, +++ odb: *mut git_odb, +++ progress_cb: git_indexer_progress_cb, +++ progress_payload: *mut c_void, +++ ) -> c_int; +++ +++ pub fn git_odb_hash( +++ out: *mut git_oid, +++ data: *const c_void, +++ len: size_t, +++ otype: git_object_t, +++ ) -> c_int; +++ +++ pub fn git_odb_hashfile(out: *mut git_oid, path: *const c_char, otype: git_object_t) -> c_int; +++ +++ pub fn git_odb_exists_prefix( +++ out: *mut git_oid, +++ odb: *mut git_odb, +++ short_oid: *const git_oid, +++ len: size_t, +++ ) -> c_int; +++ +++ pub fn git_odb_exists(odb: *mut git_odb, oid: *const git_oid) -> c_int; +++ pub fn git_odb_exists_ext(odb: *mut git_odb, oid: *const git_oid, flags: c_uint) -> c_int; +++ +++ pub fn git_odb_refresh(odb: *mut git_odb) -> c_int; +++ +++ pub fn git_odb_object_id(obj: *mut git_odb_object) -> *const git_oid; +++ pub fn git_odb_object_size(obj: *mut git_odb_object) -> size_t; +++ pub fn git_odb_object_type(obj: *mut git_odb_object) -> git_object_t; +++ pub fn git_odb_object_data(obj: *mut git_odb_object) -> *const c_void; +++ pub fn git_odb_object_dup(out: *mut *mut git_odb_object, obj: *mut git_odb_object) -> c_int; +++ pub fn git_odb_object_free(obj: *mut git_odb_object); +++ +++ pub fn git_odb_init_backend(odb: *mut git_odb_backend, version: c_uint) -> c_int; +++ +++ pub fn git_odb_add_backend( +++ odb: *mut git_odb, +++ backend: *mut git_odb_backend, +++ priority: c_int, +++ ) -> c_int; +++ +++ pub fn git_odb_backend_pack( +++ out: *mut *mut git_odb_backend, +++ objects_dir: *const c_char, +++ ) -> c_int; +++ +++ pub fn git_odb_backend_one_pack( +++ out: *mut *mut git_odb_backend, +++ objects_dir: *const c_char, +++ ) -> c_int; +++ +++ pub fn git_odb_add_disk_alternate(odb: *mut git_odb, path: *const c_char) -> c_int; +++ +++ pub fn git_odb_backend_loose( +++ out: *mut *mut git_odb_backend, +++ objects_dir: *const c_char, +++ compression_level: c_int, +++ do_fsync: c_int, +++ dir_mode: c_uint, +++ file_mode: c_uint, +++ ) -> c_int; +++ +++ pub fn git_odb_add_alternate( +++ odb: *mut git_odb, +++ backend: *mut git_odb_backend, +++ priority: c_int, +++ ) -> c_int; +++ +++ pub fn git_odb_backend_malloc(backend: *mut git_odb_backend, len: size_t) -> *mut c_void; +++ +++ pub fn git_odb_num_backends(odb: *mut git_odb) -> size_t; +++ pub fn git_odb_get_backend( +++ backend: *mut *mut git_odb_backend, +++ odb: *mut git_odb, +++ position: size_t, +++ ) -> c_int; +++ +++ // mempack +++ pub fn git_mempack_new(out: *mut *mut git_odb_backend) -> c_int; +++ pub fn git_mempack_reset(backend: *mut git_odb_backend) -> c_int; +++ pub fn git_mempack_dump( +++ pack: *mut git_buf, +++ repo: *mut git_repository, +++ backend: *mut git_odb_backend, +++ ) -> c_int; +++ +++ // refdb +++ pub fn git_refdb_new(out: *mut *mut git_refdb, repo: *mut git_repository) -> c_int; +++ pub fn git_refdb_open(out: *mut *mut git_refdb, repo: *mut git_repository) -> c_int; +++ pub fn git_refdb_backend_fs( +++ out: *mut *mut git_refdb_backend, +++ repo: *mut git_repository, +++ ) -> c_int; +++ pub fn git_refdb_init_backend(backend: *mut git_refdb_backend, version: c_uint) -> c_int; +++ pub fn git_refdb_set_backend(refdb: *mut git_refdb, backend: *mut git_refdb_backend) -> c_int; +++ pub fn git_refdb_compress(refdb: *mut git_refdb) -> c_int; +++ pub fn git_refdb_free(refdb: *mut git_refdb); +++ +++ // rebase +++ pub fn git_rebase_init_options(opts: *mut git_rebase_options, version: c_uint) -> c_int; +++ pub fn git_rebase_init( +++ out: *mut *mut git_rebase, +++ repo: *mut git_repository, +++ branch: *const git_annotated_commit, +++ upstream: *const git_annotated_commit, +++ onto: *const git_annotated_commit, +++ opts: *const git_rebase_options, +++ ) -> c_int; +++ pub fn git_rebase_open( +++ out: *mut *mut git_rebase, +++ repo: *mut git_repository, +++ opts: *const git_rebase_options, +++ ) -> c_int; +++ pub fn git_rebase_operation_entrycount(rebase: *mut git_rebase) -> size_t; +++ pub fn git_rebase_operation_current(rebase: *mut git_rebase) -> size_t; +++ pub fn git_rebase_operation_byindex( +++ rebase: *mut git_rebase, +++ idx: size_t, +++ ) -> *mut git_rebase_operation; +++ pub fn git_rebase_orig_head_id(rebase: *mut git_rebase) -> *const git_oid; +++ pub fn git_rebase_orig_head_name(rebase: *mut git_rebase) -> *const c_char; +++ pub fn git_rebase_next( +++ operation: *mut *mut git_rebase_operation, +++ rebase: *mut git_rebase, +++ ) -> c_int; +++ pub fn git_rebase_inmemory_index(index: *mut *mut git_index, rebase: *mut git_rebase) -> c_int; +++ pub fn git_rebase_commit( +++ id: *mut git_oid, +++ rebase: *mut git_rebase, +++ author: *const git_signature, +++ committer: *const git_signature, +++ message_encoding: *const c_char, +++ message: *const c_char, +++ ) -> c_int; +++ pub fn git_rebase_abort(rebase: *mut git_rebase) -> c_int; +++ pub fn git_rebase_finish(rebase: *mut git_rebase, signature: *const git_signature) -> c_int; +++ pub fn git_rebase_free(rebase: *mut git_rebase); +++ +++ // cherrypick +++ pub fn git_cherrypick_init_options(opts: *mut git_cherrypick_options, version: c_uint) +++ -> c_int; +++ pub fn git_cherrypick( +++ repo: *mut git_repository, +++ commit: *mut git_commit, +++ options: *const git_cherrypick_options, +++ ) -> c_int; +++ pub fn git_cherrypick_commit( +++ out: *mut *mut git_index, +++ repo: *mut git_repository, +++ cherrypick_commit: *mut git_commit, +++ our_commit: *mut git_commit, +++ mainline: c_uint, +++ merge_options: *const git_merge_options, +++ ) -> c_int; +++ +++ // apply +++ pub fn git_apply_options_init(opts: *mut git_apply_options, version: c_uint) -> c_int; +++ pub fn git_apply_to_tree( +++ out: *mut *mut git_index, +++ repo: *mut git_repository, +++ preimage: *mut git_tree, +++ diff: *mut git_diff, +++ options: *const git_apply_options, +++ ) -> c_int; +++ pub fn git_apply( +++ repo: *mut git_repository, +++ diff: *mut git_diff, +++ location: git_apply_location_t, +++ options: *const git_apply_options, +++ ) -> c_int; +++ +++ // revert +++ pub fn git_revert_options_init(opts: *mut git_revert_options, version: c_uint) -> c_int; +++ pub fn git_revert_commit( +++ out: *mut *mut git_index, +++ repo: *mut git_repository, +++ revert_commit: *mut git_commit, +++ our_commit: *mut git_commit, +++ mainline: c_uint, +++ merge_options: *const git_merge_options, +++ ) -> c_int; +++ pub fn git_revert( +++ repo: *mut git_repository, +++ commit: *mut git_commit, +++ given_opts: *const git_revert_options, +++ ) -> c_int; +++ +++ // Common +++ pub fn git_libgit2_version(major: *mut c_int, minor: *mut c_int, rev: *mut c_int) -> c_int; +++ pub fn git_libgit2_features() -> c_int; +++ pub fn git_libgit2_opts(option: c_int, ...) -> c_int; +++ +++ // Worktrees +++ pub fn git_worktree_list(out: *mut git_strarray, repo: *mut git_repository) -> c_int; +++ pub fn git_worktree_lookup( +++ out: *mut *mut git_worktree, +++ repo: *mut git_repository, +++ name: *const c_char, +++ ) -> c_int; +++ pub fn git_worktree_open_from_repository( +++ out: *mut *mut git_worktree, +++ repo: *mut git_repository, +++ ) -> c_int; +++ pub fn git_worktree_free(wt: *mut git_worktree); +++ pub fn git_worktree_validate(wt: *const git_worktree) -> c_int; +++ pub fn git_worktree_add_options_init( +++ opts: *mut git_worktree_add_options, +++ version: c_uint, +++ ) -> c_int; +++ pub fn git_worktree_add( +++ out: *mut *mut git_worktree, +++ repo: *mut git_repository, +++ name: *const c_char, +++ path: *const c_char, +++ opts: *const git_worktree_add_options, +++ ) -> c_int; +++ pub fn git_worktree_lock(wt: *mut git_worktree, reason: *const c_char) -> c_int; +++ pub fn git_worktree_unlock(wt: *mut git_worktree) -> c_int; +++ pub fn git_worktree_is_locked(reason: *mut git_buf, wt: *const git_worktree) -> c_int; +++ pub fn git_worktree_name(wt: *const git_worktree) -> *const c_char; +++ pub fn git_worktree_path(wt: *const git_worktree) -> *const c_char; +++ pub fn git_worktree_prune_options_init( +++ opts: *mut git_worktree_prune_options, +++ version: c_uint, +++ ) -> c_int; +++ pub fn git_worktree_is_prunable( +++ wt: *mut git_worktree, +++ opts: *mut git_worktree_prune_options, +++ ) -> c_int; +++ pub fn git_worktree_prune( +++ wt: *mut git_worktree, +++ opts: *mut git_worktree_prune_options, +++ ) -> c_int; +++ +++ // Ref transactions +++ pub fn git_transaction_new(out: *mut *mut git_transaction, repo: *mut git_repository) -> c_int; +++ pub fn git_transaction_lock_ref(tx: *mut git_transaction, refname: *const c_char) -> c_int; +++ pub fn git_transaction_set_target( +++ tx: *mut git_transaction, +++ refname: *const c_char, +++ target: *const git_oid, +++ sig: *const git_signature, +++ msg: *const c_char, +++ ) -> c_int; +++ pub fn git_transaction_set_symbolic_target( +++ tx: *mut git_transaction, +++ refname: *const c_char, +++ target: *const c_char, +++ sig: *const git_signature, +++ msg: *const c_char, +++ ) -> c_int; +++ pub fn git_transaction_set_reflog( +++ tx: *mut git_transaction, +++ refname: *const c_char, +++ reflog: *const git_reflog, +++ ) -> c_int; +++ pub fn git_transaction_remove(tx: *mut git_transaction, refname: *const c_char) -> c_int; +++ pub fn git_transaction_commit(tx: *mut git_transaction) -> c_int; +++ pub fn git_transaction_free(tx: *mut git_transaction); +++ +++ // Mailmap +++ pub fn git_mailmap_new(out: *mut *mut git_mailmap) -> c_int; +++ pub fn git_mailmap_from_buffer( +++ out: *mut *mut git_mailmap, +++ buf: *const c_char, +++ len: size_t, +++ ) -> c_int; +++ pub fn git_mailmap_from_repository( +++ out: *mut *mut git_mailmap, +++ repo: *mut git_repository, +++ ) -> c_int; +++ pub fn git_mailmap_free(mm: *mut git_mailmap); +++ pub fn git_mailmap_resolve_signature( +++ out: *mut *mut git_signature, +++ mm: *const git_mailmap, +++ sig: *const git_signature, +++ ) -> c_int; +++ pub fn git_mailmap_add_entry( +++ mm: *mut git_mailmap, +++ real_name: *const c_char, +++ real_email: *const c_char, +++ replace_name: *const c_char, +++ replace_email: *const c_char, +++ ) -> c_int; +++ +++ // email +++ pub fn git_email_create_from_diff( +++ out: *mut git_buf, +++ diff: *mut git_diff, +++ patch_idx: usize, +++ patch_count: usize, +++ commit_id: *const git_oid, +++ summary: *const c_char, +++ body: *const c_char, +++ author: *const git_signature, +++ given_opts: *const git_email_create_options, +++ ) -> c_int; +++ +++ pub fn git_email_create_from_commit( +++ out: *mut git_buf, +++ commit: *mut git_commit, +++ given_opts: *const git_email_create_options, +++ ) -> c_int; +++ +++ pub fn git_trace_set(level: git_trace_level_t, cb: git_trace_cb) -> c_int; +++} +++ +++pub fn init() { +++ use std::sync::Once; +++ +++ static INIT: Once = Once::new(); +++ INIT.call_once(|| unsafe { +++ openssl_init(); +++ ssh_init(); +++ let rc = git_libgit2_init(); +++ if rc >= 0 { +++ // Note that we intentionally never schedule `git_libgit2_shutdown` +++ // to get called. There's not really a great time to call that and +++ // #276 has some more info about how automatically doing it can +++ // cause problems. +++ return; +++ } +++ +++ let git_error = git_error_last(); +++ let error = if !git_error.is_null() { +++ CStr::from_ptr((*git_error).message).to_string_lossy() +++ } else { +++ "unknown error".into() +++ }; +++ panic!( +++ "couldn't initialize the libgit2 library: {}, error: {}", +++ rc, error +++ ); +++ }); +++} +++ +++#[cfg(all(unix, feature = "https"))] +++#[doc(hidden)] +++pub fn openssl_init() { +++ openssl_sys::init(); +++} +++ +++#[cfg(any(windows, not(feature = "https")))] +++#[doc(hidden)] +++pub fn openssl_init() {} +++ +++#[cfg(feature = "ssh")] +++fn ssh_init() { +++ libssh2::init(); +++} +++ +++#[cfg(not(feature = "ssh"))] +++fn ssh_init() {} +++ +++#[doc(hidden)] +++pub fn vendored() -> bool { +++ cfg!(libgit2_vendored) +++} diff --cc extra/sha1-checked-0.10.0/.cargo-checksum.json index 0000000000,0000000000,0000000000..e6e44ae8f1 new file mode 100644 --- /dev/null +++ b/extra/sha1-checked-0.10.0/.cargo-checksum.json @@@@ -1,0 -1,0 -1,0 +1,1 @@@@ +++{"files":{"CHANGELOG.md":"66380ce326b6b03522fa2b3ae8a5d23453378d9421822160959b0fe98e75aebb","Cargo.toml":"6c9b65bf842b71222af16c58f2f6616e82c7390e765199e23a465481e3c17c21","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"6d6da4c40195ecbd22595195acd91e1b50bf61bfe0275fa57f8c4d0290f72674","README.md":"fc17b4c8065ccecc63e45cf1e091b8029311655db02bbab5000270346f9c642c","benches/mod.rs":"019335b3f8c28d0626b7cda461659ddf8753c9d21922cef78a26fb10373768f9","src/compress.rs":"b7eadea87d7495fafd8232a5a667f039e61503e41d57f5f21c5d73f51ad29d0b","src/lib.rs":"917cd14ae4af8965f99d97a4a5b5bf9466fca9c14dc2af186f893922119c2c5e","src/ubc_check.rs":"24bce5b8aecfb4394ad961aa2c4112335f0b374e2961971f5843e3175468a904","tests/data/sha-mbles-1.bin":"3ead211681cec93d265c8ac123dd062e105408cebf82fa6e2b126f4f40bcb88c","tests/data/sha-mbles-2.bin":"208feafe1c6a95c73f662514ac48761f25e1f3b74922521a98d9ce287f4a2197","tests/data/sha1.blb":"b9c03b9e56e0a7b08a6d6867599a33cab1a55aec3f41fef910c133fc35dc2851","tests/data/sha1_reducedsha_coll.bin":"f238052907fa3ce28e550806a61f30a73b3394185e63c290439053bef45b3216","tests/data/shattered-1.pdf":"2bb787a73e37352f92383abe7e2902936d1059ad9f1ba6daaa9c1e58ee6970d0","tests/data/shattered-2.pdf":"d4488775d29bdef7993367d541064dbdda50d383f89f0aa13a6ff2e0894ba5ff","tests/mod.rs":"2b5d76415769e882174ee00114bb4cb1955b05261a341b039e0f96ae44408d1f"},"package":"89f599ac0c323ebb1c6082821a54962b839832b03984598375bff3975b804423"} diff --cc extra/sha1-checked-0.10.0/CHANGELOG.md index 0000000000,0000000000,0000000000..dadf785692 new file mode 100644 --- /dev/null +++ b/extra/sha1-checked-0.10.0/CHANGELOG.md @@@@ -1,0 -1,0 -1,0 +1,8 @@@@ +++# Changelog +++ +++All notable changes to this project will be documented in this file. +++ +++The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +++and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +++ +++## UNRELEASED diff --cc extra/sha1-checked-0.10.0/Cargo.toml index 0000000000,0000000000,0000000000..45cdc43a43 new file mode 100644 --- /dev/null +++ b/extra/sha1-checked-0.10.0/Cargo.toml @@@@ -1,0 -1,0 -1,0 +1,78 @@@@ +++# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +++# +++# When uploading crates to the registry Cargo will automatically +++# "normalize" Cargo.toml files for maximal compatibility +++# with all versions of Cargo and also rewrite `path` dependencies +++# to registry (e.g., crates.io) dependencies. +++# +++# If you are reading this file be aware that the original Cargo.toml +++# will likely look very different (and much more reasonable). +++# See Cargo.toml.orig for the original contents. +++ +++[package] +++edition = "2021" +++rust-version = "1.72" +++name = "sha1-checked" +++version = "0.10.0" +++authors = ["RustCrypto Developers"] +++exclude = [ +++ "sha1-checked/tests/data/shattered-1.pdf", +++ "sha1-checked/tests/data/shattered-2.pdf", +++] +++description = "SHA-1 hash function with collision detection" +++documentation = "https://docs.rs/sha1-checked" +++readme = "README.md" +++keywords = [ +++ "crypto", +++ "sha1", +++ "hash", +++ "digest", +++] +++categories = [ +++ "cryptography", +++ "no-std", +++] +++license = "MIT OR Apache-2.0" +++repository = "https://github.com/RustCrypto/hashes" +++ +++[package.metadata.docs.rs] +++all-features = true +++rustdoc-args = [ +++ "--cfg", +++ "docsrs", +++] +++ +++[dependencies.digest] +++version = "0.10.7" +++ +++[dependencies.sha1] +++version = "0.10.6" +++features = ["compress"] +++default-features = false +++ +++[dependencies.zeroize] +++version = "1.7" +++optional = true +++default-features = false +++ +++[dev-dependencies.digest] +++version = "0.10.7" +++features = ["dev"] +++ +++[dev-dependencies.hex-literal] +++version = "0.4" +++ +++[features] +++default = [ +++ "oid", +++ "std", +++] +++oid = [ +++ "digest/oid", +++ "sha1/oid", +++] +++std = [ +++ "digest/std", +++ "sha1/std", +++] +++zeroize = ["dep:zeroize"] diff --cc extra/sha1-checked-0.10.0/LICENSE-APACHE index 0000000000,0000000000,0000000000..78173fa2e7 new file mode 100644 --- /dev/null +++ b/extra/sha1-checked-0.10.0/LICENSE-APACHE @@@@ -1,0 -1,0 -1,0 +1,201 @@@@ +++ Apache License +++ Version 2.0, January 2004 +++ http://www.apache.org/licenses/ +++ +++TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +++ +++1. Definitions. +++ +++ "License" shall mean the terms and conditions for use, reproduction, +++ and distribution as defined by Sections 1 through 9 of this document. +++ +++ "Licensor" shall mean the copyright owner or entity authorized by +++ the copyright owner that is granting the License. +++ +++ "Legal Entity" shall mean the union of the acting entity and all +++ other entities that control, are controlled by, or are under common +++ control with that entity. For the purposes of this definition, +++ "control" means (i) the power, direct or indirect, to cause the +++ direction or management of such entity, whether by contract or +++ otherwise, or (ii) ownership of fifty percent (50%) or more of the +++ outstanding shares, or (iii) beneficial ownership of such entity. +++ +++ "You" (or "Your") shall mean an individual or Legal Entity +++ exercising permissions granted by this License. +++ +++ "Source" form shall mean the preferred form for making modifications, +++ including but not limited to software source code, documentation +++ source, and configuration files. +++ +++ "Object" form shall mean any form resulting from mechanical +++ transformation or translation of a Source form, including but +++ not limited to compiled object code, generated documentation, +++ and conversions to other media types. +++ +++ "Work" shall mean the work of authorship, whether in Source or +++ Object form, made available under the License, as indicated by a +++ copyright notice that is included in or attached to the work +++ (an example is provided in the Appendix below). +++ +++ "Derivative Works" shall mean any work, whether in Source or Object +++ form, that is based on (or derived from) the Work and for which the +++ editorial revisions, annotations, elaborations, or other modifications +++ represent, as a whole, an original work of authorship. For the purposes +++ of this License, Derivative Works shall not include works that remain +++ separable from, or merely link (or bind by name) to the interfaces of, +++ the Work and Derivative Works thereof. +++ +++ "Contribution" shall mean any work of authorship, including +++ the original version of the Work and any modifications or additions +++ to that Work or Derivative Works thereof, that is intentionally +++ submitted to Licensor for inclusion in the Work by the copyright owner +++ or by an individual or Legal Entity authorized to submit on behalf of +++ the copyright owner. For the purposes of this definition, "submitted" +++ means any form of electronic, verbal, or written communication sent +++ to the Licensor or its representatives, including but not limited to +++ communication on electronic mailing lists, source code control systems, +++ and issue tracking systems that are managed by, or on behalf of, the +++ Licensor for the purpose of discussing and improving the Work, but +++ excluding communication that is conspicuously marked or otherwise +++ designated in writing by the copyright owner as "Not a Contribution." +++ +++ "Contributor" shall mean Licensor and any individual or Legal Entity +++ on behalf of whom a Contribution has been received by Licensor and +++ subsequently incorporated within the Work. +++ +++2. Grant of Copyright License. Subject to the terms and conditions of +++ this License, each Contributor hereby grants to You a perpetual, +++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable +++ copyright license to reproduce, prepare Derivative Works of, +++ publicly display, publicly perform, sublicense, and distribute the +++ Work and such Derivative Works in Source or Object form. +++ +++3. Grant of Patent License. Subject to the terms and conditions of +++ this License, each Contributor hereby grants to You a perpetual, +++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable +++ (except as stated in this section) patent license to make, have made, +++ use, offer to sell, sell, import, and otherwise transfer the Work, +++ where such license applies only to those patent claims licensable +++ by such Contributor that are necessarily infringed by their +++ Contribution(s) alone or by combination of their Contribution(s) +++ with the Work to which such Contribution(s) was submitted. If You +++ institute patent litigation against any entity (including a +++ cross-claim or counterclaim in a lawsuit) alleging that the Work +++ or a Contribution incorporated within the Work constitutes direct +++ or contributory patent infringement, then any patent licenses +++ granted to You under this License for that Work shall terminate +++ as of the date such litigation is filed. +++ +++4. Redistribution. You may reproduce and distribute copies of the +++ Work or Derivative Works thereof in any medium, with or without +++ modifications, and in Source or Object form, provided that You +++ meet the following conditions: +++ +++ (a) You must give any other recipients of the Work or +++ Derivative Works a copy of this License; and +++ +++ (b) You must cause any modified files to carry prominent notices +++ stating that You changed the files; and +++ +++ (c) You must retain, in the Source form of any Derivative Works +++ that You distribute, all copyright, patent, trademark, and +++ attribution notices from the Source form of the Work, +++ excluding those notices that do not pertain to any part of +++ the Derivative Works; and +++ +++ (d) If the Work includes a "NOTICE" text file as part of its +++ distribution, then any Derivative Works that You distribute must +++ include a readable copy of the attribution notices contained +++ within such NOTICE file, excluding those notices that do not +++ pertain to any part of the Derivative Works, in at least one +++ of the following places: within a NOTICE text file distributed +++ as part of the Derivative Works; within the Source form or +++ documentation, if provided along with the Derivative Works; or, +++ within a display generated by the Derivative Works, if and +++ wherever such third-party notices normally appear. The contents +++ of the NOTICE file are for informational purposes only and +++ do not modify the License. You may add Your own attribution +++ notices within Derivative Works that You distribute, alongside +++ or as an addendum to the NOTICE text from the Work, provided +++ that such additional attribution notices cannot be construed +++ as modifying the License. +++ +++ You may add Your own copyright statement to Your modifications and +++ may provide additional or different license terms and conditions +++ for use, reproduction, or distribution of Your modifications, or +++ for any such Derivative Works as a whole, provided Your use, +++ reproduction, and distribution of the Work otherwise complies with +++ the conditions stated in this License. +++ +++5. Submission of Contributions. Unless You explicitly state otherwise, +++ any Contribution intentionally submitted for inclusion in the Work +++ by You to the Licensor shall be under the terms and conditions of +++ this License, without any additional terms or conditions. +++ Notwithstanding the above, nothing herein shall supersede or modify +++ the terms of any separate license agreement you may have executed +++ with Licensor regarding such Contributions. +++ +++6. Trademarks. This License does not grant permission to use the trade +++ names, trademarks, service marks, or product names of the Licensor, +++ except as required for reasonable and customary use in describing the +++ origin of the Work and reproducing the content of the NOTICE file. +++ +++7. Disclaimer of Warranty. Unless required by applicable law or +++ agreed to in writing, Licensor provides the Work (and each +++ Contributor provides its Contributions) on an "AS IS" BASIS, +++ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +++ implied, including, without limitation, any warranties or conditions +++ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +++ PARTICULAR PURPOSE. You are solely responsible for determining the +++ appropriateness of using or redistributing the Work and assume any +++ risks associated with Your exercise of permissions under this License. +++ +++8. Limitation of Liability. In no event and under no legal theory, +++ whether in tort (including negligence), contract, or otherwise, +++ unless required by applicable law (such as deliberate and grossly +++ negligent acts) or agreed to in writing, shall any Contributor be +++ liable to You for damages, including any direct, indirect, special, +++ incidental, or consequential damages of any character arising as a +++ result of this License or out of the use or inability to use the +++ Work (including but not limited to damages for loss of goodwill, +++ work stoppage, computer failure or malfunction, or any and all +++ other commercial damages or losses), even if such Contributor +++ has been advised of the possibility of such damages. +++ +++9. Accepting Warranty or Additional Liability. While redistributing +++ the Work or Derivative Works thereof, You may choose to offer, +++ and charge a fee for, acceptance of support, warranty, indemnity, +++ or other liability obligations and/or rights consistent with this +++ License. However, in accepting such obligations, You may act only +++ on Your own behalf and on Your sole responsibility, not on behalf +++ of any other Contributor, and only if You agree to indemnify, +++ defend, and hold each Contributor harmless for any liability +++ incurred by, or claims asserted against, such Contributor by reason +++ of your accepting any such warranty or additional liability. +++ +++END OF TERMS AND CONDITIONS +++ +++APPENDIX: How to apply the Apache License to your work. +++ +++ To apply the Apache License to your work, attach the following +++ boilerplate notice, with the fields enclosed by brackets "[]" +++ replaced with your own identifying information. (Don't include +++ the brackets!) The text should be enclosed in the appropriate +++ comment syntax for the file format. We also recommend that a +++ file or class name and description of purpose be included on the +++ same "printed page" as the copyright notice for easier +++ identification within third-party archives. +++ +++Copyright [yyyy] [name of copyright owner] +++ +++Licensed under the Apache License, Version 2.0 (the "License"); +++you may not use this file except in compliance with the License. +++You may obtain a copy of the License at +++ +++ http://www.apache.org/licenses/LICENSE-2.0 +++ +++Unless required by applicable law or agreed to in writing, software +++distributed under the License is distributed on an "AS IS" BASIS, +++WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +++See the License for the specific language governing permissions and +++limitations under the License. diff --cc extra/sha1-checked-0.10.0/LICENSE-MIT index 0000000000,0000000000,0000000000..455de7c85d new file mode 100644 --- /dev/null +++ b/extra/sha1-checked-0.10.0/LICENSE-MIT @@@@ -1,0 -1,0 -1,0 +1,25 @@@@ +++Copyright (c) 2024 The RustCrypto Project Developers +++ +++Permission is hereby granted, free of charge, to any +++person obtaining a copy of this software and associated +++documentation files (the "Software"), to deal in the +++Software without restriction, including without +++limitation the rights to use, copy, modify, merge, +++publish, distribute, sublicense, and/or sell copies of +++the Software, and to permit persons to whom the Software +++is furnished to do so, subject to the following +++conditions: +++ +++The above copyright notice and this permission notice +++shall be included in all copies or substantial portions +++of the Software. +++ +++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +++ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +++TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +++PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +++SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +++CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +++OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +++IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +++DEALINGS IN THE SOFTWARE. diff --cc extra/sha1-checked-0.10.0/README.md index 0000000000,0000000000,0000000000..32c4bc9128 new file mode 100644 --- /dev/null +++ b/extra/sha1-checked-0.10.0/README.md @@@@ -1,0 -1,0 -1,0 +1,98 @@@@ +++# RustCrypto: SHA-1 Checked +++ +++[![crate][crate-image]][crate-link] +++[![Docs][docs-image]][docs-link] +++![Apache2/MIT licensed][license-image] +++![Rust Version][rustc-image] +++[![Project Chat][chat-image]][chat-link] +++[![Build Status][build-image]][build-link] +++ +++Pure Rust implementation of the [SHA-1] cryptographic hash algorithm with collision detection. +++ +++## 🚨 Warning: Cryptographically Broken! 🚨 +++ +++The SHA-1 hash function should be considered cryptographically broken and +++unsuitable for further use in any security critical capacity, as it is +++[practically vulnerable to chosen-prefix collisions][1]. +++ +++But, this crate provides the detection [algorithm] pioneered by git, to detect hash collisions when they +++occur and prevent them. The [paper] has more details on how this works. +++ +++This implementation will be slower to use than the pure SHA-1 implementation, as more work as to be done. +++ +++## Examples +++ +++### One-shot API +++ +++```rust +++use hex_literal::hex; +++use sha1_checked::Sha1; +++ +++let result = Sha1::try_digest(b"hello world"); +++assert_eq!(result.hash().as_ref(), hex!("2aae6c35c94fcfb415dbe95f408b9ce91ee846ed")); +++assert!(!result.has_collision()); +++``` +++ +++### Incremental API +++ +++```rust +++use hex_literal::hex; +++use sha1_checked::{Sha1, Digest}; +++ +++let mut hasher = Sha1::new(); +++hasher.update(b"hello world"); +++let result = hasher.try_finalize(); +++ +++assert_eq!(result.hash().as_ref(), hex!("2aae6c35c94fcfb415dbe95f408b9ce91ee846ed")); +++assert!(!result.has_collision()); +++``` +++ +++Also, see the [examples section] in the RustCrypto/hashes readme. +++ +++## Minimum Supported Rust Version +++ +++Rust **1.72** or higher. +++ +++Minimum supported Rust version can be changed in the future, but it will be +++done with a minor version bump. +++ +++## SemVer Policy +++ +++- All on-by-default features of this library are covered by SemVer +++- MSRV is considered exempt from SemVer as noted above +++ +++## License +++ +++The crate is licensed under either of: +++ +++* [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) +++* [MIT license](http://opensource.org/licenses/MIT) +++ +++at your option. +++ +++### Contribution +++ +++Unless you explicitly state otherwise, any contribution intentionally submitted +++for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +++dual licensed as above, without any additional terms or conditions. +++ +++[//]: # (badges) +++ +++[crate-image]: https://img.shields.io/crates/v/sha1-checked.svg +++[crate-link]: https://crates.io/crates/sha1-checked +++[docs-image]: https://docs.rs/sha1-checked/badge.svg +++[docs-link]: https://docs.rs/sha1-checked/ +++[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +++[rustc-image]: https://img.shields.io/badge/rustc-1.72+-blue.svg +++[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg +++[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260041-hashes +++[build-image]: https://github.com/RustCrypto/hashes/workflows/sha1-checked/badge.svg?branch=master +++[build-link]: https://github.com/RustCrypto/hashes/actions?query=workflow%3Asha1-checked +++ +++[//]: # (general links) +++ +++[SHA-1]: https://en.wikipedia.org/wiki/SHA-1 +++[1]: https://sha-mbles.github.io/ +++[examples section]: https://github.com/RustCrypto/hashes#Examples +++[algorithm]: https://github.com/cr-marcstevens/sha1collisiondetection +++[paper]: https://marc-stevens.nl/research/papers/C13-S.pdf diff --cc extra/sha1-checked-0.10.0/src/compress.rs index 0000000000,0000000000,0000000000..60e4bf8763 new file mode 100644 --- /dev/null +++ b/extra/sha1-checked-0.10.0/src/compress.rs @@@@ -1,0 -1,0 -1,0 +1,787 @@@@ +++//! Direct translation of the C code found at +++//! [sha1.c](https://github.com/cr-marcstevens/sha1collisiondetection/blob/master/lib/sha1.c). +++//! +++//! For the original license and source details see the comments in `src/checked.rs`. +++ +++#![allow(clippy::many_single_char_names, clippy::too_many_arguments)] +++ +++use crate::{ +++ BLOCK_SIZE, +++ {ubc_check::Testt, DetectionState}, +++}; +++ +++const K: [u32; 4] = [0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6]; +++ +++#[inline(always)] +++fn mix(w: &mut [u32; 80], t: usize) -> u32 { +++ (w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]).rotate_left(1) +++} +++ +++#[inline(always)] +++fn f1(b: u32, c: u32, d: u32) -> u32 { +++ d ^ b & (c ^ d) +++} +++ +++#[inline(always)] +++fn f2(b: u32, c: u32, d: u32) -> u32 { +++ b ^ c ^ d +++} +++ +++#[inline(always)] +++fn f3(b: u32, c: u32, d: u32) -> u32 { +++ (b & c).wrapping_add(d & (b ^ c)) +++} +++ +++#[inline(always)] +++fn f4(b: u32, c: u32, d: u32) -> u32 { +++ b ^ c ^ d +++} +++ +++#[inline(always)] +++fn round3_step(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, mt: u32) { +++ *e = e.wrapping_add( +++ a.rotate_left(5) +++ .wrapping_add(f3(*b, c, d)) +++ .wrapping_add(K[2]) +++ .wrapping_add(mt), +++ ); +++ *b = b.rotate_left(30); +++} +++ +++#[inline(always)] +++fn round4_step(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, mt: u32) { +++ *e = e.wrapping_add( +++ a.rotate_left(5) +++ .wrapping_add(f4(*b, c, d)) +++ .wrapping_add(K[3]) +++ .wrapping_add(mt), +++ ); +++ *b = b.rotate_left(30); +++} +++ +++#[inline(always)] +++fn round1_step_bw(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, mt: u32) { +++ *b = b.rotate_right(30); +++ *e = e.wrapping_sub( +++ a.rotate_left(5) +++ .wrapping_add(f1(*b, c, d)) +++ .wrapping_add(K[0]) +++ .wrapping_add(mt), +++ ); +++} +++ +++#[inline(always)] +++fn round2_step_bw(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, mt: u32) { +++ *b = b.rotate_right(30); +++ *e = e.wrapping_sub( +++ a.rotate_left(5) +++ .wrapping_add(f2(*b, c, d)) +++ .wrapping_add(K[1]) +++ .wrapping_add(mt), +++ ); +++} +++ +++#[inline(always)] +++fn round3_step_bw(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, mt: u32) { +++ *b = b.rotate_right(30); +++ *e = e.wrapping_sub( +++ a.rotate_left(5) +++ .wrapping_add(f3(*b, c, d)) +++ .wrapping_add(K[2]) +++ .wrapping_add(mt), +++ ); +++} +++ +++#[inline(always)] +++fn round4_step_bw(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, mt: u32) { +++ *b = b.rotate_right(30); +++ *e = e.wrapping_sub( +++ a.rotate_left(5) +++ .wrapping_add(f4(*b, c, d)) +++ .wrapping_add(K[3]) +++ .wrapping_add(mt), +++ ); +++} +++ +++#[inline(always)] +++fn full_round3_step(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, w: &mut [u32; 80], t: usize) { +++ w[t] = mix(w, t); +++ *e = e.wrapping_add( +++ w[t].wrapping_add(a.rotate_left(5)) +++ .wrapping_add(f3(*b, c, d)) +++ .wrapping_add(K[2]), +++ ); +++ *b = b.rotate_left(30); +++} +++ +++#[inline(always)] +++fn full_round4_step(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, w: &mut [u32; 80], t: usize) { +++ w[t] = mix(w, t); +++ *e = e.wrapping_add( +++ w[t].wrapping_add(a.rotate_left(5)) +++ .wrapping_add(f4(*b, c, d)) +++ .wrapping_add(K[3]), +++ ); +++ *b = b.rotate_left(30); +++} +++ +++#[inline] +++fn round2_step4( +++ a: &mut u32, +++ b: &mut u32, +++ c: &mut u32, +++ d: &mut u32, +++ e: &mut u32, +++ w: &[u32; 80], +++ t: usize, +++) { +++ // 1 +++ *e = e.wrapping_add( +++ w[t].wrapping_add(a.rotate_left(5)) +++ .wrapping_add(f2(*b, *c, *d)) +++ .wrapping_add(K[1]), +++ ); +++ *b = b.rotate_left(30); +++ +++ // 2 +++ *d = d.wrapping_add( +++ w[t + 1] +++ .wrapping_add(e.rotate_left(5)) +++ .wrapping_add(f2(*a, *b, *c)) +++ .wrapping_add(K[1]), +++ ); +++ *a = a.rotate_left(30); +++ +++ // 3 +++ *c = c.wrapping_add( +++ w[t + 2] +++ .wrapping_add(d.rotate_left(5)) +++ .wrapping_add(f2(*e, *a, *b)) +++ .wrapping_add(K[1]), +++ ); +++ *e = e.rotate_left(30); +++ +++ // 4 +++ *b = b.wrapping_add( +++ w[t + 3] +++ .wrapping_add(c.rotate_left(5)) +++ .wrapping_add(f2(*d, *e, *a)) +++ .wrapping_add(K[1]), +++ ); +++ *d = d.rotate_left(30); +++} +++ +++#[inline] +++fn round3_step4( +++ a: &mut u32, +++ b: &mut u32, +++ c: &mut u32, +++ d: &mut u32, +++ e: &mut u32, +++ w: &[u32; 80], +++ t: usize, +++) { +++ // 1 +++ *e = e.wrapping_add( +++ w[t].wrapping_add(a.rotate_left(5)) +++ .wrapping_add(f3(*b, *c, *d)) +++ .wrapping_add(K[2]), +++ ); +++ *b = b.rotate_left(30); +++ +++ // 2 +++ *d = d.wrapping_add( +++ w[t + 1] +++ .wrapping_add(e.rotate_left(5)) +++ .wrapping_add(f3(*a, *b, *c)) +++ .wrapping_add(K[2]), +++ ); +++ *a = a.rotate_left(30); +++ +++ // 3 +++ *c = c.wrapping_add( +++ w[t + 2] +++ .wrapping_add(d.rotate_left(5)) +++ .wrapping_add(f3(*e, *a, *b)) +++ .wrapping_add(K[2]), +++ ); +++ *e = e.rotate_left(30); +++ +++ // 4 +++ *b = b.wrapping_add( +++ w[t + 3] +++ .wrapping_add(c.rotate_left(5)) +++ .wrapping_add(f3(*d, *e, *a)) +++ .wrapping_add(K[2]), +++ ); +++ *d = d.rotate_left(30); +++} +++ +++#[inline] +++fn round4_step4( +++ a: &mut u32, +++ b: &mut u32, +++ c: &mut u32, +++ d: &mut u32, +++ e: &mut u32, +++ w: &[u32; 80], +++ t: usize, +++) { +++ // 1 +++ *e = e.wrapping_add( +++ w[t].wrapping_add(a.rotate_left(5)) +++ .wrapping_add(f4(*b, *c, *d)) +++ .wrapping_add(K[3]), +++ ); +++ *b = b.rotate_left(30); +++ +++ // 2 +++ *d = d.wrapping_add( +++ w[t + 1] +++ .wrapping_add(e.rotate_left(5)) +++ .wrapping_add(f4(*a, *b, *c)) +++ .wrapping_add(K[3]), +++ ); +++ *a = a.rotate_left(30); +++ +++ // 3 +++ *c = c.wrapping_add( +++ w[t + 2] +++ .wrapping_add(d.rotate_left(5)) +++ .wrapping_add(f4(*e, *a, *b)) +++ .wrapping_add(K[3]), +++ ); +++ *e = e.rotate_left(30); +++ +++ // 4 +++ *b = b.wrapping_add( +++ w[t + 3] +++ .wrapping_add(c.rotate_left(5)) +++ .wrapping_add(f4(*d, *e, *a)) +++ .wrapping_add(K[3]), +++ ); +++ *d = d.rotate_left(30); +++} +++ +++#[inline] +++fn full_round1_step_load4( +++ a: &mut u32, +++ b: &mut u32, +++ c: &mut u32, +++ d: &mut u32, +++ e: &mut u32, +++ m: &[u32; 16], +++ w: &mut [u32; 80], +++ t: usize, +++) { +++ // load +++ w[t..t + 4].copy_from_slice(&m[t..t + 4]); +++ round1_step4(a, b, c, d, e, w, t); +++} +++ +++#[inline(always)] +++fn round1_step4( +++ a: &mut u32, +++ b: &mut u32, +++ c: &mut u32, +++ d: &mut u32, +++ e: &mut u32, +++ w: &[u32; 80], +++ t: usize, +++) { +++ // 1 +++ *e = e.wrapping_add( +++ w[t].wrapping_add(a.rotate_left(5)) +++ .wrapping_add(f1(*b, *c, *d)) +++ .wrapping_add(K[0]), +++ ); +++ *b = b.rotate_left(30); +++ +++ // 2 +++ *d = d.wrapping_add( +++ w[t + 1] +++ .wrapping_add(e.rotate_left(5)) +++ .wrapping_add(f1(*a, *b, *c)) +++ .wrapping_add(K[0]), +++ ); +++ *a = a.rotate_left(30); +++ +++ // 3 +++ *c = c.wrapping_add( +++ w[t + 2] +++ .wrapping_add(d.rotate_left(5)) +++ .wrapping_add(f1(*e, *a, *b)) +++ .wrapping_add(K[0]), +++ ); +++ *e = e.rotate_left(30); +++ +++ // 4 +++ *b = b.wrapping_add( +++ w[t + 3] +++ .wrapping_add(c.rotate_left(5)) +++ .wrapping_add(f1(*d, *e, *a)) +++ .wrapping_add(K[0]), +++ ); +++ *d = d.rotate_left(30); +++} +++ +++#[inline] +++fn full_round1_step_expand4( +++ a: &mut u32, +++ b: &mut u32, +++ c: &mut u32, +++ d: &mut u32, +++ e: &mut u32, +++ w: &mut [u32; 80], +++ t: usize, +++) { +++ w[t] = mix(w, t); +++ w[t + 1] = mix(w, t + 1); +++ w[t + 2] = mix(w, t + 2); +++ w[t + 3] = mix(w, t + 3); +++ round1_step4(a, b, c, d, e, w, t); +++} +++ +++#[inline] +++fn full_round2_step4( +++ a: &mut u32, +++ b: &mut u32, +++ c: &mut u32, +++ d: &mut u32, +++ e: &mut u32, +++ w: &mut [u32; 80], +++ t: usize, +++) { +++ w[t] = mix(w, t); +++ w[t + 1] = mix(w, t + 1); +++ w[t + 2] = mix(w, t + 2); +++ w[t + 3] = mix(w, t + 3); +++ round2_step4(a, b, c, d, e, w, t); +++} +++ +++#[inline] +++fn full_round3_step4( +++ a: &mut u32, +++ b: &mut u32, +++ c: &mut u32, +++ d: &mut u32, +++ e: &mut u32, +++ w: &mut [u32; 80], +++ t: usize, +++) { +++ w[t] = mix(w, t); +++ w[t + 1] = mix(w, t + 1); +++ w[t + 2] = mix(w, t + 2); +++ w[t + 3] = mix(w, t + 3); +++ round3_step4(a, b, c, d, e, w, t); +++} +++ +++#[inline] +++fn full_round4_step4( +++ a: &mut u32, +++ b: &mut u32, +++ c: &mut u32, +++ d: &mut u32, +++ e: &mut u32, +++ w: &mut [u32; 80], +++ t: usize, +++) { +++ w[t] = mix(w, t); +++ w[t + 1] = mix(w, t + 1); +++ w[t + 2] = mix(w, t + 2); +++ w[t + 3] = mix(w, t + 3); +++ round4_step4(a, b, c, d, e, w, t); +++} +++ +++#[inline] +++fn round1_step_bw4( +++ a: &mut u32, +++ b: &mut u32, +++ c: &mut u32, +++ d: &mut u32, +++ e: &mut u32, +++ m: &[u32; 80], +++ t: usize, +++) { +++ round1_step_bw(*a, b, *c, *d, e, m[t]); +++ round1_step_bw(*b, c, *d, *e, a, m[t - 1]); +++ round1_step_bw(*c, d, *e, *a, b, m[t - 2]); +++ round1_step_bw(*d, e, *a, *b, c, m[t - 3]); +++} +++ +++#[inline] +++fn round2_step_bw4( +++ a: &mut u32, +++ b: &mut u32, +++ c: &mut u32, +++ d: &mut u32, +++ e: &mut u32, +++ m: &[u32; 80], +++ t: usize, +++) { +++ round2_step_bw(*a, b, *c, *d, e, m[t]); +++ round2_step_bw(*b, c, *d, *e, a, m[t - 1]); +++ round2_step_bw(*c, d, *e, *a, b, m[t - 2]); +++ round2_step_bw(*d, e, *a, *b, c, m[t - 3]); +++} +++ +++#[inline] +++fn round3_step_bw4( +++ a: &mut u32, +++ b: &mut u32, +++ c: &mut u32, +++ d: &mut u32, +++ e: &mut u32, +++ m: &[u32; 80], +++ t: usize, +++) { +++ round3_step_bw(*a, b, *c, *d, e, m[t]); +++ round3_step_bw(*b, c, *d, *e, a, m[t - 1]); +++ round3_step_bw(*c, d, *e, *a, b, m[t - 2]); +++ round3_step_bw(*d, e, *a, *b, c, m[t - 3]); +++} +++ +++#[inline] +++fn round4_step_bw4( +++ a: &mut u32, +++ b: &mut u32, +++ c: &mut u32, +++ d: &mut u32, +++ e: &mut u32, +++ m: &[u32; 80], +++ t: usize, +++) { +++ round4_step_bw(*a, b, *c, *d, e, m[t]); +++ round4_step_bw(*b, c, *d, *e, a, m[t - 1]); +++ round4_step_bw(*c, d, *e, *a, b, m[t - 2]); +++ round4_step_bw(*d, e, *a, *b, c, m[t - 3]); +++} +++ +++fn add_assign(left: &mut [u32; 5], right: [u32; 5]) { +++ left[0] = left[0].wrapping_add(right[0]); +++ left[1] = left[1].wrapping_add(right[1]); +++ left[2] = left[2].wrapping_add(right[2]); +++ left[3] = left[3].wrapping_add(right[3]); +++ left[4] = left[4].wrapping_add(right[4]); +++} +++ +++fn compression_w(ihv: &mut [u32; 5], w: &[u32; 80]) { +++ let [mut a, mut b, mut c, mut d, mut e] = ihv; +++ +++ round1_step4(&mut a, &mut b, &mut c, &mut d, &mut e, w, 0); +++ round1_step4(&mut b, &mut c, &mut d, &mut e, &mut a, w, 4); +++ round1_step4(&mut c, &mut d, &mut e, &mut a, &mut b, w, 8); +++ round1_step4(&mut d, &mut e, &mut a, &mut b, &mut c, w, 12); +++ round1_step4(&mut e, &mut a, &mut b, &mut c, &mut d, w, 16); +++ +++ round2_step4(&mut a, &mut b, &mut c, &mut d, &mut e, w, 20); +++ round2_step4(&mut b, &mut c, &mut d, &mut e, &mut a, w, 24); +++ round2_step4(&mut c, &mut d, &mut e, &mut a, &mut b, w, 28); +++ round2_step4(&mut d, &mut e, &mut a, &mut b, &mut c, w, 32); +++ round2_step4(&mut e, &mut a, &mut b, &mut c, &mut d, w, 36); +++ +++ round3_step4(&mut a, &mut b, &mut c, &mut d, &mut e, w, 40); +++ round3_step4(&mut b, &mut c, &mut d, &mut e, &mut a, w, 44); +++ round3_step4(&mut c, &mut d, &mut e, &mut a, &mut b, w, 48); +++ round3_step4(&mut d, &mut e, &mut a, &mut b, &mut c, w, 52); +++ round3_step4(&mut e, &mut a, &mut b, &mut c, &mut d, w, 56); +++ +++ round4_step4(&mut a, &mut b, &mut c, &mut d, &mut e, w, 60); +++ round4_step4(&mut b, &mut c, &mut d, &mut e, &mut a, w, 64); +++ round4_step4(&mut c, &mut d, &mut e, &mut a, &mut b, w, 68); +++ round4_step4(&mut d, &mut e, &mut a, &mut b, &mut c, w, 72); +++ round4_step4(&mut e, &mut a, &mut b, &mut c, &mut d, w, 76); +++ +++ add_assign(ihv, [a, b, c, d, e]); +++} +++ +++fn compression_states( +++ ihv: &mut [u32; 5], +++ m: &[u32; 16], +++ w: &mut [u32; 80], +++ state_58: &mut [u32; 5], +++ state_65: &mut [u32; 5], +++) { +++ let [mut a, mut b, mut c, mut d, mut e] = ihv; +++ +++ full_round1_step_load4(&mut a, &mut b, &mut c, &mut d, &mut e, m, w, 0); +++ full_round1_step_load4(&mut b, &mut c, &mut d, &mut e, &mut a, m, w, 4); +++ full_round1_step_load4(&mut c, &mut d, &mut e, &mut a, &mut b, m, w, 8); +++ full_round1_step_load4(&mut d, &mut e, &mut a, &mut b, &mut c, m, w, 12); +++ +++ full_round1_step_expand4(&mut e, &mut a, &mut b, &mut c, &mut d, w, 16); +++ +++ full_round2_step4(&mut a, &mut b, &mut c, &mut d, &mut e, w, 20); +++ full_round2_step4(&mut b, &mut c, &mut d, &mut e, &mut a, w, 24); +++ full_round2_step4(&mut c, &mut d, &mut e, &mut a, &mut b, w, 28); +++ full_round2_step4(&mut d, &mut e, &mut a, &mut b, &mut c, w, 32); +++ full_round2_step4(&mut e, &mut a, &mut b, &mut c, &mut d, w, 36); +++ +++ full_round3_step4(&mut a, &mut b, &mut c, &mut d, &mut e, w, 40); +++ full_round3_step4(&mut b, &mut c, &mut d, &mut e, &mut a, w, 44); +++ full_round3_step4(&mut c, &mut d, &mut e, &mut a, &mut b, w, 48); +++ full_round3_step4(&mut d, &mut e, &mut a, &mut b, &mut c, w, 52); +++ +++ full_round3_step(e, &mut a, b, c, &mut d, w, 56); +++ full_round3_step(d, &mut e, a, b, &mut c, w, 57); +++ +++ // Store state58 +++ *state_58 = [a, b, c, d, e]; +++ +++ full_round3_step(c, &mut d, e, a, &mut b, w, 58); +++ full_round3_step(b, &mut c, d, e, &mut a, w, 59); +++ +++ full_round4_step4(&mut a, &mut b, &mut c, &mut d, &mut e, w, 60); +++ full_round4_step(b, &mut c, d, e, &mut a, w, 64); +++ +++ // Store state65 +++ *state_65 = [a, b, c, d, e]; +++ +++ full_round4_step(a, &mut b, c, d, &mut e, w, 65); +++ full_round4_step(e, &mut a, b, c, &mut d, w, 66); +++ full_round4_step(d, &mut e, a, b, &mut c, w, 67); +++ +++ full_round4_step4(&mut c, &mut d, &mut e, &mut a, &mut b, w, 68); +++ full_round4_step4(&mut d, &mut e, &mut a, &mut b, &mut c, w, 72); +++ full_round4_step4(&mut e, &mut a, &mut b, &mut c, &mut d, w, 76); +++ +++ add_assign(ihv, [a, b, c, d, e]); +++} +++ +++fn recompress_fast_58( +++ ihvin: &mut [u32; 5], +++ ihvout: &mut [u32; 5], +++ me2: &[u32; 80], +++ state: &[u32; 5], +++) { +++ let [mut a, mut b, mut c, mut d, mut e] = state; +++ +++ round3_step_bw(d, &mut e, a, b, &mut c, me2[57]); +++ round3_step_bw(e, &mut a, b, c, &mut d, me2[56]); +++ +++ round3_step_bw4(&mut a, &mut b, &mut c, &mut d, &mut e, me2, 55); +++ round3_step_bw4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 51); +++ round3_step_bw4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 47); +++ round3_step_bw4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 43); +++ +++ round2_step_bw4(&mut b, &mut c, &mut d, &mut e, &mut a, me2, 39); +++ round2_step_bw4(&mut a, &mut b, &mut c, &mut d, &mut e, me2, 35); +++ round2_step_bw4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 31); +++ round2_step_bw4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 27); +++ round2_step_bw4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 23); +++ +++ round1_step_bw4(&mut b, &mut c, &mut d, &mut e, &mut a, me2, 19); +++ round1_step_bw4(&mut a, &mut b, &mut c, &mut d, &mut e, me2, 15); +++ round1_step_bw4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 11); +++ round1_step_bw4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 7); +++ round1_step_bw4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 3); +++ +++ *ihvin = [a, b, c, d, e]; +++ [a, b, c, d, e] = *state; +++ +++ round3_step(c, &mut d, e, a, &mut b, me2[58]); +++ round3_step(b, &mut c, d, e, &mut a, me2[59]); +++ +++ round4_step4(&mut a, &mut b, &mut c, &mut d, &mut e, me2, 60); +++ round4_step4(&mut b, &mut c, &mut d, &mut e, &mut a, me2, 64); +++ round4_step4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 68); +++ round4_step4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 72); +++ round4_step4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 76); +++ +++ ihvout[0] = ihvin[0].wrapping_add(a); +++ ihvout[1] = ihvin[1].wrapping_add(b); +++ ihvout[2] = ihvin[2].wrapping_add(c); +++ ihvout[3] = ihvin[3].wrapping_add(d); +++ ihvout[4] = ihvin[4].wrapping_add(e); +++} +++ +++fn recompress_fast_65( +++ ihvin: &mut [u32; 5], +++ ihvout: &mut [u32; 5], +++ me2: &[u32; 80], +++ state: &[u32; 5], +++) { +++ let [mut a, mut b, mut c, mut d, mut e] = state; +++ +++ round4_step_bw(b, &mut c, d, e, &mut a, me2[64]); +++ round4_step_bw4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 63); +++ +++ round3_step_bw4(&mut b, &mut c, &mut d, &mut e, &mut a, me2, 59); +++ round3_step_bw4(&mut a, &mut b, &mut c, &mut d, &mut e, me2, 55); +++ round3_step_bw4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 51); +++ round3_step_bw4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 47); +++ round3_step_bw4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 43); +++ +++ round2_step_bw4(&mut b, &mut c, &mut d, &mut e, &mut a, me2, 39); +++ round2_step_bw4(&mut a, &mut b, &mut c, &mut d, &mut e, me2, 35); +++ round2_step_bw4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 31); +++ round2_step_bw4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 27); +++ round2_step_bw4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 23); +++ +++ round1_step_bw4(&mut b, &mut c, &mut d, &mut e, &mut a, me2, 19); +++ round1_step_bw4(&mut a, &mut b, &mut c, &mut d, &mut e, me2, 15); +++ round1_step_bw4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 11); +++ round1_step_bw4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 7); +++ round1_step_bw4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 3); +++ +++ *ihvin = [a, b, c, d, e]; +++ [a, b, c, d, e] = *state; +++ +++ round4_step(a, &mut b, c, d, &mut e, me2[65]); +++ round4_step(e, &mut a, b, c, &mut d, me2[66]); +++ round4_step(d, &mut e, a, b, &mut c, me2[67]); +++ +++ round4_step4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 68); +++ round4_step4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 72); +++ round4_step4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 76); +++ +++ ihvout[0] = ihvin[0].wrapping_add(a); +++ ihvout[1] = ihvin[1].wrapping_add(b); +++ ihvout[2] = ihvin[2].wrapping_add(c); +++ ihvout[3] = ihvin[3].wrapping_add(d); +++ ihvout[4] = ihvin[4].wrapping_add(e); +++} +++ +++fn recompression_step( +++ step: Testt, +++ ihvin: &mut [u32; 5], +++ ihvout: &mut [u32; 5], +++ me2: &[u32; 80], +++ state: &[u32; 5], +++) { +++ match step { +++ Testt::T58 => { +++ recompress_fast_58(ihvin, ihvout, me2, state); +++ } +++ Testt::T65 => { +++ recompress_fast_65(ihvin, ihvout, me2, state); +++ } +++ } +++} +++ +++#[inline(always)] +++fn xor(a: &[u32; 5], b: &[u32; 5]) -> u32 { +++ a[0] ^ b[0] | a[1] ^ b[1] | a[2] ^ b[2] | a[3] ^ b[3] | a[4] ^ b[4] +++} +++ +++#[inline] +++pub(super) fn compress( +++ state: &mut [u32; 5], +++ ctx: &mut DetectionState, +++ blocks: &[[u8; BLOCK_SIZE]], +++) { +++ let mut block_u32 = [0u32; BLOCK_SIZE / 4]; +++ +++ for block in blocks.iter() { +++ ctx.ihv1.copy_from_slice(&*state); +++ +++ for (o, chunk) in block_u32.iter_mut().zip(block.chunks_exact(4)) { +++ *o = u32::from_be_bytes(chunk.try_into().unwrap()); +++ } +++ +++ let DetectionState { +++ m1, +++ state_58, +++ state_65, +++ .. +++ } = ctx; +++ +++ compression_states(state, &block_u32, m1, state_58, state_65); +++ +++ let ubc_mask = if ctx.ubc_check { +++ crate::ubc_check::ubc_check(&ctx.m1) +++ } else { +++ 0xFFFFFFFF +++ }; +++ +++ if ubc_mask != 0 { +++ let mut ihvtmp = [0u32; 5]; +++ for dv_type in &crate::ubc_check::SHA1_DVS { +++ if ubc_mask & (1 << dv_type.maskb) != 0 { +++ for ((m2, m1), dm) in +++ ctx.m2.iter_mut().zip(ctx.m1.iter()).zip(dv_type.dm.iter()) +++ { +++ *m2 = m1 ^ dm; +++ } +++ let DetectionState { +++ ihv2, +++ m2, +++ state_58, +++ state_65, +++ .. +++ } = ctx; +++ +++ recompression_step( +++ dv_type.testt, +++ ihv2, +++ &mut ihvtmp, +++ m2, +++ match dv_type.testt { +++ Testt::T58 => state_58, +++ Testt::T65 => state_65, +++ }, +++ ); +++ +++ // to verify SHA-1 collision detection code with collisions for reduced-step SHA-1 +++ if (0 == xor(&ihvtmp, &*state)) +++ || (ctx.reduced_round_collision && 0 == xor(&ctx.ihv1, &ctx.ihv2)) +++ { +++ ctx.found_collision = true; +++ +++ if ctx.safe_hash { +++ compression_w(state, &ctx.m1); +++ compression_w(state, &ctx.m1); +++ } +++ break; +++ } +++ } +++ } +++ } +++ } +++} +++ +++const SHA1_PADDING: [u8; 64] = [ +++ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +++ 0, +++]; +++ +++#[inline] +++pub(super) fn finalize( +++ state: &mut [u32; 5], +++ total: u64, +++ last_block: &[u8], +++ ctx: &mut DetectionState, +++) { +++ let mut total = total + last_block.len() as u64; +++ let last = last_block.len(); +++ let needs_two_blocks = last >= 56; +++ +++ let mut buffer = [0u8; BLOCK_SIZE]; +++ buffer[..last].copy_from_slice(last_block); +++ let left = BLOCK_SIZE - last; +++ +++ if needs_two_blocks { +++ let padn = 120 - last; +++ let (pad0, pad1) = SHA1_PADDING[..padn].split_at(left); +++ buffer[last..].copy_from_slice(pad0); +++ compress(state, ctx, &[buffer]); +++ buffer[..pad1.len()].copy_from_slice(pad1); +++ } else { +++ let padn = 56 - last; +++ buffer[last..56].copy_from_slice(&SHA1_PADDING[..padn]); +++ } +++ +++ total <<= 3; +++ +++ buffer[56] = (total >> 56) as u8; +++ buffer[57] = (total >> 48) as u8; +++ buffer[58] = (total >> 40) as u8; +++ buffer[59] = (total >> 32) as u8; +++ buffer[60] = (total >> 24) as u8; +++ buffer[61] = (total >> 16) as u8; +++ buffer[62] = (total >> 8) as u8; +++ buffer[63] = total as u8; +++ +++ compress(state, ctx, &[buffer]); +++} diff --cc extra/sha1-checked-0.10.0/src/lib.rs index 0000000000,0000000000,0000000000..1dcf28daf3 new file mode 100644 --- /dev/null +++ b/extra/sha1-checked-0.10.0/src/lib.rs @@@@ -1,0 -1,0 -1,0 +1,369 @@@@ +++#![no_std] +++#![doc = include_str!("../README.md")] +++#![doc( +++ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", +++ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" +++)] +++#![cfg_attr(docsrs, feature(doc_auto_cfg))] +++#![warn(missing_docs, rust_2018_idioms)] +++ +++//! Collision checked Sha1. +++//! +++//! General techniques and implementation are based on the research and implementation done in [1], [2] by +++//! Marc Stevens. +++//! +++//! +++//! Original license can be found in [3]. +++//! +++//! [1]: https://github.com/cr-marcstevens/sha1collisiondetection +++//! [2]: https://marc-stevens.nl/research/papers/C13-S.pdf +++//! [3]: https://github.com/cr-marcstevens/sha1collisiondetection/blob/master/LICENSE.txt +++ +++pub use digest::{self, Digest}; +++ +++use core::slice::from_ref; +++ +++#[cfg(feature = "std")] +++extern crate std; +++ +++use digest::{ +++ block_buffer::{BlockBuffer, Eager}, +++ core_api::BlockSizeUser, +++ typenum::{Unsigned, U20, U64}, +++ FixedOutput, FixedOutputReset, HashMarker, Output, OutputSizeUser, Reset, Update, +++}; +++#[cfg(feature = "zeroize")] +++use zeroize::{Zeroize, ZeroizeOnDrop}; +++ +++const BLOCK_SIZE: usize = ::BlockSize::USIZE; +++const STATE_LEN: usize = 5; +++const INITIAL_H: [u32; 5] = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]; +++ +++mod compress; +++mod ubc_check; +++ +++/// SHA-1 collision detection hasher state. +++#[derive(Clone)] +++pub struct Sha1 { +++ h: [u32; STATE_LEN], +++ block_len: u64, +++ detection: Option, +++ buffer: BlockBuffer, +++} +++ +++impl HashMarker for Sha1 {} +++ +++impl Default for Sha1 { +++ fn default() -> Self { +++ Builder::default().build() +++ } +++} +++ +++impl Sha1 { +++ /// Create a new Sha1 instance, with collision detection enabled. +++ pub fn new() -> Self { +++ Self::default() +++ } +++ +++ /// Create a new Sha1 builder to configure detection. +++ pub fn builder() -> Builder { +++ Builder::default() +++ } +++ +++ /// Oneshot hashing, reporting the collision state. +++ /// +++ /// # Examples +++ /// +++ /// ``` +++ /// use hex_literal::hex; +++ /// use sha1_checked::Sha1; +++ /// +++ /// let result = Sha1::try_digest(b"hello world"); +++ /// assert_eq!(result.hash().as_ref(), hex!("2aae6c35c94fcfb415dbe95f408b9ce91ee846ed")); +++ /// assert!(!result.has_collision()); +++ /// ``` +++ pub fn try_digest(data: impl AsRef<[u8]>) -> CollisionResult { +++ let mut hasher = Self::default(); +++ Digest::update(&mut hasher, data); +++ hasher.try_finalize() +++ } +++ +++ /// Try finalization, reporting the collision state. +++ pub fn try_finalize(mut self) -> CollisionResult { +++ let mut out = Output::::default(); +++ self.finalize_inner(&mut out); +++ +++ if let Some(ref ctx) = self.detection { +++ if ctx.found_collision { +++ if ctx.safe_hash { +++ return CollisionResult::Mitigated(out); +++ } +++ return CollisionResult::Collision(out); +++ } +++ } +++ CollisionResult::Ok(out) +++ } +++ +++ fn finalize_inner(&mut self, out: &mut Output) { +++ let bs = 64; +++ let buffer = &mut self.buffer; +++ let h = &mut self.h; +++ +++ if let Some(ref mut ctx) = self.detection { +++ let last_block = buffer.get_data(); +++ compress::finalize(h, bs * self.block_len, last_block, ctx); +++ } else { +++ let bit_len = 8 * (buffer.get_pos() as u64 + bs * self.block_len); +++ buffer.len64_padding_be(bit_len, |b| sha1::compress(h, from_ref(b))); +++ } +++ +++ for (chunk, v) in out.chunks_exact_mut(4).zip(h.iter()) { +++ chunk.copy_from_slice(&v.to_be_bytes()); +++ } +++ } +++} +++ +++/// Result when trying to finalize a hash. +++#[derive(Debug)] +++pub enum CollisionResult { +++ /// No collision. +++ Ok(Output), +++ /// Collision occured, but was mititgated. +++ Mitigated(Output), +++ /// Collision occured, the hash is the one that collided. +++ Collision(Output), +++} +++ +++impl CollisionResult { +++ /// Returns the output hash. +++ pub fn hash(&self) -> &Output { +++ match self { +++ CollisionResult::Ok(ref s) => s, +++ CollisionResult::Mitigated(ref s) => s, +++ CollisionResult::Collision(ref s) => s, +++ } +++ } +++ +++ /// Returns if there was a collision +++ pub fn has_collision(&self) -> bool { +++ !matches!(self, CollisionResult::Ok(_)) +++ } +++} +++ +++impl core::fmt::Debug for Sha1 { +++ #[inline] +++ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { +++ f.write_str("Sha1CollisionDetection { .. }") +++ } +++} +++ +++impl Reset for Sha1 { +++ #[inline] +++ fn reset(&mut self) { +++ self.h = INITIAL_H; +++ self.block_len = 0; +++ self.buffer.reset(); +++ if let Some(ref mut ctx) = self.detection { +++ ctx.reset(); +++ } +++ } +++} +++ +++impl Update for Sha1 { +++ #[inline] +++ fn update(&mut self, input: &[u8]) { +++ let Self { +++ h, +++ detection, +++ buffer, +++ .. +++ } = self; +++ buffer.digest_blocks(input, |blocks| { +++ self.block_len += blocks.len() as u64; +++ if let Some(ref mut ctx) = detection { +++ // SAFETY: GenericArray and [u8; 64] have +++ // exactly the same memory layout +++ let blocks: &[[u8; BLOCK_SIZE]] = +++ unsafe { &*(blocks as *const _ as *const [[u8; BLOCK_SIZE]]) }; +++ compress::compress(h, ctx, blocks); +++ } else { +++ sha1::compress(h, blocks); +++ } +++ }); +++ } +++} +++ +++impl OutputSizeUser for Sha1 { +++ type OutputSize = U20; +++} +++ +++impl FixedOutput for Sha1 { +++ #[inline] +++ fn finalize_into(mut self, out: &mut Output) { +++ self.finalize_inner(out); +++ } +++} +++ +++impl FixedOutputReset for Sha1 { +++ #[inline] +++ fn finalize_into_reset(&mut self, out: &mut Output) { +++ self.finalize_inner(out); +++ Reset::reset(self); +++ } +++} +++ +++#[cfg(feature = "zeroize")] +++impl ZeroizeOnDrop for Sha1 {} +++ +++impl Drop for DetectionState { +++ #[inline] +++ fn drop(&mut self) { +++ #[cfg(feature = "zeroize")] +++ { +++ self.ihv1.zeroize(); +++ self.ihv2.zeroize(); +++ self.m1.zeroize(); +++ self.m2.zeroize(); +++ self.state_58.zeroize(); +++ self.state_65.zeroize(); +++ } +++ } +++} +++ +++#[cfg(feature = "zeroize")] +++impl ZeroizeOnDrop for DetectionState {} +++ +++#[cfg(feature = "oid")] +++#[cfg_attr(docsrs, doc(cfg(feature = "oid")))] +++impl digest::const_oid::AssociatedOid for Sha1 { +++ const OID: digest::const_oid::ObjectIdentifier = sha1::Sha1Core::OID; +++} +++ +++#[cfg(feature = "std")] +++impl std::io::Write for Sha1 { +++ #[inline] +++ fn write(&mut self, buf: &[u8]) -> std::io::Result { +++ Update::update(self, buf); +++ Ok(buf.len()) +++ } +++ +++ #[inline] +++ fn flush(&mut self) -> std::io::Result<()> { +++ Ok(()) +++ } +++} +++ +++/// Builder for collision detection configuration. +++#[derive(Clone)] +++pub struct Builder { +++ detect_collision: bool, +++ safe_hash: bool, +++ ubc_check: bool, +++ reduced_round_collision: bool, +++} +++ +++impl Default for Builder { +++ fn default() -> Self { +++ Self { +++ detect_collision: true, +++ safe_hash: true, +++ ubc_check: true, +++ reduced_round_collision: false, +++ } +++ } +++} +++ +++impl Builder { +++ /// Should we detect collisions at all? Default: true +++ pub fn detect_collision(mut self, detect: bool) -> Self { +++ self.detect_collision = detect; +++ self +++ } +++ +++ /// Should a fix be automatically be applied, or the original hash be returned? Default: true +++ pub fn safe_hash(mut self, safe_hash: bool) -> Self { +++ self.safe_hash = safe_hash; +++ self +++ } +++ +++ /// Should unavoidable bitconditions be used to speed up the check? Default: true +++ pub fn use_ubc(mut self, ubc: bool) -> Self { +++ self.ubc_check = ubc; +++ self +++ } +++ +++ /// Should reduced round collisions be used? Default: false +++ pub fn reduced_round_collision(mut self, reduced: bool) -> Self { +++ self.reduced_round_collision = reduced; +++ self +++ } +++ +++ fn into_detection_state(self) -> Option { +++ if self.detect_collision { +++ Some(DetectionState { +++ safe_hash: self.safe_hash, +++ reduced_round_collision: self.reduced_round_collision, +++ ubc_check: self.ubc_check, +++ found_collision: false, +++ ihv1: Default::default(), +++ ihv2: Default::default(), +++ m1: [0; 80], +++ m2: [0; 80], +++ state_58: Default::default(), +++ state_65: Default::default(), +++ }) +++ } else { +++ None +++ } +++ } +++ +++ /// Create a Sha1 with a specific collision detection configuration. +++ pub fn build(self) -> Sha1 { +++ let detection = self.into_detection_state(); +++ Sha1 { +++ h: INITIAL_H, +++ block_len: 0, +++ detection, +++ buffer: Default::default(), +++ } +++ } +++} +++ +++/// The internal state used to do collision detection. +++#[derive(Clone, Debug)] +++struct DetectionState { +++ safe_hash: bool, +++ ubc_check: bool, +++ reduced_round_collision: bool, +++ /// Has a collision been detected? +++ found_collision: bool, +++ ihv1: [u32; 5], +++ ihv2: [u32; 5], +++ m1: [u32; 80], +++ m2: [u32; 80], +++ /// Stores past states, for faster recompression. +++ state_58: [u32; 5], +++ state_65: [u32; 5], +++} +++ +++impl Default for DetectionState { +++ fn default() -> Self { +++ Builder::default() +++ .into_detection_state() +++ .expect("enabled by default") +++ } +++} +++ +++impl DetectionState { +++ fn reset(&mut self) { +++ // Do not reset the config, it needs to be preserved +++ +++ self.found_collision = false; +++ self.ihv1 = Default::default(); +++ self.ihv2 = Default::default(); +++ self.m1 = [0; 80]; +++ self.m2 = [0; 80]; +++ self.state_58 = Default::default(); +++ self.state_65 = Default::default(); +++ } +++} diff --cc extra/sha1-checked-0.10.0/src/ubc_check.rs index 0000000000,0000000000,0000000000..2ce34455eb new file mode 100644 --- /dev/null +++ b/extra/sha1-checked-0.10.0/src/ubc_check.rs @@@@ -1,0 -1,0 -1,0 +1,1175 @@@@ +++//! Direct translation of the C code found at +++//! [ubc_check.c](https://github.com/cr-marcstevens/sha1collisiondetection/blob/master/lib/ubc_check.c). +++//! +++//! For the original license and source details see the comments in `src/checked.rs`. +++//! +++//! The original C code file was generated by the 'parse_bitrel' program in the tools section +++//! using the data files from directory 'tools/data/3565'. +++ +++const DV_I_43_0_BIT: u32 = 1 << 0; +++const DV_I_44_0_BIT: u32 = 1 << 1; +++const DV_I_45_0_BIT: u32 = 1 << 2; +++const DV_I_46_0_BIT: u32 = 1 << 3; +++const DV_I_46_2_BIT: u32 = 1 << 4; +++const DV_I_47_0_BIT: u32 = 1 << 5; +++const DV_I_47_2_BIT: u32 = 1 << 6; +++const DV_I_48_0_BIT: u32 = 1 << 7; +++const DV_I_48_2_BIT: u32 = 1 << 8; +++const DV_I_49_0_BIT: u32 = 1 << 9; +++const DV_I_49_2_BIT: u32 = 1 << 10; +++const DV_I_50_0_BIT: u32 = 1 << 11; +++const DV_I_50_2_BIT: u32 = 1 << 12; +++const DV_I_51_0_BIT: u32 = 1 << 13; +++const DV_I_51_2_BIT: u32 = 1 << 14; +++const DV_I_52_0_BIT: u32 = 1 << 15; +++const DV_II_45_0_BIT: u32 = 1 << 16; +++const DV_II_46_0_BIT: u32 = 1 << 17; +++const DV_II_46_2_BIT: u32 = 1 << 18; +++const DV_II_47_0_BIT: u32 = 1 << 19; +++const DV_II_48_0_BIT: u32 = 1 << 20; +++const DV_II_49_0_BIT: u32 = 1 << 21; +++const DV_II_49_2_BIT: u32 = 1 << 22; +++const DV_II_50_0_BIT: u32 = 1 << 23; +++const DV_II_50_2_BIT: u32 = 1 << 24; +++const DV_II_51_0_BIT: u32 = 1 << 25; +++const DV_II_51_2_BIT: u32 = 1 << 26; +++const DV_II_52_0_BIT: u32 = 1 << 27; +++const DV_II_53_0_BIT: u32 = 1 << 28; +++const DV_II_54_0_BIT: u32 = 1 << 29; +++const DV_II_55_0_BIT: u32 = 1 << 30; +++const DV_II_56_0_BIT: u32 = 1 << 31; +++ +++pub struct Info { +++ pub dv_type: u32, +++ pub dv_k: u32, +++ pub dv_b: u32, +++ pub testt: Testt, +++ pub maski: i32, +++ pub maskb: i32, +++ pub dm: [u32; 80], +++} +++ +++#[derive(Copy, Clone)] +++#[repr(u32)] +++pub enum Testt { +++ T58 = 58, +++ T65 = 65, +++} +++ +++/// Contains a list of SHA-1 Disturbance Vectors (DV) to check +++/// `dv_type`, `dv_k` and `dv_b` define the DV: I(K,B) or II(K,B) (see the paper) +++/// `dm[80]` is the expanded message block XOR-difference defined by the DV +++/// testt is the step to do the recompression from for collision detection +++/// `maski` and `maskb` define the bit to check for each DV in the dvmask returned by [`ubc_check`]. +++pub const SHA1_DVS: [Info; 32] = [ +++ Info { +++ dv_type: 1, +++ dv_k: 43, +++ dv_b: 0, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 0, +++ dm: [ +++ 0x8000000, 0x9800000c, 0xd8000010, 0x8000010, 0xb8000010, 0x98000000, 0x60000000, 0x8, +++ 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, 0x28000000, 0x20000010, 0x48000000, +++ 0x8000018, 0x60000000, 0x90000010, 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, +++ 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, 0x90000018, 0x60000000, +++ 0x90000010, 0x90000010, 0x90000000, 0x80000000, 0x10, 0xa0000000, 0x20000000, +++ 0xa0000000, 0x20000010, 0, 0x20000010, 0x20000000, 0x10, 0x20000000, 0x10, 0xa0000000, +++ 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, +++ 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, 0x49, 0x103, 0x80000009, +++ 0x80000012, 0x80000202, 0x18, 0x164, 0x408, 0x800000e6, 0x8000004c, 0x803, 0x80000161, +++ 0x80000599, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 44, +++ dv_b: 0, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 1, +++ dm: [ +++ 0xb4000008, 0x8000000, 0x9800000c, 0xd8000010, 0x8000010, 0xb8000010, 0x98000000, +++ 0x60000000, 0x8, 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, 0x28000000, +++ 0x20000010, 0x48000000, 0x8000018, 0x60000000, 0x90000010, 0xf0000010, 0x90000008, +++ 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, +++ 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, 0x80000000, 0x10, +++ 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0, 0x20000010, 0x20000000, 0x10, +++ 0x20000000, 0x10, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +++ 0x1, 0x20, 0x1, 0x40000002, 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, +++ 0x49, 0x103, 0x80000009, 0x80000012, 0x80000202, 0x18, 0x164, 0x408, 0x800000e6, +++ 0x8000004c, 0x803, 0x80000161, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 45, +++ dv_b: 0, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 2, +++ dm: [ +++ 0xf4000014, 0xb4000008, 0x8000000, 0x9800000c, 0xd8000010, 0x8000010, 0xb8000010, +++ 0x98000000, 0x60000000, 0x8, 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, +++ 0x28000000, 0x20000010, 0x48000000, 0x8000018, 0x60000000, 0x90000010, 0xf0000010, +++ 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, +++ 0xf0000010, 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, 0x80000000, +++ 0x10, 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0, 0x20000010, 0x20000000, 0x10, +++ 0x20000000, 0x10, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +++ 0x1, 0x20, 0x1, 0x40000002, 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, +++ 0x49, 0x103, 0x80000009, 0x80000012, 0x80000202, 0x18, 0x164, 0x408, 0x800000e6, +++ 0x8000004c, 0x803, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 46, +++ dv_b: 0, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 3, +++ dm: [ +++ 0x2c000010, 0xf4000014, 0xb4000008, 0x8000000, 0x9800000c, 0xd8000010, 0x8000010, +++ 0xb8000010, 0x98000000, 0x60000000, 0x8, 0xc0000000, 0x90000014, 0x10000010, +++ 0xb8000014, 0x28000000, 0x20000010, 0x48000000, 0x8000018, 0x60000000, 0x90000010, +++ 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, +++ 0x90000000, 0xf0000010, 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, +++ 0x80000000, 0x10, 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0, 0x20000010, +++ 0x20000000, 0x10, 0x20000000, 0x10, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, +++ 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000040, 0x40000002, 0x80000004, +++ 0x80000080, 0x80000006, 0x49, 0x103, 0x80000009, 0x80000012, 0x80000202, 0x18, 0x164, +++ 0x408, 0x800000e6, 0x8000004c, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 46, +++ dv_b: 2, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 4, +++ dm: [ +++ 0xb0000040, 0xd0000053, 0xd0000022, 0x20000000, 0x60000032, 0x60000043, 0x20000040, +++ 0xe0000042, 0x60000002, 0x80000001, 0x20, 0x3, 0x40000052, 0x40000040, 0xe0000052, +++ 0xa0000000, 0x80000040, 0x20000001, 0x20000060, 0x80000001, 0x40000042, 0xc0000043, +++ 0x40000022, 0x3, 0x40000042, 0xc0000043, 0xc0000022, 0x1, 0x40000002, 0xc0000043, +++ 0x40000062, 0x80000001, 0x40000042, 0x40000042, 0x40000002, 0x2, 0x40, 0x80000002, +++ 0x80000000, 0x80000002, 0x80000040, 0, 0x80000040, 0x80000000, 0x40, 0x80000000, 0x40, +++ 0x80000002, 0, 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x4, 0x80, 0x4, +++ 0x9, 0x101, 0x9, 0x12, 0x202, 0x1a, 0x124, 0x40c, 0x26, 0x4a, 0x80a, 0x60, 0x590, +++ 0x1020, 0x39a, 0x132, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 47, +++ dv_b: 0, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 5, +++ dm: [ +++ 0xc8000010, 0x2c000010, 0xf4000014, 0xb4000008, 0x8000000, 0x9800000c, 0xd8000010, +++ 0x8000010, 0xb8000010, 0x98000000, 0x60000000, 0x8, 0xc0000000, 0x90000014, 0x10000010, +++ 0xb8000014, 0x28000000, 0x20000010, 0x48000000, 0x8000018, 0x60000000, 0x90000010, +++ 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, +++ 0x90000000, 0xf0000010, 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, +++ 0x80000000, 0x10, 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0, 0x20000010, +++ 0x20000000, 0x10, 0x20000000, 0x10, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, +++ 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000040, 0x40000002, 0x80000004, +++ 0x80000080, 0x80000006, 0x49, 0x103, 0x80000009, 0x80000012, 0x80000202, 0x18, 0x164, +++ 0x408, 0x800000e6, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 47, +++ dv_b: 2, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 6, +++ dm: [ +++ 0x20000043, 0xb0000040, 0xd0000053, 0xd0000022, 0x20000000, 0x60000032, 0x60000043, +++ 0x20000040, 0xe0000042, 0x60000002, 0x80000001, 0x20, 0x3, 0x40000052, 0x40000040, +++ 0xe0000052, 0xa0000000, 0x80000040, 0x20000001, 0x20000060, 0x80000001, 0x40000042, +++ 0xc0000043, 0x40000022, 0x3, 0x40000042, 0xc0000043, 0xc0000022, 0x1, 0x40000002, +++ 0xc0000043, 0x40000062, 0x80000001, 0x40000042, 0x40000042, 0x40000002, 0x2, 0x40, +++ 0x80000002, 0x80000000, 0x80000002, 0x80000040, 0, 0x80000040, 0x80000000, 0x40, +++ 0x80000000, 0x40, 0x80000002, 0, 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +++ 0x4, 0x80, 0x4, 0x9, 0x101, 0x9, 0x12, 0x202, 0x1a, 0x124, 0x40c, 0x26, 0x4a, 0x80a, +++ 0x60, 0x590, 0x1020, 0x39a, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 48, +++ dv_b: 0, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 7, +++ dm: [ +++ 0xb800000a, 0xc8000010, 0x2c000010, 0xf4000014, 0xb4000008, 0x8000000, 0x9800000c, +++ 0xd8000010, 0x8000010, 0xb8000010, 0x98000000, 0x60000000, 0x8, 0xc0000000, 0x90000014, +++ 0x10000010, 0xb8000014, 0x28000000, 0x20000010, 0x48000000, 0x8000018, 0x60000000, +++ 0x90000010, 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, +++ 0x40000000, 0x90000000, 0xf0000010, 0x90000018, 0x60000000, 0x90000010, 0x90000010, +++ 0x90000000, 0x80000000, 0x10, 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0, +++ 0x20000010, 0x20000000, 0x10, 0x20000000, 0x10, 0xa0000000, 0, 0x20000000, 0x20000000, +++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000040, 0x40000002, +++ 0x80000004, 0x80000080, 0x80000006, 0x49, 0x103, 0x80000009, 0x80000012, 0x80000202, +++ 0x18, 0x164, 0x408, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 48, +++ dv_b: 2, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 8, +++ dm: [ +++ 0xe000002a, 0x20000043, 0xb0000040, 0xd0000053, 0xd0000022, 0x20000000, 0x60000032, +++ 0x60000043, 0x20000040, 0xe0000042, 0x60000002, 0x80000001, 0x20, 0x3, 0x40000052, +++ 0x40000040, 0xe0000052, 0xa0000000, 0x80000040, 0x20000001, 0x20000060, 0x80000001, +++ 0x40000042, 0xc0000043, 0x40000022, 0x3, 0x40000042, 0xc0000043, 0xc0000022, 0x1, +++ 0x40000002, 0xc0000043, 0x40000062, 0x80000001, 0x40000042, 0x40000042, 0x40000002, +++ 0x2, 0x40, 0x80000002, 0x80000000, 0x80000002, 0x80000040, 0, 0x80000040, 0x80000000, +++ 0x40, 0x80000000, 0x40, 0x80000002, 0, 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, +++ 0, 0, 0x4, 0x80, 0x4, 0x9, 0x101, 0x9, 0x12, 0x202, 0x1a, 0x124, 0x40c, 0x26, 0x4a, +++ 0x80a, 0x60, 0x590, 0x1020, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 49, +++ dv_b: 0, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 9, +++ dm: [ +++ 0x18000000, 0xb800000a, 0xc8000010, 0x2c000010, 0xf4000014, 0xb4000008, 0x8000000, +++ 0x9800000c, 0xd8000010, 0x8000010, 0xb8000010, 0x98000000, 0x60000000, 0x8, 0xc0000000, +++ 0x90000014, 0x10000010, 0xb8000014, 0x28000000, 0x20000010, 0x48000000, 0x8000018, +++ 0x60000000, 0x90000010, 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, +++ 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, 0x90000018, 0x60000000, 0x90000010, +++ 0x90000010, 0x90000000, 0x80000000, 0x10, 0xa0000000, 0x20000000, 0xa0000000, +++ 0x20000010, 0, 0x20000010, 0x20000000, 0x10, 0x20000000, 0x10, 0xa0000000, 0, +++ 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, +++ 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, 0x49, 0x103, 0x80000009, +++ 0x80000012, 0x80000202, 0x18, 0x164, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 49, +++ dv_b: 2, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 10, +++ dm: [ +++ 0x60000000, 0xe000002a, 0x20000043, 0xb0000040, 0xd0000053, 0xd0000022, 0x20000000, +++ 0x60000032, 0x60000043, 0x20000040, 0xe0000042, 0x60000002, 0x80000001, 0x20, 0x3, +++ 0x40000052, 0x40000040, 0xe0000052, 0xa0000000, 0x80000040, 0x20000001, 0x20000060, +++ 0x80000001, 0x40000042, 0xc0000043, 0x40000022, 0x3, 0x40000042, 0xc0000043, +++ 0xc0000022, 0x1, 0x40000002, 0xc0000043, 0x40000062, 0x80000001, 0x40000042, +++ 0x40000042, 0x40000002, 0x2, 0x40, 0x80000002, 0x80000000, 0x80000002, 0x80000040, 0, +++ 0x80000040, 0x80000000, 0x40, 0x80000000, 0x40, 0x80000002, 0, 0x80000000, 0x80000000, +++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x4, 0x80, 0x4, 0x9, 0x101, 0x9, 0x12, 0x202, 0x1a, +++ 0x124, 0x40c, 0x26, 0x4a, 0x80a, 0x60, 0x590, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 50, +++ dv_b: 0, +++ testt: Testt::T65, +++ maski: 0, +++ maskb: 11, +++ dm: [ +++ 0x800000c, 0x18000000, 0xb800000a, 0xc8000010, 0x2c000010, 0xf4000014, 0xb4000008, +++ 0x8000000, 0x9800000c, 0xd8000010, 0x8000010, 0xb8000010, 0x98000000, 0x60000000, 0x8, +++ 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, 0x28000000, 0x20000010, 0x48000000, +++ 0x8000018, 0x60000000, 0x90000010, 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, +++ 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, 0x90000018, 0x60000000, +++ 0x90000010, 0x90000010, 0x90000000, 0x80000000, 0x10, 0xa0000000, 0x20000000, +++ 0xa0000000, 0x20000010, 0, 0x20000010, 0x20000000, 0x10, 0x20000000, 0x10, 0xa0000000, +++ 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, +++ 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, 0x49, 0x103, 0x80000009, +++ 0x80000012, 0x80000202, 0x18, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 50, +++ dv_b: 2, +++ testt: Testt::T65, +++ maski: 0, +++ maskb: 12, +++ dm: [ +++ 0x20000030, 0x60000000, 0xe000002a, 0x20000043, 0xb0000040, 0xd0000053, 0xd0000022, +++ 0x20000000, 0x60000032, 0x60000043, 0x20000040, 0xe0000042, 0x60000002, 0x80000001, +++ 0x20, 0x3, 0x40000052, 0x40000040, 0xe0000052, 0xa0000000, 0x80000040, 0x20000001, +++ 0x20000060, 0x80000001, 0x40000042, 0xc0000043, 0x40000022, 0x3, 0x40000042, +++ 0xc0000043, 0xc0000022, 0x1, 0x40000002, 0xc0000043, 0x40000062, 0x80000001, +++ 0x40000042, 0x40000042, 0x40000002, 0x2, 0x40, 0x80000002, 0x80000000, 0x80000002, +++ 0x80000040, 0, 0x80000040, 0x80000000, 0x40, 0x80000000, 0x40, 0x80000002, 0, +++ 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x4, 0x80, 0x4, 0x9, 0x101, 0x9, +++ 0x12, 0x202, 0x1a, 0x124, 0x40c, 0x26, 0x4a, 0x80a, 0x60, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 51, +++ dv_b: 0, +++ testt: Testt::T65, +++ maski: 0, +++ maskb: 13, +++ dm: [ +++ 0xe8000000, 0x800000c, 0x18000000, 0xb800000a, 0xc8000010, 0x2c000010, 0xf4000014, +++ 0xb4000008, 0x8000000, 0x9800000c, 0xd8000010, 0x8000010, 0xb8000010, 0x98000000, +++ 0x60000000, 0x8, 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, 0x28000000, +++ 0x20000010, 0x48000000, 0x8000018, 0x60000000, 0x90000010, 0xf0000010, 0x90000008, +++ 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, +++ 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, 0x80000000, 0x10, +++ 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0, 0x20000010, 0x20000000, 0x10, +++ 0x20000000, 0x10, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +++ 0x1, 0x20, 0x1, 0x40000002, 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, +++ 0x49, 0x103, 0x80000009, 0x80000012, 0x80000202, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 51, +++ dv_b: 2, +++ testt: Testt::T65, +++ maski: 0, +++ maskb: 14, +++ dm: [ +++ 0xa0000003, 0x20000030, 0x60000000, 0xe000002a, 0x20000043, 0xb0000040, 0xd0000053, +++ 0xd0000022, 0x20000000, 0x60000032, 0x60000043, 0x20000040, 0xe0000042, 0x60000002, +++ 0x80000001, 0x20, 0x3, 0x40000052, 0x40000040, 0xe0000052, 0xa0000000, 0x80000040, +++ 0x20000001, 0x20000060, 0x80000001, 0x40000042, 0xc0000043, 0x40000022, 0x3, +++ 0x40000042, 0xc0000043, 0xc0000022, 0x1, 0x40000002, 0xc0000043, 0x40000062, +++ 0x80000001, 0x40000042, 0x40000042, 0x40000002, 0x2, 0x40, 0x80000002, 0x80000000, +++ 0x80000002, 0x80000040, 0, 0x80000040, 0x80000000, 0x40, 0x80000000, 0x40, 0x80000002, +++ 0, 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x4, 0x80, 0x4, 0x9, 0x101, +++ 0x9, 0x12, 0x202, 0x1a, 0x124, 0x40c, 0x26, 0x4a, 0x80a, +++ ], +++ }, +++ Info { +++ dv_type: 1, +++ dv_k: 52, +++ dv_b: 0, +++ testt: Testt::T65, +++ maski: 0, +++ maskb: 15, +++ dm: [ +++ 0x4000010, 0xe8000000, 0x800000c, 0x18000000, 0xb800000a, 0xc8000010, 0x2c000010, +++ 0xf4000014, 0xb4000008, 0x8000000, 0x9800000c, 0xd8000010, 0x8000010, 0xb8000010, +++ 0x98000000, 0x60000000, 0x8, 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, +++ 0x28000000, 0x20000010, 0x48000000, 0x8000018, 0x60000000, 0x90000010, 0xf0000010, +++ 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, +++ 0xf0000010, 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, 0x80000000, +++ 0x10, 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0, 0x20000010, 0x20000000, 0x10, +++ 0x20000000, 0x10, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +++ 0x1, 0x20, 0x1, 0x40000002, 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, +++ 0x49, 0x103, 0x80000009, 0x80000012, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 45, +++ dv_b: 0, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 16, +++ dm: [ +++ 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, 0xb0000010, 0xc, +++ 0xb8000010, 0x8000018, 0x78000010, 0x8000014, 0x70000010, 0xb800001c, 0xe8000000, +++ 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, 0x98000010, +++ 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0x20000000, 0x10, +++ 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, +++ 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, 0x20000000, 0x20000000, +++ 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, +++ 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, 0x80000005, 0xc0000082, +++ 0xc0000046, 0x4000004b, 0x80000107, 0x89, 0x14, 0x8000024b, 0x11b, 0x8000016d, +++ 0x8000041a, 0x2e4, 0x80000054, 0x967, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 46, +++ dv_b: 0, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 17, +++ dm: [ +++ 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, +++ 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, 0x8000014, 0x70000010, 0xb800001c, +++ 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, +++ 0x98000010, 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0x20000000, +++ 0x10, 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, +++ 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, 0x20000000, 0x20000000, +++ 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, +++ 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, 0x80000005, 0xc0000082, +++ 0xc0000046, 0x4000004b, 0x80000107, 0x89, 0x14, 0x8000024b, 0x11b, 0x8000016d, +++ 0x8000041a, 0x2e4, 0x80000054, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 46, +++ dv_b: 2, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 18, +++ dm: [ +++ 0x90000070, 0xb0000053, 0x30000008, 0x43, 0xd0000072, 0xb0000010, 0xf0000062, +++ 0xc0000042, 0x30, 0xe0000042, 0x20000060, 0xe0000041, 0x20000050, 0xc0000041, +++ 0xe0000072, 0xa0000003, 0xc0000012, 0x60000041, 0xc0000032, 0x20000001, 0xc0000002, +++ 0xe0000042, 0x60000042, 0x80000002, 0, 0, 0x80000000, 0x2, 0x40, 0, 0x80000040, +++ 0x80000000, 0x40, 0x80000001, 0x60, 0x80000003, 0x40000002, 0xc0000040, 0xc0000002, +++ 0x80000000, 0x80000000, 0x80000002, 0x40, 0x2, 0x80000000, 0x80000000, 0x80000000, 0x2, +++ 0x40, 0, 0x80000040, 0x80000002, 0, 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0x4, +++ 0x80, 0x4, 0x9, 0x105, 0x89, 0x16, 0x20b, 0x11b, 0x12d, 0x41e, 0x224, 0x50, 0x92e, +++ 0x46c, 0x5b6, 0x106a, 0xb90, 0x152, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 47, +++ dv_b: 0, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 19, +++ dm: [ +++ 0x20000010, 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, +++ 0xbc000018, 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, 0x8000014, 0x70000010, +++ 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, +++ 0xb8000010, 0x98000010, 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, +++ 0x20000000, 0x10, 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, +++ 0x20000000, 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, 0x20000000, +++ 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, 0x20000000, 0, +++ 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, 0x80000005, +++ 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, 0x89, 0x14, 0x8000024b, 0x11b, +++ 0x8000016d, 0x8000041a, 0x2e4, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 48, +++ dv_b: 0, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 20, +++ dm: [ +++ 0xbc00001a, 0x20000010, 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, +++ 0x2c000004, 0xbc000018, 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, 0x8000014, +++ 0x70000010, 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, +++ 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, +++ 0x20000010, 0x20000000, 0x10, 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, +++ 0xb0000000, 0x20000000, 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, +++ 0x20000000, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, +++ 0x20000000, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, +++ 0x80000005, 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, 0x89, 0x14, 0x8000024b, +++ 0x11b, 0x8000016d, 0x8000041a, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 49, +++ dv_b: 0, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 21, +++ dm: [ +++ 0x3c000004, 0xbc00001a, 0x20000010, 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, +++ 0xb400001c, 0x2c000004, 0xbc000018, 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, +++ 0x8000014, 0x70000010, 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, +++ 0x48000000, 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, 0, 0, 0x20000000, +++ 0x80000000, 0x10, 0, 0x20000010, 0x20000000, 0x10, 0x60000000, 0x18, 0xe0000000, +++ 0x90000000, 0x30000010, 0xb0000000, 0x20000000, 0x20000000, 0xa0000000, 0x10, +++ 0x80000000, 0x20000000, 0x20000000, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, +++ 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, +++ 0x40000041, 0x40000022, 0x80000005, 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, +++ 0x89, 0x14, 0x8000024b, 0x11b, 0x8000016d, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 49, +++ dv_b: 2, +++ testt: Testt::T58, +++ maski: 0, +++ maskb: 22, +++ dm: [ +++ 0xf0000010, 0xf000006a, 0x80000040, 0x90000070, 0xb0000053, 0x30000008, 0x43, +++ 0xd0000072, 0xb0000010, 0xf0000062, 0xc0000042, 0x30, 0xe0000042, 0x20000060, +++ 0xe0000041, 0x20000050, 0xc0000041, 0xe0000072, 0xa0000003, 0xc0000012, 0x60000041, +++ 0xc0000032, 0x20000001, 0xc0000002, 0xe0000042, 0x60000042, 0x80000002, 0, 0, +++ 0x80000000, 0x2, 0x40, 0, 0x80000040, 0x80000000, 0x40, 0x80000001, 0x60, 0x80000003, +++ 0x40000002, 0xc0000040, 0xc0000002, 0x80000000, 0x80000000, 0x80000002, 0x40, 0x2, +++ 0x80000000, 0x80000000, 0x80000000, 0x2, 0x40, 0, 0x80000040, 0x80000002, 0, +++ 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0x4, 0x80, 0x4, 0x9, 0x105, 0x89, 0x16, +++ 0x20b, 0x11b, 0x12d, 0x41e, 0x224, 0x50, 0x92e, 0x46c, 0x5b6, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 50, +++ dv_b: 0, +++ testt: Testt::T65, +++ maski: 0, +++ maskb: 23, +++ dm: [ +++ 0xb400001c, 0x3c000004, 0xbc00001a, 0x20000010, 0x2400001c, 0xec000014, 0xc000002, +++ 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, 0xb0000010, 0xc, 0xb8000010, 0x8000018, +++ 0x78000010, 0x8000014, 0x70000010, 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, +++ 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, 0, 0, +++ 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0x20000000, 0x10, 0x60000000, 0x18, +++ 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, 0x20000000, 0xa0000000, +++ 0x10, 0x80000000, 0x20000000, 0x20000000, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, +++ 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, +++ 0x40000041, 0x40000022, 0x80000005, 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, +++ 0x89, 0x14, 0x8000024b, 0x11b, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 50, +++ dv_b: 2, +++ testt: Testt::T65, +++ maski: 0, +++ maskb: 24, +++ dm: [ +++ 0xd0000072, 0xf0000010, 0xf000006a, 0x80000040, 0x90000070, 0xb0000053, 0x30000008, +++ 0x43, 0xd0000072, 0xb0000010, 0xf0000062, 0xc0000042, 0x30, 0xe0000042, 0x20000060, +++ 0xe0000041, 0x20000050, 0xc0000041, 0xe0000072, 0xa0000003, 0xc0000012, 0x60000041, +++ 0xc0000032, 0x20000001, 0xc0000002, 0xe0000042, 0x60000042, 0x80000002, 0, 0, +++ 0x80000000, 0x2, 0x40, 0, 0x80000040, 0x80000000, 0x40, 0x80000001, 0x60, 0x80000003, +++ 0x40000002, 0xc0000040, 0xc0000002, 0x80000000, 0x80000000, 0x80000002, 0x40, 0x2, +++ 0x80000000, 0x80000000, 0x80000000, 0x2, 0x40, 0, 0x80000040, 0x80000002, 0, +++ 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0x4, 0x80, 0x4, 0x9, 0x105, 0x89, 0x16, +++ 0x20b, 0x11b, 0x12d, 0x41e, 0x224, 0x50, 0x92e, 0x46c, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 51, +++ dv_b: 0, +++ testt: Testt::T65, +++ maski: 0, +++ maskb: 25, +++ dm: [ +++ 0xc0000010, 0xb400001c, 0x3c000004, 0xbc00001a, 0x20000010, 0x2400001c, 0xec000014, +++ 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, 0xb0000010, 0xc, 0xb8000010, +++ 0x8000018, 0x78000010, 0x8000014, 0x70000010, 0xb800001c, 0xe8000000, 0xb0000004, +++ 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, 0, +++ 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0x20000000, 0x10, 0x60000000, 0x18, +++ 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, 0x20000000, 0xa0000000, +++ 0x10, 0x80000000, 0x20000000, 0x20000000, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, +++ 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, +++ 0x40000041, 0x40000022, 0x80000005, 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, +++ 0x89, 0x14, 0x8000024b, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 51, +++ dv_b: 2, +++ testt: Testt::T65, +++ maski: 0, +++ maskb: 26, +++ dm: [ +++ 0x43, 0xd0000072, 0xf0000010, 0xf000006a, 0x80000040, 0x90000070, 0xb0000053, +++ 0x30000008, 0x43, 0xd0000072, 0xb0000010, 0xf0000062, 0xc0000042, 0x30, 0xe0000042, +++ 0x20000060, 0xe0000041, 0x20000050, 0xc0000041, 0xe0000072, 0xa0000003, 0xc0000012, +++ 0x60000041, 0xc0000032, 0x20000001, 0xc0000002, 0xe0000042, 0x60000042, 0x80000002, 0, +++ 0, 0x80000000, 0x2, 0x40, 0, 0x80000040, 0x80000000, 0x40, 0x80000001, 0x60, +++ 0x80000003, 0x40000002, 0xc0000040, 0xc0000002, 0x80000000, 0x80000000, 0x80000002, +++ 0x40, 0x2, 0x80000000, 0x80000000, 0x80000000, 0x2, 0x40, 0, 0x80000040, 0x80000002, 0, +++ 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0x4, 0x80, 0x4, 0x9, 0x105, 0x89, 0x16, +++ 0x20b, 0x11b, 0x12d, 0x41e, 0x224, 0x50, 0x92e, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 52, +++ dv_b: 0, +++ testt: Testt::T65, +++ maski: 0, +++ maskb: 27, +++ dm: [ +++ 0xc000002, 0xc0000010, 0xb400001c, 0x3c000004, 0xbc00001a, 0x20000010, 0x2400001c, +++ 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, 0xb0000010, 0xc, +++ 0xb8000010, 0x8000018, 0x78000010, 0x8000014, 0x70000010, 0xb800001c, 0xe8000000, +++ 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, 0x98000010, +++ 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0x20000000, 0x10, +++ 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, +++ 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, 0x20000000, 0x20000000, +++ 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, +++ 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, 0x80000005, 0xc0000082, +++ 0xc0000046, 0x4000004b, 0x80000107, 0x89, 0x14, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 53, +++ dv_b: 0, +++ testt: Testt::T65, +++ maski: 0, +++ maskb: 28, +++ dm: [ +++ 0xcc000014, 0xc000002, 0xc0000010, 0xb400001c, 0x3c000004, 0xbc00001a, 0x20000010, +++ 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, +++ 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, 0x8000014, 0x70000010, 0xb800001c, +++ 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, +++ 0x98000010, 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0x20000000, +++ 0x10, 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, +++ 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, 0x20000000, 0x20000000, +++ 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, +++ 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, 0x80000005, 0xc0000082, +++ 0xc0000046, 0x4000004b, 0x80000107, 0x89, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 54, +++ dv_b: 0, +++ testt: Testt::T65, +++ maski: 0, +++ maskb: 29, +++ dm: [ +++ 0x400001c, 0xcc000014, 0xc000002, 0xc0000010, 0xb400001c, 0x3c000004, 0xbc00001a, +++ 0x20000010, 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, +++ 0xbc000018, 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, 0x8000014, 0x70000010, +++ 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, +++ 0xb8000010, 0x98000010, 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, +++ 0x20000000, 0x10, 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, +++ 0x20000000, 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, 0x20000000, +++ 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, 0x20000000, 0, +++ 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, 0x80000005, +++ 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 55, +++ dv_b: 0, +++ testt: Testt::T65, +++ maski: 0, +++ maskb: 30, +++ dm: [ +++ 0x10, 0x400001c, 0xcc000014, 0xc000002, 0xc0000010, 0xb400001c, 0x3c000004, 0xbc00001a, +++ 0x20000010, 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, +++ 0xbc000018, 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, 0x8000014, 0x70000010, +++ 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, +++ 0xb8000010, 0x98000010, 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, +++ 0x20000000, 0x10, 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, +++ 0x20000000, 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, 0x20000000, +++ 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, 0x20000000, 0, +++ 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, 0x80000005, +++ 0xc0000082, 0xc0000046, 0x4000004b, +++ ], +++ }, +++ Info { +++ dv_type: 2, +++ dv_k: 56, +++ dv_b: 0, +++ testt: Testt::T65, +++ maski: 0, +++ maskb: 31, +++ dm: [ +++ 0x2600001a, 0x10, 0x400001c, 0xcc000014, 0xc000002, 0xc0000010, 0xb400001c, 0x3c000004, +++ 0xbc00001a, 0x20000010, 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, +++ 0x2c000004, 0xbc000018, 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, 0x8000014, +++ 0x70000010, 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, +++ 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, +++ 0x20000010, 0x20000000, 0x10, 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, +++ 0xb0000000, 0x20000000, 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, +++ 0x20000000, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, +++ 0x20000000, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, +++ 0x80000005, 0xc0000082, 0xc0000046, +++ ], +++ }, +++]; +++ +++/// Takes as input an expanded message block and verifies the unavoidable bitconditions +++/// for all listed DVs it returns a dvmask where each bit belonging to a DV is set if +++/// all unavoidable bitconditions for that DV have been met thus one needs to do the +++/// recompression check for each DV that has its bit set. +++#[inline] +++pub const fn ubc_check(w: &[u32; 80]) -> u32 { +++ let mut mask: u32 = !0; +++ mask &= ((w[44] ^ w[45]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_48_0_BIT +++ | DV_I_51_0_BIT +++ | DV_I_52_0_BIT +++ | DV_II_45_0_BIT +++ | DV_II_46_0_BIT +++ | DV_II_50_0_BIT +++ | DV_II_51_0_BIT); +++ mask &= ((w[49] ^ w[50]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_46_0_BIT +++ | DV_II_45_0_BIT +++ | DV_II_50_0_BIT +++ | DV_II_51_0_BIT +++ | DV_II_55_0_BIT +++ | DV_II_56_0_BIT); +++ mask &= ((w[48] ^ w[49]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_45_0_BIT +++ | DV_I_52_0_BIT +++ | DV_II_49_0_BIT +++ | DV_II_50_0_BIT +++ | DV_II_54_0_BIT +++ | DV_II_55_0_BIT); +++ mask &= ((w[47] ^ w[50] >> 25) & (1 << 4)).wrapping_sub((1) << 4) +++ | !(DV_I_47_0_BIT +++ | DV_I_49_0_BIT +++ | DV_I_51_0_BIT +++ | DV_II_45_0_BIT +++ | DV_II_51_0_BIT +++ | DV_II_56_0_BIT); +++ mask &= ((w[47] ^ w[48]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_44_0_BIT +++ | DV_I_51_0_BIT +++ | DV_II_48_0_BIT +++ | DV_II_49_0_BIT +++ | DV_II_53_0_BIT +++ | DV_II_54_0_BIT); +++ mask &= ((w[46] >> 4 ^ w[49] >> 29) & 1).wrapping_sub(1) +++ | !(DV_I_46_0_BIT +++ | DV_I_48_0_BIT +++ | DV_I_50_0_BIT +++ | DV_I_52_0_BIT +++ | DV_II_50_0_BIT +++ | DV_II_55_0_BIT); +++ mask &= ((w[46] ^ w[47]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_43_0_BIT +++ | DV_I_50_0_BIT +++ | DV_II_47_0_BIT +++ | DV_II_48_0_BIT +++ | DV_II_52_0_BIT +++ | DV_II_53_0_BIT); +++ mask &= ((w[45] >> 4 ^ w[48] >> 29) & 1).wrapping_sub(1) +++ | !(DV_I_45_0_BIT +++ | DV_I_47_0_BIT +++ | DV_I_49_0_BIT +++ | DV_I_51_0_BIT +++ | DV_II_49_0_BIT +++ | DV_II_54_0_BIT); +++ mask &= ((w[45] ^ w[46]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_49_0_BIT +++ | DV_I_52_0_BIT +++ | DV_II_46_0_BIT +++ | DV_II_47_0_BIT +++ | DV_II_51_0_BIT +++ | DV_II_52_0_BIT); +++ mask &= ((w[44] >> 4 ^ w[47] >> 29) & 1).wrapping_sub(1) +++ | !(DV_I_44_0_BIT +++ | DV_I_46_0_BIT +++ | DV_I_48_0_BIT +++ | DV_I_50_0_BIT +++ | DV_II_48_0_BIT +++ | DV_II_53_0_BIT); +++ mask &= ((w[43] >> 4 ^ w[46] >> 29) & 1).wrapping_sub(1) +++ | !(DV_I_43_0_BIT +++ | DV_I_45_0_BIT +++ | DV_I_47_0_BIT +++ | DV_I_49_0_BIT +++ | DV_II_47_0_BIT +++ | DV_II_52_0_BIT); +++ mask &= ((w[43] ^ w[44]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_47_0_BIT +++ | DV_I_50_0_BIT +++ | DV_I_51_0_BIT +++ | DV_II_45_0_BIT +++ | DV_II_49_0_BIT +++ | DV_II_50_0_BIT); +++ mask &= ((w[42] >> 4 ^ w[45] >> 29) & 1).wrapping_sub(1) +++ | !(DV_I_44_0_BIT +++ | DV_I_46_0_BIT +++ | DV_I_48_0_BIT +++ | DV_I_52_0_BIT +++ | DV_II_46_0_BIT +++ | DV_II_51_0_BIT); +++ mask &= ((w[41] >> 4 ^ w[44] >> 29) & 1).wrapping_sub(1) +++ | !(DV_I_43_0_BIT +++ | DV_I_45_0_BIT +++ | DV_I_47_0_BIT +++ | DV_I_51_0_BIT +++ | DV_II_45_0_BIT +++ | DV_II_50_0_BIT); +++ mask &= ((w[40] ^ w[41]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_44_0_BIT +++ | DV_I_47_0_BIT +++ | DV_I_48_0_BIT +++ | DV_II_46_0_BIT +++ | DV_II_47_0_BIT +++ | DV_II_56_0_BIT); +++ mask &= ((w[54] ^ w[55]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_51_0_BIT | DV_II_47_0_BIT | DV_II_50_0_BIT | DV_II_55_0_BIT | DV_II_56_0_BIT); +++ mask &= ((w[53] ^ w[54]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_50_0_BIT | DV_II_46_0_BIT | DV_II_49_0_BIT | DV_II_54_0_BIT | DV_II_55_0_BIT); +++ mask &= ((w[52] ^ w[53]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_49_0_BIT | DV_II_45_0_BIT | DV_II_48_0_BIT | DV_II_53_0_BIT | DV_II_54_0_BIT); +++ mask &= ((w[50] ^ w[53] >> 25) & (1 << 4)).wrapping_sub(1 << 4) +++ | !(DV_I_50_0_BIT | DV_I_52_0_BIT | DV_II_46_0_BIT | DV_II_48_0_BIT | DV_II_54_0_BIT); +++ mask &= ((w[50] ^ w[51]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_47_0_BIT | DV_II_46_0_BIT | DV_II_51_0_BIT | DV_II_52_0_BIT | DV_II_56_0_BIT); +++ mask &= ((w[49] ^ w[52] >> 25) & (1 << 4)).wrapping_sub(1 << 4) +++ | !(DV_I_49_0_BIT | DV_I_51_0_BIT | DV_II_45_0_BIT | DV_II_47_0_BIT | DV_II_53_0_BIT); +++ mask &= ((w[48] ^ w[51] >> 25) & (1 << 4)).wrapping_sub(1 << 4) +++ | !(DV_I_48_0_BIT | DV_I_50_0_BIT | DV_I_52_0_BIT | DV_II_46_0_BIT | DV_II_52_0_BIT); +++ mask &= ((w[42] ^ w[43]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_46_0_BIT | DV_I_49_0_BIT | DV_I_50_0_BIT | DV_II_48_0_BIT | DV_II_49_0_BIT); +++ mask &= ((w[41] ^ w[42]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_45_0_BIT | DV_I_48_0_BIT | DV_I_49_0_BIT | DV_II_47_0_BIT | DV_II_48_0_BIT); +++ mask &= ((w[40] >> 4 ^ w[43] >> 29) & 1).wrapping_sub(1) +++ | !(DV_I_44_0_BIT | DV_I_46_0_BIT | DV_I_50_0_BIT | DV_II_49_0_BIT | DV_II_56_0_BIT); +++ mask &= ((w[39] >> 4 ^ w[42] >> 29) & 1).wrapping_sub(1) +++ | !(DV_I_43_0_BIT | DV_I_45_0_BIT | DV_I_49_0_BIT | DV_II_48_0_BIT | DV_II_55_0_BIT); +++ if mask & (DV_I_44_0_BIT | DV_I_48_0_BIT | DV_II_47_0_BIT | DV_II_54_0_BIT | DV_II_56_0_BIT) +++ != 0 +++ { +++ mask &= ((w[38] >> 4 ^ w[41] >> 29) & 1).wrapping_sub(1) +++ | !(DV_I_44_0_BIT | DV_I_48_0_BIT | DV_II_47_0_BIT | DV_II_54_0_BIT | DV_II_56_0_BIT) +++ } +++ mask &= ((w[37] >> 4 ^ w[40] >> 29) & 1).wrapping_sub(1) +++ | !(DV_I_43_0_BIT | DV_I_47_0_BIT | DV_II_46_0_BIT | DV_II_53_0_BIT | DV_II_55_0_BIT); +++ if mask & (DV_I_52_0_BIT | DV_II_48_0_BIT | DV_II_51_0_BIT | DV_II_56_0_BIT) != 0 { +++ mask &= ((w[55] ^ w[56]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_52_0_BIT | DV_II_48_0_BIT | DV_II_51_0_BIT | DV_II_56_0_BIT) +++ } +++ if mask & (DV_I_52_0_BIT | DV_II_48_0_BIT | DV_II_50_0_BIT | DV_II_56_0_BIT) != 0 { +++ mask &= ((w[52] ^ w[55] >> 25) & (1 << 4)).wrapping_sub(1 << 4) +++ | !(DV_I_52_0_BIT | DV_II_48_0_BIT | DV_II_50_0_BIT | DV_II_56_0_BIT) +++ } +++ if mask & (DV_I_51_0_BIT | DV_II_47_0_BIT | DV_II_49_0_BIT | DV_II_55_0_BIT) != 0 { +++ mask &= ((w[51] ^ w[54] >> 25) & (1 << 4)).wrapping_sub(1 << 4) +++ | !(DV_I_51_0_BIT | DV_II_47_0_BIT | DV_II_49_0_BIT | DV_II_55_0_BIT) +++ } +++ if mask & (DV_I_48_0_BIT | DV_II_47_0_BIT | DV_II_52_0_BIT | DV_II_53_0_BIT) != 0 { +++ mask &= ((w[51] ^ w[52]) >> 29 & 1).wrapping_sub(1) +++ | !(DV_I_48_0_BIT | DV_II_47_0_BIT | DV_II_52_0_BIT | DV_II_53_0_BIT) +++ } +++ if mask & (DV_I_46_0_BIT | DV_I_49_0_BIT | DV_II_45_0_BIT | DV_II_48_0_BIT) != 0 { +++ mask &= ((w[36] >> 4 ^ w[40] >> 29) & 1).wrapping_sub(1) +++ | !(DV_I_46_0_BIT | DV_I_49_0_BIT | DV_II_45_0_BIT | DV_II_48_0_BIT) +++ } +++ if mask & (DV_I_52_0_BIT | DV_II_48_0_BIT | DV_II_49_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[53] ^ w[56]) >> 29 & 1) +++ | !(DV_I_52_0_BIT | DV_II_48_0_BIT | DV_II_49_0_BIT) +++ } +++ if mask & (DV_I_50_0_BIT | DV_II_46_0_BIT | DV_II_47_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[51] ^ w[54]) >> 29 & 1) +++ | !(DV_I_50_0_BIT | DV_II_46_0_BIT | DV_II_47_0_BIT) +++ } +++ if mask & (DV_I_49_0_BIT | DV_I_51_0_BIT | DV_II_45_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[50] ^ w[52]) >> 29 & 1) +++ | !(DV_I_49_0_BIT | DV_I_51_0_BIT | DV_II_45_0_BIT) +++ } +++ if mask & (DV_I_48_0_BIT | DV_I_50_0_BIT | DV_I_52_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[49] ^ w[51]) >> 29 & 1) +++ | !(DV_I_48_0_BIT | DV_I_50_0_BIT | DV_I_52_0_BIT) +++ } +++ if mask & (DV_I_47_0_BIT | DV_I_49_0_BIT | DV_I_51_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[48] ^ w[50]) >> 29 & 1) +++ | !(DV_I_47_0_BIT | DV_I_49_0_BIT | DV_I_51_0_BIT) +++ } +++ if mask & (DV_I_46_0_BIT | DV_I_48_0_BIT | DV_I_50_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[47] ^ w[49]) >> 29 & 1) +++ | !(DV_I_46_0_BIT | DV_I_48_0_BIT | DV_I_50_0_BIT) +++ } +++ if mask & (DV_I_45_0_BIT | DV_I_47_0_BIT | DV_I_49_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[46] ^ w[48]) >> 29 & 1) +++ | !(DV_I_45_0_BIT | DV_I_47_0_BIT | DV_I_49_0_BIT) +++ } +++ mask &= ((w[45] ^ w[47]) & (1 << 6)).wrapping_sub(1 << 6) +++ | !(DV_I_47_2_BIT | DV_I_49_2_BIT | DV_I_51_2_BIT); +++ if mask & (DV_I_44_0_BIT | DV_I_46_0_BIT | DV_I_48_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[45] ^ w[47]) >> 29 & 1) +++ | !(DV_I_44_0_BIT | DV_I_46_0_BIT | DV_I_48_0_BIT) +++ } +++ mask &= ((w[44] ^ w[46]) >> 6 & 1).wrapping_sub(1) +++ | !(DV_I_46_2_BIT | DV_I_48_2_BIT | DV_I_50_2_BIT); +++ if mask & (DV_I_43_0_BIT | DV_I_45_0_BIT | DV_I_47_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[44] ^ w[46]) >> 29 & 1) +++ | !(DV_I_43_0_BIT | DV_I_45_0_BIT | DV_I_47_0_BIT) +++ } +++ mask &= (0u32).wrapping_sub((w[41] ^ w[42] >> 5) & (1 << 1)) +++ | !(DV_I_48_2_BIT | DV_II_46_2_BIT | DV_II_51_2_BIT); +++ mask &= (0u32).wrapping_sub((w[40] ^ w[41] >> 5) & (1 << 1)) +++ | !(DV_I_47_2_BIT | DV_I_51_2_BIT | DV_II_50_2_BIT); +++ if mask & (DV_I_44_0_BIT | DV_I_46_0_BIT | DV_II_56_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[40] ^ w[42]) >> 4 & 1) +++ | !(DV_I_44_0_BIT | DV_I_46_0_BIT | DV_II_56_0_BIT) +++ } +++ mask &= (0u32).wrapping_sub((w[39] ^ w[40] >> 5) & (1 << 1)) +++ | !(DV_I_46_2_BIT | DV_I_50_2_BIT | DV_II_49_2_BIT); +++ if mask & (DV_I_43_0_BIT | DV_I_45_0_BIT | DV_II_55_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[39] ^ w[41]) >> 4 & 1) +++ | !(DV_I_43_0_BIT | DV_I_45_0_BIT | DV_II_55_0_BIT) +++ } +++ if mask & (DV_I_44_0_BIT | DV_II_54_0_BIT | DV_II_56_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[38] ^ w[40]) >> 4 & 1) +++ | !(DV_I_44_0_BIT | DV_II_54_0_BIT | DV_II_56_0_BIT) +++ } +++ if mask & (DV_I_43_0_BIT | DV_II_53_0_BIT | DV_II_55_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[37] ^ w[39]) >> 4 & 1) +++ | !(DV_I_43_0_BIT | DV_II_53_0_BIT | DV_II_55_0_BIT) +++ } +++ mask &= (0u32).wrapping_sub((w[36] ^ w[37] >> 5) & (1 << 1)) +++ | !(DV_I_47_2_BIT | DV_I_50_2_BIT | DV_II_46_2_BIT); +++ if mask & (DV_I_45_0_BIT | DV_I_48_0_BIT | DV_II_47_0_BIT) != 0 { +++ mask &= ((w[35] >> 4 ^ w[39] >> 29) & 1).wrapping_sub(1) +++ | !(DV_I_45_0_BIT | DV_I_48_0_BIT | DV_II_47_0_BIT) +++ } +++ if mask & (DV_I_48_0_BIT | DV_II_48_0_BIT) != 0 { +++ mask &= +++ (0u32).wrapping_sub((w[63] ^ w[64] >> 5) & (1 << 0)) | !(DV_I_48_0_BIT | DV_II_48_0_BIT) +++ } +++ if mask & (DV_I_45_0_BIT | DV_II_45_0_BIT) != 0 { +++ mask &= +++ (0u32).wrapping_sub((w[63] ^ w[64] >> 5) & (1 << 1)) | !(DV_I_45_0_BIT | DV_II_45_0_BIT) +++ } +++ if mask & (DV_I_47_0_BIT | DV_II_47_0_BIT) != 0 { +++ mask &= +++ (0u32).wrapping_sub((w[62] ^ w[63] >> 5) & (1 << 0)) | !(DV_I_47_0_BIT | DV_II_47_0_BIT) +++ } +++ if mask & (DV_I_46_0_BIT | DV_II_46_0_BIT) != 0 { +++ mask &= +++ (0u32).wrapping_sub((w[61] ^ w[62] >> 5) & (1 << 0)) | !(DV_I_46_0_BIT | DV_II_46_0_BIT) +++ } +++ mask &= +++ (0u32).wrapping_sub((w[61] ^ w[62] >> 5) & (1 << 2)) | !(DV_I_46_2_BIT | DV_II_46_2_BIT); +++ if mask & (DV_I_45_0_BIT | DV_II_45_0_BIT) != 0 { +++ mask &= +++ (0u32).wrapping_sub((w[60] ^ w[61] >> 5) & (1 << 0)) | !(DV_I_45_0_BIT | DV_II_45_0_BIT) +++ } +++ if mask & (DV_II_51_0_BIT | DV_II_54_0_BIT) != 0 { +++ mask &= ((w[58] ^ w[59]) >> 29 & 1).wrapping_sub(1) | !(DV_II_51_0_BIT | DV_II_54_0_BIT) +++ } +++ if mask & (DV_II_50_0_BIT | DV_II_53_0_BIT) != 0 { +++ mask &= ((w[57] ^ w[58]) >> 29 & 1).wrapping_sub(1) | !(DV_II_50_0_BIT | DV_II_53_0_BIT) +++ } +++ if mask & (DV_II_52_0_BIT | DV_II_54_0_BIT) != 0 { +++ mask &= ((w[56] ^ w[59] >> 25) & (1 << 4)).wrapping_sub(1 << 4) +++ | !(DV_II_52_0_BIT | DV_II_54_0_BIT) +++ } +++ if mask & (DV_II_51_0_BIT | DV_II_52_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[56] ^ w[59]) >> 29 & 1) | !(DV_II_51_0_BIT | DV_II_52_0_BIT) +++ } +++ if mask & (DV_II_49_0_BIT | DV_II_52_0_BIT) != 0 { +++ mask &= ((w[56] ^ w[57]) >> 29 & 1).wrapping_sub(1) | !(DV_II_49_0_BIT | DV_II_52_0_BIT) +++ } +++ if mask & (DV_II_51_0_BIT | DV_II_53_0_BIT) != 0 { +++ mask &= ((w[55] ^ w[58] >> 25) & (1 << 4)).wrapping_sub(1 << 4) +++ | !(DV_II_51_0_BIT | DV_II_53_0_BIT) +++ } +++ if mask & (DV_II_50_0_BIT | DV_II_52_0_BIT) != 0 { +++ mask &= ((w[54] ^ w[57] >> 25) & (1 << 4)).wrapping_sub(1 << 4) +++ | !(DV_II_50_0_BIT | DV_II_52_0_BIT) +++ } +++ if mask & (DV_II_49_0_BIT | DV_II_51_0_BIT) != 0 { +++ mask &= ((w[53] ^ w[56] >> 25) & (1 << 4)).wrapping_sub(1 << 4) +++ | !(DV_II_49_0_BIT | DV_II_51_0_BIT) +++ } +++ mask &= +++ ((w[51] ^ w[50] >> 5) & (1 << 1)).wrapping_sub(1 << 1) | !(DV_I_50_2_BIT | DV_II_46_2_BIT); +++ mask &= ((w[48] ^ w[50]) & (1 << 6)).wrapping_sub(1 << 6) | !(DV_I_50_2_BIT | DV_II_46_2_BIT); +++ if mask & (DV_I_51_0_BIT | DV_I_52_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[48] ^ w[55]) >> 29 & 1) | !(DV_I_51_0_BIT | DV_I_52_0_BIT) +++ } +++ mask &= ((w[47] ^ w[49]) & (1 << 6)).wrapping_sub(1 << 6) | !(DV_I_49_2_BIT | DV_I_51_2_BIT); +++ mask &= +++ ((w[48] ^ w[47] >> 5) & (1 << 1)).wrapping_sub(1 << 1) | !(DV_I_47_2_BIT | DV_II_51_2_BIT); +++ mask &= ((w[46] ^ w[48]) & (1 << 6)).wrapping_sub(1 << 6) | !(DV_I_48_2_BIT | DV_I_50_2_BIT); +++ mask &= +++ ((w[47] ^ w[46] >> 5) & (1 << 1)).wrapping_sub(1 << 1) | !(DV_I_46_2_BIT | DV_II_50_2_BIT); +++ mask &= +++ (0u32).wrapping_sub((w[44] ^ w[45] >> 5) & (1 << 1)) | !(DV_I_51_2_BIT | DV_II_49_2_BIT); +++ mask &= ((w[43] ^ w[45]) & (1 << 6)).wrapping_sub(1 << 6) | !(DV_I_47_2_BIT | DV_I_49_2_BIT); +++ mask &= ((w[42] ^ w[44]) >> 6 & 1).wrapping_sub(1) | !(DV_I_46_2_BIT | DV_I_48_2_BIT); +++ mask &= +++ ((w[43] ^ w[42] >> 5) & (1 << 1)).wrapping_sub(1 << 1) | !(DV_II_46_2_BIT | DV_II_51_2_BIT); +++ mask &= +++ ((w[42] ^ w[41] >> 5) & (1 << 1)).wrapping_sub(1 << 1) | !(DV_I_51_2_BIT | DV_II_50_2_BIT); +++ mask &= +++ ((w[41] ^ w[40] >> 5) & (1 << 1)).wrapping_sub(1 << 1) | !(DV_I_50_2_BIT | DV_II_49_2_BIT); +++ if mask & (DV_I_52_0_BIT | DV_II_51_0_BIT) != 0 { +++ mask &= ((w[39] ^ w[43] >> 25) & (1 << 4)).wrapping_sub(1 << 4) +++ | !(DV_I_52_0_BIT | DV_II_51_0_BIT) +++ } +++ if mask & (DV_I_51_0_BIT | DV_II_50_0_BIT) != 0 { +++ mask &= ((w[38] ^ w[42] >> 25) & (1 << 4)).wrapping_sub(1 << 4) +++ | !(DV_I_51_0_BIT | DV_II_50_0_BIT) +++ } +++ if mask & (DV_I_48_2_BIT | DV_I_51_2_BIT) != 0 { +++ mask &= +++ (0u32).wrapping_sub((w[37] ^ w[38] >> 5) & (1 << 1)) | !(DV_I_48_2_BIT | DV_I_51_2_BIT) +++ } +++ if mask & (DV_I_50_0_BIT | DV_II_49_0_BIT) != 0 { +++ mask &= ((w[37] ^ w[41] >> 25) & (1 << 4)).wrapping_sub(1 << 4) +++ | !(DV_I_50_0_BIT | DV_II_49_0_BIT) +++ } +++ if mask & (DV_II_52_0_BIT | DV_II_54_0_BIT) != 0 { +++ mask &= (0u32).wrapping_sub((w[36] ^ w[38]) & (1 << 4)) | !(DV_II_52_0_BIT | DV_II_54_0_BIT) +++ } +++ mask &= (0u32).wrapping_sub((w[35] ^ w[36] >> 5) & (1 << 1)) | !(DV_I_46_2_BIT | DV_I_49_2_BIT); +++ if mask & (DV_I_51_0_BIT | DV_II_47_0_BIT) != 0 { +++ mask &= ((w[35] ^ w[39] >> 25) & (1 << 3)).wrapping_sub(1 << 3) +++ | !(DV_I_51_0_BIT | DV_II_47_0_BIT) +++ } +++ if mask != 0 { +++ if mask & DV_I_43_0_BIT != 0 +++ && ((w[61] ^ w[62] >> 5) & (1 << 1) == 0 +++ || (w[59] ^ w[63] >> 25) & (1 << 5) != 0 +++ || (w[58] ^ w[63] >> 30) & (1 << 0) == 0) +++ { +++ mask &= !DV_I_43_0_BIT +++ } +++ if mask & DV_I_44_0_BIT != 0 +++ && ((w[62] ^ w[63] >> 5) & (1 << 1) == 0 +++ || (w[60] ^ w[64] >> 25) & (1 << 5) != 0 +++ || (w[59] ^ w[64] >> 30) & (1 << 0) == 0) +++ { +++ mask &= !DV_I_44_0_BIT +++ } +++ if mask & DV_I_46_2_BIT != 0 { +++ mask &= !((w[40] ^ w[42]) >> 2) | !DV_I_46_2_BIT +++ } +++ if mask & DV_I_47_2_BIT != 0 +++ && ((w[62] ^ w[63] >> 5) & (1 << 2) == 0 || (w[41] ^ w[43]) & (1 << 6) != 0) +++ { +++ mask &= !DV_I_47_2_BIT +++ } +++ if mask & DV_I_48_2_BIT != 0 +++ && ((w[63] ^ w[64] >> 5) & (1 << 2) == 0 || (w[48] ^ w[49] << 5) & (1 << 6) != 0) +++ { +++ mask &= !DV_I_48_2_BIT +++ } +++ if mask & DV_I_49_2_BIT != 0 +++ && ((w[49] ^ w[50] << 5) & (1 << 6) != 0 +++ || (w[42] ^ w[50]) & (1 << 1) == 0 +++ || (w[39] ^ w[40] << 5) & (1 << 6) != 0 +++ || (w[38] ^ w[40]) & (1 << 1) == 0) +++ { +++ mask &= !DV_I_49_2_BIT +++ } +++ if mask & DV_I_50_0_BIT != 0 { +++ mask &= (w[36] ^ w[37]) << 7 | !DV_I_50_0_BIT +++ } +++ if mask & DV_I_50_2_BIT != 0 { +++ mask &= (w[43] ^ w[51]) << 11 | !DV_I_50_2_BIT +++ } +++ if mask & DV_I_51_0_BIT != 0 { +++ mask &= (w[37] ^ w[38]) << 9 | !DV_I_51_0_BIT +++ } +++ if mask & DV_I_51_2_BIT != 0 +++ && ((w[51] ^ w[52] << 5) & (1 << 6) != 0 +++ || (w[49] ^ w[51]) & (1 << 6) != 0 +++ || (w[37] ^ w[37] >> 5) & (1 << 1) != 0 +++ || (w[35] ^ w[39] >> 25) & (1 << 5) != 0) +++ { +++ mask &= !DV_I_51_2_BIT +++ } +++ if mask & DV_I_52_0_BIT != 0 { +++ mask &= (w[38] ^ w[39]) << 11 | !DV_I_52_0_BIT +++ } +++ if mask & DV_II_46_2_BIT != 0 { +++ mask &= (w[47] ^ w[51]) << 17 | !DV_II_46_2_BIT +++ } +++ if mask & DV_II_48_0_BIT != 0 +++ && ((w[36] ^ w[40] >> 25) & (1 << 3) != 0 || (w[35] ^ w[40] << 2) & (1 << 30) == 0) +++ { +++ mask &= !DV_II_48_0_BIT +++ } +++ if mask & DV_II_49_0_BIT != 0 +++ && ((w[37] ^ w[41] >> 25) & (1 << 3) != 0 || (w[36] ^ w[41] << 2) & (1 << 30) == 0) +++ { +++ mask &= !DV_II_49_0_BIT +++ } +++ if mask & DV_II_49_2_BIT != 0 +++ && ((w[53] ^ w[54] << 5) & (1 << 6) != 0 +++ || (w[51] ^ w[53]) & (1 << 6) != 0 +++ || (w[50] ^ w[54]) & (1 << 1) == 0 +++ || (w[45] ^ w[46] << 5) & (1 << 6) != 0 +++ || (w[37] ^ w[41] >> 25) & (1 << 5) != 0 +++ || (w[36] ^ w[41] >> 30) & (1 << 0) == 0) +++ { +++ mask &= !DV_II_49_2_BIT +++ } +++ if mask & DV_II_50_0_BIT != 0 +++ && ((w[55] ^ w[58]) & (1 << 29) == 0 +++ || (w[38] ^ w[42] >> 25) & (1 << 3) != 0 +++ || (w[37] ^ w[42] << 2) & (1 << 30) == 0) +++ { +++ mask &= !DV_II_50_0_BIT +++ } +++ if mask & DV_II_50_2_BIT != 0 +++ && ((w[54] ^ w[55] << 5) & (1 << 6) != 0 +++ || (w[52] ^ w[54]) & (1 << 6) != 0 +++ || (w[51] ^ w[55]) & (1 << 1) == 0 +++ || (w[45] ^ w[47]) & (1 << 1) == 0 +++ || (w[38] ^ w[42] >> 25) & (1 << 5) != 0 +++ || (w[37] ^ w[42] >> 30) & (1 << 0) == 0) +++ { +++ mask &= !DV_II_50_2_BIT +++ } +++ if mask & DV_II_51_0_BIT != 0 +++ && ((w[39] ^ w[43] >> 25) & (1 << 3) != 0 || (w[38] ^ w[43] << 2) & (1 << 30) == 0) +++ { +++ mask &= !DV_II_51_0_BIT +++ } +++ if mask & DV_II_51_2_BIT != 0 +++ && ((w[55] ^ w[56] << 5) & (1 << 6) != 0 +++ || (w[53] ^ w[55]) & (1 << 6) != 0 +++ || (w[52] ^ w[56]) & (1 << 1) == 0 +++ || (w[46] ^ w[48]) & (1 << 1) == 0 +++ || (w[39] ^ w[43] >> 25) & (1 << 5) != 0 +++ || (w[38] ^ w[43] >> 30) & (1 << 0) == 0) +++ { +++ mask &= !DV_II_51_2_BIT +++ } +++ if mask & DV_II_52_0_BIT != 0 +++ && ((w[59] ^ w[60]) & (1 << 29) != 0 +++ || (w[40] ^ w[44] >> 25) & (1 << 3) != 0 +++ || (w[40] ^ w[44] >> 25) & (1 << 4) != 0 +++ || (w[39] ^ w[44] << 2) & (1 << 30) == 0) +++ { +++ mask &= !DV_II_52_0_BIT +++ } +++ if mask & DV_II_53_0_BIT != 0 +++ && ((w[58] ^ w[61]) & (1 << 29) == 0 +++ || (w[57] ^ w[61] >> 25) & (1 << 4) != 0 +++ || (w[41] ^ w[45] >> 25) & (1 << 3) != 0 +++ || (w[41] ^ w[45] >> 25) & (1 << 4) != 0) +++ { +++ mask &= !DV_II_53_0_BIT +++ } +++ if mask & DV_II_54_0_BIT != 0 +++ && ((w[58] ^ w[62] >> 25) & (1 << 4) != 0 +++ || (w[42] ^ w[46] >> 25) & (1 << 3) != 0 +++ || (w[42] ^ w[46] >> 25) & (1 << 4) != 0) +++ { +++ mask &= !DV_II_54_0_BIT +++ } +++ if mask & DV_II_55_0_BIT != 0 +++ && ((w[59] ^ w[63] >> 25) & (1 << 4) != 0 +++ || (w[57] ^ w[59] >> 25) & (1 << 4) != 0 +++ || (w[43] ^ w[47] >> 25) & (1 << 3) != 0 +++ || (w[43] ^ w[47] >> 25) & (1 << 4) != 0) +++ { +++ mask &= !DV_II_55_0_BIT +++ } +++ if mask & DV_II_56_0_BIT != 0 +++ && ((w[60] ^ w[64] >> 25) & (1 << 4) != 0 +++ || (w[44] ^ w[48] >> 25) & (1 << 3) != 0 +++ || (w[44] ^ w[48] >> 25) & (1 << 4) != 0) +++ { +++ mask &= !DV_II_56_0_BIT +++ } +++ } +++ mask +++}