Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml10
-rw-r--r--CHANGELOG.md22
-rw-r--r--CMakeLists.txt15
-rw-r--r--README.md9
-rw-r--r--examples/general.c4
-rw-r--r--examples/network/fetch.c4
-rw-r--r--examples/rev-list.c4
-rw-r--r--examples/showindex.c4
-rw-r--r--include/git2.h2
-rw-r--r--include/git2/common.h16
-rw-r--r--include/git2/describe.h162
-rw-r--r--include/git2/errors.h2
-rw-r--r--include/git2/merge.h15
-rw-r--r--include/git2/reflog.h2
-rw-r--r--include/git2/remote.h24
-rw-r--r--include/git2/reset.h5
-rw-r--r--include/git2/sys/hashsig.h (renamed from src/hashsig.h)18
-rw-r--r--include/git2/sys/refdb_backend.h13
-rw-r--r--include/git2/sys/repository.h13
-rw-r--r--include/git2/sys/transport.h4
-rw-r--r--include/git2/transaction.h111
-rw-r--r--include/git2/transport.h61
-rw-r--r--include/git2/types.h42
-rwxr-xr-xscript/cibuild.sh7
-rw-r--r--src/attr.c12
-rw-r--r--src/cc-compat.h8
-rw-r--r--src/clone.c4
-rw-r--r--src/commit_list.h2
-rw-r--r--src/config_file.c2
-rw-r--r--src/describe.c871
-rw-r--r--src/diff_patch.c1
-rw-r--r--src/diff_tform.c2
-rw-r--r--src/fileops.c8
-rw-r--r--src/filter.c13
-rw-r--r--src/global.c3
-rw-r--r--src/global.h3
-rw-r--r--src/hashsig.c2
-rw-r--r--src/ignore.c4
-rw-r--r--src/index.c53
-rw-r--r--src/merge.c93
-rw-r--r--src/netops.c14
-rw-r--r--src/netops.h4
-rw-r--r--src/odb_loose.c2
-rw-r--r--src/oidmap.h16
-rw-r--r--src/pack.c2
-rw-r--r--src/path.c32
-rw-r--r--src/path.h2
-rw-r--r--src/pool.c2
-rw-r--r--src/posix.c7
-rw-r--r--src/posix.h2
-rw-r--r--src/refdb.c19
-rw-r--r--src/refdb.h3
-rw-r--r--src/refdb_fs.c118
-rw-r--r--src/reflog.c2
-rw-r--r--src/refs.c6
-rw-r--r--src/refs.h2
-rw-r--r--src/remote.c215
-rw-r--r--src/remote.h3
-rw-r--r--src/repository.c30
-rw-r--r--src/reset.c4
-rw-r--r--src/revwalk.c118
-rw-r--r--src/revwalk.h9
-rw-r--r--src/settings.c22
-rw-r--r--src/signature.c24
-rw-r--r--src/signature.h2
-rw-r--r--src/stash.c38
-rw-r--r--src/thread-utils.h4
-rw-r--r--src/transaction.c352
-rw-r--r--src/transports/http.c67
-rw-r--r--src/transports/smart.c2
-rw-r--r--src/transports/smart.h1
-rw-r--r--src/transports/smart_protocol.c6
-rw-r--r--src/transports/ssh.c50
-rw-r--r--src/transports/winhttp.c142
-rw-r--r--src/userdiff.h6
-rw-r--r--tests/attr/repo.c43
-rw-r--r--tests/blame/blame_helpers.c2
-rw-r--r--tests/checkout/conflict.c6
-rw-r--r--tests/checkout/tree.c2
-rw-r--r--tests/cherrypick/workdir.c59
-rw-r--r--tests/config/stress.c12
-rw-r--r--tests/core/buffer.c2
-rw-r--r--tests/core/path.c53
-rw-r--r--tests/describe/describe.c50
-rw-r--r--tests/describe/describe_helpers.c42
-rw-r--r--tests/describe/describe_helpers.h15
-rw-r--r--tests/describe/t6120.c156
-rw-r--r--tests/fetchhead/fetchhead_data.h15
-rw-r--r--tests/fetchhead/nonetwork.c2
-rw-r--r--tests/index/names.c4
-rw-r--r--tests/index/reuc.c8
-rw-r--r--tests/merge/merge_helpers.c2
-rw-r--r--tests/merge/merge_helpers.h8
-rw-r--r--tests/merge/trees/treediff.c2
-rw-r--r--tests/merge/workdir/dirty.c8
-rw-r--r--tests/merge/workdir/simple.c4
-rw-r--r--tests/merge/workdir/submodules.c4
-rw-r--r--tests/network/fetchlocal.c38
-rw-r--r--tests/network/remote/local.c114
-rw-r--r--tests/network/remote/remotes.c1
-rw-r--r--tests/object/raw/chars.c2
-rw-r--r--tests/odb/foreach.c2
-rw-r--r--tests/online/clone.c87
-rw-r--r--tests/online/fetch.c10
-rw-r--r--tests/online/fetchhead.c20
-rw-r--r--tests/online/push.c2
-rw-r--r--tests/online/push_util.h2
-rw-r--r--tests/pack/packbuilder.c6
-rw-r--r--tests/path/core.c2
-rw-r--r--tests/refs/transactions.c110
-rw-r--r--tests/repo/init.c1
-rw-r--r--tests/reset/hard.c14
-rw-r--r--tests/reset/mixed.c10
-rw-r--r--tests/reset/soft.c22
-rw-r--r--tests/resources/config/config126
-rw-r--r--tests/resources/describe/.gitted/HEAD1
-rw-r--r--tests/resources/describe/.gitted/config8
-rw-r--r--tests/resources/describe/.gitted/indexbin0 -> 262 bytes
-rw-r--r--tests/resources/describe/.gitted/logs/HEAD14
-rw-r--r--tests/resources/describe/.gitted/logs/refs/heads/master14
-rw-r--r--tests/resources/describe/.gitted/objects/03/00021985931292d0611b9232e757035fefc04dbin0 -> 108 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/10/8b485d8268ea595df8ffea74f0f4b186577d32bin0 -> 125 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/10/bd08b099ecb79184c60183f5c94ca915f427adbin0 -> 127 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/17/8481050188cf00d7d9cd5a11e43ab8fab9294fbin0 -> 17 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/19/1faf88a5826a99f475baaf8b13652c4e40bfe6bin0 -> 19 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/1e/016431ec7b22dd3e23f3e6f5f68f358f9227cfbin0 -> 156 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/22/3b7836fb19fdf64ba2d3cd6173c6a283141f78bin0 -> 17 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/25/d5edf8c0ef17e8a13b8da75913dcec4ea7afc1bin0 -> 87 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/2b/df67abb163a4ffb2d7f3f0880c9fe5068ce782bin0 -> 21 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/31/fc9136820b507e938a9c6b88bf2c567a9f6f4bbin0 -> 153 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/42/8f9554a2eec22de29898819b579466af7c1583bin0 -> 80 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/4d/6558b8fa764baeb0f19c1e857df91e0eda5a0fbin0 -> 155 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/4f/2d9ce01ad5249cabdc6565366af8aff85b1525bin0 -> 18 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/52/912fbab0715dec53d43053966e78ad213ba359bin0 -> 127 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/56/26abf0f72e58d7a153368ba57db4c673c0e171bin0 -> 19 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/61/26a5f9c57ebc81e64370ec3095184ad92dab1cbin0 -> 151 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/62/d8fe9f6db631bd3a19140699101c9e281c9f9dbin0 -> 17 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/65/a91bc2262480dce4c5979519aae6668368eb4ebin0 -> 77 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/68/0166b6cd31f76354fee2572618e6b0142d05e62
-rw-r--r--tests/resources/describe/.gitted/objects/69/3a3de402bb23897ed5c931273e53c78eff0495bin0 -> 49 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/6a/12b56088706aa6c39ccd23b7c7ce60f3a0b9a1bin0 -> 154 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/6d/218e42592043041c4da016ff298cf241b86c3cbin0 -> 77 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/75/bb152c600647586c226d98411b1d2f9861af5abin0 -> 80 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/81/f4b1aac643e6983fab370eae8aefccecbf3a4cbin0 -> 152 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/8e/c1d96451ff05451720e4e8968812c46b35e5e4bin0 -> 49 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/94/9b98e208015bfc0e2f573debc34ae2f97a7f0ebin0 -> 186 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/9c/06d71b8406ab97537e3acdc39a2c4ade7a9411bin0 -> 49 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/a6/095f816e81f64651595d488badc42399837d6abin0 -> 153 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/a9/e3325a07117aa5381e044a8d96c26eb30d729dbin0 -> 49 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/a9/eb02af13df030159e39f70330d5c8a476556912
-rw-r--r--tests/resources/describe/.gitted/objects/aa/d8d5cef3915ab78b3227abaaac99b62db9eb54bin0 -> 49 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/aa/ddd4f14847e0e323924ec262c2343249a84f8bbin0 -> 125 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/b2/40c0fb88c5a629e00ebc1275fa1f33e364a7053
-rw-r--r--tests/resources/describe/.gitted/objects/ce/1c4f8b6120122e23d4442925d98c56c41917d8bin0 -> 187 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/d5/aab219a814ddbe4b3aaedf03cdea491b218ec4bin0 -> 80 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/f2/ad6c76f0115a6ba5b00456a849810e7ec0af20bin0 -> 17 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/f7/0f10e4db19068f79bc43844b49f3eece45c4e8bin0 -> 17 bytes
-rw-r--r--tests/resources/describe/.gitted/objects/f7/19efd430d52bcfc8566a43b2eb655688d38871bin0 -> 19 bytes
-rw-r--r--tests/resources/describe/.gitted/refs/heads/master1
-rw-r--r--tests/resources/describe/.gitted/refs/tags/A1
-rw-r--r--tests/resources/describe/.gitted/refs/tags/B1
-rw-r--r--tests/resources/describe/.gitted/refs/tags/D1
-rw-r--r--tests/resources/describe/.gitted/refs/tags/R1
-rw-r--r--tests/resources/describe/.gitted/refs/tags/c1
-rw-r--r--tests/resources/describe/.gitted/refs/tags/e1
-rw-r--r--tests/resources/describe/another1
-rw-r--r--tests/resources/describe/file1
-rw-r--r--tests/resources/describe/side1
-rw-r--r--tests/resources/userdiff/.gitted/indexbin1336 -> 1558 bytes
-rw-r--r--tests/resources/userdiff/.gitted/objects/09/65b377c214bbe5e0d18fcdaf556df7fa7ed7c8bin0 -> 850 bytes
-rw-r--r--tests/resources/userdiff/.gitted/objects/0c/20ef1409ae1df4d5a76cdbd98d5c33ccdb6bccbin0 -> 120 bytes
-rw-r--r--tests/resources/userdiff/.gitted/objects/39/ea75107a09091ba54ff86fcc780b59477e42cdbin0 -> 854 bytes
-rw-r--r--tests/resources/userdiff/.gitted/objects/3c/c08384deae5957247bc36776ab626cc9e0582bbin0 -> 116 bytes
-rw-r--r--tests/resources/userdiff/.gitted/objects/46/8d6f2afc940e14c76347fa9af26e429a3c9044bin0 -> 851 bytes
-rw-r--r--tests/resources/userdiff/.gitted/objects/53/917973acfe0111f93c2cfaacf854be245880e8bin0 -> 846 bytes
-rw-r--r--tests/resources/userdiff/.gitted/objects/63/1d44e0c72e8cd1b594fa11d7d1ee8a6d67ff67bin0 -> 183 bytes
-rw-r--r--tests/resources/userdiff/.gitted/objects/f3/be389d351e4bcc6dcc4b5fe22134ef0f63f8bdbin0 -> 117 bytes
-rw-r--r--tests/resources/userdiff/after/file.javascript188
-rw-r--r--tests/resources/userdiff/before/file.javascript190
-rw-r--r--tests/resources/userdiff/expected/driver/diff.javascript55
-rw-r--r--tests/resources/userdiff/expected/nodriver/diff.javascript55
-rw-r--r--tests/resources/userdiff/files/file.javascript188
-rw-r--r--tests/revert/workdir.c28
-rw-r--r--tests/revwalk/basic.c8
-rw-r--r--tests/revwalk/mergebase.c24
-rw-r--r--tests/stash/save.c17
-rw-r--r--tests/threads/basic.c14
-rw-r--r--tests/transport/register.c2
188 files changed, 3963 insertions, 786 deletions
diff --git a/.travis.yml b/.travis.yml
index 362b88224..589edfa36 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -31,8 +31,14 @@ matrix:
- compiler: gcc
env: COVERITY=1
os: linux
+ - compiler: gcc
+ env:
+ - VALGRIND=1
+ OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=Debug"
+ os: linux
allow_failures:
- env: COVERITY=1
+ - env: VALGRIND=1
install:
- ./script/install-deps-${TRAVIS_OS_NAME}.sh
@@ -43,8 +49,8 @@ script:
# Run Tests
after_success:
- - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install valgrind; fi
- - if [ "$TRAVIS_OS_NAME" = "linux" ]; then valgrind --leak-check=full --show-reachable=yes --suppressions=./libgit2_clar.supp _build/libgit2_clar -ionline; fi
+ - if [ "$TRAVIS_OS_NAME" = "linux" -a -n "$VALGRIND" ]; then sudo apt-get -qq install valgrind; fi
+ - if [ "$TRAVIS_OS_NAME" = "linux" -a -n "$VALGRIND" ]; then valgrind --leak-check=full --show-reachable=yes --suppressions=./libgit2_clar.supp _build/libgit2_clar -ionline; fi
# Only watch the development and master branches
branches:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4664c4d41..82733f653 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,11 @@ v0.21 + 1
* Use a map for the treebuilder, making insertion O(1)
+* Introduce reference transactions, which allow multiple references to
+ be locked at the same time and updates be queued. This also allows
+ us to safely update a reflog with arbitrary contents, as we need to
+ do for stash.
+
* LF -> CRLF filter refuses to handle mixed-EOL files
* LF -> CRLF filter now runs when * text = auto (with Git for Windows 1.9.4)
@@ -21,6 +26,10 @@ v0.21 + 1
as, so this introduces the USERNAME credential type which the ssh
transport will use to ask for the username.
+* The build system now accepts an option EMBED_SSH_PATH which when set
+ tells it to include a copy of libssh2 at the given location. This is
+ enabled for MSVC.
+
* The git_transport_register function no longer takes a priority and takes
a URL scheme name (eg "http") instead of a prefix like "http://"
@@ -46,11 +55,24 @@ v0.21 + 1
repository_cb_payload to allow the user to create a repository with
custom options.
+* The option to ignore certificate errors via git_remote_cert_check()
+ is no longer present. Instead, git_remote_callbacks has gained a new
+ entry which lets the user perform their own certificate checks.
+
* git_clone_into and git_clone_local_into have been removed from the
public API in favour of git_clone callbacks
* Add support for refspecs with the asterisk in the middle of a
pattern.
+* Fetching now performs opportunistic updates. To achieve this, we
+ introduce a difference between active and passive refspecs, which
+ make git_remote_download and git_remote_fetch to take a list of
+ resfpecs to be the active list, similarly to how git fetch accepts a
+ list on the command-line.
+
* Introduce git_merge_bases() and the git_oidarray type to expose all
merge bases between two commits.
+
+* Introduce git_merge_bases_many() to expose all merge bases between
+ multiple commits.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 76cca4f22..7da4a8963 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -60,6 +60,10 @@ IF(MSVC)
# HTTP transport, invoke CMake with the "-DWINHTTP=OFF" argument.
OPTION( WINHTTP "Use Win32 WinHTTP routines" ON )
+ # If you want to embed a copy of libssh2 into libgit2, pass a
+ # path to libssh2
+ OPTION( EMBED_SSH_PATH "Path to libssh2 to embed (Windows)" OFF )
+
ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE)
@@ -134,6 +138,13 @@ STRING(REGEX REPLACE "^.*LIBGIT2_SOVERSION ([0-9]+)$" "\\1" LIBGIT2_SOVERSION "$
# Find required dependencies
INCLUDE_DIRECTORIES(src include)
+IF (WIN32 AND EMBED_SSH_PATH)
+ FILE(GLOB SRC_SSH "${EMBED_SSH_PATH}/src/*.c")
+ INCLUDE_DIRECTORIES("${EMBED_SSH_PATH}/include")
+ FILE(WRITE "${EMBED_SSH_PATH}/src/libssh2_config.h" "#define HAVE_WINCNG\n#define LIBSSH2_WINCNG\n#include \"../win32/libssh2_config.h\"")
+ ADD_DEFINITIONS(-DGIT_SSH)
+ENDIF()
+
IF (WIN32 AND WINHTTP AND NOT MINGW)
ADD_DEFINITIONS(-DGIT_WINHTTP)
INCLUDE_DIRECTORIES(deps/http-parser)
@@ -393,7 +404,7 @@ ELSE()
ENDIF()
# Compile and link libgit2
-ADD_LIBRARY(git2 ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1} ${WIN_RC})
+ADD_LIBRARY(git2 ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SSH} ${SRC_SHA1} ${WIN_RC})
TARGET_LINK_LIBRARIES(git2 ${SSL_LIBRARIES})
TARGET_LINK_LIBRARIES(git2 ${SSH_LIBRARIES})
TARGET_LINK_LIBRARIES(git2 ${GSSAPI_LIBRARIES})
@@ -459,7 +470,7 @@ IF (BUILD_CLAR)
${CLAR_PATH}/clar.c
PROPERTIES OBJECT_DEPENDS ${CLAR_PATH}/clar.suite)
- ADD_EXECUTABLE(libgit2_clar ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_CLAR} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1})
+ ADD_EXECUTABLE(libgit2_clar ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_CLAR} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SSH} ${SRC_SHA1})
TARGET_LINK_LIBRARIES(libgit2_clar ${SSL_LIBRARIES})
TARGET_LINK_LIBRARIES(libgit2_clar ${SSH_LIBRARIES})
diff --git a/README.md b/README.md
index 0020a7762..b315eed1a 100644
--- a/README.md
+++ b/README.md
@@ -55,7 +55,7 @@ dependencies, it can make use of a few libraries to add to it:
- pthreads (non-Windows) to enable threadsafe access as well as multi-threaded pack generation
- OpenSSL (non-Windows) to talk over HTTPS and provide the SHA-1 functions
-- LibSSH2 to enable the ssh transport
+- LibSSH2 to enable the SSH transport
- iconv (OSX) to handle the HFS+ path encoding peculiarities
Building libgit2 - Using CMake
@@ -119,8 +119,7 @@ You need to run the CMake commands from the Visual Studio command
prompt, not the regular or Windows SDK one. Select the right generator
for your version with the `-G "Visual Studio X" option.
-See [the wiki]
-(https://github.com/libgit2/libgit2/wiki/Building-libgit2-on-Windows)
+See [the website](https://libgit2.github.com/docs/guides/build-and-link)
for more detailed instructions.
Android
@@ -195,6 +194,8 @@ Here are the bindings to libgit2 that are currently available:
* git2r <https://github.com/ropensci/git2r>
* Ruby
* Rugged <https://github.com/libgit2/rugged>
+* Rust
+ * git2-rs <https://github.com/alexcrichton/git2-rs>
* Vala
* libgit2.vapi <https://github.com/apmasell/vapis/blob/master/libgit2.vapi>
@@ -211,7 +212,7 @@ workflow, the libgit2 [coding conventions](CONVENTIONS.md), and out list of
License
==================================
-`libgit2` is under GPL2 **with linking exemption**. This means you can link to
+`libgit2` is under GPL2 **with linking exception**. This means you can link to
and use the library from any program, proprietary or open source; paid or
gratis. However, you cannot modify libgit2 and distribute it without
supplying the source.
diff --git a/examples/general.c b/examples/general.c
index ae8756338..051d69380 100644
--- a/examples/general.c
+++ b/examples/general.c
@@ -94,8 +94,8 @@ int main (int argc, char** argv)
// Next we will convert the 20 byte raw SHA1 value to a human readable 40
// char hex value.
printf("\n*Raw to Hex*\n");
- char out[41];
- out[40] = '\0';
+ char out[GIT_OID_HEXSZ+1];
+ out[GIT_OID_HEXSZ] = '\0';
// If you have a oid, you can easily get the hex value of the SHA as well.
git_oid_fmt(out, &oid);
diff --git a/examples/network/fetch.c b/examples/network/fetch.c
index 03f1541a4..ab78fc9bd 100644
--- a/examples/network/fetch.c
+++ b/examples/network/fetch.c
@@ -36,7 +36,7 @@ static void *download(void *ptr)
// 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.
- if (git_remote_download(data->remote) < 0) {
+ if (git_remote_download(data->remote, NULL) < 0) {
data->ret = -1;
goto exit;
}
@@ -155,7 +155,7 @@ int fetch(git_repository *repo, int argc, char **argv)
// 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 neede objects are available locally.
+ // changed but all the needed objects are available locally.
if (git_remote_update_tips(remote, NULL, NULL) < 0)
return -1;
diff --git a/examples/rev-list.c b/examples/rev-list.c
index 5c0d751a3..940a01136 100644
--- a/examples/rev-list.c
+++ b/examples/rev-list.c
@@ -22,7 +22,7 @@ int main (int argc, char **argv)
git_repository *repo;
git_revwalk *walk;
git_oid oid;
- char buf[41];
+ char buf[GIT_OID_HEXSZ+1];
git_threads_init();
@@ -32,7 +32,7 @@ int main (int argc, char **argv)
while (!git_revwalk_next(&oid, walk)) {
git_oid_fmt(buf, &oid);
- buf[40] = '\0';
+ buf[GIT_OID_HEXSZ] = '\0';
printf("%s\n", buf);
}
diff --git a/examples/showindex.c b/examples/showindex.c
index ad4a16e8e..604124f12 100644
--- a/examples/showindex.c
+++ b/examples/showindex.c
@@ -20,8 +20,8 @@ int main (int argc, char** argv)
unsigned int i, ecount;
char *dir = ".";
size_t dirlen;
- char out[41];
- out[40] = '\0';
+ char out[GIT_OID_HEXSZ+1];
+ out[GIT_OID_HEXSZ] = '\0';
git_threads_init();
diff --git a/include/git2.h b/include/git2.h
index f74976061..baa7fcaf8 100644
--- a/include/git2.h
+++ b/include/git2.h
@@ -19,6 +19,7 @@
#include "git2/commit.h"
#include "git2/common.h"
#include "git2/config.h"
+#include "git2/describe.h"
#include "git2/diff.h"
#include "git2/errors.h"
#include "git2/filter.h"
@@ -32,6 +33,7 @@
#include "git2/notes.h"
#include "git2/object.h"
#include "git2/odb.h"
+#include "git2/odb_backend.h"
#include "git2/oid.h"
#include "git2/pack.h"
#include "git2/patch.h"
diff --git a/include/git2/common.h b/include/git2/common.h
index 32237efed..ddeaf77a2 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -83,6 +83,8 @@ GIT_BEGIN_DECL
*/
#define GIT_OID_HEX_ZERO "0000000000000000000000000000000000000000"
+#define FLAG_BITS 27
+
/**
* Return the version of the libgit2 library
* being currently used.
@@ -136,7 +138,8 @@ typedef enum {
GIT_OPT_ENABLE_CACHING,
GIT_OPT_GET_CACHED_MEMORY,
GIT_OPT_GET_TEMPLATE_PATH,
- GIT_OPT_SET_TEMPLATE_PATH
+ GIT_OPT_SET_TEMPLATE_PATH,
+ GIT_OPT_SET_SSL_CERT_LOCATIONS,
} git_libgit2_opt_t;
/**
@@ -221,6 +224,17 @@ typedef enum {
* >
* > - `path` directory of template.
*
+ * * opts(GIT_OPT_SET_SSL_CERT_LOCATIONS, const char *file, const char *path)
+ *
+ * > Set the SSL certificate-authority locations.
+ * >
+ * > - `file` is the location of a file containing several
+ * > certificates concatenated together.
+ * > - `path` is the location of a directory holding several
+ * > certificates, one per file.
+ * >
+ * > Either parameter may be `NULL`, but not both.
+ *
* @param option Option key
* @param ... value to set the option
* @return 0 on success, <0 on failure
diff --git a/include/git2/describe.h b/include/git2/describe.h
new file mode 100644
index 000000000..66b88c4fa
--- /dev/null
+++ b/include/git2/describe.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_git_describe_h__
+#define INCLUDE_git_describe_h__
+
+#include "common.h"
+#include "types.h"
+#include "buffer.h"
+
+/**
+ * @file git2/describe.h
+ * @brief Git describing routines
+ * @defgroup git_describe Git describing routines
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Reference lookup strategy
+ *
+ * These behave like the --tags and --all optios to git-describe,
+ * namely they say to look for any reference in either refs/tags/ or
+ * refs/ respectively.
+ */
+typedef enum {
+ GIT_DESCRIBE_DEFAULT,
+ GIT_DESCRIBE_TAGS,
+ GIT_DESCRIBE_ALL,
+} git_describe_strategy_t;
+
+/**
+ * Describe options structure
+ *
+ * Initialize with `GIT_DESCRIBE_OPTIONS_INIT` macro to correctly set
+ * the `version` field. E.g.
+ *
+ * git_describe_options opts = GIT_DESCRIBE_OPTIONS_INIT;
+ */
+typedef struct git_describe_options {
+ unsigned int version;
+
+ unsigned int max_candidates_tags; /** default: 10 */
+ unsigned int describe_strategy; /** default: GIT_DESCRIBE_DEFAULT */
+ const char *pattern;
+ /**
+ * When calculating the distance from the matching tag or
+ * reference, only walk down the first-parent ancestry.
+ */
+ int only_follow_first_parent;
+ /**
+ * If no matching tag or reference is found, the describe
+ * operation would normally fail. If this option is set, it
+ * will instead fall back to showing the full id of the
+ * commit.
+ */
+ int show_commit_oid_as_fallback;
+} git_describe_options;
+
+#define GIT_DESCRIBE_DEFAULT_MAX_CANDIDATES_TAGS 10
+#define GIT_DESCRIBE_DEFAULT_ABBREVIATED_SIZE 7
+
+#define GIT_DESCRIBE_OPTIONS_VERSION 1
+#define GIT_DESCRIBE_OPTIONS_INIT { \
+ GIT_DESCRIBE_OPTIONS_VERSION, \
+ GIT_DESCRIBE_DEFAULT_MAX_CANDIDATES_TAGS, \
+}
+
+GIT_EXTERN(int) git_describe_init_options(git_describe_options *opts, unsigned int version);
+
+/**
+ * Options for formatting the describe string
+ */
+typedef struct {
+ unsigned int version;
+
+ /**
+ * Size of the abbreviated commit id to use. This value is the
+ * lower bound for the length of the abbreviated string. The
+ * default is 7.
+ */
+ unsigned int abbreviated_size;
+
+ /**
+ * Set to use the long format even when a shorter name could be used.
+ */
+ int always_use_long_format;
+
+ /**
+ * If the workdir is dirty and this is set, this string will
+ * be appended to the description string.
+ */
+ char *dirty_suffix;
+} git_describe_format_options;
+
+#define GIT_DESCRIBE_FORMAT_OPTIONS_VERSION 1
+#define GIT_DESCRIBE_FORMAT_OPTIONS_INIT { \
+ GIT_DESCRIBE_FORMAT_OPTIONS_VERSION, \
+ GIT_DESCRIBE_DEFAULT_ABBREVIATED_SIZE, \
+ }
+
+GIT_EXTERN(int) git_describe_init_format_options(git_describe_format_options *opts, unsigned int version);
+
+typedef struct git_describe_result git_describe_result;
+
+/**
+ * Describe a commit
+ *
+ * Perform the describe operation on the given committish object.
+ *
+ * @param result pointer to store the result. You must free this once
+ * you're done with it.
+ * @param committish a committish to describe
+ * @param opts the lookup options
+ */
+GIT_EXTERN(int) git_describe_commit(
+ git_describe_result **result,
+ git_object *committish,
+ git_describe_options *opts);
+
+/**
+ * Describe a commit
+ *
+ * Perform the describe operation on the current commit and the
+ * worktree. After peforming describe on HEAD, a status is run and the
+ * description is considered to be dirty if there are.
+ *
+ * @param result pointer to store the result. You must free this once
+ * you're done with it.
+ * @param repo the repository in which to perform the describe
+ * @param opts the lookup options
+ */
+GIT_EXTERN(int) git_describe_workdir(
+ git_describe_result **out,
+ git_repository *repo,
+ git_describe_options *opts);
+
+/**
+ * Print the describe result to a buffer
+ *
+ * @param result the result from `git_describe_commit()` or
+ * `git_describe_workdir()`.
+ * @param opt the formatting options
+ */
+GIT_EXTERN(int) git_describe_format(
+ git_buf *out,
+ const git_describe_result *result,
+ const git_describe_format_options *opts);
+
+/**
+ * Free the describe result.
+ */
+GIT_EXTERN(void) git_describe_result_free(git_describe_result *result);
+
+/** @} */
+GIT_END_DECL
+
+#endif
diff --git a/include/git2/errors.h b/include/git2/errors.h
index b91560631..1e3ed3acb 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -42,6 +42,7 @@ typedef enum {
GIT_ELOCKED = -14, /**< Lock file prevented operation */
GIT_EMODIFIED = -15, /**< Reference value does not match expected */
GIT_EAUTH = -16, /**< Authentication error */
+ GIT_ECERTIFICATE = -17, /**< Server certificate is invalid */
GIT_PASSTHROUGH = -30, /**< Internal only */
GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */
@@ -88,6 +89,7 @@ typedef enum {
GITERR_REVERT,
GITERR_CALLBACK,
GITERR_CHERRYPICK,
+ GITERR_DESCRIBE,
} git_error_t;
/**
diff --git a/include/git2/merge.h b/include/git2/merge.h
index bd5ebc1bd..ed1b9a30f 100644
--- a/include/git2/merge.h
+++ b/include/git2/merge.h
@@ -352,6 +352,21 @@ GIT_EXTERN(int) git_merge_base_many(
const git_oid input_array[]);
/**
+ * Find all merge bases given a list of commits
+ *
+ * @param out array in which to store the resulting ids
+ * @param repo the repository where the commits exist
+ * @param length The number of commits in the provided `input_array`
+ * @param input_array oids of the commits
+ * @return Zero on success; GIT_ENOTFOUND or -1 on failure.
+ */
+GIT_EXTERN(int) git_merge_bases_many(
+ git_oidarray *out,
+ git_repository *repo,
+ size_t length,
+ const git_oid input_array[]);
+
+/**
* Find a merge base in preparation for an octopus merge
*
* @param out the OID of a merge base considering all the commits
diff --git a/include/git2/reflog.h b/include/git2/reflog.h
index ac42a231c..c949a28f0 100644
--- a/include/git2/reflog.h
+++ b/include/git2/reflog.h
@@ -102,7 +102,7 @@ GIT_EXTERN(size_t) git_reflog_entrycount(git_reflog *reflog);
* equal to 0 (zero) and less than `git_reflog_entrycount()`.
* @return the entry; NULL if not found
*/
-GIT_EXTERN(const git_reflog_entry *) git_reflog_entry_byindex(git_reflog *reflog, size_t idx);
+GIT_EXTERN(const git_reflog_entry *) git_reflog_entry_byindex(const git_reflog *reflog, size_t idx);
/**
* Remove an entry from the reflog by its index
diff --git a/include/git2/remote.h b/include/git2/remote.h
index de5823e6d..422c93d38 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -306,9 +306,12 @@ GIT_EXTERN(int) git_remote_ls(const git_remote_head ***out, size_t *size, git_r
* The .idx file will be created and both it and the packfile with be
* renamed to their final name.
*
+ * @param remote the remote
+ * @param refspecs the refspecs to use for this negotiation and
+ * download. Use NULL or an empty array to use the base refspecs
* @return 0 or an error code
*/
-GIT_EXTERN(int) git_remote_download(git_remote *remote);
+GIT_EXTERN(int) git_remote_download(git_remote *remote, const git_strarray *refspecs);
/**
* Check whether the remote is connected
@@ -373,6 +376,8 @@ GIT_EXTERN(int) git_remote_update_tips(
* disconnect and update the remote-tracking branches.
*
* @param remote the remote to fetch from
+ * @param refspecs the refspecs to use for this fetch. Pass NULL or an
+ * empty array to use the base refspecs.
* @param signature The identity to use when updating reflogs
* @param reflog_message The message to insert into the reflogs. If NULL, the
* default is "fetch"
@@ -380,6 +385,7 @@ GIT_EXTERN(int) git_remote_update_tips(
*/
GIT_EXTERN(int) git_remote_fetch(
git_remote *remote,
+ const git_strarray *refspecs,
const git_signature *signature,
const char *reflog_message);
@@ -408,14 +414,6 @@ GIT_EXTERN(int) git_remote_supported_url(const char* url);
GIT_EXTERN(int) git_remote_list(git_strarray *out, git_repository *repo);
/**
- * Choose whether to check the server's certificate (applies to HTTPS only)
- *
- * @param remote the remote to configure
- * @param check whether to check the server's certificate (defaults to yes)
- */
-GIT_EXTERN(void) git_remote_check_cert(git_remote *remote, int check);
-
-/**
* Argument to the completion callback which tells it which operation
* finished.
*/
@@ -456,6 +454,14 @@ struct git_remote_callbacks {
git_cred_acquire_cb credentials;
/**
+ * If cert verification fails, this will be called to let the
+ * user make the final decision of whether to allow the
+ * connection to proceed. Returns 1 to allow the connection, 0
+ * to disallow it or a negative value to indicate an error.
+ */
+ git_transport_certificate_check_cb certificate_check;
+
+ /**
* During the download of new data, this will be regularly
* called with the current count of progress done by the
* indexer.
diff --git a/include/git2/reset.h b/include/git2/reset.h
index ea7217efe..5f2ba572d 100644
--- a/include/git2/reset.h
+++ b/include/git2/reset.h
@@ -52,6 +52,10 @@ typedef enum {
*
* @param reset_type Kind of reset operation to perform.
*
+ * @param checkout_opts Checkout options to be used for a HARD reset.
+ * The checkout_strategy field will be overridden (based on reset_type).
+ * This parameter can be used to propagate notify and progress callbacks.
+ *
* @param signature The identity that will used to populate the reflog entry
*
* @param log_message The one line long message to be appended to the reflog.
@@ -65,6 +69,7 @@ GIT_EXTERN(int) git_reset(
git_repository *repo,
git_object *target,
git_reset_t reset_type,
+ git_checkout_options *checkout_opts,
git_signature *signature,
const char *log_message);
diff --git a/src/hashsig.h b/include/git2/sys/hashsig.h
index 8c920cbf1..cd735e1b5 100644
--- a/src/hashsig.h
+++ b/include/git2/sys/hashsig.h
@@ -4,10 +4,12 @@
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
-#ifndef INCLUDE_hashsig_h__
-#define INCLUDE_hashsig_h__
+#ifndef INCLUDE_sys_hashsig_h__
+#define INCLUDE_sys_hashsig_h__
-#include "common.h"
+#include "git2/common.h"
+
+GIT_BEGIN_DECL
/**
* Similarity signature of line hashes for a buffer
@@ -35,7 +37,7 @@ typedef enum {
* @param buflen The length of the data at `buf`
* @param generate_pairwise_hashes Should pairwise runs be hashed
*/
-extern int git_hashsig_create(
+GIT_EXTERN(int) git_hashsig_create(
git_hashsig **out,
const char *buf,
size_t buflen,
@@ -50,7 +52,7 @@ extern int git_hashsig_create(
* This will return an error if the file doesn't contain enough data to
* compute a valid signature.
*/
-extern int git_hashsig_create_fromfile(
+GIT_EXTERN(int) git_hashsig_create_fromfile(
git_hashsig **out,
const char *path,
git_hashsig_option_t opts);
@@ -58,15 +60,17 @@ extern int git_hashsig_create_fromfile(
/**
* Release memory for a content similarity signature
*/
-extern void git_hashsig_free(git_hashsig *sig);
+GIT_EXTERN(void) git_hashsig_free(git_hashsig *sig);
/**
* Measure similarity between two files
*
* @return <0 for error, [0 to 100] as similarity score
*/
-extern int git_hashsig_compare(
+GIT_EXTERN(int) git_hashsig_compare(
const git_hashsig *a,
const git_hashsig *b);
+GIT_END_DECL
+
#endif
diff --git a/include/git2/sys/refdb_backend.h b/include/git2/sys/refdb_backend.h
index 3b216a287..d943e550f 100644
--- a/include/git2/sys/refdb_backend.h
+++ b/include/git2/sys/refdb_backend.h
@@ -153,6 +153,19 @@ struct git_refdb_backend {
* Remove a reflog.
*/
int (*reflog_delete)(git_refdb_backend *backend, const char *name);
+
+ /**
+ * Lock a reference. The opaque parameter will be passed to the unlock function
+ */
+ int (*lock)(void **payload_out, git_refdb_backend *backend, const char *refname);
+
+ /**
+ * Unlock a reference. Only one of target or symbolic_target
+ * will be set. success indicates whether to update the
+ * reference or discard the lock (if it's false)
+ */
+ int (*unlock)(git_refdb_backend *backend, void *payload, int success, int update_reflog,
+ const git_reference *ref, const git_signature *sig, const char *message);
};
#define GIT_REFDB_BACKEND_VERSION 1
diff --git a/include/git2/sys/repository.h b/include/git2/sys/repository.h
index 36f8b5836..dd7b22e06 100644
--- a/include/git2/sys/repository.h
+++ b/include/git2/sys/repository.h
@@ -119,6 +119,19 @@ GIT_EXTERN(void) git_repository_set_refdb(git_repository *repo, git_refdb *refdb
*/
GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index);
+/**
+ * Set a repository to be bare.
+ *
+ * Clear the working directory and set core.bare to true. You may also
+ * want to call `git_repository_set_index(repo, NULL)` since a bare repo
+ * typically does not have an index, but this function will not do that
+ * for you.
+ *
+ * @param repo Repo to make bare
+ * @return 0 on success, <0 on failure
+ */
+GIT_EXTERN(int) git_repository_set_bare(git_repository *repo);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/sys/transport.h b/include/git2/sys/transport.h
index 62ac455d3..1e8f4e4ed 100644
--- a/include/git2/sys/transport.h
+++ b/include/git2/sys/transport.h
@@ -23,9 +23,6 @@ GIT_BEGIN_DECL
typedef enum {
GIT_TRANSPORTFLAGS_NONE = 0,
- /* If the connection is secured with SSL/TLS, the authenticity
- * of the server certificate should not be verified. */
- GIT_TRANSPORTFLAGS_NO_CHECK_CERT = 1
} git_transport_flags_t;
typedef struct git_transport git_transport;
@@ -37,6 +34,7 @@ struct git_transport {
git_transport *transport,
git_transport_message_cb progress_cb,
git_transport_message_cb error_cb,
+ git_transport_certificate_check_cb certificate_check_cb,
void *payload);
/* Connect the transport to the remote repository, using the given
diff --git a/include/git2/transaction.h b/include/git2/transaction.h
new file mode 100644
index 000000000..64abb0c69
--- /dev/null
+++ b/include/git2/transaction.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_git_transaction_h__
+#define INCLUDE_git_transaction_h__
+
+#include "common.h"
+GIT_BEGIN_DECL
+
+/**
+ * Create a new transaction object
+ *
+ * This does not lock anything, but sets up the transaction object to
+ * know from which repository to lock.
+ *
+ * @param out the resulting transaction
+ * @param repo the repository in which to lock
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_transaction_new(git_transaction **out, git_repository *repo);
+
+/**
+ * Lock a reference
+ *
+ * Lock the specified reference. This is the first step to updating a
+ * reference.
+ *
+ * @param tx the transaction
+ * @param refname the reference to lock
+ * @return 0 or an error message
+ */
+GIT_EXTERN(int) git_transaction_lock_ref(git_transaction *tx, const char *refname);
+
+/**
+ * Set the target of a reference
+ *
+ * Set the target of the specified reference. This reference must be
+ * locked.
+ *
+ * @param tx the transaction
+ * @param refname reference to update
+ * @param target target to set the reference to
+ * @param sig signature to use in the reflog; pass NULL to read the identity from the config
+ * @param msg message to use in the reflog
+ * @return 0, GIT_ENOTFOUND if the reference is not among the locked ones, or an error code
+ */
+GIT_EXTERN(int) git_transaction_set_target(git_transaction *tx, const char *refname, const git_oid *target, const git_signature *sig, const char *msg);
+
+/**
+ * Set the target of a reference
+ *
+ * Set the target of the specified reference. This reference must be
+ * locked.
+ *
+ * @param tx the transaction
+ * @param refname reference to update
+ * @param target target to set the reference to
+ * @param sig signature to use in the reflog; pass NULL to read the identity from the config
+ * @param msg message to use in the reflog
+ * @return 0, GIT_ENOTFOUND if the reference is not among the locked ones, or an error code
+ */
+GIT_EXTERN(int) git_transaction_set_symbolic_target(git_transaction *tx, const char *refname, const char *target, const git_signature *sig, const char *msg);
+
+/**
+ * Set the reflog of a reference
+ *
+ * Set the specified reference's reflog. If this is combined with
+ * setting the target, that update won't be written to the reflog.
+ *
+ * @param tx the transaction
+ * @param refname the reference whose reflog to set
+ * @param reflog the reflog as it should be written out
+ * @return 0, GIT_ENOTFOUND if the reference is not among the locked ones, or an error code
+ */
+GIT_EXTERN(int) git_transaction_set_reflog(git_transaction *tx, const char *refname, const git_reflog *reflog);
+
+/**
+ * Remove a reference
+ *
+ * @param tx the transaction
+ * @param refname the reference to remove
+ * @return 0, GIT_ENOTFOUND if the reference is not among the locked ones, or an error code
+ */
+GIT_EXTERN(int) git_transaction_remove(git_transaction *tx, const char *refname);
+
+/**
+ * Commit the changes from the transaction
+ *
+ * Perform the changes that have been queued. The updates will be made
+ * one by one, and the first failure will stop the processing.
+ *
+ * @param tx the transaction
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_transaction_commit(git_transaction *tx);
+
+/**
+ * Free the resources allocated by this transaction
+ *
+ * If any references remain locked, they will be unlocked without any
+ * changes made to them.
+ *
+ * @param tx the transaction
+ */
+GIT_EXTERN(void) git_transaction_free(git_transaction *tx);
+
+GIT_END_DECL
+#endif
diff --git a/include/git2/transport.h b/include/git2/transport.h
index 7090698ac..39df479c7 100644
--- a/include/git2/transport.h
+++ b/include/git2/transport.h
@@ -20,6 +20,67 @@
*/
GIT_BEGIN_DECL
+/**
+ * Type of SSH host fingerprint
+ */
+typedef enum {
+ /** MD5 is available */
+ GIT_CERT_SSH_MD5 = (1 << 0),
+ /** SHA-1 is available */
+ GIT_CERT_SSH_SHA1 = (1 << 1),
+} git_cert_ssh_t;
+
+/**
+ * Hostkey information taken from libssh2
+ */
+typedef struct {
+ /**
+ * Type of certificate. Here to share the header with
+ * `git_cert`.
+ */
+ git_cert_t cert_type;
+ /**
+ * A hostkey type from libssh2, either
+ * `GIT_CERT_SSH_MD5` or `GIT_CERT_SSH_SHA1`
+ */
+ git_cert_ssh_t type;
+
+ /**
+ * Hostkey hash. If type has `GIT_CERT_SSH_MD5` set, this will
+ * have the MD5 hash of the hostkey.
+ */
+ unsigned char hash_md5[16];
+
+ /**
+ * Hostkey hash. If type has `GIT_CERT_SSH_SHA1` set, this will
+ * have the SHA-1 hash of the hostkey.
+ */
+ unsigned char hash_sha1[20];
+} git_cert_hostkey;
+
+/**
+ * X.509 certificate information
+ */
+typedef struct {
+ /**
+ * Type of certificate. Here to share the header with
+ * `git_cert`.
+ */
+ git_cert_t cert_type;
+ /**
+ * Pointer to the X.509 certificate data
+ */
+ void *data;
+ /**
+ * Length of the memory block pointed to by `data`.
+ */
+ size_t len;
+} git_cert_x509;
+
+/*
+ *** Begin interface for credentials acquisition ***
+ */
+
/** Authentication type requested */
typedef enum {
/* git_cred_userpass_plaintext */
diff --git a/include/git2/types.h b/include/git2/types.h
index 7ed1bcd4c..64cdfcdda 100644
--- a/include/git2/types.h
+++ b/include/git2/types.h
@@ -171,6 +171,9 @@ typedef struct git_reference git_reference;
/** Iterator for references */
typedef struct git_reference_iterator git_reference_iterator;
+/** Transactional interface to references */
+typedef struct git_transaction git_transaction;
+
/** Merge heads, the input to merge */
typedef struct git_merge_head git_merge_head;
@@ -254,6 +257,45 @@ typedef int (*git_transfer_progress_cb)(const git_transfer_progress *stats, void
typedef int (*git_transport_message_cb)(const char *str, int len, void *payload);
/**
+ * Type of host certificate structure that is passed to the check callback
+ */
+typedef enum git_cert_t {
+ /**
+ * The `data` argument to the callback will be a pointer to
+ * the DER-encoded data.
+ */
+ GIT_CERT_X509,
+ /**
+ * The `data` argument to the callback will be a pointer to a
+ * `git_cert_hostkey` structure.
+ */
+ GIT_CERT_HOSTKEY_LIBSSH2,
+} git_cert_t;
+
+/**
+ * Parent type for `git_cert_hostkey` and `git_cert_x509`.
+ */
+typedef struct {
+ /**
+ * Type of certificate. A `GIT_CERT_` value.
+ */
+ git_cert_t cert_type;
+} git_cert;
+
+/**
+ * Callback for the user's custom certificate checks.
+ *
+ * @param type The type of certificate or host info, SSH or X.509
+ * @param data The data for the certificate or host info
+ * @param len The size of the certificate or host info
+ * @param valid Whether the libgit2 checks (OpenSSL or WinHTTP) think
+ * this certificate is valid
+ * @param host Hostname of the host libgit2 connected to
+ * @param payload Payload provided by the caller
+ */
+typedef int (*git_transport_certificate_check_cb)(git_cert *cert, int valid, const char *host, void *payload);
+
+/**
* Opaque structure representing a submodule.
*/
typedef struct git_submodule git_submodule;
diff --git a/script/cibuild.sh b/script/cibuild.sh
index e58c0849c..abe31d0dc 100755
--- a/script/cibuild.sh
+++ b/script/cibuild.sh
@@ -15,7 +15,7 @@ export GITTEST_REMOTE_URL="git://localhost/test.git"
mkdir _build
cd _build
cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS || exit $?
-cmake --build . --target install || exit $?
+make -j2 install || exit $?
ctest -V . || exit $?
# Now that we've tested the raw git protocol, let's set up ssh to we
@@ -33,6 +33,9 @@ ssh-keygen -t rsa -f ~/.ssh/id_rsa -N "" -q
cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys
ssh-keyscan -t rsa localhost >>~/.ssh/known_hosts
+# Get the fingerprint for localhost and remove the colons so we can parse it as a hex number
+export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -F localhost -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':')
+
export GITTEST_REMOTE_URL="ssh://localhost/$HOME/_temp/test.git"
export GITTEST_REMOTE_USER=$USER
export GITTEST_REMOTE_SSH_KEY="$HOME/.ssh/id_rsa"
@@ -40,6 +43,6 @@ export GITTEST_REMOTE_SSH_PUBKEY="$HOME/.ssh/id_rsa.pub"
export GITTEST_REMOTE_SSH_PASSPHRASE=""
if [ -e ./libgit2_clar ]; then
- ./libgit2_clar -sonline::push -sonline::clone::cred_callback &&
+ ./libgit2_clar -sonline::push -sonline::clone::cred_callback -sonline::clone::ssh_cert &&
./libgit2_clar -sonline::clone::ssh_with_paths
fi
diff --git a/src/attr.c b/src/attr.c
index 05b0c1b3c..a02172689 100644
--- a/src/attr.c
+++ b/src/attr.c
@@ -377,7 +377,7 @@ static int push_attr_file(
return error;
}
-static int push_one_attr(void *ref, git_buf *path)
+static int push_one_attr(void *ref, const char *path)
{
int error = 0, n_src, i;
attr_walk_up_info *info = (attr_walk_up_info *)ref;
@@ -388,7 +388,7 @@ static int push_one_attr(void *ref, git_buf *path)
for (i = 0; !error && i < n_src; ++i)
error = push_attr_file(
- info->repo, info->files, src[i], path->ptr, GIT_ATTR_FILE);
+ info->repo, info->files, src[i], path, GIT_ATTR_FILE);
return error;
}
@@ -411,7 +411,7 @@ static int collect_attr_files(
const char *path,
git_vector *files)
{
- int error;
+ int error = 0;
git_buf dir = GIT_BUF_INIT;
const char *workdir = git_repository_workdir(repo);
attr_walk_up_info info = { NULL };
@@ -447,7 +447,11 @@ static int collect_attr_files(
giterr_clear(); /* no error even if there is no index */
info.files = files;
- error = git_path_walk_up(&dir, workdir, push_one_attr, &info);
+ if (!strcmp(dir.ptr, "."))
+ error = push_one_attr(&info, "");
+ else
+ error = git_path_walk_up(&dir, workdir, push_one_attr, &info);
+
if (error < 0)
goto cleanup;
diff --git a/src/cc-compat.h b/src/cc-compat.h
index e73cb6de8..0b66d8ba1 100644
--- a/src/cc-compat.h
+++ b/src/cc-compat.h
@@ -35,6 +35,14 @@
# define GIT_TYPEOF(x)
#endif
+#if defined(__GNUC__)
+# define GIT_ALIGN(x,size) x __attribute__ ((aligned(size)))
+#elif defined(_MSC_VER)
+# define GIT_ALIGN(x,size) __declspec(align(size)) x
+#else
+# define GIT_ALIGN(x,size) x
+#endif
+
#define GIT_UNUSED(x) ((void)(x))
/* Define the printf format specifer to use for size_t output */
diff --git a/src/clone.c b/src/clone.c
index 43b839003..f18f07611 100644
--- a/src/clone.c
+++ b/src/clone.c
@@ -358,7 +358,7 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_check
git_remote_set_update_fetchhead(remote, 0);
git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
- if ((error = git_remote_fetch(remote, signature, git_buf_cstr(&reflog_message))) != 0)
+ if ((error = git_remote_fetch(remote, NULL, signature, git_buf_cstr(&reflog_message))) != 0)
goto cleanup;
error = checkout_branch(repo, remote, co_opts, branch, signature, git_buf_cstr(&reflog_message));
@@ -553,7 +553,7 @@ static int clone_local_into(git_repository *repo, git_remote *remote, const git_
git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
- if ((error = git_remote_fetch(remote, signature, git_buf_cstr(&reflog_message))) != 0)
+ if ((error = git_remote_fetch(remote, NULL, signature, git_buf_cstr(&reflog_message))) != 0)
goto cleanup;
error = checkout_branch(repo, remote, co_opts, branch, signature, git_buf_cstr(&reflog_message));
diff --git a/src/commit_list.h b/src/commit_list.h
index 490d841be..7cd3945ae 100644
--- a/src/commit_list.h
+++ b/src/commit_list.h
@@ -25,7 +25,7 @@ typedef struct git_commit_list_node {
uninteresting:1,
topo_delay:1,
parsed:1,
- flags : 4;
+ flags : FLAG_BITS;
unsigned short in_degree;
unsigned short out_degree;
diff --git a/src/config_file.c b/src/config_file.c
index 7106f18db..8f55c42f3 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -1163,7 +1163,7 @@ static int strip_comments(char *line, int in_quotes)
}
/* skip any space at the end */
- if (ptr > line && git__isspace(ptr[-1])) {
+ while (ptr > line && git__isspace(ptr[-1])) {
ptr--;
}
ptr[0] = '\0';
diff --git a/src/describe.c b/src/describe.c
new file mode 100644
index 000000000..08c99a7d2
--- /dev/null
+++ b/src/describe.c
@@ -0,0 +1,871 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#include "git2/describe.h"
+#include "git2/strarray.h"
+#include "git2/diff.h"
+#include "git2/status.h"
+
+#include "common.h"
+#include "commit.h"
+#include "commit_list.h"
+#include "oidmap.h"
+#include "refs.h"
+#include "revwalk.h"
+#include "tag.h"
+#include "vector.h"
+#include "repository.h"
+
+/* Ported from https://github.com/git/git/blob/89dde7882f71f846ccd0359756d27bebc31108de/builtin/describe.c */
+
+struct commit_name {
+ git_tag *tag;
+ unsigned prio:2; /* annotated tag = 2, tag = 1, head = 0 */
+ unsigned name_checked:1;
+ git_oid sha1;
+ char *path;
+
+ /* Khash workaround. They original key has to still be reachable */
+ git_oid peeled;
+};
+
+static void *oidmap_value_bykey(git_oidmap *map, const git_oid *key)
+{
+ khint_t pos = git_oidmap_lookup_index(map, key);
+
+ if (!git_oidmap_valid_index(map, pos))
+ return NULL;
+
+ return git_oidmap_value_at(map, pos);
+}
+
+static struct commit_name *find_commit_name(
+ git_oidmap *names,
+ const git_oid *peeled)
+{
+ return (struct commit_name *)(oidmap_value_bykey(names, peeled));
+}
+
+static int replace_name(
+ git_tag **tag,
+ git_repository *repo,
+ struct commit_name *e,
+ unsigned int prio,
+ const git_oid *sha1)
+{
+ git_time_t e_time = 0, t_time = 0;
+
+ if (!e || e->prio < prio)
+ return 1;
+
+ if (e->prio == 2 && prio == 2) {
+ /* Multiple annotated tags point to the same commit.
+ * Select one to keep based upon their tagger date.
+ */
+ git_tag *t = NULL;
+
+ if (!e->tag) {
+ if (git_tag_lookup(&t, repo, &e->sha1) < 0)
+ return 1;
+ e->tag = t;
+ }
+
+ if (git_tag_lookup(&t, repo, sha1) < 0)
+ return 0;
+
+ *tag = t;
+
+ if (e->tag->tagger)
+ e_time = e->tag->tagger->when.time;
+
+ if (t->tagger)
+ t_time = t->tagger->when.time;
+
+ if (e_time < t_time)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int add_to_known_names(
+ git_repository *repo,
+ git_oidmap *names,
+ const char *path,
+ const git_oid *peeled,
+ unsigned int prio,
+ const git_oid *sha1)
+{
+ struct commit_name *e = find_commit_name(names, peeled);
+ bool found = (e != NULL);
+
+ git_tag *tag = NULL;
+ if (replace_name(&tag, repo, e, prio, sha1)) {
+ if (!found) {
+ e = git__malloc(sizeof(struct commit_name));
+ GITERR_CHECK_ALLOC(e);
+
+ e->path = NULL;
+ e->tag = NULL;
+ }
+
+ if (e->tag)
+ git_tag_free(e->tag);
+ e->tag = tag;
+ e->prio = prio;
+ e->name_checked = 0;
+ git_oid_cpy(&e->sha1, sha1);
+ git__free(e->path);
+ e->path = git__strdup(path);
+ git_oid_cpy(&e->peeled, peeled);
+
+ if (!found) {
+ int ret;
+
+ git_oidmap_insert(names, &e->peeled, e, ret);
+ if (ret < 0)
+ return -1;
+ }
+ }
+ else
+ git_tag_free(tag);
+
+ return 0;
+}
+
+static int retrieve_peeled_tag_or_object_oid(
+ git_oid *peeled_out,
+ git_oid *ref_target_out,
+ git_repository *repo,
+ const char *refname)
+{
+ git_reference *ref;
+ git_object *peeled = NULL;
+ int error;
+
+ if ((error = git_reference_lookup_resolved(&ref, repo, refname, -1)) < 0)
+ return error;
+
+ if ((error = git_reference_peel(&peeled, ref, GIT_OBJ_ANY)) < 0)
+ goto cleanup;
+
+ git_oid_cpy(ref_target_out, git_reference_target(ref));
+ git_oid_cpy(peeled_out, git_object_id(peeled));
+
+ if (git_oid_cmp(ref_target_out, peeled_out) != 0)
+ error = 1; /* The reference was pointing to a annotated tag */
+ else
+ error = 0; /* Any other object */
+
+cleanup:
+ git_reference_free(ref);
+ git_object_free(peeled);
+ return error;
+}
+
+struct git_describe_result {
+ int dirty;
+ int exact_match;
+ int fallback_to_id;
+ git_oid commit_id;
+ git_repository *repo;
+ struct commit_name *name;
+ struct possible_tag *tag;
+};
+
+struct get_name_data
+{
+ git_describe_options *opts;
+ git_repository *repo;
+ git_oidmap *names;
+ git_describe_result *result;
+};
+
+static int commit_name_dup(struct commit_name **out, struct commit_name *in)
+{
+ struct commit_name *name;
+
+ name = git__malloc(sizeof(struct commit_name));
+ GITERR_CHECK_ALLOC(name);
+
+ memcpy(name, in, sizeof(struct commit_name));
+ name->tag = NULL;
+ name->path = NULL;
+
+ if (in->tag && git_object_dup((git_object **) &name->tag, (git_object *) in->tag) < 0)
+ return -1;
+
+ name->path = git__strdup(in->path);
+ GITERR_CHECK_ALLOC(name->path);
+
+ *out = name;
+ return 0;
+}
+
+static int get_name(const char *refname, void *payload)
+{
+ struct get_name_data *data;
+ bool is_tag, is_annotated, all;
+ git_oid peeled, sha1;
+ unsigned int prio;
+ int error = 0;
+
+ data = (struct get_name_data *)payload;
+ is_tag = !git__prefixcmp(refname, GIT_REFS_TAGS_DIR);
+ all = data->opts->describe_strategy == GIT_DESCRIBE_ALL;
+
+ /* Reject anything outside refs/tags/ unless --all */
+ if (!all && !is_tag)
+ return 0;
+
+ /* Accept only tags that match the pattern, if given */
+ if (data->opts->pattern && (!is_tag || p_fnmatch(data->opts->pattern,
+ refname + strlen(GIT_REFS_TAGS_DIR), 0)))
+ return 0;
+
+ /* Is it annotated? */
+ if ((error = retrieve_peeled_tag_or_object_oid(
+ &peeled, &sha1, data->repo, refname)) < 0)
+ return error;
+
+ is_annotated = error;
+
+ /*
+ * By default, we only use annotated tags, but with --tags
+ * we fall back to lightweight ones (even without --tags,
+ * we still remember lightweight ones, only to give hints
+ * in an error message). --all allows any refs to be used.
+ */
+ if (is_annotated)
+ prio = 2;
+ else if (is_tag)
+ prio = 1;
+ else
+ prio = 0;
+
+ add_to_known_names(data->repo, data->names,
+ all ? refname + strlen(GIT_REFS_DIR) : refname + strlen(GIT_REFS_TAGS_DIR),
+ &peeled, prio, &sha1);
+ return 0;
+}
+
+struct possible_tag {
+ struct commit_name *name;
+ int depth;
+ int found_order;
+ unsigned flag_within;
+};
+
+static int possible_tag_dup(struct possible_tag **out, struct possible_tag *in)
+{
+ struct possible_tag *tag;
+
+ tag = git__malloc(sizeof(struct possible_tag));
+ GITERR_CHECK_ALLOC(tag);
+
+ memcpy(tag, in, sizeof(struct possible_tag));
+ tag->name = NULL;
+
+ if (commit_name_dup(&tag->name, in->name) < 0)
+ return -1;
+
+ *out = tag;
+ return 0;
+}
+
+static int compare_pt(const void *a_, const void *b_)
+{
+ struct possible_tag *a = (struct possible_tag *)a_;
+ struct possible_tag *b = (struct possible_tag *)b_;
+ if (a->depth != b->depth)
+ return a->depth - b->depth;
+ if (a->found_order != b->found_order)
+ return a->found_order - b->found_order;
+ return 0;
+}
+
+#define SEEN (1u << 0)
+
+static unsigned long finish_depth_computation(
+ git_pqueue *list,
+ git_revwalk *walk,
+ struct possible_tag *best)
+{
+ unsigned long seen_commits = 0;
+ int error, i;
+
+ while (git_pqueue_size(list) > 0) {
+ git_commit_list_node *c = git_pqueue_pop(list);
+ seen_commits++;
+ if (c->flags & best->flag_within) {
+ size_t index = 0;
+ while (git_pqueue_size(list) > index) {
+ git_commit_list_node *i = git_pqueue_get(list, index);
+ if (!(i->flags & best->flag_within))
+ break;
+ index++;
+ }
+ if (index > git_pqueue_size(list))
+ break;
+ } else
+ best->depth++;
+ for (i = 0; i < c->out_degree; i++) {
+ git_commit_list_node *p = c->parents[i];
+ if ((error = git_commit_list_parse(walk, p)) < 0)
+ return error;
+ if (!(p->flags & SEEN))
+ if ((error = git_pqueue_insert(list, p)) < 0)
+ return error;
+ p->flags |= c->flags;
+ }
+ }
+ return seen_commits;
+}
+
+static int display_name(git_buf *buf, git_repository *repo, struct commit_name *n)
+{
+ if (n->prio == 2 && !n->tag) {
+ if (git_tag_lookup(&n->tag, repo, &n->sha1) < 0) {
+ giterr_set(GITERR_TAG, "Annotated tag '%s' not available", n->path);
+ return -1;
+ }
+ }
+
+ if (n->tag && !n->name_checked) {
+ if (!git_tag_name(n->tag)) {
+ giterr_set(GITERR_TAG, "Annotated tag '%s' has no embedded name", n->path);
+ return -1;
+ }
+
+ /* TODO: Cope with warnings
+ if (strcmp(n->tag->tag, all ? n->path + 5 : n->path))
+ warning(_("tag '%s' is really '%s' here"), n->tag->tag, n->path);
+ */
+
+ n->name_checked = 1;
+ }
+
+ if (n->tag)
+ git_buf_printf(buf, "%s", git_tag_name(n->tag));
+ else
+ git_buf_printf(buf, "%s", n->path);
+
+ return 0;
+}
+
+static int find_unique_abbrev_size(
+ int *out,
+ git_repository *repo,
+ const git_oid *oid_in,
+ int abbreviated_size)
+{
+ size_t size = abbreviated_size;
+ git_odb *odb;
+ git_oid dummy;
+ int error;
+
+ if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
+ return error;
+
+ while (size < GIT_OID_HEXSZ) {
+ if ((error = git_odb_exists_prefix(&dummy, odb, oid_in, size)) == 0) {
+ *out = (int) size;
+ return 0;
+ }
+
+ /* If the error wasn't that it's not unique, then it's a proper error */
+ if (error != GIT_EAMBIGUOUS)
+ return error;
+
+ /* Try again with a larger size */
+ size++;
+ }
+
+ /* If we didn't find any shorter prefix, we have to do the whole thing */
+ *out = GIT_OID_HEXSZ;
+
+ return 0;
+}
+
+static int show_suffix(
+ git_buf *buf,
+ int depth,
+ git_repository *repo,
+ const git_oid* id,
+ size_t abbrev_size)
+{
+ int error, size;
+
+ char hex_oid[GIT_OID_HEXSZ];
+
+ if ((error = find_unique_abbrev_size(&size, repo, id, abbrev_size)) < 0)
+ return error;
+
+ git_oid_fmt(hex_oid, id);
+
+ git_buf_printf(buf, "-%d-g", depth);
+
+ git_buf_put(buf, hex_oid, size);
+
+ return git_buf_oom(buf) ? -1 : 0;
+}
+
+#define MAX_CANDIDATES_TAGS FLAG_BITS - 1
+
+static int describe_not_found(const git_oid *oid, const char *message_format) {
+ char oid_str[GIT_OID_HEXSZ + 1];
+ git_oid_tostr(oid_str, sizeof(oid_str), oid);
+
+ giterr_set(GITERR_DESCRIBE, message_format, oid_str);
+ return GIT_ENOTFOUND;
+}
+
+static int describe(
+ struct get_name_data *data,
+ git_commit *commit)
+{
+ struct commit_name *n;
+ struct possible_tag *best;
+ bool all, tags;
+ git_revwalk *walk = NULL;
+ git_pqueue list;
+ git_commit_list_node *cmit, *gave_up_on = NULL;
+ git_vector all_matches = GIT_VECTOR_INIT;
+ unsigned int match_cnt = 0, annotated_cnt = 0, cur_match;
+ unsigned long seen_commits = 0; /* TODO: Check long */
+ unsigned int unannotated_cnt = 0;
+ int error;
+
+ if (git_vector_init(&all_matches, MAX_CANDIDATES_TAGS, compare_pt) < 0)
+ return -1;
+
+ if ((error = git_pqueue_init(&list, 0, 2, git_commit_list_time_cmp)) < 0)
+ goto cleanup;
+
+ all = data->opts->describe_strategy == GIT_DESCRIBE_ALL;
+ tags = data->opts->describe_strategy == GIT_DESCRIBE_TAGS;
+
+ git_oid_cpy(&data->result->commit_id, git_commit_id(commit));
+
+ n = find_commit_name(data->names, git_commit_id(commit));
+ if (n && (tags || all || n->prio == 2)) {
+ /*
+ * Exact match to an existing ref.
+ */
+ data->result->exact_match = 1;
+ if ((error = commit_name_dup(&data->result->name, n)) < 0)
+ goto cleanup;
+
+ goto cleanup;
+ }
+
+ if (!data->opts->max_candidates_tags) {
+ error = describe_not_found(
+ git_commit_id(commit),
+ "Cannot describe - no tag exactly matches '%s'");
+
+ goto cleanup;
+ }
+
+ if ((error = git_revwalk_new(&walk, git_commit_owner(commit))) < 0)
+ goto cleanup;
+
+ if ((cmit = git_revwalk__commit_lookup(walk, git_commit_id(commit))) == NULL)
+ goto cleanup;
+
+ if ((error = git_commit_list_parse(walk, cmit)) < 0)
+ goto cleanup;
+
+ cmit->flags = SEEN;
+
+ if ((error = git_pqueue_insert(&list, cmit)) < 0)
+ goto cleanup;
+
+ while (git_pqueue_size(&list) > 0)
+ {
+ int i;
+
+ git_commit_list_node *c = (git_commit_list_node *)git_pqueue_pop(&list);
+ seen_commits++;
+
+ n = find_commit_name(data->names, &c->oid);
+
+ if (n) {
+ if (!tags && !all && n->prio < 2) {
+ unannotated_cnt++;
+ } else if (match_cnt < data->opts->max_candidates_tags) {
+ struct possible_tag *t = git__malloc(sizeof(struct commit_name));
+ GITERR_CHECK_ALLOC(t);
+ if ((error = git_vector_insert(&all_matches, t)) < 0)
+ goto cleanup;
+
+ match_cnt++;
+
+ t->name = n;
+ t->depth = seen_commits - 1;
+ t->flag_within = 1u << match_cnt;
+ t->found_order = match_cnt;
+ c->flags |= t->flag_within;
+ if (n->prio == 2)
+ annotated_cnt++;
+ }
+ else {
+ gave_up_on = c;
+ break;
+ }
+ }
+
+ for (cur_match = 0; cur_match < match_cnt; cur_match++) {
+ struct possible_tag *t = git_vector_get(&all_matches, cur_match);
+ if (!(c->flags & t->flag_within))
+ t->depth++;
+ }
+
+ if (annotated_cnt && (git_pqueue_size(&list) == 0)) {
+ /*
+ if (debug) {
+ char oid_str[GIT_OID_HEXSZ + 1];
+ git_oid_tostr(oid_str, sizeof(oid_str), &c->oid);
+
+ fprintf(stderr, "finished search at %s\n", oid_str);
+ }
+ */
+ break;
+ }
+ for (i = 0; i < c->out_degree; i++) {
+ git_commit_list_node *p = c->parents[i];
+ if ((error = git_commit_list_parse(walk, p)) < 0)
+ goto cleanup;
+ if (!(p->flags & SEEN))
+ if ((error = git_pqueue_insert(&list, p)) < 0)
+ goto cleanup;
+ p->flags |= c->flags;
+
+ if (data->opts->only_follow_first_parent)
+ break;
+ }
+ }
+
+ if (!match_cnt) {
+ if (data->opts->show_commit_oid_as_fallback) {
+ data->result->fallback_to_id = 1;
+ git_oid_cpy(&data->result->commit_id, &cmit->oid);
+
+ goto cleanup;
+ }
+ if (unannotated_cnt) {
+ error = describe_not_found(git_commit_id(commit),
+ "Cannot describe - "
+ "No annotated tags can describe '%s'."
+ "However, there were unannotated tags.");
+ goto cleanup;
+ }
+ else {
+ error = describe_not_found(git_commit_id(commit),
+ "Cannot describe - "
+ "No tags can describe '%s'.");
+ goto cleanup;
+ }
+ }
+
+ best = (struct possible_tag *)git_vector_get(&all_matches, 0);
+
+ git_vector_sort(&all_matches);
+
+ best = (struct possible_tag *)git_vector_get(&all_matches, 0);
+
+ if (gave_up_on) {
+ git_pqueue_insert(&list, gave_up_on);
+ seen_commits--;
+ }
+ if ((error = finish_depth_computation(
+ &list, walk, best)) < 0)
+ goto cleanup;
+
+ seen_commits += error;
+ if ((error = possible_tag_dup(&data->result->tag, best)) < 0)
+ goto cleanup;
+
+ /*
+ {
+ static const char *prio_names[] = {
+ "head", "lightweight", "annotated",
+ };
+
+ char oid_str[GIT_OID_HEXSZ + 1];
+
+ if (debug) {
+ for (cur_match = 0; cur_match < match_cnt; cur_match++) {
+ struct possible_tag *t = (struct possible_tag *)git_vector_get(&all_matches, cur_match);
+ fprintf(stderr, " %-11s %8d %s\n",
+ prio_names[t->name->prio],
+ t->depth, t->name->path);
+ }
+ fprintf(stderr, "traversed %lu commits\n", seen_commits);
+ if (gave_up_on) {
+ git_oid_tostr(oid_str, sizeof(oid_str), &gave_up_on->oid);
+ fprintf(stderr,
+ "more than %i tags found; listed %i most recent\n"
+ "gave up search at %s\n",
+ data->opts->max_candidates_tags, data->opts->max_candidates_tags,
+ oid_str);
+ }
+ }
+ }
+ */
+
+ git_oid_cpy(&data->result->commit_id, &cmit->oid);
+
+cleanup:
+ {
+ size_t i;
+ struct possible_tag *match;
+ git_vector_foreach(&all_matches, i, match) {
+ git__free(match);
+ }
+ }
+ git_vector_free(&all_matches);
+ git_pqueue_free(&list);
+ git_revwalk_free(walk);
+ return error;
+}
+
+static int normalize_options(
+ git_describe_options *dst,
+ const git_describe_options *src)
+{
+ git_describe_options default_options = GIT_DESCRIBE_OPTIONS_INIT;
+ if (!src) src = &default_options;
+
+ *dst = *src;
+
+ if (dst->max_candidates_tags > GIT_DESCRIBE_DEFAULT_MAX_CANDIDATES_TAGS)
+ dst->max_candidates_tags = GIT_DESCRIBE_DEFAULT_MAX_CANDIDATES_TAGS;
+
+ return 0;
+}
+
+int git_describe_commit(
+ git_describe_result **result,
+ git_object *committish,
+ git_describe_options *opts)
+{
+ struct get_name_data data;
+ struct commit_name *name;
+ git_commit *commit;
+ int error = -1;
+ git_describe_options normalized;
+
+ assert(committish);
+
+ data.result = git__calloc(1, sizeof(git_describe_result));
+ GITERR_CHECK_ALLOC(data.result);
+ data.result->repo = git_object_owner(committish);
+
+ data.opts = opts;
+ data.repo = git_object_owner(committish);
+
+ if ((error = normalize_options(&normalized, opts)) < 0)
+ return error;
+
+ GITERR_CHECK_VERSION(
+ &normalized,
+ GIT_DESCRIBE_OPTIONS_VERSION,
+ "git_describe_options");
+
+ data.names = git_oidmap_alloc();
+ GITERR_CHECK_ALLOC(data.names);
+
+ /** TODO: contains to be implemented */
+
+ if ((error = git_object_peel((git_object **)(&commit), committish, GIT_OBJ_COMMIT)) < 0)
+ goto cleanup;
+
+ if (git_reference_foreach_name(
+ git_object_owner(committish),
+ get_name, &data) < 0)
+ goto cleanup;
+
+ if (git_oidmap_size(data.names) == 0) {
+ giterr_set(GITERR_DESCRIBE, "Cannot describe - "
+ "No reference found, cannot describe anything.");
+ error = -1;
+ goto cleanup;
+ }
+
+ if ((error = describe(&data, commit)) < 0)
+ goto cleanup;
+
+cleanup:
+ git_commit_free(commit);
+
+ git_oidmap_foreach_value(data.names, name, {
+ git_tag_free(name->tag);
+ git__free(name->path);
+ git__free(name);
+ });
+
+ git_oidmap_free(data.names);
+
+ if (error < 0)
+ git_describe_result_free(data.result);
+ else
+ *result = data.result;
+
+ return error;
+}
+
+int git_describe_workdir(
+ git_describe_result **out,
+ git_repository *repo,
+ git_describe_options *opts)
+{
+ int error;
+ git_oid current_id;
+ git_status_list *status = NULL;
+ git_status_options status_opts = GIT_STATUS_OPTIONS_INIT;
+ git_describe_result *result;
+ git_object *commit;
+
+ if ((error = git_reference_name_to_id(&current_id, repo, GIT_HEAD_FILE)) < 0)
+ return error;
+
+ if ((error = git_object_lookup(&commit, repo, &current_id, GIT_OBJ_COMMIT)) < 0)
+ return error;
+
+ /* The first step is to perform a describe of HEAD, so we can leverage this */
+ if ((error = git_describe_commit(&result, commit, opts)) < 0)
+ goto out;
+
+ if ((error = git_status_list_new(&status, repo, &status_opts)) < 0)
+ goto out;
+
+
+ if (git_status_list_entrycount(status) > 0)
+ result->dirty = 1;
+
+out:
+ git_object_free(commit);
+ git_status_list_free(status);
+
+ if (error < 0)
+ git_describe_result_free(result);
+ else
+ *out = result;
+
+ return error;
+}
+
+int git_describe_format(git_buf *out, const git_describe_result *result, const git_describe_format_options *opts)
+{
+ int error;
+ git_repository *repo;
+ struct commit_name *name;
+
+ assert(out && result);
+
+ GITERR_CHECK_VERSION(opts, GIT_DESCRIBE_FORMAT_OPTIONS_VERSION, "git_describe_format_options");
+ git_buf_sanitize(out);
+
+
+ if (opts->always_use_long_format && opts->abbreviated_size == 0) {
+ giterr_set(GITERR_DESCRIBE, "Cannot describe - "
+ "'always_use_long_format' is incompatible with a zero"
+ "'abbreviated_size'");
+ return -1;
+ }
+
+
+ repo = result->repo;
+
+ /* If we did find an exact match, then it's the easier method */
+ if (result->exact_match) {
+ name = result->name;
+ if ((error = display_name(out, repo, name)) < 0)
+ return error;
+
+ if (opts->always_use_long_format) {
+ const git_oid *id = name->tag ? git_tag_target_id(name->tag) : &result->commit_id;
+ if ((error = show_suffix(out, 0, repo, id, opts->abbreviated_size)) < 0)
+ return error;
+ }
+
+ if (result->dirty && opts->dirty_suffix)
+ git_buf_puts(out, opts->dirty_suffix);
+
+ return git_buf_oom(out) ? -1 : 0;
+ }
+
+ /* If we didn't find *any* tags, we fall back to the commit's id */
+ if (result->fallback_to_id) {
+ char hex_oid[GIT_OID_HEXSZ + 1] = {0};
+ int size;
+ if ((error = find_unique_abbrev_size(
+ &size, repo, &result->commit_id, opts->abbreviated_size)) < 0)
+ return -1;
+
+ git_oid_fmt(hex_oid, &result->commit_id);
+ git_buf_put(out, hex_oid, size);
+
+ if (result->dirty && opts->dirty_suffix)
+ git_buf_puts(out, opts->dirty_suffix);
+
+ return git_buf_oom(out) ? -1 : 0;
+ }
+
+ /* Lastly, if we found a matching tag, we show that */
+ name = result->tag->name;
+
+ if ((error = display_name(out, repo, name)) < 0)
+ return error;
+
+ if (opts->abbreviated_size) {
+ if ((error = show_suffix(out, result->tag->depth, repo,
+ &result->commit_id, opts->abbreviated_size)) < 0)
+ return error;
+ }
+
+ if (result->dirty && opts->dirty_suffix) {
+ git_buf_puts(out, opts->dirty_suffix);
+ }
+
+ return git_buf_oom(out) ? -1 : 0;
+}
+
+void git_describe_result_free(git_describe_result *result)
+{
+ if (result == NULL)
+ return;
+
+ if (result->name) {
+ git_tag_free(result->name->tag);
+ git__free(result->name->path);
+ git__free(result->name);
+ }
+
+ if (result->tag) {
+ git_tag_free(result->tag->name->tag);
+ git__free(result->tag->name->path);
+ git__free(result->tag->name);
+ git__free(result->tag);
+ }
+
+ git__free(result);
+}
+
+int git_describe_init_options(git_describe_options *opts, unsigned int version)
+{
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(
+ opts, version, git_describe_options, GIT_DESCRIBE_OPTIONS_INIT);
+ return 0;
+}
+
+int git_describe_init_format_options(git_describe_format_options *opts, unsigned int version)
+{
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(
+ opts, version, git_describe_format_options, GIT_DESCRIBE_FORMAT_OPTIONS_INIT);
+ return 0;
+}
diff --git a/src/diff_patch.c b/src/diff_patch.c
index 8e90efceb..317dbeabb 100644
--- a/src/diff_patch.c
+++ b/src/diff_patch.c
@@ -273,6 +273,7 @@ int git_diff_foreach(
return error;
memset(&xo, 0, sizeof(xo));
+ memset(&patch, 0, sizeof(patch));
diff_output_init(
&xo.output, &diff->opts, file_cb, hunk_cb, data_cb, payload);
git_xdiff_init(&xo, &diff->opts);
diff --git a/src/diff_tform.c b/src/diff_tform.c
index 423a0ca33..9ebce06a0 100644
--- a/src/diff_tform.c
+++ b/src/diff_tform.c
@@ -8,9 +8,9 @@
#include "git2/config.h"
#include "git2/blob.h"
+#include "git2/sys/hashsig.h"
#include "diff.h"
-#include "hashsig.h"
#include "path.h"
#include "fileops.h"
#include "config.h"
diff --git a/src/fileops.c b/src/fileops.c
index 34659ad3b..bd9d27c7a 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -505,15 +505,15 @@ static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path)
return error;
}
-static int futils__rmdir_empty_parent(void *opaque, git_buf *path)
+static int futils__rmdir_empty_parent(void *opaque, const char *path)
{
futils__rmdir_data *data = opaque;
int error = 0;
- if (git_buf_len(path) <= data->baselen)
+ if (strlen(path) <= data->baselen)
error = GIT_ITEROVER;
- else if (p_rmdir(git_buf_cstr(path)) < 0) {
+ else if (p_rmdir(path) < 0) {
int en = errno;
if (en == ENOENT || en == ENOTDIR) {
@@ -521,7 +521,7 @@ static int futils__rmdir_empty_parent(void *opaque, git_buf *path)
} else if (en == ENOTEMPTY || en == EEXIST || en == EBUSY) {
error = GIT_ITEROVER;
} else {
- error = git_path_set_error(errno, git_buf_cstr(path), "rmdir");
+ error = git_path_set_error(errno, path, "rmdir");
}
}
diff --git a/src/filter.c b/src/filter.c
index b9e4f9ec8..b5a8bdd66 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -38,7 +38,7 @@ struct git_filter_list {
};
typedef struct {
- const char *filter_name;
+ char *filter_name;
git_filter *filter;
int priority;
int initialized;
@@ -75,6 +75,7 @@ static void filter_registry_shutdown(void)
fdef->initialized = false;
}
+ git__free(fdef->filter_name);
git__free(fdef->attrdata);
git__free(fdef);
}
@@ -230,6 +231,8 @@ int git_filter_register(
size_t nattr = 0, nmatch = 0;
git_buf attrs = GIT_BUF_INIT;
+ assert(name && filter);
+
if (filter_registry_initialize() < 0)
return -1;
@@ -246,7 +249,9 @@ int git_filter_register(
sizeof(git_filter_def) + 2 * nattr * sizeof(char *), 1);
GITERR_CHECK_ALLOC(fdef);
- fdef->filter_name = name;
+ fdef->filter_name = git__strdup(name);
+ GITERR_CHECK_ALLOC(fdef->filter_name);
+
fdef->filter = filter;
fdef->priority = priority;
fdef->nattrs = nattr;
@@ -256,6 +261,7 @@ int git_filter_register(
filter_def_set_attrs(fdef);
if (git_vector_insert(&git__filter_registry->filters, fdef) < 0) {
+ git__free(fdef->filter_name);
git__free(fdef->attrdata);
git__free(fdef);
return -1;
@@ -270,6 +276,8 @@ int git_filter_unregister(const char *name)
size_t pos;
git_filter_def *fdef;
+ assert(name);
+
/* cannot unregister default filters */
if (!strcmp(GIT_FILTER_CRLF, name) || !strcmp(GIT_FILTER_IDENT, name)) {
giterr_set(GITERR_FILTER, "Cannot unregister filter '%s'", name);
@@ -288,6 +296,7 @@ int git_filter_unregister(const char *name)
fdef->initialized = false;
}
+ git__free(fdef->filter_name);
git__free(fdef->attrdata);
git__free(fdef);
diff --git a/src/global.c b/src/global.c
index f89c73256..4a0b680ef 100644
--- a/src/global.c
+++ b/src/global.c
@@ -223,6 +223,9 @@ int init_error = 0;
static void cb__free_status(void *st)
{
+ git_global_st *state = (git_global_st *) st;
+ git__free(state->error_t.message);
+
git__free(st);
}
diff --git a/src/global.h b/src/global.h
index 106504628..a89a8d6ab 100644
--- a/src/global.h
+++ b/src/global.h
@@ -7,13 +7,14 @@
#ifndef INCLUDE_global_h__
#define INCLUDE_global_h__
+#include "common.h"
#include "mwindow.h"
#include "hash.h"
typedef struct {
git_error *last_error;
git_error error_t;
- char oid_fmt[41];
+ char oid_fmt[GIT_OID_HEXSZ+1];
} git_global_st;
#ifdef GIT_SSL
diff --git a/src/hashsig.c b/src/hashsig.c
index 109f966ba..a6d5f2041 100644
--- a/src/hashsig.c
+++ b/src/hashsig.c
@@ -4,7 +4,7 @@
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "hashsig.h"
+#include "git2/sys/hashsig.h"
#include "fileops.h"
#include "util.h"
diff --git a/src/ignore.c b/src/ignore.c
index 78f01ac44..520bcfe41 100644
--- a/src/ignore.c
+++ b/src/ignore.c
@@ -91,11 +91,11 @@ static int push_ignore_file(
return error;
}
-static int push_one_ignore(void *payload, git_buf *path)
+static int push_one_ignore(void *payload, const char *path)
{
git_ignores *ign = payload;
ign->depth++;
- return push_ignore_file(ign, &ign->ign_path, path->ptr, GIT_IGNORE_FILE);
+ return push_ignore_file(ign, &ign->ign_path, path, GIT_IGNORE_FILE);
}
static int get_internal_ignores(git_attr_file **out, git_repository *repo)
diff --git a/src/index.c b/src/index.c
index b63a0bec6..8b757f269 100644
--- a/src/index.c
+++ b/src/index.c
@@ -1767,35 +1767,42 @@ static size_t read_entry(
git_index_entry **out, const void *buffer, size_t buffer_size)
{
size_t path_length, entry_size;
- uint16_t flags_raw;
const char *path_ptr;
- const struct entry_short *source = buffer;
+ struct entry_short source;
git_index_entry entry = {{0}};
if (INDEX_FOOTER_SIZE + minimal_entry_size > buffer_size)
return 0;
- entry.ctime.seconds = (git_time_t)ntohl(source->ctime.seconds);
- entry.ctime.nanoseconds = ntohl(source->ctime.nanoseconds);
- entry.mtime.seconds = (git_time_t)ntohl(source->mtime.seconds);
- entry.mtime.nanoseconds = ntohl(source->mtime.nanoseconds);
- entry.dev = ntohl(source->dev);
- entry.ino = ntohl(source->ino);
- entry.mode = ntohl(source->mode);
- entry.uid = ntohl(source->uid);
- entry.gid = ntohl(source->gid);
- entry.file_size = ntohl(source->file_size);
- git_oid_cpy(&entry.id, &source->oid);
- entry.flags = ntohs(source->flags);
+ /* buffer is not guaranteed to be aligned */
+ memcpy(&source, buffer, sizeof(struct entry_short));
+
+ entry.ctime.seconds = (git_time_t)ntohl(source.ctime.seconds);
+ entry.ctime.nanoseconds = ntohl(source.ctime.nanoseconds);
+ entry.mtime.seconds = (git_time_t)ntohl(source.mtime.seconds);
+ entry.mtime.nanoseconds = ntohl(source.mtime.nanoseconds);
+ entry.dev = ntohl(source.dev);
+ entry.ino = ntohl(source.ino);
+ entry.mode = ntohl(source.mode);
+ entry.uid = ntohl(source.uid);
+ entry.gid = ntohl(source.gid);
+ entry.file_size = ntohl(source.file_size);
+ git_oid_cpy(&entry.id, &source.oid);
+ entry.flags = ntohs(source.flags);
if (entry.flags & GIT_IDXENTRY_EXTENDED) {
- const struct entry_long *source_l = (const struct entry_long *)source;
- path_ptr = source_l->path;
+ uint16_t flags_raw;
+ size_t flags_offset;
- flags_raw = ntohs(source_l->flags_extended);
- memcpy(&entry.flags_extended, &flags_raw, 2);
+ flags_offset = offsetof(struct entry_long, flags_extended);
+ memcpy(&flags_raw, (const char *) buffer + flags_offset,
+ sizeof(flags_raw));
+ flags_raw = ntohs(flags_raw);
+
+ memcpy(&entry.flags_extended, &flags_raw, sizeof(flags_raw));
+ path_ptr = (const char *) buffer + offsetof(struct entry_long, path);
} else
- path_ptr = source->path;
+ path_ptr = (const char *) buffer + offsetof(struct entry_short, path);
path_length = entry.flags & GIT_IDXENTRY_NAMEMASK;
@@ -1846,14 +1853,12 @@ static int read_header(struct index_header *dest, const void *buffer)
static size_t read_extension(git_index *index, const char *buffer, size_t buffer_size)
{
- const struct index_extension *source;
struct index_extension dest;
size_t total_size;
- source = (const struct index_extension *)(buffer);
-
- memcpy(dest.signature, source->signature, 4);
- dest.extension_size = ntohl(source->extension_size);
+ /* buffer is not guaranteed to be aligned */
+ memcpy(&dest, buffer, sizeof(struct index_extension));
+ dest.extension_size = ntohl(dest.extension_size);
total_size = dest.extension_size + sizeof(struct index_extension);
diff --git a/src/merge.c b/src/merge.c
index 926a600cc..8252f6767 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -22,7 +22,6 @@
#include "tree.h"
#include "merge_file.h"
#include "blob.h"
-#include "hashsig.h"
#include "oid.h"
#include "index.h"
#include "filebuf.h"
@@ -42,6 +41,7 @@
#include "git2/tree.h"
#include "git2/oidarray.h"
#include "git2/sys/index.h"
+#include "git2/sys/hashsig.h"
#define GIT_MERGE_INDEX_ENTRY_EXISTS(X) ((X).mode != 0)
#define GIT_MERGE_INDEX_ENTRY_ISFILE(X) S_ISREG((X).mode)
@@ -62,16 +62,14 @@ struct merge_diff_df_data {
/* Merge base computation */
-int git_merge_base_many(git_oid *out, git_repository *repo, size_t length, const git_oid input_array[])
+int merge_bases_many(git_commit_list **out, git_revwalk **walk_out, git_repository *repo, size_t length, const git_oid input_array[])
{
- git_revwalk *walk;
+ git_revwalk *walk = NULL;
git_vector list;
git_commit_list *result = NULL;
+ git_commit_list_node *commit;
int error = -1;
unsigned int i;
- git_commit_list_node *commit;
-
- assert(out && repo && input_array);
if (length < 2) {
giterr_set(GITERR_INVALID, "At least two commits are required to find an ancestor. Provided 'length' was %u.", length);
@@ -82,37 +80,92 @@ int git_merge_base_many(git_oid *out, git_repository *repo, size_t length, const
return -1;
if (git_revwalk_new(&walk, repo) < 0)
- goto cleanup;
+ goto on_error;
for (i = 1; i < length; i++) {
commit = git_revwalk__commit_lookup(walk, &input_array[i]);
if (commit == NULL)
- goto cleanup;
+ goto on_error;
git_vector_insert(&list, commit);
}
commit = git_revwalk__commit_lookup(walk, &input_array[0]);
if (commit == NULL)
- goto cleanup;
+ goto on_error;
if (git_merge__bases_many(&result, walk, commit, &list) < 0)
- goto cleanup;
+ goto on_error;
if (!result) {
giterr_set(GITERR_MERGE, "No merge base found");
error = GIT_ENOTFOUND;
- goto cleanup;
+ goto on_error;
}
+ *out = result;
+ *walk_out = walk;
+
+ git_vector_free(&list);
+ return 0;
+
+on_error:
+ git_vector_free(&list);
+ git_revwalk_free(walk);
+ return error;
+}
+
+int git_merge_base_many(git_oid *out, git_repository *repo, size_t length, const git_oid input_array[])
+{
+ git_revwalk *walk;
+ git_commit_list *result = NULL;
+ int error = 0;
+
+ assert(out && repo && input_array);
+
+ if ((error = merge_bases_many(&result, &walk, repo, length, input_array)) < 0)
+ return error;
+
git_oid_cpy(out, &result->item->oid);
- error = 0;
+ git_commit_list_free(&result);
+ git_revwalk_free(walk);
+
+ return 0;
+}
+
+int git_merge_bases_many(git_oidarray *out, git_repository *repo, size_t length, const git_oid input_array[])
+{
+ git_revwalk *walk;
+ git_commit_list *list, *result = NULL;
+ int error = 0;
+ git_array_oid_t array;
+
+ assert(out && repo && input_array);
+
+ if ((error = merge_bases_many(&result, &walk, repo, length, input_array)) < 0)
+ return error;
+
+ git_array_init(array);
+
+ list = result;
+ while (list) {
+ git_oid *id = git_array_alloc(array);
+ if (id == NULL) {
+ error = -1;
+ goto cleanup;
+ }
+
+ git_oid_cpy(id, &list->item->oid);
+ list = list->next;
+ }
+
+ git_oidarray__from_array(out, &array);
cleanup:
git_commit_list_free(&result);
git_revwalk_free(walk);
- git_vector_free(&list);
+
return error;
}
@@ -2338,7 +2391,6 @@ done:
static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_index *index_new, git_vector *merged_paths)
{
- git_index *index_repo = NULL;
git_diff *wd_diff_list = NULL;
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
int error = 0;
@@ -2347,6 +2399,16 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde
*conflicts = 0;
+ /* We need to have merged at least 1 file for the possibility to exist to
+ * have conflicts with the workdir. Passing 0 as the pathspec count paramter
+ * will consider all files in the working directory, that is, we may detect
+ * a conflict if there were untracked files in the workdir prior to starting
+ * the merge. This typically happens when cherry-picking a commmit whose
+ * changes have already been applied.
+ */
+ if (merged_paths->length == 0)
+ return 0;
+
opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED;
/* Workdir changes may exist iff they do not conflict with changes that
@@ -2356,13 +2418,12 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde
opts.pathspec.count = merged_paths->length;
opts.pathspec.strings = (char **)merged_paths->contents;
- if ((error = git_diff_index_to_workdir(&wd_diff_list, repo, index_repo, &opts)) < 0)
+ if ((error = git_diff_index_to_workdir(&wd_diff_list, repo, NULL, &opts)) < 0)
goto done;
*conflicts = wd_diff_list->deltas.length;
done:
- git_index_free(index_repo);
git_diff_free(wd_diff_list);
return error;
diff --git a/src/netops.c b/src/netops.c
index fceb4fb74..adbae61c4 100644
--- a/src/netops.c
+++ b/src/netops.c
@@ -384,10 +384,10 @@ on_error:
cert_fail_name:
OPENSSL_free(peer_cn);
giterr_set(GITERR_SSL, "hostname does not match certificate");
- return -1;
+ return GIT_ECERTIFICATE;
}
-static int ssl_setup(gitno_socket *socket, const char *host, int flags)
+static int ssl_setup(gitno_socket *socket, const char *host)
{
int ret;
@@ -406,9 +406,6 @@ static int ssl_setup(gitno_socket *socket, const char *host, int flags)
if ((ret = SSL_connect(socket->ssl.ssl)) <= 0)
return ssl_set_error(&socket->ssl, ret);
- if (GITNO_CONNECT_SSL_NO_CHECK_CERT & flags)
- return 0;
-
return verify_server_cert(&socket->ssl, host);
}
#endif
@@ -461,7 +458,7 @@ int gitno_connect(gitno_socket *s_out, const char *host, const char *port, int f
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_UNSPEC;
- if ((ret = p_getaddrinfo(host, port, &hints, &info)) < 0) {
+ if ((ret = p_getaddrinfo(host, port, &hints, &info)) != 0) {
giterr_set(GITERR_NET,
"Failed to resolve address for %s: %s", host, p_gai_strerror(ret));
return -1;
@@ -494,8 +491,9 @@ int gitno_connect(gitno_socket *s_out, const char *host, const char *port, int f
p_freeaddrinfo(info);
#ifdef GIT_SSL
- if ((flags & GITNO_CONNECT_SSL) && ssl_setup(s_out, host, flags) < 0)
- return -1;
+ if ((flags & GITNO_CONNECT_SSL) &&
+ (ret = ssl_setup(s_out, host)) < 0)
+ return ret;
#else
/* SSL is not supported */
if (flags & GITNO_CONNECT_SSL) {
diff --git a/src/netops.h b/src/netops.h
index 75113fc7f..8ad915301 100644
--- a/src/netops.h
+++ b/src/netops.h
@@ -41,10 +41,6 @@ typedef struct gitno_buffer {
enum {
/* Attempt to create an SSL connection. */
GITNO_CONNECT_SSL = 1,
-
- /* Valid only when GITNO_CONNECT_SSL is also specified.
- * Indicates that the server certificate should not be validated. */
- GITNO_CONNECT_SSL_NO_CHECK_CERT = 2,
};
/**
diff --git a/src/odb_loose.c b/src/odb_loose.c
index b2e8bed4d..ef6de41a9 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -714,7 +714,7 @@ struct foreach_state {
GIT_INLINE(int) filename_to_oid(git_oid *oid, const char *ptr)
{
int v, i = 0;
- if (strlen(ptr) != 41)
+ if (strlen(ptr) != GIT_OID_HEXSZ+1)
return -1;
if (ptr[2] != '/') {
diff --git a/src/oidmap.h b/src/oidmap.h
index a29c7cd35..b871a7926 100644
--- a/src/oidmap.h
+++ b/src/oidmap.h
@@ -32,4 +32,20 @@ GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid)
#define git_oidmap_alloc() kh_init(oid)
#define git_oidmap_free(h) kh_destroy(oid,h), h = NULL
+#define git_oidmap_lookup_index(h, k) kh_get(oid, h, k)
+#define git_oidmap_valid_index(h, idx) (idx != kh_end(h))
+
+#define git_oidmap_value_at(h, idx) kh_val(h, idx)
+
+#define git_oidmap_insert(h, key, val, rval) do { \
+ khiter_t __pos = kh_put(oid, h, key, &rval); \
+ if (rval >= 0) { \
+ if (rval == 0) kh_key(h, __pos) = key; \
+ kh_val(h, __pos) = val; \
+ } } while (0)
+
+#define git_oidmap_foreach_value kh_foreach_value
+
+#define git_oidmap_size(h) kh_size(h)
+
#endif
diff --git a/src/pack.c b/src/pack.c
index 7c1cfe03e..516e0f3ca 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -620,7 +620,7 @@ int git_packfile_unpack(
struct pack_chain_elem *elem = NULL, *stack;
git_pack_cache_entry *cached = NULL;
struct pack_chain_elem small_stack[SMALL_STACK_SIZE];
- size_t stack_size, elem_pos;
+ size_t stack_size = 0, elem_pos;
git_otype base_type;
/*
diff --git a/src/path.c b/src/path.c
index d29b992fe..21b6e18d6 100644
--- a/src/path.c
+++ b/src/path.c
@@ -417,7 +417,7 @@ int git_path_fromurl(git_buf *local_path_out, const char *file_url)
int git_path_walk_up(
git_buf *path,
const char *ceiling,
- int (*cb)(void *data, git_buf *),
+ int (*cb)(void *data, const char *),
void *data)
{
int error = 0;
@@ -435,12 +435,20 @@ int git_path_walk_up(
}
scan = git_buf_len(path);
+ /* empty path: yield only once */
+ if (!scan) {
+ error = cb(data, "");
+ if (error)
+ giterr_set_after_callback(error);
+ return error;
+ }
+
iter.ptr = path->ptr;
iter.size = git_buf_len(path);
iter.asize = path->asize;
while (scan >= stop) {
- error = cb(data, &iter);
+ error = cb(data, iter.ptr);
iter.ptr[scan] = oldc;
if (error) {
@@ -460,6 +468,13 @@ int git_path_walk_up(
if (scan >= 0)
iter.ptr[scan] = oldc;
+ /* relative path: yield for the last component */
+ if (!error && stop == 0 && iter.ptr[0] != '/') {
+ error = cb(data, "");
+ if (error)
+ giterr_set_after_callback(error);
+ }
+
return error;
}
@@ -753,7 +768,7 @@ int git_path_cmp(
int git_path_make_relative(git_buf *path, const char *parent)
{
const char *p, *q, *p_dirsep, *q_dirsep;
- size_t plen = path->size, newlen, depth = 1, i;
+ size_t plen = path->size, newlen, depth = 1, i, offset;
for (p_dirsep = p = path->ptr, q_dirsep = q = parent; *p && *q; p++, q++) {
if (*p == '/' && *q == '/') {
@@ -793,8 +808,11 @@ int git_path_make_relative(git_buf *path, const char *parent)
newlen = (depth * 3) + plen;
+ /* save the offset as we might realllocate the pointer */
+ offset = p - path->ptr;
if (git_buf_try_grow(path, newlen + 1, 1, 0) < 0)
return -1;
+ p = path->ptr + offset;
memmove(path->ptr + (depth * 3), p, plen + 1);
@@ -965,7 +983,7 @@ int git_path_direach(
path_dirent_data de_data;
struct dirent *de, *de_buf = (struct dirent *)&de_data;
- (void)flags;
+ GIT_UNUSED(flags);
#ifdef GIT_USE_ICONV
git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
@@ -1036,7 +1054,7 @@ int git_path_dirload(
path_dirent_data de_data;
struct dirent *de, *de_buf = (struct dirent *)&de_data;
- (void)flags;
+ GIT_UNUSED(flags);
#ifdef GIT_USE_ICONV
git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
@@ -1088,8 +1106,10 @@ int git_path_dirload(
entry_path[path_len] = '/';
memcpy(&entry_path[path_len + need_slash], de_path, de_len);
- if ((error = git_vector_insert(contents, entry_path)) < 0)
+ if ((error = git_vector_insert(contents, entry_path)) < 0) {
+ git__free(entry_path);
break;
+ }
}
closedir(dir);
diff --git a/src/path.h b/src/path.h
index d0a9de707..11bb6d173 100644
--- a/src/path.h
+++ b/src/path.h
@@ -323,7 +323,7 @@ extern int git_path_cmp(
extern int git_path_walk_up(
git_buf *pathbuf,
const char *ceiling,
- int (*callback)(void *payload, git_buf *path),
+ int (*callback)(void *payload, const char *path),
void *payload);
/**
diff --git a/src/pool.c b/src/pool.c
index a516ff9eb..30555273e 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -7,7 +7,7 @@ struct git_pool_page {
git_pool_page *next;
uint32_t size;
uint32_t avail;
- char data[GIT_FLEX_ARRAY];
+ GIT_ALIGN(char data[GIT_FLEX_ARRAY], 8);
};
struct pool_freelist {
diff --git a/src/posix.c b/src/posix.c
index 7aeb0e6c1..21b049e1b 100644
--- a/src/posix.c
+++ b/src/posix.c
@@ -151,15 +151,14 @@ int p_rename(const char *from, const char *to)
#endif /* GIT_WIN32 */
-int p_read(git_file fd, void *buf, size_t cnt)
+ssize_t p_read(git_file fd, void *buf, size_t cnt)
{
char *b = buf;
while (cnt) {
ssize_t r;
#ifdef GIT_WIN32
- assert((size_t)((unsigned int)cnt) == cnt);
- r = read(fd, b, (unsigned int)cnt);
+ r = read(fd, b, cnt > INT_MAX ? INT_MAX : (unsigned int)cnt);
#else
r = read(fd, b, cnt);
#endif
@@ -173,7 +172,7 @@ int p_read(git_file fd, void *buf, size_t cnt)
cnt -= r;
b += r;
}
- return (int)(b - (char *)buf);
+ return (b - (char *)buf);
}
int p_write(git_file fd, const void *buf, size_t cnt)
diff --git a/src/posix.h b/src/posix.h
index 9ef348739..71c403c2f 100644
--- a/src/posix.h
+++ b/src/posix.h
@@ -97,7 +97,7 @@ typedef int git_file;
* Use your manpages to check the docs on these.
*/
-extern int p_read(git_file fd, void *buf, size_t cnt);
+extern ssize_t p_read(git_file fd, void *buf, size_t cnt);
extern int p_write(git_file fd, const void *buf, size_t cnt);
#define p_close(fd) close(fd)
diff --git a/src/refdb.c b/src/refdb.c
index 69bf74734..16fb519a6 100644
--- a/src/refdb.c
+++ b/src/refdb.c
@@ -242,3 +242,22 @@ int git_refdb_init_backend(git_refdb_backend *backend, unsigned int version)
backend, version, git_refdb_backend, GIT_REFDB_BACKEND_INIT);
return 0;
}
+
+int git_refdb_lock(void **payload, git_refdb *db, const char *refname)
+{
+ assert(payload && db && refname);
+
+ if (!db->backend->lock) {
+ giterr_set(GITERR_REFERENCE, "backend does not support locking");
+ return -1;
+ }
+
+ return db->backend->lock(payload, db->backend, refname);
+}
+
+int git_refdb_unlock(git_refdb *db, void *payload, int success, int update_reflog, const git_reference *ref, const git_signature *sig, const char *message)
+{
+ assert(db);
+
+ return db->backend->unlock(db->backend, payload, success, update_reflog, ref, sig, message);
+}
diff --git a/src/refdb.h b/src/refdb.h
index cbad86faf..4ee3b8065 100644
--- a/src/refdb.h
+++ b/src/refdb.h
@@ -51,6 +51,7 @@ int git_refdb_reflog_write(git_reflog *reflog);
int git_refdb_has_log(git_refdb *db, const char *refname);
int git_refdb_ensure_log(git_refdb *refdb, const char *refname);
-
+int git_refdb_lock(void **payload, git_refdb *db, const char *refname);
+int git_refdb_unlock(git_refdb *db, void *payload, int success, int update_reflog, const git_reference *ref, const git_signature *sig, const char *message);
#endif
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index 0e36ca8ac..f39ba4f9c 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -745,6 +745,57 @@ static int loose_commit(git_filebuf *file, const git_reference *ref)
return git_filebuf_commit(file);
}
+static int refdb_fs_backend__lock(void **out, git_refdb_backend *_backend, const char *refname)
+{
+ int error;
+ git_filebuf *lock;
+ refdb_fs_backend *backend = (refdb_fs_backend *) _backend;
+
+ lock = git__calloc(1, sizeof(git_filebuf));
+ GITERR_CHECK_ALLOC(lock);
+
+ if ((error = loose_lock(lock, backend, refname)) < 0) {
+ git__free(lock);
+ return error;
+ }
+
+ *out = lock;
+ return 0;
+}
+
+static int refdb_fs_backend__write_tail(
+ git_refdb_backend *_backend,
+ const git_reference *ref,
+ git_filebuf *file,
+ int update_reflog,
+ const git_signature *who,
+ const char *message,
+ const git_oid *old_id,
+ const char *old_target);
+
+static int refdb_fs_backend__delete_tail(
+ git_refdb_backend *_backend,
+ git_filebuf *file,
+ const char *ref_name,
+ const git_oid *old_id, const char *old_target);
+
+static int refdb_fs_backend__unlock(git_refdb_backend *backend, void *payload, int success, int update_reflog,
+ const git_reference *ref, const git_signature *sig, const char *message)
+{
+ git_filebuf *lock = (git_filebuf *) payload;
+ int error = 0;
+
+ if (success == 2)
+ error = refdb_fs_backend__delete_tail(backend, lock, ref->name, NULL, NULL);
+ else if (success)
+ error = refdb_fs_backend__write_tail(backend, ref, lock, update_reflog, sig, message, NULL, NULL);
+ else
+ git_filebuf_cleanup(lock);
+
+ git__free(lock);
+ return error;
+}
+
/*
* Find out what object this reference resolves to.
*
@@ -1063,7 +1114,6 @@ cleanup:
return error;
}
-
static int refdb_fs_backend__write(
git_refdb_backend *_backend,
const git_reference *ref,
@@ -1075,9 +1125,7 @@ static int refdb_fs_backend__write(
{
refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
git_filebuf file = GIT_FILEBUF_INIT;
- int error = 0, cmp = 0, should_write;
- const char *new_target = NULL;
- const git_oid *new_id = NULL;
+ int error = 0;
assert(backend);
@@ -1089,6 +1137,24 @@ static int refdb_fs_backend__write(
if ((error = loose_lock(&file, backend, ref->name)) < 0)
return error;
+ return refdb_fs_backend__write_tail(_backend, ref, &file, true, who, message, old_id, old_target);
+}
+
+static int refdb_fs_backend__write_tail(
+ git_refdb_backend *_backend,
+ const git_reference *ref,
+ git_filebuf *file,
+ int update_reflog,
+ const git_signature *who,
+ const char *message,
+ const git_oid *old_id,
+ const char *old_target)
+{
+ refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
+ int error = 0, cmp = 0, should_write;
+ const char *new_target = NULL;
+ const git_oid *new_id = NULL;
+
if ((error = cmp_old_ref(&cmp, _backend, ref->name, old_id, old_target)) < 0)
goto on_error;
@@ -1113,20 +1179,22 @@ static int refdb_fs_backend__write(
goto on_error; /* not really error */
}
- if ((error = should_write_reflog(&should_write, backend->repo, ref->name)) < 0)
- goto on_error;
-
- if (should_write) {
- if ((error = reflog_append(backend, ref, NULL, NULL, who, message)) < 0)
- goto on_error;
- if ((error = maybe_append_head(backend, ref, who, message)) < 0)
+ if (update_reflog) {
+ if ((error = should_write_reflog(&should_write, backend->repo, ref->name)) < 0)
goto on_error;
+
+ if (should_write) {
+ if ((error = reflog_append(backend, ref, NULL, NULL, who, message)) < 0)
+ goto on_error;
+ if ((error = maybe_append_head(backend, ref, who, message)) < 0)
+ goto on_error;
+ }
}
- return loose_commit(&file, ref);
+ return loose_commit(file, ref);
on_error:
- git_filebuf_cleanup(&file);
+ git_filebuf_cleanup(file);
return error;
}
@@ -1136,17 +1204,29 @@ static int refdb_fs_backend__delete(
const git_oid *old_id, const char *old_target)
{
refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
- git_buf loose_path = GIT_BUF_INIT;
- size_t pack_pos;
git_filebuf file = GIT_FILEBUF_INIT;
- int error = 0, cmp = 0;
- bool loose_deleted = 0;
+ int error = 0;
assert(backend && ref_name);
if ((error = loose_lock(&file, backend, ref_name)) < 0)
return error;
+ return refdb_fs_backend__delete_tail(_backend, &file, ref_name, old_id, old_target);
+}
+
+static int refdb_fs_backend__delete_tail(
+ git_refdb_backend *_backend,
+ git_filebuf *file,
+ const char *ref_name,
+ const git_oid *old_id, const char *old_target)
+{
+ refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
+ git_buf loose_path = GIT_BUF_INIT;
+ size_t pack_pos;
+ int error = 0, cmp = 0;
+ bool loose_deleted = 0;
+
error = cmp_old_ref(&cmp, _backend, ref_name, old_id, old_target);
if (error < 0)
goto cleanup;
@@ -1192,7 +1272,7 @@ static int refdb_fs_backend__delete(
error = packed_write(backend);
cleanup:
- git_filebuf_cleanup(&file);
+ git_filebuf_cleanup(file);
return error;
}
@@ -1837,6 +1917,8 @@ int git_refdb_backend_fs(
backend->parent.del = &refdb_fs_backend__delete;
backend->parent.rename = &refdb_fs_backend__rename;
backend->parent.compress = &refdb_fs_backend__compress;
+ backend->parent.lock = &refdb_fs_backend__lock;
+ backend->parent.unlock = &refdb_fs_backend__unlock;
backend->parent.has_log = &refdb_reflog_fs__has_log;
backend->parent.ensure_log = &refdb_reflog_fs__ensure_log;
backend->parent.free = &refdb_fs_backend__free;
diff --git a/src/reflog.c b/src/reflog.c
index 8e41621ea..22aa7d8ed 100644
--- a/src/reflog.c
+++ b/src/reflog.c
@@ -148,7 +148,7 @@ size_t git_reflog_entrycount(git_reflog *reflog)
return reflog->entries.length;
}
-const git_reflog_entry * git_reflog_entry_byindex(git_reflog *reflog, size_t idx)
+const git_reflog_entry * git_reflog_entry_byindex(const git_reflog *reflog, size_t idx)
{
assert(reflog);
diff --git a/src/refs.c b/src/refs.c
index 1603876da..08e407e48 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -411,7 +411,7 @@ static int reference__create(
return 0;
}
-static int log_signature(git_signature **out, git_repository *repo)
+int git_reference__log_signature(git_signature **out, git_repository *repo)
{
int error;
git_signature *who;
@@ -441,7 +441,7 @@ int git_reference_create_matching(
assert(id);
if (!signature) {
- if ((error = log_signature(&who, repo)) < 0)
+ if ((error = git_reference__log_signature(&who, repo)) < 0)
return error;
else
signature = who;
@@ -482,7 +482,7 @@ int git_reference_symbolic_create_matching(
assert(target);
if (!signature) {
- if ((error = log_signature(&who, repo)) < 0)
+ if ((error = git_reference__log_signature(&who, repo)) < 0)
return error;
else
signature = who;
diff --git a/src/refs.h b/src/refs.h
index 2e79bdfca..c6ec429a5 100644
--- a/src/refs.h
+++ b/src/refs.h
@@ -98,4 +98,6 @@ int git_reference_lookup_resolved(
const char *name,
int max_deref);
+int git_reference__log_signature(git_signature **out, git_repository *repo);
+
#endif
diff --git a/src/remote.c b/src/remote.c
index fa5ec8b4c..10b56243f 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -21,7 +21,7 @@
static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs);
-static int add_refspec(git_remote *remote, const char *string, bool is_fetch)
+static int add_refspec_to(git_vector *vector, const char *string, bool is_fetch)
{
git_refspec *spec;
@@ -34,7 +34,7 @@ static int add_refspec(git_remote *remote, const char *string, bool is_fetch)
}
spec->push = !is_fetch;
- if (git_vector_insert(&remote->refspecs, spec) < 0) {
+ if (git_vector_insert(vector, spec) < 0) {
git_refspec__free(spec);
git__free(spec);
return -1;
@@ -43,6 +43,11 @@ static int add_refspec(git_remote *remote, const char *string, bool is_fetch)
return 0;
}
+static int add_refspec(git_remote *remote, const char *string, bool is_fetch)
+{
+ return add_refspec_to(&remote->refspecs, string, is_fetch);
+}
+
static int download_tags_value(git_remote *remote, git_config *cfg)
{
const git_config_entry *ce;
@@ -80,6 +85,8 @@ static int ensure_remote_name_is_valid(const char *name)
return error;
}
+#if 0
+/* We could export this as a helper */
static int get_check_cert(int *out, git_repository *repo)
{
git_config *cfg;
@@ -105,6 +112,7 @@ static int get_check_cert(int *out, git_repository *repo)
*out = git_config__get_bool_force(cfg, "http.sslverify", 1);
return 0;
}
+#endif
static int create_internal(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
{
@@ -121,9 +129,6 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n
remote->repo = repo;
remote->update_fetchhead = 1;
- if (get_check_cert(&remote->check_cert, repo) < 0)
- goto on_error;
-
if (git_vector_init(&remote->refs, 32, NULL) < 0)
goto on_error;
@@ -274,7 +279,6 @@ int git_remote_dup(git_remote **dest, git_remote *source)
remote->transport_cb_payload = source->transport_cb_payload;
remote->repo = source->repo;
remote->download_tags = source->download_tags;
- remote->check_cert = source->check_cert;
remote->update_fetchhead = source->update_fetchhead;
if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
@@ -369,11 +373,9 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
remote->name = git__strdup(name);
GITERR_CHECK_ALLOC(remote->name);
- if ((error = get_check_cert(&remote->check_cert, repo)) < 0)
- goto cleanup;
-
if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
git_vector_init(&remote->refspecs, 2, NULL) < 0 ||
+ git_vector_init(&remote->passive_refspecs, 2, NULL) < 0 ||
git_vector_init(&remote->active_refspecs, 2, NULL) < 0) {
error = -1;
goto cleanup;
@@ -673,12 +675,9 @@ int git_remote_connect(git_remote *remote, git_direction direction)
return error;
if (t->set_callbacks &&
- (error = t->set_callbacks(t, remote->callbacks.sideband_progress, NULL, remote->callbacks.payload)) < 0)
+ (error = t->set_callbacks(t, remote->callbacks.sideband_progress, NULL, remote->callbacks.certificate_check, remote->callbacks.payload)) < 0)
goto on_error;
- if (!remote->check_cert)
- flags |= GIT_TRANSPORTFLAGS_NO_CHECK_CERT;
-
if ((error = t->connect(t, url, remote->callbacks.credentials, remote->callbacks.payload, direction, flags)) != 0)
goto on_error;
@@ -820,20 +819,43 @@ static int ls_to_vector(git_vector *out, git_remote *remote)
return 0;
}
-int git_remote_download(git_remote *remote)
+int git_remote_download(git_remote *remote, const git_strarray *refspecs)
{
- int error;
- git_vector refs;
+ int error = -1;
+ size_t i;
+ git_vector refs, specs, *to_active;
assert(remote);
if (ls_to_vector(&refs, remote) < 0)
return -1;
+ if ((git_vector_init(&specs, 0, NULL)) < 0)
+ goto on_error;
+
+ remote->passed_refspecs = 0;
+ if (!refspecs || !refspecs->count) {
+ to_active = &remote->refspecs;
+ } else {
+ for (i = 0; i < refspecs->count; i++) {
+ if ((error = add_refspec_to(&specs, refspecs->strings[i], true)) < 0)
+ goto on_error;
+ }
+
+ to_active = &specs;
+ remote->passed_refspecs = 1;
+ }
+
+ free_refspecs(&remote->passive_refspecs);
+ if ((error = dwim_refspecs(&remote->passive_refspecs, &remote->refspecs, &refs)) < 0)
+ goto on_error;
+
free_refspecs(&remote->active_refspecs);
+ error = dwim_refspecs(&remote->active_refspecs, to_active, &refs);
- error = dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &refs);
git_vector_free(&refs);
+ free_refspecs(&specs);
+ git_vector_free(&specs);
if (error < 0)
return error;
@@ -842,10 +864,17 @@ int git_remote_download(git_remote *remote)
return error;
return git_fetch_download_pack(remote);
+
+on_error:
+ git_vector_free(&refs);
+ free_refspecs(&specs);
+ git_vector_free(&specs);
+ return error;
}
int git_remote_fetch(
git_remote *remote,
+ const git_strarray *refspecs,
const git_signature *signature,
const char *reflog_message)
{
@@ -856,7 +885,7 @@ int git_remote_fetch(
if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) != 0)
return error;
- error = git_remote_download(remote);
+ error = git_remote_download(remote, refspecs);
/* We don't need to be connected anymore */
git_remote_disconnect(remote);
@@ -898,13 +927,15 @@ static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *upda
return 0;
}
-static int remote_head_for_ref(git_remote_head **out, git_refspec *spec, git_vector *update_heads, git_reference *ref)
+static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_refspec *spec, git_vector *update_heads, git_reference *ref)
{
git_reference *resolved_ref = NULL;
git_buf remote_name = GIT_BUF_INIT;
git_buf upstream_name = GIT_BUF_INIT;
+ git_buf config_key = GIT_BUF_INIT;
git_repository *repo;
- const char *ref_name;
+ git_config *config = NULL;
+ const char *ref_name, *branch_remote;
int error = 0;
assert(out && spec && ref);
@@ -924,6 +955,11 @@ static int remote_head_for_ref(git_remote_head **out, git_refspec *spec, git_vec
}
if ((!git_reference__is_branch(ref_name)) ||
+ (error = git_repository_config_snapshot(&config, repo)) < 0 ||
+ (error = git_buf_printf(&config_key, "branch.%s.remote",
+ ref_name + strlen(GIT_REFS_HEADS_DIR))) < 0 ||
+ (error = git_config_get_string(&branch_remote, config, git_buf_cstr(&config_key))) < 0 ||
+ git__strcmp(git_remote_name(remote), branch_remote) ||
(error = git_branch_upstream_name(&upstream_name, repo, ref_name)) < 0 ||
(error = git_refspec_rtransform(&remote_name, spec, upstream_name.ptr)) < 0) {
/* Not an error if there is no upstream */
@@ -939,6 +975,8 @@ cleanup:
git_reference_free(resolved_ref);
git_buf_free(&remote_name);
git_buf_free(&upstream_name);
+ git_buf_free(&config_key);
+ git_config_free(config);
return error;
}
@@ -967,7 +1005,7 @@ static int git_remote_write_fetchhead(git_remote *remote, git_refspec *spec, git
/* Determine what to merge: if refspec was a wildcard, just use HEAD */
if (git_refspec_is_wildcard(spec)) {
if ((error = git_reference_lookup(&head_ref, remote->repo, GIT_HEAD_FILE)) < 0 ||
- (error = remote_head_for_ref(&merge_remote_ref, spec, update_heads, head_ref)) < 0)
+ (error = remote_head_for_ref(&merge_remote_ref, remote, spec, update_heads, head_ref)) < 0)
goto cleanup;
} else {
/* If we're fetching a single refspec, that's the only thing that should be in FETCH_HEAD. */
@@ -1065,16 +1103,20 @@ static int update_tips_for_spec(
if (autotag && !git_odb_exists(odb, &head->oid))
continue;
- if (git_vector_insert(&update_heads, head) < 0)
+ if (!autotag && git_vector_insert(&update_heads, head) < 0)
goto on_error;
error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
if (error < 0 && error != GIT_ENOTFOUND)
goto on_error;
- if (error == GIT_ENOTFOUND)
+ if (error == GIT_ENOTFOUND) {
memset(&old, 0, GIT_OID_RAWSZ);
+ if (autotag && git_vector_insert(&update_heads, head) < 0)
+ goto on_error;
+ }
+
if (!git_oid__cmp(&old, &head->oid))
continue;
@@ -1109,6 +1151,96 @@ on_error:
}
+/**
+ * Iteration over the three vectors, with a pause whenever we find a match
+ *
+ * On each stop, we store the iteration stat in the inout i,j,k
+ * parameters, and return the currently matching passive refspec as
+ * well as the head which we matched.
+ */
+static int next_head(const git_remote *remote, git_vector *refs,
+ git_refspec **out_spec, git_remote_head **out_head,
+ size_t *out_i, size_t *out_j, size_t *out_k)
+{
+ const git_vector *active, *passive;
+ git_remote_head *head;
+ git_refspec *spec, *passive_spec;
+ size_t i, j, k;
+
+ active = &remote->active_refspecs;
+ passive = &remote->passive_refspecs;
+
+ i = *out_i;
+ j = *out_j;
+ k = *out_k;
+
+ for (; i < refs->length; i++) {
+ head = git_vector_get(refs, i);
+
+ if (!git_reference_is_valid_name(head->name))
+ continue;
+
+ for (; j < active->length; j++) {
+ spec = git_vector_get(active, j);
+
+ if (!git_refspec_src_matches(spec, head->name))
+ continue;
+
+ for (; k < passive->length; k++) {
+ passive_spec = git_vector_get(passive, k);
+
+ if (!git_refspec_src_matches(passive_spec, head->name))
+ continue;
+
+ *out_spec = passive_spec;
+ *out_head = head;
+ *out_i = i;
+ *out_j = j;
+ *out_k = k + 1;
+ return 0;
+
+ }
+ k = 0;
+ }
+ j = 0;
+ }
+
+ return GIT_ITEROVER;
+}
+
+static int opportunistic_updates(const git_remote *remote, git_vector *refs, const git_signature *sig, const char *msg)
+{
+ size_t i, j, k;
+ git_refspec *spec;
+ git_remote_head *head;
+ git_reference *ref;
+ git_buf refname = GIT_BUF_INIT;
+ int error;
+
+ i = j = k = 0;
+
+ while ((error = next_head(remote, refs, &spec, &head, &i, &j, &k)) == 0) {
+ /*
+ * If we got here, there is a refspec which was used
+ * for fetching which matches the source of one of the
+ * passive refspecs, so we should update that
+ * remote-tracking branch, but not add it to
+ * FETCH_HEAD
+ */
+
+ if ((error = git_refspec_transform(&refname, spec, head->name)) < 0)
+ return error;
+
+ error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, true, sig, msg);
+ git_buf_free(&refname);
+
+ if (error < 0)
+ return error;
+ }
+
+ return 0;
+}
+
int git_remote_update_tips(
git_remote *remote,
const git_signature *signature,
@@ -1139,6 +1271,10 @@ int git_remote_update_tips(
goto out;
}
+ /* only try to do opportunisitic updates if the refpec lists differ */
+ if (remote->passed_refspecs)
+ error = opportunistic_updates(remote, &refs, signature, reflog_message);
+
out:
git_vector_free(&refs);
git_refspec__free(&tagspec);
@@ -1192,6 +1328,9 @@ void git_remote_free(git_remote *remote)
free_refspecs(&remote->active_refspecs);
git_vector_free(&remote->active_refspecs);
+ free_refspecs(&remote->passive_refspecs);
+ git_vector_free(&remote->passive_refspecs);
+
git__free(remote->url);
git__free(remote->pushurl);
git__free(remote->name);
@@ -1244,13 +1383,6 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo)
return 0;
}
-void git_remote_check_cert(git_remote *remote, int check)
-{
- assert(remote);
-
- remote->check_cert = check;
-}
-
int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks)
{
assert(remote && callbacks);
@@ -1263,6 +1395,7 @@ int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *cal
return remote->transport->set_callbacks(remote->transport,
remote->callbacks.sideband_progress,
NULL,
+ remote->callbacks.certificate_check,
remote->callbacks.payload);
return 0;
@@ -1649,27 +1782,14 @@ void git_remote_clear_refspecs(git_remote *remote)
git_vector_clear(&remote->refspecs);
}
-static int add_and_dwim(git_remote *remote, const char *str, int push)
-{
- git_refspec *spec;
- git_vector *vec;
-
- if (add_refspec(remote, str, !push) < 0)
- return -1;
-
- vec = &remote->refspecs;
- spec = git_vector_get(vec, vec->length - 1);
- return git_refspec__dwim_one(&remote->active_refspecs, spec, &remote->refs);
-}
-
int git_remote_add_fetch(git_remote *remote, const char *refspec)
{
- return add_and_dwim(remote, refspec, false);
+ return add_refspec(remote, refspec, true);
}
int git_remote_add_push(git_remote *remote, const char *refspec)
{
- return add_and_dwim(remote, refspec, true);
+ return add_refspec(remote, refspec, false);
}
static int set_refspecs(git_remote *remote, git_strarray *array, int push)
@@ -1697,10 +1817,7 @@ static int set_refspecs(git_remote *remote, git_strarray *array, int push)
return -1;
}
- free_refspecs(&remote->active_refspecs);
- git_vector_clear(&remote->active_refspecs);
-
- return dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs);
+ return 0;
}
int git_remote_set_fetch_refspecs(git_remote *remote, git_strarray *array)
diff --git a/src/remote.h b/src/remote.h
index c471756b8..b79ace438 100644
--- a/src/remote.h
+++ b/src/remote.h
@@ -23,6 +23,7 @@ struct git_remote {
git_vector refs;
git_vector refspecs;
git_vector active_refspecs;
+ git_vector passive_refspecs;
git_transport_cb transport_cb;
void *transport_cb_payload;
git_transport *transport;
@@ -31,8 +32,8 @@ struct git_remote {
git_transfer_progress stats;
unsigned int need_pack;
git_remote_autotag_option_t download_tags;
- int check_cert;
int update_fetchhead;
+ int passed_refspecs;
};
const char* git_remote__urlfordirection(struct git_remote *remote, int direction);
diff --git a/src/repository.c b/src/repository.c
index d86d8905a..f032c899d 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -1567,8 +1567,10 @@ int git_repository_head_unborn(git_repository *repo)
error = git_repository_head(&ref, repo);
git_reference_free(ref);
- if (error == GIT_EUNBORNBRANCH)
+ if (error == GIT_EUNBORNBRANCH) {
+ giterr_clear();
return 1;
+ }
if (error < 0)
return -1;
@@ -1681,6 +1683,32 @@ int git_repository_is_bare(git_repository *repo)
return repo->is_bare;
}
+int git_repository_set_bare(git_repository *repo)
+{
+ int error;
+ git_config *config;
+
+ assert(repo);
+
+ if (repo->is_bare)
+ return 0;
+
+ if ((error = git_repository_config__weakptr(&config, repo)) < 0)
+ return error;
+
+ if ((error = git_config_set_bool(config, "core.bare", false)) < 0)
+ return error;
+
+ if ((error = git_config__update_entry(config, "core.worktree", NULL, true, true)) < 0)
+ return error;
+
+ git__free(repo->workdir);
+ repo->workdir = NULL;
+ repo->is_bare = 1;
+
+ return 0;
+}
+
int git_repository_head_tree(git_tree **tree, git_repository *repo)
{
git_reference *head;
diff --git a/src/reset.c b/src/reset.c
index 248c91d3a..d063abe25 100644
--- a/src/reset.c
+++ b/src/reset.c
@@ -100,6 +100,7 @@ int git_reset(
git_repository *repo,
git_object *target,
git_reset_t reset_type,
+ git_checkout_options *checkout_opts,
git_signature *signature,
const char *log_message)
{
@@ -112,6 +113,9 @@ int git_reset(
assert(repo && target);
+ if (checkout_opts)
+ opts = *checkout_opts;
+
if (git_object_owner(target) != repo) {
giterr_set(GITERR_OBJECT,
"%s - The given target does not belong to this repository.", ERROR_MSG);
diff --git a/src/revwalk.c b/src/revwalk.c
index bd07d02cb..4dca7599a 100644
--- a/src/revwalk.c
+++ b/src/revwalk.c
@@ -116,6 +116,7 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting,
int error;
git_object *obj, *oobj;
git_commit_list_node *commit;
+ git_commit_list *list;
if ((error = git_object_lookup(&oobj, walk->repo, oid, GIT_OBJ_ANY)) < 0)
return error;
@@ -141,14 +142,20 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting,
if (commit == NULL)
return -1; /* error already reported by failed lookup */
+ if (uninteresting)
+ walk->did_hide = 1;
+ else
+ walk->did_push = 1;
+
commit->uninteresting = uninteresting;
- if (walk->one == NULL && !uninteresting) {
- walk->one = commit;
- } else {
- if (git_vector_insert(&walk->twos, commit) < 0)
- return -1;
+ list = walk->user_input;
+ if (git_commit_list_insert(commit, &list) == NULL) {
+ giterr_set_oom();
+ return -1;
}
+ walk->user_input = list;
+
return 0;
}
@@ -367,29 +374,97 @@ static int revwalk_next_reverse(git_commit_list_node **object_out, git_revwalk *
}
+static int interesting(git_pqueue *list)
+{
+ size_t i;
+
+ for (i = 0; i < git_pqueue_size(list); i++) {
+ git_commit_list_node *commit = git_pqueue_get(list, i);
+ if (!commit->uninteresting)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int contains(git_pqueue *list, git_commit_list_node *node)
+{
+ size_t i;
+
+ for (i = 0; i < git_pqueue_size(list); i++) {
+ git_commit_list_node *commit = git_pqueue_get(list, i);
+ if (commit == node)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int premark_uninteresting(git_revwalk *walk)
+{
+ int error = 0;
+ unsigned short i;
+ git_pqueue q;
+ git_commit_list *list;
+ git_commit_list_node *commit, *parent;
+
+ if ((error = git_pqueue_init(&q, 0, 8, git_commit_list_time_cmp)) < 0)
+ return error;
+
+ for (list = walk->user_input; list; list = list->next) {
+ if ((error = git_commit_list_parse(walk, list->item)) < 0)
+ goto cleanup;
+
+ if ((error = git_pqueue_insert(&q, list->item)) < 0)
+ goto cleanup;
+ }
+
+ while (interesting(&q)) {
+ commit = git_pqueue_pop(&q);
+
+ for (i = 0; i < commit->out_degree; i++) {
+ parent = commit->parents[i];
+
+ if ((error = git_commit_list_parse(walk, parent)) < 0)
+ goto cleanup;
+
+ if (commit->uninteresting)
+ parent->uninteresting = 1;
+
+ if (contains(&q, parent))
+ continue;
+
+ if ((error = git_pqueue_insert(&q, parent)) < 0)
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ git_pqueue_free(&q);
+ return error;
+}
+
static int prepare_walk(git_revwalk *walk)
{
int error;
- unsigned int i;
- git_commit_list_node *next, *two;
-
- /*
- * If walk->one is NULL, there were no positive references,
- * so we know that the walk is already over.
- */
- if (walk->one == NULL) {
+ git_commit_list *list;
+ git_commit_list_node *next;
+
+ /* If there were no pushes, we know that the walk is already over */
+ if (!walk->did_push) {
giterr_clear();
return GIT_ITEROVER;
}
- if (process_commit(walk, walk->one, walk->one->uninteresting) < 0)
- return -1;
+ if (walk->did_hide && (error = premark_uninteresting(walk)) < 0)
+ return error;
- git_vector_foreach(&walk->twos, i, two) {
- if (process_commit(walk, two, two->uninteresting) < 0)
+ for (list = walk->user_input; list; list = list->next) {
+ if (process_commit(walk, list->item, list->item->uninteresting) < 0)
return -1;
}
+
if (walk->sorting & GIT_SORT_TOPOLOGICAL) {
unsigned short i;
@@ -440,7 +515,6 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
if (git_pqueue_init(
&walk->iterator_time, 0, 8, git_commit_list_time_cmp) < 0 ||
- git_vector_init(&walk->twos, 4, NULL) < 0 ||
git_pool_init(&walk->commit_pool, 1,
git_pool__suggest_items_per_page(COMMIT_ALLOC) * COMMIT_ALLOC) < 0)
return -1;
@@ -470,7 +544,6 @@ void git_revwalk_free(git_revwalk *walk)
git_oidmap_free(walk->commits);
git_pool_clear(&walk->commit_pool);
git_pqueue_free(&walk->iterator_time);
- git_vector_free(&walk->twos);
git__free(walk);
}
@@ -540,16 +613,17 @@ void git_revwalk_reset(git_revwalk *walk)
commit->in_degree = 0;
commit->topo_delay = 0;
commit->uninteresting = 0;
+ commit->flags = 0;
});
git_pqueue_clear(&walk->iterator_time);
git_commit_list_free(&walk->iterator_topo);
git_commit_list_free(&walk->iterator_rand);
git_commit_list_free(&walk->iterator_reverse);
+ git_commit_list_free(&walk->user_input);
+ walk->first_parent = 0;
walk->walking = 0;
-
- walk->one = NULL;
- git_vector_clear(&walk->twos);
+ walk->did_push = walk->did_hide = 0;
}
int git_revwalk_add_hide_cb(
diff --git a/src/revwalk.h b/src/revwalk.h
index d81f97c01..72ddedc75 100644
--- a/src/revwalk.h
+++ b/src/revwalk.h
@@ -32,12 +32,13 @@ struct git_revwalk {
int (*enqueue)(git_revwalk *, git_commit_list_node *);
unsigned walking:1,
- first_parent: 1;
+ first_parent: 1,
+ did_hide: 1,
+ did_push: 1;
unsigned int sorting;
- /* merge base calculation */
- git_commit_list_node *one;
- git_vector twos;
+ /* the pushes and hides */
+ git_commit_list *user_input;
/* hide callback */
git_revwalk_hide_cb hide_cb;
diff --git a/src/settings.c b/src/settings.c
index 1a21ea024..971b50935 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -5,10 +5,15 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#ifdef GIT_SSL
+# include <openssl/err.h>
+#endif
+
#include <git2.h>
#include "common.h"
#include "sysdir.h"
#include "cache.h"
+#include "global.h"
void git_libgit2_version(int *major, int *minor, int *rev)
{
@@ -131,6 +136,23 @@ int git_libgit2_opts(int key, ...)
case GIT_OPT_SET_TEMPLATE_PATH:
error = git_sysdir_set(GIT_SYSDIR_TEMPLATE, va_arg(ap, const char *));
break;
+
+ case GIT_OPT_SET_SSL_CERT_LOCATIONS:
+#ifdef GIT_SSL
+ {
+ const char *file = va_arg(ap, const char *);
+ const char *path = va_arg(ap, const char *);
+ if (!SSL_CTX_load_verify_locations(git__ssl_ctx, file, path)) {
+ giterr_set(GITERR_NET, "SSL error: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ error = -1;
+ }
+ }
+#else
+ giterr_set(GITERR_NET, "Cannot set certificate locations: OpenSSL is not enabled");
+ error = -1;
+#endif
+ break;
}
va_end(ap);
diff --git a/src/signature.c b/src/signature.c
index 2a16b484a..514b153ac 100644
--- a/src/signature.c
+++ b/src/signature.c
@@ -106,6 +106,30 @@ int git_signature_dup(git_signature **dest, const git_signature *source)
return 0;
}
+int git_signature__pdup(git_signature **dest, const git_signature *source, git_pool *pool)
+{
+ git_signature *signature;
+
+ if (source == NULL)
+ return 0;
+
+ signature = git_pool_mallocz(pool, sizeof(git_signature));
+ GITERR_CHECK_ALLOC(signature);
+
+ signature->name = git_pool_strdup(pool, source->name);
+ GITERR_CHECK_ALLOC(signature->name);
+
+ signature->email = git_pool_strdup(pool, source->email);
+ GITERR_CHECK_ALLOC(signature->email);
+
+ signature->when.time = source->when.time;
+ signature->when.offset = source->when.offset;
+
+ *dest = signature;
+
+ return 0;
+}
+
int git_signature_now(git_signature **sig_out, const char *name, const char *email)
{
time_t now;
diff --git a/src/signature.h b/src/signature.h
index 24655cbf5..eb71db7db 100644
--- a/src/signature.h
+++ b/src/signature.h
@@ -15,4 +15,6 @@
int git_signature__parse(git_signature *sig, const char **buffer_out, const char *buffer_end, const char *header, char ender);
void git_signature__writebuf(git_buf *buf, const char *header, const git_signature *sig);
+int git_signature__pdup(git_signature **dest, const git_signature *source, git_pool *pool);
+
#endif
diff --git a/src/stash.c b/src/stash.c
index 22f756e35..cad87d120 100644
--- a/src/stash.c
+++ b/src/stash.c
@@ -15,6 +15,7 @@
#include "git2/status.h"
#include "git2/checkout.h"
#include "git2/index.h"
+#include "git2/transaction.h"
#include "signature.h"
static int create_error(int error, const char *msg)
@@ -232,7 +233,8 @@ static int build_untracked_tree(
}
if (flags & GIT_STASH_INCLUDE_IGNORED) {
- opts.flags |= GIT_DIFF_INCLUDE_IGNORED;
+ opts.flags |= GIT_DIFF_INCLUDE_IGNORED |
+ GIT_DIFF_RECURSE_IGNORED_DIRS;
data.include_ignored = true;
}
@@ -447,10 +449,11 @@ static int ensure_there_are_changes_to_stash(
if (include_untracked_files)
opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED |
- GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;
+ GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;
if (include_ignored_files)
- opts.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED;
+ opts.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED |
+ GIT_STATUS_OPT_RECURSE_IGNORED_DIRS;
error = git_status_foreach_ext(repo, &opts, is_dirty_cb, NULL);
@@ -599,14 +602,21 @@ int git_stash_drop(
git_repository *repo,
size_t index)
{
- git_reference *stash;
+ git_transaction *tx;
+ git_reference *stash = NULL;
git_reflog *reflog = NULL;
size_t max;
int error;
- if ((error = git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE)) < 0)
+ if ((error = git_transaction_new(&tx, repo)) < 0)
return error;
+ if ((error = git_transaction_lock_ref(tx, GIT_REFS_STASH_FILE)) < 0)
+ goto cleanup;
+
+ if ((error = git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE)) < 0)
+ goto cleanup;
+
if ((error = git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)) < 0)
goto cleanup;
@@ -621,29 +631,25 @@ int git_stash_drop(
if ((error = git_reflog_drop(reflog, index, true)) < 0)
goto cleanup;
- if ((error = git_reflog_write(reflog)) < 0)
+ if ((error = git_transaction_set_reflog(tx, GIT_REFS_STASH_FILE, reflog)) < 0)
goto cleanup;
if (max == 1) {
- error = git_reference_delete(stash);
- git_reference_free(stash);
- stash = NULL;
+ if ((error = git_transaction_remove(tx, GIT_REFS_STASH_FILE)) < 0)
+ goto cleanup;
} else if (index == 0) {
const git_reflog_entry *entry;
entry = git_reflog_entry_byindex(reflog, 0);
-
- git_reference_free(stash);
- error = git_reference_create(&stash, repo, GIT_REFS_STASH_FILE, &entry->oid_cur, 1, NULL, NULL);
- if (error < 0)
+ if ((error = git_transaction_set_target(tx, GIT_REFS_STASH_FILE, &entry->oid_cur, NULL, NULL)) < 0)
goto cleanup;
-
- /* We need to undo the writing that we just did */
- error = git_reflog_write(reflog);
}
+ error = git_transaction_commit(tx);
+
cleanup:
git_reference_free(stash);
+ git_transaction_free(tx);
git_reflog_free(reflog);
return error;
}
diff --git a/src/thread-utils.h b/src/thread-utils.h
index 5511a5117..8deedce81 100644
--- a/src/thread-utils.h
+++ b/src/thread-utils.h
@@ -183,8 +183,8 @@ GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
/* Pthreads Mutex */
#define git_mutex unsigned int
-#define git_mutex_init(a) 0
-#define git_mutex_lock(a) 0
+static int git_mutex_init(git_mutex* mutex) { GIT_UNUSED(mutex); return 0; }
+static int git_mutex_lock(git_mutex* mutex) { GIT_UNUSED(mutex); return 0; }
#define git_mutex_unlock(a) (void)0
#define git_mutex_free(a) (void)0
diff --git a/src/transaction.c b/src/transaction.c
new file mode 100644
index 000000000..ebb943cea
--- /dev/null
+++ b/src/transaction.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "common.h"
+#include "repository.h"
+#include "strmap.h"
+#include "refdb.h"
+#include "pool.h"
+#include "reflog.h"
+#include "signature.h"
+
+#include "git2/signature.h"
+#include "git2/sys/refs.h"
+#include "git2/sys/refdb_backend.h"
+
+GIT__USE_STRMAP;
+
+typedef struct {
+ const char *name;
+ void *payload;
+
+ git_ref_t ref_type;
+ union {
+ git_oid id;
+ char *symbolic;
+ } target;
+ git_reflog *reflog;
+
+ const char *message;
+ git_signature *sig;
+
+ unsigned int committed :1,
+ remove :1;
+} transaction_node;
+
+struct git_transaction {
+ git_repository *repo;
+ git_refdb *db;
+
+ git_strmap *locks;
+ git_pool pool;
+};
+
+int git_transaction_new(git_transaction **out, git_repository *repo)
+{
+ int error;
+ git_pool pool;
+ git_transaction *tx = NULL;
+
+ assert(out && repo);
+
+ if ((error = git_pool_init(&pool, 1, 0)) < 0)
+ return error;
+
+ tx = git_pool_mallocz(&pool, sizeof(git_transaction));
+ if (!tx) {
+ error = -1;
+ goto on_error;
+ }
+
+ if ((error = git_strmap_alloc(&tx->locks)) < 0) {
+ error = -1;
+ goto on_error;
+ }
+
+ if ((error = git_repository_refdb(&tx->db, repo)) < 0)
+ goto on_error;
+
+ memcpy(&tx->pool, &pool, sizeof(git_pool));
+ tx->repo = repo;
+ *out = tx;
+ return 0;
+
+on_error:
+ git_pool_clear(&pool);
+ return error;
+}
+
+int git_transaction_lock_ref(git_transaction *tx, const char *refname)
+{
+ int error;
+ transaction_node *node;
+
+ assert(tx && refname);
+
+ node = git_pool_mallocz(&tx->pool, sizeof(transaction_node));
+ GITERR_CHECK_ALLOC(node);
+
+ node->name = git_pool_strdup(&tx->pool, refname);
+ GITERR_CHECK_ALLOC(node->name);
+
+ if ((error = git_refdb_lock(&node->payload, tx->db, refname)) < 0)
+ return error;
+
+ git_strmap_insert(tx->locks, node->name, node, error);
+ if (error < 0)
+ goto cleanup;
+
+ return 0;
+
+cleanup:
+ git_refdb_unlock(tx->db, node->payload, false, false, NULL, NULL, NULL);
+
+ return error;
+}
+
+static int find_locked(transaction_node **out, git_transaction *tx, const char *refname)
+{
+ git_strmap_iter pos;
+ transaction_node *node;
+
+ pos = git_strmap_lookup_index(tx->locks, refname);
+ if (!git_strmap_valid_index(tx->locks, pos)) {
+ giterr_set(GITERR_REFERENCE, "the specified reference is not locked");
+ return GIT_ENOTFOUND;
+ }
+
+ node = git_strmap_value_at(tx->locks, pos);
+
+ *out = node;
+ return 0;
+}
+
+static int copy_common(transaction_node *node, git_transaction *tx, const git_signature *sig, const char *msg)
+{
+ if (sig && git_signature__pdup(&node->sig, sig, &tx->pool) < 0)
+ return -1;
+
+ if (!node->sig) {
+ git_signature *tmp;
+ int error;
+
+ if (git_reference__log_signature(&tmp, tx->repo) < 0)
+ return -1;
+
+ /* make sure the sig we use is in our pool */
+ error = git_signature__pdup(&node->sig, tmp, &tx->pool);
+ git_signature_free(tmp);
+ if (error < 0)
+ return error;
+ }
+
+ if (msg) {
+ node->message = git_pool_strdup(&tx->pool, msg);
+ GITERR_CHECK_ALLOC(node->message);
+ }
+
+ return 0;
+}
+
+int git_transaction_set_target(git_transaction *tx, const char *refname, const git_oid *target, const git_signature *sig, const char *msg)
+{
+ int error;
+ transaction_node *node;
+
+ assert(tx && refname && target);
+
+ if ((error = find_locked(&node, tx, refname)) < 0)
+ return error;
+
+ if ((error = copy_common(node, tx, sig, msg)) < 0)
+ return error;
+
+ git_oid_cpy(&node->target.id, target);
+ node->ref_type = GIT_REF_OID;
+
+ return 0;
+}
+
+int git_transaction_set_symbolic_target(git_transaction *tx, const char *refname, const char *target, const git_signature *sig, const char *msg)
+{
+ int error;
+ transaction_node *node;
+
+ assert(tx && refname && target);
+
+ if ((error = find_locked(&node, tx, refname)) < 0)
+ return error;
+
+ if ((error = copy_common(node, tx, sig, msg)) < 0)
+ return error;
+
+ node->target.symbolic = git_pool_strdup(&tx->pool, target);
+ GITERR_CHECK_ALLOC(node->target.symbolic);
+ node->ref_type = GIT_REF_SYMBOLIC;
+
+ return 0;
+}
+
+int git_transaction_remove(git_transaction *tx, const char *refname)
+{
+ int error;
+ transaction_node *node;
+
+ if ((error = find_locked(&node, tx, refname)) < 0)
+ return error;
+
+ node->remove = true;
+ node->ref_type = GIT_REF_OID; /* the id will be ignored */
+
+ return 0;
+}
+
+static int dup_reflog(git_reflog **out, const git_reflog *in, git_pool *pool)
+{
+ git_reflog *reflog;
+ git_reflog_entry *entries;
+ size_t len, i;
+
+ reflog = git_pool_mallocz(pool, sizeof(git_reflog));
+ GITERR_CHECK_ALLOC(reflog);
+
+ reflog->ref_name = git_pool_strdup(pool, in->ref_name);
+ GITERR_CHECK_ALLOC(reflog->ref_name);
+
+ len = in->entries.length;
+ reflog->entries.length = len;
+ reflog->entries.contents = git_pool_mallocz(pool, len * sizeof(void *));
+ GITERR_CHECK_ALLOC(reflog->entries.contents);
+
+ entries = git_pool_mallocz(pool, len * sizeof(git_reflog_entry));
+ GITERR_CHECK_ALLOC(entries);
+
+ for (i = 0; i < len; i++) {
+ const git_reflog_entry *src;
+ git_reflog_entry *tgt;
+
+ tgt = &entries[i];
+ reflog->entries.contents[i] = tgt;
+
+ src = git_vector_get(&in->entries, i);
+ git_oid_cpy(&tgt->oid_old, &src->oid_old);
+ git_oid_cpy(&tgt->oid_cur, &src->oid_cur);
+
+ tgt->msg = git_pool_strdup(pool, src->msg);
+ GITERR_CHECK_ALLOC(tgt->msg);
+
+ if (git_signature__pdup(&tgt->committer, src->committer, pool) < 0)
+ return -1;
+ }
+
+
+ *out = reflog;
+ return 0;
+}
+
+int git_transaction_set_reflog(git_transaction *tx, const char *refname, const git_reflog *reflog)
+{
+ int error;
+ transaction_node *node;
+
+ assert(tx && refname && reflog);
+
+ if ((error = find_locked(&node, tx, refname)) < 0)
+ return error;
+
+ if ((error = dup_reflog(&node->reflog, reflog, &tx->pool)) < 0)
+ return error;
+
+ return 0;
+}
+
+static int update_target(git_refdb *db, transaction_node *node)
+{
+ git_reference *ref;
+ int error, update_reflog;
+
+ if (node->ref_type == GIT_REF_OID) {
+ ref = git_reference__alloc(node->name, &node->target.id, NULL);
+ } else if (node->ref_type == GIT_REF_SYMBOLIC) {
+ ref = git_reference__alloc_symbolic(node->name, node->target.symbolic);
+ } else {
+ assert(0);
+ }
+
+ GITERR_CHECK_ALLOC(ref);
+ update_reflog = node->reflog == NULL;
+
+ if (node->remove) {
+ error = git_refdb_unlock(db, node->payload, 2, false, ref, NULL, NULL);
+ } else if (node->ref_type == GIT_REF_OID) {
+ error = git_refdb_unlock(db, node->payload, true, update_reflog, ref, node->sig, node->message);
+ } else if (node->ref_type == GIT_REF_SYMBOLIC) {
+ error = git_refdb_unlock(db, node->payload, true, update_reflog, ref, node->sig, node->message);
+ } else {
+ assert(0);
+ }
+
+ git_reference_free(ref);
+ node->committed = true;
+
+ return error;
+}
+
+int git_transaction_commit(git_transaction *tx)
+{
+ transaction_node *node;
+ git_strmap_iter pos;
+ int error;
+
+ assert(tx);
+
+ for (pos = kh_begin(tx->locks); pos < kh_end(tx->locks); pos++) {
+ if (!git_strmap_has_data(tx->locks, pos))
+ continue;
+
+ node = git_strmap_value_at(tx->locks, pos);
+ if (node->reflog) {
+ if ((error = tx->db->backend->reflog_write(tx->db->backend, node->reflog)) < 0)
+ return error;
+ }
+
+ if (node->ref_type != GIT_REF_INVALID) {
+ if ((error = update_target(tx->db, node)) < 0)
+ return error;
+ }
+ }
+
+ return 0;
+}
+
+void git_transaction_free(git_transaction *tx)
+{
+ transaction_node *node;
+ git_pool pool;
+ git_strmap_iter pos;
+
+ assert(tx);
+
+ /* start by unlocking the ones we've left hanging, if any */
+ for (pos = kh_begin(tx->locks); pos < kh_end(tx->locks); pos++) {
+ if (!git_strmap_has_data(tx->locks, pos))
+ continue;
+
+ node = git_strmap_value_at(tx->locks, pos);
+ if (node->committed)
+ continue;
+
+ git_refdb_unlock(tx->db, node->payload, false, false, NULL, NULL, NULL);
+ }
+
+ git_refdb_free(tx->db);
+ git_strmap_free(tx->locks);
+
+ /* tx is inside the pool, so we need to extract the data */
+ memcpy(&pool, &tx->pool, sizeof(git_pool));
+ git_pool_clear(&pool);
+}
diff --git a/src/transports/http.c b/src/transports/http.c
index f9df53b71..bcfeaee7f 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -19,6 +19,10 @@ git_http_auth_scheme auth_schemes[] = {
{ GIT_AUTHTYPE_BASIC, "Basic", GIT_CREDTYPE_USERPASS_PLAINTEXT, git_http_auth_basic },
};
+#ifdef GIT_SSL
+# include <openssl/x509v3.h>
+#endif
+
static const char *upload_pack_service = "upload-pack";
static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack";
static const char *upload_pack_service_url = "/git-upload-pack";
@@ -524,7 +528,7 @@ static int write_chunk(gitno_socket *socket, const char *buffer, size_t len)
static int http_connect(http_subtransport *t)
{
- int flags = 0;
+ int flags = 0, error;
if (t->connected &&
http_should_keep_alive(&t->parser) &&
@@ -541,13 +545,55 @@ static int http_connect(http_subtransport *t)
return -1;
flags |= GITNO_CONNECT_SSL;
-
- if (GIT_TRANSPORTFLAGS_NO_CHECK_CERT & tflags)
- flags |= GITNO_CONNECT_SSL_NO_CHECK_CERT;
}
- if (gitno_connect(&t->socket, t->connection_data.host, t->connection_data.port, flags) < 0)
- return -1;
+ error = gitno_connect(&t->socket, t->connection_data.host, t->connection_data.port, flags);
+
+#ifdef GIT_SSL
+ if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL) {
+ X509 *cert = SSL_get_peer_certificate(t->socket.ssl.ssl);
+ git_cert_x509 cert_info;
+ int len, is_valid;
+ unsigned char *guard, *encoded_cert;
+
+ /* Retrieve the length of the certificate first */
+ len = i2d_X509(cert, NULL);
+ if (len < 0) {
+ giterr_set(GITERR_NET, "failed to retrieve certificate information");
+ return -1;
+ }
+
+
+ encoded_cert = git__malloc(len);
+ GITERR_CHECK_ALLOC(encoded_cert);
+ /* i2d_X509 makes 'copy' point to just after the data */
+ guard = encoded_cert;
+
+ len = i2d_X509(cert, &guard);
+ if (len < 0) {
+ git__free(encoded_cert);
+ giterr_set(GITERR_NET, "failed to retrieve certificate information");
+ return -1;
+ }
+
+ giterr_clear();
+ is_valid = error != GIT_ECERTIFICATE;
+ cert_info.cert_type = GIT_CERT_X509;
+ cert_info.data = encoded_cert;
+ cert_info.len = len;
+ error = t->owner->certificate_check_cb((git_cert *) &cert_info, is_valid, t->connection_data.host, t->owner->message_cb_payload);
+ git__free(encoded_cert);
+
+ if (error < 0) {
+ if (!giterr_last())
+ giterr_set(GITERR_NET, "user cancelled certificate check");
+
+ return error;
+ }
+ }
+#endif
+ if (error < 0)
+ return error;
t->connected = 1;
return 0;
@@ -608,6 +654,7 @@ replay:
while (!*bytes_read && !t->parse_finished) {
size_t data_offset;
+ int error;
/*
* Make the parse_buffer think it's as full of data as
@@ -654,8 +701,8 @@ replay:
if (PARSE_ERROR_REPLAY == t->parse_error) {
s->sent_request = 0;
- if (http_connect(t) < 0)
- return -1;
+ if ((error = http_connect(t)) < 0)
+ return error;
goto replay;
}
@@ -907,8 +954,8 @@ static int http_action(
(ret = gitno_connection_data_from_url(&t->connection_data, url, NULL)) < 0)
return ret;
- if (http_connect(t) < 0)
- return -1;
+ if ((ret = http_connect(t)) < 0)
+ return ret;
switch (action) {
case GIT_SERVICE_UPLOADPACK_LS:
diff --git a/src/transports/smart.c b/src/transports/smart.c
index a5c3e82dc..d0f9c90e8 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -53,12 +53,14 @@ static int git_smart__set_callbacks(
git_transport *transport,
git_transport_message_cb progress_cb,
git_transport_message_cb error_cb,
+ git_transport_certificate_check_cb certificate_check_cb,
void *message_cb_payload)
{
transport_smart *t = (transport_smart *)transport;
t->progress_cb = progress_cb;
t->error_cb = error_cb;
+ t->certificate_check_cb = certificate_check_cb;
t->message_cb_payload = message_cb_payload;
return 0;
diff --git a/src/transports/smart.h b/src/transports/smart.h
index b29faae44..44e241adc 100644
--- a/src/transports/smart.h
+++ b/src/transports/smart.h
@@ -137,6 +137,7 @@ typedef struct {
int flags;
git_transport_message_cb progress_cb;
git_transport_message_cb error_cb;
+ git_transport_certificate_check_cb certificate_check_cb;
void *message_cb_payload;
git_smart_subtransport *wrapped;
git_smart_subtransport_stream *current_stream;
diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c
index 5ca5065ac..7c20382dc 100644
--- a/src/transports/smart_protocol.c
+++ b/src/transports/smart_protocol.c
@@ -640,9 +640,9 @@ static int gen_pktline(git_buf *buf, git_push *push)
{
push_spec *spec;
size_t i, len;
- char old_id[41], new_id[41];
+ char old_id[GIT_OID_HEXSZ+1], new_id[GIT_OID_HEXSZ+1];
- old_id[40] = '\0'; new_id[40] = '\0';
+ old_id[GIT_OID_HEXSZ] = '\0'; new_id[GIT_OID_HEXSZ] = '\0';
git_vector_foreach(&push->specs, i, spec) {
len = 2*GIT_OID_HEXSZ + 7 + strlen(spec->rref);
@@ -963,7 +963,7 @@ int git_smart__push(git_transport *transport, git_push *push)
#ifdef PUSH_DEBUG
{
git_remote_head *head;
- char hex[41]; hex[40] = '\0';
+ char hex[GIT_OID_HEXSZ+1]; hex[GIT_OID_HEXSZ] = '\0';
git_vector_foreach(&push->remote->refs, i, head) {
git_oid_fmt(hex, &head->oid);
diff --git a/src/transports/ssh.c b/src/transports/ssh.c
index a57d27d31..3868a529a 100644
--- a/src/transports/ssh.c
+++ b/src/transports/ssh.c
@@ -473,6 +473,46 @@ static int _git_ssh_setup_conn(
GITERR_CHECK_ALLOC(port);
}
+ if ((error = gitno_connect(&s->socket, host, port, 0)) < 0)
+ goto on_error;
+
+ if ((error = _git_ssh_session_create(&session, s->socket)) < 0)
+ goto on_error;
+
+ if (t->owner->certificate_check_cb != NULL) {
+ git_cert_hostkey cert = { 0 };
+ const char *key;
+
+ cert.cert_type = GIT_CERT_HOSTKEY_LIBSSH2;
+
+ key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
+ if (key != NULL) {
+ cert.type |= GIT_CERT_SSH_SHA1;
+ memcpy(&cert.hash_sha1, key, 20);
+ }
+
+ key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
+ if (key != NULL) {
+ cert.type |= GIT_CERT_SSH_MD5;
+ memcpy(&cert.hash_md5, key, 16);
+ }
+
+ if (cert.type == 0) {
+ giterr_set(GITERR_SSH, "unable to get the host key");
+ return -1;
+ }
+
+ /* We don't currently trust any hostkeys */
+ giterr_clear();
+ error = t->owner->certificate_check_cb((git_cert *) &cert, 0, host, t->owner->message_cb_payload);
+ if (error < 0) {
+ if (!giterr_last())
+ giterr_set(GITERR_NET, "user cancelled hostkey check");
+
+ goto on_error;
+ }
+ }
+
/* we need the username to ask for auth methods */
if (!user) {
if ((error = request_creds(&cred, t, NULL, GIT_CREDTYPE_USERNAME)) < 0)
@@ -488,12 +528,6 @@ static int _git_ssh_setup_conn(
goto on_error;
}
- if ((error = gitno_connect(&s->socket, host, port, 0)) < 0)
- goto on_error;
-
- if ((error = _git_ssh_session_create(&session, s->socket)) < 0)
- goto on_error;
-
if ((error = list_auth_methods(&auth_methods, session, user)) < 0)
goto on_error;
@@ -602,10 +636,8 @@ static int ssh_receivepack_ls(
{
const char *cmd = t->cmd_receivepack ? t->cmd_receivepack : cmd_receivepack;
- if (_git_ssh_setup_conn(t, url, cmd, stream) < 0)
- return -1;
- return 0;
+ return _git_ssh_setup_conn(t, url, cmd, stream);
}
static int ssh_receivepack(
diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c
index 6523086da..5a59dafad 100644
--- a/src/transports/winhttp.c
+++ b/src/transports/winhttp.c
@@ -16,6 +16,8 @@
#include "remote.h"
#include "repository.h"
+#include <wincrypt.h>
+#pragma comment(lib, "crypt32")
#include <winhttp.h>
#pragma comment(lib, "winhttp")
@@ -203,6 +205,39 @@ static int fallback_cred_acquire_cb(
return error;
}
+static int certificate_check(winhttp_stream *s, int valid)
+{
+ int error;
+ winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
+ PCERT_CONTEXT cert_ctx;
+ DWORD cert_ctx_size = sizeof(cert_ctx);
+ git_cert_x509 cert;
+
+ /* If there is no override, we should fail if WinHTTP doesn't think it's fine */
+ if (t->owner->certificate_check_cb == NULL && !valid)
+ return GIT_ECERTIFICATE;
+
+ if (t->owner->certificate_check_cb == NULL || !t->connection_data.use_ssl)
+ return 0;
+
+ if (!WinHttpQueryOption(s->request, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert_ctx, &cert_ctx_size)) {
+ giterr_set(GITERR_OS, "failed to get server certificate");
+ return -1;
+ }
+
+ giterr_clear();
+ cert.cert_type = GIT_CERT_X509;
+ cert.data = cert_ctx->pbCertEncoded;
+ cert.len = cert_ctx->cbCertEncoded;
+ error = t->owner->certificate_check_cb((git_cert *) &cert, valid, t->connection_data.host, t->owner->cred_acquire_payload);
+ CertFreeCertificateContext(cert_ctx);
+
+ if (error < 0 && !giterr_last())
+ giterr_set(GITERR_NET, "user cancelled certificate check");
+
+ return error;
+}
+
static int winhttp_stream_connect(winhttp_stream *s)
{
winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
@@ -353,13 +388,6 @@ static int winhttp_stream_connect(winhttp_stream *s)
if (t->owner->parent.read_flags(&t->owner->parent, &flags) < 0)
goto on_error;
-
- if ((GIT_TRANSPORTFLAGS_NO_CHECK_CERT & flags) &&
- !WinHttpSetOption(s->request, WINHTTP_OPTION_SECURITY_FLAGS,
- (LPVOID)&no_check_cert_flags, sizeof(no_check_cert_flags))) {
- giterr_set(GITERR_OS, "Failed to set options to ignore cert errors");
- goto on_error;
- }
}
/* If we have a credential on the subtransport, apply it to the request */
@@ -527,6 +555,74 @@ on_error:
return error;
}
+static int do_send_request(winhttp_stream *s, size_t len, int ignore_length)
+{
+ int request_failed = 0, cert_valid = 1, error = 0;
+
+ if (ignore_length) {
+ if (!WinHttpSendRequest(s->request,
+ WINHTTP_NO_ADDITIONAL_HEADERS, 0,
+ WINHTTP_NO_REQUEST_DATA, 0,
+ WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0)) {
+ return -1;
+ }
+ } else {
+ if (!WinHttpSendRequest(s->request,
+ WINHTTP_NO_ADDITIONAL_HEADERS, 0,
+ WINHTTP_NO_REQUEST_DATA, 0,
+ len, 0)) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int send_request(winhttp_stream *s, size_t len, int ignore_length)
+{
+ int request_failed = 0, cert_valid = 1, error = 0;
+ DWORD ignore_flags;
+
+ if ((error = do_send_request(s, len, ignore_length)) < 0)
+ request_failed = 1;
+
+ if (request_failed) {
+ if (GetLastError() != ERROR_WINHTTP_SECURE_FAILURE) {
+ giterr_set(GITERR_OS, "failed to send request");
+ return -1;
+ } else {
+ cert_valid = 0;
+ }
+ }
+
+ giterr_clear();
+ if ((error = certificate_check(s, cert_valid)) < 0) {
+ if (!giterr_last())
+ giterr_set(GITERR_OS, "user cancelled certificate check");
+
+ return error;
+ }
+
+ /* if neither the request nor the certificate check returned errors, we're done */
+ if (!request_failed)
+ return 0;
+
+ ignore_flags =
+ SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
+ SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
+ SECURITY_FLAG_IGNORE_UNKNOWN_CA;
+
+ if (!WinHttpSetOption(s->request, WINHTTP_OPTION_SECURITY_FLAGS, &ignore_flags, sizeof(ignore_flags))) {
+ giterr_set(GITERR_OS, "failed to set security options");
+ return -1;
+ }
+
+ if ((error = do_send_request(s, len, ignore_length)) < 0)
+ giterr_set(GITERR_OS, "failed to send request");
+
+ return error;
+}
+
static int winhttp_stream_read(
git_smart_subtransport_stream *stream,
char *buffer,
@@ -537,6 +633,7 @@ static int winhttp_stream_read(
winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
DWORD dw_bytes_read;
char replay_count = 0;
+ int error;
replay:
/* Enforce a reasonable cap on the number of replays */
@@ -553,15 +650,12 @@ replay:
DWORD status_code, status_code_length, content_type_length, bytes_written;
char expected_content_type_8[MAX_CONTENT_TYPE_LEN];
wchar_t expected_content_type[MAX_CONTENT_TYPE_LEN], content_type[MAX_CONTENT_TYPE_LEN];
+ int request_failed = 0, cert_valid = 1;
if (!s->sent_request) {
- if (!WinHttpSendRequest(s->request,
- WINHTTP_NO_ADDITIONAL_HEADERS, 0,
- WINHTTP_NO_REQUEST_DATA, 0,
- s->post_body_len, 0)) {
- giterr_set(GITERR_OS, "Failed to send request");
- return -1;
- }
+
+ if ((error = send_request(s, s->post_body_len, 0)) < 0)
+ return error;
s->sent_request = 1;
}
@@ -815,6 +909,7 @@ static int winhttp_stream_write_single(
winhttp_stream *s = (winhttp_stream *)stream;
winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
DWORD bytes_written;
+ int error;
if (!s->request && winhttp_stream_connect(s) < 0)
return -1;
@@ -825,13 +920,8 @@ static int winhttp_stream_write_single(
return -1;
}
- if (!WinHttpSendRequest(s->request,
- WINHTTP_NO_ADDITIONAL_HEADERS, 0,
- WINHTTP_NO_REQUEST_DATA, 0,
- (DWORD)len, 0)) {
- giterr_set(GITERR_OS, "Failed to send request");
- return -1;
- }
+ if ((error = send_request(s, len, 0)) < 0)
+ return error;
s->sent_request = 1;
@@ -954,6 +1044,7 @@ static int winhttp_stream_write_chunked(
{
winhttp_stream *s = (winhttp_stream *)stream;
winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
+ int error;
if (!s->request && winhttp_stream_connect(s) < 0)
return -1;
@@ -967,13 +1058,8 @@ static int winhttp_stream_write_chunked(
return -1;
}
- if (!WinHttpSendRequest(s->request,
- WINHTTP_NO_ADDITIONAL_HEADERS, 0,
- WINHTTP_NO_REQUEST_DATA, 0,
- WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0)) {
- giterr_set(GITERR_OS, "Failed to send request");
- return -1;
- }
+ if ((error = send_request(s, 0, 1)) < 0)
+ return error;
s->sent_request = 1;
}
diff --git a/src/userdiff.h b/src/userdiff.h
index 523f2f8d4..91c1f42dc 100644
--- a/src/userdiff.h
+++ b/src/userdiff.h
@@ -191,9 +191,9 @@ PATTERNS("php",
"|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
PATTERNS("javascript",
- "^[ \t]*(function[ \t][a-zA-Z_][^\\{]*)\n"
- "^[ \t]*(var[ \t]+[a-zA-Z_][a-zA-Z0-9_]*[ \t]*=[ \t]*function[ \t\\(][^\\{]*)\n"
- "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*[ \t]*:[ \t]*function[ \t\\(][^\\{]*)",
+ "([a-zA-Z_$][a-zA-Z0-9_$]*(\\.[a-zA-Z0-9_$]+)*[ \t]*=[ \t]*function([ \t][a-zA-Z_$][a-zA-Z0-9_$]*)?[^\\{]*)\n"
+ "([a-zA-Z_$][a-zA-Z0-9_$]*[ \t]*:[ \t]*function([ \t][a-zA-Z_$][a-zA-Z0-9_$]*)?[^\\{]*)\n"
+ "[^a-zA-Z0-9_\\$](function([ \t][a-zA-Z_$][a-zA-Z0-9_$]*)?[^\\{]*)",
/* -- */
"[a-zA-Z_][a-zA-Z0-9_]*"
"|[-+0-9.e]+[fFlL]?|0[xX]?[0-9a-fA-F]+[lL]?"
diff --git a/tests/attr/repo.c b/tests/attr/repo.c
index 5e812a72b..8baf50622 100644
--- a/tests/attr/repo.c
+++ b/tests/attr/repo.c
@@ -4,6 +4,7 @@
#include "attr.h"
#include "attr_expect.h"
+#include "git2/sys/repository.h"
static git_repository *g_repo = NULL;
@@ -333,3 +334,45 @@ void test_attr_repo__staging_properly_normalizes_line_endings_according_to_gitat
git_index_free(index);
}
+
+void test_attr_repo__bare_repo_with_index(void)
+{
+ const char *names[4] = { "test1", "test2", "test3", "test4" };
+ const char *values[4];
+ git_index *index;
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+
+ cl_git_mkfile(
+ "attr/.gitattributes",
+ "*.txt test1 test2=foobar -test3\n"
+ "trial.txt -test1 test2=barfoo !test3 test4\n");
+ cl_git_pass(git_index_add_bypath(index, ".gitattributes"));
+ git_index_free(index);
+
+ cl_must_pass(p_unlink("attr/.gitattributes"));
+ cl_assert(!git_path_exists("attr/.gitattributes"));
+
+ cl_git_pass(git_repository_set_bare(g_repo));
+
+ cl_git_pass(git_attr_get_many(values, g_repo, 0, "file.txt", 4, names));
+
+ cl_assert(GIT_ATTR_TRUE(values[0]));
+ cl_assert_equal_s("foobar", values[1]);
+ cl_assert(GIT_ATTR_FALSE(values[2]));
+ cl_assert(GIT_ATTR_UNSPECIFIED(values[3]));
+
+ cl_git_pass(git_attr_get_many(values, g_repo, 0, "trial.txt", 4, names));
+
+ cl_assert(GIT_ATTR_FALSE(values[0]));
+ cl_assert_equal_s("barfoo", values[1]);
+ cl_assert(GIT_ATTR_UNSPECIFIED(values[2]));
+ cl_assert(GIT_ATTR_TRUE(values[3]));
+
+ cl_git_pass(git_attr_get_many(values, g_repo, 0, "sub/sub/subdir.txt", 4, names));
+
+ cl_assert(GIT_ATTR_TRUE(values[0]));
+ cl_assert_equal_s("foobar", values[1]);
+ cl_assert(GIT_ATTR_FALSE(values[2]));
+ cl_assert(GIT_ATTR_UNSPECIFIED(values[3]));
+}
diff --git a/tests/blame/blame_helpers.c b/tests/blame/blame_helpers.c
index 9bb77a52d..21cd1a615 100644
--- a/tests/blame/blame_helpers.c
+++ b/tests/blame/blame_helpers.c
@@ -17,7 +17,7 @@ void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...)
void check_blame_hunk_index(git_repository *repo, git_blame *blame, int idx,
int start_line, int len, char boundary, const char *commit_id, const char *orig_path)
{
- char expected[41] = {0}, actual[41] = {0};
+ char expected[GIT_OID_HEXSZ+1] = {0}, actual[GIT_OID_HEXSZ+1] = {0};
const git_blame_hunk *hunk = git_blame_get_hunk_byindex(blame, idx);
cl_assert(hunk);
diff --git a/tests/checkout/conflict.c b/tests/checkout/conflict.c
index b8ae80576..3d763af12 100644
--- a/tests/checkout/conflict.c
+++ b/tests/checkout/conflict.c
@@ -48,7 +48,7 @@ static git_index *g_index;
struct checkout_index_entry {
uint16_t mode;
- char oid_str[41];
+ char oid_str[GIT_OID_HEXSZ+1];
int stage;
char path[128];
};
@@ -1078,8 +1078,8 @@ static void collect_progress(
{
git_vector *paths = payload;
- (void)completed_steps;
- (void)total_steps;
+ GIT_UNUSED(completed_steps);
+ GIT_UNUSED(total_steps);
if (path == NULL)
return;
diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c
index b61ef2dfc..0933f64f7 100644
--- a/tests/checkout/tree.c
+++ b/tests/checkout/tree.c
@@ -571,7 +571,7 @@ void test_checkout_tree__donot_update_deleted_file_by_default(void)
cl_git_pass(git_oid_fromstr(&old_id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
cl_git_pass(git_commit_lookup(&old_commit, g_repo, &old_id));
- cl_git_pass(git_reset(g_repo, (git_object *)old_commit, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(g_repo, (git_object *)old_commit, GIT_RESET_HARD, NULL, NULL, NULL));
cl_git_pass(p_unlink("testrepo/branch_file.txt"));
cl_git_pass(git_index_remove_bypath(index ,"branch_file.txt"));
diff --git a/tests/cherrypick/workdir.c b/tests/cherrypick/workdir.c
index f41d47833..86a385d16 100644
--- a/tests/cherrypick/workdir.c
+++ b/tests/cherrypick/workdir.c
@@ -66,7 +66,7 @@ void test_cherrypick_workdir__automerge(void)
git_tree *cherrypicked_tree = NULL;
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
git_oid_fromstr(&cherry_oid, cherrypick_oids[i]);
cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
@@ -92,6 +92,47 @@ void test_cherrypick_workdir__automerge(void)
git_signature_free(signature);
}
+/* git reset --hard cfc4f0999a8367568e049af4f72e452d40828a15
+ * git cherry-pick a43a050c588d4e92f11a6b139680923e9728477d*/
+void test_cherrypick_workdir__empty_result(void)
+{
+ git_oid head_oid;
+ git_signature *signature = NULL;
+ git_commit *head = NULL, *commit = NULL;
+ git_oid cherry_oid;
+
+ const char *cherrypick_oid = "a43a050c588d4e92f11a6b139680923e9728477d";
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "19c5c7207054604b69c84d08a7571ef9672bb5c2", 0, "file1.txt" },
+ { 0100644, "a58ca3fee5eb68b11adc2703e5843f968c9dad1e", 0, "file2.txt" },
+ { 0100644, "28d9eb4208074ad1cc84e71ccc908b34573f05d2", 0, "file3.txt" },
+ };
+
+ cl_git_pass(git_signature_new(&signature, "Picker", "picker@example.org", time(NULL), 0));
+
+ git_oid_fromstr(&head_oid, "cfc4f0999a8367568e049af4f72e452d40828a15");
+
+ /* Create an untracked file that should not conflict */
+ cl_git_mkfile(TEST_REPO_PATH "/file4.txt", "");
+ cl_assert(git_path_exists(TEST_REPO_PATH "/file4.txt"));
+
+ cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
+
+ git_oid_fromstr(&cherry_oid, cherrypick_oid);
+ cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
+ cl_git_pass(git_cherrypick(repo, commit, NULL));
+
+ /* The resulting tree should not have changed, the change was already on HEAD */
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 3));
+
+ git_commit_free(head);
+ git_commit_free(commit);
+
+ git_signature_free(signature);
+}
+
/* git reset --hard bafbf6912c09505ac60575cd43d3f2aba3bd84d8
* git cherry-pick e9b63f3655b2ad80c0ff587389b5a9589a3a7110
*/
@@ -114,7 +155,7 @@ void test_cherrypick_workdir__conflicts(void)
git_oid_fromstr(&head_oid, "bafbf6912c09505ac60575cd43d3f2aba3bd84d8");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
git_oid_fromstr(&cherry_oid, "e9b63f3655b2ad80c0ff587389b5a9589a3a7110");
cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
@@ -222,7 +263,7 @@ void test_cherrypick_workdir__conflict_use_ours(void)
git_oid_fromstr(&head_oid, "bafbf6912c09505ac60575cd43d3f2aba3bd84d8");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
git_oid_fromstr(&cherry_oid, "e9b63f3655b2ad80c0ff587389b5a9589a3a7110");
cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
@@ -234,7 +275,7 @@ void test_cherrypick_workdir__conflict_use_ours(void)
/* resolve conflicts in the index by taking "ours" */
opts.merge_opts.file_favor = GIT_MERGE_FILE_FAVOR_OURS;
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
cl_git_pass(git_cherrypick(repo, commit, &opts));
cl_assert(merge_test_index(repo_index, merge_filesystem_entries, 3));
@@ -264,7 +305,7 @@ void test_cherrypick_workdir__rename(void)
git_oid_fromstr(&head_oid, "cfc4f0999a8367568e049af4f72e452d40828a15");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
git_oid_fromstr(&cherry_oid, "2a26c7e88b285613b302ba76712bc998863f3cbc");
cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
@@ -299,7 +340,7 @@ void test_cherrypick_workdir__both_renamed(void)
git_oid_fromstr(&head_oid, "44cd2ed2052c9c68f9a439d208e9614dc2a55c70");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
git_oid_fromstr(&cherry_oid, "2a26c7e88b285613b302ba76712bc998863f3cbc");
cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
@@ -350,7 +391,7 @@ void test_cherrypick_workdir__merge_fails_without_mainline_specified(void)
git_oid_fromstr(&head_oid, "cfc4f0999a8367568e049af4f72e452d40828a15");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
git_oid_fromstr(&cherry_oid, "abe4603bc7cd5b8167a267e0e2418fd2348f8cff");
cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
@@ -382,7 +423,7 @@ void test_cherrypick_workdir__merge_first_parent(void)
git_oid_fromstr(&head_oid, "cfc4f0999a8367568e049af4f72e452d40828a15");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
git_oid_fromstr(&cherry_oid, "abe4603bc7cd5b8167a267e0e2418fd2348f8cff");
cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
@@ -414,7 +455,7 @@ void test_cherrypick_workdir__merge_second_parent(void)
git_oid_fromstr(&head_oid, "cfc4f0999a8367568e049af4f72e452d40828a15");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
git_oid_fromstr(&cherry_oid, "abe4603bc7cd5b8167a267e0e2418fd2348f8cff");
cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
diff --git a/tests/config/stress.c b/tests/config/stress.c
index 488915e79..e8e9d2b61 100644
--- a/tests/config/stress.c
+++ b/tests/config/stress.c
@@ -44,12 +44,24 @@ void test_config_stress__comments(void)
cl_git_pass(git_config_open_ondisk(&config, cl_fixture("config/config12")));
+ cl_git_pass(git_config_get_string(&str, config, "some.section.test2"));
+ cl_assert_equal_s("hello", str);
+
+ cl_git_pass(git_config_get_string(&str, config, "some.section.test3"));
+ cl_assert_equal_s("welcome", str);
+
cl_git_pass(git_config_get_string(&str, config, "some.section.other"));
cl_assert_equal_s("hello! \" ; ; ; ", str);
+ cl_git_pass(git_config_get_string(&str, config, "some.section.other2"));
+ cl_assert_equal_s("cool! \" # # # ", str);
+
cl_git_pass(git_config_get_string(&str, config, "some.section.multi"));
cl_assert_equal_s("hi, this is a ; multiline comment # with ;\n special chars and other stuff !@#", str);
+ cl_git_pass(git_config_get_string(&str, config, "some.section.multi2"));
+ cl_assert_equal_s("good, this is a ; multiline comment # with ;\n special chars and other stuff !@#", str);
+
cl_git_pass(git_config_get_string(&str, config, "some.section.back"));
cl_assert_equal_s("this is \ba phrase", str);
diff --git a/tests/core/buffer.c b/tests/core/buffer.c
index 7482dadbe..641fed630 100644
--- a/tests/core/buffer.c
+++ b/tests/core/buffer.c
@@ -1,7 +1,7 @@
#include "clar_libgit2.h"
#include "buffer.h"
#include "buf_text.h"
-#include "hashsig.h"
+#include "git2/sys/hashsig.h"
#include "fileops.h"
#define TESTSTR "Have you seen that? Have you seeeen that??"
diff --git a/tests/core/path.c b/tests/core/path.c
index 471491b87..7d3e4938f 100644
--- a/tests/core/path.c
+++ b/tests/core/path.c
@@ -356,7 +356,7 @@ typedef struct {
#define CANCEL_VALUE 1234
-static int check_one_walkup_step(void *ref, git_buf *path)
+static int check_one_walkup_step(void *ref, const char *path)
{
check_walkup_info *info = (check_walkup_info *)ref;
@@ -367,7 +367,7 @@ static int check_one_walkup_step(void *ref, git_buf *path)
info->cancel_after--;
cl_assert(info->expect[info->expect_idx] != NULL);
- cl_assert_equal_s(info->expect[info->expect_idx], path->ptr);
+ cl_assert_equal_s(info->expect[info->expect_idx], path);
info->expect_idx++;
return 0;
@@ -376,18 +376,42 @@ static int check_one_walkup_step(void *ref, git_buf *path)
void test_core_path__11_walkup(void)
{
git_buf p = GIT_BUF_INIT;
+
char *expect[] = {
- "/a/b/c/d/e/", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
- "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
- "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
- "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
- "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL,
- "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL,
- "this is a path", NULL,
- "///a///b///c///d///e///", "///a///b///c///d///", "///a///b///c///", "///a///b///", "///a///", "///", NULL,
- NULL
+ /* 1 */ "/a/b/c/d/e/", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
+ /* 2 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
+ /* 3 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
+ /* 4 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
+ /* 5 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL,
+ /* 6 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL,
+ /* 7 */ "this_is_a_path", "", NULL,
+ /* 8 */ "this_is_a_path/", "", NULL,
+ /* 9 */ "///a///b///c///d///e///", "///a///b///c///d///", "///a///b///c///", "///a///b///", "///a///", "///", NULL,
+ /* 10 */ "a/b/c/", "a/b/", "a/", "", NULL,
+ /* 11 */ "a/b/c", "a/b/", "a/", "", NULL,
+ /* 12 */ "a/b/c/", "a/b/", "a/", NULL,
+ /* 13 */ "", NULL,
+ /* 14 */ "/", NULL,
+ /* 15 */ NULL
+ };
+
+ char *root[] = {
+ /* 1 */ NULL,
+ /* 2 */ NULL,
+ /* 3 */ "/",
+ /* 4 */ "",
+ /* 5 */ "/a/b",
+ /* 6 */ "/a/b/",
+ /* 7 */ NULL,
+ /* 8 */ NULL,
+ /* 9 */ NULL,
+ /* 10 */ NULL,
+ /* 11 */ NULL,
+ /* 12 */ "a/",
+ /* 13 */ NULL,
+ /* 14 */ NULL,
};
- char *root[] = { NULL, NULL, "/", "", "/a/b", "/a/b/", NULL, NULL, NULL };
+
int i, j;
check_walkup_info info;
@@ -404,9 +428,8 @@ void test_core_path__11_walkup(void)
);
cl_assert_equal_s(p.ptr, expect[i]);
-
- /* skip to next run of expectations */
- while (expect[i] != NULL) i++;
+ cl_assert(expect[info.expect_idx] == NULL);
+ i = info.expect_idx;
}
git_buf_free(&p);
diff --git a/tests/describe/describe.c b/tests/describe/describe.c
new file mode 100644
index 000000000..9a523a169
--- /dev/null
+++ b/tests/describe/describe.c
@@ -0,0 +1,50 @@
+#include "clar_libgit2.h"
+#include "describe_helpers.h"
+
+void test_describe_describe__can_describe_against_a_bare_repo(void)
+{
+ git_repository *repo;
+ git_describe_options opts = GIT_DESCRIBE_OPTIONS_INIT;
+ git_describe_format_options fmt_opts = GIT_DESCRIBE_FORMAT_OPTIONS_INIT;
+
+ cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+
+ assert_describe("hard_tag", "HEAD", repo, &opts, &fmt_opts);
+
+ opts.show_commit_oid_as_fallback = 1;
+
+ assert_describe("be3563a*", "HEAD^", repo, &opts, &fmt_opts);
+
+ git_repository_free(repo);
+}
+
+static int delete_cb(git_reference *ref, void *payload)
+{
+ GIT_UNUSED(payload);
+
+ cl_git_pass(git_reference_delete(ref));
+ git_reference_free(ref);
+
+ return 0;
+}
+
+void test_describe_describe__cannot_describe_against_a_repo_with_no_ref(void)
+{
+ git_repository *repo;
+ git_describe_options opts = GIT_DESCRIBE_OPTIONS_INIT;
+ git_buf buf = GIT_BUF_INIT;
+ git_object *object;
+ git_describe_result *result = NULL;
+
+ repo = cl_git_sandbox_init("testrepo.git");
+ cl_git_pass(git_revparse_single(&object, repo, "HEAD"));
+
+ cl_git_pass(git_reference_foreach(repo, delete_cb, NULL));
+
+ cl_git_fail(git_describe_commit(&result, object, &opts));
+
+ git_describe_result_free(result);
+ git_object_free(object);
+ git_buf_free(&buf);
+ cl_git_sandbox_cleanup();
+}
diff --git a/tests/describe/describe_helpers.c b/tests/describe/describe_helpers.c
new file mode 100644
index 000000000..7a6a73cb8
--- /dev/null
+++ b/tests/describe/describe_helpers.c
@@ -0,0 +1,42 @@
+#include "describe_helpers.h"
+
+void assert_describe(
+ const char *expected_output,
+ const char *revparse_spec,
+ git_repository *repo,
+ git_describe_options *opts,
+ git_describe_format_options *fmt_opts)
+{
+ git_object *object;
+ git_buf label = GIT_BUF_INIT;
+ git_describe_result *result;
+
+ cl_git_pass(git_revparse_single(&object, repo, revparse_spec));
+
+ cl_git_pass(git_describe_commit(&result, object, opts));
+ cl_git_pass(git_describe_format(&label, result, fmt_opts));
+
+ cl_git_pass(p_fnmatch(expected_output, git_buf_cstr(&label), 0));
+
+ git_describe_result_free(result);
+ git_object_free(object);
+ git_buf_free(&label);
+}
+
+void assert_describe_workdir(
+ const char *expected_output,
+ git_repository *repo,
+ git_describe_options *opts,
+ git_describe_format_options *fmt_opts)
+{
+ git_buf label = GIT_BUF_INIT;
+ git_describe_result *result;
+
+ cl_git_pass(git_describe_workdir(&result, repo, opts));
+ cl_git_pass(git_describe_format(&label, result, fmt_opts));
+
+ cl_git_pass(p_fnmatch(expected_output, git_buf_cstr(&label), 0));
+
+ git_describe_result_free(result);
+ git_buf_free(&label);
+}
diff --git a/tests/describe/describe_helpers.h b/tests/describe/describe_helpers.h
new file mode 100644
index 000000000..16a0638e3
--- /dev/null
+++ b/tests/describe/describe_helpers.h
@@ -0,0 +1,15 @@
+#include "clar_libgit2.h"
+#include "buffer.h"
+
+extern void assert_describe(
+ const char *expected_output,
+ const char *revparse_spec,
+ git_repository *repo,
+ git_describe_options *opts,
+ git_describe_format_options *fmt_opts);
+
+extern void assert_describe_workdir(
+ const char *expected_output,
+ git_repository *repo,
+ git_describe_options *opts,
+ git_describe_format_options *fmt_opts);
diff --git a/tests/describe/t6120.c b/tests/describe/t6120.c
new file mode 100644
index 000000000..2377335a5
--- /dev/null
+++ b/tests/describe/t6120.c
@@ -0,0 +1,156 @@
+#include "clar_libgit2.h"
+#include "describe_helpers.h"
+#include "repository.h"
+
+// Ported from https://github.com/git/git/blob/adfc1857bdb090786fd9d22c1acec39371c76048/t/t6120-describe.sh
+
+static git_repository *repo;
+
+void test_describe_t6120__initialize(void)
+{
+ repo = cl_git_sandbox_init("describe");
+}
+
+void test_describe_t6120__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+}
+
+void test_describe_t6120__default(void)
+{
+ git_describe_options opts = GIT_DESCRIBE_OPTIONS_INIT;
+ git_describe_format_options fmt_opts = GIT_DESCRIBE_FORMAT_OPTIONS_INIT;
+
+ assert_describe("A-*", "HEAD", repo, &opts, &fmt_opts);
+ assert_describe("A-*", "HEAD^", repo, &opts, &fmt_opts);
+ assert_describe("R-*", "HEAD^^", repo, &opts, &fmt_opts);
+ assert_describe("A-*", "HEAD^^2", repo, &opts, &fmt_opts);
+ assert_describe("B", "HEAD^^2^", repo, &opts, &fmt_opts);
+ assert_describe("R-*", "HEAD^^^", repo, &opts, &fmt_opts);
+}
+
+void test_describe_t6120__tags(void)
+{
+ git_describe_options opts = GIT_DESCRIBE_OPTIONS_INIT;
+ git_describe_format_options fmt_opts = GIT_DESCRIBE_FORMAT_OPTIONS_INIT;
+ opts.describe_strategy = GIT_DESCRIBE_TAGS;
+
+ assert_describe("c-*", "HEAD", repo, &opts, &fmt_opts);
+ assert_describe("c-*", "HEAD^", repo, &opts, &fmt_opts);
+ assert_describe("e-*", "HEAD^^", repo, &opts, &fmt_opts);
+ assert_describe("c-*", "HEAD^^2", repo, &opts, &fmt_opts);
+ assert_describe("B", "HEAD^^2^", repo, &opts, &fmt_opts);
+ assert_describe("e", "HEAD^^^", repo, &opts, &fmt_opts);
+}
+
+void test_describe_t6120__all(void)
+{
+ git_describe_options opts = GIT_DESCRIBE_OPTIONS_INIT;
+ git_describe_format_options fmt_opts = GIT_DESCRIBE_FORMAT_OPTIONS_INIT;
+ opts.describe_strategy = GIT_DESCRIBE_ALL;
+
+ assert_describe("heads/master", "HEAD", repo, &opts, &fmt_opts);
+ assert_describe("tags/c-*", "HEAD^", repo, &opts, &fmt_opts);
+ assert_describe("tags/e", "HEAD^^^", repo, &opts, &fmt_opts);
+}
+
+void test_describe_t6120__longformat(void)
+{
+ git_describe_options opts = GIT_DESCRIBE_OPTIONS_INIT;
+ git_describe_format_options fmt_opts = GIT_DESCRIBE_FORMAT_OPTIONS_INIT;
+
+ fmt_opts.always_use_long_format = 1;
+
+ assert_describe("B-0-*", "HEAD^^2^", repo, &opts, &fmt_opts);
+ assert_describe("A-3-*", "HEAD^^2", repo, &opts, &fmt_opts);
+}
+
+void test_describe_t6120__firstparent(void)
+{
+ git_describe_options opts = GIT_DESCRIBE_OPTIONS_INIT;
+ git_describe_format_options fmt_opts = GIT_DESCRIBE_FORMAT_OPTIONS_INIT;
+ opts.describe_strategy = GIT_DESCRIBE_TAGS;
+
+ assert_describe("c-7-*", "HEAD", repo, &opts, &fmt_opts);
+
+ opts.only_follow_first_parent = 1;
+ assert_describe("e-3-*", "HEAD", repo, &opts, &fmt_opts);
+}
+
+void test_describe_t6120__workdir(void)
+{
+ git_describe_options opts = GIT_DESCRIBE_OPTIONS_INIT;
+ git_describe_format_options fmt_opts = GIT_DESCRIBE_FORMAT_OPTIONS_INIT;
+
+ assert_describe_workdir("A-*[0-9a-f]", repo, &opts, &fmt_opts);
+ cl_git_mkfile("describe/file", "something different");
+
+ fmt_opts.dirty_suffix = "-dirty";
+ assert_describe_workdir("A-*[0-9a-f]-dirty", repo, &opts, &fmt_opts);
+ fmt_opts.dirty_suffix = ".mod";
+ assert_describe_workdir("A-*[0-9a-f].mod", repo, &opts, &fmt_opts);
+}
+
+static void commit_and_tag(
+ git_time_t *time,
+ const char *commit_msg,
+ const char *tag_name)
+{
+ git_index *index;
+ git_oid commit_id;
+ git_reference *ref;
+
+ cl_git_pass(git_repository_index__weakptr(&index, repo));
+
+ cl_git_append2file("describe/file", "\n");
+
+ git_index_add_bypath(index, "describe/file");
+ git_index_write(index);
+
+ *time += 10;
+ cl_repo_commit_from_index(&commit_id, repo, NULL, *time, commit_msg);
+
+ if (tag_name == NULL)
+ return;
+
+ cl_git_pass(git_reference_create(&ref, repo, tag_name, &commit_id, 0, NULL, NULL));
+ git_reference_free(ref);
+}
+
+void test_describe_t6120__pattern(void)
+{
+ git_describe_options opts = GIT_DESCRIBE_OPTIONS_INIT;
+ git_describe_format_options fmt_opts = GIT_DESCRIBE_FORMAT_OPTIONS_INIT;
+ git_oid tag_id;
+ git_object *head;
+ git_signature *tagger;
+ git_time_t time;
+
+ /* set-up matching pattern tests */
+ cl_git_pass(git_revparse_single(&head, repo, "HEAD"));
+
+ time = 1380553019;
+ cl_git_pass(git_signature_new(&tagger, "tagger", "tagger@libgit2.org", time, 0));
+ cl_git_pass(git_tag_create(&tag_id, repo, "test-annotated", head, tagger, "test-annotated", 0));
+ git_signature_free(tagger);
+ git_object_free(head);
+
+ commit_and_tag(&time, "one more", "refs/tags/test1-lightweight");
+ commit_and_tag(&time, "yet another", "refs/tags/test2-lightweight");
+ commit_and_tag(&time, "even more", NULL);
+
+
+ /* Exercize */
+ opts.pattern = "test-*";
+ assert_describe("test-annotated-*", "HEAD", repo, &opts, &fmt_opts);
+
+ opts.describe_strategy = GIT_DESCRIBE_TAGS;
+ opts.pattern = "test1-*";
+ assert_describe("test1-lightweight-*", "HEAD", repo, &opts, &fmt_opts);
+
+ opts.pattern = "test2-*";
+ assert_describe("test2-lightweight-*", "HEAD", repo, &opts, &fmt_opts);
+
+ fmt_opts.always_use_long_format = 1;
+ assert_describe("test2-lightweight-*", "HEAD^", repo, &opts, &fmt_opts);
+}
diff --git a/tests/fetchhead/fetchhead_data.h b/tests/fetchhead/fetchhead_data.h
index 94402abd5..c75b65b90 100644
--- a/tests/fetchhead/fetchhead_data.h
+++ b/tests/fetchhead/fetchhead_data.h
@@ -16,6 +16,11 @@
"8f50ba15d49353813cc6e20298002c0d17b0a9ee\tnot-for-merge\ttag 'commit_tree' of git://github.com/libgit2/TestGitRepository\n" \
"6e0c7bdb9b4ed93212491ee778ca1c65047cab4e\tnot-for-merge\ttag 'nearly-dangling' of git://github.com/libgit2/TestGitRepository\n"
+#define FETCH_HEAD_WILDCARD_DATA2 \
+ "49322bb17d3acc9146f98c97d078513228bbf3c0\t\tbranch 'master' of git://github.com/libgit2/TestGitRepository\n" \
+ "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n" \
+ "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of git://github.com/libgit2/TestGitRepository\n" \
+
#define FETCH_HEAD_NO_MERGE_DATA \
"0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n" \
"49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\tbranch 'master' of git://github.com/libgit2/TestGitRepository\n" \
@@ -25,6 +30,16 @@
"8f50ba15d49353813cc6e20298002c0d17b0a9ee\tnot-for-merge\ttag 'commit_tree' of git://github.com/libgit2/TestGitRepository\n" \
"6e0c7bdb9b4ed93212491ee778ca1c65047cab4e\tnot-for-merge\ttag 'nearly-dangling' of git://github.com/libgit2/TestGitRepository\n"
+#define FETCH_HEAD_NO_MERGE_DATA2 \
+ "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n" \
+ "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\tbranch 'master' of git://github.com/libgit2/TestGitRepository\n" \
+ "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of git://github.com/libgit2/TestGitRepository\n" \
+
+#define FETCH_HEAD_NO_MERGE_DATA3 \
+ "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n" \
+ "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\tbranch 'master' of git://github.com/libgit2/TestGitRepository\n" \
+ "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of git://github.com/libgit2/TestGitRepository\n" \
+ "8f50ba15d49353813cc6e20298002c0d17b0a9ee\tnot-for-merge\ttag 'commit_tree' of git://github.com/libgit2/TestGitRepository\n" \
#define FETCH_HEAD_EXPLICIT_DATA \
"0966a434eb1a025db6b71485ab63a3bfbea520b6\t\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n"
diff --git a/tests/fetchhead/nonetwork.c b/tests/fetchhead/nonetwork.c
index 7b64a6339..c8191c5f5 100644
--- a/tests/fetchhead/nonetwork.c
+++ b/tests/fetchhead/nonetwork.c
@@ -335,7 +335,7 @@ void test_fetchhead_nonetwork__unborn_with_upstream(void)
cl_git_pass(git_remote_set_url(remote, cl_fixture("testrepo.git")));
cl_git_pass(git_remote_save(remote));
- cl_git_pass(git_remote_fetch(remote, NULL, NULL));
+ cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL));
git_remote_free(remote);
cl_git_pass(git_repository_fetchhead_foreach(repo, assert_master_for_merge, NULL));
diff --git a/tests/index/names.c b/tests/index/names.c
index 52922e9f1..c7619ed13 100644
--- a/tests/index/names.c
+++ b/tests/index/names.c
@@ -89,7 +89,7 @@ void test_index_names__cleaned_on_reset_hard(void)
cl_git_pass(git_revparse_single(&target, repo, "3a34580"));
test_index_names__add();
- cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL, NULL));
cl_assert(git_index_name_entrycount(repo_index) == 0);
git_object_free(target);
@@ -102,7 +102,7 @@ void test_index_names__cleaned_on_reset_mixed(void)
cl_git_pass(git_revparse_single(&target, repo, "3a34580"));
test_index_names__add();
- cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL, NULL, NULL));
cl_assert(git_index_name_entrycount(repo_index) == 0);
git_object_free(target);
diff --git a/tests/index/reuc.c b/tests/index/reuc.c
index 0b4d71a6a..0b948a29e 100644
--- a/tests/index/reuc.c
+++ b/tests/index/reuc.c
@@ -298,7 +298,7 @@ void test_index_reuc__cleaned_on_reset_hard(void)
cl_git_pass(git_revparse_single(&target, repo, "3a34580"));
test_index_reuc__add();
- cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL, NULL));
cl_assert(reuc_entry_exists() == false);
git_object_free(target);
@@ -311,7 +311,7 @@ void test_index_reuc__cleaned_on_reset_mixed(void)
cl_git_pass(git_revparse_single(&target, repo, "3a34580"));
test_index_reuc__add();
- cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL, NULL, NULL));
cl_assert(reuc_entry_exists() == false);
git_object_free(target);
@@ -323,10 +323,10 @@ void test_index_reuc__retained_on_reset_soft(void)
cl_git_pass(git_revparse_single(&target, repo, "3a34580"));
- git_reset(repo, target, GIT_RESET_HARD, NULL, NULL);
+ git_reset(repo, target, GIT_RESET_HARD, NULL, NULL, NULL);
test_index_reuc__add();
- cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL, NULL));
cl_assert(reuc_entry_exists() == true);
git_object_free(target);
diff --git a/tests/merge/merge_helpers.c b/tests/merge/merge_helpers.c
index 154985f11..e3e703943 100644
--- a/tests/merge/merge_helpers.c
+++ b/tests/merge/merge_helpers.c
@@ -327,7 +327,7 @@ int merge_test_reuc(git_index *index, const struct merge_reuc_entry expected[],
int dircount(void *payload, git_buf *pathbuf)
{
- int *entries = payload;
+ size_t *entries = payload;
size_t len = git_buf_len(pathbuf);
if (len < 5 || strcmp(pathbuf->ptr + (git_buf_len(pathbuf) - 5), "/.git") != 0)
diff --git a/tests/merge/merge_helpers.h b/tests/merge/merge_helpers.h
index fddf8fab1..554c24b7c 100644
--- a/tests/merge/merge_helpers.h
+++ b/tests/merge/merge_helpers.h
@@ -49,7 +49,7 @@
struct merge_index_entry {
uint16_t mode;
- char oid_str[41];
+ char oid_str[GIT_OID_HEXSZ+1];
int stage;
char path[128];
};
@@ -70,9 +70,9 @@ struct merge_reuc_entry {
unsigned int ancestor_mode;
unsigned int our_mode;
unsigned int their_mode;
- char ancestor_oid_str[41];
- char our_oid_str[41];
- char their_oid_str[41];
+ char ancestor_oid_str[GIT_OID_HEXSZ+1];
+ char our_oid_str[GIT_OID_HEXSZ+1];
+ char their_oid_str[GIT_OID_HEXSZ+1];
};
struct merge_index_conflict_data {
diff --git a/tests/merge/trees/treediff.c b/tests/merge/trees/treediff.c
index 2298a302b..8b47f7dee 100644
--- a/tests/merge/trees/treediff.c
+++ b/tests/merge/trees/treediff.c
@@ -3,7 +3,7 @@
#include "merge.h"
#include "../merge_helpers.h"
#include "diff.h"
-#include "hashsig.h"
+#include "git2/sys/hashsig.h"
static git_repository *repo;
diff --git a/tests/merge/workdir/dirty.c b/tests/merge/workdir/dirty.c
index 2f776853e..0549b06b3 100644
--- a/tests/merge/workdir/dirty.c
+++ b/tests/merge/workdir/dirty.c
@@ -182,7 +182,7 @@ static void stage_content(char *content[])
cl_git_pass(git_repository_head(&head, repo));
cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJ_COMMIT));
- cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, NULL, NULL, NULL));
for (i = 0, filename = content[i], text = content[++i];
filename && text;
@@ -209,7 +209,7 @@ static int merge_dirty_files(char *dirty_files[])
cl_git_pass(git_repository_head(&head, repo));
cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJ_COMMIT));
- cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, NULL, NULL, NULL));
write_files(dirty_files);
@@ -229,7 +229,7 @@ static int merge_differently_filtered_files(char *files[])
cl_git_pass(git_repository_head(&head, repo));
cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJ_COMMIT));
- cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, NULL, NULL, NULL));
write_files(files);
hack_index(files);
@@ -266,7 +266,7 @@ void test_merge_workdir_dirty__unstaged_deletes_maintained(void)
cl_git_pass(git_repository_head(&head, repo));
cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJ_COMMIT));
- cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, NULL, NULL, NULL));
cl_git_pass(p_unlink("merge-resolve/unchanged.txt"));
diff --git a/tests/merge/workdir/simple.c b/tests/merge/workdir/simple.c
index 327408dc9..fcd84dcd1 100644
--- a/tests/merge/workdir/simple.c
+++ b/tests/merge/workdir/simple.c
@@ -516,7 +516,7 @@ void test_merge_workdir_simple__directory_file(void)
cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_DIR OURS_DIRECTORY_FILE, 1, NULL, NULL));
cl_git_pass(git_reference_name_to_id(&head_commit_id, repo, GIT_HEAD_FILE));
cl_git_pass(git_commit_lookup(&head_commit, repo, &head_commit_id));
- cl_git_pass(git_reset(repo, (git_object *)head_commit, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head_commit, GIT_RESET_HARD, NULL, NULL, NULL));
cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_DIRECTORY_FILE));
cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0]));
@@ -608,7 +608,7 @@ void test_merge_workdir_simple__binary(void)
cl_git_pass(git_oid_fromstr(&their_oid, "ad01aebfdf2ac13145efafe3f9fcf798882f1730"));
cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid));
- cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD, NULL, NULL, NULL));
cl_git_pass(git_merge_head_from_id(&their_head, repo, &their_oid));
diff --git a/tests/merge/workdir/submodules.c b/tests/merge/workdir/submodules.c
index e093e77ab..eec9f14a9 100644
--- a/tests/merge/workdir/submodules.c
+++ b/tests/merge/workdir/submodules.c
@@ -44,7 +44,7 @@ void test_merge_workdir_submodules__automerge(void)
cl_git_pass(git_reference_lookup(&our_ref, repo, "refs/heads/" SUBMODULE_MAIN_BRANCH));
cl_git_pass(git_commit_lookup(&our_commit, repo, git_reference_target(our_ref)));
- cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD, NULL, NULL, NULL));
cl_git_pass(git_reference_lookup(&their_ref, repo, "refs/heads/" SUBMODULE_OTHER_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref));
@@ -77,7 +77,7 @@ void test_merge_workdir_submodules__take_changed(void)
cl_git_pass(git_reference_lookup(&our_ref, repo, "refs/heads/" SUBMODULE_MAIN_BRANCH));
cl_git_pass(git_commit_lookup(&our_commit, repo, git_reference_target(our_ref)));
- cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD, NULL, NULL, NULL));
cl_git_pass(git_reference_lookup(&their_ref, repo, "refs/heads/" SUBMODULE_OTHER2_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref));
diff --git a/tests/network/fetchlocal.c b/tests/network/fetchlocal.c
index 8809f427d..eb9a1087a 100644
--- a/tests/network/fetchlocal.c
+++ b/tests/network/fetchlocal.c
@@ -36,7 +36,7 @@ void test_network_fetchlocal__complete(void)
cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url));
git_remote_set_callbacks(origin, &callbacks);
cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH));
- cl_git_pass(git_remote_download(origin));
+ cl_git_pass(git_remote_download(origin, NULL));
cl_git_pass(git_remote_update_tips(origin, NULL, NULL));
cl_git_pass(git_reference_list(&refnames, repo));
@@ -74,7 +74,7 @@ void test_network_fetchlocal__partial(void)
cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url));
git_remote_set_callbacks(origin, &callbacks);
cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH));
- cl_git_pass(git_remote_download(origin));
+ cl_git_pass(git_remote_download(origin, NULL));
cl_git_pass(git_remote_update_tips(origin, NULL, NULL));
git_strarray_free(&refnames);
@@ -127,3 +127,37 @@ void test_network_fetchlocal__clone_into_mirror(void)
git_repository_free(repo);
cl_fixture_cleanup("./foo.git");
}
+
+void test_network_fetchlocal__multi_remotes(void)
+{
+ git_repository *repo = cl_git_sandbox_init("testrepo.git");
+ git_remote *test, *test2;
+ git_strarray refnames = {0};
+ git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
+
+ callbacks.transfer_progress = transfer_cb;
+ cl_git_pass(git_remote_load(&test, repo, "test"));
+ cl_git_pass(git_remote_set_url(test, cl_git_fixture_url("testrepo.git")));
+ git_remote_set_callbacks(test, &callbacks);
+ cl_git_pass(git_remote_connect(test, GIT_DIRECTION_FETCH));
+ cl_git_pass(git_remote_download(test, NULL));
+ cl_git_pass(git_remote_update_tips(test, NULL, NULL));
+
+ cl_git_pass(git_reference_list(&refnames, repo));
+ cl_assert_equal_i(32, (int)refnames.count);
+
+ cl_git_pass(git_remote_load(&test2, repo, "test_with_pushurl"));
+ cl_git_pass(git_remote_set_url(test2, cl_git_fixture_url("testrepo.git")));
+ git_remote_set_callbacks(test2, &callbacks);
+ cl_git_pass(git_remote_connect(test2, GIT_DIRECTION_FETCH));
+ cl_git_pass(git_remote_download(test2, NULL));
+ cl_git_pass(git_remote_update_tips(test2, NULL, NULL));
+
+ cl_git_pass(git_reference_list(&refnames, repo));
+ cl_assert_equal_i(44, (int)refnames.count);
+
+ git_strarray_free(&refnames);
+ git_remote_free(test);
+ git_remote_free(test2);
+ git_repository_free(repo);
+}
diff --git a/tests/network/remote/local.c b/tests/network/remote/local.c
index f1084fc38..c6c9e4ca9 100644
--- a/tests/network/remote/local.c
+++ b/tests/network/remote/local.c
@@ -116,16 +116,20 @@ void test_network_remote_local__nested_tags_are_completely_peeled(void)
void test_network_remote_local__shorthand_fetch_refspec0(void)
{
- const char *refspec = "master:remotes/sloppy/master";
- const char *refspec2 = "master:boh/sloppy/master";
+ char *refspec_strings[] = {
+ "master:remotes/sloppy/master",
+ "master:boh/sloppy/master",
+ };
+ git_strarray array = {
+ refspec_strings,
+ 2,
+ };
git_reference *ref;
connect_to_local_repository(cl_fixture("testrepo.git"));
- cl_git_pass(git_remote_add_fetch(remote, refspec));
- cl_git_pass(git_remote_add_fetch(remote, refspec2));
- cl_git_pass(git_remote_download(remote));
+ cl_git_pass(git_remote_download(remote, &array));
cl_git_pass(git_remote_update_tips(remote, NULL, NULL));
cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/sloppy/master"));
@@ -137,17 +141,21 @@ void test_network_remote_local__shorthand_fetch_refspec0(void)
void test_network_remote_local__shorthand_fetch_refspec1(void)
{
- const char *refspec = "master";
- const char *refspec2 = "hard_tag";
+ char *refspec_strings[] = {
+ "master",
+ "hard_tag",
+ };
+ git_strarray array = {
+ refspec_strings,
+ 2,
+ };
git_reference *ref;
connect_to_local_repository(cl_fixture("testrepo.git"));
git_remote_clear_refspecs(remote);
- cl_git_pass(git_remote_add_fetch(remote, refspec));
- cl_git_pass(git_remote_add_fetch(remote, refspec2));
- cl_git_pass(git_remote_download(remote));
+ cl_git_pass(git_remote_download(remote, &array));
cl_git_pass(git_remote_update_tips(remote, NULL, NULL));
cl_git_fail(git_reference_lookup(&ref, repo, "refs/remotes/master"));
@@ -162,7 +170,7 @@ void test_network_remote_local__tagopt(void)
connect_to_local_repository(cl_fixture("testrepo.git"));
git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_ALL);
- cl_git_pass(git_remote_download(remote));
+ cl_git_pass(git_remote_download(remote, NULL));
cl_git_pass(git_remote_update_tips(remote, NULL, NULL));
@@ -174,14 +182,20 @@ void test_network_remote_local__tagopt(void)
void test_network_remote_local__push_to_bare_remote(void)
{
+ char *refspec_strings[] = {
+ "master:master",
+ };
+ git_strarray array = {
+ refspec_strings,
+ 1,
+ };
/* Should be able to push to a bare remote */
git_remote *localremote;
git_push *push;
/* Get some commits */
connect_to_local_repository(cl_fixture("testrepo.git"));
- cl_git_pass(git_remote_add_fetch(remote, "master:master"));
- cl_git_pass(git_remote_download(remote));
+ cl_git_pass(git_remote_download(remote, &array));
cl_git_pass(git_remote_update_tips(remote, NULL, NULL));
git_remote_disconnect(remote);
@@ -210,6 +224,13 @@ void test_network_remote_local__push_to_bare_remote(void)
void test_network_remote_local__push_to_bare_remote_with_file_url(void)
{
+ char *refspec_strings[] = {
+ "master:master",
+ };
+ git_strarray array = {
+ refspec_strings,
+ 1,
+ };
/* Should be able to push to a bare remote */
git_remote *localremote;
git_push *push;
@@ -217,8 +238,7 @@ void test_network_remote_local__push_to_bare_remote_with_file_url(void)
/* Get some commits */
connect_to_local_repository(cl_fixture("testrepo.git"));
- cl_git_pass(git_remote_add_fetch(remote, "master:master"));
- cl_git_pass(git_remote_download(remote));
+ cl_git_pass(git_remote_download(remote, &array));
cl_git_pass(git_remote_update_tips(remote, NULL, NULL));
git_remote_disconnect(remote);
@@ -251,14 +271,20 @@ void test_network_remote_local__push_to_bare_remote_with_file_url(void)
void test_network_remote_local__push_to_non_bare_remote(void)
{
+ char *refspec_strings[] = {
+ "master:master",
+ };
+ git_strarray array = {
+ refspec_strings,
+ 1,
+ };
/* Shouldn't be able to push to a non-bare remote */
git_remote *localremote;
git_push *push;
/* Get some commits */
connect_to_local_repository(cl_fixture("testrepo.git"));
- cl_git_pass(git_remote_add_fetch(remote, "master:master"));
- cl_git_pass(git_remote_download(remote));
+ cl_git_pass(git_remote_download(remote, &array));
cl_git_pass(git_remote_update_tips(remote, NULL, NULL));
git_remote_disconnect(remote);
@@ -287,7 +313,13 @@ void test_network_remote_local__push_to_non_bare_remote(void)
void test_network_remote_local__fetch(void)
{
- const char *refspec = "master:remotes/sloppy/master";
+ char *refspec_strings[] = {
+ "master:remotes/sloppy/master",
+ };
+ git_strarray array = {
+ refspec_strings,
+ 1,
+ };
git_reflog *log;
const git_reflog_entry *entry;
@@ -297,9 +329,8 @@ void test_network_remote_local__fetch(void)
cl_git_pass(git_signature_now(&sig, "Foo Bar", "foo@example.com"));
connect_to_local_repository(cl_fixture("testrepo.git"));
- cl_git_pass(git_remote_add_fetch(remote, refspec));
- cl_git_pass(git_remote_fetch(remote, sig, "UPDAAAAAATE!!"));
+ cl_git_pass(git_remote_fetch(remote, &array, sig, "UPDAAAAAATE!!"));
cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/sloppy/master"));
git_reference_free(ref);
@@ -316,7 +347,13 @@ void test_network_remote_local__fetch(void)
void test_network_remote_local__reflog(void)
{
- const char *refspec = "master:remotes/sloppy/master";
+ char *refspec_strings[] = {
+ "master:remotes/sloppy/master",
+ };
+ git_strarray array = {
+ refspec_strings,
+ 1,
+ };
git_reflog *log;
const git_reflog_entry *entry;
@@ -325,9 +362,8 @@ void test_network_remote_local__reflog(void)
cl_git_pass(git_signature_now(&sig, "Foo Bar", "foo@example.com"));
connect_to_local_repository(cl_fixture("testrepo.git"));
- cl_git_pass(git_remote_add_fetch(remote, refspec));
- cl_git_pass(git_remote_download(remote));
+ cl_git_pass(git_remote_download(remote, &array));
cl_git_pass(git_remote_update_tips(remote, sig, "UPDAAAAAATE!!"));
cl_git_pass(git_reflog_read(&log, repo, "refs/remotes/sloppy/master"));
@@ -342,7 +378,13 @@ void test_network_remote_local__reflog(void)
void test_network_remote_local__fetch_default_reflog_message(void)
{
- const char *refspec = "master:remotes/sloppy/master";
+ char *refspec_strings[] = {
+ "master:remotes/sloppy/master",
+ };
+ git_strarray array = {
+ refspec_strings,
+ 1,
+ };
git_reflog *log;
const git_reflog_entry *entry;
@@ -352,9 +394,8 @@ void test_network_remote_local__fetch_default_reflog_message(void)
cl_git_pass(git_signature_now(&sig, "Foo Bar", "foo@example.com"));
connect_to_local_repository(cl_fixture("testrepo.git"));
- cl_git_pass(git_remote_add_fetch(remote, refspec));
- cl_git_pass(git_remote_fetch(remote, sig, NULL));
+ cl_git_pass(git_remote_fetch(remote, &array, sig, NULL));
cl_git_pass(git_reflog_read(&log, repo, "refs/remotes/sloppy/master"));
cl_assert_equal_i(1, git_reflog_entrycount(log));
@@ -367,3 +408,24 @@ void test_network_remote_local__fetch_default_reflog_message(void)
git_reflog_free(log);
git_signature_free(sig);
}
+
+void test_network_remote_local__opportunistic_update(void)
+{
+ git_reference *ref;
+ char *refspec_strings[] = {
+ "master",
+ };
+ git_strarray array = {
+ refspec_strings,
+ 1,
+ };
+
+ /* this remote has a passive refspec of "refs/heads/<star>:refs/remotes/origin/<star>" */
+ cl_git_pass(git_remote_create(&remote, repo, "origin", cl_git_fixture_url("testrepo.git")));
+ /* and we pass the active refspec "master" */
+ cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL));
+
+ /* and we expect that to update our copy of origin's master */
+ cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/origin/master"));
+ git_reference_free(ref);
+}
diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c
index d176774ea..df424e961 100644
--- a/tests/network/remote/remotes.c
+++ b/tests/network/remote/remotes.c
@@ -547,6 +547,7 @@ void test_network_remote_remotes__single_branch(void)
}
cl_assert_equal_i(1, count);
+ git_strarray_free(&refs);
git_repository_free(repo);
}
diff --git a/tests/object/raw/chars.c b/tests/object/raw/chars.c
index 206bf7119..cde0bdbf6 100644
--- a/tests/object/raw/chars.c
+++ b/tests/object/raw/chars.c
@@ -12,7 +12,7 @@ void test_object_raw_chars__find_invalid_chars_in_oid(void)
0xb7, 0x75, 0x21, 0x3c, 0x23,
0xa8, 0xbd, 0x74, 0xf5, 0xe0,
};
- char in[41] = "16a67770b7d8d72317c4b775213c23a8bd74f5e0";
+ char in[] = "16a67770b7d8d72317c4b775213c23a8bd74f5e0";
unsigned int i;
for (i = 0; i < 256; i++) {
diff --git a/tests/odb/foreach.c b/tests/odb/foreach.c
index 56daf7574..75448a2f7 100644
--- a/tests/odb/foreach.c
+++ b/tests/odb/foreach.c
@@ -87,7 +87,7 @@ void test_odb_foreach__files_in_objects_dir(void)
git_repository *repo;
git_odb *odb;
git_buf buf = GIT_BUF_INIT;
- size_t nobj = 0;
+ int nobj = 0;
cl_fixture_sandbox("testrepo.git");
cl_git_pass(git_repository_open(&repo, "testrepo.git"));
diff --git a/tests/online/clone.c b/tests/online/clone.c
index 6a6c049f8..13abd39bd 100644
--- a/tests/online/clone.c
+++ b/tests/online/clone.c
@@ -473,8 +473,95 @@ void test_online_clone__ssh_cannot_change_username(void)
cl_git_fail(git_clone(&g_repo, "ssh://git@github.com/libgit2/TestGitRepository", "./foo", &g_options));
}
+int ssh_certificate_check(git_cert *cert, int valid, const char *host, void *payload)
+{
+ git_cert_hostkey *key;
+ git_oid expected = {{0}}, actual = {{0}};
+ const char *expected_str;
+
+ GIT_UNUSED(valid);
+ GIT_UNUSED(payload);
+
+ expected_str = cl_getenv("GITTEST_REMOTE_SSH_FINGERPRINT");
+ cl_assert(expected_str);
+
+ cl_git_pass(git_oid_fromstrp(&expected, expected_str));
+ cl_assert_equal_i(GIT_CERT_HOSTKEY_LIBSSH2, cert->cert_type);
+ key = (git_cert_hostkey *) cert;
+
+ /*
+ * We need to figure out how long our input was to check for
+ * the type. Here we abuse the fact that both hashes fit into
+ * our git_oid type.
+ */
+ if (strlen(expected_str) == 32 && key->type & GIT_CERT_SSH_MD5) {
+ memcpy(&actual.id, key->hash_md5, 16);
+ } else if (strlen(expected_str) == 40 && key->type & GIT_CERT_SSH_SHA1) {
+ memcpy(&actual, key->hash_sha1, 20);
+ } else {
+ cl_fail("Cannot find a usable SSH hash");
+ }
+
+ cl_assert(!memcmp(&expected, &actual, 20));
+
+ cl_assert_equal_s("localhost", host);
+
+ return GIT_EUSER;
+}
+
+void test_online_clone__ssh_cert(void)
+{
+ g_options.remote_callbacks.certificate_check = ssh_certificate_check;
+
+ if (!cl_getenv("GITTEST_REMOTE_SSH_FINGERPRINT"))
+ cl_skip();
+
+ cl_git_fail_with(GIT_EUSER, git_clone(&g_repo, "ssh://localhost/foo", "./foo", &g_options));
+}
+
void test_online_clone__url_with_no_path_returns_EINVALIDSPEC(void)
{
cl_git_fail_with(git_clone(&g_repo, "http://github.com", "./foo", &g_options),
GIT_EINVALIDSPEC);
}
+
+static int fail_certificate_check(git_cert *cert, int valid, const char *host, void *payload)
+{
+ GIT_UNUSED(cert);
+ GIT_UNUSED(valid);
+ GIT_UNUSED(host);
+ GIT_UNUSED(payload);
+
+ return GIT_ECERTIFICATE;
+}
+
+void test_online_clone__certificate_invalid(void)
+{
+ g_options.remote_callbacks.certificate_check = fail_certificate_check;
+
+ cl_git_fail_with(git_clone(&g_repo, "https://github.com/libgit2/TestGitRepository", "./foo", &g_options),
+ GIT_ECERTIFICATE);
+
+#ifdef GIT_SSH
+ cl_git_fail_with(git_clone(&g_repo, "ssh://github.com/libgit2/TestGitRepository", "./foo", &g_options),
+ GIT_ECERTIFICATE);
+#endif
+}
+
+static int succeed_certificate_check(git_cert *cert, int valid, const char *host, void *payload)
+{
+ GIT_UNUSED(cert);
+ GIT_UNUSED(valid);
+ GIT_UNUSED(payload);
+
+ cl_assert_equal_s("github.com", host);
+
+ return 0;
+}
+
+void test_online_clone__certificate_valid(void)
+{
+ g_options.remote_callbacks.certificate_check = succeed_certificate_check;
+
+ cl_git_pass(git_clone(&g_repo, "https://github.com/libgit2/TestGitRepository", "./foo", &g_options));
+}
diff --git a/tests/online/fetch.c b/tests/online/fetch.c
index f03a6faa6..ce92ee82b 100644
--- a/tests/online/fetch.c
+++ b/tests/online/fetch.c
@@ -47,7 +47,7 @@ static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n)
git_remote_set_callbacks(remote, &callbacks);
git_remote_set_autotag(remote, flag);
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH));
- cl_git_pass(git_remote_download(remote));
+ cl_git_pass(git_remote_download(remote, NULL));
cl_git_pass(git_remote_update_tips(remote, NULL, NULL));
git_remote_disconnect(remote);
cl_assert_equal_i(counter, n);
@@ -86,11 +86,11 @@ void test_online_fetch__fetch_twice(void)
git_remote *remote;
cl_git_pass(git_remote_create(&remote, _repo, "test", "git://github.com/libgit2/TestGitRepository.git"));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH));
- cl_git_pass(git_remote_download(remote));
+ cl_git_pass(git_remote_download(remote, NULL));
git_remote_disconnect(remote);
git_remote_connect(remote, GIT_DIRECTION_FETCH);
- cl_git_pass(git_remote_download(remote));
+ cl_git_pass(git_remote_download(remote, NULL));
git_remote_disconnect(remote);
git_remote_free(remote);
@@ -128,7 +128,7 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date
callbacks.transfer_progress = &transferProgressCallback;
callbacks.payload = &invoked;
git_remote_set_callbacks(remote, &callbacks);
- cl_git_pass(git_remote_download(remote));
+ cl_git_pass(git_remote_download(remote, NULL));
cl_assert_equal_i(false, invoked);
@@ -162,7 +162,7 @@ void test_online_fetch__can_cancel(void)
git_remote_set_callbacks(remote, &callbacks);
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH));
- cl_git_fail_with(git_remote_download(remote), -4321);
+ cl_git_fail_with(git_remote_download(remote, NULL), -4321);
git_remote_disconnect(remote);
git_remote_free(remote);
}
diff --git a/tests/online/fetchhead.c b/tests/online/fetchhead.c
index 0b3f20db1..bd423bbb0 100644
--- a/tests/online/fetchhead.c
+++ b/tests/online/fetchhead.c
@@ -40,17 +40,19 @@ static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fet
git_remote *remote;
git_buf fetchhead_buf = GIT_BUF_INIT;
int equals = 0;
+ git_strarray array, *active_refs = NULL;
cl_git_pass(git_remote_load(&remote, g_repo, "origin"));
git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO);
if(fetchspec != NULL) {
- git_remote_clear_refspecs(remote);
- git_remote_add_fetch(remote, fetchspec);
+ array.count = 1;
+ array.strings = (char **) &fetchspec;
+ active_refs = &array;
}
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH));
- cl_git_pass(git_remote_download(remote));
+ cl_git_pass(git_remote_download(remote, active_refs));
cl_git_pass(git_remote_update_tips(remote, NULL, NULL));
git_remote_disconnect(remote);
git_remote_free(remote);
@@ -67,6 +69,11 @@ static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fet
void test_online_fetchhead__wildcard_spec(void)
{
fetchhead_test_clone();
+ fetchhead_test_fetch(NULL, FETCH_HEAD_WILDCARD_DATA2);
+ cl_git_pass(git_tag_delete(g_repo, "annotated_tag"));
+ cl_git_pass(git_tag_delete(g_repo, "blob"));
+ cl_git_pass(git_tag_delete(g_repo, "commit_tree"));
+ cl_git_pass(git_tag_delete(g_repo, "nearly-dangling"));
fetchhead_test_fetch(NULL, FETCH_HEAD_WILDCARD_DATA);
}
@@ -87,5 +94,12 @@ void test_online_fetchhead__no_merges(void)
cl_git_pass(git_config_delete_entry(config, "branch.master.merge"));
git_config_free(config);
+ fetchhead_test_fetch(NULL, FETCH_HEAD_NO_MERGE_DATA2);
+ cl_git_pass(git_tag_delete(g_repo, "annotated_tag"));
+ cl_git_pass(git_tag_delete(g_repo, "blob"));
+ cl_git_pass(git_tag_delete(g_repo, "commit_tree"));
+ cl_git_pass(git_tag_delete(g_repo, "nearly-dangling"));
fetchhead_test_fetch(NULL, FETCH_HEAD_NO_MERGE_DATA);
+ cl_git_pass(git_tag_delete(g_repo, "commit_tree"));
+ fetchhead_test_fetch(NULL, FETCH_HEAD_NO_MERGE_DATA3);
}
diff --git a/tests/online/push.c b/tests/online/push.c
index 70ec705fe..b09c7ad1f 100644
--- a/tests/online/push.c
+++ b/tests/online/push.c
@@ -408,7 +408,7 @@ void test_online_push__initialize(void)
/* Now that we've deleted everything, fetch from the remote */
cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_FETCH));
- cl_git_pass(git_remote_download(_remote));
+ cl_git_pass(git_remote_download(_remote, NULL));
cl_git_pass(git_remote_update_tips(_remote, NULL, NULL));
git_remote_disconnect(_remote);
}
diff --git a/tests/online/push_util.h b/tests/online/push_util.h
index a7207c49e..7736912d6 100644
--- a/tests/online/push_util.h
+++ b/tests/online/push_util.h
@@ -12,7 +12,7 @@ extern const git_oid OID_ZERO;
* @param data pointer to a record_callbacks_data instance
*/
#define RECORD_CALLBACKS_INIT(data) \
- { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, record_update_tips_cb, data }
+ { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, data }
typedef struct {
char *name;
diff --git a/tests/pack/packbuilder.c b/tests/pack/packbuilder.c
index 1059424ed..29f3e2d64 100644
--- a/tests/pack/packbuilder.c
+++ b/tests/pack/packbuilder.c
@@ -47,7 +47,7 @@ void test_pack_packbuilder__cleanup(void)
git_indexer_free(_indexer);
_indexer = NULL;
- p_chdir("..");
+ cl_git_pass(p_chdir(".."));
cl_git_sandbox_cleanup();
_repo = NULL;
}
@@ -93,7 +93,7 @@ void test_pack_packbuilder__create_pack(void)
git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
git_hash_ctx ctx;
git_oid hash;
- char hex[41]; hex[40] = '\0';
+ char hex[GIT_OID_HEXSZ+1]; hex[GIT_OID_HEXSZ] = '\0';
seed_packbuilder();
@@ -135,7 +135,7 @@ void test_pack_packbuilder__create_pack(void)
void test_pack_packbuilder__get_hash(void)
{
- char hex[41]; hex[40] = '\0';
+ char hex[GIT_OID_HEXSZ+1]; hex[GIT_OID_HEXSZ] = '\0';
seed_packbuilder();
diff --git a/tests/path/core.c b/tests/path/core.c
index be63e309b..45f54df29 100644
--- a/tests/path/core.c
+++ b/tests/path/core.c
@@ -16,8 +16,6 @@ static void test_make_relative(
void test_path_core__make_relative(void)
{
- git_buf buf = GIT_BUF_INIT;
-
test_make_relative("foo.c", "/path/to/foo.c", "/path/to", 0);
test_make_relative("bar/foo.c", "/path/to/bar/foo.c", "/path/to", 0);
test_make_relative("foo.c", "/path/to/foo.c", "/path/to/", 0);
diff --git a/tests/refs/transactions.c b/tests/refs/transactions.c
new file mode 100644
index 000000000..39ea1cae5
--- /dev/null
+++ b/tests/refs/transactions.c
@@ -0,0 +1,110 @@
+#include "clar_libgit2.h"
+#include "git2/transaction.h"
+
+static git_repository *g_repo;
+static git_transaction *g_tx;
+
+void test_refs_transactions__initialize(void)
+{
+ g_repo = cl_git_sandbox_init("testrepo");
+ cl_git_pass(git_transaction_new(&g_tx, g_repo));
+}
+
+void test_refs_transactions__cleanup(void)
+{
+ git_transaction_free(g_tx);
+ cl_git_sandbox_cleanup();
+}
+
+void test_refs_transactions__single_ref_oid(void)
+{
+ git_reference *ref;
+ git_oid id;
+
+ git_oid_fromstr(&id, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
+
+ cl_git_pass(git_transaction_lock_ref(g_tx, "refs/heads/master"));
+ cl_git_pass(git_transaction_set_target(g_tx, "refs/heads/master", &id, NULL, NULL));
+ cl_git_pass(git_transaction_commit(g_tx));
+
+ cl_git_pass(git_reference_lookup(&ref, g_repo, "refs/heads/master"));
+
+ cl_assert(!git_oid_cmp(&id, git_reference_target(ref)));
+ git_reference_free(ref);
+}
+
+void test_refs_transactions__single_ref_symbolic(void)
+{
+ git_reference *ref;
+
+ cl_git_pass(git_transaction_lock_ref(g_tx, "HEAD"));
+ cl_git_pass(git_transaction_set_symbolic_target(g_tx, "HEAD", "refs/heads/foo", NULL, NULL));
+ cl_git_pass(git_transaction_commit(g_tx));
+
+ cl_git_pass(git_reference_lookup(&ref, g_repo, "HEAD"));
+
+ cl_assert_equal_s("refs/heads/foo", git_reference_symbolic_target(ref));
+ git_reference_free(ref);
+}
+
+void test_refs_transactions__single_ref_mix_types(void)
+{
+ git_reference *ref;
+ git_oid id;
+
+ git_oid_fromstr(&id, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
+
+ cl_git_pass(git_transaction_lock_ref(g_tx, "refs/heads/master"));
+ cl_git_pass(git_transaction_lock_ref(g_tx, "HEAD"));
+ cl_git_pass(git_transaction_set_symbolic_target(g_tx, "refs/heads/master", "refs/heads/foo", NULL, NULL));
+ cl_git_pass(git_transaction_set_target(g_tx, "HEAD", &id, NULL, NULL));
+ cl_git_pass(git_transaction_commit(g_tx));
+
+ cl_git_pass(git_reference_lookup(&ref, g_repo, "refs/heads/master"));
+ cl_assert_equal_s("refs/heads/foo", git_reference_symbolic_target(ref));
+ git_reference_free(ref);
+
+ cl_git_pass(git_reference_lookup(&ref, g_repo, "HEAD"));
+ cl_assert(!git_oid_cmp(&id, git_reference_target(ref)));
+ git_reference_free(ref);
+}
+
+void test_refs_transactions__single_ref_delete(void)
+{
+ git_reference *ref;
+
+ cl_git_pass(git_transaction_lock_ref(g_tx, "refs/heads/master"));
+ cl_git_pass(git_transaction_remove(g_tx, "refs/heads/master"));
+ cl_git_pass(git_transaction_commit(g_tx));
+
+ cl_git_fail_with(GIT_ENOTFOUND, git_reference_lookup(&ref, g_repo, "refs/heads/master"));
+}
+
+void test_refs_transactions__single_create(void)
+{
+ git_reference *ref;
+ const char *name = "refs/heads/new-branch";
+ git_oid id;
+
+ cl_git_fail_with(GIT_ENOTFOUND, git_reference_lookup(&ref, g_repo, name));
+
+ cl_git_pass(git_transaction_lock_ref(g_tx, name));
+
+ git_oid_fromstr(&id, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
+ cl_git_pass(git_transaction_set_target(g_tx, name, &id, NULL, NULL));
+ cl_git_pass(git_transaction_commit(g_tx));
+
+ cl_git_pass(git_reference_lookup(&ref, g_repo, name));
+ cl_assert(!git_oid_cmp(&id, git_reference_target(ref)));
+ git_reference_free(ref);
+}
+
+void test_refs_transactions__unlocked_set(void)
+{
+ git_oid id;
+
+ cl_git_pass(git_transaction_lock_ref(g_tx, "refs/heads/master"));
+ git_oid_fromstr(&id, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
+ cl_git_fail_with(GIT_ENOTFOUND, git_transaction_set_target(g_tx, "refs/heads/foo", &id, NULL, NULL));
+ cl_git_pass(git_transaction_commit(g_tx));
+}
diff --git a/tests/repo/init.c b/tests/repo/init.c
index 999afd625..189b0894a 100644
--- a/tests/repo/init.c
+++ b/tests/repo/init.c
@@ -423,6 +423,7 @@ void test_repo_init__relative_gitdir_2(void)
/* make the directory first, then it should succeed */
cl_git_pass(git_repository_init_ext(&_repo, "root/b/my_repository", &opts));
+ git_buf_free(&full_path);
cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "root/b/c_wd/"));
cl_assert(!git__suffixcmp(git_repository_path(_repo), "root/b/my_repository/"));
diff --git a/tests/reset/hard.c b/tests/reset/hard.c
index c6bf7a8ac..e8cf10071 100644
--- a/tests/reset/hard.c
+++ b/tests/reset/hard.c
@@ -71,7 +71,7 @@ void test_reset_hard__resetting_reverts_modified_files(void)
cl_git_pass(git_revparse_single(&target, repo, "26a125e"));
- cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL, NULL));
for (i = 0; i < 4; ++i) {
cl_git_pass(git_buf_joinpath(&path, wd, files[i]));
@@ -96,7 +96,7 @@ void test_reset_hard__cannot_reset_in_a_bare_repository(void)
cl_git_pass(git_revparse_single(&target, bare, KNOWN_COMMIT_IN_BARE_REPO));
- cl_assert_equal_i(GIT_EBAREREPO, git_reset(bare, target, GIT_RESET_HARD, NULL, NULL));
+ cl_assert_equal_i(GIT_EBAREREPO, git_reset(bare, target, GIT_RESET_HARD, NULL, NULL, NULL));
git_repository_free(bare);
}
@@ -152,7 +152,7 @@ void test_reset_hard__resetting_reverts_unmerged(void)
cl_git_pass(git_index_write(index));
cl_git_pass(git_revparse_single(&target, repo, "26a125e"));
- cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL, NULL));
cl_assert(git_path_exists("status/conflicting_file") == 0);
@@ -183,7 +183,7 @@ void test_reset_hard__cleans_up_merge(void)
cl_git_mkfile(git_buf_cstr(&orig_head_path), "0017bd4ab1ec30440b17bae1680cff124ab5f1f6");
cl_git_pass(git_revparse_single(&target, repo, "0017bd4"));
- cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL, NULL));
cl_assert(!git_path_exists(git_buf_cstr(&merge_head_path)));
cl_assert(!git_path_exists(git_buf_cstr(&merge_msg_path)));
@@ -208,7 +208,7 @@ void test_reset_hard__reflog_is_correct(void)
/* Branch not moving, no reflog entry */
cl_git_pass(git_revparse_single(&target, repo, "HEAD^{commit}"));
- cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL, NULL));
reflog_check(repo, "HEAD", 3, "emeric.fermas@gmail.com", exp_msg);
reflog_check(repo, "refs/heads/master", 3, "emeric.fermas@gmail.com", exp_msg);
@@ -217,7 +217,7 @@ void test_reset_hard__reflog_is_correct(void)
/* Moved branch, expect default message */
exp_msg = "reset: moving";
cl_git_pass(git_revparse_single(&target, repo, "HEAD~^{commit}"));
- cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL, NULL));
reflog_check(repo, "HEAD", 4, NULL, exp_msg);
reflog_check(repo, "refs/heads/master", 4, NULL, exp_msg);
@@ -226,7 +226,7 @@ void test_reset_hard__reflog_is_correct(void)
/* Moved branch, expect custom message */
exp_msg = "message1";
cl_git_pass(git_revparse_single(&target, repo, "HEAD~^{commit}"));
- cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, "message1"));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL, NULL, "message1"));
reflog_check(repo, "HEAD", 5, NULL, exp_msg);
reflog_check(repo, "refs/heads/master", 5, NULL, exp_msg);
}
diff --git a/tests/reset/mixed.c b/tests/reset/mixed.c
index 55b8a2f88..cb7a44d5f 100644
--- a/tests/reset/mixed.c
+++ b/tests/reset/mixed.c
@@ -29,7 +29,7 @@ void test_reset_mixed__cannot_reset_in_a_bare_repository(void)
cl_git_pass(git_revparse_single(&target, bare, KNOWN_COMMIT_IN_BARE_REPO));
- cl_assert_equal_i(GIT_EBAREREPO, git_reset(bare, target, GIT_RESET_MIXED, NULL, NULL));
+ cl_assert_equal_i(GIT_EBAREREPO, git_reset(bare, target, GIT_RESET_MIXED, NULL, NULL, NULL));
git_repository_free(bare);
}
@@ -42,7 +42,7 @@ void test_reset_mixed__resetting_refreshes_the_index_to_the_commit_tree(void)
cl_assert(status == GIT_STATUS_CURRENT);
cl_git_pass(git_revparse_single(&target, repo, "605812a"));
- cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL, NULL, NULL));
cl_git_pass(git_status_file(&status, repo, "macro_bad"));
cl_assert(status == GIT_STATUS_WT_NEW);
@@ -57,7 +57,7 @@ void test_reset_mixed__reflog_is_correct(void)
/* Branch not moving, no reflog entry */
cl_git_pass(git_revparse_single(&target, repo, "HEAD^{commit}"));
- cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL, NULL, NULL));
reflog_check(repo, "HEAD", 9, "yoram.harmelin@gmail.com", exp_msg);
reflog_check(repo, "refs/heads/master", 9, "yoram.harmelin@gmail.com", exp_msg);
@@ -67,7 +67,7 @@ void test_reset_mixed__reflog_is_correct(void)
/* Moved branch, expect default message */
exp_msg = "reset: moving";
cl_git_pass(git_revparse_single(&target, repo, "HEAD~^{commit}"));
- cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL, NULL, NULL));
reflog_check(repo, "HEAD", 10, NULL, exp_msg);
reflog_check(repo, "refs/heads/master", 10, NULL, exp_msg);
@@ -77,7 +77,7 @@ void test_reset_mixed__reflog_is_correct(void)
/* Moved branch, expect custom message */
exp_msg = "message1";
cl_git_pass(git_revparse_single(&target, repo, "HEAD~^{commit}"));
- cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL, "message1"));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL, NULL, "message1"));
reflog_check(repo, "HEAD", 11, NULL, exp_msg);
reflog_check(repo, "refs/heads/master", 11, NULL, exp_msg);
}
diff --git a/tests/reset/soft.c b/tests/reset/soft.c
index c889c0355..95b86683a 100644
--- a/tests/reset/soft.c
+++ b/tests/reset/soft.c
@@ -30,7 +30,7 @@ static void assert_reset_soft(bool should_be_detached)
cl_assert(git_repository_head_detached(repo) == should_be_detached);
- cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL, NULL));
cl_assert(git_repository_head_detached(repo) == should_be_detached);
@@ -61,7 +61,7 @@ void test_reset_soft__resetting_to_the_commit_pointed_at_by_the_Head_does_not_ch
cl_git_pass(git_revparse_single(&target, repo, raw_head_oid));
- cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL, NULL));
cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD"));
cl_git_pass(git_oid_streq(&oid, raw_head_oid));
@@ -74,7 +74,7 @@ void test_reset_soft__resetting_to_a_tag_sets_the_Head_to_the_peeled_commit(void
/* b25fa35 is a tag, pointing to another tag which points to commit e90810b */
cl_git_pass(git_revparse_single(&target, repo, "b25fa35"));
- cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL, NULL));
cl_assert(git_repository_head_detached(repo) == false);
cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD"));
@@ -86,12 +86,12 @@ void test_reset_soft__cannot_reset_to_a_tag_not_pointing_at_a_commit(void)
/* 53fc32d is the tree of commit e90810b */
cl_git_pass(git_revparse_single(&target, repo, "53fc32d"));
- cl_git_fail(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL));
+ cl_git_fail(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL, NULL));
git_object_free(target);
/* 521d87c is an annotated tag pointing to a blob */
cl_git_pass(git_revparse_single(&target, repo, "521d87c"));
- cl_git_fail(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL));
+ cl_git_fail(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL, NULL));
}
void test_reset_soft__resetting_against_an_unborn_head_repo_makes_the_head_no_longer_unborn(void)
@@ -104,7 +104,7 @@ void test_reset_soft__resetting_against_an_unborn_head_repo_makes_the_head_no_lo
cl_assert_equal_i(true, git_repository_head_unborn(repo));
- cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL, NULL));
cl_assert_equal_i(false, git_repository_head_unborn(repo));
@@ -124,7 +124,7 @@ void test_reset_soft__fails_when_merging(void)
cl_git_pass(git_revparse_single(&target, repo, KNOWN_COMMIT_IN_BARE_REPO));
- cl_assert_equal_i(GIT_EUNMERGED, git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL));
+ cl_assert_equal_i(GIT_EUNMERGED, git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL, NULL));
cl_git_pass(p_unlink(git_buf_cstr(&merge_head_path)));
git_buf_free(&merge_head_path);
@@ -152,7 +152,7 @@ void test_reset_soft__fails_when_index_contains_conflicts_independently_of_MERGE
cl_git_pass(git_reference_peel(&target, head, GIT_OBJ_COMMIT));
git_reference_free(head);
- cl_assert_equal_i(GIT_EUNMERGED, git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL));
+ cl_assert_equal_i(GIT_EUNMERGED, git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL, NULL));
}
void test_reset_soft_reflog_is_correct(void)
@@ -164,19 +164,19 @@ void test_reset_soft_reflog_is_correct(void)
/* Branch not moving, no reflog entry */
cl_git_pass(git_revparse_single(&target, repo, "HEAD^{commit}"));
- cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL, NULL));
reflog_check(repo, "HEAD", 9, "yoram.harmelin@gmail.com", exp_msg);
reflog_check(repo, "refs/heads/master", 9, "yoram.harmelin@gmail.com", exp_msg);
/* Moved branch, expect default message */
cl_git_pass(git_revparse_single(&target, repo, "HEAD~^{commit}"));
- cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL, NULL));
reflog_check(repo, "HEAD", 9, "yoram.harmelin@gmail.com", exp_msg);
reflog_check(repo, "refs/heads/master", 10, NULL, "reset: moving");
/* Moved branch, expect custom message */
cl_git_pass(git_revparse_single(&target, repo, "HEAD~^{commit}"));
- cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, "message1"));
+ cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL, NULL, "message1"));
reflog_check(repo, "HEAD", 9, "yoram.harmelin@gmail.com", exp_msg);
reflog_check(repo, "refs/heads/master", 11, NULL, "message1");
}
diff --git a/tests/resources/config/config12 b/tests/resources/config/config12
index b57a81b08..6917880b5 100644
--- a/tests/resources/config/config12
+++ b/tests/resources/config/config12
@@ -1,7 +1,13 @@
[some "section"]
test = hi ; comment
+ test2 = hello ; comment
+ test3 = welcome #comment
other = "hello! \" ; ; ; " ; more test
+ other2 = "cool! \" # # # " # more test
multi = "hi, this is a ; \
multiline comment # with ;\n special chars \
and other stuff !@#"
+ multi2 = "good, this is a ; \
+multiline comment # with ;\n special chars \
+and other stuff !@#" #^^^
back = "this is \ba phrase"
diff --git a/tests/resources/describe/.gitted/HEAD b/tests/resources/describe/.gitted/HEAD
new file mode 100644
index 000000000..cb4380516
--- /dev/null
+++ b/tests/resources/describe/.gitted/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests/resources/describe/.gitted/config b/tests/resources/describe/.gitted/config
new file mode 100644
index 000000000..454e576b9
--- /dev/null
+++ b/tests/resources/describe/.gitted/config
@@ -0,0 +1,8 @@
+[core]
+ repositoryformatversion = 0
+ filemode = false
+ bare = false
+ logallrefupdates = true
+ symlinks = false
+ ignorecase = true
+ hideDotFiles = dotGitOnly
diff --git a/tests/resources/describe/.gitted/index b/tests/resources/describe/.gitted/index
new file mode 100644
index 000000000..f5f35e26b
--- /dev/null
+++ b/tests/resources/describe/.gitted/index
Binary files differ
diff --git a/tests/resources/describe/.gitted/logs/HEAD b/tests/resources/describe/.gitted/logs/HEAD
new file mode 100644
index 000000000..fc49c6fa3
--- /dev/null
+++ b/tests/resources/describe/.gitted/logs/HEAD
@@ -0,0 +1,14 @@
+0000000000000000000000000000000000000000 108b485d8268ea595df8ffea74f0f4b186577d32 nulltoken <emeric.fermas@gmail.com> 1380209394 +0200 commit (initial): initial
+108b485d8268ea595df8ffea74f0f4b186577d32 4d6558b8fa764baeb0f19c1e857df91e0eda5a0f nulltoken <emeric.fermas@gmail.com> 1380209404 +0200 commit: second
+4d6558b8fa764baeb0f19c1e857df91e0eda5a0f b240c0fb88c5a629e00ebc1275fa1f33e364a705 nulltoken <emeric.fermas@gmail.com> 1380209414 +0200 commit: third
+b240c0fb88c5a629e00ebc1275fa1f33e364a705 81f4b1aac643e6983fab370eae8aefccecbf3a4c nulltoken <emeric.fermas@gmail.com> 1380209425 +0200 commit: A
+81f4b1aac643e6983fab370eae8aefccecbf3a4c 6126a5f9c57ebc81e64370ec3095184ad92dab1c nulltoken <emeric.fermas@gmail.com> 1380209445 +0200 commit: c
+6126a5f9c57ebc81e64370ec3095184ad92dab1c 4d6558b8fa764baeb0f19c1e857df91e0eda5a0f nulltoken <emeric.fermas@gmail.com> 1380209455 +0200 reset: moving to 4d6558b8fa764baeb0f19c1e857df91e0eda5a0f
+4d6558b8fa764baeb0f19c1e857df91e0eda5a0f 31fc9136820b507e938a9c6b88bf2c567a9f6f4b nulltoken <emeric.fermas@gmail.com> 1380209465 +0200 commit: B
+31fc9136820b507e938a9c6b88bf2c567a9f6f4b ce1c4f8b6120122e23d4442925d98c56c41917d8 nulltoken <emeric.fermas@gmail.com> 1380209486 +0200 merge c: Merge made by the 'recursive' strategy.
+ce1c4f8b6120122e23d4442925d98c56c41917d8 4d6558b8fa764baeb0f19c1e857df91e0eda5a0f nulltoken <emeric.fermas@gmail.com> 1380209486 +0200 reset: moving to 4d6558b8fa764baeb0f19c1e857df91e0eda5a0f
+4d6558b8fa764baeb0f19c1e857df91e0eda5a0f 6a12b56088706aa6c39ccd23b7c7ce60f3a0b9a1 nulltoken <emeric.fermas@gmail.com> 1380209496 +0200 commit: D
+6a12b56088706aa6c39ccd23b7c7ce60f3a0b9a1 1e016431ec7b22dd3e23f3e6f5f68f358f9227cf nulltoken <emeric.fermas@gmail.com> 1380209527 +0200 commit: another
+1e016431ec7b22dd3e23f3e6f5f68f358f9227cf a9eb02af13df030159e39f70330d5c8a47655691 nulltoken <emeric.fermas@gmail.com> 1380209547 +0200 commit: yet another
+a9eb02af13df030159e39f70330d5c8a47655691 949b98e208015bfc0e2f573debc34ae2f97a7f0e nulltoken <emeric.fermas@gmail.com> 1380209557 +0200 merge ce1c4f8b6120122e23d4442925d98c56c41917d8: Merge made by the 'recursive' strategy.
+949b98e208015bfc0e2f573debc34ae2f97a7f0e a6095f816e81f64651595d488badc42399837d6a nulltoken <emeric.fermas@gmail.com> 1380209567 +0200 commit: x
diff --git a/tests/resources/describe/.gitted/logs/refs/heads/master b/tests/resources/describe/.gitted/logs/refs/heads/master
new file mode 100644
index 000000000..fc49c6fa3
--- /dev/null
+++ b/tests/resources/describe/.gitted/logs/refs/heads/master
@@ -0,0 +1,14 @@
+0000000000000000000000000000000000000000 108b485d8268ea595df8ffea74f0f4b186577d32 nulltoken <emeric.fermas@gmail.com> 1380209394 +0200 commit (initial): initial
+108b485d8268ea595df8ffea74f0f4b186577d32 4d6558b8fa764baeb0f19c1e857df91e0eda5a0f nulltoken <emeric.fermas@gmail.com> 1380209404 +0200 commit: second
+4d6558b8fa764baeb0f19c1e857df91e0eda5a0f b240c0fb88c5a629e00ebc1275fa1f33e364a705 nulltoken <emeric.fermas@gmail.com> 1380209414 +0200 commit: third
+b240c0fb88c5a629e00ebc1275fa1f33e364a705 81f4b1aac643e6983fab370eae8aefccecbf3a4c nulltoken <emeric.fermas@gmail.com> 1380209425 +0200 commit: A
+81f4b1aac643e6983fab370eae8aefccecbf3a4c 6126a5f9c57ebc81e64370ec3095184ad92dab1c nulltoken <emeric.fermas@gmail.com> 1380209445 +0200 commit: c
+6126a5f9c57ebc81e64370ec3095184ad92dab1c 4d6558b8fa764baeb0f19c1e857df91e0eda5a0f nulltoken <emeric.fermas@gmail.com> 1380209455 +0200 reset: moving to 4d6558b8fa764baeb0f19c1e857df91e0eda5a0f
+4d6558b8fa764baeb0f19c1e857df91e0eda5a0f 31fc9136820b507e938a9c6b88bf2c567a9f6f4b nulltoken <emeric.fermas@gmail.com> 1380209465 +0200 commit: B
+31fc9136820b507e938a9c6b88bf2c567a9f6f4b ce1c4f8b6120122e23d4442925d98c56c41917d8 nulltoken <emeric.fermas@gmail.com> 1380209486 +0200 merge c: Merge made by the 'recursive' strategy.
+ce1c4f8b6120122e23d4442925d98c56c41917d8 4d6558b8fa764baeb0f19c1e857df91e0eda5a0f nulltoken <emeric.fermas@gmail.com> 1380209486 +0200 reset: moving to 4d6558b8fa764baeb0f19c1e857df91e0eda5a0f
+4d6558b8fa764baeb0f19c1e857df91e0eda5a0f 6a12b56088706aa6c39ccd23b7c7ce60f3a0b9a1 nulltoken <emeric.fermas@gmail.com> 1380209496 +0200 commit: D
+6a12b56088706aa6c39ccd23b7c7ce60f3a0b9a1 1e016431ec7b22dd3e23f3e6f5f68f358f9227cf nulltoken <emeric.fermas@gmail.com> 1380209527 +0200 commit: another
+1e016431ec7b22dd3e23f3e6f5f68f358f9227cf a9eb02af13df030159e39f70330d5c8a47655691 nulltoken <emeric.fermas@gmail.com> 1380209547 +0200 commit: yet another
+a9eb02af13df030159e39f70330d5c8a47655691 949b98e208015bfc0e2f573debc34ae2f97a7f0e nulltoken <emeric.fermas@gmail.com> 1380209557 +0200 merge ce1c4f8b6120122e23d4442925d98c56c41917d8: Merge made by the 'recursive' strategy.
+949b98e208015bfc0e2f573debc34ae2f97a7f0e a6095f816e81f64651595d488badc42399837d6a nulltoken <emeric.fermas@gmail.com> 1380209567 +0200 commit: x
diff --git a/tests/resources/describe/.gitted/objects/03/00021985931292d0611b9232e757035fefc04d b/tests/resources/describe/.gitted/objects/03/00021985931292d0611b9232e757035fefc04d
new file mode 100644
index 000000000..4b98de8fb
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/03/00021985931292d0611b9232e757035fefc04d
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/10/8b485d8268ea595df8ffea74f0f4b186577d32 b/tests/resources/describe/.gitted/objects/10/8b485d8268ea595df8ffea74f0f4b186577d32
new file mode 100644
index 000000000..0d6187b10
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/10/8b485d8268ea595df8ffea74f0f4b186577d32
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/10/bd08b099ecb79184c60183f5c94ca915f427ad b/tests/resources/describe/.gitted/objects/10/bd08b099ecb79184c60183f5c94ca915f427ad
new file mode 100644
index 000000000..3540cfae0
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/10/bd08b099ecb79184c60183f5c94ca915f427ad
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/17/8481050188cf00d7d9cd5a11e43ab8fab9294f b/tests/resources/describe/.gitted/objects/17/8481050188cf00d7d9cd5a11e43ab8fab9294f
new file mode 100644
index 000000000..f2eaf83e5
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/17/8481050188cf00d7d9cd5a11e43ab8fab9294f
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/19/1faf88a5826a99f475baaf8b13652c4e40bfe6 b/tests/resources/describe/.gitted/objects/19/1faf88a5826a99f475baaf8b13652c4e40bfe6
new file mode 100644
index 000000000..e44246b17
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/19/1faf88a5826a99f475baaf8b13652c4e40bfe6
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/1e/016431ec7b22dd3e23f3e6f5f68f358f9227cf b/tests/resources/describe/.gitted/objects/1e/016431ec7b22dd3e23f3e6f5f68f358f9227cf
new file mode 100644
index 000000000..a8769814b
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/1e/016431ec7b22dd3e23f3e6f5f68f358f9227cf
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/22/3b7836fb19fdf64ba2d3cd6173c6a283141f78 b/tests/resources/describe/.gitted/objects/22/3b7836fb19fdf64ba2d3cd6173c6a283141f78
new file mode 100644
index 000000000..faf1fbe7c
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/22/3b7836fb19fdf64ba2d3cd6173c6a283141f78
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/25/d5edf8c0ef17e8a13b8da75913dcec4ea7afc1 b/tests/resources/describe/.gitted/objects/25/d5edf8c0ef17e8a13b8da75913dcec4ea7afc1
new file mode 100644
index 000000000..3353bf9ea
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/25/d5edf8c0ef17e8a13b8da75913dcec4ea7afc1
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/2b/df67abb163a4ffb2d7f3f0880c9fe5068ce782 b/tests/resources/describe/.gitted/objects/2b/df67abb163a4ffb2d7f3f0880c9fe5068ce782
new file mode 100644
index 000000000..d0398e6e3
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/2b/df67abb163a4ffb2d7f3f0880c9fe5068ce782
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/31/fc9136820b507e938a9c6b88bf2c567a9f6f4b b/tests/resources/describe/.gitted/objects/31/fc9136820b507e938a9c6b88bf2c567a9f6f4b
new file mode 100644
index 000000000..7752a9558
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/31/fc9136820b507e938a9c6b88bf2c567a9f6f4b
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/42/8f9554a2eec22de29898819b579466af7c1583 b/tests/resources/describe/.gitted/objects/42/8f9554a2eec22de29898819b579466af7c1583
new file mode 100644
index 000000000..f27d552fd
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/42/8f9554a2eec22de29898819b579466af7c1583
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/4d/6558b8fa764baeb0f19c1e857df91e0eda5a0f b/tests/resources/describe/.gitted/objects/4d/6558b8fa764baeb0f19c1e857df91e0eda5a0f
new file mode 100644
index 000000000..311ee2fad
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/4d/6558b8fa764baeb0f19c1e857df91e0eda5a0f
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/4f/2d9ce01ad5249cabdc6565366af8aff85b1525 b/tests/resources/describe/.gitted/objects/4f/2d9ce01ad5249cabdc6565366af8aff85b1525
new file mode 100644
index 000000000..f04379f35
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/4f/2d9ce01ad5249cabdc6565366af8aff85b1525
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/52/912fbab0715dec53d43053966e78ad213ba359 b/tests/resources/describe/.gitted/objects/52/912fbab0715dec53d43053966e78ad213ba359
new file mode 100644
index 000000000..5deb7ec06
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/52/912fbab0715dec53d43053966e78ad213ba359
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/56/26abf0f72e58d7a153368ba57db4c673c0e171 b/tests/resources/describe/.gitted/objects/56/26abf0f72e58d7a153368ba57db4c673c0e171
new file mode 100644
index 000000000..4d5447467
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/56/26abf0f72e58d7a153368ba57db4c673c0e171
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/61/26a5f9c57ebc81e64370ec3095184ad92dab1c b/tests/resources/describe/.gitted/objects/61/26a5f9c57ebc81e64370ec3095184ad92dab1c
new file mode 100644
index 000000000..e71707f4b
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/61/26a5f9c57ebc81e64370ec3095184ad92dab1c
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/62/d8fe9f6db631bd3a19140699101c9e281c9f9d b/tests/resources/describe/.gitted/objects/62/d8fe9f6db631bd3a19140699101c9e281c9f9d
new file mode 100644
index 000000000..734f7dc42
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/62/d8fe9f6db631bd3a19140699101c9e281c9f9d
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/65/a91bc2262480dce4c5979519aae6668368eb4e b/tests/resources/describe/.gitted/objects/65/a91bc2262480dce4c5979519aae6668368eb4e
new file mode 100644
index 000000000..ef9f53a39
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/65/a91bc2262480dce4c5979519aae6668368eb4e
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/68/0166b6cd31f76354fee2572618e6b0142d05e6 b/tests/resources/describe/.gitted/objects/68/0166b6cd31f76354fee2572618e6b0142d05e6
new file mode 100644
index 000000000..36f198686
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/68/0166b6cd31f76354fee2572618e6b0142d05e6
@@ -0,0 +1,2 @@
+xŒK @]sŠÙ›4¤|c<Co0ŒS‚–Ö .¼½¸yy›÷:eÐ&žŽôîàH›4; Á£#rl#óÝØäÙ³8\-aŠ¤Uÿ¾ø¨µtÕÇcù3Kƒý³mýxÊ©Ò
+O«´Jï[®T¶i$WÐ6 Á8kç!¨Ô¢~U<)a \ No newline at end of file
diff --git a/tests/resources/describe/.gitted/objects/69/3a3de402bb23897ed5c931273e53c78eff0495 b/tests/resources/describe/.gitted/objects/69/3a3de402bb23897ed5c931273e53c78eff0495
new file mode 100644
index 000000000..80a08fc3a
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/69/3a3de402bb23897ed5c931273e53c78eff0495
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/6a/12b56088706aa6c39ccd23b7c7ce60f3a0b9a1 b/tests/resources/describe/.gitted/objects/6a/12b56088706aa6c39ccd23b7c7ce60f3a0b9a1
new file mode 100644
index 000000000..9c773e4b5
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/6a/12b56088706aa6c39ccd23b7c7ce60f3a0b9a1
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/6d/218e42592043041c4da016ff298cf241b86c3c b/tests/resources/describe/.gitted/objects/6d/218e42592043041c4da016ff298cf241b86c3c
new file mode 100644
index 000000000..59fc7095c
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/6d/218e42592043041c4da016ff298cf241b86c3c
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/75/bb152c600647586c226d98411b1d2f9861af5a b/tests/resources/describe/.gitted/objects/75/bb152c600647586c226d98411b1d2f9861af5a
new file mode 100644
index 000000000..a2016f45f
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/75/bb152c600647586c226d98411b1d2f9861af5a
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/81/f4b1aac643e6983fab370eae8aefccecbf3a4c b/tests/resources/describe/.gitted/objects/81/f4b1aac643e6983fab370eae8aefccecbf3a4c
new file mode 100644
index 000000000..e47f3fb85
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/81/f4b1aac643e6983fab370eae8aefccecbf3a4c
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/8e/c1d96451ff05451720e4e8968812c46b35e5e4 b/tests/resources/describe/.gitted/objects/8e/c1d96451ff05451720e4e8968812c46b35e5e4
new file mode 100644
index 000000000..432b2c193
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/8e/c1d96451ff05451720e4e8968812c46b35e5e4
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/94/9b98e208015bfc0e2f573debc34ae2f97a7f0e b/tests/resources/describe/.gitted/objects/94/9b98e208015bfc0e2f573debc34ae2f97a7f0e
new file mode 100644
index 000000000..2c7aafab5
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/94/9b98e208015bfc0e2f573debc34ae2f97a7f0e
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/9c/06d71b8406ab97537e3acdc39a2c4ade7a9411 b/tests/resources/describe/.gitted/objects/9c/06d71b8406ab97537e3acdc39a2c4ade7a9411
new file mode 100644
index 000000000..5fff6fa1f
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/9c/06d71b8406ab97537e3acdc39a2c4ade7a9411
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/a6/095f816e81f64651595d488badc42399837d6a b/tests/resources/describe/.gitted/objects/a6/095f816e81f64651595d488badc42399837d6a
new file mode 100644
index 000000000..eb9ab148a
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/a6/095f816e81f64651595d488badc42399837d6a
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/a9/e3325a07117aa5381e044a8d96c26eb30d729d b/tests/resources/describe/.gitted/objects/a9/e3325a07117aa5381e044a8d96c26eb30d729d
new file mode 100644
index 000000000..ee45b7650
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/a9/e3325a07117aa5381e044a8d96c26eb30d729d
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/a9/eb02af13df030159e39f70330d5c8a47655691 b/tests/resources/describe/.gitted/objects/a9/eb02af13df030159e39f70330d5c8a47655691
new file mode 100644
index 000000000..320161a55
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/a9/eb02af13df030159e39f70330d5c8a47655691
@@ -0,0 +1,2 @@
+xŽA
+à »öî Aý&1PJ¯òÕgc±fÑÛ×3t÷˜aà…’óÖ¤!uiqdöF/ì´ÑÃzbFLŠBÛEwé¬xsÅѤ†Ò“%0{cb$J„)ir‰F—cæŸm-Uç¾·òÂ!oȨ[jæÏã™yÛ‡Pò]jrʨe´³¼ö¡D§ýdß¹ø¢I>J[QÅhK% \ No newline at end of file
diff --git a/tests/resources/describe/.gitted/objects/aa/d8d5cef3915ab78b3227abaaac99b62db9eb54 b/tests/resources/describe/.gitted/objects/aa/d8d5cef3915ab78b3227abaaac99b62db9eb54
new file mode 100644
index 000000000..4cbaff192
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/aa/d8d5cef3915ab78b3227abaaac99b62db9eb54
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/aa/ddd4f14847e0e323924ec262c2343249a84f8b b/tests/resources/describe/.gitted/objects/aa/ddd4f14847e0e323924ec262c2343249a84f8b
new file mode 100644
index 000000000..651ec782e
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/aa/ddd4f14847e0e323924ec262c2343249a84f8b
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/b2/40c0fb88c5a629e00ebc1275fa1f33e364a705 b/tests/resources/describe/.gitted/objects/b2/40c0fb88c5a629e00ebc1275fa1f33e364a705
new file mode 100644
index 000000000..fe86e7c7c
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/b2/40c0fb88c5a629e00ebc1275fa1f33e364a705
@@ -0,0 +1,3 @@
+xŽM
+à »öî AͧQ(¥WñçÙJc,ÖÜ¿ž¡«7 ¼Øj-ƒ+E—Ñner†´ÌYè9› Xg¬•*’ «†±ï8§d´¶Áf¿
+Ad预Õ[ÊNB yíEfþ¯Öùqîûhoü†Š^â’Ñ«ÿ>žÕ—}‰­Þ¹\­P‘$~ Ø´óäÀŸ9¯ÒûµGG¬ \ No newline at end of file
diff --git a/tests/resources/describe/.gitted/objects/ce/1c4f8b6120122e23d4442925d98c56c41917d8 b/tests/resources/describe/.gitted/objects/ce/1c4f8b6120122e23d4442925d98c56c41917d8
new file mode 100644
index 000000000..408c5da33
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/ce/1c4f8b6120122e23d4442925d98c56c41917d8
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/d5/aab219a814ddbe4b3aaedf03cdea491b218ec4 b/tests/resources/describe/.gitted/objects/d5/aab219a814ddbe4b3aaedf03cdea491b218ec4
new file mode 100644
index 000000000..4512d16d6
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/d5/aab219a814ddbe4b3aaedf03cdea491b218ec4
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/f2/ad6c76f0115a6ba5b00456a849810e7ec0af20 b/tests/resources/describe/.gitted/objects/f2/ad6c76f0115a6ba5b00456a849810e7ec0af20
new file mode 100644
index 000000000..a36463115
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/f2/ad6c76f0115a6ba5b00456a849810e7ec0af20
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/f7/0f10e4db19068f79bc43844b49f3eece45c4e8 b/tests/resources/describe/.gitted/objects/f7/0f10e4db19068f79bc43844b49f3eece45c4e8
new file mode 100644
index 000000000..2e15b4fb0
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/f7/0f10e4db19068f79bc43844b49f3eece45c4e8
Binary files differ
diff --git a/tests/resources/describe/.gitted/objects/f7/19efd430d52bcfc8566a43b2eb655688d38871 b/tests/resources/describe/.gitted/objects/f7/19efd430d52bcfc8566a43b2eb655688d38871
new file mode 100644
index 000000000..b2d51d93b
--- /dev/null
+++ b/tests/resources/describe/.gitted/objects/f7/19efd430d52bcfc8566a43b2eb655688d38871
Binary files differ
diff --git a/tests/resources/describe/.gitted/refs/heads/master b/tests/resources/describe/.gitted/refs/heads/master
new file mode 100644
index 000000000..0b2a54130
--- /dev/null
+++ b/tests/resources/describe/.gitted/refs/heads/master
@@ -0,0 +1 @@
+a6095f816e81f64651595d488badc42399837d6a
diff --git a/tests/resources/describe/.gitted/refs/tags/A b/tests/resources/describe/.gitted/refs/tags/A
new file mode 100644
index 000000000..aced4fd0f
--- /dev/null
+++ b/tests/resources/describe/.gitted/refs/tags/A
@@ -0,0 +1 @@
+aaddd4f14847e0e323924ec262c2343249a84f8b
diff --git a/tests/resources/describe/.gitted/refs/tags/B b/tests/resources/describe/.gitted/refs/tags/B
new file mode 100644
index 000000000..ab1a5e69a
--- /dev/null
+++ b/tests/resources/describe/.gitted/refs/tags/B
@@ -0,0 +1 @@
+52912fbab0715dec53d43053966e78ad213ba359
diff --git a/tests/resources/describe/.gitted/refs/tags/D b/tests/resources/describe/.gitted/refs/tags/D
new file mode 100644
index 000000000..90f420854
--- /dev/null
+++ b/tests/resources/describe/.gitted/refs/tags/D
@@ -0,0 +1 @@
+10bd08b099ecb79184c60183f5c94ca915f427ad
diff --git a/tests/resources/describe/.gitted/refs/tags/R b/tests/resources/describe/.gitted/refs/tags/R
new file mode 100644
index 000000000..ef04b7c9f
--- /dev/null
+++ b/tests/resources/describe/.gitted/refs/tags/R
@@ -0,0 +1 @@
+680166b6cd31f76354fee2572618e6b0142d05e6
diff --git a/tests/resources/describe/.gitted/refs/tags/c b/tests/resources/describe/.gitted/refs/tags/c
new file mode 100644
index 000000000..650d82fdb
--- /dev/null
+++ b/tests/resources/describe/.gitted/refs/tags/c
@@ -0,0 +1 @@
+6126a5f9c57ebc81e64370ec3095184ad92dab1c
diff --git a/tests/resources/describe/.gitted/refs/tags/e b/tests/resources/describe/.gitted/refs/tags/e
new file mode 100644
index 000000000..5e88d6f13
--- /dev/null
+++ b/tests/resources/describe/.gitted/refs/tags/e
@@ -0,0 +1 @@
+1e016431ec7b22dd3e23f3e6f5f68f358f9227cf
diff --git a/tests/resources/describe/another b/tests/resources/describe/another
new file mode 100644
index 000000000..a3d00fa8a
--- /dev/null
+++ b/tests/resources/describe/another
@@ -0,0 +1 @@
+DDD
diff --git a/tests/resources/describe/file b/tests/resources/describe/file
new file mode 100644
index 000000000..fd66be08d
--- /dev/null
+++ b/tests/resources/describe/file
@@ -0,0 +1 @@
+X
diff --git a/tests/resources/describe/side b/tests/resources/describe/side
new file mode 100644
index 000000000..fd66be08d
--- /dev/null
+++ b/tests/resources/describe/side
@@ -0,0 +1 @@
+X
diff --git a/tests/resources/userdiff/.gitted/index b/tests/resources/userdiff/.gitted/index
index b69d5cfb1..548dc7bfd 100644
--- a/tests/resources/userdiff/.gitted/index
+++ b/tests/resources/userdiff/.gitted/index
Binary files differ
diff --git a/tests/resources/userdiff/.gitted/objects/09/65b377c214bbe5e0d18fcdaf556df7fa7ed7c8 b/tests/resources/userdiff/.gitted/objects/09/65b377c214bbe5e0d18fcdaf556df7fa7ed7c8
new file mode 100644
index 000000000..cbaf4c1bc
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/objects/09/65b377c214bbe5e0d18fcdaf556df7fa7ed7c8
Binary files differ
diff --git a/tests/resources/userdiff/.gitted/objects/0c/20ef1409ae1df4d5a76cdbd98d5c33ccdb6bcc b/tests/resources/userdiff/.gitted/objects/0c/20ef1409ae1df4d5a76cdbd98d5c33ccdb6bcc
new file mode 100644
index 000000000..fa149da98
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/objects/0c/20ef1409ae1df4d5a76cdbd98d5c33ccdb6bcc
Binary files differ
diff --git a/tests/resources/userdiff/.gitted/objects/39/ea75107a09091ba54ff86fcc780b59477e42cd b/tests/resources/userdiff/.gitted/objects/39/ea75107a09091ba54ff86fcc780b59477e42cd
new file mode 100644
index 000000000..748373621
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/objects/39/ea75107a09091ba54ff86fcc780b59477e42cd
Binary files differ
diff --git a/tests/resources/userdiff/.gitted/objects/3c/c08384deae5957247bc36776ab626cc9e0582b b/tests/resources/userdiff/.gitted/objects/3c/c08384deae5957247bc36776ab626cc9e0582b
new file mode 100644
index 000000000..29b72fbbc
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/objects/3c/c08384deae5957247bc36776ab626cc9e0582b
Binary files differ
diff --git a/tests/resources/userdiff/.gitted/objects/46/8d6f2afc940e14c76347fa9af26e429a3c9044 b/tests/resources/userdiff/.gitted/objects/46/8d6f2afc940e14c76347fa9af26e429a3c9044
new file mode 100644
index 000000000..5fc839170
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/objects/46/8d6f2afc940e14c76347fa9af26e429a3c9044
Binary files differ
diff --git a/tests/resources/userdiff/.gitted/objects/53/917973acfe0111f93c2cfaacf854be245880e8 b/tests/resources/userdiff/.gitted/objects/53/917973acfe0111f93c2cfaacf854be245880e8
new file mode 100644
index 000000000..debf7e40f
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/objects/53/917973acfe0111f93c2cfaacf854be245880e8
Binary files differ
diff --git a/tests/resources/userdiff/.gitted/objects/63/1d44e0c72e8cd1b594fa11d7d1ee8a6d67ff67 b/tests/resources/userdiff/.gitted/objects/63/1d44e0c72e8cd1b594fa11d7d1ee8a6d67ff67
new file mode 100644
index 000000000..e8b884cd5
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/objects/63/1d44e0c72e8cd1b594fa11d7d1ee8a6d67ff67
Binary files differ
diff --git a/tests/resources/userdiff/.gitted/objects/f3/be389d351e4bcc6dcc4b5fe22134ef0f63f8bd b/tests/resources/userdiff/.gitted/objects/f3/be389d351e4bcc6dcc4b5fe22134ef0f63f8bd
new file mode 100644
index 000000000..cfbef992d
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/objects/f3/be389d351e4bcc6dcc4b5fe22134ef0f63f8bd
Binary files differ
diff --git a/tests/resources/userdiff/after/file.javascript b/tests/resources/userdiff/after/file.javascript
index 7cd3c5a8a..53917973a 100644
--- a/tests/resources/userdiff/after/file.javascript
+++ b/tests/resources/userdiff/after/file.javascript
@@ -1,108 +1,108 @@
-/*
- Some code extracted from https://github.com/julianlloyd/scrollReveal.js
- which happens to be a trending Javascript repo with an MIT license at
- the time I was working on Javascript userdiff support in libgit2
+define(function(require, exports, module) {
+ module.exports = Player;
- I extracted just some of the code, so I suspect this is no longer valid
- Javascript code, but it contains enough example patterns to work.
-*/
-;(function (window) {
+ var Key = require("./key")
+ , Direction = require("./direction");
- 'use strict';
+ function Player(game) {
+ this.game = game;
- var docElem = window.document.documentElement;
+ this.image = new Image("./assets/fighter.png");
+ this.game.resources.add(this.image);
- function getViewportH () {
- var client = docElem['clientHeight'],
- inner = window['innerHeight'],
- sample = window['otherProperty'];
+ this.x = 0;
+ this.y = 0;
- return (client < inner) ? inner : client;
- }
-
- function getOffset (el) {
- var offsetTop = 0,
- offsetLeft = 0;
+ this.pixelX = 10;
+ this.pixelY = 10;
- do {
- if (!isNaN(el.offsetTop)) {
- offsetTop += el.offsetTop + 1;
- }
- if (!isNaN(el.offsetLeft)) {
- offsetLeft += el.offsetLeft;
- }
- } while (el = el.offsetParent)
-
- return {
- top: offsetTop,
- left: offsetLeft
- }
+ this.animationStep = 0;
}
- function isElementInViewport (el, h) {
- var scrolled = window.pageYOffset,
- viewed = scrolled + getViewportH(),
- elTop = getOffset(el).top,
- elBottom = elTop + el.offsetHeight,
- h = h || 0;
-
- return (elTop + el.offsetHeight * h) <= viewed && (elBottom) >= scrolled;
- }
-
- scrollReveal.prototype = {
-
- _init: function () {
-
- var self = this;
-
- this.elems = Array.prototype.slice.call(docElem.querySelectorAll('[data-scrollReveal]'));
- this.scrolled = false;
+ Player.prototype.update = function() {
+ if (!this.isWalking()) {
+ this.handleInput();
+ }
- this.elems.forEach(function (el, i) {
- self.animate(el);
- });
+ if (this.isWalking()) {
+ // Increase the animation step.
+ this.animationStep = ++this.animationStep % 60;
- var scrollHandler = function () {
- if (!self.scrolled) {
- self.scrolled = true;
- setTimeout(function () {
- self._scrollPage();
- }, 61);
- }
- };
+ if (this.x * 32 > this.pixelX) {
+ this.pixelX++;
+ } else if (this.x * 32 < this.pixelX) {
+ this.pixelX--;
+ }
- var resizeHandler = function () {
- function delayed() {
- self._scrollPage();
- self.resizeTimeout = null;
- }
- if (self.resizeTimeout) {
- clearTimeout(self.resizeTimeout);
+ if (this.y * 32 > this.pixelY) {
+ this.pixelY++;
+ } else if (this.y * 32 < this.pixelY) {
+ this.pixelY--;
+ }
+ } else {
+ // Reset the animation step.
+ this.animationStep = 0;
+ }
+ };
+
+ Player.prototype.handleInput = function() {
+ var keyboard = this.game.keyboard, finalAction, action, inputs = {
+ 'moveDown': keyboard.isDown(Key.DOWN),
+ 'moveUp': keyboard.isDown(Key.UP),
+ 'moveLeft': keyboard.isDown(Key.LEFT),
+ 'moveRight': keyboard.isDown(Key.RIGHT)
+ };
+
+ for (action in inputs) {
+ if (inputs[action]) {
+ if (!finalAction || inputs[finalAction] < inputs[action]) {
+ finalAction = action;
}
- self.resizeTimeout = setTimeout(delayed, 200);
- };
-
- window.addEventListener('scroll', scrollHandler, false);
- window.addEventListener('resize', resizeHandler, false);
- },
-
- /*=============================================================================*/
-
- _scrollPage: function () {
- var self = this;
-
- this.elems.forEach(function (el, i) {
- if (isElementInViewport(el, self.options.viewportFactor)) {
- self.animate(el);
- }
- });
- this.scrolled = false;
- this.tested = true;
- },
- }; // end scrollReveal.prototype
+ }
+ }
- document.addEventListener("DOMContentLoaded", function (evt) {
- window.scrollReveal = new scrollReveal();
- });
+ this[finalAction] && this[finalAction]();
+ };
+
+ Player.prototype.isWalking = function() {
+ return this.x * 32 != this.pixelX || this.y * 32 != this.pixelY;
+ };
+
+ Player.prototype.moveDown = function() {
+ this.y += 1;
+ this.direction = Direction.DOWN;
+ };
+
+ Player.prototype.moveUp = function() {
+ this.y -= 1;
+ this.direction = Direction.UP;
+ };
+
+ Player.prototype.moveLeft = function() {
+ this.x -= 5;
+ this.direction = Direction.LEFT;
+ };
+
+ Player.prototype.moveRight = function() {
+ this.x += 1;
+ this.direction = Direction.RIGHT;
+ };
+
+ Player.prototype.draw = function(context) {
+ var offsetX = Math.floor(this.animationStep / 15) * 32, offsetY = 0;
+
+ switch(this.direction) {
+ case Direction.UP:
+ offsetY = 48 * 3;
+ break;
+ case Direction.RIGHT:
+ offsetY = 48 * 2;
+ break;
+ case Direction.LEFT:
+ offsetY = 48;
+ break;
+ }
-})(window);
+ context.drawImage(this.image.data, offsetX, offsetY, 32, 48, this.pixelX, this.pixelY, 32, 48);
+ };
+});
diff --git a/tests/resources/userdiff/before/file.javascript b/tests/resources/userdiff/before/file.javascript
index b9f1286e5..0965b377c 100644
--- a/tests/resources/userdiff/before/file.javascript
+++ b/tests/resources/userdiff/before/file.javascript
@@ -1,109 +1,109 @@
-/*
- Some code extracted from https://github.com/julianlloyd/scrollReveal.js
- which happens to be a trending Javascript repo with an MIT license at
- the time I was working on Javascript userdiff support in libgit2
+define(function(require, exports, module) {
+ module.exports = Player;
- I extracted just some of the code, so I suspect this is no longer valid
- Javascript code, but it contains enough example patterns to work.
-*/
-;(function (window) {
+ var Key = require("./key")
+ , Direction = require("./direction")
+ , Image = require("./image");
- 'use strict';
+ function Player(game) {
+ this.game = game;
- var docElem = window.document.documentElement;
+ this.image = new Image("./assets/fighter.png");
+ this.game.resources.add(this.image);
- function getViewportH () {
- var client = docElem['clientHeight'],
- inner = window['innerHeight'];
+ this.x = 0;
+ this.y = 0;
- return (client < inner) ? inner : client;
- }
-
- function getOffset (el) {
- var offsetTop = 0,
- offsetLeft = 0;
+ this.pixelX = 0;
+ this.pixelY = 0;
- do {
- if (!isNaN(el.offsetTop)) {
- offsetTop += el.offsetTop;
- }
- if (!isNaN(el.offsetLeft)) {
- offsetLeft += el.offsetLeft;
- }
- } while (el = el.offsetParent)
-
- return {
- top: offsetTop,
- left: offsetLeft
- }
+ this.animationStep = 0;
}
- function isElementInViewport (el, h) {
- var scrolled = window.pageYOffset,
- viewed = scrolled + getViewportH(),
- elH = el.offsetHeight,
- elTop = getOffset(el).top,
- elBottom = elTop + elH,
- h = h || 0;
-
- return (elTop + elH * h) <= viewed && (elBottom) >= scrolled;
- }
-
- scrollReveal.prototype = {
-
- _init: function () {
-
- var self = this;
-
- this.elems = Array.prototype.slice.call(docElem.querySelectorAll('[data-scrollReveal]'));
- this.scrolled = false;
+ Player.prototype.update = function() {
+ if (!this.isWalking()) {
+ this.handleInput();
+ }
- // Initialize all scrollreveals, triggering all
- // reveals on visible elements.
- this.elems.forEach(function (el, i) {
- self.animate(el);
- });
+ if (this.isWalking()) {
+ // Increase the animation step.
+ this.animationStep = ++this.animationStep % 60;
- var scrollHandler = function () {
- if (!self.scrolled) {
- self.scrolled = true;
- setTimeout(function () {
- self._scrollPage();
- }, 60);
- }
- };
+ if (this.x * 32 > this.pixelX) {
+ this.pixelX++;
+ } else if (this.x * 32 < this.pixelX) {
+ this.pixelX--;
+ }
- var resizeHandler = function () {
- function delayed() {
- self._scrollPage();
- self.resizeTimeout = null;
- }
- if (self.resizeTimeout) {
- clearTimeout(self.resizeTimeout);
+ if (this.y * 32 > this.pixelY) {
+ this.pixelY++;
+ } else if (this.y * 32 < this.pixelY) {
+ this.pixelY--;
+ }
+ } else {
+ // Reset the animation step.
+ this.animationStep = 0;
+ }
+ };
+
+ Player.prototype.handleInput = function() {
+ var keyboard = this.game.keyboard, finalAction, action, inputs = {
+ 'moveDown': keyboard.isDown(Key.DOWN),
+ 'moveUp': keyboard.isDown(Key.UP),
+ 'moveLeft': keyboard.isDown(Key.LEFT),
+ 'moveRight': keyboard.isDown(Key.RIGHT)
+ };
+
+ for (action in inputs) {
+ if (inputs[action]) {
+ if (!finalAction || inputs[finalAction] < inputs[action]) {
+ finalAction = action;
}
- self.resizeTimeout = setTimeout(delayed, 200);
- };
-
- window.addEventListener('scroll', scrollHandler, false);
- window.addEventListener('resize', resizeHandler, false);
- },
-
- /*=============================================================================*/
-
- _scrollPage: function () {
- var self = this;
-
- this.elems.forEach(function (el, i) {
- if (isElementInViewport(el, self.options.viewportFactor)) {
- self.animate(el);
- }
- });
- this.scrolled = false;
- },
- }; // end scrollReveal.prototype
+ }
+ }
- document.addEventListener("DOMContentLoaded", function (evt) {
- window.scrollReveal = new scrollReveal();
- });
+ this[finalAction] && this[finalAction]();
+ };
+
+ Player.prototype.isWalking = function() {
+ return this.x * 32 != this.pixelX || this.y * 32 != this.pixelY;
+ };
+
+ Player.prototype.moveDown = function() {
+ this.y += 1;
+ this.direction = Direction.DOWN;
+ };
+
+ Player.prototype.moveUp = function() {
+ this.y -= 1;
+ this.direction = Direction.UP;
+ };
+
+ Player.prototype.moveLeft = function() {
+ this.x -= 1;
+ this.direction = Direction.LEFT;
+ };
+
+ Player.prototype.moveRight = function() {
+ this.x += 1;
+ this.direction = Direction.RIGHT;
+ };
+
+ Player.prototype.draw = function(context) {
+ var offsetX = Math.floor(this.animationStep / 15) * 32, offsetY = 0;
+
+ switch(this.direction) {
+ case Direction.UP:
+ offsetY = 48 * 3;
+ break;
+ case Direction.RIGHT:
+ offsetY = 48 * 2;
+ break;
+ case Direction.LEFT:
+ offsetY = 48;
+ break;
+ }
-})(window);
+ context.drawImage(this.image.data, offsetX, offsetY, 32, 48, this.pixelX, this.pixelY - 16, 32, 48);
+ };
+});
diff --git a/tests/resources/userdiff/expected/driver/diff.javascript b/tests/resources/userdiff/expected/driver/diff.javascript
index 4e65d0746..4cefe5cff 100644
--- a/tests/resources/userdiff/expected/driver/diff.javascript
+++ b/tests/resources/userdiff/expected/driver/diff.javascript
@@ -1,40 +1,27 @@
diff --git a/files/file.javascript b/files/file.javascript
-index b9f1286..7cd3c5a 100644
+index 0965b37..5391797 100644
--- a/files/file.javascript
+++ b/files/file.javascript
-@@ -16,3 +16,4 @@ function getViewportH ()
- var client = docElem['clientHeight'],
-- inner = window['innerHeight'];
-+ inner = window['innerHeight'],
-+ sample = window['otherProperty'];
+@@ -4,4 +4,3 @@ function(require, exports, module)
+ var Key = require("./key")
+- , Direction = require("./direction")
+- , Image = require("./image");
++ , Direction = require("./direction");
-@@ -27,3 +28,3 @@ function getOffset (el)
- if (!isNaN(el.offsetTop)) {
-- offsetTop += el.offsetTop;
-+ offsetTop += el.offsetTop + 1;
- }
-@@ -43,8 +44,7 @@ function isElementInViewport (el, h)
- viewed = scrolled + getViewportH(),
-- elH = el.offsetHeight,
- elTop = getOffset(el).top,
-- elBottom = elTop + elH,
-+ elBottom = elTop + el.offsetHeight,
- h = h || 0;
+@@ -16,4 +15,4 @@ function Player(game)
-- return (elTop + elH * h) <= viewed && (elBottom) >= scrolled;
-+ return (elTop + el.offsetHeight * h) <= viewed && (elBottom) >= scrolled;
- }
-@@ -60,4 +60,2 @@ _init: function ()
+- this.pixelX = 0;
+- this.pixelY = 0;
++ this.pixelX = 10;
++ this.pixelY = 10;
-- // Initialize all scrollreveals, triggering all
-- // reveals on visible elements.
- this.elems.forEach(function (el, i) {
-@@ -71,3 +69,3 @@ var scrollHandler = function ()
- self._scrollPage();
-- }, 60);
-+ }, 61);
- }
-@@ -101,2 +99,3 @@ _scrollPage: function ()
- this.scrolled = false;
-+ this.tested = true;
- },
+@@ -82,3 +81,3 @@ Player.prototype.moveUp = function()
+ Player.prototype.moveLeft = function() {
+- this.x -= 1;
++ this.x -= 5;
+ this.direction = Direction.LEFT;
+@@ -106,3 +105,3 @@ Player.prototype.draw = function(context)
+
+- context.drawImage(this.image.data, offsetX, offsetY, 32, 48, this.pixelX, this.pixelY - 16, 32, 48);
++ context.drawImage(this.image.data, offsetX, offsetY, 32, 48, this.pixelX, this.pixelY, 32, 48);
+ };
diff --git a/tests/resources/userdiff/expected/nodriver/diff.javascript b/tests/resources/userdiff/expected/nodriver/diff.javascript
index 69afe4fd8..4bbd54764 100644
--- a/tests/resources/userdiff/expected/nodriver/diff.javascript
+++ b/tests/resources/userdiff/expected/nodriver/diff.javascript
@@ -1,40 +1,27 @@
diff --git a/files/file.javascript b/files/file.javascript
-index b9f1286..7cd3c5a 100644
+index 0965b37..5391797 100644
--- a/files/file.javascript
+++ b/files/file.javascript
-@@ -16,3 +16,4 @@
- var client = docElem['clientHeight'],
-- inner = window['innerHeight'];
-+ inner = window['innerHeight'],
-+ sample = window['otherProperty'];
+@@ -4,4 +4,3 @@ define(function(require, exports, module) {
+ var Key = require("./key")
+- , Direction = require("./direction")
+- , Image = require("./image");
++ , Direction = require("./direction");
-@@ -27,3 +28,3 @@
- if (!isNaN(el.offsetTop)) {
-- offsetTop += el.offsetTop;
-+ offsetTop += el.offsetTop + 1;
- }
-@@ -43,8 +44,7 @@
- viewed = scrolled + getViewportH(),
-- elH = el.offsetHeight,
- elTop = getOffset(el).top,
-- elBottom = elTop + elH,
-+ elBottom = elTop + el.offsetHeight,
- h = h || 0;
+@@ -16,4 +15,4 @@ define(function(require, exports, module) {
-- return (elTop + elH * h) <= viewed && (elBottom) >= scrolled;
-+ return (elTop + el.offsetHeight * h) <= viewed && (elBottom) >= scrolled;
- }
-@@ -60,4 +60,2 @@
+- this.pixelX = 0;
+- this.pixelY = 0;
++ this.pixelX = 10;
++ this.pixelY = 10;
-- // Initialize all scrollreveals, triggering all
-- // reveals on visible elements.
- this.elems.forEach(function (el, i) {
-@@ -71,3 +69,3 @@
- self._scrollPage();
-- }, 60);
-+ }, 61);
- }
-@@ -101,2 +99,3 @@
- this.scrolled = false;
-+ this.tested = true;
- },
+@@ -82,3 +81,3 @@ define(function(require, exports, module) {
+ Player.prototype.moveLeft = function() {
+- this.x -= 1;
++ this.x -= 5;
+ this.direction = Direction.LEFT;
+@@ -106,3 +105,3 @@ define(function(require, exports, module) {
+
+- context.drawImage(this.image.data, offsetX, offsetY, 32, 48, this.pixelX, this.pixelY - 16, 32, 48);
++ context.drawImage(this.image.data, offsetX, offsetY, 32, 48, this.pixelX, this.pixelY, 32, 48);
+ };
diff --git a/tests/resources/userdiff/files/file.javascript b/tests/resources/userdiff/files/file.javascript
index 7cd3c5a8a..53917973a 100644
--- a/tests/resources/userdiff/files/file.javascript
+++ b/tests/resources/userdiff/files/file.javascript
@@ -1,108 +1,108 @@
-/*
- Some code extracted from https://github.com/julianlloyd/scrollReveal.js
- which happens to be a trending Javascript repo with an MIT license at
- the time I was working on Javascript userdiff support in libgit2
+define(function(require, exports, module) {
+ module.exports = Player;
- I extracted just some of the code, so I suspect this is no longer valid
- Javascript code, but it contains enough example patterns to work.
-*/
-;(function (window) {
+ var Key = require("./key")
+ , Direction = require("./direction");
- 'use strict';
+ function Player(game) {
+ this.game = game;
- var docElem = window.document.documentElement;
+ this.image = new Image("./assets/fighter.png");
+ this.game.resources.add(this.image);
- function getViewportH () {
- var client = docElem['clientHeight'],
- inner = window['innerHeight'],
- sample = window['otherProperty'];
+ this.x = 0;
+ this.y = 0;
- return (client < inner) ? inner : client;
- }
-
- function getOffset (el) {
- var offsetTop = 0,
- offsetLeft = 0;
+ this.pixelX = 10;
+ this.pixelY = 10;
- do {
- if (!isNaN(el.offsetTop)) {
- offsetTop += el.offsetTop + 1;
- }
- if (!isNaN(el.offsetLeft)) {
- offsetLeft += el.offsetLeft;
- }
- } while (el = el.offsetParent)
-
- return {
- top: offsetTop,
- left: offsetLeft
- }
+ this.animationStep = 0;
}
- function isElementInViewport (el, h) {
- var scrolled = window.pageYOffset,
- viewed = scrolled + getViewportH(),
- elTop = getOffset(el).top,
- elBottom = elTop + el.offsetHeight,
- h = h || 0;
-
- return (elTop + el.offsetHeight * h) <= viewed && (elBottom) >= scrolled;
- }
-
- scrollReveal.prototype = {
-
- _init: function () {
-
- var self = this;
-
- this.elems = Array.prototype.slice.call(docElem.querySelectorAll('[data-scrollReveal]'));
- this.scrolled = false;
+ Player.prototype.update = function() {
+ if (!this.isWalking()) {
+ this.handleInput();
+ }
- this.elems.forEach(function (el, i) {
- self.animate(el);
- });
+ if (this.isWalking()) {
+ // Increase the animation step.
+ this.animationStep = ++this.animationStep % 60;
- var scrollHandler = function () {
- if (!self.scrolled) {
- self.scrolled = true;
- setTimeout(function () {
- self._scrollPage();
- }, 61);
- }
- };
+ if (this.x * 32 > this.pixelX) {
+ this.pixelX++;
+ } else if (this.x * 32 < this.pixelX) {
+ this.pixelX--;
+ }
- var resizeHandler = function () {
- function delayed() {
- self._scrollPage();
- self.resizeTimeout = null;
- }
- if (self.resizeTimeout) {
- clearTimeout(self.resizeTimeout);
+ if (this.y * 32 > this.pixelY) {
+ this.pixelY++;
+ } else if (this.y * 32 < this.pixelY) {
+ this.pixelY--;
+ }
+ } else {
+ // Reset the animation step.
+ this.animationStep = 0;
+ }
+ };
+
+ Player.prototype.handleInput = function() {
+ var keyboard = this.game.keyboard, finalAction, action, inputs = {
+ 'moveDown': keyboard.isDown(Key.DOWN),
+ 'moveUp': keyboard.isDown(Key.UP),
+ 'moveLeft': keyboard.isDown(Key.LEFT),
+ 'moveRight': keyboard.isDown(Key.RIGHT)
+ };
+
+ for (action in inputs) {
+ if (inputs[action]) {
+ if (!finalAction || inputs[finalAction] < inputs[action]) {
+ finalAction = action;
}
- self.resizeTimeout = setTimeout(delayed, 200);
- };
-
- window.addEventListener('scroll', scrollHandler, false);
- window.addEventListener('resize', resizeHandler, false);
- },
-
- /*=============================================================================*/
-
- _scrollPage: function () {
- var self = this;
-
- this.elems.forEach(function (el, i) {
- if (isElementInViewport(el, self.options.viewportFactor)) {
- self.animate(el);
- }
- });
- this.scrolled = false;
- this.tested = true;
- },
- }; // end scrollReveal.prototype
+ }
+ }
- document.addEventListener("DOMContentLoaded", function (evt) {
- window.scrollReveal = new scrollReveal();
- });
+ this[finalAction] && this[finalAction]();
+ };
+
+ Player.prototype.isWalking = function() {
+ return this.x * 32 != this.pixelX || this.y * 32 != this.pixelY;
+ };
+
+ Player.prototype.moveDown = function() {
+ this.y += 1;
+ this.direction = Direction.DOWN;
+ };
+
+ Player.prototype.moveUp = function() {
+ this.y -= 1;
+ this.direction = Direction.UP;
+ };
+
+ Player.prototype.moveLeft = function() {
+ this.x -= 5;
+ this.direction = Direction.LEFT;
+ };
+
+ Player.prototype.moveRight = function() {
+ this.x += 1;
+ this.direction = Direction.RIGHT;
+ };
+
+ Player.prototype.draw = function(context) {
+ var offsetX = Math.floor(this.animationStep / 15) * 32, offsetY = 0;
+
+ switch(this.direction) {
+ case Direction.UP:
+ offsetY = 48 * 3;
+ break;
+ case Direction.RIGHT:
+ offsetY = 48 * 2;
+ break;
+ case Direction.LEFT:
+ offsetY = 48;
+ break;
+ }
-})(window);
+ context.drawImage(this.image.data, offsetX, offsetY, 32, 48, this.pixelX, this.pixelY, 32, 48);
+ };
+});
diff --git a/tests/revert/workdir.c b/tests/revert/workdir.c
index e3d7e968a..0121429d8 100644
--- a/tests/revert/workdir.c
+++ b/tests/revert/workdir.c
@@ -48,7 +48,7 @@ void test_revert_workdir__automerge(void)
git_oid_fromstr(&head_oid, "72333f47d4e83616630ff3b0ffe4c0faebcc3c45");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
git_oid_fromstr(&revert_oid, "d1d403d22cbe24592d725f442835cf46fe60c8ac");
cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
@@ -81,7 +81,7 @@ void test_revert_workdir__conflicts(void)
cl_git_pass(git_repository_head(&head_ref, repo));
cl_git_pass(git_reference_peel((git_object **)&head, head_ref, GIT_OBJ_COMMIT));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
cl_git_pass(git_revert(repo, commit, NULL));
@@ -144,7 +144,7 @@ void test_revert_workdir__orphan(void)
git_oid_fromstr(&head_oid, "39467716290f6df775a91cdb9a4eb39295018145");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
git_oid_fromstr(&revert_oid, "ebb03002cee5d66c7732dd06241119fe72ab96a5");
cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
@@ -179,7 +179,7 @@ void test_revert_workdir__again(void)
cl_git_pass(git_repository_head(&head_ref, repo));
cl_git_pass(git_reference_peel((git_object **)&orig_head, head_ref, GIT_OBJ_COMMIT));
- cl_git_pass(git_reset(repo, (git_object *)orig_head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)orig_head, GIT_RESET_HARD, NULL, NULL, NULL));
cl_git_pass(git_revert(repo, orig_head, NULL));
@@ -227,7 +227,7 @@ void test_revert_workdir__again_after_automerge(void)
git_oid_fromstr(&head_oid, "72333f47d4e83616630ff3b0ffe4c0faebcc3c45");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
git_oid_fromstr(&revert_oid, "d1d403d22cbe24592d725f442835cf46fe60c8ac");
cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
@@ -275,7 +275,7 @@ void test_revert_workdir__again_after_edit(void)
cl_git_pass(git_oid_fromstr(&orig_head_oid, "399fb3aba3d9d13f7d40a9254ce4402067ef3149"));
cl_git_pass(git_commit_lookup(&orig_head, repo, &orig_head_oid));
- cl_git_pass(git_reset(repo, (git_object *)orig_head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)orig_head, GIT_RESET_HARD, NULL, NULL, NULL));
cl_git_pass(git_oid_fromstr(&revert_oid, "2d440f2b3147d3dc7ad1085813478d6d869d5a4d"));
cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
@@ -326,7 +326,7 @@ void test_revert_workdir__again_after_edit_two(void)
cl_git_pass(git_oid_fromstr(&head_commit_oid, "e34ef1afe54eb526fd92eec66084125f340f1d65"));
cl_git_pass(git_commit_lookup(&head_commit, repo, &head_commit_oid));
- cl_git_pass(git_reset(repo, (git_object *)head_commit, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head_commit, GIT_RESET_HARD, NULL, NULL, NULL));
cl_git_pass(git_oid_fromstr(&revert_commit_oid, "71eb9c2b53dbbf3c45fb28b27c850db4b7fb8011"));
cl_git_pass(git_commit_lookup(&revert_commit, repo, &revert_commit_oid));
@@ -379,7 +379,7 @@ void test_revert_workdir__conflict_use_ours(void)
git_oid_fromstr(&head_oid, "72333f47d4e83616630ff3b0ffe4c0faebcc3c45");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
git_oid_fromstr(&revert_oid, "d1d403d22cbe24592d725f442835cf46fe60c8ac");
cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
@@ -415,7 +415,7 @@ void test_revert_workdir__rename_1_of_2(void)
git_oid_fromstr(&head_oid, "cef56612d71a6af8d8015691e4865f7fece905b5");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
git_oid_fromstr(&revert_oid, "55568c8de5322ff9a95d72747a239cdb64a19965");
cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
@@ -449,7 +449,7 @@ void test_revert_workdir__rename(void)
git_oid_fromstr(&head_oid, "55568c8de5322ff9a95d72747a239cdb64a19965");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
git_oid_fromstr(&revert_oid, "0aa8c7e40d342fff78d60b29a4ba8e993ed79c51");
cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
@@ -478,7 +478,7 @@ void test_revert_workdir__head(void)
/* HEAD is 2d440f2b3147d3dc7ad1085813478d6d869d5a4d */
cl_git_pass(git_repository_head(&head, repo));
cl_git_pass(git_reference_peel((git_object **)&commit, head, GIT_OBJ_COMMIT));
- cl_git_pass(git_reset(repo, (git_object *)commit, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)commit, GIT_RESET_HARD, NULL, NULL, NULL));
cl_git_pass(git_revert(repo, commit, NULL));
cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
@@ -515,7 +515,7 @@ void test_revert_workdir__merge_fails_without_mainline_specified(void)
git_oid_fromstr(&head_oid, "5acdc74af27172ec491d213ee36cea7eb9ef2579");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
cl_must_fail(git_revert(repo, head, NULL));
cl_assert(!git_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
@@ -542,7 +542,7 @@ void test_revert_workdir__merge_first_parent(void)
git_oid_fromstr(&head_oid, "5acdc74af27172ec491d213ee36cea7eb9ef2579");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
cl_git_pass(git_revert(repo, head, &opts));
@@ -567,7 +567,7 @@ void test_revert_workdir__merge_second_parent(void)
git_oid_fromstr(&head_oid, "5acdc74af27172ec491d213ee36cea7eb9ef2579");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
- cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL, NULL, NULL));
cl_git_pass(git_revert(repo, head, &opts));
diff --git a/tests/revwalk/basic.c b/tests/revwalk/basic.c
index b015db18b..ff05fa249 100644
--- a/tests/revwalk/basic.c
+++ b/tests/revwalk/basic.c
@@ -49,12 +49,12 @@ static const int result_bytes = 24;
static int get_commit_index(git_oid *raw_oid)
{
int i;
- char oid[40];
+ char oid[GIT_OID_HEXSZ];
git_oid_fmt(oid, raw_oid);
for (i = 0; i < commit_count; ++i)
- if (memcmp(oid, commit_ids[i], 40) == 0)
+ if (memcmp(oid, commit_ids[i], GIT_OID_HEXSZ) == 0)
return i;
return -1;
@@ -74,9 +74,9 @@ static int test_walk_only(git_revwalk *walk,
while (git_revwalk_next(&oid, walk) == 0) {
result_array[i++] = get_commit_index(&oid);
/*{
- char str[41];
+ char str[GIT_OID_HEXSZ+1];
git_oid_fmt(str, &oid);
- str[40] = 0;
+ str[GIT_OID_HEXSZ] = 0;
printf(" %d) %s\n", i, str);
}*/
}
diff --git a/tests/revwalk/mergebase.c b/tests/revwalk/mergebase.c
index 677e1a1b6..fa974eb9a 100644
--- a/tests/revwalk/mergebase.c
+++ b/tests/revwalk/mergebase.c
@@ -127,7 +127,7 @@ void test_revwalk_mergebase__prefer_youngest_merge_base(void)
{
git_oid result, one, two, expected;
- cl_git_pass(git_oid_fromstr(&one, "a4a7dce85cf63874e984719f4fdd239f5145052f "));
+ cl_git_pass(git_oid_fromstr(&one, "a4a7dce85cf63874e984719f4fdd239f5145052f"));
cl_git_pass(git_oid_fromstr(&two, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
cl_git_pass(git_oid_fromstr(&expected, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
@@ -140,7 +140,7 @@ void test_revwalk_mergebase__multiple_merge_bases(void)
git_oid one, two, expected1, expected2;
git_oidarray result = {NULL, 0};
- cl_git_pass(git_oid_fromstr(&one, "a4a7dce85cf63874e984719f4fdd239f5145052f "));
+ cl_git_pass(git_oid_fromstr(&one, "a4a7dce85cf63874e984719f4fdd239f5145052f"));
cl_git_pass(git_oid_fromstr(&two, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
cl_git_pass(git_oid_fromstr(&expected1, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
cl_git_pass(git_oid_fromstr(&expected2, "9fd738e8f7967c078dceed8190330fc8648ee56a"));
@@ -153,6 +153,26 @@ void test_revwalk_mergebase__multiple_merge_bases(void)
git_oidarray_free(&result);
}
+void test_revwalk_mergebase__multiple_merge_bases_many_commits(void)
+{
+ git_oid expected1, expected2;
+ git_oidarray result = {NULL, 0};
+
+ git_oid *input = git__malloc(sizeof(git_oid) * 2);
+
+ cl_git_pass(git_oid_fromstr(&input[0], "a4a7dce85cf63874e984719f4fdd239f5145052f"));
+ cl_git_pass(git_oid_fromstr(&input[1], "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
+ cl_git_pass(git_oid_fromstr(&expected1, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
+ cl_git_pass(git_oid_fromstr(&expected2, "9fd738e8f7967c078dceed8190330fc8648ee56a"));
+
+ cl_git_pass(git_merge_bases_many(&result, _repo, 2, input));
+ cl_assert_equal_i(2, result.count);
+ cl_assert_equal_oid(&expected1, &result.ids[0]);
+ cl_assert_equal_oid(&expected2, &result.ids[1]);
+
+ git_oidarray_free(&result);
+}
+
void test_revwalk_mergebase__no_off_by_one_missing(void)
{
git_oid result, one, two;
diff --git a/tests/stash/save.c b/tests/stash/save.c
index 3b301bfc0..a5bdd0cbe 100644
--- a/tests/stash/save.c
+++ b/tests/stash/save.c
@@ -368,6 +368,23 @@ void test_stash_save__including_untracked_without_any_untracked_file_creates_an_
assert_object_oid("stash^3^{tree}", EMPTY_TREE, GIT_OBJ_TREE);
}
+void test_stash_save__ignored_directory(void)
+{
+ cl_git_pass(p_mkdir("stash/ignored_directory", 0777));
+ cl_git_pass(p_mkdir("stash/ignored_directory/sub", 0777));
+ cl_git_mkfile("stash/ignored_directory/sub/some_file", "stuff");
+
+ assert_status(repo, "ignored_directory/sub/some_file", GIT_STATUS_WT_NEW);
+ cl_git_pass(git_ignore_add_rule(repo, "ignored_directory/"));
+ assert_status(repo, "ignored_directory/sub/some_file", GIT_STATUS_IGNORED);
+
+ cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED | GIT_STASH_INCLUDE_IGNORED));
+
+ cl_assert(!git_path_exists("stash/ignored_directory/sub/some_file"));
+ cl_assert(!git_path_exists("stash/ignored_directory/sub"));
+ cl_assert(!git_path_exists("stash/ignored_directory"));
+}
+
void test_stash_save__skip_submodules(void)
{
git_repository *untracked_repo;
diff --git a/tests/threads/basic.c b/tests/threads/basic.c
index a329ee7f9..eb15293c7 100644
--- a/tests/threads/basic.c
+++ b/tests/threads/basic.c
@@ -1,5 +1,6 @@
#include "clar_libgit2.h"
+#include "thread_helpers.h"
#include "cache.h"
@@ -34,3 +35,16 @@ void test_threads_basic__multiple_init(void)
cl_git_pass(git_repository_open(&nested_repo, cl_fixture("testrepo.git")));
git_repository_free(nested_repo);
}
+
+static void *set_error(void *dummy)
+{
+ giterr_set(GITERR_INVALID, "oh no, something happened!\n");
+
+ return dummy;
+}
+
+/* Set errors so we can check that we free it */
+void test_threads_basic__set_error(void)
+{
+ run_in_parallel(1, 4, set_error, NULL, NULL);
+}
diff --git a/tests/transport/register.c b/tests/transport/register.c
index 937194c1c..ea917d5d3 100644
--- a/tests/transport/register.c
+++ b/tests/transport/register.c
@@ -47,6 +47,7 @@ void test_transport_register__custom_transport_ssh(void)
cl_git_fail_with(git_transport_new(&transport, NULL, "git@somehost:somepath"), -1);
#else
cl_git_pass(git_transport_new(&transport, NULL, "git@somehost:somepath"));
+ transport->free(transport);
#endif
cl_git_pass(git_transport_register("ssh", dummy_transport, NULL));
@@ -62,5 +63,6 @@ void test_transport_register__custom_transport_ssh(void)
cl_git_fail_with(git_transport_new(&transport, NULL, "git@somehost:somepath"), -1);
#else
cl_git_pass(git_transport_new(&transport, NULL, "git@somehost:somepath"));
+ transport->free(transport);
#endif
}