--- /dev/null
--- /dev/null
--- /dev/null
+++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 <infinity0@debian.org> Mon, 16 Oct 2017 18:02:23 +0200
--- /dev/null
--- /dev/null
--- /dev/null
+++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 <sylvestre@debian.org>, Fri, 13 Feb 2015 15:08:43 +0100
--- /dev/null
--- /dev/null
--- /dev/null
+++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.
--- /dev/null
--- /dev/null
--- /dev/null
+++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 <sylvestre@debian.org> Tue, 20 Jan 2015 08:50:28 +0100
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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)
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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 <registry>`?')
+++
+++ 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:]))
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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,/}"
--- /dev/null
--- /dev/null
--- /dev/null
+++usr/share/doc/cargo/reference
+++usr/share/doc/cargo/book
--- /dev/null
--- /dev/null
--- /dev/null
+++etc/bash_completion.d/cargo cargo
--- /dev/null
--- /dev/null
--- /dev/null
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++usr/share/man/man1/cargo-*.1
+++usr/share/man/man1/cargo.1
--- /dev/null
--- /dev/null
--- /dev/null
+++rustc (1.85.0+dfsg2-3) unstable; urgency=medium
+++
+++ * baseline: enable SSE2 for i386 build (Closes: #1095862)
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> Fri, 11 Apr 2025 13:40:09 +0200
+++
+++rustc (1.85.0+dfsg2-2) unstable; urgency=medium
+++
+++ * Upload to unstable
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Mon, 17 Mar 2025 06:54:23 +0100
+++
+++rustc (1.85.0+dfsg1-1) unstable; urgency=medium
+++
+++ * New (stable) upstream release.
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Tue, 08 Oct 2024 14:34:41 +0200
+++
+++rustc (1.81.0+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Wed, 11 Sep 2024 08:26:59 +0200
+++
+++rustc (1.80.1+dfsg1-1) unstable; urgency=medium
+++
+++ * upload to unstable
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Tue, 25 Jun 2024 09:40:12 +0200
+++
+++rustc (1.78.0+dfsg1-2) unstable; urgency=medium
+++
+++ * unbreak loongson64 build
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Mon, 27 May 2024 22:20:44 +0200
+++
+++rustc (1.72.1+dfsg1-1) unstable; urgency=medium
+++
+++ * upload to unstable
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Fri, 17 May 2024 08:38:11 +0200
+++
+++rustc (1.71.1+dfsg1-1) unstable; urgency=medium
+++
+++ * upload to unstable
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Wed, 08 May 2024 18:48:48 +0200
+++
+++rustc (1.70.0+dfsg2-1) unstable; urgency=medium
+++
+++ * upload to unstable
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <ema@debian.org> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Sun, 14 Jan 2024 20:06:29 +0100
+++
+++rustc (1.70.0+dfsg1-2) unstable; urgency=medium
+++
+++ * Upload to unstable
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Sat, 02 Dec 2023 11:19:31 +0100
+++
+++rustc (1.70.0+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> Wed, 20 Sep 2023 20:18:40 +0200
+++
+++rustc (1.70.0+dfsg1-1~exp3) experimental; urgency=medium
+++
+++ * more test fixes
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Thu, 14 Sep 2023 09:07:26 +0200
+++
+++rustc (1.69.0+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Tue, 12 Sep 2023 10:17:15 +0200
+++
+++rustc (1.68.2+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Wed, 02 Aug 2023 13:17:47 +0200
+++
+++rustc (1.67.1+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <f.gruenbichler@proxmox.com> Fri, 07 Jul 2023 10:01:33 +0200
+++
+++rustc (1.66.0+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <jbicha@ubuntu.com> Mon, 26 Jun 2023 17:16:27 -0400
+++
+++rustc (1.65.0+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable
+++
+++ -- Fabian Grünbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Wed, 07 Dec 2022 17:29:00 +0100
+++
+++rustc (1.63.0+dfsg1-1~exp1) experimental; urgency=medium
+++
+++ * New upstream release
+++
+++ -- Fabian Gruenbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Mon, 31 Oct 2022 14:19:34 +0100
+++
+++rustc (1.62.1+dfsg1-1~exp1) experimental; urgency=medium
+++
+++ * New upstream release
+++
+++ -- Fabian Gruenbichler <debian@fabian.gruenbichler.email> 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 <debian@fabian.gruenbichler.email> Mon, 10 Oct 2022 20:19:05 +0200
+++
+++rustc (1.61.0+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable (Closes: #1020394)
+++
+++ -- Sylvestre Ledru <sylvestre@debian.org> 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 <f.gruenbichler@proxmox.com> 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 <f.gruenbichler@proxmox.com> Mon, 5 Sep 2022 10:03:18 +0200
+++
+++rustc (1.60.0+dfsg1-1~exp1) experimental; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Fabian Gruenbichler <f.gruenbichler@proxmox.com> 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 <infinity0@debian.org> Tue, 21 Jun 2022 11:06:16 +0100
+++
+++rustc (1.59.0+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> Tue, 29 Mar 2022 14:32:01 +0100
+++
+++rustc (1.58.1+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> Tue, 08 Mar 2022 11:32:29 +0000
+++
+++rustc (1.57.0+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable. (Closes: #1005203)
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <f.gruenbichler@proxmox.com> Thu, 03 Feb 2022 19:14:04 +0100
+++
+++rustc (1.56.0+dfsg1-2) unstable; urgency=medium
+++
+++ * Update to debhelper 13.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Wed, 13 Oct 2021 22:06:15 +0100
+++
+++rustc (1.55.0+dfsg1-1~exp1) experimental; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> Sat, 09 Oct 2021 03:22:08 +0100
+++
+++rustc (1.54.0+dfsg1-3) unstable; urgency=medium
+++
+++ * Fix links to cargo-doc.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Sat, 09 Oct 2021 00:24:37 +0100
+++
+++rustc (1.54.0+dfsg1-1~exp1) experimental; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Wed, 06 Oct 2021 19:01:54 +0100
+++
+++rustc (1.53.0+dfsg1-2) unstable; urgency=medium
+++
+++ * Fix some test failures.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Wed, 29 Sep 2021 20:05:55 +0100
+++
+++rustc (1.52.1+dfsg1-1~exp3) experimental; urgency=medium
+++
+++ * Update to LLVM 12.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> Sat, 15 May 2021 22:42:38 +0100
+++
+++rustc (1.52.1+dfsg1-1~exp1) experimental; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> Sat, 15 May 2021 15:21:27 +0100
+++
+++rustc (1.52.0+dfsg1-1~exp1) experimental; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Mon, 12 Apr 2021 11:04:36 +0100
+++
+++rustc (1.50.0+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Fri, 09 Apr 2021 16:54:20 +0100
+++
+++rustc (1.50.0+dfsg1-1~exp1) experimental; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> Sat, 18 Sep 2021 11:33:09 +0100
+++
+++rustc (1.49.0+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable.
+++
+++ -- Ximin Luo <infinity0@debian.org> Sat, 28 Aug 2021 10:48:11 +0100
+++
+++rustc (1.49.0+dfsg1-1~exp1) experimental; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Sun, 20 Dec 2020 18:52:10 +0000
+++
+++rustc (1.48.0+dfsg1-1) unstable; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Sat, 05 Sep 2020 16:11:16 +0100
+++
+++rustc (1.46.0+dfsg1-1) unstable; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Thu, 06 Aug 2020 21:11:39 +0100
+++
+++rustc (1.45.0+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable.
+++
+++ -- Ximin Luo <infinity0@debian.org> Wed, 05 Aug 2020 21:41:39 +0100
+++
+++rustc (1.45.0+dfsg1-1~exp1) experimental; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Mon, 27 Jul 2020 13:15:20 +0100
+++
+++rustc (1.44.1+dfsg1-1~exp1) experimental; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Mon, 27 Apr 2020 13:09:20 +0100
+++
+++rustc (1.42.0+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> Sat, 04 Apr 2020 16:06:03 +0100
+++
+++rustc (1.41.1+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Sun, 05 Jan 2020 13:35:46 +0000
+++
+++rustc (1.40.0+dfsg1-4) unstable; urgency=medium
+++
+++ * Experimental riscv64 support.
+++
+++ -- Ximin Luo <infinity0@debian.org> Sat, 04 Jan 2020 05:40:11 +0000
+++
+++rustc (1.40.0+dfsg1-3) unstable; urgency=medium
+++
+++ * Work around upstream #59264 again. :/
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Sun, 29 Dec 2019 22:17:04 +0000
+++
+++rustc (1.40.0+dfsg1-1~exp1) experimental; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Thu, 05 Dec 2019 22:51:41 +0000
+++
+++rustc (1.39.0+dfsg1-1) unstable; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> Fri, 29 Nov 2019 00:05:16 +0000
+++
+++rustc (1.38.0+dfsg1-1) unstable; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Wed, 17 Jul 2019 18:25:06 -0700
+++
+++rustc (1.36.0+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable.
+++
+++ -- Ximin Luo <infinity0@debian.org> Tue, 16 Jul 2019 20:27:55 -0700
+++
+++rustc (1.36.0+dfsg1-1~exp1) experimental; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Sun, 17 Mar 2019 12:52:57 -0700
+++
+++rustc (1.32.0+dfsg1-1) unstable; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Sat, 15 Dec 2018 13:52:26 -0800
+++
+++rustc (1.31.0+dfsg1-1~exp1) experimental; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <jcristau@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Thu, 19 Jul 2018 08:52:03 -0700
+++
+++rustc (1.27.1+dfsg1-1~exp2) experimental; urgency=medium
+++
+++ * Fix some failing tests.
+++
+++ -- Ximin Luo <infinity0@debian.org> Wed, 18 Jul 2018 09:06:44 -0700
+++
+++rustc (1.27.1+dfsg1-1~exp1) unstable; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Wed, 30 May 2018 20:58:46 -0700
+++
+++rustc (1.26.1+dfsg1-1) unstable; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Fri, 18 May 2018 01:11:15 -0700
+++
+++rustc (1.25.0+dfsg1-1~exp2) experimental; urgency=medium
+++
+++ * Install missing codegen-backends.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Sat, 03 Mar 2018 14:23:29 +0100
+++
+++rustc (1.23.0+dfsg1-1) unstable; urgency=medium
+++
+++ * Upload to unstable.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Sat, 21 Oct 2017 14:20:17 +0200
+++
+++rustc (1.20.0+dfsg1-1) unstable; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Mon, 17 Jul 2017 23:04:03 +0200
+++
+++rustc (1.18.0+dfsg1-1) experimental; urgency=medium
+++
+++ * New upstream release.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Wed, 21 Jun 2017 10:46:27 +0200
+++
+++rustc (1.17.0+dfsg2-6) unstable; urgency=medium
+++
+++ * Upload to unstable.
+++
+++ -- Ximin Luo <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <sylvestre@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <sylvestre@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <lucab@debian.org> 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 <sylvestre@debian.org> 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 <infinity0@debian.org> 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 <sylvestre@debian.org> 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 <sylvestre@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> 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 <infinity0@debian.org> Sun, 17 Jul 2016 03:40:49 +0200
+++
+++rustc (1.9.0+dfsg1-1) unstable; urgency=medium
+++
+++ * New upstream release (Closes: #825752)
+++
+++ -- Sylvestre Ledru <sylvestre@debian.org> 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 <sylvestre@debian.org> Fri, 15 Apr 2016 12:01:45 +0200
+++
+++rustc (1.7.0+dfsg1-1) unstable; urgency=medium
+++
+++ * New upstream release
+++
+++ -- Sylvestre Ledru <sylvestre@debian.org> 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 <sylvestre@debian.org> 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 <gus@debian.org> 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 <sylvestre@debian.org> 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 <sylvestre@debian.org> 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 <sylvestre@debian.org> 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 <sylvestre@debian.org> 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 <sylvestre@debian.org> 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 <gus@debian.org> 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 <gus@debian.org> 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 <gus@debian.org> 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 <sylvestre@debian.org> 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 <sylvestre@debian.org> 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 <sylvestre@debian.org> 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 <sylvestre@debian.org> Fri, 23 Jan 2015 15:47:37 +0100
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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."
--- /dev/null
--- /dev/null
--- /dev/null
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++Source: rustc
+++Section: devel
+++Priority: optional
+++Maintainer: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++Uploaders:
+++ Ximin Luo <infinity0@debian.org>,
+++ Sylvestre Ledru <sylvestre@debian.org>,
+++ Fabian Grünbichler <debian@fabian.gruenbichler.email>
+++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) <!pkg.rustc.dlstage0>,
+++ rustc:native (>= 1.84.0+dfsg) <!pkg.rustc.dlstage0>,
+++ rustc:native (<= 1.85.0+dfsg++) <!pkg.rustc.dlstage0>,
+++ llvm-19-dev:native,
+++ llvm-19-tools:native,
+++ gcc-mingw-w64-x86-64-posix:native [amd64] <pkg.rustc.windows>,
+++ gcc-mingw-w64-i686-posix:native [i386] <pkg.rustc.windows>,
+++ 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) <!nocheck> | binutils-2.26 <!nocheck>,
+++# temporarily disabled cause of #1066794 / t64 transition
+++ git <!nocheck>,
+++ procps <!nocheck>,
+++# below are optional tools even for 'make check'
+++ gdb (>= 7.12) <!nocheck>,
+++# Extra build-deps needed for x.py to download stuff in pkg.rustc.dlstage0.
+++ curl <pkg.rustc.dlstage0>,
+++ ca-certificates <pkg.rustc.dlstage0>,
+++Build-Depends-Indep:
+++ wasi-libc (>= 0.0~git20241209.574b88d~~) <!nowasm>,
+++ wasi-libc (<= 0.0~git20241209.574b88d++) <!nowasm>,
+++ clang-19:native,
+++# see #1057780, gdb now Conflicts gdb-minimal
+++#Build-Conflicts: gdb-minimal <!nocheck>
+++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: <pkg.rustc.windows>
+++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: <!nowasm>
+++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: <!nodoc>
+++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: <!nodoc>
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++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 <japaricious@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/rust-lang-nursery/compiler-builtins
+++
+++Files: vendor/ahash-*/*
+++Copyright: 2019-2022 Tom Kaitchuck <Tom.Kaitchuck@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/tkaitchuck/ahash
+++
+++Files: vendor/android_system_properties-*/*
+++Copyright: 2022-2022 Nicolas Silva <nical@fastmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/nical/android_system_properties
+++
+++Files: vendor/anes-*/*
+++Copyright: 2019-2023 Robert Vojta <rvojta@me.com>
+++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 <eopage@gmail.com>
+++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 <fitzgen@gmail.com>
+++ 2017-2024 Manish Goregaokar <manishsmail@gmail.com>
+++ 2017-2024 Simonas Kazlauskas <arbitrary@kazlauskas.me>
+++ 2017-2024 Brian L. Troutwine <brian@troutwine.us>
+++ 2017-2024 Corey Farwell <coreyf@rwell.org>
+++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 <open-source@jhpratt.dev>
+++ 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 <jacob@jhpratt.dev>
+++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 <alex@alexcrichton.com>
+++ 2015-2017 Keegan McAllister <kmcallister@mozilla.com>
+++ 2015-2017 Chris Morgan <me@chrismorgan.info>
+++ 2014-2017 The html5ever Project Developers
+++ 2014-2017 The Servo Project Developers
+++ 2013-2017 Simon Sapin <simon.sapin@exyr.org>
+++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 <zicklag@katharostech.com>
+++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 <alex@alexcrichton.com>
+++ 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 <jackefransham@hotmail.co.uk>
+++License: MIT
+++
+++Files: vendor/dlmalloc-*/*
+++Copyright: 2017-2019 Alex Crichton <alex@alexcrichton.com>
+++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 <dl@cs.oswego.edu>
+++License: CC0-1.0
+++
+++Files: vendor/addr2line-*/*
+++Copyright:
+++ 2016-2021 Nick Fitzgerald <fitzgen@gmail.com>
+++ 2016-2021 Philip Craig <philipjcraig@gmail.com>
+++ 2016-2021 Jon Gjengset <jon@thesquareplanet.com>
+++ 2016-2021 Noah Bergbauer <noah.bergbauer@tum.de>
+++License: Apache-2.0 or MIT
+++Comment: see https://github.com/gimli-rs/addr2line
+++
+++Files:
+++ vendor/adler-*/*
+++Copyright: 2020-2021 Jonas Schievink <jonasschievink@gmail.com>
+++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 <jonasschievink@gmail.com>
+++ 2020-2024 oyvindln <oyvindln@users.noreply.github.com>
+++License: 0BSD OR MIT OR Apache-2.0
+++Comment: see https://github.com/oyvindln/adler2
+++
+++Files: vendor/allocator-api2-*/*
+++Copyright: 2023-2024 Zakarum <zaq.dev@icloud.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/zakarumych/allocator-api2
+++
+++Files: vendor/always-assert-*/*
+++Copyright: 2021-2021 Aleksey Kladov <aleksey.kladov@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/matklad/always-assert
+++
+++Files: vendor/ammonia-*/*
+++Copyright: 2015-2018 Michael Howell <michael@notriddle.com>
+++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 <gandalf@mozilla.com>
+++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 <jamslam@gmail.com>
+++ 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 <vorner@vorner.cz>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/vorner/arc-swap
+++
+++Files: vendor/arrayref-*/*
+++Copyright: 2015-2024 David Roundy <roundyd@physics.oregonstate.edu>
+++License: BSD-2-Clause
+++Comment: see https://github.com/droundy/arrayref
+++
+++Files: vendor/autocfg-*/*
+++Copyright: 2018-2020 Josh Stone <cuviper@gmail.com>
+++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 <alice@alicemaz.com>
+++ 2015-2024 Marshall Pierce <marshall@mpierce.org>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/marshallpierce/rust-base64
+++
+++Files: vendor/basic-toml-*/*
+++Copyright: 2014-2023 Alex Crichton <alex@alexcrichton.com>
+++ 2014-2023 David Tolnay <dtolnay@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/dtolnay/basic-toml
+++
+++Files: vendor/bincode-*/*
+++Copyright: 2014-2024 Ty Overby <ty@pre-alpha.com>
+++ 2014-2024 Francesco Mazzoli <f@mazzo.li>
+++ 2014-2024 David Tolnay <dtolnay@gmail.com>
+++ 2014-2024 Zoey Riordan <zoey@dos.cafe>
+++License: MIT
+++Comment: see https://github.com/servo/bincode
+++
+++Files: vendor/bitmaps-*/*
+++Copyright: 2019-2024 Bodil Stokke <bodil@bodil.org>
+++License: MPL-2.0+
+++Comment: see https://github.com/bodil/bitmaps
+++
+++Files: vendor/bit-set-*/*
+++Copyright: 2015-2023 Alexis Beingessner <a.beingessner@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/contain-rs/bit-set
+++
+++Files: vendor/bit-vec-*/*
+++Copyright: 2015-2023 Alexis Beingessner <a.beingessner@gmail.com>
+++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 <oconnor663@gmail.com>
+++ 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 <hello@near.org>
+++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 <jamslam@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/BurntSushi/bstr
+++
+++Files: vendor/bumpalo-*/*
+++Copyright: 2018-2024 Nick Fitzgerald <fitzgen@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/fitzgen/bumpalo
+++
+++Files: vendor/bytecount-*/*
+++Copyright: 2016-2020 Andre Bogus <bogusandre@gmail.de>
+++ 2016-2020 Joshua Landau <joshua@landau.ws>
+++License: Apache-2.0 or MIT
+++Comment: see https://github.com/llogiq/bytecount
+++
+++Files: vendor/byteorder-*/*
+++Copyright: 2015-2023 Andrew Gallant <jamslam@gmail.com>
+++License: Unlicense OR MIT
+++Comment: see https://github.com/BurntSushi/byteorder
+++
+++Files: vendor/bytesize-*/*
+++Copyright: 2015-2023 Hyunsik Choi <hyunsik.choi@gmail.com>
+++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 <jamslam@gmail.com>
+++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 <saoirse@without.boats>
+++ 2020-2022 Ashley Williams <ashley666ashley@gmail.com>
+++ 2020-2022 Steve Klabnik <steve@steveklabnik.com>
+++ 2020-2022 Rain <rain@sunshowers.io>
+++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 <git-spam-no-reply9815368754983@oli-obk.de>
+++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 <jorge@japaric.io>
+++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 <public+rust@mearie.org>
+++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 <npmccallum@profian.com>
+++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. <kbknapp@gmail.com>
+++License: MIT
+++Comment: see https://github.com/clap-rs/clap
+++
+++Files: vendor/clap-cargo-*/*
+++Copyright: 2019-2024 Ed Page <eopage@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/crate-ci/clap-cargo
+++
+++Files: vendor/clru-*/*
+++Copyright: 2020-2023 marmeladema <xademax@gmail.com>
+++License: MIT
+++Comment: see https://github.com/marmeladema/clru-rs
+++
+++Files: vendor/color-eyre-*/*
+++Copyright: 2020-2023 Jane Lusby <jlusby@yaah.dev>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/yaahc/color-eyre
+++
+++Files: vendor/color-spantrace-*/*
+++Copyright: 2020-2024 Jane Lusby <jlusby@yaah.dev>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/yaahc/color-spantrace
+++
+++Files: vendor/colored-*/*
+++Copyright: 2016-2020 Thomas Wickham <mackwic@gmail.com>
+++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 <johann.david.dev@protonmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://gitlab.com/yolenoyer/color-print
+++
+++Files: vendor/comma-*/*
+++Copyright: 2019-2023 Ethan McTague <ethan@tague.me>
+++License: MIT
+++Comment: see https://github.com/emctague/comma
+++
+++Files: vendor/constant_time_eq-*/*
+++Copyright: 2015-2024 Cesar Eduardo Barros <cesarb@cesarb.eti.br>
+++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 <armin.ronacher@active-4.com>
+++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 <mail@david-peter.de>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/sharkdp/content_inspector
+++
+++Files: vendor/countme-*/*
+++Copyright: 2021-2022 Aleksey Kladov <aleksey.kladov@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/matklad/countme
+++
+++Files: vendor/cov-mark-*/*
+++Copyright: 2020-2021 Aleksey Kladov <aleksey.kladov@gmail.com>
+++ 2020-2021 Simonas Kazlauskas <cov-mark@kazlauskas.me>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/matklad/cov-mark
+++
+++Files: vendor/crc32fast-*/*
+++Copyright: 2018-2019 Sam Rijs <srijs@airpost.net>
+++ 2018-2019 Alex Crichton <alex@alexcrichton.com>
+++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 <japaricious@gmail.com>
+++ 2014-2024 Brook Heisler <brookheisler@gmail.com>
+++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 <github@pureftpd.org>
+++License: MIT
+++Comment: see https://github.com/jedisct1/rust-ct-codecs
+++
+++Files: vendor/ctrlc-*/*
+++Copyright: 2015-2024 Antti Keränen <detegr@gmail.com>
+++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 <alex@alexcrichton.com>
+++License: MIT
+++Comment: see https://github.com/alexcrichton/curl-rust
+++
+++Files:
+++ vendor/darling-*/*
+++ vendor/darling_core-*/*
+++ vendor/darling_macro-*/*
+++Copyright: 2017-2024 Ted Driggs <ted.driggs@outlook.com>
+++License: MIT
+++Comment: see https://github.com/TedDriggs/darling
+++
+++Files: vendor/dashmap-5.*/*
+++Copyright: 2019-2024 Acrimon <joel.wejdenstal@gmail.com>
+++License: MIT
+++Comment: see https://github.com/xacrimon/dashmap
+++
+++Files: vendor/datafrog-*/*
+++Copyright:
+++ 2018 Frank McSherry <fmcsherry@me.com>
+++ 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 <rollie@rollie.dev>
+++License: MIT
+++Comment: see https://github.com/waltzofpearls/dateparser
+++
+++Files:
+++ vendor/dbus-*/*
+++ vendor/libdbus-sys-*/*
+++Copyright: 2014-2024 David Henningsson <diwic@ubuntu.com>
+++License: Apache-2.0 or MIT
+++Comment: see https://github.com/diwic/dbus-rs
+++
+++Files: vendor/deranged-*/*
+++Copyright: 2020-2023 Jacob Pratt <jacob@jhpratt.dev>
+++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 <kiegel@gmx.de>
+++ 2016-2024 Pascal Hertleif <killercup@gmail.com>
+++ 2016-2024 Jan-Erik Rediger <janerik@fnordig.de>
+++ 2016-2024 Ted Driggs <ted.driggs@outlook.com>
+++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 <lymia@lymiahugs.com>
+++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 <utkarshkukreti@gmail.com>
+++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 <simon@ochsenreither.de>
+++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 <dtolnay@gmail.com>
+++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 <simon@ochsenreither.de>
+++ 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 <jlusby@yaah.dev>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/yaahc/displaydoc
+++
+++Files: vendor/drop_bomb-*/*
+++Copyright: 2018-2020 Aleksey Kladov <aleksey.kladov@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/matklad/drop_bomb
+++
+++Files: vendor/doc-comment-*/*
+++Copyright: 2018-2020 Guillaume Gomez <guillaume1.gomez@gmail.com>
+++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 <graham.dennis@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/GrahamDennis/dot-rust
+++
+++Files: vendor/dunce-*/*
+++Copyright: 2017-2023 Kornel <kornel@geekhood.net>
+++License: CC0-1.0
+++Comment: see https://gitlab.com/kornelski/dunce
+++
+++Files: vendor/dyn-clone-1.*/*
+++Copyright: 2018-2024 David Tolnay <dtolnay@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/dtolnay/dyn-clone
+++
+++Files: vendor/ed25519-compact-*/*
+++Copyright: 2020-2024 Frank Denis <github@pureftpd.org>
+++License: MIT
+++Comment: see https://github.com/jedisct1/rust-ed25519-compact
+++
+++Files: vendor/elasticlunr-rs-*/*
+++Copyright: 2017-2018 Matt Ickstadt <mattico8@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/mattico/elasticlunr-rs
+++
+++Files: vendor/elsa-*/*
+++Copyright: 2018-2023 Manish Goregaokar <manishsmail@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/manishearth/elsa
+++
+++Files: vendor/ena-*/*
+++Copyright: 2015-2020 Niko Matsakis <niko@alum.mit.edu>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/nikomatsakis/ena
+++
+++Files: vendor/encoding_rs-*/*
+++Copyright: 2016-2024 Henri Sivonen <hsivonen@hsivonen.fi>
+++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 <dtolnay@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/dtolnay/erased-serde
+++
+++Files: vendor/errno-*/*
+++Copyright: 2015-2022 Chris Wong <lambda.fairy@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/lambda-fairy/rust-errno
+++
+++Files: vendor/equivalent-*/*
+++Copyright: 2016-2023 Josh Stone <cuviper@gmail.com>
+++License: Apache-2.0 OR MIT
+++Comment: see https://github.com/cuviper/equivalent
+++
+++Files: vendor/escargot-*/*
+++Copyright: 2018-2024 Ed Page <eopage@gmail.com>
+++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 <dtolnay@gmail.com>
+++ 2019-2024 Jane Lusby <jlusby42@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/yaahc/eyre
+++
+++Files: vendor/fallible-iterator-*/*
+++Copyright: 2016-2019 Steven Fackler <sfackler@gmail.com>
+++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 <sfackler@gmail.com>
+++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 <stjepang@gmail.com>
+++License: Apache-2.0 OR MIT
+++Comment: see https://github.com/smol-rs/fastrand
+++
+++Files: vendor/fd-lock-*/*
+++Copyright: 2019-2022 Yoshua Wuyts <yoshuawuyts@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/yoshuawuyts/fd-lock
+++
+++Files: vendor/ff-*/*
+++Copyright: 2017-2023 Sean Bowe <ewillbefull@gmail.com>
+++ 2017-2023 Jack Grigg <thestr4d@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/zkcrypto/ff
+++
+++Files: vendor/fiat-crypto-*/*
+++Copyright: 2015-2024 Fiat Crypto library authors <jgross@mit.edu>
+++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 <diggsey@googlemail.com>
+++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 <gandalf@mozilla.com>
+++ 2016-2022 Staś Małolepszy <stas@mozilla.com>
+++ 2016-2022 Manish Goregaokar <manishsmail@gmail.com>
+++License: Apache-2.0 or MIT
+++Comment: see https://github.com/projectfluent/fluent-rs
+++
+++Files: vendor/fluent-langneg-*/*
+++Copyright: 2017-2021 Zibi Braniecki <gandalf@mozilla.com>
+++License: Apache-2.0
+++Comment: see https://github.com/projectfluent/fluent-langneg-rs
+++
+++Files: vendor/foldhash-0.*/*
+++Copyright: 2024-2024 Orson Peters <orsonpeters@gmail.com>
+++License: Zlib
+++Comment: see https://github.com/orlp/foldhash
+++
+++Files:
+++ vendor/foreign-types-*/*
+++ vendor/foreign-types-shared-*/*
+++Copyright: 2017-2023 Steven Fackler <sfackler@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/sfackler/foreign-types
+++
+++Files: vendor/fortanix-sgx-abi-*/*
+++Copyright: 2015-2019 Jethro Beekman <jethro@fortanix.com>
+++License: MPL-2.0
+++Comment: see https://github.com/fortanix/rust-sgx
+++
+++Files: vendor/fs-err-*/*
+++Copyright: 2020-2020 Andrew Hickman <andrew.hickman1@sky.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/andrewhickman/fs-err
+++
+++
+++Files: vendor/fsevent-sys-*/*
+++Copyright: 2014-2019 Pierre Baillet <pierre@baillet.name>
+++License: MIT
+++Comment: see https://github.com/octplane/fsevent-rust/
+++
+++Files: vendor/fs_extra-*/*
+++Copyright: 2017-2023 Denis Kurilenko <webdesus@gmail.com>
+++License: MIT
+++Comment: see https://github.com/webdesus/fs_extra
+++
+++Files: vendor/fst-*/*
+++Copyright: 2015-2023 Andrew Gallant <jamslam@gmail.com>
+++License: Unlicense or MIT
+++Comment: see https://github.com/BurntSushi/fst
+++
+++Files: vendor/futf-*/*
+++Copyright: 2015-2018 Keegan McAllister <kmcallister@mozilla.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/servo/futf
+++
+++Files:
+++ vendor/generic-array-*/*
+++Copyright:
+++ 2015-2020 Bartłomiej Kamiński <fizyk20@gmail.com>
+++ 2015-2020 Aaron Trent <novacrazy@gmail.com>
+++License: MIT
+++Comment: see https://github.com/fizyk20/generic-array.git
+++
+++Files: vendor/gimli-*/*
+++Copyright:
+++ 2016-2021 Nick Fitzgerald <fitzgen@gmail.com>
+++ 2016-2021 Philip Craig <philipjcraig@gmail.com>
+++License: Apache-2.0 or MIT
+++Comment: see https://github.com/gimli-rs/gimli
+++
+++
+++Files:
+++ extra/git2-*/*
+++ extra/git2-curl-*/*
+++ extra/libgit2-sys-*/*
+++ vendor/git2-*/*
+++ vendor/git2-curl-*/*
+++ vendor/libgit2-sys-*/*
+++Copyright: 2014-2024 Josh Triplett <josh@joshtriplett.org>
+++ 2014-2024 Alex Crichton <alex@alexcrichton.com>
+++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 <gitoxide@conor.fastmail.fm>
+++ 2018-2024 Jiahao XU <Jiahao_XU@outlook.com>
+++ 2018-2024 Sebastian Thiel <sebastian.thiel@icloud.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/Byron/gitoxide
+++
+++Files: vendor/group-*/*
+++Copyright: 2018-2023 Sean Bowe <ewillbefull@gmail.com>
+++ 2018-2023 Jack Grigg <jack@z.cash>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/zkcrypto/group
+++
+++Files: vendor/gsgdt-*/*
+++Copyright: 2020 Vishnunarayan K I <appukuttancr@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/vn-ki/gsgdt-rs
+++
+++Files: vendor/half-*/*
+++Copyright: 2016-2024 Kathryn Long <squeeself@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/starkat99/half-rs
+++
+++Files: vendor/handlebars-*/*
+++Copyright: 2014-2017 Ning Sun <sunng@about.me>
+++License: MIT
+++Comment: see https://github.com/sunng87/handlebars-rust
+++
+++Files: vendor/hashlink-*/*
+++Copyright: 2019-2024 kyren <kerriganw@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/kyren/hashlink
+++
+++Files: vendor/heck-*/*
+++Copyright: 2017-2018 Without Boats <woboats@gmail.com>
+++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 <kokakiwi@kokakiwi.net>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/KokaKiwi/rust-hex
+++
+++Files: vendor/home-*/*
+++Copyright: 2017-2022 Brian Anderson <andersrb@gmail.com>
+++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 <len@magiclen.org>
+++License: MIT
+++Comment: see https://github.com/magiclen/html-escape
+++
+++Files: vendor/html_parser-0.*/*
+++Copyright: 2020-2023 Mathias Iversen <work@mathiasiversen.com>
+++License: MIT
+++Comment: see https://github.com/mathiversen/html-parser
+++
+++Files: vendor/http-auth-*/*
+++Copyright: 2021-2023 Scott Lamp <slamb@slamb.org>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/scottlamb/http-auth
+++
+++Files: vendor/humansize-*/*
+++Copyright: 2016-2022 Leopold Arkham <leopold.arkham@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/LeopoldArkham/humansize
+++
+++Files:
+++ vendor/humantime-*/*
+++Copyright:
+++ 2016-2018 Paul Colomiets <paul@colomiets.name>
+++ 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 <lambda.fairy@gmail.com>
+++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 <strawman@astraw.com>
+++ 2020-2024 René Kijewski <rene.kijewski@fu-berlin.de>
+++ 2020-2024 Ryan Lopopolo <rjl@hyperbo.la>
+++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 <ted.driggs@outlook.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/TedDriggs/ident_case
+++
+++Files: vendor/id-arena-*/*
+++Copyright: 2018-2023 Nick Fitzgerald <fitzgen@gmail.com>
+++ 2018-2023 Aleksey Kladov <aleksey.kladov@gmail.com>
+++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 <bodil@bodil.org>
+++License: MPL-2.0+
+++Comment: see https://github.com/bodil/im-rs
+++
+++Files: vendor/indenter-*/*
+++Copyright: 2020-2023 Jane Lusby <jlusby@yaah.dev>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/yaahc/indenter
+++
+++Files: vendor/indexmap-*/*
+++Copyright: 2016-2019 bluss
+++ 2016-2019 Josh Stone <cuviper@gmail.com>
+++License: Apache-2.0 or MIT
+++Comment: see https://github.com/bluss/indexmap
+++
+++Files:
+++ vendor/indoc-*/*
+++Copyright: 2016-2022 David Tolnay <dtolnay@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/dtolnay/indoc
+++
+++Files: vendor/inotify-0.*/*
+++Copyright: 2014-2025 Hanno Braun <mail@hannobraun.de>
+++ 2014-2025 Félix Saparelli <me@passcod.name>
+++ 2014-2025 Cristian Kubis <cristian.kubis@tsunix.de>
+++ 2014-2025 Frank Denis <github@pureftpd.org>
+++License: ISC
+++Comment: see https://github.com/hannobraun/inotify
+++
+++Files: vendor/inotify-sys-0.*/*
+++Copyright: 2017-2021 Hanno Braun <hb@hannobraun.de>
+++License: ISC
+++Comment: see https://github.com/hannobraun/inotify-sys
+++
+++Files: vendor/intl_pluralrules-*/*
+++Copyright: 2018-2021 Kekoa Riggin <kekoariggin@gmail.com>
+++ 2018-2021 Zibi Braniecki <zbraniecki@mozilla.com>
+++License: Apache-2.0 or MIT
+++Comment: see https://github.com/zbraniecki/pluralrules
+++
+++Files: vendor/is_executable-*/*
+++Copyright: 2017-2024 Nick Fitzgerald <fitzgen@gmail.com>
+++License: Apache-2.0 or MIT
+++Comment: see https://github.com/fitzgen/is_executable
+++
+++Files: vendor/is-terminal-*/*
+++Copyright: 2022-2023 softprops <d.tangren@gmail.com>
+++ 2022-2023 Dan Gohman <dev@sunfishcode.online>
+++License: MIT
+++Comment: see https://github.com/sunfishcode/is-terminal
+++
+++Files: vendor/is_terminal_polyfill-*/*
+++Copyright: 2023-2024 Ed Page <eopage@gmail.com>
+++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 <jamslam@gmail.com>
+++License: Unlicense OR MIT
+++Comment: see https://github.com/BurntSushi/jiff
+++
+++Files: vendor/jod-thread-*/*
+++Copyright: 2019-2020 Aleksey Kladov <aleksey.kladov@gmail.com>
+++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 <freestrings@gmail.com>
+++License: MIT
+++Comment: see https://github.com/freestrings/jsonpath
+++
+++Files: vendor/kqueue-1.*/*
+++Copyright: 2016-2024 William Orr <will@worrbase.com>
+++License: MIT
+++Comment: see https://gitlab.com/rust-kqueue/rust-kqueue
+++
+++Files: vendor/kqueue-sys-1.*/*
+++Copyright: 2016-2023 William Orr <will@worrbase.com>
+++ 2016-2023 Daniel (dmilith) Dettlaff <dmilith@me.com>
+++License: MIT
+++Comment: see https://gitlab.com/rust-kqueue/rust-kqueue-sys
+++
+++Files: vendor/kstring-*/*
+++Copyright: 2014-2024 Ed Page <eopage@gmail.com>
+++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 <alex@alexcrichton.com>
+++ 2016-2020 Nikita Pekin <contact@nikitapek.in>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/indiv0/lazycell
+++
+++Files: vendor/lazy_static-*/*
+++Copyright: 2014-2018 Marvin Löbel <loebel.marvin@gmail.com>
+++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 <fitzgen@gmail.com>
+++ 2016-2022 Philip Craig <philipjcraig@gmail.com>
+++License: Apache-2.0 or MIT
+++Comment: see https://github.com/gimli-rs/leb128
+++
+++Files: vendor/lexopt-*/*
+++Copyright: 2021-2023 Jan Verbeek <jan.verbeek@posteo.nl>
+++License: MIT
+++Comment: see https://github.com/blyxxyz/lexopt
+++
+++Files: vendor/levenshtein-*/*
+++Copyright: 2016-2021 Titus Wormer <tituswormer@gmail.com>
+++License: MIT
+++Comment: see https://github.com/wooorm/levenshtein-rs
+++
+++Files: vendor/libloading-*/*
+++Copyright: 2015-2022 Simonas Kazlauskas <libloading@kazlauskas.me>
+++License: ISC
+++Comment: see https://github.com/nagisa/rust_libloading/
+++
+++Files: vendor/libm-*/*
+++Copyright: 2018-2024 Jorge Aparicio <jorge@japaric.io>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/rust-lang-nursery/libm
+++
+++Files: vendor/libssh2-sys-*/*
+++Copyright: 2014-2024 Alex Crichton <alex@alexcrichton.com>
+++ 2014-2024 Wez Furlong <wez@wezfurlong.org>
+++ 2014-2024 Matteo Bigoi <bigo@crisidev.org>
+++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 <alex@alexcrichton.com>
+++ 2014-2024 Josh Triplett <josh@joshtriplett.org>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/rust-lang/libz-sys
+++
+++Files: vendor/line-index-*/*
+++Copyright:
+++ 2024 Ariel Davis <ariel.z.davis@icloud.com>
+++ 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 <tom@hur.st>
+++License: MIT
+++Comment: see https://github.com/Freaky/rust-linereader.git
+++
+++Files: vendor/linked-hash-map-*/*
+++Copyright: 2015-2022 Stepan Koltsov <stepan.koltsov@gmail.com>
+++ 2015-2022 Andrew Paseltiner <apaseltiner@gmail.com>
+++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 <dev@sunfishcode.online>
+++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 <marwes91@gmail.com>
+++ 2016-2022 Bruno Medeiros <bruno.do.medeiros@gmail.com>
+++License: MIT
+++Comment: see https://github.com/gluon-lang/lsp-types
+++
+++Files: vendor/lz4_flex-*/*
+++Copyright: 2020-2024 Pascal Seitz <pascal.seitz@gmail.com>
+++ 2020-2024 Arthur Silva <arthurprs@gmail.com>
+++ 2020-2024 ticki <Ticki@users.noreply.github.com>
+++License: MIT
+++Comment: see https://github.com/pseitz/lz4_flex
+++
+++Files: vendor/mac-*/*
+++Copyright: 2014-2017 Jonathan Reem <jonathan.reem@gmail.com>
+++License: MIT
+++Comment:
+++ see https://github.com/reem/rust-mac.git
+++
+++Files: vendor/matchers-*/*
+++Copyright: 2019-2019 Eliza Weisman <eliza@buoyant.io>
+++License: MIT
+++Comment: see https://github.com/hawkw/matchers
+++
+++Files: vendor/maybe-async-*/*
+++Copyright: 2020-2024 Guoli Lyu <guoli-lv@hotmail.com>
+++License: MIT
+++Comment: see https://github.com/fMeow/maybe-async-rs
+++
+++Files: vendor/mdbook-*/*
+++Copyright: 2015-2017 Mathieu David <mathieudavid@mathieudavid.org>
+++License: MPL-2.0
+++Comment: see https://github.com/azerupi/mdBook
+++
+++Files: vendor/measureme-*/*
+++Copyright: 2019-2020 Wesley Wiser <wwiser@gmail.com>
+++ 2019-2020 Michael Woerister <michaelwoerister@posteo>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/rust-lang/measureme
+++
+++Files: vendor/memmap2-*/*
+++Copyright: 2015-2021 Dan Burkert <dan@danburkert.com>
+++ 2015-2021 Evgeniy Reizner <razrfalcon@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/RazrFalcon/memmap2-rs
+++
+++Files: vendor/memoffset-*/*
+++Copyright: 2017-2019 Gilad Naaman <gilad.naaman@gmail.com>
+++License: MIT
+++Comment: see https://github.com/Gilnaa/memoffset
+++
+++Files: vendor/mime-*/*
+++Copyright: 2014-2019 Sean McArthur <sean@seanmonstar.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/hyperium/mime
+++
+++Files: vendor/mime_guess-*/*
+++Copyright: 2015-2023 Austin Bonander <austin.bonander@gmail.com>
+++License: MIT
+++Comment: see https://github.com/abonander/mime_guess
+++
+++Files: vendor/minifier-*/*
+++Copyright: 2017-2018 Guillaume Gomez <guillaume1.gomez@gmail.com>
+++License: MIT
+++Comment:
+++ see https://github.com/GuillaumeGomez/minifier-rs
+++
+++Files: vendor/miniz_oxide-*/*
+++Copyright: 2017-2020 Frommi <daniil.liferenko@gmail.com>
+++License: MIT
+++Comment: see https://github.com/Frommi/miniz_oxide
+++
+++Files: vendor/mio-0.*/*
+++Copyright: 2014-2024 Carl Lerche <me@carllerche.com>
+++ 2014-2024 Thomas de Zeeuw <thomasdezeeuw@gmail.com>
+++ 2014-2024 Tokio Contributors <team@tokio.rs>
+++License: MIT
+++Comment: see https://github.com/tokio-rs/mio
+++
+++Files: vendor/new_debug_unreachable-*/*
+++Copyright: 2014-2018 Matt Brubeck <mbrubeck@limpet.net>
+++ 2014-2018 Jonathan Reem <jonathan.reem@gmail.com>
+++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 <admin@parity.io>
+++License: Apache-2.0 OR MIT
+++Comment: see https://github.com/paritytech/nohash-hasher
+++
+++Files: vendor/normalize-line-endings-*/*
+++Copyright: 2016-2018 Richard Dodd <richdodj@gmail.com>
+++License: Apache-2.0
+++Comment: see https://github.com/derekdreery/normalize-line-endings
+++
+++Files: vendor/notify-6.*/*
+++Copyright: 2014-2025 Félix Saparelli <me@passcod.name>
+++ 2014-2025 Daniel Faust <hessijames@gmail.com>
+++ 2014-2025 Aron Heinecke <Ox0p54r36@t-online.de>
+++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) <ryan.havvy@gmail.com>
+++ 2014-2024 Josh Triplett <josh@joshtriplett.org>
+++ 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 <open-source@jhpratt.dev>
+++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) <ryan.havvy@gmail.com>
+++ 2014-2023 Josh Triplett <josh@joshtriplett.org>
+++ 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 <sean.monstar@gmail.com>
+++License: MIT
+++Comment: see https://github.com/seanmonstar/num_cpus
+++
+++Files: vendor/number_prefix-*/*
+++Copyright: 2014-2020 Benjamin Sago <ogham@bsago.me>
+++License: MIT
+++Comment: see https://github.com/ogham/rust-number-prefix
+++
+++Files:
+++ vendor/object-*/*
+++ vendor/object-0.*/*
+++Copyright:
+++ 2016-2020 Nick Fitzgerald <fitzgen@gmail.com>
+++ 2016-2020 Philip Craig <philipjcraig@gmail.com>
+++License: Apache-2.0 or MIT
+++Comment: see https://github.com/gimli-rs/object
+++
+++Files: vendor/odht-*/*
+++Copyright: 2021 Michael Woerister <michaelwoerister@posteo>
+++License: Apache-2.0 or MIT
+++Comment: see https://github.com/rust-lang/odht
+++
+++Files: vendor/once_cell-*/*
+++Copyright: 2018-2019 Aleksey Kladov <aleksey.kladov@gmail.com>
+++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 <will@willspeak.me>
+++ 2015-2023 Ivan Ivashchenko <defuz@me.com>
+++License: MIT
+++Comment: see http://github.com/iwillspeak/rust-onig
+++
+++Files: vendor/oorandom-*/*
+++Copyright: 2019-2021 Simon Heath <icefox@dreamquest.io>
+++License: MIT
+++Comment: see https://sr.ht/~icefox/oorandom/
+++
+++Files:
+++ vendor/opener-*/*
+++ vendor/opener-0.*/*
+++Copyright: 2018-2024 Brian Bowman <seeker14491@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/Seeker14491/opener
+++
+++Files: vendor/openssl-*/*
+++Copyright: 2011-2024 Steven Fackler <sfackler@gmail.com>
+++License: Apache-2.0
+++Comment: see https://github.com/sfackler/rust-openssl
+++
+++Files: vendor/openssl-macros-*/*
+++Copyright: 2022-2024 Steven Fackler <sfackler@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/sfackler/rust-openssl
+++
+++Files: vendor/openssl-probe-*/*
+++Copyright: 2016-2022 Alex Crichton <alex@alexcrichton.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/sfackler/rust-openssl
+++
+++Files: vendor/openssl-sys-*/*
+++Copyright: 2011-2024 Alex Crichton <alex@alexcrichton.com>
+++ 2011-2024 Steven Fackler <sfackler@gmail.com>
+++License: MIT
+++Comment: see https://github.com/sfackler/rust-openssl
+++
+++Files: vendor/option-ext-*/*
+++Copyright: 2022-2023 Simon Ochsenreither <simon@ochsenreither.de>
+++License: MPL-2.0
+++Comment: see https://github.com/soc/option-ext.git
+++
+++Files: vendor/ordered-float-*/*
+++Copyright: 2014-2024 Jonathan Reem <jonathan.reem@gmail.com>
+++ 2014-2024 Matt Brubeck <mbrubeck@limpet.net>
+++License: MIT
+++Comment: see https://github.com/reem/rust-ordered-float
+++
+++Files: vendor/orion-*/*
+++Copyright: 2018-2024 brycx <brycx@protonmail.com>
+++License: MIT
+++Comment: see https://github.com/orion-rs/orion
+++
+++Files: vendor/os_info-*/*
+++Copyright: 2015-2024 Jan Schulte <hello@unexpected-co.de>
+++ 2015-2024 Stanislav Tkach <stanislav.tkach@gmail.com>
+++License: MIT
+++Comment: see https://github.com/stanislav-tkach/os_info
+++
+++Files: vendor/overload-*/*
+++Copyright: 2019-2022 Daniel Salvadori <danaugrs@gmail.com>
+++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 <amanieu@gmail.com>
+++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 <ogham@bsago.me>
+++License: MIT
+++
+++Files: vendor/papergrid-*/*
+++Copyright: 2020-2024 Maxim Zhiburt <zhiburt@gmail.com>
+++License: MIT
+++Comment: see https://github.com/zhiburt/tabled
+++
+++Files:
+++ vendor/partial_ref-*/*
+++ vendor/partial_ref_derive-*/*
+++Copyright: 2018-2021 Jannis Harder <me@jix.one>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/jix/partial_ref
+++
+++Files: vendor/pasetors-*/*
+++Copyright: 2020-2024 brycx <brycx@protonmail.com>
+++License: MIT
+++Comment: see https://github.com/brycx/pasetors
+++
+++Files: vendor/pathdiff-*/*
+++Copyright: 2017-2020 Manish Goregaokar <manishsmail@gmail.com>
+++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 <jimb@red-bean.com>
+++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 <dragostiselice@gmail.com>
+++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 <sfackler@gmail.com>
+++License: MIT
+++Comment: see https://github.com/sfackler/rust-phf
+++
+++Files: vendor/pin-project-lite-*/*
+++Copyright: 2018-2021 Taiki Endo <te316e89@gmail.com>
+++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 <haohou302@gmail.com>
+++License: MIT
+++Comment: see https://github.com/plotters-rs/plotters
+++
+++Files: vendor/polib-*/*
+++Copyright: 2022-2024 Brett Dong <brett.browning.dong@gmail.com>
+++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 <jacob@jhpratt.dev>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/jhpratt/powerfmt
+++
+++Files: vendor/precomputed-hash-*/*
+++Copyright: 2017-2017 Emilio Cobos Álvarez <emilio@crisal.io>
+++License: MIT
+++Comment: see https://github.com/emilio/precomputed-hash
+++
+++Files: vendor/pretty_assertions-*/*
+++Copyright: 2017-2022 Colin Kiegel <kiegel@gmx.de>
+++ 2017-2022 Florent Fayolle <florent.fayolle69@gmail.com>
+++ 2017-2022 Tom Milligan <code@tommilligan.net>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/colin-kiegel/rust-pretty-assertions
+++
+++Files: vendor/prettydiff-*/*
+++Copyright: 2019-2024 Roman Koblov <penpen938@me.com>
+++License: MIT
+++Comment: see https://github.com/romankoblov/prettydiff
+++
+++Files: vendor/proc-macro-hack-*/*
+++Copyright: 2016-2022 David Tolnay <dtolnay@gmail.com>
+++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 <felix@passcod.name>
+++License: Apache-2.0 OR MIT
+++Comment: see https://github.com/watchexec/process-wrap
+++
+++Files: vendor/prodash-*/*
+++Copyright: 2020-2023 Sebastian Thiel <sebastian.thiel@icloud.com>
+++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 <stepan.koltsov@gmail.com>
+++License: MIT
+++Comment: see https://github.com/stepancheg/rust-protobuf/
+++
+++Files: vendor/psm-*/*
+++Copyright: 2015-2020 Simonas Kazlauskas <git@kazlauskas.me>
+++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 <raph@google.com>
+++License: MIT
+++Comment: see https://github.com/google/pulldown-cmark
+++
+++Files: vendor/punycode-*/*
+++Copyright: 2015-2019 mcarton <cartonmartin+git@gmail.com>
+++License: MIT
+++Comment: see https://github.com/mcarton/rust-punycode.git
+++
+++Files: vendor/quickcheck-0.4.1/*
+++Copyright: 2014-2023 Andrew Gallant <jamslam@gmail.com>
+++License: Unlicense or MIT
+++Comment: see https://github.com/BurntSushi/quickcheck
+++
+++Files: vendor/quick-error-*/*
+++Copyright:
+++ 2015-2023 Paul Colomiets <paul@colomiets.name>
+++ 2015-2023 Colin Kiegel <kiegel@gmx.de>
+++License: MIT or Apache-2.0
+++Comment: see http://github.com/tailhook/quick-error
+++
+++Files: vendor/quine-mc_cluskey-*/*
+++Copyright: 2016-2016 Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
+++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 <niko@alum.mit.edu>
+++ 2014-2018 Josh Stone <cuviper@gmail.com>
+++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 <david.rheinsberg@gmail.com>
+++ 2018-2024 Tom Gundersen <teg@jklm.no>
+++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 <david.rheinsberg@gmail.com>
+++ 2018-2022 Tom Gundersen <teg@jklm.no>
+++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 <goyox86@gmail.com>
+++ 2017-2021 Wesley Hershberger <mggmugginsmc@gmail.com>
+++License: MIT
+++Comment: see https://gitlab.redox-os.org/redox-os/users
+++
+++Files: vendor/redox_syscall-*/*
+++Copyright: 2016-2021 Jeremy Soller <jackpot51@gmail.com>
+++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 <jamslam@gmail.com>
+++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 <aleksey.kladov@gmail.com>
+++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 <dirkjan@ochtman.nl>
+++ 2015-2021 Marvin Löbel <loebel.marvin@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/Kimundi/rustc-version-rs
+++
+++Files: vendor/rustfix-*/*
+++Copyright:
+++ 2016-2021 Pascal Hertleif <killercup@gmail.com>
+++ 2016-2021 Oliver Schneider <oli-obk@users.noreply.github.com>
+++License: Apache-2.0 or MIT
+++Comment: see https://github.com/killercup/rustfix
+++
+++Files: vendor/rustix-*/*
+++Copyright: 2020-2023 Dan Gohman <dev@sunfishcode.online>
+++ 2020-2023 Jakub Konka <kubkon@jakubkonka.com>
+++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 <dtolnay@gmail.com>
+++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 <moritz.borcherding@web.de>
+++License: MIT
+++Comment: see https://github.com/KillingSpark/zstd-rs
+++
+++Files: vendor/ryu-*/*
+++Copyright: 2018-2018 David Tolnay <dtolnay@gmail.com>
+++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 <gesau@hotmail.co.uk>
+++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 <lukas.bergdoll@gmail.com>
+++License: Apache-2.0
+++Comment: see https://github.com/Voultapher/self_cell
+++
+++Files: vendor/semver-*/*
+++Copyright:
+++ 2014-2020 Steve Klabnik <steve@steveklabnik.com>
+++ 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 <erick.tryzelaar@gmail.com>
+++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 <erick.tryzelaar@gmail.com>
+++ 2016-2024 David Tolnay <dtolnay@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/serde-rs/serde
+++
+++Files: vendor/serde_ignored-*/*
+++Copyright: 2017-2024 David Tolnay <dtolnay@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/dtolnay/serde-ignored
+++
+++Files: vendor/serde_repr-*/*
+++Copyright: 2019-2022 David Tolnay <dtolnay@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/dtolnay/serde-repr
+++
+++Files: vendor/serde_spanned-*/*
+++Copyright:
+++ 2014-2023 Alex Crichton <alex@alexcrichton.com>
+++ 2023 Ed Page <eopage@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/toml-rs/toml
+++
+++Files: vendor/serde-untagged-*/*
+++Copyright: 2023-2024 David Tolnay <dtolnay@gmail.com>
+++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 <armin.ronacher@active-4.com>
+++License: BSD-3-Clause
+++Comment: see https://github.com/mitsuhiko/sha1-smol
+++
+++Files: vendor/sharded-slab-*/*
+++Copyright: 2019-2020 Eliza Weisman <eliza@buoyant.io>
+++License: MIT
+++Comment: see https://github.com/hawkw/sharded-slab
+++
+++Files: vendor/shell-escape-*/*
+++Copyright: 2016-2020 Steven Fackler <sfackler@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/sfackler/shell-escape
+++
+++Files: vendor/shell-words-*/*
+++Copyright: 2018-2022 Tomasz Miąsko <tomasz.miasko@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/tmiasko/shell-words
+++
+++Files: vendor/shlex-*/*
+++Copyright: 2015-2015 comex <comexk@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/comex/rust-shlex
+++
+++Files: vendor/similar-*/*
+++Copyright: 2021-2024 Armin Ronacher <armin.ronacher@active-4.com>
+++ 2021-2024 Pierre-Étienne Meunier <pe@pijul.org>
+++ 2021-2024 Brandon Williams <bwilliams.eng@gmail.com>
+++License: Apache-2.0
+++Comment: see https://github.com/mitsuhiko/similar
+++
+++Files: vendor/siphasher-*/*
+++Copyright: 2016-2018 Frank Denis <github@pureftpd.org>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/jedisct1/rust-siphash
+++
+++Files: vendor/sized-chunks-*/*
+++Copyright: 2019-2022 Bodil Stokke <bodil@bodil.org>
+++License: MPL-2.0+
+++Comment: see https://github.com/bodil/sized-chunks
+++
+++Files: vendor/smallvec-*/*
+++Copyright: 2015-2020 Simon Sapin <simon.sapin@exyr.org>
+++License: MPL-2.0
+++Comment: see https://github.com/servo/rust-smallvec
+++
+++Files: vendor/smol_str-*/*
+++Copyright: 2018-2022 Aleksey Kladov <aleksey.kladov@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/rust-analyzer/smol_str
+++
+++Files:
+++ vendor/snapbox-*/*
+++ vendor/snapbox-macros-*/*
+++Copyright: Ed Page <eopage@gmail.com> 2022
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/assert-rs/trycmd/
+++
+++Files: vendor/socket2-*/*
+++Copyright: 2017-2024 Alex Crichton <alex@alexcrichton.com>
+++ 2017-2024 Thomas de Zeeuw <thomasdezeeuw@gmail.com>
+++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 <opensource@embark-studios.com>
+++ 2019-2024 Jake Shadle <jake.shadle@embark-studios.com>
+++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 <mikko.murto@hhpartners.fi>
+++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 <n210241048576@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/storyyeller/stable_deref_trait
+++
+++Files: vendor/stacker-*/*
+++Copyright: 2015-2020 Alex Crichton <alex@alexcrichton.com>
+++ 2015-2020 Simonas Kazlauskas <git@kazlauskas.me>
+++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 <dannyguo91@gmail.com>
+++License: MIT
+++Comment: see https://github.com/dguo/strsim-rs
+++
+++Files:
+++ vendor/strum-*/*
+++ vendor/strum_macros-*/*
+++Copyright: 2017-2023 Peter Glotfelty <peter.glotfelty@microsoft.com>
+++License: MIT
+++Comment: see https://github.com/Peternator7/strum
+++
+++Files: vendor/subtle-*/*
+++Copyright: 2017-2023 Isis Lovecruft <isis@patternsinthevoid.net>
+++ 2017-2023 Henry de Valence <hdevalence@hdevalence.ca>
+++License: BSD-3-Clause
+++Comment: see https://github.com/dalek-cryptography/subtle
+++
+++Files: vendor/supports-hyperlinks-*/*
+++Copyright: 2021-2024 Kat Marchán <kzm@zkat.tech>
+++License: Apache-2.0
+++Comment: see https://github.com/zkat/supports-hyperlinks
+++
+++Files: vendor/supports-unicode-*/*
+++Copyright: 2021-2024 Kat Marchán <kzm@zkat.tech>
+++License: Apache-2.0
+++Comment: see https://github.com/zkat/supports-unicode
+++
+++Files:
+++ vendor/synstructure-*/*
+++ vendor/synstructure-0.*/*
+++Copyright:
+++ 2016-2023 Nika Layzell <nika@thelayzells.com>
+++License: MIT
+++Comment: see https://github.com/mystor/synstructure
+++
+++Files: vendor/syntect-5.*/*
+++Copyright: 2016-2024 Tristan Hume <tristan@thume.ca>
+++License: MIT
+++Comment: see https://github.com/trishume/syntect
+++
+++Files: vendor/sysinfo-*/*
+++Copyright: 2015-2022 Guillaume Gomez <guillaume1.gomez@gmail.com>
+++License: MIT
+++Comment: see https://github.com/GuillaumeGomez/sysinfo
+++
+++Files: vendor/tabled-*/*
+++Copyright: 2020-2024 Maxim Zhiburt <zhiburt@gmail.com>
+++License: MIT
+++Comment: see https://github.com/zhiburt/tabled
+++
+++Files: vendor/tempfile-*/*
+++Copyright: 2015-2018 Steven Allen <steven@stebalien.com>
+++ 2015-2018 The Rust Project Developers
+++ 2015-2018 Ashley Mannix <ashleymannix@live.com.au>
+++ 2015-2018 Jason White <jasonaw0@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/Stebalien/tempfile
+++
+++Files: vendor/tendril-*/*
+++Copyright: 2015-2017 Keegan McAllister <mcallister.keegan@gmail.com>
+++ 2015-2017 Simon Sapin <simon.sapin@exyr.org>
+++ 2015-2017 Chris Morgan <me@chrismorgan.info>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/servo/tendril
+++
+++Files: vendor/tenthash-*/*
+++Copyright: 2022-2025 Nathan Vegdahl <cessen@cessen.com>
+++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 <achin@eminence32.net>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/eminence/terminal-size
+++
+++Files: vendor/termize-*/*
+++Copyright: 2016-2020 Yuki Okushi <huyuumi.dev@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/JohnTitor/termize
+++
+++Files: vendor/text-size-*/*
+++Copyright: 2018-2021 Aleksey Kladov <aleksey.kladov@gmail.com>
+++ 2018-2021 Christopher Durham (CAD97) <cad97@cad97.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/rust-analyzer/text-size
+++
+++Files: vendor/textwrap-0.*/*
+++Copyright: 2016-2024 Martin Geisler <martin@geisler.net>
+++License: MIT
+++Comment: see https://github.com/mgeisler/textwrap
+++
+++Files: vendor/thin-vec-*/*
+++Copyright: 2017-2022 Aria Beingessner <a.beingessner@gmail.com>
+++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 <dtolnay@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/dtolnay/thiserror
+++
+++Files: vendor/thorin-dwp-*/*
+++Copyright: 2021-2022 David Wood <david.wood@huawei.com>
+++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 <coreyf@rwell.org>
+++ 2015-2021 Stefan Schindler <dns2utf8@estada.ch>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/rust-threadpool/rust-threadpool
+++
+++Files: vendor/time-macros-*/*
+++Copyright: 2019-2024 Jacob Pratt <open-source@jhpratt.dev>
+++ 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 <raph.levien@gmail.com>
+++ 2019-2022 Zibi Braniecki <zibi@braniecki.net>
+++License: Apache-2.0 or MIT
+++Comment: see https://github.com/zbraniecki/tinystr
+++
+++Files: vendor/tinytemplate-*/*
+++Copyright: 2018-2022 Brook Heisler <brookheisler@gmail.com>
+++License: Apache-2.0 OR MIT
+++Comment: see https://github.com/bheisler/TinyTemplate
+++
+++Files: vendor/tinyvec-*/*
+++Copyright: 2020 Lokathor <zefria@gmail.com>
+++License: Zlib
+++Comment: see https://github.com/Lokathor/tinyvec
+++
+++Files: vendor/tinyvec_macros-*/*
+++Copyright: 2020 Soveu <marx.tomasz@gmail.com>
+++License: MIT or Apache-2.0 or Zlib
+++Comment: see https://github.com/Soveu/tinyvec_macros
+++
+++Files: vendor/topological-sort-*/*
+++Copyright: 2015-2018 gifnksm <makoto.nksm+github@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/gifnksm/topological-sort-rs
+++
+++Files: vendor/toml-*/*
+++Copyright: 2014-2024 Alex Crichton <alex@alexcrichton.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/toml-rs/toml
+++
+++Files: vendor/toml_datetime-*/*
+++Copyright: 2014-2024 Alex Crichton <alex@alexcrichton.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/toml-rs/toml
+++
+++Files: vendor/toml_edit-*/*
+++Copyright: 2014-2024 Andronik Ordian <write@reusable.software>
+++ 2014-2024 Ed Page <eopage@gmail.com>
+++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 <dbarsky@amazon.com>
+++ 2018-2024 Eliza Weisman <eliza@buoyant.io>
+++ 2018-2024 Jane Lusby <jlusby@yaah.dev>
+++ 2018-2024 Tokio Contributors <team@tokio.rs>
+++License: MIT
+++Comment: see https://github.com/tokio-rs/tracing
+++
+++Files: vendor/tracing-chrome-*/*
+++Copyright: 2020-2024 Thoren Paulson <thoren.paulson@gmail.com>
+++License: MIT
+++Comment: see https://github.com/thoren-d/tracing-chrome
+++
+++Files: vendor/tracing-tree-0.*/*
+++Copyright: 2020-2020 David Barsky <me@davidbarsky.com>
+++ 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 <jake.goulding@gmail.com>
+++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 <dtolnay@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/dtolnay/typeid
+++
+++Files: vendor/type-map-*/*
+++Copyright: 2019-2022 Jacob Brown <kardeiz@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/kardeiz/type-map
+++
+++Files: vendor/typenum-*/*
+++Copyright: 2015-2019 Paho Lurie-Gregg <paho@paholg.com>
+++ 2015-2019 Andre Bogus <bogusandre@gmail.com>
+++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 <laumann.thomas@gmail.com>
+++ 2015-2024 Manish Goregaokar <manishsmail@gmail.com>
+++ 2022-2024 Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
+++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 <cameron.studdstreet@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/cameron1024/unarray
+++
+++Files: vendor/unicode-bom-*/*
+++Copyright: 2018-2023 Phil Booth <pmbooth@gmail.com>
+++License: Apache-2.0
+++Comment: see https://gitlab.com/philbooth/unicode-bom
+++
+++Files: vendor/unicode-properties-*/*
+++Copyright: 2022-2024 Charles Lew <crlf0710@gmail.com>
+++ 2022-2024 Manish Goregaokar <manishsmail@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/unicode-rs/unicode-properties
+++
+++Files: vendor/unwinding-*/*
+++Copyright: 2021-2024 Gary Guo <gary@garyguo.net>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/nbdd0121/unwinding/
+++
+++Files: vendor/utf16_iter-*/*
+++Copyright: 2022-2023 Henri Sivonen <hsivonen@hsivonen.fi>
+++License: Apache-2.0 OR MIT
+++Comment: see https://github.com/hsivonen/utf16_iter
+++
+++Files: vendor/utf8_iter-*/*
+++Copyright: 2022-2023 Henri Sivonen <hsivonen@hsivonen.fi>
+++License: Apache-2.0 OR MIT
+++Comment: see https://github.com/hsivonen/utf8_iter
+++
+++Files: vendor/utf8-width-*/*
+++Copyright: 2020-2023 Magic Len <len@magiclen.org>
+++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 <me@jix.one>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/jix/varisat
+++
+++Files: vendor/vcpkg-*/*
+++Copyright: 2017-2024 Jim McGrath <jimmc2@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/mcgoo/vcpkg-rs
+++
+++Files: vendor/vec_mut_scan-*/*
+++Copyright: 2019-2023 Jannis Harder <me@jix.one>
+++License: 0BSD
+++Comment: see https://github.com/jix/vec_mut_scan
+++
+++Files: vendor/version_check-*/*
+++Copyright: 2017-2019 Sergio Benitez <sb@sergio.bz>
+++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 <jamslam@gmail.com>
+++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 <aleksey.kladov@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/matklad/ungrammar
+++
+++Files: vendor/unicase-*/*
+++Copyright: 2014-2019 Sean McArthur <sean@seanmonstar.com>
+++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 <kwantam@gmail.com>
+++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 <erick.tryzelaar@gmail.com>
+++ 2015-2017 kwantam <kwantam@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/unicode-rs/unicode-xid
+++
+++Files: vendor/unicode-script-*/*
+++Copyright: 2017-2020 Manish Goregaokar <manishsmail@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/unicode-rs/unicode-script
+++
+++Files: vendor/unicode-security-*/*
+++Copyright: 2020-2020 Charles Lew <crlf0710@gmail.com>
+++ 2020-2020 Manish Goregaokar <manishsmail@gmail.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/unicode-rs/unicode-security
+++
+++Files: vendor/unified-diff-*/*
+++Copyright: 2021-2021 Michael Howell <michael@notriddle.com>
+++ 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 <simon.sapin@exyr.org>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/SimonSapin/rust-utf8
+++
+++Files: vendor/utf8parse-*/*
+++Copyright: 2016-2023 Joe Wilm <joe@jwilm.com>
+++ 2016-2023 Christian Duerr <contact@christianduerr.com>
+++License: Apache-2.0 OR MIT
+++Comment: see https://github.com/alacritty/vte
+++
+++Files: vendor/uuid-*/*
+++Copyright: 2014-2023 Ashley Mannix<ashleymannix@live.com.au>
+++ 2014-2023 Christopher Armstrong
+++ 2014-2023 Dylan DPC<dylan.dpc@gmail.com>
+++ 2014-2023 Hunar Roop Kahlon<hunar.roop@gmail.com>
+++License: Apache-2.0 OR MIT
+++Comment: see https://github.com/uuid-rs/uuid
+++
+++Files: vendor/wait-timeout-*/*
+++Copyright: 2015-2021 Alex Crichton <alex@alexcrichton.com>
+++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 <fitzgen@gmail.com>
+++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 <alex@alexcrichton.com>
+++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 <ydelendik@mozilla.com>
+++ 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 <contact@geoffroycouprie.com>
+++License: MIT
+++Comment: see https://github.com/winnow-rs/winnow
+++
+++Files: vendor/xattr-*/*
+++Copyright: 2015-2017 Steven Allen <steven@stebalien.com>
+++License: MIT or Apache-2.0
+++Comment: see https://github.com/Stebalien/xattr
+++
+++Files: vendor/yansi-*/*
+++Copyright: 2017-2022 Sergio Benitez <sb@sergio.bz>
+++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) <ryan.havvy@gmail.com>
+++ 2014-2020 Josh Triplett <josh@joshtriplett.org>
+++ 2014-2020 Juan Aguilar Santillana <mhpoin@gmail.com>
+++License: MIT
+++Comment: see https://github.com/botika/yansi-term
+++
+++Files:
+++ vendor/zerocopy-*/*
+++ vendor/zerocopy-derive-*/*
+++Copyright: 2019-2024 Joshua Liebow-Feeser <joshlf@google.com>
+++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 <me@carllerche.com>
+++ 2015-2022 Sean McArthur <sean@seanmonstar.com>
+++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 <alex@alexcrichton.com>
+++ 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 <ahuszagh@gmail.com>
+++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 <mail@josefbrandl.de>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/rust-lang-nursery/pin-utils
+++
+++Files: vendor/slab-*/*
+++Copyright: 2015-2022 Carl Lerche <me@carllerche.com>
+++License: MIT
+++Comment: see https://github.com/carllerche/slab
+++
+++Files: vendor/tokio-*/*
+++Copyright: 2016-2022 Tokio Contributors <team@tokio.rs>
+++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 <hsivonen@hsivonen.fi>
+++License: Apache-2.0 OR MIT
+++Comment: see https://github.com/hsivonen/write16
+++
+++Files: vendor/write-json-*/*
+++Copyright: 2020-2020 Aleksey Kladov <aleksey.kladov@gmail.com>
+++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 <aleksey.kladov@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/matklad/xflags
+++
+++Files:
+++ vendor/xshell-*/*
+++ vendor/xshell-macros-*/*
+++Copyright: 2020-2022 Aleksey Kladov <aleksey.kladov@gmail.com>
+++License: MIT OR Apache-2.0
+++Comment: see https://github.com/matklad/xshell
+++
+++Files: vendor/zip-*/*
+++Copyright: 2014-2023 Mathijs van de Nes <git@mathijs.vd-nes.nl>
+++ 2014-2023 Marli Frost <marli@frost.red>
+++ 2014-2023 Ryan Levick <ryan.levick@gmail.com>
+++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 <pkg-rust-maintainers@alioth-lists.debian.net>
+++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 <http://unlicense.org/>
+++
+++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 <https://www.unicode.org/copyright.html>
+++ 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.
+++
--- /dev/null
--- /dev/null
--- /dev/null
+++README.md
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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> <patch-file>"; 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"
--- /dev/null
--- /dev/null
--- /dev/null
+++[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
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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)
--- /dev/null
--- /dev/null
--- /dev/null
+++usr/lib/${DEB_HOST_MULTIARCH}/
--- /dev/null
--- /dev/null
--- /dev/null
+++# "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
--- /dev/null
--- /dev/null
--- /dev/null
+++# normally added by dh_makeshlibs, but fails for our versioning scheme
+++activate-noawait ldconfig
--- /dev/null
--- /dev/null
--- /dev/null
+++usr/lib/rustlib/wasm32-*/lib/
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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 *
--- /dev/null
--- /dev/null
--- /dev/null
+++usr/lib/rustlib/${env:WINDOWS_ARCH}-pc-windows-gnu/lib/
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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]
--- /dev/null
--- /dev/null
--- /dev/null
+++usr/lib/rustlib/${env:DEB_HOST_RUST_TYPE}/lib/
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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(*)
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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 <<eof
+++================================================================================
+++orig-stage0 bootstrapping tarball created in ../rustc_${upstream_version}.orig-stage0.tar.xz
+++containing the upstream compilers for $upstream_bootstrap_arch
+++
+++You *probably* now want to do the following steps:
+++
+++1. Add [$(echo $upstream_bootstrap_arch | sed -e 's/\S*/!\0/g')] to the rustc/cargo Build-Depends in d/control
+++2. Update d/changelog
+++3. Run \`dpkg-source -b .\` to generate a .dsc that includes this tarball.
+++================================================================================
+++eof
--- /dev/null
--- /dev/null
--- /dev/null
+++/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript */
+++var _self = (typeof window !== 'undefined')
+++ ? window // if in browser
+++ : (
+++ (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope)
+++ ? self // if in worker
+++ : {} // if in node js
+++ );
+++
+++/**
+++ * Prism: Lightweight, robust, elegant syntax highlighting
+++ * MIT license http://www.opensource.org/licenses/mit-license.php/
+++ * @author Lea Verou http://lea.verou.me
+++ */
+++
+++var Prism = (function(){
+++
+++// Private helper vars
+++var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i;
+++
+++var _ = _self.Prism = {
+++ util: {
+++ encode: function (tokens) {
+++ if (tokens instanceof Token) {
+++ return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias);
+++ } else if (_.util.type(tokens) === 'Array') {
+++ return tokens.map(_.util.encode);
+++ } else {
+++ return tokens.replace(/&/g, '&').replace(/</g, '<').replace(/\u00a0/g, ' ');
+++ }
+++ },
+++
+++ type: function (o) {
+++ return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1];
+++ },
+++
+++ // Deep clone a language definition (e.g. to extend it)
+++ clone: function (o) {
+++ var type = _.util.type(o);
+++
+++ switch (type) {
+++ case 'Object':
+++ var clone = {};
+++
+++ for (var key in o) {
+++ if (o.hasOwnProperty(key)) {
+++ clone[key] = _.util.clone(o[key]);
+++ }
+++ }
+++
+++ return clone;
+++
+++ case 'Array':
+++ // Check for existence for IE8
+++ return o.map && o.map(function(v) { return _.util.clone(v); });
+++ }
+++
+++ return o;
+++ }
+++ },
+++
+++ languages: {
+++ extend: function (id, redef) {
+++ var lang = _.util.clone(_.languages[id]);
+++
+++ for (var key in redef) {
+++ lang[key] = redef[key];
+++ }
+++
+++ return lang;
+++ },
+++
+++ /**
+++ * Insert a token before another token in a language literal
+++ * As this needs to recreate the object (we cannot actually insert before keys in object literals),
+++ * we cannot just provide an object, we need anobject and a key.
+++ * @param inside The key (or language id) of the parent
+++ * @param before The key to insert before. If not provided, the function appends instead.
+++ * @param insert Object with the key/value pairs to insert
+++ * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted.
+++ */
+++ insertBefore: function (inside, before, insert, root) {
+++ root = root || _.languages;
+++ var grammar = root[inside];
+++
+++ if (arguments.length == 2) {
+++ insert = arguments[1];
+++
+++ for (var newToken in insert) {
+++ if (insert.hasOwnProperty(newToken)) {
+++ grammar[newToken] = insert[newToken];
+++ }
+++ }
+++
+++ return grammar;
+++ }
+++
+++ var ret = {};
+++
+++ for (var token in grammar) {
+++
+++ if (grammar.hasOwnProperty(token)) {
+++
+++ if (token == before) {
+++
+++ for (var newToken in insert) {
+++
+++ if (insert.hasOwnProperty(newToken)) {
+++ ret[newToken] = insert[newToken];
+++ }
+++ }
+++ }
+++
+++ ret[token] = grammar[token];
+++ }
+++ }
+++
+++ // Update references in other language definitions
+++ _.languages.DFS(_.languages, function(key, value) {
+++ if (value === root[inside] && key != inside) {
+++ this[key] = ret;
+++ }
+++ });
+++
+++ return root[inside] = ret;
+++ },
+++
+++ // Traverse a language definition with Depth First Search
+++ DFS: function(o, callback, type) {
+++ for (var i in o) {
+++ if (o.hasOwnProperty(i)) {
+++ callback.call(o, i, o[i], type || i);
+++
+++ if (_.util.type(o[i]) === 'Object') {
+++ _.languages.DFS(o[i], callback);
+++ }
+++ else if (_.util.type(o[i]) === 'Array') {
+++ _.languages.DFS(o[i], callback, i);
+++ }
+++ }
+++ }
+++ }
+++ },
+++
+++ highlightAll: function(async, callback) {
+++ var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');
+++
+++ for (var i=0, element; element = elements[i++];) {
+++ _.highlightElement(element, async === true, callback);
+++ }
+++ },
+++
+++ highlightElement: function(element, async, callback) {
+++ // Find language
+++ var language, grammar, parent = element;
+++
+++ while (parent && !lang.test(parent.className)) {
+++ parent = parent.parentNode;
+++ }
+++
+++ if (parent) {
+++ language = (parent.className.match(lang) || [,''])[1];
+++ grammar = _.languages[language];
+++ }
+++
+++ // Set language on the element, if not present
+++ element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
+++
+++ // Set language on the parent, for styling
+++ parent = element.parentNode;
+++
+++ if (/pre/i.test(parent.nodeName)) {
+++ parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
+++ }
+++
+++ if (!grammar) {
+++ return;
+++ }
+++
+++ var code = element.textContent;
+++
+++ if(!code) {
+++ return;
+++ }
+++
+++ code = code.replace(/^(?:\r?\n|\r)/,'');
+++
+++ var env = {
+++ element: element,
+++ language: language,
+++ grammar: grammar,
+++ code: code
+++ };
+++
+++ _.hooks.run('before-highlight', env);
+++
+++ if (async && _self.Worker) {
+++ var worker = new Worker(_.filename);
+++
+++ worker.onmessage = function(evt) {
+++ env.highlightedCode = Token.stringify(JSON.parse(evt.data), language);
+++
+++ _.hooks.run('before-insert', env);
+++
+++ env.element.innerHTML = env.highlightedCode;
+++
+++ callback && callback.call(env.element);
+++ _.hooks.run('after-highlight', env);
+++ };
+++
+++ worker.postMessage(JSON.stringify({
+++ language: env.language,
+++ code: env.code
+++ }));
+++ }
+++ else {
+++ env.highlightedCode = _.highlight(env.code, env.grammar, env.language);
+++
+++ _.hooks.run('before-insert', env);
+++
+++ env.element.innerHTML = env.highlightedCode;
+++
+++ callback && callback.call(element);
+++
+++ _.hooks.run('after-highlight', env);
+++ }
+++ },
+++
+++ highlight: function (text, grammar, language) {
+++ var tokens = _.tokenize(text, grammar);
+++ return Token.stringify(_.util.encode(tokens), language);
+++ },
+++
+++ tokenize: function(text, grammar, language) {
+++ var Token = _.Token;
+++
+++ var strarr = [text];
+++
+++ var rest = grammar.rest;
+++
+++ if (rest) {
+++ for (var token in rest) {
+++ grammar[token] = rest[token];
+++ }
+++
+++ delete grammar.rest;
+++ }
+++
+++ tokenloop: for (var token in grammar) {
+++ if(!grammar.hasOwnProperty(token) || !grammar[token]) {
+++ continue;
+++ }
+++
+++ var patterns = grammar[token];
+++ patterns = (_.util.type(patterns) === "Array") ? patterns : [patterns];
+++
+++ for (var j = 0; j < patterns.length; ++j) {
+++ var pattern = patterns[j],
+++ inside = pattern.inside,
+++ lookbehind = !!pattern.lookbehind,
+++ lookbehindLength = 0,
+++ alias = pattern.alias;
+++
+++ pattern = pattern.pattern || pattern;
+++
+++ for (var i=0; i<strarr.length; i++) { // Don’t cache length as it changes during the loop
+++
+++ var str = strarr[i];
+++
+++ if (strarr.length > 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 + '</' + env.tag + '>';
+++
+++};
+++
+++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': /<!--[\w\W]*?-->/,
+++ 'prolog': /<\?[\w\W]+?\?>/,
+++ 'doctype': /<!DOCTYPE[\w\W]+?>/,
+++ 'cdata': /<!\[CDATA\[[\w\W]*?]]>/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: /<style[\w\W]*?>[\w\W]*?<\/style>/i,
+++ inside: {
+++ 'tag': {
+++ pattern: /<style[\w\W]*?>|<\/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: /<script[\w\W]*?>[\w\W]*?<\/script>/i,
+++ inside: {
+++ 'tag': {
+++ pattern: /<script[\w\W]*?>|<\/script>/i,
+++ inside: Prism.languages.markup.tag.inside
+++ },
+++ rest: Prism.languages.javascript
+++ },
+++ alias: 'language-javascript'
+++ }
+++ });
+++}
+++;
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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
--- /dev/null
--- /dev/null
--- /dev/null
+++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 = []
--- /dev/null
--- /dev/null
--- /dev/null
+++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 <infinity0@debian.org>
+++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"),
--- /dev/null
--- /dev/null
--- /dev/null
+++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 <infinity0@debian.org>
+++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::<Vec<_>>();
++++ v.clear();
+++ assert_eq!(
+++- addrs.iter().filter(|&(_, &v)| v > 1).collect::<Vec<_>>(),
++++ v,
+++ vec![],
+++ "There should be no duplicate localhost entries"
+++ );
--- /dev/null
--- /dev/null
--- /dev/null
+++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();
+++
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Angus Lees <gus@debian.org>
+++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')"
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Angus Lees <gus@debian.org>
+++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-17
+++ if [ -f "$RUST_LLDB" ]; then
+++ lldb="$RUST_LLDB"
+++ else
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Angus Lees <gus@debian.org>
+++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()
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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);
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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");
--- /dev/null
--- /dev/null
--- /dev/null
+++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
+++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 <f.gruenbichler@proxmox.com>
+++---
+++ 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<Library, libloading::Error> {
+++
+++ #[cfg(unix)]
+++ fn load_library(file: &Utf8Path) -> Result<Library, libloading::Error> {
++++ // 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()) }
+++ }
--- /dev/null
--- /dev/null
--- /dev/null
+++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
+++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 <f.gruenbichler@proxmox.com>
+++---
+++ 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");
+++ }
+++ }
+++ }
--- /dev/null
--- /dev/null
--- /dev/null
+++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <debian@fabian.gruenbichler.email>
+++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 <debian@fabian.gruenbichler.email>
+++---
+++ 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 {
--- /dev/null
--- /dev/null
--- /dev/null
+++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
+++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 <f.gruenbichler@proxmox.com>
+++---
+++ 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 {
--- /dev/null
--- /dev/null
--- /dev/null
+++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <git@fabian.gruenbichler.email>
+++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 <git@fabian.gruenbichler.email>
+++---
+++ 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(&[
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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 {
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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");
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Matthijs van Otterdijk <matthijs@wirevirt.net>
+++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() {
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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>()), &[dist::Rustc {
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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())
+++ }
+++ }
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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.
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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);
+++ }
+++
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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
+++
--- /dev/null
--- /dev/null
--- /dev/null
+++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <git@fabian.gruenbichler.email>
+++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 <git@fabian.gruenbichler.email>
+++---
+++ 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
+++
--- /dev/null
--- /dev/null
--- /dev/null
+++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <debian@fabian.gruenbichler.email>
+++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 <debian@fabian.gruenbichler.email>
+++---
+++ 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(
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Ximin Luo <infinity0@debian.org>
+++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<AtomicUsize>) {
+++ }
+++
+++ // 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<Mutex<u32>> = 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<Mutex<u32>> = 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<Mutex<u32>> = 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()
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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\
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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(
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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;
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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].
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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<Vec<String>> = 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 &[];
+++ }
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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<Vec<u8>, 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::Library, Error> {
+++ 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();
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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}}
+++
+++ <!-- Fonts -->
+++- <link rel="stylesheet" href="{{ path_to_root }}FontAwesome/css/font-awesome.css">
+++- {{#if copy_fonts}}
+++- <link rel="stylesheet" href="{{ path_to_root }}fonts/fonts.css">
+++- {{/if}}
++++ <link rel="stylesheet" href="{{ path_to_root }}css/font-awesome.min.css">
+++
+++ <!-- Highlight.js Stylesheets -->
+++ <link rel="stylesheet" href="{{ path_to_root }}highlight.css">
+++@@ -50,7 +47,7 @@
+++
+++ {{#if mathjax_support}}
+++ <!-- MathJax -->
+++- <script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
++++ <script async src="MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
+++ {{/if}}
+++
+++ <!-- Provide site root to javascript -->
+++@@ -63,32 +60,6 @@
+++ </head>
+++ <body>
+++ <div id="body-container">
+++- <!-- Work around some values being stored in localStorage wrapped in quotes -->
+++- <script>
+++- try {
+++- var theme = localStorage.getItem('mdbook-theme');
+++- var sidebar = localStorage.getItem('mdbook-sidebar');
+++-
+++- if (theme.startsWith('"') && theme.endsWith('"')) {
+++- localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
+++- }
+++-
+++- if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
+++- localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
+++- }
+++- } catch (e) { }
+++- </script>
+++-
+++- <!-- Set the theme before any content is loaded, prevents flash -->
+++- <script>
+++- var theme;
+++- try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
+++- if (theme === null || theme === undefined) { theme = default_theme; }
+++- const html = document.documentElement;
+++- html.classList.remove('{{ default_theme }}')
+++- html.classList.add(theme);
+++- html.classList.add("js");
+++- </script>
+++
+++ <input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
+++
+++@@ -296,54 +267,8 @@
+++ </script>
+++ {{/if}}
+++
+++- {{#if google_analytics}}
+++- <!-- Google Analytics Tag -->
+++- <script>
+++- var localAddrs = ["localhost", "127.0.0.1", ""];
+++-
+++- // make sure we don't activate google analytics if the developer is
+++- // inspecting the book locally...
+++- if (localAddrs.indexOf(document.location.hostname) === -1) {
+++- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+++- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+++- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+++- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
+++-
+++- ga('create', '{{google_analytics}}', 'auto');
+++- ga('send', 'pageview');
+++- }
+++- </script>
+++- {{/if}}
+++-
+++- {{#if playground_line_numbers}}
+++- <script>
+++- window.playground_line_numbers = true;
+++- </script>
+++- {{/if}}
+++-
+++- {{#if playground_copyable}}
+++- <script>
+++- window.playground_copyable = true;
+++- </script>
+++- {{/if}}
+++-
+++- {{#if playground_js}}
+++- <script src="{{ path_to_root }}ace.js"></script>
+++- <script src="{{ path_to_root }}editor.js"></script>
+++- <script src="{{ path_to_root }}mode-rust.js"></script>
+++- <script src="{{ path_to_root }}theme-dawn.js"></script>
+++- <script src="{{ path_to_root }}theme-tomorrow_night.js"></script>
+++- {{/if}}
+++-
+++- {{#if search_js}}
+++- <script src="{{ path_to_root }}elasticlunr.min.js"></script>
+++- <script src="{{ path_to_root }}mark.min.js"></script>
+++- <script src="{{ path_to_root }}searcher.js"></script>
+++- {{/if}}
+++-
+++- <script src="{{ path_to_root }}clipboard.min.js"></script>
+++- <script src="{{ path_to_root }}highlight.js"></script>
+++- <script src="{{ path_to_root }}book.js"></script>
++++ <script src="{{ path_to_root }}highlight.js" type="text/javascript" charset="utf-8"></script>
++++ <script src="{{ path_to_root }}book.js" type="text/javascript" charset="utf-8"></script>
+++
+++ <!-- Custom JS scripts -->
+++ {{#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}}
+++
+++ <!-- Fonts -->
+++- <link rel="stylesheet" href="{{ path_to_root }}FontAwesome/css/font-awesome.css">
+++- {{#if copy_fonts}}
+++- <link rel="stylesheet" href="{{ path_to_root }}fonts/fonts.css">
+++- {{/if}}
++++ <link rel="stylesheet" href="{{ path_to_root }}css/font-awesome.min.css">
+++
+++ <!-- Highlight.js Stylesheets -->
+++ <link rel="stylesheet" href="{{ path_to_root }}highlight.css">
+++@@ -50,7 +47,7 @@
+++
+++ {{#if mathjax_support}}
+++ <!-- MathJax -->
+++- <script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
++++ <script async src="MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
+++ {{/if}}
+++
+++ <!-- Provide site root to javascript -->
+++@@ -248,54 +245,8 @@
+++ </script>
+++ {{/if}}
+++
+++- {{#if google_analytics}}
+++- <!-- Google Analytics Tag -->
+++- <script>
+++- var localAddrs = ["localhost", "127.0.0.1", ""];
+++-
+++- // make sure we don't activate google analytics if the developer is
+++- // inspecting the book locally...
+++- if (localAddrs.indexOf(document.location.hostname) === -1) {
+++- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+++- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+++- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+++- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
+++-
+++- ga('create', '{{google_analytics}}', 'auto');
+++- ga('send', 'pageview');
+++- }
+++- </script>
+++- {{/if}}
+++-
+++- {{#if playground_line_numbers}}
+++- <script>
+++- window.playground_line_numbers = true;
+++- </script>
+++- {{/if}}
+++-
+++- {{#if playground_copyable}}
+++- <script>
+++- window.playground_copyable = true;
+++- </script>
+++- {{/if}}
+++-
+++- {{#if playground_js}}
+++- <script src="{{ path_to_root }}ace.js"></script>
+++- <script src="{{ path_to_root }}editor.js"></script>
+++- <script src="{{ path_to_root }}mode-rust.js"></script>
+++- <script src="{{ path_to_root }}theme-dawn.js"></script>
+++- <script src="{{ path_to_root }}theme-tomorrow_night.js"></script>
+++- {{/if}}
+++-
+++- {{#if search_js}}
+++- <script src="{{ path_to_root }}elasticlunr.min.js"></script>
+++- <script src="{{ path_to_root }}mark.min.js"></script>
+++- <script src="{{ path_to_root }}searcher.js"></script>
+++- {{/if}}
+++-
+++- <script src="{{ path_to_root }}clipboard.min.js"></script>
+++- <script src="{{ path_to_root }}highlight.js"></script>
+++- <script src="{{ path_to_root }}book.js"></script>
++++ <script src="{{ path_to_root }}highlight.js" type="text/javascript" charset="utf-8"></script>
++++ <script src="{{ path_to_root }}book.js" type="text/javascript" charset="utf-8"></script>
+++
+++ <!-- Custom JS scripts -->
+++ {{#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<Vec<u8>>,
+++ pub favicon_svg: Option<Vec<u8>>,
+++ pub js: Vec<u8>,
+++- pub highlight_css: Vec<u8>,
+++ pub tomorrow_night_css: Vec<u8>,
+++ pub ayu_highlight_css: Vec<u8>,
+++- pub highlight_js: Vec<u8>,
+++- pub clipboard_js: Vec<u8>,
+++ }
+++
+++ 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 @@
+++ <link rel="stylesheet" href="{{ path_to_root }}css/print.css" media="print">
+++ {{/if}}
+++ <!-- Fonts -->
+++- <link rel="stylesheet" href="{{ path_to_root }}FontAwesome/css/font-awesome.css">
++++ <link rel="stylesheet" href="{{ path_to_root }}css/font-awesome.min.css">
+++ {{#if copy_fonts}}
+++- <link rel="stylesheet" href="{{ path_to_root }}fonts/fonts.css">
+++ {{/if}}
+++ <!-- Custom theme stylesheets -->
+++ {{#each additional_css}}
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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 = [
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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 = [
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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 = []
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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"
+++
--- /dev/null
--- /dev/null
--- /dev/null
+++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
+++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 <f.gruenbichler@proxmox.com>
+++---
+++ 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"
+++
--- /dev/null
--- /dev/null
--- /dev/null
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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!(""); }
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Simon Chopin <simon.chopin@canonical.com>
+++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() {}
+++ ```
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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();
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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())));
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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 <git@fabian.gruenbichler.email>
+++---
+++ 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};
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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: TrustedLen>(_: &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: TrustedLen>(_: &I) {}
+++
++++#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
+++ #[test]
+++ fn shared_from_iter_normal() {
+++ // Exercise the base implementation for non-`TrustedLen` iterators.
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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}");
--- /dev/null
--- /dev/null
--- /dev/null
+++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <git@fabian.gruenbichler.email>
+++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 <git@fabian.gruenbichler.email>
+++---
+++ 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<dyn std::error::Error>> {
+++ }
+++
+++ 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<dyn std::error::Error>> {
+++ 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(())
--- /dev/null
--- /dev/null
--- /dev/null
+++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <git@fabian.gruenbichler.email>
+++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 <git@fabian.gruenbichler.email>
+++---
+++ 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"
--- /dev/null
--- /dev/null
--- /dev/null
+++From: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+++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);
+++ }
--- /dev/null
--- /dev/null
--- /dev/null
+++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <debian@fabian.gruenbichler.email>
+++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 <debian@fabian.gruenbichler.email>
+++---
+++ 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);
+++ }
+++
--- /dev/null
--- /dev/null
--- /dev/null
+++From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
+++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 <f.gruenbichler@proxmox.com>
+++---
+++ 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();
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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)
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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"
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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,<img src="https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test%20(bors)/badge.svg[^"]*" alt="\([^"]*\)" />,<span class="deb-privacy-replace--github.com-badge">\1</span>,g' \
+++ -e 's,<img src="https://img.shields.io/[^"]*" alt="\([^"]*\)" />,<span class="deb-privacy-replace--shields-io">\1</span>,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"
--- /dev/null
--- /dev/null
--- /dev/null
+++usr/bin/rust-analyzer
--- /dev/null
--- /dev/null
--- /dev/null
+++usr/bin/clippy-driver
+++usr/bin/cargo-clippy
--- /dev/null
--- /dev/null
--- /dev/null
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++debian/tmp/usr/share/doc/docs/html
--- /dev/null
--- /dev/null
--- /dev/null
+++debian/icons/rust-logo-32x32-blk.png usr/share/doc/rust-doc/html/
--- /dev/null
--- /dev/null
--- /dev/null
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++usr/share/man/man1/gdb.1.gz usr/share/man/man1/rust-gdb.1.gz
--- /dev/null
--- /dev/null
--- /dev/null
+++usr/bin/rust-lldb
+++usr/lib/rustlib/etc/lldb_commands
+++usr/lib/rustlib/etc/lldb_lookup.py
+++usr/lib/rustlib/etc/lldb_providers.py
--- /dev/null
--- /dev/null
--- /dev/null
+++usr/share/man/man1/lldb-19.1.gz usr/share/man/man1/rust-lldb.1.gz
--- /dev/null
--- /dev/null
--- /dev/null
+++usr/lib/rustlib/${env:DEB_HOST_RUST_TYPE}/bin/wasm-component-ld
--- /dev/null
--- /dev/null
--- /dev/null
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++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}
--- /dev/null
--- /dev/null
--- /dev/null
+++usr/src/rustc-${env:RUST_LONG_VERSION} usr/lib/rustlib/src/rust
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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]
--- /dev/null
--- /dev/null
--- /dev/null
+++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/
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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]
--- /dev/null
--- /dev/null
--- /dev/null
+++debian/tmp/usr/share/man/man1/rustc.1
+++debian/tmp/usr/share/man/man1/rustdoc.1
+++
--- /dev/null
--- /dev/null
--- /dev/null
+++usr/bin/rustfmt
+++usr/bin/cargo-fmt
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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 <whitelist> <filter_description> [<extra args to suspicious-source>]
+++
+++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."
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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 <<eof
+++[source.crates-io]
+++replace-with = "vendored-sources"
+++
+++[source.vendored-sources]
+++directory = "$PWD/vendor"
+++eof
+++cargo lock list > 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
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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 "???"
+++ ))
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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)
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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"
+++
--- /dev/null
--- /dev/null
--- /dev/null
+++3.0 (quilt)
--- /dev/null
--- /dev/null
--- /dev/null
+++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.
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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 * (*)
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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
--- /dev/null
--- /dev/null
--- /dev/null
+++#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
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/bin/bash
+++set -euo pipefail
+++
+++tmpdir=$(mktemp -d)
+++cd "$tmpdir"
+++
+++cargo new hello
+++cd hello
+++
+++cat <<EOF > 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 <<EOF > .cargo/config.toml
+++[source.crates-io]
+++replace-with = "vendored-sources"
+++
+++[source.vendored-sources]
+++directory = "vendor"
+++EOF
+++
+++cargo check
+++cargo build
+++cargo test
+++cargo run
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/bin/bash
+++set -euo pipefail
+++
+++tmpdir=$(mktemp -d)
+++cd "$tmpdir"
+++
+++cargo new hello
+++cd hello
+++
+++cat <<EOF > 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 <<EOF > .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"
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/bin/bash
+++set -euo pipefail
+++
+++tmpdir=$(mktemp -d)
+++cd "$tmpdir"
+++
+++cargo new hello
+++cd hello
+++
+++cat <<EOF > 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 <<EOF > .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"
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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 "$@"
--- /dev/null
--- /dev/null
--- /dev/null
+++## 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
--- /dev/null
--- /dev/null
--- /dev/null
+++-----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-----
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/usr/bin/node --experimental-wasi-unstable-preview1
+++///
+++/// Simple WASI executor, adapted from the NodeJS WASI module API docs [1].
+++///
+++/// Usage: wasi-node <command> [<args> .. ]
+++///
+++/// 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);
+++})();
--- /dev/null
--- /dev/null
--- /dev/null
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++{"files":{"CHANGELOG.md":"433aae66b26ec1e1d867def155919cee89d831b0d14e5d20b9e80e1f11a20101","Cargo.toml":"49cac7eabb933177c492b5fa3a57813fb19e7471bb64d76777d172b81588738d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","src/lib.rs":"b1919f3ae4b6e4eba32fe74167ca13393baecccb04f986cdd4de71b122d48701","tests/all.rs":"5b48bca5608c533f4763f850a9b838cffe09e73e529261f16c331e10296f8e14"},"package":"be8dcabbc09ece4d30a9aa983d5804203b7e2f8054a171f792deff59b56d31fa"}
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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)
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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 <josh@joshtriplett.org>",
+++ "Alex Crichton <alex@alexcrichton.com>",
+++]
+++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",
+++]
--- /dev/null
--- /dev/null
--- /dev/null
+++ 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.
--- /dev/null
--- /dev/null
--- /dev/null
+++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.
--- /dev/null
--- /dev/null
--- /dev/null
+++//! 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<Mutex<Easy>>,
+++ /// 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<Mutex<String>>,
+++}
+++
+++struct CurlSubtransport {
+++ handle: Arc<Mutex<Easy>>,
+++ service: &'static str,
+++ url_path: &'static str,
+++ base_url: Arc<Mutex<String>>,
+++ method: &'static str,
+++ reader: Option<Cursor<Vec<u8>>>,
+++ 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<Mutex<Easy>>) -> Result<Transport, Error> {
+++ 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<Box<dyn SmartSubtransportStream>, 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<E: Into<Box<dyn error::Error + Send + Sync>>>(&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<usize> {
+++ 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<usize> {
+++ if self.reader.is_none() {
+++ self.execute(data)?;
+++ }
+++ Ok(data.len())
+++ }
+++ fn flush(&mut self) -> io::Result<()> {
+++ Ok(())
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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());
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++{"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"}
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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)
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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 <https://github.com/libgit2/libgit2/blob/main/docs/changelog.md>
+++ can be helpful for seeing what has changed.
+++ The project has recently started labeling API and ABI breaking changes with labels:
+++ <https://github.com/libgit2/libgit2/pulls?q=is%3Apr+label%3A%22api+breaking%22%2C%22abi+breaking%22+is%3Aclosed>
+++ 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 <https://github.com/rust-lang/git2-rs/actions/workflows/publish.yml> (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`
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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",
+++]
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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 <josh@joshtriplett.org>",
+++ "Alex Crichton <alex@alexcrichton.com>",
+++]
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++{
+++ "drips": {
+++ "ethereum": {
+++ "ownedBy": "0x298f6e7CC02D6aa94E2b135f46F1761da7A44E58"
+++ }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++ 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.
--- /dev/null
--- /dev/null
--- /dev/null
+++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.
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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
--- /dev/null
--- /dev/null
--- /dev/null
+++#!/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
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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
+++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+++ */
+++
+++#![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<String>,
+++ #[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),
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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
+++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+++ */
+++
+++#![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<String>,
+++ #[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),
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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
+++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+++ */
+++
+++#![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<String>,
+++}
+++
+++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<Signature>) {
+++ 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),
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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
+++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+++ */
+++
+++#![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<Progress<'static>>,
+++ total: usize,
+++ current: usize,
+++ path: Option<PathBuf>,
+++ 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),
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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
+++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+++ */
+++
+++#![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<String>,
+++ #[structopt(name = "to_oid")]
+++ arg_to_oid: Option<String>,
+++ #[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<String>,
+++ #[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<u16>,
+++ #[structopt(name = "find-copies", short = 'C', long)]
+++ /// set threshold for finding copies (default 50)
+++ flag_find_copies: Option<u16>,
+++ #[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<u32>,
+++ #[structopt(name = "inter-hunk-context", long)]
+++ /// maximum lines of change between hunks
+++ flag_inter_hunk_context: Option<u32>,
+++ #[structopt(name = "abbrev", long)]
+++ /// length to abbreviate commits to
+++ flag_abbrev: Option<u16>,
+++ #[structopt(name = "src-prefix", long)]
+++ /// show given source prefix instead of 'a/'
+++ flag_src_prefix: Option<String>,
+++ #[structopt(name = "dst-prefix", long)]
+++ /// show given destination prefix instead of 'b/'
+++ flag_dst_prefix: Option<String>,
+++ #[structopt(name = "path", long = "git-dir")]
+++ /// path to git repository to use
+++ flag_git_dir: Option<String>,
+++}
+++
+++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<DiffHunk>,
+++ 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<Option<Object<'a>>, 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<Option<Blob<'a>>, 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),
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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
+++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+++ */
+++
+++#![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<String>,
+++}
+++
+++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),
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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
+++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+++ */
+++
+++#![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 <dir> as an initialization template
+++ flag_template: Option<String>,
+++ #[structopt(name = "separate-git-dir", long)]
+++ /// use <dir> as the .git directory
+++ flag_separate_git_dir: Option<String>,
+++ #[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<String>,
+++}
+++
+++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<RepositoryInitMode, Error> {
+++ 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),
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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
+++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+++ */
+++
+++#![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<String>,
+++ #[structopt(name = "committer", long)]
+++ /// committer to sort by
+++ flag_committer: Option<String>,
+++ #[structopt(name = "pat", long = "grep")]
+++ /// pattern to filter commit messages by
+++ flag_grep: Option<String>,
+++ #[structopt(name = "dir", long = "git-dir")]
+++ /// alternative git directory to use
+++ flag_git_dir: Option<String>,
+++ #[structopt(name = "skip", long)]
+++ /// number of commits to skip
+++ flag_skip: Option<usize>,
+++ #[structopt(name = "max-count", short = 'n', long)]
+++ /// maximum number of commits to show
+++ flag_max_count: Option<usize>,
+++ #[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<usize>,
+++ #[structopt(name = "min-parents")]
+++ /// specify a minimum number of parents for a commit
+++ flag_min_parents: Option<usize>,
+++ #[structopt(name = "patch", long, short)]
+++ /// show commit diff
+++ flag_patch: bool,
+++ #[structopt(name = "commit")]
+++ arg_commit: Vec<String>,
+++ #[structopt(name = "spec", last = true)]
+++ arg_spec: Vec<String>,
+++}
+++
+++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<String>) -> 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<String>) -> 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<bool, Error> {
+++ 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<usize> {
+++ 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),
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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
+++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+++ */
+++
+++#![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),
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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
+++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+++ */
+++
+++use clap::Parser;
+++use git2::Repository;
+++use std::io::{self, Write};
+++use std::str;
+++
+++#[derive(Parser)]
+++struct Args {
+++ arg_remote: Option<String>,
+++ arg_branch: Option<String>,
+++}
+++
+++fn do_fetch<'a>(
+++ repo: &'a git2::Repository,
+++ refs: &[&str],
+++ remote: &'a mut git2::Remote,
+++) -> Result<git2::AnnotatedCommit<'a>, 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),
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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
+++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+++ */
+++
+++#![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 <spec>
+++ flag_not: Vec<String>,
+++ #[structopt(name = "spec", last = true)]
+++ arg_spec: Vec<String>,
+++}
+++
+++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),
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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
+++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+++ */
+++
+++#![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<String>,
+++}
+++
+++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),
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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
+++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+++ */
+++
+++#![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<String>,
+++ #[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<String>,
+++ #[structopt(name = "opt-files", long = "ignore-submodules")]
+++ /// setting for ignoring submodules [all]
+++ flag_ignore_submodules: Option<String>,
+++ #[structopt(name = "dir", long = "git-dir")]
+++ /// git directory to analyze
+++ flag_git_dir: Option<String>,
+++ #[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 <file>...\" 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{} <file>...\" to update what will be committed)
+++# (use \"git checkout -- <file>...\" 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 <file>...\" 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 <file>...\" 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),
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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
+++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+++ */
+++
+++#![deny(warnings)]
+++
+++use clap::Parser;
+++use git2::{Commit, Error, Repository, Tag};
+++use std::str;
+++
+++#[derive(Parser)]
+++struct Args {
+++ arg_tagname: Option<String>,
+++ arg_object: Option<String>,
+++ arg_pattern: Option<String>,
+++ #[structopt(name = "n", short)]
+++ /// specify number of lines from the annotation to print
+++ flag_n: Option<u32>,
+++ #[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<String>,
+++ #[structopt(name = "msg", short, long = "message")]
+++ /// message for a new tag
+++ flag_message: Option<String>,
+++}
+++
+++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),
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++//! git_apply support
+++//! see original: <https://github.com/libgit2/libgit2/blob/master/include/git2/apply.h>
+++
+++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 <https://libgit2.org/libgit2/#HEAD/type/git_apply_options>
+++#[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<Box<HunkCB<'cb>>>,
+++ delta_cb: Option<Box<DeltaCB<'cb>>>,
+++}
+++
+++type HunkCB<'a> = dyn FnMut(Option<DiffHunk<'_>>) -> bool + 'a;
+++type DeltaCB<'a> = dyn FnMut(Option<DiffDelta<'_>>) -> 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<F>(&mut self, cb: F) -> &mut Self
+++ where
+++ F: FnMut(Option<DiffHunk<'_>>) -> bool + 'cb,
+++ {
+++ self.hunk_cb = Some(Box::new(cb) as Box<HunkCB<'cb>>);
+++
+++ 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<F>(&mut self, cb: F) -> &mut Self
+++ where
+++ F: FnMut(Option<DiffDelta<'_>>) -> bool + 'cb,
+++ {
+++ self.delta_cb = Some(Box::new(cb) as Box<DeltaCB<'cb>>);
+++
+++ 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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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"));
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<usize>,
+++ 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<Blame<'_>, 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<BlameHunk<'_>> {
+++ 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<BlameHunk<'_>> {
+++ 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<BlameHunk<'blame>> {
+++ self.range.next().and_then(|i| self.blame.get_index(i))
+++ }
+++
+++ fn size_hint(&self) -> (usize, Option<usize>) {
+++ self.range.size_hint()
+++ }
+++}
+++
+++impl<'blame> DoubleEndedIterator for BlameIter<'blame> {
+++ fn next_back(&mut self) -> Option<BlameHunk<'blame>> {
+++ 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());
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Object<'repo>>,
+++}
+++
+++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::<Object<'_>>());
+++ 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<Object<'repo>>,
+++}
+++
+++impl<'repo> BlobWriter<'repo> {
+++ /// Finalize blob writing stream and write the blob to the object db
+++ pub fn commit(mut self) -> Result<Oid, Error> {
+++ // 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<usize> {
+++ 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();
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<References<'repo>>,
+++}
+++
+++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<bool, Error> {
+++ 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<Branch<'repo>, 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<Option<&str>, 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<Branch<'repo>, 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<Result<(Branch<'repo>, 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());
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<u8>`, 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) }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++//! 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<CString>,
+++ local: bool,
+++ hardlinks: bool,
+++ checkout: Option<CheckoutBuilder<'cb>>,
+++ fetch_opts: Option<FetchOptions<'cb>>,
+++ clone_local: Option<CloneLocal>,
+++ remote_create: Option<Box<RemoteCreate<'cb>>>,
+++}
+++
+++/// 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<Remote<'a>, 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<raw::git_tree_update>,
+++ paths: Vec<CString>,
+++}
+++
+++/// A builder struct for configuring checkouts of a repository.
+++pub struct CheckoutBuilder<'cb> {
+++ their_label: Option<CString>,
+++ our_label: Option<CString>,
+++ ancestor_label: Option<CString>,
+++ target_dir: Option<CString>,
+++ paths: Vec<CString>,
+++ path_ptrs: Vec<*const c_char>,
+++ file_perm: Option<i32>,
+++ dir_perm: Option<i32>,
+++ disable_filters: bool,
+++ checkout_opts: u32,
+++ progress: Option<Box<Progress<'cb>>>,
+++ notify: Option<Box<Notify<'cb>>>,
+++ 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<DiffFile<'_>>,
+++ Option<DiffFile<'_>>,
+++ Option<DiffFile<'_>>,
+++ ) -> 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<F>(&mut self, f: F) -> &mut RepoBuilder<'cb>
+++ where
+++ F: for<'a> FnMut(&'a Repository, &str, &str) -> Result<Remote<'a>, 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<Repository, Error> {
+++ 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<RemoteCreate<'_>>;
+++ 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<T: IntoCString>(&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<F>(&mut self, cb: F) -> &mut CheckoutBuilder<'cb>
+++ where
+++ F: FnMut(Option<&Path>, usize, usize) + 'cb,
+++ {
+++ self.progress = Some(Box::new(cb) as Box<Progress<'cb>>);
+++ 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<F>(&mut self, cb: F) -> &mut CheckoutBuilder<'cb>
+++ where
+++ F: FnMut(
+++ CheckoutNotificationType,
+++ Option<&Path>,
+++ Option<DiffFile<'_>>,
+++ Option<DiffFile<'_>>,
+++ Option<DiffFile<'_>>,
+++ ) -> bool
+++ + 'cb,
+++ {
+++ self.notify = Some(Box::new(cb) as Box<Notify<'cb>>);
+++ 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<T: IntoCString>(&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<T: IntoCString>(&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<Oid, Error> {
+++ 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();
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++#![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<T> {
+++ fn convert(&self) -> T;
+++}
+++
+++pub fn convert<T, U: Convert<T>>(u: &U) -> T {
+++ u.convert()
+++}
+++
+++pub fn c_try(ret: libc::c_int) -> Result<libc::c_int, Error> {
+++ 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<T: Copy> Convert<T> for T {
+++ fn convert(&self) -> T {
+++ *self
+++ }
+++ }
+++
+++ impl Convert<libc::c_int> 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<T> 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<T, U: Convert<*const T>> Convert<*const T> for Option<U> {
+++ fn convert(&self) -> *const T {
+++ self.as_ref().map(|s| s.convert()).unwrap_or(ptr::null())
+++ }
+++ }
+++
+++ impl<T, U: Convert<*mut T>> Convert<*mut T> for Option<U> {
+++ fn convert(&self) -> *mut T {
+++ self.as_ref()
+++ .map(|s| s.convert())
+++ .unwrap_or(ptr::null_mut())
+++ }
+++ }
+++
+++ impl Convert<raw::git_reset_t> 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<raw::git_direction> for Direction {
+++ fn convert(&self) -> raw::git_direction {
+++ match *self {
+++ Direction::Push => raw::GIT_DIRECTION_PUSH,
+++ Direction::Fetch => raw::GIT_DIRECTION_FETCH,
+++ }
+++ }
+++ }
+++
+++ impl Convert<raw::git_object_t> 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<raw::git_object_t> for Option<ObjectType> {
+++ fn convert(&self) -> raw::git_object_t {
+++ self.unwrap_or(ObjectType::Any).convert()
+++ }
+++ }
+++
+++ impl Convert<raw::git_branch_t> 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<raw::git_branch_t> for Option<BranchType> {
+++ fn convert(&self) -> raw::git_branch_t {
+++ self.map(|s| s.convert()).unwrap_or(raw::GIT_BRANCH_ALL)
+++ }
+++ }
+++
+++ impl Convert<raw::git_config_level_t> 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<raw::git_diff_format_t> 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<raw::git_merge_file_favor_t> 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<raw::git_submodule_ignore_t> 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<raw::git_submodule_update_t> 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<raw::git_remote_autotag_option_t> 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<raw::git_fetch_prune_t> 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,
+++ }
+++ }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++//! 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<T>(&self, kind: raw::git_cert_t) -> Option<&T> {
+++ assert_eq!(mem::size_of::<Cert<'a>>(), mem::size_of::<T>());
+++ 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<SshHostKeyType> {
+++ 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
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<CheckoutBuilder<'cb>>,
+++ merge_opts: Option<MergeOptions>,
+++}
+++
+++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
+++ }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Object<'repo>>,
+++}
+++
+++/// An iterator over the parent commits of a commit.
+++///
+++/// Aborts iteration when a commit cannot be found
+++pub struct Parents<'commit, 'repo> {
+++ range: Range<usize>,
+++ 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<usize>,
+++ 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<Tree<'repo>, 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<T: IntoCString>(&self, field: T) -> Result<Buf, Error> {
+++ 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<Signature<'static>, 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<Signature<'static>, 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<Oid, Error> {
+++ 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<Commit<'repo>, 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<Oid, Error> {
+++ 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::<Object<'_>>());
+++ 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<Commit<'repo>> {
+++ self.range.next().and_then(|i| self.commit.parent(i).ok())
+++ }
+++ fn size_hint(&self) -> (usize, Option<usize>) {
+++ 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<Commit<'repo>> {
+++ 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<Oid> {
+++ self.range
+++ .next()
+++ .and_then(|i| self.commit.parent_id(i).ok())
+++ }
+++ fn size_hint(&self) -> (usize, Option<usize>) {
+++ self.range.size_hint()
+++ }
+++}
+++
+++/// Aborts iteration when a commit cannot be found
+++impl<'commit> DoubleEndedIterator for ParentIds<'commit> {
+++ fn next_back(&mut self) -> Option<Oid> {
+++ 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();
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<ConfigEntry<'cfg>>,
+++ _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<Config, Error> {
+++ 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<Config, Error> {
+++ 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<Config, Error> {
+++ 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<PathBuf, Error> {
+++ 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<PathBuf, Error> {
+++ 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<PathBuf, Error> {
+++ 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<bool, Error> {
+++ 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<i32, Error> {
+++ 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<i64, Error> {
+++ 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<String, Error> {
+++ 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<PathBuf, Error> {
+++ 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<ConfigEntry<'_>, 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<ConfigEntries<'_>, 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<ConfigEntries<'_>, 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<Config, Error> {
+++ 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<Config, Error> {
+++ 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<Config, Error> {
+++ 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: IntoCString>(s: S) -> Result<bool, Error> {
+++ 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: IntoCString>(s: S) -> Result<i32, Error> {
+++ 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: IntoCString>(s: S) -> Result<i64, Error> {
+++ 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<Result<&ConfigEntry<'cfg>, 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<F: FnMut(&ConfigEntry<'cfg>)>(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<String> = 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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<String>,
+++ protocol: Option<String>,
+++ host: Option<String>,
+++ port: Option<u16>,
+++ path: Option<String>,
+++ url: String,
+++ commands: Vec<String>,
+++}
+++
+++impl Cred {
+++ /// Create a "default" credential usable for Negotiate mechanisms like NTLM
+++ /// or Kerberos authentication.
+++ pub fn default() -> Result<Cred, Error> {
+++ 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<Cred, Error> {
+++ 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<Cred, Error> {
+++ 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<Cred, Error> {
+++ 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<Cred, Error> {
+++ 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<Cred, Error> {
+++ 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<Cred, Error> {
+++ 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<String> {
+++ 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<String>,
+++ ) -> (Option<String>, Option<String>) {
+++ 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<u8>) -> (Option<String>, Option<String>) {
+++ // 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) {}
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<String, Error> {
+++ 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");
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<CString>,
+++ pathspec_ptrs: Vec<*const c_char>,
+++ old_prefix: Option<CString>,
+++ new_prefix: Option<CString>,
+++ 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<usize>,
+++ 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<DiffHunk<'_>>, 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<DiffHunk<'_>>, 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<DiffDelta<'_>> {
+++ 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<F>(&self, format: DiffFormat, mut cb: F) -> Result<(), Error>
+++ where
+++ F: FnMut(DiffDelta<'_>, Option<DiffHunk<'_>>, 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<DiffStats, Error> {
+++ 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<Buf, Error> {
+++ 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<Oid, Error> {
+++ 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<Diff<'static>, 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<T: IntoCString>(&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<T: IntoCString>(&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<T: IntoCString>(&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<DiffDelta<'diff>> {
+++ self.range.next().and_then(|i| self.diff.get_delta(i))
+++ }
+++ fn size_hint(&self) -> (usize, Option<usize>) {
+++ self.range.size_hint()
+++ }
+++}
+++impl<'diff> DoubleEndedIterator for Deltas<'diff> {
+++ fn next_back(&mut self) -> Option<DiffDelta<'diff>> {
+++ 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<u32> {
+++ 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<u32> {
+++ 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<Buf, Error> {
+++ 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 <dummy@dummy.org>\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<DiffLineType> = 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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<CString>,
+++ 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<T: IntoCString>(&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<T: IntoCString>(
+++ diff: &Diff<'_>,
+++ patch_idx: usize,
+++ patch_count: usize,
+++ commit_id: &Oid,
+++ summary: T,
+++ body: T,
+++ author: &Signature<'_>,
+++ opts: &mut EmailCreateOptions,
+++ ) -> Result<Self, Error> {
+++ 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<Self, Error> {
+++ let buf = Buf::new();
+++ unsafe {
+++ try_call!(raw::git_email_create_from_commit(
+++ buf.raw(),
+++ commit.raw(),
+++ opts.raw()
+++ ));
+++ Ok(Self { buf })
+++ }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<str>,
+++}
+++
+++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<S: AsRef<str>>(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<NulError> for Error {
+++ fn from(_: NulError) -> Error {
+++ Error::from_str(
+++ "data contained a nul byte that could not be \
+++ represented as a string",
+++ )
+++ }
+++}
+++
+++impl From<JoinPathsError> 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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<usize>,
+++ 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<IndexEntry>,
+++ /// The index entry originating from the user's copy of the repository.
+++ /// Its contents conflict with 'their' index entry
+++ pub our: Option<IndexEntry>,
+++ /// The index entry originating from the external repository.
+++ /// Its contents conflict with 'our' index entry
+++ pub their: Option<IndexEntry>,
+++}
+++
+++/// 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<u8>,
+++}
+++
+++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<Index, Error> {
+++ 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<Index, Error> {
+++ 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<T, I>(
+++ &mut self,
+++ pathspecs: I,
+++ flag: IndexAddOption,
+++ mut cb: Option<&mut IndexMatchedPath<'_>>,
+++ ) -> Result<(), Error>
+++ where
+++ T: IntoCString,
+++ I: IntoIterator<Item = T>,
+++ {
+++ 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<IndexEntry> {
+++ 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<IndexConflicts<'_>, 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<IndexEntry> {
+++ 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<T, I>(
+++ &mut self,
+++ pathspecs: I,
+++ mut cb: Option<&mut IndexMatchedPath<'_>>,
+++ ) -> Result<(), Error>
+++ where
+++ T: IntoCString,
+++ I: IntoIterator<Item = T>,
+++ {
+++ 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<T, I>(
+++ &mut self,
+++ pathspecs: I,
+++ mut cb: Option<&mut IndexMatchedPath<'_>>,
+++ ) -> Result<(), Error>
+++ where
+++ T: IntoCString,
+++ I: IntoIterator<Item = T>,
+++ {
+++ 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<Oid, Error> {
+++ 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<Oid, Error> {
+++ 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<T: IntoCString>(&self, prefix: T) -> Result<usize, Error> {
+++ 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<IndexEntry> {
+++ self.range.next().map(|i| self.index.get(i).unwrap())
+++ }
+++}
+++
+++impl<'index> Iterator for IndexConflicts<'index> {
+++ type Item = Result<IndexConflict, Error>;
+++ fn next(&mut self) -> Option<Result<IndexConflict, Error>> {
+++ 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(),
+++ }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Self, Error> {
+++ 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-<checksum>.pack` and
+++ /// `pack-<checksum>.idx` respectively).
+++ pub fn commit(mut self) -> Result<String, Error> {
+++ 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<F>(&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<IndexerProgress<'a>>);
+++
+++ self
+++ }
+++}
+++
+++impl io::Write for Indexer<'_> {
+++ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+++ 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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++//! # 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<T: IntoCString>(o: Option<T>) -> Result<Option<CString>, 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<ObjectType> {
+++ 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<ObjectType> {
+++ 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<ReferenceType> {
+++ 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<FileMode> 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<FileMode> 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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Mailmap, Error> {
+++ 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<Mailmap, Error> {
+++ 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<Signature<'static>, 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 = "<prøper@emæil> <email>";
+++ 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"));
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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(())
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Commit<'repo>>,
+++}
+++
+++/// 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) }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<T: IntoCString>(
+++ message: T,
+++ comment_char: Option<u8>,
+++) -> Result<String, Error> {
+++ _message_prettify(message.into_c_string()?, comment_char)
+++}
+++
+++fn _message_prettify(message: CString, comment_char: Option<u8>) -> Result<String, Error> {
+++ 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<u8> = 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<MessageTrailersStrs, Error> {
+++ _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<S: IntoCString>(message: S) -> Result<MessageTrailersBytes, Error> {
+++ _message_trailers(message.into_c_string()?).map(|res| MessageTrailersBytes(res))
+++}
+++
+++fn _message_trailers(message: CString) -> Result<MessageTrailers, Error> {
+++ 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<usize>,
+++}
+++
+++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::Item> {
+++ self.0
+++ .range
+++ .next()
+++ .map(|index| to_str_tuple(&self.0.trailers, index))
+++ }
+++
+++ fn size_hint(&self) -> (usize, Option<usize>) {
+++ 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::Item> {
+++ 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::Item> {
+++ self.0
+++ .range
+++ .next()
+++ .map(|index| to_bytes_tuple(&self.0.trailers, index))
+++ }
+++
+++ fn size_hint(&self) -> (usize, Option<usize>) {
+++ 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::Item> {
+++ 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
+++ }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Result<(Oid, Oid), Error>> {
+++ 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());
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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> {
+++ 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<Object<'repo>, 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<Blob<'repo>, 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<Commit<'repo>, 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<Tag<'repo>, 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<Tree<'repo>, 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<Buf, Error> {
+++ 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<Commit<'repo>, 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<Tag<'repo>, 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<Tree<'repo>, 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<Blob<'repo>, 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<Describe<'_>, 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<T>(&self, kind: ObjectType) -> Option<&T> {
+++ assert_eq!(mem::size_of::<Object<'_>>(), mem::size_of::<T>());
+++ if self.kind() == Some(kind) {
+++ unsafe { Some(&*(self as *const _ as *const T)) }
+++ } else {
+++ None
+++ }
+++ }
+++
+++ fn cast_into<T>(self, kind: ObjectType) -> Result<T, Object<'repo>> {
+++ assert_eq!(mem::size_of_val(&self), mem::size_of::<T>());
+++ 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<T>(self, kind: ObjectType) -> T;
+++}
+++
+++impl<'repo> CastOrPanic for Object<'repo> {
+++ fn cast_or_panic<T>(self, kind: ObjectType) -> T {
+++ assert_eq!(mem::size_of_val(&self), mem::size_of::<T>());
+++ 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) }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Object<'repo>>,
+++}
+++
+++// `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<Odb<'a>, 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<OdbWriter<'_>, 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<C>(&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<OdbObject<'_>, 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<Oid, Error> {
+++ 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<OdbPackwriter<'_>, 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<Oid, Error> {
+++ 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<Mempack<'odb>, 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<Object<'a>>,
+++}
+++
+++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<Object<'repo>>,
+++}
+++
+++// `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<usize> {
+++ 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<Object<'repo>>,
+++}
+++
+++// `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<Oid, Error> {
+++ 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<usize> {
+++ 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<Box<IndexerProgress<'repo>>>,
+++}
+++
+++/// 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<i32, Error> {
+++ 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<F>(&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<IndexerProgress<'repo>>);
+++ self
+++ }
+++}
+++
+++impl<'repo> io::Write for OdbPackwriter<'repo> {
+++ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+++ 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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Oid, Error> {
+++ 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<Oid, Error> {
+++ 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<Oid, Error> {
+++ 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<P: AsRef<Path>>(kind: ObjectType, path: P) -> Result<Oid, Error> {
+++ 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, Error> {
+++ 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<Ordering> {
+++ 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<H: Hasher>(&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());
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++//! 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::<Oid>(), 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) }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++//! 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<P>(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::<u8>()
+++ ));
+++ 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<CString, Error> {
+++ 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<StringArray, Error> {
+++ 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<E>(extensions: &[E]) -> Result<(), Error>
+++where
+++ for<'x> &'x E: IntoCString,
+++{
+++ crate::init();
+++
+++ let extensions = extensions
+++ .iter()
+++ .map(|e| e.into_c_string())
+++ .collect::<Result<Vec<_>, _>>()?;
+++
+++ let extension_ptrs = extensions.iter().map(|e| e.as_ptr()).collect::<Vec<_>>();
+++
+++ 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<P>(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::<libc::c_char>()
+++ ));
+++ }
+++
+++ 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<P>(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::<libc::c_char>(),
+++ 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<libc::size_t, Error> {
+++ 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<libc::size_t, Error> {
+++ 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<libc::size_t, Error> {
+++ 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<libc::c_int, Error> {
+++ 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<libc::c_int, Error> {
+++ 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);
+++ }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Box<Box<ProgressCb<'repo>>>>,
+++ _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<F>(&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<F>(&mut self, progress: F) -> Result<(), Error>
+++ where
+++ F: FnMut(PackBuilderStage, u32, u32) -> bool + 'repo,
+++ {
+++ let mut progress = Box::new(Box::new(progress) as Box<ProgressCb<'_>>);
+++ 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<Oid> {
+++ 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<ProgressCb<'_>>;
+++ (*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<u8> {
+++ [].iter()
+++ .chain(b"PACK") // signature
+++ .chain(&[0, 0, 0, 2]) // version number
+++ .chain(&[0, 0, 0, len]) // number of objects
+++ .cloned()
+++ .collect::<Vec<u8>>()
+++ }
+++
+++ fn empty_pack_header() -> Vec<u8> {
+++ 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::<Vec<u8>>()
+++ }
+++
+++ #[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::<u8>::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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++use std::any::Any;
+++use std::cell::RefCell;
+++
+++thread_local!(static LAST_ERROR: RefCell<Option<Box<dyn Any + Send>>> = {
+++ RefCell::new(None)
+++});
+++
+++pub fn wrap<T, F: FnOnce() -> T + std::panic::UnwindSafe>(f: F) -> Option<T> {
+++ 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())
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Option<Self>, 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<Self, Error> {
+++ 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<Self, Error> {
+++ 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<Self, Error> {
+++ 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<usize, Error> {
+++ 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<DiffLine<'buffers>, 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<Buf, Error> {
+++ 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()
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<usize>,
+++ list: &'list PathspecMatchList<'list>,
+++}
+++
+++/// Iterator over the matching diff deltas.
+++pub struct PathspecDiffEntries<'list> {
+++ range: Range<usize>,
+++ list: &'list PathspecMatchList<'list>,
+++}
+++
+++/// Iterator over the failed list of pathspec items that did not match.
+++pub struct PathspecFailedEntries<'list> {
+++ range: Range<usize>,
+++ list: &'list PathspecMatchList<'list>,
+++}
+++
+++impl Pathspec {
+++ /// Creates a new pathspec from a list of specs to match against.
+++ pub fn new<I, T>(specs: I) -> Result<Pathspec, Error>
+++ where
+++ T: IntoCString,
+++ I: IntoIterator<Item = T>,
+++ {
+++ 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<PathspecMatchList<'_>, 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<PathspecMatchList<'_>, 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<PathspecMatchList<'_>, 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<PathspecMatchList<'_>, 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<DiffDelta<'_>> {
+++ 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<usize>) {
+++ 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<DiffDelta<'list>> {
+++ self.range.next().and_then(|i| self.list.diff_entry(i))
+++ }
+++ fn size_hint(&self) -> (usize, Option<usize>) {
+++ self.range.size_hint()
+++ }
+++}
+++impl<'list> DoubleEndedIterator for PathspecDiffEntries<'list> {
+++ fn next_back(&mut self) -> Option<DiffDelta<'list>> {
+++ 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<usize>) {
+++ 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()));
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<CString>,
+++ 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(),
+++ }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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 _) }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<CString>,
+++ merge_options: Option<MergeOptions>,
+++ checkout_options: Option<CheckoutBuilder<'cb>>,
+++}
+++
+++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<Oid> {
+++ 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<RebaseOperation<'_>> {
+++ 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<usize> {
+++ 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<Index, Error> {
+++ 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<Oid, Error> {
+++ 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<RebaseOperation<'rebase>, 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<Result<RebaseOperation<'rebase>, 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<RebaseOperationType> {
+++ 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<Rebase<'rebase>>,
+++}
+++
+++impl<'rebase> RebaseOperation<'rebase> {
+++ /// The type of rebase operation
+++ pub fn kind(&self) -> Option<RebaseOperationType> {
+++ 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();
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Refdb<'repo>>,
+++}
+++
+++/// An iterator over the references in a repository.
+++pub struct References<'repo> {
+++ raw: *mut raw::git_reference_iterator,
+++ _marker: marker::PhantomData<Refdb<'repo>>,
+++}
+++
+++/// 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<String, Error> {
+++ 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> {
+++ 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<Oid> {
+++ 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<Oid> {
+++ 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<Reference<'repo>, 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<Object<'repo>, 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<Blob<'repo>, 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<Commit<'repo>, 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<Tree<'repo>, 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<Tag<'repo>, 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<Reference<'repo>, 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<Reference<'repo>, 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<Reference<'repo>, 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<Ordering> {
+++ 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<Reference<'repo>, Error>;
+++ fn next(&mut self) -> Option<Result<Reference<'repo>, 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<Result<&'references str, Error>> {
+++ 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();
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<usize>,
+++ 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<ReflogEntry<'_>> {
+++ 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<ReflogEntry<'reflog>> {
+++ self.range.next().and_then(|i| self.reflog.get(i))
+++ }
+++ fn size_hint(&self) -> (usize, Option<usize>) {
+++ self.range.size_hint()
+++ }
+++}
+++impl<'reflog> DoubleEndedIterator for ReflogIter<'reflog> {
+++ fn next_back(&mut self) -> Option<ReflogEntry<'reflog>> {
+++ 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();
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Buf, Error> {
+++ 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<Buf, Error> {
+++ 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
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<usize>,
+++ 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<RemoteCallbacks<'cb>>,
+++ depth: i32,
+++ proxy: Option<ProxyOptions<'cb>>,
+++ prune: FetchPrune,
+++ update_flags: RemoteUpdateFlags,
+++ download_tags: AutotagOption,
+++ follow_redirects: RemoteRedirect,
+++ custom_headers: Vec<CString>,
+++ custom_headers_ptrs: Vec<*const c_char>,
+++}
+++
+++/// Options to control the behavior of a git push.
+++pub struct PushOptions<'cb> {
+++ callbacks: Option<RemoteCallbacks<'cb>>,
+++ proxy: Option<ProxyOptions<'cb>>,
+++ pb_parallelism: u32,
+++ follow_redirects: RemoteRedirect,
+++ custom_headers: Vec<CString>,
+++ custom_headers_ptrs: Vec<*const c_char>,
+++ remote_push_options: Vec<CString>,
+++ 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<RemoteCallbacks<'cb>>,
+++ _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<S: Into<Vec<u8>>>(url: S) -> Result<Remote<'repo>, 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<Buf, Error> {
+++ 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<RemoteCallbacks<'cb>>,
+++ proxy_options: Option<ProxyOptions<'cb>>,
+++ ) -> Result<RemoteConnection<'repo, 'connection, 'cb>, 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<Str: AsRef<str> + 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<Refspec<'repo>> {
+++ 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<Str: AsRef<str> + 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<Str: AsRef<str> + 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::<RemoteHead<'_>>(),
+++ 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<RemoteCallbacks<'_>>) -> 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<StringArray, Error> {
+++ 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<StringArray, Error> {
+++ 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<Refspec<'repo>> {
+++ self.range.next().and_then(|i| self.remote.get_refspec(i))
+++ }
+++ fn size_hint(&self) -> (usize, Option<usize>) {
+++ self.range.size_hint()
+++ }
+++}
+++impl<'repo> DoubleEndedIterator for Refspecs<'repo> {
+++ fn next_back(&mut self) -> Option<Refspec<'repo>> {
+++ 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<Buf, Error> {
+++ 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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Box<PushTransferProgress<'a>>>,
+++ progress: Option<Box<IndexerProgress<'a>>>,
+++ pack_progress: Option<Box<PackProgress<'a>>>,
+++ credentials: Option<Box<Credentials<'a>>>,
+++ sideband_progress: Option<Box<TransportMessage<'a>>>,
+++ update_tips: Option<Box<UpdateTips<'a>>>,
+++ certificate_check: Option<Box<CertificateCheck<'a>>>,
+++ push_update_reference: Option<Box<PushUpdateReference<'a>>>,
+++ push_negotiation: Option<Box<PushNegotiation<'a>>>,
+++}
+++
+++/// 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<Cred, Error> + '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<CertificateCheckStatus, Error> + '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<F>(&mut self, cb: F) -> &mut RemoteCallbacks<'a>
+++ where
+++ F: FnMut(&str, Option<&str>, CredentialType) -> Result<Cred, Error> + 'a,
+++ {
+++ self.credentials = Some(Box::new(cb) as Box<Credentials<'a>>);
+++ self
+++ }
+++
+++ /// The callback through which progress is monitored.
+++ pub fn transfer_progress<F>(&mut self, cb: F) -> &mut RemoteCallbacks<'a>
+++ where
+++ F: FnMut(Progress<'_>) -> bool + 'a,
+++ {
+++ self.progress = Some(Box::new(cb) as Box<IndexerProgress<'a>>);
+++ 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<F>(&mut self, cb: F) -> &mut RemoteCallbacks<'a>
+++ where
+++ F: FnMut(&[u8]) -> bool + 'a,
+++ {
+++ self.sideband_progress = Some(Box::new(cb) as Box<TransportMessage<'a>>);
+++ self
+++ }
+++
+++ /// Each time a reference is updated locally, the callback will be called
+++ /// with information about it.
+++ pub fn update_tips<F>(&mut self, cb: F) -> &mut RemoteCallbacks<'a>
+++ where
+++ F: FnMut(&str, Oid, Oid) -> bool + 'a,
+++ {
+++ self.update_tips = Some(Box::new(cb) as Box<UpdateTips<'a>>);
+++ 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<F>(&mut self, cb: F) -> &mut RemoteCallbacks<'a>
+++ where
+++ F: FnMut(&Cert<'_>, &str) -> Result<CertificateCheckStatus, Error> + 'a,
+++ {
+++ self.certificate_check = Some(Box::new(cb) as Box<CertificateCheck<'a>>);
+++ 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<F>(&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<PushUpdateReference<'a>>);
+++ self
+++ }
+++
+++ /// The callback through which progress of push transfer is monitored
+++ ///
+++ /// Parameters:
+++ /// * current
+++ /// * total
+++ /// * bytes
+++ pub fn push_transfer_progress<F>(&mut self, cb: F) -> &mut RemoteCallbacks<'a>
+++ where
+++ F: FnMut(usize, usize, usize) + 'a,
+++ {
+++ self.push_progress = Some(Box::new(cb) as Box<PushTransferProgress<'a>>);
+++ 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<F>(&mut self, cb: F) -> &mut RemoteCallbacks<'a>
+++ where
+++ F: FnMut(PackBuilderStage, usize, usize) + 'a,
+++ {
+++ self.pack_progress = Some(Box::new(cb) as Box<PackProgress<'a>>);
+++ 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<F>(&mut self, cb: F) -> &mut RemoteCallbacks<'a>
+++ where
+++ F: FnMut(&[PushUpdate<'_>]) -> Result<(), Error> + 'a,
+++ {
+++ self.push_negotiation = Some(Box::new(cb) as Box<PushNegotiation<'a>>);
+++ 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)
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<CString>,
+++ description: Option<CString>,
+++ template_path: Option<CString>,
+++ initial_head: Option<CString>,
+++ origin_url: Option<CString>,
+++}
+++
+++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<P: AsRef<Path>>(path: P) -> Result<Repository, Error> {
+++ 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<P: AsRef<Path>>(path: P) -> Result<Repository, Error> {
+++ 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<Repository, Error> {
+++ 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<P, O, I>(
+++ path: P,
+++ flags: RepositoryOpenFlags,
+++ ceiling_dirs: I,
+++ ) -> Result<Repository, Error>
+++ where
+++ P: AsRef<Path>,
+++ O: AsRef<OsStr>,
+++ I: IntoIterator<Item = O>,
+++ {
+++ 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<Repository, Error> {
+++ 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<P: AsRef<Path>>(path: P) -> Result<Repository, Error> {
+++ // 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<P: AsRef<Path>, I, O>(path: P, ceiling_dirs: I) -> Result<PathBuf, Error>
+++ where
+++ O: AsRef<OsStr>,
+++ I: IntoIterator<Item = O>,
+++ {
+++ 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<P: AsRef<Path>>(path: P) -> Result<Repository, Error> {
+++ 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<P: AsRef<Path>>(path: P) -> Result<Repository, Error> {
+++ 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<P: AsRef<Path>>(
+++ path: P,
+++ opts: &RepositoryInitOptions,
+++ ) -> Result<Repository, Error> {
+++ 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<P: AsRef<Path>>(url: &str, into: P) -> Result<Repository, Error> {
+++ 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<P: AsRef<Path>>(url: &str, into: P) -> Result<Repository, Error> {
+++ 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<Repository, Error> {
+++ 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<Repository>) -> 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<Revspec<'_>, 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<Object<'_>, 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
+++ /// <http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions> for
+++ /// information on the syntax accepted.
+++ ///
+++ /// In some cases (`@{<-n>}` or `<branchname>@{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<Reference<'_>>), 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<bool, Error> {
+++ 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<String, Error> {
+++ 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<StringArray, Error> {
+++ 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<Remote<'_>, 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<Remote<'_>, 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<Remote<'_>, 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<Remote<'_>, 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<StringArray, Error> {
+++ 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<T, I>(&self, target: Option<&Object<'_>>, paths: I) -> Result<(), Error>
+++ where
+++ T: IntoCString,
+++ I: IntoIterator<Item = T>,
+++ {
+++ 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<Reference<'_>, 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<bool, Error> {
+++ 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<References<'_>, 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<References<'_>, 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<Vec<Submodule<'_>>, Error> {
+++ struct Data<'a, 'b> {
+++ repo: &'b Repository,
+++ ret: &'a mut Vec<Submodule<'b>>,
+++ }
+++ 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<Statuses<'_>, 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<bool, Error> {
+++ 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<Status, Error> {
+++ 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<BranchType>) -> Result<Branches<'_>, 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<Index, Error> {
+++ 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<Config, Error> {
+++ 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<Option<&str>, 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<Option<&[u8]>, 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<Oid, Error> {
+++ 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<Oid, Error> {
+++ // 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<BlobWriter<'_>, 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<Blob<'_>, 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<Odb<'_>, 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<Branch<'_>, 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<Branch<'_>, 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<Branch<'_>, 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<Oid, Error> {
+++ let update_ref = crate::opt_cstr(update_ref)?;
+++ let mut parent_ptrs = parents
+++ .iter()
+++ .map(|p| p.raw() as *const raw::git_commit)
+++ .collect::<Vec<_>>();
+++ 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<Buf, Error> {
+++ let mut parent_ptrs = parents
+++ .iter()
+++ .map(|p| p.raw() as *const raw::git_commit)
+++ .collect::<Vec<_>>();
+++ 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<Oid, Error> {
+++ 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<Commit<'_>, 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<Commit<'_>, 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<AnnotatedCommit<'_>, 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<ObjectType>) -> Result<Object<'_>, 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<ObjectType>,
+++ ) -> Result<Object<'_>, 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<Reference<'_>, 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<Reference<'_>, 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<Reference<'_>, 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<Reference<'_>, 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<Reference<'_>, 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<Reference<'_>, 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<Oid, Error> {
+++ 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<AnnotatedCommit<'_>, 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<AnnotatedCommit<'_>, 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<Signature<'static>, 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<Submodule<'_>, 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<Submodule<'_>, 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<SubmoduleStatus, Error> {
+++ 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<Tree<'_>, 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<TreeBuilder<'_>, 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<Oid, Error> {
+++ 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<Oid, Error> {
+++ 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<Oid, Error> {
+++ 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<Tag<'_>, 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<Tag<'_>, 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<StringArray, Error> {
+++ 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<T>(&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::<Vec<_>>();
+++
+++ 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<Index, Error> {
+++ 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<Index, Error> {
+++ 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::<Vec<_>>();
+++ 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::<Vec<_>>();
+++ 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<Rebase<'_>, 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<Rebase<'_>, 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<Oid, Error> {
+++ 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<String, Error> {
+++ 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<Notes<'_>, 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<Note<'_>, 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<Revwalk<'_>, 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<Blame<'_>, 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<Oid, Error> {
+++ 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<Oid, Error> {
+++ 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<Oid, Error> {
+++ 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<OidArray, Error> {
+++ 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<OidArray, Error> {
+++ 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<bool, Error> {
+++ 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<Reflog, Error> {
+++ 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<bool, Error> {
+++ 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<Describe<'_>, 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 <old-tree> <new-tree>`
+++ ///
+++ /// 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<Diff<'_>, 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 <treeish>` 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<Diff<'_>, 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<Diff<'_>, 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 <treeish>`
+++ /// 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<Diff<'_>, 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 <treeish>` or `git diff-index
+++ /// <treeish>`. 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<Diff<'_>, 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 <tree>` 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<Diff<'_>, 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<PackBuilder<'_>, 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<StashFlags>,
+++ ) -> Result<Oid, Error> {
+++ 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<StashFlags>,
+++ ) -> Result<Oid, Error> {
+++ 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<Oid, Error> {
+++ 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<C>(&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<P: AsRef<Path>>(&self, path: P) -> Result<bool, Error> {
+++ 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<Index, Error> {
+++ 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<Buf, Error> {
+++ 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<Buf, Error> {
+++ 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<Buf, Error> {
+++ 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<Index, Error> {
+++ 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<Index, Error> {
+++ 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<StringArray, Error> {
+++ 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<Worktree, Error> {
+++ 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<Worktree, Error> {
+++ 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<Transaction<'a>, 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<Mailmap, Error> {
+++ 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<C>(&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<C>(&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 <author.proper@email> name <email>
+++Committer Name <committer.proper@email> <committer@email>"#,
+++ ));
+++ 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()
+++ );
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<CheckoutBuilder<'cb>>,
+++ merge_opts: Option<MergeOptions>,
+++}
+++
+++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
+++ }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++use crate::{Object, RevparseMode};
+++
+++/// A revspec represents a range of revisions within a repository.
+++pub struct Revspec<'repo> {
+++ from: Option<Object<'repo>>,
+++ to: Option<Object<'repo>>,
+++ mode: RevparseMode,
+++}
+++
+++impl<'repo> Revspec<'repo> {
+++ /// Assembles a new revspec from the from/to components.
+++ pub fn from_objects(
+++ from: Option<Object<'repo>>,
+++ to: Option<Object<'repo>>,
+++ 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
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<C>(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<Revwalk<'repo>, 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 `<commit>..<commit>` where each
+++ /// `<commit>` 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<RevwalkWithHideCb<'repo, 'cb, C>, 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::<C>),
+++ 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<Oid, Error>;
+++ fn next(&mut self) -> Option<Result<Oid, Error>> {
+++ 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<Oid, Error>;
+++ fn next(&mut self) -> Option<Result<Oid, Error>> {
+++ 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<crate::Oid> = walk.by_ref().collect::<Result<Vec<_>, _>>().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<crate::Oid> = walk.by_ref().collect::<Result<Vec<_>, _>>().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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Signature<'static>, 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<Signature<'static>, 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("<foo>", "bar", &Time::new(89, 0)).is_err());
+++ assert!(Signature::now("<foo>", "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());
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<CString>,
+++ flags: Option<StashFlags>,
+++ stasher: Signature<'a>,
+++ pathspec: Vec<CString>,
+++ 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<StashFlags>) -> &mut Self {
+++ self.flags = flags;
+++ self
+++ }
+++
+++ /// Add to the array of paths patterns to build the stash.
+++ pub fn pathspec<T: IntoCString>(&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<Box<StashApplyProgressCb<'cb>>>,
+++ checkout_options: Option<CheckoutBuilder<'cb>>,
+++ 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<C>(&mut self, callback: C) -> &mut StashApplyOptions<'cb>
+++ where
+++ C: FnMut(StashApplyProgress) -> bool + 'cb,
+++ {
+++ self.progress = Some(Box::new(callback) as Box<StashApplyProgressCb<'cb>>);
+++ 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<C>(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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<CString>,
+++ 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<usize>,
+++}
+++
+++/// 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<T: IntoCString>(&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<StatusEntry<'_>> {
+++ 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<StatusEntry<'a>> {
+++ self.range.next().and_then(|i| self.statuses.get(i))
+++ }
+++ fn size_hint(&self) -> (usize, Option<usize>) {
+++ self.range.size_hint()
+++ }
+++}
+++impl<'a> DoubleEndedIterator for StatusIter<'a> {
+++ fn next_back(&mut self) -> Option<StatusEntry<'a>> {
+++ 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<DiffDelta<'statuses>> {
+++ 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<DiffDelta<'statuses>> {
+++ 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));
+++ }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++//! 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<usize>,
+++ arr: &'a StringArray,
+++}
+++
+++/// A forward iterator over the strings of an array, casted to `&[u8]`.
+++pub struct IterBytes<'a> {
+++ range: Range<usize>,
+++ 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<Option<&'a str>> {
+++ self.range.next().map(|i| self.arr.get(i))
+++ }
+++ fn size_hint(&self) -> (usize, Option<usize>) {
+++ self.range.size_hint()
+++ }
+++}
+++impl<'a> DoubleEndedIterator for Iter<'a> {
+++ fn next_back(&mut self) -> Option<Option<&'a str>> {
+++ 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<usize>) {
+++ 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) }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Repository, Error> {
+++ 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<Oid> {
+++ 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<Oid> {
+++ 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<Oid> {
+++ 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<Repository, Error> {
+++ 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<Repository, Error> {
+++ 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());
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Object<'repo>>,
+++}
+++
+++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<Object<'repo>, 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<Signature<'_>> {
+++ 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<Object<'repo>, 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<ObjectType> {
+++ 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::<Object<'_>>());
+++ 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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++//! git_tag_foreach support
+++//! see original: <https://libgit2.org/libgit2/#HEAD/group/tag/git_tag_foreach>
+++
+++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<dyn FnMut(Oid, &[u8]) -> 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: <https://libgit2.org/libgit2/#HEAD/group/callback/git_tag_foreach_cb>
+++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");
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<PathBuf> {
+++ Ok(original.canonicalize()?.to_path_buf())
+++}
+++#[cfg(unix)]
+++pub fn realpath(original: &Path) -> io::Result<PathBuf> {
+++ 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)))
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Ordering> {
+++ 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<Ordering> {
+++ 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(), '+');
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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");
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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)
+++ ))
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++//! 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<Box<dyn SmartSubtransportStream>, 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<T: Read + Write + Send + 'static> SmartSubtransportStream for T {}
+++
+++type TransportFactory = dyn Fn(&Remote<'_>) -> Result<Transport, Error> + 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<TransportFactory>,
+++}
+++
+++/// 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<dyn SmartSubtransport>,
+++}
+++
+++/// 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<dyn SmartSubtransportStream>,
+++}
+++
+++/// 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<F>(prefix: &str, factory: F) -> Result<(), Error>
+++where
+++ F: Fn(&Remote<'_>) -> Result<Transport, Error> + 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<S>(remote: &Remote<'_>, rpc: bool, subtransport: S) -> Result<Transport, Error>
+++ 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<Remote<'a>>,
+++ }
+++ 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<RawSmartSubtransport>>(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<RawSmartSubtransportStream>>(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<Box<dyn SmartSubtransportStream>, 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()),
+++ }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Object<'repo>>,
+++}
+++
+++/// 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<usize>,
+++ 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<i32> for TreeWalkResult {
+++ fn into(self) -> i32 {
+++ self as i32
+++ }
+++}
+++
+++impl Into<raw::git_treewalk_mode> 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<C, T>(&self, mode: TreeWalkMode, mut callback: C) -> Result<(), Error>
+++ where
+++ C: FnMut(&str, &TreeEntry<'_>) -> T,
+++ T: Into<i32>,
+++ {
+++ unsafe {
+++ let mut data = TreeWalkCbData {
+++ callback: &mut callback,
+++ };
+++ try_call!(raw::git_tree_walk(
+++ self.raw(),
+++ mode as raw::git_treewalk_mode,
+++ treewalk_cb::<T>,
+++ &mut data as *mut _ as *mut c_void
+++ ));
+++ Ok(())
+++ }
+++ }
+++
+++ /// Lookup a tree entry by SHA value.
+++ pub fn get_id(&self, id: Oid) -> Option<TreeEntry<'_>> {
+++ 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<TreeEntry<'_>> {
+++ 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<TreeEntry<'_>> {
+++ 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<TreeEntry<'_>> {
+++ 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<TreeEntry<'static>, 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::<Object<'_>>());
+++ 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<T: Into<i32>>(
+++ 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<Object<'a>, 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> {
+++ 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<Ordering> {
+++ 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<TreeEntry<'tree>> {
+++ self.range.next().and_then(|i| self.tree.get(i))
+++ }
+++ fn size_hint(&self) -> (usize, Option<usize>) {
+++ self.range.size_hint()
+++ }
+++ fn nth(&mut self, n: usize) -> Option<TreeEntry<'tree>> {
+++ self.range.nth(n).and_then(|i| self.tree.get(i))
+++ }
+++}
+++impl<'tree> DoubleEndedIterator for TreeIter<'tree> {
+++ fn next_back(&mut self) -> Option<TreeEntry<'tree>> {
+++ 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<TreeEntry<'a>>,
+++ repo: &'a Repository,
+++ }
+++
+++ impl<'a> Iterator for TestTreeIter<'a> {
+++ type Item = TreeEntry<'a>;
+++
+++ fn next(&mut self) -> Option<TreeEntry<'a>> {
+++ 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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<P>(&self, filename: P) -> Result<Option<TreeEntry<'_>>, 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<P: IntoCString>(
+++ &mut self,
+++ filename: P,
+++ oid: Oid,
+++ filemode: i32,
+++ ) -> Result<TreeEntry<'_>, 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<P: IntoCString>(&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<F>(&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<Oid, Error> {
+++ 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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<T> IsNull for *const T {
+++ fn is_ptr_null(&self) -> bool {
+++ self.is_null()
+++ }
+++}
+++impl<T> 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<T>(raw: T) -> Option<Self>
+++ where
+++ T: Copy + IsNull,
+++ Self: Binding<Raw = T>,
+++ {
+++ 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<T, I>(
+++ iter: I,
+++) -> Result<(Vec<CString>, Vec<*const c_char>, raw::git_strarray), Error>
+++where
+++ T: IntoCString,
+++ I: IntoIterator<Item = T>,
+++{
+++ let cstrs = iter
+++ .into_iter()
+++ .map(|i| fixup_windows_path(i.into_c_string()?))
+++ .collect::<Result<Vec<CString>, _>>()?;
+++ 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<T, I>(
+++ iter: I,
+++) -> Result<(Vec<CString>, Vec<*const c_char>, raw::git_strarray), Error>
+++where
+++ T: IntoCString,
+++ I: IntoIterator<Item = T>,
+++{
+++ let cstrs = iter
+++ .into_iter()
+++ .map(|i| i.into_c_string())
+++ .collect::<Result<Vec<CString>, _>>()?;
+++ let ptrs = cstrs.iter().map(|i| i.as_ptr()).collect::<Vec<_>>();
+++ 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<CString, Error>;
+++}
+++
+++impl<'a, T: IntoCString + Clone> IntoCString for &'a T {
+++ fn into_c_string(self) -> Result<CString, Error> {
+++ self.clone().into_c_string()
+++ }
+++}
+++
+++impl<'a> IntoCString for &'a str {
+++ fn into_c_string(self) -> Result<CString, Error> {
+++ Ok(CString::new(self)?)
+++ }
+++}
+++
+++impl IntoCString for String {
+++ fn into_c_string(self) -> Result<CString, Error> {
+++ Ok(CString::new(self.into_bytes())?)
+++ }
+++}
+++
+++impl IntoCString for CString {
+++ fn into_c_string(self) -> Result<CString, Error> {
+++ Ok(self)
+++ }
+++}
+++
+++impl<'a> IntoCString for &'a Path {
+++ fn into_c_string(self) -> Result<CString, Error> {
+++ let s: &OsStr = self.as_ref();
+++ s.into_c_string()
+++ }
+++}
+++
+++impl IntoCString for PathBuf {
+++ fn into_c_string(self) -> Result<CString, Error> {
+++ let s: OsString = self.into();
+++ s.into_c_string()
+++ }
+++}
+++
+++impl<'a> IntoCString for &'a OsStr {
+++ fn into_c_string(self) -> Result<CString, Error> {
+++ self.to_os_string().into_c_string()
+++ }
+++}
+++
+++impl IntoCString for OsString {
+++ #[cfg(unix)]
+++ fn into_c_string(self) -> Result<CString, Error> {
+++ 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<CString, Error> {
+++ 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<CString, Error> {
+++ Ok(CString::new(self)?)
+++ }
+++}
+++
+++impl IntoCString for Vec<u8> {
+++ fn into_c_string(self) -> Result<CString, Error> {
+++ Ok(CString::new(self)?)
+++ }
+++}
+++
+++pub fn into_opt_c_string<S>(opt_s: Option<S>) -> Result<Option<CString>, 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<CString, Error> {
+++ 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<T: IntoCString>(path: T) -> Result<CString, Error> {
+++ fixup_windows_path(path.into_c_string()?)
+++}
+++
+++#[cfg(windows)]
+++fn fixup_windows_path<P: Into<Vec<u8>>>(path: P) -> Result<CString, Error> {
+++ let mut bytes: Vec<u8> = 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<CString, Error> {
+++ 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");
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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()
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++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<Reference<'a>>,
+++}
+++
+++/// 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<String>),
+++}
+++
+++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<Worktree, Error> {
+++ 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<WorktreeLockStatus, Error> {
+++ 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<bool, Error> {
+++ 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);
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++//! 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(())
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++//! 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(())
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++//! 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<dyn std::error::Error>> {
+++ 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(())
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++//! 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(())
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++{"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"}
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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.
--- /dev/null
--- /dev/null
--- /dev/null
+++# 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 <josh@joshtriplett.org>",
+++ "Alex Crichton <alex@alexcrichton.com>",
+++]
+++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
--- /dev/null
--- /dev/null
--- /dev/null
+++ 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.
--- /dev/null
--- /dev/null
--- /dev/null
+++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.
--- /dev/null
--- /dev/null
--- /dev/null
+++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<pkg_config::Library, pkg_config::Error> {
+++ 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<Path>, to: impl AsRef<Path>) {
+++ 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<Path>) {
+++ 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::<io::Result<Vec<_>>>().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);
+++ }
+++ }
+++}
--- /dev/null
--- /dev/null
--- /dev/null
+++#![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<extern "C" fn(*const c_char, size_t, size_t, *mut c_void)>;
+++
+++pub type git_checkout_perfdata_cb =
+++ Option<extern "C" fn(*const git_checkout_perfdata, *mut c_void)>;
+++
+++#[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<extern "C" fn(*const git_indexer_progress, *mut c_void) -> 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<extern "C" fn(*mut git_remote, c_int, *mut c_void) -> 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<extern "C" fn(git_remote_completion_type, *mut c_void) -> 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<extern "C" fn(*const c_char, *const git_oid, *const git_oid, *mut c_void) -> 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<extern "C" fn(*const c_char, c_int, *mut c_void) -> 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<extern "C" fn(*const git_indexer_progress, *mut c_void) -> c_int>;
+++pub type git_packbuilder_progress =
+++ Option<extern "C" fn(git_packbuilder_stage_t, c_uint, c_uint, *mut c_void) -> c_int>;
+++pub type git_push_transfer_progress =
+++ Option<extern "C" fn(c_uint, c_uint, size_t, *mut c_void) -> c_int>;
+++pub type git_transport_certificate_check_cb =
+++ Option<extern "C" fn(*mut git_cert, c_int, *const c_char, *mut c_void) -> c_int>;
+++pub type git_push_negotiation =
+++ Option<extern "C" fn(*mut *const git_push_update, size_t, *mut c_void) -> c_int>;
+++
+++pub type git_push_update_reference_cb =
+++ Option<extern "C" fn(*const c_char, *const c_char, *mut c_void) -> c_int>;
+++pub type git_url_resolve_cb =
+++ Option<extern "C" fn(*mut git_buf, *const c_char, c_int, *mut c_void) -> 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<extern "C" fn(*mut *mut git_repository, *const c_char, c_int, *mut c_void) -> 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<extern "C" fn(*const git_tree_entry, *mut c_void) -> c_int>;
+++
+++pub type git_revwalk_hide_cb = Option<extern "C" fn(*const git_oid, *mut c_void) -> 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<extern "C" fn(*const c_char, *const c_char, *mut c_void) -> 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<extern "C" fn(*mut git_submodule, *const c_char, *mut c_void) -> 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<extern "C" fn(*mut git_writestream, *const c_char, size_t) -> c_int>,
+++ pub close: Option<extern "C" fn(*mut git_writestream) -> c_int>,
+++ pub free: Option<extern "C" fn(*mut git_writestream)>,
+++}
+++
+++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<extern "C" fn(*mut git_cred)>,
+++}
+++
+++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<extern "C" fn(name: *const c_char, oid: *mut git_oid, payload: *mut c_void) -> 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<extern "C" fn(*const git_diff_delta, f32, *mut c_void) -> c_int>;
+++pub type git_diff_hunk_cb =
+++ Option<extern "C" fn(*const git_diff_delta, *const git_diff_hunk, *mut c_void) -> 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<extern "C" fn(*const git_diff_delta, *const git_diff_binary, *mut c_void) -> 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<extern "C" fn(*const git_diff, *const c_char, *const c_char, *mut c_void) -> 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<extern "C" fn(*mut c_void, *mut c_void)>,
+++ pub similarity:
+++ Option<extern "C" fn(*mut c_int, *mut c_void, *mut c_void, *mut c_void) -> 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<extern "C" fn(capabilities: *mut c_uint, transport: *mut git_transport) -> 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<extern "C" fn(transport: *mut git_transport, push: *mut git_push) -> 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<extern "C" fn(out: *mut git_oidarray, transport: *mut git_transport) -> 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<extern "C" fn(transport: *mut git_transport) -> c_int>,
+++ pub cancel: Option<extern "C" fn(transport: *mut git_transport)>,
+++ pub close: Option<extern "C" fn(transport: *mut git_transport) -> c_int>,
+++ pub free: Option<extern "C" fn(transport: *mut git_transport)>,
+++}
+++
+++#[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<extern "C" fn(*mut git_odb_backend, *const git_oid) -> c_int>,
+++
+++ pub exists_prefix:
+++ Option<extern "C" fn(*mut git_oid, *mut git_odb_backend, *const git_oid, size_t) -> c_int>,
+++
+++ pub refresh: Option<extern "C" fn(*mut git_odb_backend) -> c_int>,
+++
+++ pub foreach:
+++ Option<extern "C" fn(*mut git_odb_backend, git_odb_foreach_cb, *mut c_void) -> 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<extern "C" fn(*mut git_odb_backend) -> c_int>,
+++
+++ pub freshen: Option<extern "C" fn(*mut git_odb_backend, *const git_oid) -> c_int>,
+++
+++ pub free: Option<extern "C" fn(*mut git_odb_backend)>,
+++}
+++
+++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<unsafe extern "C" fn(*mut git_odb_writepack, *mut git_indexer_progress) -> c_int>,
+++
+++ pub free: Option<unsafe extern "C" fn(*mut git_odb_writepack)>,
+++}
+++
+++#[repr(C)]
+++pub struct git_refdb_backend {
+++ pub version: c_uint,
+++ pub exists: Option<extern "C" fn(*mut c_int, *mut git_refdb_backend, *const c_char) -> 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<extern "C" fn(*mut git_refdb_backend) -> c_int>,
+++ pub has_log: Option<extern "C" fn(*mut git_refdb_backend, *const c_char) -> c_int>,
+++ pub ensure_log: Option<extern "C" fn(*mut git_refdb_backend, *const c_char) -> c_int>,
+++ pub free: Option<extern "C" fn(*mut git_refdb_backend)>,
+++ pub reflog_read:
+++ Option<extern "C" fn(*mut *mut git_reflog, *mut git_refdb_backend, *const c_char) -> c_int>,
+++ pub reflog_write: Option<extern "C" fn(*mut git_refdb_backend, *mut git_reflog) -> c_int>,
+++ pub reflog_rename:
+++ Option<extern "C" fn(*mut git_refdb_backend, *const c_char, *const c_char) -> c_int>,
+++ pub reflog_delete: Option<extern "C" fn(*mut git_refdb_backend, *const c_char) -> c_int>,
+++ pub lock:
+++ Option<extern "C" fn(*mut *mut c_void, *mut git_refdb_backend, *const c_char) -> 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<extern "C" fn(*mut git_smart_subtransport_stream, *const c_char, size_t) -> c_int>,
+++ pub free: Option<extern "C" fn(*mut git_smart_subtransport_stream)>,
+++}
+++
+++#[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<extern "C" fn(*mut git_smart_subtransport) -> c_int>,
+++ pub free: Option<extern "C" fn(*mut git_smart_subtransport)>,
+++}
+++
+++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<extern "C" fn(progress: git_stash_apply_progress_t, payload: *mut c_void) -> 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<extern "C" fn(*const c_void, size_t, *mut c_void) -> c_int>;
+++
+++pub type git_odb_foreach_cb =
+++ Option<extern "C" fn(id: *const git_oid, payload: *mut c_void) -> 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<extern "C" fn(delta: *const git_diff_delta, payload: *mut c_void) -> c_int>;
+++
+++pub type git_apply_hunk_cb =
+++ Option<extern "C" fn(hunk: *const git_diff_hunk, payload: *mut c_void) -> 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<extern "C" fn(oid: *const git_oid, payload: *mut c_void) -> 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<extern "C" fn(level: git_trace_level_t, msg: *const c_char)>;
+++
+++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)
+++}