]> git.proxmox.com Git - libgit2.git/commitdiff
New upstream version 1.4.3+dfsg.1
authorMohammed Bilal <mdbilal@disroot.org>
Thu, 5 May 2022 10:45:21 +0000 (10:45 +0000)
committerMohammed Bilal <mdbilal@disroot.org>
Thu, 5 May 2022 10:45:21 +0000 (10:45 +0000)
621 files changed:
.github/release.yml [new file with mode: 0644]
.github/workflows/main.yml
.github/workflows/nightly.yml
.vscode/launch.json
.vscode/tasks.json
CMakeLists.txt
COPYING
README.md
ci/test.sh
cmake/AddCFlagIfSupported.cmake
cmake/DefaultCFlags.cmake [new file with mode: 0644]
cmake/EnableWarnings.cmake
cmake/FindCoreFoundation.cmake
cmake/FindGSSAPI.cmake
cmake/FindGSSFramework.cmake
cmake/FindHTTPParser.cmake [new file with mode: 0644]
cmake/FindHTTP_Parser.cmake [deleted file]
cmake/FindIconv.cmake
cmake/FindLibSSH2.cmake
cmake/FindPCRE.cmake
cmake/FindPCRE2.cmake
cmake/FindPkgLibraries.cmake
cmake/FindSecurity.cmake
cmake/FindStatNsec.cmake
cmake/Findfutimens.cmake
cmake/FindmbedTLS.cmake
cmake/IdeSplitSources.cmake
cmake/PkgBuildConfig.cmake
cmake/SanitizeBool.cmake
cmake/SelectGSSAPI.cmake
cmake/SelectHTTPParser.cmake [new file with mode: 0644]
cmake/SelectHTTPSBackend.cmake
cmake/SelectHashes.cmake
cmake/SelectRegex.cmake [new file with mode: 0644]
cmake/SelectSSH.cmake [new file with mode: 0644]
cmake/SelectWinHTTP.cmake [new file with mode: 0644]
cmake/SelectZlib.cmake [new file with mode: 0644]
docs/api-stability.md [new file with mode: 0644]
docs/buffers.md [new file with mode: 0644]
docs/changelog.md
docs/contributing.md
docs/error-handling.md
docs/fuzzing.md
docs/release.md
docs/threading.md
examples/CMakeLists.txt
examples/add.c
examples/blame.c
examples/commit.c
examples/common.h
examples/diff.c
examples/index-pack.c
examples/remote.c
examples/status.c
fuzzers/CMakeLists.txt
fuzzers/commit_graph_fuzzer.c
fuzzers/config_file_fuzzer.c
fuzzers/corpora/midx/666a779eed16847c6930a71c0547a34e52db409e [new file with mode: 0644]
fuzzers/corpora/objects/blob
fuzzers/download_refs_fuzzer.c
fuzzers/midx_fuzzer.c
fuzzers/objects_fuzzer.c
fuzzers/packfile_fuzzer.c
fuzzers/patch_parse_fuzzer.c
fuzzers/standalone_driver.c
fuzzers/standalone_driver.h [new file with mode: 0644]
include/git2/apply.h
include/git2/attr.h
include/git2/blame.h
include/git2/blob.h
include/git2/branch.h
include/git2/buffer.h
include/git2/cert.h
include/git2/checkout.h
include/git2/clone.h
include/git2/commit.h
include/git2/common.h
include/git2/config.h
include/git2/credential.h
include/git2/credential_helpers.h
include/git2/deprecated.h
include/git2/describe.h
include/git2/diff.h
include/git2/email.h
include/git2/errors.h
include/git2/filter.h
include/git2/graph.h
include/git2/ignore.h
include/git2/index.h
include/git2/indexer.h
include/git2/merge.h
include/git2/message.h
include/git2/object.h
include/git2/odb.h
include/git2/odb_backend.h
include/git2/pack.h
include/git2/patch.h
include/git2/pathspec.h
include/git2/proxy.h
include/git2/rebase.h
include/git2/refdb.h
include/git2/reflog.h
include/git2/refs.h
include/git2/remote.h
include/git2/repository.h
include/git2/reset.h
include/git2/revparse.h
include/git2/revwalk.h
include/git2/signature.h
include/git2/stash.h
include/git2/status.h
include/git2/submodule.h
include/git2/sys/commit_graph.h
include/git2/sys/odb_backend.h
include/git2/sys/remote.h [new file with mode: 0644]
include/git2/sys/stream.h
include/git2/sys/transport.h
include/git2/tag.h
include/git2/tree.h
include/git2/types.h
include/git2/version.h
include/git2/worktree.h
package.json
src/CMakeLists.txt
src/annotated_commit.h
src/apply.c
src/apply.h
src/attr.c
src/attr_file.c
src/attr_file.h
src/attrcache.c
src/blame_git.c
src/blob.c
src/blob.h
src/branch.c
src/branch.h
src/buf.c [new file with mode: 0644]
src/buf.h [new file with mode: 0644]
src/buffer.c [deleted file]
src/buffer.h [deleted file]
src/cc-compat.h
src/checkout.c
src/cherrypick.c
src/clone.c
src/commit.c
src/commit.h
src/commit_graph.c
src/commit_graph.h
src/commit_list.c
src/common.h
src/config.c
src/config.h
src/config_file.c
src/config_mem.c
src/config_parse.c
src/crlf.c
src/date.c
src/date.h [new file with mode: 0644]
src/describe.c
src/diff.c
src/diff.h
src/diff_driver.c
src/diff_driver.h
src/diff_file.c
src/diff_generate.c
src/diff_generate.h
src/diff_print.c
src/diff_stats.c
src/diff_stats.h [new file with mode: 0644]
src/diff_tform.c
src/diff_xdiff.c
src/email.c
src/email.h
src/errors.c
src/features.h.in
src/fetch.c
src/fetch.h
src/fetchhead.c
src/filebuf.c
src/filebuf.h
src/filter.c
src/filter.h
src/fs_path.c [new file with mode: 0644]
src/fs_path.h [new file with mode: 0644]
src/futils.c
src/futils.h
src/hash.c
src/hash.h
src/hash/sha1.h
src/hash/sha1/collisiondetect.c
src/hash/sha1/common_crypto.c
src/hash/sha1/generic.c
src/hash/sha1/mbedtls.c
src/hash/sha1/openssl.c
src/hash/sha1/sha1dc/sha1.c
src/hash/sha1/win32.c
src/ident.c
src/ignore.c
src/ignore.h
src/index.c
src/index.h
src/indexer.c
src/iterator.c
src/iterator.h
src/khash.h
src/libgit2.c
src/mailmap.c
src/merge.c
src/merge.h
src/merge_driver.c
src/merge_file.c
src/message.c
src/message.h [deleted file]
src/midx.c
src/midx.h
src/mwindow.c
src/net.c
src/net.h
src/netops.c
src/netops.h
src/notes.c
src/object.c
src/object.h
src/odb.c
src/odb.h
src/odb_loose.c
src/odb_mempack.c
src/odb_pack.c
src/oid.c
src/oid.h
src/pack-objects.c
src/pack-objects.h
src/pack.c
src/patch.c
src/patch.h
src/patch_generate.c
src/patch_generate.h
src/patch_parse.c
src/path.c
src/path.h
src/pathspec.c
src/pathspec.h
src/posix.c
src/posix.h
src/pqueue.h
src/proxy.c
src/proxy.h
src/push.c
src/push.h
src/rand.c [new file with mode: 0644]
src/rand.h [new file with mode: 0644]
src/reader.c
src/reader.h
src/rebase.c
src/refdb_fs.c
src/refs.c
src/refs.h
src/refspec.c
src/refspec.h
src/regexp.c
src/remote.c
src/remote.h
src/repository.c
src/repository.h
src/reset.c
src/revert.c
src/revparse.c
src/revwalk.c
src/signature.c
src/signature.h
src/sortedcache.c
src/sortedcache.h
src/stash.c
src/status.c
src/str.c [new file with mode: 0644]
src/str.h [new file with mode: 0644]
src/streams/mbedtls.c
src/streams/openssl_dynamic.h
src/submodule.c
src/submodule.h
src/sysdir.c
src/sysdir.h
src/tag.c
src/thread.h
src/threadstate.c
src/threadstate.h
src/trace.c
src/trace.h
src/trailer.c
src/transaction.c
src/transport.c
src/transports/auth.c
src/transports/auth.h
src/transports/auth_negotiate.c
src/transports/auth_ntlm.c
src/transports/auth_ntlm.h
src/transports/git.c
src/transports/http.c
src/transports/http.h
src/transports/httpclient.c
src/transports/local.c
src/transports/smart.c
src/transports/smart.h
src/transports/smart_pkt.c
src/transports/smart_protocol.c
src/transports/ssh.c
src/transports/winhttp.c
src/tree-cache.c
src/tree-cache.h
src/tree.c
src/tree.h
src/unix/map.c
src/unix/posix.h
src/unix/realpath.c
src/util.c
src/util.h
src/vector.h
src/win32/findfile.c
src/win32/findfile.h
src/win32/path_w32.c
src/win32/path_w32.h
src/win32/posix.h
src/win32/posix_w32.c
src/win32/w32_buffer.c
src/win32/w32_buffer.h
src/win32/w32_leakcheck.c
src/worktree.c
src/worktree.h
src/xdiff/git-xdiff.h [new file with mode: 0644]
src/xdiff/xdiff.h
src/xdiff/xdiffi.c
src/xdiff/xemit.c
src/xdiff/xhistogram.c
src/xdiff/xinclude.h
src/xdiff/xmerge.c
src/xdiff/xpatience.c
src/xdiff/xprepare.c
src/xdiff/xutils.c
src/zstream.c
src/zstream.h
tests/CMakeLists.txt
tests/README.md
tests/apply/fromdiff.c
tests/apply/fromfile.c
tests/apply/partial.c
tests/attr/repo.c
tests/buf/basic.c [deleted file]
tests/buf/oom.c [deleted file]
tests/buf/percent.c [deleted file]
tests/buf/quote.c [deleted file]
tests/buf/splice.c [deleted file]
tests/checkout/checkout_helpers.c
tests/checkout/checkout_helpers.h
tests/checkout/conflict.c
tests/checkout/crlf.c
tests/checkout/head.c
tests/checkout/icase.c
tests/checkout/index.c
tests/checkout/nasty.c
tests/checkout/tree.c
tests/checkout/typechange.c
tests/cherrypick/bare.c
tests/cherrypick/workdir.c
tests/clar.h
tests/clar/summary.h
tests/clar_libgit2.c
tests/clar_libgit2.h
tests/clar_libgit2_timer.c
tests/clar_libgit2_timer.h
tests/clar_libgit2_trace.c
tests/clone/local.c
tests/clone/nonetwork.c
tests/commit/commit.c
tests/commit/parse.c
tests/commit/write.c
tests/config/conditionals.c
tests/config/config_helpers.c
tests/config/configlevel.c
tests/config/global.c
tests/config/include.c
tests/config/multivar.c
tests/config/new.c
tests/config/read.c
tests/config/readonly.c
tests/config/stress.c
tests/config/write.c
tests/core/buf.c [new file with mode: 0644]
tests/core/buffer.c [deleted file]
tests/core/copy.c
tests/core/dirent.c
tests/core/env.c
tests/core/filebuf.c
tests/core/futils.c
tests/core/gitstr.c [new file with mode: 0644]
tests/core/iconv.c
tests/core/init.c
tests/core/link.c
tests/core/mkdir.c
tests/core/oid.c
tests/core/path.c
tests/core/posix.c
tests/core/rmdir.c
tests/core/sha1.c
tests/core/sortedcache.c
tests/core/stat.c
tests/core/structinit.c
tests/core/useragent.c
tests/core/utf8.c
tests/core/zstream.c
tests/date/date.c
tests/date/rfc2822.c
tests/describe/describe.c
tests/describe/describe_helpers.c
tests/describe/describe_helpers.h
tests/diff/binary.c
tests/diff/blob.c
tests/diff/drivers.c
tests/diff/externalmodifications.c [new file with mode: 0644]
tests/diff/format_email.c
tests/diff/parse.c
tests/diff/patch.c
tests/diff/rename.c
tests/diff/stats.c
tests/diff/submodules.c
tests/diff/tree.c
tests/diff/workdir.c
tests/email/create.c
tests/email/create.c.bak [new file with mode: 0644]
tests/fetch/local.c [new file with mode: 0644]
tests/fetchhead/fetchhead_data.h
tests/fetchhead/nonetwork.c
tests/filter/crlf.c
tests/filter/custom_helpers.c
tests/filter/custom_helpers.h
tests/filter/file.c
tests/filter/query.c
tests/filter/stream.c
tests/filter/systemattrs.c
tests/filter/wildcard.c
tests/generate.py
tests/graph/commit_graph.c [deleted file]
tests/graph/commitgraph.c [new file with mode: 0644]
tests/graph/reachable_from_any.c
tests/headertest.c [new file with mode: 0644]
tests/ignore/path.c
tests/ignore/status.c
tests/index/crlf.c
tests/index/filemodes.c
tests/index/nsec.c
tests/index/racy.c
tests/index/tests.c
tests/iterator/index.c
tests/iterator/tree.c
tests/iterator/workdir.c
tests/mailmap/parsing.c
tests/main.c
tests/merge/analysis.c
tests/merge/conflict_data.h
tests/merge/driver.c
tests/merge/files.c
tests/merge/merge_helpers.c
tests/merge/merge_helpers.h
tests/merge/trees/automerge.c
tests/merge/trees/modeconflict.c
tests/merge/trees/renames.c
tests/merge/trees/trivial.c
tests/merge/trees/whitespace.c
tests/merge/workdir/dirty.c
tests/merge/workdir/recursive.c
tests/merge/workdir/renames.c
tests/merge/workdir/setup.c
tests/merge/workdir/simple.c
tests/merge/workdir/submodules.c
tests/merge/workdir/trivial.c
tests/message/trailer.c
tests/network/fetchlocal.c
tests/network/remote/defaultbranch.c
tests/network/remote/local.c
tests/network/remote/push.c
tests/network/remote/remotes.c
tests/network/url/parse.c
tests/network/url/redirect.c
tests/network/url/scp.c [new file with mode: 0644]
tests/network/url/valid.c [new file with mode: 0644]
tests/notes/notes.c
tests/notes/notesref.c
tests/object/blob/filter.c
tests/object/blob/fromstream.c
tests/object/blob/write.c
tests/object/commit/commitstagedfile.c
tests/object/lookup.c
tests/object/message.c
tests/object/raw/convert.c
tests/object/raw/hash.c
tests/object/raw/short.c
tests/object/raw/write.c
tests/object/tag/write.c
tests/object/tree/read.c
tests/object/tree/write.c
tests/object/validate.c [new file with mode: 0644]
tests/odb/alternates.c
tests/odb/backend/backend_helpers.c
tests/odb/backend/backend_helpers.h
tests/odb/backend/multiple.c
tests/odb/backend/nonrefreshing.c
tests/odb/backend/refreshing.c [new file with mode: 0644]
tests/odb/backend/simple.c
tests/odb/emptyobjects.c
tests/odb/foreach.c
tests/odb/freshen.c
tests/odb/largefiles.c
tests/odb/loose.c
tests/online/clone.c
tests/online/customcert.c
tests/online/fetch.c
tests/online/fetchhead.c
tests/online/push.c
tests/online/push_util.c
tests/online/remotes.c
tests/pack/filelimit.c
tests/pack/indexer.c
tests/pack/midx.c
tests/pack/packbuilder.c
tests/patch/parse.c
tests/patch/patch_common.h
tests/patch/print.c
tests/path/core.c
tests/path/dotgit.c
tests/path/win32.c
tests/rebase/iterator.c
tests/rebase/merge.c
tests/rebase/sign.c
tests/rebase/submodule.c
tests/refs/basic.c
tests/refs/branches/create.c
tests/refs/branches/delete.c
tests/refs/branches/iterator.c
tests/refs/branches/move.c
tests/refs/branches/name.c
tests/refs/branches/remote.c
tests/refs/branches/upstreamname.c
tests/refs/crashes.c
tests/refs/delete.c
tests/refs/foreachglob.c
tests/refs/iterator.c
tests/refs/pack.c
tests/refs/read.c
tests/refs/ref_helpers.c
tests/refs/reflog/messages.c
tests/refs/reflog/reflog.c
tests/refs/reflog/reflog_helpers.c
tests/refs/reflog/reflog_helpers.h
tests/refs/rename.c
tests/refs/revparse.c
tests/refs/shorthand.c
tests/refs/tags/name.c
tests/remote/fetch.c
tests/remote/httpproxy.c
tests/remote/insteadof.c
tests/repo/config.c
tests/repo/discover.c
tests/repo/env.c
tests/repo/hashfile.c
tests/repo/init.c
tests/repo/message.c
tests/repo/open.c
tests/repo/repo_helpers.c
tests/repo/reservedname.c
tests/repo/setters.c
tests/repo/state.c
tests/repo/template.c
tests/reset/hard.c
tests/reset/mixed.c
tests/reset/soft.c
tests/resources/config/config22 [new file with mode: 0644]
tests/resources/peeled.git/packed-refs
tests/resources/renames/.gitted/objects/41/a766bb079e18ff6a24571831bd751168799a02 [new file with mode: 0644]
tests/resources/renames/.gitted/objects/ba/8b004914491b129b4feff51b5fd8553b8e8156 [new file with mode: 0644]
tests/resources/renames/.gitted/objects/e5/6d39ca6d946331aa79c9c443d46c8a6ed4f550 [new file with mode: 0644]
tests/resources/renames/.gitted/refs/heads/case-insensitive-status [new file with mode: 0644]
tests/resources/testrepo.git/logs/refs/heads/with-empty-log [new file with mode: 0644]
tests/resources/testrepo.git/packed-refs
tests/resources/testrepo.git/refs/heads/with-empty-log [new file with mode: 0644]
tests/resources/testrepo/.gitted/packed-refs
tests/resources/testrepo2/.gitted/config
tests/resources/testrepo2/.gitted/packed-refs
tests/revert/bare.c
tests/revert/workdir.c
tests/stash/apply.c
tests/stash/drop.c
tests/stash/save.c
tests/status/renames.c
tests/status/submodules.c
tests/status/worktree.c
tests/str/basic.c [new file with mode: 0644]
tests/str/oom.c [new file with mode: 0644]
tests/str/percent.c [new file with mode: 0644]
tests/str/quote.c [new file with mode: 0644]
tests/str/splice.c [new file with mode: 0644]
tests/stress/diff.c
tests/submodule/add.c
tests/submodule/escape.c
tests/submodule/init.c
tests/submodule/inject_option.c
tests/submodule/lookup.c
tests/submodule/modify.c
tests/submodule/nosubs.c
tests/submodule/open.c
tests/submodule/repository_init.c
tests/submodule/status.c
tests/submodule/submodule_helpers.c
tests/submodule/update.c
tests/valgrind-supp-mac.txt
tests/win32/forbidden.c
tests/win32/longpath.c
tests/win32/systemdir.c [new file with mode: 0644]
tests/worktree/merge.c
tests/worktree/open.c
tests/worktree/refs.c
tests/worktree/submodule.c
tests/worktree/worktree.c

diff --git a/.github/release.yml b/.github/release.yml
new file mode 100644 (file)
index 0000000..c3c8da2
--- /dev/null
@@ -0,0 +1,20 @@
+changelog:
+  categories:
+  - title: New features
+    labels:
+    - feature
+  - title: Bug fixes
+    labels:
+    - bug
+  - title: Code cleanups
+    labels:
+    - cleanup
+  - title: CI improvements
+    labels:
+    - build
+  - title: Documentation improvements
+    labels:
+    - documentation
+  - title: Other changes
+    labels:
+      - '*'
index 572f025444a23879cbb2fe3cf4ab21a305c9ee33..74bab53f3082ad6cca03f7650b119c566a324924 100644 (file)
@@ -22,8 +22,7 @@ jobs:
   # with both the sha and "latest" so that the subsequent runs need not
   # know the sha.  Only do this on CI builds (when the event is a "push")
   # because PR builds from forks lack permission to write packages.
-  build_containers:
-    name: Create docker image
+  containers:
     strategy:
       matrix:
         container:
@@ -46,6 +45,7 @@ jobs:
         - name: centos7
         - name: centos8
     runs-on: ubuntu-latest
+    name: "Create container: ${{ matrix.container.name }}"
     steps:
     - name: Check out repository
       uses: actions/checkout@v2
@@ -80,76 +80,75 @@ jobs:
   # and their details.  Then we build either in a docker container (Linux)
   # or on the actual hosts (macOS, Windows).
   build:
-    name: Build
-    needs: [ build_containers ]
+    needs: [ containers ]
     strategy:
       matrix:
         platform:
-        - # Xenial, GCC, OpenSSL
+        - name: "Linux (Xenial, GCC, OpenSSL)"
           container:
             name: xenial
           env:
             CC: gcc
             CMAKE_GENERATOR: Ninja
-            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DDEBUG_STRICT_ALLOC=ON -DDEBUG_STRICT_OPEN=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON -DDEBUG_STRICT_ALLOC=ON -DDEBUG_STRICT_OPEN=ON
           os: ubuntu-latest
-        - # Xenial, GCC, mbedTLS
+        - name: Linux (Xenial, GCC, mbedTLS)
           container:
             name: xenial
           env:
             CC: gcc
             CMAKE_GENERATOR: Ninja
-            CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
           os: ubuntu-latest
-        - # Xenial, Clang, OpenSSL
+        - name: "Linux (Xenial, Clang, OpenSSL)"
           container:
             name: xenial
           env:
             CC: clang
             CMAKE_GENERATOR: Ninja
-            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
           os: ubuntu-latest
-        - # Xenial, Clang, mbedTLS
+        - name: "Linux (Xenial, Clang, mbedTLS)"
           container:
             name: xenial
           env:
             CC: clang
-            CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
             CMAKE_GENERATOR: Ninja
           os: ubuntu-latest
-        - # Focal, Clang 10, mbedTLS, MemorySanitizer
+        - name: "Linux (MemorySanitizer)"
           container:
             name: focal
           env:
             CC: clang-10
             CFLAGS: -fsanitize=memory -fsanitize-memory-track-origins=2 -fsanitize-blacklist=/home/libgit2/source/script/sanitizers.supp -fno-optimize-sibling-calls -fno-omit-frame-pointer
-            CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local/msan -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
+            CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local/msan -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON
             CMAKE_GENERATOR: Ninja
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
             ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
             UBSAN_OPTIONS: print_stacktrace=1
           os: ubuntu-latest
-        - # Focal, Clang 10, OpenSSL, UndefinedBehaviorSanitizer
+        - name: "Linux (UndefinedBehaviorSanitizer)"
           container:
             name: focal
           env:
             CC: clang-10
             CFLAGS: -fsanitize=undefined,nullability -fno-sanitize-recover=undefined,nullability -fsanitize-blacklist=/home/libgit2/source/script/sanitizers.supp -fno-optimize-sibling-calls -fno-omit-frame-pointer
-            CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local -DUSE_HTTPS=OpenSSL -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
+            CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local -DUSE_HTTPS=OpenSSL -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON
             CMAKE_GENERATOR: Ninja
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
             ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
             UBSAN_OPTIONS: print_stacktrace=1
           os: ubuntu-latest
-        - # Focal, Clang 10, OpenSSL, ThreadSanitizer
+        - name: "Linux (ThreadSanitizer)"
           container:
             name: focal
           env:
             CC: clang-10
             CFLAGS: -fsanitize=thread -fno-optimize-sibling-calls -fno-omit-frame-pointer
-            CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local -DUSE_HTTPS=OpenSSL -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
+            CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local -DUSE_HTTPS=OpenSSL -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON
             CMAKE_GENERATOR: Ninja
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
@@ -157,7 +156,7 @@ jobs:
             UBSAN_OPTIONS: print_stacktrace=1
             TSAN_OPTIONS: suppressions=/home/libgit2/source/script/thread-sanitizer.supp second_deadlock_stack=1
           os: ubuntu-latest
-        - # macOS
+        - name: "macOS"
           os: macos-10.15
           env:
             CC: clang
@@ -166,7 +165,7 @@ jobs:
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
           setup-script: osx
-        - # Windows amd64 Visual Studio
+        - name: "Windows (amd64, Visual Studio)"
           os: windows-2019
           env:
             ARCH: amd64
@@ -174,7 +173,7 @@ jobs:
             CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
-        - # Windows x86 Visual Studio
+        - name: "Windows (x86, Visual Studio)"
           os: windows-2019
           env:
             ARCH: x86
@@ -182,7 +181,7 @@ jobs:
             CMAKE_OPTIONS: -A Win32 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
-        - # Windows amd64 mingw
+        - name: "Windows (amd64, mingw)"
           os: windows-2019
           setup-script: mingw
           env:
@@ -193,7 +192,7 @@ jobs:
             BUILD_PATH: D:\Temp\mingw64\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
-        - # Windows x86 mingw
+        - name: "Windows (x86, mingw)"
           os: windows-2019
           setup-script: mingw
           env:
@@ -207,6 +206,7 @@ jobs:
       fail-fast: false
     env: ${{ matrix.platform.env }}
     runs-on: ${{ matrix.platform.os }}
+    name: "Build: ${{ matrix.platform.name }}"
     steps:
     - name: Check out repository
       uses: actions/checkout@v2
@@ -269,7 +269,7 @@ jobs:
   # published to our documentation site.
   documentation:
     name: Generate documentation
-    needs: [build_containers]
+    needs: [ containers ]
     runs-on: ubuntu-latest
     steps:
     - name: Check out repository
@@ -300,4 +300,4 @@ jobs:
     - name: Push documentation branch
       working-directory: source
       run: git push origin gh-pages
-      if: github.event_name != 'pull_request' && github.repository == 'libgit2/libgit2'
+      if: github.event_name == 'push' && github.repository == 'libgit2/libgit2'
index 47ebf464d11ab0727ba87c23712f09227f9b05e9..5513d5b435f1bcdb513bf05008b3b7d75a9e1995 100644 (file)
@@ -15,71 +15,71 @@ jobs:
   # targets and their details.  Then we build either in a docker container
   # (Linux) or on the actual hosts (macOS, Windows).
   build:
-    name: Build
     strategy:
       matrix:
         platform:
-        - # Xenial, GCC, OpenSSL
+        - name: Linux (Xenial, GCC, OpenSSL)
           container:
             name: xenial
           env:
             CC: gcc
             CMAKE_GENERATOR: Ninja
-            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
           os: ubuntu-latest
-        - # Xenial, GCC, mbedTLS
+        - name: "Linux (Xenial, GCC, mbedTLS)"
           container:
             name: xenial
           env:
             CC: gcc
             CMAKE_GENERATOR: Ninja
-            CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
           os: ubuntu-latest
-        - # Xenial, Clang, OpenSSL
+        - name: "Linux (Xenial, Clang, OpenSSL)"
           container:
             name: xenial
           env:
             CC: clang
             CMAKE_GENERATOR: Ninja
-            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
           os: ubuntu-latest
-        - # Xenial, Clang, mbedTLS
+        - name: "Linux (Xenial, Clang, mbedTLS)"
           container:
             name: xenial
           env:
             CC: clang
-            CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
             CMAKE_GENERATOR: Ninja
           os: ubuntu-latest
-        - # Xenial, GCC, thread-free
+        - name: "Linux (no threads)"
           container:
             name: xenial
           env:
             CC: gcc
-            CMAKE_OPTIONS: -DTHREADSAFE=OFF -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DTHREADSAFE=OFF -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
             CMAKE_GENERATOR: Ninja
           os: ubuntu-latest
-        - # Xenial, Clang, OpenSSL (dynamically loaded)
+        - name: "Linux (dynamically-loaded OpenSSL)"
           container:
             name: xenial
           env:
             CC: clang
-            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL-Dynamic -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL-Dynamic -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
             CMAKE_GENERATOR: Ninja
           os: ubuntu-latest
-        - # Focal, Clang 10, mbedTLS, MemorySanitizer
+        - name: "Linux (MemorySanitizer)"
           container:
             name: focal
           env:
             CC: clang-10
             CFLAGS: -fsanitize=memory -fsanitize-memory-track-origins=2 -fsanitize-blacklist=/home/libgit2/source/script/sanitizers.supp -fno-optimize-sibling-calls -fno-omit-frame-pointer
-            CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local/msan -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
+            CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local/msan -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON
             CMAKE_GENERATOR: Ninja
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
             ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
+            UBSAN_OPTIONS: print_stacktrace=1
           os: ubuntu-latest
-        - # Focal, Clang 10, OpenSSL, UndefinedBehaviorSanitizer
+        - name: "Linux (UndefinedBehaviorSanitizer)"
           container:
             name: focal
           env:
@@ -91,7 +91,7 @@ jobs:
             SKIP_NEGOTIATE_TESTS: true
             ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
           os: ubuntu-latest
-        - # Focal, Clang 10, OpenSSL, ThreadSanitizer
+        - name: "Linux (ThreadSanitizer)"
           container:
             name: focal
           env:
@@ -104,7 +104,7 @@ jobs:
             ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
             TSAN_OPTIONS: suppressions=/home/libgit2/source/script/thread-sanitizer.supp second_deadlock_stack=1
           os: ubuntu-latest
-        - # Focal, Clang 10, mmap emulation (NO_MMAP)
+        - name: "Linux (no mmap)"
           container:
             name: focal
           env:
@@ -115,23 +115,23 @@ jobs:
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
           os: ubuntu-latest
-        - # CentOS 7
+        - name: "Linux (CentOS 7)"
           container:
             name: centos7
           env:
-            CMAKE_OPTIONS: -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
             PKG_CONFIG_PATH: /usr/local/lib/pkgconfig
             SKIP_NEGOTIATE_TESTS: true
           os: ubuntu-latest
-        - # CentOS 7, OpenSSL (dynamically loaded)
+        - name: "Linux (CentOS 7, dynamically-loaded OpenSSL)"
           container:
             name: centos7
           env:
-            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL-Dynamic -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL-Dynamic -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
             PKG_CONFIG_PATH: /usr/local/lib/pkgconfig
             SKIP_NEGOTIATE_TESTS: true
           os: ubuntu-latest
-        - # CentOS 8
+        - name: "Linux (CentOS 8)"
           container:
             name: centos8
           env:
@@ -140,7 +140,7 @@ jobs:
             SKIP_NEGOTIATE_TESTS: true
             SKIP_SSH_TESTS: true
           os: ubuntu-latest
-        - # CentOS 8, OpenSSL (dynamically loaded)
+        - name: "Linux (CentOS 8, dynamically-loaded OpenSSL)"
           container:
             name: centos8
           env:
@@ -149,7 +149,7 @@ jobs:
             SKIP_NEGOTIATE_TESTS: true
             SKIP_SSH_TESTS: true
           os: ubuntu-latest
-        - # macOS
+        - name: "macOS"
           os: macos-10.15
           env:
             CC: clang
@@ -158,7 +158,7 @@ jobs:
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
           setup-script: osx
-        - # Windows amd64 Visual Studio
+        - name: "Windows (amd64, Visual Studio)"
           os: windows-2019
           env:
             ARCH: amd64
@@ -166,7 +166,7 @@ jobs:
             CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
-        - # Windows amd64 Visual Studio (NO_MMAP)
+        - name: "Windows (no mmap)"
           os: windows-2019
           env:
             ARCH: amd64
@@ -175,7 +175,7 @@ jobs:
             CMAKE_OPTIONS: -A x64 -DDEPRECATE_HARD=ON
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
-        - # Windows x86 Visual Studio
+        - name: "Windows (x86, Visual Studio)"
           os: windows-2019
           env:
             ARCH: x86
@@ -183,7 +183,7 @@ jobs:
             CMAKE_OPTIONS: -A Win32 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
-        - # Windows amd64 mingw
+        - name: "Windows (amd64, mingw)"
           os: windows-2019
           setup-script: mingw
           env:
@@ -194,7 +194,7 @@ jobs:
             BUILD_PATH: D:\Temp\mingw64\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
-        - # Windows x86 mingw
+        - name: "Windows (x86, mingw)"
           os: windows-2019
           setup-script: mingw
           env:
@@ -205,17 +205,17 @@ jobs:
             BUILD_PATH: D:\Temp\mingw32\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin
             SKIP_SSH_TESTS: true
             SKIP_NEGOTIATE_TESTS: true
-        - # Bionic, GCC, OpenSSL (dynamically loaded)
+        - name: "Linux (Bionic, GCC, dynamically-loaded OpenSSL)"
           container:
             name: bionic
             dockerfile: bionic
           env:
             CC: gcc
             CMAKE_GENERATOR: Ninja
-            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL-Dynamic -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL-Dynamic -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
             RUN_INVASIVE_TESTS: true
           os: ubuntu-latest
-        - # Bionic, x86, Clang, OpenSSL
+        - name: "Linux (x86, Bionic, Clang, OpenSSL)"
           container:
             name: bionic-x86
             dockerfile: bionic
@@ -223,20 +223,20 @@ jobs:
           env:
             CC: clang
             CMAKE_GENERATOR: Ninja
-            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
             RUN_INVASIVE_TESTS: true
           os: ubuntu-latest
-        - # Bionic, x86, GCC, OpenSSL
+        - name: "Linux (x86, Bionic, GCC, OpenSSL)"
           container:
             name: bionic-x86
             dockerfile: bionic
           env:
             CC: gcc
             CMAKE_GENERATOR: Ninja
-            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
             RUN_INVASIVE_TESTS: true
           os: ubuntu-latest
-        - # Bionic, arm32, GCC, OpenSSL
+        - name: "Linux (arm32, Bionic, GCC, OpenSSL)"
           container:
             name: bionic-arm32
             dockerfile: bionic
@@ -244,11 +244,11 @@ jobs:
           env:
             CC: gcc
             CMAKE_GENERATOR: Ninja
-            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_GSSAPI=ON -DUSE_SSH=ON
             RUN_INVASIVE_TESTS: true
             SKIP_PROXY_TESTS: true
           os: ubuntu-latest
-        - # Bionic, arm64, GCC, OpenSSL
+        - name: "Linux (arm64, Bionic, GCC, OpenSSL)"
           container:
             name: bionic-arm64
             dockerfile: bionic
@@ -256,11 +256,12 @@ jobs:
           env:
             CC: gcc
             CMAKE_GENERATOR: Ninja
-            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_GSSAPI=ON
+            CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_GSSAPI=ON -DUSE_SSH=ON
             RUN_INVASIVE_TESTS: true
             SKIP_PROXY_TESTS: true
           os: ubuntu-latest
       fail-fast: false
+    name: "Build ${{ matrix.platform.name }}"
     env: ${{ matrix.platform.env }}
     runs-on: ${{ matrix.platform.os }}
     steps:
index d47d93aab10d066d084ef90ca2137021bd00e7e0..62d4ec949b19334b1ded62028543b390d5fe58a0 100644 (file)
@@ -8,7 +8,7 @@
             "name": "(gdb) Launch",
             "type": "cppdbg",
             "request": "launch",
-            "program": "${workspaceFolder}/build/libgit2_clar",
+            "program": "${workspaceFolder}/build/libgit2_tests",
             "args": [],
             "stopAtEntry": false,
             "cwd": "${fileDirname}",
@@ -24,4 +24,4 @@
             ]
         }
     ]
-}
\ No newline at end of file
+}
index 64142d3410d525d08438c66259509c4f5cebda6c..24b4d745b315ff7bbc2ed04ab6ea39993ef740e8 100644 (file)
@@ -16,7 +16,7 @@
       {
         "label": "Run Tests",
         "type": "shell",
-        "command": "build/libgit2_clar -v",
+        "command": "build/libgit2_tests -v",
         "group": "test",
         "presentation": {
           "reveal": "always",
@@ -24,4 +24,4 @@
         }
       }
     ]
-  }
\ No newline at end of file
+  }
index 3dccec3109a4889044af02a95f75cbb46b381954..9ff6748e05e5b26f028215b76ca323d8cda9a42f 100644 (file)
 # CMake build script for the libgit2 project
-#
-# Building (out of source build):
-# > mkdir build && cd build
-# > cmake .. [-DSETTINGS=VALUE]
-# > cmake --build .
-#
-# Testing:
-# > ctest -V
-#
-# Install:
-# > cmake --build . --target install
+# See `README.md` for build instructions.
 
-CMAKE_MINIMUM_REQUIRED(VERSION 3.5.1)
+cmake_minimum_required(VERSION 3.5.1)
 
-project(libgit2 VERSION "1.3.0" LANGUAGES C)
+project(libgit2 VERSION "1.4.3" LANGUAGES C)
 
 # Add find modules to the path
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${libgit2_SOURCE_DIR}/cmake/")
-
-INCLUDE(CheckLibraryExists)
-INCLUDE(CheckFunctionExists)
-INCLUDE(CheckSymbolExists)
-INCLUDE(CheckStructHasMember)
-INCLUDE(CheckPrototypeDefinition) # Added in CMake 3.0
-INCLUDE(AddCFlagIfSupported)
-INCLUDE(FindPkgLibraries)
-INCLUDE(FindThreads)
-INCLUDE(FindStatNsec)
-INCLUDE(Findfutimens)
-INCLUDE(GNUInstallDirs)
-INCLUDE(IdeSplitSources)
-INCLUDE(FeatureSummary)
-INCLUDE(EnableWarnings)
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
 
+#
 # Build options
 #
-OPTION(SONAME                          "Set the (SO)VERSION of the target"                      ON)
-OPTION(BUILD_SHARED_LIBS               "Build Shared Library (OFF for Static)"                  ON)
-OPTION(THREADSAFE                      "Build libgit2 as threadsafe"                            ON)
-OPTION(BUILD_CLAR                      "Build Tests using the Clar suite"                       ON)
-OPTION(BUILD_EXAMPLES                  "Build library usage example apps"                      OFF)
-OPTION(BUILD_FUZZERS                   "Build the fuzz targets"                                OFF)
-OPTION(ENABLE_TRACE                    "Enables tracing support"                               ON)
-OPTION(LIBGIT2_FILENAME                        "Name of the produced binary"                           OFF)
-OPTION(USE_SSH                         "Link with libssh2 to enable SSH support"                ON)
-OPTION(USE_HTTPS                       "Enable HTTPS support. Can be set to a specific backend" ON)
-OPTION(USE_SHA1                                "Enable SHA1. Can be set to CollisionDetection(ON)/HTTPS/Generic" ON)
-OPTION(USE_GSSAPI                      "Link with libgssapi for SPNEGO auth"                   OFF)
-OPTION(USE_STANDALONE_FUZZERS          "Enable standalone fuzzers (compatible with gcc)"       OFF)
-OPTION(USE_LEAK_CHECKER                        "Run tests with leak checker"                           OFF)
-OPTION(DEBUG_POOL                      "Enable debug pool allocator"                           OFF)
-OPTION(DEBUG_STRICT_ALLOC              "Enable strict allocator behavior"                      OFF)
-OPTION(DEBUG_STRICT_OPEN               "Enable path validation in open"                        OFF)
-OPTION(ENABLE_WERROR                   "Enable compilation with -Werror"                       OFF)
-OPTION(USE_BUNDLED_ZLIB                "Use the bundled version of zlib. Can be set to one of Bundled(ON)/Chromium. The Chromium option requires a x86_64 processor with SSE4.2 and CLMUL"                     OFF)
-   SET(USE_HTTP_PARSER                 "" CACHE STRING "Specifies the HTTP Parser implementation; either system or builtin.")
-OPTION(DEPRECATE_HARD                  "Do not include deprecated functions in the library"    OFF)
-   SET(REGEX_BACKEND                   "" CACHE STRING "Regular expression implementation. One of regcomp_l, pcre2, pcre, regcomp, or builtin.")
 
-IF (UNIX)
-       IF (NOT USE_HTTPS)
-           OPTION(USE_NTLMCLIENT               "Enable NTLM support on Unix."                          OFF )
-       ELSE()
-           OPTION(USE_NTLMCLIENT               "Enable NTLM support on Unix."                          ON )
-       ENDIF()
-ENDIF()
+# Optional subsystems
+option(BUILD_SHARED_LIBS       "Build Shared Library (OFF for Static)"                  ON)
+option(BUILD_TESTS             "Build Tests using the Clar suite"                       ON)
+option(BUILD_EXAMPLES          "Build library usage example apps"                      OFF)
+option(BUILD_FUZZERS           "Build the fuzz targets"                                OFF)
+
+# Suggested functionality that may not be available on a per-platform basis
+option(USE_THREADS             "Use threads for parallel processing when possible"      ON)
+option(USE_NSEC                "Support nanosecond precision file mtimes and ctimes"    ON)
+
+# Backend selection
+option(USE_SSH                 "Link with libssh2 to enable SSH support"               OFF)
+option(USE_HTTPS               "Enable HTTPS support. Can be set to a specific backend" ON)
+option(USE_SHA1                "Enable SHA1. Can be set to CollisionDetection(ON)/HTTPS/Generic" ON)
+option(USE_GSSAPI              "Link with libgssapi for SPNEGO auth"      OFF)
+   set(USE_HTTP_PARSER         "" CACHE STRING "Specifies the HTTP Parser implementation; either system or builtin.")
+   set(REGEX_BACKEND           "" CACHE STRING "Regular expression implementation. One of regcomp_l, pcre2, pcre, regcomp, or builtin.")
+option(USE_BUNDLED_ZLIB        "Use the bundled version of zlib. Can be set to one of Bundled(ON)/Chromium. The Chromium option requires a x86_64 processor with SSE4.2 and CLMUL" OFF)
+
+# Debugging options
+option(USE_LEAK_CHECKER        "Run tests with leak checker"                           OFF)
+option(USE_STANDALONE_FUZZERS  "Enable standalone fuzzers (compatible with gcc)"       OFF)
+option(DEBUG_POOL              "Enable debug pool allocator"                           OFF)
+option(DEBUG_STRICT_ALLOC      "Enable strict allocator behavior"                      OFF)
+option(DEBUG_STRICT_OPEN       "Enable path validation in open"                        OFF)
+
+# Output options
+option(SONAME                  "Set the (SO)VERSION of the target"                      ON)
+   set(LIBGIT2_FILENAME        "git2" CACHE STRING "Name of the produced binary")
+option(DEPRECATE_HARD          "Do not include deprecated functions in the library"    OFF)
+
+# Compilation options
+option(ENABLE_WERROR           "Enable compilation with -Werror"                       OFF)
+
+if(UNIX)
+       # NTLM client requires crypto libraries from the system HTTPS stack
+       if(NOT USE_HTTPS)
+               option(USE_NTLMCLIENT  "Enable NTLM support on Unix."                  OFF)
+       else()
+               option(USE_NTLMCLIENT  "Enable NTLM support on Unix."                   ON)
+       endif()
 
-IF (UNIX AND NOT APPLE)
-       OPTION(ENABLE_REPRODUCIBLE_BUILDS "Enable reproducible builds"                          OFF)
-ENDIF()
+       option(ENABLE_REPRODUCIBLE_BUILDS "Enable reproducible builds"                 OFF)
+endif()
 
-IF (APPLE)
-       OPTION(USE_ICONV                "Link with and use iconv library"                        ON)
-ENDIF()
+if(APPLE)
+       option(USE_ICONV           "Link with and use iconv library"                    ON)
+endif()
 
-IF(MSVC)
+if(MSVC)
        # This option must match the settings used in your program, in particular if you
        # are linking statically
-       OPTION(STATIC_CRT               "Link the static CRT libraries"                          ON)
+       option(STATIC_CRT          "Link the static CRT libraries"                      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)
-ENDIF()
-
-
-IF(WIN32)
-       # By default, libgit2 is built with WinHTTP.  To use the built-in
-       # HTTP transport, invoke CMake with the "-DWINHTTP=OFF" argument.
-       OPTION(WINHTTP                  "Use Win32 WinHTTP routines"                             ON)
-ENDIF()
+       option(EMBED_SSH_PATH      "Path to libssh2 to embed (Windows)"                OFF)
 
-IF(MSVC)
        # Enable leak checking using the debugging C runtime.
-       OPTION(WIN32_LEAKCHECK          "Enable leak reporting via crtdbg"                      OFF)
-ENDIF()
-
-IF (DEPRECATE_HARD)
-       ADD_DEFINITIONS(-DGIT_DEPRECATE_HARD)
-ENDIF()
-
-# Platform specific compilation flags
-IF (MSVC)
-       IF (STDCALL)
-               MESSAGE(FATAL_ERROR "The STDCALL option is no longer supported; libgit2 is now always built as a cdecl library.  If you're using PInvoke, please add the CallingConventions.Cdecl attribute for support.")
-       ENDIF()
-
-       ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS)
-       ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
-       ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE)
-
-       STRING(REPLACE "/Zm1000" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
-
-       # /GF - String pooling
-       # /MP - Parallel build
-       SET(CMAKE_C_FLAGS "/GF /MP /nologo ${CMAKE_C_FLAGS}")
-
-       # /Gd - explicitly set cdecl calling convention
-       SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Gd")
-
-       IF (NOT (MSVC_VERSION LESS 1900))
-               # /guard:cf - Enable Control Flow Guard
-               SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /guard:cf")
-       ENDIF()
-
-       IF (STATIC_CRT)
-               SET(CRT_FLAG_DEBUG "/MTd")
-               SET(CRT_FLAG_RELEASE "/MT")
-       ELSE()
-               SET(CRT_FLAG_DEBUG "/MDd")
-               SET(CRT_FLAG_RELEASE "/MD")
-       ENDIF()
-
-       IF (WIN32_LEAKCHECK)
-               SET(GIT_WIN32_LEAKCHECK 1)
-               SET(CRT_FLAG_DEBUG "${CRT_FLAG_DEBUG}")
-               SET(CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES} Dbghelp.lib")
-       ENDIF()
-
-       # /Zi - Create debugging information
-       # /Od - Disable optimization
-       # /D_DEBUG - #define _DEBUG
-       # /MTd - Statically link the multithreaded debug version of the CRT
-       # /MDd - Dynamically link the multithreaded debug version of the CRT
-       # /RTC1 - Run time checks
-       SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Zi /Od /D_DEBUG /RTC1 ${CRT_FLAG_DEBUG}")
+       option(WIN32_LEAKCHECK     "Enable leak reporting via crtdbg"                  OFF)
+endif()
 
-       # /DNDEBUG - Disables asserts
-       # /MT - Statically link the multithreaded release version of the CRT
-       # /MD - Dynamically link the multithreaded release version of the CRT
-       # /O2 - Optimize for speed
-       # /Oy - Enable frame pointer omission (FPO) (otherwise CMake will automatically turn it off)
-       # /GL - Link time code generation (whole program optimization)
-       # /Gy - Function-level linking
-       SET(CMAKE_C_FLAGS_RELEASE "/DNDEBUG /O2 /Oy /GL /Gy ${CRT_FLAG_RELEASE}")
-
-       # /Oy- - Disable frame pointer omission (FPO)
-       SET(CMAKE_C_FLAGS_RELWITHDEBINFO "/DNDEBUG /Zi /O2 /Oy- /GL /Gy ${CRT_FLAG_RELEASE}")
-
-       # /O1 - Optimize for size
-       SET(CMAKE_C_FLAGS_MINSIZEREL "/DNDEBUG /O1 /Oy /GL /Gy ${CRT_FLAG_RELEASE}")
-
-       # /IGNORE:4221 - Ignore empty compilation units
-       SET(CMAKE_STATIC_LINKER_FLAGS "/IGNORE:4221")
-
-       # /DYNAMICBASE - Address space load randomization (ASLR)
-       # /NXCOMPAT - Data execution prevention (DEP)
-       # /LARGEADDRESSAWARE - >2GB user address space on x86
-       # /VERSION - Embed version information in PE header
-       SET(CMAKE_EXE_LINKER_FLAGS "/DYNAMICBASE /NXCOMPAT /LARGEADDRESSAWARE /VERSION:${libgit2_VERSION_MAJOR}.${libgit2_VERSION_MINOR}")
-
-       IF (NOT (MSVC_VERSION LESS 1900))
-               # /GUARD:CF - Enable Control Flow Guard
-               SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /GUARD:CF")
-       ENDIF()
-
-       # /DEBUG - Create a PDB
-       # /LTCG - Link time code generation (whole program optimization)
-       # /OPT:REF /OPT:ICF - Fold out duplicate code at link step
-       # /INCREMENTAL:NO - Required to use /LTCG
-       # /DEBUGTYPE:cv,fixup - Additional data embedded in the PDB (requires /INCREMENTAL:NO, so not on for Debug)
-       SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG")
-       SET(CMAKE_EXE_LINKER_FLAGS_RELEASE "/RELEASE /LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO")
-       SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/DEBUG /RELEASE /LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO /DEBUGTYPE:cv,fixup")
-       SET(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "/RELEASE /LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO")
-
-       # Same linker settings for DLL as EXE
-       SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
-       SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
-       SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
-       SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
-       SET(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL}")
-ELSE ()
-       IF (ENABLE_REPRODUCIBLE_BUILDS)
-               SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Dqc <TARGET> <LINK_FLAGS> <OBJECTS>")
-               SET(CMAKE_C_ARCHIVE_APPEND "<CMAKE_AR> Dq  <TARGET> <LINK_FLAGS> <OBJECTS>")
-               SET(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -D <TARGET>")
-       ENDIF()
-
-       SET(CMAKE_C_FLAGS "-D_GNU_SOURCE ${CMAKE_C_FLAGS}")
-
-       ENABLE_WARNINGS(all)
-       ENABLE_WARNINGS(extra)
-
-       IF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
-               SET(CMAKE_C_FLAGS "-D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS ${CMAKE_C_FLAGS}")
-       ENDIF()
+if(WIN32)
+       # By default, libgit2 is built with WinHTTP.  To use the built-in
+       # HTTP transport, invoke CMake with the "-DUSE_WINHTTP=OFF" argument.
+       option(USE_WINHTTP         "Use Win32 WinHTTP routines"                         ON)
+endif()
+
+if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
+       set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
+endif()
+
+
+# Modules
+
+include(CheckLibraryExists)
+include(CheckFunctionExists)
+include(CheckSymbolExists)
+include(CheckStructHasMember)
+include(CheckPrototypeDefinition)
+include(AddCFlagIfSupported)
+include(FindPkgLibraries)
+include(FindThreads)
+include(FindStatNsec)
+include(Findfutimens)
+include(GNUInstallDirs)
+include(IdeSplitSources)
+include(FeatureSummary)
+include(EnableWarnings)
+include(DefaultCFlags)
 
-       SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -O0")
 
-       IF (MINGW OR MSYS) # MinGW and MSYS always do PIC and complain if we tell them to
-               STRING(REGEX REPLACE "-fPIC" "" CMAKE_SHARED_LIBRARY_C_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}")
-       ELSEIF (BUILD_SHARED_LIBS)
-               ADD_C_FLAG_IF_SUPPORTED(-fvisibility=hidden)
+#
+# Subdirectories
+#
 
-               SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
-       ENDIF ()
+add_subdirectory(src)
 
-       IF (MINGW)
-               # MinGW >= 3.14 uses the C99-style stdio functions
-               # automatically, but forks like mingw-w64 still want
-               # us to define this in order to use them
-               ADD_DEFINITIONS(-D__USE_MINGW_ANSI_STDIO=1)
-       ENDIF ()
+if(BUILD_TESTS)
+       enable_testing()
+       add_subdirectory(tests)
+endif()
 
-       enable_warnings(documentation)
-       disable_warnings(documentation-deprecated-sync)
-       disable_warnings(missing-field-initializers)
-       enable_warnings(strict-aliasing)
-       enable_warnings(strict-prototypes)
-       enable_warnings(declaration-after-statement)
-       enable_warnings(shift-count-overflow)
-       enable_warnings(unused-const-variable)
-       enable_warnings(unused-function)
-       enable_warnings(int-conversion)
-       enable_warnings(c11-extensions)
-       enable_warnings(c99-c11-compat)
+if(BUILD_EXAMPLES)
+       add_subdirectory(examples)
+endif()
 
-       # MinGW uses gcc, which expects POSIX formatting for printf, but
-       # uses the Windows C library, which uses its own format specifiers.
-       # Disable format specifier warnings.
-       if(MINGW)
-               disable_warnings(format)
-               disable_warnings(format-security)
-       else()
-               enable_warnings(format)
-               enable_warnings(format-security)
+if(BUILD_FUZZERS)
+       if((BUILD_TESTS OR BUILD_EXAMPLES) AND NOT USE_STANDALONE_FUZZERS)
+               message(FATAL_ERROR "Cannot build the fuzzer and the tests or examples together")
        endif()
-ENDIF()
-
-# Ensure that MinGW provides the correct header files.
-IF (WIN32 AND NOT CYGWIN)
-       ADD_DEFINITIONS(-DWIN32 -D_WIN32_WINNT=0x0600)
-ENDIF()
-
-IF( NOT CMAKE_CONFIGURATION_TYPES )
-       # Build Debug by default
-       IF (NOT CMAKE_BUILD_TYPE)
-               SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
-       ENDIF ()
-ELSE()
-       # Using a multi-configuration generator eg MSVC or Xcode
-       # that uses CMAKE_CONFIGURATION_TYPES and not CMAKE_BUILD_TYPE
-ENDIF()
-
-IF(BUILD_FUZZERS AND NOT USE_STANDALONE_FUZZERS)
-       # The actual sanitizer link target will be added when linking the fuzz
-       # targets.
-       SET(CMAKE_REQUIRED_FLAGS "-fsanitize=fuzzer-no-link")
-       ADD_C_FLAG(-fsanitize=fuzzer-no-link)
-       UNSET(CMAKE_REQUIRED_FLAGS)
-ENDIF ()
-
-ADD_SUBDIRECTORY(src)
-
-# Tests
-IF (NOT MSVC)
-   IF (NOT BUILD_SHARED_LIBS)
-       SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
-   ENDIF()
-ENDIF ()
-
-IF (BUILD_CLAR)
-       ENABLE_TESTING()
-       ADD_SUBDIRECTORY(tests)
-ENDIF ()
+       add_subdirectory(fuzzers)
+endif()
 
-IF (BUILD_EXAMPLES)
-       ADD_SUBDIRECTORY(examples)
-ENDIF ()
 
-IF(BUILD_FUZZERS)
-       IF(NOT USE_STANDALONE_FUZZERS)
-               IF(BUILD_EXAMPLES)
-                       MESSAGE(FATAL_ERROR "Cannot build the fuzzer targets and the examples together")
-               ENDIF()
-               IF(BUILD_CLAR)
-                       MESSAGE(FATAL_ERROR "Cannot build the fuzzer targets and the tests together")
-               ENDIF()
-       ENDIF()
-       ADD_SUBDIRECTORY(fuzzers)
-ENDIF()
+# Summary
 
-FEATURE_SUMMARY(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:")
-FEATURE_SUMMARY(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:")
+feature_summary(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:")
+feature_summary(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:")
diff --git a/COPYING b/COPYING
index 6bb39b0c1d9a530ad92f036b4315f53363404189..ccfb7dbf8dee553ec83ec1fe4ce2f17097de6e04 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -406,30 +406,35 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 ----------------------------------------------------------------------
 
-The regex library (deps/regex/) is licensed under the GNU LGPL
-(available at the end of this file).
+The bundled PCRE implementation (deps/pcre/) is licensed under the BSD
+license.
 
-Definitions for data structures and routines for the regular
-expression library.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
 
-Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005,2006,2008
-Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
 
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
 
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Lesser General Public License for more details.
+    * Neither the name of the University of Cambridge nor the name of Google
+      Inc. nor the names of their contributors may be used to endorse or
+      promote products derived from this software without specific prior
+      written permission.
 
-You should have received a copy of the GNU Lesser General Public
-License along with the GNU C Library; if not, write to the Free
-Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
 
 ----------------------------------------------------------------------
 
@@ -1127,3 +1132,15 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 OF THE POSSIBILITY OF SUCH DAMAGE.
 
+----------------------------------------------------------------------
+
+The xoroshiro256** implementation is licensed in the public domain:
+
+Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
+
+To the extent possible under law, the author has dedicated all copyright
+and related and neighboring rights to this software to the public domain
+worldwide. This software is distributed without any warranty.
+
+See <http://creativecommons.org/publicdomain/zero/1.0/>.
+
index 0cbde525b5a3448d91625dfcc052bc750e69ace3..c73b50701ad42c022d4bfd2eb719e5825b730d63 100644 (file)
--- a/README.md
+++ b/README.md
@@ -4,8 +4,8 @@ libgit2 - the Git linkable library
 | Build Status | |
 | ------------ | - |
 | **main** branch CI builds | [![CI Build](https://github.com/libgit2/libgit2/workflows/CI%20Build/badge.svg?event=push)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush) |
-| **v1.2 branch** CI builds | [![CI Build](https://github.com/libgit2/libgit2/workflows/CI%20Build/badge.svg?branch=maint%2Fv1.2&event=push)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.2) |
-| **v1.1 branch** CI builds | [![CI Build](https://github.com/libgit2/libgit2/workflows/CI%20Build/badge.svg?branch=maint%2Fv1.1&event=push)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.1) |
+| **v1.4 branch** CI builds | [![CI Build](https://github.com/libgit2/libgit2/workflows/CI%20Build/badge.svg?branch=maint%2Fv1.4&event=push)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.4) |
+| **v1.3 branch** CI builds | [![CI Build](https://github.com/libgit2/libgit2/workflows/CI%20Build/badge.svg?branch=maint%2Fv1.3&event=push)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.3) |
 | **Nightly** builds | [![Nightly Build](https://github.com/libgit2/libgit2/workflows/Nightly%20Build/badge.svg)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22Nightly+Build%22) [![Coverity Scan Status](https://scan.coverity.com/projects/639/badge.svg)](https://scan.coverity.com/projects/639) |
 
 `libgit2` is a portable, pure C implementation of the Git core methods
@@ -236,18 +236,18 @@ Once built, you can run the tests from the `build` directory with the command
 
 Alternatively you can run the test suite directly using,
 
-       $ ./libgit2_clar
+       $ ./libgit2_tests
 
 Invoking the test suite directly is useful because it allows you to execute
 individual tests, or groups of tests using the `-s` flag.  For example, to
 run the index tests:
 
-    $ ./libgit2_clar -sindex
+    $ ./libgit2_tests -sindex
 
 To run a single test named `index::racy::diff`, which corresponds to the test
 function [`test_index_racy__diff`](https://github.com/libgit2/libgit2/blob/main/tests/index/racy.c#L23):
 
-    $ ./libgit2_clar -sindex::racy::diff
+    $ ./libgit2_tests -sindex::racy::diff
 
 The test suite will print a `.` for every passing test, and an `F` for any
 failing test.  An `S` indicates that a test was skipped because it is not
@@ -278,8 +278,8 @@ The following CMake variables are declared:
 - `CMAKE_INSTALL_LIBDIR`: Where to install libraries to.
 - `CMAKE_INSTALL_INCLUDEDIR`: Where to install headers to.
 - `BUILD_SHARED_LIBS`: Build libgit2 as a Shared Library (defaults to ON)
-- `BUILD_CLAR`: Build [Clar](https://github.com/vmg/clar)-based test suite (defaults to ON)
-- `THREADSAFE`: Build libgit2 with threading support (defaults to ON)
+- `BUILD_TESTS`: Build the unit and integration test suites (defaults to ON)
+- `USE_THREADS`: Build libgit2 with threading support (defaults to ON)
 
 To list all build options and their current value, you can do the
 following:
@@ -301,6 +301,8 @@ compiler and linker. These flags are rarely used but can be useful for
 - `CMAKE_FIND_ROOT_PATH`: Override the search path for libraries
 - `ZLIB_LIBRARY`, `OPENSSL_SSL_LIBRARY` AND `OPENSSL_CRYPTO_LIBRARY`:
 Tell CMake where to find those specific libraries
+- `LINK_WITH_STATIC_LIBRARIES`: Link only with static versions of
+system libraries
 
 MacOS X
 -------
@@ -392,8 +394,6 @@ Here are the bindings to libgit2 that are currently available:
     * Git-Raw <https://github.com/jacquesg/p5-Git-Raw>
 * PHP
     * php-git <https://github.com/libgit2/php-git>
-* PowerShell
-    * PSGit <https://github.com/PoshCode/PSGit>
 * Python
     * pygit2 <https://github.com/libgit2/pygit2>
 * R
index 4d6c41f7675a62851fd1e1c247dadd08c366af42..a9483977883b9d845928a418a00b38940c5c885d 100755 (executable)
@@ -83,7 +83,7 @@ echo "##########################################################################
 if [ -z "$SKIP_GITDAEMON_TESTS" ]; then
        echo "Starting git daemon..."
        GITDAEMON_DIR=`mktemp -d ${TMPDIR}/gitdaemon.XXXXXXXX`
-       git init --bare "${GITDAEMON_DIR}/test.git"
+       git init --bare "${GITDAEMON_DIR}/test.git" >/dev/null
        git daemon --listen=localhost --export-all --enable=receive-pack --base-path="${GITDAEMON_DIR}" "${GITDAEMON_DIR}" 2>/dev/null &
        GITDAEMON_PID=$!
        disown $GITDAEMON_PID
@@ -101,8 +101,8 @@ if [ -z "$SKIP_PROXY_TESTS" ]; then
        java -jar poxyproxy.jar --address 127.0.0.1 --port 8090 --credentials foo:bar --auth-type ntlm --quiet &
 fi
 
-if [ -z "$SKIP_NTLM_TESTS" ]; then
-       curl --location --silent --show-error https://github.com/ethomson/poxygit/releases/download/v0.4.0/poxygit-0.4.0.jar >poxygit.jar
+if [ -z "$SKIP_NTLM_TESTS" -o -z "$SKIP_ONLINE_TESTS" ]; then
+       curl --location --silent --show-error https://github.com/ethomson/poxygit/releases/download/v0.5.1/poxygit-0.5.1.jar >poxygit.jar
 
        echo ""
        echo "Starting HTTP server..."
@@ -112,10 +112,11 @@ if [ -z "$SKIP_NTLM_TESTS" ]; then
 fi
 
 if [ -z "$SKIP_SSH_TESTS" ]; then
+       echo ""
        echo "Starting ssh daemon..."
        HOME=`mktemp -d ${TMPDIR}/home.XXXXXXXX`
        SSHD_DIR=`mktemp -d ${TMPDIR}/sshd.XXXXXXXX`
-       git init --bare "${SSHD_DIR}/test.git"
+       git init --bare "${SSHD_DIR}/test.git" >/dev/null
        cat >"${SSHD_DIR}/sshd_config" <<-EOF
        Port 2222
        ListenAddress 0.0.0.0
@@ -188,9 +189,11 @@ if [ -z "$SKIP_ONLINE_TESTS" ]; then
        echo "## Running (online) tests"
        echo "##############################################################################"
 
-       export GITTEST_FLAKY_RETRY=5
+       export GITTEST_REMOTE_REDIRECT_INITIAL="http://localhost:9000/initial-redirect/libgit2/TestGitRepository"
+       export GITTEST_REMOTE_REDIRECT_SUBSEQUENT="http://localhost:9000/subsequent-redirect/libgit2/TestGitRepository"
        run_test online
-       unset GITTEST_FLAKY_RETRY
+       unset GITTEST_REMOTE_REDIRECT_INITIAL
+       unset GITTEST_REMOTE_REDIRECT_SUBSEQUENT
 
        # Run the online tests that immutably change global state separately
        # to avoid polluting the test environment.
@@ -231,9 +234,7 @@ if [ -z "$SKIP_PROXY_TESTS" ]; then
        export GITTEST_REMOTE_PROXY_HOST="localhost:8090"
        export GITTEST_REMOTE_PROXY_USER="foo"
        export GITTEST_REMOTE_PROXY_PASS="bar"
-       export GITTEST_FLAKY_RETRY=5
        run_test proxy
-       unset GITTEST_FLAKY_RETRY
        unset GITTEST_REMOTE_PROXY_HOST
        unset GITTEST_REMOTE_PROXY_USER
        unset GITTEST_REMOTE_PROXY_PASS
@@ -299,18 +300,28 @@ if [ -z "$SKIP_NEGOTIATE_TESTS" -a -n "$GITTEST_NEGOTIATE_PASSWORD" ]; then
 fi
 
 if [ -z "$SKIP_SSH_TESTS" ]; then
-       echo ""
-       echo "Running ssh tests"
-       echo ""
-
-       export GITTEST_REMOTE_URL="ssh://localhost:2222/$SSHD_DIR/test.git"
        export GITTEST_REMOTE_USER=$USER
        export GITTEST_REMOTE_SSH_KEY="${HOME}/.ssh/id_rsa"
        export GITTEST_REMOTE_SSH_PUBKEY="${HOME}/.ssh/id_rsa.pub"
        export GITTEST_REMOTE_SSH_PASSPHRASE=""
        export GITTEST_REMOTE_SSH_FINGERPRINT="${SSH_FINGERPRINT}"
+
+       echo ""
+       echo "Running ssh tests"
+       echo ""
+
+       export GITTEST_REMOTE_URL="ssh://localhost:2222/$SSHD_DIR/test.git"
+       run_test ssh
+       unset GITTEST_REMOTE_URL
+
+       echo ""
+       echo "Running ssh tests (scp-style paths)"
+       echo ""
+
+       export GITTEST_REMOTE_URL="[localhost:2222]:$SSHD_DIR/test.git"
        run_test ssh
        unset GITTEST_REMOTE_URL
+
        unset GITTEST_REMOTE_USER
        unset GITTEST_REMOTE_SSH_KEY
        unset GITTEST_REMOTE_SSH_PUBKEY
index b7aaa7910a969afe106300e301ebb905f0b382b3..685f26a00fc3623f96da6fc08971304ae39aa363 100644 (file)
@@ -3,28 +3,28 @@
 #  <flag> - the compiler flag to test
 # This internally calls the CHECK_C_COMPILER_FLAG macro.
 
-INCLUDE(CheckCCompilerFlag)
+include(CheckCCompilerFlag)
 
-MACRO(ADD_C_FLAG _FLAG)
-       STRING(TOUPPER ${_FLAG} UPCASE)
-       STRING(REGEX REPLACE "[-=]" "_" UPCASE_PRETTY ${UPCASE})
-       STRING(REGEX REPLACE "^_+" "" UPCASE_PRETTY ${UPCASE_PRETTY})
-       CHECK_C_COMPILER_FLAG(${_FLAG} IS_${UPCASE_PRETTY}_SUPPORTED)
+macro(ADD_C_FLAG _FLAG)
+       string(TOUPPER ${_FLAG} UPCASE)
+       string(REGEX REPLACE "[-=]" "_" UPCASE_PRETTY ${UPCASE})
+       string(REGEX REPLACE "^_+" "" UPCASE_PRETTY ${UPCASE_PRETTY})
+       check_c_compiler_flag(${_FLAG} IS_${UPCASE_PRETTY}_SUPPORTED)
 
-       IF(IS_${UPCASE_PRETTY}_SUPPORTED)
-               SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FLAG}")
-       ELSE()
-               MESSAGE(FATAL_ERROR "Required flag ${_FLAG} is not supported")
-       ENDIF()
-ENDMACRO()
+       if(IS_${UPCASE_PRETTY}_SUPPORTED)
+               set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FLAG}")
+       else()
+               message(FATAL_ERROR "Required flag ${_FLAG} is not supported")
+       endif()
+endmacro()
 
-MACRO(ADD_C_FLAG_IF_SUPPORTED _FLAG)
-       STRING(TOUPPER ${_FLAG} UPCASE)
-       STRING(REGEX REPLACE "[-=]" "_" UPCASE_PRETTY ${UPCASE})
-       STRING(REGEX REPLACE "^_+" "" UPCASE_PRETTY ${UPCASE_PRETTY})
-       CHECK_C_COMPILER_FLAG(${_FLAG} IS_${UPCASE_PRETTY}_SUPPORTED)
+macro(ADD_C_FLAG_IF_SUPPORTED _FLAG)
+       string(TOUPPER ${_FLAG} UPCASE)
+       string(REGEX REPLACE "[-=]" "_" UPCASE_PRETTY ${UPCASE})
+       string(REGEX REPLACE "^_+" "" UPCASE_PRETTY ${UPCASE_PRETTY})
+       check_c_compiler_flag(${_FLAG} IS_${UPCASE_PRETTY}_SUPPORTED)
 
-       IF(IS_${UPCASE_PRETTY}_SUPPORTED)
-               SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FLAG}")
-       ENDIF()
-ENDMACRO()
+       if(IS_${UPCASE_PRETTY}_SUPPORTED)
+               set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FLAG}")
+       endif()
+endmacro()
diff --git a/cmake/DefaultCFlags.cmake b/cmake/DefaultCFlags.cmake
new file mode 100644 (file)
index 0000000..a9c9ab9
--- /dev/null
@@ -0,0 +1,154 @@
+# Platform specific compilation flags
+if(MSVC)
+       add_definitions(-D_SCL_SECURE_NO_WARNINGS)
+       add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
+       add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
+
+       string(REPLACE "/Zm1000" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
+
+       # /GF - String pooling
+       # /MP - Parallel build
+       set(CMAKE_C_FLAGS "/GF /MP /nologo ${CMAKE_C_FLAGS}")
+
+       # /Gd - explicitly set cdecl calling convention
+       set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Gd")
+
+       if(NOT (MSVC_VERSION LESS 1900))
+               # /guard:cf - Enable Control Flow Guard
+               set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /guard:cf")
+       endif()
+
+       if(STATIC_CRT)
+               set(CRT_FLAG_DEBUG "/MTd")
+               set(CRT_FLAG_RELEASE "/MT")
+       else()
+               set(CRT_FLAG_DEBUG "/MDd")
+               set(CRT_FLAG_RELEASE "/MD")
+       endif()
+
+       if(WIN32_LEAKCHECK)
+               set(GIT_WIN32_LEAKCHECK 1)
+               set(CRT_FLAG_DEBUG "${CRT_FLAG_DEBUG}")
+               set(CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES} Dbghelp.lib")
+       endif()
+
+       # /Zi - Create debugging information
+       # /Od - Disable optimization
+       # /D_DEBUG - #define _DEBUG
+       # /MTd - Statically link the multithreaded debug version of the CRT
+       # /MDd - Dynamically link the multithreaded debug version of the CRT
+       # /RTC1 - Run time checks
+       set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Zi /Od /D_DEBUG /RTC1 ${CRT_FLAG_DEBUG}")
+
+       # /DNDEBUG - Disables asserts
+       # /MT - Statically link the multithreaded release version of the CRT
+       # /MD - Dynamically link the multithreaded release version of the CRT
+       # /O2 - Optimize for speed
+       # /Oy - Enable frame pointer omission (FPO) (otherwise CMake will automatically turn it off)
+       # /GL - Link time code generation (whole program optimization)
+       # /Gy - Function-level linking
+       set(CMAKE_C_FLAGS_RELEASE "/DNDEBUG /O2 /Oy /GL /Gy ${CRT_FLAG_RELEASE}")
+
+       # /Oy- - Disable frame pointer omission (FPO)
+       set(CMAKE_C_FLAGS_RELWITHDEBINFO "/DNDEBUG /Zi /O2 /Oy- /GL /Gy ${CRT_FLAG_RELEASE}")
+
+       # /O1 - Optimize for size
+       set(CMAKE_C_FLAGS_MINSIZEREL "/DNDEBUG /O1 /Oy /GL /Gy ${CRT_FLAG_RELEASE}")
+
+       # /IGNORE:4221 - Ignore empty compilation units
+       set(CMAKE_STATIC_LINKER_FLAGS "/IGNORE:4221")
+
+       # /DYNAMICBASE - Address space load randomization (ASLR)
+       # /NXCOMPAT - Data execution prevention (DEP)
+       # /LARGEADDRESSAWARE - >2GB user address space on x86
+       # /VERSION - Embed version information in PE header
+       set(CMAKE_EXE_LINKER_FLAGS "/DYNAMICBASE /NXCOMPAT /LARGEADDRESSAWARE /VERSION:${libgit2_VERSION_MAJOR}.${libgit2_VERSION_MINOR}")
+
+       if(NOT (MSVC_VERSION LESS 1900))
+               # /GUARD:CF - Enable Control Flow Guard
+               set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /GUARD:CF")
+       endif()
+
+       # /DEBUG - Create a PDB
+       # /LTCG - Link time code generation (whole program optimization)
+       # /OPT:REF /OPT:ICF - Fold out duplicate code at link step
+       # /INCREMENTAL:NO - Required to use /LTCG
+       # /DEBUGTYPE:cv,fixup - Additional data embedded in the PDB (requires /INCREMENTAL:NO, so not on for Debug)
+       set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG")
+       set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/RELEASE /LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO")
+       set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/DEBUG /RELEASE /LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO /DEBUGTYPE:cv,fixup")
+       set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "/RELEASE /LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO")
+
+       # Same linker settings for DLL as EXE
+       set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
+       set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
+       set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
+       set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
+       set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL}")
+else()
+       if(ENABLE_REPRODUCIBLE_BUILDS)
+               set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Dqc <TARGET> <LINK_FLAGS> <OBJECTS>")
+               set(CMAKE_C_ARCHIVE_APPEND "<CMAKE_AR> Dq  <TARGET> <LINK_FLAGS> <OBJECTS>")
+               set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -D <TARGET>")
+       endif()
+
+       if(NOT BUILD_SHARED_LIBS AND LINK_WITH_STATIC_LIBRARIES)
+               set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
+       endif()
+
+       set(CMAKE_C_FLAGS "-D_GNU_SOURCE ${CMAKE_C_FLAGS}")
+
+       enable_warnings(all)
+       enable_warnings(extra)
+
+       if(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
+               set(CMAKE_C_FLAGS "-D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS ${CMAKE_C_FLAGS}")
+       endif()
+
+       set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -O0")
+
+       if(MINGW OR MSYS) # MinGW and MSYS always do PIC and complain if we tell them to
+               string(REGEX REPLACE "-fPIC" "" CMAKE_SHARED_LIBRARY_C_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}")
+       elseif(BUILD_SHARED_LIBS)
+               add_c_flag_IF_SUPPORTED(-fvisibility=hidden)
+
+               set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+       endif()
+
+       if(MINGW)
+               # MinGW >= 3.14 uses the C99-style stdio functions
+               # automatically, but forks like mingw-w64 still want
+               # us to define this in order to use them
+               add_definitions(-D__USE_MINGW_ANSI_STDIO=1)
+       endif()
+
+       enable_warnings(documentation)
+       disable_warnings(documentation-deprecated-sync)
+       disable_warnings(missing-field-initializers)
+       enable_warnings(missing-declarations)
+       enable_warnings(strict-aliasing)
+       enable_warnings(strict-prototypes)
+       enable_warnings(declaration-after-statement)
+       enable_warnings(shift-count-overflow)
+       enable_warnings(unused-const-variable)
+       enable_warnings(unused-function)
+       enable_warnings(int-conversion)
+       enable_warnings(c11-extensions)
+       enable_warnings(c99-c11-compat)
+
+       # MinGW uses gcc, which expects POSIX formatting for printf, but
+       # uses the Windows C library, which uses its own format specifiers.
+       # Disable format specifier warnings.
+       if(MINGW)
+               disable_warnings(format)
+               disable_warnings(format-security)
+       else()
+               enable_warnings(format)
+               enable_warnings(format-security)
+       endif()
+endif()
+
+# Ensure that MinGW provides the correct header files.
+if(WIN32 AND NOT CYGWIN)
+       add_definitions(-DWIN32 -D_WIN32_WINNT=0x0600)
+endif()
index b61ed7e90d4b602a302188a7d3ba1e3a075e83b6..0700b521b6880d3e88df1493b6f6d21e1015c7d7 100644 (file)
@@ -1,15 +1,15 @@
-MACRO(ENABLE_WARNINGS flag)
-       ADD_C_FLAG_IF_SUPPORTED(-W${flag})
-ENDMACRO()
+macro(ENABLE_WARNINGS flag)
+       add_c_flag_if_supported(-W${flag})
+endmacro()
 
-MACRO(DISABLE_WARNINGS flag)
-       ADD_C_FLAG_IF_SUPPORTED(-Wno-${flag})
-ENDMACRO()
+macro(DISABLE_WARNINGS flag)
+       add_c_flag_if_supported(-Wno-${flag})
+endmacro()
 
-IF(ENABLE_WERROR)
-       IF(MSVC)
-               ADD_COMPILE_OPTIONS(-WX)
-       ELSE()
-               ADD_C_FLAG_IF_SUPPORTED(-Werror)
-       ENDIF()
-ENDIF()
+if(ENABLE_WERROR)
+       if(MSVC)
+               add_compile_options(-WX)
+       else()
+               add_c_flag_if_supported(-Werror)
+       endif()
+endif()
index 191aa595cfcc33c6799007a52a67dcd9317a2866..b419ec9abd92e5a51cba126e67cf04447bd67f39 100644 (file)
@@ -6,21 +6,21 @@
 # COREFOUNDATION_LDFLAGS
 #
 
-FIND_PATH(COREFOUNDATION_INCLUDE_DIR NAMES CoreFoundation.h)
-FIND_LIBRARY(COREFOUNDATION_LIBRARIES NAMES CoreFoundation)
-IF (COREFOUNDATION_INCLUDE_DIR AND COREFOUNDATION_LIBRARIES)
-       IF (NOT CoreFoundation_FIND_QUIETLY)
-               MESSAGE(STATUS "Found CoreFoundation ${COREFOUNDATION_LIBRARIES}")
-       ENDIF()
-       SET(COREFOUNDATION_FOUND TRUE)
-       SET(COREFOUNDATION_LDFLAGS "-framework CoreFoundation")
-ENDIF ()
+find_path(COREFOUNDATION_INCLUDE_DIR NAMES CoreFoundation.h)
+find_library(COREFOUNDATION_LIBRARIES NAMES CoreFoundation)
+if(COREFOUNDATION_INCLUDE_DIR AND COREFOUNDATION_LIBRARIES)
+       if(NOT CoreFoundation_FIND_QUIETLY)
+               message(STATUS "Found CoreFoundation ${COREFOUNDATION_LIBRARIES}")
+       endif()
+       set(COREFOUNDATION_FOUND TRUE)
+       set(COREFOUNDATION_LDFLAGS "-framework CoreFoundation")
+endif()
 
-IF (CoreFoundation_FIND_REQUIRED AND NOT COREFOUNDATION_FOUND)
-       MESSAGE(FATAL_ERROR "CoreFoundation not found")
-ENDIF()
+if(CoreFoundation_FIND_REQUIRED AND NOT COREFOUNDATION_FOUND)
+       message(FATAL_ERROR "CoreFoundation not found")
+endif()
 
-MARK_AS_ADVANCED(
+mark_as_advanced(
        COREFOUNDATION_INCLUDE_DIR
        COREFOUNDATION_LIBRARIES
 )
index 37357c4cd4bb9d56a65d0f4adf76f7c9202dea95..a11d72a67d509a283d1948992dd6f4b75410bab3 100644 (file)
@@ -5,7 +5,7 @@
 #  GSSAPI_ROOT_DIR - Set this variable to the root installation of GSSAPI
 #
 # Read-Only variables:
-#  GSSAPI_FLAVOR_MIT - set to TURE if MIT Kerberos has been found
+#  GSSAPI_FLAVOR_MIT - set to TRUE if MIT Kerberos has been found
 #  GSSAPI_FLAVOR_HEIMDAL - set to TRUE if Heimdal Kerberos has been found
 #  GSSAPI_FOUND - system has GSSAPI
 #  GSSAPI_INCLUDE_DIR - the GSSAPI include directory
 #
 
 find_path(GSSAPI_ROOT_DIR
-    NAMES
-        include/gssapi.h
-        include/gssapi/gssapi.h
-    HINTS
-        ${_GSSAPI_ROOT_HINTS}
-    PATHS
-        ${_GSSAPI_ROOT_PATHS}
-)
+       NAMES include/gssapi.h include/gssapi/gssapi.h
+       HINTS ${_GSSAPI_ROOT_HINTS}
+       PATHS ${_GSSAPI_ROOT_PATHS})
 mark_as_advanced(GSSAPI_ROOT_DIR)
 
-if (UNIX)
-    find_program(KRB5_CONFIG
-        NAMES
-            krb5-config
-        PATHS
-            ${GSSAPI_ROOT_DIR}/bin
-            /opt/local/bin)
-    mark_as_advanced(KRB5_CONFIG)
-
-    if (KRB5_CONFIG)
-        # Check if we have MIT KRB5
-        execute_process(
-            COMMAND
-                ${KRB5_CONFIG} --vendor
-            RESULT_VARIABLE
-                _GSSAPI_VENDOR_RESULT
-            OUTPUT_VARIABLE
-                _GSSAPI_VENDOR_STRING)
-
-        if (_GSSAPI_VENDOR_STRING MATCHES ".*Massachusetts.*")
-            set(GSSAPI_FLAVOR_MIT TRUE)
-        else()
-            execute_process(
-                COMMAND
-                    ${KRB5_CONFIG} --libs gssapi
-                RESULT_VARIABLE
-                    _GSSAPI_LIBS_RESULT
-                OUTPUT_VARIABLE
-                    _GSSAPI_LIBS_STRING)
-
-            if (_GSSAPI_LIBS_STRING MATCHES ".*roken.*")
-                set(GSSAPI_FLAVOR_HEIMDAL TRUE)
-            endif()
-        endif()
-
-        # Get the include dir
-        execute_process(
-            COMMAND
-                ${KRB5_CONFIG} --cflags gssapi
-            RESULT_VARIABLE
-                _GSSAPI_INCLUDE_RESULT
-            OUTPUT_VARIABLE
-                _GSSAPI_INCLUDE_STRING)
-        string(REGEX REPLACE "(\r?\n)+$" "" _GSSAPI_INCLUDE_STRING "${_GSSAPI_INCLUDE_STRING}")
-        string(REGEX REPLACE " *-I" "" _GSSAPI_INCLUDEDIR "${_GSSAPI_INCLUDE_STRING}")
-    endif()
-
-    if (NOT GSSAPI_FLAVOR_MIT AND NOT GSSAPI_FLAVOR_HEIMDAL)
-        # Check for HEIMDAL
-        find_package(PkgConfig)
-        if (PKG_CONFIG_FOUND)
-            pkg_check_modules(_GSSAPI heimdal-gssapi)
-        endif (PKG_CONFIG_FOUND)
-
-        if (_GSSAPI_FOUND)
-            set(GSSAPI_FLAVOR_HEIMDAL TRUE)
-        else()
-            find_path(_GSSAPI_ROKEN
-                NAMES
-                    roken.h
-                PATHS
-                    ${GSSAPI_ROOT_DIR}/include
-                    ${_GSSAPI_INCLUDEDIR})
-            if (_GSSAPI_ROKEN)
-                set(GSSAPI_FLAVOR_HEIMDAL TRUE)
-            endif()
-        endif ()
-    endif()
-endif (UNIX)
+if(UNIX)
+       find_program(KRB5_CONFIG
+               NAMES krb5-config
+               PATHS ${GSSAPI_ROOT_DIR}/bin /opt/local/bin)
+       mark_as_advanced(KRB5_CONFIG)
+
+       if(KRB5_CONFIG)
+               # Check if we have MIT KRB5
+               execute_process(
+                       COMMAND ${KRB5_CONFIG} --vendor
+                       RESULT_VARIABLE _GSSAPI_VENDOR_RESULT
+                       OUTPUT_VARIABLE _GSSAPI_VENDOR_STRING)
+
+               if(_GSSAPI_VENDOR_STRING MATCHES ".*Massachusetts.*")
+                       set(GSSAPI_FLAVOR_MIT TRUE)
+               else()
+                       execute_process(
+                               COMMAND ${KRB5_CONFIG} --libs gssapi
+                               RESULT_VARIABLE _GSSAPI_LIBS_RESULT
+                               OUTPUT_VARIABLE _GSSAPI_LIBS_STRING)
+
+                       if(_GSSAPI_LIBS_STRING MATCHES ".*roken.*")
+                               set(GSSAPI_FLAVOR_HEIMDAL TRUE)
+                       endif()
+               endif()
+
+               # Get the include dir
+               execute_process(
+                       COMMAND ${KRB5_CONFIG} --cflags gssapi
+                       RESULT_VARIABLE _GSSAPI_INCLUDE_RESULT
+                       OUTPUT_VARIABLE _GSSAPI_INCLUDE_STRING)
+               string(REGEX REPLACE "(\r?\n)+$" "" _GSSAPI_INCLUDE_STRING "${_GSSAPI_INCLUDE_STRING}")
+               string(REGEX REPLACE " *-I" "" _GSSAPI_INCLUDEDIR "${_GSSAPI_INCLUDE_STRING}")
+       endif()
+
+       if(NOT GSSAPI_FLAVOR_MIT AND NOT GSSAPI_FLAVOR_HEIMDAL)
+               # Check for HEIMDAL
+               find_package(PkgConfig)
+               if(PKG_CONFIG_FOUND)
+                       pkg_check_modules(_GSSAPI heimdal-gssapi)
+               endif()
+
+               if(_GSSAPI_FOUND)
+                       set(GSSAPI_FLAVOR_HEIMDAL TRUE)
+               else()
+                       find_path(_GSSAPI_ROKEN
+                               NAMES roken.h
+                               PATHS ${GSSAPI_ROOT_DIR}/include ${_GSSAPI_INCLUDEDIR})
+                       if(_GSSAPI_ROKEN)
+                               set(GSSAPI_FLAVOR_HEIMDAL TRUE)
+                       endif()
+               endif()
+       endif()
+endif()
 
 find_path(GSSAPI_INCLUDE_DIR
-    NAMES
-        gssapi.h
-        gssapi/gssapi.h
-    PATHS
-        ${GSSAPI_ROOT_DIR}/include
-        ${_GSSAPI_INCLUDEDIR}
-)
-
-if (GSSAPI_FLAVOR_MIT)
-    find_library(GSSAPI_LIBRARY
-        NAMES
-            gssapi_krb5
-        PATHS
-            ${GSSAPI_ROOT_DIR}/lib
-            ${_GSSAPI_LIBDIR}
-    )
-
-    find_library(KRB5_LIBRARY
-        NAMES
-            krb5
-        PATHS
-            ${GSSAPI_ROOT_DIR}/lib
-            ${_GSSAPI_LIBDIR}
-    )
-
-    find_library(K5CRYPTO_LIBRARY
-        NAMES
-            k5crypto
-        PATHS
-            ${GSSAPI_ROOT_DIR}/lib
-            ${_GSSAPI_LIBDIR}
-    )
-
-    find_library(COM_ERR_LIBRARY
-        NAMES
-            com_err
-        PATHS
-            ${GSSAPI_ROOT_DIR}/lib
-            ${_GSSAPI_LIBDIR}
-    )
-
-    if (GSSAPI_LIBRARY)
-        set(GSSAPI_LIBRARIES
-            ${GSSAPI_LIBRARIES}
-            ${GSSAPI_LIBRARY}
-        )
-    endif (GSSAPI_LIBRARY)
-
-    if (KRB5_LIBRARY)
-        set(GSSAPI_LIBRARIES
-            ${GSSAPI_LIBRARIES}
-            ${KRB5_LIBRARY}
-        )
-    endif (KRB5_LIBRARY)
-
-    if (K5CRYPTO_LIBRARY)
-        set(GSSAPI_LIBRARIES
-            ${GSSAPI_LIBRARIES}
-            ${K5CRYPTO_LIBRARY}
-        )
-    endif (K5CRYPTO_LIBRARY)
-
-    if (COM_ERR_LIBRARY)
-        set(GSSAPI_LIBRARIES
-            ${GSSAPI_LIBRARIES}
-            ${COM_ERR_LIBRARY}
-        )
-    endif (COM_ERR_LIBRARY)
-endif (GSSAPI_FLAVOR_MIT)
-
-if (GSSAPI_FLAVOR_HEIMDAL)
-    find_library(GSSAPI_LIBRARY
-        NAMES
-            gssapi
-        PATHS
-            ${GSSAPI_ROOT_DIR}/lib
-            ${_GSSAPI_LIBDIR}
-    )
-
-    find_library(KRB5_LIBRARY
-        NAMES
-            krb5
-        PATHS
-            ${GSSAPI_ROOT_DIR}/lib
-            ${_GSSAPI_LIBDIR}
-    )
-
-    find_library(HCRYPTO_LIBRARY
-        NAMES
-            hcrypto
-        PATHS
-            ${GSSAPI_ROOT_DIR}/lib
-            ${_GSSAPI_LIBDIR}
-    )
-
-    find_library(COM_ERR_LIBRARY
-        NAMES
-            com_err
-        PATHS
-            ${GSSAPI_ROOT_DIR}/lib
-            ${_GSSAPI_LIBDIR}
-    )
-
-    find_library(HEIMNTLM_LIBRARY
-        NAMES
-            heimntlm
-        PATHS
-            ${GSSAPI_ROOT_DIR}/lib
-            ${_GSSAPI_LIBDIR}
-    )
-
-    find_library(HX509_LIBRARY
-        NAMES
-            hx509
-        PATHS
-            ${GSSAPI_ROOT_DIR}/lib
-            ${_GSSAPI_LIBDIR}
-    )
-
-    find_library(ASN1_LIBRARY
-        NAMES
-            asn1
-        PATHS
-            ${GSSAPI_ROOT_DIR}/lib
-            ${_GSSAPI_LIBDIR}
-    )
-
-    find_library(WIND_LIBRARY
-        NAMES
-            wind
-        PATHS
-            ${GSSAPI_ROOT_DIR}/lib
-            ${_GSSAPI_LIBDIR}
-    )
-
-    find_library(ROKEN_LIBRARY
-        NAMES
-            roken
-        PATHS
-            ${GSSAPI_ROOT_DIR}/lib
-            ${_GSSAPI_LIBDIR}
-    )
-
-    if (GSSAPI_LIBRARY)
-        set(GSSAPI_LIBRARIES
-            ${GSSAPI_LIBRARIES}
-            ${GSSAPI_LIBRARY}
-        )
-    endif (GSSAPI_LIBRARY)
-
-    if (KRB5_LIBRARY)
-        set(GSSAPI_LIBRARIES
-            ${GSSAPI_LIBRARIES}
-            ${KRB5_LIBRARY}
-        )
-    endif (KRB5_LIBRARY)
-
-    if (HCRYPTO_LIBRARY)
-        set(GSSAPI_LIBRARIES
-            ${GSSAPI_LIBRARIES}
-            ${HCRYPTO_LIBRARY}
-        )
-    endif (HCRYPTO_LIBRARY)
-
-    if (COM_ERR_LIBRARY)
-        set(GSSAPI_LIBRARIES
-            ${GSSAPI_LIBRARIES}
-            ${COM_ERR_LIBRARY}
-        )
-    endif (COM_ERR_LIBRARY)
-
-    if (HEIMNTLM_LIBRARY)
-        set(GSSAPI_LIBRARIES
-            ${GSSAPI_LIBRARIES}
-            ${HEIMNTLM_LIBRARY}
-        )
-    endif (HEIMNTLM_LIBRARY)
-
-    if (HX509_LIBRARY)
-        set(GSSAPI_LIBRARIES
-            ${GSSAPI_LIBRARIES}
-            ${HX509_LIBRARY}
-        )
-    endif (HX509_LIBRARY)
-
-    if (ASN1_LIBRARY)
-        set(GSSAPI_LIBRARIES
-            ${GSSAPI_LIBRARIES}
-            ${ASN1_LIBRARY}
-        )
-    endif (ASN1_LIBRARY)
-
-    if (WIND_LIBRARY)
-        set(GSSAPI_LIBRARIES
-            ${GSSAPI_LIBRARIES}
-            ${WIND_LIBRARY}
-        )
-    endif (WIND_LIBRARY)
-
-    if (ROKEN_LIBRARY)
-        set(GSSAPI_LIBRARIES
-            ${GSSAPI_LIBRARIES}
-            ${WIND_LIBRARY}
-        )
-    endif (ROKEN_LIBRARY)
-endif (GSSAPI_FLAVOR_HEIMDAL)
+       NAMES gssapi.h gssapi/gssapi.h
+       PATHS ${GSSAPI_ROOT_DIR}/include ${_GSSAPI_INCLUDEDIR})
+
+if(GSSAPI_FLAVOR_MIT)
+       find_library(GSSAPI_LIBRARY
+               NAMES gssapi_krb5
+               PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR})
+
+       find_library(KRB5_LIBRARY
+               NAMES krb5
+               PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR})
+
+       find_library(K5CRYPTO_LIBRARY
+               NAMES k5crypto
+               PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR})
+
+       find_library(COM_ERR_LIBRARY
+               NAMES com_err
+               PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR})
+
+       if(GSSAPI_LIBRARY)
+               set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${GSSAPI_LIBRARY})
+       endif()
+
+       if(KRB5_LIBRARY)
+               set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${KRB5_LIBRARY})
+       endif()
+
+       if(K5CRYPTO_LIBRARY)
+               set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${K5CRYPTO_LIBRARY})
+       endif()
+
+       if(COM_ERR_LIBRARY)
+               set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${COM_ERR_LIBRARY})
+       endif()
+endif()
+
+if(GSSAPI_FLAVOR_HEIMDAL)
+       find_library(GSSAPI_LIBRARY
+               NAMES gssapi
+               PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR})
+
+       find_library(KRB5_LIBRARY
+               NAMES krb5
+               PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR})
+
+       find_library(HCRYPTO_LIBRARY
+               NAMES hcrypto
+               PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR})
+
+       find_library(COM_ERR_LIBRARY
+               NAMES com_err
+               PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR})
+
+       find_library(HEIMNTLM_LIBRARY
+               NAMES heimntlm
+               PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR})
+
+       find_library(HX509_LIBRARY
+               NAMES hx509
+               PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR})
+
+       find_library(ASN1_LIBRARY
+               NAMES asn1
+               PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR})
+
+       find_library(WIND_LIBRARY
+               NAMES wind
+               PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR})
+
+       find_library(ROKEN_LIBRARY
+               NAMES roken
+               PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR})
+
+       if(GSSAPI_LIBRARY)
+               set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${GSSAPI_LIBRARY})
+       endif()
+
+       if(KRB5_LIBRARY)
+               set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${KRB5_LIBRARY})
+       endif()
+
+       if(HCRYPTO_LIBRARY)
+               set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${HCRYPTO_LIBRARY})
+       endif()
+
+       if(COM_ERR_LIBRARY)
+               set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${COM_ERR_LIBRARY})
+       endif()
+
+       if(HEIMNTLM_LIBRARY)
+               set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${HEIMNTLM_LIBRARY})
+       endif()
+
+       if(HX509_LIBRARY)
+               set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${HX509_LIBRARY})
+       endif()
+
+       if(ASN1_LIBRARY)
+               set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${ASN1_LIBRARY})
+       endif()
+
+       if(WIND_LIBRARY)
+               set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${WIND_LIBRARY})
+       endif()
+
+       if(ROKEN_LIBRARY)
+               set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${WIND_LIBRARY})
+       endif()
+endif()
 
 include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args(GSSAPI DEFAULT_MSG GSSAPI_LIBRARIES GSSAPI_INCLUDE_DIR)
 
-if (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
-    set(GSSAPI_FOUND TRUE)
-endif (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
+if(GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
+       set(GSSAPI_FOUND TRUE)
+endif(GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
 
 # show the GSSAPI_INCLUDE_DIRS and GSSAPI_LIBRARIES variables only in the advanced view
 mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES)
index dcf7249160c4a3e778bf0683a347be584a05e8a8..1b0c936d7ccdc819325d768bd4dcaf959238ca3e 100644 (file)
@@ -7,21 +7,21 @@
 # GSSFRAMEWORK_LDFLAGS
 #
 
-FIND_PATH(GSSFRAMEWORK_INCLUDE_DIR NAMES GSS.h)
-FIND_LIBRARY(GSSFRAMEWORK_LIBRARIES NAMES GSS)
-IF (GSSFRAMEWORK_INCLUDE_DIR AND GSSFRAMEWORK_LIBRARIES)
-       IF (NOT CoreFoundation_FIND_QUIETLY)
-               MESSAGE(STATUS "Found GSS.framework ${GSSFRAMEWORK_LIBRARIES}")
-       ENDIF()
-       SET(GSSFRAMEWORK_FOUND TRUE)
-       SET(GSSFRAMEWORK_LDFLAGS "-framework GSS")
-ENDIF ()
+find_path(GSSFRAMEWORK_INCLUDE_DIR NAMES GSS.h)
+find_library(GSSFRAMEWORK_LIBRARIES NAMES GSS)
+if(GSSFRAMEWORK_INCLUDE_DIR AND GSSFRAMEWORK_LIBRARIES)
+       if(NOT CoreFoundation_FIND_QUIETLY)
+               message(STATUS "Found GSS.framework ${GSSFRAMEWORK_LIBRARIES}")
+       endif()
+       set(GSSFRAMEWORK_FOUND TRUE)
+       set(GSSFRAMEWORK_LDFLAGS "-framework GSS")
+endif()
 
-IF (GSS_FIND_REQUIRED AND NOT GSSFRAMEWORK_FOUND)
-       MESSAGE(FATAL_ERROR "CoreFoundation not found")
-ENDIF()
+if(GSS_FIND_REQUIRED AND NOT GSSFRAMEWORK_FOUND)
+       message(FATAL_ERROR "CoreFoundation not found")
+endif()
 
-MARK_AS_ADVANCED(
+mark_as_advanced(
        GSSFRAMEWORK_INCLUDE_DIR
        GSSFRAMEWORK_LIBRARIES
        GSSFRAMEWORK_LDFLAGS
diff --git a/cmake/FindHTTPParser.cmake b/cmake/FindHTTPParser.cmake
new file mode 100644 (file)
index 0000000..3350190
--- /dev/null
@@ -0,0 +1,39 @@
+# - Try to find http-parser
+#
+# Defines the following variables:
+#
+# HTTP_PARSER_FOUND - system has http-parser
+# HTTP_PARSER_INCLUDE_DIR - the http-parser include directory
+# HTTP_PARSER_LIBRARIES - Link these to use http-parser
+# HTTP_PARSER_VERSION_MAJOR - major version
+# HTTP_PARSER_VERSION_MINOR - minor version
+# HTTP_PARSER_VERSION_STRING - the version of http-parser found
+
+# Find the header and library
+find_path(HTTP_PARSER_INCLUDE_DIR NAMES http_parser.h)
+find_library(HTTP_PARSER_LIBRARY NAMES http_parser libhttp_parser)
+
+# Found the header, read version
+if(HTTP_PARSER_INCLUDE_DIR AND EXISTS "${HTTP_PARSER_INCLUDE_DIR}/http_parser.h")
+       file(READ "${HTTP_PARSER_INCLUDE_DIR}/http_parser.h" HTTP_PARSER_H)
+       if(HTTP_PARSER_H)
+               string(REGEX REPLACE ".*#define[\t ]+HTTP_PARSER_VERSION_MAJOR[\t ]+([0-9]+).*" "\\1" HTTP_PARSER_VERSION_MAJOR "${HTTP_PARSER_H}")
+               string(REGEX REPLACE ".*#define[\t ]+HTTP_PARSER_VERSION_MINOR[\t ]+([0-9]+).*" "\\1" HTTP_PARSER_VERSION_MINOR "${HTTP_PARSER_H}")
+               set(HTTP_PARSER_VERSION_STRING "${HTTP_PARSER_VERSION_MAJOR}.${HTTP_PARSER_VERSION_MINOR}")
+       endif()
+       unset(HTTP_PARSER_H)
+endif()
+
+# Handle the QUIETLY and REQUIRED arguments and set HTTP_PARSER_FOUND
+# to TRUE if all listed variables are TRUE
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(HTTP_Parser REQUIRED_VARS HTTP_PARSER_INCLUDE_DIR HTTP_PARSER_LIBRARY)
+
+# Hide advanced variables
+mark_as_advanced(HTTP_PARSER_INCLUDE_DIR HTTP_PARSER_LIBRARY)
+
+# Set standard variables
+if(HTTP_PARSER_FOUND)
+       set(HTTP_PARSER_LIBRARIES ${HTTP_PARSER_LIBRARY})
+       set(HTTP_PARSER_INCLUDE_DIRS ${HTTP_PARSER_INCLUDE_DIR})
+endif()
diff --git a/cmake/FindHTTP_Parser.cmake b/cmake/FindHTTP_Parser.cmake
deleted file mode 100644 (file)
index d92bf75..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-# - Try to find http-parser
-#
-# Defines the following variables:
-#
-# HTTP_PARSER_FOUND - system has http-parser
-# HTTP_PARSER_INCLUDE_DIR - the http-parser include directory
-# HTTP_PARSER_LIBRARIES - Link these to use http-parser
-# HTTP_PARSER_VERSION_MAJOR - major version
-# HTTP_PARSER_VERSION_MINOR - minor version
-# HTTP_PARSER_VERSION_STRING - the version of http-parser found
-
-# Find the header and library
-FIND_PATH(HTTP_PARSER_INCLUDE_DIR NAMES http_parser.h)
-FIND_LIBRARY(HTTP_PARSER_LIBRARY NAMES http_parser libhttp_parser)
-
-# Found the header, read version
-if (HTTP_PARSER_INCLUDE_DIR AND EXISTS "${HTTP_PARSER_INCLUDE_DIR}/http_parser.h")
-       FILE(READ "${HTTP_PARSER_INCLUDE_DIR}/http_parser.h" HTTP_PARSER_H)
-       IF (HTTP_PARSER_H)
-               STRING(REGEX REPLACE ".*#define[\t ]+HTTP_PARSER_VERSION_MAJOR[\t ]+([0-9]+).*" "\\1" HTTP_PARSER_VERSION_MAJOR "${HTTP_PARSER_H}")
-               STRING(REGEX REPLACE ".*#define[\t ]+HTTP_PARSER_VERSION_MINOR[\t ]+([0-9]+).*" "\\1" HTTP_PARSER_VERSION_MINOR "${HTTP_PARSER_H}")
-               SET(HTTP_PARSER_VERSION_STRING "${HTTP_PARSER_VERSION_MAJOR}.${HTTP_PARSER_VERSION_MINOR}")
-       ENDIF()
-       UNSET(HTTP_PARSER_H)
-ENDIF()
-
-# Handle the QUIETLY and REQUIRED arguments and set HTTP_PARSER_FOUND
-# to TRUE if all listed variables are TRUE
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(HTTP_Parser REQUIRED_VARS HTTP_PARSER_INCLUDE_DIR HTTP_PARSER_LIBRARY)
-
-# Hide advanced variables
-MARK_AS_ADVANCED(HTTP_PARSER_INCLUDE_DIR HTTP_PARSER_LIBRARY)
-
-# Set standard variables
-IF (HTTP_PARSER_FOUND)
-       SET(HTTP_PARSER_LIBRARIES ${HTTP_PARSER_LIBRARY})
-       set(HTTP_PARSER_INCLUDE_DIRS ${HTTP_PARSER_INCLUDE_DIR})
-ENDIF()
index 3c66cdad41cfd7820455666444385d1fc39433a7..9e6ded99dc4da68e149707ce8e926838d0749eb3 100644 (file)
@@ -6,40 +6,40 @@
 # ICONV_LIBRARIES - Link these to use Iconv
 #
 
-IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
+if(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
        # Already in cache, be silent
-       SET(ICONV_FIND_QUIETLY TRUE)
-ENDIF()
+       set(ICONV_FIND_QUIETLY TRUE)
+endif()
 
-FIND_PATH(ICONV_INCLUDE_DIR iconv.h)
-CHECK_FUNCTION_EXISTS(iconv_open libc_has_iconv)
-FIND_LIBRARY(iconv_lib NAMES iconv libiconv libiconv-2 c)
+find_path(ICONV_INCLUDE_DIR iconv.h)
+check_function_exists(iconv_open libc_has_iconv)
+find_library(iconv_lib NAMES iconv libiconv libiconv-2 c)
 
-IF(ICONV_INCLUDE_DIR AND libc_has_iconv)
-       SET(ICONV_FOUND TRUE)
-       SET(ICONV_LIBRARIES "")
-       IF(NOT ICONV_FIND_QUIETLY)
-               MESSAGE(STATUS "Found Iconv: provided by libc")
-       ENDIF(NOT ICONV_FIND_QUIETLY)
-ELSEIF(ICONV_INCLUDE_DIR AND iconv_lib)
-       SET(ICONV_FOUND TRUE)
+if(ICONV_INCLUDE_DIR AND libc_has_iconv)
+       set(ICONV_FOUND TRUE)
+       set(ICONV_LIBRARIES "")
+       if(NOT ICONV_FIND_QUIETLY)
+               message(STATUS "Found Iconv: provided by libc")
+       endif(NOT ICONV_FIND_QUIETLY)
+elseif(ICONV_INCLUDE_DIR AND iconv_lib)
+       set(ICONV_FOUND TRUE)
        # split iconv into -L and -l linker options, so we can
        # set them for pkg-config
-       GET_FILENAME_COMPONENT(iconv_path ${iconv_lib} PATH)
-       GET_FILENAME_COMPONENT(iconv_name ${iconv_lib} NAME_WE)
-       STRING(REGEX REPLACE "^lib" "" iconv_name ${iconv_name})
-       SET(ICONV_LIBRARIES "-L${iconv_path} -l${iconv_name}")
+       get_filename_component(iconv_path ${iconv_lib} PATH)
+       get_filename_component(iconv_name ${iconv_lib} NAME_WE)
+       string(REGEX REPLACE "^lib" "" iconv_name ${iconv_name})
+       set(ICONV_LIBRARIES "-L${iconv_path} -l${iconv_name}")
 
-       IF(NOT ICONV_FIND_QUIETLY)
-               MESSAGE(STATUS "Found Iconv: ${ICONV_LIBRARIES}")
-       ENDIF(NOT ICONV_FIND_QUIETLY)
-ELSE()
-       IF(Iconv_FIND_REQUIRED)
-               MESSAGE(FATAL_ERROR "Could not find Iconv")
-       ENDIF(Iconv_FIND_REQUIRED)
-ENDIF()
+       if(NOT ICONV_FIND_QUIETLY)
+               message(STATUS "Found Iconv: ${ICONV_LIBRARIES}")
+       endif()
+else()
+       if(Iconv_FIND_REQUIRED)
+               message(FATAL_ERROR "Could not find Iconv")
+       endif(Iconv_FIND_REQUIRED)
+endif()
 
-MARK_AS_ADVANCED(
+mark_as_advanced(
        ICONV_INCLUDE_DIR
        ICONV_LIBRARIES
 )
index ff5893525a6e1f617c11b4817e51704dcebed80e..c571997c434800a82a2124f7aba947ded7a819f4 100644 (file)
@@ -2,12 +2,12 @@
 # LIBSSH2_INCLUDE_DIR - the libssh2 include directory
 # LIBSSH2_LIBRARY - the libssh2 library name
 
-FIND_PATH(LIBSSH2_INCLUDE_DIR libssh2.h)
+find_path(LIBSSH2_INCLUDE_DIR libssh2.h)
 
-FIND_LIBRARY(LIBSSH2_LIBRARY NAMES ssh2 libssh2)
+find_library(LIBSSH2_LIBRARY NAMES ssh2 libssh2)
 
-INCLUDE(FindPackageHandleStandardArgs)
+include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args(LibSSH2
-    REQUIRED_VARS LIBSSH2_LIBRARY LIBSSH2_INCLUDE_DIR)
+       REQUIRED_VARS LIBSSH2_LIBRARY LIBSSH2_INCLUDE_DIR)
 
-MARK_AS_ADVANCED(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY)
+mark_as_advanced(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY)
index 74ed61e5391f63e6591a51f1155b35601f8a4a0b..3a7cfad919c562de7ac0fc752425c211a1984063 100644 (file)
 # PCRE_FOUND   - True if pcre found.
 
 # Look for the header file.
-FIND_PATH(PCRE_INCLUDE_DIR NAMES pcreposix.h)
+find_path(PCRE_INCLUDE_DIR NAMES pcreposix.h)
 
 # Look for the library.
-FIND_LIBRARY(PCRE_LIBRARY NAMES pcre)
-FIND_LIBRARY(PCRE_POSIX_LIBRARY NAMES pcreposix)
+find_library(PCRE_LIBRARY NAMES pcre)
+find_library(PCRE_POSIX_LIBRARY NAMES pcreposix)
 
 # Handle the QUIETLY and REQUIRED arguments and set PCRE_FOUND to TRUE if all listed variables are TRUE.
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG PCRE_LIBRARY PCRE_POSIX_LIBRARY PCRE_INCLUDE_DIR)
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(PCRE DEFAULT_MSG PCRE_LIBRARY PCRE_POSIX_LIBRARY PCRE_INCLUDE_DIR)
 
 # Copy the results to the output variables.
-IF(PCRE_FOUND)
-       SET(PCRE_LIBRARIES ${PCRE_LIBRARY} ${PCRE_POSIX_LIBRARY})
-       SET(PCRE_INCLUDE_DIRS ${PCRE_INCLUDE_DIR})
-ELSE(PCRE_FOUND)
-       SET(PCRE_LIBRARIES)
-       SET(PCRE_INCLUDE_DIRS)
-ENDIF(PCRE_FOUND)
+if(PCRE_FOUND)
+       set(PCRE_LIBRARIES ${PCRE_LIBRARY} ${PCRE_POSIX_LIBRARY})
+       set(PCRE_INCLUDE_DIRS ${PCRE_INCLUDE_DIR})
+else(PCRE_FOUND)
+       set(PCRE_LIBRARIES)
+       set(PCRE_INCLUDE_DIRS)
+endif()
 
-MARK_AS_ADVANCED(PCRE_INCLUDE_DIRS PCRE_LIBRARIES)
+mark_as_advanced(PCRE_INCLUDE_DIRS PCRE_LIBRARIES)
index f8c5639d57c243868f9d63553333e1d57ac8e46d..d4b8e676184d2113e623ff10286ba2a99911deec 100644 (file)
 # PCRE2_FOUND  - True if pcre found.
 
 # Look for the header file.
-FIND_PATH(PCRE2_INCLUDE_DIR NAMES pcre2posix.h)
+find_path(PCRE2_INCLUDE_DIR NAMES pcre2posix.h)
 
 # Look for the library.
-FIND_LIBRARY(PCRE2_LIBRARY NAMES pcre2-8)
+find_library(PCRE2_LIBRARY NAMES pcre2-8)
 
 # Handle the QUIETLY and REQUIRED arguments and set PCRE2_FOUND to TRUE if all listed variables are TRUE.
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2 DEFAULT_MSG PCRE2_LIBRARY PCRE2_INCLUDE_DIR)
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(PCRE2 DEFAULT_MSG PCRE2_LIBRARY PCRE2_INCLUDE_DIR)
 
 # Copy the results to the output variables.
-IF(PCRE2_FOUND)
-       SET(PCRE2_LIBRARIES ${PCRE2_LIBRARY})
-       SET(PCRE2_INCLUDE_DIRS ${PCRE2_INCLUDE_DIR})
-ELSE(PCRE2_FOUND)
-       SET(PCRE2_LIBRARIES)
-       SET(PCRE2_INCLUDE_DIRS)
-ENDIF(PCRE2_FOUND)
+if(PCRE2_FOUND)
+       set(PCRE2_LIBRARIES ${PCRE2_LIBRARY})
+       set(PCRE2_INCLUDE_DIRS ${PCRE2_INCLUDE_DIR})
+else(PCRE2_FOUND)
+       set(PCRE2_LIBRARIES)
+       set(PCRE2_INCLUDE_DIRS)
+endif()
 
-MARK_AS_ADVANCED(PCRE2_INCLUDE_DIRS PCRE2_LIBRARIES)
+mark_as_advanced(PCRE2_INCLUDE_DIRS PCRE2_LIBRARIES)
index 49311c382a84f3eff5edd527fc4e878cfdd21672..220bb2ce21a4202c38e0682829fa26019ed47176 100644 (file)
@@ -1,28 +1,28 @@
-INCLUDE(FindPkgConfig)
+include(FindPkgConfig)
 
 # This function will find and set up a pkg-config based module.
 # If a pc-file was found, it will resolve library paths to
 # absolute paths. Furthermore, the function will automatically
 # fall back to use static libraries in case no dynamic libraries
 # were found.
-FUNCTION(FIND_PKGLIBRARIES prefix package)
-       PKG_CHECK_MODULES(${prefix} ${package})
-       IF(NOT ${prefix}_FOUND)
-               RETURN()
-       ENDIF()
+function(FIND_PKGLIBRARIES prefix package)
+       pkg_check_modules(${prefix} ${package})
+       if(NOT ${prefix}_FOUND)
+               return()
+       endif()
 
-       FOREACH(LIBRARY ${${prefix}_LIBRARIES})
-               FIND_LIBRARY(${LIBRARY}_RESOLVED ${LIBRARY} PATHS ${${prefix}_LIBRARY_DIRS})
-               IF(${${LIBRARY}_RESOLVED} STREQUAL "${LIBRARY}_RESOLVED-NOTFOUND")
-                       MESSAGE(FATAL_ERROR "could not resolve ${LIBRARY}")
-               ENDIF()
-               LIST(APPEND RESOLVED_LIBRARIES ${${LIBRARY}_RESOLVED})
-       ENDFOREACH(LIBRARY)
+       foreach(LIBRARY ${${prefix}_LIBRARIES})
+               find_library(${LIBRARY}_RESOLVED ${LIBRARY} PATHS ${${prefix}_LIBRARY_DIRS})
+               if(${${LIBRARY}_RESOLVED} STREQUAL "${LIBRARY}_RESOLVED-NOTFOUND")
+                       message(FATAL_ERROR "could not resolve ${LIBRARY}")
+               endif()
+               list(APPEND RESOLVED_LIBRARIES ${${LIBRARY}_RESOLVED})
+       endforeach()
 
-       SET(${prefix}_FOUND 1 PARENT_SCOPE)
-       SET(${prefix}_LIBRARIES ${RESOLVED_LIBRARIES} PARENT_SCOPE)
-       SET(${prefix}_INCLUDE_DIRS ${${prefix}_INCLUDE_DIRS} PARENT_SCOPE)
-       SET(${prefix}_LDFLAGS ${${prefix}_LDFLAGS} PARENT_SCOPE)
+       set(${prefix}_FOUND 1 PARENT_SCOPE)
+       set(${prefix}_LIBRARIES ${RESOLVED_LIBRARIES} PARENT_SCOPE)
+       set(${prefix}_INCLUDE_DIRS ${${prefix}_INCLUDE_DIRS} PARENT_SCOPE)
+       set(${prefix}_LDFLAGS ${${prefix}_LDFLAGS} PARENT_SCOPE)
 
-       MESSAGE(STATUS "  Resolved libraries: ${RESOLVED_LIBRARIES}")
-ENDFUNCTION()
+       message(STATUS "  Resolved libraries: ${RESOLVED_LIBRARIES}")
+endfunction()
index a538c02c1ec96f2eeec2f6c45a147206b1c608af..14a2e2dd7bb8c9dcd005dd69a29728fd50b16a1b 100644 (file)
@@ -7,22 +7,22 @@
 # SECURITY_HAS_SSLCREATECONTEXT
 #
 
-FIND_PATH(SECURITY_INCLUDE_DIR NAMES Security/Security.h)
-FIND_LIBRARY(SECURITY_LIBRARIES NAMES Security)
-IF (SECURITY_INCLUDE_DIR AND SECURITY_LIBRARIES)
-       IF (NOT Security_FIND_QUIETLY)
-               MESSAGE(STATUS "Found Security ${SECURITY_LIBRARIES}")
-       ENDIF()
-       SET(SECURITY_FOUND TRUE)
-       SET(SECURITY_LDFLAGS "-framework Security")
-       CHECK_LIBRARY_EXISTS("${SECURITY_LIBRARIES}" SSLCreateContext "Security/SecureTransport.h" SECURITY_HAS_SSLCREATECONTEXT)
-ENDIF ()
+find_path(SECURITY_INCLUDE_DIR NAMES Security/Security.h)
+find_library(SECURITY_LIBRARIES NAMES Security)
+if(SECURITY_INCLUDE_DIR AND SECURITY_LIBRARIES)
+       if(NOT Security_FIND_QUIETLY)
+               message(STATUS "Found Security ${SECURITY_LIBRARIES}")
+       endif()
+       set(SECURITY_FOUND TRUE)
+       set(SECURITY_LDFLAGS "-framework Security")
+       check_library_exists("${SECURITY_LIBRARIES}" SSLCreateContext "Security/SecureTransport.h" SECURITY_HAS_SSLCREATECONTEXT)
+endif()
 
-IF (Security_FIND_REQUIRED AND NOT SECURITY_FOUND)
-       MESSAGE(FATAL_ERROR "Security not found")
-ENDIF()
+if(Security_FIND_REQUIRED AND NOT SECURITY_FOUND)
+       message(FATAL_ERROR "Security not found")
+endif()
 
-MARK_AS_ADVANCED(
+mark_as_advanced(
        SECURITY_INCLUDE_DIR
        SECURITY_LIBRARIES
 )
index a4a09fa812061cfa5a2cb2332082fbec44f2b9b5..9dfdf51c4e7886546fd7047129943e77a8cf49e1 100644 (file)
@@ -1,26 +1,20 @@
-INCLUDE(FeatureSummary)
+include(FeatureSummary)
 
-CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtim "sys/types.h;sys/stat.h"
+check_struct_has_member("struct stat" st_mtim "sys/types.h;sys/stat.h"
        HAVE_STRUCT_STAT_ST_MTIM LANGUAGE C)
-CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtimespec "sys/types.h;sys/stat.h"
+check_struct_has_member("struct stat" st_mtimespec "sys/types.h;sys/stat.h"
        HAVE_STRUCT_STAT_ST_MTIMESPEC LANGUAGE C)
-CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_nsec sys/stat.h
+check_struct_has_member("struct stat" st_mtime_nsec sys/stat.h
        HAVE_STRUCT_STAT_MTIME_NSEC LANGUAGE C)
 
-IF (HAVE_STRUCT_STAT_ST_MTIM)
-       CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec sys/stat.h
+if(HAVE_STRUCT_STAT_ST_MTIM)
+       check_struct_has_member("struct stat" st_mtim.tv_nsec sys/stat.h
                HAVE_STRUCT_STAT_NSEC LANGUAGE C)
-ELSEIF (HAVE_STRUCT_STAT_ST_MTIMESPEC)
-       CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec sys/stat.h
+elseif(HAVE_STRUCT_STAT_ST_MTIMESPEC)
+       check_struct_has_member("struct stat" st_mtimespec.tv_nsec sys/stat.h
                HAVE_STRUCT_STAT_NSEC LANGUAGE C)
-ELSE ()
-       SET( HAVE_STRUCT_STAT_NSEC ON )
-ENDIF()
+else()
+       set(HAVE_STRUCT_STAT_NSEC ON )
+endif()
 
-IF (HAVE_STRUCT_STAT_NSEC OR WIN32)
-       OPTION( USE_NSEC                "Care about sub-second file mtimes and ctimes"  ON  )
-ELSE()
-       SET(USE_NSEC OFF)
-ENDIF()
-
-ADD_FEATURE_INFO(nanoseconds USE_NSEC "whether to use sub-second file mtimes and ctimes")
+add_feature_info(nanoseconds USE_NSEC "support nanosecond precision file mtimes and ctimes")
index 73b79528ac64b661b85480dbae5d630933f422cf..3449c9d54e9a5b736ea2705df92fec7dba258e72 100644 (file)
@@ -1,14 +1,14 @@
-INCLUDE(EnableWarnings)
+include(EnableWarnings)
 
-IF (APPLE)
+if(APPLE)
        # We cannot simply CHECK_FUNCTION_EXISTS on macOS because
        # MACOSX_DEPLOYMENT_TARGET may be set to a version in the past
        # that doesn't have futimens.  Instead we need to enable warnings
        # as errors, then check for the symbol existing in `sys/stat.h`,
        # then reset warnings as errors.
-       ENABLE_WARNINGS(error)
-       CHECK_SYMBOL_EXISTS(futimens sys/stat.h HAVE_FUTIMENS)
-       DISABLE_WARNINGS(error)
-ELSE ()
-       CHECK_FUNCTION_EXISTS(futimens HAVE_FUTIMENS)
-ENDIF ()
+       enable_warnings(error)
+       check_symbol_exists(futimens sys/stat.h HAVE_FUTIMENS)
+       disable_warnings(error)
+else()
+       check_function_exists(futimens HAVE_FUTIMENS)
+endif()
index 93297555e818812b013a5b7887b198de2cecb679..a4a5487c296c13a976d170c24379383006e56075 100644 (file)
 # Hint
 #  MBEDTLS_ROOT_DIR can be pointed to a local mbedTLS installation.
 
-SET(_MBEDTLS_ROOT_HINTS
-    ${MBEDTLS_ROOT_DIR}
-    ENV MBEDTLS_ROOT_DIR
-)
+set(_MBEDTLS_ROOT_HINTS
+       ${MBEDTLS_ROOT_DIR}
+       ENV MBEDTLS_ROOT_DIR)
 
-SET(_MBEDTLS_ROOT_HINTS_AND_PATHS
-    HINTS ${_MBEDTLS_ROOT_HINTS}
-    PATHS ${_MBEDTLS_ROOT_PATHS}
-)
+set(_MBEDTLS_ROOT_HINTS_AND_PATHS
+       HINTS ${_MBEDTLS_ROOT_HINTS}
+       PATHS ${_MBEDTLS_ROOT_PATHS})
 
-FIND_PATH(MBEDTLS_INCLUDE_DIR
-    NAMES mbedtls/version.h
-    ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
-    PATH_SUFFIXES include
-)
+find_path(MBEDTLS_INCLUDE_DIR
+       NAMES mbedtls/version.h
+       ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
+       PATH_SUFFIXES include)
 
-IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARIES)
-    # Already in cache, be silent
-    SET(MBEDTLS_FIND_QUIETLY TRUE)
-ENDIF()
+if(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARIES)
+       # Already in cache, be silent
+       set(MBEDTLS_FIND_QUIETLY TRUE)
+endif()
 
-FIND_LIBRARY(MBEDTLS_LIBRARY
-    NAMES mbedtls libmbedtls
-    ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
-    PATH_SUFFIXES library
-)
-FIND_LIBRARY(MBEDX509_LIBRARY
-    NAMES mbedx509 libmbedx509
-    ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
-    PATH_SUFFIXES library
-)
-FIND_LIBRARY(MBEDCRYPTO_LIBRARY
-    NAMES mbedcrypto libmbedcrypto
-    ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
-    PATH_SUFFIXES library
-)
+find_library(MBEDTLS_LIBRARY
+       NAMES mbedtls libmbedtls
+       ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
+       PATH_SUFFIXES library)
+find_library(MBEDX509_LIBRARY
+       NAMES mbedx509 libmbedx509
+       ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
+       PATH_SUFFIXES library)
+find_library(MBEDCRYPTO_LIBRARY
+       NAMES mbedcrypto libmbedcrypto
+       ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
+       PATH_SUFFIXES library)
 
-IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY)
-     SET(MBEDTLS_FOUND TRUE)
-ENDIF()
+if(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY)
+        set(MBEDTLS_FOUND TRUE)
+endif()
 
-IF(MBEDTLS_FOUND)
-    # split mbedTLS into -L and -l linker options, so we can set them for pkg-config
-    GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_DIR ${MBEDTLS_LIBRARY} PATH)
-    GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY} NAME_WE)
-    GET_FILENAME_COMPONENT(MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY} NAME_WE)
-    GET_FILENAME_COMPONENT(MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY} NAME_WE)
-    STRING(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE})
-    STRING(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE})
-    STRING(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE})
-    SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}")
+if(MBEDTLS_FOUND)
+       # split mbedTLS into -L and -l linker options, so we can set them for pkg-config
+       get_filename_component(MBEDTLS_LIBRARY_DIR ${MBEDTLS_LIBRARY} PATH)
+       get_filename_component(MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY} NAME_WE)
+       get_filename_component(MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY} NAME_WE)
+       get_filename_component(MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY} NAME_WE)
+       string(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE})
+       string(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE})
+       string(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE})
+       set(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}")
 
-    IF(NOT MBEDTLS_FIND_QUIETLY)
-        MESSAGE(STATUS "Found mbedTLS:")
-        FILE(READ ${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h MBEDTLSCONTENT)
-        STRING(REGEX MATCH "MBEDTLS_VERSION_STRING +\"[0-9|.]+\"" MBEDTLSMATCH ${MBEDTLSCONTENT})
-        IF (MBEDTLSMATCH)
-            STRING(REGEX REPLACE "MBEDTLS_VERSION_STRING +\"([0-9|.]+)\"" "\\1" MBEDTLS_VERSION ${MBEDTLSMATCH})
-            MESSAGE(STATUS "  version ${MBEDTLS_VERSION}")
-        ENDIF(MBEDTLSMATCH)
-        MESSAGE(STATUS "  TLS: ${MBEDTLS_LIBRARY}")
-        MESSAGE(STATUS "  X509: ${MBEDX509_LIBRARY}")
-        MESSAGE(STATUS "  Crypto: ${MBEDCRYPTO_LIBRARY}")
-    ENDIF(NOT MBEDTLS_FIND_QUIETLY)
-ELSE(MBEDTLS_FOUND)
-    IF(MBEDTLS_FIND_REQUIRED)
-        MESSAGE(FATAL_ERROR "Could not find mbedTLS")
-    ENDIF(MBEDTLS_FIND_REQUIRED)
-ENDIF(MBEDTLS_FOUND)
+       if(NOT MBEDTLS_FIND_QUIETLY)
+               message(STATUS "Found mbedTLS:")
+               file(READ ${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h MBEDTLSCONTENT)
+               string(REGEX MATCH "MBEDTLS_VERSION_STRING +\"[0-9|.]+\"" MBEDTLSMATCH ${MBEDTLSCONTENT})
+               if(MBEDTLSMATCH)
+                   string(REGEX REPLACE "MBEDTLS_VERSION_STRING +\"([0-9|.]+)\"" "\\1" MBEDTLS_VERSION ${MBEDTLSMATCH})
+                   message(STATUS "  version ${MBEDTLS_VERSION}")
+               endif()
+               message(STATUS "  TLS: ${MBEDTLS_LIBRARY}")
+               message(STATUS "  X509: ${MBEDX509_LIBRARY}")
+               message(STATUS "  Crypto: ${MBEDCRYPTO_LIBRARY}")
+       endif()
+else(MBEDTLS_FOUND)
+       if(MBEDTLS_FIND_REQUIRED)
+               message(FATAL_ERROR "Could not find mbedTLS")
+       endif()
+endif()
 
-MARK_AS_ADVANCED(
-    MBEDTLS_INCLUDE_DIR
-    MBEDTLS_LIBRARY_DIR
-    MBEDTLS_LIBRARIES
-    MBEDTLS_LIBRARY
-    MBEDX509_LIBRARY
-    MBEDCRYPTO_LIBRARY
-)
+mark_as_advanced(
+       MBEDTLS_INCLUDE_DIR
+       MBEDTLS_LIBRARY_DIR
+       MBEDTLS_LIBRARIES
+       MBEDTLS_LIBRARY
+       MBEDX509_LIBRARY
+       MBEDCRYPTO_LIBRARY)
index e2e09b4ce15443f3a335fb5d92b58bfa09c38ee1..4f928ac081f040fe9c8bc04a362033781819fecd 100644 (file)
@@ -1,22 +1,22 @@
 # This function splits the sources files up into their appropriate
 # subdirectories.  This is especially useful for IDEs like Xcode and
-# Visual Studio, so that you can navigate into the libgit2_clar project,
+# Visual Studio, so that you can navigate into the libgit2_tests project,
 # and see the folders within the tests folder (instead of just seeing all
 # source and tests in a single folder.)
-FUNCTION(IDE_SPLIT_SOURCES target)
-       IF(MSVC_IDE OR CMAKE_GENERATOR STREQUAL Xcode)
-               GET_TARGET_PROPERTY(sources ${target} SOURCES)
-               FOREACH(source ${sources})
-                       IF(source MATCHES ".*/")
-                               STRING(REPLACE ${libgit2_SOURCE_DIR}/ "" rel ${source})
-                               IF(rel)
-                                       STRING(REGEX REPLACE "/([^/]*)$" "" rel ${rel})
-                                       IF(rel)
-                                               STRING(REPLACE "/" "\\\\" rel ${rel})
-                                               SOURCE_GROUP(${rel} FILES ${source})
-                                       ENDIF()
-                               ENDIF()
-                       ENDIF()
-               ENDFOREACH()
-       ENDIF()
-ENDFUNCTION()
+function(IDE_SPLIT_SOURCES target)
+       if(MSVC_IDE OR CMAKE_GENERATOR STREQUAL Xcode)
+               get_target_property(sources ${target} SOURCES)
+               foreach(source ${sources})
+                       if(source MATCHES ".*/")
+                               string(REPLACE ${PROJECT_SOURCE_DIR}/ "" rel ${source})
+                               if(rel)
+                                       string(REGEX REPLACE "/([^/]*)$" "" rel ${rel})
+                                       if(rel)
+                                               string(REPLACE "/" "\\\\" rel ${rel})
+                                               source_group(${rel} FILES ${source})
+                                       endif()
+                               endif()
+                       endif()
+               endforeach()
+       endif()
+endfunction()
index 54c5e294cc7a88baf983cc3be1a4f5bc054f7d82..c8939e63a2eba8134db70db6c6576245437ed486 100644 (file)
@@ -2,76 +2,76 @@
 #
 
 function(pkg_build_config)
-    set(options)
-    set(oneValueArgs NAME DESCRIPTION VERSION FILENAME LIBS_SELF)
-    set(multiValueArgs LIBS PRIVATE_LIBS REQUIRES CFLAGS)
+       set(options)
+       set(oneValueArgs NAME DESCRIPTION VERSION FILENAME LIBS_SELF)
+       set(multiValueArgs LIBS PRIVATE_LIBS REQUIRES CFLAGS)
 
-    cmake_parse_arguments(PKGCONFIG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+       cmake_parse_arguments(PKGCONFIG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
-    if (NOT DEFINED PKGCONFIG_FILENAME AND DEFINED PKGCONFIG_NAME)
-        set(PKGCONFIG_FILENAME ${PKGCONFIG_NAME})
-    endif()
-    if (NOT DEFINED PKGCONFIG_FILENAME)
-        message(FATAL_ERROR "Missing FILENAME argument")
-    endif()
-    set(PKGCONFIG_FILE "${PROJECT_BINARY_DIR}/${PKGCONFIG_FILENAME}.pc")
+       if (NOT DEFINED PKGCONFIG_FILENAME AND DEFINED PKGCONFIG_NAME)
+               set(PKGCONFIG_FILENAME ${PKGCONFIG_NAME})
+       endif()
+       if (NOT DEFINED PKGCONFIG_FILENAME)
+               message(FATAL_ERROR "Missing FILENAME argument")
+       endif()
+       set(PKGCONFIG_FILE "${PROJECT_BINARY_DIR}/${PKGCONFIG_FILENAME}.pc")
 
-    if (NOT DEFINED PKGCONFIG_DESCRIPTION)
-        message(FATAL_ERROR "Missing DESCRIPTION argument")
-    endif()
+       if (NOT DEFINED PKGCONFIG_DESCRIPTION)
+               message(FATAL_ERROR "Missing DESCRIPTION argument")
+       endif()
 
-    if (NOT DEFINED PKGCONFIG_VERSION)
-        message(FATAL_ERROR "Missing VERSION argument")
-    endif()
+       if (NOT DEFINED PKGCONFIG_VERSION)
+               message(FATAL_ERROR "Missing VERSION argument")
+       endif()
 
-    # Write .pc "header"
-    file(WRITE "${PKGCONFIG_FILE}"
-        "prefix=\"${CMAKE_INSTALL_PREFIX}\"\n"
-        "libdir=\"${CMAKE_INSTALL_FULL_LIBDIR}\"\n"
-        "includedir=\"${CMAKE_INSTALL_FULL_INCLUDEDIR}\"\n"
-        "\n"
-        "Name: ${PKGCONFIG_NAME}\n"
-        "Description: ${PKGCONFIG_DESCRIPTION}\n"
-        "Version: ${PKGCONFIG_VERSION}\n"
-    )
+       # Write .pc "header"
+       file(WRITE "${PKGCONFIG_FILE}"
+               "prefix=\"${CMAKE_INSTALL_PREFIX}\"\n"
+               "libdir=\"${CMAKE_INSTALL_FULL_LIBDIR}\"\n"
+               "includedir=\"${CMAKE_INSTALL_FULL_INCLUDEDIR}\"\n"
+               "\n"
+               "Name: ${PKGCONFIG_NAME}\n"
+               "Description: ${PKGCONFIG_DESCRIPTION}\n"
+               "Version: ${PKGCONFIG_VERSION}\n"
+       )
 
-    # Prepare Libs
-    if(NOT DEFINED PKGCONFIG_LIBS_SELF)
-        set(PKGCONFIG_LIBS_SELF "${PKGCONFIG_FILE}")
-    endif()
+       # Prepare Libs
+       if(NOT DEFINED PKGCONFIG_LIBS_SELF)
+               set(PKGCONFIG_LIBS_SELF "${PKGCONFIG_FILE}")
+       endif()
 
-    if(NOT DEFINED PKGCONFIG_LIBS)
-        set(PKGCONFIG_LIBS "-l${PKGCONFIG_LIBS_SELF}")
-    else()
-        list(INSERT PKGCONFIG_LIBS 0 "-l${PKGCONFIG_LIBS_SELF}")
-    endif()
+       if(NOT DEFINED PKGCONFIG_LIBS)
+               set(PKGCONFIG_LIBS "-l${PKGCONFIG_LIBS_SELF}")
+       else()
+               list(INSERT PKGCONFIG_LIBS 0 "-l${PKGCONFIG_LIBS_SELF}")
+       endif()
 
-    list(REMOVE_DUPLICATES PKGCONFIG_LIBS)
-    string(REPLACE ";" " " PKGCONFIG_LIBS "${PKGCONFIG_LIBS}")
-    file(APPEND "${PKGCONFIG_FILE}" "Libs: -L\${libdir} ${PKGCONFIG_LIBS}\n")
+       list(REMOVE_DUPLICATES PKGCONFIG_LIBS)
+       string(REPLACE ";" " " PKGCONFIG_LIBS "${PKGCONFIG_LIBS}")
+       file(APPEND "${PKGCONFIG_FILE}" "Libs: -L\${libdir} ${PKGCONFIG_LIBS}\n")
 
-    # Prepare Libs.private
-    if(DEFINED PKGCONFIG_PRIVATE_LIBS)
-        list(REMOVE_DUPLICATES PKGCONFIG_PRIVATE_LIBS)
-        string(REPLACE ";" " " PKGCONFIG_PRIVATE_LIBS "${PKGCONFIG_PRIVATE_LIBS}")
-        file(APPEND "${PKGCONFIG_FILE}" "Libs.private: ${PKGCONFIG_PRIVATE_LIBS}\n")
-    endif()
+       # Prepare Libs.private
+       if(DEFINED PKGCONFIG_PRIVATE_LIBS)
+               list(REMOVE_DUPLICATES PKGCONFIG_PRIVATE_LIBS)
+               string(REPLACE ";" " " PKGCONFIG_PRIVATE_LIBS "${PKGCONFIG_PRIVATE_LIBS}")
+               file(APPEND "${PKGCONFIG_FILE}" "Libs.private: ${PKGCONFIG_PRIVATE_LIBS}\n")
+       endif()
 
-    # Prepare Requires.private
-    if(DEFINED PKGCONFIG_REQUIRES)
-        list(REMOVE_DUPLICATES PKGCONFIG_REQUIRES)
-        string(REPLACE ";" " " PKGCONFIG_REQUIRES "${PKGCONFIG_REQUIRES}")
-        file(APPEND "${PKGCONFIG_FILE}" "Requires.private: ${PKGCONFIG_REQUIRES}\n")
-    endif()
+       # Prepare Requires.private
+       if(DEFINED PKGCONFIG_REQUIRES)
+               list(REMOVE_DUPLICATES PKGCONFIG_REQUIRES)
+               string(REPLACE ";" " " PKGCONFIG_REQUIRES "${PKGCONFIG_REQUIRES}")
+               file(APPEND "${PKGCONFIG_FILE}" "Requires.private: ${PKGCONFIG_REQUIRES}\n")
+       endif()
 
-    # Prepare Cflags
-    if(DEFINED PKGCONFIG_CFLAGS)
-        string(REPLACE ";" " " PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS}")
-    else()
-        set(PKGCONFIG_CFLAGS "")
-    endif()
-    file(APPEND "${PKGCONFIG_FILE}" "Cflags: -I\${includedir} ${PKGCONFIG_CFLAGS}\n")
+       # Prepare Cflags
+       if(DEFINED PKGCONFIG_CFLAGS)
+               string(REPLACE ";" " " PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS}")
+       else()
+               set(PKGCONFIG_CFLAGS "")
+       endif()
+       file(APPEND "${PKGCONFIG_FILE}" "Cflags: -I\${includedir} ${PKGCONFIG_CFLAGS}\n")
 
-    # Install .pc file
-    install(FILES "${PKGCONFIG_FILE}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+       # Install .pc file
+       install(FILES "${PKGCONFIG_FILE}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
 endfunction()
index b5b99a6904736ba751af098bf5106e6106618bf0..586c17d05286a6fef67b1148ffb00b7e467710c1 100644 (file)
@@ -1,20 +1,20 @@
-FUNCTION(SanitizeBool VAR)
-       STRING(TOLOWER "${${VAR}}" VALUE)
-       IF(VALUE STREQUAL "on")
-               SET(${VAR} "ON" PARENT_SCOPE)
-       ELSEIF(VALUE STREQUAL "yes")
-               SET(${VAR} "ON" PARENT_SCOPE)
-       ELSEIF(VALUE STREQUAL "true")
-               SET(${VAR} "ON" PARENT_SCOPE)
-       ELSEIF(VALUE STREQUAL "1")
-               SET(${VAR} "ON" PARENT_SCOPE)
-       ELSEIF(VALUE STREQUAL "off")
-               SET(${VAR} "OFF" PARENT_SCOPE)
-       ELSEIF(VALUE STREQUAL "no")
-               SET(${VAR} "OFF" PARENT_SCOPE)
-       ELSEIF(VALUE STREQUAL "false")
-               SET(${VAR} "OFF" PARENT_SCOPE)
-       ELSEIF(VALUE STREQUAL "0")
-               SET(${VAR} "OFF" PARENT_SCOPE)
-       ENDIF()
-ENDFUNCTION()
+function(SanitizeBool VAR)
+       string(TOLOWER "${${VAR}}" VALUE)
+       if(VALUE STREQUAL "on")
+               set(${VAR} "ON" PARENT_SCOPE)
+       elseif(VALUE STREQUAL "yes")
+               set(${VAR} "ON" PARENT_SCOPE)
+       elseif(VALUE STREQUAL "true")
+               set(${VAR} "ON" PARENT_SCOPE)
+       elseif(VALUE STREQUAL "1")
+               set(${VAR} "ON" PARENT_SCOPE)
+       elseif(VALUE STREQUAL "off")
+               set(${VAR} "OFF" PARENT_SCOPE)
+       elseif(VALUE STREQUAL "no")
+               set(${VAR} "OFF" PARENT_SCOPE)
+       elseif(VALUE STREQUAL "false")
+               set(${VAR} "OFF" PARENT_SCOPE)
+       elseif(VALUE STREQUAL "0")
+               set(${VAR} "OFF" PARENT_SCOPE)
+       endif()
+endfunction()
index 0a42eeefdfdb0ace1bf125fce56183875e492435..24e2d68b9a7f6f715f1bda0a835a93f04248e48e 100644 (file)
@@ -1,48 +1,48 @@
-INCLUDE(SanitizeBool)
+include(SanitizeBool)
 
 # We try to find any packages our backends might use
-FIND_PACKAGE(GSSAPI)
-IF (CMAKE_SYSTEM_NAME MATCHES "Darwin")
-       INCLUDE(FindGSSFramework)
-ENDIF()
+find_package(GSSAPI)
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+       include(FindGSSFramework)
+endif()
 
-IF(USE_GSSAPI)
+if(USE_GSSAPI)
        # Auto-select GSS backend
-       SanitizeBool(USE_GSSAPI)
-       IF (USE_GSSAPI STREQUAL ON)
-               IF (GSSFRAMEWORK_FOUND)
-                       SET(USE_GSSAPI "GSS.framework")
-               ELSEIF(GSSAPI_FOUND)
-                       SET(USE_GSSAPI "gssapi")
-               ELSE()
-                       MESSAGE(FATAL_ERROR "Unable to autodetect a usable GSS backend."
+       sanitizebool(USE_GSSAPI)
+       if(USE_GSSAPI STREQUAL ON)
+               if(GSSFRAMEWORK_FOUND)
+                       set(USE_GSSAPI "GSS.framework")
+               elseif(GSSAPI_FOUND)
+                       set(USE_GSSAPI "gssapi")
+               else()
+                       message(FATAL_ERROR "Unable to autodetect a usable GSS backend."
                                "Please pass the backend name explicitly (-DUSE_GSS=backend)")
-               ENDIF()
-       ENDIF()
+               endif()
+       endif()
 
        # Check that we can find what's required for the selected backend
-       IF (USE_GSSAPI STREQUAL "GSS.framework")
-               IF (NOT GSSFRAMEWORK_FOUND)
-                       MESSAGE(FATAL_ERROR "Asked for GSS.framework backend, but it wasn't found")
-               ENDIF()
+       if(USE_GSSAPI STREQUAL "GSS.framework")
+               if(NOT GSSFRAMEWORK_FOUND)
+                       message(FATAL_ERROR "Asked for GSS.framework backend, but it wasn't found")
+               endif()
 
-               LIST(APPEND LIBGIT2_LIBS ${GSSFRAMEWORK_LIBRARIES})
+               list(APPEND LIBGIT2_SYSTEM_LIBS ${GSSFRAMEWORK_LIBRARIES})
 
-               SET(GIT_GSSFRAMEWORK 1)
-               ADD_FEATURE_INFO(SPNEGO GIT_GSSFRAMEWORK "SPNEGO authentication support (${USE_GSSAPI})")
-       ELSEIF (USE_GSSAPI STREQUAL "gssapi")
-               IF (NOT GSSAPI_FOUND)
-                       MESSAGE(FATAL_ERROR "Asked for gssapi GSS backend, but it wasn't found")
-               ENDIF()
+               set(GIT_GSSFRAMEWORK 1)
+               add_feature_info(SPNEGO GIT_GSSFRAMEWORK "SPNEGO authentication support (${USE_GSSAPI})")
+       elseif(USE_GSSAPI STREQUAL "gssapi")
+               if(NOT GSSAPI_FOUND)
+                       message(FATAL_ERROR "Asked for gssapi GSS backend, but it wasn't found")
+               endif()
 
-               LIST(APPEND LIBGIT2_LIBS ${GSSAPI_LIBRARIES})
+               list(APPEND LIBGIT2_SYSTEM_LIBS ${GSSAPI_LIBRARIES})
 
-               SET(GIT_GSSAPI 1)
-               ADD_FEATURE_INFO(SPNEGO GIT_GSSAPI "SPNEGO authentication support (${USE_GSSAPI})")
-       ELSE()
-               MESSAGE(FATAL_ERROR "Asked for backend ${USE_GSSAPI} but it wasn't found")
-       ENDIF()
-ELSE()
-       SET(GIT_GSSAPI 0)
-       ADD_FEATURE_INFO(SPNEGO NO "SPNEGO authentication support")
-ENDIF()
+               set(GIT_GSSAPI 1)
+               add_feature_info(SPNEGO GIT_GSSAPI "SPNEGO authentication support (${USE_GSSAPI})")
+       else()
+               message(FATAL_ERROR "Asked for backend ${USE_GSSAPI} but it wasn't found")
+       endif()
+else()
+       set(GIT_GSSAPI 0)
+       add_feature_info(SPNEGO NO "SPNEGO authentication support")
+endif()
diff --git a/cmake/SelectHTTPParser.cmake b/cmake/SelectHTTPParser.cmake
new file mode 100644 (file)
index 0000000..955aea3
--- /dev/null
@@ -0,0 +1,19 @@
+# Optional external dependency: http-parser
+if(USE_HTTP_PARSER STREQUAL "system")
+       find_package(HTTPParser)
+
+       if(HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2)
+               list(APPEND LIBGIT2_SYSTEM_INCLUDES ${HTTP_PARSER_INCLUDE_DIRS})
+               list(APPEND LIBGIT2_SYSTEM_LIBS ${HTTP_PARSER_LIBRARIES})
+               list(APPEND LIBGIT2_PC_LIBS "-lhttp_parser")
+               add_feature_info(http-parser ON "http-parser support (system)")
+       else()
+               message(FATAL_ERROR "http-parser support was requested but not found")
+       endif()
+else()
+       message(STATUS "http-parser version 2 was not found or disabled; using bundled 3rd-party sources.")
+       add_subdirectory("${PROJECT_SOURCE_DIR}/deps/http-parser" "${PROJECT_BINARY_DIR}/deps/http-parser")
+       list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${PROJECT_SOURCE_DIR}/deps/http-parser")
+       list(APPEND LIBGIT2_DEPENDENCY_OBJECTS "$<TARGET_OBJECTS:http-parser>")
+       add_feature_info(http-parser ON "http-parser support (bundled)")
+endif()
index 4998f0f2ac92154bc3e40860175ccee2ac91a6d9..79319502eb3de5390106cb50c8a61e584d02801e 100644 (file)
-INCLUDE(SanitizeBool)
+include(SanitizeBool)
 
 # We try to find any packages our backends might use
-FIND_PACKAGE(OpenSSL)
-FIND_PACKAGE(mbedTLS)
-IF (CMAKE_SYSTEM_NAME MATCHES "Darwin")
-       FIND_PACKAGE(Security)
-       FIND_PACKAGE(CoreFoundation)
-ENDIF()
+find_package(OpenSSL)
+find_package(mbedTLS)
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+       find_package(Security)
+       find_package(CoreFoundation)
+endif()
 
-IF(USE_HTTPS)
+if(USE_HTTPS)
        # Auto-select TLS backend
-       SanitizeBool(USE_HTTPS)
-       IF (USE_HTTPS STREQUAL ON)
-               IF (SECURITY_FOUND)
-                       IF (SECURITY_HAS_SSLCREATECONTEXT)
-                               SET(USE_HTTPS "SecureTransport")
-                       ELSE()
-                               MESSAGE(STATUS "Security framework is too old, falling back to OpenSSL")
-                               SET(USE_HTTPS "OpenSSL")
-                       ENDIF()
-               ELSEIF (WINHTTP)
-                       SET(USE_HTTPS "WinHTTP")
-               ELSEIF(OPENSSL_FOUND)
-                       SET(USE_HTTPS "OpenSSL")
-               ELSEIF(MBEDTLS_FOUND)
-                       SET(USE_HTTPS "mbedTLS")
-               ELSE()
-                       MESSAGE(FATAL_ERROR "Unable to autodetect a usable HTTPS backend."
+       sanitizebool(USE_HTTPS)
+       if(USE_HTTPS STREQUAL ON)
+               if(SECURITY_FOUND)
+                       if(SECURITY_HAS_SSLCREATECONTEXT)
+                               set(USE_HTTPS "SecureTransport")
+                       else()
+                               message(STATUS "Security framework is too old, falling back to OpenSSL")
+                               set(USE_HTTPS "OpenSSL")
+                       endif()
+               elseif(USE_WINHTTP)
+                       set(USE_HTTPS "WinHTTP")
+               elseif(OPENSSL_FOUND)
+                       set(USE_HTTPS "OpenSSL")
+               elseif(MBEDTLS_FOUND)
+                       set(USE_HTTPS "mbedTLS")
+               else()
+                       message(FATAL_ERROR "Unable to autodetect a usable HTTPS backend."
                                "Please pass the backend name explicitly (-DUSE_HTTPS=backend)")
-               ENDIF()
-       ENDIF()
+               endif()
+       endif()
 
        # Check that we can find what's required for the selected backend
-       IF (USE_HTTPS STREQUAL "SecureTransport")
-               IF (NOT COREFOUNDATION_FOUND)
-                       MESSAGE(FATAL_ERROR "Cannot use SecureTransport backend, CoreFoundation.framework not found")
-               ENDIF()
-               IF (NOT SECURITY_FOUND)
-                       MESSAGE(FATAL_ERROR "Cannot use SecureTransport backend, Security.framework not found")
-               ENDIF()
-               IF (NOT SECURITY_HAS_SSLCREATECONTEXT)
-                       MESSAGE(FATAL_ERROR "Cannot use SecureTransport backend, SSLCreateContext not supported")
-               ENDIF()
+       if(USE_HTTPS STREQUAL "SecureTransport")
+               if(NOT COREFOUNDATION_FOUND)
+                       message(FATAL_ERROR "Cannot use SecureTransport backend, CoreFoundation.framework not found")
+               endif()
+               if(NOT SECURITY_FOUND)
+                       message(FATAL_ERROR "Cannot use SecureTransport backend, Security.framework not found")
+               endif()
+               if(NOT SECURITY_HAS_SSLCREATECONTEXT)
+                       message(FATAL_ERROR "Cannot use SecureTransport backend, SSLCreateContext not supported")
+               endif()
 
-               SET(GIT_SECURE_TRANSPORT 1)
-               LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${SECURITY_INCLUDE_DIR})
-               LIST(APPEND LIBGIT2_LIBS ${COREFOUNDATION_LDFLAGS} ${SECURITY_LDFLAGS})
-               LIST(APPEND LIBGIT2_PC_LIBS ${COREFOUNDATION_LDFLAGS} ${SECURITY_LDFLAGS})
-       ELSEIF (USE_HTTPS STREQUAL "OpenSSL")
-               IF (NOT OPENSSL_FOUND)
-                       MESSAGE(FATAL_ERROR "Asked for OpenSSL TLS backend, but it wasn't found")
-               ENDIF()
+               set(GIT_SECURE_TRANSPORT 1)
+               list(APPEND LIBGIT2_SYSTEM_INCLUDES ${SECURITY_INCLUDE_DIR})
+               list(APPEND LIBGIT2_SYSTEM_LIBS ${COREFOUNDATION_LDFLAGS} ${SECURITY_LDFLAGS})
+               list(APPEND LIBGIT2_PC_LIBS ${COREFOUNDATION_LDFLAGS} ${SECURITY_LDFLAGS})
+       elseif(USE_HTTPS STREQUAL "OpenSSL")
+               if(NOT OPENSSL_FOUND)
+                       message(FATAL_ERROR "Asked for OpenSSL TLS backend, but it wasn't found")
+               endif()
 
-               SET(GIT_OPENSSL 1)
-               LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${OPENSSL_INCLUDE_DIR})
-               LIST(APPEND LIBGIT2_LIBS ${OPENSSL_LIBRARIES})
-               LIST(APPEND LIBGIT2_PC_LIBS ${OPENSSL_LDFLAGS})
-               LIST(APPEND LIBGIT2_PC_REQUIRES "openssl")
-       ELSEIF(USE_HTTPS STREQUAL "mbedTLS")
-               IF (NOT MBEDTLS_FOUND)
-                       MESSAGE(FATAL_ERROR "Asked for mbedTLS backend, but it wasn't found")
-               ENDIF()
+               set(GIT_OPENSSL 1)
+               list(APPEND LIBGIT2_SYSTEM_INCLUDES ${OPENSSL_INCLUDE_DIR})
+               list(APPEND LIBGIT2_SYSTEM_LIBS ${OPENSSL_LIBRARIES})
+               list(APPEND LIBGIT2_PC_LIBS ${OPENSSL_LDFLAGS})
+               list(APPEND LIBGIT2_PC_REQUIRES "openssl")
+       elseif(USE_HTTPS STREQUAL "mbedTLS")
+               if(NOT MBEDTLS_FOUND)
+                       message(FATAL_ERROR "Asked for mbedTLS backend, but it wasn't found")
+               endif()
 
-               IF(NOT CERT_LOCATION)
-                       MESSAGE(STATUS "Auto-detecting default certificates location")
-                       IF(CMAKE_SYSTEM_NAME MATCHES Darwin)
+               if(NOT CERT_LOCATION)
+                       message(STATUS "Auto-detecting default certificates location")
+                       if(CMAKE_SYSTEM_NAME MATCHES Darwin)
                                # Check for an Homebrew installation
-                               SET(OPENSSL_CMD "/usr/local/opt/openssl/bin/openssl")
-                       ELSE()
-                               SET(OPENSSL_CMD "openssl")
-                       ENDIF()
-                       EXECUTE_PROCESS(COMMAND ${OPENSSL_CMD} version -d OUTPUT_VARIABLE OPENSSL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
-                       IF(OPENSSL_DIR)
-                               STRING(REGEX REPLACE "^OPENSSLDIR: \"(.*)\"$" "\\1/" OPENSSL_DIR ${OPENSSL_DIR})
+                               set(OPENSSL_CMD "/usr/local/opt/openssl/bin/openssl")
+                       else()
+                               set(OPENSSL_CMD "openssl")
+                       endif()
+                       execute_process(COMMAND ${OPENSSL_CMD} version -d OUTPUT_VARIABLE OPENSSL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
+                       if(OPENSSL_DIR)
+                               string(REGEX REPLACE "^OPENSSLDIR: \"(.*)\"$" "\\1/" OPENSSL_DIR ${OPENSSL_DIR})
 
-                               SET(OPENSSL_CA_LOCATIONS
+                               set(OPENSSL_CA_LOCATIONS
                                        "ca-bundle.pem"             # OpenSUSE Leap 42.1
                                        "cert.pem"                  # Ubuntu 14.04, FreeBSD
                                        "certs/ca-certificates.crt" # Ubuntu 16.04
                                        "certs/ca.pem"              # Debian 7
                                )
-                               FOREACH(SUFFIX IN LISTS OPENSSL_CA_LOCATIONS)
-                                       SET(LOC "${OPENSSL_DIR}${SUFFIX}")
-                                       IF(NOT CERT_LOCATION AND EXISTS "${OPENSSL_DIR}${SUFFIX}")
-                                               SET(CERT_LOCATION ${LOC})
-                                       ENDIF()
-                               ENDFOREACH()
-                       ELSE()
-                               MESSAGE(FATAL_ERROR "Unable to find OpenSSL executable. Please provide default certificate location via CERT_LOCATION")
-                       ENDIF()
-               ENDIF()
+                               foreach(SUFFIX IN LISTS OPENSSL_CA_LOCATIONS)
+                                       set(LOC "${OPENSSL_DIR}${SUFFIX}")
+                                       if(NOT CERT_LOCATION AND EXISTS "${OPENSSL_DIR}${SUFFIX}")
+                                               set(CERT_LOCATION ${LOC})
+                                       endif()
+                               endforeach()
+                       else()
+                               message(FATAL_ERROR "Unable to find OpenSSL executable. Please provide default certificate location via CERT_LOCATION")
+                       endif()
+               endif()
 
-               IF(CERT_LOCATION)
-                       IF(NOT EXISTS ${CERT_LOCATION})
-                               MESSAGE(FATAL_ERROR "Cannot use CERT_LOCATION=${CERT_LOCATION} as it doesn't exist")
-                       ENDIF()
-                       ADD_FEATURE_INFO(CERT_LOCATION ON "using certificates from ${CERT_LOCATION}")
-                       ADD_DEFINITIONS(-DGIT_DEFAULT_CERT_LOCATION="${CERT_LOCATION}")
-               ENDIF()
+               if(CERT_LOCATION)
+                       if(NOT EXISTS ${CERT_LOCATION})
+                               message(FATAL_ERROR "Cannot use CERT_LOCATION=${CERT_LOCATION} as it doesn't exist")
+                       endif()
+                       add_feature_info(CERT_LOCATION ON "using certificates from ${CERT_LOCATION}")
+                       add_definitions(-DGIT_DEFAULT_CERT_LOCATION="${CERT_LOCATION}")
+               endif()
 
-               SET(GIT_MBEDTLS 1)
-               LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${MBEDTLS_INCLUDE_DIR})
-               LIST(APPEND LIBGIT2_LIBS ${MBEDTLS_LIBRARIES})
+               set(GIT_MBEDTLS 1)
+               list(APPEND LIBGIT2_SYSTEM_INCLUDES ${MBEDTLS_INCLUDE_DIR})
+               list(APPEND LIBGIT2_SYSTEM_LIBS ${MBEDTLS_LIBRARIES})
                # mbedTLS has no pkgconfig file, hence we can't require it
                # https://github.com/ARMmbed/mbedtls/issues/228
                # For now, pass its link flags as our own
-               LIST(APPEND LIBGIT2_PC_LIBS ${MBEDTLS_LIBRARIES})
-       ELSEIF (USE_HTTPS STREQUAL "WinHTTP")
+               list(APPEND LIBGIT2_PC_LIBS ${MBEDTLS_LIBRARIES})
+       elseif(USE_HTTPS STREQUAL "WinHTTP")
                # WinHTTP setup was handled in the WinHTTP-specific block above
-       ELSEIF (USE_HTTPS STREQUAL "OpenSSL-Dynamic")
-               SET(GIT_OPENSSL 1)
-               SET(GIT_OPENSSL_DYNAMIC 1)
-               LIST(APPEND LIBGIT2_LIBS dl)
-       ELSE()
-               MESSAGE(FATAL_ERROR "Asked for backend ${USE_HTTPS} but it wasn't found")
-       ENDIF()
+       elseif(USE_HTTPS STREQUAL "OpenSSL-Dynamic")
+               set(GIT_OPENSSL 1)
+               set(GIT_OPENSSL_DYNAMIC 1)
+               list(APPEND LIBGIT2_SYSTEM_LIBS dl)
+       else()
+               message(FATAL_ERROR "Asked for backend ${USE_HTTPS} but it wasn't found")
+       endif()
 
-       SET(GIT_HTTPS 1)
-       ADD_FEATURE_INFO(HTTPS GIT_HTTPS "using ${USE_HTTPS}")
-ELSE()
-       SET(GIT_HTTPS 0)
-       ADD_FEATURE_INFO(HTTPS NO "")
-ENDIF()
+       set(GIT_HTTPS 1)
+       add_feature_info(HTTPS GIT_HTTPS "using ${USE_HTTPS}")
+else()
+       set(GIT_HTTPS 0)
+       add_feature_info(HTTPS NO "")
+endif()
index 092cdfd051a956a5e4cb7c283afd84c36fe1bd82..bedd8c4e332f76553559e4edae6c427c28753496 100644 (file)
@@ -1,62 +1,52 @@
 # Select a hash backend
 
-INCLUDE(SanitizeBool)
+include(SanitizeBool)
 
 # USE_SHA1=CollisionDetection(ON)/HTTPS/Generic/OFF
+sanitizebool(USE_SHA1)
 
-SanitizeBool(USE_SHA1)
-IF(USE_SHA1 STREQUAL ON)
+if(USE_SHA1 STREQUAL ON)
        SET(USE_SHA1 "CollisionDetection")
-ELSEIF(USE_SHA1 STREQUAL "HTTPS")
-       IF(USE_HTTPS STREQUAL "SecureTransport")
-               SET(USE_SHA1 "CommonCrypto")
-       ELSEIF(USE_HTTPS STREQUAL "WinHTTP")
-               SET(USE_SHA1 "Win32")
-       ELSEIF(USE_HTTPS)
-               SET(USE_SHA1 ${USE_HTTPS})
-       ELSE()
-               SET(USE_SHA1 "CollisionDetection")
-       ENDIF()
-ENDIF()
+elseif(USE_SHA1 STREQUAL "HTTPS")
+       if(USE_HTTPS STREQUAL "SecureTransport")
+               set(USE_SHA1 "CommonCrypto")
+       elseif(USE_HTTPS STREQUAL "WinHTTP")
+               set(USE_SHA1 "Win32")
+       elseif(USE_HTTPS)
+               set(USE_SHA1 ${USE_HTTPS})
+       else()
+               set(USE_SHA1 "CollisionDetection")
+       endif()
+endif()
 
-IF(USE_SHA1 STREQUAL "CollisionDetection")
-       SET(GIT_SHA1_COLLISIONDETECT 1)
-       ADD_DEFINITIONS(-DSHA1DC_NO_STANDARD_INCLUDES=1)
-       ADD_DEFINITIONS(-DSHA1DC_CUSTOM_INCLUDE_SHA1_C=\"common.h\")
-       ADD_DEFINITIONS(-DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C=\"common.h\")
-       FILE(GLOB SRC_SHA1 hash/sha1/collisiondetect.* hash/sha1/sha1dc/*)
-ELSEIF(USE_SHA1 STREQUAL "OpenSSL")
+if(USE_SHA1 STREQUAL "CollisionDetection")
+       set(GIT_SHA1_COLLISIONDETECT 1)
+       add_definitions(-DSHA1DC_NO_STANDARD_INCLUDES=1)
+       add_definitions(-DSHA1DC_CUSTOM_INCLUDE_SHA1_C=\"common.h\")
+       add_definitions(-DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C=\"common.h\")
+elseif(USE_SHA1 STREQUAL "OpenSSL")
        # OPENSSL_FOUND should already be set, we're checking USE_HTTPS
 
-       SET(GIT_SHA1_OPENSSL 1)
-       IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
-               LIST(APPEND LIBGIT2_PC_LIBS "-lssl")
-       ELSE()
-               LIST(APPEND LIBGIT2_PC_REQUIRES "openssl")
-       ENDIF()
-       FILE(GLOB SRC_SHA1 hash/sha1/openssl.*)
-ELSEIF(USE_SHA1 STREQUAL "CommonCrypto")
-       SET(GIT_SHA1_COMMON_CRYPTO 1)
-       FILE(GLOB SRC_SHA1 hash/sha1/common_crypto.*)
-ELSEIF(USE_SHA1 STREQUAL "mbedTLS")
-       SET(GIT_SHA1_MBEDTLS 1)
-       FILE(GLOB SRC_SHA1 hash/sha1/mbedtls.*)
-       LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${MBEDTLS_INCLUDE_DIR})
-       LIST(APPEND LIBGIT2_LIBS ${MBEDTLS_LIBRARIES})
+       set(GIT_SHA1_OPENSSL 1)
+       if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+               list(APPEND LIBGIT2_PC_LIBS "-lssl")
+       else()
+               list(APPEND LIBGIT2_PC_REQUIRES "openssl")
+       endif()
+elseif(USE_SHA1 STREQUAL "CommonCrypto")
+       set(GIT_SHA1_COMMON_CRYPTO 1)
+elseif(USE_SHA1 STREQUAL "mbedTLS")
+       set(GIT_SHA1_MBEDTLS 1)
+       list(APPEND LIBGIT2_SYSTEM_INCLUDES ${MBEDTLS_INCLUDE_DIR})
+       list(APPEND LIBGIT2_SYSTEM_LIBS ${MBEDTLS_LIBRARIES})
        # mbedTLS has no pkgconfig file, hence we can't require it
        # https://github.com/ARMmbed/mbedtls/issues/228
        # For now, pass its link flags as our own
-       LIST(APPEND LIBGIT2_PC_LIBS ${MBEDTLS_LIBRARIES})
-ELSEIF(USE_SHA1 STREQUAL "Win32")
-       SET(GIT_SHA1_WIN32 1)
-       FILE(GLOB SRC_SHA1 hash/sha1/win32.*)
-ELSEIF(USE_SHA1 STREQUAL "Generic")
-       FILE(GLOB SRC_SHA1 hash/sha1/generic.*)
-ELSE()
-       MESSAGE(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}")
-ENDIF()
+       list(APPEND LIBGIT2_PC_LIBS ${MBEDTLS_LIBRARIES})
+elseif(USE_SHA1 STREQUAL "Win32")
+       set(GIT_SHA1_WIN32 1)
+elseif(NOT (USE_SHA1 STREQUAL "Generic"))
+       message(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}")
+endif()
 
-list(APPEND SRC_SHA1 "hash/sha1.h")
-list(SORT SRC_SHA1)
-
-ADD_FEATURE_INFO(SHA ON "using ${USE_SHA1}")
+add_feature_info(SHA ON "using ${USE_SHA1}")
diff --git a/cmake/SelectRegex.cmake b/cmake/SelectRegex.cmake
new file mode 100644 (file)
index 0000000..2a3a91b
--- /dev/null
@@ -0,0 +1,51 @@
+# Specify regular expression implementation
+find_package(PCRE)
+
+if(REGEX_BACKEND STREQUAL "")
+       check_symbol_exists(regcomp_l "regex.h;xlocale.h" HAVE_REGCOMP_L)
+
+       if(HAVE_REGCOMP_L)
+               set(REGEX_BACKEND "regcomp_l")
+       elseif(PCRE_FOUND)
+               set(REGEX_BACKEND "pcre")
+       else()
+               set(REGEX_BACKEND "builtin")
+       endif()
+endif()
+
+if(REGEX_BACKEND STREQUAL "regcomp_l")
+       add_feature_info(regex ON "using system regcomp_l")
+       set(GIT_REGEX_REGCOMP_L 1)
+elseif(REGEX_BACKEND STREQUAL "pcre2")
+       find_package(PCRE2)
+
+       if(NOT PCRE2_FOUND)
+               MESSAGE(FATAL_ERROR "PCRE2 support was requested but not found")
+       endif()
+
+       add_feature_info(regex ON "using system PCRE2")
+       set(GIT_REGEX_PCRE2 1)
+
+       list(APPEND LIBGIT2_SYSTEM_INCLUDES ${PCRE2_INCLUDE_DIRS})
+       list(APPEND LIBGIT2_SYSTEM_LIBS ${PCRE2_LIBRARIES})
+       list(APPEND LIBGIT2_PC_REQUIRES "libpcre2-8")
+elseif(REGEX_BACKEND STREQUAL "pcre")
+       add_feature_info(regex ON "using system PCRE")
+       set(GIT_REGEX_PCRE 1)
+
+       list(APPEND LIBGIT2_SYSTEM_INCLUDES ${PCRE_INCLUDE_DIRS})
+       list(APPEND LIBGIT2_SYSTEM_LIBS ${PCRE_LIBRARIES})
+       list(APPEND LIBGIT2_PC_REQUIRES "libpcre")
+elseif(REGEX_BACKEND STREQUAL "regcomp")
+       add_feature_info(regex ON "using system regcomp")
+       set(GIT_REGEX_REGCOMP 1)
+elseif(REGEX_BACKEND STREQUAL "builtin")
+       add_feature_info(regex ON "using bundled PCRE")
+       set(GIT_REGEX_BUILTIN 1)
+
+       add_subdirectory("${PROJECT_SOURCE_DIR}/deps/pcre" "${PROJECT_BINARY_DIR}/deps/pcre")
+       list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${PROJECT_SOURCE_DIR}/deps/pcre")
+       list(APPEND LIBGIT2_DEPENDENCY_OBJECTS $<TARGET_OBJECTS:pcre>)
+else()
+       message(FATAL_ERROR "The REGEX_BACKEND option provided is not supported")
+endif()
diff --git a/cmake/SelectSSH.cmake b/cmake/SelectSSH.cmake
new file mode 100644 (file)
index 0000000..23dfc97
--- /dev/null
@@ -0,0 +1,41 @@
+# Optional external dependency: libssh2
+if(USE_SSH)
+       find_pkglibraries(LIBSSH2 libssh2)
+       if(NOT LIBSSH2_FOUND)
+               find_package(LibSSH2)
+               set(LIBSSH2_INCLUDE_DIRS ${LIBSSH2_INCLUDE_DIR})
+               get_filename_component(LIBSSH2_LIBRARY_DIRS "${LIBSSH2_LIBRARY}" DIRECTORY)
+               set(LIBSSH2_LIBRARIES ${LIBSSH2_LIBRARY})
+               set(LIBSSH2_LDFLAGS "-lssh2")
+       endif()
+
+       if(NOT LIBSSH2_FOUND)
+               message(FATAL_ERROR "LIBSSH2 not found. Set CMAKE_PREFIX_PATH if it is installed outside of the default search path.")
+       endif()
+endif()
+
+if(LIBSSH2_FOUND)
+       set(GIT_SSH 1)
+       list(APPEND LIBGIT2_SYSTEM_INCLUDES ${LIBSSH2_INCLUDE_DIRS})
+       list(APPEND LIBGIT2_SYSTEM_LIBS ${LIBSSH2_LIBRARIES})
+       list(APPEND LIBGIT2_PC_LIBS ${LIBSSH2_LDFLAGS})
+
+       check_library_exists("${LIBSSH2_LIBRARIES}" libssh2_userauth_publickey_frommemory "${LIBSSH2_LIBRARY_DIRS}" HAVE_LIBSSH2_MEMORY_CREDENTIALS)
+       if(HAVE_LIBSSH2_MEMORY_CREDENTIALS)
+               set(GIT_SSH_MEMORY_CREDENTIALS 1)
+       endif()
+else()
+       message(STATUS "LIBSSH2 not found. Set CMAKE_PREFIX_PATH if it is installed outside of the default search path.")
+endif()
+
+if(WIN32 AND EMBED_SSH_PATH)
+       file(GLOB SSH_SRC "${EMBED_SSH_PATH}/src/*.c")
+       list(SORT SSH_SRC)
+       list(APPEND LIBGIT2_DEPENDENCY_OBJECTS ${SSH_SRC})
+
+       list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${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\"")
+       set(GIT_SSH 1)
+endif()
+
+add_feature_info(SSH GIT_SSH "SSH transport support")
diff --git a/cmake/SelectWinHTTP.cmake b/cmake/SelectWinHTTP.cmake
new file mode 100644 (file)
index 0000000..96e0bdb
--- /dev/null
@@ -0,0 +1,17 @@
+if(WIN32 AND USE_WINHTTP)
+       set(GIT_WINHTTP 1)
+
+       # Since MinGW does not come with headers or an import library for winhttp,
+       # we have to include a private header and generate our own import library
+       if(MINGW)
+               add_subdirectory("${PROJECT_SOURCE_DIR}/deps/winhttp" "${PROJECT_BINARY_DIR}/deps/winhttp")
+               list(APPEND LIBGIT2_SYSTEM_LIBS winhttp)
+               list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${PROJECT_SOURCE_DIR}/deps/winhttp")
+       else()
+               list(APPEND LIBGIT2_SYSTEM_LIBS "winhttp")
+               list(APPEND LIBGIT2_PC_LIBS "-lwinhttp")
+       endif()
+
+       list(APPEND LIBGIT2_SYSTEM_LIBS "rpcrt4" "crypt32" "ole32")
+       list(APPEND LIBGIT2_PC_LIBS "-lrpcrt4" "-lcrypt32" "-lole32")
+endif()
diff --git a/cmake/SelectZlib.cmake b/cmake/SelectZlib.cmake
new file mode 100644 (file)
index 0000000..fb4361a
--- /dev/null
@@ -0,0 +1,34 @@
+# Optional external dependency: zlib
+include(SanitizeBool)
+
+SanitizeBool(USE_BUNDLED_ZLIB)
+if(USE_BUNDLED_ZLIB STREQUAL ON)
+       set(USE_BUNDLED_ZLIB "Bundled")
+endif()
+
+if(USE_BUNDLED_ZLIB STREQUAL "OFF")
+       find_package(ZLIB)
+       if(ZLIB_FOUND)
+               list(APPEND LIBGIT2_SYSTEM_INCLUDES ${ZLIB_INCLUDE_DIRS})
+               list(APPEND LIBGIT2_SYSTEM_LIBS ${ZLIB_LIBRARIES})
+               if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+                       list(APPEND LIBGIT2_PC_LIBS "-lz")
+               else()
+                       list(APPEND LIBGIT2_PC_REQUIRES "zlib")
+               endif()
+               add_feature_info(zlib ON "using system zlib")
+       else()
+               message(STATUS "zlib was not found; using bundled 3rd-party sources." )
+       endif()
+endif()
+if(USE_BUNDLED_ZLIB STREQUAL "Chromium")
+       add_subdirectory("${PROJECT_SOURCE_DIR}/deps/chromium-zlib" "${PROJECT_BINARY_DIR}/deps/chromium-zlib")
+       list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${PROJECT_SOURCE_DIR}/deps/chromium-zlib")
+       list(APPEND LIBGIT2_DEPENDENCY_OBJECTS $<TARGET_OBJECTS:chromium_zlib>)
+       add_feature_info(zlib ON "using (Chromium) bundled zlib")
+elseif(USE_BUNDLED_ZLIB OR NOT ZLIB_FOUND)
+       add_subdirectory("${PROJECT_SOURCE_DIR}/deps/zlib" "${PROJECT_BINARY_DIR}/deps/zlib")
+       list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${PROJECT_SOURCE_DIR}/deps/zlib")
+       list(APPEND LIBGIT2_DEPENDENCY_OBJECTS $<TARGET_OBJECTS:zlib>)
+       add_feature_info(zlib ON "using bundled zlib")
+endif()
diff --git a/docs/api-stability.md b/docs/api-stability.md
new file mode 100644 (file)
index 0000000..a02e864
--- /dev/null
@@ -0,0 +1,63 @@
+The maintainers of the libgit2 project believe that having a stable API
+to program against is important for our users and the ecosystem - whether
+you're building against the libgit2 C APIs directly, creating a wrapper to
+a managed language, or programming against one of those managed wrappers
+like LibGit2Sharp or Rugged.
+
+Our API stability considerations are:
+
+* Our standard API is considered stable through a major release.
+
+  * We define our "standard API" to be anything included in the "git2.h"
+    header - in other words, anything defined in a header in the `git2`
+    directory.
+
+  * APIs will maintain their signature and will not be removed within a
+    major release, but new APIs may be added.
+
+  * Any APIs may be marked as deprecated within a major release, but will
+    not be removed until the next major release (at the earliest).  You
+    may define `GIT_DEPRECATE_HARD` to produce compiler warnings if you
+    target these deprecated APIs.
+
+  * We consider API compatibility to be against the C APIs.  That means
+    that we may use macros to keep API compatibility - for example, if we
+    rename a structure from `git_widget_options` to `git_foobar_options`
+    then we would `#define git_widget_options git_foobar_options` to retain
+    API compatibility.  Note that this does _not_ provide ABI compatibility.
+
+* Our systems API is only considered stable through a _minor_ release.
+
+  * We define our "systems API" to be anything included in the `git2/sys`
+    directory.  These are not "standard" APIs but are mechanisms to extend
+    libgit2 by adding new extensions - for example, a custom HTTPS transport,
+    TLS engine, or merge strategy.
+
+  * Additionally, the cmake options and the resulting constants that it
+    produces to be "systems API".
+
+  * Generally these mechanism are well defined and will not need significant
+    changes, but are considered a part of the library itself and may need
+
+  * Systems API changes will be noted specially within a release's changelog.
+
+* Our ABI is only considered stable through a _minor_ release.
+
+  * Our ABI consists of actual symbol names in the library, the function
+    signatures, and the actual layout of structures.  These are only
+    stable within minor releases, they are not stable within major releases
+    (yet).
+
+  * Since many FFIs use ABIs directly (for example, .NET P/Invoke or Rust),
+    this instability is unfortunate.
+
+  * In a future major release, we will begin providing ABI stability
+    throughout the major release cycle.
+
+  * ABI changes will be noted specially within a release's changelog.
+
+* Point releases are _generally_ only for bugfixes, and generally do _not_
+  include new features.  This means that point releases generally do _not_
+  include new APIs.  Point releases will never break API, systems API or
+  ABI compatibility.
+
diff --git a/docs/buffers.md b/docs/buffers.md
new file mode 100644 (file)
index 0000000..2f2148b
--- /dev/null
@@ -0,0 +1,63 @@
+Memory allocation and ownership
+-------------------------------
+
+Any library needs to _take_ data from users, and then _return_ data to
+users.  With some types this is simple - integer parameters and return
+types are trivial.  But with more complex data types, things are more
+complicated.  Even something seemingly simple, like a C string, requires
+discipline: we cannot simple return an allocated hunk of memory for
+callers to `free`, since some systems have multiple allocators and users
+cannot necessarily reason about the allocator used and which corresponding
+deallocation function to call to free the memory.
+
+## Objects
+
+Most types in libgit2 are "opaque" types, which we treat as "objects" (even
+though C is "not an object oriented language").  You may create an object -
+for example, with `git_odb_new`, or libgit2 may return you an object as an
+"out" parameter - for example, with `git_repository_open`.  With any of
+these objects, you should call their corresponding `_free` function (for
+example, `git_odb_free` or `git_repository_free`) when you are done using
+them.
+
+## Structures
+
+libgit2 will often take _input_ as structures (for example, options
+structures like `git_merge_options`).  Rarely, libgit2 will return data in
+a structure.  This is typically used for simpler data types, like `git_buf`
+and `git_strarray`.  Users should allocate the structure themselves (either
+on the stack or the heap) and pass a pointer to it.  Since libgit2 does not
+allocate the structure itself, only the data inside of it, the deallocation
+functions are suffixed with `_dispose` instead of `_free`, since they only
+free the data _inside_ the structure.
+
+## Strings or continuous memory buffers (`git_buf`)
+
+libgit2 typically _takes_ NUL-terminated strings ("C strings") with a
+`const char *`, and typically _takes_ raw data with a `const char *` and a
+corresponding `size_t` for its size.  libgit2 typically _returns_ strings
+or raw data in a `git_buf` structure.  The given data buffer will always be
+NUL terminated (even if it contains binary data) and the `size` member will
+always contain the size (in bytes) of the contents of the pointer (excluding
+the NUL terminator).
+
+In other words, if a `git_buf` contains the string `foo` then the memory
+buffer will be { `f`, `o`, `o`, `\0` } and the size will be `3`.
+
+Callers _must_ initialize the buffer with `GIT_BUF_INIT` (or by setting
+all the members to `0`) when it is created, before passing a pointer
+to the buffer to libgit2 for the first time.
+
+Subsequent calls to libgit2 APIs that take a buffer can re-use a
+buffer that was previously used.  The buffer will be cleared and grown
+to accommodate the new contents (if necessary).  The new data will
+written into the buffer, overwriting the previous contents.  This
+allows callers to reduce the number of allocations performed by the
+library.
+
+Callers must call `git_buf_dispose` when they have finished.
+
+Note that the deprecated `git_diff_format_email` API does not follow
+this behavior; subsequent calls will concatenate data to the buffer
+instead of rewriting it.  Users should move to the new `git_email`
+APIs that follow the `git_buf` standards.
index 8060874df0eceeaddb5f4198635802c76e0bea19..32a67d2c7198b075be10841368fbb20a29c01a9a 100644 (file)
@@ -1,3 +1,133 @@
+v1.4.3
+------
+
+🔒 This is a security release to provide compatibility with git's changes to address [CVE 2022-24765](https://github.blog/2022-04-12-git-security-vulnerability-announced/).
+
+**libgit2 is not directly affected** by this vulnerability, because libgit2 does not directly invoke any executable. But we are providing these changes as a security release for any users that use libgit2 for repository discovery and then _also_ use git on that repository. In this release, we will now validate that the user opening the repository is the same user that owns the on-disk repository. This is to match git's behavior.
+
+In addition, we are providing several correctness fixes where invalid input can lead to a crash. These may prevent possible denial of service attacks. At this time there are not known exploits to these issues.
+
+Full list of changes:
+
+* Validate repository directory ownership (v1.4) by @ethomson in https://github.com/libgit2/libgit2/pull/6267
+* midx: Fix an undefined behavior (left-shift signed overflow) by @lhchavez in https://github.com/libgit2/libgit2/pull/6260
+* fetch: support OID refspec without dst by @ethomson in https://github.com/libgit2/libgit2/pull/6251
+* Fix crash when regenerating a patch with unquoted spaces in filename by @jorio in https://github.com/libgit2/libgit2/pull/6244
+
+All users of the v1.4 release line are recommended to upgrade.
+
+**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.4.2...v1.4.3
+
+v1.4.2
+------
+
+This is a bugfix release with the following changes:
+
+* remote: do store the update_tips callback error value by @carlosmn in https://github.com/libgit2/libgit2/pull/6226
+* win32: `find_system_dirs` does not return `GIT_ENOTFOUND` by @ethomson in https://github.com/libgit2/libgit2/pull/6228
+
+v1.4.1
+------
+
+This is a bugfix release with the following changes:
+
+* xdiff: use xdl_free not free by @ethomson
+* cmake: Fix package name for system http-parser by @mgorny
+* Free parent and ref in lg2_commit before returning by @apnadkarni
+
+v1.4
+----
+
+This is release v1.4.0, "Fisematenten".  This release includes several new features and bugfixes, improves compatibility with git, and begins preparation for SHA256 support in a future release.
+
+## What's Changed
+### New features
+* diff: update rename limit to 1000 to match git's behavior by @ethomson in https://github.com/libgit2/libgit2/pull/6092
+* odb: support checking for object existence without refresh by @joshtriplett in https://github.com/libgit2/libgit2/pull/6107
+* object: provide a low-level mechanism to validate whether a raw object is valid (`git_object_rawcontent_is_valid`) by @ethomson in https://github.com/libgit2/libgit2/pull/6128
+* blob: provide a function to identify binary content by @ethomson in https://github.com/libgit2/libgit2/pull/6142
+* status: add `rename_threshold` to `git_status_options`. by @arroz in https://github.com/libgit2/libgit2/pull/6158
+* remote: support `http.followRedirects` (`false` and `initial`) and follow initial redirects by default by @ethomson in https://github.com/libgit2/libgit2/pull/6175
+* remote: support scp style paths with ports (`[git@github.com:22]:libgit2/libgit2`) by @ethomson in https://github.com/libgit2/libgit2/pull/6167
+* win32: update git for windows configuration file location compatibility by @csware in https://github.com/libgit2/libgit2/pull/6151 and @ethomson in https://github.com/libgit2/libgit2/pull/6180
+* refs: speed up packed reference lookups when packed refs are sorted by @ccstolley in https://github.com/libgit2/libgit2/pull/6138
+* merge: support zdiff3 conflict styles by @ethomson in https://github.com/libgit2/libgit2/pull/6195
+* remote: support fetching by object id (using "+oid:ref" refspec syntax) by @ethomson in https://github.com/libgit2/libgit2/pull/6203
+* merge: callers can specify virtual-base building behavior and to optionally accept conflict markers as a resolution by @boretrk in https://github.com/libgit2/libgit2/pull/6204
+
+### Bug fixes
+* Fix a gcc 11 warning in src/threadstate.c by @lhchavez in https://github.com/libgit2/libgit2/pull/6115
+* Fix a gcc 11 warning in src/thread.h by @lhchavez in https://github.com/libgit2/libgit2/pull/6116
+* cmake: re-enable WinHTTP by @ethomson in https://github.com/libgit2/libgit2/pull/6120
+* Fix repo init when template dir is non-existent by @ammgws in https://github.com/libgit2/libgit2/pull/6106
+* cmake: use project-specific root variable instead of CMAKE_SOURCE_DIR by @Qix- in https://github.com/libgit2/libgit2/pull/6146
+* Better revparse compatibility for at time notation by @yoichi in https://github.com/libgit2/libgit2/pull/6095
+* remotes: fix insteadOf/pushInsteadOf handling by @mkhl in https://github.com/libgit2/libgit2/pull/6101
+* git_commit_summary: ignore lines with spaces by @stforek in https://github.com/libgit2/libgit2/pull/6125
+* Config parsing by @csware in https://github.com/libgit2/libgit2/pull/6124
+* config: handle empty conditional in includeIf by @ethomson in https://github.com/libgit2/libgit2/pull/6165
+* #6154 git_status_list_new case insensitive fix by @arroz in https://github.com/libgit2/libgit2/pull/6159
+* futils_mktmp: don't use umask by @boretrk in https://github.com/libgit2/libgit2/pull/6178
+* revparse: support bare '@' by @ethomson in https://github.com/libgit2/libgit2/pull/6196
+* odb: check for write failures by @ethomson in https://github.com/libgit2/libgit2/pull/6206
+* push: Prepare pack before sending pack header. by @ccstolley in https://github.com/libgit2/libgit2/pull/6205
+* mktmp: improve our temp file creation by @ethomson in https://github.com/libgit2/libgit2/pull/6207
+* diff_file: fix crash if size of diffed file changes in workdir by @jorio in https://github.com/libgit2/libgit2/pull/6208
+* merge: comment conflicts lines in MERGE_MSG by @ethomson in https://github.com/libgit2/libgit2/pull/6197
+* Fix crashes in example programs on Windows (sprintf_s not compatible with snprintf) by @apnadkarni in https://github.com/libgit2/libgit2/pull/6212
+
+### Code cleanups
+* Introduce `git_remote_connect_options` by @ethomson in https://github.com/libgit2/libgit2/pull/6161
+* hash: separate hashes and git_oid by @ethomson in https://github.com/libgit2/libgit2/pull/6082
+* `git_buf`: now a public-only API (`git_str` is our internal API) by @ethomson in https://github.com/libgit2/libgit2/pull/6078
+* cmake: cleanups and consistency by @ethomson in https://github.com/libgit2/libgit2/pull/6084
+* path: refactor utility path functions by @ethomson in https://github.com/libgit2/libgit2/pull/6104
+* str: git_str_free is never a function by @ethomson in https://github.com/libgit2/libgit2/pull/6111
+* cmake refactorings by @ethomson in https://github.com/libgit2/libgit2/pull/6112
+* Add missing-declarations warning globally by @ethomson in https://github.com/libgit2/libgit2/pull/6113
+* cmake: further refactorings by @ethomson in https://github.com/libgit2/libgit2/pull/6114
+* tag: set validity to 0 by default by @ethomson in https://github.com/libgit2/libgit2/pull/6119
+* util: minor cleanup and refactoring to the date class by @ethomson in https://github.com/libgit2/libgit2/pull/6121
+* Minor code cleanups by @ethomson in https://github.com/libgit2/libgit2/pull/6122
+* Fix a long long that crept past by @NattyNarwhal in https://github.com/libgit2/libgit2/pull/6094
+* remote: refactor insteadof application by @ethomson in https://github.com/libgit2/libgit2/pull/6147
+* ntmlclient: fix linking with libressl by @boretrk in https://github.com/libgit2/libgit2/pull/6157
+* c99: change single bit flags to unsigned by @boretrk in https://github.com/libgit2/libgit2/pull/6179
+* Fix typos by @rex4539 in https://github.com/libgit2/libgit2/pull/6164
+* diff_driver: split global_drivers array into separate elements by @boretrk in https://github.com/libgit2/libgit2/pull/6184
+* cmake: disable some gnu extensions by @boretrk in https://github.com/libgit2/libgit2/pull/6185
+* Disabling setting `CMAKE_FIND_LIBRARY_SUFFIXES` on Apple platforms. by @arroz in https://github.com/libgit2/libgit2/pull/6153
+* C90: add inline macro to xdiff and mbedtls by @boretrk in https://github.com/libgit2/libgit2/pull/6200
+* SHA256: early preparation by @ethomson in https://github.com/libgit2/libgit2/pull/6192
+
+### CI improvements
+* tests: rename test runner to `libgit2_tests`, build option to `BUILD_TESTS`. by @ethomson in https://github.com/libgit2/libgit2/pull/6083
+* ci: only update docs on push by @ethomson in https://github.com/libgit2/libgit2/pull/6108
+* Pedantic header test by @boretrk in https://github.com/libgit2/libgit2/pull/6086
+* ci: build with ssh on nightly by @ethomson in https://github.com/libgit2/libgit2/pull/6148
+* ci: improve the name in CI runs by @ethomson in https://github.com/libgit2/libgit2/pull/6198
+
+### Documentation improvements
+* Document that `git_odb` is thread-safe by @joshtriplett in https://github.com/libgit2/libgit2/pull/6109
+* Improve documentation by @punkymaniac in https://github.com/libgit2/libgit2/pull/6168
+
+### Other changes
+* libgit2_clar is now libgit2_tests by @mkhl in https://github.com/libgit2/libgit2/pull/6100
+* Remove PSGit from Language Bindings section of README by @cestrand in https://github.com/libgit2/libgit2/pull/6150
+* COPYING: remove regex copyright, add PCRE copyright by @ethomson in https://github.com/libgit2/libgit2/pull/6187
+* meta: add a release configuration file by @ethomson in https://github.com/libgit2/libgit2/pull/6211
+
+## New Contributors
+* @mkhl made their first contribution in https://github.com/libgit2/libgit2/pull/6100
+* @ammgws made their first contribution in https://github.com/libgit2/libgit2/pull/6106
+* @yoichi made their first contribution in https://github.com/libgit2/libgit2/pull/6095
+* @stforek made their first contribution in https://github.com/libgit2/libgit2/pull/6125
+* @cestrand made their first contribution in https://github.com/libgit2/libgit2/pull/6150
+* @rex4539 made their first contribution in https://github.com/libgit2/libgit2/pull/6164
+* @jorio made their first contribution in https://github.com/libgit2/libgit2/pull/6208
+
+**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.3.0...v1.4.0
+
 v1.3
 ----
 
@@ -1963,3 +2093,8 @@ v0.22
   functions. This is not something which we can know to do. A
   last-resort convenience function is provided in sys/openssl.h,
   `git_openssl_set_locking()` which can be used to set the locking.
+
+* `git_reference_*()` functions use mmap() + binary search for packed
+  refs lookups when using the fs backend. Previously all entries were
+  read into a hashtable, which could be slow for repositories with a
+  large number of refs.
index f3e559c9d812a64d78aab63df6bface5932dfede..03e0017093beef609d411f3501445cfe447ae6c6 100644 (file)
@@ -120,15 +120,15 @@ In addition to new tests, please ensure that your changes do not cause
 any other test failures.  Running the entire test suite is helpful
 before you submit a pull request.  When you build libgit2, the test
 suite will also be built.  You can run most of the tests by simply running
-the resultant `libgit2_clar` binary.  If you want to run a specific
+the resultant `libgit2_tests` binary.  If you want to run a specific
 unit test, you can name it with the `-s` option.  For example:
 
-    libgit2_clar -sstatus::worktree::long_filenames
+    libgit2_tests -sstatus::worktree::long_filenames
 
 Or you can run an entire class of tests.  For example, to run all the
 worktree status tests:
 
-    libgit2_clar -sstatus::worktree
+    libgit2_tests -sstatus::worktree
 
 The default test run is fairly exhaustive, but it will exclude some
 unit tests by default: in particular, those that talk to network
@@ -136,7 +136,7 @@ servers and the tests that manipulate the filesystem in onerous
 ways (and may need to have special privileges to run).  To run the
 network tests:
 
-    libgit2_clar -ionline
+    libgit2_tests -ionline
 
 In addition, various tests may be enabled by environment variables,
 like the ones that write exceptionally large repositories or manipulate
index 05725f2ed064f151fc80e104609acb1f0c29d286..13ce78f5f6c83cecd100df43d2396fd4caa7c7a3 100644 (file)
@@ -21,7 +21,7 @@ critical failures (such as a packfile being corrupted, a loose object
 having the wrong access permissions, etc.) all of which will return -1.
 When the object lookup is successful, it will return 0.
 
-If libgit2 was compiled with threads enabled (`-DTHREADSAFE=ON` when using
+If libgit2 was compiled with threads enabled (`-DUSE_THREADS=ON` when using
 CMake), then the error message will be kept in thread-local storage, so it
 will not be modified by other threads.  If threads are not enabled, then
 the error message is in global data.
index 25b32cb047471db3fc0ac61c5059b69e7ed16de9..2bf4ccca915fdfde51b5f96f5444cb3ed934041d 100644 (file)
@@ -19,7 +19,7 @@ automated fuzz testing. libFuzzer only works with clang.
    and [`leak`/`address,leak`](https://clang.llvm.org/docs/LeakSanitizer.html).
 3. Create the cmake build environment and configure the build with the
    sanitizer chosen: `CC=/usr/bin/clang-6.0 CFLAGS="-fsanitize=address" cmake
-   -DBUILD_CLAR=OFF -DBUILD_FUZZERS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo ..`.
+   -DBUILD_TESTS=OFF -DBUILD_FUZZERS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo ..`.
    Note that building the fuzzer targets is incompatible with the
    tests and examples.
 4. Build libgit2: `cmake --build .`
index 3200c4449e47f9eeedadb8135c2b6c22012fd137..87fccaabe63a878213f9f63a626e4f6a340b74dc 100644 (file)
@@ -80,4 +80,4 @@ and run it against our description file with the tip of `main` checked out.
 
     cm doc api.docurium
 
-It will start up a few proceses and write out the results as a new commit onto the `gh-pages` branch. That can be pushed to GitHub to update what will show up on our documentation reference site.
+It will start up a few processes and write out the results as a new commit onto the `gh-pages` branch. That can be pushed to GitHub to update what will show up on our documentation reference site.
index ddfaf7ae59ac9535a300e2befb127aa9fc431934..de085c807cc4d20b0c557194ffde169fa501a606 100644 (file)
@@ -21,6 +21,9 @@ There are some objects which are read-only/immutable and are thus safe
 to share across threads, such as references and configuration
 snapshots.
 
+The `git_odb` object uses locking internally, and is thread-safe to use from
+multiple threads simultaneously.
+
 Error messages
 --------------
 
index 8cc72b35e4fac7b5ebd7c661cffbb205fc4b20ec..235e72adaed0d808f3ee56d051f1422ea2b096da 100644 (file)
@@ -1,15 +1,16 @@
-INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDES})
-INCLUDE_DIRECTORIES(SYSTEM ${LIBGIT2_SYSTEM_INCLUDES})
+file(GLOB SRC_EXAMPLES *.c *.h)
 
-FILE(GLOB LG2_SOURCES *.c *.h)
-ADD_EXECUTABLE(lg2 ${LG2_SOURCES})
-SET_TARGET_PROPERTIES(lg2 PROPERTIES C_STANDARD 90)
+add_executable(lg2 ${SRC_EXAMPLES})
+set_target_properties(lg2 PROPERTIES C_STANDARD 90)
 
 # Ensure that we do not use deprecated functions internally
-ADD_DEFINITIONS(-DGIT_DEPRECATE_HARD)
+add_definitions(-DGIT_DEPRECATE_HARD)
 
-IF(WIN32 OR ANDROID)
-       TARGET_LINK_LIBRARIES(lg2 git2)
-ELSE()
-       TARGET_LINK_LIBRARIES(lg2 git2 pthread)
-ENDIF()
+target_include_directories(lg2 PRIVATE ${LIBGIT2_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES})
+target_include_directories(lg2 SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
+
+if(WIN32 OR ANDROID)
+       target_link_libraries(lg2 git2)
+else()
+       target_link_libraries(lg2 git2 pthread)
+endif()
index 542360ea9bfe6ec51182d6e70d123b5a8efbe44d..1c93b11404af36cd206cd1fb702af76845148e69 100644 (file)
@@ -28,7 +28,7 @@
 
 enum index_mode {
        INDEX_NONE,
-       INDEX_ADD,
+       INDEX_ADD
 };
 
 struct index_options {
@@ -110,22 +110,7 @@ int print_matched_cb(const char *path, const char *matched_pathspec, void *paylo
        return ret;
 }
 
-void init_array(git_strarray *array, int argc, char **argv)
-{
-       unsigned int i;
-
-       array->count = argc;
-       array->strings = calloc(array->count, sizeof(char *));
-       assert(array->strings != NULL);
-
-       for (i = 0; i < array->count; i++) {
-               array->strings[i] = argv[i];
-       }
-
-       return;
-}
-
-void print_usage(void)
+static void print_usage(void)
 {
        fprintf(stderr, "usage: add [options] [--] file-spec [file-spec] [...]\n\n");
        fprintf(stderr, "\t-n, --dry-run    dry run\n");
index 954c97b17d170397d2c9f8e743e096e06e64f9e5..77087a5771abc4a21ec97c7fa06bb2ac4e45189d 100644 (file)
@@ -49,7 +49,7 @@ int lg2_blame(git_repository *repo, int argc, char *argv[])
        if (o.F) blameopts.flags |= GIT_BLAME_FIRST_PARENT;
 
        /**
-        * The commit range comes in "commitish" form. Use the rev-parse API to
+        * The commit range comes in "committish" form. Use the rev-parse API to
         * nail down the end points.
         */
        if (o.commitspec) {
@@ -70,7 +70,7 @@ int lg2_blame(git_repository *repo, int argc, char *argv[])
 
        /**
         * Get the raw data inside the blob for output. We use the
-        * `commitish:path/to/file.txt` format to find it.
+        * `committish:path/to/file.txt` format to find it.
         */
        if (git_oid_is_zero(&blameopts.newest_commit))
                strcpy(spec, "HEAD");
index cd9782de10746599b89f1cc73f9207c63ef5c229..aedc1af7e1c5b0e453ed171e6ca38ba393256f76 100644 (file)
@@ -26,7 +26,7 @@
  * This does have:
  *
  * - Example of performing a git commit with a comment
- * 
+ *
  */
 int lg2_commit(git_repository *repo, int argc, char **argv)
 {
@@ -36,10 +36,10 @@ int lg2_commit(git_repository *repo, int argc, char **argv)
 
        git_oid commit_oid,tree_oid;
        git_tree *tree;
-       git_index *index;       
+       git_index *index;
        git_object *parent = NULL;
        git_reference *ref = NULL;
-       git_signature *signature;       
+       git_signature *signature;
 
        /* Validate args */
        if (argc < 3 || strcmp(opt, "-m") != 0) {
@@ -62,9 +62,9 @@ int lg2_commit(git_repository *repo, int argc, char **argv)
        check_lg2(git_index_write(index), "Could not write index", NULL);;
 
        check_lg2(git_tree_lookup(&tree, repo, &tree_oid), "Error looking up tree", NULL);
-       
+
        check_lg2(git_signature_default(&signature, repo), "Error creating signature", NULL);
-       
+
        check_lg2(git_commit_create_v(
                &commit_oid,
                repo,
@@ -78,7 +78,9 @@ int lg2_commit(git_repository *repo, int argc, char **argv)
 
        git_index_free(index);
        git_signature_free(signature);
-       git_tree_free(tree);    
+       git_tree_free(tree);
+       git_object_free(parent);
+       git_reference_free(ref);
 
        return error;
 }
index f86e92c3574c7f46d8335c714a35859b4e24fdcd..901c041461356b3881b341842ab500b949a1a0a8 100644 (file)
@@ -45,7 +45,7 @@
 #endif
 
 #ifdef _MSC_VER
-#define snprintf sprintf_s
+#define snprintf _snprintf
 #define strcasecmp strcmpi
 #endif
 
index 2305c86524f8589e0b69b3d06e0c961eba0f207b..a9fb5d4428a2c5aba566f5e0a7020cb276974371 100644 (file)
@@ -344,7 +344,7 @@ static void parse_opts(struct diff_options *o, int argc, char *argv[])
 static void diff_print_stats(git_diff *diff, struct diff_options *o)
 {
        git_diff_stats *stats;
-       git_buf b = GIT_BUF_INIT_CONST(NULL, 0);
+       git_buf b = GIT_BUF_INIT;
        git_diff_stats_format_t format = 0;
 
        check_lg2(
index c58ac038ad0d4474c8a71ecfe8f23b6c1f71acc9..df37dd0c45e084550275aa5dc2b015257a48ef69 100644 (file)
@@ -17,7 +17,6 @@ int lg2_index_pack(git_repository *repo, int argc, char **argv)
        git_indexer *idx;
        git_indexer_progress stats = {0, 0};
        int error;
-       char hash[GIT_OID_HEXSZ + 1] = {0};
        int fd;
        ssize_t read_bytes;
        char buf[512];
@@ -61,8 +60,7 @@ int lg2_index_pack(git_repository *repo, int argc, char **argv)
 
        printf("\rIndexing %u of %u\n", stats.indexed_objects, stats.total_objects);
 
-       git_oid_fmt(hash, git_indexer_hash(idx));
-       puts(hash);
+       puts(git_indexer_name(idx));
 
  cleanup:
        close(fd);
index 57f758c6ca3203d9e5ef55100af35b3940c96a5f..14fac030cd157a6fab171cc88eb38da1307e30d6 100644 (file)
@@ -27,7 +27,7 @@ enum subcmd {
        subcmd_remove,
        subcmd_rename,
        subcmd_seturl,
-       subcmd_show,
+       subcmd_show
 };
 
 struct remote_opts {
index 8cf922127bfd8a7a4971e80a05f5b0be4a1261d0..e659efb059b15a912ac3062ede4ce8e7732ec946 100644 (file)
@@ -38,7 +38,7 @@ enum {
        FORMAT_DEFAULT   = 0,
        FORMAT_LONG      = 1,
        FORMAT_SHORT     = 2,
-       FORMAT_PORCELAIN = 3,
+       FORMAT_PORCELAIN = 3
 };
 
 #define MAX_PATHSPEC 8
index 59eca24d00711067a1fa6a6bcf14020b2298e840..eaa490fd9b437bd67d2fa433ec1693693c345ee8 100644 (file)
@@ -1,23 +1,26 @@
-LINK_DIRECTORIES(${LIBGIT2_LIBDIRS})
-INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDES})
-INCLUDE_DIRECTORIES(SYSTEM ${LIBGIT2_SYSTEM_INCLUDES})
+if(BUILD_FUZZERS AND NOT USE_STANDALONE_FUZZERS)
+       set(CMAKE_REQUIRED_FLAGS "-fsanitize=fuzzer-no-link")
+       add_c_flag(-fsanitize=fuzzer)
+       add_c_flag(-fsanitize=fuzzer-no-link)
+       unset(CMAKE_REQUIRED_FLAGS)
+endif()
 
-IF(BUILD_FUZZERS AND NOT USE_STANDALONE_FUZZERS)
-       ADD_C_FLAG(-fsanitize=fuzzer)
-ENDIF ()
+file(GLOB SRC_FUZZERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *_fuzzer.c)
+foreach(fuzz_target_src ${SRC_FUZZERS})
+       string(REPLACE ".c" "" fuzz_target_name ${fuzz_target_src})
+       string(REPLACE "_fuzzer" "" fuzz_name ${fuzz_target_name})
 
-FILE(GLOB SRC_FUZZ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *_fuzzer.c)
-FOREACH(fuzz_target_src ${SRC_FUZZ})
-       STRING(REPLACE ".c" "" fuzz_target_name ${fuzz_target_src})
-       STRING(REPLACE "_fuzzer" "" fuzz_name ${fuzz_target_name})
+       set(${fuzz_target_name}_SOURCES ${fuzz_target_src} ${LIBGIT2_OBJECTS})
+       if(USE_STANDALONE_FUZZERS)
+               list(APPEND ${fuzz_target_name}_SOURCES "standalone_driver.c")
+       endif()
+       add_executable(${fuzz_target_name} ${${fuzz_target_name}_SOURCES})
+       set_target_properties(${fuzz_target_name} PROPERTIES C_STANDARD 90)
 
-       SET(${fuzz_target_name}_SOURCES ${fuzz_target_src} ${LIBGIT2_OBJECTS})
-       IF(USE_STANDALONE_FUZZERS)
-               LIST(APPEND ${fuzz_target_name}_SOURCES "standalone_driver.c")
-       ENDIF()
-       ADD_EXECUTABLE(${fuzz_target_name} ${${fuzz_target_name}_SOURCES})
-       SET_TARGET_PROPERTIES(${fuzz_target_name} PROPERTIES C_STANDARD 90)
-       TARGET_LINK_LIBRARIES(${fuzz_target_name} ${LIBGIT2_LIBS})
+       target_include_directories(${fuzz_target_name} PRIVATE ${LIBGIT2_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES})
+       target_include_directories(${fuzz_target_name} SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
 
-       ADD_TEST(${fuzz_target_name} "${CMAKE_CURRENT_BINARY_DIR}/${fuzz_target_name}" "${CMAKE_CURRENT_SOURCE_DIR}/corpora/${fuzz_name}")
-ENDFOREACH()
+       target_link_libraries(${fuzz_target_name} ${LIBGIT2_SYSTEM_LIBS})
+
+       add_test(${fuzz_target_name} "${CMAKE_CURRENT_BINARY_DIR}/${fuzz_target_name}" "${CMAKE_CURRENT_SOURCE_DIR}/corpora/${fuzz_name}")
+endforeach()
index b41816ed95115af36cfcac65811eacb12fe9a900..1c46d78c7146cd4de8fbffc91113760539d82882 100644 (file)
 
 #include "git2.h"
 
-#include "buffer.h"
 #include "common.h"
+#include "str.h"
 #include "futils.h"
 #include "hash.h"
 #include "commit_graph.h"
 
+#include "standalone_driver.h"
+
 int LLVMFuzzerInitialize(int *argc, char ***argv)
 {
        GIT_UNUSED(argc);
@@ -33,7 +35,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
        git_commit_graph_file file = {{0}};
        git_commit_graph_entry e;
-       git_buf commit_graph_buf = GIT_BUF_INIT;
+       git_str commit_graph_buf = GIT_STR_INIT;
+       unsigned char hash[GIT_HASH_SHA1_SIZE];
        git_oid oid = {{0}};
        bool append_hash = false;
 
@@ -50,22 +53,24 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
        size -= 4;
 
        if (append_hash) {
-               if (git_buf_init(&commit_graph_buf, size + sizeof(oid)) < 0)
+               if (git_str_init(&commit_graph_buf, size + GIT_HASH_SHA1_SIZE) < 0)
                        goto cleanup;
-               if (git_hash_buf(&oid, data, size) < 0) {
+               if (git_hash_buf(hash, data, size, GIT_HASH_ALGORITHM_SHA1) < 0) {
                        fprintf(stderr, "Failed to compute the SHA1 hash\n");
                        abort();
                }
                memcpy(commit_graph_buf.ptr, data, size);
-               memcpy(commit_graph_buf.ptr + size, &oid, sizeof(oid));
+               memcpy(commit_graph_buf.ptr + size, hash, GIT_HASH_SHA1_SIZE);
+
+               memcpy(oid.id, hash, GIT_OID_RAWSZ);
        } else {
-               git_buf_attach_notowned(&commit_graph_buf, (char *)data, size);
+               git_str_attach_notowned(&commit_graph_buf, (char *)data, size);
        }
 
        if (git_commit_graph_file_parse(
                            &file,
-                           (const unsigned char *)git_buf_cstr(&commit_graph_buf),
-                           git_buf_len(&commit_graph_buf))
+                           (const unsigned char *)git_str_cstr(&commit_graph_buf),
+                           git_str_len(&commit_graph_buf))
            < 0)
                goto cleanup;
 
@@ -75,6 +80,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 
 cleanup:
        git_commit_graph_file_close(&file);
-       git_buf_dispose(&commit_graph_buf);
+       git_str_dispose(&commit_graph_buf);
        return 0;
 }
index 526c93928daabac0a13f1000b2f4340e79dd5aaf..890adbfc528499ad152ecea94e3eb76ef5271084 100644 (file)
 #include "git2.h"
 #include "config_backend.h"
 
+#include "standalone_driver.h"
+
 #define UNUSED(x) (void)(x)
 
-int foreach_cb(const git_config_entry *entry, void *payload)
+static int foreach_cb(const git_config_entry *entry, void *payload)
 {
        UNUSED(entry);
        UNUSED(payload);
diff --git a/fuzzers/corpora/midx/666a779eed16847c6930a71c0547a34e52db409e b/fuzzers/corpora/midx/666a779eed16847c6930a71c0547a34e52db409e
new file mode 100644 (file)
index 0000000..ed9e0d0
Binary files /dev/null and b/fuzzers/corpora/midx/666a779eed16847c6930a71c0547a34e52db409e differ
index 9fe99d8d56810427a1dc74237f7714d9832d2980..b09444c80cffe2b1c5ae37e0c6f930975dd88422 100644 (file)
@@ -64,7 +64,7 @@ slack channel once you've registered.
 
 If you have questions about the library, please be sure to check out the
 [API documentation](http://libgit2.github.com/libgit2/).  If you still have
-questions, reach out to us on Slack or post a question on 
+questions, reach out to us on Slack or post a question on
 [StackOverflow](http://stackoverflow.com/questions/tagged/libgit2) (with the `libgit2` tag).
 
 **Reporting Bugs**
@@ -187,18 +187,18 @@ Once built, you can run the tests from the `build` directory with the command
 
 Alternatively you can run the test suite directly using,
 
-       $ ./libgit2_clar
+       $ ./libgit2_tests
 
 Invoking the test suite directly is useful because it allows you to execute
 individual tests, or groups of tests using the `-s` flag.  For example, to
 run the index tests:
 
-    $ ./libgit2_clar -sindex
+    $ ./libgit2_tests -sindex
 
 To run a single test named `index::racy::diff`, which corresponds to the test
 function (`test_index_racy__diff`)[https://github.com/libgit2/libgit2/blob/master/tests/index/racy.c#L23]:
 
-    $ ./libgit2_clar -sindex::racy::diff
+    $ ./libgit2_tests -sindex::racy::diff
 
 The test suite will print a `.` for every passing test, and an `F` for any
 failing test.  An `S` indicates that a test was skipped because it is not
@@ -229,7 +229,7 @@ The following CMake variables are declared:
 - `LIB_INSTALL_DIR`: Where to install libraries to.
 - `INCLUDE_INSTALL_DIR`: Where to install headers to.
 - `BUILD_SHARED_LIBS`: Build libgit2 as a Shared Library (defaults to ON)
-- `BUILD_CLAR`: Build [Clar](https://github.com/vmg/clar)-based test suite (defaults to ON)
+- `BUILD_TESTS`: Build [Clar](https://github.com/vmg/clar)-based test suite (defaults to ON)
 - `THREADSAFE`: Build libgit2 with threading support (defaults to ON)
 - `STDCALL`: Build libgit2 as `stdcall`. Turn off for `cdecl` (Windows; defaults to ON)
 
index c5726cba186afb34e4525a8be33264e558199211..ff95cd107ef69045f60587f85e24acb3519e5a62 100644 (file)
@@ -15,6 +15,8 @@
 #include "git2/sys/transport.h"
 #include "futils.h"
 
+#include "standalone_driver.h"
+
 #define UNUSED(x) (void)(x)
 
 struct fuzzer_buffer {
@@ -130,7 +132,7 @@ static int fuzzer_subtransport_new(
        return 0;
 }
 
-int fuzzer_subtransport_cb(
+static int fuzzer_subtransport_cb(
        git_smart_subtransport **out,
        git_transport *owner,
        void *payload)
@@ -145,7 +147,7 @@ int fuzzer_subtransport_cb(
        return 0;
 }
 
-int fuzzer_transport_cb(git_transport **out, git_remote *owner, void *param)
+static int fuzzer_transport_cb(git_transport **out, git_remote *owner, void *param)
 {
        git_smart_subtransport_definition def = {
                fuzzer_subtransport_cb,
@@ -155,7 +157,7 @@ int fuzzer_transport_cb(git_transport **out, git_remote *owner, void *param)
        return git_transport_smart(out, owner, &def);
 }
 
-void fuzzer_git_abort(const char *op)
+static void fuzzer_git_abort(const char *op)
 {
        const git_error *err = git_error_last();
        fprintf(stderr, "unexpected libgit error: %s: %s\n",
index e67873faa536450ff3595e30b8d4b2072c880773..4c3124e47823d7ff3eef2d846014e4a810018294 100644 (file)
 
 #include "git2.h"
 
-#include "buffer.h"
 #include "common.h"
 #include "futils.h"
 #include "hash.h"
 #include "midx.h"
 
+#include "standalone_driver.h"
+
 int LLVMFuzzerInitialize(int *argc, char ***argv)
 {
        GIT_UNUSED(argc);
@@ -33,7 +34,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
        git_midx_file idx = {{0}};
        git_midx_entry e;
-       git_buf midx_buf = GIT_BUF_INIT;
+       git_str midx_buf = GIT_STR_INIT;
+       unsigned char hash[GIT_HASH_SHA1_SIZE];
        git_oid oid = {{0}};
        bool append_hash = false;
 
@@ -50,19 +52,21 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
        size -= 4;
 
        if (append_hash) {
-               if (git_buf_init(&midx_buf, size + sizeof(oid)) < 0)
+               if (git_str_init(&midx_buf, size + GIT_HASH_SHA1_SIZE) < 0)
                        goto cleanup;
-               if (git_hash_buf(&oid, data, size) < 0) {
+               if (git_hash_buf(hash, data, size, GIT_HASH_ALGORITHM_SHA1) < 0) {
                        fprintf(stderr, "Failed to compute the SHA1 hash\n");
                        abort();
                }
                memcpy(midx_buf.ptr, data, size);
-               memcpy(midx_buf.ptr + size, &oid, sizeof(oid));
+               memcpy(midx_buf.ptr + size, hash, GIT_HASH_SHA1_SIZE);
+
+               memcpy(oid.id, hash, GIT_OID_RAWSZ);
        } else {
-               git_buf_attach_notowned(&midx_buf, (char *)data, size);
+               git_str_attach_notowned(&midx_buf, (char *)data, size);
        }
 
-       if (git_midx_parse(&idx, (const unsigned char *)git_buf_cstr(&midx_buf), git_buf_len(&midx_buf)) < 0)
+       if (git_midx_parse(&idx, (const unsigned char *)git_str_cstr(&midx_buf), git_str_len(&midx_buf)) < 0)
                goto cleanup;
 
        /* Search for any oid, just to exercise that codepath. */
@@ -71,6 +75,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 
 cleanup:
        git_midx_close(&idx);
-       git_buf_dispose(&midx_buf);
+       git_str_dispose(&midx_buf);
        return 0;
 }
index 1feff778dddf2e6ee290d4792fd6d70318cb4171..51b4a1ed4158358a7bdca55246f1a942c7f53d58 100644 (file)
@@ -10,6 +10,8 @@
 #include "git2.h"
 #include "object.h"
 
+#include "standalone_driver.h"
+
 #define UNUSED(x) (void)(x)
 
 int LLVMFuzzerInitialize(int *argc, char ***argv)
index 50c11575524f81c7add893c314e66ad733adc689..6002fa1de8f1f0bb6979ddef778c9de3b3a5b42b 100644 (file)
@@ -12,7 +12,9 @@
 #include "git2.h"
 #include "git2/sys/mempack.h"
 #include "common.h"
-#include "buffer.h"
+#include "str.h"
+
+#include "standalone_driver.h"
 
 static git_odb *odb = NULL;
 static git_odb_backend *mempack = NULL;
@@ -53,7 +55,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
        git_indexer_progress stats = {0, 0};
        git_indexer *indexer = NULL;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_oid oid;
        bool append_hash = false;
 
@@ -99,19 +101,19 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
        if (git_indexer_commit(indexer, &stats) < 0)
                goto cleanup;
 
-       if (git_buf_printf(&path, "pack-%s.idx", git_oid_tostr_s(git_indexer_hash(indexer))) < 0)
+       if (git_str_printf(&path, "pack-%s.idx", git_indexer_name(indexer)) < 0)
                goto cleanup;
-       p_unlink(git_buf_cstr(&path));
+       p_unlink(git_str_cstr(&path));
 
-       git_buf_clear(&path);
+       git_str_clear(&path);
 
-       if (git_buf_printf(&path, "pack-%s.pack", git_oid_tostr_s(git_indexer_hash(indexer))) < 0)
+       if (git_str_printf(&path, "pack-%s.pack", git_indexer_name(indexer)) < 0)
                goto cleanup;
-       p_unlink(git_buf_cstr(&path));
+       p_unlink(git_str_cstr(&path));
 
 cleanup:
        git_mempack_reset(mempack);
        git_indexer_free(indexer);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        return 0;
 }
index a9b02ad4dd38d98c4545330683e856e86127421c..2e65a01fd88f0fc2d73475b898f5010c4007eba6 100644 (file)
@@ -11,6 +11,8 @@
 #include "patch.h"
 #include "patch_parse.h"
 
+#include "standalone_driver.h"
+
 #define UNUSED(x) (void)(x)
 
 int LLVMFuzzerInitialize(int *argc, char ***argv)
index 90e7013339c63df777b96099e224e4d729a4fcae..cd4f71751ae52a133df69d5dbc6e0e8f8577a8d5 100644 (file)
 #include "futils.h"
 #include "path.h"
 
-extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);
-extern int LLVMFuzzerInitialize(int *argc, char ***argv);
+#include "standalone_driver.h"
 
 static int run_one_file(const char *filename)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        int error = 0;
 
        if (git_futils_readbuffer(&buf, filename) < 0) {
@@ -27,7 +26,7 @@ static int run_one_file(const char *filename)
 
        LLVMFuzzerTestOneInput((const unsigned char *)buf.ptr, buf.size);
 exit:
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
@@ -52,7 +51,7 @@ int main(int argc, char **argv)
        fprintf(stderr, "Running %s against %s\n", argv[0], argv[1]);
        LLVMFuzzerInitialize(&argc, &argv);
 
-       if (git_path_dirload(&corpus_files, argv[1], 0, 0x0) < 0) {
+       if (git_fs_path_dirload(&corpus_files, argv[1], 0, 0x0) < 0) {
                fprintf(stderr, "Failed to scan corpus directory '%s': %s\n",
                        argv[1], git_error_last()->message);
                error = -1;
diff --git a/fuzzers/standalone_driver.h b/fuzzers/standalone_driver.h
new file mode 100644 (file)
index 0000000..507fcb9
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * 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_standalone_driver_h__
+#define INCLUDE_standalone_driver_h__
+
+extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);
+extern int LLVMFuzzerInitialize(int *argc, char ***argv);
+
+#endif
index bc637df1c2ac591d665d47241abf28c5daf2913c..db652bde0b398aa1fe03f8b204aa716730393908 100644 (file)
@@ -32,6 +32,8 @@ GIT_BEGIN_DECL
  *
  * @param delta The delta to be applied
  * @param payload User-specified payload
+ * @return 0 if the delta is applied, < 0 if the apply process will be aborted
+ *     or > 0 if the delta will not be applied.
  */
 typedef int GIT_CALLBACK(git_apply_delta_cb)(
        const git_diff_delta *delta,
@@ -48,6 +50,8 @@ typedef int GIT_CALLBACK(git_apply_delta_cb)(
  *
  * @param hunk The hunk to be applied
  * @param payload User-specified payload
+ * @return 0 if the hunk is applied, < 0 if the apply process will be aborted
+ *     or > 0 if the hunk will not be applied.
  */
 typedef int GIT_CALLBACK(git_apply_hunk_cb)(
        const git_diff_hunk *hunk,
@@ -59,7 +63,7 @@ typedef enum {
         * Don't actually make changes, just test that the patch applies.
         * This is the equivalent of `git apply --check`.
         */
-       GIT_APPLY_CHECK = (1 << 0),
+       GIT_APPLY_CHECK = (1 << 0)
 } git_apply_flags_t;
 
 /**
@@ -89,6 +93,16 @@ typedef struct {
 #define GIT_APPLY_OPTIONS_VERSION 1
 #define GIT_APPLY_OPTIONS_INIT {GIT_APPLY_OPTIONS_VERSION}
 
+/**
+ * Initialize git_apply_options structure
+ *
+ * Initialize a `git_apply_options` with default values. Equivalent to creating
+ * an instance with GIT_APPLY_OPTIONS_INIT.
+ *
+ * @param opts The `git_apply_options` struct to initialize.
+ * @param version The struct version; pass `GIT_APPLY_OPTIONS_VERSION`
+ * @return 0 on success or -1 on failure.
+ */
 GIT_EXTERN(int) git_apply_options_init(git_apply_options *opts, unsigned int version);
 
 /**
@@ -127,7 +141,7 @@ typedef enum {
         * Apply the patch to both the working directory and the index.
         * This is the equivalent of `git apply --index`.
         */
-       GIT_APPLY_LOCATION_BOTH = 2,
+       GIT_APPLY_LOCATION_BOTH = 2
 } git_apply_location_t;
 
 /**
index 3891a0c972995be10d4126b4a9a2bb033611919e..0c838727d14a77fc3ac483fb8ee56866581d5179 100644 (file)
@@ -83,7 +83,7 @@ typedef enum {
        GIT_ATTR_VALUE_UNSPECIFIED = 0, /**< The attribute has been left unspecified */
        GIT_ATTR_VALUE_TRUE,   /**< The attribute has been set */
        GIT_ATTR_VALUE_FALSE,  /**< The attribute has been unset */
-       GIT_ATTR_VALUE_STRING, /**< This attribute has a value */
+       GIT_ATTR_VALUE_STRING  /**< This attribute has a value */
 } git_attr_value_t;
 
 /**
@@ -177,6 +177,7 @@ typedef struct {
  *             not have to exist, but if it does not, then it will be
  *             treated as a plain file (not a directory).
  * @param name The name of the attribute to look up.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_attr_get(
        const char **value_out,
@@ -199,6 +200,7 @@ GIT_EXTERN(int) git_attr_get(
  *             not have to exist, but if it does not, then it will be
  *             treated as a plain file (not a directory).
  * @param name The name of the attribute to look up.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_attr_get_ext(
        const char **value_out,
@@ -235,6 +237,7 @@ GIT_EXTERN(int) git_attr_get_ext(
  *             it will be treated as a plain file (i.e. not a directory).
  * @param num_attr The number of attributes being looked up
  * @param names An array of num_attr strings containing attribute names.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_attr_get_many(
        const char **values_out,
@@ -259,6 +262,7 @@ GIT_EXTERN(int) git_attr_get_many(
  *             it will be treated as a plain file (i.e. not a directory).
  * @param num_attr The number of attributes being looked up
  * @param names An array of num_attr strings containing attribute names.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_attr_get_many_ext(
        const char **values_out,
@@ -344,11 +348,16 @@ GIT_EXTERN(int) git_attr_cache_flush(
  * Add a macro definition.
  *
  * Macros will automatically be loaded from the top level `.gitattributes`
- * file of the repository (plus the build-in "binary" macro).  This
+ * file of the repository (plus the built-in "binary" macro).  This
  * function allows you to add others.  For example, to add the default
  * macro, you would call:
  *
  *     git_attr_add_macro(repo, "binary", "-diff -crlf");
+ *
+ * @param repo The repository to add the macro in.
+ * @param name The name of the macro.
+ * @param values The value for the macro.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_attr_add_macro(
        git_repository *repo,
index d193ce14ed5f2870dfab75032c9b5d3ffb6fa3f8..cb961a562095117c8bd168944679ef790b142671 100644 (file)
@@ -73,7 +73,7 @@ typedef enum {
        GIT_BLAME_USE_MAILMAP = (1<<5),
 
        /** Ignore whitespace differences */
-       GIT_BLAME_IGNORE_WHITESPACE = (1<<6),
+       GIT_BLAME_IGNORE_WHITESPACE = (1<<6)
 } git_blame_flag_t;
 
 /**
@@ -203,6 +203,9 @@ typedef struct git_blame git_blame;
 
 /**
  * Gets the number of hunks that exist in the blame structure.
+ *
+ * @param blame The blame structure to query.
+ * @return The number of hunks.
  */
 GIT_EXTERN(uint32_t) git_blame_get_hunk_count(git_blame *blame);
 
index 8fc73919d939efb8dc5ef268ed06604b262ceb5b..6db85f38d1b31dda7ade6e15364f02c504e67d2d 100644 (file)
@@ -119,7 +119,7 @@ typedef enum {
         * When set, filters will be loaded from a `.gitattributes` file
         * in the specified commit.
         */
-       GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT = (1 << 3),
+       GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT = (1 << 3)
 } git_blob_filter_flag_t;
 
 /**
@@ -284,12 +284,25 @@ GIT_EXTERN(int) git_blob_create_from_buffer(
  */
 GIT_EXTERN(int) git_blob_is_binary(const git_blob *blob);
 
+/**
+ * Determine if the given content is most certainly binary or not;
+ * this is the same mechanism used by `git_blob_is_binary` but only
+ * looking at raw data.
+ *
+ * @param data The blob data which content should be analyzed
+ * @param len The length of the data
+ * @return 1 if the content of the blob is detected
+ * as binary; 0 otherwise.
+ */
+GIT_EXTERN(int) git_blob_data_is_binary(const char *data, size_t len);
+
 /**
  * Create an in-memory copy of a blob. The copy must be explicitly
  * free'd or it will leak.
  *
  * @param out Pointer to store the copy of the object
  * @param source Original object to copy
+ * @return 0.
  */
 GIT_EXTERN(int) git_blob_dup(git_blob **out, git_blob *source);
 
index 24ea7f7d0f3709f538ead08d3ea0dcf0b7e74529..36a393d108f8386672c3e7b6c9ebf11e77d6c6a2 100644 (file)
@@ -34,6 +34,8 @@ GIT_BEGIN_DECL
  *
  * @param out Pointer where to store the underlying reference.
  *
+ * @param repo the repository to create the branch in.
+ *
  * @param branch_name Name for the branch; this name is
  * validated for consistency. It should also not conflict with
  * an already existing branch name.
index 926f1332dfe986f714a27c639861ffbc8b4ad5f8..9fa97203457cfd2ef18d7429c64333c182d0a9d0 100644 (file)
@@ -23,110 +23,50 @@ GIT_BEGIN_DECL
  *
  * Sometimes libgit2 wants to return an allocated data buffer to the
  * caller and have the caller take responsibility for freeing that memory.
- * This can be awkward if the caller does not have easy access to the same
- * allocation functions that libgit2 is using.  In those cases, libgit2
- * will fill in a `git_buf` and the caller can use `git_buf_dispose()` to
- * release it when they are done.
+ * To make ownership clear in these cases, libgit2 uses  `git_buf` to
+ * return this data.  Callers should use `git_buf_dispose()` to release
+ * the memory when they are done.
  *
- * A `git_buf` may also be used for the caller to pass in a reference to
- * a block of memory they hold.  In this case, libgit2 will not resize or
- * free the memory, but will read from it as needed.
- *
- * Some APIs may occasionally do something slightly unusual with a buffer,
- * such as setting `ptr` to a value that was passed in by the user.  In
- * those cases, the behavior will be clearly documented by the API.
+ * A `git_buf` contains a pointer to a NUL-terminated C string, and
+ * the length of the string (not including the NUL terminator).
  */
 typedef struct {
        /**
-        * The buffer contents.
-        *
-        * `ptr` points to the start of the allocated memory.  If it is NULL,
-        * then the `git_buf` is considered empty and libgit2 will feel free
-        * to overwrite it with new data.
+        * The buffer contents.  `ptr` points to the start of the buffer
+        * being returned.  The buffer's length (in bytes) is specified
+        * by the `size` member of the structure, and contains a NUL
+        * terminator at position `(size + 1)`.
         */
-       char   *ptr;
+       char *ptr;
 
        /**
-        * `asize` holds the known total amount of allocated memory if the `ptr`
-        *  was allocated by libgit2.  It may be larger than `size`.  If `ptr`
-        *  was not allocated by libgit2 and should not be resized and/or freed,
-        *  then `asize` will be set to zero.
+        * This field is reserved and unused.
         */
-       size_t asize;
+       size_t reserved;
 
        /**
-        * `size` holds the size (in bytes) of the data that is actually used.
+        * The length (in bytes) of the buffer pointed to by `ptr`,
+        * not including a NUL terminator.
         */
        size_t size;
 } git_buf;
 
 /**
- * Static initializer for git_buf from static buffer
+ * Use to initialize a `git_buf` before passing it to a function that
+ * will populate it.
  */
-#define GIT_BUF_INIT_CONST(STR,LEN) { (char *)(STR), 0, (size_t)(LEN) }
+#define GIT_BUF_INIT { NULL, 0, 0 }
 
 /**
  * Free the memory referred to by the git_buf.
  *
  * Note that this does not free the `git_buf` itself, just the memory
- * pointed to by `buffer->ptr`.  This will not free the memory if it looks
- * like it was not allocated internally, but it will clear the buffer back
- * to the empty state.
+ * pointed to by `buffer->ptr`.
  *
  * @param buffer The buffer to deallocate
  */
 GIT_EXTERN(void) git_buf_dispose(git_buf *buffer);
 
-/**
- * Resize the buffer allocation to make more space.
- *
- * This will attempt to grow the buffer to accommodate the target size.
- *
- * If the buffer refers to memory that was not allocated by libgit2 (i.e.
- * the `asize` field is zero), then `ptr` will be replaced with a newly
- * allocated block of data.  Be careful so that memory allocated by the
- * caller is not lost.  As a special variant, if you pass `target_size` as
- * 0 and the memory is not allocated by libgit2, this will allocate a new
- * buffer of size `size` and copy the external data into it.
- *
- * Currently, this will never shrink a buffer, only expand it.
- *
- * If the allocation fails, this will return an error and the buffer will be
- * marked as invalid for future operations, invaliding the contents.
- *
- * @param buffer The buffer to be resized; may or may not be allocated yet
- * @param target_size The desired available size
- * @return 0 on success, -1 on allocation failure
- */
-GIT_EXTERN(int) git_buf_grow(git_buf *buffer, size_t target_size);
-
-/**
- * Set buffer to a copy of some raw data.
- *
- * @param buffer The buffer to set
- * @param data The data to copy into the buffer
- * @param datalen The length of the data to copy into the buffer
- * @return 0 on success, -1 on allocation failure
- */
-GIT_EXTERN(int) git_buf_set(
-       git_buf *buffer, const void *data, size_t datalen);
-
-/**
-* Check quickly if buffer looks like it contains binary data
-*
-* @param buf Buffer to check
-* @return 1 if buffer looks like non-text data
-*/
-GIT_EXTERN(int) git_buf_is_binary(const git_buf *buf);
-
-/**
-* Check quickly if buffer contains a NUL byte
-*
-* @param buf Buffer to check
-* @return 1 if buffer contains a NUL byte
-*/
-GIT_EXTERN(int) git_buf_contains_nul(const git_buf *buf);
-
 GIT_END_DECL
 
 /** @} */
index 0ed38ffcdd411e6558f13cd47580da965d463911..05213a5719245e41191a2242138cc7b99504f30b 100644 (file)
@@ -44,7 +44,7 @@ typedef enum git_cert_t {
         * information about the certificate. This is used when using
         * curl.
         */
-       GIT_CERT_STRARRAY,
+       GIT_CERT_STRARRAY
 } git_cert_t;
 
 /**
@@ -82,7 +82,7 @@ typedef enum {
        /** SHA-256 is available */
        GIT_CERT_SSH_SHA256 = (1 << 2),
        /** Raw hostkey is available */
-       GIT_CERT_SSH_RAW = (1 << 3),
+       GIT_CERT_SSH_RAW = (1 << 3)
 } git_cert_ssh_t;
 
 typedef enum {
index c7aeee431208c3953e271d3a0cbb0fed503f3ec3..9f834111a67d9bd85028a20ad56547093feffba5 100644 (file)
@@ -182,7 +182,10 @@ typedef enum {
         * notifications; don't update the working directory or index.
         */
        GIT_CHECKOUT_DRY_RUN = (1u << 24),
-       
+
+       /** Include common ancestor data in zdiff3 format for conflicts */
+       GIT_CHECKOUT_CONFLICT_STYLE_ZDIFF3 = (1u << 25),
+
        /**
         * THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED
         */
@@ -190,7 +193,7 @@ typedef enum {
        /** Recursively checkout submodules with same options (NOT IMPLEMENTED) */
        GIT_CHECKOUT_UPDATE_SUBMODULES = (1u << 16),
        /** Recursively checkout submodules if HEAD moved in super repo (NOT IMPLEMENTED) */
-       GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED = (1u << 17),
+       GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED = (1u << 17)
 
 } git_checkout_strategy_t;
 
index 3c3ea260eff783149f8402091c6475005ff2258c..3481f254c9d5321df45e781e48bba7eab96ee3c5 100644 (file)
@@ -49,7 +49,7 @@ typedef enum {
         * Bypass the git-aware transport, but do not try to use
         * hardlinks.
         */
-       GIT_CLONE_LOCAL_NO_LINKS,
+       GIT_CLONE_LOCAL_NO_LINKS
 } git_clone_local_t;
 
 /**
@@ -74,8 +74,8 @@ typedef int GIT_CALLBACK(git_remote_create_cb)(
        void *payload);
 
 /**
- * The signature of a function matchin git_repository_init, with an
- * aditional void * as callback payload.
+ * The signature of a function matching git_repository_init, with an
+ * additional void * as callback payload.
  *
  * Callers of git_clone my provide a function matching this signature
  * to override the repository creation and customization process
index 4d74b8994fc2a281f62dfb0e51ffa35b7b6d59ee..67170cb9c83de5318dfb1c15ba8486e988e4dce6 100644 (file)
@@ -479,6 +479,7 @@ GIT_EXTERN(int) git_commit_create_buffer(
  * to the commit and write it into the given repository.
  *
  * @param out the resulting commit id
+ * @param repo the repository to create the commit in.
  * @param commit_content the content of the unsigned commit object
  * @param signature the signature to add to the commit. Leave `NULL`
  * to create a commit without adding a signature field.
@@ -499,6 +500,7 @@ GIT_EXTERN(int) git_commit_create_with_signature(
  *
  * @param out Pointer to store the copy of the commit
  * @param source Original commit to copy
+ * @return 0
  */
 GIT_EXTERN(int) git_commit_dup(git_commit **out, git_commit *source);
 
index 2ee82902529d2373570ecce199f72c21767ba4e3..b8c4ad53172b9f3afb77652e68c54fae0411b834 100644 (file)
@@ -147,7 +147,7 @@ typedef enum {
    * If set, libgit2 was built with support for sub-second resolution in file
    * modification times.
    */
-       GIT_FEATURE_NSEC        = (1 << 3),
+       GIT_FEATURE_NSEC        = (1 << 3)
 } git_feature_t;
 
 /**
@@ -167,6 +167,9 @@ typedef enum {
  * - GIT_FEATURE_SSH
  *   Libgit2 supports the SSH protocol for network operations. This requires
  *   the libssh2 library to be found when compiling libgit2
+ *
+ * - GIT_FEATURE_NSEC
+ *   Libgit2 supports the sub-second resolution in file modification times.
  */
 GIT_EXTERN(int) git_libgit2_features(void);
 
@@ -211,7 +214,9 @@ typedef enum {
        GIT_OPT_SET_ODB_PACKED_PRIORITY,
        GIT_OPT_SET_ODB_LOOSE_PRIORITY,
        GIT_OPT_GET_EXTENSIONS,
-       GIT_OPT_SET_EXTENSIONS
+       GIT_OPT_SET_EXTENSIONS,
+       GIT_OPT_GET_OWNER_VALIDATION,
+       GIT_OPT_SET_OWNER_VALIDATION
 } git_libgit2_opt_t;
 
 /**
@@ -449,6 +454,14 @@ typedef enum {
  *      > to support repositories with the `noop` extension but does want
  *      > to support repositories with the `newext` extension.
  *
+ *   opts(GIT_OPT_GET_OWNER_VALIDATION, int *enabled)
+ *      > Gets the owner validation setting for repository
+ *      > directories.
+ *
+ *   opts(GIT_OPT_SET_OWNER_VALIDATION, int enabled)
+ *      > Set that repository directories should be owned by the current
+ *      > user. The default is to validate ownership.
+ *
  * @param option Option key
  * @param ... value to set the option
  * @return 0 on success, <0 on failure
index 7c8e388b2379177a935ac74cf41a723a8a8dc64b..a5486a4c97ddc6f51179f8c00722a15f49e9888a 100644 (file)
@@ -55,7 +55,7 @@ typedef enum {
        /** Represents the highest level available config file (i.e. the most
         * specific config file available that actually is loaded)
         */
-       GIT_CONFIG_HIGHEST_LEVEL = -1,
+       GIT_CONFIG_HIGHEST_LEVEL = -1
 } git_config_level_t;
 
 /**
@@ -72,14 +72,17 @@ typedef struct git_config_entry {
 
 /**
  * Free a config entry
+ *
+ * @param entry The entry to free.
  */
-GIT_EXTERN(void) git_config_entry_free(git_config_entry *);
+GIT_EXTERN(void) git_config_entry_free(git_config_entry *entry);
 
 /**
  * A config enumeration callback
  *
  * @param entry the entry currently being enumerated
  * @param payload a user-specified pointer
+ * @return non-zero to terminate the iteration.
  */
 typedef int GIT_CALLBACK(git_config_foreach_cb)(const git_config_entry *entry, void *payload);
 
@@ -269,6 +272,7 @@ GIT_EXTERN(int) git_config_open_level(
  *
  * @param out pointer in which to store the config object
  * @param config the config object in which to look
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_config_open_global(git_config **out, git_config *config);
 
@@ -422,6 +426,7 @@ GIT_EXTERN(int) git_config_get_string_buf(git_buf *out, const git_config *cfg, c
  * interested in. Use NULL to indicate all
  * @param callback the function to be called on each value of the variable
  * @param payload opaque pointer to pass to the callback
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_config_get_multivar_foreach(const git_config *cfg, const char *name, const char *regexp, git_config_foreach_cb callback, void *payload);
 
@@ -437,6 +442,7 @@ GIT_EXTERN(int) git_config_get_multivar_foreach(const git_config *cfg, const cha
  * @param name the variable's name
  * @param regexp regular expression to filter which variables we're
  * interested in. Use NULL to indicate all
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_config_multivar_iterator_new(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp);
 
@@ -515,6 +521,7 @@ GIT_EXTERN(int) git_config_set_string(git_config *cfg, const char *name, const c
  * @param name the variable's name
  * @param regexp a regular expression to indicate which values to replace
  * @param value the new value.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value);
 
@@ -524,6 +531,7 @@ GIT_EXTERN(int) git_config_set_multivar(git_config *cfg, const char *name, const
  *
  * @param cfg the configuration
  * @param name the variable to delete
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_config_delete_entry(git_config *cfg, const char *name);
 
@@ -568,7 +576,8 @@ GIT_EXTERN(int) git_config_foreach(
  * `git_config_iterator_free` when done.
  *
  * @param out pointer to store the iterator
- * @param cfg where to ge the variables from
+ * @param cfg where to get the variables from
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_config_iterator_new(git_config_iterator **out, const git_config *cfg);
 
@@ -585,6 +594,7 @@ GIT_EXTERN(int) git_config_iterator_new(git_config_iterator **out, const git_con
  * @param out pointer to store the iterator
  * @param cfg where to ge the variables from
  * @param regexp regular expression to match the names
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_config_iterator_glob_new(git_config_iterator **out, const git_config *cfg, const char *regexp);
 
@@ -662,6 +672,7 @@ GIT_EXTERN(int) git_config_get_mapped(
  * @param maps array of `git_configmap` objects specifying the possible mappings
  * @param map_n number of mapping objects in `maps`
  * @param value value to parse
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_config_lookup_map_value(
        int *out,
@@ -678,6 +689,7 @@ GIT_EXTERN(int) git_config_lookup_map_value(
  *
  * @param out place to store the result of the parsing
  * @param value value to parse
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_config_parse_bool(int *out, const char *value);
 
@@ -690,6 +702,7 @@ GIT_EXTERN(int) git_config_parse_bool(int *out, const char *value);
  *
  * @param out place to store the result of the parsing
  * @param value value to parse
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_config_parse_int32(int32_t *out, const char *value);
 
@@ -702,6 +715,7 @@ GIT_EXTERN(int) git_config_parse_int32(int32_t *out, const char *value);
  *
  * @param out place to store the result of the parsing
  * @param value value to parse
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_config_parse_int64(int64_t *out, const char *value);
 
@@ -717,6 +731,7 @@ GIT_EXTERN(int) git_config_parse_int64(int64_t *out, const char *value);
  *
  * @param out placae to store the result of parsing
  * @param value the path to evaluate
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_config_parse_path(git_buf *out, const char *value);
 
@@ -735,6 +750,7 @@ GIT_EXTERN(int) git_config_parse_path(git_buf *out, const char *value);
  * @param regexp regular expression to match against config names (can be NULL)
  * @param callback the function to call on each variable
  * @param payload the data to pass to the callback
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_config_backend_foreach_match(
        git_config_backend *backend,
index 9426a6ea2bf2625086ffa31ff5311719a6491276..7a04bc064795f4ae7894596841ae99eb84657a33 100644 (file)
@@ -75,7 +75,7 @@ typedef enum {
         *
         * @see git_credential_ssh_key_memory_new
         */
-       GIT_CREDENTIAL_SSH_MEMORY = (1u << 6),
+       GIT_CREDENTIAL_SSH_MEMORY = (1u << 6)
 } git_credential_t;
 
 /**
@@ -254,6 +254,7 @@ typedef void GIT_CALLBACK(git_credential_ssh_interactive_cb)(
  * Create a new ssh keyboard-interactive based credential object.
  * The supplied credential parameter will be internally duplicated.
  *
+ * @param out The newly created credential object.
  * @param username Username to use to authenticate.
  * @param prompt_callback The callback method used for prompts.
  * @param payload Additional data to pass to the callback.
index 9a70ecb385693238da3c1a52a8fb3fd9d398bfc8..f0fb07041d9b1ecfba6f30cffc3bcdd449a07473 100644 (file)
@@ -39,6 +39,7 @@ typedef struct git_credential_userpass_payload {
  * @param allowed_types A bitmask stating which credential types are OK to return.
  * @param payload The payload provided when specifying this callback.  (This is
  *        interpreted as a `git_credential_userpass_payload*`.)
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_credential_userpass(
                git_credential **out,
index 37b9fa0e2f1549bb64a83f6dc551a29715676b77..f73d7da6181f7793615c377e7ed4fea6c6872260 100644 (file)
@@ -313,7 +313,7 @@ typedef enum {
        GIT_DIFF_FORMAT_EMAIL_NONE = 0,
 
        /** Don't insert "[PATCH]" in the subject header*/
-       GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER = (1 << 0),
+       GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER = (1 << 0)
 
 } git_diff_format_email_flags_t;
 
index 1d2ca1496fb6f71bd6f55c92db4b92c71371977e..7a796f1309c7437855122df588bbfb3543f523d2 100644 (file)
@@ -30,7 +30,7 @@ GIT_BEGIN_DECL
 typedef enum {
        GIT_DESCRIBE_DEFAULT,
        GIT_DESCRIBE_TAGS,
-       GIT_DESCRIBE_ALL,
+       GIT_DESCRIBE_ALL
 } git_describe_strategy_t;
 
 /**
@@ -142,6 +142,7 @@ typedef struct git_describe_result git_describe_result;
  * you're done with it.
  * @param committish a committish to describe
  * @param opts the lookup options (or NULL for defaults)
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_describe_commit(
        git_describe_result **result,
@@ -152,13 +153,14 @@ GIT_EXTERN(int) git_describe_commit(
  * 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
+ * worktree. After performing describe on HEAD, a status is run and the
  * description is considered to be dirty if there are.
  *
  * @param out 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 (or NULL for defaults)
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_describe_workdir(
        git_describe_result **out,
@@ -172,6 +174,7 @@ GIT_EXTERN(int) git_describe_workdir(
  * @param result the result from `git_describe_commit()` or
  * `git_describe_workdir()`.
  * @param opts the formatting options (or NULL for defaults)
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_describe_format(
        git_buf *out,
@@ -180,6 +183,8 @@ GIT_EXTERN(int) git_describe_format(
 
 /**
  * Free the describe result.
+ *
+ * @param result The result to free.
  */
 GIT_EXTERN(void) git_describe_result_free(git_describe_result *result);
 
index a14c01993faca354582b8fba59c838f11ad4082e..3839f0033ce7fcc563d60cf078c412ce3af0790d 100644 (file)
@@ -170,7 +170,7 @@ typedef enum {
        /** Include the necessary deflate / delta information so that `git-apply`
         *  can apply given diff information to binary files.
         */
-       GIT_DIFF_SHOW_BINARY = (1u << 30),
+       GIT_DIFF_SHOW_BINARY = (1u << 30)
 } git_diff_option_t;
 
 /**
@@ -208,6 +208,7 @@ typedef enum {
        GIT_DIFF_FLAG_NOT_BINARY = (1u << 1), /**< file(s) treated as text data */
        GIT_DIFF_FLAG_VALID_ID   = (1u << 2), /**< `id` value is known correct */
        GIT_DIFF_FLAG_EXISTS     = (1u << 3), /**< file exists at this side of the delta */
+       GIT_DIFF_FLAG_VALID_SIZE = (1u << 4)  /**< file size value is known correct */
 } git_diff_flag_t;
 
 /**
@@ -231,7 +232,7 @@ typedef enum {
        GIT_DELTA_UNTRACKED = 7,   /**< entry is untracked item in workdir */
        GIT_DELTA_TYPECHANGE = 8,  /**< type of entry changed between old and new */
        GIT_DELTA_UNREADABLE = 9,  /**< entry is unreadable */
-       GIT_DELTA_CONFLICTED = 10, /**< entry in the index is conflicted */
+       GIT_DELTA_CONFLICTED = 10  /**< entry in the index is conflicted */
 } git_delta_t;
 
 /**
@@ -497,7 +498,7 @@ typedef enum {
        GIT_DIFF_BINARY_LITERAL,
 
        /** The binary data is the delta from one side to the other. */
-       GIT_DIFF_BINARY_DELTA,
+       GIT_DIFF_BINARY_DELTA
 } git_diff_binary_t;
 
 /** The contents of one of the files in a binary diff. */
@@ -706,7 +707,7 @@ typedef enum {
         * GIT_DIFF_INCLUDE_UNMODIFIED flag.  If you do not want UNMODIFIED
         * records in the final result, pass this flag to have them removed.
         */
-       GIT_DIFF_FIND_REMOVE_UNMODIFIED = (1u << 16),
+       GIT_DIFF_FIND_REMOVE_UNMODIFIED = (1u << 16)
 } git_diff_find_t;
 
 /**
@@ -758,7 +759,7 @@ typedef struct {
        uint16_t copy_threshold;
 
        /**
-        * Treshold below which similar files will be split into a delete/add pair.
+        * Threshold below which similar files will be split into a delete/add pair.
         * This is equivalent to the last part of the -B option. Defaults to 60.
         */
        uint16_t break_rewrite_threshold;
@@ -768,7 +769,7 @@ typedef struct {
         *
         * This is a little different from the `-l` option from Git because we
         * will still process up to this many matches before abandoning the search.
-        * Defaults to 200.
+        * Defaults to 1000.
         */
        size_t rename_limit;
 
@@ -831,6 +832,7 @@ GIT_EXTERN(void) git_diff_free(git_diff *diff);
  * @param old_tree A git_tree object to diff from, or NULL for empty tree.
  * @param new_tree A git_tree object to diff to, or NULL for empty tree.
  * @param opts Structure with options to influence diff or NULL for defaults.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_diff_tree_to_tree(
        git_diff **diff,
@@ -857,6 +859,7 @@ GIT_EXTERN(int) git_diff_tree_to_tree(
  * @param old_tree A git_tree object to diff from, or NULL for empty tree.
  * @param index The index to diff with; repo index used if NULL.
  * @param opts Structure with options to influence diff or NULL for defaults.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_diff_tree_to_index(
        git_diff **diff,
@@ -884,6 +887,7 @@ GIT_EXTERN(int) git_diff_tree_to_index(
  * @param repo The repository.
  * @param index The index to diff from; repo index used if NULL.
  * @param opts Structure with options to influence diff or NULL for defaults.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_diff_index_to_workdir(
        git_diff **diff,
@@ -913,6 +917,7 @@ GIT_EXTERN(int) git_diff_index_to_workdir(
  * @param repo The repository containing the tree.
  * @param old_tree A git_tree object to diff from, or NULL for empty tree.
  * @param opts Structure with options to influence diff or NULL for defaults.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_diff_tree_to_workdir(
        git_diff **diff,
@@ -932,6 +937,7 @@ GIT_EXTERN(int) git_diff_tree_to_workdir(
  * @param repo The repository containing the tree.
  * @param old_tree A git_tree object to diff from, or NULL for empty tree.
  * @param opts Structure with options to influence diff or NULL for defaults.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_diff_tree_to_workdir_with_index(
        git_diff **diff,
@@ -950,6 +956,7 @@ GIT_EXTERN(int) git_diff_tree_to_workdir_with_index(
  * @param old_index A git_index object to diff from.
  * @param new_index A git_index object to diff to.
  * @param opts Structure with options to influence diff or NULL for defaults.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_diff_index_to_index(
        git_diff **diff,
@@ -970,6 +977,7 @@ GIT_EXTERN(int) git_diff_index_to_index(
  *
  * @param onto Diff to merge into.
  * @param from Diff to merge.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_diff_merge(
        git_diff *onto,
@@ -1107,7 +1115,7 @@ typedef enum {
        GIT_DIFF_FORMAT_RAW          = 3u, /**< like git diff --raw */
        GIT_DIFF_FORMAT_NAME_ONLY    = 4u, /**< like git diff --name-only */
        GIT_DIFF_FORMAT_NAME_STATUS  = 5u, /**< like git diff --name-status */
-       GIT_DIFF_FORMAT_PATCH_ID     = 6u, /**< git diff as used by git patch-id */
+       GIT_DIFF_FORMAT_PATCH_ID     = 6u  /**< git diff as used by git patch-id */
 } git_diff_format_t;
 
 /**
@@ -1311,13 +1319,13 @@ typedef enum {
        GIT_DIFF_STATS_NUMBER = (1u << 2),
 
        /** Extended header information such as creations, renames and mode changes, equivalent of `--summary` */
-       GIT_DIFF_STATS_INCLUDE_SUMMARY = (1u << 3),
+       GIT_DIFF_STATS_INCLUDE_SUMMARY = (1u << 3)
 } git_diff_stats_format_t;
 
 /**
  * Accumulate diff statistics for all patches.
  *
- * @param out Structure containg the diff statistics.
+ * @param out Structure containing the diff statistics.
  * @param diff A git_diff generated by one of the above functions.
  * @return 0 on success; non-zero on error
  */
index b56be5d0edce00c4f37e0d2bfe6cff2fdf76e72b..20393653e9f4f2635f9a5ec96f61209d566a9e82 100644 (file)
@@ -34,7 +34,7 @@ typedef enum {
        GIT_EMAIL_CREATE_ALWAYS_NUMBER = (1u << 1),
 
        /** Do not perform rename or similarity detection. */
-       GIT_EMAIL_CREATE_NO_RENAMES = (1u << 2),
+       GIT_EMAIL_CREATE_NO_RENAMES = (1u << 2)
 } git_email_create_flags_t;
 
 /**
index de51582d58ec7b340bd510a15bfb80033221ba4a..16712f988b987071ccbbdcbbe4080c48e6ad851b 100644 (file)
@@ -58,6 +58,7 @@ typedef enum {
        GIT_EMISMATCH       = -33,      /**< Hashsum mismatch in object */
        GIT_EINDEXDIRTY     = -34,      /**< Unsaved changes in the index would be overwritten */
        GIT_EAPPLYFAIL      = -35,      /**< Patch application failed */
+       GIT_EOWNER          = -36       /**< The object is not owned by the current user */
 } git_error_code;
 
 /**
index 0465e5b144ad27de41ce639736483208a4673f02..79bf14ce5b7e4b6ed060a048d3612108a5446156 100644 (file)
@@ -32,7 +32,7 @@ typedef enum {
        GIT_FILTER_TO_WORKTREE = 0,
        GIT_FILTER_SMUDGE = GIT_FILTER_TO_WORKTREE,
        GIT_FILTER_TO_ODB = 1,
-       GIT_FILTER_CLEAN = GIT_FILTER_TO_ODB,
+       GIT_FILTER_CLEAN = GIT_FILTER_TO_ODB
 } git_filter_mode_t;
 
 /**
@@ -54,7 +54,7 @@ typedef enum {
         * Load attributes from `.gitattributes` in a given commit.
         * This can only be specified in a `git_filter_options`.
         */
-       GIT_FILTER_ATTRIBUTES_FROM_COMMIT = (1u << 3),
+       GIT_FILTER_ATTRIBUTES_FROM_COMMIT = (1u << 3)
 } git_filter_flag_t;
 
 /**
@@ -196,6 +196,7 @@ GIT_EXTERN(int) git_filter_list_apply_to_buffer(
  * @param repo the repository in which to perform the filtering
  * @param path the path of the file to filter, a relative path will be
  * taken as relative to the workdir
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_filter_list_apply_to_file(
        git_buf *out,
@@ -209,6 +210,7 @@ GIT_EXTERN(int) git_filter_list_apply_to_file(
  * @param out buffer into which to store the filtered file
  * @param filters the list of filters to apply
  * @param blob the blob to filter
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_filter_list_apply_to_blob(
        git_buf *out,
@@ -222,6 +224,7 @@ GIT_EXTERN(int) git_filter_list_apply_to_blob(
  * @param buffer the buffer to filter
  * @param len the size of the buffer
  * @param target the stream into which the data will be written
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_filter_list_stream_buffer(
        git_filter_list *filters,
@@ -237,6 +240,7 @@ GIT_EXTERN(int) git_filter_list_stream_buffer(
  * @param path the path of the file to filter, a relative path will be
  * taken as relative to the workdir
  * @param target the stream into which the data will be written
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_filter_list_stream_file(
        git_filter_list *filters,
@@ -250,6 +254,7 @@ GIT_EXTERN(int) git_filter_list_stream_file(
  * @param filters the list of filters to apply
  * @param blob the blob to filter
  * @param target the stream into which the data will be written
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_filter_list_stream_blob(
        git_filter_list *filters,
index 712ae474a060b63a5b06ad80b627b60e6d6c22ce..56edb2f87f91338c926c2abc196394e0f2f39826 100644 (file)
@@ -33,6 +33,7 @@ GIT_BEGIN_DECL
  * @param repo the repository where the commits exist
  * @param local the commit for local
  * @param upstream the commit for upstream
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_graph_ahead_behind(size_t *ahead, size_t *behind, git_repository *repo, const git_oid *local, const git_oid *upstream);
 
index f5143f3ad27a6f780f7d34ff215534d2b64fa078..4c441c63384f2c5bc818ac30219d3fe058dadba8 100644 (file)
@@ -29,7 +29,7 @@ GIT_BEGIN_DECL
  * This would add three rules to the ignores.
  *
  * @param repo The repository to add ignore rules to.
- * @param rules Text of rules, a la the contents of a .gitignore file.
+ * @param rules Text of rules, the contents to add on a .gitignore file.
  *              It is okay to have multiple rules in the text; if so,
  *              each rule should be terminated with a newline.
  * @return 0 on success
index 532a52091f4c24b0dbbb04942e620a3c6a9e0137..981535dadad7099b14f791dd38d07de4bb319395 100644 (file)
@@ -86,7 +86,7 @@ typedef struct git_index_entry {
  */
 typedef enum {
        GIT_INDEX_ENTRY_EXTENDED  = (0x4000),
-       GIT_INDEX_ENTRY_VALID     = (0x8000),
+       GIT_INDEX_ENTRY_VALID     = (0x8000)
 } git_index_entry_flag_t;
 
 #define GIT_INDEX_ENTRY_STAGE(E) \
@@ -119,7 +119,7 @@ typedef enum {
 
        GIT_INDEX_ENTRY_EXTENDED_FLAGS =  (GIT_INDEX_ENTRY_INTENT_TO_ADD | GIT_INDEX_ENTRY_SKIP_WORKTREE),
 
-       GIT_INDEX_ENTRY_UPTODATE       =  (1 << 2),
+       GIT_INDEX_ENTRY_UPTODATE       =  (1 << 2)
 } git_index_entry_extended_flag_t;
 
 /** Capabilities of system that affect index actions. */
@@ -127,7 +127,7 @@ typedef enum {
        GIT_INDEX_CAPABILITY_IGNORE_CASE = 1,
        GIT_INDEX_CAPABILITY_NO_FILEMODE = 2,
        GIT_INDEX_CAPABILITY_NO_SYMLINKS = 4,
-       GIT_INDEX_CAPABILITY_FROM_OWNER  = -1,
+       GIT_INDEX_CAPABILITY_FROM_OWNER  = -1
 } git_index_capability_t;
 
 
@@ -140,7 +140,7 @@ typedef enum {
        GIT_INDEX_ADD_DEFAULT = 0,
        GIT_INDEX_ADD_FORCE = (1u << 0),
        GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH = (1u << 1),
-       GIT_INDEX_ADD_CHECK_PATHSPEC = (1u << 2),
+       GIT_INDEX_ADD_CHECK_PATHSPEC = (1u << 2)
 } git_index_add_option_t;
 
 /** Git index stage states */
@@ -163,7 +163,7 @@ typedef enum {
        GIT_INDEX_STAGE_OURS = 2,
 
        /** The "theirs" side of a conflict. */
-       GIT_INDEX_STAGE_THEIRS = 3,
+       GIT_INDEX_STAGE_THEIRS = 3
 } git_index_stage_t;
 
 /**
@@ -296,6 +296,7 @@ GIT_EXTERN(int) git_index_write(git_index *index);
  */
 GIT_EXTERN(const char *) git_index_path(const git_index *index);
 
+#ifndef GIT_DEPRECATE_HARD
 /**
  * Get the checksum of the index
  *
@@ -303,10 +304,12 @@ GIT_EXTERN(const char *) git_index_path(const git_index *index);
  * last 20 bytes which are the checksum itself). In cases where the
  * index does not exist on-disk, it will be zeroed out.
  *
+ * @deprecated this function is deprecated with no replacement
  * @param index an existing index object
  * @return a pointer to the checksum of the index
  */
 GIT_EXTERN(const git_oid *) git_index_checksum(git_index *index);
+#endif
 
 /**
  * Read a tree into the index file with stats
@@ -491,6 +494,7 @@ GIT_EXTERN(int) git_index_entry_is_conflict(const git_index_entry *entry);
  *
  * @param iterator_out The newly created iterator
  * @param index The index to iterate
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_index_iterator_new(
        git_index_iterator **iterator_out,
@@ -787,6 +791,7 @@ GIT_EXTERN(int) git_index_conflict_cleanup(git_index *index);
 /**
  * Determine if the index contains entries representing file conflicts.
  *
+ * @param index An existing index object.
  * @return 1 if at least one conflict is found, 0 otherwise.
  */
 GIT_EXTERN(int) git_index_has_conflicts(const git_index *index);
@@ -811,6 +816,7 @@ GIT_EXTERN(int) git_index_conflict_iterator_new(
  * @param ancestor_out Pointer to store the ancestor side of the conflict
  * @param our_out Pointer to store our side of the conflict
  * @param their_out Pointer to store their side of the conflict
+ * @param iterator The conflict iterator.
  * @return 0 (no error), GIT_ITEROVER (iteration is done) or an error code
  *         (negative value)
  */
index a434d243f267102a771424d1769ecea75e73aec8..ffe9bf366d5bd2761a5041b544c93f7fa740ff40 100644 (file)
@@ -98,6 +98,7 @@ GIT_EXTERN(int) git_indexer_options_init(
  * will be returned if there are bases missing)
  * @param opts Optional structure containing additional options. See
  * `git_indexer_options` above.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_indexer_new(
                git_indexer **out,
@@ -113,6 +114,7 @@ GIT_EXTERN(int) git_indexer_new(
  * @param data the data to add
  * @param size the size of the data in bytes
  * @param stats stat storage
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_indexer_append(git_indexer *idx, const void *data, size_t size, git_indexer_progress *stats);
 
@@ -122,18 +124,35 @@ GIT_EXTERN(int) git_indexer_append(git_indexer *idx, const void *data, size_t si
  * Resolve any pending deltas and write out the index file
  *
  * @param idx the indexer
+ * @param stats Stat storage.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_indexer_commit(git_indexer *idx, git_indexer_progress *stats);
 
+#ifndef GIT_DEPRECATE_HARD
 /**
  * Get the packfile's hash
  *
  * A packfile's name is derived from the sorted hashing of all object
  * names. This is only correct after the index has been finalized.
  *
+ * @deprecated use git_indexer_name
  * @param idx the indexer instance
+ * @return the packfile's hash
  */
 GIT_EXTERN(const git_oid *) git_indexer_hash(const git_indexer *idx);
+#endif
+
+/**
+ * Get the unique name for the resulting packfile.
+ *
+ * The packfile's name is derived from the packfile's content.
+ * This is only correct after the index has been finalized.
+ *
+ * @param idx the indexer instance
+ * @return a NUL terminated string for the packfile name
+ */
+GIT_EXTERN(const char *) git_indexer_name(const git_indexer *idx);
 
 /**
  * Free the indexer and its resources
index fc27c9d1dc98077645f51e5114c56431367456d4..e90941a499f335e2c57b3235a74d93c1ce06b16e 100644 (file)
@@ -92,6 +92,14 @@ typedef enum {
         * merge base to `git-merge-resolve`.
         */
        GIT_MERGE_NO_RECURSIVE = (1 << 3),
+
+       /**
+        * Treat this merge as if it is to produce the virtual base
+        * of a recursive merge.  This will ensure that there are
+        * no conflicts, any conflicting regions will keep conflict
+        * markers in the merge result.
+        */
+       GIT_MERGE_VIRTUAL_BASE = (1 << 4)
 } git_merge_flag_t;
 
 /**
@@ -127,7 +135,7 @@ typedef enum {
         * which has the result of combining both files.  The index will not
         * record a conflict.
         */
-       GIT_MERGE_FILE_FAVOR_UNION = 3,
+       GIT_MERGE_FILE_FAVOR_UNION = 3
 } git_merge_file_favor_t;
 
 /**
@@ -160,6 +168,16 @@ typedef enum {
 
        /** Take extra time to find minimal diff */
        GIT_MERGE_FILE_DIFF_MINIMAL = (1 << 7),
+
+       /** Create zdiff3 ("zealous diff3")-style files */
+       GIT_MERGE_FILE_STYLE_ZDIFF3 = (1 << 8),
+
+       /**
+        * Do not produce file conflicts when common regions have
+        * changed; keep the conflict markers in the file and accept
+        * that as the merge result.
+        */
+       GIT_MERGE_FILE_ACCEPT_CONFLICTS = (1 << 9)
 } git_merge_file_flag_t;
 
 #define GIT_MERGE_CONFLICT_MARKER_SIZE 7
@@ -341,7 +359,7 @@ typedef enum {
         * a valid commit.  No merge can be performed, but the caller may wish
         * to simply set HEAD to the target commit(s).
         */
-       GIT_MERGE_ANALYSIS_UNBORN = (1 << 3),
+       GIT_MERGE_ANALYSIS_UNBORN = (1 << 3)
 } git_merge_analysis_t;
 
 /**
@@ -364,7 +382,7 @@ typedef enum {
         * There is a `merge.ff=only` configuration setting, suggesting that
         * the user only wants fast-forward merges.
         */
-       GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY = (1 << 1),
+       GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY = (1 << 1)
 } git_merge_preference_t;
 
 /**
@@ -372,6 +390,7 @@ typedef enum {
  * merging them into the HEAD of the repository.
  *
  * @param analysis_out analysis enumeration that the result is written into
+ * @param preference_out One of the `git_merge_preference_t` flag.
  * @param repo the repository to merge
  * @param their_heads the heads to merge into
  * @param their_heads_len the number of heads to merge
@@ -389,6 +408,7 @@ GIT_EXTERN(int) git_merge_analysis(
  * merging them into a reference.
  *
  * @param analysis_out analysis enumeration that the result is written into
+ * @param preference_out One of the `git_merge_preference_t` flag.
  * @param repo the repository to merge
  * @param our_ref the reference to perform the analysis from
  * @param their_heads the heads to merge into
index 42ca3e5c291208430cff76658d427e12a4af0fea..cd3ddf730e0bf49e92b79efa7a6bf3ccc0adc41f 100644 (file)
@@ -75,6 +75,8 @@ GIT_EXTERN(int) git_message_trailers(git_message_trailer_array *arr, const char
 /**
  * Clean's up any allocated memory in the git_message_trailer_array filled by
  * a call to git_message_trailers.
+ *
+ * @param arr The trailer to free.
  */
 GIT_EXTERN(void) git_message_trailer_array_free(git_message_trailer_array *arr);
 
index 984dbb7ac0ab33cb2cba45292ed3fb5f374f849c..5610a476f492286068d6896bcc38933490228b44 100644 (file)
@@ -221,9 +221,32 @@ GIT_EXTERN(int) git_object_peel(
  *
  * @param dest Pointer to store the copy of the object
  * @param source Original object to copy
+ * @return 0 or an error code
  */
 GIT_EXTERN(int) git_object_dup(git_object **dest, git_object *source);
 
+/**
+ * Analyzes a buffer of raw object content and determines its validity.
+ * Tree, commit, and tag objects will be parsed and ensured that they
+ * are valid, parseable content.  (Blobs are always valid by definition.)
+ * An error message will be set with an informative message if the object
+ * is not valid.
+ *
+ * @warning This function is experimental and its signature may change in
+ * the future.
+ *
+ * @param valid Output pointer to set with validity of the object content
+ * @param buf The contents to validate
+ * @param len The length of the buffer
+ * @param type The type of the object in the buffer
+ * @return 0 on success or an error code
+ */
+GIT_EXTERN(int) git_object_rawcontent_is_valid(
+       int *valid,
+       const char *buf,
+       size_t len,
+       git_object_t type);
+
 /** @} */
 GIT_END_DECL
 
index dd484553ff24397ef519a20d21f4ec0e45c7cc58..0ffe3f32815589b174ae7c59913f6d50242cefdc 100644 (file)
  */
 GIT_BEGIN_DECL
 
+/** Flags controlling the behavior of ODB lookup operations */
+typedef enum {
+       /**
+        * Don't call `git_odb_refresh` if the lookup fails. Useful when doing
+        * a batch of lookup operations for objects that may legitimately not
+        * exist. When using this flag, you may wish to manually call
+        * `git_odb_refresh` before processing a batch of objects.
+        */
+       GIT_ODB_LOOKUP_NO_REFRESH = (1 << 0)
+} git_odb_lookup_flags_t;
+
 /**
  * Function type for callbacks from git_odb_foreach.
  */
@@ -155,6 +166,17 @@ GIT_EXTERN(int) git_odb_read_header(size_t *len_out, git_object_t *type_out, git
  */
 GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id);
 
+/**
+ * Determine if the given object can be found in the object database, with
+ * extended options.
+ *
+ * @param db database to be searched for the given object.
+ * @param id the object to search for.
+ * @param flags flags affecting the lookup (see `git_odb_lookup_flags_t`)
+ * @return 1 if the object was found, 0 otherwise
+ */
+GIT_EXTERN(int) git_odb_exists_ext(git_odb *db, const git_oid *id, unsigned int flags);
+
 /**
  * Determine if an object can be found in the object database by an
  * abbreviated object ID.
@@ -192,12 +214,13 @@ typedef struct git_odb_expand_id {
 
 /**
  * Determine if one or more objects can be found in the object database
- * by their abbreviated object ID and type.  The given array will be
- * updated in place:  for each abbreviated ID that is unique in the
- * database, and of the given type (if specified), the full object ID,
- * object ID length (`GIT_OID_HEXSZ`) and type will be written back to
- * the array.  For IDs that are not found (or are ambiguous), the
- * array entry will be zeroed.
+ * by their abbreviated object ID and type.
+ *
+ * The given array will be updated in place: for each abbreviated ID that is
+ * unique in the database, and of the given type (if specified),
+ * the full object ID, object ID length (`GIT_OID_HEXSZ`) and type will be
+ * written back to the array. For IDs that are not found (or are ambiguous),
+ * the array entry will be zeroed.
  *
  * Note that since this function operates on multiple objects, the
  * underlying database will not be asked to be reloaded if an object is
@@ -323,6 +346,11 @@ GIT_EXTERN(int) git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stre
  * Read from an odb stream
  *
  * Most backends don't implement streaming reads
+ *
+ * @param stream the stream
+ * @param buffer a user-allocated buffer to store the data in.
+ * @param len the buffer's length
+ * @return 0 if the read succeeded, error code otherwise
  */
 GIT_EXTERN(int) git_odb_stream_read(git_odb_stream *stream, char *buffer, size_t len);
 
@@ -383,6 +411,7 @@ GIT_EXTERN(int) git_odb_open_rstream(
  * Be aware that this is called inline with network and indexing operations,
  * so performance may be affected.
  * @param progress_payload payload for the progress callback
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_odb_write_pack(
        git_odb_writepack **out,
@@ -400,6 +429,7 @@ GIT_EXTERN(int) git_odb_write_pack(
  * exist).
  *
  * @param db object database where the `multi-pack-index` file will be written.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_odb_write_multi_pack_index(
        git_odb *db);
@@ -556,7 +586,7 @@ GIT_EXTERN(int) git_odb_get_backend(git_odb_backend **out, git_odb *odb, size_t
 /**
  * Set the git commit-graph for the ODB.
  *
- * After a successfull call, the ownership of the cgraph parameter will be
+ * After a successful call, the ownership of the cgraph parameter will be
  * transferred to libgit2, and the caller should not free it.
  *
  * The commit-graph can also be unset by explicitly passing NULL as the cgraph
index c593bac26cb4912bed56714d0078419beb66c1c7..5ad777b177df703e3d2c1225f26fd37cf789392d 100644 (file)
@@ -71,7 +71,7 @@ GIT_EXTERN(int) git_odb_backend_one_pack(git_odb_backend **out, const char *inde
 typedef enum {
        GIT_STREAM_RDONLY = (1 << 1),
        GIT_STREAM_WRONLY = (1 << 2),
-       GIT_STREAM_RW = (GIT_STREAM_RDONLY | GIT_STREAM_WRONLY),
+       GIT_STREAM_RW = (GIT_STREAM_RDONLY | GIT_STREAM_WRONLY)
 } git_odb_stream_t;
 
 /**
index 3b9beb66521cffa4abddd724c94b44a70540e9f9..0f6bd2ab9281808f8581e38bb2eb6b82fce8a33e 100644 (file)
@@ -51,7 +51,7 @@ GIT_BEGIN_DECL
  */
 typedef enum {
        GIT_PACKBUILDER_ADDING_OBJECTS = 0,
-       GIT_PACKBUILDER_DELTAFICATION = 1,
+       GIT_PACKBUILDER_DELTAFICATION = 1
 } git_packbuilder_stage_t;
 
 /**
@@ -148,6 +148,7 @@ GIT_EXTERN(int) git_packbuilder_insert_recur(git_packbuilder *pb, const git_oid
  *
  * @param buf Buffer where to write the packfile
  * @param pb The packbuilder
+ * @return 0 or an error code
  */
 GIT_EXTERN(int) git_packbuilder_write_buf(git_buf *buf, git_packbuilder *pb);
 
@@ -169,15 +170,30 @@ GIT_EXTERN(int) git_packbuilder_write(
        git_indexer_progress_cb progress_cb,
        void *progress_cb_payload);
 
+#ifndef GIT_DEPRECATE_HARD
 /**
-* Get the packfile's hash
-*
-* A packfile's name is derived from the sorted hashing of all object
-* names. This is only correct after the packfile has been written.
-*
-* @param pb The packbuilder object
-*/
+ * Get the packfile's hash
+ *
+ * A packfile's name is derived from the sorted hashing of all object
+ * names. This is only correct after the packfile has been written.
+ *
+ * @deprecated use git_packbuilder_name
+ * @param pb The packbuilder object
+ * @return 0 or an error code
+ */
 GIT_EXTERN(const git_oid *) git_packbuilder_hash(git_packbuilder *pb);
+#endif
+
+/**
+ * Get the unique name for the resulting packfile.
+ *
+ * The packfile's name is derived from the packfile's content.
+ * This is only correct after the packfile has been written.
+ *
+ * @param pb the packbuilder instance
+ * @return a NUL terminated string for the packfile name
+ */
+GIT_EXTERN(const char *) git_packbuilder_name(git_packbuilder *pb);
 
 /**
  * Callback used to iterate over packed objects
index fde9659e713aa969e175284b511bce4bd92a8621..9cf758a3edb9046bd597b9b5e247221bdd9cb43a 100644 (file)
@@ -139,17 +139,25 @@ GIT_EXTERN(int) git_patch_from_buffers(
 
 /**
  * Free a git_patch object.
+ *
+ * @param patch The patch to free.
  */
 GIT_EXTERN(void) git_patch_free(git_patch *patch);
 
 /**
  * Get the delta associated with a patch.  This delta points to internal
  * data and you do not have to release it when you are done with it.
+ *
+ * @param patch The patch in which to get the delta.
+ * @return The delta associated with the patch.
  */
 GIT_EXTERN(const git_diff_delta *) git_patch_get_delta(const git_patch *patch);
 
 /**
  * Get the number of hunks in a patch
+ *
+ * @param patch The patch in which to get the number of hunks.
+ * @return The number of hunks of the patch.
  */
 GIT_EXTERN(size_t) git_patch_num_hunks(const git_patch *patch);
 
index 329965789709fefc60a1bbfb58d6fcb0215fe1ab..acbd5cd1d6f39596b19047c57dd12377f2c3e48c 100644 (file)
@@ -69,7 +69,7 @@ typedef enum {
         * just test if there were any matches at all or in combination with
         * GIT_PATHSPEC_FIND_FAILURES to validate a pathspec.
         */
-       GIT_PATHSPEC_FAILURES_ONLY  = (1u << 5),
+       GIT_PATHSPEC_FAILURES_ONLY  = (1u << 5)
 } git_pathspec_flag_t;
 
 /**
index 653425dee079416a46813cecf83b5c4de79e8ec4..cfc0c645f8bb09633df3496b372a710aeaff0165 100644 (file)
@@ -32,7 +32,7 @@ typedef enum {
        /**
         * Connect via the URL given in the options
         */
-       GIT_PROXY_SPECIFIED,
+       GIT_PROXY_SPECIFIED
 } git_proxy_t;
 
 /**
index 11e452cbf01159d099d325b4469033b539932768..b1ac71f94eeee65891451de4e2d4ea1a2df01ae1 100644 (file)
@@ -152,7 +152,7 @@ typedef enum {
         * No commit will be cherry-picked.  The client should run the given
         * command and (if successful) continue.
         */
-       GIT_REBASE_OPERATION_EXEC,
+       GIT_REBASE_OPERATION_EXEC
 } git_rebase_operation_t;
 
 #define GIT_REBASE_OPTIONS_VERSION 1
@@ -242,6 +242,7 @@ GIT_EXTERN(int) git_rebase_open(
 /**
  * Gets the original `HEAD` ref name for merge rebases.
  *
+ * @param rebase The in-progress rebase.
  * @return The original `HEAD` ref name
  */
 GIT_EXTERN(const char *) git_rebase_orig_head_name(git_rebase *rebase);
@@ -249,6 +250,7 @@ GIT_EXTERN(const char *) git_rebase_orig_head_name(git_rebase *rebase);
 /**
  * Gets the original `HEAD` id for merge rebases.
  *
+ * @param rebase The in-progress rebase.
  * @return The original `HEAD` id
  */
 GIT_EXTERN(const git_oid *) git_rebase_orig_head_id(git_rebase *rebase);
@@ -256,6 +258,7 @@ GIT_EXTERN(const git_oid *) git_rebase_orig_head_id(git_rebase *rebase);
 /**
  * Gets the `onto` ref name for merge rebases.
  *
+ * @param rebase The in-progress rebase.
  * @return The `onto` ref name
  */
 GIT_EXTERN(const char *) git_rebase_onto_name(git_rebase *rebase);
@@ -263,6 +266,7 @@ GIT_EXTERN(const char *) git_rebase_onto_name(git_rebase *rebase);
 /**
  * Gets the `onto` id for merge rebases.
  *
+ * @param rebase The in-progress rebase.
  * @return The `onto` id
  */
 GIT_EXTERN(const git_oid *) git_rebase_onto_id(git_rebase *rebase);
@@ -322,6 +326,10 @@ GIT_EXTERN(int) git_rebase_next(
  * This is only applicable for in-memory rebases; for rebases within
  * a working directory, the changes were applied to the repository's
  * index.
+ *
+ * @param index The result index of the last operation.
+ * @param rebase The in-progress rebase.
+ * @return 0 or an error code
  */
 GIT_EXTERN(int) git_rebase_inmemory_index(
        git_index **index,
index a315876aefdb5e8c0abf08e499914bb324459b8a..c4849abdc4e57af4a625966f7127c48908a72712 100644 (file)
@@ -52,6 +52,9 @@ GIT_EXTERN(int) git_refdb_open(git_refdb **out, git_repository *repo);
  * Suggests that the given refdb compress or optimize its references.
  * This mechanism is implementation specific.  For on-disk reference
  * databases, for example, this may pack all loose references.
+ *
+ * @param refdb The reference database to optimize.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_refdb_compress(git_refdb *refdb);
 
index c949a28f02cb22a4684bcfa7c196fda237593a90..ec365c1fab265ff2ed9e7ba09db2ff798c883918 100644 (file)
@@ -31,7 +31,7 @@ GIT_BEGIN_DECL
  * git_reflog_free().
  *
  * @param out pointer to reflog
- * @param repo the repostiory
+ * @param repo the repository
  * @param name reference to look up
  * @return 0 or an error code
  */
index 7ebb209b29196dbabbd7a5c013561eb8dc342495..06f8bb97c487c40ae5f0e4a0d564764e47be4433 100644 (file)
@@ -57,7 +57,7 @@ GIT_EXTERN(int) git_reference_name_to_id(
 /**
  * Lookup a reference by DWIMing its short name
  *
- * Apply the git precendence rules to the given shorthand to determine
+ * Apply the git precedence rules to the given shorthand to determine
  * which reference the user is referring to.
  *
  * @param out pointer in which to store the reference
@@ -686,7 +686,7 @@ typedef enum {
         * so the `ONELEVEL` naming rules aren't enforced and 'master'
         * becomes a valid name.
         */
-       GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND = (1u << 2),
+       GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND = (1u << 2)
 } git_reference_format_t;
 
 /**
index 4d57eaaf74f96713c64c193e3fb0dc3e528320ba..8c9c26f3fd58b937e5cd1e7cd00ca6fdb500c2c7 100644 (file)
@@ -41,6 +41,30 @@ GIT_EXTERN(int) git_remote_create(
                const char *name,
                const char *url);
 
+/**
+ * Remote redirection settings; whether redirects to another host
+ * are permitted.  By default, git will follow a redirect on the
+ * initial request (`/info/refs`), but not subsequent requests.
+ */
+typedef enum {
+       /**
+        * Do not follow any off-site redirects at any stage of
+        * the fetch or push.
+        */
+       GIT_REMOTE_REDIRECT_NONE = (1 << 0),
+
+       /**
+        * Allow off-site redirects only upon the initial request.
+        * This is the default.
+        */
+       GIT_REMOTE_REDIRECT_INITIAL = (1 << 1),
+
+       /**
+        * Allow redirects at any stage in the fetch or push.
+        */
+       GIT_REMOTE_REDIRECT_ALL = (1 << 2)
+} git_remote_redirect_t;
+
 /**
  * Remote creation options flags
  */
@@ -49,7 +73,7 @@ typedef enum {
        GIT_REMOTE_CREATE_SKIP_INSTEADOF = (1 << 0),
 
        /** Don't build a fetchspec from the name if none is set */
-       GIT_REMOTE_CREATE_SKIP_DEFAULT_FETCHSPEC = (1 << 1),
+       GIT_REMOTE_CREATE_SKIP_DEFAULT_FETCHSPEC = (1 << 1)
 } git_remote_create_flags;
 
 /**
@@ -300,6 +324,7 @@ GIT_EXTERN(int) git_remote_add_fetch(git_repository *repo, const char *remote, c
  *
  * @param array pointer to the array in which to store the strings
  * @param remote the remote to query
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_remote_get_fetch_refspecs(git_strarray *array, const git_remote *remote);
 
@@ -324,6 +349,7 @@ GIT_EXTERN(int) git_remote_add_push(git_repository *repo, const char *remote, co
  *
  * @param array pointer to the array in which to store the strings
  * @param remote the remote to query
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_remote_get_push_refspecs(git_strarray *array, const git_remote *remote);
 
@@ -344,23 +370,6 @@ GIT_EXTERN(size_t) git_remote_refspec_count(const git_remote *remote);
  */
 GIT_EXTERN(const git_refspec *)git_remote_get_refspec(const git_remote *remote, size_t n);
 
-/**
- * Open a connection to a remote
- *
- * The transport is selected based on the URL. The direction argument
- * is due to a limitation of the git protocol (over TCP or SSH) which
- * starts up a specific binary which can only do the one or the other.
- *
- * @param remote the remote to connect to
- * @param direction GIT_DIRECTION_FETCH if you want to fetch or
- * GIT_DIRECTION_PUSH if you want to push
- * @param callbacks the callbacks to use for this connection
- * @param proxy_opts proxy settings
- * @param custom_headers extra HTTP headers to use in this connection
- * @return 0 or an error code
- */
-GIT_EXTERN(int) git_remote_connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_proxy_options *proxy_opts, const git_strarray *custom_headers);
-
 /**
  * Get the remote repository's reference advertisement list
  *
@@ -443,7 +452,7 @@ GIT_EXTERN(int) git_remote_list(git_strarray *out, git_repository *repo);
 typedef enum git_remote_completion_t {
        GIT_REMOTE_COMPLETION_DOWNLOAD,
        GIT_REMOTE_COMPLETION_INDEXING,
-       GIT_REMOTE_COMPLETION_ERROR,
+       GIT_REMOTE_COMPLETION_ERROR
 } git_remote_completion_t;
 
 /** Push network progress notification function */
@@ -665,7 +674,7 @@ typedef enum {
        /**
         * Force pruning off
         */
-       GIT_FETCH_NO_PRUNE,
+       GIT_FETCH_NO_PRUNE
 } git_fetch_prune_t;
 
 /**
@@ -690,7 +699,7 @@ typedef enum {
        /**
         * Ask for the all the tags.
         */
-       GIT_REMOTE_DOWNLOAD_TAGS_ALL,
+       GIT_REMOTE_DOWNLOAD_TAGS_ALL
 } git_remote_autotag_option_t;
 
 /**
@@ -734,6 +743,13 @@ typedef struct {
         */
        git_proxy_options proxy_opts;
 
+       /**
+        * Whether to allow off-site redirects.  If this is not
+        * specified, the `http.followRedirects` configuration setting
+        * will be consulted.
+        */
+       git_remote_redirect_t follow_redirects;
+
        /**
         * Extra headers for this fetch operation
         */
@@ -785,6 +801,13 @@ typedef struct {
        */
        git_proxy_options proxy_opts;
 
+       /**
+        * Whether to allow off-site redirects.  If this is not
+        * specified, the `http.followRedirects` configuration setting
+        * will be consulted.
+        */
+       git_remote_redirect_t follow_redirects;
+
        /**
         * Extra headers for this push operation
         */
@@ -809,7 +832,100 @@ GIT_EXTERN(int) git_push_options_init(
        unsigned int version);
 
 /**
- * Download and index the packfile
+ * Remote creation options structure
+ *
+ * Initialize with `GIT_REMOTE_CREATE_OPTIONS_INIT`. Alternatively, you can
+ * use `git_remote_create_options_init`.
+ *
+ */
+typedef struct {
+       unsigned int version;
+
+       /** Callbacks to use for this connection */
+       git_remote_callbacks callbacks;
+
+       /** HTTP Proxy settings */
+       git_proxy_options proxy_opts;
+
+       /**
+        * Whether to allow off-site redirects.  If this is not
+        * specified, the `http.followRedirects` configuration setting
+        * will be consulted.
+        */
+       git_remote_redirect_t follow_redirects;
+
+       /** Extra HTTP headers to use in this connection */
+       git_strarray custom_headers;
+} git_remote_connect_options;
+
+#define GIT_REMOTE_CONNECT_OPTIONS_VERSION 1
+#define GIT_REMOTE_CONNECT_OPTIONS_INIT { \
+       GIT_REMOTE_CONNECT_OPTIONS_VERSION, \
+       GIT_REMOTE_CALLBACKS_INIT, \
+       GIT_PROXY_OPTIONS_INIT }
+
+/**
+ * Initialize git_remote_connect_options structure.
+ *
+ * Initializes a `git_remote_connect_options` with default values.
+ * Equivalent to creating an instance with
+ * `GIT_REMOTE_CONNECT_OPTIONS_INIT`.
+ *
+ * @param opts The `git_remote_connect_options` struct to initialize.
+ * @param version The struct version; pass `GIT_REMOTE_CONNECT_OPTIONS_VERSION`.
+ * @return Zero on success; -1 on failure.
+ */
+GIT_EXTERN(int) git_remote_connect_options_init(
+               git_remote_connect_options *opts,
+               unsigned int version);
+
+/**
+ * Open a connection to a remote.
+ *
+ * The transport is selected based on the URL; the direction argument
+ * is due to a limitation of the git protocol which starts up a
+ * specific binary which can only do the one or the other.
+ *
+ * @param remote the remote to connect to
+ * @param direction GIT_DIRECTION_FETCH if you want to fetch or
+ * GIT_DIRECTION_PUSH if you want to push
+ * @param callbacks the callbacks to use for this connection
+ * @param proxy_opts proxy settings
+ * @param custom_headers extra HTTP headers to use in this connection
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_remote_connect(
+       git_remote *remote,
+       git_direction direction,
+       const git_remote_callbacks *callbacks,
+       const git_proxy_options *proxy_opts,
+       const git_strarray *custom_headers);
+
+/**
+ * Open a connection to a remote with extended options.
+ *
+ * The transport is selected based on the URL; the direction argument
+ * is due to a limitation of the git protocol which starts up a
+ * specific binary which can only do the one or the other.
+ *
+ * The given options structure will form the defaults for connection
+ * options and callback setup.  Callers may override these defaults
+ * by specifying `git_fetch_options` or `git_push_options` in
+ * subsequent calls.
+ *
+ * @param remote the remote to connect to
+ * @param direction GIT_DIRECTION_FETCH if you want to fetch or
+ * GIT_DIRECTION_PUSH if you want to push
+ * @param opts the remote connection options
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_remote_connect_ext(
+       git_remote *remote,
+       git_direction direction,
+       const git_remote_connect_options *opts);
+
+/**
+ * Download and index the packfile.
  *
  * Connect to the remote if it hasn't been done yet, negotiate with
  * the remote git which objects are missing, download and index the
@@ -818,19 +934,31 @@ GIT_EXTERN(int) git_push_options_init(
  * The .idx file will be created and both it and the packfile with be
  * renamed to their final name.
  *
+ * If options are specified and this remote is already connected then
+ * the existing remote connection options will be discarded and the
+ * remote will now use the new options.
+ *
  * @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
- * @param opts the options to use for this fetch
+ * @param opts the options to use for this fetch or NULL
  * @return 0 or an error code
  */
- GIT_EXTERN(int) git_remote_download(git_remote *remote, const git_strarray *refspecs, const git_fetch_options *opts);
+ GIT_EXTERN(int) git_remote_download(
+       git_remote *remote,
+       const git_strarray *refspecs,
+       const git_fetch_options *opts);
 
 /**
  * Create a packfile and send it to the server
  *
  * Connect to the remote if it hasn't been done yet, negotiate with
- * the remote git which objects are missing, create a packfile with the missing objects and send it.
+ * the remote git which objects are missing, create a packfile with
+ * the missing objects and send it.
+ *
+ * If options are specified and this remote is already connected then
+ * the existing remote connection options will be discarded and the
+ * remote will now use the new options.
  *
  * @param remote the remote
  * @param refspecs the refspecs to use for this negotiation and
@@ -838,17 +966,23 @@ GIT_EXTERN(int) git_push_options_init(
  * @param opts the options to use for this push
  * @return 0 or an error code
  */
-GIT_EXTERN(int) git_remote_upload(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts);
+GIT_EXTERN(int) git_remote_upload(
+       git_remote *remote,
+       const git_strarray *refspecs,
+       const git_push_options *opts);
 
 /**
- * Update the tips to the new state
+ * Update the tips to the new state.
+ *
+ * If callbacks are not specified then the callbacks specified to
+ * `git_remote_connect` will be used (if it was called).
  *
  * @param remote the remote to update
  * @param reflog_message The message to insert into the reflogs. If
  * NULL and fetching, the default is "fetch <name>", where <name> is
  * the name of the remote (or its url, for in-memory remotes). This
  * parameter is ignored when pushing.
- * @param callbacks  pointer to the callback structure to use
+ * @param callbacks  pointer to the callback structure to use or NULL
  * @param update_fetchhead whether to write to FETCH_HEAD. Pass 1 to behave like git.
  * @param download_tags what the behaviour for downloading tags is for this fetch. This is
  * ignored for push. This must be the same value passed to `git_remote_download()`.
@@ -862,15 +996,19 @@ GIT_EXTERN(int) git_remote_update_tips(
                const char *reflog_message);
 
 /**
- * Download new data and update tips
+ * Download new data and update tips.
  *
  * Convenience function to connect to a remote, download the data,
  * disconnect and update the remote-tracking branches.
  *
+ * If options are specified and this remote is already connected then
+ * the existing remote connection options will be discarded and the
+ * remote will now use the new options.
+ *
  * @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 opts options to use for this fetch
+ * @param opts options to use for this fetch or NULL
  * @param reflog_message The message to insert into the reflogs. If NULL, the
  *                                                              default is "fetch"
  * @return 0 or an error code
@@ -882,27 +1020,36 @@ GIT_EXTERN(int) git_remote_fetch(
                const char *reflog_message);
 
 /**
- * Prune tracking refs that are no longer present on remote
+ * Prune tracking refs that are no longer present on remote.
+ *
+ * If callbacks are not specified then the callbacks specified to
+ * `git_remote_connect` will be used (if it was called).
  *
  * @param remote the remote to prune
  * @param callbacks callbacks to use for this prune
  * @return 0 or an error code
  */
-GIT_EXTERN(int) git_remote_prune(git_remote *remote, const git_remote_callbacks *callbacks);
+GIT_EXTERN(int) git_remote_prune(
+       git_remote *remote,
+       const git_remote_callbacks *callbacks);
 
 /**
- * Perform a push
+ * Perform a push.
  *
- * Peform all the steps from a push.
+ * If options are specified and this remote is already connected then
+ * the existing remote connection options will be discarded and the
+ * remote will now use the new options.
  *
  * @param remote the remote to push to
  * @param refspecs the refspecs to use for pushing. If NULL or an empty
  *                 array, the configured refspecs will be used
  * @param opts options to use for this push
+ * @return 0 or an error code.
  */
-GIT_EXTERN(int) git_remote_push(git_remote *remote,
-                               const git_strarray *refspecs,
-                               const git_push_options *opts);
+GIT_EXTERN(int) git_remote_push(
+       git_remote *remote,
+       const git_strarray *refspecs,
+       const git_push_options *opts);
 
 /**
  * Get the statistics structure that is filled in by the fetch operation.
index 8d1cffc9bf62fe7ee733a8707b8ccb2a68015a7b..c87f3c96252507523b59f3ddc4393bb4f8381a40 100644 (file)
@@ -141,7 +141,7 @@ typedef enum {
         * `git_repository_open_ext` with this flag will error out if either
         * $GIT_WORK_TREE or $GIT_COMMON_DIR is set.
         */
-       GIT_REPOSITORY_OPEN_FROM_ENV  = (1 << 4),
+       GIT_REPOSITORY_OPEN_FROM_ENV  = (1 << 4)
 } git_repository_open_flag_t;
 
 /**
@@ -267,7 +267,7 @@ typedef enum {
         * If an alternate workdir is specified, use relative paths for the gitdir
         * and core.worktree.
         */
-       GIT_REPOSITORY_INIT_RELATIVE_GITLINK  = (1u << 6),
+       GIT_REPOSITORY_INIT_RELATIVE_GITLINK  = (1u << 6)
 } git_repository_init_flag_t;
 
 /**
@@ -292,7 +292,7 @@ typedef enum {
        /**
         * Use "--shared=all" behavior, adding world readability.
         */
-       GIT_REPOSITORY_INIT_SHARED_ALL   = 0002777,
+       GIT_REPOSITORY_INIT_SHARED_ALL   = 0002777
 } git_repository_init_mode_t;
 
 /**
@@ -673,6 +673,9 @@ GIT_EXTERN(int) git_repository_message(git_buf *out, git_repository *repo);
  * Remove git's prepared message.
  *
  * Remove the message that `git_repository_message` retrieves.
+ *
+ * @param repo Repository to remove prepared message from.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_repository_message_remove(git_repository *repo);
 
@@ -808,19 +811,19 @@ GIT_EXTERN(int) git_repository_set_head(
  * If the provided committish cannot be found in the repository, the HEAD
  * is unaltered and GIT_ENOTFOUND is returned.
  *
- * If the provided commitish cannot be peeled into a commit, the HEAD
+ * If the provided committish cannot be peeled into a commit, the HEAD
  * is unaltered and -1 is returned.
  *
  * Otherwise, the HEAD will eventually be detached and will directly point to
  * the peeled Commit.
  *
  * @param repo Repository pointer
- * @param commitish Object id of the Commit the HEAD should point to
+ * @param committish Object id of the Commit the HEAD should point to
  * @return 0 on success, or an error code
  */
 GIT_EXTERN(int) git_repository_set_head_detached(
        git_repository *repo,
-       const git_oid *commitish);
+       const git_oid *committish);
 
 /**
  * Make the repository HEAD directly point to the Commit.
@@ -836,7 +839,7 @@ GIT_EXTERN(int) git_repository_set_head_detached(
  */
 GIT_EXTERN(int) git_repository_set_head_detached_from_annotated(
        git_repository *repo,
-       const git_annotated_commit *commitish);
+       const git_annotated_commit *committish);
 
 /**
  * Detach the HEAD.
@@ -846,7 +849,7 @@ GIT_EXTERN(int) git_repository_set_head_detached_from_annotated(
  * If the HEAD is already detached and points to a Tag, the HEAD is
  * updated into making it point to the peeled Commit, and 0 is returned.
  *
- * If the HEAD is already detached and points to a non commitish, the HEAD is
+ * If the HEAD is already detached and points to a non committish, the HEAD is
  * unaltered, and -1 is returned.
  *
  * Otherwise, the HEAD will be detached and point to the peeled Commit.
@@ -876,7 +879,7 @@ typedef enum {
        GIT_REPOSITORY_STATE_REBASE_INTERACTIVE,
        GIT_REPOSITORY_STATE_REBASE_MERGE,
        GIT_REPOSITORY_STATE_APPLY_MAILBOX,
-       GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE,
+       GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE
 } git_repository_state_t;
 
 /**
@@ -928,6 +931,7 @@ GIT_EXTERN(int) git_repository_is_shallow(git_repository *repo);
  * @param name where to store the pointer to the name
  * @param email where to store the pointer to the email
  * @param repo the repository
+ * @return 0 or an error code
  */
 GIT_EXTERN(int) git_repository_ident(const char **name, const char **email, const git_repository *repo);
 
@@ -941,6 +945,7 @@ GIT_EXTERN(int) git_repository_ident(const char **name, const char **email, cons
  * @param repo the repository to configure
  * @param name the name to use for the reflog entries
  * @param email the email to use for the reflog entries
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_repository_set_ident(git_repository *repo, const char *name, const char *email);
 
index be25414336a3caebb776151581db3feb7d3d83f9..b2ee2ba7bfba7eb1b5137bd48fdeddf3f007283a 100644 (file)
@@ -26,7 +26,7 @@ GIT_BEGIN_DECL
 typedef enum {
        GIT_RESET_SOFT  = 1, /**< Move the head to the given commit */
        GIT_RESET_MIXED = 2, /**< SOFT plus reset index to the commit */
-       GIT_RESET_HARD  = 3, /**< MIXED plus changes in working tree discarded */
+       GIT_RESET_HARD  = 3  /**< MIXED plus changes in working tree discarded */
 } git_reset_t;
 
 /**
@@ -48,7 +48,7 @@ typedef enum {
  *
  * @param target Committish to which the Head should be moved to. This object
  * must belong to the given `repo` and can either be a git_commit or a
- * git_tag. When a git_tag is being passed, it should be dereferencable
+ * git_tag. When a git_tag is being passed, it should be dereferenceable
  * to a git_commit which oid will be used as the target of the branch.
  *
  * @param reset_type Kind of reset operation to perform.
index e14ddee96cf27aa9312ffde89d473228f70b3d7c..51ea2dc13f59efa85da53be851dd557c1a7bc2b3 100644 (file)
@@ -74,7 +74,7 @@ typedef enum {
        /** The spec targeted a range of commits. */
        GIT_REVSPEC_RANGE          = 1 << 1,
        /** The spec used the '...' operator, which invokes special semantics. */
-       GIT_REVSPEC_MERGE_BASE     = 1 << 2,
+       GIT_REVSPEC_MERGE_BASE     = 1 << 2
 } git_revspec_t;
 
 /**
index 98dcbf8d13a1fa72ce005ea744f4cd87a8a496a5..4aa9f5b1e0e9d50c9720be595b6fe65a143bf976 100644 (file)
@@ -49,7 +49,7 @@ typedef enum {
         * order; this sorting mode can be combined with
         * any of the above.
         */
-       GIT_SORT_REVERSE = 1 << 2,
+       GIT_SORT_REVERSE = 1 << 2
 } git_sort_t;
 
 /**
@@ -249,6 +249,7 @@ GIT_EXTERN(int) git_revwalk_push_range(git_revwalk *walk, const char *range);
  *
  * No parents other than the first for each commit will be enqueued.
  *
+ * @param walk The revision walker.
  * @return 0 or an error code
  */
 GIT_EXTERN(int) git_revwalk_simplify_first_parent(git_revwalk *walk);
@@ -277,6 +278,7 @@ GIT_EXTERN(git_repository *) git_revwalk_repository(git_revwalk *walk);
  *
  * @param commit_id oid of Commit
  * @param payload User-specified pointer to data to be passed as data payload
+ * @return non-zero to hide the commmit and it parent.
  */
 typedef int GIT_CALLBACK(git_revwalk_hide_cb)(
        const git_oid *commit_id,
@@ -288,6 +290,7 @@ typedef int GIT_CALLBACK(git_revwalk_hide_cb)(
  * @param walk the revision walker
  * @param hide_cb  callback function to hide a commit and its parents
  * @param payload  data payload to be passed to callback function
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_revwalk_add_hide_cb(
        git_revwalk *walk,
index b14f3ea89067e1e6cff4864d76d553e2883b0aab..849998e66f7afd2407a9d8d4896a6467ce8e640f 100644 (file)
@@ -71,7 +71,7 @@ GIT_EXTERN(int) git_signature_default(git_signature **out, git_repository *repo)
  *
  * @param out new signature
  * @param buf signature string
- * @return 0 on success, or an error code
+ * @return 0 on success, GIT_EINVALID if the signature is not parseable, or an error code
  */
 GIT_EXTERN(int) git_signature_from_buffer(git_signature **out, const char *buf);
 
index 795920ebc767aec4267d2fc35975ab21c1163809..32e6f95764cf1eae62216728531d94d9d4152203 100644 (file)
@@ -44,7 +44,7 @@ typedef enum {
         * All ignored files are also stashed and then cleaned up from
         * the working directory
         */
-       GIT_STASH_INCLUDE_IGNORED = (1 << 2),
+       GIT_STASH_INCLUDE_IGNORED = (1 << 2)
 } git_stash_flags;
 
 /**
@@ -78,7 +78,7 @@ typedef enum {
        /* Try to reinstate not only the working tree's changes,
         * but also the index's changes.
         */
-       GIT_STASH_APPLY_REINSTATE_INDEX = (1 << 0),
+       GIT_STASH_APPLY_REINSTATE_INDEX = (1 << 0)
 } git_stash_apply_flags;
 
 /** Stash apply progression states */
@@ -104,7 +104,7 @@ typedef enum {
        GIT_STASH_APPLY_PROGRESS_CHECKOUT_MODIFIED,
 
        /** The stash was applied successfully. */
-       GIT_STASH_APPLY_PROGRESS_DONE,
+       GIT_STASH_APPLY_PROGRESS_DONE
 } git_stash_apply_progress_t;
 
 /**
index 543e3faa8f7c64472c3b140a10bffb15ca702a44..d8f9663b42a368997944bfe859a7b0e978c93c0e 100644 (file)
@@ -48,7 +48,7 @@ typedef enum {
        GIT_STATUS_WT_UNREADABLE    = (1u << 12),
 
        GIT_STATUS_IGNORED          = (1u << 14),
-       GIT_STATUS_CONFLICTED       = (1u << 15),
+       GIT_STATUS_CONFLICTED       = (1u << 15)
 } git_status_t;
 
 /**
@@ -87,7 +87,7 @@ typedef enum {
         * Only gives status based on index to working directory comparison,
         * not comparing the index to the HEAD.
         */
-       GIT_STATUS_SHOW_WORKDIR_ONLY = 2,
+       GIT_STATUS_SHOW_WORKDIR_ONLY = 2
 } git_status_show_t;
 
 /**
@@ -204,7 +204,7 @@ typedef enum {
         * Unreadable files will be detected and given the status
         * untracked instead of unreadable.
         */
-       GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED  = (1u << 15),
+       GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED  = (1u << 15)
 } git_status_opt_t;
 
 #define GIT_STATUS_OPT_DEFAULTS \
@@ -250,6 +250,12 @@ typedef struct {
         * working directory and index; defaults to HEAD.
         */
        git_tree          *baseline;
+
+       /**
+        * Threshold above which similar files will be considered renames.
+        * This is equivalent to the -M option. Defaults to 50.
+        */
+       uint16_t          rename_threshold;
 } git_status_options;
 
 #define GIT_STATUS_OPTIONS_VERSION 1
index 29d8bc1ce556942f5f3f3fd4dcc791f74b286ff7..2082966f6bb2a241b8b85de1ca924759979b8c2d 100644 (file)
@@ -85,7 +85,7 @@ typedef enum {
        GIT_SUBMODULE_STATUS_WD_MODIFIED       = (1u << 10),
        GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED = (1u << 11),
        GIT_SUBMODULE_STATUS_WD_WD_MODIFIED    = (1u << 12),
-       GIT_SUBMODULE_STATUS_WD_UNTRACKED      = (1u << 13),
+       GIT_SUBMODULE_STATUS_WD_UNTRACKED      = (1u << 13)
 } git_submodule_status_t;
 
 #define GIT_SUBMODULE_STATUS__IN_FLAGS         0x000Fu
@@ -181,7 +181,7 @@ GIT_EXTERN(int) git_submodule_update_options_init(
  * @param submodule Submodule object
  * @param init If the submodule is not initialized, setting this flag to true
  *        will initialize the submodule before updating. Otherwise, this will
- *        return an error if attempting to update an uninitialzed repository.
+ *        return an error if attempting to update an uninitialized repository.
  *        but setting this to true forces them to be updated.
  * @param options configuration options for the update.  If NULL, the
  *        function works as though GIT_SUBMODULE_UPDATE_OPTIONS_INIT was passed.
@@ -229,6 +229,7 @@ GIT_EXTERN(int) git_submodule_lookup(
  *
  * @param out Pointer to store the copy of the submodule.
  * @param source Original submodule to copy.
+ * @return 0
  */
 GIT_EXTERN(int) git_submodule_dup(git_submodule **out, git_submodule *source);
 
@@ -320,6 +321,7 @@ GIT_EXTERN(int) git_submodule_clone(
  * (but doesn't actually do the commit).
  *
  * @param submodule The submodule to finish adding.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_submodule_add_finalize(git_submodule *submodule);
 
@@ -589,6 +591,9 @@ GIT_EXTERN(int) git_submodule_repo_init(
  * submodule config, acting like "git submodule sync".  This is useful if
  * you have altered the URL for the submodule (or it has been altered by a
  * fetch of upstream changes) and you need to update your local repo.
+ *
+ * @param submodule The submodule to copy.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_submodule_sync(git_submodule *submodule);
 
index f6c0fc4b5db47cbf533e86c2d617236f9c5831ba..823c7ed579bbc7ee7562a5fa2d63cd35f1f5dbc3 100644 (file)
@@ -94,7 +94,7 @@ typedef enum {
         * Do not split commit-graph files. The other split strategy-related option
         * fields are ignored.
         */
-       GIT_COMMIT_GRAPH_SPLIT_STRATEGY_SINGLE_FILE = 0,
+       GIT_COMMIT_GRAPH_SPLIT_STRATEGY_SINGLE_FILE = 0
 } git_commit_graph_split_strategy_t;
 
 /**
index 9ae0ed9b3edee764656f1545e4ba54d368fcca66..8598f94e5617eb9689ddc9782128718ac3bf4476 100644 (file)
@@ -69,11 +69,8 @@ struct git_odb_backend {
         * If the backend implements a refreshing mechanism, it should be exposed
         * through this endpoint. Each call to `git_odb_refresh()` will invoke it.
         *
-        * However, the backend implementation should try to stay up-to-date as much
-        * as possible by itself as libgit2 will not automatically invoke
-        * `git_odb_refresh()`. For instance, a potential strategy for the backend
-        * implementation to achieve this could be to internally invoke this
-        * endpoint on failed lookups (ie. `exists()`, `read()`, `read_header()`).
+        * The odb layer will automatically call this when needed on failed
+        * lookups (ie. `exists()`, `read()`, `read_header()`).
         */
        int GIT_CALLBACK(refresh)(git_odb_backend *);
 
diff --git a/include/git2/sys/remote.h b/include/git2/sys/remote.h
new file mode 100644 (file)
index 0000000..dd243ca
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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_sys_git_remote_h
+#define INCLUDE_sys_git_remote_h
+
+/**
+ * @file git2/sys/remote.h
+ * @brief Low-level remote functionality for custom transports
+ * @defgroup git_remote Low-level remote functionality
+ * @ingroup Git
+ * @{
+*/
+
+GIT_BEGIN_DECL
+
+typedef enum {
+       /** Remote supports fetching an advertised object by ID. */
+       GIT_REMOTE_CAPABILITY_TIP_OID = (1 << 0),
+
+       /** Remote supports fetching an individual reachable object. */
+       GIT_REMOTE_CAPABILITY_REACHABLE_OID = (1 << 1),
+} git_remote_capability_t;
+
+/** @} */
+GIT_END_DECL
+#endif
index 6f93cc48c3228c7cbb30446d7455aef7621ccf59..e0e03a2d7647188e0011754e82c3a5b2f3ba20b9 100644 (file)
@@ -79,7 +79,7 @@ typedef enum {
        GIT_STREAM_STANDARD = 1,
 
        /** A TLS-encrypted socket. */
-       GIT_STREAM_TLS = 2,
+       GIT_STREAM_TLS = 2
 } git_stream_t;
 
 /**
index fee34544fa9510b569ff14fb2ef7a068c94fa0e0..f0c2a3eabeb5d260de2a059d002115c74d355904 100644 (file)
 
 GIT_BEGIN_DECL
 
-/**
- * Flags to pass to transport
- *
- * Currently unused.
- */
-typedef enum {
-       GIT_TRANSPORTFLAGS_NONE = 0,
-} git_transport_flags_t;
-
 struct git_transport {
        unsigned int version; /**< The struct version */
 
-       /** Set progress and error callbacks */
-       int GIT_CALLBACK(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 *payload);
-
-       /** Set custom headers for HTTP requests */
-       int GIT_CALLBACK(set_custom_headers)(
-               git_transport *transport,
-               const git_strarray *custom_headers);
-
        /**
         * Connect the transport to the remote repository, using the given
         * direction.
@@ -56,11 +34,27 @@ struct git_transport {
        int GIT_CALLBACK(connect)(
                git_transport *transport,
                const char *url,
-               git_credential_acquire_cb cred_acquire_cb,
-               void *cred_acquire_payload,
-               const git_proxy_options *proxy_opts,
                int direction,
-               int flags);
+               const git_remote_connect_options *connect_opts);
+
+       /**
+        * Resets the connect options for the given transport.  This
+        * is useful for updating settings or callbacks for an already
+        * connected transport.
+        */
+       int GIT_CALLBACK(set_connect_opts)(
+               git_transport *transport,
+               const git_remote_connect_options *connect_opts);
+
+       /**
+        * Gets the capabilities for this remote repository.
+        *
+        * This function may be called after a successful call to
+        * `connect()`.
+        */
+       int GIT_CALLBACK(capabilities)(
+               unsigned int *capabilities,
+               git_transport *transport);
 
        /**
         * Get the list of available references in the remote repository.
@@ -75,7 +69,9 @@ struct git_transport {
                git_transport *transport);
 
        /** Executes the push whose context is in the git_push object. */
-       int GIT_CALLBACK(push)(git_transport *transport, git_push *push, const git_remote_callbacks *callbacks);
+       int GIT_CALLBACK(push)(
+               git_transport *transport,
+               git_push *push);
 
        /**
         * Negotiate a fetch with the remote repository.
@@ -99,16 +95,11 @@ struct git_transport {
        int GIT_CALLBACK(download_pack)(
                git_transport *transport,
                git_repository *repo,
-               git_indexer_progress *stats,
-               git_indexer_progress_cb progress_cb,
-               void *progress_payload);
+               git_indexer_progress *stats);
 
        /** Checks to see if the transport is connected */
        int GIT_CALLBACK(is_connected)(git_transport *transport);
 
-       /** Reads the flags value previously passed into connect() */
-       int GIT_CALLBACK(read_flags)(git_transport *transport, int *flags);
-
        /** Cancels any outstanding transport operation */
        void GIT_CALLBACK(cancel)(git_transport *transport);
 
@@ -289,7 +280,7 @@ typedef enum {
        GIT_SERVICE_UPLOADPACK_LS = 1,
        GIT_SERVICE_UPLOADPACK = 2,
        GIT_SERVICE_RECEIVEPACK_LS = 3,
-       GIT_SERVICE_RECEIVEPACK = 4,
+       GIT_SERVICE_RECEIVEPACK = 4
 } git_smart_service_t;
 
 typedef struct git_smart_subtransport git_smart_subtransport;
index a3921369dad67db313eb43df4eb4db6810b2f1d1..9830536559051134c3ab22a7927c642d0889b06b 100644 (file)
@@ -362,6 +362,7 @@ GIT_EXTERN(int) git_tag_peel(
  *
  * @param out Pointer to store the copy of the tag
  * @param source Original tag to copy
+ * @return 0
  */
 GIT_EXTERN(int) git_tag_dup(git_tag **out, git_tag *source);
 
index f2289fc7e6c13cb615a47ecd1ce4055d8ea6ce2c..ce0a60907faa6f0aaa7a22c371411753dd7ef8b9 100644 (file)
@@ -255,7 +255,7 @@ GIT_EXTERN(int) git_treebuilder_new(
        git_treebuilder **out, git_repository *repo, const git_tree *source);
 
 /**
- * Clear all the entires in the builder
+ * Clear all the entries in the builder
  *
  * @param bld Builder to clear
  * @return 0 on success; error code otherwise
@@ -386,7 +386,7 @@ typedef int GIT_CALLBACK(git_treewalk_cb)(
 /** Tree traversal modes */
 typedef enum {
        GIT_TREEWALK_PRE = 0, /* Pre-order */
-       GIT_TREEWALK_POST = 1, /* Post-order */
+       GIT_TREEWALK_POST = 1 /* Post-order */
 } git_treewalk_mode;
 
 /**
@@ -418,6 +418,7 @@ GIT_EXTERN(int) git_tree_walk(
  *
  * @param out Pointer to store the copy of the tree
  * @param source Original tree to copy
+ * @return 0
  */
 GIT_EXTERN(int) git_tree_dup(git_tree **out, git_tree *source);
 
@@ -428,7 +429,7 @@ typedef enum {
        /** Update or insert an entry at the specified path */
        GIT_TREE_UPDATE_UPSERT,
        /** Remove an entry from the specified path */
-       GIT_TREE_UPDATE_REMOVE,
+       GIT_TREE_UPDATE_REMOVE
 } git_tree_update_t;
 
 /**
index aac8e42e285772df63a91f917ae0c4b2730eccee..d4b033dc770e5010178872407ef19e43594b8490 100644 (file)
@@ -78,7 +78,7 @@ typedef enum {
        GIT_OBJECT_BLOB =      3, /**< A file revision object. */
        GIT_OBJECT_TAG =       4, /**< An annotated tag object. */
        GIT_OBJECT_OFS_DELTA = 6, /**< A delta, base is given by an offset. */
-       GIT_OBJECT_REF_DELTA = 7, /**< A delta, base is given by object id. */
+       GIT_OBJECT_REF_DELTA = 7  /**< A delta, base is given by object id. */
 } git_object_t;
 
 /** An open object database handle. */
@@ -208,14 +208,14 @@ typedef enum {
        GIT_REFERENCE_INVALID  = 0, /**< Invalid reference */
        GIT_REFERENCE_DIRECT   = 1, /**< A reference that points at an object id */
        GIT_REFERENCE_SYMBOLIC = 2, /**< A reference that points at another reference */
-       GIT_REFERENCE_ALL      = GIT_REFERENCE_DIRECT | GIT_REFERENCE_SYMBOLIC,
+       GIT_REFERENCE_ALL      = GIT_REFERENCE_DIRECT | GIT_REFERENCE_SYMBOLIC
 } git_reference_t;
 
 /** Basic type of any Git branch. */
 typedef enum {
        GIT_BRANCH_LOCAL = 1,
        GIT_BRANCH_REMOTE = 2,
-       GIT_BRANCH_ALL = GIT_BRANCH_LOCAL|GIT_BRANCH_REMOTE,
+       GIT_BRANCH_ALL = GIT_BRANCH_LOCAL|GIT_BRANCH_REMOTE
 } git_branch_t;
 
 /** Valid modes for index and tree entries. */
@@ -225,7 +225,7 @@ typedef enum {
        GIT_FILEMODE_BLOB                = 0100644,
        GIT_FILEMODE_BLOB_EXECUTABLE     = 0100755,
        GIT_FILEMODE_LINK                = 0120000,
-       GIT_FILEMODE_COMMIT              = 0160000,
+       GIT_FILEMODE_COMMIT              = 0160000
 } git_filemode_t;
 
 /**
@@ -236,7 +236,7 @@ typedef struct git_refspec git_refspec;
 
 /**
  * Git's idea of a remote repository. A remote can be anonymous (in
- * which case it does not have backing configuration entires).
+ * which case it does not have backing configuration entries).
  */
 typedef struct git_remote git_remote;
 
@@ -334,7 +334,7 @@ typedef enum {
        GIT_SUBMODULE_IGNORE_NONE      = 1,  /**< any change or untracked == dirty */
        GIT_SUBMODULE_IGNORE_UNTRACKED = 2,  /**< dirty if tracked files change */
        GIT_SUBMODULE_IGNORE_DIRTY     = 3,  /**< only dirty if HEAD moved */
-       GIT_SUBMODULE_IGNORE_ALL       = 4,  /**< never dirty */
+       GIT_SUBMODULE_IGNORE_ALL       = 4   /**< never dirty */
 } git_submodule_ignore_t;
 
 /**
@@ -350,7 +350,7 @@ typedef enum {
 typedef enum {
        GIT_SUBMODULE_RECURSE_NO = 0,
        GIT_SUBMODULE_RECURSE_YES = 1,
-       GIT_SUBMODULE_RECURSE_ONDEMAND = 2,
+       GIT_SUBMODULE_RECURSE_ONDEMAND = 2
 } git_submodule_recurse_t;
 
 typedef struct git_writestream git_writestream;
index 3503a62781ad7d38f7692491134162cc07ed61c9..980f70b69e20570d22cf0c55925ae59d553fbfae 100644 (file)
@@ -7,12 +7,12 @@
 #ifndef INCLUDE_git_version_h__
 #define INCLUDE_git_version_h__
 
-#define LIBGIT2_VERSION "1.3.0"
+#define LIBGIT2_VERSION "1.4.3"
 #define LIBGIT2_VER_MAJOR 1
-#define LIBGIT2_VER_MINOR 3
-#define LIBGIT2_VER_REVISION 0
+#define LIBGIT2_VER_MINOR 4
+#define LIBGIT2_VER_REVISION 3
 #define LIBGIT2_VER_PATCH 0
 
-#define LIBGIT2_SOVERSION "1.3"
+#define LIBGIT2_SOVERSION "1.4"
 
 #endif
index 23084d8cd87527e7ffadc97d7ca608d057ceeeda..bb024dc940e91d321834704a77e91acc961cc8c2 100644 (file)
@@ -52,6 +52,7 @@ GIT_EXTERN(int) git_worktree_lookup(git_worktree **out, git_repository *repo, co
  *
  * @param out Out-pointer for the newly allocated worktree
  * @param repo Repository to look up worktree for
+ * @return 0 or an error code
  */
 GIT_EXTERN(int) git_worktree_open_from_repository(git_worktree **out, git_repository *repo);
 
@@ -86,10 +87,15 @@ typedef struct git_worktree_add_options {
 
        int lock; /**< lock newly created worktree */
        git_reference *ref; /**< reference to use for the new worktree HEAD */
+
+       /**
+        * Options for the checkout.
+        */
+       git_checkout_options checkout_options;
 } git_worktree_add_options;
 
 #define GIT_WORKTREE_ADD_OPTIONS_VERSION 1
-#define GIT_WORKTREE_ADD_OPTIONS_INIT {GIT_WORKTREE_ADD_OPTIONS_VERSION,0,NULL}
+#define GIT_WORKTREE_ADD_OPTIONS_INIT {GIT_WORKTREE_ADD_OPTIONS_VERSION,0,NULL,GIT_CHECKOUT_OPTIONS_INIT}
 
 /**
  * Initialize git_worktree_add_options structure
@@ -185,7 +191,7 @@ typedef enum {
        /* Prune working tree even if it is locked */
        GIT_WORKTREE_PRUNE_LOCKED = 1u << 1,
        /* Prune checked out working tree */
-       GIT_WORKTREE_PRUNE_WORKING_TREE = 1u << 2,
+       GIT_WORKTREE_PRUNE_WORKING_TREE = 1u << 2
 } git_worktree_prune_t;
 
 /**
@@ -232,6 +238,10 @@ GIT_EXTERN(int) git_worktree_prune_options_init(
  * If the worktree is not valid and not locked or if the above
  * flags have been passed in, this function will return a
  * positive value.
+ *
+ * @param wt Worktree to check.
+ * @param opts The prunable options.
+ * @return 1 if the worktree is prunable, 0 otherwise, or an error code.
  */
 GIT_EXTERN(int) git_worktree_is_prunable(git_worktree *wt,
        git_worktree_prune_options *opts);
index e2e672f9fe6f76b37f972802e9da7ce42f4795ea..5caa47aeae96b21df4d34748d812219333b87796 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "libgit2",
-  "version": "1.3.0",
+  "version": "1.4.3",
   "repo": "https://github.com/libgit2/libgit2",
   "description": " A cross-platform, linkable library implementation of Git that you can use in your application.",
   "install": "mkdir build && cd build && cmake .. && cmake --build ."
index fdb367335b4f8063a21d31ee7e91ec81f5863767..e7b54d036ab7d4abbfe47ae52d1eb4bb3fb8509b 100644 (file)
@@ -1,95 +1,85 @@
 add_library(git2internal OBJECT)
 set_target_properties(git2internal PROPERTIES C_STANDARD 90)
+set_target_properties(git2internal PROPERTIES C_EXTENSIONS OFF)
 
-IF(DEBUG_POOL)
-       SET(GIT_DEBUG_POOL 1)
-ENDIF()
-ADD_FEATURE_INFO(debugpool GIT_DEBUG_POOL "debug pool allocator")
 
-IF(DEBUG_STRICT_ALLOC)
-       SET(GIT_DEBUG_STRICT_ALLOC 1)
-ENDIF()
-ADD_FEATURE_INFO(debugalloc GIT_DEBUG_STRICT_ALLOC "debug strict allocators")
+if(DEPRECATE_HARD)
+        add_definitions(-DGIT_DEPRECATE_HARD)
+endif()
+
+if(DEBUG_POOL)
+       set(GIT_DEBUG_POOL 1)
+endif()
+add_feature_info(debugpool GIT_DEBUG_POOL "debug pool allocator")
+
+if(DEBUG_STRICT_ALLOC)
+       set(GIT_DEBUG_STRICT_ALLOC 1)
+endif()
+add_feature_info(debugalloc GIT_DEBUG_STRICT_ALLOC "debug strict allocators")
+
+if(DEBUG_STRICT_OPEN)
+       set(GIT_DEBUG_STRICT_OPEN 1)
+endif()
+add_feature_info(debugopen GIT_DEBUG_STRICT_OPEN "path validation in open")
 
-IF(DEBUG_STRICT_OPEN)
-       SET(GIT_DEBUG_STRICT_OPEN 1)
-ENDIF()
-ADD_FEATURE_INFO(debugopen GIT_DEBUG_STRICT_OPEN "path validation in open")
 
-INCLUDE(PkgBuildConfig)
-INCLUDE(SanitizeBool)
+include(PkgBuildConfig)
+include(SanitizeBool)
 
 # This variable will contain the libraries we need to put into
 # libgit2.pc's Requires.private. That is, what we're linking to or
 # what someone who's statically linking us needs to link to.
-SET(LIBGIT2_PC_REQUIRES "")
+set(LIBGIT2_PC_REQUIRES "")
 # This will be set later if we use the system's http-parser library or
 # use iconv (OSX) and will be written to the Libs.private field in the
 # pc file.
-SET(LIBGIT2_PC_LIBS "")
+set(LIBGIT2_PC_LIBS "")
 
-SET(LIBGIT2_INCLUDES
+set(LIBGIT2_INCLUDES
        "${CMAKE_CURRENT_BINARY_DIR}"
-       "${libgit2_SOURCE_DIR}/src"
-       "${libgit2_SOURCE_DIR}/include")
-SET(LIBGIT2_SYSTEM_INCLUDES "")
-SET(LIBGIT2_LIBS "")
-
-enable_warnings(missing-declarations)
-
-# Enable tracing
-IF(ENABLE_TRACE)
-       SET(GIT_TRACE 1)
-ENDIF()
-ADD_FEATURE_INFO(tracing GIT_TRACE "tracing support")
+       "${PROJECT_SOURCE_DIR}/src"
+       "${PROJECT_SOURCE_DIR}/include")
 
-IF (HAVE_FUTIMENS)
-       SET(GIT_USE_FUTIMENS 1)
-ENDIF ()
-ADD_FEATURE_INFO(futimens GIT_USE_FUTIMENS "futimens support")
+if(HAVE_FUTIMENS)
+       set(GIT_USE_FUTIMENS 1)
+endif ()
+add_feature_info(futimens GIT_USE_FUTIMENS "futimens support")
 
-CHECK_PROTOTYPE_DEFINITION(qsort_r
+check_prototype_definition(qsort_r
        "void qsort_r(void *base, size_t nmemb, size_t size, void *thunk, int (*compar)(void *, const void *, const void *))"
-       "" "stdlib.h" HAVE_QSORT_R_BSD)
-IF (HAVE_QSORT_R_BSD)
-       target_compile_definitions(git2internal PRIVATE HAVE_QSORT_R_BSD)
-ENDIF()
+       "" "stdlib.h" GIT_QSORT_R_BSD)
 
-CHECK_PROTOTYPE_DEFINITION(qsort_r
+check_prototype_definition(qsort_r
        "void qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg)"
-       "" "stdlib.h" HAVE_QSORT_R_GNU)
-IF (HAVE_QSORT_R_GNU)
-       target_compile_definitions(git2internal PRIVATE HAVE_QSORT_R_GNU)
-ENDIF()
+       "" "stdlib.h" GIT_QSORT_R_GNU)
 
-CHECK_FUNCTION_EXISTS(qsort_s HAVE_QSORT_S)
-IF (HAVE_QSORT_S)
-       target_compile_definitions(git2internal PRIVATE HAVE_QSORT_S)
-ENDIF ()
+check_function_exists(qsort_s GIT_QSORT_S)
+
+check_function_exists(getentropy GIT_RAND_GETENTROPY)
 
 # Find required dependencies
 
-IF(WIN32)
-       LIST(APPEND LIBGIT2_LIBS ws2_32)
-ELSEIF(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
-       LIST(APPEND LIBGIT2_LIBS socket nsl)
-       LIST(APPEND LIBGIT2_PC_LIBS "-lsocket" "-lnsl")
-ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Haiku")
-       LIST(APPEND LIBGIT2_LIBS network)
-       LIST(APPEND LIBGIT2_PC_LIBS "-lnetwork")
-ENDIF()
-
-CHECK_LIBRARY_EXISTS(rt clock_gettime "time.h" NEED_LIBRT)
-IF(NEED_LIBRT)
-       LIST(APPEND LIBGIT2_LIBS rt)
-       LIST(APPEND LIBGIT2_PC_LIBS "-lrt")
-ENDIF()
-
-IF(THREADSAFE)
-       LIST(APPEND LIBGIT2_LIBS ${CMAKE_THREAD_LIBS_INIT})
-       LIST(APPEND LIBGIT2_PC_LIBS ${CMAKE_THREAD_LIBS_INIT})
-ENDIF()
-ADD_FEATURE_INFO(threadsafe THREADSAFE "threadsafe support")
+if(WIN32)
+       list(APPEND LIBGIT2_SYSTEM_LIBS ws2_32)
+elseif(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
+       list(APPEND LIBGIT2_SYSTEM_LIBS socket nsl)
+       list(APPEND LIBGIT2_PC_LIBS "-lsocket" "-lnsl")
+elseif(CMAKE_SYSTEM_NAME MATCHES "Haiku")
+       list(APPEND LIBGIT2_SYSTEM_LIBS network)
+       list(APPEND LIBGIT2_PC_LIBS "-lnetwork")
+endif()
+
+check_library_exists(rt clock_gettime "time.h" NEED_LIBRT)
+if(NEED_LIBRT)
+       list(APPEND LIBGIT2_SYSTEM_LIBS rt)
+       list(APPEND LIBGIT2_PC_LIBS "-lrt")
+endif()
+
+if(USE_THREADS)
+       list(APPEND LIBGIT2_SYSTEM_LIBS ${CMAKE_THREAD_LIBS_INIT})
+       list(APPEND LIBGIT2_PC_LIBS ${CMAKE_THREAD_LIBS_INIT})
+endif()
+add_feature_info(threadsafe USE_THREADS "threadsafe support")
 
 
 if(WIN32 AND EMBED_SSH_PATH)
@@ -102,218 +92,90 @@ if(WIN32 AND EMBED_SSH_PATH)
        set(GIT_SSH 1)
 endif()
 
-IF (WIN32 AND WINHTTP)
-       SET(GIT_WINHTTP 1)
-
-       # Since MinGW does not come with headers or an import library for winhttp,
-       # we have to include a private header and generate our own import library
-       IF (MINGW)
-               ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/winhttp" "${libgit2_BINARY_DIR}/deps/winhttp")
-               LIST(APPEND LIBGIT2_LIBS winhttp)
-               LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/winhttp")
-       ELSE()
-               LIST(APPEND LIBGIT2_LIBS "winhttp")
-               LIST(APPEND LIBGIT2_PC_LIBS "-lwinhttp")
-       ENDIF ()
-
-       LIST(APPEND LIBGIT2_LIBS "rpcrt4" "crypt32" "ole32")
-       LIST(APPEND LIBGIT2_PC_LIBS "-lrpcrt4" "-lcrypt32" "-lole32")
-ENDIF()
-
 include(SelectHTTPSBackend)
 include(SelectHashes)
+include(SelectHTTPParser)
+include(SelectRegex)
+include(SelectSSH)
+include(SelectWinHTTP)
+include(SelectZlib)
+
+
+if(USE_SHA1 STREQUAL "CollisionDetection")
+       file(GLOB SRC_SHA1 hash/sha1/collisiondetect.* hash/sha1/sha1dc/*)
+elseif(USE_SHA1 STREQUAL "OpenSSL")
+       file(GLOB SRC_SHA1 hash/sha1/openssl.*)
+elseif(USE_SHA1 STREQUAL "CommonCrypto")
+       file(GLOB SRC_SHA1 hash/sha1/common_crypto.*)
+elseif(USE_SHA1 STREQUAL "mbedTLS")
+       file(GLOB SRC_SHA1 hash/sha1/mbedtls.*)
+elseif(USE_SHA1 STREQUAL "Win32")
+       file(GLOB SRC_SHA1 hash/sha1/win32.*)
+elseif(USE_SHA1 STREQUAL "Generic")
+       file(GLOB SRC_SHA1 hash/sha1/generic.*)
+endif()
+list(APPEND SRC_SHA1 "hash/sha1.h")
 target_sources(git2internal PRIVATE ${SRC_SHA1})
 
-# Specify regular expression implementation
-FIND_PACKAGE(PCRE)
-
-IF(REGEX_BACKEND STREQUAL "")
-       CHECK_SYMBOL_EXISTS(regcomp_l "regex.h;xlocale.h" HAVE_REGCOMP_L)
-
-       IF(HAVE_REGCOMP_L)
-               SET(REGEX_BACKEND "regcomp_l")
-       ELSEIF(PCRE_FOUND)
-               SET(REGEX_BACKEND "pcre")
-       ELSE()
-               SET(REGEX_BACKEND "builtin")
-       ENDIF()
-ENDIF()
-
-IF(REGEX_BACKEND STREQUAL "regcomp_l")
-       ADD_FEATURE_INFO(regex ON "using system regcomp_l")
-       SET(GIT_REGEX_REGCOMP_L 1)
-ELSEIF(REGEX_BACKEND STREQUAL "pcre2")
-       FIND_PACKAGE(PCRE2)
-
-       IF(NOT PCRE2_FOUND)
-               MESSAGE(FATAL_ERROR "PCRE2 support was requested but not found")
-       ENDIF()
-
-       ADD_FEATURE_INFO(regex ON "using system PCRE2")
-       SET(GIT_REGEX_PCRE2 1)
-
-       LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${PCRE2_INCLUDE_DIRS})
-       LIST(APPEND LIBGIT2_LIBS ${PCRE2_LIBRARIES})
-       LIST(APPEND LIBGIT2_PC_REQUIRES "libpcre2-8")
-ELSEIF(REGEX_BACKEND STREQUAL "pcre")
-       ADD_FEATURE_INFO(regex ON "using system PCRE")
-       SET(GIT_REGEX_PCRE 1)
-
-       LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${PCRE_INCLUDE_DIRS})
-       LIST(APPEND LIBGIT2_LIBS ${PCRE_LIBRARIES})
-       LIST(APPEND LIBGIT2_PC_REQUIRES "libpcre")
-ELSEIF(REGEX_BACKEND STREQUAL "regcomp")
-       ADD_FEATURE_INFO(regex ON "using system regcomp")
-       SET(GIT_REGEX_REGCOMP 1)
-ELSEIF(REGEX_BACKEND STREQUAL "builtin")
-       ADD_FEATURE_INFO(regex ON "using bundled PCRE")
-       SET(GIT_REGEX_BUILTIN 1)
-
-       ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/pcre" "${libgit2_BINARY_DIR}/deps/pcre")
-       LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/pcre")
-       LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:pcre>)
-ELSE()
-       MESSAGE(FATAL_ERROR "The REGEX_BACKEND option provided is not supported")
-ENDIF()
-
-# Optional external dependency: http-parser
-IF(USE_HTTP_PARSER STREQUAL "system")
-       FIND_PACKAGE(HTTP_Parser)
-
-       IF (HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2)
-               LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${HTTP_PARSER_INCLUDE_DIRS})
-               LIST(APPEND LIBGIT2_LIBS ${HTTP_PARSER_LIBRARIES})
-               LIST(APPEND LIBGIT2_PC_LIBS "-lhttp_parser")
-               ADD_FEATURE_INFO(http-parser ON "http-parser support (system)")
-       ELSE()
-               MESSAGE(FATAL_ERROR "http-parser support was requested but not found")
-       ENDIF()
-ELSE()
-       MESSAGE(STATUS "http-parser version 2 was not found or disabled; using bundled 3rd-party sources.")
-       ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/http-parser" "${libgit2_BINARY_DIR}/deps/http-parser")
-       LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/http-parser")
-       LIST(APPEND LIBGIT2_OBJECTS "$<TARGET_OBJECTS:http-parser>")
-       ADD_FEATURE_INFO(http-parser ON "http-parser support (bundled)")
-ENDIF()
-
-# Optional external dependency: zlib
-SanitizeBool(USE_BUNDLED_ZLIB)
-IF(USE_BUNDLED_ZLIB STREQUAL ON)
-       SET(USE_BUNDLED_ZLIB "Bundled")
-ENDIF()
-
-IF(USE_BUNDLED_ZLIB STREQUAL "OFF")
-       FIND_PACKAGE(ZLIB)
-       IF(ZLIB_FOUND)
-               LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${ZLIB_INCLUDE_DIRS})
-               LIST(APPEND LIBGIT2_LIBS ${ZLIB_LIBRARIES})
-               IF(APPLE OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
-                       LIST(APPEND LIBGIT2_PC_LIBS "-lz")
-               ELSE()
-                       LIST(APPEND LIBGIT2_PC_REQUIRES "zlib")
-               ENDIF()
-               ADD_FEATURE_INFO(zlib ON "using system zlib")
-       ELSE()
-               MESSAGE(STATUS "zlib was not found; using bundled 3rd-party sources." )
-       ENDIF()
-ENDIF()
-IF(USE_BUNDLED_ZLIB STREQUAL "Chromium")
-       ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/chromium-zlib" "${libgit2_BINARY_DIR}/deps/chromium-zlib")
-       LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/chromium-zlib")
-       LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:chromium_zlib>)
-       ADD_FEATURE_INFO(zlib ON "using (Chromium) bundled zlib")
-ELSEIF(USE_BUNDLED_ZLIB OR NOT ZLIB_FOUND)
-       ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/zlib" "${libgit2_BINARY_DIR}/deps/zlib")
-       LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/zlib")
-       LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:zlib>)
-       ADD_FEATURE_INFO(zlib ON "using bundled zlib")
-ENDIF()
-
-# Optional external dependency: libssh2
-IF (USE_SSH)
-       FIND_PKGLIBRARIES(LIBSSH2 libssh2)
-       IF (NOT LIBSSH2_FOUND)
-               FIND_PACKAGE(LibSSH2)
-               SET(LIBSSH2_INCLUDE_DIRS ${LIBSSH2_INCLUDE_DIR})
-               GET_FILENAME_COMPONENT(LIBSSH2_LIBRARY_DIRS "${LIBSSH2_LIBRARY}" DIRECTORY)
-               SET(LIBSSH2_LIBRARIES ${LIBSSH2_LIBRARY})
-               SET(LIBSSH2_LDFLAGS "-lssh2")
-       ENDIF()
-ENDIF()
-IF (LIBSSH2_FOUND)
-       SET(GIT_SSH 1)
-       LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${LIBSSH2_INCLUDE_DIRS})
-       LIST(APPEND LIBGIT2_LIBS ${LIBSSH2_LIBRARIES})
-       LIST(APPEND LIBGIT2_PC_LIBS ${LIBSSH2_LDFLAGS})
-
-       CHECK_LIBRARY_EXISTS("${LIBSSH2_LIBRARIES}" libssh2_userauth_publickey_frommemory "${LIBSSH2_LIBRARY_DIRS}" HAVE_LIBSSH2_MEMORY_CREDENTIALS)
-       IF (HAVE_LIBSSH2_MEMORY_CREDENTIALS)
-               SET(GIT_SSH_MEMORY_CREDENTIALS 1)
-       ENDIF()
-ELSE()
-       MESSAGE(STATUS "LIBSSH2 not found. Set CMAKE_PREFIX_PATH if it is installed outside of the default search path.")
-ENDIF()
-ADD_FEATURE_INFO(SSH GIT_SSH "SSH transport support")
-
 # Optional external dependency: ntlmclient
-IF (USE_NTLMCLIENT)
-       SET(GIT_NTLM 1)
-       ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/ntlmclient" "${libgit2_BINARY_DIR}/deps/ntlmclient")
-       LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/ntlmclient")
-       LIST(APPEND LIBGIT2_OBJECTS "$<TARGET_OBJECTS:ntlmclient>")
-ENDIF()
-ADD_FEATURE_INFO(ntlmclient GIT_NTLM "NTLM authentication support for Unix")
+if(USE_NTLMCLIENT)
+       set(GIT_NTLM 1)
+       add_subdirectory("${PROJECT_SOURCE_DIR}/deps/ntlmclient" "${PROJECT_BINARY_DIR}/deps/ntlmclient")
+       list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${PROJECT_SOURCE_DIR}/deps/ntlmclient")
+       list(APPEND LIBGIT2_DEPENDENCY_OBJECTS "$<TARGET_OBJECTS:ntlmclient>")
+endif()
+add_feature_info(ntlmclient GIT_NTLM "NTLM authentication support for Unix")
 
 # Optional external dependency: GSSAPI
 
-INCLUDE(SelectGSSAPI)
+include(SelectGSSAPI)
 
 # Optional external dependency: iconv
-IF (USE_ICONV)
-       FIND_PACKAGE(Iconv)
-ENDIF()
-IF (ICONV_FOUND)
-       SET(GIT_USE_ICONV 1)
-       LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${ICONV_INCLUDE_DIR})
-       LIST(APPEND LIBGIT2_LIBS ${ICONV_LIBRARIES})
-       LIST(APPEND LIBGIT2_PC_LIBS ${ICONV_LIBRARIES})
-ENDIF()
-ADD_FEATURE_INFO(iconv GIT_USE_ICONV "iconv encoding conversion support")
-
-
-IF (THREADSAFE)
-       IF (NOT WIN32)
-               FIND_PACKAGE(Threads REQUIRED)
-       ENDIF()
-
-       SET(GIT_THREADS 1)
-ENDIF()
-
-IF (USE_NSEC)
-       SET(GIT_USE_NSEC 1)
-ENDIF()
-
-IF (HAVE_STRUCT_STAT_ST_MTIM)
-       SET(GIT_USE_STAT_MTIM 1)
-ELSEIF (HAVE_STRUCT_STAT_ST_MTIMESPEC)
-       SET(GIT_USE_STAT_MTIMESPEC 1)
-ELSEIF (HAVE_STRUCT_STAT_ST_MTIME_NSEC)
-       SET(GIT_USE_STAT_MTIME_NSEC 1)
-ENDIF()
+if(USE_ICONV)
+       find_package(Iconv)
+endif()
+if(ICONV_FOUND)
+       set(GIT_USE_ICONV 1)
+       list(APPEND LIBGIT2_SYSTEM_INCLUDES ${ICONV_INCLUDE_DIR})
+       list(APPEND LIBGIT2_SYSTEM_LIBS ${ICONV_LIBRARIES})
+       list(APPEND LIBGIT2_PC_LIBS ${ICONV_LIBRARIES})
+endif()
+add_feature_info(iconv GIT_USE_ICONV "iconv encoding conversion support")
+
+
+if(USE_THREADS)
+       if(NOT WIN32)
+               find_package(Threads REQUIRED)
+       endif()
+
+       set(GIT_THREADS 1)
+endif()
+
+if(USE_NSEC)
+       set(GIT_USE_NSEC 1)
+endif()
+
+if(HAVE_STRUCT_STAT_ST_MTIM)
+       set(GIT_USE_STAT_MTIM 1)
+elseif(HAVE_STRUCT_STAT_ST_MTIMESPEC)
+       set(GIT_USE_STAT_MTIMESPEC 1)
+elseif(HAVE_STRUCT_STAT_ST_MTIME_NSEC)
+       set(GIT_USE_STAT_MTIME_NSEC 1)
+endif()
 
 target_compile_definitions(git2internal PRIVATE _FILE_OFFSET_BITS=64)
 
 # Collect sourcefiles
 file(GLOB SRC_H
-       "${libgit2_SOURCE_DIR}/include/git2.h"
-       "${libgit2_SOURCE_DIR}/include/git2/*.h"
-       "${libgit2_SOURCE_DIR}/include/git2/sys/*.h")
+       "${PROJECT_SOURCE_DIR}/include/git2.h"
+       "${PROJECT_SOURCE_DIR}/include/git2/*.h"
+       "${PROJECT_SOURCE_DIR}/include/git2/sys/*.h")
 list(SORT SRC_H)
 target_sources(git2internal PRIVATE ${SRC_H})
 
 # On Windows use specific platform sources
 if(WIN32 AND NOT CYGWIN)
-       SET(WIN_RC "win32/git2.rc")
+       set(WIN_RC "win32/git2.rc")
 
        file(GLOB SRC_OS win32/*.c win32/*.h)
        list(SORT SRC_OS)
@@ -326,9 +188,9 @@ else()
        target_sources(git2internal PRIVATE ${SRC_OS})
 endif()
 
-IF (USE_LEAK_CHECKER STREQUAL "valgrind")
+if(USE_LEAK_CHECKER STREQUAL "valgrind")
        target_compile_definitions(git2internal PRIVATE VALGRIND)
-ENDIF()
+endif()
 
 file(GLOB SRC_GIT2 *.c *.h
        allocators/*.c allocators/*.h
@@ -338,65 +200,77 @@ file(GLOB SRC_GIT2 *.c *.h
 list(SORT SRC_GIT2)
 target_sources(git2internal PRIVATE ${SRC_GIT2})
 
-IF(APPLE)
+if(APPLE)
        # The old Secure Transport API has been deprecated in macOS 10.15.
-       SET_SOURCE_FILES_PROPERTIES(streams/stransport.c PROPERTIES COMPILE_FLAGS -Wno-deprecated)
-ENDIF()
+       set_source_files_properties(streams/stransport.c PROPERTIES COMPILE_FLAGS -Wno-deprecated)
+endif()
 
 # the xdiff dependency is not (yet) warning-free, disable warnings as
 # errors for the xdiff sources until we've sorted them out
-IF(MSVC)
-       SET_SOURCE_FILES_PROPERTIES(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS -WX-)
-       SET_SOURCE_FILES_PROPERTIES(xdiff/xutils.c PROPERTIES COMPILE_FLAGS -WX-)
-ENDIF()
+if(MSVC)
+       set_source_files_properties(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS -WX-)
+       set_source_files_properties(xdiff/xemit.c PROPERTIES COMPILE_FLAGS -WX-)
+       set_source_files_properties(xdiff/xhistogram.c PROPERTIES COMPILE_FLAGS -WX-)
+       set_source_files_properties(xdiff/xmerge.c PROPERTIES COMPILE_FLAGS -WX-)
+       set_source_files_properties(xdiff/xutils.c PROPERTIES COMPILE_FLAGS -WX-)
+       set_source_files_properties(xdiff/xpatience.c PROPERTIES COMPILE_FLAGS -WX-)
+else()
+       set_source_files_properties(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter")
+       set_source_files_properties(xdiff/xemit.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter")
+       set_source_files_properties(xdiff/xhistogram.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
+       set_source_files_properties(xdiff/xutils.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
+       set_source_files_properties(xdiff/xpatience.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
+endif()
 
 # Determine architecture of the machine
-IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
-       SET(GIT_ARCH_64 1)
-ELSEIF (CMAKE_SIZEOF_VOID_P EQUAL 4)
-       SET(GIT_ARCH_32 1)
-ELSEIF (CMAKE_SIZEOF_VOID_P)
-       MESSAGE(FATAL_ERROR "Unsupported architecture (pointer size is ${CMAKE_SIZEOF_VOID_P} bytes)")
-ELSE()
-       MESSAGE(FATAL_ERROR "Unsupported architecture (CMAKE_SIZEOF_VOID_P is unset)")
-ENDIF()
-
-CONFIGURE_FILE(features.h.in git2/sys/features.h)
-
-IDE_SPLIT_SOURCES(git2internal)
-LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:git2internal>)
-
-TARGET_INCLUDE_DIRECTORIES(git2internal PRIVATE ${LIBGIT2_INCLUDES} PUBLIC ${libgit2_SOURCE_DIR}/include)
-TARGET_INCLUDE_DIRECTORIES(git2internal SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
-
-SET(LIBGIT2_OBJECTS ${LIBGIT2_OBJECTS} PARENT_SCOPE)
-SET(LIBGIT2_INCLUDES ${LIBGIT2_INCLUDES} PARENT_SCOPE)
-SET(LIBGIT2_SYSTEM_INCLUDES ${LIBGIT2_SYSTEM_INCLUDES} PARENT_SCOPE)
-SET(LIBGIT2_LIBS ${LIBGIT2_LIBS} PARENT_SCOPE)
-
-IF(XCODE_VERSION)
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+       set(GIT_ARCH_64 1)
+elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
+       set(GIT_ARCH_32 1)
+elseif(CMAKE_SIZEOF_VOID_P)
+       message(FATAL_ERROR "Unsupported architecture (pointer size is ${CMAKE_SIZEOF_VOID_P} bytes)")
+else()
+       message(FATAL_ERROR "Unsupported architecture (CMAKE_SIZEOF_VOID_P is unset)")
+endif()
+
+configure_file(features.h.in git2/sys/features.h)
+
+ide_split_sources(git2internal)
+list(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:git2internal> ${LIBGIT2_DEPENDENCY_OBJECTS})
+
+target_include_directories(git2internal PRIVATE ${LIBGIT2_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES} PUBLIC ${PROJECT_SOURCE_DIR}/include)
+target_include_directories(git2internal SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
+
+set(LIBGIT2_INCLUDES ${LIBGIT2_INCLUDES} PARENT_SCOPE)
+set(LIBGIT2_OBJECTS ${LIBGIT2_OBJECTS} PARENT_SCOPE)
+set(LIBGIT2_DEPENDENCY_INCLUDES ${LIBGIT2_DEPENDENCY_INCLUDES} PARENT_SCOPE)
+set(LIBGIT2_DEPENDENCY_OBJECTS ${LIBGIT2_DEPENDENCY_OBJECTS} PARENT_SCOPE)
+set(LIBGIT2_SYSTEM_INCLUDES ${LIBGIT2_SYSTEM_INCLUDES} PARENT_SCOPE)
+set(LIBGIT2_SYSTEM_LIBS ${LIBGIT2_SYSTEM_LIBS} PARENT_SCOPE)
+
+if(XCODE_VERSION)
        # This is required for Xcode to actually link the libgit2 library
        # when using only object libraries.
-       FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.c "")
-       LIST(APPEND LIBGIT2_OBJECTS ${CMAKE_CURRENT_BINARY_DIR}/dummy.c)
-ENDIF()
+       file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.c "")
+       list(APPEND LIBGIT2_OBJECTS ${CMAKE_CURRENT_BINARY_DIR}/dummy.c)
+endif()
 
 # Compile and link libgit2
-ADD_LIBRARY(git2 ${WIN_RC} ${LIBGIT2_OBJECTS})
-TARGET_LINK_LIBRARIES(git2 ${LIBGIT2_LIBS})
+add_library(git2 ${WIN_RC} ${LIBGIT2_OBJECTS})
+target_link_libraries(git2 ${LIBGIT2_SYSTEM_LIBS})
 
-SET_TARGET_PROPERTIES(git2 PROPERTIES C_STANDARD 90)
-SET_TARGET_PROPERTIES(git2 PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${libgit2_BINARY_DIR})
-SET_TARGET_PROPERTIES(git2 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${libgit2_BINARY_DIR})
-SET_TARGET_PROPERTIES(git2 PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${libgit2_BINARY_DIR})
+set_target_properties(git2 PROPERTIES C_STANDARD 90)
+set_target_properties(git2 PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
+set_target_properties(git2 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
+set_target_properties(git2 PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
 
 # Workaround for Cmake bug #0011240 (see http://public.kitware.com/Bug/view.php?id=11240)
 # Win64+MSVC+static libs = linker error
-IF(MSVC AND GIT_ARCH_64 AND NOT BUILD_SHARED_LIBS)
-  SET_TARGET_PROPERTIES(git2 PROPERTIES STATIC_LIBRARY_FLAGS "/MACHINE:x64")
-ENDIF()
+if(MSVC AND GIT_ARCH_64 AND NOT BUILD_SHARED_LIBS)
+       set_target_properties(git2 PROPERTIES STATIC_LIBRARY_FLAGS "/MACHINE:x64")
+endif()
 
-IDE_SPLIT_SOURCES(git2)
+ide_split_sources(git2)
 
 if(SONAME)
        set_target_properties(git2 PROPERTIES VERSION ${libgit2_VERSION})
@@ -409,7 +283,7 @@ if(SONAME)
        endif()
 endif()
 
-PKG_BUILD_CONFIG(NAME libgit2
+pkg_build_config(NAME libgit2
        VERSION ${libgit2_VERSION}
        DESCRIPTION "The git library, take 2"
        LIBS_SELF git2
@@ -417,17 +291,17 @@ PKG_BUILD_CONFIG(NAME libgit2
        REQUIRES ${LIBGIT2_PC_REQUIRES}
 )
 
-IF (MSVC_IDE)
-   # Precompiled headers
-   SET_TARGET_PROPERTIES(git2 PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
-   SET_SOURCE_FILES_PROPERTIES(win32/precompiled.c COMPILE_FLAGS "/Ycprecompiled.h")
-ENDIF ()
+if(MSVC_IDE)
+       # Precompiled headers
+       set_target_properties(git2 PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
+       set_source_files_properties(win32/precompiled.c COMPILE_FLAGS "/Ycprecompiled.h")
+endif()
 
 # Install
-INSTALL(TARGETS git2
+install(TARGETS git2
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
 )
-INSTALL(DIRECTORY ${libgit2_SOURCE_DIR}/include/git2 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
-INSTALL(FILES ${libgit2_SOURCE_DIR}/include/git2.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/git2 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+install(FILES ${PROJECT_SOURCE_DIR}/include/git2.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
index b390066b2c9bf99bfcef152c0a1e473abf169209..444a2ed10722e315114185bce0c7a76fec1b2177 100644 (file)
@@ -15,7 +15,7 @@
 
 typedef enum {
        GIT_ANNOTATED_COMMIT_REAL = 1,
-       GIT_ANNOTATED_COMMIT_VIRTUAL = 2,
+       GIT_ANNOTATED_COMMIT_VIRTUAL = 2
 } git_annotated_commit_t;
 
 /**
index 7c65cd79db6705cc4fb99e2c030a1e43fce68b55..18304da4df7a7150e3f9ddec2655c527c6f360cf 100644 (file)
@@ -265,7 +265,7 @@ done:
 }
 
 static int apply_hunks(
-       git_buf *out,
+       git_str *out,
        const char *source,
        size_t source_len,
        git_patch *patch,
@@ -286,7 +286,7 @@ static int apply_hunks(
        }
 
        git_vector_foreach(&image.lines, i, line)
-               git_buf_put(out, line->content, line->content_len);
+               git_str_put(out, line->content, line->content_len);
 
 done:
        patch_image_free(&image);
@@ -295,24 +295,24 @@ done:
 }
 
 static int apply_binary_delta(
-       git_buf *out,
+       git_str *out,
        const char *source,
        size_t source_len,
        git_diff_binary_file *binary_file)
 {
-       git_buf inflated = GIT_BUF_INIT;
+       git_str inflated = GIT_STR_INIT;
        int error = 0;
 
        /* no diff means identical contents */
        if (binary_file->datalen == 0)
-               return git_buf_put(out, source, source_len);
+               return git_str_put(out, source, source_len);
 
        error = git_zstream_inflatebuf(&inflated,
                binary_file->data, binary_file->datalen);
 
        if (!error && inflated.size != binary_file->inflatedlen) {
                error = apply_err("inflated delta does not match expected length");
-               git_buf_dispose(out);
+               git_str_dispose(out);
        }
 
        if (error < 0)
@@ -330,7 +330,7 @@ static int apply_binary_delta(
                out->asize = data_len;
        }
        else if (binary_file->type == GIT_DIFF_BINARY_LITERAL) {
-               git_buf_swap(out, &inflated);
+               git_str_swap(out, &inflated);
        }
        else {
                error = apply_err("unknown binary delta type");
@@ -338,17 +338,17 @@ static int apply_binary_delta(
        }
 
 done:
-       git_buf_dispose(&inflated);
+       git_str_dispose(&inflated);
        return error;
 }
 
 static int apply_binary(
-       git_buf *out,
+       git_str *out,
        const char *source,
        size_t source_len,
        git_patch *patch)
 {
-       git_buf reverse = GIT_BUF_INIT;
+       git_str reverse = GIT_STR_INIT;
        int error = 0;
 
        if (!patch->binary.contains_data) {
@@ -378,14 +378,14 @@ static int apply_binary(
 
 done:
        if (error < 0)
-               git_buf_dispose(out);
+               git_str_dispose(out);
 
-       git_buf_dispose(&reverse);
+       git_str_dispose(&reverse);
        return error;
 }
 
 int git_apply__patch(
-       git_buf *contents_out,
+       git_str *contents_out,
        char **filename_out,
        unsigned int *mode_out,
        const char *source,
@@ -423,13 +423,13 @@ int git_apply__patch(
        else if (patch->hunks.size)
                error = apply_hunks(contents_out, source, source_len, patch, &ctx);
        else
-               error = git_buf_put(contents_out, source, source_len);
+               error = git_str_put(contents_out, source, source_len);
 
        if (error)
                goto done;
 
        if (patch->delta->status == GIT_DELTA_DELETED &&
-               git_buf_len(contents_out) > 0) {
+               git_str_len(contents_out) > 0) {
                error = apply_err("removal patch leaves file contents");
                goto done;
        }
@@ -456,7 +456,7 @@ static int apply_one(
        const git_apply_options *opts)
 {
        git_patch *patch = NULL;
-       git_buf pre_contents = GIT_BUF_INIT, post_contents = GIT_BUF_INIT;
+       git_str pre_contents = GIT_STR_INIT, post_contents = GIT_STR_INIT;
        const git_diff_delta *delta;
        char *filename = NULL;
        unsigned int mode;
@@ -579,8 +579,8 @@ static int apply_one(
                git_strmap_delete(removed_paths, delta->new_file.path);
 
 done:
-       git_buf_dispose(&pre_contents);
-       git_buf_dispose(&post_contents);
+       git_str_dispose(&pre_contents);
+       git_str_dispose(&post_contents);
        git__free(filename);
        git_patch_free(patch);
 
index 11ec75637083563b69d2ff87b05613058d1a6da2..e990a71071cca6355ccc0cd49a0504966e087d92 100644 (file)
 
 #include "git2/patch.h"
 #include "git2/apply.h"
-#include "buffer.h"
+#include "str.h"
 
 extern int git_apply__patch(
-       git_buf *out,
+       git_str *out,
        char **filename,
        unsigned int *mode,
        const char *source,
index 95b49e3de41132abf778c894724919607c0f400e..1623b1d4570949426f6e7e86e6ba0a8e61e5fc83 100644 (file)
@@ -338,7 +338,7 @@ GIT_INLINE(int) preload_attr_file(
 }
 
 static int system_attr_file(
-       git_buf *out,
+       git_str *out,
        git_attr_session *attr_session)
 {
        int error;
@@ -366,11 +366,11 @@ static int system_attr_file(
        if (attr_session->sysdir.size == 0)
                return GIT_ENOTFOUND;
 
-       /* We can safely provide a git_buf with no allocation (asize == 0) to
-        * a consumer. This allows them to treat this as a regular `git_buf`,
-        * but their call to `git_buf_dispose` will not attempt to free it.
+       /* We can safely provide a git_str with no allocation (asize == 0) to
+        * a consumer. This allows them to treat this as a regular `git_str`,
+        * but their call to `git_str_dispose` will not attempt to free it.
         */
-       git_buf_attach_notowned(
+       git_str_attach_notowned(
                out, attr_session->sysdir.ptr, attr_session->sysdir.size);
        return 0;
 }
@@ -380,7 +380,7 @@ static int attr_setup(
        git_attr_session *attr_session,
        git_attr_options *opts)
 {
-       git_buf system = GIT_BUF_INIT, info = GIT_BUF_INIT;
+       git_str system = GIT_STR_INIT, info = GIT_STR_INIT;
        git_attr_file_source index_source = { GIT_ATTR_FILE_SOURCE_INDEX, NULL, GIT_ATTR_FILE, NULL };
        git_attr_file_source head_source = { GIT_ATTR_FILE_SOURCE_HEAD, NULL, GIT_ATTR_FILE, NULL };
        git_attr_file_source commit_source = { GIT_ATTR_FILE_SOURCE_COMMIT, NULL, GIT_ATTR_FILE, NULL };
@@ -411,7 +411,7 @@ static int attr_setup(
                                       git_repository_attr_cache(repo)->cfg_attr_file)) < 0)
                goto out;
 
-       if ((error = git_repository_item_path(&info, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 ||
+       if ((error = git_repository__item_path(&info, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 ||
            (error = preload_attr_file(repo, attr_session, info.ptr, GIT_ATTR_FILE_INREPO)) < 0) {
                if (error != GIT_ENOTFOUND)
                        goto out;
@@ -447,8 +447,8 @@ static int attr_setup(
                attr_session->init_setup = 1;
 
 out:
-       git_buf_dispose(&system);
-       git_buf_dispose(&info);
+       git_str_dispose(&system);
+       git_str_dispose(&info);
 
        return error;
 }
@@ -625,11 +625,11 @@ static int collect_attr_files(
        git_vector *files)
 {
        int error = 0;
-       git_buf dir = GIT_BUF_INIT, attrfile = GIT_BUF_INIT;
+       git_str dir = GIT_STR_INIT, attrfile = GIT_STR_INIT;
        const char *workdir = git_repository_workdir(repo);
        attr_walk_up_info info = { NULL };
 
-       GIT_ASSERT(!git_path_is_absolute(path));
+       GIT_ASSERT(!git_fs_path_is_absolute(path));
 
        if ((error = attr_setup(repo, attr_session, opts)) < 0)
                return error;
@@ -637,23 +637,23 @@ static int collect_attr_files(
        /* Resolve path in a non-bare repo */
        if (workdir != NULL) {
                if (!(error = git_repository_workdir_path(&dir, repo, path)))
-                       error = git_path_find_dir(&dir);
+                       error = git_fs_path_find_dir(&dir);
        }
        else {
-               error = git_path_dirname_r(&dir, path);
+               error = git_fs_path_dirname_r(&dir, path);
        }
 
        if (error < 0)
                goto cleanup;
 
-       /* in precendence order highest to lowest:
+       /* in precedence order highest to lowest:
         * - $GIT_DIR/info/attributes
         * - path components with .gitattributes
         * - config core.attributesfile
         * - $GIT_PREFIX/etc/gitattributes
         */
 
-       if ((error = git_repository_item_path(&attrfile, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 ||
+       if ((error = git_repository__item_path(&attrfile, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 ||
            (error = push_attr_file(repo, attr_session, files, attrfile.ptr, GIT_ATTR_FILE_INREPO)) < 0) {
                if (error != GIT_ENOTFOUND)
                        goto cleanup;
@@ -670,7 +670,7 @@ static int collect_attr_files(
        if (!strcmp(dir.ptr, "."))
                error = push_one_attr(&info, "");
        else
-               error = git_path_walk_up(&dir, workdir, push_one_attr, &info);
+               error = git_fs_path_walk_up(&dir, workdir, push_one_attr, &info);
 
        if (error < 0)
                goto cleanup;
@@ -693,8 +693,8 @@ static int collect_attr_files(
  cleanup:
        if (error < 0)
                release_attr_files(files);
-       git_buf_dispose(&attrfile);
-       git_buf_dispose(&dir);
+       git_str_dispose(&attrfile);
+       git_str_dispose(&dir);
 
        return error;
 }
index 71bd20a0f64104688e276f2b8f00f120328bb3ed..0eb881a9b92b124538f5aea92e94fe0d59c23fd2 100644 (file)
@@ -117,13 +117,13 @@ int git_attr_file__load(
        git_tree *tree = NULL;
        git_tree_entry *tree_entry = NULL;
        git_blob *blob = NULL;
-       git_buf content = GIT_BUF_INIT;
+       git_str content = GIT_STR_INIT;
        const char *content_str;
        git_attr_file *file;
        struct stat st;
        bool nonexistent = false;
        int bom_offset;
-       git_buf_bom_t bom;
+       git_str_bom_t bom;
        git_oid id;
        git_object_size_t blobsize;
 
@@ -143,7 +143,7 @@ int git_attr_file__load(
                blobsize = git_blob_rawsize(blob);
 
                GIT_ERROR_CHECK_BLOBSIZE(blobsize);
-               git_buf_put(&content, git_blob_rawcontent(blob), (size_t)blobsize);
+               git_str_put(&content, git_blob_rawcontent(blob), (size_t)blobsize);
                break;
        }
        case GIT_ATTR_FILE_SOURCE_FILE: {
@@ -198,7 +198,7 @@ int git_attr_file__load(
                blobsize = git_blob_rawsize(blob);
 
                GIT_ERROR_CHECK_BLOBSIZE(blobsize);
-               if ((error = git_buf_put(&content,
+               if ((error = git_str_put(&content,
                        git_blob_rawcontent(blob), (size_t)blobsize)) < 0)
                        goto cleanup;
 
@@ -213,10 +213,10 @@ int git_attr_file__load(
                goto cleanup;
 
        /* advance over a UTF8 BOM */
-       content_str = git_buf_cstr(&content);
-       bom_offset = git_buf_detect_bom(&bom, &content);
+       content_str = git_str_cstr(&content);
+       bom_offset = git_str_detect_bom(&bom, &content);
 
-       if (bom == GIT_BUF_BOM_UTF8)
+       if (bom == GIT_STR_BOM_UTF8)
                content_str += bom_offset;
 
        /* store the key of the attr_reader; don't bother with cache
@@ -250,7 +250,7 @@ cleanup:
        git_tree_entry_free(tree_entry);
        git_tree_free(tree);
        git_commit_free(commit);
-       git_buf_dispose(&content);
+       git_str_dispose(&content);
 
        return error;
 }
@@ -345,7 +345,7 @@ int git_attr_file__parse_buffer(
        int error = 0;
 
        /* If subdir file path, convert context for file paths */
-       if (attrs->entry && git_path_root(attrs->entry->path) < 0 &&
+       if (attrs->entry && git_fs_path_root(attrs->entry->path) < 0 &&
            !git__suffixcmp(attrs->entry->path, "/" GIT_ATTR_FILE))
                context = attrs->entry->path;
 
@@ -435,7 +435,7 @@ int git_attr_file__lookup_one(
 
 int git_attr_file__load_standalone(git_attr_file **out, const char *path)
 {
-       git_buf content = GIT_BUF_INIT;
+       git_str content = GIT_STR_INIT;
        git_attr_file_source source = { GIT_ATTR_FILE_SOURCE_FILE };
        git_attr_file *file = NULL;
        int error;
@@ -457,7 +457,7 @@ int git_attr_file__load_standalone(git_attr_file **out, const char *path)
 out:
        if (error < 0)
                git_attr_file__free(file);
-       git_buf_dispose(&content);
+       git_str_dispose(&content);
 
        return error;
 }
@@ -558,9 +558,9 @@ int git_attr_path__init(
        ssize_t root;
 
        /* build full path as best we can */
-       git_buf_init(&info->full, 0);
+       git_str_init(&info->full, 0);
 
-       if (git_path_join_unrooted(&info->full, path, base, &root) < 0)
+       if (git_fs_path_join_unrooted(&info->full, path, base, &root) < 0)
                return -1;
 
        info->path = info->full.ptr + root;
@@ -596,7 +596,7 @@ int git_attr_path__init(
 
        case GIT_DIR_FLAG_UNKNOWN:
        default:
-               info->is_dir = (int)git_path_isdir(info->full.ptr);
+               info->is_dir = (int)git_fs_path_isdir(info->full.ptr);
                break;
        }
 
@@ -605,7 +605,7 @@ int git_attr_path__init(
 
 void git_attr_path__free(git_attr_path *info)
 {
-       git_buf_dispose(&info->full);
+       git_str_dispose(&info->full);
        info->path = NULL;
        info->basename = NULL;
 }
@@ -1020,8 +1020,8 @@ void git_attr_session__free(git_attr_session *session)
        if (!session)
                return;
 
-       git_buf_dispose(&session->sysdir);
-       git_buf_dispose(&session->tmp);
+       git_str_dispose(&session->sysdir);
+       git_str_dispose(&session->tmp);
 
        memset(session, 0, sizeof(git_attr_session));
 }
index d634e6da948498731f8534711ca30338a2df645e..08630d1a6eb427134f65a68a850d8ed4882f3d24 100644 (file)
@@ -13,7 +13,7 @@
 #include "git2/attr.h"
 #include "vector.h"
 #include "pool.h"
-#include "buffer.h"
+#include "str.h"
 #include "futils.h"
 
 #define GIT_ATTR_FILE                  ".gitattributes"
@@ -118,7 +118,7 @@ struct git_attr_file_entry {
 };
 
 typedef struct {
-       git_buf  full;
+       git_str  full;
        char    *path;
        char    *basename;
        int      is_dir;
@@ -132,8 +132,8 @@ typedef struct {
        int key;
        unsigned int init_setup:1,
                init_sysdir:1;
-       git_buf sysdir;
-       git_buf tmp;
+       git_str sysdir;
+       git_str tmp;
 } git_attr_session;
 
 extern int git_attr_session__init(git_attr_session *attr_session, git_repository *repo);
index 2b36b7a9c98d2aac755f54fc39c2e7039be8b3ff..b16d95c3c02bec9982adebecb4e5f38e0202d439 100644 (file)
@@ -12,6 +12,7 @@
 #include "config.h"
 #include "sysdir.h"
 #include "ignore.h"
+#include "path.h"
 
 GIT_INLINE(int) attr_cache_lock(git_attr_cache *cache)
 {
@@ -43,11 +44,12 @@ int git_attr_cache__alloc_file_entry(
        const char *path,
        git_pool *pool)
 {
+       git_str fullpath_str = GIT_STR_INIT;
        size_t baselen = 0, pathlen = strlen(path);
        size_t cachesize = sizeof(git_attr_file_entry) + pathlen + 1;
        git_attr_file_entry *ce;
 
-       if (base != NULL && git_path_root(path) < 0) {
+       if (base != NULL && git_fs_path_root(path) < 0) {
                baselen = strlen(base);
                cachesize += baselen;
 
@@ -66,7 +68,10 @@ int git_attr_cache__alloc_file_entry(
        }
        memcpy(&ce->fullpath[baselen], path, pathlen);
 
-       if (git_path_validate_workdir_with_len(repo, ce->fullpath, pathlen + baselen) < 0)
+       fullpath_str.ptr = ce->fullpath;
+       fullpath_str.size = pathlen + baselen;
+
+       if (git_path_validate_str_length(repo, &fullpath_str) < 0)
                return -1;
 
        ce->path = &ce->fullpath[baselen];
@@ -161,7 +166,7 @@ static int attr_cache_lookup(
        git_attr_file_source *source)
 {
        int error = 0;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        const char *wd = git_repository_workdir(repo);
        const char *filename;
        git_attr_cache *cache = git_repository_attr_cache(repo);
@@ -169,11 +174,11 @@ static int attr_cache_lookup(
        git_attr_file *file = NULL;
 
        /* join base and path as needed */
-       if (source->base != NULL && git_path_root(source->filename) < 0) {
-               git_buf *p = attr_session ? &attr_session->tmp : &path;
+       if (source->base != NULL && git_fs_path_root(source->filename) < 0) {
+               git_str *p = attr_session ? &attr_session->tmp : &path;
 
-               if (git_buf_joinpath(p, source->base, source->filename) < 0 ||
-                   git_path_validate_workdir_buf(repo, p) < 0)
+               if (git_str_joinpath(p, source->base, source->filename) < 0 ||
+                   git_path_validate_str_length(repo, p) < 0)
                        return -1;
 
                filename = p->ptr;
@@ -203,7 +208,7 @@ cleanup:
        *out_file  = file;
        *out_entry = entry;
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        return error;
 }
 
@@ -281,7 +286,7 @@ bool git_attr_cache__is_cached(
 static int attr_cache__lookup_path(
        char **out, git_config *cfg, const char *key, const char *fallback)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        int error;
        git_config_entry *entry = NULL;
 
@@ -296,17 +301,17 @@ static int attr_cache__lookup_path(
                /* expand leading ~/ as needed */
                if (cfgval && cfgval[0] == '~' && cfgval[1] == '/') {
                        if (! (error = git_sysdir_expand_global_file(&buf, &cfgval[2])))
-                               *out = git_buf_detach(&buf);
+                               *out = git_str_detach(&buf);
                } else if (cfgval) {
                        *out = git__strdup(cfgval);
                }
        }
        else if (!git_sysdir_find_xdg_file(&buf, fallback)) {
-               *out = git_buf_detach(&buf);
+               *out = git_str_detach(&buf);
        }
 
        git_config_entry_free(entry);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        return error;
 }
index 3d514a1bc0f4de760db084d5e4a08d9d08898e36..2504b338ac595fcf04b361dfceac5587536dcdca 100644 (file)
@@ -393,7 +393,7 @@ static void fill_origin_blob(git_blame__origin *o, mmfile_t *file)
        memset(file, 0, sizeof(*file));
        if (o->blob) {
                file->ptr = (char*)git_blob_rawcontent(o->blob);
-               file->size = (size_t)git_blob_rawsize(o->blob);
+               file->size = (long)git_blob_rawsize(o->blob);
        }
 }
 
index 09b5b5d9121a300fad5bf82aa6a6e701001063f1..19ce8b3b50b2e4839eac864acf840c2ecc397c0c 100644 (file)
@@ -12,6 +12,7 @@
 #include "git2/repository.h"
 #include "git2/odb_backend.h"
 
+#include "buf.h"
 #include "filebuf.h"
 #include "filter.h"
 
@@ -35,12 +36,12 @@ git_object_size_t git_blob_rawsize(const git_blob *blob)
                return (git_object_size_t)git_odb_object_size(blob->data.odb);
 }
 
-int git_blob__getbuf(git_buf *buffer, git_blob *blob)
+int git_blob__getbuf(git_str *buffer, git_blob *blob)
 {
        git_object_size_t size = git_blob_rawsize(blob);
 
        GIT_ERROR_CHECK_BLOBSIZE(size);
-       return git_buf_set(buffer, git_blob_rawcontent(blob), (size_t)size);
+       return git_str_set(buffer, git_blob_rawcontent(blob), (size_t)size);
 }
 
 void git_blob__free(void *_blob)
@@ -142,9 +143,9 @@ static int write_file_filtered(
        git_repository* repo)
 {
        int error;
-       git_buf tgt = GIT_BUF_INIT;
+       git_str tgt = GIT_STR_INIT;
 
-       error = git_filter_list_apply_to_file(&tgt, fl, repo, full_path);
+       error = git_filter_list__apply_to_file(&tgt, fl, repo, full_path);
 
        /* Write the file to disk if it was properly filtered */
        if (!error) {
@@ -153,7 +154,7 @@ static int write_file_filtered(
                error = git_odb_write(id, odb, tgt.ptr, tgt.size, GIT_OBJECT_BLOB);
        }
 
-       git_buf_dispose(&tgt);
+       git_str_dispose(&tgt);
        return error;
 }
 
@@ -193,7 +194,7 @@ int git_blob__create_from_paths(
        git_odb *odb = NULL;
        git_object_size_t size;
        mode_t mode;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        GIT_ASSERT_ARG(hint_path || !try_load_filters);
 
@@ -204,7 +205,7 @@ int git_blob__create_from_paths(
                content_path = path.ptr;
        }
 
-       if ((error = git_path_lstat(content_path, &st)) < 0 ||
+       if ((error = git_fs_path_lstat(content_path, &st)) < 0 ||
                (error = git_repository_odb(&odb, repo)) < 0)
                goto done;
 
@@ -261,7 +262,7 @@ int git_blob__create_from_paths(
 
 done:
        git_odb_free(odb);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return error;
 }
@@ -276,11 +277,11 @@ int git_blob_create_from_disk(
        git_oid *id, git_repository *repo, const char *path)
 {
        int error;
-       git_buf full_path = GIT_BUF_INIT;
+       git_str full_path = GIT_STR_INIT;
        const char *workdir, *hintpath = NULL;
 
-       if ((error = git_path_prettify(&full_path, path, NULL)) < 0) {
-               git_buf_dispose(&full_path);
+       if ((error = git_fs_path_prettify(&full_path, path, NULL)) < 0) {
+               git_str_dispose(&full_path);
                return error;
        }
 
@@ -290,9 +291,9 @@ int git_blob_create_from_disk(
                hintpath = full_path.ptr + strlen(workdir);
 
        error = git_blob__create_from_paths(
-               id, NULL, repo, git_buf_cstr(&full_path), hintpath, 0, !!hintpath);
+               id, NULL, repo, git_str_cstr(&full_path), hintpath, 0, !!hintpath);
 
-       git_buf_dispose(&full_path);
+       git_str_dispose(&full_path);
        return error;
 }
 
@@ -330,7 +331,7 @@ static int blob_writestream_write(git_writestream *_stream, const char *buffer,
 int git_blob_create_from_stream(git_writestream **out, git_repository *repo, const char *hintpath)
 {
        int error;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        blob_writestream *stream;
 
        GIT_ASSERT_ARG(out);
@@ -349,11 +350,11 @@ int git_blob_create_from_stream(git_writestream **out, git_repository *repo, con
        stream->parent.close = blob_writestream_close;
        stream->parent.free  = blob_writestream_free;
 
-       if ((error = git_repository_item_path(&path, repo, GIT_REPOSITORY_ITEM_OBJECTS)) < 0
-               || (error = git_buf_joinpath(&path, path.ptr, "streamed")) < 0)
+       if ((error = git_repository__item_path(&path, repo, GIT_REPOSITORY_ITEM_OBJECTS)) < 0
+               || (error = git_str_joinpath(&path, path.ptr, "streamed")) < 0)
                goto cleanup;
 
-       if ((error = git_filebuf_open_withsize(&stream->fbuf, git_buf_cstr(&path), GIT_FILEBUF_TEMPORARY,
+       if ((error = git_filebuf_open_withsize(&stream->fbuf, git_str_cstr(&path), GIT_FILEBUF_TEMPORARY,
                                               0666, 2 * 1024 * 1024)) < 0)
                goto cleanup;
 
@@ -363,7 +364,7 @@ cleanup:
        if (error < 0)
                blob_writestream_free((git_writestream *) stream);
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        return error;
 }
 
@@ -391,16 +392,25 @@ cleanup:
 
 int git_blob_is_binary(const git_blob *blob)
 {
-       git_buf content = GIT_BUF_INIT;
+       git_str content = GIT_STR_INIT;
        git_object_size_t size;
 
        GIT_ASSERT_ARG(blob);
 
        size = git_blob_rawsize(blob);
 
-       git_buf_attach_notowned(&content, git_blob_rawcontent(blob),
+       git_str_attach_notowned(&content, git_blob_rawcontent(blob),
                (size_t)min(size, GIT_FILTER_BYTES_TO_CHECK_NUL));
-       return git_buf_is_binary(&content);
+       return git_str_is_binary(&content);
+}
+
+int git_blob_data_is_binary(const char *str, size_t len)
+{
+       git_str content = GIT_STR_INIT;
+
+       git_str_attach_notowned(&content, str, len);
+
+       return git_str_is_binary(&content);
 }
 
 int git_blob_filter_options_init(
@@ -418,10 +428,10 @@ int git_blob_filter(
        const char *path,
        git_blob_filter_options *given_opts)
 {
-       int error = 0;
-       git_filter_list *fl = NULL;
        git_blob_filter_options opts = GIT_BLOB_FILTER_OPTIONS_INIT;
        git_filter_options filter_opts = GIT_FILTER_OPTIONS_INIT;
+       git_filter_list *fl = NULL;
+       int error = 0;
 
        GIT_ASSERT_ARG(blob);
        GIT_ASSERT_ARG(path);
@@ -430,9 +440,6 @@ int git_blob_filter(
        GIT_ERROR_CHECK_VERSION(
                given_opts, GIT_BLOB_FILTER_OPTIONS_VERSION, "git_blob_filter_options");
 
-       if (git_buf_sanitize(out) < 0)
-               return -1;
-
        if (given_opts != NULL)
                memcpy(&opts, given_opts, sizeof(git_blob_filter_options));
 
index e5770991eb730b2b62101fd89617db2e24b0deb2..9a5dda2254e9580817c1d608a38ec7050e9665ee 100644 (file)
@@ -38,7 +38,7 @@ struct git_blob {
 void git_blob__free(void *blob);
 int git_blob__parse(void *blob, git_odb_object *obj);
 int git_blob__parse_raw(void *blob, const char *data, size_t size);
-int git_blob__getbuf(git_buf *buffer, git_blob *blob);
+int git_blob__getbuf(git_str *buffer, git_blob *blob);
 
 extern int git_blob__create_from_paths(
        git_oid *out_oid,
index e6818a86df5ba162c08a7947348f5629f03a7fa4..2e29af99dd27fb3ff6ba8fa1b9fed089c8de0d14 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "branch.h"
 
+#include "buf.h"
 #include "commit.h"
 #include "tag.h"
 #include "config.h"
@@ -27,11 +28,11 @@ static int retrieve_branch_reference(
        git_reference *branch = NULL;
        int error = 0;
        char *prefix;
-       git_buf ref_name = GIT_BUF_INIT;
+       git_str ref_name = GIT_STR_INIT;
 
        prefix = is_remote ? GIT_REFS_REMOTES_DIR : GIT_REFS_HEADS_DIR;
 
-       if ((error = git_buf_joinpath(&ref_name, prefix, branch_name)) < 0)
+       if ((error = git_str_joinpath(&ref_name, prefix, branch_name)) < 0)
                /* OOM */;
        else if ((error = git_reference_lookup(&branch, repo, ref_name.ptr)) < 0)
                git_error_set(
@@ -40,7 +41,7 @@ static int retrieve_branch_reference(
 
        *branch_reference_out = branch; /* will be NULL on error */
 
-       git_buf_dispose(&ref_name);
+       git_str_dispose(&ref_name);
        return error;
 }
 
@@ -62,8 +63,8 @@ static int create_branch(
 {
        int is_unmovable_head = 0;
        git_reference *branch = NULL;
-       git_buf canonical_branch_name = GIT_BUF_INIT,
-                         log_message = GIT_BUF_INIT;
+       git_str canonical_branch_name = GIT_STR_INIT,
+                         log_message = GIT_STR_INIT;
        int error = -1;
        int bare = git_repository_is_bare(repository);
 
@@ -96,22 +97,22 @@ static int create_branch(
                goto cleanup;
        }
 
-       if (git_buf_joinpath(&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name) < 0)
+       if (git_str_joinpath(&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name) < 0)
                goto cleanup;
 
-       if (git_buf_printf(&log_message, "branch: Created from %s", from) < 0)
+       if (git_str_printf(&log_message, "branch: Created from %s", from) < 0)
                goto cleanup;
 
        error = git_reference_create(&branch, repository,
-               git_buf_cstr(&canonical_branch_name), git_commit_id(commit), force,
-               git_buf_cstr(&log_message));
+               git_str_cstr(&canonical_branch_name), git_commit_id(commit), force,
+               git_str_cstr(&log_message));
 
        if (!error)
                *ref_out = branch;
 
 cleanup:
-       git_buf_dispose(&canonical_branch_name);
-       git_buf_dispose(&log_message);
+       git_str_dispose(&canonical_branch_name);
+       git_str_dispose(&log_message);
        return error;
 }
 
@@ -122,7 +123,10 @@ int git_branch_create(
        const git_commit *commit,
        int force)
 {
-       return create_branch(ref_out, repository, branch_name, commit, git_oid_tostr_s(git_commit_id(commit)), force);
+       char commit_id[GIT_OID_HEXSZ + 1];
+
+       git_oid_tostr(commit_id, GIT_OID_HEXSZ + 1, git_commit_id(commit));
+       return create_branch(ref_out, repository, branch_name, commit, commit_id, force);
 }
 
 int git_branch_create_from_annotated(
@@ -174,7 +178,7 @@ int git_branch_is_checked_out(const git_reference *branch)
 int git_branch_delete(git_reference *branch)
 {
        int is_head;
-       git_buf config_section = GIT_BUF_INIT;
+       git_str config_section = GIT_STR_INIT;
        int error = -1;
 
        GIT_ASSERT_ARG(branch);
@@ -200,18 +204,18 @@ int git_branch_delete(git_reference *branch)
                return -1;
        }
 
-       if (git_buf_join(&config_section, '.', "branch",
+       if (git_str_join(&config_section, '.', "branch",
                        git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR)) < 0)
                goto on_error;
 
        if (git_config_rename_section(
-               git_reference_owner(branch), git_buf_cstr(&config_section), NULL) < 0)
+               git_reference_owner(branch), git_str_cstr(&config_section), NULL) < 0)
                goto on_error;
 
        error = git_reference_delete(branch);
 
 on_error:
-       git_buf_dispose(&config_section);
+       git_str_dispose(&config_section);
        return error;
 }
 
@@ -286,10 +290,10 @@ int git_branch_move(
        const char *new_branch_name,
        int force)
 {
-       git_buf new_reference_name = GIT_BUF_INIT,
-               old_config_section = GIT_BUF_INIT,
-               new_config_section = GIT_BUF_INIT,
-               log_message = GIT_BUF_INIT;
+       git_str new_reference_name = GIT_STR_INIT,
+               old_config_section = GIT_STR_INIT,
+               new_config_section = GIT_STR_INIT,
+               log_message = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(branch);
@@ -298,35 +302,35 @@ int git_branch_move(
        if (!git_reference_is_branch(branch))
                return not_a_local_branch(git_reference_name(branch));
 
-       if ((error = git_buf_joinpath(&new_reference_name, GIT_REFS_HEADS_DIR, new_branch_name)) < 0)
+       if ((error = git_str_joinpath(&new_reference_name, GIT_REFS_HEADS_DIR, new_branch_name)) < 0)
                goto done;
 
-       if ((error = git_buf_printf(&log_message, "branch: renamed %s to %s",
-                                   git_reference_name(branch), git_buf_cstr(&new_reference_name))) < 0)
+       if ((error = git_str_printf(&log_message, "branch: renamed %s to %s",
+                                   git_reference_name(branch), git_str_cstr(&new_reference_name))) < 0)
                        goto done;
 
        /* first update ref then config so failure won't trash config */
 
        error = git_reference_rename(
-               out, branch, git_buf_cstr(&new_reference_name), force,
-               git_buf_cstr(&log_message));
+               out, branch, git_str_cstr(&new_reference_name), force,
+               git_str_cstr(&log_message));
        if (error < 0)
                goto done;
 
-       git_buf_join(&old_config_section, '.', "branch",
+       git_str_join(&old_config_section, '.', "branch",
                git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR));
-       git_buf_join(&new_config_section, '.', "branch", new_branch_name);
+       git_str_join(&new_config_section, '.', "branch", new_branch_name);
 
        error = git_config_rename_section(
                git_reference_owner(branch),
-               git_buf_cstr(&old_config_section),
-               git_buf_cstr(&new_config_section));
+               git_str_cstr(&old_config_section),
+               git_str_cstr(&new_config_section));
 
 done:
-       git_buf_dispose(&new_reference_name);
-       git_buf_dispose(&old_config_section);
-       git_buf_dispose(&new_config_section);
-       git_buf_dispose(&log_message);
+       git_str_dispose(&new_reference_name);
+       git_str_dispose(&old_config_section);
+       git_str_dispose(&new_config_section);
+       git_str_dispose(&log_message);
 
        return error;
 }
@@ -384,20 +388,20 @@ int git_branch_name(
 }
 
 static int retrieve_upstream_configuration(
-       git_buf *out,
+       git_str *out,
        const git_config *config,
        const char *canonical_branch_name,
        const char *format)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        int error;
 
-       if (git_buf_printf(&buf, format,
+       if (git_str_printf(&buf, format,
                canonical_branch_name + strlen(GIT_REFS_HEADS_DIR)) < 0)
                        return -1;
 
-       error = git_config_get_string_buf(out, config, git_buf_cstr(&buf));
-       git_buf_dispose(&buf);
+       error = git_config__get_string_buf(out, config, git_str_cstr(&buf));
+       git_str_dispose(&buf);
        return error;
 }
 
@@ -406,20 +410,26 @@ int git_branch_upstream_name(
        git_repository *repo,
        const char *refname)
 {
-       git_buf remote_name = GIT_BUF_INIT;
-       git_buf merge_name = GIT_BUF_INIT;
-       git_buf buf = GIT_BUF_INIT;
+       GIT_BUF_WRAP_PRIVATE(out, git_branch__upstream_name, repo, refname);
+}
+
+int git_branch__upstream_name(
+       git_str *out,
+       git_repository *repo,
+       const char *refname)
+{
+       git_str remote_name = GIT_STR_INIT;
+       git_str merge_name = GIT_STR_INIT;
+       git_str buf = GIT_STR_INIT;
        int error = -1;
        git_remote *remote = NULL;
        const git_refspec *refspec;
        git_config *config;
 
        GIT_ASSERT_ARG(out);
+       GIT_ASSERT_ARG(repo);
        GIT_ASSERT_ARG(refname);
 
-       if ((error = git_buf_sanitize(out)) < 0)
-               return error;
-
        if (!git_reference__is_branch(refname))
                return not_a_local_branch(refname);
 
@@ -434,75 +444,109 @@ int git_branch_upstream_name(
                &merge_name, config, refname, "branch.%s.merge")) < 0)
                        goto cleanup;
 
-       if (git_buf_len(&remote_name) == 0 || git_buf_len(&merge_name) == 0) {
+       if (git_str_len(&remote_name) == 0 || git_str_len(&merge_name) == 0) {
                git_error_set(GIT_ERROR_REFERENCE,
                        "branch '%s' does not have an upstream", refname);
                error = GIT_ENOTFOUND;
                goto cleanup;
        }
 
-       if (strcmp(".", git_buf_cstr(&remote_name)) != 0) {
-               if ((error = git_remote_lookup(&remote, repo, git_buf_cstr(&remote_name))) < 0)
+       if (strcmp(".", git_str_cstr(&remote_name)) != 0) {
+               if ((error = git_remote_lookup(&remote, repo, git_str_cstr(&remote_name))) < 0)
                        goto cleanup;
 
-               refspec = git_remote__matching_refspec(remote, git_buf_cstr(&merge_name));
+               refspec = git_remote__matching_refspec(remote, git_str_cstr(&merge_name));
                if (!refspec) {
                        error = GIT_ENOTFOUND;
                        goto cleanup;
                }
 
-               if (git_refspec_transform(&buf, refspec, git_buf_cstr(&merge_name)) < 0)
+               if (git_refspec__transform(&buf, refspec, git_str_cstr(&merge_name)) < 0)
                        goto cleanup;
        } else
-               if (git_buf_set(&buf, git_buf_cstr(&merge_name), git_buf_len(&merge_name)) < 0)
+               if (git_str_set(&buf, git_str_cstr(&merge_name), git_str_len(&merge_name)) < 0)
                        goto cleanup;
 
-       error = git_buf_set(out, git_buf_cstr(&buf), git_buf_len(&buf));
+       git_str_swap(out, &buf);
 
 cleanup:
        git_config_free(config);
        git_remote_free(remote);
-       git_buf_dispose(&remote_name);
-       git_buf_dispose(&merge_name);
-       git_buf_dispose(&buf);
+       git_str_dispose(&remote_name);
+       git_str_dispose(&merge_name);
+       git_str_dispose(&buf);
        return error;
 }
 
-static int git_branch_upstream_with_format(git_buf *buf, git_repository *repo, const char *refname, const char *format, const char *format_name)
+static int git_branch_upstream_with_format(
+       git_str *out,
+       git_repository *repo,
+       const char *refname,
+       const char *format,
+       const char *format_name)
 {
-       int error;
        git_config *cfg;
+       int error;
 
        if (!git_reference__is_branch(refname))
                return not_a_local_branch(refname);
 
-       if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
+       if ((error = git_repository_config__weakptr(&cfg, repo)) < 0 ||
+           (error = retrieve_upstream_configuration(out, cfg, refname, format)) < 0)
                return error;
 
-       if ((error = git_buf_sanitize(buf)) < 0 ||
-           (error = retrieve_upstream_configuration(buf, cfg, refname, format)) < 0)
-               return error;
-
-       if (git_buf_len(buf) == 0) {
+       if (git_str_len(out) == 0) {
                git_error_set(GIT_ERROR_REFERENCE, "branch '%s' does not have an upstream %s", refname, format_name);
                error = GIT_ENOTFOUND;
-               git_buf_clear(buf);
        }
 
        return error;
 }
 
-int git_branch_upstream_remote(git_buf *buf, git_repository *repo, const char *refname)
+int git_branch_upstream_remote(
+       git_buf *out,
+       git_repository *repo,
+       const char *refname)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_branch__upstream_remote, repo, refname);
+}
+
+int git_branch__upstream_remote(
+       git_str *out,
+       git_repository *repo,
+       const char *refname)
 {
-       return git_branch_upstream_with_format(buf, repo, refname, "branch.%s.remote", "remote");
+       return git_branch_upstream_with_format(out, repo, refname, "branch.%s.remote", "remote");
 }
 
-int git_branch_upstream_merge(git_buf *buf, git_repository *repo, const char *refname)
+int git_branch_upstream_merge(
+       git_buf *out,
+       git_repository *repo,
+       const char *refname)
 {
-       return git_branch_upstream_with_format(buf, repo, refname, "branch.%s.merge", "merge");
+       GIT_BUF_WRAP_PRIVATE(out, git_branch__upstream_merge, repo, refname);
 }
 
-int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refname)
+int git_branch__upstream_merge(
+       git_str *out,
+       git_repository *repo,
+       const char *refname)
+{
+       return git_branch_upstream_with_format(out, repo, refname, "branch.%s.merge", "merge");
+}
+
+int git_branch_remote_name(
+       git_buf *out,
+       git_repository *repo,
+       const char *refname)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_branch__remote_name, repo, refname);
+}
+
+int git_branch__remote_name(
+       git_str *out,
+       git_repository *repo,
+       const char *refname)
 {
        git_strarray remote_list = {0};
        size_t i;
@@ -511,13 +555,10 @@ int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refna
        int error = 0;
        char *remote_name = NULL;
 
-       GIT_ASSERT_ARG(buf);
+       GIT_ASSERT_ARG(out);
        GIT_ASSERT_ARG(repo);
        GIT_ASSERT_ARG(refname);
 
-       if ((error = git_buf_sanitize(buf)) < 0)
-               return error;
-
        /* Verify that this is a remote branch */
        if (!git_reference__is_remote(refname)) {
                git_error_set(GIT_ERROR_INVALID, "reference '%s' is not a remote branch.",
@@ -557,8 +598,8 @@ int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refna
        }
 
        if (remote_name) {
-               git_buf_clear(buf);
-               error = git_buf_puts(buf, remote_name);
+               git_str_clear(out);
+               error = git_str_puts(out, remote_name);
        } else {
                git_error_set(GIT_ERROR_REFERENCE,
                        "could not determine remote for '%s'", refname);
@@ -567,7 +608,7 @@ int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refna
 
 cleanup:
        if (error < 0)
-               git_buf_dispose(buf);
+               git_str_dispose(out);
 
        git_strarray_dispose(&remote_list);
        return error;
@@ -578,49 +619,49 @@ int git_branch_upstream(
        const git_reference *branch)
 {
        int error;
-       git_buf tracking_name = GIT_BUF_INIT;
+       git_str tracking_name = GIT_STR_INIT;
 
-       if ((error = git_branch_upstream_name(&tracking_name,
+       if ((error = git_branch__upstream_name(&tracking_name,
                git_reference_owner(branch), git_reference_name(branch))) < 0)
                        return error;
 
        error = git_reference_lookup(
                tracking_out,
                git_reference_owner(branch),
-               git_buf_cstr(&tracking_name));
+               git_str_cstr(&tracking_name));
 
-       git_buf_dispose(&tracking_name);
+       git_str_dispose(&tracking_name);
        return error;
 }
 
 static int unset_upstream(git_config *config, const char *shortname)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
-       if (git_buf_printf(&buf, "branch.%s.remote", shortname) < 0)
+       if (git_str_printf(&buf, "branch.%s.remote", shortname) < 0)
                return -1;
 
-       if (git_config_delete_entry(config, git_buf_cstr(&buf)) < 0)
+       if (git_config_delete_entry(config, git_str_cstr(&buf)) < 0)
                goto on_error;
 
-       git_buf_clear(&buf);
-       if (git_buf_printf(&buf, "branch.%s.merge", shortname) < 0)
+       git_str_clear(&buf);
+       if (git_str_printf(&buf, "branch.%s.merge", shortname) < 0)
                goto on_error;
 
-       if (git_config_delete_entry(config, git_buf_cstr(&buf)) < 0)
+       if (git_config_delete_entry(config, git_str_cstr(&buf)) < 0)
                goto on_error;
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return 0;
 
 on_error:
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return -1;
 }
 
 int git_branch_set_upstream(git_reference *branch, const char *branch_name)
 {
-       git_buf key = GIT_BUF_INIT, remote_name = GIT_BUF_INIT, merge_refspec = GIT_BUF_INIT;
+       git_str key = GIT_STR_INIT, remote_name = GIT_STR_INIT, merge_refspec = GIT_STR_INIT;
        git_reference *upstream;
        git_repository *repo;
        git_remote *remote = NULL;
@@ -662,31 +703,31 @@ int git_branch_set_upstream(git_reference *branch, const char *branch_name)
         * name on the remote is and use that.
         */
        if (local)
-               error = git_buf_puts(&remote_name, ".");
+               error = git_str_puts(&remote_name, ".");
        else
-               error = git_branch_remote_name(&remote_name, repo, git_reference_name(upstream));
+               error = git_branch__remote_name(&remote_name, repo, git_reference_name(upstream));
 
        if (error < 0)
                goto on_error;
 
-       /* Update the upsteam branch config with the new name */
-       if (git_buf_printf(&key, "branch.%s.remote", shortname) < 0)
+       /* Update the upstream branch config with the new name */
+       if (git_str_printf(&key, "branch.%s.remote", shortname) < 0)
                goto on_error;
 
-       if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&remote_name)) < 0)
+       if (git_config_set_string(config, git_str_cstr(&key), git_str_cstr(&remote_name)) < 0)
                goto on_error;
 
        if (local) {
                /* A local branch uses the upstream refname directly */
-               if (git_buf_puts(&merge_refspec, git_reference_name(upstream)) < 0)
+               if (git_str_puts(&merge_refspec, git_reference_name(upstream)) < 0)
                        goto on_error;
        } else {
                /* We transform the upstream branch name according to the remote's refspecs */
-               if (git_remote_lookup(&remote, repo, git_buf_cstr(&remote_name)) < 0)
+               if (git_remote_lookup(&remote, repo, git_str_cstr(&remote_name)) < 0)
                        goto on_error;
 
                fetchspec = git_remote__matching_dst_refspec(remote, git_reference_name(upstream));
-               if (!fetchspec || git_refspec_rtransform(&merge_refspec, fetchspec, git_reference_name(upstream)) < 0)
+               if (!fetchspec || git_refspec__rtransform(&merge_refspec, fetchspec, git_reference_name(upstream)) < 0)
                        goto on_error;
 
                git_remote_free(remote);
@@ -694,25 +735,25 @@ int git_branch_set_upstream(git_reference *branch, const char *branch_name)
        }
 
        /* Update the merge branch config with the refspec */
-       git_buf_clear(&key);
-       if (git_buf_printf(&key, "branch.%s.merge", shortname) < 0)
+       git_str_clear(&key);
+       if (git_str_printf(&key, "branch.%s.merge", shortname) < 0)
                goto on_error;
 
-       if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&merge_refspec)) < 0)
+       if (git_config_set_string(config, git_str_cstr(&key), git_str_cstr(&merge_refspec)) < 0)
                goto on_error;
 
        git_reference_free(upstream);
-       git_buf_dispose(&key);
-       git_buf_dispose(&remote_name);
-       git_buf_dispose(&merge_refspec);
+       git_str_dispose(&key);
+       git_str_dispose(&remote_name);
+       git_str_dispose(&merge_refspec);
 
        return 0;
 
 on_error:
        git_reference_free(upstream);
-       git_buf_dispose(&key);
-       git_buf_dispose(&remote_name);
-       git_buf_dispose(&merge_refspec);
+       git_str_dispose(&key);
+       git_str_dispose(&remote_name);
+       git_str_dispose(&merge_refspec);
        git_remote_free(remote);
 
        return -1;
@@ -749,7 +790,7 @@ int git_branch_is_head(
 
 int git_branch_name_is_valid(int *valid, const char *name)
 {
-       git_buf ref_name = GIT_BUF_INIT;
+       git_str ref_name = GIT_STR_INIT;
        int error = 0;
 
        GIT_ASSERT(valid);
@@ -765,13 +806,13 @@ int git_branch_name_is_valid(int *valid, const char *name)
        if (!name || name[0] == '-' || !git__strcmp(name, "HEAD"))
                goto done;
 
-       if ((error = git_buf_puts(&ref_name, GIT_REFS_HEADS_DIR)) < 0 ||
-           (error = git_buf_puts(&ref_name, name)) < 0)
+       if ((error = git_str_puts(&ref_name, GIT_REFS_HEADS_DIR)) < 0 ||
+           (error = git_str_puts(&ref_name, name)) < 0)
                goto done;
 
        error = git_reference_name_is_valid(valid, ref_name.ptr);
 
 done:
-       git_buf_dispose(&ref_name);
+       git_str_dispose(&ref_name);
        return error;
 }
index 5ae227c05aa14f483bc229ba21ba04ee34db30f9..b4db42a0137300aa63c402d0e368c0e3a37c8a90 100644 (file)
@@ -9,10 +9,22 @@
 
 #include "common.h"
 
-#include "buffer.h"
+#include "str.h"
 
-int git_branch_upstream__name(
-       git_buf *tracking_name,
+int git_branch__remote_name(
+       git_str *out,
+       git_repository *repo,
+       const char *refname);
+int git_branch__upstream_remote(
+       git_str *out,
+       git_repository *repo,
+       const char *refname);
+int git_branch__upstream_merge(
+       git_str *out,
+       git_repository *repo,
+       const char *refname);
+int git_branch__upstream_name(
+       git_str *tracking_name,
        git_repository *repo,
        const char *canonical_branch_name);
 
diff --git a/src/buf.c b/src/buf.c
new file mode 100644 (file)
index 0000000..652f5dd
--- /dev/null
+++ b/src/buf.c
@@ -0,0 +1,126 @@
+/*
+ * 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 "buf.h"
+#include "common.h"
+
+int git_buf_sanitize(git_buf *buf)
+{
+       GIT_ASSERT_ARG(buf);
+
+       if (buf->reserved > 0)
+               buf->ptr[0] = '\0';
+       else
+               buf->ptr = git_str__initstr;
+
+       buf->size = 0;
+       return 0;
+}
+
+int git_buf_tostr(git_str *out, git_buf *buf)
+{
+       GIT_ASSERT_ARG(out);
+       GIT_ASSERT_ARG(buf);
+
+       if (git_buf_sanitize(buf) < 0)
+               return -1;
+
+       out->ptr = buf->ptr;
+       out->asize = buf->reserved;
+       out->size = buf->size;
+
+       buf->ptr = git_str__initstr;
+       buf->reserved = 0;
+       buf->size = 0;
+
+       return 0;
+}
+
+int git_buf_fromstr(git_buf *out, git_str *str)
+{
+       GIT_ASSERT_ARG(out);
+       GIT_ASSERT_ARG(str);
+
+       out->ptr = str->ptr;
+       out->reserved = str->asize;
+       out->size = str->size;
+
+       str->ptr = git_str__initstr;
+       str->asize = 0;
+       str->size = 0;
+
+       return 0;
+}
+
+void git_buf_dispose(git_buf *buf)
+{
+       if (!buf)
+               return;
+
+       if (buf->ptr != git_str__initstr)
+               git__free(buf->ptr);
+
+       buf->ptr = git_str__initstr;
+       buf->reserved = 0;
+       buf->size = 0;
+}
+
+#ifndef GIT_DEPRECATE_HARD
+int git_buf_grow(git_buf *buffer, size_t target_size)
+{
+       char *newptr;
+
+       if (buffer->reserved >= target_size)
+               return 0;
+
+       if (buffer->ptr == git_str__initstr)
+               newptr = git__malloc(target_size);
+       else
+               newptr = git__realloc(buffer->ptr, target_size);
+
+       if (!newptr)
+               return -1;
+
+       buffer->ptr = newptr;
+       buffer->reserved = target_size;
+       return 0;
+}
+
+int git_buf_set(git_buf *buffer, const void *data, size_t datalen)
+{
+       size_t alloclen;
+
+       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, datalen, 1);
+
+       if (git_buf_grow(buffer, alloclen) < 0)
+               return -1;
+
+       memmove(buffer->ptr, data, datalen);
+       buffer->size = datalen;
+       buffer->ptr[buffer->size] = '\0';
+
+       return 0;
+}
+
+int git_buf_is_binary(const git_buf *buf)
+{
+       git_str str = GIT_STR_INIT_CONST(buf->ptr, buf->size);
+       return git_str_is_binary(&str);
+}
+
+int git_buf_contains_nul(const git_buf *buf)
+{
+       git_str str = GIT_STR_INIT_CONST(buf->ptr, buf->size);
+       return git_str_contains_nul(&str);
+}
+
+void git_buf_free(git_buf *buffer)
+{
+       git_buf_dispose(buffer);
+}
+
+#endif
diff --git a/src/buf.h b/src/buf.h
new file mode 100644 (file)
index 0000000..4bc7f27
--- /dev/null
+++ b/src/buf.h
@@ -0,0 +1,50 @@
+/*
+ * 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_buf_h__
+#define INCLUDE_buf_h__
+
+#include "git2/buffer.h"
+#include "common.h"
+
+/*
+ * Adapts a private API that takes a `git_str` into a public API that
+ * takes a `git_buf`.
+ */
+
+#define GIT_BUF_WRAP_PRIVATE(buf, fn, ...) \
+  { \
+       git_str str = GIT_STR_INIT; \
+       int error; \
+       if ((error = git_buf_tostr(&str, buf)) == 0 && \
+           (error = fn(&str, __VA_ARGS__)) == 0) \
+               error = git_buf_fromstr(buf, &str); \
+       git_str_dispose(&str); \
+       return error; \
+}
+
+/**
+ * "Sanitizes" a buffer from user input.  This simply ensures that the
+ * `git_buf` has nice defaults if the user didn't set the members to
+ * anything, so that if we return early we don't leave it populated
+ * with nonsense.
+ */
+extern int git_buf_sanitize(git_buf *from_user);
+
+/**
+ * Populate a `git_str` from a `git_buf` for passing to libgit2 internal
+ * functions.  Sanitizes the given `git_buf` before proceeding.  The
+ * `git_buf` will no longer point to this memory.
+ */
+extern int git_buf_tostr(git_str *out, git_buf *buf);
+
+/**
+ * Populate a `git_buf` from a `git_str` for returning to a user.
+ * The `git_str` will no longer point to this memory.
+ */
+extern int git_buf_fromstr(git_buf *out, git_str *str);
+
+#endif
diff --git a/src/buffer.c b/src/buffer.c
deleted file mode 100644 (file)
index fe087ea..0000000
+++ /dev/null
@@ -1,1366 +0,0 @@
-/*
- * 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 "buffer.h"
-#include "posix.h"
-#include "git2/buffer.h"
-#include <ctype.h>
-
-/* Used as default value for git_buf->ptr so that people can always
- * assume ptr is non-NULL and zero terminated even for new git_bufs.
- */
-char git_buf__initbuf[1];
-
-char git_buf__oom[1];
-
-#define ENSURE_SIZE(b, d) \
-       if ((b)->ptr == git_buf__oom || \
-           ((d) > (b)->asize && git_buf_grow((b), (d)) < 0))\
-               return -1;
-
-
-int git_buf_init(git_buf *buf, size_t initial_size)
-{
-       buf->asize = 0;
-       buf->size = 0;
-       buf->ptr = git_buf__initbuf;
-
-       ENSURE_SIZE(buf, initial_size);
-
-       return 0;
-}
-
-int git_buf_try_grow(
-       git_buf *buf, size_t target_size, bool mark_oom)
-{
-       char *new_ptr;
-       size_t new_size;
-
-       if (buf->ptr == git_buf__oom)
-               return -1;
-
-       if (buf->asize == 0 && buf->size != 0) {
-               git_error_set(GIT_ERROR_INVALID, "cannot grow a borrowed buffer");
-               return GIT_EINVALID;
-       }
-
-       if (!target_size)
-               target_size = buf->size;
-
-       if (target_size <= buf->asize)
-               return 0;
-
-       if (buf->asize == 0) {
-               new_size = target_size;
-               new_ptr = NULL;
-       } else {
-               new_size = buf->asize;
-               /*
-                * Grow the allocated buffer by 1.5 to allow
-                * re-use of memory holes resulting from the
-                * realloc. If this is still too small, then just
-                * use the target size.
-                */
-               if ((new_size = (new_size << 1) - (new_size >> 1)) < target_size)
-                       new_size = target_size;
-               new_ptr = buf->ptr;
-       }
-
-       /* round allocation up to multiple of 8 */
-       new_size = (new_size + 7) & ~7;
-
-       if (new_size < buf->size) {
-               if (mark_oom) {
-                       if (buf->ptr && buf->ptr != git_buf__initbuf)
-                               git__free(buf->ptr);
-                       buf->ptr = git_buf__oom;
-               }
-
-               git_error_set_oom();
-               return -1;
-       }
-
-       new_ptr = git__realloc(new_ptr, new_size);
-
-       if (!new_ptr) {
-               if (mark_oom) {
-                       if (buf->ptr && (buf->ptr != git_buf__initbuf))
-                               git__free(buf->ptr);
-                       buf->ptr = git_buf__oom;
-               }
-               return -1;
-       }
-
-       buf->asize = new_size;
-       buf->ptr   = new_ptr;
-
-       /* truncate the existing buffer size if necessary */
-       if (buf->size >= buf->asize)
-               buf->size = buf->asize - 1;
-       buf->ptr[buf->size] = '\0';
-
-       return 0;
-}
-
-int git_buf_grow(git_buf *buffer, size_t target_size)
-{
-       return git_buf_try_grow(buffer, target_size, true);
-}
-
-int git_buf_grow_by(git_buf *buffer, size_t additional_size)
-{
-       size_t newsize;
-
-       if (GIT_ADD_SIZET_OVERFLOW(&newsize, buffer->size, additional_size)) {
-               buffer->ptr = git_buf__oom;
-               return -1;
-       }
-
-       return git_buf_try_grow(buffer, newsize, true);
-}
-
-void git_buf_dispose(git_buf *buf)
-{
-       if (!buf) return;
-
-       if (buf->asize > 0 && buf->ptr != NULL && buf->ptr != git_buf__oom)
-               git__free(buf->ptr);
-
-       git_buf_init(buf, 0);
-}
-
-#ifndef GIT_DEPRECATE_HARD
-void git_buf_free(git_buf *buf)
-{
-       git_buf_dispose(buf);
-}
-#endif
-
-int git_buf_sanitize(git_buf *buf)
-{
-       if (buf->ptr == NULL) {
-               GIT_ASSERT_ARG(buf->size == 0 && buf->asize == 0);
-
-               buf->ptr = git_buf__initbuf;
-       } else if (buf->asize > buf->size) {
-               buf->ptr[buf->size] = '\0';
-       }
-
-       return 0;
-}
-
-void git_buf_clear(git_buf *buf)
-{
-       buf->size = 0;
-
-       if (!buf->ptr) {
-               buf->ptr = git_buf__initbuf;
-               buf->asize = 0;
-       }
-
-       if (buf->asize > 0)
-               buf->ptr[0] = '\0';
-}
-
-int git_buf_set(git_buf *buf, const void *data, size_t len)
-{
-       size_t alloclen;
-
-       if (len == 0 || data == NULL) {
-               git_buf_clear(buf);
-       } else {
-               if (data != buf->ptr) {
-                       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, len, 1);
-                       ENSURE_SIZE(buf, alloclen);
-                       memmove(buf->ptr, data, len);
-               }
-
-               buf->size = len;
-               if (buf->asize > buf->size)
-                       buf->ptr[buf->size] = '\0';
-
-       }
-       return 0;
-}
-
-int git_buf_sets(git_buf *buf, const char *string)
-{
-       return git_buf_set(buf, string, string ? strlen(string) : 0);
-}
-
-int git_buf_putc(git_buf *buf, char c)
-{
-       size_t new_size;
-       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, 2);
-       ENSURE_SIZE(buf, new_size);
-       buf->ptr[buf->size++] = c;
-       buf->ptr[buf->size] = '\0';
-       return 0;
-}
-
-int git_buf_putcn(git_buf *buf, char c, size_t len)
-{
-       size_t new_size;
-       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, len);
-       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
-       ENSURE_SIZE(buf, new_size);
-       memset(buf->ptr + buf->size, c, len);
-       buf->size += len;
-       buf->ptr[buf->size] = '\0';
-       return 0;
-}
-
-int git_buf_put(git_buf *buf, const char *data, size_t len)
-{
-       if (len) {
-               size_t new_size;
-
-               GIT_ASSERT_ARG(data);
-
-               GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, len);
-               GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
-               ENSURE_SIZE(buf, new_size);
-               memmove(buf->ptr + buf->size, data, len);
-               buf->size += len;
-               buf->ptr[buf->size] = '\0';
-       }
-       return 0;
-}
-
-int git_buf_puts(git_buf *buf, const char *string)
-{
-       GIT_ASSERT_ARG(string);
-
-       return git_buf_put(buf, string, strlen(string));
-}
-
-static const char base64_encode[] =
-       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-int git_buf_encode_base64(git_buf *buf, const char *data, size_t len)
-{
-       size_t extra = len % 3;
-       uint8_t *write, a, b, c;
-       const uint8_t *read = (const uint8_t *)data;
-       size_t blocks = (len / 3) + !!extra, alloclen;
-
-       GIT_ERROR_CHECK_ALLOC_ADD(&blocks, blocks, 1);
-       GIT_ERROR_CHECK_ALLOC_MULTIPLY(&alloclen, blocks, 4);
-       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, buf->size);
-
-       ENSURE_SIZE(buf, alloclen);
-       write = (uint8_t *)&buf->ptr[buf->size];
-
-       /* convert each run of 3 bytes into 4 output bytes */
-       for (len -= extra; len > 0; len -= 3) {
-               a = *read++;
-               b = *read++;
-               c = *read++;
-
-               *write++ = base64_encode[a >> 2];
-               *write++ = base64_encode[(a & 0x03) << 4 | b >> 4];
-               *write++ = base64_encode[(b & 0x0f) << 2 | c >> 6];
-               *write++ = base64_encode[c & 0x3f];
-       }
-
-       if (extra > 0) {
-               a = *read++;
-               b = (extra > 1) ? *read++ : 0;
-
-               *write++ = base64_encode[a >> 2];
-               *write++ = base64_encode[(a & 0x03) << 4 | b >> 4];
-               *write++ = (extra > 1) ? base64_encode[(b & 0x0f) << 2] : '=';
-               *write++ = '=';
-       }
-
-       buf->size = ((char *)write) - buf->ptr;
-       buf->ptr[buf->size] = '\0';
-
-       return 0;
-}
-
-/* The inverse of base64_encode */
-static const int8_t base64_decode[] = {
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
-       52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1,  0, -1, -1,
-       -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
-       15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-       -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-};
-
-int git_buf_decode_base64(git_buf *buf, const char *base64, size_t len)
-{
-       size_t i;
-       int8_t a, b, c, d;
-       size_t orig_size = buf->size, new_size;
-
-       if (len % 4) {
-               git_error_set(GIT_ERROR_INVALID, "invalid base64 input");
-               return -1;
-       }
-
-       GIT_ASSERT_ARG(len % 4 == 0);
-       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, (len / 4 * 3), buf->size);
-       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
-       ENSURE_SIZE(buf, new_size);
-
-       for (i = 0; i < len; i += 4) {
-               if ((a = base64_decode[(unsigned char)base64[i]]) < 0 ||
-                       (b = base64_decode[(unsigned char)base64[i+1]]) < 0 ||
-                       (c = base64_decode[(unsigned char)base64[i+2]]) < 0 ||
-                       (d = base64_decode[(unsigned char)base64[i+3]]) < 0) {
-                       buf->size = orig_size;
-                       buf->ptr[buf->size] = '\0';
-
-                       git_error_set(GIT_ERROR_INVALID, "invalid base64 input");
-                       return -1;
-               }
-
-               buf->ptr[buf->size++] = ((a << 2) | (b & 0x30) >> 4);
-               buf->ptr[buf->size++] = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2);
-               buf->ptr[buf->size++] = (c & 0x03) << 6 | (d & 0x3f);
-       }
-
-       buf->ptr[buf->size] = '\0';
-       return 0;
-}
-
-static const char base85_encode[] =
-       "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
-
-int git_buf_encode_base85(git_buf *buf, const char *data, size_t len)
-{
-       size_t blocks = (len / 4) + !!(len % 4), alloclen;
-
-       GIT_ERROR_CHECK_ALLOC_MULTIPLY(&alloclen, blocks, 5);
-       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, buf->size);
-       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
-
-       ENSURE_SIZE(buf, alloclen);
-
-       while (len) {
-               uint32_t acc = 0;
-               char b85[5];
-               int i;
-
-               for (i = 24; i >= 0; i -= 8) {
-                       uint8_t ch = *data++;
-                       acc |= (uint32_t)ch << i;
-
-                       if (--len == 0)
-                               break;
-               }
-
-               for (i = 4; i >= 0; i--) {
-                       int val = acc % 85;
-                       acc /= 85;
-
-                       b85[i] = base85_encode[val];
-               }
-
-               for (i = 0; i < 5; i++)
-                       buf->ptr[buf->size++] = b85[i];
-       }
-
-       buf->ptr[buf->size] = '\0';
-
-       return 0;
-}
-
-/* The inverse of base85_encode */
-static const int8_t base85_decode[] = {
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, 63, -1, 64, 65, 66, 67, -1, 68, 69, 70, 71, -1, 72, -1, -1,
-        1,  2,  3,  4,  5,  6,  7,  8,  9, 10, -1, 73, 74, 75, 76, 77,
-       78, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
-       26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -1, -1, -1, 79, 80,
-       81, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-       52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 82, 83, 84, 85, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-};
-
-int git_buf_decode_base85(
-       git_buf *buf,
-       const char *base85,
-       size_t base85_len,
-       size_t output_len)
-{
-       size_t orig_size = buf->size, new_size;
-
-       if (base85_len % 5 ||
-               output_len > base85_len * 4 / 5) {
-               git_error_set(GIT_ERROR_INVALID, "invalid base85 input");
-               return -1;
-       }
-
-       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, output_len, buf->size);
-       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
-       ENSURE_SIZE(buf, new_size);
-
-       while (output_len) {
-               unsigned acc = 0;
-               int de, cnt = 4;
-               unsigned char ch;
-               do {
-                       ch = *base85++;
-                       de = base85_decode[ch];
-                       if (--de < 0)
-                               goto on_error;
-
-                       acc = acc * 85 + de;
-               } while (--cnt);
-               ch = *base85++;
-               de = base85_decode[ch];
-               if (--de < 0)
-                       goto on_error;
-
-               /* Detect overflow. */
-               if (0xffffffff / 85 < acc ||
-                       0xffffffff - de < (acc *= 85))
-                       goto on_error;
-
-               acc += de;
-
-               cnt = (output_len < 4) ? (int)output_len : 4;
-               output_len -= cnt;
-               do {
-                       acc = (acc << 8) | (acc >> 24);
-                       buf->ptr[buf->size++] = acc;
-               } while (--cnt);
-       }
-
-       buf->ptr[buf->size] = 0;
-
-       return 0;
-
-on_error:
-       buf->size = orig_size;
-       buf->ptr[buf->size] = '\0';
-
-       git_error_set(GIT_ERROR_INVALID, "invalid base85 input");
-       return -1;
-}
-
-#define HEX_DECODE(c) ((c | 32) % 39 - 9)
-
-int git_buf_decode_percent(
-       git_buf *buf,
-       const char *str,
-       size_t str_len)
-{
-       size_t str_pos, new_size;
-
-       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, str_len);
-       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
-       ENSURE_SIZE(buf, new_size);
-
-       for (str_pos = 0; str_pos < str_len; buf->size++, str_pos++) {
-               if (str[str_pos] == '%' &&
-                       str_len > str_pos + 2 &&
-                       isxdigit(str[str_pos + 1]) &&
-                       isxdigit(str[str_pos + 2])) {
-                       buf->ptr[buf->size] = (HEX_DECODE(str[str_pos + 1]) << 4) +
-                               HEX_DECODE(str[str_pos + 2]);
-                       str_pos += 2;
-               } else {
-                       buf->ptr[buf->size] = str[str_pos];
-               }
-       }
-
-       buf->ptr[buf->size] = '\0';
-       return 0;
-}
-
-int git_buf_vprintf(git_buf *buf, const char *format, va_list ap)
-{
-       size_t expected_size, new_size;
-       int len;
-
-       GIT_ERROR_CHECK_ALLOC_MULTIPLY(&expected_size, strlen(format), 2);
-       GIT_ERROR_CHECK_ALLOC_ADD(&expected_size, expected_size, buf->size);
-       ENSURE_SIZE(buf, expected_size);
-
-       while (1) {
-               va_list args;
-               va_copy(args, ap);
-
-               len = p_vsnprintf(
-                       buf->ptr + buf->size,
-                       buf->asize - buf->size,
-                       format, args
-               );
-
-               va_end(args);
-
-               if (len < 0) {
-                       git__free(buf->ptr);
-                       buf->ptr = git_buf__oom;
-                       return -1;
-               }
-
-               if ((size_t)len + 1 <= buf->asize - buf->size) {
-                       buf->size += len;
-                       break;
-               }
-
-               GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, len);
-               GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
-               ENSURE_SIZE(buf, new_size);
-       }
-
-       return 0;
-}
-
-int git_buf_printf(git_buf *buf, const char *format, ...)
-{
-       int r;
-       va_list ap;
-
-       va_start(ap, format);
-       r = git_buf_vprintf(buf, format, ap);
-       va_end(ap);
-
-       return r;
-}
-
-int git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf)
-{
-       size_t copylen;
-
-       GIT_ASSERT_ARG(data);
-       GIT_ASSERT_ARG(datasize);
-       GIT_ASSERT_ARG(buf);
-
-       data[0] = '\0';
-
-       if (buf->size == 0 || buf->asize <= 0)
-               return 0;
-
-       copylen = buf->size;
-       if (copylen > datasize - 1)
-               copylen = datasize - 1;
-       memmove(data, buf->ptr, copylen);
-       data[copylen] = '\0';
-
-       return 0;
-}
-
-void git_buf_consume_bytes(git_buf *buf, size_t len)
-{
-       git_buf_consume(buf, buf->ptr + len);
-}
-
-void git_buf_consume(git_buf *buf, const char *end)
-{
-       if (end > buf->ptr && end <= buf->ptr + buf->size) {
-               size_t consumed = end - buf->ptr;
-               memmove(buf->ptr, end, buf->size - consumed);
-               buf->size -= consumed;
-               buf->ptr[buf->size] = '\0';
-       }
-}
-
-void git_buf_truncate(git_buf *buf, size_t len)
-{
-       if (len >= buf->size)
-               return;
-
-       buf->size = len;
-       if (buf->size < buf->asize)
-               buf->ptr[buf->size] = '\0';
-}
-
-void git_buf_shorten(git_buf *buf, size_t amount)
-{
-       if (buf->size > amount)
-               git_buf_truncate(buf, buf->size - amount);
-       else
-               git_buf_clear(buf);
-}
-
-void git_buf_truncate_at_char(git_buf *buf, char separator)
-{
-       ssize_t idx = git_buf_find(buf, separator);
-       if (idx >= 0)
-               git_buf_truncate(buf, (size_t)idx);
-}
-
-void git_buf_rtruncate_at_char(git_buf *buf, char separator)
-{
-       ssize_t idx = git_buf_rfind_next(buf, separator);
-       git_buf_truncate(buf, idx < 0 ? 0 : (size_t)idx);
-}
-
-void git_buf_swap(git_buf *buf_a, git_buf *buf_b)
-{
-       git_buf t = *buf_a;
-       *buf_a = *buf_b;
-       *buf_b = t;
-}
-
-char *git_buf_detach(git_buf *buf)
-{
-       char *data = buf->ptr;
-
-       if (buf->asize == 0 || buf->ptr == git_buf__oom)
-               return NULL;
-
-       git_buf_init(buf, 0);
-
-       return data;
-}
-
-int git_buf_attach(git_buf *buf, char *ptr, size_t asize)
-{
-       git_buf_dispose(buf);
-
-       if (ptr) {
-               buf->ptr = ptr;
-               buf->size = strlen(ptr);
-               if (asize)
-                       buf->asize = (asize < buf->size) ? buf->size + 1 : asize;
-               else /* pass 0 to fall back on strlen + 1 */
-                       buf->asize = buf->size + 1;
-       }
-
-       ENSURE_SIZE(buf, asize);
-       return 0;
-}
-
-void git_buf_attach_notowned(git_buf *buf, const char *ptr, size_t size)
-{
-       if (git_buf_is_allocated(buf))
-               git_buf_dispose(buf);
-
-       if (!size) {
-               git_buf_init(buf, 0);
-       } else {
-               buf->ptr = (char *)ptr;
-               buf->asize = 0;
-               buf->size = size;
-       }
-}
-
-int git_buf_join_n(git_buf *buf, char separator, int nbuf, ...)
-{
-       va_list ap;
-       int i;
-       size_t total_size = 0, original_size = buf->size;
-       char *out, *original = buf->ptr;
-
-       if (buf->size > 0 && buf->ptr[buf->size - 1] != separator)
-               ++total_size; /* space for initial separator */
-
-       /* Make two passes to avoid multiple reallocation */
-
-       va_start(ap, nbuf);
-       for (i = 0; i < nbuf; ++i) {
-               const char *segment;
-               size_t segment_len;
-
-               segment = va_arg(ap, const char *);
-               if (!segment)
-                       continue;
-
-               segment_len = strlen(segment);
-
-               GIT_ERROR_CHECK_ALLOC_ADD(&total_size, total_size, segment_len);
-
-               if (segment_len == 0 || segment[segment_len - 1] != separator)
-                       GIT_ERROR_CHECK_ALLOC_ADD(&total_size, total_size, 1);
-       }
-       va_end(ap);
-
-       /* expand buffer if needed */
-       if (total_size == 0)
-               return 0;
-
-       GIT_ERROR_CHECK_ALLOC_ADD(&total_size, total_size, 1);
-       if (git_buf_grow_by(buf, total_size) < 0)
-               return -1;
-
-       out = buf->ptr + buf->size;
-
-       /* append separator to existing buf if needed */
-       if (buf->size > 0 && out[-1] != separator)
-               *out++ = separator;
-
-       va_start(ap, nbuf);
-       for (i = 0; i < nbuf; ++i) {
-               const char *segment;
-               size_t segment_len;
-
-               segment = va_arg(ap, const char *);
-               if (!segment)
-                       continue;
-
-               /* deal with join that references buffer's original content */
-               if (segment >= original && segment < original + original_size) {
-                       size_t offset = (segment - original);
-                       segment = buf->ptr + offset;
-                       segment_len = original_size - offset;
-               } else {
-                       segment_len = strlen(segment);
-               }
-
-               /* skip leading separators */
-               if (out > buf->ptr && out[-1] == separator)
-                       while (segment_len > 0 && *segment == separator) {
-                               segment++;
-                               segment_len--;
-                       }
-
-               /* copy over next buffer */
-               if (segment_len > 0) {
-                       memmove(out, segment, segment_len);
-                       out += segment_len;
-               }
-
-               /* append trailing separator (except for last item) */
-               if (i < nbuf - 1 && out > buf->ptr && out[-1] != separator)
-                       *out++ = separator;
-       }
-       va_end(ap);
-
-       /* set size based on num characters actually written */
-       buf->size = out - buf->ptr;
-       buf->ptr[buf->size] = '\0';
-
-       return 0;
-}
-
-int git_buf_join(
-       git_buf *buf,
-       char separator,
-       const char *str_a,
-       const char *str_b)
-{
-       size_t strlen_a = str_a ? strlen(str_a) : 0;
-       size_t strlen_b = strlen(str_b);
-       size_t alloc_len;
-       int need_sep = 0;
-       ssize_t offset_a = -1;
-
-       /* not safe to have str_b point internally to the buffer */
-       if (buf->size)
-               GIT_ASSERT_ARG(str_b < buf->ptr || str_b >= buf->ptr + buf->size);
-
-       /* figure out if we need to insert a separator */
-       if (separator && strlen_a) {
-               while (*str_b == separator) { str_b++; strlen_b--; }
-               if (str_a[strlen_a - 1] != separator)
-                       need_sep = 1;
-       }
-
-       /* str_a could be part of the buffer */
-       if (buf->size && str_a >= buf->ptr && str_a < buf->ptr + buf->size)
-               offset_a = str_a - buf->ptr;
-
-       GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, strlen_a, strlen_b);
-       GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, need_sep);
-       GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 1);
-       ENSURE_SIZE(buf, alloc_len);
-
-       /* fix up internal pointers */
-       if (offset_a >= 0)
-               str_a = buf->ptr + offset_a;
-
-       /* do the actual copying */
-       if (offset_a != 0 && str_a)
-               memmove(buf->ptr, str_a, strlen_a);
-       if (need_sep)
-               buf->ptr[strlen_a] = separator;
-       memcpy(buf->ptr + strlen_a + need_sep, str_b, strlen_b);
-
-       buf->size = strlen_a + strlen_b + need_sep;
-       buf->ptr[buf->size] = '\0';
-
-       return 0;
-}
-
-int git_buf_join3(
-       git_buf *buf,
-       char separator,
-       const char *str_a,
-       const char *str_b,
-       const char *str_c)
-{
-       size_t len_a = strlen(str_a),
-               len_b = strlen(str_b),
-               len_c = strlen(str_c),
-               len_total;
-       int sep_a = 0, sep_b = 0;
-       char *tgt;
-
-       /* for this function, disallow pointers into the existing buffer */
-       GIT_ASSERT(str_a < buf->ptr || str_a >= buf->ptr + buf->size);
-       GIT_ASSERT(str_b < buf->ptr || str_b >= buf->ptr + buf->size);
-       GIT_ASSERT(str_c < buf->ptr || str_c >= buf->ptr + buf->size);
-
-       if (separator) {
-               if (len_a > 0) {
-                       while (*str_b == separator) { str_b++; len_b--; }
-                       sep_a = (str_a[len_a - 1] != separator);
-               }
-               if (len_a > 0 || len_b > 0)
-                       while (*str_c == separator) { str_c++; len_c--; }
-               if (len_b > 0)
-                       sep_b = (str_b[len_b - 1] != separator);
-       }
-
-       GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_a, sep_a);
-       GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_total, len_b);
-       GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_total, sep_b);
-       GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_total, len_c);
-       GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_total, 1);
-       ENSURE_SIZE(buf, len_total);
-
-       tgt = buf->ptr;
-
-       if (len_a) {
-               memcpy(tgt, str_a, len_a);
-               tgt += len_a;
-       }
-       if (sep_a)
-               *tgt++ = separator;
-       if (len_b) {
-               memcpy(tgt, str_b, len_b);
-               tgt += len_b;
-       }
-       if (sep_b)
-               *tgt++ = separator;
-       if (len_c)
-               memcpy(tgt, str_c, len_c);
-
-       buf->size = len_a + sep_a + len_b + sep_b + len_c;
-       buf->ptr[buf->size] = '\0';
-
-       return 0;
-}
-
-void git_buf_rtrim(git_buf *buf)
-{
-       while (buf->size > 0) {
-               if (!git__isspace(buf->ptr[buf->size - 1]))
-                       break;
-
-               buf->size--;
-       }
-
-       if (buf->asize > buf->size)
-               buf->ptr[buf->size] = '\0';
-}
-
-int git_buf_cmp(const git_buf *a, const git_buf *b)
-{
-       int result = memcmp(a->ptr, b->ptr, min(a->size, b->size));
-       return (result != 0) ? result :
-               (a->size < b->size) ? -1 : (a->size > b->size) ? 1 : 0;
-}
-
-int git_buf_splice(
-       git_buf *buf,
-       size_t where,
-       size_t nb_to_remove,
-       const char *data,
-       size_t nb_to_insert)
-{
-       char *splice_loc;
-       size_t new_size, alloc_size;
-
-       GIT_ASSERT(buf);
-       GIT_ASSERT(where <= buf->size);
-       GIT_ASSERT(nb_to_remove <= buf->size - where);
-
-       splice_loc = buf->ptr + where;
-
-       /* Ported from git.git
-        * https://github.com/git/git/blob/16eed7c/strbuf.c#L159-176
-        */
-       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, (buf->size - nb_to_remove), nb_to_insert);
-       GIT_ERROR_CHECK_ALLOC_ADD(&alloc_size, new_size, 1);
-       ENSURE_SIZE(buf, alloc_size);
-
-       memmove(splice_loc + nb_to_insert,
-               splice_loc + nb_to_remove,
-               buf->size - where - nb_to_remove);
-
-       memcpy(splice_loc, data, nb_to_insert);
-
-       buf->size = new_size;
-       buf->ptr[buf->size] = '\0';
-       return 0;
-}
-
-/* Quote per http://marc.info/?l=git&m=112927316408690&w=2 */
-int git_buf_quote(git_buf *buf)
-{
-       const char whitespace[] = { 'a', 'b', 't', 'n', 'v', 'f', 'r' };
-       git_buf quoted = GIT_BUF_INIT;
-       size_t i = 0;
-       bool quote = false;
-       int error = 0;
-
-       /* walk to the first char that needs quoting */
-       if (buf->size && buf->ptr[0] == '!')
-               quote = true;
-
-       for (i = 0; !quote && i < buf->size; i++) {
-               if (buf->ptr[i] == '"' || buf->ptr[i] == '\\' ||
-                       buf->ptr[i] < ' ' || buf->ptr[i] > '~') {
-                       quote = true;
-                       break;
-               }
-       }
-
-       if (!quote)
-               goto done;
-
-       git_buf_putc(&quoted, '"');
-       git_buf_put(&quoted, buf->ptr, i);
-
-       for (; i < buf->size; i++) {
-               /* whitespace - use the map above, which is ordered by ascii value */
-               if (buf->ptr[i] >= '\a' && buf->ptr[i] <= '\r') {
-                       git_buf_putc(&quoted, '\\');
-                       git_buf_putc(&quoted, whitespace[buf->ptr[i] - '\a']);
-               }
-
-               /* double quote and backslash must be escaped */
-               else if (buf->ptr[i] == '"' || buf->ptr[i] == '\\') {
-                       git_buf_putc(&quoted, '\\');
-                       git_buf_putc(&quoted, buf->ptr[i]);
-               }
-
-               /* escape anything unprintable as octal */
-               else if (buf->ptr[i] != ' ' &&
-                               (buf->ptr[i] < '!' || buf->ptr[i] > '~')) {
-                       git_buf_printf(&quoted, "\\%03o", (unsigned char)buf->ptr[i]);
-               }
-
-               /* yay, printable! */
-               else {
-                       git_buf_putc(&quoted, buf->ptr[i]);
-               }
-       }
-
-       git_buf_putc(&quoted, '"');
-
-       if (git_buf_oom(&quoted)) {
-               error = -1;
-               goto done;
-       }
-
-       git_buf_swap(&quoted, buf);
-
-done:
-       git_buf_dispose(&quoted);
-       return error;
-}
-
-/* Unquote per http://marc.info/?l=git&m=112927316408690&w=2 */
-int git_buf_unquote(git_buf *buf)
-{
-       size_t i, j;
-       char ch;
-
-       git_buf_rtrim(buf);
-
-       if (buf->size < 2 || buf->ptr[0] != '"' || buf->ptr[buf->size-1] != '"')
-               goto invalid;
-
-       for (i = 0, j = 1; j < buf->size-1; i++, j++) {
-               ch = buf->ptr[j];
-
-               if (ch == '\\') {
-                       if (j == buf->size-2)
-                               goto invalid;
-
-                       ch = buf->ptr[++j];
-
-                       switch (ch) {
-                       /* \" or \\ simply copy the char in */
-                       case '"': case '\\':
-                               break;
-
-                       /* add the appropriate escaped char */
-                       case 'a': ch = '\a'; break;
-                       case 'b': ch = '\b'; break;
-                       case 'f': ch = '\f'; break;
-                       case 'n': ch = '\n'; break;
-                       case 'r': ch = '\r'; break;
-                       case 't': ch = '\t'; break;
-                       case 'v': ch = '\v'; break;
-
-                       /* \xyz digits convert to the char*/
-                       case '0': case '1': case '2': case '3':
-                               if (j == buf->size-3) {
-                                       git_error_set(GIT_ERROR_INVALID,
-                                               "truncated quoted character \\%c", ch);
-                                       return -1;
-                               }
-
-                               if (buf->ptr[j+1] < '0' || buf->ptr[j+1] > '7' ||
-                                       buf->ptr[j+2] < '0' || buf->ptr[j+2] > '7') {
-                                       git_error_set(GIT_ERROR_INVALID,
-                                               "truncated quoted character \\%c%c%c",
-                                               buf->ptr[j], buf->ptr[j+1], buf->ptr[j+2]);
-                                       return -1;
-                               }
-
-                               ch = ((buf->ptr[j] - '0') << 6) |
-                                       ((buf->ptr[j+1] - '0') << 3) |
-                                       (buf->ptr[j+2] - '0');
-                               j += 2;
-                               break;
-
-                       default:
-                               git_error_set(GIT_ERROR_INVALID, "invalid quoted character \\%c", ch);
-                               return -1;
-                       }
-               }
-
-               buf->ptr[i] = ch;
-       }
-
-       buf->ptr[i] = '\0';
-       buf->size = i;
-
-       return 0;
-
-invalid:
-       git_error_set(GIT_ERROR_INVALID, "invalid quoted line");
-       return -1;
-}
-
-int git_buf_puts_escaped(
-       git_buf *buf,
-       const char *string,
-       const char *esc_chars,
-       const char *esc_with)
-{
-       const char *scan;
-       size_t total = 0, esc_len = strlen(esc_with), count, alloclen;
-
-       if (!string)
-               return 0;
-
-       for (scan = string; *scan; ) {
-               /* count run of non-escaped characters */
-               count = strcspn(scan, esc_chars);
-               total += count;
-               scan += count;
-               /* count run of escaped characters */
-               count = strspn(scan, esc_chars);
-               total += count * (esc_len + 1);
-               scan += count;
-       }
-
-       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, total, 1);
-       if (git_buf_grow_by(buf, alloclen) < 0)
-               return -1;
-
-       for (scan = string; *scan; ) {
-               count = strcspn(scan, esc_chars);
-
-               memmove(buf->ptr + buf->size, scan, count);
-               scan += count;
-               buf->size += count;
-
-               for (count = strspn(scan, esc_chars); count > 0; --count) {
-                       /* copy escape sequence */
-                       memmove(buf->ptr + buf->size, esc_with, esc_len);
-                       buf->size += esc_len;
-                       /* copy character to be escaped */
-                       buf->ptr[buf->size] = *scan;
-                       buf->size++;
-                       scan++;
-               }
-       }
-
-       buf->ptr[buf->size] = '\0';
-
-       return 0;
-}
-
-void git_buf_unescape(git_buf *buf)
-{
-       buf->size = git__unescape(buf->ptr);
-}
-
-int git_buf_crlf_to_lf(git_buf *tgt, const git_buf *src)
-{
-       const char *scan = src->ptr;
-       const char *scan_end = src->ptr + src->size;
-       const char *next = memchr(scan, '\r', src->size);
-       size_t new_size;
-       char *out;
-
-       GIT_ASSERT(tgt != src);
-
-       if (!next)
-               return git_buf_set(tgt, src->ptr, src->size);
-
-       /* reduce reallocs while in the loop */
-       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, src->size, 1);
-       if (git_buf_grow(tgt, new_size) < 0)
-               return -1;
-
-       out = tgt->ptr;
-       tgt->size = 0;
-
-       /* Find the next \r and copy whole chunk up to there to tgt */
-       for (; next; scan = next + 1, next = memchr(scan, '\r', scan_end - scan)) {
-               if (next > scan) {
-                       size_t copylen = (size_t)(next - scan);
-                       memcpy(out, scan, copylen);
-                       out += copylen;
-               }
-
-               /* Do not drop \r unless it is followed by \n */
-               if (next + 1 == scan_end || next[1] != '\n')
-                       *out++ = '\r';
-       }
-
-       /* Copy remaining input into dest */
-       if (scan < scan_end) {
-               size_t remaining = (size_t)(scan_end - scan);
-               memcpy(out, scan, remaining);
-               out += remaining;
-       }
-
-       tgt->size = (size_t)(out - tgt->ptr);
-       tgt->ptr[tgt->size] = '\0';
-
-       return 0;
-}
-
-int git_buf_lf_to_crlf(git_buf *tgt, const git_buf *src)
-{
-       const char *start = src->ptr;
-       const char *end = start + src->size;
-       const char *scan = start;
-       const char *next = memchr(scan, '\n', src->size);
-       size_t alloclen;
-
-       GIT_ASSERT(tgt != src);
-
-       if (!next)
-               return git_buf_set(tgt, src->ptr, src->size);
-
-       /* attempt to reduce reallocs while in the loop */
-       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, src->size, src->size >> 4);
-       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
-       if (git_buf_grow(tgt, alloclen) < 0)
-               return -1;
-       tgt->size = 0;
-
-       for (; next; scan = next + 1, next = memchr(scan, '\n', end - scan)) {
-               size_t copylen = next - scan;
-
-               /* if we find mixed line endings, carry on */
-               if (copylen && next[-1] == '\r')
-                       copylen--;
-
-               GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, copylen, 3);
-               if (git_buf_grow_by(tgt, alloclen) < 0)
-                       return -1;
-
-               if (copylen) {
-                       memcpy(tgt->ptr + tgt->size, scan, copylen);
-                       tgt->size += copylen;
-               }
-
-               tgt->ptr[tgt->size++] = '\r';
-               tgt->ptr[tgt->size++] = '\n';
-       }
-
-       tgt->ptr[tgt->size] = '\0';
-       return git_buf_put(tgt, scan, end - scan);
-}
-
-int git_buf_common_prefix(git_buf *buf, char *const *const strings, size_t count)
-{
-       size_t i;
-       const char *str, *pfx;
-
-       git_buf_clear(buf);
-
-       if (!strings || !count)
-               return 0;
-
-       /* initialize common prefix to first string */
-       if (git_buf_sets(buf, strings[0]) < 0)
-               return -1;
-
-       /* go through the rest of the strings, truncating to shared prefix */
-       for (i = 1; i < count; ++i) {
-
-               for (str = strings[i], pfx = buf->ptr;
-                    *str && *str == *pfx;
-                    str++, pfx++)
-                       /* scanning */;
-
-               git_buf_truncate(buf, pfx - buf->ptr);
-
-               if (!buf->size)
-                       break;
-       }
-
-       return 0;
-}
-
-int git_buf_is_binary(const git_buf *buf)
-{
-       const char *scan = buf->ptr, *end = buf->ptr + buf->size;
-       git_buf_bom_t bom;
-       int printable = 0, nonprintable = 0;
-
-       scan += git_buf_detect_bom(&bom, buf);
-
-       if (bom > GIT_BUF_BOM_UTF8)
-               return 1;
-
-       while (scan < end) {
-               unsigned char c = *scan++;
-
-               /* Printable characters are those above SPACE (0x1F) excluding DEL,
-                * and including BS, ESC and FF.
-                */
-               if ((c > 0x1F && c != 127) || c == '\b' || c == '\033' || c == '\014')
-                       printable++;
-               else if (c == '\0')
-                       return true;
-               else if (!git__isspace(c))
-                       nonprintable++;
-       }
-
-       return ((printable >> 7) < nonprintable);
-}
-
-int git_buf_contains_nul(const git_buf *buf)
-{
-       return (memchr(buf->ptr, '\0', buf->size) != NULL);
-}
-
-int git_buf_detect_bom(git_buf_bom_t *bom, const git_buf *buf)
-{
-       const char *ptr;
-       size_t len;
-
-       *bom = GIT_BUF_BOM_NONE;
-       /* need at least 2 bytes to look for any BOM */
-       if (buf->size < 2)
-               return 0;
-
-       ptr = buf->ptr;
-       len = buf->size;
-
-       switch (*ptr++) {
-       case 0:
-               if (len >= 4 && ptr[0] == 0 && ptr[1] == '\xFE' && ptr[2] == '\xFF') {
-                       *bom = GIT_BUF_BOM_UTF32_BE;
-                       return 4;
-               }
-               break;
-       case '\xEF':
-               if (len >= 3 && ptr[0] == '\xBB' && ptr[1] == '\xBF') {
-                       *bom = GIT_BUF_BOM_UTF8;
-                       return 3;
-               }
-               break;
-       case '\xFE':
-               if (*ptr == '\xFF') {
-                       *bom = GIT_BUF_BOM_UTF16_BE;
-                       return 2;
-               }
-               break;
-       case '\xFF':
-               if (*ptr != '\xFE')
-                       break;
-               if (len >= 4 && ptr[1] == 0 && ptr[2] == 0) {
-                       *bom = GIT_BUF_BOM_UTF32_LE;
-                       return 4;
-               } else {
-                       *bom = GIT_BUF_BOM_UTF16_LE;
-                       return 2;
-               }
-               break;
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-bool git_buf_gather_text_stats(
-       git_buf_text_stats *stats, const git_buf *buf, bool skip_bom)
-{
-       const char *scan = buf->ptr, *end = buf->ptr + buf->size;
-       int skip;
-
-       memset(stats, 0, sizeof(*stats));
-
-       /* BOM detection */
-       skip = git_buf_detect_bom(&stats->bom, buf);
-       if (skip_bom)
-               scan += skip;
-
-       /* Ignore EOF character */
-       if (buf->size > 0 && end[-1] == '\032')
-               end--;
-
-       /* Counting loop */
-       while (scan < end) {
-               unsigned char c = *scan++;
-
-               if (c > 0x1F && c != 0x7F)
-                       stats->printable++;
-               else switch (c) {
-                       case '\0':
-                               stats->nul++;
-                               stats->nonprintable++;
-                               break;
-                       case '\n':
-                               stats->lf++;
-                               break;
-                       case '\r':
-                               stats->cr++;
-                               if (scan < end && *scan == '\n')
-                                       stats->crlf++;
-                               break;
-                       case '\t': case '\f': case '\v': case '\b': case 0x1b: /*ESC*/
-                               stats->printable++;
-                               break;
-                       default:
-                               stats->nonprintable++;
-                               break;
-                       }
-       }
-
-       /* Treat files with a bare CR as binary */
-       return (stats->cr != stats->crlf || stats->nul > 0 ||
-               ((stats->printable >> 7) < stats->nonprintable));
-}
diff --git a/src/buffer.h b/src/buffer.h
deleted file mode 100644 (file)
index 75930e2..0000000
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * 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_buffer_h__
-#define INCLUDE_buffer_h__
-
-#include "common.h"
-#include "git2/strarray.h"
-#include "git2/buffer.h"
-
-/* typedef struct {
- *     char   *ptr;
- *     size_t asize, size;
- * } git_buf;
- */
-
-typedef enum {
-       GIT_BUF_BOM_NONE = 0,
-       GIT_BUF_BOM_UTF8 = 1,
-       GIT_BUF_BOM_UTF16_LE = 2,
-       GIT_BUF_BOM_UTF16_BE = 3,
-       GIT_BUF_BOM_UTF32_LE = 4,
-       GIT_BUF_BOM_UTF32_BE = 5
-} git_buf_bom_t;
-
-typedef struct {
-       git_buf_bom_t bom; /* BOM found at head of text */
-       unsigned int nul, cr, lf, crlf; /* NUL, CR, LF and CRLF counts */
-       unsigned int printable, nonprintable; /* These are just approximations! */
-} git_buf_text_stats;
-
-extern char git_buf__initbuf[];
-extern char git_buf__oom[];
-
-/* Use to initialize buffer structure when git_buf is on stack */
-#define GIT_BUF_INIT { git_buf__initbuf, 0, 0 }
-
-/**
- * Static initializer for git_buf from static buffer
- */
-#ifdef GIT_DEPRECATE_HARD
-# define GIT_BUF_INIT_CONST(STR,LEN) { (char *)(STR), 0, (size_t)(LEN) }
-#endif
-
-GIT_INLINE(bool) git_buf_is_allocated(const git_buf *buf)
-{
-       return (buf->ptr != NULL && buf->asize > 0);
-}
-
-/**
- * Initialize a git_buf structure.
- *
- * For the cases where GIT_BUF_INIT cannot be used to do static
- * initialization.
- */
-extern int git_buf_init(git_buf *buf, size_t initial_size);
-
-#ifdef GIT_DEPRECATE_HARD
-
-/**
- * Resize the buffer allocation to make more space.
- *
- * This will attempt to grow the buffer to accommodate the target size.
- *
- * If the buffer refers to memory that was not allocated by libgit2 (i.e.
- * the `asize` field is zero), then `ptr` will be replaced with a newly
- * allocated block of data.  Be careful so that memory allocated by the
- * caller is not lost.  As a special variant, if you pass `target_size` as
- * 0 and the memory is not allocated by libgit2, this will allocate a new
- * buffer of size `size` and copy the external data into it.
- *
- * Currently, this will never shrink a buffer, only expand it.
- *
- * If the allocation fails, this will return an error and the buffer will be
- * marked as invalid for future operations, invaliding the contents.
- *
- * @param buffer The buffer to be resized; may or may not be allocated yet
- * @param target_size The desired available size
- * @return 0 on success, -1 on allocation failure
- */
-int git_buf_grow(git_buf *buffer, size_t target_size);
-
-#endif
-
-/**
- * Resize the buffer allocation to make more space.
- *
- * This will attempt to grow the buffer to accommodate the additional size.
- * It is similar to `git_buf_grow`, but performs the new size calculation,
- * checking for overflow.
- *
- * Like `git_buf_grow`, if this is a user-supplied buffer, this will allocate
- * a new buffer.
- */
-extern int git_buf_grow_by(git_buf *buffer, size_t additional_size);
-
-/**
- * Attempt to grow the buffer to hold at least `target_size` bytes.
- *
- * If the allocation fails, this will return an error.  If `mark_oom` is true,
- * this will mark the buffer as invalid for future operations; if false,
- * existing buffer content will be preserved, but calling code must handle
- * that buffer was not expanded.  If `preserve_external` is true, then any
- * existing data pointed to be `ptr` even if `asize` is zero will be copied
- * into the newly allocated buffer.
- */
-extern int git_buf_try_grow(
-       git_buf *buf, size_t target_size, bool mark_oom);
-
-/**
- * Sanitizes git_buf structures provided from user input.  Users of the
- * library, when providing git_buf's, may wish to provide a NULL ptr for
- * ease of handling.  The buffer routines, however, expect a non-NULL ptr
- * always.  This helper method simply handles NULL input, converting to a
- * git_buf__initbuf. If a buffer with a non-NULL ptr is passed in, this method
- * assures that the buffer is '\0'-terminated.
- */
-extern int git_buf_sanitize(git_buf *buf);
-
-extern void git_buf_swap(git_buf *buf_a, git_buf *buf_b);
-extern char *git_buf_detach(git_buf *buf);
-extern int git_buf_attach(git_buf *buf, char *ptr, size_t asize);
-
-/* Populates a `git_buf` where the contents are not "owned" by the
- * buffer, and calls to `git_buf_dispose` will not free the given buf.
- */
-extern void git_buf_attach_notowned(
-       git_buf *buf, const char *ptr, size_t size);
-
-/**
- * Test if there have been any reallocation failures with this git_buf.
- *
- * Any function that writes to a git_buf can fail due to memory allocation
- * issues.  If one fails, the git_buf will be marked with an OOM error and
- * further calls to modify the buffer will fail.  Check git_buf_oom() at the
- * end of your sequence and it will be true if you ran out of memory at any
- * point with that buffer.
- *
- * @return false if no error, true if allocation error
- */
-GIT_INLINE(bool) git_buf_oom(const git_buf *buf)
-{
-       return (buf->ptr == git_buf__oom);
-}
-
-/*
- * Functions below that return int value error codes will return 0 on
- * success or -1 on failure (which generally means an allocation failed).
- * Using a git_buf where the allocation has failed with result in -1 from
- * all further calls using that buffer.  As a result, you can ignore the
- * return code of these functions and call them in a series then just call
- * git_buf_oom at the end.
- */
-
-#ifdef GIT_DEPRECATE_HARD
-int git_buf_set(git_buf *buffer, const void *data, size_t datalen);
-#endif
-
-int git_buf_sets(git_buf *buf, const char *string);
-int git_buf_putc(git_buf *buf, char c);
-int git_buf_putcn(git_buf *buf, char c, size_t len);
-int git_buf_put(git_buf *buf, const char *data, size_t len);
-int git_buf_puts(git_buf *buf, const char *string);
-int git_buf_printf(git_buf *buf, const char *format, ...) GIT_FORMAT_PRINTF(2, 3);
-int git_buf_vprintf(git_buf *buf, const char *format, va_list ap);
-void git_buf_clear(git_buf *buf);
-void git_buf_consume_bytes(git_buf *buf, size_t len);
-void git_buf_consume(git_buf *buf, const char *end);
-void git_buf_truncate(git_buf *buf, size_t len);
-void git_buf_shorten(git_buf *buf, size_t amount);
-void git_buf_truncate_at_char(git_buf *buf, char separator);
-void git_buf_rtruncate_at_char(git_buf *path, char separator);
-
-/** General join with separator */
-int git_buf_join_n(git_buf *buf, char separator, int nbuf, ...);
-/** Fast join of two strings - first may legally point into `buf` data */
-int git_buf_join(git_buf *buf, char separator, const char *str_a, const char *str_b);
-/** Fast join of three strings - cannot reference `buf` data */
-int git_buf_join3(git_buf *buf, char separator, const char *str_a, const char *str_b, const char *str_c);
-
-/**
- * Join two strings as paths, inserting a slash between as needed.
- * @return 0 on success, -1 on failure
- */
-GIT_INLINE(int) git_buf_joinpath(git_buf *buf, const char *a, const char *b)
-{
-       return git_buf_join(buf, '/', a, b);
-}
-
-GIT_INLINE(const char *) git_buf_cstr(const git_buf *buf)
-{
-       return buf->ptr;
-}
-
-GIT_INLINE(size_t) git_buf_len(const git_buf *buf)
-{
-       return buf->size;
-}
-
-int git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf);
-
-#define git_buf_PUTS(buf, str) git_buf_put(buf, str, sizeof(str) - 1)
-
-GIT_INLINE(ssize_t) git_buf_rfind_next(const git_buf *buf, char ch)
-{
-       ssize_t idx = (ssize_t)buf->size - 1;
-       while (idx >= 0 && buf->ptr[idx] == ch) idx--;
-       while (idx >= 0 && buf->ptr[idx] != ch) idx--;
-       return idx;
-}
-
-GIT_INLINE(ssize_t) git_buf_rfind(const git_buf *buf, char ch)
-{
-       ssize_t idx = (ssize_t)buf->size - 1;
-       while (idx >= 0 && buf->ptr[idx] != ch) idx--;
-       return idx;
-}
-
-GIT_INLINE(ssize_t) git_buf_find(const git_buf *buf, char ch)
-{
-       void *found = memchr(buf->ptr, ch, buf->size);
-       return found ? (ssize_t)((const char *)found - buf->ptr) : -1;
-}
-
-/* Remove whitespace from the end of the buffer */
-void git_buf_rtrim(git_buf *buf);
-
-int git_buf_cmp(const git_buf *a, const git_buf *b);
-
-/* Quote and unquote a buffer as specified in
- * http://marc.info/?l=git&m=112927316408690&w=2
- */
-int git_buf_quote(git_buf *buf);
-int git_buf_unquote(git_buf *buf);
-
-/* Write data as base64 encoded in buffer */
-int git_buf_encode_base64(git_buf *buf, const char *data, size_t len);
-/* Decode the given bas64 and write the result to the buffer */
-int git_buf_decode_base64(git_buf *buf, const char *base64, size_t len);
-
-/* Write data as "base85" encoded in buffer */
-int git_buf_encode_base85(git_buf *buf, const char *data, size_t len);
-/* Decode the given "base85" and write the result to the buffer */
-int git_buf_decode_base85(git_buf *buf, const char *base64, size_t len, size_t output_len);
-
-/* Decode the given percent-encoded string and write the result to the buffer */
-int git_buf_decode_percent(git_buf *buf, const char *str, size_t len);
-
-/*
- * Insert, remove or replace a portion of the buffer.
- *
- * @param buf The buffer to work with
- *
- * @param where The location in the buffer where the transformation
- * should be applied.
- *
- * @param nb_to_remove The number of chars to be removed. 0 to not
- * remove any character in the buffer.
- *
- * @param data A pointer to the data which should be inserted.
- *
- * @param nb_to_insert The number of chars to be inserted. 0 to not
- * insert any character from the buffer.
- *
- * @return 0 or an error code.
- */
-int git_buf_splice(
-       git_buf *buf,
-       size_t where,
-       size_t nb_to_remove,
-       const char *data,
-       size_t nb_to_insert);
-
-/**
- * Append string to buffer, prefixing each character from `esc_chars` with
- * `esc_with` string.
- *
- * @param buf Buffer to append data to
- * @param string String to escape and append
- * @param esc_chars Characters to be escaped
- * @param esc_with String to insert in from of each found character
- * @return 0 on success, <0 on failure (probably allocation problem)
- */
-extern int git_buf_puts_escaped(
-       git_buf *buf,
-       const char *string,
-       const char *esc_chars,
-       const char *esc_with);
-
-/**
- * Append string escaping characters that are regex special
- */
-GIT_INLINE(int) git_buf_puts_escape_regex(git_buf *buf, const char *string)
-{
-       return git_buf_puts_escaped(buf, string, "^.[]$()|*+?{}\\", "\\");
-}
-
-/**
- * Unescape all characters in a buffer in place
- *
- * I.e. remove backslashes
- */
-extern void git_buf_unescape(git_buf *buf);
-
-/**
- * Replace all \r\n with \n.
- *
- * @return 0 on success, -1 on memory error
- */
-extern int git_buf_crlf_to_lf(git_buf *tgt, const git_buf *src);
-
-/**
- * Replace all \n with \r\n. Does not modify existing \r\n.
- *
- * @return 0 on success, -1 on memory error
- */
-extern int git_buf_lf_to_crlf(git_buf *tgt, const git_buf *src);
-
-/**
- * Fill buffer with the common prefix of a array of strings
- *
- * Buffer will be set to empty if there is no common prefix
- */
-extern int git_buf_common_prefix(git_buf *buf, char *const *const strings, size_t count);
-
-/**
- * Check if a buffer begins with a UTF BOM
- *
- * @param bom Set to the type of BOM detected or GIT_BOM_NONE
- * @param buf Buffer in which to check the first bytes for a BOM
- * @return Number of bytes of BOM data (or 0 if no BOM found)
- */
-extern int git_buf_detect_bom(git_buf_bom_t *bom, const git_buf *buf);
-
-/**
- * Gather stats for a piece of text
- *
- * Fill the `stats` structure with counts of unreadable characters, carriage
- * returns, etc, so it can be used in heuristics.  This automatically skips
- * a trailing EOF (\032 character).  Also it will look for a BOM at the
- * start of the text and can be told to skip that as well.
- *
- * @param stats Structure to be filled in
- * @param buf Text to process
- * @param skip_bom Exclude leading BOM from stats if true
- * @return Does the buffer heuristically look like binary data
- */
-extern bool git_buf_gather_text_stats(
-       git_buf_text_stats *stats, const git_buf *buf, bool skip_bom);
-
-#ifdef GIT_DEPRECATE_HARD
-
-/**
-* Check quickly if buffer looks like it contains binary data
-*
-* @param buf Buffer to check
-* @return 1 if buffer looks like non-text data
-*/
-int git_buf_is_binary(const git_buf *buf);
-
-/**
-* Check quickly if buffer contains a NUL byte
-*
-* @param buf Buffer to check
-* @return 1 if buffer contains a NUL byte
-*/
-int git_buf_contains_nul(const git_buf *buf);
-
-#endif
-
-#endif
index f701b2d9351912e6259e9ae8a4107915f597a896..a0971e86c9885bf4d2f9b647e0ba8b24ee84c3f0 100644 (file)
@@ -75,7 +75,7 @@
 #      define PRIdZ "zd"
 #endif
 
-/* Micosoft Visual C/C++ */
+/* Microsoft Visual C/C++ */
 #if defined(_MSC_VER)
 /* disable "deprecated function" warnings */
 #      pragma warning ( disable : 4996 )
index 3a171066b4e725dba8783879301930ceb72e13e5..6a4643196b00b355cca58d6c608230454b78b13f 100644 (file)
 #include "diff_generate.h"
 #include "pathspec.h"
 #include "diff_xdiff.h"
-#include "path.h"
+#include "fs_path.h"
 #include "attr.h"
 #include "pool.h"
 #include "strmap.h"
+#include "path.h"
 
 /* See docs/checkout-internals.md for more information */
 
@@ -44,7 +45,7 @@ enum {
        CHECKOUT_ACTION__UPDATE_CONFLICT = 32,
        CHECKOUT_ACTION__MAX = 32,
        CHECKOUT_ACTION__REMOVE_AND_UPDATE =
-               (CHECKOUT_ACTION__UPDATE_BLOB | CHECKOUT_ACTION__REMOVE),
+               (CHECKOUT_ACTION__UPDATE_BLOB | CHECKOUT_ACTION__REMOVE)
 };
 
 typedef struct {
@@ -61,9 +62,9 @@ typedef struct {
        git_vector update_conflicts;
        git_vector *update_reuc;
        git_vector *update_names;
-       git_buf target_path;
+       git_str target_path;
        size_t target_len;
-       git_buf tmp;
+       git_str tmp;
        unsigned int strategy;
        int can_symlink;
        int respect_filemode;
@@ -80,11 +81,11 @@ typedef struct {
        const git_index_entry *ours;
        const git_index_entry *theirs;
 
-       int name_collision:1,
-               directoryfile:1,
-               one_to_two:1,
-               binary:1,
-               submodule:1;
+       unsigned int name_collision:1,
+                    directoryfile:1,
+                    one_to_two:1,
+                    binary:1,
+                    submodule:1;
 } checkout_conflictdata;
 
 static int checkout_notify(
@@ -321,14 +322,14 @@ static int checkout_action_no_wd(
 }
 
 static int checkout_target_fullpath(
-       git_buf **out, checkout_data *data, const char *path)
+       git_str **out, checkout_data *data, const char *path)
 {
-       git_buf_truncate(&data->target_path, data->target_len);
+       git_str_truncate(&data->target_path, data->target_len);
 
-       if (path && git_buf_puts(&data->target_path, path) < 0)
+       if (path && git_str_puts(&data->target_path, path) < 0)
                return -1;
 
-       if (git_path_validate_workdir_buf(data->repo, &data->target_path) < 0)
+       if (git_path_validate_str_length(data->repo, &data->target_path) < 0)
                return -1;
 
        *out = &data->target_path;
@@ -339,7 +340,7 @@ static int checkout_target_fullpath(
 static bool wd_item_is_removable(
        checkout_data *data, const git_index_entry *wd)
 {
-       git_buf *full;
+       git_str *full;
 
        if (wd->mode != GIT_FILEMODE_TREE)
                return true;
@@ -347,7 +348,7 @@ static bool wd_item_is_removable(
        if (checkout_target_fullpath(&full, data, wd->path) < 0)
                return false;
 
-       return !full || !git_path_contains(full, DOT_GIT);
+       return !full || !git_fs_path_contains(full, DOT_GIT);
 }
 
 static int checkout_queue_remove(checkout_data *data, const char *path)
@@ -423,7 +424,7 @@ static int checkout_action_wd_only(
 
                /* copy the entry for issuing notification callback later */
                git_index_entry saved_wd = *wd;
-               git_buf_sets(&data->tmp, wd->path);
+               git_str_sets(&data->tmp, wd->path);
                saved_wd.path = data->tmp.ptr;
 
                error = git_iterator_advance_over(
@@ -476,12 +477,12 @@ static bool submodule_is_config_only(
 
 static bool checkout_is_empty_dir(checkout_data *data, const char *path)
 {
-       git_buf *fullpath;
+       git_str *fullpath;
 
        if (checkout_target_fullpath(&fullpath, data, path) < 0)
                return false;
 
-       return git_path_is_empty_dir(fullpath->ptr);
+       return git_fs_path_is_empty_dir(fullpath->ptr);
 }
 
 static int checkout_action_with_wd(
@@ -962,7 +963,7 @@ static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, g
 {
        git_index *index;
 
-       /* Only write conficts from sources that have them: indexes. */
+       /* Only write conflicts from sources that have them: indexes. */
        if ((index = git_iterator_index(data->target)) == NULL)
                return 0;
 
@@ -1201,12 +1202,12 @@ static int checkout_conflicts_mark_directoryfile(
                                goto done;
                        }
 
-                       prefixed = git_path_equal_or_prefixed(path, entry->path, NULL);
+                       prefixed = git_fs_path_equal_or_prefixed(path, entry->path, NULL);
 
-                       if (prefixed == GIT_PATH_EQUAL)
+                       if (prefixed == GIT_FS_PATH_EQUAL)
                                continue;
 
-                       if (prefixed == GIT_PATH_PREFIX)
+                       if (prefixed == GIT_FS_PATH_PREFIX)
                                conflict->directoryfile = 1;
 
                        break;
@@ -1280,14 +1281,14 @@ static int checkout_verify_paths(
        unsigned int flags = GIT_PATH_REJECT_WORKDIR_DEFAULTS;
 
        if (action & CHECKOUT_ACTION__REMOVE) {
-               if (!git_path_validate(repo, delta->old_file.path, delta->old_file.mode, flags)) {
+               if (!git_path_is_valid(repo, delta->old_file.path, delta->old_file.mode, flags)) {
                        git_error_set(GIT_ERROR_CHECKOUT, "cannot remove invalid path '%s'", delta->old_file.path);
                        return -1;
                }
        }
 
        if (action & ~CHECKOUT_ACTION__REMOVE) {
-               if (!git_path_validate(repo, delta->new_file.path, delta->new_file.mode, flags)) {
+               if (!git_path_is_valid(repo, delta->new_file.path, delta->new_file.mode, flags)) {
                        git_error_set(GIT_ERROR_CHECKOUT, "cannot checkout to invalid path '%s'", delta->new_file.path);
                        return -1;
                }
@@ -1584,7 +1585,7 @@ static int blob_content_to_link(
        git_blob *blob,
        const char *path)
 {
-       git_buf linktarget = GIT_BUF_INIT;
+       git_str linktarget = GIT_STR_INIT;
        int error;
 
        if ((error = mkpath2file(data, path, data->opts.dir_mode)) < 0)
@@ -1594,10 +1595,10 @@ static int blob_content_to_link(
                return error;
 
        if (data->can_symlink) {
-               if ((error = p_symlink(git_buf_cstr(&linktarget), path)) < 0)
+               if ((error = p_symlink(git_str_cstr(&linktarget), path)) < 0)
                        git_error_set(GIT_ERROR_OS, "could not create symlink %s", path);
        } else {
-               error = git_futils_fake_symlink(git_buf_cstr(&linktarget), path);
+               error = git_futils_fake_symlink(git_str_cstr(&linktarget), path);
        }
 
        if (!error) {
@@ -1609,7 +1610,7 @@ static int blob_content_to_link(
                st->st_mode = GIT_FILEMODE_LINK;
        }
 
-       git_buf_dispose(&linktarget);
+       git_str_dispose(&linktarget);
 
        return error;
 }
@@ -1636,7 +1637,7 @@ static int checkout_submodule_update_index(
        checkout_data *data,
        const git_diff_file *file)
 {
-       git_buf *fullpath;
+       git_str *fullpath;
        struct stat st;
 
        /* update the index unless prevented */
@@ -1772,7 +1773,7 @@ static int checkout_blob(
        checkout_data *data,
        const git_diff_file *file)
 {
-       git_buf *fullpath;
+       git_str *fullpath;
        struct stat st;
        int error = 0;
 
@@ -1809,7 +1810,7 @@ static int checkout_remove_the_old(
        git_diff_delta *delta;
        const char *str;
        size_t i;
-       git_buf *fullpath;
+       git_str *fullpath;
        uint32_t flg = GIT_RMDIR_EMPTY_PARENTS |
                GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_REMOVE_BLOCKERS;
 
@@ -1927,40 +1928,40 @@ static int checkout_lookup_head_tree(git_tree **out, git_repository *repo)
 
 
 static int conflict_entry_name(
-       git_buf *out,
+       git_str *out,
        const char *side_name,
        const char *filename)
 {
-       if (git_buf_puts(out, side_name) < 0 ||
-               git_buf_putc(out, ':') < 0 ||
-               git_buf_puts(out, filename) < 0)
+       if (git_str_puts(out, side_name) < 0 ||
+               git_str_putc(out, ':') < 0 ||
+               git_str_puts(out, filename) < 0)
                return -1;
 
        return 0;
 }
 
-static int checkout_path_suffixed(git_buf *path, const char *suffix)
+static int checkout_path_suffixed(git_str *path, const char *suffix)
 {
        size_t path_len;
        int i = 0, error = 0;
 
-       if ((error = git_buf_putc(path, '~')) < 0 || (error = git_buf_puts(path, suffix)) < 0)
+       if ((error = git_str_putc(path, '~')) < 0 || (error = git_str_puts(path, suffix)) < 0)
                return -1;
 
-       path_len = git_buf_len(path);
+       path_len = git_str_len(path);
 
-       while (git_path_exists(git_buf_cstr(path)) && i < INT_MAX) {
-               git_buf_truncate(path, path_len);
+       while (git_fs_path_exists(git_str_cstr(path)) && i < INT_MAX) {
+               git_str_truncate(path, path_len);
 
-               if ((error = git_buf_putc(path, '_')) < 0 ||
-                       (error = git_buf_printf(path, "%d", i)) < 0)
+               if ((error = git_str_putc(path, '_')) < 0 ||
+                       (error = git_str_printf(path, "%d", i)) < 0)
                        return error;
 
                i++;
        }
 
        if (i == INT_MAX) {
-               git_buf_truncate(path, path_len);
+               git_str_truncate(path, path_len);
 
                git_error_set(GIT_ERROR_CHECKOUT, "could not write '%s': working directory file exists", path->ptr);
                return GIT_EEXISTS;
@@ -1974,8 +1975,8 @@ static int checkout_write_entry(
        checkout_conflictdata *conflict,
        const git_index_entry *side)
 {
-       const char *hint_path, *suffix;
-       git_buf *fullpath;
+       const char *hint_path = NULL, *suffix;
+       git_str *fullpath;
        struct stat st;
        int error;
 
@@ -2025,7 +2026,7 @@ static int checkout_write_entries(
 }
 
 static int checkout_merge_path(
-       git_buf *out,
+       git_str *out,
        checkout_data *data,
        checkout_conflictdata *conflict,
        git_merge_file_result *result)
@@ -2033,8 +2034,8 @@ static int checkout_merge_path(
        const char *our_label_raw, *their_label_raw, *suffix;
        int error = 0;
 
-       if ((error = git_buf_joinpath(out, data->opts.target_directory, result->path)) < 0 ||
-           (error = git_path_validate_workdir_buf(data->repo, out)) < 0)
+       if ((error = git_str_joinpath(out, data->opts.target_directory, result->path)) < 0 ||
+           (error = git_path_validate_str_length(data->repo, out)) < 0)
                return error;
 
        /* Most conflicts simply use the filename in the index */
@@ -2056,9 +2057,9 @@ static int checkout_write_merge(
        checkout_data *data,
        checkout_conflictdata *conflict)
 {
-       git_buf our_label = GIT_BUF_INIT, their_label = GIT_BUF_INIT,
-               path_suffixed = GIT_BUF_INIT, path_workdir = GIT_BUF_INIT,
-               in_data = GIT_BUF_INIT, out_data = GIT_BUF_INIT;
+       git_str our_label = GIT_STR_INIT, their_label = GIT_STR_INIT,
+               path_suffixed = GIT_STR_INIT, path_workdir = GIT_STR_INIT,
+               in_data = GIT_STR_INIT, out_data = GIT_STR_INIT;
        git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT;
        git_merge_file_result result = {0};
        git_filebuf output = GIT_FILEBUF_INIT;
@@ -2069,6 +2070,9 @@ static int checkout_write_merge(
        if (data->opts.checkout_strategy & GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)
                opts.flags |= GIT_MERGE_FILE_STYLE_DIFF3;
 
+       if (data->opts.checkout_strategy & GIT_CHECKOUT_CONFLICT_STYLE_ZDIFF3)
+               opts.flags |= GIT_MERGE_FILE_STYLE_ZDIFF3;
+
        opts.ancestor_label = data->opts.ancestor_label ?
                data->opts.ancestor_label : "ancestor";
        opts.our_label = data->opts.our_label ?
@@ -2088,8 +2092,8 @@ static int checkout_write_merge(
                        &their_label, opts.their_label, conflict->theirs->path)) < 0)
                        goto done;
 
-               opts.our_label = git_buf_cstr(&our_label);
-               opts.their_label = git_buf_cstr(&their_label);
+               opts.our_label = git_str_cstr(&our_label);
+               opts.their_label = git_str_cstr(&their_label);
        }
 
        if ((error = git_merge_file_from_index(&result, data->repo,
@@ -2106,7 +2110,7 @@ static int checkout_write_merge(
                goto done;
 
        if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 &&
-               (error = checkout_safe_for_update_only(data, git_buf_cstr(&path_workdir), result.mode)) <= 0)
+               (error = checkout_safe_for_update_only(data, git_str_cstr(&path_workdir), result.mode)) <= 0)
                goto done;
 
        if (!data->opts.disable_filters) {
@@ -2127,7 +2131,7 @@ static int checkout_write_merge(
        }
 
        if ((error = mkpath2file(data, path_workdir.ptr, data->opts.dir_mode)) < 0 ||
-               (error = git_filebuf_open(&output, git_buf_cstr(&path_workdir), GIT_FILEBUF_DO_NOT_BUFFER, result.mode)) < 0 ||
+               (error = git_filebuf_open(&output, git_str_cstr(&path_workdir), GIT_FILEBUF_DO_NOT_BUFFER, result.mode)) < 0 ||
                (error = git_filebuf_write(&output, out_data.ptr, out_data.size)) < 0 ||
                (error = git_filebuf_commit(&output)) < 0)
                goto done;
@@ -2135,13 +2139,13 @@ static int checkout_write_merge(
 done:
        git_filter_list_free(fl);
 
-       git_buf_dispose(&out_data);
-       git_buf_dispose(&our_label);
-       git_buf_dispose(&their_label);
+       git_str_dispose(&out_data);
+       git_str_dispose(&our_label);
+       git_str_dispose(&their_label);
 
        git_merge_file_result_free(&result);
-       git_buf_dispose(&path_workdir);
-       git_buf_dispose(&path_suffixed);
+       git_str_dispose(&path_workdir);
+       git_str_dispose(&path_suffixed);
 
        return error;
 }
@@ -2321,8 +2325,8 @@ static void checkout_data_clear(checkout_data *data)
        git__free(data->pfx);
        data->pfx = NULL;
 
-       git_buf_dispose(&data->target_path);
-       git_buf_dispose(&data->tmp);
+       git_str_dispose(&data->target_path);
+       git_str_dispose(&data->tmp);
 
        git_index_free(data->index);
        data->index = NULL;
@@ -2337,10 +2341,10 @@ static int validate_target_directory(checkout_data *data)
 {
        int error;
 
-       if ((error = git_path_validate_workdir(data->repo, data->opts.target_directory)) < 0)
+       if ((error = git_path_validate_length(data->repo, data->opts.target_directory)) < 0)
                return error;
 
-       if (git_path_isdir(data->opts.target_directory))
+       if (git_fs_path_isdir(data->opts.target_directory))
                return 0;
 
        error = checkout_mkdir(data, data->opts.target_directory, NULL,
@@ -2492,6 +2496,8 @@ static int checkout_data_init(
                        data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_MERGE;
                else if (strcmp(conflict_style->value, "diff3") == 0)
                        data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_DIFF3;
+               else if (strcmp(conflict_style->value, "zdiff3") == 0)
+                       data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_ZDIFF3;
                else {
                        git_error_set(GIT_ERROR_CHECKOUT, "unknown style '%s' given for 'merge.conflictstyle'",
                                conflict_style->value);
@@ -2506,12 +2512,12 @@ static int checkout_data_init(
            (error = git_vector_init(&data->removes, 0, git__strcmp_cb)) < 0 ||
            (error = git_vector_init(&data->remove_conflicts, 0, NULL)) < 0 ||
            (error = git_vector_init(&data->update_conflicts, 0, NULL)) < 0 ||
-           (error = git_buf_puts(&data->target_path, data->opts.target_directory)) < 0 ||
-           (error = git_path_to_dir(&data->target_path)) < 0 ||
+           (error = git_str_puts(&data->target_path, data->opts.target_directory)) < 0 ||
+           (error = git_fs_path_to_dir(&data->target_path)) < 0 ||
            (error = git_strmap_new(&data->mkdir_map)) < 0)
                goto cleanup;
 
-       data->target_len = git_buf_len(&data->target_path);
+       data->target_len = git_str_len(&data->target_path);
 
        git_attr_session__init(&data->attr_session, data->repo);
 
@@ -2623,7 +2629,7 @@ int git_checkout_iterator(
 
        if (data.strategy & GIT_CHECKOUT_DRY_RUN)
                goto cleanup;
-       
+
        data.total_steps = counts[CHECKOUT_ACTION__REMOVE] +
                counts[CHECKOUT_ACTION__REMOVE_CONFLICT] +
                counts[CHECKOUT_ACTION__UPDATE_BLOB] +
index 4287956c9c3a58e8816910019c224bfde5b20692..9ec4962b99a77c07615be88d9a422318735c1c2b 100644 (file)
@@ -26,10 +26,10 @@ static int write_cherrypick_head(
        const char *commit_oidstr)
 {
        git_filebuf file = GIT_FILEBUF_INIT;
-       git_buf file_path = GIT_BUF_INIT;
+       git_str file_path = GIT_STR_INIT;
        int error = 0;
 
-       if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_CHERRYPICK_HEAD_FILE)) >= 0 &&
+       if ((error = git_str_joinpath(&file_path, repo->gitdir, GIT_CHERRYPICK_HEAD_FILE)) >= 0 &&
                (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_CHERRYPICK_FILE_MODE)) >= 0 &&
                (error = git_filebuf_printf(&file, "%s\n", commit_oidstr)) >= 0)
                error = git_filebuf_commit(&file);
@@ -37,7 +37,7 @@ static int write_cherrypick_head(
        if (error < 0)
                git_filebuf_cleanup(&file);
 
-       git_buf_dispose(&file_path);
+       git_str_dispose(&file_path);
 
        return error;
 }
@@ -47,10 +47,10 @@ static int write_merge_msg(
        const char *commit_msg)
 {
        git_filebuf file = GIT_FILEBUF_INIT;
-       git_buf file_path = GIT_BUF_INIT;
+       git_str file_path = GIT_STR_INIT;
        int error = 0;
 
-       if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
+       if ((error = git_str_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
                (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_CHERRYPICK_FILE_MODE)) < 0 ||
                (error = git_filebuf_printf(&file, "%s", commit_msg)) < 0)
                goto cleanup;
@@ -61,7 +61,7 @@ cleanup:
        if (error < 0)
                git_filebuf_cleanup(&file);
 
-       git_buf_dispose(&file_path);
+       git_str_dispose(&file_path);
 
        return error;
 }
@@ -175,7 +175,7 @@ int git_cherrypick(
        git_commit *our_commit = NULL;
        char commit_oidstr[GIT_OID_HEXSZ + 1];
        const char *commit_msg, *commit_summary;
-       git_buf their_label = GIT_BUF_INIT;
+       git_str their_label = GIT_STR_INIT;
        git_index *index = NULL;
        git_indexwriter indexwriter = GIT_INDEXWRITER_INIT;
        int error = 0;
@@ -197,8 +197,8 @@ int git_cherrypick(
        git_oid_nfmt(commit_oidstr, sizeof(commit_oidstr), git_commit_id(commit));
 
        if ((error = write_merge_msg(repo, commit_msg)) < 0 ||
-               (error = git_buf_printf(&their_label, "%.7s... %s", commit_oidstr, commit_summary)) < 0 ||
-               (error = cherrypick_normalize_opts(repo, &opts, given_opts, git_buf_cstr(&their_label))) < 0 ||
+               (error = git_str_printf(&their_label, "%.7s... %s", commit_oidstr, commit_summary)) < 0 ||
+               (error = cherrypick_normalize_opts(repo, &opts, given_opts, git_str_cstr(&their_label))) < 0 ||
                (error = git_indexwriter_init_for_operation(&indexwriter, repo, &opts.checkout_opts.checkout_strategy)) < 0 ||
                (error = write_cherrypick_head(repo, commit_oidstr)) < 0 ||
                (error = git_repository_head(&our_ref, repo)) < 0 ||
@@ -220,7 +220,7 @@ done:
        git_index_free(index);
        git_commit_free(our_commit);
        git_reference_free(our_ref);
-       git_buf_dispose(&their_label);
+       git_str_dispose(&their_label);
 
        return error;
 }
index 752df3b92d864f7772b2106a5aa4dd5d23ccc941..1843875f8e541f6fff5cf3af83c9fb73173aeab2 100644 (file)
@@ -19,7 +19,7 @@
 #include "remote.h"
 #include "futils.h"
 #include "refs.h"
-#include "path.h"
+#include "fs_path.h"
 #include "repository.h"
 #include "odb.h"
 
@@ -34,7 +34,7 @@ static int create_branch(
 {
        git_commit *head_obj = NULL;
        git_reference *branch_ref = NULL;
-       git_buf refname = GIT_BUF_INIT;
+       git_str refname = GIT_STR_INIT;
        int error;
 
        /* Find the target commit */
@@ -42,11 +42,11 @@ static int create_branch(
                return error;
 
        /* Create the new branch */
-       if ((error = git_buf_printf(&refname, GIT_REFS_HEADS_DIR "%s", name)) < 0)
+       if ((error = git_str_printf(&refname, GIT_REFS_HEADS_DIR "%s", name)) < 0)
                return error;
 
-       error = git_reference_create(&branch_ref, repo, git_buf_cstr(&refname), target, 0, log_message);
-       git_buf_dispose(&refname);
+       error = git_reference_create(&branch_ref, repo, git_str_cstr(&refname), target, 0, log_message);
+       git_str_dispose(&refname);
        git_commit_free(head_obj);
 
        if (!error)
@@ -64,29 +64,29 @@ static int setup_tracking_config(
        const char *merge_target)
 {
        git_config *cfg;
-       git_buf remote_key = GIT_BUF_INIT, merge_key = GIT_BUF_INIT;
+       git_str remote_key = GIT_STR_INIT, merge_key = GIT_STR_INIT;
        int error = -1;
 
        if (git_repository_config__weakptr(&cfg, repo) < 0)
                return -1;
 
-       if (git_buf_printf(&remote_key, "branch.%s.remote", branch_name) < 0)
+       if (git_str_printf(&remote_key, "branch.%s.remote", branch_name) < 0)
                goto cleanup;
 
-       if (git_buf_printf(&merge_key, "branch.%s.merge", branch_name) < 0)
+       if (git_str_printf(&merge_key, "branch.%s.merge", branch_name) < 0)
                goto cleanup;
 
-       if (git_config_set_string(cfg, git_buf_cstr(&remote_key), remote_name) < 0)
+       if (git_config_set_string(cfg, git_str_cstr(&remote_key), remote_name) < 0)
                goto cleanup;
 
-       if (git_config_set_string(cfg, git_buf_cstr(&merge_key), merge_target) < 0)
+       if (git_config_set_string(cfg, git_str_cstr(&merge_key), merge_target) < 0)
                goto cleanup;
 
        error = 0;
 
 cleanup:
-       git_buf_dispose(&remote_key);
-       git_buf_dispose(&merge_key);
+       git_str_dispose(&remote_key);
+       git_str_dispose(&merge_key);
        return error;
 }
 
@@ -139,7 +139,7 @@ static int update_head_to_new_branch(
 
 static int update_head_to_default(git_repository *repo)
 {
-       git_buf initialbranch = GIT_BUF_INIT;
+       git_str initialbranch = GIT_STR_INIT;
        const char *branch_name;
        int error = 0;
 
@@ -158,24 +158,24 @@ static int update_head_to_default(git_repository *repo)
                initialbranch.ptr);
 
 done:
-       git_buf_dispose(&initialbranch);
+       git_str_dispose(&initialbranch);
        return error;
 }
 
 static int update_remote_head(
        git_repository *repo,
        git_remote *remote,
-       git_buf *target,
+       git_str *target,
        const char *reflog_message)
 {
        git_refspec *refspec;
        git_reference *remote_head = NULL;
-       git_buf remote_head_name = GIT_BUF_INIT;
-       git_buf remote_branch_name = GIT_BUF_INIT;
+       git_str remote_head_name = GIT_STR_INIT;
+       git_str remote_branch_name = GIT_STR_INIT;
        int error;
 
        /* Determine the remote tracking ref name from the local branch */
-       refspec = git_remote__matching_refspec(remote, git_buf_cstr(target));
+       refspec = git_remote__matching_refspec(remote, git_str_cstr(target));
 
        if (refspec == NULL) {
                git_error_set(GIT_ERROR_NET, "the remote's default branch does not fit the refspec configuration");
@@ -183,13 +183,13 @@ static int update_remote_head(
                goto cleanup;
        }
 
-       if ((error = git_refspec_transform(
+       if ((error = git_refspec__transform(
                &remote_branch_name,
                refspec,
-               git_buf_cstr(target))) < 0)
+               git_str_cstr(target))) < 0)
                goto cleanup;
 
-       if ((error = git_buf_printf(&remote_head_name,
+       if ((error = git_str_printf(&remote_head_name,
                "%s%s/%s",
                GIT_REFS_REMOTES_DIR,
                git_remote_name(remote),
@@ -199,15 +199,15 @@ static int update_remote_head(
        error = git_reference_symbolic_create(
                &remote_head,
                repo,
-               git_buf_cstr(&remote_head_name),
-               git_buf_cstr(&remote_branch_name),
+               git_str_cstr(&remote_head_name),
+               git_str_cstr(&remote_branch_name),
                true,
                reflog_message);
 
 cleanup:
        git_reference_free(remote_head);
-       git_buf_dispose(&remote_branch_name);
-       git_buf_dispose(&remote_head_name);
+       git_str_dispose(&remote_branch_name);
+       git_str_dispose(&remote_head_name);
        return error;
 }
 
@@ -220,7 +220,7 @@ static int update_head_to_remote(
        size_t refs_len;
        const git_remote_head *remote_head, **refs;
        const git_oid *remote_head_id;
-       git_buf branch = GIT_BUF_INIT;
+       git_str branch = GIT_STR_INIT;
 
        if ((error = git_remote_ls(&refs, &refs_len, remote)) < 0)
                return error;
@@ -235,7 +235,7 @@ static int update_head_to_remote(
 
        remote_head_id = &remote_head->oid;
 
-       error = git_remote_default_branch(&branch, remote);
+       error = git_remote__default_branch(&branch, remote);
        if (error == GIT_ENOTFOUND) {
                error = git_repository_set_head_detached(
                        repo, remote_head_id);
@@ -248,11 +248,11 @@ static int update_head_to_remote(
        error = update_head_to_new_branch(
                repo,
                remote_head_id,
-               git_buf_cstr(&branch),
+               git_str_cstr(&branch),
                reflog_message);
 
 cleanup:
-       git_buf_dispose(&branch);
+       git_str_dispose(&branch);
 
        return error;
 }
@@ -264,36 +264,36 @@ static int update_head_to_branch(
                const char *reflog_message)
 {
        int retcode;
-       git_buf remote_branch_name = GIT_BUF_INIT;
+       git_str remote_branch_name = GIT_STR_INIT;
        git_reference *remote_ref = NULL;
-       git_buf default_branch = GIT_BUF_INIT;
+       git_str default_branch = GIT_STR_INIT;
 
        GIT_ASSERT_ARG(remote);
        GIT_ASSERT_ARG(branch);
 
-       if ((retcode = git_buf_printf(&remote_branch_name, GIT_REFS_REMOTES_DIR "%s/%s",
+       if ((retcode = git_str_printf(&remote_branch_name, GIT_REFS_REMOTES_DIR "%s/%s",
                git_remote_name(remote), branch)) < 0 )
                goto cleanup;
 
-       if ((retcode = git_reference_lookup(&remote_ref, repo, git_buf_cstr(&remote_branch_name))) < 0)
+       if ((retcode = git_reference_lookup(&remote_ref, repo, git_str_cstr(&remote_branch_name))) < 0)
                goto cleanup;
 
        if ((retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch,
                        reflog_message)) < 0)
                goto cleanup;
 
-       if ((retcode = git_remote_default_branch(&default_branch, remote)) < 0)
+       if ((retcode = git_remote__default_branch(&default_branch, remote)) < 0)
                goto cleanup;
 
-       if (!git_remote__matching_refspec(remote, git_buf_cstr(&default_branch)))
+       if (!git_remote__matching_refspec(remote, git_str_cstr(&default_branch)))
                goto cleanup;
 
        retcode = update_remote_head(repo, remote, &default_branch, reflog_message);
 
 cleanup:
        git_reference_free(remote_ref);
-       git_buf_dispose(&remote_branch_name);
-       git_buf_dispose(&default_branch);
+       git_str_dispose(&remote_branch_name);
+       git_str_dispose(&default_branch);
        return retcode;
 }
 
@@ -333,7 +333,7 @@ static int create_and_configure_origin(
        void *payload = options->remote_cb_payload;
 
        /* If the path exists and is a dir, the url should be the absolute path */
-       if (git_path_root(url) < 0 && git_path_exists(url) && git_path_isdir(url)) {
+       if (git_fs_path_root(url) < 0 && git_fs_path_exists(url) && git_fs_path_isdir(url)) {
                if (p_realpath(url, buf) == NULL)
                        return -1;
 
@@ -392,7 +392,7 @@ static int checkout_branch(git_repository *repo, git_remote *remote, const git_c
 static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch_options *opts, const git_checkout_options *co_opts, const char *branch)
 {
        int error;
-       git_buf reflog_message = GIT_BUF_INIT;
+       git_str reflog_message = GIT_STR_INIT;
        git_fetch_options fetch_opts;
        git_remote *remote;
 
@@ -410,31 +410,31 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch
        memcpy(&fetch_opts, opts, sizeof(git_fetch_options));
        fetch_opts.update_fetchhead = 0;
        fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
-       git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
+       git_str_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
 
-       if ((error = git_remote_fetch(remote, NULL, &fetch_opts, git_buf_cstr(&reflog_message))) != 0)
+       if ((error = git_remote_fetch(remote, NULL, &fetch_opts, git_str_cstr(&reflog_message))) != 0)
                goto cleanup;
 
-       error = checkout_branch(repo, remote, co_opts, branch, git_buf_cstr(&reflog_message));
+       error = checkout_branch(repo, remote, co_opts, branch, git_str_cstr(&reflog_message));
 
 cleanup:
        git_remote_free(remote);
-       git_buf_dispose(&reflog_message);
+       git_str_dispose(&reflog_message);
 
        return error;
 }
 
 int git_clone__should_clone_local(const char *url_or_path, git_clone_local_t local)
 {
-       git_buf fromurl = GIT_BUF_INIT;
+       git_str fromurl = GIT_STR_INIT;
        const char *path = url_or_path;
        bool is_url, is_local;
 
        if (local == GIT_CLONE_NO_LOCAL)
                return 0;
 
-       if ((is_url = git_path_is_local_file_url(url_or_path)) != 0) {
-               if (git_path_fromurl(&fromurl, url_or_path) < 0) {
+       if ((is_url = git_fs_path_is_local_file_url(url_or_path)) != 0) {
+               if (git_fs_path_fromurl(&fromurl, url_or_path) < 0) {
                        is_local = -1;
                        goto done;
                }
@@ -443,10 +443,10 @@ int git_clone__should_clone_local(const char *url_or_path, git_clone_local_t loc
        }
 
        is_local = (!is_url || local != GIT_CLONE_LOCAL_AUTO) &&
-               git_path_isdir(path);
+               git_fs_path_isdir(path);
 
 done:
-       git_buf_dispose(&fromurl);
+       git_str_dispose(&fromurl);
        return is_local;
 }
 
@@ -474,14 +474,14 @@ static int git__clone(
        GIT_ERROR_CHECK_VERSION(&options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options");
 
        /* Only clone to a new directory or an empty directory */
-       if (git_path_exists(local_path) && !use_existing && !git_path_is_empty_dir(local_path)) {
+       if (git_fs_path_exists(local_path) && !use_existing && !git_fs_path_is_empty_dir(local_path)) {
                git_error_set(GIT_ERROR_INVALID,
                        "'%s' exists and is not an empty directory", local_path);
                return GIT_EEXISTS;
        }
 
        /* Only remove the root directory on failure if we create it */
-       if (git_path_exists(local_path))
+       if (git_fs_path_exists(local_path))
                rmdir_flags |= GIT_RMDIR_SKIP_ROOT;
 
        if (options.repository_cb)
@@ -586,8 +586,8 @@ static int clone_local_into(git_repository *repo, git_remote *remote, const git_
 {
        int error, flags;
        git_repository *src;
-       git_buf src_odb = GIT_BUF_INIT, dst_odb = GIT_BUF_INIT, src_path = GIT_BUF_INIT;
-       git_buf reflog_message = GIT_BUF_INIT;
+       git_str src_odb = GIT_STR_INIT, dst_odb = GIT_STR_INIT, src_path = GIT_STR_INIT;
+       git_str reflog_message = GIT_STR_INIT;
 
        GIT_ASSERT_ARG(repo);
        GIT_ASSERT_ARG(remote);
@@ -602,17 +602,17 @@ static int clone_local_into(git_repository *repo, git_remote *remote, const git_
         * repo, if it's not rooted, the path should be relative to
         * the repository's worktree/gitdir.
         */
-       if ((error = git_path_from_url_or_path(&src_path, git_remote_url(remote))) < 0)
+       if ((error = git_fs_path_from_url_or_path(&src_path, git_remote_url(remote))) < 0)
                return error;
 
        /* Copy .git/objects/ from the source to the target */
-       if ((error = git_repository_open(&src, git_buf_cstr(&src_path))) < 0) {
-               git_buf_dispose(&src_path);
+       if ((error = git_repository_open(&src, git_str_cstr(&src_path))) < 0) {
+               git_str_dispose(&src_path);
                return error;
        }
 
-       if (git_repository_item_path(&src_odb, src, GIT_REPOSITORY_ITEM_OBJECTS) < 0
-               || git_repository_item_path(&dst_odb, repo, GIT_REPOSITORY_ITEM_OBJECTS) < 0) {
+       if (git_repository__item_path(&src_odb, src, GIT_REPOSITORY_ITEM_OBJECTS) < 0 ||
+           git_repository__item_path(&dst_odb, repo, GIT_REPOSITORY_ITEM_OBJECTS) < 0) {
                error = -1;
                goto cleanup;
        }
@@ -621,7 +621,7 @@ static int clone_local_into(git_repository *repo, git_remote *remote, const git_
        if (can_link(git_repository_path(src), git_repository_path(repo), link))
                flags |= GIT_CPDIR_LINK_FILES;
 
-       error = git_futils_cp_r(git_buf_cstr(&src_odb), git_buf_cstr(&dst_odb),
+       error = git_futils_cp_r(git_str_cstr(&src_odb), git_str_cstr(&dst_odb),
                                flags, GIT_OBJECT_DIR_MODE);
 
        /*
@@ -631,25 +631,25 @@ static int clone_local_into(git_repository *repo, git_remote *remote, const git_
         */
        if (error < 0 && link) {
                flags &= ~GIT_CPDIR_LINK_FILES;
-               error = git_futils_cp_r(git_buf_cstr(&src_odb), git_buf_cstr(&dst_odb),
+               error = git_futils_cp_r(git_str_cstr(&src_odb), git_str_cstr(&dst_odb),
                                        flags, GIT_OBJECT_DIR_MODE);
        }
 
        if (error < 0)
                goto cleanup;
 
-       git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
+       git_str_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
 
-       if ((error = git_remote_fetch(remote, NULL, fetch_opts, git_buf_cstr(&reflog_message))) != 0)
+       if ((error = git_remote_fetch(remote, NULL, fetch_opts, git_str_cstr(&reflog_message))) != 0)
                goto cleanup;
 
-       error = checkout_branch(repo, remote, co_opts, branch, git_buf_cstr(&reflog_message));
+       error = checkout_branch(repo, remote, co_opts, branch, git_str_cstr(&reflog_message));
 
 cleanup:
-       git_buf_dispose(&reflog_message);
-       git_buf_dispose(&src_path);
-       git_buf_dispose(&src_odb);
-       git_buf_dispose(&dst_odb);
+       git_str_dispose(&reflog_message);
+       git_str_dispose(&src_path);
+       git_str_dispose(&src_odb);
+       git_str_dispose(&dst_odb);
        git_repository_free(src);
        return error;
 }
index 96259d5bb14c9929f990efc49802eedd60aa265f..b137463f3956db890cf1cf63fa29b094710bf767 100644 (file)
 #include "git2/mailmap.h"
 #include "git2/sys/commit.h"
 
+#include "buf.h"
 #include "odb.h"
 #include "commit.h"
 #include "signature.h"
-#include "message.h"
 #include "refs.h"
 #include "object.h"
 #include "array.h"
@@ -42,7 +42,7 @@ void git_commit__free(void *_commit)
 }
 
 static int git_commit__create_buffer_internal(
-       git_buf *out,
+       git_str *out,
        const git_signature *author,
        const git_signature *committer,
        const char *message_encoding,
@@ -67,17 +67,17 @@ static int git_commit__create_buffer_internal(
        git_signature__writebuf(out, "committer ", committer);
 
        if (message_encoding != NULL)
-               git_buf_printf(out, "encoding %s\n", message_encoding);
+               git_str_printf(out, "encoding %s\n", message_encoding);
 
-       git_buf_putc(out, '\n');
+       git_str_putc(out, '\n');
 
-       if (git_buf_puts(out, message) < 0)
+       if (git_str_puts(out, message) < 0)
                goto on_error;
 
        return 0;
 
 on_error:
-       git_buf_dispose(out);
+       git_str_dispose(out);
        return -1;
 }
 
@@ -136,7 +136,7 @@ static int git_commit__create_internal(
        int error;
        git_odb *odb;
        git_reference *ref = NULL;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        const git_oid *current_id = NULL;
        git_array_oid_t parents = GIT_ARRAY_INIT;
 
@@ -179,7 +179,7 @@ static int git_commit__create_internal(
 cleanup:
        git_array_clear(parents);
        git_reference_free(ref);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
@@ -395,6 +395,7 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig
        git_oid parent_id;
        size_t header_len;
        git_signature dummy_sig;
+       int error;
 
        GIT_ASSERT_ARG(commit);
        GIT_ASSERT_ARG(data);
@@ -431,14 +432,14 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig
                commit->author = git__malloc(sizeof(git_signature));
                GIT_ERROR_CHECK_ALLOC(commit->author);
 
-               if (git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n') < 0)
-                       return -1;
+               if ((error = git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n')) < 0)
+                       return error;
        }
 
        /* Some tools create multiple author fields, ignore the extra ones */
        while (!git__prefixncmp(buffer, buffer_end - buffer, "author ")) {
-               if (git_signature__parse(&dummy_sig, &buffer, buffer_end, "author ", '\n') < 0)
-                       return -1;
+               if ((error = git_signature__parse(&dummy_sig, &buffer, buffer_end, "author ", '\n')) < 0)
+                       return error;
 
                git__free(dummy_sig.name);
                git__free(dummy_sig.email);
@@ -448,8 +449,8 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig
        commit->committer = git__malloc(sizeof(git_signature));
        GIT_ERROR_CHECK_ALLOC(commit->committer);
 
-       if (git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n') < 0)
-               return -1;
+       if ((error = git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n')) < 0)
+               return error;
 
        if (flags & GIT_COMMIT_PARSE_QUICK)
                return 0;
@@ -493,7 +494,7 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig
 
 bad_buffer:
        git_error_set(GIT_ERROR_OBJECT, "failed to parse bad commit object");
-       return -1;
+       return GIT_EINVALID;
 }
 
 int git_commit__parse_raw(void *commit, const char *data, size_t size)
@@ -545,8 +546,8 @@ const char *git_commit_message(const git_commit *commit)
 
 const char *git_commit_summary(git_commit *commit)
 {
-       git_buf summary = GIT_BUF_INIT;
-       const char *msg, *space;
+       git_str summary = GIT_STR_INIT;
+       const char *msg, *space, *next;
        bool space_contains_newline = false;
 
        GIT_ASSERT_ARG_WITH_RETVAL(commit, NULL);
@@ -555,10 +556,21 @@ const char *git_commit_summary(git_commit *commit)
                for (msg = git_commit_message(commit), space = NULL; *msg; ++msg) {
                        char next_character = msg[0];
                        /* stop processing at the end of the first paragraph */
-                       if (next_character == '\n' && (!msg[1] || msg[1] == '\n'))
-                               break;
+                       if (next_character == '\n') {
+                               if (!msg[1])
+                                       break;
+                               if (msg[1] == '\n')
+                                       break;
+                               /* stop processing if next line contains only whitespace */
+                               next = msg + 1;
+                               while (*next && git__isspace_nonlf(*next)) {
+                                       ++next;
+                               }
+                               if (!*next || *next == '\n') 
+                                       break;
+                       }
                        /* record the beginning of contiguous whitespace runs */
-                       else if (git__isspace(next_character)) {
+                       if (git__isspace(next_character)) {
                                if(space == NULL) {
                                        space = msg;
                                        space_contains_newline = false;
@@ -570,17 +582,17 @@ const char *git_commit_summary(git_commit *commit)
                                /* process any recorded whitespace */
                                if (space) {
                                        if(space_contains_newline)
-                                               git_buf_putc(&summary, ' '); /* if the space contains a newline, collapse to ' ' */
+                                               git_str_putc(&summary, ' '); /* if the space contains a newline, collapse to ' ' */
                                        else
-                                               git_buf_put(&summary, space, (msg - space)); /* otherwise copy it */
+                                               git_str_put(&summary, space, (msg - space)); /* otherwise copy it */
                                        space = NULL;
                                }
                                /* copy the next character */
-                               git_buf_putc(&summary, next_character);
+                               git_str_putc(&summary, next_character);
                        }
                }
 
-               commit->summary = git_buf_detach(&summary);
+               commit->summary = git_str_detach(&summary);
                if (!commit->summary)
                        commit->summary = git__strdup("");
        }
@@ -678,11 +690,22 @@ int git_commit_nth_gen_ancestor(
        return 0;
 }
 
-int git_commit_header_field(git_buf *out, const git_commit *commit, const char *field)
+int git_commit_header_field(
+       git_buf *out,
+       const git_commit *commit,
+       const char *field)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_commit__header_field, commit, field);
+}
+
+int git_commit__header_field(
+       git_str *out,
+       const git_commit *commit,
+       const char *field)
 {
        const char *eol, *buf = commit->raw_header;
 
-       git_buf_clear(out);
+       git_str_clear(out);
 
        while ((eol = strchr(buf, '\n'))) {
                /* We can skip continuations here */
@@ -706,22 +729,22 @@ int git_commit_header_field(git_buf *out, const git_commit *commit, const char *
 
                buf++; /* skip the SP */
 
-               git_buf_put(out, buf, eol - buf);
-               if (git_buf_oom(out))
+               git_str_put(out, buf, eol - buf);
+               if (git_str_oom(out))
                        goto oom;
 
                /* If the next line starts with SP, it's multi-line, we must continue */
                while (eol[1] == ' ') {
-                       git_buf_putc(out, '\n');
+                       git_str_putc(out, '\n');
                        buf = eol + 2;
                        eol = strchr(buf, '\n');
                        if (!eol)
                                goto malformed;
 
-                       git_buf_put(out, buf, eol - buf);
+                       git_str_put(out, buf, eol - buf);
                }
 
-               if (git_buf_oom(out))
+               if (git_str_oom(out))
                        goto oom;
 
                return 0;
@@ -738,7 +761,35 @@ oom:
        return -1;
 }
 
-int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_repository *repo, git_oid *commit_id, const char *field)
+int git_commit_extract_signature(
+       git_buf *signature_out,
+       git_buf *signed_data_out,
+       git_repository *repo,
+       git_oid *commit_id,
+       const char *field)
+{
+       git_str signature = GIT_STR_INIT, signed_data = GIT_STR_INIT;
+       int error;
+
+       if ((error = git_buf_tostr(&signature, signature_out)) < 0 ||
+           (error = git_buf_tostr(&signed_data, signed_data_out)) < 0 ||
+           (error = git_commit__extract_signature(&signature, &signed_data, repo, commit_id, field)) < 0 ||
+           (error = git_buf_fromstr(signature_out, &signature)) < 0 ||
+           (error = git_buf_fromstr(signed_data_out, &signed_data)) < 0)
+               goto done;
+
+done:
+       git_str_dispose(&signature);
+       git_str_dispose(&signed_data);
+       return error;
+}
+
+int git_commit__extract_signature(
+       git_str *signature,
+       git_str *signed_data,
+       git_repository *repo,
+       git_oid *commit_id,
+       const char *field)
 {
        git_odb_object *obj;
        git_odb *odb;
@@ -746,8 +797,8 @@ int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_r
        const char *h, *eol;
        int error;
 
-       git_buf_clear(signature);
-       git_buf_clear(signed_data);
+       git_str_clear(signature);
+       git_str_clear(signed_data);
 
        if (!field)
                field = "gpgsig";
@@ -769,7 +820,7 @@ int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_r
        while ((h = strchr(buf, '\n')) && h[1] != '\0') {
                h++;
                if (git__prefixcmp(buf, field)) {
-                       if (git_buf_put(signed_data, buf, h - buf) < 0)
+                       if (git_str_put(signed_data, buf, h - buf) < 0)
                                return -1;
 
                        buf = h;
@@ -788,25 +839,25 @@ int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_r
 
                h++; /* skip the SP */
 
-               git_buf_put(signature, h, eol - h);
-               if (git_buf_oom(signature))
+               git_str_put(signature, h, eol - h);
+               if (git_str_oom(signature))
                        goto oom;
 
                /* If the next line starts with SP, it's multi-line, we must continue */
                while (eol[1] == ' ') {
-                       git_buf_putc(signature, '\n');
+                       git_str_putc(signature, '\n');
                        h = eol + 2;
                        eol = strchr(h, '\n');
                        if (!eol)
                                goto malformed;
 
-                       git_buf_put(signature, h, eol - h);
+                       git_str_put(signature, h, eol - h);
                }
 
-               if (git_buf_oom(signature))
+               if (git_str_oom(signature))
                        goto oom;
 
-               error = git_buf_puts(signed_data, eol+1);
+               error = git_str_puts(signed_data, eol+1);
                git_odb_object_free(obj);
                return error;
        }
@@ -826,12 +877,29 @@ oom:
 
 cleanup:
        git_odb_object_free(obj);
-       git_buf_clear(signature);
-       git_buf_clear(signed_data);
+       git_str_clear(signature);
+       git_str_clear(signed_data);
        return error;
 }
 
-int git_commit_create_buffer(git_buf *out,
+int git_commit_create_buffer(
+       git_buf *out,
+       git_repository *repo,
+       const git_signature *author,
+       const git_signature *committer,
+       const char *message_encoding,
+       const char *message,
+       const git_tree *tree,
+       size_t parent_count,
+       const git_commit *parents[])
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_commit__create_buffer, repo,
+                            author, committer, message_encoding, message,
+                            tree, parent_count, parents);
+}
+
+int git_commit__create_buffer(
+       git_str *out,
        git_repository *repo,
        const git_signature *author,
        const git_signature *committer,
@@ -866,7 +934,7 @@ int git_commit_create_buffer(git_buf *out,
 /**
  * Append to 'out' properly marking continuations when there's a newline in 'content'
  */
-static int format_header_field(git_buf *out, const char *field, const char *content)
+static int format_header_field(git_str *out, const char *field, const char *content)
 {
        const char *lf;
 
@@ -874,19 +942,19 @@ static int format_header_field(git_buf *out, const char *field, const char *cont
        GIT_ASSERT_ARG(field);
        GIT_ASSERT_ARG(content);
 
-       git_buf_puts(out, field);
-       git_buf_putc(out, ' ');
+       git_str_puts(out, field);
+       git_str_putc(out, ' ');
 
        while ((lf = strchr(content, '\n')) != NULL) {
-               git_buf_put(out, content, lf - content);
-               git_buf_puts(out, "\n ");
+               git_str_put(out, content, lf - content);
+               git_str_puts(out, "\n ");
                content = lf + 1;
        }
 
-       git_buf_puts(out, content);
-       git_buf_putc(out, '\n');
+       git_str_puts(out, content);
+       git_str_putc(out, '\n');
 
-       return git_buf_oom(out) ? -1 : 0;
+       return git_str_oom(out) ? -1 : 0;
 }
 
 static const git_oid *commit_parent_from_commit(size_t n, void *payload)
@@ -908,15 +976,17 @@ int git_commit_create_with_signature(
        int error = 0;
        const char *field;
        const char *header_end;
-       git_buf commit = GIT_BUF_INIT;
+       git_str commit = GIT_STR_INIT;
        git_commit *parsed;
        git_array_oid_t parents = GIT_ARRAY_INIT;
 
        /* The first step is to verify that all the tree and parents exist */
        parsed = git__calloc(1, sizeof(git_commit));
        GIT_ERROR_CHECK_ALLOC(parsed);
-       if ((error = commit_parse(parsed, commit_content, strlen(commit_content), 0)) < 0)
+       if (commit_parse(parsed, commit_content, strlen(commit_content), 0) < 0) {
+               error = -1;
                goto cleanup;
+       }
 
        if ((error = validate_tree_and_parents(&parents, repo, &parsed->tree_id, commit_parent_from_commit, parsed, NULL, true)) < 0)
                goto cleanup;
@@ -933,7 +1003,7 @@ int git_commit_create_with_signature(
 
        /* The header ends after the first LF */
        header_end++;
-       git_buf_put(&commit, commit_content, header_end - commit_content);
+       git_str_put(&commit, commit_content, header_end - commit_content);
 
        if (signature != NULL) {
                field = signature_field ? signature_field : "gpgsig";
@@ -942,9 +1012,9 @@ int git_commit_create_with_signature(
                        goto cleanup;
        }
 
-       git_buf_puts(&commit, header_end);
+       git_str_puts(&commit, header_end);
 
-       if (git_buf_oom(&commit))
+       if (git_str_oom(&commit))
                return -1;
 
        if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
@@ -955,7 +1025,7 @@ int git_commit_create_with_signature(
 
 cleanup:
        git_commit__free(parsed);
-       git_buf_dispose(&commit);
+       git_str_dispose(&commit);
        return error;
 }
 
index 318ce5cba4d0127d1ef385a397953ce2f5f0f22c..7a2454e6192d287aa3fa128816169315f57889a7 100644 (file)
@@ -33,12 +33,35 @@ struct git_commit {
        char *body;
 };
 
+int git_commit__header_field(
+       git_str *out,
+       const git_commit *commit,
+       const char *field);
+
+int git_commit__extract_signature(
+       git_str *signature,
+       git_str *signed_data,
+       git_repository *repo,
+       git_oid *commit_id,
+       const char *field);
+
+int git_commit__create_buffer(
+       git_str *out,
+       git_repository *repo,
+       const git_signature *author,
+       const git_signature *committer,
+       const char *message_encoding,
+       const char *message,
+       const git_tree *tree,
+       size_t parent_count,
+       const git_commit *parents[]);
+
 void git_commit__free(void *commit);
 int git_commit__parse(void *commit, git_odb_object *obj);
 int git_commit__parse_raw(void *commit, const char *data, size_t size);
 
 typedef enum {
-       GIT_COMMIT_PARSE_QUICK = (1 << 0), /**< Only parse parents and committer info */
+       GIT_COMMIT_PARSE_QUICK = (1 << 0) /**< Only parse parents and committer info */
 } git_commit__parse_flags;
 
 int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags);
index f663fc5d3beefdb57f9d848557fcecfcf93a3619..70e866b92c20b325a5fad93a63ceade17b6912df 100644 (file)
@@ -8,6 +8,7 @@
 #include "commit_graph.h"
 
 #include "array.h"
+#include "buf.h"
 #include "filebuf.h"
 #include "futils.h"
 #include "hash.h"
@@ -200,7 +201,8 @@ int git_commit_graph_file_parse(
        struct git_commit_graph_chunk *last_chunk;
        uint32_t i;
        off64_t last_chunk_offset, chunk_offset, trailer_offset;
-       git_oid cgraph_checksum = {{0}};
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
+       size_t checksum_size;
        int error;
        struct git_commit_graph_chunk chunk_oid_fanout = {0}, chunk_oid_lookup = {0},
                                      chunk_commit_data = {0}, chunk_extra_edge_list = {0},
@@ -226,13 +228,15 @@ int git_commit_graph_file_parse(
         */
        last_chunk_offset = sizeof(struct git_commit_graph_header) + (1 + hdr->chunks) * 12;
        trailer_offset = size - GIT_OID_RAWSZ;
+       checksum_size = GIT_HASH_SHA1_SIZE;
+
        if (trailer_offset < last_chunk_offset)
                return commit_graph_error("wrong commit-graph size");
-       git_oid_cpy(&file->checksum, (git_oid *)(data + trailer_offset));
+       memcpy(file->checksum, (data + trailer_offset), checksum_size);
 
-       if (git_hash_buf(&cgraph_checksum, data, (size_t)trailer_offset) < 0)
+       if (git_hash_buf(checksum, data, (size_t)trailer_offset, GIT_HASH_ALGORITHM_SHA1) < 0)
                return commit_graph_error("could not calculate signature");
-       if (!git_oid_equal(&cgraph_checksum, &file->checksum))
+       if (memcmp(checksum, file->checksum, checksum_size) != 0)
                return commit_graph_error("index signature mismatch");
 
        chunk_hdr = data + sizeof(struct git_commit_graph_header);
@@ -308,12 +312,12 @@ int git_commit_graph_new(git_commit_graph **cgraph_out, const char *objects_dir,
        cgraph = git__calloc(1, sizeof(git_commit_graph));
        GIT_ERROR_CHECK_ALLOC(cgraph);
 
-       error = git_buf_joinpath(&cgraph->filename, objects_dir, "info/commit-graph");
+       error = git_str_joinpath(&cgraph->filename, objects_dir, "info/commit-graph");
        if (error < 0)
                goto error;
 
        if (open_file) {
-               error = git_commit_graph_file_open(&cgraph->file, git_buf_cstr(&cgraph->filename));
+               error = git_commit_graph_file_open(&cgraph->file, git_str_cstr(&cgraph->filename));
                if (error < 0)
                        goto error;
                cgraph->checked = 1;
@@ -387,7 +391,7 @@ int git_commit_graph_get_file(git_commit_graph_file **file_out, git_commit_graph
                cgraph->checked = 1;
 
                /* Best effort */
-               error = git_commit_graph_file_open(&result, git_buf_cstr(&cgraph->filename));
+               error = git_commit_graph_file_open(&result, git_str_cstr(&cgraph->filename));
 
                if (error < 0)
                        return error;
@@ -407,7 +411,7 @@ void git_commit_graph_refresh(git_commit_graph *cgraph)
                return;
 
        if (cgraph->file
-           && git_commit_graph_file_needs_refresh(cgraph->file, git_buf_cstr(&cgraph->filename))) {
+           && git_commit_graph_file_needs_refresh(cgraph->file, git_str_cstr(&cgraph->filename))) {
                /* We just free the commit graph. The next time it is requested, it will be
                 * re-loaded. */
                git_commit_graph_file_free(cgraph->file);
@@ -475,7 +479,8 @@ bool git_commit_graph_file_needs_refresh(const git_commit_graph_file *file, cons
        git_file fd = -1;
        struct stat st;
        ssize_t bytes_read;
-       git_oid cgraph_checksum = {{0}};
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
+       size_t checksum_size = GIT_HASH_SHA1_SIZE;
 
        /* TODO: properly open the file without access time using O_NOATIME */
        fd = git_futils_open_ro(path);
@@ -493,12 +498,12 @@ bool git_commit_graph_file_needs_refresh(const git_commit_graph_file *file, cons
                return true;
        }
 
-       bytes_read = p_pread(fd, cgraph_checksum.id, GIT_OID_RAWSZ, st.st_size - GIT_OID_RAWSZ);
+       bytes_read = p_pread(fd, checksum, checksum_size, st.st_size - checksum_size);
        p_close(fd);
-       if (bytes_read != GIT_OID_RAWSZ)
+       if (bytes_read != (ssize_t)checksum_size)
                return true;
 
-       return !git_oid_equal(&cgraph_checksum, &file->checksum);
+       return (memcmp(checksum, file->checksum, checksum_size) != 0);
 }
 
 int git_commit_graph_entry_find(
@@ -597,7 +602,7 @@ void git_commit_graph_free(git_commit_graph *cgraph)
        if (!cgraph)
                return;
 
-       git_buf_dispose(&cgraph->filename);
+       git_str_dispose(&cgraph->filename);
        git_commit_graph_file_free(cgraph->file);
        git__free(cgraph);
 }
@@ -623,13 +628,13 @@ int git_commit_graph_writer_new(git_commit_graph_writer **out, const char *objec
        git_commit_graph_writer *w = git__calloc(1, sizeof(git_commit_graph_writer));
        GIT_ERROR_CHECK_ALLOC(w);
 
-       if (git_buf_sets(&w->objects_info_dir, objects_info_dir) < 0) {
+       if (git_str_sets(&w->objects_info_dir, objects_info_dir) < 0) {
                git__free(w);
                return -1;
        }
 
        if (git_vector_init(&w->commits, 0, packed_commit__cmp) < 0) {
-               git_buf_dispose(&w->objects_info_dir);
+               git_str_dispose(&w->objects_info_dir);
                git__free(w);
                return -1;
        }
@@ -649,7 +654,7 @@ void git_commit_graph_writer_free(git_commit_graph_writer *w)
        git_vector_foreach (&w->commits, i, packed_commit)
                packed_commit_free(packed_commit);
        git_vector_free(&w->commits);
-       git_buf_dispose(&w->objects_info_dir);
+       git_str_dispose(&w->objects_info_dir);
        git__free(w);
 }
 
@@ -753,7 +758,7 @@ enum generation_number_commit_state {
        GENERATION_NUMBER_COMMIT_STATE_UNVISITED = 0,
        GENERATION_NUMBER_COMMIT_STATE_ADDED = 1,
        GENERATION_NUMBER_COMMIT_STATE_EXPANDED = 2,
-       GENERATION_NUMBER_COMMIT_STATE_VISITED = 3,
+       GENERATION_NUMBER_COMMIT_STATE_VISITED = 3
 };
 
 static int compute_generation_numbers(git_vector *commits)
@@ -931,8 +936,8 @@ static int write_chunk_header(
 
 static int commit_graph_write_buf(const char *buf, size_t size, void *data)
 {
-       git_buf *b = (git_buf *)data;
-       return git_buf_put(b, buf, size);
+       git_str *b = (git_str *)data;
+       return git_str_put(b, buf, size);
 }
 
 struct commit_graph_write_hash_context {
@@ -971,9 +976,10 @@ static int commit_graph_write(
        uint32_t extra_edge_list_count;
        uint32_t oid_fanout[256];
        off64_t offset;
-       git_buf oid_lookup = GIT_BUF_INIT, commit_data = GIT_BUF_INIT,
-               extra_edge_list = GIT_BUF_INIT;
-       git_oid cgraph_checksum = {{0}};
+       git_str oid_lookup = GIT_STR_INIT, commit_data = GIT_STR_INIT,
+               extra_edge_list = GIT_STR_INIT;
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
+       size_t checksum_size;
        git_hash_ctx ctx;
        struct commit_graph_write_hash_context hash_cb_data = {0};
 
@@ -986,7 +992,8 @@ static int commit_graph_write(
        hash_cb_data.cb_data = cb_data;
        hash_cb_data.ctx = &ctx;
 
-       error = git_hash_ctx_init(&ctx);
+       checksum_size = GIT_HASH_SHA1_SIZE;
+       error = git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA1);
        if (error < 0)
                return error;
        cb_data = &hash_cb_data;
@@ -1011,7 +1018,7 @@ static int commit_graph_write(
 
        /* Fill the OID Lookup table. */
        git_vector_foreach (&w->commits, i, packed_commit) {
-               error = git_buf_put(&oid_lookup,
+               error = git_str_put(&oid_lookup,
                        (const char *)&packed_commit->sha1, sizeof(git_oid));
                if (error < 0)
                        goto cleanup;
@@ -1026,7 +1033,7 @@ static int commit_graph_write(
                size_t *packed_index;
                unsigned int parentcount = (unsigned int)git_array_size(packed_commit->parents);
 
-               error = git_buf_put(&commit_data,
+               error = git_str_put(&commit_data,
                                (const char *)&packed_commit->tree_oid,
                                sizeof(git_oid));
                if (error < 0)
@@ -1038,7 +1045,7 @@ static int commit_graph_write(
                        packed_index = git_array_get(packed_commit->parent_indices, 0);
                        word = htonl((uint32_t)*packed_index);
                }
-               error = git_buf_put(&commit_data, (const char *)&word, sizeof(word));
+               error = git_str_put(&commit_data, (const char *)&word, sizeof(word));
                if (error < 0)
                        goto cleanup;
 
@@ -1050,7 +1057,7 @@ static int commit_graph_write(
                } else {
                        word = htonl(0x80000000u | extra_edge_list_count);
                }
-               error = git_buf_put(&commit_data, (const char *)&word, sizeof(word));
+               error = git_str_put(&commit_data, (const char *)&word, sizeof(word));
                if (error < 0)
                        goto cleanup;
 
@@ -1061,7 +1068,7 @@ static int commit_graph_write(
                                        packed_commit->parent_indices, parent_i);
                                word = htonl((uint32_t)(*packed_index | (parent_i + 1 == parentcount ? 0x80000000u : 0)));
 
-                               error = git_buf_put(&extra_edge_list,
+                               error = git_str_put(&extra_edge_list,
                                                (const char *)&word,
                                                sizeof(word));
                                if (error < 0)
@@ -1074,19 +1081,19 @@ static int commit_graph_write(
                commit_time = (uint64_t)packed_commit->commit_time;
                if (generation > GIT_COMMIT_GRAPH_GENERATION_NUMBER_MAX)
                        generation = GIT_COMMIT_GRAPH_GENERATION_NUMBER_MAX;
-               word = ntohl((uint32_t)((generation << 2) | ((commit_time >> 32ull) & 0x3ull)));
-               error = git_buf_put(&commit_data, (const char *)&word, sizeof(word));
+               word = ntohl((uint32_t)((generation << 2) | (((uint32_t)(commit_time >> 32)) & 0x3) ));
+               error = git_str_put(&commit_data, (const char *)&word, sizeof(word));
                if (error < 0)
                        goto cleanup;
-               word = ntohl((uint32_t)(commit_time & 0xffffffffull));
-               error = git_buf_put(&commit_data, (const char *)&word, sizeof(word));
+               word = ntohl((uint32_t)(commit_time & 0xfffffffful));
+               error = git_str_put(&commit_data, (const char *)&word, sizeof(word));
                if (error < 0)
                        goto cleanup;
        }
 
        /* Write the header. */
        hdr.chunks = 3;
-       if (git_buf_len(&extra_edge_list) > 0)
+       if (git_str_len(&extra_edge_list) > 0)
                hdr.chunks++;
        error = write_cb((const char *)&hdr, sizeof(hdr), cb_data);
        if (error < 0)
@@ -1101,17 +1108,17 @@ static int commit_graph_write(
        error = write_chunk_header(COMMIT_GRAPH_OID_LOOKUP_ID, offset, write_cb, cb_data);
        if (error < 0)
                goto cleanup;
-       offset += git_buf_len(&oid_lookup);
+       offset += git_str_len(&oid_lookup);
        error = write_chunk_header(COMMIT_GRAPH_COMMIT_DATA_ID, offset, write_cb, cb_data);
        if (error < 0)
                goto cleanup;
-       offset += git_buf_len(&commit_data);
-       if (git_buf_len(&extra_edge_list) > 0) {
+       offset += git_str_len(&commit_data);
+       if (git_str_len(&extra_edge_list) > 0) {
                error = write_chunk_header(
                                COMMIT_GRAPH_EXTRA_EDGE_LIST_ID, offset, write_cb, cb_data);
                if (error < 0)
                        goto cleanup;
-               offset += git_buf_len(&extra_edge_list);
+               offset += git_str_len(&extra_edge_list);
        }
        error = write_chunk_header(0, offset, write_cb, cb_data);
        if (error < 0)
@@ -1121,28 +1128,28 @@ static int commit_graph_write(
        error = write_cb((const char *)oid_fanout, sizeof(oid_fanout), cb_data);
        if (error < 0)
                goto cleanup;
-       error = write_cb(git_buf_cstr(&oid_lookup), git_buf_len(&oid_lookup), cb_data);
+       error = write_cb(git_str_cstr(&oid_lookup), git_str_len(&oid_lookup), cb_data);
        if (error < 0)
                goto cleanup;
-       error = write_cb(git_buf_cstr(&commit_data), git_buf_len(&commit_data), cb_data);
+       error = write_cb(git_str_cstr(&commit_data), git_str_len(&commit_data), cb_data);
        if (error < 0)
                goto cleanup;
-       error = write_cb(git_buf_cstr(&extra_edge_list), git_buf_len(&extra_edge_list), cb_data);
+       error = write_cb(git_str_cstr(&extra_edge_list), git_str_len(&extra_edge_list), cb_data);
        if (error < 0)
                goto cleanup;
 
        /* Finalize the checksum and write the trailer. */
-       error = git_hash_final(&cgraph_checksum, &ctx);
+       error = git_hash_final(checksum, &ctx);
        if (error < 0)
                goto cleanup;
-       error = write_cb((const char *)&cgraph_checksum, sizeof(cgraph_checksum), cb_data);
+       error = write_cb((char *)checksum, checksum_size, cb_data);
        if (error < 0)
                goto cleanup;
 
 cleanup:
-       git_buf_dispose(&oid_lookup);
-       git_buf_dispose(&commit_data);
-       git_buf_dispose(&extra_edge_list);
+       git_str_dispose(&oid_lookup);
+       git_str_dispose(&commit_data);
+       git_str_dispose(&extra_edge_list);
        git_hash_ctx_cleanup(&ctx);
        return error;
 }
@@ -1171,21 +1178,21 @@ int git_commit_graph_writer_commit(
 {
        int error;
        int filebuf_flags = GIT_FILEBUF_DO_NOT_BUFFER;
-       git_buf commit_graph_path = GIT_BUF_INIT;
+       git_str commit_graph_path = GIT_STR_INIT;
        git_filebuf output = GIT_FILEBUF_INIT;
 
        /* TODO: support options and fill in defaults. */
        GIT_UNUSED(opts);
 
-       error = git_buf_joinpath(
-                       &commit_graph_path, git_buf_cstr(&w->objects_info_dir), "commit-graph");
+       error = git_str_joinpath(
+                       &commit_graph_path, git_str_cstr(&w->objects_info_dir), "commit-graph");
        if (error < 0)
                return error;
 
        if (git_repository__fsync_gitdir)
                filebuf_flags |= GIT_FILEBUF_FSYNC;
-       error = git_filebuf_open(&output, git_buf_cstr(&commit_graph_path), filebuf_flags, 0644);
-       git_buf_dispose(&commit_graph_path);
+       error = git_filebuf_open(&output, git_str_cstr(&commit_graph_path), filebuf_flags, 0644);
+       git_str_dispose(&commit_graph_path);
        if (error < 0)
                return error;
 
@@ -1199,9 +1206,17 @@ int git_commit_graph_writer_commit(
 }
 
 int git_commit_graph_writer_dump(
-               git_buf *cgraph,
-               git_commit_graph_writer *w,
-               git_commit_graph_writer_options *opts)
+       git_buf *cgraph,
+       git_commit_graph_writer *w,
+       git_commit_graph_writer_options *opts)
+{
+       GIT_BUF_WRAP_PRIVATE(cgraph, git_commit_graph__writer_dump, w, opts);
+}
+
+int git_commit_graph__writer_dump(
+       git_str *cgraph,
+       git_commit_graph_writer *w,
+       git_commit_graph_writer_options *opts)
 {
        /* TODO: support options. */
        GIT_UNUSED(opts);
index 9d0a827de0a9994bd08801d16e6cdbdce807d37c..45e125b9e16be65f1b339d344e2eb4b024be279f 100644 (file)
@@ -15,6 +15,8 @@
 
 #include "map.h"
 #include "vector.h"
+#include "oid.h"
+#include "hash.h"
 
 /**
  * A commit-graph file.
@@ -55,7 +57,7 @@ typedef struct git_commit_graph_file {
        size_t num_extra_edge_list;
 
        /* The trailer of the file. Contains the SHA1-checksum of the whole file. */
-       git_oid checksum;
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
 } git_commit_graph_file;
 
 /**
@@ -92,7 +94,7 @@ typedef struct git_commit_graph_entry {
 /* A wrapper for git_commit_graph_file to enable lazy loading in the ODB. */
 struct git_commit_graph {
        /* The path to the commit-graph file. Something like ".git/objects/info/commit-graph". */
-       git_buf filename;
+       git_str filename;
 
        /* The underlying commit-graph file. */
        git_commit_graph_file *file;
@@ -127,12 +129,17 @@ struct git_commit_graph_writer {
         * The path of the `objects/info` directory where the `commit-graph` will be
         * stored.
         */
-       git_buf objects_info_dir;
+       git_str objects_info_dir;
 
        /* The list of packed commits. */
        git_vector commits;
 };
 
+int git_commit_graph__writer_dump(
+       git_str *cgraph,
+       git_commit_graph_writer *w,
+       git_commit_graph_writer_options *opts);
+
 /*
  * Returns whether the git_commit_graph_file needs to be reloaded since the
  * contents of the commit-graph file have changed on disk.
index 692b1495f51c74d7d9ba9ba78a3a99e8bb22c07b..4585508bc4183b39da9055487545ba112d718c85 100644 (file)
@@ -124,16 +124,15 @@ static int commit_quick_parse(
 {
        git_oid *parent_oid;
        git_commit *commit;
-       int error;
        size_t i;
 
        commit = git__calloc(1, sizeof(*commit));
        GIT_ERROR_CHECK_ALLOC(commit);
        commit->object.repo = walk->repo;
 
-       if ((error = git_commit__parse_ext(commit, obj, GIT_COMMIT_PARSE_QUICK)) < 0) {
+       if (git_commit__parse_ext(commit, obj, GIT_COMMIT_PARSE_QUICK) < 0) {
                git__free(commit);
-               return error;
+               return -1;
        }
 
        if (!git__is_uint16(git_array_size(commit->parent_ids))) {
index 9bb1116b53149192793f6b64c8eab9a1a04c21ad..549bddb59322b0e648ab770e3200b9748365f7b0 100644 (file)
 /**
  * Check a pointer allocation result, returning -1 if it failed.
  */
-#define GIT_ERROR_CHECK_ALLOC(ptr) if (ptr == NULL) { return -1; }
+#define GIT_ERROR_CHECK_ALLOC(ptr) do { \
+       if ((ptr) == NULL) { return -1; } \
+       } while(0)
 
 /**
- * Check a buffer allocation result, returning -1 if it failed.
+ * Check a string buffer allocation result, returning -1 if it failed.
  */
-#define GIT_ERROR_CHECK_ALLOC_BUF(buf) if ((void *)(buf) == NULL || git_buf_oom(buf)) { return -1; }
+#define GIT_ERROR_CHECK_ALLOC_STR(buf) do { \
+       if ((void *)(buf) == NULL || git_str_oom(buf)) { return -1; } \
+       } while(0)
 
 /**
  * Check a return value and propagate result if non-zero.
@@ -202,6 +206,9 @@ GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int v
 
 /* NOTE: other git_error functions are in the public errors.h header file */
 
+/* Forward declare git_str */
+typedef struct git_str git_str;
+
 #include "util.h"
 
 #endif
index 3251cd51fdb46ec7ab1978807e6da2a60b25cae0..6bd59f2a5a871c52700d4a141d6d5b5e724d0d73 100644 (file)
@@ -10,6 +10,7 @@
 #include "git2/config.h"
 #include "git2/sys/config.h"
 
+#include "buf.h"
 #include "config_backend.h"
 #include "regexp.h"
 #include "sysdir.h"
@@ -848,7 +849,40 @@ static int is_readonly(const git_config *cfg)
        return 1;
 }
 
-int git_config_get_path(git_buf *out, const git_config *cfg, const char *name)
+static int git_config__parse_path(git_str *out, const char *value)
+{
+       GIT_ASSERT_ARG(out);
+       GIT_ASSERT_ARG(value);
+
+       if (value[0] == '~') {
+               if (value[1] != '\0' && value[1] != '/') {
+                       git_error_set(GIT_ERROR_CONFIG, "retrieving a homedir by name is not supported");
+                       return -1;
+               }
+
+               return git_sysdir_expand_global_file(out, value[1] ? &value[2] : NULL);
+       }
+
+       return git_str_sets(out, value);
+}
+
+int git_config_parse_path(git_buf *out, const char *value)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_config__parse_path, value);
+}
+
+int git_config_get_path(
+       git_buf *out,
+       const git_config *cfg,
+       const char *name)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_config__get_path, cfg, name);
+}
+
+int git_config__get_path(
+       git_str *out,
+       const git_config *cfg,
+       const char *name)
 {
        git_config_entry *entry;
        int error;
@@ -856,7 +890,7 @@ int git_config_get_path(git_buf *out, const git_config *cfg, const char *name)
        if ((error = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
                return error;
 
-        error = git_config_parse_path(out, entry->value);
+        error = git_config__parse_path(out, entry->value);
         git_config_entry_free(entry);
 
         return error;
@@ -883,19 +917,25 @@ int git_config_get_string(
 
 int git_config_get_string_buf(
        git_buf *out, const git_config *cfg, const char *name)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_config__get_string_buf, cfg, name);
+}
+
+int git_config__get_string_buf(
+       git_str *out, const git_config *cfg, const char *name)
 {
        git_config_entry *entry;
        int ret;
        const char *str;
 
-       if ((ret = git_buf_sanitize(out)) < 0)
-               return ret;
+       GIT_ASSERT_ARG(out);
+       GIT_ASSERT_ARG(cfg);
 
        ret  = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS);
        str = !ret ? (entry->value ? entry->value : "") : NULL;
 
        if (str)
-               ret = git_buf_puts(out, str);
+               ret = git_str_puts(out, str);
 
        git_config_entry_free(entry);
 
@@ -1087,101 +1127,116 @@ void git_config_iterator_free(git_config_iterator *iter)
 
 int git_config_find_global(git_buf *path)
 {
-       int error;
-
-       if ((error = git_buf_sanitize(path)) < 0)
-               return error;
+       GIT_BUF_WRAP_PRIVATE(path, git_sysdir_find_global_file, GIT_CONFIG_FILENAME_GLOBAL);
+}
 
+int git_config__find_global(git_str *path)
+{
        return git_sysdir_find_global_file(path, GIT_CONFIG_FILENAME_GLOBAL);
 }
 
 int git_config_find_xdg(git_buf *path)
 {
-       int error;
-
-       if ((error = git_buf_sanitize(path)) < 0)
-               return error;
+       GIT_BUF_WRAP_PRIVATE(path, git_sysdir_find_global_file, GIT_CONFIG_FILENAME_XDG);
+}
 
+int git_config__find_xdg(git_str *path)
+{
        return git_sysdir_find_xdg_file(path, GIT_CONFIG_FILENAME_XDG);
 }
 
 int git_config_find_system(git_buf *path)
 {
-       int error;
-
-       if ((error = git_buf_sanitize(path)) < 0)
-               return error;
+       GIT_BUF_WRAP_PRIVATE(path, git_sysdir_find_global_file, GIT_CONFIG_FILENAME_SYSTEM);
+}
 
+int git_config__find_system(git_str *path)
+{
        return git_sysdir_find_system_file(path, GIT_CONFIG_FILENAME_SYSTEM);
 }
 
 int git_config_find_programdata(git_buf *path)
 {
-       int ret;
+       git_str str = GIT_STR_INIT;
+       int error;
 
-       if ((ret = git_buf_sanitize(path)) < 0)
-               return ret;
+       if ((error = git_buf_tostr(&str, path)) == 0 &&
+           (error = git_config__find_programdata(&str)) == 0)
+               error = git_buf_fromstr(path, &str);
 
-       ret = git_sysdir_find_programdata_file(path,
-                                              GIT_CONFIG_FILENAME_PROGRAMDATA);
-       if (ret != GIT_OK)
-               return ret;
+       git_str_dispose(&str);
+       return error;
+}
+
+int git_config__find_programdata(git_str *path)
+{
+       bool is_safe;
+
+       if (git_sysdir_find_programdata_file(path, GIT_CONFIG_FILENAME_PROGRAMDATA) < 0 ||
+           git_fs_path_owner_is_system_or_current_user(&is_safe, path->ptr) < 0)
+               return -1;
 
-       return git_path_validate_system_file_ownership(path->ptr);
+       if (!is_safe) {
+               git_error_set(GIT_ERROR_CONFIG, "programdata path has invalid ownership");
+               return -1;
+       }
+
+       return 0;
 }
 
-int git_config__global_location(git_buf *buf)
+int git_config__global_location(git_str *buf)
 {
-       const git_buf *paths;
+       const git_str *paths;
        const char *sep, *start;
 
        if (git_sysdir_get(&paths, GIT_SYSDIR_GLOBAL) < 0)
                return -1;
 
        /* no paths, so give up */
-       if (!paths || !git_buf_len(paths))
+       if (!paths || !git_str_len(paths))
                return -1;
 
        /* find unescaped separator or end of string */
-       for (sep = start = git_buf_cstr(paths); *sep; ++sep) {
+       for (sep = start = git_str_cstr(paths); *sep; ++sep) {
                if (*sep == GIT_PATH_LIST_SEPARATOR &&
                        (sep <= start || sep[-1] != '\\'))
                        break;
        }
 
-       if (git_buf_set(buf, start, (size_t)(sep - start)) < 0)
+       if (git_str_set(buf, start, (size_t)(sep - start)) < 0)
                return -1;
 
-       return git_buf_joinpath(buf, buf->ptr, GIT_CONFIG_FILENAME_GLOBAL);
+       return git_str_joinpath(buf, buf->ptr, GIT_CONFIG_FILENAME_GLOBAL);
 }
 
 int git_config_open_default(git_config **out)
 {
        int error;
        git_config *cfg = NULL;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        if ((error = git_config_new(&cfg)) < 0)
                return error;
 
-       if (!git_config_find_global(&buf) || !git_config__global_location(&buf)) {
+       if (!git_config__find_global(&buf) ||
+           !git_config__global_location(&buf)) {
                error = git_config_add_file_ondisk(cfg, buf.ptr,
                        GIT_CONFIG_LEVEL_GLOBAL, NULL, 0);
        }
 
-       if (!error && !git_config_find_xdg(&buf))
+       if (!error && !git_config__find_xdg(&buf))
                error = git_config_add_file_ondisk(cfg, buf.ptr,
                        GIT_CONFIG_LEVEL_XDG, NULL, 0);
 
-       if (!error && !git_config_find_system(&buf))
+       if (!error && !git_config__find_system(&buf))
                error = git_config_add_file_ondisk(cfg, buf.ptr,
                        GIT_CONFIG_LEVEL_SYSTEM, NULL, 0);
 
-       if (!error && !git_config_find_programdata(&buf))
+       if (!error && !git_config__find_programdata(&buf))
                error = git_config_add_file_ondisk(cfg, buf.ptr,
                        GIT_CONFIG_LEVEL_PROGRAMDATA, NULL, 0);
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        if (error) {
                git_config_free(cfg);
@@ -1375,28 +1430,6 @@ fail_parse:
        return -1;
 }
 
-int git_config_parse_path(git_buf *out, const char *value)
-{
-       int error;
-
-       GIT_ASSERT_ARG(out);
-       GIT_ASSERT_ARG(value);
-
-       if ((error = git_buf_sanitize(out)) < 0)
-               return error;
-
-       if (value[0] == '~') {
-               if (value[1] != '\0' && value[1] != '/') {
-                       git_error_set(GIT_ERROR_CONFIG, "retrieving a homedir by name is not supported");
-                       return -1;
-               }
-
-               return git_sysdir_expand_global_file(out, value[1] ? &value[2] : NULL);
-       }
-
-       return git_buf_sets(out, value);
-}
-
 static int normalize_section(char *start, char *end)
 {
        char *scan;
@@ -1459,7 +1492,7 @@ invalid:
 
 struct rename_data {
        git_config *config;
-       git_buf *name;
+       git_str *name;
        size_t old_len;
 };
 
@@ -1469,15 +1502,15 @@ static int rename_config_entries_cb(
 {
        int error = 0;
        struct rename_data *data = (struct rename_data *)payload;
-       size_t base_len = git_buf_len(data->name);
+       size_t base_len = git_str_len(data->name);
 
        if (base_len > 0 &&
-               !(error = git_buf_puts(data->name, entry->name + data->old_len)))
+               !(error = git_str_puts(data->name, entry->name + data->old_len)))
        {
                error = git_config_set_string(
-                       data->config, git_buf_cstr(data->name), entry->value);
+                       data->config, git_str_cstr(data->name), entry->value);
 
-               git_buf_truncate(data->name, base_len);
+               git_str_truncate(data->name, base_len);
        }
 
        if (!error)
@@ -1492,13 +1525,13 @@ int git_config_rename_section(
        const char *new_section_name)
 {
        git_config *config;
-       git_buf pattern = GIT_BUF_INIT, replace = GIT_BUF_INIT;
+       git_str pattern = GIT_STR_INIT, replace = GIT_STR_INIT;
        int error = 0;
        struct rename_data data;
 
-       git_buf_puts_escape_regex(&pattern, old_section_name);
+       git_str_puts_escape_regex(&pattern, old_section_name);
 
-       if ((error = git_buf_puts(&pattern, "\\..+")) < 0)
+       if ((error = git_str_puts(&pattern, "\\..+")) < 0)
                goto cleanup;
 
        if ((error = git_repository_config__weakptr(&config, repo)) < 0)
@@ -1508,7 +1541,7 @@ int git_config_rename_section(
        data.name    = &replace;
        data.old_len = strlen(old_section_name) + 1;
 
-       if ((error = git_buf_join(&replace, '.', new_section_name, "")) < 0)
+       if ((error = git_str_join(&replace, '.', new_section_name, "")) < 0)
                goto cleanup;
 
        if (new_section_name != NULL &&
@@ -1520,11 +1553,11 @@ int git_config_rename_section(
        }
 
        error = git_config_foreach_match(
-               config, git_buf_cstr(&pattern), rename_config_entries_cb, &data);
+               config, git_str_cstr(&pattern), rename_config_entries_cb, &data);
 
 cleanup:
-       git_buf_dispose(&pattern);
-       git_buf_dispose(&replace);
+       git_str_dispose(&pattern);
+       git_str_dispose(&replace);
 
        return error;
 }
index a1d8f7d2314ff2eaecf072730f5fbd3665e6c94d..01b84b157f780e58fb0af296c8748f268eb8ec7a 100644 (file)
@@ -27,7 +27,12 @@ struct git_config {
        git_vector backends;
 };
 
-extern int git_config__global_location(git_buf *buf);
+extern int git_config__global_location(git_str *buf);
+
+extern int git_config__find_global(git_str *path);
+extern int git_config__find_xdg(git_str *path);
+extern int git_config__find_system(git_str *path);
+extern int git_config__find_programdata(git_str *path);
 
 extern int git_config_rename_section(
        git_repository *repo,
@@ -51,6 +56,14 @@ extern int git_config__update_entry(
        bool overwrite_existing,
        bool only_if_existing);
 
+int git_config__get_path(
+       git_str *out,
+       const git_config *cfg,
+       const char *name);
+
+int git_config__get_string_buf(
+       git_str *out, const git_config *cfg, const char *name);
+
 /*
  * Lookup functions that cannot fail.  These functions look up a config
  * value and return a fallback value if the value is missing or if any
@@ -83,7 +96,7 @@ int git_config_lookup_map_enum(git_configmap_t *type_out,
 /**
  * Unlock the backend with the highest priority
  *
- * Unlocking will allow other writers to updat the configuration
+ * Unlocking will allow other writers to update the configuration
  * file. Optionally, any changes performed since the lock will be
  * applied to the configuration.
  *
index 3588e6be6c4183da0ef1c33d56cccf6f90fad014..66fcb8ae29564e92100af004745bdf91bf15b4e1 100644 (file)
@@ -11,7 +11,7 @@
 #include "git2/sys/config.h"
 
 #include "array.h"
-#include "buffer.h"
+#include "str.h"
 #include "config_backend.h"
 #include "config_entries.h"
 #include "config_parse.h"
 #include "regexp.h"
 #include "sysdir.h"
 #include "wildmatch.h"
+#include "hash.h"
 
 /* Max depth for [include] directives */
 #define MAX_INCLUDE_DEPTH 10
 
 typedef struct config_file {
        git_futils_filestamp stamp;
-       git_oid checksum;
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
        char *path;
        git_array_t(struct config_file) includes;
 } config_file;
@@ -41,7 +42,7 @@ typedef struct {
 
        bool locked;
        git_filebuf locked_buf;
-       git_buf locked_content;
+       git_str locked_content;
 
        config_file file;
 } config_file_backend;
@@ -108,7 +109,7 @@ static int config_file_open(git_config_backend *cfg, git_config_level_t level, c
        if ((res = git_config_entries_new(&b->entries)) < 0)
                return res;
 
-       if (!git_path_exists(b->file.path))
+       if (!git_fs_path_exists(b->file.path))
                return 0;
 
        /*
@@ -131,8 +132,8 @@ static int config_file_open(git_config_backend *cfg, git_config_level_t level, c
 static int config_file_is_modified(int *modified, config_file *file)
 {
        config_file *include;
-       git_buf buf = GIT_BUF_INIT;
-       git_oid hash;
+       git_str buf = GIT_STR_INIT;
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
        uint32_t i;
        int error = 0;
 
@@ -144,10 +145,10 @@ static int config_file_is_modified(int *modified, config_file *file)
        if ((error = git_futils_readbuffer(&buf, file->path)) < 0)
                goto out;
 
-       if ((error = git_hash_buf(&hash, buf.ptr, buf.size)) < 0)
+       if ((error = git_hash_buf(checksum, buf.ptr, buf.size, GIT_HASH_ALGORITHM_SHA1)) < 0)
                goto out;
 
-       if (!git_oid_equal(&hash, &file->checksum)) {
+       if (memcmp(checksum, file->checksum, GIT_HASH_SHA1_SIZE) != 0) {
                *modified = 1;
                goto out;
        }
@@ -159,7 +160,7 @@ check_includes:
        }
 
 out:
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        return error;
 }
@@ -486,7 +487,7 @@ static int config_file_unlock(git_config_backend *_cfg, int success)
        }
 
        git_filebuf_cleanup(&cfg->locked_buf);
-       git_buf_dispose(&cfg->locked_content);
+       git_str_dispose(&cfg->locked_content);
        cfg->locked = false;
 
        return error;
@@ -523,19 +524,19 @@ int git_config_backend_from_file(git_config_backend **out, const char *path)
        return 0;
 }
 
-static int included_path(git_buf *out, const char *dir, const char *path)
+static int included_path(git_str *out, const char *dir, const char *path)
 {
        /* From the user's home */
        if (path[0] == '~' && path[1] == '/')
                return git_sysdir_expand_global_file(out, &path[1]);
 
-       return git_path_join_unrooted(out, path, dir, NULL);
+       return git_fs_path_join_unrooted(out, path, dir, NULL);
 }
 
 /* Escape the values to write them to the file */
 static char *escape_value(const char *ptr)
 {
-       git_buf buf;
+       git_str buf;
        size_t len;
        const char *esc;
 
@@ -545,39 +546,39 @@ static char *escape_value(const char *ptr)
        if (!len)
                return git__calloc(1, sizeof(char));
 
-       if (git_buf_init(&buf, len) < 0)
+       if (git_str_init(&buf, len) < 0)
                return NULL;
 
        while (*ptr != '\0') {
                if ((esc = strchr(git_config_escaped, *ptr)) != NULL) {
-                       git_buf_putc(&buf, '\\');
-                       git_buf_putc(&buf, git_config_escapes[esc - git_config_escaped]);
+                       git_str_putc(&buf, '\\');
+                       git_str_putc(&buf, git_config_escapes[esc - git_config_escaped]);
                } else {
-                       git_buf_putc(&buf, *ptr);
+                       git_str_putc(&buf, *ptr);
                }
                ptr++;
        }
 
-       if (git_buf_oom(&buf))
+       if (git_str_oom(&buf))
                return NULL;
 
-       return git_buf_detach(&buf);
+       return git_str_detach(&buf);
 }
 
 static int parse_include(config_file_parse_data *parse_data, const char *file)
 {
        config_file *include;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        char *dir;
        int result;
 
        if (!file)
                return 0;
 
-       if ((result = git_path_dirname_r(&path, parse_data->file->path)) < 0)
+       if ((result = git_fs_path_dirname_r(&path, parse_data->file->path)) < 0)
                return result;
 
-       dir = git_buf_detach(&path);
+       dir = git_str_detach(&path);
        result = included_path(&path, dir, file);
        git__free(dir);
 
@@ -588,7 +589,7 @@ static int parse_include(config_file_parse_data *parse_data, const char *file)
        GIT_ERROR_CHECK_ALLOC(include);
        memset(include, 0, sizeof(*include));
        git_array_init(include->includes);
-       include->path = git_buf_detach(&path);
+       include->path = git_str_detach(&path);
 
        result = config_file_read(parse_data->entries, parse_data->repo, include,
                                  parse_data->level, parse_data->depth+1);
@@ -608,38 +609,38 @@ static int do_match_gitdir(
        const char *condition,
        bool case_insensitive)
 {
-       git_buf pattern = GIT_BUF_INIT, gitdir = GIT_BUF_INIT;
+       git_str pattern = GIT_STR_INIT, gitdir = GIT_STR_INIT;
        int error;
 
-       if (condition[0] == '.' && git_path_is_dirsep(condition[1])) {
-               git_path_dirname_r(&pattern, cfg_file);
-               git_buf_joinpath(&pattern, pattern.ptr, condition + 2);
-       } else if (condition[0] == '~' && git_path_is_dirsep(condition[1]))
+       if (condition[0] == '.' && git_fs_path_is_dirsep(condition[1])) {
+               git_fs_path_dirname_r(&pattern, cfg_file);
+               git_str_joinpath(&pattern, pattern.ptr, condition + 2);
+       } else if (condition[0] == '~' && git_fs_path_is_dirsep(condition[1]))
                git_sysdir_expand_global_file(&pattern, condition + 1);
-       else if (!git_path_is_absolute(condition))
-               git_buf_joinpath(&pattern, "**", condition);
+       else if (!git_fs_path_is_absolute(condition))
+               git_str_joinpath(&pattern, "**", condition);
        else
-               git_buf_sets(&pattern, condition);
+               git_str_sets(&pattern, condition);
 
-       if (git_path_is_dirsep(condition[strlen(condition) - 1]))
-               git_buf_puts(&pattern, "**");
+       if (git_fs_path_is_dirsep(condition[strlen(condition) - 1]))
+               git_str_puts(&pattern, "**");
 
-       if (git_buf_oom(&pattern)) {
+       if (git_str_oom(&pattern)) {
                error = -1;
                goto out;
        }
 
-       if ((error = git_repository_item_path(&gitdir, repo, GIT_REPOSITORY_ITEM_GITDIR)) < 0)
+       if ((error = git_repository__item_path(&gitdir, repo, GIT_REPOSITORY_ITEM_GITDIR)) < 0)
                goto out;
 
-       if (git_path_is_dirsep(gitdir.ptr[gitdir.size - 1]))
-               git_buf_truncate(&gitdir, gitdir.size - 1);
+       if (git_fs_path_is_dirsep(gitdir.ptr[gitdir.size - 1]))
+               git_str_truncate(&gitdir, gitdir.size - 1);
 
        *matches = wildmatch(pattern.ptr, gitdir.ptr,
                             WM_PATHNAME | (case_insensitive ? WM_CASEFOLD : 0)) == WM_MATCH;
 out:
-       git_buf_dispose(&pattern);
-       git_buf_dispose(&gitdir);
+       git_str_dispose(&pattern);
+       git_str_dispose(&gitdir);
        return error;
 }
 
@@ -667,7 +668,7 @@ static int conditional_match_onbranch(
        const char *cfg_file,
        const char *condition)
 {
-       git_buf reference = GIT_BUF_INIT, buf = GIT_BUF_INIT;
+       git_str reference = GIT_STR_INIT, buf = GIT_STR_INIT;
        int error;
 
        GIT_UNUSED(cfg_file);
@@ -680,33 +681,33 @@ static int conditional_match_onbranch(
         * an endless recursion.
         */
 
-       if ((error = git_buf_joinpath(&buf, git_repository_path(repo), GIT_HEAD_FILE)) < 0 ||
+       if ((error = git_str_joinpath(&buf, git_repository_path(repo), GIT_HEAD_FILE)) < 0 ||
            (error = git_futils_readbuffer(&reference, buf.ptr)) < 0)
                goto out;
-       git_buf_rtrim(&reference);
+       git_str_rtrim(&reference);
 
        if (git__strncmp(reference.ptr, GIT_SYMREF, strlen(GIT_SYMREF)))
                goto out;
-       git_buf_consume(&reference, reference.ptr + strlen(GIT_SYMREF));
+       git_str_consume(&reference, reference.ptr + strlen(GIT_SYMREF));
 
        if (git__strncmp(reference.ptr, GIT_REFS_HEADS_DIR, strlen(GIT_REFS_HEADS_DIR)))
                goto out;
-       git_buf_consume(&reference, reference.ptr + strlen(GIT_REFS_HEADS_DIR));
+       git_str_consume(&reference, reference.ptr + strlen(GIT_REFS_HEADS_DIR));
 
        /*
         * If the condition ends with a '/', then we should treat it as if
         * it had '**' appended.
         */
-       if ((error = git_buf_sets(&buf, condition)) < 0)
+       if ((error = git_str_sets(&buf, condition)) < 0)
                goto out;
-       if (git_path_is_dirsep(condition[strlen(condition) - 1]) &&
-           (error = git_buf_puts(&buf, "**")) < 0)
+       if (git_fs_path_is_dirsep(condition[strlen(condition) - 1]) &&
+           (error = git_str_puts(&buf, "**")) < 0)
                goto out;
 
        *matches = wildmatch(buf.ptr, reference.ptr, WM_PATHNAME) == WM_MATCH;
 out:
-       git_buf_dispose(&reference);
-       git_buf_dispose(&buf);
+       git_str_dispose(&reference);
+       git_str_dispose(&buf);
 
        return error;
 
@@ -724,14 +725,25 @@ static const struct {
 static int parse_conditional_include(config_file_parse_data *parse_data, const char *section, const char *file)
 {
        char *condition;
-       size_t i;
+       size_t section_len, i;
        int error = 0, matches;
 
        if (!parse_data->repo || !file)
                return 0;
 
-       condition = git__substrdup(section + strlen("includeIf."),
-                                  strlen(section) - strlen("includeIf.") - strlen(".path"));
+       section_len = strlen(section);
+
+       /*
+        * We checked that the string starts with `includeIf.` and ends
+        * in `.path` to get here.  Make sure it consists of more.
+        */
+       if (section_len < CONST_STRLEN("includeIf.") + CONST_STRLEN(".path"))
+               return 0;
+
+       condition = git__substrdup(section + CONST_STRLEN("includeIf."),
+               section_len - CONST_STRLEN("includeIf.") - CONST_STRLEN(".path"));
+
+       GIT_ERROR_CHECK_ALLOC(condition);
 
        for (i = 0; i < ARRAY_SIZE(conditions); i++) {
                if (git__prefixcmp(condition, conditions[i].prefix))
@@ -763,7 +775,7 @@ static int read_on_variable(
        void *data)
 {
        config_file_parse_data *parse_data = (config_file_parse_data *)data;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_config_entry *entry;
        const char *c;
        int result = 0;
@@ -777,19 +789,19 @@ static int read_on_variable(
                 * here. Git appears to warn in most cases if it sees
                 * un-namespaced config options.
                 */
-               git_buf_puts(&buf, current_section);
-               git_buf_putc(&buf, '.');
+               git_str_puts(&buf, current_section);
+               git_str_putc(&buf, '.');
        }
 
        for (c = var_name; *c; c++)
-               git_buf_putc(&buf, git__tolower(*c));
+               git_str_putc(&buf, git__tolower(*c));
 
-       if (git_buf_oom(&buf))
+       if (git_str_oom(&buf))
                return -1;
 
        entry = git__calloc(1, sizeof(git_config_entry));
        GIT_ERROR_CHECK_ALLOC(entry);
-       entry->name = git_buf_detach(&buf);
+       entry->name = git_str_detach(&buf);
        entry->value = var_value ? git__strdup(var_value) : NULL;
        entry->level = parse_data->level;
        entry->include_depth = parse_data->depth;
@@ -856,12 +868,12 @@ static int config_file_read(
        git_config_level_t level,
        int depth)
 {
-       git_buf contents = GIT_BUF_INIT;
+       git_str contents = GIT_STR_INIT;
        struct stat st;
        int error;
 
        if (p_stat(file->path, &st) < 0) {
-               error = git_path_set_error(errno, file->path, "stat");
+               error = git_fs_path_set_error(errno, file->path, "stat");
                goto out;
        }
 
@@ -869,7 +881,7 @@ static int config_file_read(
                goto out;
 
        git_futils_filestamp_set_from_stat(&file->stamp, &st);
-       if ((error = git_hash_buf(&file->checksum, contents.ptr, contents.size)) < 0)
+       if ((error = git_hash_buf(file->checksum, contents.ptr, contents.size, GIT_HASH_ALGORITHM_SHA1)) < 0)
                goto out;
 
        if ((error = config_file_read_buffer(entries, repo, file, level, depth,
@@ -877,36 +889,36 @@ static int config_file_read(
                goto out;
 
 out:
-       git_buf_dispose(&contents);
+       git_str_dispose(&contents);
        return error;
 }
 
-static int write_section(git_buf *fbuf, const char *key)
+static int write_section(git_str *fbuf, const char *key)
 {
        int result;
        const char *dot;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        /* All of this just for [section "subsection"] */
        dot = strchr(key, '.');
-       git_buf_putc(&buf, '[');
+       git_str_putc(&buf, '[');
        if (dot == NULL) {
-               git_buf_puts(&buf, key);
+               git_str_puts(&buf, key);
        } else {
                char *escaped;
-               git_buf_put(&buf, key, dot - key);
+               git_str_put(&buf, key, dot - key);
                escaped = escape_value(dot + 1);
                GIT_ERROR_CHECK_ALLOC(escaped);
-               git_buf_printf(&buf, " \"%s\"", escaped);
+               git_str_printf(&buf, " \"%s\"", escaped);
                git__free(escaped);
        }
-       git_buf_puts(&buf, "]\n");
+       git_str_puts(&buf, "]\n");
 
-       if (git_buf_oom(&buf))
+       if (git_str_oom(&buf))
                return -1;
 
-       result = git_buf_put(fbuf, git_buf_cstr(&buf), buf.size);
-       git_buf_dispose(&buf);
+       result = git_str_put(fbuf, git_str_cstr(&buf), buf.size);
+       git_str_dispose(&buf);
 
        return result;
 }
@@ -930,8 +942,8 @@ static const char *quotes_for_value(const char *value)
 }
 
 struct write_data {
-       git_buf *buf;
-       git_buf buffered_comment;
+       git_str *buf;
+       git_str buffered_comment;
        unsigned int in_section : 1,
                preg_replaced : 1;
        const char *orig_section;
@@ -942,12 +954,12 @@ struct write_data {
        const char *value;
 };
 
-static int write_line_to(git_buf *buf, const char *line, size_t line_len)
+static int write_line_to(git_str *buf, const char *line, size_t line_len)
 {
-       int result = git_buf_put(buf, line, line_len);
+       int result = git_str_put(buf, line, line_len);
 
        if (!result && line_len && line[line_len-1] != '\n')
-               result = git_buf_printf(buf, "\n");
+               result = git_str_printf(buf, "\n");
 
        return result;
 }
@@ -963,7 +975,7 @@ static int write_value(struct write_data *write_data)
        int result;
 
        q = quotes_for_value(write_data->value);
-       result = git_buf_printf(write_data->buf,
+       result = git_str_printf(write_data->buf,
                "\t%s = %s%s%s\n", write_data->orig_name, q, write_data->value, q);
 
        /* If we are updating a single name/value, we're done.  Setting `value`
@@ -1002,8 +1014,8 @@ static int write_on_section(
         * If there were comments just before this section, dump them as well.
         */
        if (!result) {
-               result = git_buf_put(write_data->buf, write_data->buffered_comment.ptr, write_data->buffered_comment.size);
-               git_buf_clear(&write_data->buffered_comment);
+               result = git_str_put(write_data->buf, write_data->buffered_comment.ptr, write_data->buffered_comment.size);
+               git_str_clear(&write_data->buffered_comment);
        }
 
        if (!result)
@@ -1031,10 +1043,10 @@ static int write_on_variable(
        /*
         * If there were comments just before this variable, let's dump them as well.
         */
-       if ((error = git_buf_put(write_data->buf, write_data->buffered_comment.ptr, write_data->buffered_comment.size)) < 0)
+       if ((error = git_str_put(write_data->buf, write_data->buffered_comment.ptr, write_data->buffered_comment.size)) < 0)
                return error;
 
-       git_buf_clear(&write_data->buffered_comment);
+       git_str_clear(&write_data->buffered_comment);
 
        /* See if we are to update this name/value pair; first examine name */
        if (write_data->in_section &&
@@ -1081,7 +1093,7 @@ static int write_on_eof(
        /*
         * If we've buffered comments when reaching EOF, make sure to dump them.
         */
-       if ((result = git_buf_put(write_data->buf, write_data->buffered_comment.ptr, write_data->buffered_comment.size)) < 0)
+       if ((result = git_str_put(write_data->buf, write_data->buffered_comment.ptr, write_data->buffered_comment.size)) < 0)
                return result;
 
        /* If we are at the EOF and have not written our value (again, for a
@@ -1108,7 +1120,7 @@ static int config_file_write(config_file_backend *cfg, const char *orig_key, con
 
 {
        char *orig_section = NULL, *section = NULL, *orig_name, *name, *ldot;
-       git_buf buf = GIT_BUF_INIT, contents = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT, contents = GIT_STR_INIT;
        git_config_parser parser = GIT_CONFIG_PARSER_INIT;
        git_filebuf file = GIT_FILEBUF_INIT;
        struct write_data write_data;
@@ -1117,7 +1129,7 @@ static int config_file_write(config_file_backend *cfg, const char *orig_key, con
        memset(&write_data, 0, sizeof(write_data));
 
        if (cfg->locked) {
-               error = git_buf_puts(&contents, git_buf_cstr(&cfg->locked_content) == NULL ? "" : git_buf_cstr(&cfg->locked_content));
+               error = git_str_puts(&contents, git_str_cstr(&cfg->locked_content) == NULL ? "" : git_str_cstr(&cfg->locked_content));
        } else {
                if ((error = git_filebuf_open(&file, cfg->file.path, GIT_FILEBUF_HASH_CONTENTS,
                                              GIT_CONFIG_FILE_MODE)) < 0)
@@ -1157,10 +1169,10 @@ static int config_file_write(config_file_backend *cfg, const char *orig_key, con
        if (cfg->locked) {
                size_t len = buf.asize;
                /* Update our copy with the modified contents */
-               git_buf_dispose(&cfg->locked_content);
-               git_buf_attach(&cfg->locked_content, git_buf_detach(&buf), len);
+               git_str_dispose(&cfg->locked_content);
+               git_str_attach(&cfg->locked_content, git_str_detach(&buf), len);
        } else {
-               git_filebuf_write(&file, git_buf_cstr(&buf), git_buf_len(&buf));
+               git_filebuf_write(&file, git_str_cstr(&buf), git_str_len(&buf));
 
                if ((error = git_filebuf_commit(&file)) < 0)
                        goto done;
@@ -1172,9 +1184,9 @@ static int config_file_write(config_file_backend *cfg, const char *orig_key, con
 done:
        git__free(section);
        git__free(orig_section);
-       git_buf_dispose(&write_data.buffered_comment);
-       git_buf_dispose(&buf);
-       git_buf_dispose(&contents);
+       git_str_dispose(&write_data.buffered_comment);
+       git_str_dispose(&buf);
+       git_str_dispose(&contents);
        git_filebuf_cleanup(&file);
        git_config_parser_dispose(&parser);
 
index 5b573a995c932c6ab59ee4c0375455193ce8f735..560229cf534a187d49401b4965b201e679e05e3b 100644 (file)
@@ -14,7 +14,7 @@
 typedef struct {
        git_config_backend parent;
        git_config_entries *entries;
-       git_buf cfg;
+       git_str cfg;
 } config_memory_backend;
 
 typedef struct {
@@ -38,7 +38,7 @@ static int read_variable_cb(
        void *payload)
 {
        config_memory_parse_data *parse_data = (config_memory_parse_data *) payload;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_config_entry *entry;
        const char *c;
        int result;
@@ -52,19 +52,19 @@ static int read_variable_cb(
                 * here. Git appears to warn in most cases if it sees
                 * un-namespaced config options.
                 */
-               git_buf_puts(&buf, current_section);
-               git_buf_putc(&buf, '.');
+               git_str_puts(&buf, current_section);
+               git_str_putc(&buf, '.');
        }
 
        for (c = var_name; *c; c++)
-               git_buf_putc(&buf, git__tolower(*c));
+               git_str_putc(&buf, git__tolower(*c));
 
-       if (git_buf_oom(&buf))
+       if (git_str_oom(&buf))
                return -1;
 
        entry = git__calloc(1, sizeof(git_config_entry));
        GIT_ERROR_CHECK_ALLOC(entry);
-       entry->name = git_buf_detach(&buf);
+       entry->name = git_str_detach(&buf);
        entry->value = var_value ? git__strdup(var_value) : NULL;
        entry->level = parse_data->level;
        entry->include_depth = 0;
@@ -178,7 +178,7 @@ static void config_memory_free(git_config_backend *_backend)
                return;
 
        git_config_entries_free(backend->entries);
-       git_buf_dispose(&backend->cfg);
+       git_str_dispose(&backend->cfg);
        git__free(backend);
 }
 
@@ -194,7 +194,7 @@ int git_config_backend_from_string(git_config_backend **out, const char *cfg, si
                return -1;
        }
 
-       if (git_buf_set(&backend->cfg, cfg, len) < 0) {
+       if (git_str_set(&backend->cfg, cfg, len) < 0) {
                git_config_entries_free(backend->entries);
                git__free(backend);
                return -1;
index 9f95e67d78c59df575c6aa8bf72fe4397b16ba9b..06931368e7b7ed8e704b02e423bc35feb55fa00b 100644 (file)
@@ -36,7 +36,7 @@ static int strip_comments(char *line, int in_quotes)
        char *ptr;
 
        for (ptr = line; *ptr; ++ptr) {
-               if (ptr[0] == '"' && ptr > line && ptr[-1] != '\\')
+               if (ptr[0] == '"' && ((ptr > line && ptr[-1] != '\\') || ptr == line))
                        quote_count++;
 
                if ((ptr[0] == ';' || ptr[0] == '#') &&
@@ -67,7 +67,7 @@ static int parse_subsection_header(git_config_parser *reader, const char *line,
        int c, rpos;
        const char *first_quote, *last_quote;
        const char *line_start = line;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        size_t quoted_len, alloc_len, base_name_len = strlen(base_name);
 
        /* Skip any additional whitespace before our section name */
@@ -97,8 +97,8 @@ static int parse_subsection_header(git_config_parser *reader, const char *line,
        GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, base_name_len, quoted_len);
        GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
 
-       if (git_buf_grow(&buf, alloc_len) < 0 ||
-           git_buf_printf(&buf, "%s.", base_name) < 0)
+       if (git_str_grow(&buf, alloc_len) < 0 ||
+           git_str_printf(&buf, "%s.", base_name) < 0)
                goto end_error;
 
        rpos = 0;
@@ -132,25 +132,25 @@ static int parse_subsection_header(git_config_parser *reader, const char *line,
                        break;
                }
 
-               git_buf_putc(&buf, (char)c);
+               git_str_putc(&buf, (char)c);
                c = line[++rpos];
        } while (line + rpos < last_quote);
 
 end_parse:
-       if (git_buf_oom(&buf))
+       if (git_str_oom(&buf))
                goto end_error;
 
        if (line[rpos] != '"' || line[rpos + 1] != ']') {
                set_parse_error(reader, rpos, "unexpected text after closing quotes");
-               git_buf_dispose(&buf);
+               git_str_dispose(&buf);
                return -1;
        }
 
-       *section_name = git_buf_detach(&buf);
+       *section_name = git_str_detach(&buf);
        return (int)(&line[rpos + 2] - line_start); /* rpos is at the closing quote */
 
 end_error:
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        return -1;
 }
@@ -227,11 +227,11 @@ fail_parse:
 
 static int skip_bom(git_parse_ctx *parser)
 {
-       git_buf buf = GIT_BUF_INIT_CONST(parser->content, parser->content_len);
-       git_buf_bom_t bom;
-       int bom_offset = git_buf_detect_bom(&bom, &buf);
+       git_str buf = GIT_STR_INIT_CONST(parser->content, parser->content_len);
+       git_str_bom_t bom;
+       int bom_offset = git_str_detect_bom(&bom, &buf);
 
-       if (bom == GIT_BUF_BOM_UTF8)
+       if (bom == GIT_STR_BOM_UTF8)
                git_parse_advance_chars(parser, bom_offset);
 
        /* TODO: reference implementation is pretty stupid with BoM */
@@ -325,7 +325,7 @@ done:
        return 0;
 }
 
-static int parse_multiline_variable(git_config_parser *reader, git_buf *value, int in_quotes)
+static int parse_multiline_variable(git_config_parser *reader, git_str *value, int in_quotes, size_t *line_len)
 {
        int quote_count;
        bool multiline = true;
@@ -338,6 +338,10 @@ static int parse_multiline_variable(git_config_parser *reader, git_buf *value, i
                git_parse_advance_line(&reader->ctx);
                line = git__strndup(reader->ctx.line, reader->ctx.line_len);
                GIT_ERROR_CHECK_ALLOC(line);
+               if (GIT_ADD_SIZET_OVERFLOW(line_len, *line_len, reader->ctx.line_len)) {
+                       error = -1;
+                       goto out;
+               }
 
                /*
                 * We've reached the end of the file, there is no continuation.
@@ -358,7 +362,7 @@ static int parse_multiline_variable(git_config_parser *reader, git_buf *value, i
                        goto out;
 
                /* Add this line to the multiline var */
-               if ((error = git_buf_puts(value, proc_line)) < 0)
+               if ((error = git_str_puts(value, proc_line)) < 0)
                        goto out;
 
 next:
@@ -415,7 +419,7 @@ static int parse_name(
        return 0;
 }
 
-static int parse_variable(git_config_parser *reader, char **var_name, char **var_value)
+static int parse_variable(git_config_parser *reader, char **var_name, char **var_value, size_t *line_len)
 {
        const char *value_start = NULL;
        char *line = NULL, *name = NULL, *value = NULL;
@@ -445,18 +449,18 @@ static int parse_variable(git_config_parser *reader, char **var_name, char **var
                        goto out;
 
                if (multiline) {
-                       git_buf multi_value = GIT_BUF_INIT;
-                       git_buf_attach(&multi_value, value, 0);
+                       git_str multi_value = GIT_STR_INIT;
+                       git_str_attach(&multi_value, value, 0);
                        value = NULL;
 
-                       if (parse_multiline_variable(reader, &multi_value, quote_count % 2) < 0 ||
-                           git_buf_oom(&multi_value)) {
+                       if (parse_multiline_variable(reader, &multi_value, quote_count % 2, line_len) < 0 ||
+                           git_str_oom(&multi_value)) {
                                error = -1;
-                               git_buf_dispose(&multi_value);
+                               git_str_dispose(&multi_value);
                                goto out;
                        }
 
-                       value = git_buf_detach(&multi_value);
+                       value = git_str_detach(&multi_value);
                }
        }
 
@@ -554,7 +558,7 @@ int git_config_parse(
                        break;
 
                default: /* assume variable declaration */
-                       if ((result = parse_variable(parser, &var_name, &var_value)) == 0 && on_variable) {
+                       if ((result = parse_variable(parser, &var_name, &var_value, &line_len)) == 0 && on_variable) {
                                result = on_variable(parser, current_section, var_name, var_value, line_start, line_len, payload);
                                git__free(var_name);
                                git__free(var_value);
index 406f7140f211ce841b9ce18afa19b831c77ed83a..1e1f1e84558b4658c2d0bcacdbe2a1ad5c542621 100644 (file)
@@ -12,6 +12,7 @@
 #include "git2/index.h"
 #include "git2/sys/filter.h"
 
+#include "buf.h"
 #include "futils.h"
 #include "hash.h"
 #include "filter.h"
@@ -25,7 +26,7 @@ typedef enum {
        GIT_CRLF_TEXT_CRLF,
        GIT_CRLF_AUTO,
        GIT_CRLF_AUTO_INPUT,
-       GIT_CRLF_AUTO_CRLF,
+       GIT_CRLF_AUTO_CRLF
 } git_crlf_t;
 
 struct crlf_attrs {
@@ -152,7 +153,7 @@ static git_configmap_value output_eol(struct crlf_attrs *ca)
 GIT_INLINE(int) check_safecrlf(
        struct crlf_attrs *ca,
        const git_filter_source *src,
-       git_buf_text_stats *stats)
+       git_str_text_stats *stats)
 {
        const char *filename = git_filter_source_path(src);
 
@@ -206,19 +207,19 @@ GIT_INLINE(int) check_safecrlf(
 
 static int crlf_apply_to_odb(
        struct crlf_attrs *ca,
-       git_buf *to,
-       const git_buf *from,
+       git_str *to,
+       const git_str *from,
        const git_filter_source *src)
 {
-       git_buf_text_stats stats;
+       git_str_text_stats stats;
        bool is_binary;
        int error;
 
        /* Binary attribute? Empty file? Nothing to do */
-       if (ca->crlf_action == GIT_CRLF_BINARY || !git_buf_len(from))
+       if (ca->crlf_action == GIT_CRLF_BINARY || from->size == 0)
                return GIT_PASSTHROUGH;
 
-       is_binary = git_buf_gather_text_stats(&stats, from, false);
+       is_binary = git_str_gather_text_stats(&stats, from, false);
 
        /* Heuristics to see if we can skip the conversion.
         * Straight from Core Git.
@@ -246,22 +247,22 @@ static int crlf_apply_to_odb(
                return GIT_PASSTHROUGH;
 
        /* Actually drop the carriage returns */
-       return git_buf_crlf_to_lf(to, from);
+       return git_str_crlf_to_lf(to, from);
 }
 
 static int crlf_apply_to_workdir(
        struct crlf_attrs *ca,
-       git_buf *to,
-       const git_buf *from)
+       git_str *to,
+       const git_str *from)
 {
-       git_buf_text_stats stats;
+       git_str_text_stats stats;
        bool is_binary;
 
        /* Empty file? Nothing to do. */
-       if (git_buf_len(from) == 0 || output_eol(ca) != GIT_EOL_CRLF)
+       if (git_str_len(from) == 0 || output_eol(ca) != GIT_EOL_CRLF)
                return GIT_PASSTHROUGH;
 
-       is_binary = git_buf_gather_text_stats(&stats, from, false);
+       is_binary = git_str_gather_text_stats(&stats, from, false);
 
        /* If there are no LFs, or all LFs are part of a CRLF, nothing to do */
        if (stats.lf == 0 || stats.lf == stats.crlf)
@@ -280,7 +281,7 @@ static int crlf_apply_to_workdir(
                        return GIT_PASSTHROUGH;
        }
 
-       return git_buf_lf_to_crlf(to, from);
+       return git_str_lf_to_crlf(to, from);
 }
 
 static int convert_attrs(
@@ -368,22 +369,24 @@ static int crlf_check(
 static int crlf_apply(
        git_filter *self,
        void **payload, /* may be read and/or set */
-       git_buf *to,
-       const git_buf *from,
+       git_str *to,
+       const git_str *from,
        const git_filter_source *src)
 {
+       int error = 0;
+
        /* initialize payload in case `check` was bypassed */
        if (!*payload) {
-               int error = crlf_check(self, payload, src, NULL);
-
-               if (error < 0)
+               if ((error = crlf_check(self, payload, src, NULL)) < 0)
                        return error;
        }
 
        if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE)
-               return crlf_apply_to_workdir(*payload, to, from);
+               error = crlf_apply_to_workdir(*payload, to, from);
        else
-               return crlf_apply_to_odb(*payload, to, from, src);
+               error = crlf_apply_to_odb(*payload, to, from, src);
+
+       return error;
 }
 
 static int crlf_stream(
index 2297ee66cf34b0a912ed270c6cf7f8ab0c3c6407..0e5ffc96b06674c3c7233eedf684712df9824b0a 100644 (file)
@@ -11,8 +11,8 @@
 #endif
 
 #include "util.h"
-#include "cache.h"
 #include "posix.h"
+#include "date.h"
 
 #include <ctype.h>
 #include <time.h>
@@ -853,11 +853,11 @@ static git_time_t approxidate_str(const char *date,
        }
        pending_number(&tm, &number);
        if (!touched)
-               *error_ret = 1;
+               *error_ret = -1;
        return update_tm(&tm, &now, 0);
 }
 
-int git__date_parse(git_time_t *out, const char *date)
+int git_date_parse(git_time_t *out, const char *date)
 {
        time_t time_sec;
        git_time_t timestamp;
@@ -872,34 +872,27 @@ int git__date_parse(git_time_t *out, const char *date)
                return -1;
 
        *out = approxidate_str(date, time_sec, &error_ret);
-   return error_ret;
+       return error_ret;
 }
 
-int git__date_rfc2822_fmt(char *out, size_t len, const git_time *date)
+int git_date_rfc2822_fmt(git_str *out, git_time_t time, int offset)
 {
-       int written;
-       struct tm gmt;
        time_t t;
+       struct tm gmt;
 
        GIT_ASSERT_ARG(out);
-       GIT_ASSERT_ARG(date);
 
-       t = (time_t) (date->time + date->offset * 60);
+       t = (time_t) (time + offset * 60);
 
-       if (p_gmtime_r (&t, &gmt) == NULL)
+       if (p_gmtime_r(&t, &gmt) == NULL)
                return -1;
 
-       written = p_snprintf(out, len, "%.3s, %u %.3s %.4u %02u:%02u:%02u %+03d%02d",
+       return git_str_printf(out, "%.3s, %u %.3s %.4u %02u:%02u:%02u %+03d%02d",
                weekday_names[gmt.tm_wday],
                gmt.tm_mday,
                month_names[gmt.tm_mon],
                gmt.tm_year + 1900,
                gmt.tm_hour, gmt.tm_min, gmt.tm_sec,
-               date->offset / 60, date->offset % 60);
-
-       if (written < 0 || (written > (int) len - 1))
-               return -1;
-
-       return 0;
+               offset / 60, offset % 60);
 }
 
diff --git a/src/date.h b/src/date.h
new file mode 100644 (file)
index 0000000..7ebd3c3
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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_date_h__
+#define INCLUDE_date_h__
+
+#include "util.h"
+#include "str.h"
+
+/*
+ * Parse a string into a value as a git_time_t.
+ *
+ * Sample valid input:
+ * - "yesterday"
+ * - "July 17, 2003"
+ * - "2003-7-17 08:23"
+ */
+extern int git_date_parse(git_time_t *out, const char *date);
+
+/*
+ * Format a git_time as a RFC2822 string
+ *
+ * @param out buffer to store formatted date
+ * @param time the time to be formatted
+ * @param offset the timezone offset
+ * @return 0 if successful; -1 on error
+ */
+extern int git_date_rfc2822_fmt(git_str *out, git_time_t time, int offset);
+
+#endif
index 103d0da5c8d212f39c831e46c11e9d608c54de28..1033eac500a05c4cbd40c0fd45019a057cf88ad2 100644 (file)
@@ -12,6 +12,7 @@
 #include "git2/diff.h"
 #include "git2/status.h"
 
+#include "buf.h"
 #include "commit.h"
 #include "commit_list.h"
 #include "oidmap.h"
@@ -322,7 +323,7 @@ static unsigned long finish_depth_computation(
        return seen_commits;
 }
 
-static int display_name(git_buf *buf, git_repository *repo, struct commit_name *n)
+static int display_name(git_str *buf, git_repository *repo, struct commit_name *n)
 {
        if (n->prio == 2 && !n->tag) {
                if (git_tag_lookup(&n->tag, repo, &n->sha1) < 0) {
@@ -346,9 +347,9 @@ static int display_name(git_buf *buf, git_repository *repo, struct commit_name *
        }
 
        if (n->tag)
-               git_buf_printf(buf, "%s", git_tag_name(n->tag));
+               git_str_printf(buf, "%s", git_tag_name(n->tag));
        else
-               git_buf_printf(buf, "%s", n->path);
+               git_str_printf(buf, "%s", n->path);
 
        return 0;
 }
@@ -388,7 +389,7 @@ static int find_unique_abbrev_size(
 }
 
 static int show_suffix(
-       git_buf *buf,
+       git_str *buf,
        int depth,
        git_repository *repo,
        const git_oid *id,
@@ -403,11 +404,11 @@ static int show_suffix(
 
        git_oid_fmt(hex_oid, id);
 
-       git_buf_printf(buf, "-%d-g", depth);
+       git_str_printf(buf, "-%d-g", depth);
 
-       git_buf_put(buf, hex_oid, size);
+       git_str_put(buf, hex_oid, size);
 
-       return git_buf_oom(buf) ? -1 : 0;
+       return git_str_oom(buf) ? -1 : 0;
 }
 
 #define MAX_CANDIDATES_TAGS FLAG_BITS - 1
@@ -769,7 +770,10 @@ static int normalize_format_options(
        return 0;
 }
 
-int git_describe_format(git_buf *out, const git_describe_result *result, const git_describe_format_options *given)
+static int git_describe__format(
+       git_str *out,
+       const git_describe_result *result,
+       const git_describe_format_options *given)
 {
        int error;
        git_repository *repo;
@@ -782,10 +786,6 @@ int git_describe_format(git_buf *out, const git_describe_result *result, const g
        GIT_ERROR_CHECK_VERSION(given, GIT_DESCRIBE_FORMAT_OPTIONS_VERSION, "git_describe_format_options");
        normalize_format_options(&opts, given);
 
-       if ((error = git_buf_sanitize(out)) < 0)
-               return error;
-
-
        if (opts.always_use_long_format && opts.abbreviated_size == 0) {
                git_error_set(GIT_ERROR_DESCRIBE, "cannot describe - "
                        "'always_use_long_format' is incompatible with a zero"
@@ -809,9 +809,9 @@ int git_describe_format(git_buf *out, const git_describe_result *result, const g
                }
 
                if (result->dirty && opts.dirty_suffix)
-                       git_buf_puts(out, opts.dirty_suffix);
+                       git_str_puts(out, opts.dirty_suffix);
 
-               return git_buf_oom(out) ? -1 : 0;
+               return git_str_oom(out) ? -1 : 0;
        }
 
        /* If we didn't find *any* tags, we fall back to the commit's id */
@@ -824,12 +824,12 @@ int git_describe_format(git_buf *out, const git_describe_result *result, const g
                        return -1;
 
                git_oid_fmt(hex_oid, &result->commit_id);
-               git_buf_put(out, hex_oid, size);
+               git_str_put(out, hex_oid, size);
 
                if (result->dirty && opts.dirty_suffix)
-                       git_buf_puts(out, opts.dirty_suffix);
+                       git_str_puts(out, opts.dirty_suffix);
 
-               return git_buf_oom(out) ? -1 : 0;
+               return git_str_oom(out) ? -1 : 0;
        }
 
        /* Lastly, if we found a matching tag, we show that */
@@ -845,10 +845,18 @@ int git_describe_format(git_buf *out, const git_describe_result *result, const g
        }
 
        if (result->dirty && opts.dirty_suffix) {
-               git_buf_puts(out, opts.dirty_suffix);
+               git_str_puts(out, opts.dirty_suffix);
        }
 
-       return git_buf_oom(out) ? -1 : 0;
+       return git_str_oom(out) ? -1 : 0;
+}
+
+int git_describe_format(
+       git_buf *out,
+       const git_describe_result *result,
+       const git_describe_format_options *given)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_describe__format, result, given);
 }
 
 void git_describe_result_free(git_describe_result *result)
index 30b9f647a45a37fede8ef611a6132aad26d25050..9840d6050daf5c166b02e7e1d4a43981a426cf14 100644 (file)
@@ -8,6 +8,7 @@
 #include "diff.h"
 
 #include "common.h"
+#include "buf.h"
 #include "patch.h"
 #include "email.h"
 #include "commit.h"
@@ -162,6 +163,7 @@ int git_diff_format_email(
        const git_diff_format_email_options *opts)
 {
        git_email_create_options email_create_opts = GIT_EMAIL_CREATE_OPTIONS_INIT;
+       git_str email = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(out);
@@ -172,14 +174,29 @@ int git_diff_format_email(
                GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION,
                "git_format_email_options");
 
+       /* This is a `git_buf` special case; subsequent calls append. */
+       email.ptr = out->ptr;
+       email.asize = out->reserved;
+       email.size = out->size;
+
+       out->ptr = git_str__initstr;
+       out->reserved = 0;
+       out->size = 0;
+
        if ((opts->flags & GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER) != 0)
                email_create_opts.subject_prefix = "";
 
-
-       error = git_email__append_from_diff(out, diff, opts->patch_no,
+       error = git_email__append_from_diff(&email, diff, opts->patch_no,
                opts->total_patches, opts->id, opts->summary, opts->body,
                opts->author, &email_create_opts);
 
+       if (error < 0)
+               goto done;
+
+       error = git_buf_fromstr(out, &email);
+
+done:
+       git_str_dispose(&email);
        return error;
 }
 
@@ -269,7 +286,7 @@ static int flush_hunk(git_oid *result, git_hash_ctx *ctx)
        unsigned short carry = 0;
        int error, i;
 
-       if ((error = git_hash_final(&hash, ctx)) < 0 ||
+       if ((error = git_hash_final(hash.id, ctx)) < 0 ||
            (error = git_hash_init(ctx)) < 0)
                return error;
 
@@ -282,7 +299,7 @@ static int flush_hunk(git_oid *result, git_hash_ctx *ctx)
        return 0;
 }
 
-static void strip_spaces(git_buf *buf)
+static void strip_spaces(git_str *buf)
 {
        char *src = buf->ptr, *dst = buf->ptr;
        char c;
@@ -295,7 +312,7 @@ static void strip_spaces(git_buf *buf)
                }
        }
 
-       git_buf_truncate(buf, len);
+       git_str_truncate(buf, len);
 }
 
 static int diff_patchid_print_callback_to_buf(
@@ -305,7 +322,7 @@ static int diff_patchid_print_callback_to_buf(
        void *payload)
 {
        struct patch_id_args *args = (struct patch_id_args *) payload;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        int error = 0;
 
        if (line->origin == GIT_DIFF_LINE_CONTEXT_EOFNL ||
@@ -331,7 +348,7 @@ static int diff_patchid_print_callback_to_buf(
                args->first_file = 0;
 
 out:
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
@@ -352,7 +369,7 @@ int git_diff_patchid(git_oid *out, git_diff *diff, git_diff_patchid_options *opt
 
        memset(&args, 0, sizeof(args));
        args.first_file = 1;
-       if ((error = git_hash_ctx_init(&args.ctx)) < 0)
+       if ((error = git_hash_ctx_init(&args.ctx, GIT_HASH_ALGORITHM_SHA1)) < 0)
                goto out;
 
        if ((error = git_diff_print(diff,
index 69233b39fbf08f5587f3618dc9735c67437328a4..2cc35e65b7c74864ae9839323c39863f3be0e8d2 100644 (file)
@@ -14,9 +14,7 @@
 #include "git2/sys/diff.h"
 #include "git2/oid.h"
 
-#include <stdio.h>
 #include "vector.h"
-#include "buffer.h"
 #include "iterator.h"
 #include "repository.h"
 #include "pool.h"
@@ -28,7 +26,7 @@
 typedef enum {
        GIT_DIFF_TYPE_UNKNOWN = 0,
        GIT_DIFF_TYPE_GENERATED = 1,
-       GIT_DIFF_TYPE_PARSED = 2,
+       GIT_DIFF_TYPE_PARSED = 2
 } git_diff_origin_t;
 
 struct git_diff {
@@ -53,7 +51,7 @@ struct git_diff {
 };
 
 extern int git_diff_delta__format_file_header(
-       git_buf *out,
+       git_str *out,
        const git_diff_delta *delta,
        const char *oldpfx,
        const char *newpfx,
index a3892d35eeaa68e53a62819c728f323410a90c27..5f25fdb442ba7fe14510d5529e8d5a61650d7914 100644 (file)
@@ -21,7 +21,7 @@ typedef enum {
        DIFF_DRIVER_AUTO = 0,
        DIFF_DRIVER_BINARY = 1,
        DIFF_DRIVER_TEXT = 2,
-       DIFF_DRIVER_PATTERNLIST = 3,
+       DIFF_DRIVER_PATTERNLIST = 3
 } git_diff_driver_t;
 
 typedef struct {
@@ -51,11 +51,9 @@ struct git_diff_driver_registry {
 
 #define FORCE_DIFFABLE (GIT_DIFF_FORCE_TEXT | GIT_DIFF_FORCE_BINARY)
 
-static git_diff_driver global_drivers[3] = {
-       { DIFF_DRIVER_AUTO,   0, 0, },
-       { DIFF_DRIVER_BINARY, GIT_DIFF_FORCE_BINARY, 0 },
-       { DIFF_DRIVER_TEXT,   GIT_DIFF_FORCE_TEXT, 0 },
-};
+static git_diff_driver diff_driver_auto =   { DIFF_DRIVER_AUTO,   0, 0 };
+static git_diff_driver diff_driver_binary = { DIFF_DRIVER_BINARY, GIT_DIFF_FORCE_BINARY, 0 };
+static git_diff_driver diff_driver_text =   { DIFF_DRIVER_TEXT,   GIT_DIFF_FORCE_TEXT, 0 };
 
 git_diff_driver_registry *git_diff_driver_registry_new(void)
 {
@@ -90,7 +88,7 @@ static int diff_driver_add_patterns(
        int error = 0;
        const char *scan, *end;
        git_diff_driver_pattern *pat = NULL;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        for (scan = regex_str; scan; scan = end) {
                /* get pattern to fill in */
@@ -105,10 +103,10 @@ static int diff_driver_add_patterns(
                }
 
                if ((end = strchr(scan, '\n')) != NULL) {
-                       error = git_buf_set(&buf, scan, end - scan);
+                       error = git_str_set(&buf, scan, end - scan);
                        end++;
                } else {
-                       error = git_buf_sets(&buf, scan);
+                       error = git_str_sets(&buf, scan);
                }
                if (error < 0)
                        break;
@@ -122,7 +120,7 @@ static int diff_driver_add_patterns(
 
        if (error && pat != NULL)
                (void)git_array_pop(drv->fn_patterns); /* release last item */
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        /* We want to ignore bad patterns, so return success regardless */
        return 0;
@@ -237,7 +235,7 @@ static int git_diff_driver_load(
        git_diff_driver *drv;
        size_t namelen;
        git_config *cfg = NULL;
-       git_buf name = GIT_BUF_INIT;
+       git_str name = GIT_STR_INIT;
        git_config_entry *ce = NULL;
        bool found_driver = false;
 
@@ -260,13 +258,13 @@ static int git_diff_driver_load(
                goto done;
        }
 
-       if ((error = git_buf_printf(&name, "diff.%s.binary", driver_name)) < 0)
+       if ((error = git_str_printf(&name, "diff.%s.binary", driver_name)) < 0)
                goto done;
 
        switch (git_config__get_bool_force(cfg, name.ptr, -1)) {
        case true:
                /* if diff.<driver>.binary is true, just return the binary driver */
-               *out = &global_drivers[DIFF_DRIVER_BINARY];
+               *out = &diff_driver_binary;
                goto done;
        case false:
                /* if diff.<driver>.binary is false, force binary checks off */
@@ -281,8 +279,8 @@ static int git_diff_driver_load(
 
        /* TODO: warn if diff.<name>.command or diff.<name>.textconv are set */
 
-       git_buf_truncate(&name, namelen + strlen("diff.."));
-       if ((error = git_buf_PUTS(&name, "xfuncname")) < 0)
+       git_str_truncate(&name, namelen + strlen("diff.."));
+       if ((error = git_str_PUTS(&name, "xfuncname")) < 0)
                goto done;
 
        if ((error = git_config_get_multivar_foreach(
@@ -292,8 +290,8 @@ static int git_diff_driver_load(
                git_error_clear(); /* no diff.<driver>.xfuncname, so just continue */
        }
 
-       git_buf_truncate(&name, namelen + strlen("diff.."));
-       if ((error = git_buf_PUTS(&name, "funcname")) < 0)
+       git_str_truncate(&name, namelen + strlen("diff.."));
+       if ((error = git_str_PUTS(&name, "funcname")) < 0)
                goto done;
 
        if ((error = git_config_get_multivar_foreach(
@@ -309,8 +307,8 @@ static int git_diff_driver_load(
                found_driver = true;
        }
 
-       git_buf_truncate(&name, namelen + strlen("diff.."));
-       if ((error = git_buf_PUTS(&name, "wordregex")) < 0)
+       git_str_truncate(&name, namelen + strlen("diff.."));
+       if ((error = git_str_PUTS(&name, "wordregex")) < 0)
                goto done;
 
        if ((error = git_config__lookup_entry(&ce, cfg, name.ptr, false)) < 0)
@@ -340,7 +338,7 @@ static int git_diff_driver_load(
 
 done:
        git_config_entry_free(ce);
-       git_buf_dispose(&name);
+       git_str_dispose(&name);
        git_config_free(cfg);
 
        if (!*out) {
@@ -374,9 +372,9 @@ int git_diff_driver_lookup(
        else if (GIT_ATTR_IS_UNSPECIFIED(values[0]))
                /* just use the auto value */;
        else if (GIT_ATTR_IS_FALSE(values[0]))
-               *out = &global_drivers[DIFF_DRIVER_BINARY];
+               *out = &diff_driver_binary;
        else if (GIT_ATTR_IS_TRUE(values[0]))
-               *out = &global_drivers[DIFF_DRIVER_TEXT];
+               *out = &diff_driver_text;
 
        /* otherwise look for driver information in config and build driver */
        else if ((error = git_diff_driver_load(out, repo, values[0])) < 0) {
@@ -387,7 +385,7 @@ int git_diff_driver_lookup(
        }
 
        if (!*out)
-               *out = &global_drivers[DIFF_DRIVER_AUTO];
+               *out = &diff_driver_auto;
 
        return error;
 }
@@ -420,11 +418,11 @@ void git_diff_driver_update_options(
 int git_diff_driver_content_is_binary(
        git_diff_driver *driver, const char *content, size_t content_len)
 {
-       git_buf search = GIT_BUF_INIT;
+       git_str search = GIT_STR_INIT;
 
        GIT_UNUSED(driver);
 
-       git_buf_attach_notowned(&search, content,
+       git_str_attach_notowned(&search, content,
                min(content_len, GIT_FILTER_BYTES_TO_CHECK_NUL));
 
        /* TODO: provide encoding / binary detection callbacks that can
@@ -432,15 +430,15 @@ int git_diff_driver_content_is_binary(
         * let's just use the simple NUL-byte detection that core git uses.
         */
 
-       /* previously was: if (git_buf_is_binary(&search)) */
-       if (git_buf_contains_nul(&search))
+       /* previously was: if (git_str_is_binary(&search)) */
+       if (git_str_contains_nul(&search))
                return 1;
 
        return 0;
 }
 
 static int diff_context_line__simple(
-       git_diff_driver *driver, git_buf *line)
+       git_diff_driver *driver, git_str *line)
 {
        char firstch = line->ptr[0];
        GIT_UNUSED(driver);
@@ -448,7 +446,7 @@ static int diff_context_line__simple(
 }
 
 static int diff_context_line__pattern_match(
-       git_diff_driver *driver, git_buf *line)
+       git_diff_driver *driver, git_str *line)
 {
        size_t i, maxi = git_array_size(driver->fn_patterns);
        git_regmatch pmatch[2];
@@ -462,9 +460,9 @@ static int diff_context_line__pattern_match(
 
                        /* use pmatch data to trim line data */
                        i = (pmatch[1].start >= 0) ? 1 : 0;
-                       git_buf_consume(line, git_buf_cstr(line) + pmatch[i].start);
-                       git_buf_truncate(line, pmatch[i].end - pmatch[i].start);
-                       git_buf_rtrim(line);
+                       git_str_consume(line, git_str_cstr(line) + pmatch[i].start);
+                       git_str_truncate(line, pmatch[i].end - pmatch[i].start);
+                       git_str_rtrim(line);
 
                        return true;
                }
@@ -482,9 +480,9 @@ static long diff_context_find(
 {
        git_diff_find_context_payload *ctxt = payload;
 
-       if (git_buf_set(&ctxt->line, line, (size_t)line_len) < 0)
+       if (git_str_set(&ctxt->line, line, (size_t)line_len) < 0)
                return -1;
-       git_buf_rtrim(&ctxt->line);
+       git_str_rtrim(&ctxt->line);
 
        if (!ctxt->line.size)
                return -1;
@@ -511,14 +509,14 @@ void git_diff_find_context_init(
                payload_out->driver = driver;
                payload_out->match_line = (driver->type == DIFF_DRIVER_PATTERNLIST) ?
                        diff_context_line__pattern_match : diff_context_line__simple;
-               git_buf_init(&payload_out->line, 0);
+               git_str_init(&payload_out->line, 0);
        }
 }
 
 void git_diff_find_context_clear(git_diff_find_context_payload *payload)
 {
        if (payload) {
-               git_buf_dispose(&payload->line);
+               git_str_dispose(&payload->line);
                payload->driver = NULL;
        }
 }
index a03a67e676e73c880e6db016268cfe58ff3cd479..03711e89e8bef125a0702f40516b6896d84a7b53 100644 (file)
@@ -10,7 +10,7 @@
 #include "common.h"
 
 #include "attr_file.h"
-#include "buffer.h"
+#include "str.h"
 
 typedef struct git_diff_driver_registry git_diff_driver_registry;
 
@@ -34,12 +34,12 @@ typedef long (*git_diff_find_context_fn)(
        const char *, long, char *, long, void *);
 
 typedef int (*git_diff_find_context_line)(
-       git_diff_driver *, git_buf *);
+       git_diff_driver *, git_str *);
 
 typedef struct {
        git_diff_driver *driver;
        git_diff_find_context_line match_line;
-       git_buf line;
+       git_str line;
 } git_diff_find_context_payload;
 
 void git_diff_find_context_init(
index eeaf4a5a274fc6873073eddba40e1ac90ca41084..c7e9fbeeed3d859a88ad81c5817c22260e030703 100644 (file)
@@ -178,7 +178,7 @@ static int diff_file_content_commit_to_str(
        git_diff_file_content *fc, bool check_status)
 {
        char oid[GIT_OID_HEXSZ+1];
-       git_buf content = GIT_BUF_INIT;
+       git_str content = GIT_STR_INIT;
        const char *status = "";
 
        if (check_status) {
@@ -217,11 +217,11 @@ static int diff_file_content_commit_to_str(
        }
 
        git_oid_tostr(oid, sizeof(oid), &fc->file->id);
-       if (git_buf_printf(&content, "Subproject commit %s%s\n", oid, status) < 0)
+       if (git_str_printf(&content, "Subproject commit %s%s\n", oid, status) < 0)
                return -1;
 
-       fc->map.len  = git_buf_len(&content);
-       fc->map.data = git_buf_detach(&content);
+       fc->map.len  = git_str_len(&content);
+       fc->map.data = git_str_detach(&content);
        fc->flags |= GIT_DIFF_FLAG__FREE_DATA;
 
        return 0;
@@ -270,24 +270,24 @@ static int diff_file_content_load_blob(
 }
 
 static int diff_file_content_load_workdir_symlink_fake(
-       git_diff_file_content *fc, git_buf *path)
+       git_diff_file_content *fc, git_str *path)
 {
-       git_buf target = GIT_BUF_INIT;
+       git_str target = GIT_STR_INIT;
        int error;
 
        if ((error = git_futils_readbuffer(&target, path->ptr)) < 0)
                return error;
 
-       fc->map.len = git_buf_len(&target);
-       fc->map.data = git_buf_detach(&target);
+       fc->map.len = git_str_len(&target);
+       fc->map.data = git_str_detach(&target);
        fc->flags |= GIT_DIFF_FLAG__FREE_DATA;
 
-       git_buf_dispose(&target);
+       git_str_dispose(&target);
        return error;
 }
 
 static int diff_file_content_load_workdir_symlink(
-       git_diff_file_content *fc, git_buf *path)
+       git_diff_file_content *fc, git_str *path)
 {
        ssize_t alloc_len, read_len;
        int symlink_supported, error;
@@ -309,7 +309,7 @@ static int diff_file_content_load_workdir_symlink(
 
        fc->flags |= GIT_DIFF_FLAG__FREE_DATA;
 
-       read_len = p_readlink(git_buf_cstr(path), fc->map.data, alloc_len);
+       read_len = p_readlink(git_str_cstr(path), fc->map.data, alloc_len);
        if (read_len < 0) {
                git_error_set(GIT_ERROR_OS, "failed to read symlink '%s'", fc->file->path);
                return -1;
@@ -321,23 +321,32 @@ static int diff_file_content_load_workdir_symlink(
 
 static int diff_file_content_load_workdir_file(
        git_diff_file_content *fc,
-       git_buf *path,
+       git_str *path,
        git_diff_options *diff_opts)
 {
        int error = 0;
        git_filter_list *fl = NULL;
-       git_file fd = git_futils_open_ro(git_buf_cstr(path));
-       git_buf raw = GIT_BUF_INIT;
+       git_file fd = git_futils_open_ro(git_str_cstr(path));
+       git_str raw = GIT_STR_INIT;
+       git_object_size_t new_file_size = 0;
 
        if (fd < 0)
                return fd;
 
-       if (!fc->file->size)
-           error = git_futils_filesize(&fc->file->size, fd);
+       error = git_futils_filesize(&new_file_size, fd);
 
-       if (error < 0 || !fc->file->size)
+       if (error < 0)
                goto cleanup;
 
+       if (!(fc->file->flags & GIT_DIFF_FLAG_VALID_SIZE)) {
+               fc->file->size = new_file_size;
+               fc->file->flags |= GIT_DIFF_FLAG_VALID_SIZE;
+       } else if (fc->file->size != new_file_size) {
+               git_error_set(GIT_ERROR_FILESYSTEM, "file changed before we could read it");
+               error = -1;
+               goto cleanup;
+       }
+
        if ((diff_opts->flags & GIT_DIFF_SHOW_BINARY) == 0 &&
                diff_file_content_binary_by_size(fc))
                goto cleanup;
@@ -360,7 +369,7 @@ static int diff_file_content_load_workdir_file(
        }
 
        if (!(error = git_futils_readbuffer_fd(&raw, fd, (size_t)fc->file->size))) {
-               git_buf out = GIT_BUF_INIT;
+               git_str out = GIT_STR_INIT;
 
                error = git_filter_list__convert_buf(&out, fl, &raw);
 
@@ -383,7 +392,7 @@ static int diff_file_content_load_workdir(
        git_diff_options *diff_opts)
 {
        int error = 0;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        if (fc->file->mode == GIT_FILEMODE_COMMIT)
                return diff_file_content_commit_to_str(fc, true);
@@ -406,7 +415,7 @@ static int diff_file_content_load_workdir(
                fc->file->flags |= GIT_DIFF_FLAG_VALID_ID;
        }
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        return error;
 }
 
index aba9e52ba7fa94470fa38073a69eabc0bd91644f..cfaefba66c21c42a24d00584dcd771aab8a80ccb 100644 (file)
@@ -117,6 +117,26 @@ static bool diff_pathspec_match(
                matched_pathspec, NULL);
 }
 
+static void diff_delta__flag_known_size(git_diff_file *file)
+{
+       /*
+        * If we don't know the ID, that can only come from the workdir
+        * iterator, which means we *do* know the file size.  This is a
+        * leaky abstraction, but alas.  Otherwise, we test against the
+        * empty blob id.
+        */
+       if (file->size ||
+           !(file->flags & GIT_DIFF_FLAG_VALID_ID) ||
+           git_oid_equal(&file->id, &git_oid__empty_blob_sha1))
+               file->flags |= GIT_DIFF_FLAG_VALID_SIZE;
+}
+
+static void diff_delta__flag_known_sizes(git_diff_delta *delta)
+{
+       diff_delta__flag_known_size(&delta->old_file);
+       diff_delta__flag_known_size(&delta->new_file);
+}
+
 static int diff_delta__from_one(
        git_diff_generated *diff,
        git_delta_t status,
@@ -182,6 +202,8 @@ static int diff_delta__from_one(
        if (has_old || !git_oid_is_zero(&delta->new_file.id))
                delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
 
+       diff_delta__flag_known_sizes(delta);
+
        return diff_insert_delta(diff, delta, matched_pathspec);
 }
 
@@ -244,6 +266,8 @@ static int diff_delta__from_two(
                        delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
        }
 
+       diff_delta__flag_known_sizes(delta);
+
        return diff_insert_delta(diff, delta, matched_pathspec);
 }
 
@@ -586,7 +610,7 @@ int git_diff__oid_for_entry(
        const git_oid *update_match)
 {
        git_diff_generated *diff;
-       git_buf full_path = GIT_BUF_INIT;
+       git_str full_path = GIT_STR_INIT;
        git_index_entry entry = *src;
        git_filter_list *fl = NULL;
        int error = 0;
@@ -605,8 +629,8 @@ int git_diff__oid_for_entry(
                diff->base.perf.stat_calls++;
 
                if (p_stat(full_path.ptr, &st) < 0) {
-                       error = git_path_set_error(errno, entry.path, "stat");
-                       git_buf_dispose(&full_path);
+                       error = git_fs_path_set_error(errno, entry.path, "stat");
+                       git_str_dispose(&full_path);
                        return error;
                }
 
@@ -669,7 +693,7 @@ int git_diff__oid_for_entry(
                }
        }
 
-       git_buf_dispose(&full_path);
+       git_str_dispose(&full_path);
        return error;
 }
 
@@ -1023,10 +1047,10 @@ static int handle_unmatched_new_item(
 
                /* do not advance into directories that contain a .git file */
                if (recurse_into_dir && !contains_oitem) {
-                       git_buf *full = NULL;
+                       git_str *full = NULL;
                        if (git_iterator_current_workdir_path(&full, info->new_iter) < 0)
                                return -1;
-                       if (full && git_path_contains(full, DOT_GIT)) {
+                       if (full && git_fs_path_contains(full, DOT_GIT)) {
                                /* TODO: warning if not a valid git repository */
                                recurse_into_dir = false;
                        }
index 5186d552c2c74585c87c3d22e9f7083bd8cc73e0..b782f29c6e417d7a79df5e98882c724d5154cdf6 100644 (file)
@@ -18,7 +18,7 @@ enum {
        GIT_DIFFCAPS_IGNORE_STAT      = (1 << 1), /* use stat? */
        GIT_DIFFCAPS_TRUST_MODE_BITS  = (1 << 2), /* use st_mode? */
        GIT_DIFFCAPS_TRUST_CTIME      = (1 << 3), /* use st_ctime? */
-       GIT_DIFFCAPS_USE_DEV          = (1 << 4), /* use st_dev? */
+       GIT_DIFFCAPS_USE_DEV          = (1 << 4)  /* use st_dev? */
 };
 
 #define DIFF_FLAGS_KNOWN_BINARY (GIT_DIFF_FLAG_BINARY|GIT_DIFF_FLAG_NOT_BINARY)
@@ -36,7 +36,7 @@ enum {
        GIT_DIFF_FLAG__TO_SPLIT   = (1 << 17), /* split entry during rename det. */
        GIT_DIFF_FLAG__IS_RENAME_TARGET = (1 << 18),
        GIT_DIFF_FLAG__IS_RENAME_SOURCE = (1 << 19),
-       GIT_DIFF_FLAG__HAS_SELF_SIMILARITY = (1 << 20),
+       GIT_DIFF_FLAG__HAS_SELF_SIMILARITY = (1 << 20)
 };
 
 #define GIT_DIFF_FLAG__CLEAR_INTERNAL(F) (F) = ((F) & 0x00FFFF)
@@ -119,8 +119,10 @@ GIT_INLINE(int) git_diff_file__resolve_zero_size(
 
        git_odb_free(odb);
 
-       if (!error)
+       if (!error) {
                file->size = (git_object_size_t)len;
+               file->flags |= GIT_DIFF_FLAG_VALID_SIZE;
+       }
 
        return error;
 }
index 062e267b00c7cece47de3efed67cf45396422ce4..6c5a2cdc813be6060b007ce417cbe3da5eb7d3d3 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "common.h"
 
+#include "buf.h"
 #include "diff.h"
 #include "diff_file.h"
 #include "patch_generate.h"
@@ -21,7 +22,7 @@ typedef struct {
        git_diff_line_cb print_cb;
        void *payload;
 
-       git_buf *buf;
+       git_str *buf;
        git_diff_line line;
 
        const char *old_prefix;
@@ -34,7 +35,7 @@ typedef struct {
 
 static int diff_print_info_init__common(
        diff_print_info *pi,
-       git_buf *out,
+       git_str *out,
        git_repository *repo,
        git_diff_format_t format,
        git_diff_line_cb cb,
@@ -65,7 +66,7 @@ static int diff_print_info_init__common(
 
 static int diff_print_info_init_fromdiff(
        diff_print_info *pi,
-       git_buf *out,
+       git_str *out,
        git_diff *diff,
        git_diff_format_t format,
        git_diff_line_cb cb,
@@ -89,7 +90,7 @@ static int diff_print_info_init_fromdiff(
 
 static int diff_print_info_init_frompatch(
        diff_print_info *pi,
-       git_buf *out,
+       git_str *out,
        git_patch *patch,
        git_diff_format_t format,
        git_diff_line_cb cb,
@@ -142,7 +143,7 @@ static int diff_print_one_name_only(
        const git_diff_delta *delta, float progress, void *data)
 {
        diff_print_info *pi = data;
-       git_buf *out = pi->buf;
+       git_str *out = pi->buf;
 
        GIT_UNUSED(progress);
 
@@ -150,15 +151,15 @@ static int diff_print_one_name_only(
                delta->status == GIT_DELTA_UNMODIFIED)
                return 0;
 
-       git_buf_clear(out);
-       git_buf_puts(out, delta->new_file.path);
-       git_buf_putc(out, '\n');
-       if (git_buf_oom(out))
+       git_str_clear(out);
+       git_str_puts(out, delta->new_file.path);
+       git_str_putc(out, '\n');
+       if (git_str_oom(out))
                return -1;
 
        pi->line.origin      = GIT_DIFF_LINE_FILE_HDR;
-       pi->line.content     = git_buf_cstr(out);
-       pi->line.content_len = git_buf_len(out);
+       pi->line.content     = git_str_cstr(out);
+       pi->line.content_len = git_str_len(out);
 
        return pi->print_cb(delta, NULL, &pi->line, pi->payload);
 }
@@ -167,7 +168,7 @@ static int diff_print_one_name_status(
        const git_diff_delta *delta, float progress, void *data)
 {
        diff_print_info *pi = data;
-       git_buf *out = pi->buf;
+       git_str *out = pi->buf;
        char old_suffix, new_suffix, code = git_diff_status_char(delta->status);
        int(*strcomp)(const char *, const char *) = pi->strcomp ?
                pi->strcomp : git__strcmp;
@@ -180,26 +181,26 @@ static int diff_print_one_name_status(
        old_suffix = diff_pick_suffix(delta->old_file.mode);
        new_suffix = diff_pick_suffix(delta->new_file.mode);
 
-       git_buf_clear(out);
+       git_str_clear(out);
 
        if (delta->old_file.path != delta->new_file.path &&
                strcomp(delta->old_file.path,delta->new_file.path) != 0)
-               git_buf_printf(out, "%c\t%s%c %s%c\n", code,
+               git_str_printf(out, "%c\t%s%c %s%c\n", code,
                        delta->old_file.path, old_suffix, delta->new_file.path, new_suffix);
        else if (delta->old_file.mode != delta->new_file.mode &&
                delta->old_file.mode != 0 && delta->new_file.mode != 0)
-               git_buf_printf(out, "%c\t%s%c %s%c\n", code,
+               git_str_printf(out, "%c\t%s%c %s%c\n", code,
                        delta->old_file.path, old_suffix, delta->new_file.path, new_suffix);
        else if (old_suffix != ' ')
-               git_buf_printf(out, "%c\t%s%c\n", code, delta->old_file.path, old_suffix);
+               git_str_printf(out, "%c\t%s%c\n", code, delta->old_file.path, old_suffix);
        else
-               git_buf_printf(out, "%c\t%s\n", code, delta->old_file.path);
-       if (git_buf_oom(out))
+               git_str_printf(out, "%c\t%s\n", code, delta->old_file.path);
+       if (git_str_oom(out))
                return -1;
 
        pi->line.origin      = GIT_DIFF_LINE_FILE_HDR;
-       pi->line.content     = git_buf_cstr(out);
-       pi->line.content_len = git_buf_len(out);
+       pi->line.content     = git_str_cstr(out);
+       pi->line.content_len = git_str_len(out);
 
        return pi->print_cb(delta, NULL, &pi->line, pi->payload);
 }
@@ -208,7 +209,7 @@ static int diff_print_one_raw(
        const git_diff_delta *delta, float progress, void *data)
 {
        diff_print_info *pi = data;
-       git_buf *out = pi->buf;
+       git_str *out = pi->buf;
        int id_abbrev;
        char code = git_diff_status_char(delta->status);
        char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1];
@@ -218,7 +219,7 @@ static int diff_print_one_raw(
        if ((pi->flags & GIT_DIFF_SHOW_UNMODIFIED) == 0 && code == ' ')
                return 0;
 
-       git_buf_clear(out);
+       git_str_clear(out);
 
        id_abbrev = delta->old_file.mode ? delta->old_file.id_abbrev :
                delta->new_file.id_abbrev;
@@ -233,43 +234,43 @@ static int diff_print_one_raw(
        git_oid_tostr(start_oid, pi->id_strlen + 1, &delta->old_file.id);
        git_oid_tostr(end_oid, pi->id_strlen + 1, &delta->new_file.id);
 
-       git_buf_printf(
+       git_str_printf(
                out, (pi->id_strlen <= GIT_OID_HEXSZ) ?
                        ":%06o %06o %s... %s... %c" : ":%06o %06o %s %s %c",
                delta->old_file.mode, delta->new_file.mode, start_oid, end_oid, code);
 
        if (delta->similarity > 0)
-               git_buf_printf(out, "%03u", delta->similarity);
+               git_str_printf(out, "%03u", delta->similarity);
 
        if (delta->old_file.path != delta->new_file.path)
-               git_buf_printf(
+               git_str_printf(
                        out, "\t%s %s\n", delta->old_file.path, delta->new_file.path);
        else
-               git_buf_printf(
+               git_str_printf(
                        out, "\t%s\n", delta->old_file.path ?
                        delta->old_file.path : delta->new_file.path);
 
-       if (git_buf_oom(out))
+       if (git_str_oom(out))
                return -1;
 
        pi->line.origin      = GIT_DIFF_LINE_FILE_HDR;
-       pi->line.content     = git_buf_cstr(out);
-       pi->line.content_len = git_buf_len(out);
+       pi->line.content     = git_str_cstr(out);
+       pi->line.content_len = git_str_len(out);
 
        return pi->print_cb(delta, NULL, &pi->line, pi->payload);
 }
 
 static int diff_print_modes(
-       git_buf *out, const git_diff_delta *delta)
+       git_str *out, const git_diff_delta *delta)
 {
-       git_buf_printf(out, "old mode %o\n", delta->old_file.mode);
-       git_buf_printf(out, "new mode %o\n", delta->new_file.mode);
+       git_str_printf(out, "old mode %o\n", delta->old_file.mode);
+       git_str_printf(out, "new mode %o\n", delta->new_file.mode);
 
-       return git_buf_oom(out) ? -1 : 0;
+       return git_str_oom(out) ? -1 : 0;
 }
 
 static int diff_print_oid_range(
-       git_buf *out, const git_diff_delta *delta, int id_strlen,
+       git_str *out, const git_diff_delta *delta, int id_strlen,
        bool print_index)
 {
        char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1];
@@ -295,34 +296,39 @@ static int diff_print_oid_range(
 
        if (delta->old_file.mode == delta->new_file.mode) {
                if (print_index)
-                       git_buf_printf(out, "index %s..%s %o\n",
+                       git_str_printf(out, "index %s..%s %o\n",
                                start_oid, end_oid, delta->old_file.mode);
        } else {
                if (delta->old_file.mode == 0)
-                       git_buf_printf(out, "new file mode %o\n", delta->new_file.mode);
+                       git_str_printf(out, "new file mode %o\n", delta->new_file.mode);
                else if (delta->new_file.mode == 0)
-                       git_buf_printf(out, "deleted file mode %o\n", delta->old_file.mode);
+                       git_str_printf(out, "deleted file mode %o\n", delta->old_file.mode);
                else
                        diff_print_modes(out, delta);
 
                if (print_index)
-                       git_buf_printf(out, "index %s..%s\n", start_oid, end_oid);
+                       git_str_printf(out, "index %s..%s\n", start_oid, end_oid);
        }
 
-       return git_buf_oom(out) ? -1 : 0;
+       return git_str_oom(out) ? -1 : 0;
 }
 
 static int diff_delta_format_path(
-       git_buf *out, const char *prefix, const char *filename)
+       git_str *out, const char *prefix, const char *filename)
 {
-       if (git_buf_joinpath(out, prefix, filename) < 0)
+       if (!filename) {
+               /* don't prefix "/dev/null" */
+               return git_str_puts(out, "/dev/null");
+       }
+
+       if (git_str_joinpath(out, prefix, filename) < 0)
                return -1;
 
-       return git_buf_quote(out);
+       return git_str_quote(out);
 }
 
 static int diff_delta_format_with_paths(
-       git_buf *out,
+       git_str *out,
        const git_diff_delta *delta,
        const char *template,
        const char *oldpath,
@@ -334,14 +340,14 @@ static int diff_delta_format_with_paths(
        if (git_oid_is_zero(&delta->new_file.id))
                newpath = "/dev/null";
 
-       return git_buf_printf(out, template, oldpath, newpath);
+       return git_str_printf(out, template, oldpath, newpath);
 }
 
 static int diff_delta_format_similarity_header(
-       git_buf *out,
+       git_str *out,
        const git_diff_delta *delta)
 {
-       git_buf old_path = GIT_BUF_INIT, new_path = GIT_BUF_INIT;
+       git_str old_path = GIT_STR_INIT, new_path = GIT_STR_INIT;
        const char *type;
        int error = 0;
 
@@ -357,13 +363,13 @@ static int diff_delta_format_similarity_header(
        else
                type = "copy";
 
-       if ((error = git_buf_puts(&old_path, delta->old_file.path)) < 0 ||
-           (error = git_buf_puts(&new_path, delta->new_file.path)) < 0 ||
-           (error = git_buf_quote(&old_path)) < 0 ||
-           (error = git_buf_quote(&new_path)) < 0)
+       if ((error = git_str_puts(&old_path, delta->old_file.path)) < 0 ||
+           (error = git_str_puts(&new_path, delta->new_file.path)) < 0 ||
+           (error = git_str_quote(&old_path)) < 0 ||
+           (error = git_str_quote(&new_path)) < 0)
                goto done;
 
-       git_buf_printf(out,
+       git_str_printf(out,
                "similarity index %d%%\n"
                "%s from %s\n"
                "%s to %s\n",
@@ -371,12 +377,12 @@ static int diff_delta_format_similarity_header(
                type, old_path.ptr,
                type, new_path.ptr);
 
-       if (git_buf_oom(out))
+       if (git_str_oom(out))
                error = -1;
 
 done:
-       git_buf_dispose(&old_path);
-       git_buf_dispose(&new_path);
+       git_str_dispose(&old_path);
+       git_str_dispose(&new_path);
 
        return error;
 }
@@ -398,14 +404,14 @@ static bool delta_is_unchanged(const git_diff_delta *delta)
 }
 
 int git_diff_delta__format_file_header(
-       git_buf *out,
+       git_str *out,
        const git_diff_delta *delta,
        const char *oldpfx,
        const char *newpfx,
        int id_strlen,
        bool print_index)
 {
-       git_buf old_path = GIT_BUF_INIT, new_path = GIT_BUF_INIT;
+       git_str old_path = GIT_STR_INIT, new_path = GIT_STR_INIT;
        bool unchanged = delta_is_unchanged(delta);
        int error = 0;
 
@@ -422,9 +428,9 @@ int git_diff_delta__format_file_header(
                        &new_path, newpfx, delta->new_file.path)) < 0)
                goto done;
 
-       git_buf_clear(out);
+       git_str_clear(out);
 
-       git_buf_printf(out, "diff --git %s %s\n",
+       git_str_printf(out, "diff --git %s %s\n",
                old_path.ptr, new_path.ptr);
 
        if (unchanged && delta->old_file.mode != delta->new_file.mode)
@@ -446,12 +452,12 @@ int git_diff_delta__format_file_header(
                                "--- %s\n+++ %s\n", old_path.ptr, new_path.ptr);
        }
 
-       if (git_buf_oom(out))
+       if (git_str_oom(out))
                error = -1;
 
 done:
-       git_buf_dispose(&old_path);
-       git_buf_dispose(&new_path);
+       git_str_dispose(&old_path);
+       git_str_dispose(&new_path);
 
        return error;
 }
@@ -467,7 +473,7 @@ static int format_binary(
                "delta" : "literal";
        const char *scan, *end;
 
-       git_buf_printf(pi->buf, "%s %" PRIuZ "\n", typename, inflatedlen);
+       git_str_printf(pi->buf, "%s %" PRIuZ "\n", typename, inflatedlen);
        pi->line.num_lines++;
 
        for (scan = data, end = data + datalen; scan < end; ) {
@@ -476,22 +482,22 @@ static int format_binary(
                        chunk_len = 52;
 
                if (chunk_len <= 26)
-                       git_buf_putc(pi->buf, (char)chunk_len + 'A' - 1);
+                       git_str_putc(pi->buf, (char)chunk_len + 'A' - 1);
                else
-                       git_buf_putc(pi->buf, (char)chunk_len - 26 + 'a' - 1);
+                       git_str_putc(pi->buf, (char)chunk_len - 26 + 'a' - 1);
 
-               git_buf_encode_base85(pi->buf, scan, chunk_len);
-               git_buf_putc(pi->buf, '\n');
+               git_str_encode_base85(pi->buf, scan, chunk_len);
+               git_str_putc(pi->buf, '\n');
 
-               if (git_buf_oom(pi->buf))
+               if (git_str_oom(pi->buf))
                        return -1;
 
                scan += chunk_len;
                pi->line.num_lines++;
        }
-       git_buf_putc(pi->buf, '\n');
+       git_str_putc(pi->buf, '\n');
 
-       if (git_buf_oom(pi->buf))
+       if (git_str_oom(pi->buf))
                return -1;
 
        return 0;
@@ -501,7 +507,7 @@ static int diff_print_patch_file_binary_noshow(
        diff_print_info *pi, git_diff_delta *delta,
        const char *old_pfx, const char *new_pfx)
 {
-       git_buf old_path = GIT_BUF_INIT, new_path = GIT_BUF_INIT;
+       git_str old_path = GIT_STR_INIT, new_path = GIT_STR_INIT;
        int error;
 
        if ((error = diff_delta_format_path(&old_path, old_pfx, delta->old_file.path)) < 0 ||
@@ -513,8 +519,8 @@ static int diff_print_patch_file_binary_noshow(
        pi->line.num_lines = 1;
 
 done:
-       git_buf_dispose(&old_path);
-       git_buf_dispose(&new_path);
+       git_str_dispose(&old_path);
+       git_str_dispose(&new_path);
        return error;
 }
 
@@ -534,7 +540,7 @@ static int diff_print_patch_file_binary(
                        pi, delta, old_pfx, new_pfx);
 
        pre_binary_size = pi->buf->size;
-       git_buf_printf(pi->buf, "GIT binary patch\n");
+       git_str_printf(pi->buf, "GIT binary patch\n");
        pi->line.num_lines++;
 
        if ((error = format_binary(pi, binary->new_file.type, binary->new_file.data,
@@ -543,7 +549,7 @@ static int diff_print_patch_file_binary(
                                   binary->old_file.datalen, binary->old_file.inflatedlen)) < 0) {
                if (error == GIT_EBUFS) {
                        git_error_clear();
-                       git_buf_truncate(pi->buf, pre_binary_size);
+                       git_str_truncate(pi->buf, pre_binary_size);
 
                        return diff_print_patch_file_binary_noshow(
                                pi, delta, old_pfx, new_pfx);
@@ -589,8 +595,8 @@ static int diff_print_patch_file(
                return error;
 
        pi->line.origin      = GIT_DIFF_LINE_FILE_HDR;
-       pi->line.content     = git_buf_cstr(pi->buf);
-       pi->line.content_len = git_buf_len(pi->buf);
+       pi->line.content     = git_str_cstr(pi->buf);
+       pi->line.content_len = git_str_len(pi->buf);
 
        return pi->print_cb(delta, NULL, &pi->line, pi->payload);
 }
@@ -607,15 +613,15 @@ static int diff_print_patch_binary(
                pi->new_prefix ? pi->new_prefix : DIFF_NEW_PREFIX_DEFAULT;
        int error;
 
-       git_buf_clear(pi->buf);
+       git_str_clear(pi->buf);
 
        if ((error = diff_print_patch_file_binary(
                pi, (git_diff_delta *)delta, old_pfx, new_pfx, binary)) < 0)
                return error;
 
        pi->line.origin = GIT_DIFF_LINE_BINARY;
-       pi->line.content = git_buf_cstr(pi->buf);
-       pi->line.content_len = git_buf_len(pi->buf);
+       pi->line.content = git_str_cstr(pi->buf);
+       pi->line.content_len = git_str_len(pi->buf);
 
        return pi->print_cb(delta, NULL, &pi->line, pi->payload);
 }
@@ -659,7 +665,7 @@ int git_diff_print(
        void *payload)
 {
        int error;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        diff_print_info pi;
        git_diff_file_cb print_file = NULL;
        git_diff_binary_cb print_binary = NULL;
@@ -704,7 +710,7 @@ int git_diff_print(
        }
 
 out:
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
@@ -714,7 +720,7 @@ int git_diff_print_callback__to_buf(
        const git_diff_line *line,
        void *payload)
 {
-       git_buf *output = payload;
+       git_str *output = payload;
        GIT_UNUSED(delta); GIT_UNUSED(hunk);
 
        if (!output) {
@@ -725,9 +731,9 @@ int git_diff_print_callback__to_buf(
        if (line->origin == GIT_DIFF_LINE_ADDITION ||
            line->origin == GIT_DIFF_LINE_DELETION ||
            line->origin == GIT_DIFF_LINE_CONTEXT)
-               git_buf_putc(output, line->origin);
+               git_str_putc(output, line->origin);
 
-       return git_buf_put(output, line->content, line->content_len);
+       return git_str_put(output, line->content, line->content_len);
 }
 
 int git_diff_print_callback__to_file_handle(
@@ -761,18 +767,24 @@ int git_diff_print_callback__to_file_handle(
        return 0;
 }
 
-/* print a git_diff to a git_buf */
+/* print a git_diff to a git_str */
 int git_diff_to_buf(git_buf *out, git_diff *diff, git_diff_format_t format)
 {
+       git_str str = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(out);
        GIT_ASSERT_ARG(diff);
 
-       if ((error = git_buf_sanitize(out)) < 0)
-               return error;
+       if ((error = git_buf_tostr(&str, out)) < 0 ||
+           (error = git_diff_print(diff, format, git_diff_print_callback__to_buf, &str)) < 0)
+               goto done;
+
+       error = git_buf_fromstr(out, &str);
 
-       return git_diff_print(diff, format, git_diff_print_callback__to_buf, out);
+done:
+       git_str_dispose(&str);
+       return error;
 }
 
 /* print a git_patch to an output callback */
@@ -781,7 +793,7 @@ int git_patch_print(
        git_diff_line_cb print_cb,
        void *payload)
 {
-       git_buf temp = GIT_BUF_INIT;
+       git_str temp = GIT_STR_INIT;
        diff_print_info pi;
        int error;
 
@@ -799,20 +811,20 @@ int git_patch_print(
        }
 
 out:
-       git_buf_dispose(&temp);
+       git_str_dispose(&temp);
        return error;
 }
 
-/* print a git_patch to a git_buf */
+/* print a git_patch to a git_str */
 int git_patch_to_buf(git_buf *out, git_patch *patch)
 {
-       int error;
+       GIT_BUF_WRAP_PRIVATE(out, git_patch__to_buf, patch);
+}
 
+int git_patch__to_buf(git_str *out, git_patch *patch)
+{
        GIT_ASSERT_ARG(out);
        GIT_ASSERT_ARG(patch);
 
-       if ((error = git_buf_sanitize(out)) < 0)
-               return error;
-
        return git_patch_print(patch, git_diff_print_callback__to_buf, out);
 }
index 41a25bf8acaaf0574a153878a554b7167882d1ac..259939844a50470c90cc5512a2860a161d4b26ed 100644 (file)
@@ -5,8 +5,10 @@
  * a Linking Exception. For full terms see the included COPYING file.
  */
 
-#include "common.h"
+#include "diff_stats.h"
 
+#include "buf.h"
+#include "common.h"
 #include "vector.h"
 #include "diff.h"
 #include "patch_generate.h"
@@ -47,7 +49,7 @@ static int digits_for_value(size_t val)
 }
 
 static int diff_file_stats_full_to_buf(
-       git_buf *out,
+       git_str *out,
        const git_diff_delta *delta,
        const diff_file_stats *filestat,
        const git_diff_stats *stats,
@@ -68,14 +70,14 @@ static int diff_file_stats_full_to_buf(
 
                padding = stats->max_name - strlen(old_path) - strlen(new_path);
 
-               if ((common_dirlen = git_path_common_dirlen(old_path, new_path)) &&
+               if ((common_dirlen = git_fs_path_common_dirlen(old_path, new_path)) &&
                    common_dirlen <= INT_MAX) {
-                       error = git_buf_printf(out, " %.*s{%s"DIFF_RENAME_FILE_SEPARATOR"%s}",
+                       error = git_str_printf(out, " %.*s{%s"DIFF_RENAME_FILE_SEPARATOR"%s}",
                                               (int) common_dirlen, old_path,
                                               old_path + common_dirlen,
                                               new_path + common_dirlen);
                } else {
-                       error = git_buf_printf(out, " %s" DIFF_RENAME_FILE_SEPARATOR "%s",
+                       error = git_str_printf(out, " %s" DIFF_RENAME_FILE_SEPARATOR "%s",
                                               old_path, new_path);
                }
 
@@ -83,7 +85,7 @@ static int diff_file_stats_full_to_buf(
                        goto on_error;
        } else {
                adddel_path = new_path ? new_path : old_path;
-               if (git_buf_printf(out, " %s", adddel_path) < 0)
+               if (git_str_printf(out, " %s", adddel_path) < 0)
                        goto on_error;
 
                padding = stats->max_name - strlen(adddel_path);
@@ -92,28 +94,28 @@ static int diff_file_stats_full_to_buf(
                        padding += strlen(DIFF_RENAME_FILE_SEPARATOR);
        }
 
-       if (git_buf_putcn(out, ' ', padding) < 0 ||
-               git_buf_puts(out, " | ") < 0)
+       if (git_str_putcn(out, ' ', padding) < 0 ||
+               git_str_puts(out, " | ") < 0)
                goto on_error;
 
        if (delta->flags & GIT_DIFF_FLAG_BINARY) {
-               if (git_buf_printf(out,
+               if (git_str_printf(out,
                                "Bin %" PRId64 " -> %" PRId64 " bytes", old_size, new_size) < 0)
                        goto on_error;
        }
        else {
-               if (git_buf_printf(out,
+               if (git_str_printf(out,
                                "%*" PRIuZ, stats->max_digits,
                                filestat->insertions + filestat->deletions) < 0)
                        goto on_error;
 
                if (filestat->insertions || filestat->deletions) {
-                       if (git_buf_putc(out, ' ') < 0)
+                       if (git_str_putc(out, ' ') < 0)
                                goto on_error;
 
                        if (!width) {
-                               if (git_buf_putcn(out, '+', filestat->insertions) < 0 ||
-                                       git_buf_putcn(out, '-', filestat->deletions) < 0)
+                               if (git_str_putcn(out, '+', filestat->insertions) < 0 ||
+                                       git_str_putcn(out, '-', filestat->deletions) < 0)
                                        goto on_error;
                        } else {
                                size_t total = filestat->insertions + filestat->deletions;
@@ -122,21 +124,21 @@ static int diff_file_stats_full_to_buf(
                                size_t plus = full * filestat->insertions / total;
                                size_t minus = full - plus;
 
-                               if (git_buf_putcn(out, '+', max(plus,  1)) < 0 ||
-                                       git_buf_putcn(out, '-', max(minus, 1)) < 0)
+                               if (git_str_putcn(out, '+', max(plus,  1)) < 0 ||
+                                       git_str_putcn(out, '-', max(minus, 1)) < 0)
                                        goto on_error;
                        }
                }
        }
 
-       git_buf_putc(out, '\n');
+       git_str_putc(out, '\n');
 
 on_error:
-       return (git_buf_oom(out) ? -1 : 0);
+       return (git_str_oom(out) ? -1 : 0);
 }
 
 static int diff_file_stats_number_to_buf(
-       git_buf *out,
+       git_str *out,
        const git_diff_delta *delta,
        const diff_file_stats *filestats)
 {
@@ -144,29 +146,29 @@ static int diff_file_stats_number_to_buf(
        const char *path = delta->new_file.path;
 
        if (delta->flags & GIT_DIFF_FLAG_BINARY)
-               error = git_buf_printf(out, "%-8c" "%-8c" "%s\n", '-', '-', path);
+               error = git_str_printf(out, "%-8c" "%-8c" "%s\n", '-', '-', path);
        else
-               error = git_buf_printf(out, "%-8" PRIuZ "%-8" PRIuZ "%s\n",
+               error = git_str_printf(out, "%-8" PRIuZ "%-8" PRIuZ "%s\n",
                        filestats->insertions, filestats->deletions, path);
 
        return error;
 }
 
 static int diff_file_stats_summary_to_buf(
-       git_buf *out,
+       git_str *out,
        const git_diff_delta *delta)
 {
        if (delta->old_file.mode != delta->new_file.mode) {
                if (delta->old_file.mode == 0) {
-                       git_buf_printf(out, " create mode %06o %s\n",
+                       git_str_printf(out, " create mode %06o %s\n",
                                delta->new_file.mode, delta->new_file.path);
                }
                else if (delta->new_file.mode == 0) {
-                       git_buf_printf(out, " delete mode %06o %s\n",
+                       git_str_printf(out, " delete mode %06o %s\n",
                                delta->old_file.mode, delta->old_file.path);
                }
                else {
-                       git_buf_printf(out, " mode change %06o => %06o %s\n",
+                       git_str_printf(out, " mode change %06o => %06o %s\n",
                                delta->old_file.mode, delta->new_file.mode, delta->new_file.path);
                }
        }
@@ -278,6 +280,15 @@ int git_diff_stats_to_buf(
        const git_diff_stats *stats,
        git_diff_stats_format_t format,
        size_t width)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_diff__stats_to_buf, stats, format, width);
+}
+
+int git_diff__stats_to_buf(
+       git_str *out,
+       const git_diff_stats *stats,
+       git_diff_stats_format_t format,
+       size_t width)
 {
        int error = 0;
        size_t i;
@@ -320,23 +331,23 @@ int git_diff_stats_to_buf(
        }
 
        if (format & GIT_DIFF_STATS_FULL || format & GIT_DIFF_STATS_SHORT) {
-               git_buf_printf(
+               git_str_printf(
                        out, " %" PRIuZ " file%s changed",
                        stats->files_changed, stats->files_changed != 1 ? "s" : "");
 
                if (stats->insertions || stats->deletions == 0)
-                       git_buf_printf(
+                       git_str_printf(
                                out, ", %" PRIuZ " insertion%s(+)",
                                stats->insertions, stats->insertions != 1 ? "s" : "");
 
                if (stats->deletions || stats->insertions == 0)
-                       git_buf_printf(
+                       git_str_printf(
                                out, ", %" PRIuZ " deletion%s(-)",
                                stats->deletions, stats->deletions != 1 ? "s" : "");
 
-               git_buf_putc(out, '\n');
+               git_str_putc(out, '\n');
 
-               if (git_buf_oom(out))
+               if (git_str_oom(out))
                        return -1;
        }
 
diff --git a/src/diff_stats.h b/src/diff_stats.h
new file mode 100644 (file)
index 0000000..c71862b
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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_diff_stats_h__
+#define INCLUDE_diff_stats_h__
+
+#include "common.h"
+
+int git_diff__stats_to_buf(
+       git_str *out,
+       const git_diff_stats *stats,
+       git_diff_stats_format_t format,
+       size_t width);
+
+#endif
index 908175d34128ce3aea5778eaab5ea559f9fc78c1..913d649b0fb8750a727eba55e4b4762905a2ede2 100644 (file)
@@ -13,7 +13,7 @@
 
 #include "diff.h"
 #include "diff_generate.h"
-#include "path.h"
+#include "fs_path.h"
 #include "futils.h"
 #include "config.h"
 
@@ -241,7 +241,7 @@ int git_diff_find_similar__calc_similarity(
 
 #define DEFAULT_THRESHOLD 50
 #define DEFAULT_BREAK_REWRITE_THRESHOLD 60
-#define DEFAULT_RENAME_LIMIT 200
+#define DEFAULT_RENAME_LIMIT 1000
 
 static int normalize_find_opts(
        git_diff *diff,
@@ -375,7 +375,7 @@ static int apply_splits_and_deletes(
        size_t i;
        git_diff_delta *delta;
 
-       if (git_vector_init(&onto, expected_size, git_diff_delta__cmp) < 0)
+       if (git_vector_init(&onto, expected_size, diff->deltas._cmp) < 0)
                return -1;
 
        /* build new delta list without TO_DELETE and splitting TO_SPLIT */
@@ -444,7 +444,7 @@ typedef struct {
        git_iterator_t src;
        git_repository *repo;
        git_diff_file *file;
-       git_buf data;
+       git_str data;
        git_odb_object *odb_obj;
        git_blob *blob;
 } similarity_info;
@@ -458,9 +458,10 @@ static int similarity_init(
        info->file = similarity_get_file(diff, file_idx);
        info->odb_obj = NULL;
        info->blob = NULL;
-       git_buf_init(&info->data, 0);
+       git_str_init(&info->data, 0);
 
-       if (info->file->size > 0 || info->src == GIT_ITERATOR_WORKDIR)
+       if ((info->file->flags & GIT_DIFF_FLAG_VALID_SIZE) ||
+           info->src == GIT_ITERATOR_WORKDIR)
                return 0;
 
        return git_diff_file__resolve_zero_size(
@@ -481,7 +482,7 @@ static int similarity_sig(
                        return error;
 
                /* if path is not a regular file, just skip this item */
-               if (!git_path_isfile(info->data.ptr))
+               if (!git_fs_path_isfile(info->data.ptr))
                        return 0;
 
                /* TODO: apply wd-to-odb filters to file data if necessary */
@@ -529,7 +530,7 @@ static void similarity_unload(similarity_info *info)
        if (info->blob)
                git_blob_free(info->blob);
        else
-               git_buf_dispose(&info->data);
+               git_str_dispose(&info->data);
 }
 
 #define FLAG_SET(opts,flag_name) (((opts)->flags & flag_name) != 0)
index 278e2be36e94c63a55875fb442cc5f4aae1a3baa..3f6eccac13d46120c8536b151133e660ea62ffe8 100644 (file)
@@ -218,14 +218,9 @@ static int git_xdiff(git_patch_generated_output *output, git_patch_generated *pa
         * updates are needed to xo->params.flags
         */
 
-       git_patch_generated_old_data(&info.xd_old_data.ptr, &info.xd_old_data.size, patch);
-       git_patch_generated_new_data(&info.xd_new_data.ptr, &info.xd_new_data.size, patch);
-
-       if (info.xd_old_data.size > GIT_XDIFF_MAX_SIZE ||
-               info.xd_new_data.size > GIT_XDIFF_MAX_SIZE) {
-               git_error_set(GIT_ERROR_INVALID, "files too large for diff");
+       if (git_patch_generated_old_data(&info.xd_old_data.ptr, &info.xd_old_data.size, patch) < 0 ||
+           git_patch_generated_new_data(&info.xd_new_data.ptr, &info.xd_new_data.size, patch) < 0)
                return -1;
-       }
 
        xdl_diff(&info.xd_old_data, &info.xd_new_data,
                &xo->params, &xo->config, &xo->callback);
@@ -261,5 +256,5 @@ void git_xdiff_init(git_xdiff_output *xo, const git_diff_options *opts)
        if (flags & GIT_DIFF_IGNORE_BLANK_LINES)
                xo->params.flags |= XDF_IGNORE_BLANK_LINES;
 
-       xo->callback.outf = git_xdiff_cb;
+       xo->callback.out_line = git_xdiff_cb;
 }
index df63b6ec3b645c2d16f0b9e95146b2bed1453240..e19a2928cbb777d02ee13be3d0095b700877db67 100644 (file)
@@ -7,9 +7,12 @@
 
 #include "email.h"
 
-#include "buffer.h"
 #include "common.h"
+#include "buf.h"
 #include "diff_generate.h"
+#include "diff_stats.h"
+#include "patch.h"
+#include "date.h"
 
 #include "git2/email.h"
 #include "git2/patch.h"
@@ -32,7 +35,7 @@ GIT_INLINE(int) include_prefix(
 }
 
 static int append_prefix(
-       git_buf *out,
+       git_str *out,
        size_t patch_idx,
        size_t patch_count,
        git_email_create_options *opts)
@@ -40,16 +43,16 @@ static int append_prefix(
        const char *subject_prefix = opts->subject_prefix ?
                opts->subject_prefix : "PATCH";
 
-       git_buf_putc(out, '[');
+       git_str_putc(out, '[');
 
        if (*subject_prefix)
-               git_buf_puts(out, subject_prefix);
+               git_str_puts(out, subject_prefix);
 
        if (opts->reroll_number) {
                if (*subject_prefix)
-                       git_buf_putc(out, ' ');
+                       git_str_putc(out, ' ');
 
-               git_buf_printf(out, "v%" PRIuZ, opts->reroll_number);
+               git_str_printf(out, "v%" PRIuZ, opts->reroll_number);
        }
 
        if ((opts->flags & GIT_EMAIL_CREATE_ALWAYS_NUMBER) != 0 ||
@@ -58,20 +61,33 @@ static int append_prefix(
                        opts->start_number : 1;
 
                if (*subject_prefix || opts->reroll_number)
-                       git_buf_putc(out, ' ');
+                       git_str_putc(out, ' ');
 
-               git_buf_printf(out, "%" PRIuZ "/%" PRIuZ,
+               git_str_printf(out, "%" PRIuZ "/%" PRIuZ,
                               patch_idx + (start_number - 1),
                               patch_count + (start_number - 1));
        }
 
-       git_buf_puts(out, "]");
+       git_str_puts(out, "]");
 
-       return git_buf_oom(out) ? -1 : 0;
+       return git_str_oom(out) ? -1 : 0;
+}
+
+static int append_date(
+       git_str *out,
+       const git_time *date)
+{
+       int error;
+
+       if ((error = git_str_printf(out, "Date: ")) == 0 &&
+           (error = git_date_rfc2822_fmt(out, date->time, date->offset)) == 0)
+           error = git_str_putc(out, '\n');
+
+       return error;
 }
 
 static int append_subject(
-       git_buf *out,
+       git_str *out,
        size_t patch_idx,
        size_t patch_count,
        const char *summary,
@@ -88,25 +104,25 @@ static int append_subject(
                        summary_len = (nl - summary);
        }
 
-       if ((error = git_buf_puts(out, "Subject: ")) < 0)
+       if ((error = git_str_puts(out, "Subject: ")) < 0)
                return error;
 
        if (prefix &&
            (error = append_prefix(out, patch_idx, patch_count, opts)) < 0)
                return error;
 
-       if (prefix && summary_len && (error = git_buf_putc(out, ' ')) < 0)
+       if (prefix && summary_len && (error = git_str_putc(out, ' ')) < 0)
                return error;
 
        if (summary_len &&
-           (error = git_buf_put(out, summary, summary_len)) < 0)
+           (error = git_str_put(out, summary, summary_len)) < 0)
                return error;
 
-       return git_buf_putc(out, '\n');
+       return git_str_putc(out, '\n');
 }
 
 static int append_header(
-       git_buf *out,
+       git_str *out,
        size_t patch_idx,
        size_t patch_count,
        const git_oid *commit_id,
@@ -115,24 +131,22 @@ static int append_header(
        git_email_create_options *opts)
 {
        char id[GIT_OID_HEXSZ];
-       char date[GIT_DATE_RFC2822_SZ];
        int error;
 
        if ((error = git_oid_fmt(id, commit_id)) < 0 ||
-           (error = git_buf_printf(out, "From %.*s %s\n", GIT_OID_HEXSZ, id, EMAIL_TIMESTAMP)) < 0 ||
-           (error = git_buf_printf(out, "From: %s <%s>\n", author->name, author->email)) < 0 ||
-           (error = git__date_rfc2822_fmt(date, sizeof(date), &author->when)) < 0 ||
-           (error = git_buf_printf(out, "Date: %s\n", date)) < 0 ||
+           (error = git_str_printf(out, "From %.*s %s\n", GIT_OID_HEXSZ, id, EMAIL_TIMESTAMP)) < 0 ||
+           (error = git_str_printf(out, "From: %s <%s>\n", author->name, author->email)) < 0 ||
+           (error = append_date(out, &author->when)) < 0 ||
            (error = append_subject(out, patch_idx, patch_count, summary, opts)) < 0)
                return error;
 
-       if ((error = git_buf_putc(out, '\n')) < 0)
+       if ((error = git_str_putc(out, '\n')) < 0)
                return error;
 
        return 0;
 }
 
-static int append_body(git_buf *out, const char *body)
+static int append_body(git_str *out, const char *body)
 {
        size_t body_len;
        int error;
@@ -142,16 +156,16 @@ static int append_body(git_buf *out, const char *body)
 
        body_len = strlen(body);
 
-       if ((error = git_buf_puts(out, body)) < 0)
+       if ((error = git_str_puts(out, body)) < 0)
                return error;
 
        if (body_len && body[body_len - 1] != '\n')
-               error = git_buf_putc(out, '\n');
+               error = git_str_putc(out, '\n');
 
        return error;
 }
 
-static int append_diffstat(git_buf *out, git_diff *diff)
+static int append_diffstat(git_str *out, git_diff *diff)
 {
        git_diff_stats *stats = NULL;
        unsigned int format_flags;
@@ -160,14 +174,14 @@ static int append_diffstat(git_buf *out, git_diff *diff)
        format_flags = GIT_DIFF_STATS_FULL | GIT_DIFF_STATS_INCLUDE_SUMMARY;
 
        if ((error = git_diff_get_stats(&stats, diff)) == 0 &&
-           (error = git_diff_stats_to_buf(out, stats, format_flags, 0)) == 0)
-               error = git_buf_putc(out, '\n');
+           (error = git_diff__stats_to_buf(out, stats, format_flags, 0)) == 0)
+               error = git_str_putc(out, '\n');
 
        git_diff_stats_free(stats);
        return error;
 }
 
-static int append_patches(git_buf *out, git_diff *diff)
+static int append_patches(git_str *out, git_diff *diff)
 {
        size_t i, deltas;
        int error = 0;
@@ -178,7 +192,7 @@ static int append_patches(git_buf *out, git_diff *diff)
                git_patch *patch = NULL;
 
                if ((error = git_patch_from_diff(&patch, diff, i)) >= 0)
-                       error = git_patch_to_buf(out, patch);
+                       error = git_patch__to_buf(out, patch);
 
                git_patch_free(patch);
 
@@ -190,7 +204,7 @@ static int append_patches(git_buf *out, git_diff *diff)
 }
 
 int git_email__append_from_diff(
-       git_buf *out,
+       git_str *out,
        git_diff *diff,
        size_t patch_idx,
        size_t patch_count,
@@ -216,14 +230,12 @@ int git_email__append_from_diff(
        if (given_opts)
                memcpy(&opts, given_opts, sizeof(git_email_create_options));
 
-       git_buf_sanitize(out);
-
        if ((error = append_header(out, patch_idx, patch_count, commit_id, summary, author, &opts)) == 0 &&
            (error = append_body(out, body)) == 0 &&
-           (error = git_buf_puts(out, "---\n")) == 0 &&
+           (error = git_str_puts(out, "---\n")) == 0 &&
            (error = append_diffstat(out, diff)) == 0 &&
            (error = append_patches(out, diff)) == 0)
-               error = git_buf_puts(out, "--\nlibgit2 " LIBGIT2_VERSION "\n\n");
+               error = git_str_puts(out, "--\nlibgit2 " LIBGIT2_VERSION "\n\n");
 
        return error;
 }
@@ -239,15 +251,19 @@ int git_email_create_from_diff(
        const git_signature *author,
        const git_email_create_options *given_opts)
 {
+       git_str email = GIT_STR_INIT;
        int error;
 
-       git_buf_sanitize(out);
-       git_buf_clear(out);
+       git_buf_tostr(&email, out);
 
-       error = git_email__append_from_diff(out, diff, patch_idx,
+       error = git_email__append_from_diff(&email, diff, patch_idx,
                patch_count, commit_id, summary, body, author,
                given_opts);
 
+       if (error == 0)
+               error = git_buf_fromstr(out, &email);
+
+       git_str_dispose(&email);
        return error;
 }
 
index 7aeb462abc1a23b66006e75f731442f9d3873924..083e56d5c4537e794b5f6ba139b1f570eb23a223 100644 (file)
@@ -12,7 +12,7 @@
 #include "git2/email.h"
 
 extern int git_email__append_from_diff(
-       git_buf *out,
+       git_str *out,
        git_diff *diff,
        size_t patch_idx,
        size_t patch_count,
index ce883b2dad17758ba3936b8c58d5f04f2a12a012..3614b9ce5f5e84fa909922995dc69e8ba355ed25 100644 (file)
@@ -9,7 +9,7 @@
 
 #include "threadstate.h"
 #include "posix.h"
-#include "buffer.h"
+#include "str.h"
 #include "libgit2.h"
 
 /********************************************
@@ -29,7 +29,7 @@ static git_error g_git_uninitialized_error = {
 static void set_error_from_buffer(int error_class)
 {
        git_error *error = &GIT_THREADSTATE->error_t;
-       git_buf *buf = &GIT_THREADSTATE->error_buf;
+       git_str *buf = &GIT_THREADSTATE->error_buf;
 
        error->message = buf->ptr;
        error->klass = error_class;
@@ -39,11 +39,11 @@ static void set_error_from_buffer(int error_class)
 
 static void set_error(int error_class, char *string)
 {
-       git_buf *buf = &GIT_THREADSTATE->error_buf;
+       git_str *buf = &GIT_THREADSTATE->error_buf;
 
-       git_buf_clear(buf);
+       git_str_clear(buf);
        if (string) {
-               git_buf_puts(buf, string);
+               git_str_puts(buf, string);
                git__free(string);
        }
 
@@ -70,20 +70,20 @@ void git_error_vset(int error_class, const char *fmt, va_list ap)
        DWORD win32_error_code = (error_class == GIT_ERROR_OS) ? GetLastError() : 0;
 #endif
        int error_code = (error_class == GIT_ERROR_OS) ? errno : 0;
-       git_buf *buf = &GIT_THREADSTATE->error_buf;
+       git_str *buf = &GIT_THREADSTATE->error_buf;
 
-       git_buf_clear(buf);
+       git_str_clear(buf);
        if (fmt) {
-               git_buf_vprintf(buf, fmt, ap);
+               git_str_vprintf(buf, fmt, ap);
                if (error_class == GIT_ERROR_OS)
-                       git_buf_PUTS(buf, ": ");
+                       git_str_PUTS(buf, ": ");
        }
 
        if (error_class == GIT_ERROR_OS) {
 #ifdef GIT_WIN32
                char * win32_error = git_win32_get_error_message(win32_error_code);
                if (win32_error) {
-                       git_buf_puts(buf, win32_error);
+                       git_str_puts(buf, win32_error);
                        git__free(win32_error);
 
                        SetLastError(0);
@@ -91,26 +91,26 @@ void git_error_vset(int error_class, const char *fmt, va_list ap)
                else
 #endif
                if (error_code)
-                       git_buf_puts(buf, strerror(error_code));
+                       git_str_puts(buf, strerror(error_code));
 
                if (error_code)
                        errno = 0;
        }
 
-       if (!git_buf_oom(buf))
+       if (!git_str_oom(buf))
                set_error_from_buffer(error_class);
 }
 
 int git_error_set_str(int error_class, const char *string)
 {
-       git_buf *buf = &GIT_THREADSTATE->error_buf;
+       git_str *buf = &GIT_THREADSTATE->error_buf;
 
        GIT_ASSERT_ARG(string);
 
-       git_buf_clear(buf);
-       git_buf_puts(buf, string);
+       git_str_clear(buf);
+       git_str_puts(buf, string);
 
-       if (git_buf_oom(buf))
+       if (git_str_oom(buf))
                return -1;
 
        set_error_from_buffer(error_class);
@@ -142,7 +142,7 @@ const git_error *git_error_last(void)
 int git_error_state_capture(git_error_state *state, int error_code)
 {
        git_error *error = GIT_THREADSTATE->last_error;
-       git_buf *error_buf = &GIT_THREADSTATE->error_buf;
+       git_str *error_buf = &GIT_THREADSTATE->error_buf;
 
        memset(state, 0, sizeof(git_error_state));
 
@@ -158,7 +158,7 @@ int git_error_state_capture(git_error_state *state, int error_code)
                if (state->oom)
                        state->error_msg.message = g_git_oom_error.message;
                else
-                       state->error_msg.message = git_buf_detach(error_buf);
+                       state->error_msg.message = git_str_detach(error_buf);
        }
 
        git_error_clear();
index 202cef49ecb3b26983b872b957711ce666948276..f920135da594bce0414e35d9972cbd75712115b2 100644 (file)
@@ -5,7 +5,6 @@
 #cmakedefine GIT_DEBUG_STRICT_ALLOC 1
 #cmakedefine GIT_DEBUG_STRICT_OPEN 1
 
-#cmakedefine GIT_TRACE 1
 #cmakedefine GIT_THREADS 1
 #cmakedefine GIT_WIN32_LEAKCHECK 1
 
 #cmakedefine GIT_REGEX_PCRE2
 #cmakedefine GIT_REGEX_BUILTIN 1
 
+#cmakedefine GIT_QSORT_R_BSD
+#cmakedefine GIT_QSORT_R_GNU
+#cmakedefine GIT_QSORT_S
+
 #cmakedefine GIT_SSH 1
 #cmakedefine GIT_SSH_MEMORY_CREDENTIALS 1
 
@@ -45,4 +48,6 @@
 #cmakedefine GIT_SHA1_OPENSSL 1
 #cmakedefine GIT_SHA1_MBEDTLS 1
 
+#cmakedefine GIT_RAND_GETENTROPY 1
+
 #endif
index dedbb54fa5443e04ded887c61a3d9ab528c4d035..e9f30d9bc5a979c91f842d4fea48ae1831720dec 100644 (file)
@@ -11,6 +11,7 @@
 #include "git2/refs.h"
 #include "git2/revwalk.h"
 #include "git2/transport.h"
+#include "git2/sys/remote.h"
 
 #include "remote.h"
 #include "refspec.h"
@@ -19,7 +20,7 @@
 #include "repository.h"
 #include "refs.h"
 
-static int maybe_want(git_remote *remote, git_remote_head *head, git_odb *odb, git_refspec *tagspec, git_remote_autotag_option_t tagopt)
+static int maybe_want(git_remote *remote, git_remote_head *head, git_refspec *tagspec, git_remote_autotag_option_t tagopt)
 {
        int match = 0, valid;
 
@@ -44,23 +45,60 @@ static int maybe_want(git_remote *remote, git_remote_head *head, git_odb *odb, g
        if (!match)
                return 0;
 
-       /* If we have the object, mark it so we don't ask for it */
-       if (git_odb_exists(odb, &head->oid)) {
-               head->local = 1;
+       return git_vector_insert(&remote->refs, head);
+}
+
+static int mark_local(git_remote *remote)
+{
+       git_remote_head *head;
+       git_odb *odb;
+       size_t i;
+
+       if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
+               return -1;
+
+       git_vector_foreach(&remote->refs, i, head) {
+               /* If we have the object, mark it so we don't ask for it */
+               if (git_odb_exists(odb, &head->oid))
+                       head->local = 1;
+               else
+                       remote->need_pack = 1;
        }
-       else
-               remote->need_pack = 1;
 
-       return git_vector_insert(&remote->refs, head);
+       return 0;
+}
+
+static int maybe_want_oid(git_remote *remote, git_refspec *spec)
+{
+       git_remote_head *oid_head;
+
+       oid_head = git__calloc(1, sizeof(git_remote_head));
+       GIT_ERROR_CHECK_ALLOC(oid_head);
+
+       git_oid_fromstr(&oid_head->oid, spec->src);
+
+       if (spec->dst) {
+               oid_head->name = git__strdup(spec->dst);
+               GIT_ERROR_CHECK_ALLOC(oid_head->name);
+       }
+
+       if (git_vector_insert(&remote->local_heads, oid_head) < 0 ||
+           git_vector_insert(&remote->refs, oid_head) < 0)
+               return -1;
+
+       return 0;
 }
 
 static int filter_wants(git_remote *remote, const git_fetch_options *opts)
 {
        git_remote_head **heads;
-       git_refspec tagspec, head;
+       git_refspec tagspec, head, *spec;
        int error = 0;
        git_odb *odb;
        size_t i, heads_len;
+       unsigned int remote_caps;
+       unsigned int oid_mask = GIT_REMOTE_CAPABILITY_TIP_OID |
+                               GIT_REMOTE_CAPABILITY_REACHABLE_OID;
        git_remote_autotag_option_t tagopt = remote->download_tags;
 
        if (opts && opts->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED)
@@ -87,17 +125,36 @@ static int filter_wants(git_remote *remote, const git_fetch_options *opts)
                        goto cleanup;
        }
 
-       if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
+       if ((error = git_repository_odb__weakptr(&odb, remote->repo)) < 0)
                goto cleanup;
 
-       if (git_remote_ls((const git_remote_head ***)&heads, &heads_len, remote) < 0)
+       if ((error = git_remote_ls((const git_remote_head ***)&heads, &heads_len, remote)) < 0 ||
+           (error = git_remote_capabilities(&remote_caps, remote)) < 0)
                goto cleanup;
 
+       /* Handle remote heads */
        for (i = 0; i < heads_len; i++) {
-               if ((error = maybe_want(remote, heads[i], odb, &tagspec, tagopt)) < 0)
-                       break;
+               if ((error = maybe_want(remote, heads[i], &tagspec, tagopt)) < 0)
+                       goto cleanup;
        }
 
+       /* Handle explicitly specified OID specs */
+       git_vector_foreach(&remote->active_refspecs, i, spec) {
+               if (!git_oid__is_hexstr(spec->src))
+                       continue;
+
+               if (!(remote_caps & oid_mask)) {
+                       git_error_set(GIT_ERROR_INVALID, "cannot fetch a specific object from the remote repository");
+                       error = -1;
+                       goto cleanup;
+               }
+
+               if ((error = maybe_want_oid(remote, spec)) < 0)
+                       goto cleanup;
+       }
+
+       error = mark_local(remote);
+
 cleanup:
        git_refspec__dispose(&tagspec);
 
@@ -115,10 +172,8 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts)
 
        remote->need_pack = 0;
 
-       if (filter_wants(remote, opts) < 0) {
-               git_error_set(GIT_ERROR_NET, "failed to filter the reference list for wants");
+       if (filter_wants(remote, opts) < 0)
                return -1;
-       }
 
        /* Don't try to negotiate when we don't want anything */
        if (!remote->need_pack)
@@ -134,21 +189,14 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts)
                remote->refs.length);
 }
 
-int git_fetch_download_pack(git_remote *remote, const git_remote_callbacks *callbacks)
+int git_fetch_download_pack(git_remote *remote)
 {
        git_transport *t = remote->transport;
-       git_indexer_progress_cb progress = NULL;
-       void *payload = NULL;
 
        if (!remote->need_pack)
                return 0;
 
-       if (callbacks) {
-               progress = callbacks->transfer_progress;
-               payload  = callbacks->payload;
-       }
-
-       return t->download_pack(t, remote->repo, &remote->stats, progress, payload);
+       return t->download_pack(t, remote->repo, &remote->stats);
 }
 
 int git_fetch_options_init(git_fetch_options *opts, unsigned int version)
index 1c75af9c30699cb88e04d2ff6c5c91e076178919..10b6731f0a20aa659d8b0f5c954f8023cb44c8b6 100644 (file)
@@ -15,7 +15,7 @@
 
 int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts);
 
-int git_fetch_download_pack(git_remote *remote, const git_remote_callbacks *callbacks);
+int git_fetch_download_pack(git_remote *remote);
 
 int git_fetch_setup_walk(git_revwalk **out, git_repository *repo);
 
index 88c567e4847828a4261de2e1694bb8a8ce8024ff..6511124efce4ef174561a39094d565c3861a4c42 100644 (file)
@@ -10,7 +10,7 @@
 #include "git2/types.h"
 #include "git2/oid.h"
 
-#include "buffer.h"
+#include "str.h"
 #include "futils.h"
 #include "filebuf.h"
 #include "refs.h"
@@ -44,7 +44,7 @@ static char *sanitized_remote_url(const char *remote_url)
        int error;
 
        if (git_net_url_parse(&url, remote_url) == 0) {
-               git_buf buf = GIT_BUF_INIT;
+               git_str buf = GIT_STR_INIT;
 
                git__free(url.username);
                git__free(url.password);
@@ -53,7 +53,7 @@ static char *sanitized_remote_url(const char *remote_url)
                if ((error = git_net_url_fmt(&buf, &url)) < 0)
                        goto fallback;
 
-               sanitized = git_buf_detach(&buf);
+               sanitized = git_str_detach(&buf);
        }
 
 fallback:
@@ -143,22 +143,22 @@ static int fetchhead_ref_write(
 int git_fetchhead_write(git_repository *repo, git_vector *fetchhead_refs)
 {
        git_filebuf file = GIT_FILEBUF_INIT;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        unsigned int i;
        git_fetchhead_ref *fetchhead_ref;
 
        GIT_ASSERT_ARG(repo);
        GIT_ASSERT_ARG(fetchhead_refs);
 
-       if (git_buf_joinpath(&path, repo->gitdir, GIT_FETCH_HEAD_FILE) < 0)
+       if (git_str_joinpath(&path, repo->gitdir, GIT_FETCH_HEAD_FILE) < 0)
                return -1;
 
        if (git_filebuf_open(&file, path.ptr, GIT_FILEBUF_APPEND, GIT_REFS_FILE_MODE) < 0) {
-               git_buf_dispose(&path);
+               git_str_dispose(&path);
                return -1;
        }
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        git_vector_sort(fetchhead_refs);
 
@@ -171,7 +171,7 @@ int git_fetchhead_write(git_repository *repo, git_vector *fetchhead_refs)
 static int fetchhead_ref_parse(
        git_oid *oid,
        unsigned int *is_merge,
-       git_buf *ref_name,
+       git_str *ref_name,
        const char **remote_url,
        char *line,
        size_t line_num)
@@ -259,12 +259,12 @@ static int fetchhead_ref_parse(
                *remote_url = desc;
        }
 
-       git_buf_clear(ref_name);
+       git_str_clear(ref_name);
 
        if (type)
-               git_buf_join(ref_name, '/', type, name);
+               git_str_join(ref_name, '/', type, name);
        else if(name)
-               git_buf_puts(ref_name, name);
+               git_str_puts(ref_name, name);
 
        return error;
 }
@@ -273,7 +273,7 @@ int git_repository_fetchhead_foreach(git_repository *repo,
        git_repository_fetchhead_foreach_cb cb,
        void *payload)
 {
-       git_buf path = GIT_BUF_INIT, file = GIT_BUF_INIT, name = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT, file = GIT_STR_INIT, name = GIT_STR_INIT;
        const char *ref_name;
        git_oid oid;
        const char *remote_url;
@@ -285,10 +285,10 @@ int git_repository_fetchhead_foreach(git_repository *repo,
        GIT_ASSERT_ARG(repo);
        GIT_ASSERT_ARG(cb);
 
-       if (git_buf_joinpath(&path, repo->gitdir, GIT_FETCH_HEAD_FILE) < 0)
+       if (git_str_joinpath(&path, repo->gitdir, GIT_FETCH_HEAD_FILE) < 0)
                return -1;
 
-       if ((error = git_futils_readbuffer(&file, git_buf_cstr(&path))) < 0)
+       if ((error = git_futils_readbuffer(&file, git_str_cstr(&path))) < 0)
                goto done;
 
        buffer = file.ptr;
@@ -300,8 +300,8 @@ int git_repository_fetchhead_foreach(git_repository *repo,
                                &oid, &is_merge, &name, &remote_url, line, line_num)) < 0)
                        goto done;
 
-               if (git_buf_len(&name) > 0)
-                       ref_name = git_buf_cstr(&name);
+               if (git_str_len(&name) > 0)
+                       ref_name = git_str_cstr(&name);
                else
                        ref_name = NULL;
 
@@ -319,9 +319,9 @@ int git_repository_fetchhead_foreach(git_repository *repo,
        }
 
 done:
-       git_buf_dispose(&file);
-       git_buf_dispose(&path);
-       git_buf_dispose(&name);
+       git_str_dispose(&file);
+       git_str_dispose(&path);
+       git_str_dispose(&name);
 
        return error;
 }
index a3f6b14839aa0bf50dfb466f92c25164598134cf..eafcba3bd6f5d7ae069f9179aaf159b3b2b834a9 100644 (file)
@@ -43,7 +43,7 @@ static int verify_last_error(git_filebuf *file)
 
 static int lock_file(git_filebuf *file, int flags, mode_t mode)
 {
-       if (git_path_exists(file->path_lock) == true) {
+       if (git_fs_path_exists(file->path_lock) == true) {
                git_error_clear(); /* actual OS error code just confuses */
                git_error_set(GIT_ERROR_OS,
                        "failed to lock file '%s' for writing", file->path_lock);
@@ -63,7 +63,7 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
 
        file->fd_is_open = true;
 
-       if ((flags & GIT_FILEBUF_APPEND) && git_path_exists(file->path_original) == true) {
+       if ((flags & GIT_FILEBUF_APPEND) && git_fs_path_exists(file->path_original) == true) {
                git_file source;
                char buffer[FILEIO_BUFSIZE];
                ssize_t read_bytes;
@@ -103,7 +103,7 @@ void git_filebuf_cleanup(git_filebuf *file)
        if (file->fd_is_open && file->fd >= 0)
                p_close(file->fd);
 
-       if (file->created_lock && !file->did_rename && file->path_lock && git_path_exists(file->path_lock))
+       if (file->created_lock && !file->did_rename && file->path_lock && git_fs_path_exists(file->path_lock))
                p_unlink(file->path_lock);
 
        if (file->compute_digest) {
@@ -195,21 +195,21 @@ static int write_deflate(git_filebuf *file, void *source, size_t len)
 
 #define MAX_SYMLINK_DEPTH 5
 
-static int resolve_symlink(git_buf *out, const char *path)
+static int resolve_symlink(git_str *out, const char *path)
 {
        int i, error, root;
        ssize_t ret;
        struct stat st;
-       git_buf curpath = GIT_BUF_INIT, target = GIT_BUF_INIT;
+       git_str curpath = GIT_STR_INIT, target = GIT_STR_INIT;
 
-       if ((error = git_buf_grow(&target, GIT_PATH_MAX + 1)) < 0 ||
-           (error = git_buf_puts(&curpath, path)) < 0)
+       if ((error = git_str_grow(&target, GIT_PATH_MAX + 1)) < 0 ||
+           (error = git_str_puts(&curpath, path)) < 0)
                return error;
 
        for (i = 0; i < MAX_SYMLINK_DEPTH; i++) {
                error = p_lstat(curpath.ptr, &st);
                if (error < 0 && errno == ENOENT) {
-                       error = git_buf_puts(out, curpath.ptr);
+                       error = git_str_puts(out, curpath.ptr);
                        goto cleanup;
                }
 
@@ -220,7 +220,7 @@ static int resolve_symlink(git_buf *out, const char *path)
                }
 
                if (!S_ISLNK(st.st_mode)) {
-                       error = git_buf_puts(out, curpath.ptr);
+                       error = git_str_puts(out, curpath.ptr);
                        goto cleanup;
                }
 
@@ -241,20 +241,20 @@ static int resolve_symlink(git_buf *out, const char *path)
                target.ptr[ret] = '\0';
                target.size = ret;
 
-               root = git_path_root(target.ptr);
+               root = git_fs_path_root(target.ptr);
                if (root >= 0) {
-                       if ((error = git_buf_sets(&curpath, target.ptr)) < 0)
+                       if ((error = git_str_sets(&curpath, target.ptr)) < 0)
                                goto cleanup;
                } else {
-                       git_buf dir = GIT_BUF_INIT;
+                       git_str dir = GIT_STR_INIT;
 
-                       if ((error = git_path_dirname_r(&dir, curpath.ptr)) < 0)
+                       if ((error = git_fs_path_dirname_r(&dir, curpath.ptr)) < 0)
                                goto cleanup;
 
-                       git_buf_swap(&curpath, &dir);
-                       git_buf_dispose(&dir);
+                       git_str_swap(&curpath, &dir);
+                       git_str_dispose(&dir);
 
-                       if ((error = git_path_apply_relative(&curpath, target.ptr)) < 0)
+                       if ((error = git_fs_path_apply_relative(&curpath, target.ptr)) < 0)
                                goto cleanup;
                }
        }
@@ -263,8 +263,8 @@ static int resolve_symlink(git_buf *out, const char *path)
        error = -1;
 
 cleanup:
-       git_buf_dispose(&curpath);
-       git_buf_dispose(&target);
+       git_str_dispose(&curpath);
+       git_str_dispose(&target);
        return error;
 }
 
@@ -305,7 +305,7 @@ int git_filebuf_open_withsize(git_filebuf *file, const char *path, int flags, mo
        if (flags & GIT_FILEBUF_HASH_CONTENTS) {
                file->compute_digest = 1;
 
-               if (git_hash_ctx_init(&file->digest) < 0)
+               if (git_hash_ctx_init(&file->digest, GIT_HASH_ALGORITHM_SHA1) < 0)
                        goto cleanup;
        }
 
@@ -332,13 +332,13 @@ int git_filebuf_open_withsize(git_filebuf *file, const char *path, int flags, mo
 
        /* If we are writing to a temp file */
        if (flags & GIT_FILEBUF_TEMPORARY) {
-               git_buf tmp_path = GIT_BUF_INIT;
+               git_str tmp_path = GIT_STR_INIT;
 
                /* Open the file as temporary for locking */
                file->fd = git_futils_mktmp(&tmp_path, path, mode);
 
                if (file->fd < 0) {
-                       git_buf_dispose(&tmp_path);
+                       git_str_dispose(&tmp_path);
                        goto cleanup;
                }
                file->fd_is_open = true;
@@ -346,17 +346,17 @@ int git_filebuf_open_withsize(git_filebuf *file, const char *path, int flags, mo
 
                /* No original path */
                file->path_original = NULL;
-               file->path_lock = git_buf_detach(&tmp_path);
+               file->path_lock = git_str_detach(&tmp_path);
                GIT_ERROR_CHECK_ALLOC(file->path_lock);
        } else {
-               git_buf resolved_path = GIT_BUF_INIT;
+               git_str resolved_path = GIT_STR_INIT;
 
                if ((error = resolve_symlink(&resolved_path, path)) < 0)
                        goto cleanup;
 
                /* Save the original path of the file */
                path_len = resolved_path.size;
-               file->path_original = git_buf_detach(&resolved_path);
+               file->path_original = git_str_detach(&resolved_path);
 
                /* create the locking path by appending ".lock" to the original */
                GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, path_len, GIT_FILELOCK_EXTLENGTH);
@@ -366,7 +366,7 @@ int git_filebuf_open_withsize(git_filebuf *file, const char *path, int flags, mo
                memcpy(file->path_lock, file->path_original, path_len);
                memcpy(file->path_lock + path_len, GIT_FILELOCK_EXTENSION, GIT_FILELOCK_EXTLENGTH);
 
-               if (git_path_isdir(file->path_original)) {
+               if (git_fs_path_isdir(file->path_original)) {
                        git_error_set(GIT_ERROR_FILESYSTEM, "path '%s' is a directory", file->path_original);
                        error = GIT_EDIRECTORY;
                        goto cleanup;
@@ -386,9 +386,9 @@ cleanup:
        return error;
 }
 
-int git_filebuf_hash(git_oid *oid, git_filebuf *file)
+int git_filebuf_hash(unsigned char *out, git_filebuf *file)
 {
-       GIT_ASSERT_ARG(oid);
+       GIT_ASSERT_ARG(out);
        GIT_ASSERT_ARG(file);
        GIT_ASSERT_ARG(file->compute_digest);
 
@@ -397,7 +397,7 @@ int git_filebuf_hash(git_oid *oid, git_filebuf *file)
        if (verify_last_error(file) < 0)
                return -1;
 
-       git_hash_final(oid, &file->digest);
+       git_hash_final(out, &file->digest);
        git_hash_ctx_cleanup(&file->digest);
        file->compute_digest = 0;
 
index 9d53bc3076fa2f4c84ba119e0d8d5776d3b31727..adbb19936ad7e8c11afdeba148540e852a1ead6e 100644 (file)
@@ -87,7 +87,7 @@ int git_filebuf_open_withsize(git_filebuf *file, const char *path, int flags, mo
 int git_filebuf_commit(git_filebuf *lock);
 int git_filebuf_commit_at(git_filebuf *lock, const char *path);
 void git_filebuf_cleanup(git_filebuf *lock);
-int git_filebuf_hash(git_oid *oid, git_filebuf *file);
+int git_filebuf_hash(unsigned char *out, git_filebuf *file);
 int git_filebuf_flush(git_filebuf *file);
 int git_filebuf_stats(time_t *mtime, size_t *size, git_filebuf *file);
 
index 73497cb3024c2d4fa8301e169fab82dde08a4016..2712e8c604418b3c84656e11a40beb6f8d2ad542 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "filter.h"
 
+#include "buf.h"
 #include "common.h"
 #include "futils.h"
 #include "hash.h"
@@ -17,6 +18,7 @@
 #include "blob.h"
 #include "attr_file.h"
 #include "array.h"
+#include "path.h"
 
 struct git_filter_source {
        git_repository    *repo;
@@ -36,7 +38,7 @@ typedef struct {
 struct git_filter_list {
        git_array_t(git_filter_entry) filters;
        git_filter_source source;
-       git_buf *temp_buf;
+       git_str *temp_buf;
        char path[GIT_FLEX_ARRAY];
 };
 
@@ -68,7 +70,7 @@ static void git_filter_global_shutdown(void);
 
 
 static int filter_def_scan_attrs(
-       git_buf *attrs, size_t *nattr, size_t *nmatch, const char *attr_str)
+       git_str *attrs, size_t *nattr, size_t *nmatch, const char *attr_str)
 {
        const char *start, *scan = attr_str;
        int has_eq;
@@ -92,9 +94,9 @@ static int filter_def_scan_attrs(
                                (*nmatch)++;
 
                        if (has_eq)
-                               git_buf_putc(attrs, '=');
-                       git_buf_put(attrs, start, scan - start);
-                       git_buf_putc(attrs, '\0');
+                               git_str_putc(attrs, '=');
+                       git_str_put(attrs, start, scan - start);
+                       git_str_putc(attrs, '\0');
                }
        }
 
@@ -152,7 +154,7 @@ static int filter_registry_insert(
 {
        git_filter_def *fdef;
        size_t nattr = 0, nmatch = 0, alloc_len;
-       git_buf attrs = GIT_BUF_INIT;
+       git_str attrs = GIT_STR_INIT;
 
        if (filter_def_scan_attrs(&attrs, &nattr, &nmatch, filter->attributes) < 0)
                return -1;
@@ -171,7 +173,7 @@ static int filter_registry_insert(
        fdef->priority    = priority;
        fdef->nattrs      = nattr;
        fdef->nmatches    = nmatch;
-       fdef->attrdata    = git_buf_detach(&attrs);
+       fdef->attrdata    = git_str_detach(&attrs);
 
        filter_def_set_attrs(fdef);
 
@@ -710,7 +712,7 @@ size_t git_filter_list_length(const git_filter_list *fl)
 
 struct buf_stream {
        git_writestream parent;
-       git_buf *target;
+       git_str *target;
        bool complete;
 };
 
@@ -721,7 +723,7 @@ static int buf_stream_write(
        GIT_ASSERT_ARG(buf_stream);
        GIT_ASSERT(buf_stream->complete == 0);
 
-       return git_buf_put(buf_stream->target, buffer, len);
+       return git_str_put(buf_stream->target, buffer, len);
 }
 
 static int buf_stream_close(git_writestream *s)
@@ -740,7 +742,7 @@ static void buf_stream_free(git_writestream *s)
        GIT_UNUSED(s);
 }
 
-static void buf_stream_init(struct buf_stream *writer, git_buf *target)
+static void buf_stream_init(struct buf_stream *writer, git_str *target)
 {
        memset(writer, 0, sizeof(struct buf_stream));
 
@@ -749,7 +751,7 @@ static void buf_stream_init(struct buf_stream *writer, git_buf *target)
        writer->parent.free = buf_stream_free;
        writer->target = target;
 
-       git_buf_clear(target);
+       git_str_clear(target);
 }
 
 int git_filter_list_apply_to_buffer(
@@ -757,13 +759,19 @@ int git_filter_list_apply_to_buffer(
        git_filter_list *filters,
        const char *in,
        size_t in_len)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_filter_list__apply_to_buffer, filters, in, in_len);
+}
+
+int git_filter_list__apply_to_buffer(
+       git_str *out,
+       git_filter_list *filters,
+       const char *in,
+       size_t in_len)
 {
        struct buf_stream writer;
        int error;
 
-       if ((error = git_buf_sanitize(out)) < 0)
-               return error;
-
        buf_stream_init(&writer, out);
 
        if ((error = git_filter_list_stream_buffer(filters,
@@ -775,23 +783,23 @@ int git_filter_list_apply_to_buffer(
 }
 
 int git_filter_list__convert_buf(
-       git_buf *out,
+       git_str *out,
        git_filter_list *filters,
-       git_buf *in)
+       git_str *in)
 {
        int error;
 
        if (!filters || git_filter_list_length(filters) == 0) {
-               git_buf_swap(out, in);
-               git_buf_dispose(in);
+               git_str_swap(out, in);
+               git_str_dispose(in);
                return 0;
        }
 
-       error = git_filter_list_apply_to_buffer(out, filters,
+       error = git_filter_list__apply_to_buffer(out, filters,
                in->ptr, in->size);
 
        if (!error)
-               git_buf_dispose(in);
+               git_str_dispose(in);
 
        return error;
 }
@@ -801,6 +809,15 @@ int git_filter_list_apply_to_file(
        git_filter_list *filters,
        git_repository *repo,
        const char *path)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_filter_list__apply_to_file, filters, repo, path);
+}
+
+int git_filter_list__apply_to_file(
+       git_str *out,
+       git_filter_list *filters,
+       git_repository *repo,
+       const char *path)
 {
        struct buf_stream writer;
        int error;
@@ -815,7 +832,7 @@ int git_filter_list_apply_to_file(
        return error;
 }
 
-static int buf_from_blob(git_buf *out, git_blob *blob)
+static int buf_from_blob(git_str *out, git_blob *blob)
 {
        git_object_size_t rawsize = git_blob_rawsize(blob);
 
@@ -824,7 +841,7 @@ static int buf_from_blob(git_buf *out, git_blob *blob)
                return -1;
        }
 
-       git_buf_attach_notowned(out, git_blob_rawcontent(blob), (size_t)rawsize);
+       git_str_attach_notowned(out, git_blob_rawcontent(blob), (size_t)rawsize);
        return 0;
 }
 
@@ -832,6 +849,14 @@ int git_filter_list_apply_to_blob(
        git_buf *out,
        git_filter_list *filters,
        git_blob *blob)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_filter_list__apply_to_blob, filters, blob);
+}
+
+int git_filter_list__apply_to_blob(
+       git_str *out,
+       git_filter_list *filters,
+       git_blob *blob)
 {
        struct buf_stream writer;
        int error;
@@ -849,12 +874,13 @@ int git_filter_list_apply_to_blob(
 struct buffered_stream {
        git_writestream parent;
        git_filter *filter;
-       int (*write_fn)(git_filter *, void **, git_buf *, const git_buf *, const git_filter_source *);
+       int (*write_fn)(git_filter *, void **, git_str *, const git_str *, const git_filter_source *);
+       int (*legacy_write_fn)(git_filter *, void **, git_buf *, const git_buf *, const git_filter_source *);
        const git_filter_source *source;
        void **payload;
-       git_buf input;
-       git_buf temp_buf;
-       git_buf *output;
+       git_str input;
+       git_str temp_buf;
+       git_str *output;
        git_writestream *target;
 };
 
@@ -864,13 +890,13 @@ static int buffered_stream_write(
        struct buffered_stream *buffered_stream = (struct buffered_stream *)s;
        GIT_ASSERT_ARG(buffered_stream);
 
-       return git_buf_put(&buffered_stream->input, buffer, len);
+       return git_str_put(&buffered_stream->input, buffer, len);
 }
 
 static int buffered_stream_close(git_writestream *s)
 {
        struct buffered_stream *buffered_stream = (struct buffered_stream *)s;
-       git_buf *writebuf;
+       git_str *writebuf;
        git_error_state error_state = {0};
        int error;
 
@@ -886,9 +912,6 @@ static int buffered_stream_close(git_writestream *s)
        if (error == GIT_PASSTHROUGH) {
                writebuf = &buffered_stream->input;
        } else if (error == 0) {
-               if ((error = git_buf_sanitize(buffered_stream->output)) < 0)
-                       return error;
-
                writebuf = buffered_stream->output;
        } else {
                /* close stream before erroring out taking care
@@ -911,8 +934,8 @@ static void buffered_stream_free(git_writestream *s)
        struct buffered_stream *buffered_stream = (struct buffered_stream *)s;
 
        if (buffered_stream) {
-               git_buf_dispose(&buffered_stream->input);
-               git_buf_dispose(&buffered_stream->temp_buf);
+               git_str_dispose(&buffered_stream->input);
+               git_str_dispose(&buffered_stream->temp_buf);
                git__free(buffered_stream);
        }
 }
@@ -920,8 +943,8 @@ static void buffered_stream_free(git_writestream *s)
 int git_filter_buffered_stream_new(
        git_writestream **out,
        git_filter *filter,
-       int (*write_fn)(git_filter *, void **, git_buf *, const git_buf *, const git_filter_source *),
-       git_buf *temp_buf,
+       int (*write_fn)(git_filter *, void **, git_str *, const git_str *, const git_filter_source *),
+       git_str *temp_buf,
        void **payload,
        const git_filter_source *source,
        git_writestream *target)
@@ -940,12 +963,43 @@ int git_filter_buffered_stream_new(
        buffered_stream->target = target;
 
        if (temp_buf)
-               git_buf_clear(temp_buf);
+               git_str_clear(temp_buf);
 
        *out = (git_writestream *)buffered_stream;
        return 0;
 }
 
+#ifndef GIT_DEPRECATE_HARD
+static int buffered_legacy_stream_new(
+       git_writestream **out,
+       git_filter *filter,
+       int (*legacy_write_fn)(git_filter *, void **, git_buf *, const git_buf *, const git_filter_source *),
+       git_str *temp_buf,
+       void **payload,
+       const git_filter_source *source,
+       git_writestream *target)
+{
+       struct buffered_stream *buffered_stream = git__calloc(1, sizeof(struct buffered_stream));
+       GIT_ERROR_CHECK_ALLOC(buffered_stream);
+
+       buffered_stream->parent.write = buffered_stream_write;
+       buffered_stream->parent.close = buffered_stream_close;
+       buffered_stream->parent.free = buffered_stream_free;
+       buffered_stream->filter = filter;
+       buffered_stream->legacy_write_fn = legacy_write_fn;
+       buffered_stream->output = temp_buf ? temp_buf : &buffered_stream->temp_buf;
+       buffered_stream->payload = payload;
+       buffered_stream->source = source;
+       buffered_stream->target = target;
+
+       if (temp_buf)
+               git_str_clear(temp_buf);
+
+       *out = (git_writestream *)buffered_stream;
+       return 0;
+}
+#endif
+
 static int setup_stream(
        git_writestream **out,
        git_filter_entry *fe,
@@ -961,7 +1015,7 @@ static int setup_stream(
         */
        if (!fe->filter->stream) {
                /* Create a stream that proxies the one-shot apply */
-               return git_filter_buffered_stream_new(out,
+               return buffered_legacy_stream_new(out,
                        fe->filter, fe->filter->apply, filters->temp_buf,
                        &fe->payload, &filters->source, last_stream);
        }
@@ -1032,7 +1086,7 @@ int git_filter_list_stream_file(
        git_writestream *target)
 {
        char buf[FILTERIO_BUFSIZE];
-       git_buf abspath = GIT_BUF_INIT;
+       git_str abspath = GIT_STR_INIT;
        const char *base = repo ? git_repository_workdir(repo) : NULL;
        git_vector filter_streams = GIT_VECTOR_INIT;
        git_writestream *stream_start;
@@ -1041,8 +1095,8 @@ int git_filter_list_stream_file(
 
        if ((error = stream_list_init(
                        &stream_start, &filter_streams, filters, target)) < 0 ||
-           (error = git_path_join_unrooted(&abspath, path, base, NULL)) < 0 ||
-           (error = git_path_validate_workdir_buf(repo, &abspath)) < 0)
+           (error = git_fs_path_join_unrooted(&abspath, path, base, NULL)) < 0 ||
+           (error = git_path_validate_str_length(repo, &abspath)) < 0)
                goto done;
 
        initialized = 1;
@@ -1067,7 +1121,7 @@ done:
        if (fd >= 0)
                p_close(fd);
        filter_streams_free(&filter_streams);
-       git_buf_dispose(&abspath);
+       git_str_dispose(&abspath);
        return error;
 }
 
@@ -1101,7 +1155,7 @@ int git_filter_list_stream_blob(
        git_blob *blob,
        git_writestream *target)
 {
-       git_buf in = GIT_BUF_INIT;
+       git_str in = GIT_STR_INIT;
 
        if (buf_from_blob(&in, blob) < 0)
                return -1;
@@ -1125,22 +1179,12 @@ int git_filter_list_stream_data(
        git_buf *data,
        git_writestream *target)
 {
-       int error;
-
-       if ((error = git_buf_sanitize(data)) < 0)
-               return error;
-
        return git_filter_list_stream_buffer(filters, data->ptr, data->size, target);
 }
 
 int git_filter_list_apply_to_data(
        git_buf *tgt, git_filter_list *filters, git_buf *src)
 {
-       int error;
-
-       if ((error = git_buf_sanitize(src)) < 0)
-           return error;
-
        return git_filter_list_apply_to_buffer(tgt, filters, src->ptr, src->size);
 }
 
index 241791276cd1f1dc603514f915744a5471a3d979..58cb4b42407c96ef49270c21ee02cbc421a71407 100644 (file)
@@ -19,7 +19,7 @@
 typedef struct {
        git_filter_options options;
        git_attr_session *attr_session;
-       git_buf *temp_buf;
+       git_str *temp_buf;
 } git_filter_session;
 
 #define GIT_FILTER_SESSION_INIT {GIT_FILTER_OPTIONS_INIT, 0}
@@ -36,14 +36,35 @@ extern int git_filter_list__load(
        git_filter_mode_t mode,
        git_filter_session *filter_session);
 
+int git_filter_list__apply_to_buffer(
+       git_str *out,
+       git_filter_list *filters,
+       const char *in,
+       size_t in_len);
+int git_filter_list__apply_to_file(
+       git_str *out,
+       git_filter_list *filters,
+       git_repository *repo,
+       const char *path);
+int git_filter_list__apply_to_blob(
+       git_str *out,
+       git_filter_list *filters,
+       git_blob *blob);
+
 /*
  * The given input buffer will be converted to the given output buffer.
  * The input buffer will be freed (_if_ it was allocated).
  */
 extern int git_filter_list__convert_buf(
-       git_buf *out,
+       git_str *out,
+       git_filter_list *filters,
+       git_str *in);
+
+extern int git_filter_list__apply_to_file(
+       git_str *out,
        git_filter_list *filters,
-       git_buf *in);
+       git_repository *repo,
+       const char *path);
 
 /*
  * Available filters
@@ -55,8 +76,8 @@ extern git_filter *git_ident_filter_new(void);
 extern int git_filter_buffered_stream_new(
        git_writestream **out,
        git_filter *filter,
-       int (*write_fn)(git_filter *, void **, git_buf *, const git_buf *, const git_filter_source *),
-       git_buf *temp_buf,
+       int (*write_fn)(git_filter *, void **, git_str *, const git_str *, const git_filter_source *),
+       git_str *temp_buf,
        void **payload,
        const git_filter_source *source,
        git_writestream *target);
diff --git a/src/fs_path.c b/src/fs_path.c
new file mode 100644 (file)
index 0000000..a67617e
--- /dev/null
@@ -0,0 +1,2071 @@
+/*
+ * 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 "fs_path.h"
+
+#include "posix.h"
+#include "repository.h"
+#ifdef GIT_WIN32
+#include "win32/posix.h"
+#include "win32/w32_buffer.h"
+#include "win32/w32_util.h"
+#include "win32/version.h"
+#include <aclapi.h>
+#else
+#include <dirent.h>
+#endif
+#include <stdio.h>
+#include <ctype.h>
+
+static int dos_drive_prefix_length(const char *path)
+{
+       int i;
+
+       /*
+        * Does it start with an ASCII letter (i.e. highest bit not set),
+        * followed by a colon?
+        */
+       if (!(0x80 & (unsigned char)*path))
+               return *path && path[1] == ':' ? 2 : 0;
+
+       /*
+        * While drive letters must be letters of the English alphabet, it is
+        * possible to assign virtually _any_ Unicode character via `subst` as
+        * a drive letter to "virtual drives". Even `1`, or `ä`. Or fun stuff
+        * like this:
+        *
+        *      subst ֍: %USERPROFILE%\Desktop
+        */
+       for (i = 1; i < 4 && (0x80 & (unsigned char)path[i]); i++)
+               ; /* skip first UTF-8 character */
+       return path[i] == ':' ? i + 1 : 0;
+}
+
+#ifdef GIT_WIN32
+static bool looks_like_network_computer_name(const char *path, int pos)
+{
+       if (pos < 3)
+               return false;
+
+       if (path[0] != '/' || path[1] != '/')
+               return false;
+
+       while (pos-- > 2) {
+               if (path[pos] == '/')
+                       return false;
+       }
+
+       return true;
+}
+#endif
+
+/*
+ * Based on the Android implementation, BSD licensed.
+ * http://android.git.kernel.org/
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+int git_fs_path_basename_r(git_str *buffer, const char *path)
+{
+       const char *endp, *startp;
+       int len, result;
+
+       /* Empty or NULL string gets treated as "." */
+       if (path == NULL || *path == '\0') {
+               startp = ".";
+               len             = 1;
+               goto Exit;
+       }
+
+       /* Strip trailing slashes */
+       endp = path + strlen(path) - 1;
+       while (endp > path && *endp == '/')
+               endp--;
+
+       /* All slashes becomes "/" */
+       if (endp == path && *endp == '/') {
+               startp = "/";
+               len     = 1;
+               goto Exit;
+       }
+
+       /* Find the start of the base */
+       startp = endp;
+       while (startp > path && *(startp - 1) != '/')
+               startp--;
+
+       /* Cast is safe because max path < max int */
+       len = (int)(endp - startp + 1);
+
+Exit:
+       result = len;
+
+       if (buffer != NULL && git_str_set(buffer, startp, len) < 0)
+               return -1;
+
+       return result;
+}
+
+/*
+ * Determine if the path is a Windows prefix and, if so, returns
+ * its actual length. If it is not a prefix, returns -1.
+ */
+static int win32_prefix_length(const char *path, int len)
+{
+#ifndef GIT_WIN32
+       GIT_UNUSED(path);
+       GIT_UNUSED(len);
+#else
+       /*
+        * Mimic unix behavior where '/.git' returns '/': 'C:/.git'
+        * will return 'C:/' here
+        */
+       if (dos_drive_prefix_length(path) == len)
+               return len;
+
+       /*
+        * Similarly checks if we're dealing with a network computer name
+        * '//computername/.git' will return '//computername/'
+        */
+       if (looks_like_network_computer_name(path, len))
+               return len;
+#endif
+
+       return -1;
+}
+
+/*
+ * Based on the Android implementation, BSD licensed.
+ * Check http://android.git.kernel.org/
+ */
+int git_fs_path_dirname_r(git_str *buffer, const char *path)
+{
+       const char *endp;
+       int is_prefix = 0, len;
+
+       /* Empty or NULL string gets treated as "." */
+       if (path == NULL || *path == '\0') {
+               path = ".";
+               len = 1;
+               goto Exit;
+       }
+
+       /* Strip trailing slashes */
+       endp = path + strlen(path) - 1;
+       while (endp > path && *endp == '/')
+               endp--;
+
+       if (endp - path + 1 > INT_MAX) {
+               git_error_set(GIT_ERROR_INVALID, "path too long");
+               len = -1;
+               goto Exit;
+       }
+
+       if ((len = win32_prefix_length(path, (int)(endp - path + 1))) > 0) {
+               is_prefix = 1;
+               goto Exit;
+       }
+
+       /* Find the start of the dir */
+       while (endp > path && *endp != '/')
+               endp--;
+
+       /* Either the dir is "/" or there are no slashes */
+       if (endp == path) {
+               path = (*endp == '/') ? "/" : ".";
+               len = 1;
+               goto Exit;
+       }
+
+       do {
+               endp--;
+       } while (endp > path && *endp == '/');
+
+       if (endp - path + 1 > INT_MAX) {
+               git_error_set(GIT_ERROR_INVALID, "path too long");
+               len = -1;
+               goto Exit;
+       }
+
+       if ((len = win32_prefix_length(path, (int)(endp - path + 1))) > 0) {
+               is_prefix = 1;
+               goto Exit;
+       }
+
+       /* Cast is safe because max path < max int */
+       len = (int)(endp - path + 1);
+
+Exit:
+       if (buffer) {
+               if (git_str_set(buffer, path, len) < 0)
+                       return -1;
+               if (is_prefix && git_str_putc(buffer, '/') < 0)
+                       return -1;
+       }
+
+       return len;
+}
+
+
+char *git_fs_path_dirname(const char *path)
+{
+       git_str buf = GIT_STR_INIT;
+       char *dirname;
+
+       git_fs_path_dirname_r(&buf, path);
+       dirname = git_str_detach(&buf);
+       git_str_dispose(&buf); /* avoid memleak if error occurs */
+
+       return dirname;
+}
+
+char *git_fs_path_basename(const char *path)
+{
+       git_str buf = GIT_STR_INIT;
+       char *basename;
+
+       git_fs_path_basename_r(&buf, path);
+       basename = git_str_detach(&buf);
+       git_str_dispose(&buf); /* avoid memleak if error occurs */
+
+       return basename;
+}
+
+size_t git_fs_path_basename_offset(git_str *buffer)
+{
+       ssize_t slash;
+
+       if (!buffer || buffer->size <= 0)
+               return 0;
+
+       slash = git_str_rfind_next(buffer, '/');
+
+       if (slash >= 0 && buffer->ptr[slash] == '/')
+               return (size_t)(slash + 1);
+
+       return 0;
+}
+
+int git_fs_path_root(const char *path)
+{
+       int offset = 0, prefix_len;
+
+       /* Does the root of the path look like a windows drive ? */
+       if ((prefix_len = dos_drive_prefix_length(path)))
+               offset += prefix_len;
+
+#ifdef GIT_WIN32
+       /* Are we dealing with a windows network path? */
+       else if ((path[0] == '/' && path[1] == '/' && path[2] != '/') ||
+               (path[0] == '\\' && path[1] == '\\' && path[2] != '\\'))
+       {
+               offset += 2;
+
+               /* Skip the computer name segment */
+               while (path[offset] && path[offset] != '/' && path[offset] != '\\')
+                       offset++;
+       }
+
+       if (path[offset] == '\\')
+               return offset;
+#endif
+
+       if (path[offset] == '/')
+               return offset;
+
+       return -1;      /* Not a real error - signals that path is not rooted */
+}
+
+static void path_trim_slashes(git_str *path)
+{
+       int ceiling = git_fs_path_root(path->ptr) + 1;
+
+       if (ceiling < 0)
+               return;
+
+       while (path->size > (size_t)ceiling) {
+               if (path->ptr[path->size-1] != '/')
+                       break;
+
+               path->ptr[path->size-1] = '\0';
+               path->size--;
+       }
+}
+
+int git_fs_path_join_unrooted(
+       git_str *path_out, const char *path, const char *base, ssize_t *root_at)
+{
+       ssize_t root;
+
+       GIT_ASSERT_ARG(path_out);
+       GIT_ASSERT_ARG(path);
+
+       root = (ssize_t)git_fs_path_root(path);
+
+       if (base != NULL && root < 0) {
+               if (git_str_joinpath(path_out, base, path) < 0)
+                       return -1;
+
+               root = (ssize_t)strlen(base);
+       } else {
+               if (git_str_sets(path_out, path) < 0)
+                       return -1;
+
+               if (root < 0)
+                       root = 0;
+               else if (base)
+                       git_fs_path_equal_or_prefixed(base, path, &root);
+       }
+
+       if (root_at)
+               *root_at = root;
+
+       return 0;
+}
+
+void git_fs_path_squash_slashes(git_str *path)
+{
+       char *p, *q;
+
+       if (path->size == 0)
+               return;
+
+       for (p = path->ptr, q = path->ptr; *q; p++, q++) {
+               *p = *q;
+
+               while (*q == '/' && *(q+1) == '/') {
+                       path->size--;
+                       q++;
+               }
+       }
+
+       *p = '\0';
+}
+
+int git_fs_path_prettify(git_str *path_out, const char *path, const char *base)
+{
+       char buf[GIT_PATH_MAX];
+
+       GIT_ASSERT_ARG(path_out);
+       GIT_ASSERT_ARG(path);
+
+       /* construct path if needed */
+       if (base != NULL && git_fs_path_root(path) < 0) {
+               if (git_str_joinpath(path_out, base, path) < 0)
+                       return -1;
+               path = path_out->ptr;
+       }
+
+       if (p_realpath(path, buf) == NULL) {
+               /* git_error_set resets the errno when dealing with a GIT_ERROR_OS kind of error */
+               int error = (errno == ENOENT || errno == ENOTDIR) ? GIT_ENOTFOUND : -1;
+               git_error_set(GIT_ERROR_OS, "failed to resolve path '%s'", path);
+
+               git_str_clear(path_out);
+
+               return error;
+       }
+
+       return git_str_sets(path_out, buf);
+}
+
+int git_fs_path_prettify_dir(git_str *path_out, const char *path, const char *base)
+{
+       int error = git_fs_path_prettify(path_out, path, base);
+       return (error < 0) ? error : git_fs_path_to_dir(path_out);
+}
+
+int git_fs_path_to_dir(git_str *path)
+{
+       if (path->asize > 0 &&
+               git_str_len(path) > 0 &&
+               path->ptr[git_str_len(path) - 1] != '/')
+               git_str_putc(path, '/');
+
+       return git_str_oom(path) ? -1 : 0;
+}
+
+void git_fs_path_string_to_dir(char *path, size_t size)
+{
+       size_t end = strlen(path);
+
+       if (end && path[end - 1] != '/' && end < size) {
+               path[end] = '/';
+               path[end + 1] = '\0';
+       }
+}
+
+int git__percent_decode(git_str *decoded_out, const char *input)
+{
+       int len, hi, lo, i;
+
+       GIT_ASSERT_ARG(decoded_out);
+       GIT_ASSERT_ARG(input);
+
+       len = (int)strlen(input);
+       git_str_clear(decoded_out);
+
+       for(i = 0; i < len; i++)
+       {
+               char c = input[i];
+
+               if (c != '%')
+                       goto append;
+
+               if (i >= len - 2)
+                       goto append;
+
+               hi = git__fromhex(input[i + 1]);
+               lo = git__fromhex(input[i + 2]);
+
+               if (hi < 0 || lo < 0)
+                       goto append;
+
+               c = (char)(hi << 4 | lo);
+               i += 2;
+
+append:
+               if (git_str_putc(decoded_out, c) < 0)
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int error_invalid_local_file_uri(const char *uri)
+{
+       git_error_set(GIT_ERROR_CONFIG, "'%s' is not a valid local file URI", uri);
+       return -1;
+}
+
+static int local_file_url_prefixlen(const char *file_url)
+{
+       int len = -1;
+
+       if (git__prefixcmp(file_url, "file://") == 0) {
+               if (file_url[7] == '/')
+                       len = 8;
+               else if (git__prefixcmp(file_url + 7, "localhost/") == 0)
+                       len = 17;
+       }
+
+       return len;
+}
+
+bool git_fs_path_is_local_file_url(const char *file_url)
+{
+       return (local_file_url_prefixlen(file_url) > 0);
+}
+
+int git_fs_path_fromurl(git_str *local_path_out, const char *file_url)
+{
+       int offset;
+
+       GIT_ASSERT_ARG(local_path_out);
+       GIT_ASSERT_ARG(file_url);
+
+       if ((offset = local_file_url_prefixlen(file_url)) < 0 ||
+               file_url[offset] == '\0' || file_url[offset] == '/')
+               return error_invalid_local_file_uri(file_url);
+
+#ifndef GIT_WIN32
+       offset--;       /* A *nix absolute path starts with a forward slash */
+#endif
+
+       git_str_clear(local_path_out);
+       return git__percent_decode(local_path_out, file_url + offset);
+}
+
+int git_fs_path_walk_up(
+       git_str *path,
+       const char *ceiling,
+       int (*cb)(void *data, const char *),
+       void *data)
+{
+       int error = 0;
+       git_str iter;
+       ssize_t stop = 0, scan;
+       char oldc = '\0';
+
+       GIT_ASSERT_ARG(path);
+       GIT_ASSERT_ARG(cb);
+
+       if (ceiling != NULL) {
+               if (git__prefixcmp(path->ptr, ceiling) == 0)
+                       stop = (ssize_t)strlen(ceiling);
+               else
+                       stop = git_str_len(path);
+       }
+       scan = git_str_len(path);
+
+       /* empty path: yield only once */
+       if (!scan) {
+               error = cb(data, "");
+               if (error)
+                       git_error_set_after_callback(error);
+               return error;
+       }
+
+       iter.ptr = path->ptr;
+       iter.size = git_str_len(path);
+       iter.asize = path->asize;
+
+       while (scan >= stop) {
+               error = cb(data, iter.ptr);
+               iter.ptr[scan] = oldc;
+
+               if (error) {
+                       git_error_set_after_callback(error);
+                       break;
+               }
+
+               scan = git_str_rfind_next(&iter, '/');
+               if (scan >= 0) {
+                       scan++;
+                       oldc = iter.ptr[scan];
+                       iter.size = scan;
+                       iter.ptr[scan] = '\0';
+               }
+       }
+
+       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)
+                       git_error_set_after_callback(error);
+       }
+
+       return error;
+}
+
+bool git_fs_path_exists(const char *path)
+{
+       GIT_ASSERT_ARG_WITH_RETVAL(path, false);
+       return p_access(path, F_OK) == 0;
+}
+
+bool git_fs_path_isdir(const char *path)
+{
+       struct stat st;
+       if (p_stat(path, &st) < 0)
+               return false;
+
+       return S_ISDIR(st.st_mode) != 0;
+}
+
+bool git_fs_path_isfile(const char *path)
+{
+       struct stat st;
+
+       GIT_ASSERT_ARG_WITH_RETVAL(path, false);
+       if (p_stat(path, &st) < 0)
+               return false;
+
+       return S_ISREG(st.st_mode) != 0;
+}
+
+bool git_fs_path_islink(const char *path)
+{
+       struct stat st;
+
+       GIT_ASSERT_ARG_WITH_RETVAL(path, false);
+       if (p_lstat(path, &st) < 0)
+               return false;
+
+       return S_ISLNK(st.st_mode) != 0;
+}
+
+#ifdef GIT_WIN32
+
+bool git_fs_path_is_empty_dir(const char *path)
+{
+       git_win32_path filter_w;
+       bool empty = false;
+
+       if (git_win32__findfirstfile_filter(filter_w, path)) {
+               WIN32_FIND_DATAW findData;
+               HANDLE hFind = FindFirstFileW(filter_w, &findData);
+
+               /* FindFirstFile will fail if there are no children to the given
+                * path, which can happen if the given path is a file (and obviously
+                * has no children) or if the given path is an empty mount point.
+                * (Most directories have at least directory entries '.' and '..',
+                * but ridiculously another volume mounted in another drive letter's
+                * path space do not, and thus have nothing to enumerate.)  If
+                * FindFirstFile fails, check if this is a directory-like thing
+                * (a mount point).
+                */
+               if (hFind == INVALID_HANDLE_VALUE)
+                       return git_fs_path_isdir(path);
+
+               /* If the find handle was created successfully, then it's a directory */
+               empty = true;
+
+               do {
+                       /* Allow the enumeration to return . and .. and still be considered
+                        * empty. In the special case of drive roots (i.e. C:\) where . and
+                        * .. do not occur, we can still consider the path to be an empty
+                        * directory if there's nothing there. */
+                       if (!git_fs_path_is_dot_or_dotdotW(findData.cFileName)) {
+                               empty = false;
+                               break;
+                       }
+               } while (FindNextFileW(hFind, &findData));
+
+               FindClose(hFind);
+       }
+
+       return empty;
+}
+
+#else
+
+static int path_found_entry(void *payload, git_str *path)
+{
+       GIT_UNUSED(payload);
+       return !git_fs_path_is_dot_or_dotdot(path->ptr);
+}
+
+bool git_fs_path_is_empty_dir(const char *path)
+{
+       int error;
+       git_str dir = GIT_STR_INIT;
+
+       if (!git_fs_path_isdir(path))
+               return false;
+
+       if ((error = git_str_sets(&dir, path)) != 0)
+               git_error_clear();
+       else
+               error = git_fs_path_direach(&dir, 0, path_found_entry, NULL);
+
+       git_str_dispose(&dir);
+
+       return !error;
+}
+
+#endif
+
+int git_fs_path_set_error(int errno_value, const char *path, const char *action)
+{
+       switch (errno_value) {
+       case ENOENT:
+       case ENOTDIR:
+               git_error_set(GIT_ERROR_OS, "could not find '%s' to %s", path, action);
+               return GIT_ENOTFOUND;
+
+       case EINVAL:
+       case ENAMETOOLONG:
+               git_error_set(GIT_ERROR_OS, "invalid path for filesystem '%s'", path);
+               return GIT_EINVALIDSPEC;
+
+       case EEXIST:
+               git_error_set(GIT_ERROR_OS, "failed %s - '%s' already exists", action, path);
+               return GIT_EEXISTS;
+
+       case EACCES:
+               git_error_set(GIT_ERROR_OS, "failed %s - '%s' is locked", action, path);
+               return GIT_ELOCKED;
+
+       default:
+               git_error_set(GIT_ERROR_OS, "could not %s '%s'", action, path);
+               return -1;
+       }
+}
+
+int git_fs_path_lstat(const char *path, struct stat *st)
+{
+       if (p_lstat(path, st) == 0)
+               return 0;
+
+       return git_fs_path_set_error(errno, path, "stat");
+}
+
+static bool _check_dir_contents(
+       git_str *dir,
+       const char *sub,
+       bool (*predicate)(const char *))
+{
+       bool result;
+       size_t dir_size = git_str_len(dir);
+       size_t sub_size = strlen(sub);
+       size_t alloc_size;
+
+       /* leave base valid even if we could not make space for subdir */
+       if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, dir_size, sub_size) ||
+               GIT_ADD_SIZET_OVERFLOW(&alloc_size, alloc_size, 2) ||
+               git_str_try_grow(dir, alloc_size, false) < 0)
+               return false;
+
+       /* save excursion */
+       if (git_str_joinpath(dir, dir->ptr, sub) < 0)
+               return false;
+
+       result = predicate(dir->ptr);
+
+       /* restore path */
+       git_str_truncate(dir, dir_size);
+       return result;
+}
+
+bool git_fs_path_contains(git_str *dir, const char *item)
+{
+       return _check_dir_contents(dir, item, &git_fs_path_exists);
+}
+
+bool git_fs_path_contains_dir(git_str *base, const char *subdir)
+{
+       return _check_dir_contents(base, subdir, &git_fs_path_isdir);
+}
+
+bool git_fs_path_contains_file(git_str *base, const char *file)
+{
+       return _check_dir_contents(base, file, &git_fs_path_isfile);
+}
+
+int git_fs_path_find_dir(git_str *dir)
+{
+       int error = 0;
+       char buf[GIT_PATH_MAX];
+
+       if (p_realpath(dir->ptr, buf) != NULL)
+               error = git_str_sets(dir, buf);
+
+       /* call dirname if this is not a directory */
+       if (!error) /* && git_fs_path_isdir(dir->ptr) == false) */
+               error = (git_fs_path_dirname_r(dir, dir->ptr) < 0) ? -1 : 0;
+
+       if (!error)
+               error = git_fs_path_to_dir(dir);
+
+       return error;
+}
+
+int git_fs_path_resolve_relative(git_str *path, size_t ceiling)
+{
+       char *base, *to, *from, *next;
+       size_t len;
+
+       GIT_ERROR_CHECK_ALLOC_STR(path);
+
+       if (ceiling > path->size)
+               ceiling = path->size;
+
+       /* recognize drive prefixes, etc. that should not be backed over */
+       if (ceiling == 0)
+               ceiling = git_fs_path_root(path->ptr) + 1;
+
+       /* recognize URL prefixes that should not be backed over */
+       if (ceiling == 0) {
+               for (next = path->ptr; *next && git__isalpha(*next); ++next);
+               if (next[0] == ':' && next[1] == '/' && next[2] == '/')
+                       ceiling = (next + 3) - path->ptr;
+       }
+
+       base = to = from = path->ptr + ceiling;
+
+       while (*from) {
+               for (next = from; *next && *next != '/'; ++next);
+
+               len = next - from;
+
+               if (len == 1 && from[0] == '.')
+                       /* do nothing with singleton dot */;
+
+               else if (len == 2 && from[0] == '.' && from[1] == '.') {
+                       /* error out if trying to up one from a hard base */
+                       if (to == base && ceiling != 0) {
+                               git_error_set(GIT_ERROR_INVALID,
+                                       "cannot strip root component off url");
+                               return -1;
+                       }
+
+                       /* no more path segments to strip,
+                        * use '../' as a new base path */
+                       if (to == base) {
+                               if (*next == '/')
+                                       len++;
+
+                               if (to != from)
+                                       memmove(to, from, len);
+
+                               to += len;
+                               /* this is now the base, can't back up from a
+                                * relative prefix */
+                               base = to;
+                       } else {
+                               /* back up a path segment */
+                               while (to > base && to[-1] == '/') to--;
+                               while (to > base && to[-1] != '/') to--;
+                       }
+               } else {
+                       if (*next == '/' && *from != '/')
+                               len++;
+
+                       if (to != from)
+                               memmove(to, from, len);
+
+                       to += len;
+               }
+
+               from += len;
+
+               while (*from == '/') from++;
+       }
+
+       *to = '\0';
+
+       path->size = to - path->ptr;
+
+       return 0;
+}
+
+int git_fs_path_apply_relative(git_str *target, const char *relpath)
+{
+       return git_str_joinpath(target, git_str_cstr(target), relpath) ||
+           git_fs_path_resolve_relative(target, 0);
+}
+
+int git_fs_path_cmp(
+       const char *name1, size_t len1, int isdir1,
+       const char *name2, size_t len2, int isdir2,
+       int (*compare)(const char *, const char *, size_t))
+{
+       unsigned char c1, c2;
+       size_t len = len1 < len2 ? len1 : len2;
+       int cmp;
+
+       cmp = compare(name1, name2, len);
+       if (cmp)
+               return cmp;
+
+       c1 = name1[len];
+       c2 = name2[len];
+
+       if (c1 == '\0' && isdir1)
+               c1 = '/';
+
+       if (c2 == '\0' && isdir2)
+               c2 = '/';
+
+       return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
+}
+
+size_t git_fs_path_common_dirlen(const char *one, const char *two)
+{
+       const char *p, *q, *dirsep = NULL;
+
+       for (p = one, q = two; *p && *q; p++, q++) {
+               if (*p == '/' && *q == '/')
+                       dirsep = p;
+               else if (*p != *q)
+                       break;
+       }
+
+       return dirsep ? (dirsep - one) + 1 : 0;
+}
+
+int git_fs_path_make_relative(git_str *path, const char *parent)
+{
+       const char *p, *q, *p_dirsep, *q_dirsep;
+       size_t plen = path->size, newlen, alloclen, depth = 1, i, offset;
+
+       for (p_dirsep = p = path->ptr, q_dirsep = q = parent; *p && *q; p++, q++) {
+               if (*p == '/' && *q == '/') {
+                       p_dirsep = p;
+                       q_dirsep = q;
+               }
+               else if (*p != *q)
+                       break;
+       }
+
+       /* need at least 1 common path segment */
+       if ((p_dirsep == path->ptr || q_dirsep == parent) &&
+               (*p_dirsep != '/' || *q_dirsep != '/')) {
+               git_error_set(GIT_ERROR_INVALID,
+                       "%s is not a parent of %s", parent, path->ptr);
+               return GIT_ENOTFOUND;
+       }
+
+       if (*p == '/' && !*q)
+               p++;
+       else if (!*p && *q == '/')
+               q++;
+       else if (!*p && !*q)
+               return git_str_clear(path), 0;
+       else {
+               p = p_dirsep + 1;
+               q = q_dirsep + 1;
+       }
+
+       plen -= (p - path->ptr);
+
+       if (!*q)
+               return git_str_set(path, p, plen);
+
+       for (; (q = strchr(q, '/')) && *(q + 1); q++)
+               depth++;
+
+       GIT_ERROR_CHECK_ALLOC_MULTIPLY(&newlen, depth, 3);
+       GIT_ERROR_CHECK_ALLOC_ADD(&newlen, newlen, plen);
+
+       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, newlen, 1);
+
+       /* save the offset as we might realllocate the pointer */
+       offset = p - path->ptr;
+       if (git_str_try_grow(path, alloclen, 1) < 0)
+               return -1;
+       p = path->ptr + offset;
+
+       memmove(path->ptr + (depth * 3), p, plen + 1);
+
+       for (i = 0; i < depth; i++)
+               memcpy(path->ptr + (i * 3), "../", 3);
+
+       path->size = newlen;
+       return 0;
+}
+
+bool git_fs_path_has_non_ascii(const char *path, size_t pathlen)
+{
+       const uint8_t *scan = (const uint8_t *)path, *end;
+
+       for (end = scan + pathlen; scan < end; ++scan)
+               if (*scan & 0x80)
+                       return true;
+
+       return false;
+}
+
+#ifdef GIT_USE_ICONV
+
+int git_fs_path_iconv_init_precompose(git_fs_path_iconv_t *ic)
+{
+       git_str_init(&ic->buf, 0);
+       ic->map = iconv_open(GIT_PATH_REPO_ENCODING, GIT_PATH_NATIVE_ENCODING);
+       return 0;
+}
+
+void git_fs_path_iconv_clear(git_fs_path_iconv_t *ic)
+{
+       if (ic) {
+               if (ic->map != (iconv_t)-1)
+                       iconv_close(ic->map);
+               git_str_dispose(&ic->buf);
+       }
+}
+
+int git_fs_path_iconv(git_fs_path_iconv_t *ic, const char **in, size_t *inlen)
+{
+       char *nfd = (char*)*in, *nfc;
+       size_t nfdlen = *inlen, nfclen, wantlen = nfdlen, alloclen, rv;
+       int retry = 1;
+
+       if (!ic || ic->map == (iconv_t)-1 ||
+               !git_fs_path_has_non_ascii(*in, *inlen))
+               return 0;
+
+       git_str_clear(&ic->buf);
+
+       while (1) {
+               GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, wantlen, 1);
+               if (git_str_grow(&ic->buf, alloclen) < 0)
+                       return -1;
+
+               nfc    = ic->buf.ptr   + ic->buf.size;
+               nfclen = ic->buf.asize - ic->buf.size;
+
+               rv = iconv(ic->map, &nfd, &nfdlen, &nfc, &nfclen);
+
+               ic->buf.size = (nfc - ic->buf.ptr);
+
+               if (rv != (size_t)-1)
+                       break;
+
+               /* if we cannot convert the data (probably because iconv thinks
+                * it is not valid UTF-8 source data), then use original data
+                */
+               if (errno != E2BIG)
+                       return 0;
+
+               /* make space for 2x the remaining data to be converted
+                * (with per retry overhead to avoid infinite loops)
+                */
+               wantlen = ic->buf.size + max(nfclen, nfdlen) * 2 + (size_t)(retry * 4);
+
+               if (retry++ > 4)
+                       goto fail;
+       }
+
+       ic->buf.ptr[ic->buf.size] = '\0';
+
+       *in    = ic->buf.ptr;
+       *inlen = ic->buf.size;
+
+       return 0;
+
+fail:
+       git_error_set(GIT_ERROR_OS, "unable to convert unicode path data");
+       return -1;
+}
+
+static const char *nfc_file = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D";
+static const char *nfd_file = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D";
+
+/* Check if the platform is decomposing unicode data for us.  We will
+ * emulate core Git and prefer to use precomposed unicode data internally
+ * on these platforms, composing the decomposed unicode on the fly.
+ *
+ * This mainly happens on the Mac where HDFS stores filenames as
+ * decomposed unicode.  Even on VFAT and SAMBA file systems, the Mac will
+ * return decomposed unicode from readdir() even when the actual
+ * filesystem is storing precomposed unicode.
+ */
+bool git_fs_path_does_decompose_unicode(const char *root)
+{
+       git_str nfc_path = GIT_STR_INIT;
+       git_str nfd_path = GIT_STR_INIT;
+       int fd;
+       bool found_decomposed = false;
+       size_t orig_len;
+       const char *trailer;
+
+       /* Create a file using a precomposed path and then try to find it
+        * using the decomposed name.  If the lookup fails, then we will mark
+        * that we should precompose unicode for this repository.
+        */
+       if (git_str_joinpath(&nfc_path, root, nfc_file) < 0)
+               goto done;
+
+       /* record original path length before trailer */
+       orig_len = nfc_path.size;
+
+       if ((fd = git_futils_mktmp(&nfc_path, nfc_path.ptr, 0666)) < 0)
+               goto done;
+       p_close(fd);
+
+       trailer = nfc_path.ptr + orig_len;
+
+       /* try to look up as NFD path */
+       if (git_str_joinpath(&nfd_path, root, nfd_file) < 0 ||
+           git_str_puts(&nfd_path, trailer) < 0)
+               goto done;
+
+       found_decomposed = git_fs_path_exists(nfd_path.ptr);
+
+       /* remove temporary file (using original precomposed path) */
+       (void)p_unlink(nfc_path.ptr);
+
+done:
+       git_str_dispose(&nfc_path);
+       git_str_dispose(&nfd_path);
+       return found_decomposed;
+}
+
+#else
+
+bool git_fs_path_does_decompose_unicode(const char *root)
+{
+       GIT_UNUSED(root);
+       return false;
+}
+
+#endif
+
+#if defined(__sun) || defined(__GNU__)
+typedef char path_dirent_data[sizeof(struct dirent) + FILENAME_MAX + 1];
+#else
+typedef struct dirent path_dirent_data;
+#endif
+
+int git_fs_path_direach(
+       git_str *path,
+       uint32_t flags,
+       int (*fn)(void *, git_str *),
+       void *arg)
+{
+       int error = 0;
+       ssize_t wd_len;
+       DIR *dir;
+       struct dirent *de;
+
+#ifdef GIT_USE_ICONV
+       git_fs_path_iconv_t ic = GIT_PATH_ICONV_INIT;
+#endif
+
+       GIT_UNUSED(flags);
+
+       if (git_fs_path_to_dir(path) < 0)
+               return -1;
+
+       wd_len = git_str_len(path);
+
+       if ((dir = opendir(path->ptr)) == NULL) {
+               git_error_set(GIT_ERROR_OS, "failed to open directory '%s'", path->ptr);
+               if (errno == ENOENT)
+                       return GIT_ENOTFOUND;
+
+               return -1;
+       }
+
+#ifdef GIT_USE_ICONV
+       if ((flags & GIT_FS_PATH_DIR_PRECOMPOSE_UNICODE) != 0)
+               (void)git_fs_path_iconv_init_precompose(&ic);
+#endif
+
+       while ((de = readdir(dir)) != NULL) {
+               const char *de_path = de->d_name;
+               size_t de_len = strlen(de_path);
+
+               if (git_fs_path_is_dot_or_dotdot(de_path))
+                       continue;
+
+#ifdef GIT_USE_ICONV
+               if ((error = git_fs_path_iconv(&ic, &de_path, &de_len)) < 0)
+                       break;
+#endif
+
+               if ((error = git_str_put(path, de_path, de_len)) < 0)
+                       break;
+
+               git_error_clear();
+               error = fn(arg, path);
+
+               git_str_truncate(path, wd_len); /* restore path */
+
+               /* Only set our own error if the callback did not set one already */
+               if (error != 0) {
+                       if (!git_error_last())
+                               git_error_set_after_callback(error);
+
+                       break;
+               }
+       }
+
+       closedir(dir);
+
+#ifdef GIT_USE_ICONV
+       git_fs_path_iconv_clear(&ic);
+#endif
+
+       return error;
+}
+
+#if defined(GIT_WIN32) && !defined(__MINGW32__)
+
+/* Using _FIND_FIRST_EX_LARGE_FETCH may increase performance in Windows 7
+ * and better.
+ */
+#ifndef FIND_FIRST_EX_LARGE_FETCH
+# define FIND_FIRST_EX_LARGE_FETCH 2
+#endif
+
+int git_fs_path_diriter_init(
+       git_fs_path_diriter *diriter,
+       const char *path,
+       unsigned int flags)
+{
+       git_win32_path path_filter;
+
+       static int is_win7_or_later = -1;
+       if (is_win7_or_later < 0)
+               is_win7_or_later = git_has_win32_version(6, 1, 0);
+
+       GIT_ASSERT_ARG(diriter);
+       GIT_ASSERT_ARG(path);
+
+       memset(diriter, 0, sizeof(git_fs_path_diriter));
+       diriter->handle = INVALID_HANDLE_VALUE;
+
+       if (git_str_puts(&diriter->path_utf8, path) < 0)
+               return -1;
+
+       path_trim_slashes(&diriter->path_utf8);
+
+       if (diriter->path_utf8.size == 0) {
+               git_error_set(GIT_ERROR_FILESYSTEM, "could not open directory '%s'", path);
+               return -1;
+       }
+
+       if ((diriter->parent_len = git_win32_path_from_utf8(diriter->path, diriter->path_utf8.ptr)) < 0 ||
+                       !git_win32__findfirstfile_filter(path_filter, diriter->path_utf8.ptr)) {
+               git_error_set(GIT_ERROR_OS, "could not parse the directory path '%s'", path);
+               return -1;
+       }
+
+       diriter->handle = FindFirstFileExW(
+               path_filter,
+               is_win7_or_later ? FindExInfoBasic : FindExInfoStandard,
+               &diriter->current,
+               FindExSearchNameMatch,
+               NULL,
+               is_win7_or_later ? FIND_FIRST_EX_LARGE_FETCH : 0);
+
+       if (diriter->handle == INVALID_HANDLE_VALUE) {
+               git_error_set(GIT_ERROR_OS, "could not open directory '%s'", path);
+               return -1;
+       }
+
+       diriter->parent_utf8_len = diriter->path_utf8.size;
+       diriter->flags = flags;
+       return 0;
+}
+
+static int diriter_update_paths(git_fs_path_diriter *diriter)
+{
+       size_t filename_len, path_len;
+
+       filename_len = wcslen(diriter->current.cFileName);
+
+       if (GIT_ADD_SIZET_OVERFLOW(&path_len, diriter->parent_len, filename_len) ||
+               GIT_ADD_SIZET_OVERFLOW(&path_len, path_len, 2))
+               return -1;
+
+       if (path_len > GIT_WIN_PATH_UTF16) {
+               git_error_set(GIT_ERROR_FILESYSTEM,
+                       "invalid path '%.*ls\\%ls' (path too long)",
+                       diriter->parent_len, diriter->path, diriter->current.cFileName);
+               return -1;
+       }
+
+       diriter->path[diriter->parent_len] = L'\\';
+       memcpy(&diriter->path[diriter->parent_len+1],
+               diriter->current.cFileName, filename_len * sizeof(wchar_t));
+       diriter->path[path_len-1] = L'\0';
+
+       git_str_truncate(&diriter->path_utf8, diriter->parent_utf8_len);
+
+       if (diriter->parent_utf8_len > 0 &&
+               diriter->path_utf8.ptr[diriter->parent_utf8_len-1] != '/')
+               git_str_putc(&diriter->path_utf8, '/');
+
+       git_str_put_w(&diriter->path_utf8, diriter->current.cFileName, filename_len);
+
+       if (git_str_oom(&diriter->path_utf8))
+               return -1;
+
+       return 0;
+}
+
+int git_fs_path_diriter_next(git_fs_path_diriter *diriter)
+{
+       bool skip_dot = !(diriter->flags & GIT_FS_PATH_DIR_INCLUDE_DOT_AND_DOTDOT);
+
+       do {
+               /* Our first time through, we already have the data from
+                * FindFirstFileW.  Use it, otherwise get the next file.
+                */
+               if (!diriter->needs_next)
+                       diriter->needs_next = 1;
+               else if (!FindNextFileW(diriter->handle, &diriter->current))
+                       return GIT_ITEROVER;
+       } while (skip_dot && git_fs_path_is_dot_or_dotdotW(diriter->current.cFileName));
+
+       if (diriter_update_paths(diriter) < 0)
+               return -1;
+
+       return 0;
+}
+
+int git_fs_path_diriter_filename(
+       const char **out,
+       size_t *out_len,
+       git_fs_path_diriter *diriter)
+{
+       GIT_ASSERT_ARG(out);
+       GIT_ASSERT_ARG(out_len);
+       GIT_ASSERT_ARG(diriter);
+       GIT_ASSERT(diriter->path_utf8.size > diriter->parent_utf8_len);
+
+       *out = &diriter->path_utf8.ptr[diriter->parent_utf8_len+1];
+       *out_len = diriter->path_utf8.size - diriter->parent_utf8_len - 1;
+       return 0;
+}
+
+int git_fs_path_diriter_fullpath(
+       const char **out,
+       size_t *out_len,
+       git_fs_path_diriter *diriter)
+{
+       GIT_ASSERT_ARG(out);
+       GIT_ASSERT_ARG(out_len);
+       GIT_ASSERT_ARG(diriter);
+
+       *out = diriter->path_utf8.ptr;
+       *out_len = diriter->path_utf8.size;
+       return 0;
+}
+
+int git_fs_path_diriter_stat(struct stat *out, git_fs_path_diriter *diriter)
+{
+       GIT_ASSERT_ARG(out);
+       GIT_ASSERT_ARG(diriter);
+
+       return git_win32__file_attribute_to_stat(out,
+               (WIN32_FILE_ATTRIBUTE_DATA *)&diriter->current,
+               diriter->path);
+}
+
+void git_fs_path_diriter_free(git_fs_path_diriter *diriter)
+{
+       if (diriter == NULL)
+               return;
+
+       git_str_dispose(&diriter->path_utf8);
+
+       if (diriter->handle != INVALID_HANDLE_VALUE) {
+               FindClose(diriter->handle);
+               diriter->handle = INVALID_HANDLE_VALUE;
+       }
+}
+
+#else
+
+int git_fs_path_diriter_init(
+       git_fs_path_diriter *diriter,
+       const char *path,
+       unsigned int flags)
+{
+       GIT_ASSERT_ARG(diriter);
+       GIT_ASSERT_ARG(path);
+
+       memset(diriter, 0, sizeof(git_fs_path_diriter));
+
+       if (git_str_puts(&diriter->path, path) < 0)
+               return -1;
+
+       path_trim_slashes(&diriter->path);
+
+       if (diriter->path.size == 0) {
+               git_error_set(GIT_ERROR_FILESYSTEM, "could not open directory '%s'", path);
+               return -1;
+       }
+
+       if ((diriter->dir = opendir(diriter->path.ptr)) == NULL) {
+               git_str_dispose(&diriter->path);
+
+               git_error_set(GIT_ERROR_OS, "failed to open directory '%s'", path);
+               return -1;
+       }
+
+#ifdef GIT_USE_ICONV
+       if ((flags & GIT_FS_PATH_DIR_PRECOMPOSE_UNICODE) != 0)
+               (void)git_fs_path_iconv_init_precompose(&diriter->ic);
+#endif
+
+       diriter->parent_len = diriter->path.size;
+       diriter->flags = flags;
+
+       return 0;
+}
+
+int git_fs_path_diriter_next(git_fs_path_diriter *diriter)
+{
+       struct dirent *de;
+       const char *filename;
+       size_t filename_len;
+       bool skip_dot = !(diriter->flags & GIT_FS_PATH_DIR_INCLUDE_DOT_AND_DOTDOT);
+       int error = 0;
+
+       GIT_ASSERT_ARG(diriter);
+
+       errno = 0;
+
+       do {
+               if ((de = readdir(diriter->dir)) == NULL) {
+                       if (!errno)
+                               return GIT_ITEROVER;
+
+                       git_error_set(GIT_ERROR_OS,
+                               "could not read directory '%s'", diriter->path.ptr);
+                       return -1;
+               }
+       } while (skip_dot && git_fs_path_is_dot_or_dotdot(de->d_name));
+
+       filename = de->d_name;
+       filename_len = strlen(filename);
+
+#ifdef GIT_USE_ICONV
+       if ((diriter->flags & GIT_FS_PATH_DIR_PRECOMPOSE_UNICODE) != 0 &&
+               (error = git_fs_path_iconv(&diriter->ic, &filename, &filename_len)) < 0)
+               return error;
+#endif
+
+       git_str_truncate(&diriter->path, diriter->parent_len);
+
+       if (diriter->parent_len > 0 &&
+               diriter->path.ptr[diriter->parent_len-1] != '/')
+               git_str_putc(&diriter->path, '/');
+
+       git_str_put(&diriter->path, filename, filename_len);
+
+       if (git_str_oom(&diriter->path))
+               return -1;
+
+       return error;
+}
+
+int git_fs_path_diriter_filename(
+       const char **out,
+       size_t *out_len,
+       git_fs_path_diriter *diriter)
+{
+       GIT_ASSERT_ARG(out);
+       GIT_ASSERT_ARG(out_len);
+       GIT_ASSERT_ARG(diriter);
+       GIT_ASSERT(diriter->path.size > diriter->parent_len);
+
+       *out = &diriter->path.ptr[diriter->parent_len+1];
+       *out_len = diriter->path.size - diriter->parent_len - 1;
+       return 0;
+}
+
+int git_fs_path_diriter_fullpath(
+       const char **out,
+       size_t *out_len,
+       git_fs_path_diriter *diriter)
+{
+       GIT_ASSERT_ARG(out);
+       GIT_ASSERT_ARG(out_len);
+       GIT_ASSERT_ARG(diriter);
+
+       *out = diriter->path.ptr;
+       *out_len = diriter->path.size;
+       return 0;
+}
+
+int git_fs_path_diriter_stat(struct stat *out, git_fs_path_diriter *diriter)
+{
+       GIT_ASSERT_ARG(out);
+       GIT_ASSERT_ARG(diriter);
+
+       return git_fs_path_lstat(diriter->path.ptr, out);
+}
+
+void git_fs_path_diriter_free(git_fs_path_diriter *diriter)
+{
+       if (diriter == NULL)
+               return;
+
+       if (diriter->dir) {
+               closedir(diriter->dir);
+               diriter->dir = NULL;
+       }
+
+#ifdef GIT_USE_ICONV
+       git_fs_path_iconv_clear(&diriter->ic);
+#endif
+
+       git_str_dispose(&diriter->path);
+}
+
+#endif
+
+int git_fs_path_dirload(
+       git_vector *contents,
+       const char *path,
+       size_t prefix_len,
+       uint32_t flags)
+{
+       git_fs_path_diriter iter = GIT_FS_PATH_DIRITER_INIT;
+       const char *name;
+       size_t name_len;
+       char *dup;
+       int error;
+
+       GIT_ASSERT_ARG(contents);
+       GIT_ASSERT_ARG(path);
+
+       if ((error = git_fs_path_diriter_init(&iter, path, flags)) < 0)
+               return error;
+
+       while ((error = git_fs_path_diriter_next(&iter)) == 0) {
+               if ((error = git_fs_path_diriter_fullpath(&name, &name_len, &iter)) < 0)
+                       break;
+
+               GIT_ASSERT(name_len > prefix_len);
+
+               dup = git__strndup(name + prefix_len, name_len - prefix_len);
+               GIT_ERROR_CHECK_ALLOC(dup);
+
+               if ((error = git_vector_insert(contents, dup)) < 0)
+                       break;
+       }
+
+       if (error == GIT_ITEROVER)
+               error = 0;
+
+       git_fs_path_diriter_free(&iter);
+       return error;
+}
+
+int git_fs_path_from_url_or_path(git_str *local_path_out, const char *url_or_path)
+{
+       if (git_fs_path_is_local_file_url(url_or_path))
+               return git_fs_path_fromurl(local_path_out, url_or_path);
+       else
+               return git_str_sets(local_path_out, url_or_path);
+}
+
+/* Reject paths like AUX or COM1, or those versions that end in a dot or
+ * colon.  ("AUX." or "AUX:")
+ */
+GIT_INLINE(bool) validate_dospath(
+       const char *component,
+       size_t len,
+       const char dospath[3],
+       bool trailing_num)
+{
+       size_t last = trailing_num ? 4 : 3;
+
+       if (len < last || git__strncasecmp(component, dospath, 3) != 0)
+               return true;
+
+       if (trailing_num && (component[3] < '1' || component[3] > '9'))
+               return true;
+
+       return (len > last &&
+               component[last] != '.' &&
+               component[last] != ':');
+}
+
+GIT_INLINE(bool) validate_char(unsigned char c, unsigned int flags)
+{
+       if ((flags & GIT_FS_PATH_REJECT_BACKSLASH) && c == '\\')
+               return false;
+
+       if ((flags & GIT_FS_PATH_REJECT_SLASH) && c == '/')
+               return false;
+
+       if (flags & GIT_FS_PATH_REJECT_NT_CHARS) {
+               if (c < 32)
+                       return false;
+
+               switch (c) {
+               case '<':
+               case '>':
+               case ':':
+               case '"':
+               case '|':
+               case '?':
+               case '*':
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+/*
+ * We fundamentally don't like some paths when dealing with user-inputted
+ * strings (to avoid escaping a sandbox): we don't want dot or dot-dot
+ * anywhere, we want to avoid writing weird paths on Windows that can't
+ * be handled by tools that use the non-\\?\ APIs, we don't want slashes
+ * or double slashes at the end of paths that can make them ambiguous.
+ *
+ * For checkout, we don't want to recurse into ".git" either.
+ */
+static bool validate_component(
+       const char *component,
+       size_t len,
+       unsigned int flags)
+{
+       if (len == 0)
+               return !(flags & GIT_FS_PATH_REJECT_EMPTY_COMPONENT);
+
+       if ((flags & GIT_FS_PATH_REJECT_TRAVERSAL) &&
+           len == 1 && component[0] == '.')
+               return false;
+
+       if ((flags & GIT_FS_PATH_REJECT_TRAVERSAL) &&
+           len == 2 && component[0] == '.' && component[1] == '.')
+               return false;
+
+       if ((flags & GIT_FS_PATH_REJECT_TRAILING_DOT) &&
+           component[len - 1] == '.')
+               return false;
+
+       if ((flags & GIT_FS_PATH_REJECT_TRAILING_SPACE) &&
+           component[len - 1] == ' ')
+               return false;
+
+       if ((flags & GIT_FS_PATH_REJECT_TRAILING_COLON) &&
+           component[len - 1] == ':')
+               return false;
+
+       if (flags & GIT_FS_PATH_REJECT_DOS_PATHS) {
+               if (!validate_dospath(component, len, "CON", false) ||
+                   !validate_dospath(component, len, "PRN", false) ||
+                   !validate_dospath(component, len, "AUX", false) ||
+                   !validate_dospath(component, len, "NUL", false) ||
+                   !validate_dospath(component, len, "COM", true)  ||
+                   !validate_dospath(component, len, "LPT", true))
+                       return false;
+       }
+
+       return true;
+}
+
+#ifdef GIT_WIN32
+GIT_INLINE(bool) validate_length(
+       const char *path,
+       size_t len,
+       size_t utf8_char_len)
+{
+       GIT_UNUSED(path);
+       GIT_UNUSED(len);
+
+       return (utf8_char_len <= MAX_PATH);
+}
+#endif
+
+bool git_fs_path_str_is_valid_ext(
+       const git_str *path,
+       unsigned int flags,
+       bool (*validate_char_cb)(char ch, void *payload),
+       bool (*validate_component_cb)(const char *component, size_t len, void *payload),
+       bool (*validate_length_cb)(const char *path, size_t len, size_t utf8_char_len),
+       void *payload)
+{
+       const char *start, *c;
+       size_t len = 0;
+
+       if (!flags)
+               return true;
+
+       for (start = c = path->ptr; *c && len < path->size; c++, len++) {
+               if (!validate_char(*c, flags))
+                       return false;
+
+               if (validate_char_cb && !validate_char_cb(*c, payload))
+                       return false;
+
+               if (*c != '/')
+                       continue;
+
+               if (!validate_component(start, (c - start), flags))
+                       return false;
+
+               if (validate_component_cb &&
+                   !validate_component_cb(start, (c - start), payload))
+                       return false;
+
+               start = c + 1;
+       }
+
+       /*
+        * We want to support paths specified as either `const char *`
+        * or `git_str *`; we pass size as `SIZE_MAX` when we use a
+        * `const char *` to avoid a `strlen`.  Ensure that we didn't
+        * have a NUL in the buffer if there was a non-SIZE_MAX length.
+        */
+       if (path->size != SIZE_MAX && len != path->size)
+               return false;
+
+       if (!validate_component(start, (c - start), flags))
+               return false;
+
+       if (validate_component_cb &&
+           !validate_component_cb(start, (c - start), payload))
+               return false;
+
+#ifdef GIT_WIN32
+       if ((flags & GIT_FS_PATH_REJECT_LONG_PATHS) != 0) {
+               size_t utf8_len = git_utf8_char_length(path->ptr, len);
+
+               if (!validate_length(path->ptr, len, utf8_len))
+                       return false;
+
+               if (validate_length_cb &&
+                   !validate_length_cb(path->ptr, len, utf8_len))
+                       return false;
+       }
+#else
+       GIT_UNUSED(validate_length_cb);
+#endif
+
+       return true;
+}
+
+int git_fs_path_validate_str_length_with_suffix(
+       git_str *path,
+       size_t suffix_len)
+{
+#ifdef GIT_WIN32
+       size_t utf8_len = git_utf8_char_length(path->ptr, path->size);
+       size_t total_len;
+
+       if (GIT_ADD_SIZET_OVERFLOW(&total_len, utf8_len, suffix_len) ||
+           total_len > MAX_PATH) {
+
+               git_error_set(GIT_ERROR_FILESYSTEM, "path too long: '%.*s'",
+                       (int)path->size, path->ptr);
+               return -1;
+       }
+#else
+       GIT_UNUSED(path);
+       GIT_UNUSED(suffix_len);
+#endif
+
+       return 0;
+}
+
+int git_fs_path_normalize_slashes(git_str *out, const char *path)
+{
+       int error;
+       char *p;
+
+       if ((error = git_str_puts(out, path)) < 0)
+               return error;
+
+       for (p = out->ptr; *p; p++) {
+               if (*p == '\\')
+                       *p = '/';
+       }
+
+       return 0;
+}
+
+bool git_fs_path_supports_symlinks(const char *dir)
+{
+       git_str path = GIT_STR_INIT;
+       bool supported = false;
+       struct stat st;
+       int fd;
+
+       if ((fd = git_futils_mktmp(&path, dir, 0666)) < 0 ||
+           p_close(fd) < 0 ||
+           p_unlink(path.ptr) < 0 ||
+           p_symlink("testing", path.ptr) < 0 ||
+           p_lstat(path.ptr, &st) < 0)
+               goto done;
+
+       supported = (S_ISLNK(st.st_mode) != 0);
+done:
+       if (path.size)
+               (void)p_unlink(path.ptr);
+       git_str_dispose(&path);
+       return supported;
+}
+
+static git_fs_path__mock_owner_t mock_owner = GIT_FS_PATH_MOCK_OWNER_NONE;
+
+void git_fs_path__set_owner(git_fs_path__mock_owner_t owner)
+{
+       mock_owner = owner;
+}
+
+#ifdef GIT_WIN32
+static PSID *sid_dup(PSID sid)
+{
+       DWORD len;
+       PSID dup;
+
+       len = GetLengthSid(sid);
+
+       if ((dup = git__malloc(len)) == NULL)
+               return NULL;
+
+       if (!CopySid(len, dup, sid)) {
+               git_error_set(GIT_ERROR_OS, "could not duplicate sid");
+               git__free(dup);
+               return NULL;
+       }
+
+       return dup;
+}
+
+static int current_user_sid(PSID *out)
+{
+       TOKEN_USER *info = NULL;
+       HANDLE token = NULL;
+       DWORD len = 0;
+       int error = -1;
+
+       if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
+               git_error_set(GIT_ERROR_OS, "could not lookup process information");
+               goto done;
+       }
+
+       if (GetTokenInformation(token, TokenUser, NULL, 0, &len) ||
+               GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+               git_error_set(GIT_ERROR_OS, "could not lookup token metadata");
+               goto done;
+       }
+
+       info = git__malloc(len);
+       GIT_ERROR_CHECK_ALLOC(info);
+
+       if (!GetTokenInformation(token, TokenUser, info, len, &len)) {
+               git_error_set(GIT_ERROR_OS, "could not lookup current user");
+               goto done;
+       }
+
+       if ((*out = sid_dup(info->User.Sid)))
+               error = 0;
+
+done:
+       if (token)
+               CloseHandle(token);
+
+       git__free(info);
+       return error;
+}
+
+static int file_owner_sid(PSID *out, const char *path)
+{
+       git_win32_path path_w32;
+       PSECURITY_DESCRIPTOR descriptor = NULL;
+       PSID owner_sid;
+       DWORD ret;
+       int error = -1;
+
+       if (git_win32_path_from_utf8(path_w32, path) < 0)
+               return -1;
+
+       ret = GetNamedSecurityInfoW(path_w32, SE_FILE_OBJECT,
+               OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+               &owner_sid, NULL, NULL, NULL, &descriptor);
+
+       if (ret == ERROR_FILE_NOT_FOUND || ret == ERROR_PATH_NOT_FOUND)
+               error = GIT_ENOTFOUND;
+       else if (ret != ERROR_SUCCESS)
+               git_error_set(GIT_ERROR_OS, "failed to get security information");
+       else if (!IsValidSid(owner_sid))
+               git_error_set(GIT_ERROR_OS, "file owner is not valid");
+       else if ((*out = sid_dup(owner_sid)))
+               error = 0;
+
+       if (descriptor)
+               LocalFree(descriptor);
+
+       return error;
+}
+
+int git_fs_path_owner_is_current_user(bool *out, const char *path)
+{
+       PSID owner_sid = NULL, user_sid = NULL;
+       int error = -1;
+
+       if (mock_owner) {
+               *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
+               return 0;
+       }
+
+       if ((error = file_owner_sid(&owner_sid, path)) < 0 ||
+           (error = current_user_sid(&user_sid)) < 0)
+               goto done;
+
+       *out = EqualSid(owner_sid, user_sid);
+       error = 0;
+
+done:
+       git__free(owner_sid);
+       git__free(user_sid);
+       return error;
+}
+
+int git_fs_path_owner_is_system(bool *out, const char *path)
+{
+       PSID owner_sid;
+
+       if (mock_owner) {
+               *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM);
+               return 0;
+       }
+
+       if (file_owner_sid(&owner_sid, path) < 0)
+               return -1;
+
+       *out = IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
+              IsWellKnownSid(owner_sid, WinLocalSystemSid);
+
+       git__free(owner_sid);
+       return 0;
+}
+
+int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path)
+{
+       PSID owner_sid = NULL, user_sid = NULL;
+       int error = -1;
+
+       if (mock_owner) {
+               *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM ||
+                       mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
+               return 0;
+       }
+
+       if (file_owner_sid(&owner_sid, path) < 0)
+               goto done;
+
+       if (IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
+           IsWellKnownSid(owner_sid, WinLocalSystemSid)) {
+               *out = 1;
+               error = 0;
+               goto done;
+       }
+
+       if (current_user_sid(&user_sid) < 0)
+               goto done;
+
+       *out = EqualSid(owner_sid, user_sid);
+       error = 0;
+
+done:
+       git__free(owner_sid);
+       git__free(user_sid);
+       return error;
+}
+
+#else
+
+static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t uids_len)
+{
+       struct stat st;
+       size_t i;
+
+       *out = false;
+
+       if (p_lstat(path, &st) != 0) {
+               if (errno == ENOENT)
+                       return GIT_ENOTFOUND;
+
+               git_error_set(GIT_ERROR_OS, "could not stat '%s'", path);
+               return -1;
+       }
+
+       for (i = 0; i < uids_len; i++) {
+               if (uids[i] == st.st_uid) {
+                       *out = true;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+int git_fs_path_owner_is_current_user(bool *out, const char *path)
+{
+       uid_t userid = geteuid();
+
+       if (mock_owner) {
+               *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
+               return 0;
+       }
+
+       return fs_path_owner_is(out, path, &userid, 1);
+}
+
+int git_fs_path_owner_is_system(bool *out, const char *path)
+{
+       uid_t userid = 0;
+
+       if (mock_owner) {
+               *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM);
+               return 0;
+       }
+
+       return fs_path_owner_is(out, path, &userid, 1);
+}
+
+int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path)
+{
+       uid_t userids[2] = { geteuid(), 0 };
+
+       if (mock_owner) {
+               *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM ||
+                       mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
+               return 0;
+       }
+
+       return fs_path_owner_is(out, path, userids, 2);
+}
+
+#endif
+
+int git_fs_path_find_executable(git_str *fullpath, const char *executable)
+{
+#ifdef GIT_WIN32
+       git_win32_path fullpath_w, executable_w;
+       int error;
+
+       if (git__utf8_to_16(executable_w, GIT_WIN_PATH_MAX, executable) < 0)
+               return -1;
+
+       error = git_win32_path_find_executable(fullpath_w, executable_w);
+
+       if (error == 0)
+               error = git_str_put_w(fullpath, fullpath_w, wcslen(fullpath_w));
+
+       return error;
+#else
+       git_str path = GIT_STR_INIT;
+       const char *current_dir, *term;
+       bool found = false;
+
+       if (git__getenv(&path, "PATH") < 0)
+               return -1;
+
+       current_dir = path.ptr;
+
+       while (*current_dir) {
+               if (! (term = strchr(current_dir, GIT_PATH_LIST_SEPARATOR)))
+                       term = strchr(current_dir, '\0');
+
+               git_str_clear(fullpath);
+               if (git_str_put(fullpath, current_dir, (term - current_dir)) < 0 ||
+                   git_str_putc(fullpath, '/') < 0 ||
+                   git_str_puts(fullpath, executable) < 0)
+                       return -1;
+
+               if (git_fs_path_isfile(fullpath->ptr)) {
+                       found = true;
+                       break;
+               }
+
+               current_dir = term;
+
+               while (*current_dir == GIT_PATH_LIST_SEPARATOR)
+                       current_dir++;
+       }
+
+       git_str_dispose(&path);
+
+       if (found)
+               return 0;
+
+       git_str_clear(fullpath);
+       return GIT_ENOTFOUND;
+#endif
+}
diff --git a/src/fs_path.h b/src/fs_path.h
new file mode 100644 (file)
index 0000000..7e6a22d
--- /dev/null
@@ -0,0 +1,772 @@
+/*
+ * 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_fs_path_h__
+#define INCLUDE_fs_path_h__
+
+#include "common.h"
+
+#include "posix.h"
+#include "str.h"
+#include "vector.h"
+#include "utf8.h"
+
+/**
+ * Path manipulation utils
+ *
+ * These are path utilities that munge paths without actually
+ * looking at the real filesystem.
+ */
+
+/*
+ * The dirname() function shall take a pointer to a character string
+ * that contains a pathname, and return a pointer to a string that is a
+ * pathname of the parent directory of that file. Trailing '/' characters
+ * in the path are not counted as part of the path.
+ *
+ * If path does not contain a '/', then dirname() shall return a pointer to
+ * the string ".". If path is a null pointer or points to an empty string,
+ * dirname() shall return a pointer to the string "." .
+ *
+ * The `git_fs_path_dirname` implementation is thread safe. The returned
+ * string must be manually free'd.
+ *
+ * The `git_fs_path_dirname_r` implementation writes the dirname to a `git_str`
+ * if the buffer pointer is not NULL.
+ * It returns an error code < 0 if there is an allocation error, otherwise
+ * the length of the dirname (which will be > 0).
+ */
+extern char *git_fs_path_dirname(const char *path);
+extern int git_fs_path_dirname_r(git_str *buffer, const char *path);
+
+/*
+ * This function returns the basename of the file, which is the last
+ * part of its full name given by fname, with the drive letter and
+ * leading directories stripped off. For example, the basename of
+ * c:/foo/bar/file.ext is file.ext, and the basename of a:foo is foo.
+ *
+ * Trailing slashes and backslashes are significant: the basename of
+ * c:/foo/bar/ is an empty string after the rightmost slash.
+ *
+ * The `git_fs_path_basename` implementation is thread safe. The returned
+ * string must be manually free'd.
+ *
+ * The `git_fs_path_basename_r` implementation writes the basename to a `git_str`.
+ * It returns an error code < 0 if there is an allocation error, otherwise
+ * the length of the basename (which will be >= 0).
+ */
+extern char *git_fs_path_basename(const char *path);
+extern int git_fs_path_basename_r(git_str *buffer, const char *path);
+
+/* Return the offset of the start of the basename.  Unlike the other
+ * basename functions, this returns 0 if the path is empty.
+ */
+extern size_t git_fs_path_basename_offset(git_str *buffer);
+
+/**
+ * Find offset to root of path if path has one.
+ *
+ * This will return a number >= 0 which is the offset to the start of the
+ * path, if the path is rooted (i.e. "/rooted/path" returns 0 and
+ * "c:/windows/rooted/path" returns 2).  If the path is not rooted, this
+ * returns -1.
+ */
+extern int git_fs_path_root(const char *path);
+
+/**
+ * Ensure path has a trailing '/'.
+ */
+extern int git_fs_path_to_dir(git_str *path);
+
+/**
+ * Ensure string has a trailing '/' if there is space for it.
+ */
+extern void git_fs_path_string_to_dir(char *path, size_t size);
+
+/**
+ * Taken from git.git; returns nonzero if the given path is "." or "..".
+ */
+GIT_INLINE(int) git_fs_path_is_dot_or_dotdot(const char *name)
+{
+       return (name[0] == '.' &&
+                         (name[1] == '\0' ||
+                               (name[1] == '.' && name[2] == '\0')));
+}
+
+#ifdef GIT_WIN32
+GIT_INLINE(int) git_fs_path_is_dot_or_dotdotW(const wchar_t *name)
+{
+       return (name[0] == L'.' &&
+                         (name[1] == L'\0' ||
+                               (name[1] == L'.' && name[2] == L'\0')));
+}
+
+#define git_fs_path_is_absolute(p) \
+       (git__isalpha((p)[0]) && (p)[1] == ':' && ((p)[2] == '\\' || (p)[2] == '/'))
+
+#define git_fs_path_is_dirsep(p) \
+       ((p) == '/' || (p) == '\\')
+
+/**
+ * Convert backslashes in path to forward slashes.
+ */
+GIT_INLINE(void) git_fs_path_mkposix(char *path)
+{
+       while (*path) {
+               if (*path == '\\')
+                       *path = '/';
+
+               path++;
+       }
+}
+#else
+#      define git_fs_path_mkposix(p) /* blank */
+
+#define git_fs_path_is_absolute(p) \
+       ((p)[0] == '/')
+
+#define git_fs_path_is_dirsep(p) \
+       ((p) == '/')
+
+#endif
+
+/**
+ * Check if string is a relative path (i.e. starts with "./" or "../")
+ */
+GIT_INLINE(int) git_fs_path_is_relative(const char *p)
+{
+       return (p[0] == '.' && (p[1] == '/' || (p[1] == '.' && p[2] == '/')));
+}
+
+/**
+ * Check if string is at end of path segment (i.e. looking at '/' or '\0')
+ */
+GIT_INLINE(int) git_fs_path_at_end_of_segment(const char *p)
+{
+       return !*p || *p == '/';
+}
+
+extern int git__percent_decode(git_str *decoded_out, const char *input);
+
+/**
+ * Extract path from file:// URL.
+ */
+extern int git_fs_path_fromurl(git_str *local_path_out, const char *file_url);
+
+
+/**
+ * Path filesystem utils
+ *
+ * These are path utilities that actually access the filesystem.
+ */
+
+/**
+ * Check if a file exists and can be accessed.
+ * @return true or false
+ */
+extern bool git_fs_path_exists(const char *path);
+
+/**
+ * Check if the given path points to a directory.
+ * @return true or false
+ */
+extern bool git_fs_path_isdir(const char *path);
+
+/**
+ * Check if the given path points to a regular file.
+ * @return true or false
+ */
+extern bool git_fs_path_isfile(const char *path);
+
+/**
+ * Check if the given path points to a symbolic link.
+ * @return true or false
+ */
+extern bool git_fs_path_islink(const char *path);
+
+/**
+ * Check if the given path is a directory, and is empty.
+ */
+extern bool git_fs_path_is_empty_dir(const char *path);
+
+/**
+ * Stat a file and/or link and set error if needed.
+ */
+extern int git_fs_path_lstat(const char *path, struct stat *st);
+
+/**
+ * Check if the parent directory contains the item.
+ *
+ * @param dir Directory to check.
+ * @param item Item that might be in the directory.
+ * @return 0 if item exists in directory, <0 otherwise.
+ */
+extern bool git_fs_path_contains(git_str *dir, const char *item);
+
+/**
+ * Check if the given path contains the given subdirectory.
+ *
+ * @param parent Directory path that might contain subdir
+ * @param subdir Subdirectory name to look for in parent
+ * @return true if subdirectory exists, false otherwise.
+ */
+extern bool git_fs_path_contains_dir(git_str *parent, const char *subdir);
+
+/**
+ * Determine the common directory length between two paths, including
+ * the final path separator.  For example, given paths 'a/b/c/1.txt
+ * and 'a/b/c/d/2.txt', the common directory is 'a/b/c/', and this
+ * will return the length of the string 'a/b/c/', which is 6.
+ *
+ * @param one The first path
+ * @param two The second path
+ * @return The length of the common directory
+ */
+extern size_t git_fs_path_common_dirlen(const char *one, const char *two);
+
+/**
+ * Make the path relative to the given parent path.
+ *
+ * @param path The path to make relative
+ * @param parent The parent path to make path relative to
+ * @return 0 if path was made relative, GIT_ENOTFOUND
+ *         if there was not common root between the paths,
+ *         or <0.
+ */
+extern int git_fs_path_make_relative(git_str *path, const char *parent);
+
+/**
+ * Check if the given path contains the given file.
+ *
+ * @param dir Directory path that might contain file
+ * @param file File name to look for in parent
+ * @return true if file exists, false otherwise.
+ */
+extern bool git_fs_path_contains_file(git_str *dir, const char *file);
+
+/**
+ * Prepend base to unrooted path or just copy path over.
+ *
+ * This will optionally return the index into the path where the "root"
+ * is, either the end of the base directory prefix or the path root.
+ */
+extern int git_fs_path_join_unrooted(
+       git_str *path_out, const char *path, const char *base, ssize_t *root_at);
+
+/**
+ * Removes multiple occurrences of '/' in a row, squashing them into a
+ * single '/'.
+ */
+extern void git_fs_path_squash_slashes(git_str *path);
+
+/**
+ * Clean up path, prepending base if it is not already rooted.
+ */
+extern int git_fs_path_prettify(git_str *path_out, const char *path, const char *base);
+
+/**
+ * Clean up path, prepending base if it is not already rooted and
+ * appending a slash.
+ */
+extern int git_fs_path_prettify_dir(git_str *path_out, const char *path, const char *base);
+
+/**
+ * Get a directory from a path.
+ *
+ * If path is a directory, this acts like `git_fs_path_prettify_dir`
+ * (cleaning up path and appending a '/').  If path is a normal file,
+ * this prettifies it, then removed the filename a la dirname and
+ * appends the trailing '/'.  If the path does not exist, it is
+ * treated like a regular filename.
+ */
+extern int git_fs_path_find_dir(git_str *dir);
+
+/**
+ * Resolve relative references within a path.
+ *
+ * This eliminates "./" and "../" relative references inside a path,
+ * as well as condensing multiple slashes into single ones.  It will
+ * not touch the path before the "ceiling" length.
+ *
+ * Additionally, this will recognize an "c:/" drive prefix or a "xyz://" URL
+ * prefix and not touch that part of the path.
+ */
+extern int git_fs_path_resolve_relative(git_str *path, size_t ceiling);
+
+/**
+ * Apply a relative path to base path.
+ *
+ * Note that the base path could be a filename or a URL and this
+ * should still work.  The relative path is walked segment by segment
+ * with three rules: series of slashes will be condensed to a single
+ * slash, "." will be eaten with no change, and ".." will remove a
+ * segment from the base path.
+ */
+extern int git_fs_path_apply_relative(git_str *target, const char *relpath);
+
+enum {
+       GIT_FS_PATH_DIR_IGNORE_CASE = (1u << 0),
+       GIT_FS_PATH_DIR_PRECOMPOSE_UNICODE = (1u << 1),
+       GIT_FS_PATH_DIR_INCLUDE_DOT_AND_DOTDOT = (1u << 2),
+};
+
+/**
+ * Walk each directory entry, except '.' and '..', calling fn(state).
+ *
+ * @param pathbuf Buffer the function reads the initial directory
+ *             path from, and updates with each successive entry's name.
+ * @param flags Combination of GIT_FS_PATH_DIR flags.
+ * @param callback Callback for each entry. Passed the `payload` and each
+ *             successive path inside the directory as a full path.  This may
+ *             safely append text to the pathbuf if needed.  Return non-zero to
+ *             cancel iteration (and return value will be propagated back).
+ * @param payload Passed to callback as first argument.
+ * @return 0 on success or error code from OS error or from callback
+ */
+extern int git_fs_path_direach(
+       git_str *pathbuf,
+       uint32_t flags,
+       int (*callback)(void *payload, git_str *path),
+       void *payload);
+
+/**
+ * Sort function to order two paths
+ */
+extern int git_fs_path_cmp(
+       const char *name1, size_t len1, int isdir1,
+       const char *name2, size_t len2, int isdir2,
+       int (*compare)(const char *, const char *, size_t));
+
+/**
+ * Invoke callback up path directory by directory until the ceiling is
+ * reached (inclusive of a final call at the root_path).
+ *
+ * Returning anything other than 0 from the callback function
+ * will stop the iteration and propagate the error to the caller.
+ *
+ * @param pathbuf Buffer the function reads the directory from and
+ *             and updates with each successive name.
+ * @param ceiling Prefix of path at which to stop walking up.  If NULL,
+ *             this will walk all the way up to the root.  If not a prefix of
+ *             pathbuf, the callback will be invoked a single time on the
+ *             original input path.
+ * @param callback Function to invoke on each path.  Passed the `payload`
+ *             and the buffer containing the current path.  The path should not
+ *             be modified in any way. Return non-zero to stop iteration.
+ * @param payload Passed to fn as the first ath.
+ */
+extern int git_fs_path_walk_up(
+       git_str *pathbuf,
+       const char *ceiling,
+       int (*callback)(void *payload, const char *path),
+       void *payload);
+
+
+enum {
+       GIT_FS_PATH_NOTEQUAL = 0,
+       GIT_FS_PATH_EQUAL = 1,
+       GIT_FS_PATH_PREFIX = 2
+};
+
+/*
+ * Determines if a path is equal to or potentially a child of another.
+ * @param parent The possible parent
+ * @param child The possible child
+ */
+GIT_INLINE(int) git_fs_path_equal_or_prefixed(
+       const char *parent,
+       const char *child,
+       ssize_t *prefixlen)
+{
+       const char *p = parent, *c = child;
+       int lastslash = 0;
+
+       while (*p && *c) {
+               lastslash = (*p == '/');
+
+               if (*p++ != *c++)
+                       return GIT_FS_PATH_NOTEQUAL;
+       }
+
+       if (*p != '\0')
+               return GIT_FS_PATH_NOTEQUAL;
+
+       if (*c == '\0') {
+               if (prefixlen)
+                       *prefixlen = p - parent;
+
+               return GIT_FS_PATH_EQUAL;
+       }
+
+       if (*c == '/' || lastslash) {
+               if (prefixlen)
+                       *prefixlen = (p - parent) - lastslash;
+
+               return GIT_FS_PATH_PREFIX;
+       }
+
+       return GIT_FS_PATH_NOTEQUAL;
+}
+
+/* translate errno to libgit2 error code and set error message */
+extern int git_fs_path_set_error(
+       int errno_value, const char *path, const char *action);
+
+/* check if non-ascii characters are present in filename */
+extern bool git_fs_path_has_non_ascii(const char *path, size_t pathlen);
+
+#define GIT_PATH_REPO_ENCODING "UTF-8"
+
+#ifdef __APPLE__
+#define GIT_PATH_NATIVE_ENCODING "UTF-8-MAC"
+#else
+#define GIT_PATH_NATIVE_ENCODING "UTF-8"
+#endif
+
+#ifdef GIT_USE_ICONV
+
+#include <iconv.h>
+
+typedef struct {
+       iconv_t map;
+       git_str buf;
+} git_fs_path_iconv_t;
+
+#define GIT_PATH_ICONV_INIT { (iconv_t)-1, GIT_STR_INIT }
+
+/* Init iconv data for converting decomposed UTF-8 to precomposed */
+extern int git_fs_path_iconv_init_precompose(git_fs_path_iconv_t *ic);
+
+/* Clear allocated iconv data */
+extern void git_fs_path_iconv_clear(git_fs_path_iconv_t *ic);
+
+/*
+ * Rewrite `in` buffer using iconv map if necessary, replacing `in`
+ * pointer internal iconv buffer if rewrite happened.  The `in` pointer
+ * will be left unchanged if no rewrite was needed.
+ */
+extern int git_fs_path_iconv(git_fs_path_iconv_t *ic, const char **in, size_t *inlen);
+
+#endif /* GIT_USE_ICONV */
+
+extern bool git_fs_path_does_decompose_unicode(const char *root);
+
+
+typedef struct git_fs_path_diriter git_fs_path_diriter;
+
+#if defined(GIT_WIN32) && !defined(__MINGW32__)
+
+struct git_fs_path_diriter
+{
+       git_win32_path path;
+       size_t parent_len;
+
+       git_str path_utf8;
+       size_t parent_utf8_len;
+
+       HANDLE handle;
+
+       unsigned int flags;
+
+       WIN32_FIND_DATAW current;
+       unsigned int needs_next;
+};
+
+#define GIT_FS_PATH_DIRITER_INIT { {0}, 0, GIT_STR_INIT, 0, INVALID_HANDLE_VALUE }
+
+#else
+
+struct git_fs_path_diriter
+{
+       git_str path;
+       size_t parent_len;
+
+       unsigned int flags;
+
+       DIR *dir;
+
+#ifdef GIT_USE_ICONV
+       git_fs_path_iconv_t ic;
+#endif
+};
+
+#define GIT_FS_PATH_DIRITER_INIT { GIT_STR_INIT }
+
+#endif
+
+/**
+ * Initialize a directory iterator.
+ *
+ * @param diriter Pointer to a diriter structure that will be setup.
+ * @param path The path that will be iterated over
+ * @param flags Directory reader flags
+ * @return 0 or an error code
+ */
+extern int git_fs_path_diriter_init(
+       git_fs_path_diriter *diriter,
+       const char *path,
+       unsigned int flags);
+
+/**
+ * Advance the directory iterator.  Will return GIT_ITEROVER when
+ * the iteration has completed successfully.
+ *
+ * @param diriter The directory iterator
+ * @return 0, GIT_ITEROVER, or an error code
+ */
+extern int git_fs_path_diriter_next(git_fs_path_diriter *diriter);
+
+/**
+ * Returns the file name of the current item in the iterator.
+ *
+ * @param out Pointer to store the path in
+ * @param out_len Pointer to store the length of the path in
+ * @param diriter The directory iterator
+ * @return 0 or an error code
+ */
+extern int git_fs_path_diriter_filename(
+       const char **out,
+       size_t *out_len,
+       git_fs_path_diriter *diriter);
+
+/**
+ * Returns the full path of the current item in the iterator; that
+ * is the current filename plus the path of the directory that the
+ * iterator was constructed with.
+ *
+ * @param out Pointer to store the path in
+ * @param out_len Pointer to store the length of the path in
+ * @param diriter The directory iterator
+ * @return 0 or an error code
+ */
+extern int git_fs_path_diriter_fullpath(
+       const char **out,
+       size_t *out_len,
+       git_fs_path_diriter *diriter);
+
+/**
+ * Performs an `lstat` on the current item in the iterator.
+ *
+ * @param out Pointer to store the stat data in
+ * @param diriter The directory iterator
+ * @return 0 or an error code
+ */
+extern int git_fs_path_diriter_stat(struct stat *out, git_fs_path_diriter *diriter);
+
+/**
+ * Closes the directory iterator.
+ *
+ * @param diriter The directory iterator
+ */
+extern void git_fs_path_diriter_free(git_fs_path_diriter *diriter);
+
+/**
+ * Load all directory entries (except '.' and '..') into a vector.
+ *
+ * For cases where `git_fs_path_direach()` is not appropriate, this
+ * allows you to load the filenames in a directory into a vector
+ * of strings. That vector can then be sorted, iterated, or whatever.
+ * Remember to free alloc of the allocated strings when you are done.
+ *
+ * @param contents Vector to fill with directory entry names.
+ * @param path The directory to read from.
+ * @param prefix_len When inserting entries, the trailing part of path
+ *             will be prefixed after this length.  I.e. given path "/a/b" and
+ *             prefix_len 3, the entries will look like "b/e1", "b/e2", etc.
+ * @param flags Combination of GIT_FS_PATH_DIR flags.
+ */
+extern int git_fs_path_dirload(
+       git_vector *contents,
+       const char *path,
+       size_t prefix_len,
+       uint32_t flags);
+
+
+/* Used for paths to repositories on the filesystem */
+extern bool git_fs_path_is_local_file_url(const char *file_url);
+extern int git_fs_path_from_url_or_path(git_str *local_path_out, const char *url_or_path);
+
+/* Flags to determine path validity in `git_fs_path_isvalid` */
+#define GIT_FS_PATH_REJECT_EMPTY_COMPONENT    (1 << 0)
+#define GIT_FS_PATH_REJECT_TRAVERSAL          (1 << 1)
+#define GIT_FS_PATH_REJECT_SLASH              (1 << 2)
+#define GIT_FS_PATH_REJECT_BACKSLASH          (1 << 3)
+#define GIT_FS_PATH_REJECT_TRAILING_DOT       (1 << 4)
+#define GIT_FS_PATH_REJECT_TRAILING_SPACE     (1 << 5)
+#define GIT_FS_PATH_REJECT_TRAILING_COLON     (1 << 6)
+#define GIT_FS_PATH_REJECT_DOS_PATHS          (1 << 7)
+#define GIT_FS_PATH_REJECT_NT_CHARS           (1 << 8)
+#define GIT_FS_PATH_REJECT_LONG_PATHS         (1 << 9)
+
+#define GIT_FS_PATH_REJECT_MAX                (1 << 9)
+
+/* Default path safety for writing files to disk: since we use the
+ * Win32 "File Namespace" APIs ("\\?\") we need to protect from
+ * paths that the normal Win32 APIs would not write.
+ */
+#ifdef GIT_WIN32
+# define GIT_FS_PATH_REJECT_FILESYSTEM_DEFAULTS \
+       GIT_FS_PATH_REJECT_EMPTY_COMPONENT | \
+       GIT_FS_PATH_REJECT_TRAVERSAL | \
+       GIT_FS_PATH_REJECT_BACKSLASH | \
+       GIT_FS_PATH_REJECT_TRAILING_DOT | \
+       GIT_FS_PATH_REJECT_TRAILING_SPACE | \
+       GIT_FS_PATH_REJECT_TRAILING_COLON | \
+       GIT_FS_PATH_REJECT_DOS_PATHS | \
+       GIT_FS_PATH_REJECT_NT_CHARS
+#else
+# define GIT_FS_PATH_REJECT_FILESYSTEM_DEFAULTS \
+       GIT_FS_PATH_REJECT_EMPTY_COMPONENT | \
+       GIT_FS_PATH_REJECT_TRAVERSAL
+#endif
+
+/**
+ * Validate a filesystem path; with custom callbacks per-character and
+ * per-path component.
+ */
+extern bool git_fs_path_str_is_valid_ext(
+       const git_str *path,
+       unsigned int flags,
+       bool (*validate_char_cb)(char ch, void *payload),
+       bool (*validate_component_cb)(const char *component, size_t len, void *payload),
+       bool (*validate_length_cb)(const char *component, size_t len, size_t utf8_char_len),
+       void *payload);
+
+GIT_INLINE(bool) git_fs_path_is_valid_ext(
+       const char *path,
+       unsigned int flags,
+       bool (*validate_char_cb)(char ch, void *payload),
+       bool (*validate_component_cb)(const char *component, size_t len, void *payload),
+       bool (*validate_length_cb)(const char *component, size_t len, size_t utf8_char_len),
+       void *payload)
+{
+       const git_str str = GIT_STR_INIT_CONST(path, SIZE_MAX);
+       return git_fs_path_str_is_valid_ext(
+               &str,
+               flags,
+               validate_char_cb,
+               validate_component_cb,
+               validate_length_cb,
+               payload);
+}
+
+/**
+ * Validate a filesystem path.  This ensures that the given path is legal
+ * and does not contain any "unsafe" components like path traversal ('.'
+ * or '..'), characters that are inappropriate for lesser filesystems
+ * (trailing ' ' or ':' characters), or filenames ("component names")
+ * that are not supported ('AUX', 'COM1").
+ */
+GIT_INLINE(bool) git_fs_path_is_valid(
+       const char *path,
+       unsigned int flags)
+{
+       const git_str str = GIT_STR_INIT_CONST(path, SIZE_MAX);
+       return git_fs_path_str_is_valid_ext(&str, flags, NULL, NULL, NULL, NULL);
+}
+
+/** Validate a filesystem path in a `git_str`. */
+GIT_INLINE(bool) git_fs_path_str_is_valid(
+       const git_str *path,
+       unsigned int flags)
+{
+       return git_fs_path_str_is_valid_ext(path, flags, NULL, NULL, NULL, NULL);
+}
+
+extern int git_fs_path_validate_str_length_with_suffix(
+       git_str *path,
+       size_t suffix_len);
+
+/**
+ * Validate an on-disk path, taking into account that it will have a
+ * suffix appended (eg, `.lock`).
+ */
+GIT_INLINE(int) git_fs_path_validate_filesystem_with_suffix(
+       const char *path,
+       size_t path_len,
+       size_t suffix_len)
+{
+#ifdef GIT_WIN32
+       size_t path_chars, total_chars;
+
+       path_chars = git_utf8_char_length(path, path_len);
+
+       if (GIT_ADD_SIZET_OVERFLOW(&total_chars, path_chars, suffix_len) ||
+           total_chars > MAX_PATH) {
+               git_error_set(GIT_ERROR_FILESYSTEM, "path too long: '%s'", path);
+               return -1;
+       }
+       return 0;
+#else
+       GIT_UNUSED(path);
+       GIT_UNUSED(path_len);
+       GIT_UNUSED(suffix_len);
+       return 0;
+#endif
+}
+
+/**
+ * Validate an path on the filesystem.  This ensures that the given
+ * path is valid for the operating system/platform; for example, this
+ * will ensure that the given absolute path is smaller than MAX_PATH on
+ * Windows.
+ *
+ * For paths within the working directory, you should use ensure that
+ * `core.longpaths` is obeyed.  Use `git_fs_path_validate_workdir`.
+ */
+GIT_INLINE(int) git_fs_path_validate_filesystem(
+       const char *path,
+       size_t path_len)
+{
+       return git_fs_path_validate_filesystem_with_suffix(path, path_len, 0);
+}
+
+/**
+ * Convert any backslashes into slashes
+ */
+int git_fs_path_normalize_slashes(git_str *out, const char *path);
+
+bool git_fs_path_supports_symlinks(const char *dir);
+
+typedef enum {
+       GIT_FS_PATH_MOCK_OWNER_NONE = 0, /* do filesystem lookups as normal */
+       GIT_FS_PATH_MOCK_OWNER_SYSTEM = 1,
+       GIT_FS_PATH_MOCK_OWNER_CURRENT_USER = 2,
+       GIT_FS_PATH_MOCK_OWNER_OTHER = 3
+} git_fs_path__mock_owner_t;
+
+/**
+ * Sets the mock ownership for files; subsequent calls to
+ * `git_fs_path_owner_is_*` functions will return this data until cleared
+ * with `GIT_FS_PATH_MOCK_OWNER_NONE`.
+ */
+void git_fs_path__set_owner(git_fs_path__mock_owner_t owner);
+
+/**
+ * Verify that the file in question is owned by an administrator or system
+ * account.
+ */
+int git_fs_path_owner_is_system(bool *out, const char *path);
+
+/**
+ * Verify that the file in question is owned by the current user;
+ */
+
+int git_fs_path_owner_is_current_user(bool *out, const char *path);
+
+/**
+ * Verify that the file in question is owned by an administrator or system
+ * account _or_ the current user;
+ */
+int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path);
+
+/**
+ * Search the current PATH for the given executable, returning the full
+ * path if it is found.
+ */
+int git_fs_path_find_executable(git_str *fullpath, const char *executable);
+
+#endif
index a44820875b16fe91046a81e3d2da65691be83bde..42c35955e30a968126e45e08056aee77c9473f82 100644 (file)
 #include "runtime.h"
 #include "strmap.h"
 #include "hash.h"
+#include "rand.h"
+
 #include <ctype.h>
 #if GIT_WIN32
 #include "win32/findfile.h"
 #endif
 
+#define GIT_FILEMODE_DEFAULT 0100666
+
 int git_futils_mkpath2file(const char *file_path, const mode_t mode)
 {
        return git_futils_mkdir(
@@ -22,32 +26,31 @@ int git_futils_mkpath2file(const char *file_path, const mode_t mode)
                GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST | GIT_MKDIR_VERIFY_DIR);
 }
 
-int git_futils_mktmp(git_buf *path_out, const char *filename, mode_t mode)
+int git_futils_mktmp(git_str *path_out, const char *filename, mode_t mode)
 {
+       const int open_flags = O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC;
+       unsigned int tries = 32;
        int fd;
-       mode_t mask;
-
-       p_umask(mask = p_umask(0));
 
-       git_buf_sets(path_out, filename);
-       git_buf_puts(path_out, "_git2_XXXXXX");
+       while (tries--) {
+               uint64_t rand = git_rand_next();
 
-       if (git_buf_oom(path_out))
-               return -1;
+               git_str_sets(path_out, filename);
+               git_str_puts(path_out, "_git2_");
+               git_str_encode_hexstr(path_out, (void *)&rand, sizeof(uint64_t));
 
-       if ((fd = p_mkstemp(path_out->ptr)) < 0) {
-               git_error_set(GIT_ERROR_OS,
-                       "failed to create temporary file '%s'", path_out->ptr);
-               return -1;
-       }
+               if (git_str_oom(path_out))
+                       return -1;
 
-       if (p_chmod(path_out->ptr, (mode & ~mask))) {
-               git_error_set(GIT_ERROR_OS,
-                       "failed to set permissions on file '%s'", path_out->ptr);
-               return -1;
+               /* Note that we open with O_CREAT | O_EXCL */
+               if ((fd = p_open(path_out->ptr, open_flags, mode)) >= 0)
+                       return fd;
        }
 
-       return fd;
+       git_error_set(GIT_ERROR_OS,
+               "failed to create temporary file '%s'", path_out->ptr);
+       git_str_dispose(path_out);
+       return -1;
 }
 
 int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode_t mode)
@@ -99,7 +102,7 @@ int git_futils_open_ro(const char *path)
 {
        int fd = p_open(path, O_RDONLY);
        if (fd < 0)
-               return git_path_set_error(errno, path, "open");
+               return git_fs_path_set_error(errno, path, "open");
        return fd;
 }
 
@@ -107,7 +110,7 @@ int git_futils_truncate(const char *path, int mode)
 {
        int fd = p_open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
        if (fd < 0)
-               return git_path_set_error(errno, path, "open");
+               return git_fs_path_set_error(errno, path, "open");
 
        close(fd);
        return 0;
@@ -145,12 +148,12 @@ mode_t git_futils_canonical_mode(mode_t raw_mode)
                return 0;
 }
 
-int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len)
+int git_futils_readbuffer_fd(git_str *buf, git_file fd, size_t len)
 {
        ssize_t read_size = 0;
        size_t alloc_len;
 
-       git_buf_clear(buf);
+       git_str_clear(buf);
 
        if (!git__is_ssizet(len)) {
                git_error_set(GIT_ERROR_INVALID, "read too large");
@@ -158,7 +161,7 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len)
        }
 
        GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, len, 1);
-       if (git_buf_grow(buf, alloc_len) < 0)
+       if (git_str_grow(buf, alloc_len) < 0)
                return -1;
 
        /* p_read loops internally to read len bytes */
@@ -166,7 +169,7 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len)
 
        if (read_size != (ssize_t)len) {
                git_error_set(GIT_ERROR_OS, "failed to read descriptor");
-               git_buf_dispose(buf);
+               git_str_dispose(buf);
                return -1;
        }
 
@@ -177,13 +180,16 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len)
 }
 
 int git_futils_readbuffer_updated(
-       git_buf *out, const char *path, git_oid *checksum, int *updated)
+       git_str *out,
+       const char *path,
+       unsigned char checksum[GIT_HASH_SHA1_SIZE],
+       int *updated)
 {
        int error;
        git_file fd;
        struct stat st;
-       git_buf buf = GIT_BUF_INIT;
-       git_oid checksum_new;
+       git_str buf = GIT_STR_INIT;
+       unsigned char checksum_new[GIT_HASH_SHA1_SIZE];
 
        GIT_ASSERT_ARG(out);
        GIT_ASSERT_ARG(path && *path);
@@ -192,7 +198,7 @@ int git_futils_readbuffer_updated(
                *updated = 0;
 
        if (p_stat(path, &st) < 0)
-               return git_path_set_error(errno, path, "stat");
+               return git_fs_path_set_error(errno, path, "stat");
 
 
        if (S_ISDIR(st.st_mode)) {
@@ -216,23 +222,23 @@ int git_futils_readbuffer_updated(
        p_close(fd);
 
        if (checksum) {
-               if ((error = git_hash_buf(&checksum_new, buf.ptr, buf.size)) < 0) {
-                       git_buf_dispose(&buf);
+               if ((error = git_hash_buf(checksum_new, buf.ptr, buf.size, GIT_HASH_ALGORITHM_SHA1)) < 0) {
+                       git_str_dispose(&buf);
                        return error;
                }
 
                /*
                 * If we were given a checksum, we only want to use it if it's different
                 */
-               if (!git_oid__cmp(checksum, &checksum_new)) {
-                       git_buf_dispose(&buf);
+               if (!memcmp(checksum, checksum_new, GIT_HASH_SHA1_SIZE)) {
+                       git_str_dispose(&buf);
                        if (updated)
                                *updated = 0;
 
                        return 0;
                }
 
-               git_oid_cpy(checksum, &checksum_new);
+               memcpy(checksum, checksum_new, GIT_HASH_SHA1_SIZE);
        }
 
        /*
@@ -241,19 +247,19 @@ int git_futils_readbuffer_updated(
        if (updated != NULL)
                *updated = 1;
 
-       git_buf_swap(out, &buf);
-       git_buf_dispose(&buf);
+       git_str_swap(out, &buf);
+       git_str_dispose(&buf);
 
        return 0;
 }
 
-int git_futils_readbuffer(git_buf *buf, const char *path)
+int git_futils_readbuffer(git_str *buf, const char *path)
 {
        return git_futils_readbuffer_updated(buf, path, NULL, NULL);
 }
 
 int git_futils_writebuffer(
-       const git_buf *buf,     const char *path, int flags, mode_t mode)
+       const git_str *buf, const char *path, int flags, mode_t mode)
 {
        int fd, do_fsync = 0, error = 0;
 
@@ -266,14 +272,14 @@ int git_futils_writebuffer(
        flags &= ~O_FSYNC;
 
        if (!mode)
-               mode = GIT_FILEMODE_BLOB;
+               mode = GIT_FILEMODE_DEFAULT;
 
        if ((fd = p_open(path, flags, mode)) < 0) {
                git_error_set(GIT_ERROR_OS, "could not open '%s' for writing", path);
                return fd;
        }
 
-       if ((error = p_write(fd, git_buf_cstr(buf), git_buf_len(buf))) < 0) {
+       if ((error = p_write(fd, git_str_cstr(buf), git_str_len(buf))) < 0) {
                git_error_set(GIT_ERROR_OS, "could not write to '%s'", path);
                (void)p_close(fd);
                return error;
@@ -415,7 +421,7 @@ GIT_INLINE(int) mkdir_validate_mode(
 }
 
 GIT_INLINE(int) mkdir_canonicalize(
-       git_buf *path,
+       git_str *path,
        uint32_t flags)
 {
        ssize_t root_len;
@@ -426,7 +432,7 @@ GIT_INLINE(int) mkdir_canonicalize(
        }
 
        /* Trim trailing slashes (except the root) */
-       if ((root_len = git_path_root(path->ptr)) < 0)
+       if ((root_len = git_fs_path_root(path->ptr)) < 0)
                root_len = 0;
        else
                root_len++;
@@ -436,18 +442,18 @@ GIT_INLINE(int) mkdir_canonicalize(
 
        /* if we are not supposed to made the last element, truncate it */
        if ((flags & GIT_MKDIR_SKIP_LAST2) != 0) {
-               git_path_dirname_r(path, path->ptr);
+               git_fs_path_dirname_r(path, path->ptr);
                flags |= GIT_MKDIR_SKIP_LAST;
        }
        if ((flags & GIT_MKDIR_SKIP_LAST) != 0) {
-               git_path_dirname_r(path, path->ptr);
+               git_fs_path_dirname_r(path, path->ptr);
        }
 
        /* We were either given the root path (or trimmed it to
        * the root), we don't have anything to do.
        */
        if (path->size <= (size_t)root_len)
-               git_buf_clear(path);
+               git_str_clear(path);
 
        return 0;
 }
@@ -457,20 +463,20 @@ int git_futils_mkdir(
        mode_t mode,
        uint32_t flags)
 {
-       git_buf make_path = GIT_BUF_INIT, parent_path = GIT_BUF_INIT;
+       git_str make_path = GIT_STR_INIT, parent_path = GIT_STR_INIT;
        const char *relative;
        struct git_futils_mkdir_options opts = { 0 };
        struct stat st;
        size_t depth = 0;
        int len = 0, root_len, error;
 
-       if ((error = git_buf_puts(&make_path, path)) < 0 ||
+       if ((error = git_str_puts(&make_path, path)) < 0 ||
                (error = mkdir_canonicalize(&make_path, flags)) < 0 ||
-               (error = git_buf_puts(&parent_path, make_path.ptr)) < 0 ||
+               (error = git_str_puts(&parent_path, make_path.ptr)) < 0 ||
                make_path.size == 0)
                goto done;
 
-       root_len = git_path_root(make_path.ptr);
+       root_len = git_fs_path_root(make_path.ptr);
 
        /* find the first parent directory that exists.  this will be used
         * as the base to dirname_relative.
@@ -489,7 +495,7 @@ int git_futils_mkdir(
                depth++;
 
                /* examine the parent of the current path */
-               if ((len = git_path_dirname_r(&parent_path, parent_path.ptr)) < 0) {
+               if ((len = git_fs_path_dirname_r(&parent_path, parent_path.ptr)) < 0) {
                        error = len;
                        goto done;
                }
@@ -538,8 +544,8 @@ int git_futils_mkdir(
                parent_path.size ? parent_path.ptr : NULL, mode, flags, &opts);
 
 done:
-       git_buf_dispose(&make_path);
-       git_buf_dispose(&parent_path);
+       git_str_dispose(&make_path);
+       git_str_dispose(&parent_path);
        return error;
 }
 
@@ -555,7 +561,7 @@ int git_futils_mkdir_relative(
        uint32_t flags,
        struct git_futils_mkdir_options *opts)
 {
-       git_buf make_path = GIT_BUF_INIT;
+       git_str make_path = GIT_STR_INIT;
        ssize_t root = 0, min_root_len;
        char lastch = '/', *tail;
        struct stat st;
@@ -566,7 +572,7 @@ int git_futils_mkdir_relative(
                opts = &empty_opts;
 
        /* build path and find "root" where we should start calling mkdir */
-       if (git_path_join_unrooted(&make_path, relative_path, base, &root) < 0)
+       if (git_fs_path_join_unrooted(&make_path, relative_path, base, &root) < 0)
                return -1;
 
        if ((error = mkdir_canonicalize(&make_path, flags)) < 0 ||
@@ -575,10 +581,10 @@ int git_futils_mkdir_relative(
 
        /* if we are not supposed to make the whole path, reset root */
        if ((flags & GIT_MKDIR_PATH) == 0)
-               root = git_buf_rfind(&make_path, '/');
+               root = git_str_rfind(&make_path, '/');
 
        /* advance root past drive name or network mount prefix */
-       min_root_len = git_path_root(make_path.ptr);
+       min_root_len = git_fs_path_root(make_path.ptr);
        if (root < min_root_len)
                root = min_root_len;
        while (root >= 0 && make_path.ptr[root] == '/')
@@ -670,7 +676,7 @@ retry_lstat:
        }
 
 done:
-       git_buf_dispose(&make_path);
+       git_str_dispose(&make_path);
        return error;
 }
 
@@ -694,13 +700,13 @@ static int futils__error_cannot_rmdir(const char *path, const char *filemsg)
        return -1;
 }
 
-static int futils__rm_first_parent(git_buf *path, const char *ceiling)
+static int futils__rm_first_parent(git_str *path, const char *ceiling)
 {
        int error = GIT_ENOTFOUND;
        struct stat st;
 
        while (error == GIT_ENOTFOUND) {
-               git_buf_rtruncate_at_char(path, '/');
+               git_str_rtruncate_at_char(path, '/');
 
                if (!path->size || git__prefixcmp(path->ptr, ceiling) != 0)
                        error = 0;
@@ -719,7 +725,7 @@ static int futils__rm_first_parent(git_buf *path, const char *ceiling)
        return error;
 }
 
-static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path)
+static int futils__rmdir_recurs_foreach(void *opaque, git_str *path)
 {
        int error = 0;
        futils__rmdir_data *data = opaque;
@@ -741,13 +747,13 @@ static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path)
                                        path->ptr, "parent is not directory");
                }
                else
-                       error = git_path_set_error(errno, path->ptr, "rmdir");
+                       error = git_fs_path_set_error(errno, path->ptr, "rmdir");
        }
 
        else if (S_ISDIR(st.st_mode)) {
                data->depth++;
 
-               error = git_path_direach(path, 0, futils__rmdir_recurs_foreach, data);
+               error = git_fs_path_direach(path, 0, futils__rmdir_recurs_foreach, data);
 
                data->depth--;
 
@@ -762,13 +768,13 @@ static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path)
                                (errno == ENOTEMPTY || errno == EEXIST || errno == EBUSY))
                                error = 0;
                        else
-                               error = git_path_set_error(errno, path->ptr, "rmdir");
+                               error = git_fs_path_set_error(errno, path->ptr, "rmdir");
                }
        }
 
        else if ((data->flags & GIT_RMDIR_REMOVE_FILES) != 0) {
                if (p_unlink(path->ptr) < 0)
-                       error = git_path_set_error(errno, path->ptr, "remove");
+                       error = git_fs_path_set_error(errno, path->ptr, "remove");
        }
 
        else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0)
@@ -792,11 +798,11 @@ static int futils__rmdir_empty_parent(void *opaque, const char *path)
                        /* do nothing */
                } else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0 &&
                        en == EBUSY) {
-                       error = git_path_set_error(errno, path, "rmdir");
+                       error = git_fs_path_set_error(errno, path, "rmdir");
                } else if (en == ENOTEMPTY || en == EEXIST || en == EBUSY) {
                        error = GIT_ITEROVER;
                } else {
-                       error = git_path_set_error(errno, path, "rmdir");
+                       error = git_fs_path_set_error(errno, path, "rmdir");
                }
        }
 
@@ -807,11 +813,11 @@ int git_futils_rmdir_r(
        const char *path, const char *base, uint32_t flags)
 {
        int error;
-       git_buf fullpath = GIT_BUF_INIT;
+       git_str fullpath = GIT_STR_INIT;
        futils__rmdir_data data;
 
        /* build path and find "root" where we should start calling mkdir */
-       if (git_path_join_unrooted(&fullpath, path, base, NULL) < 0)
+       if (git_fs_path_join_unrooted(&fullpath, path, base, NULL) < 0)
                return -1;
 
        memset(&data, 0, sizeof(data));
@@ -823,7 +829,7 @@ int git_futils_rmdir_r(
 
        /* remove now-empty parents if requested */
        if (!error && (flags & GIT_RMDIR_EMPTY_PARENTS) != 0)
-               error = git_path_walk_up(
+               error = git_fs_path_walk_up(
                        &fullpath, base, futils__rmdir_empty_parent, &data);
 
        if (error == GIT_ITEROVER) {
@@ -831,7 +837,7 @@ int git_futils_rmdir_r(
                error = 0;
        }
 
-       git_buf_dispose(&fullpath);
+       git_str_dispose(&fullpath);
 
        return error;
 }
@@ -884,7 +890,7 @@ int git_futils_cp(const char *from, const char *to, mode_t filemode)
 
        if ((ofd = p_open(to, O_WRONLY | O_CREAT | O_EXCL, filemode)) < 0) {
                p_close(ifd);
-               return git_path_set_error(errno, to, "open for writing");
+               return git_fs_path_set_error(errno, to, "open for writing");
        }
 
        return cp_by_fd(ifd, ofd, true);
@@ -900,7 +906,7 @@ int git_futils_touch(const char *path, time_t *when)
 
        ret = p_utimes(path, times);
 
-       return (ret < 0) ? git_path_set_error(errno, path, "touch") : 0;
+       return (ret < 0) ? git_fs_path_set_error(errno, path, "touch") : 0;
 }
 
 static int cp_link(const char *from, const char *to, size_t link_size)
@@ -935,7 +941,7 @@ static int cp_link(const char *from, const char *to, size_t link_size)
 
 typedef struct {
        const char *to_root;
-       git_buf to;
+       git_str to;
        ssize_t from_prefix;
        uint32_t flags;
        uint32_t mkdir_flags;
@@ -944,7 +950,7 @@ typedef struct {
 
 #define GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT (1u << 10)
 
-static int _cp_r_mkdir(cp_r_info *info, git_buf *from)
+static int _cp_r_mkdir(cp_r_info *info, git_str *from)
 {
        int error = 0;
 
@@ -966,7 +972,7 @@ static int _cp_r_mkdir(cp_r_info *info, git_buf *from)
        return error;
 }
 
-static int _cp_r_callback(void *ref, git_buf *from)
+static int _cp_r_callback(void *ref, git_str *from)
 {
        int error = 0;
        cp_r_info *info = ref;
@@ -974,14 +980,14 @@ static int _cp_r_callback(void *ref, git_buf *from)
        bool exists = false;
 
        if ((info->flags & GIT_CPDIR_COPY_DOTFILES) == 0 &&
-               from->ptr[git_path_basename_offset(from)] == '.')
+               from->ptr[git_fs_path_basename_offset(from)] == '.')
                return 0;
 
-       if ((error = git_buf_joinpath(
+       if ((error = git_str_joinpath(
                        &info->to, info->to_root, from->ptr + info->from_prefix)) < 0)
                return error;
 
-       if (!(error = git_path_lstat(info->to.ptr, &to_st)))
+       if (!(error = git_fs_path_lstat(info->to.ptr, &to_st)))
                exists = true;
        else if (error != GIT_ENOTFOUND)
                return error;
@@ -990,7 +996,7 @@ static int _cp_r_callback(void *ref, git_buf *from)
                error = 0;
        }
 
-       if ((error = git_path_lstat(from->ptr, &from_st)) < 0)
+       if ((error = git_fs_path_lstat(from->ptr, &from_st)) < 0)
                return error;
 
        if (S_ISDIR(from_st.st_mode)) {
@@ -1006,7 +1012,7 @@ static int _cp_r_callback(void *ref, git_buf *from)
 
                /* recurse onto target directory */
                if (!error && (!exists || S_ISDIR(to_st.st_mode)))
-                       error = git_path_direach(from, 0, _cp_r_callback, info);
+                       error = git_fs_path_direach(from, 0, _cp_r_callback, info);
 
                if (oldmode != 0)
                        info->dirmode = oldmode;
@@ -1061,10 +1067,10 @@ int git_futils_cp_r(
        mode_t dirmode)
 {
        int error;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        cp_r_info info;
 
-       if (git_buf_joinpath(&path, from, "") < 0) /* ensure trailing slash */
+       if (git_str_joinpath(&path, from, "") < 0) /* ensure trailing slash */
                return -1;
 
        memset(&info, 0, sizeof(info));
@@ -1072,7 +1078,7 @@ int git_futils_cp_r(
        info.flags   = flags;
        info.dirmode = dirmode;
        info.from_prefix = path.size;
-       git_buf_init(&info.to, 0);
+       git_str_init(&info.to, 0);
 
        /* precalculate mkdir flags */
        if ((flags & GIT_CPDIR_CREATE_EMPTY_DIRS) == 0) {
@@ -1090,8 +1096,8 @@ int git_futils_cp_r(
 
        error = _cp_r_callback(&info, &path);
 
-       git_buf_dispose(&path);
-       git_buf_dispose(&info.to);
+       git_str_dispose(&path);
+       git_str_dispose(&info.to);
 
        return error;
 }
@@ -1179,7 +1185,7 @@ int git_futils_fsync_parent(const char *path)
        char *parent;
        int error;
 
-       if ((parent = git_path_dirname(path)) == NULL)
+       if ((parent = git_fs_path_dirname(path)) == NULL)
                return -1;
 
        error = git_futils_fsync_dir(parent);
index 58936125ac2898e893c0004505533d623644180c..a82ec41cc63b43248b1c03024d493446553b2b66 100644 (file)
 
 #include "map.h"
 #include "posix.h"
-#include "path.h"
+#include "fs_path.h"
 #include "pool.h"
 #include "strmap.h"
-#include "oid.h"
+#include "hash.h"
 
 /**
  * Filebuffer methods
  *
  * Read whole files into an in-memory buffer for processing
  */
-extern int git_futils_readbuffer(git_buf *obj, const char *path);
+extern int git_futils_readbuffer(git_str *obj, const char *path);
 extern int git_futils_readbuffer_updated(
-       git_buf *obj, const char *path, git_oid *checksum, int *updated);
-extern int git_futils_readbuffer_fd(git_buf *obj, git_file fd, size_t len);
+       git_str *obj,
+       const char *path,
+       unsigned char checksum[GIT_HASH_SHA1_SIZE],
+       int *updated);
+extern int git_futils_readbuffer_fd(git_str *obj, git_file fd, size_t len);
 
 /* Additional constants for `git_futils_writebuffer`'s `open_flags`.  We
  * support these internally and they will be removed before the `open` call.
@@ -34,7 +37,7 @@ extern int git_futils_readbuffer_fd(git_buf *obj, git_file fd, size_t len);
 #endif
 
 extern int git_futils_writebuffer(
-       const git_buf *buf, const char *path, int open_flags, mode_t mode);
+       const git_str *buf, const char *path, int open_flags, mode_t mode);
 
 /**
  * File utils
@@ -93,7 +96,7 @@ typedef enum {
        GIT_MKDIR_SKIP_LAST2 = 32,
        GIT_MKDIR_VERIFY_DIR = 64,
        GIT_MKDIR_REMOVE_FILES = 128,
-       GIT_MKDIR_REMOVE_SYMLINKS = 256,
+       GIT_MKDIR_REMOVE_SYMLINKS = 256
 } git_futils_mkdir_flags;
 
 struct git_futils_mkdir_perfdata
@@ -156,7 +159,7 @@ typedef enum {
        GIT_RMDIR_SKIP_NONEMPTY   = (1 << 1),
        GIT_RMDIR_EMPTY_PARENTS   = (1 << 2),
        GIT_RMDIR_REMOVE_BLOCKERS = (1 << 3),
-       GIT_RMDIR_SKIP_ROOT       = (1 << 4),
+       GIT_RMDIR_SKIP_ROOT       = (1 << 4)
 } git_futils_rmdir_flags;
 
 /**
@@ -170,11 +173,20 @@ typedef enum {
 extern int git_futils_rmdir_r(const char *path, const char *base, uint32_t flags);
 
 /**
- * Create and open a temporary file with a `_git2_` suffix.
- * Writes the filename into path_out.
+ * Create and open a temporary file with a `_git2_` suffix in a
+ * protected directory; the file created will created will honor
+ * the current `umask`.  Writes the filename into path_out.
+ *
+ * This function uses a high-quality PRNG seeded by the system's
+ * entropy pool _where available_ and falls back to a simple seed
+ * (time plus system information) when not.  This is suitable for
+ * writing within a protected directory, but the system's safe
+ * temporary file creation functions should be preferred where
+ * available when writing into world-writable (temp) directories.
+ *
  * @return On success, an open file descriptor, else an error code < 0.
  */
-extern int git_futils_mktmp(git_buf *path_out, const char *filename, mode_t mode);
+extern int git_futils_mktmp(git_str *path_out, const char *filename, mode_t mode);
 
 /**
  * Move a file on the filesystem, create the
@@ -221,17 +233,17 @@ typedef enum {
        GIT_CPDIR_OVERWRITE         = (1u << 3),
        GIT_CPDIR_CHMOD_DIRS        = (1u << 4),
        GIT_CPDIR_SIMPLE_TO_MODE    = (1u << 5),
-       GIT_CPDIR_LINK_FILES        = (1u << 6),
+       GIT_CPDIR_LINK_FILES        = (1u << 6)
 } git_futils_cpdir_flags;
 
 /**
  * Copy a directory tree.
  *
  * This copies directories and files from one root to another.  You can
- * pass a combinationof GIT_CPDIR flags as defined above.
+ * pass a combination of GIT_CPDIR flags as defined above.
  *
  * If you pass the CHMOD flag, then the dirmode will be applied to all
- * directories that are created during the copy, overiding the natural
+ * directories that are created during the copy, overriding the natural
  * permissions.  If you do not pass the CHMOD flag, then the dirmode
  * will actually be copied from the source files and the `dirmode` arg
  * will be ignored.
index 5a7278e4225673a9f615dc6fa2144a811eaf82eb..98ceb05d26038e40a3a40429c9ac3b5a7c09769e 100644 (file)
@@ -12,71 +12,83 @@ int git_hash_global_init(void)
        return git_hash_sha1_global_init();
 }
 
-int git_hash_ctx_init(git_hash_ctx *ctx)
+int git_hash_ctx_init(git_hash_ctx *ctx, git_hash_algorithm_t algorithm)
 {
        int error;
 
-       if ((error = git_hash_sha1_ctx_init(&ctx->ctx.sha1)) < 0)
-               return error;
-
-       ctx->algo = GIT_HASH_ALGO_SHA1;
+       switch (algorithm) {
+       case GIT_HASH_ALGORITHM_SHA1:
+               error = git_hash_sha1_ctx_init(&ctx->ctx.sha1);
+               break;
+       default:
+               git_error_set(GIT_ERROR_INTERNAL, "unknown hash algorithm");
+               error = -1;
+       }
 
-       return 0;
+       ctx->algorithm = algorithm;
+       return error;
 }
 
 void git_hash_ctx_cleanup(git_hash_ctx *ctx)
 {
-       switch (ctx->algo) {
-               case GIT_HASH_ALGO_SHA1:
-                       git_hash_sha1_ctx_cleanup(&ctx->ctx.sha1);
-                       return;
-               default:
-                       /* unreachable */ ;
+       switch (ctx->algorithm) {
+       case GIT_HASH_ALGORITHM_SHA1:
+               git_hash_sha1_ctx_cleanup(&ctx->ctx.sha1);
+               return;
+       default:
+               /* unreachable */ ;
        }
 }
 
 int git_hash_init(git_hash_ctx *ctx)
 {
-       switch (ctx->algo) {
-               case GIT_HASH_ALGO_SHA1:
-                       return git_hash_sha1_init(&ctx->ctx.sha1);
-               default:
-                       /* unreachable */ ;
+       switch (ctx->algorithm) {
+       case GIT_HASH_ALGORITHM_SHA1:
+               return git_hash_sha1_init(&ctx->ctx.sha1);
+       default:
+               /* unreachable */ ;
        }
-       GIT_ASSERT(0);
+
+       git_error_set(GIT_ERROR_INTERNAL, "unknown hash algorithm");
        return -1;
 }
 
 int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len)
 {
-       switch (ctx->algo) {
-               case GIT_HASH_ALGO_SHA1:
-                       return git_hash_sha1_update(&ctx->ctx.sha1, data, len);
-               default:
-                       /* unreachable */ ;
+       switch (ctx->algorithm) {
+       case GIT_HASH_ALGORITHM_SHA1:
+               return git_hash_sha1_update(&ctx->ctx.sha1, data, len);
+       default:
+               /* unreachable */ ;
        }
-       GIT_ASSERT(0);
+
+       git_error_set(GIT_ERROR_INTERNAL, "unknown hash algorithm");
        return -1;
 }
 
-int git_hash_final(git_oid *out, git_hash_ctx *ctx)
+int git_hash_final(unsigned char *out, git_hash_ctx *ctx)
 {
-       switch (ctx->algo) {
-               case GIT_HASH_ALGO_SHA1:
-                       return git_hash_sha1_final(out, &ctx->ctx.sha1);
-               default:
-                       /* unreachable */ ;
+       switch (ctx->algorithm) {
+       case GIT_HASH_ALGORITHM_SHA1:
+               return git_hash_sha1_final(out, &ctx->ctx.sha1);
+       default:
+               /* unreachable */ ;
        }
-       GIT_ASSERT(0);
+
+       git_error_set(GIT_ERROR_INTERNAL, "unknown hash algorithm");
        return -1;
 }
 
-int git_hash_buf(git_oid *out, const void *data, size_t len)
+int git_hash_buf(
+       unsigned char *out,
+       const void *data,
+       size_t len,
+       git_hash_algorithm_t algorithm)
 {
        git_hash_ctx ctx;
        int error = 0;
 
-       if (git_hash_ctx_init(&ctx) < 0)
+       if (git_hash_ctx_init(&ctx, algorithm) < 0)
                return -1;
 
        if ((error = git_hash_update(&ctx, data, len)) >= 0)
@@ -87,13 +99,17 @@ int git_hash_buf(git_oid *out, const void *data, size_t len)
        return error;
 }
 
-int git_hash_vec(git_oid *out, git_buf_vec *vec, size_t n)
+int git_hash_vec(
+       unsigned char *out,
+       git_str_vec *vec,
+       size_t n,
+       git_hash_algorithm_t algorithm)
 {
        git_hash_ctx ctx;
        size_t i;
        int error = 0;
 
-       if (git_hash_ctx_init(&ctx) < 0)
+       if (git_hash_ctx_init(&ctx, algorithm) < 0)
                return -1;
 
        for (i = 0; i < n; i++) {
@@ -108,3 +124,19 @@ done:
 
        return error;
 }
+
+int git_hash_fmt(char *out, unsigned char *hash, size_t hash_len)
+{
+       static char hex[] = "0123456789abcdef";
+       char *str = out;
+       size_t i;
+
+       for (i = 0; i < hash_len; i++) {
+               *str++ = hex[hash[i] >> 4];
+               *str++ = hex[hash[i] & 0x0f];
+       }
+
+       *str++ = '\0';
+
+       return 0;
+}
index 87305cc79201eead205d62da06978469ad8fd219..507c1cb256fd3a1a5709e151fe6a48bc5e1ed964 100644 (file)
 
 #include "common.h"
 
-#include "git2/oid.h"
+#include "hash/sha1.h"
 
 typedef struct {
        void *data;
        size_t len;
-} git_buf_vec;
+} git_str_vec;
 
 typedef enum {
-       GIT_HASH_ALGO_UNKNOWN = 0,
-       GIT_HASH_ALGO_SHA1,
-} git_hash_algo_t;
-
-#include "hash/sha1.h"
+       GIT_HASH_ALGORITHM_NONE = 0,
+       GIT_HASH_ALGORITHM_SHA1
+} git_hash_algorithm_t;
 
 typedef struct git_hash_ctx {
        union {
                git_hash_sha1_ctx sha1;
        } ctx;
-       git_hash_algo_t algo;
+       git_hash_algorithm_t algorithm;
 } git_hash_ctx;
 
 int git_hash_global_init(void);
 
-int git_hash_ctx_init(git_hash_ctx *ctx);
+int git_hash_ctx_init(git_hash_ctx *ctx, git_hash_algorithm_t algorithm);
 void git_hash_ctx_cleanup(git_hash_ctx *ctx);
 
 int git_hash_init(git_hash_ctx *c);
 int git_hash_update(git_hash_ctx *c, const void *data, size_t len);
-int git_hash_final(git_oid *out, git_hash_ctx *c);
+int git_hash_final(unsigned char *out, git_hash_ctx *c);
+
+int git_hash_buf(unsigned char *out, const void *data, size_t len, git_hash_algorithm_t algorithm);
+int git_hash_vec(unsigned char *out, git_str_vec *vec, size_t n, git_hash_algorithm_t algorithm);
 
-int git_hash_buf(git_oid *out, const void *data, size_t len);
-int git_hash_vec(git_oid *out, git_buf_vec *vec, size_t n);
+int git_hash_fmt(char *out, unsigned char *hash, size_t hash_len);
 
 #endif
index fb8d62f8071b179156453c418235e5b558a76e29..4b4dae3f831a4fb4fa4d55ffb58060924e7b51ed 100644 (file)
@@ -26,6 +26,8 @@ typedef struct git_hash_sha1_ctx git_hash_sha1_ctx;
 # include "sha1/generic.h"
 #endif
 
+#define GIT_HASH_SHA1_SIZE 20
+
 int git_hash_sha1_global_init(void);
 
 int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx);
@@ -33,6 +35,6 @@ void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx);
 
 int git_hash_sha1_init(git_hash_sha1_ctx *c);
 int git_hash_sha1_update(git_hash_sha1_ctx *c, const void *data, size_t len);
-int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *c);
+int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *c);
 
 #endif
index 722ebf36f3814be04fccfd8cd6b83bc6b30f6ea0..ec7059c4c7f354530f6644b4699815a0890f8740 100644 (file)
@@ -36,10 +36,10 @@ int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
        return 0;
 }
 
-int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx)
+int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
 {
        GIT_ASSERT_ARG(ctx);
-       if (SHA1DCFinal(out->id, &ctx->c)) {
+       if (SHA1DCFinal(out, &ctx->c)) {
                git_error_set(GIT_ERROR_SHA1, "SHA1 collision attack detected");
                return -1;
        }
index 4250e0b614fb1a3cd3f8b8e13dddd50645cdac5b..9d608f4490e80fb8c7b854730f83fd21416ecd79 100644 (file)
@@ -49,9 +49,9 @@ int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *_data, size_t len)
        return 0;
 }
 
-int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx)
+int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
 {
        GIT_ASSERT_ARG(ctx);
-       CC_SHA1_Final(out->id, &ctx->c);
+       CC_SHA1_Final(out, &ctx->c);
        return 0;
 }
index 607fe3a43c95d0d184aa14846a64d77c42871461..85b34c578f8a72b79a6b5bc0939bf3896bbfda1c 100644 (file)
@@ -278,7 +278,7 @@ int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
        return 0;
 }
 
-int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx)
+int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
 {
        static const unsigned char pad[64] = { 0x80 };
        unsigned int padlen[2];
@@ -294,7 +294,7 @@ int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx)
 
        /* Output hash */
        for (i = 0; i < 5; i++)
-               put_be32(out->id + i*4, ctx->H[i]);
+               put_be32(out + i*4, ctx->H[i]);
 
        return 0;
 }
index 04e7da5facb58be68946f481cdb4f45cc58034a3..56016bec8e1f37a6fcbf4954ecac7b9ae1568240 100644 (file)
@@ -38,9 +38,9 @@ int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
        return 0;
 }
 
-int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx)
+int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
 {
        GIT_ASSERT_ARG(ctx);
-       mbedtls_sha1_finish(&ctx->c, out->id);
+       mbedtls_sha1_finish(&ctx->c, out);
        return 0;
 }
index 68d9611d4adf44caa597c5b65285c00ed5cbe01f..64bf99b3cb2817c394bd7ecf4fac9d3632ef614b 100644 (file)
@@ -46,11 +46,11 @@ int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
        return 0;
 }
 
-int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx)
+int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
 {
        GIT_ASSERT_ARG(ctx);
 
-       if (SHA1_Final(out->id, &ctx->c) != 1) {
+       if (SHA1_Final(out, &ctx->c) != 1) {
                git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to finalize hash");
                return -1;
        }
index 4d03c75d8c24510f5698256fca2ccc5ced673ef2..929822728a3ec2896904330826ba49c09b780822 100644 (file)
@@ -70,7 +70,7 @@
 /* Not under GCC-alike or glibc */
 #elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
 /*
- * *BSD and newlib (embeded linux, cygwin, etc).
+ * *BSD and newlib (embedded linux, cygwin, etc).
  * the defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN) part prevents
  * this condition from matching with Solaris/sparc.
  * (Solaris defines only one endian macro)
index a6e7061c6ac605849d102a39c6db392285992d07..b89dfbad87d7a7fa97c564dbd8cfb0b05322340a 100644 (file)
@@ -181,14 +181,14 @@ GIT_INLINE(int) hash_cryptoapi_update(git_hash_sha1_ctx *ctx, const void *_data,
        return 0;
 }
 
-GIT_INLINE(int) hash_cryptoapi_final(git_oid *out, git_hash_sha1_ctx *ctx)
+GIT_INLINE(int) hash_cryptoapi_final(unsigned char *out, git_hash_sha1_ctx *ctx)
 {
-       DWORD len = 20;
+       DWORD len = GIT_HASH_SHA1_SIZE;
        int error = 0;
 
        GIT_ASSERT(ctx->ctx.cryptoapi.valid);
 
-       if (!CryptGetHashParam(ctx->ctx.cryptoapi.hash_handle, HP_HASHVAL, out->id, &len, 0)) {
+       if (!CryptGetHashParam(ctx->ctx.cryptoapi.hash_handle, HP_HASHVAL, out, &len, 0)) {
                git_error_set(GIT_ERROR_OS, "legacy hash data could not be finished");
                error = -1;
        }
@@ -262,9 +262,9 @@ GIT_INLINE(int) hash_cng_update(git_hash_sha1_ctx *ctx, const void *_data, size_
        return 0;
 }
 
-GIT_INLINE(int) hash_cng_final(git_oid *out, git_hash_sha1_ctx *ctx)
+GIT_INLINE(int) hash_cng_final(unsigned char *out, git_hash_sha1_ctx *ctx)
 {
-       if (ctx->prov->prov.cng.finish_hash(ctx->ctx.cng.hash_handle, out->id, GIT_OID_RAWSZ, 0) < 0) {
+       if (ctx->prov->prov.cng.finish_hash(ctx->ctx.cng.hash_handle, out, GIT_HASH_SHA1_SIZE, 0) < 0) {
                git_error_set(GIT_ERROR_OS, "hash could not be finished");
                return -1;
        }
@@ -315,7 +315,7 @@ int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
        return (ctx->type == CNG) ? hash_cng_update(ctx, data, len) : hash_cryptoapi_update(ctx, data, len);
 }
 
-int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx)
+int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
 {
        GIT_ASSERT_ARG(ctx);
        GIT_ASSERT_ARG(ctx->type);
index e5aab80ed1e35f944dcd9daab3b6aa12c5de1221..53095864ee9c3e0f4a4d53b7aa8b6403bfc59d20 100644 (file)
@@ -9,7 +9,7 @@
 
 #include "git2/sys/filter.h"
 #include "filter.h"
-#include "buffer.h"
+#include "str.h"
 
 static int ident_find_id(
        const char **id_start, const char **id_end, const char *start, size_t len)
@@ -40,7 +40,7 @@ static int ident_find_id(
 }
 
 static int ident_insert_id(
-       git_buf *to, const git_buf *from, const git_filter_source *src)
+       git_str *to, const git_str *from, const git_filter_source *src)
 {
        char oid[GIT_OID_HEXSZ+1];
        const char *id_start, *id_end, *from_end = from->ptr + from->size;
@@ -60,20 +60,20 @@ static int ident_insert_id(
                5 /* "$Id: " */ + GIT_OID_HEXSZ + 2 /* " $" */ +
                (size_t)(from_end - id_end);
 
-       if (git_buf_grow(to, need_size) < 0)
+       if (git_str_grow(to, need_size) < 0)
                return -1;
 
-       git_buf_set(to, from->ptr, (size_t)(id_start - from->ptr));
-       git_buf_put(to, "$Id: ", 5);
-       git_buf_put(to, oid, GIT_OID_HEXSZ);
-       git_buf_put(to, " $", 2);
-       git_buf_put(to, id_end, (size_t)(from_end - id_end));
+       git_str_set(to, from->ptr, (size_t)(id_start - from->ptr));
+       git_str_put(to, "$Id: ", 5);
+       git_str_put(to, oid, GIT_OID_HEXSZ);
+       git_str_put(to, " $", 2);
+       git_str_put(to, id_end, (size_t)(from_end - id_end));
 
-       return git_buf_oom(to) ? -1 : 0;
+       return git_str_oom(to) ? -1 : 0;
 }
 
 static int ident_remove_id(
-       git_buf *to, const git_buf *from)
+       git_str *to, const git_str *from)
 {
        const char *id_start, *id_end, *from_end = from->ptr + from->size;
        size_t need_size;
@@ -84,27 +84,27 @@ static int ident_remove_id(
        need_size = (size_t)(id_start - from->ptr) +
                4 /* "$Id$" */ + (size_t)(from_end - id_end);
 
-       if (git_buf_grow(to, need_size) < 0)
+       if (git_str_grow(to, need_size) < 0)
                return -1;
 
-       git_buf_set(to, from->ptr, (size_t)(id_start - from->ptr));
-       git_buf_put(to, "$Id$", 4);
-       git_buf_put(to, id_end, (size_t)(from_end - id_end));
+       git_str_set(to, from->ptr, (size_t)(id_start - from->ptr));
+       git_str_put(to, "$Id$", 4);
+       git_str_put(to, id_end, (size_t)(from_end - id_end));
 
-       return git_buf_oom(to) ? -1 : 0;
+       return git_str_oom(to) ? -1 : 0;
 }
 
 static int ident_apply(
        git_filter     *self,
        void          **payload,
-       git_buf        *to,
-       const git_buf  *from,
+       git_str        *to,
+       const git_str  *from,
        const git_filter_source *src)
 {
        GIT_UNUSED(self); GIT_UNUSED(payload);
 
        /* Don't filter binary files */
-       if (git_buf_is_binary(from))
+       if (git_str_is_binary(from))
                return GIT_PASSTHROUGH;
 
        if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE)
index 9ead96ba67ef46eaba4a4fbfdd12147e64e33290..cee58d7f15f01ddd0131e76114049b944ce457ee 100644 (file)
 #include "git2/ignore.h"
 #include "common.h"
 #include "attrcache.h"
-#include "path.h"
+#include "fs_path.h"
 #include "config.h"
 #include "wildmatch.h"
+#include "path.h"
 
 #define GIT_IGNORE_INTERNAL            "[internal]exclude"
 
@@ -105,7 +106,7 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
        size_t i;
        git_attr_fnmatch *rule;
        char *path;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        *out = 0;
 
@@ -115,12 +116,12 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
 
        /* path of the file relative to the workdir, so we match the rules in subdirs */
        if (match->containing_dir) {
-               git_buf_puts(&buf, match->containing_dir);
+               git_str_puts(&buf, match->containing_dir);
        }
-       if (git_buf_puts(&buf, match->pattern) < 0)
+       if (git_str_puts(&buf, match->pattern) < 0)
                return -1;
 
-       path = git_buf_detach(&buf);
+       path = git_str_detach(&buf);
 
        git_vector_foreach(rules, i, rule) {
                if (!(rule->flags & GIT_ATTR_FNMATCH_HASWILD)) {
@@ -133,12 +134,12 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
                                continue;
                }
 
-               git_buf_clear(&buf);
+               git_str_clear(&buf);
                if (rule->containing_dir)
-                       git_buf_puts(&buf, rule->containing_dir);
-               git_buf_puts(&buf, rule->pattern);
+                       git_str_puts(&buf, rule->containing_dir);
+               git_str_puts(&buf, rule->pattern);
 
-               if (git_buf_oom(&buf))
+               if (git_str_oom(&buf))
                        goto out;
 
                /*
@@ -151,7 +152,7 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
                        effective_flags &= ~WM_PATHNAME;
 
                /* if we found a match, we want to keep this rule */
-               if ((wildmatch(git_buf_cstr(&buf), path, effective_flags)) == WM_MATCH) {
+               if ((wildmatch(git_str_cstr(&buf), path, effective_flags)) == WM_MATCH) {
                        *out = 1;
                        error = 0;
                        goto out;
@@ -162,7 +163,7 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
 
 out:
        git__free(path);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
@@ -181,7 +182,7 @@ static int parse_ignore_file(
 
        /* if subdir file path, convert context for file paths */
        if (attrs->entry &&
-               git_path_root(attrs->entry->path) < 0 &&
+               git_fs_path_root(attrs->entry->path) < 0 &&
                !git__suffixcmp(attrs->entry->path, "/" GIT_IGNORE_FILE))
                context = attrs->entry->path;
 
@@ -295,7 +296,7 @@ int git_ignore__for_path(
 {
        int error = 0;
        const char *workdir = git_repository_workdir(repo);
-       git_buf infopath = GIT_BUF_INIT;
+       git_str infopath = GIT_STR_INIT;
 
        GIT_ASSERT_ARG(repo);
        GIT_ASSERT_ARG(ignores);
@@ -313,21 +314,21 @@ int git_ignore__for_path(
                goto cleanup;
 
        /* given a unrooted path in a non-bare repo, resolve it */
-       if (workdir && git_path_root(path) < 0) {
-               git_buf local = GIT_BUF_INIT;
-
-               if ((error = git_path_dirname_r(&local, path)) < 0 ||
-                   (error = git_path_resolve_relative(&local, 0)) < 0 ||
-                   (error = git_path_to_dir(&local)) < 0 ||
-                   (error = git_buf_joinpath(&ignores->dir, workdir, local.ptr)) < 0 ||
-                   (error = git_path_validate_workdir_buf(repo, &ignores->dir)) < 0) {
+       if (workdir && git_fs_path_root(path) < 0) {
+               git_str local = GIT_STR_INIT;
+
+               if ((error = git_fs_path_dirname_r(&local, path)) < 0 ||
+                   (error = git_fs_path_resolve_relative(&local, 0)) < 0 ||
+                   (error = git_fs_path_to_dir(&local)) < 0 ||
+                   (error = git_str_joinpath(&ignores->dir, workdir, local.ptr)) < 0 ||
+                   (error = git_path_validate_str_length(repo, &ignores->dir)) < 0) {
                        /* Nothing, we just want to stop on the first error */
                }
 
-               git_buf_dispose(&local);
+               git_str_dispose(&local);
        } else {
-               if (!(error = git_buf_joinpath(&ignores->dir, path, "")))
-                   error = git_path_validate_filesystem(ignores->dir.ptr, ignores->dir.size);
+               if (!(error = git_str_joinpath(&ignores->dir, path, "")))
+                   error = git_path_validate_str_length(NULL, &ignores->dir);
        }
 
        if (error < 0)
@@ -342,14 +343,14 @@ int git_ignore__for_path(
 
        /* load .gitignore up the path */
        if (workdir != NULL) {
-               error = git_path_walk_up(
+               error = git_fs_path_walk_up(
                        &ignores->dir, workdir, push_one_ignore, ignores);
                if (error < 0)
                        goto cleanup;
        }
 
        /* load .git/info/exclude if possible */
-       if ((error = git_repository_item_path(&infopath, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 ||
+       if ((error = git_repository__item_path(&infopath, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 ||
                (error = push_ignore_file(ignores, &ignores->ign_global, infopath.ptr, GIT_IGNORE_FILE_INREPO)) < 0) {
                if (error != GIT_ENOTFOUND)
                        goto cleanup;
@@ -363,7 +364,7 @@ int git_ignore__for_path(
                        git_repository_attr_cache(repo)->cfg_excl_file);
 
 cleanup:
-       git_buf_dispose(&infopath);
+       git_str_dispose(&infopath);
        if (error < 0)
                git_ignore__free(ignores);
 
@@ -372,7 +373,7 @@ cleanup:
 
 int git_ignore__push_dir(git_ignores *ign, const char *dir)
 {
-       if (git_buf_joinpath(&ign->dir, ign->dir.ptr, dir) < 0)
+       if (git_str_joinpath(&ign->dir, ign->dir.ptr, dir) < 0)
                return -1;
 
        ign->depth++;
@@ -409,8 +410,8 @@ int git_ignore__pop_dir(git_ignores *ign)
        }
 
        if (--ign->depth > 0) {
-               git_buf_rtruncate_at_char(&ign->dir, '/');
-               git_path_to_dir(&ign->dir);
+               git_str_rtruncate_at_char(&ign->dir, '/');
+               git_fs_path_to_dir(&ign->dir);
        }
 
        return 0;
@@ -435,7 +436,7 @@ void git_ignore__free(git_ignores *ignores)
        }
        git_vector_free(&ignores->ign_global);
 
-       git_buf_dispose(&ignores->dir);
+       git_str_dispose(&ignores->dir);
 }
 
 static bool ignore_lookup_in_rules(
@@ -604,7 +605,7 @@ int git_ignore__check_pathspec_for_exact_ignores(
        size_t i;
        git_attr_fnmatch *match;
        int ignored;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        const char *filename;
        git_index *idx;
 
@@ -629,7 +630,7 @@ int git_ignore__check_pathspec_for_exact_ignores(
                        break;
 
                /* is there a file on disk that matches this exactly? */
-               if (!git_path_isfile(path.ptr))
+               if (!git_fs_path_isfile(path.ptr))
                        continue;
 
                /* is that file ignored? */
@@ -645,7 +646,7 @@ int git_ignore__check_pathspec_for_exact_ignores(
        }
 
        git_index_free(idx);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return error;
 }
index 5895d3faac930e886fdc0671b27bd75b6241e5c9..aa5ca62b7afae56364fceb8eada25138d6eb6974 100644 (file)
@@ -26,7 +26,7 @@
  */
 typedef struct {
        git_repository *repo;
-       git_buf dir; /* current directory reflected in ign_path */
+       git_str dir; /* current directory reflected in ign_path */
        git_attr_file *ign_internal;
        git_vector ign_path;
        git_vector ign_global;
@@ -48,7 +48,7 @@ enum {
        GIT_IGNORE_UNCHECKED = -2,
        GIT_IGNORE_NOTFOUND = -1,
        GIT_IGNORE_FALSE = 0,
-       GIT_IGNORE_TRUE = 1,
+       GIT_IGNORE_TRUE = 1
 };
 
 extern int git_ignore__lookup(int *out, git_ignores *ign, const char *path, git_dir_flag dir_flag);
index 5c3305170089424a2a4476a5eb11326d29e34726..aa97c642195b7d408efeb4611b7a819c8d1aaf85 100644 (file)
@@ -20,6 +20,7 @@
 #include "idxmap.h"
 #include "diff.h"
 #include "varint.h"
+#include "path.h"
 
 #include "git2/odb.h"
 #include "git2/oid.h"
@@ -33,7 +34,6 @@ static int index_apply_to_wd_diff(git_index *index, int action, const git_strarr
 
 #define minimal_entry_size (offsetof(struct entry_short, path))
 
-static const size_t INDEX_FOOTER_SIZE = GIT_OID_RAWSZ;
 static const size_t INDEX_HEADER_SIZE = 12;
 
 static const unsigned int INDEX_VERSION_NUMBER_DEFAULT = 2;
@@ -120,7 +120,7 @@ static int read_header(struct index_header *dest, const void *buffer);
 
 static int parse_index(git_index *index, const char *buffer, size_t buffer_size);
 static bool is_index_extended(git_index *index);
-static int write_index(git_oid *checksum, git_index *index, git_filebuf *file);
+static int write_index(unsigned char checksum[GIT_HASH_SHA1_SIZE], size_t *checksum_size, git_index *index, git_filebuf *file);
 
 static void index_entry_free(git_index_entry *entry);
 static void index_entry_reuc_free(git_index_reuc_entry *reuc);
@@ -420,7 +420,7 @@ int git_index_open(git_index **index_out, const char *index_path)
                        goto fail;
 
                /* Check if index file is stored on disk already */
-               if (git_path_exists(index->index_file_path) == true)
+               if (git_fs_path_exists(index->index_file_path) == true)
                        index->on_disk = 1;
        }
 
@@ -606,10 +606,12 @@ int git_index_caps(const git_index *index)
                        (index->no_symlinks ? GIT_INDEX_CAPABILITY_NO_SYMLINKS : 0));
 }
 
+#ifndef GIT_DEPRECATE_HARD
 const git_oid *git_index_checksum(git_index *index)
 {
-       return &index->checksum;
+       return (git_oid *)index->checksum;
 }
+#endif
 
 /**
  * Returns 1 for changed, 0 for not changed and <0 for errors
@@ -618,37 +620,38 @@ static int compare_checksum(git_index *index)
 {
        int fd;
        ssize_t bytes_read;
-       git_oid checksum = {{ 0 }};
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
+       size_t checksum_size = GIT_HASH_SHA1_SIZE;
 
        if ((fd = p_open(index->index_file_path, O_RDONLY)) < 0)
                return fd;
 
-       if (p_lseek(fd, -20, SEEK_END) < 0) {
+       if (p_lseek(fd, (0 - (ssize_t)checksum_size), SEEK_END) < 0) {
                p_close(fd);
                git_error_set(GIT_ERROR_OS, "failed to seek to end of file");
                return -1;
        }
 
-       bytes_read = p_read(fd, &checksum, GIT_OID_RAWSZ);
+       bytes_read = p_read(fd, checksum, checksum_size);
        p_close(fd);
 
-       if (bytes_read < 0)
+       if (bytes_read < (ssize_t)checksum_size)
                return -1;
 
-       return !!git_oid_cmp(&checksum, &index->checksum);
+       return !!memcmp(checksum, index->checksum, checksum_size);
 }
 
 int git_index_read(git_index *index, int force)
 {
        int error = 0, updated;
-       git_buf buffer = GIT_BUF_INIT;
+       git_str buffer = GIT_STR_INIT;
        git_futils_filestamp stamp = index->stamp;
 
        if (!index->index_file_path)
                return create_index_error(-1,
                        "failed to read index: The index is in-memory only");
 
-       index->on_disk = git_path_exists(index->index_file_path);
+       index->on_disk = git_fs_path_exists(index->index_file_path);
 
        if (!index->on_disk) {
                if (force && (error = git_index_clear(index)) < 0)
@@ -687,7 +690,7 @@ int git_index_read(git_index *index, int force)
                index->dirty = 0;
        }
 
-       git_buf_dispose(&buffer);
+       git_str_dispose(&buffer);
        return error;
 }
 
@@ -702,16 +705,6 @@ int git_index_read_safely(git_index *index)
        return git_index_read(index, false);
 }
 
-int git_index__changed_relative_to(
-       git_index *index, const git_oid *checksum)
-{
-       /* attempt to update index (ignoring errors) */
-       if (git_index_read(index, false) < 0)
-               git_error_clear();
-
-       return !!git_oid_cmp(&index->checksum, checksum);
-}
-
 static bool is_racy_entry(git_index *index, const git_index_entry *entry)
 {
        /* Git special-cases submodules in the check */
@@ -944,7 +937,7 @@ static int index_entry_create(
        if (st)
                mode = st->st_mode;
 
-       if (!git_path_validate(repo, path, mode, path_valid_flags)) {
+       if (!git_path_is_valid(repo, path, mode, path_valid_flags)) {
                git_error_set(GIT_ERROR_INDEX, "invalid path: '%s'", path);
                return -1;
        }
@@ -969,7 +962,7 @@ static int index_entry_init(
 {
        int error = 0;
        git_index_entry *entry = NULL;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        struct stat st;
        git_oid oid;
        git_repository *repo;
@@ -991,8 +984,8 @@ static int index_entry_init(
        if (git_repository_workdir_path(&path, repo, rel_path) < 0)
                return -1;
 
-       error = git_path_lstat(path.ptr, &st);
-       git_buf_dispose(&path);
+       error = git_fs_path_lstat(path.ptr, &st);
+       git_str_dispose(&path);
 
        if (error < 0)
                return error;
@@ -1525,7 +1518,7 @@ int git_index_add_from_buffer(
 static int add_repo_as_submodule(git_index_entry **out, git_index *index, const char *path)
 {
        git_repository *sub;
-       git_buf abspath = GIT_BUF_INIT;
+       git_str abspath = GIT_STR_INIT;
        git_repository *repo = INDEX_OWNER(index);
        git_reference *head;
        git_index_entry *entry;
@@ -1556,7 +1549,7 @@ static int add_repo_as_submodule(git_index_entry **out, git_index *index, const
 
        git_reference_free(head);
        git_repository_free(sub);
-       git_buf_dispose(&abspath);
+       git_str_dispose(&abspath);
 
        *out = entry;
        return 0;
@@ -1722,13 +1715,13 @@ int git_index_remove(git_index *index, const char *path, int stage)
 
 int git_index_remove_directory(git_index *index, const char *dir, int stage)
 {
-       git_buf pfx = GIT_BUF_INIT;
+       git_str pfx = GIT_STR_INIT;
        int error = 0;
        size_t pos;
        git_index_entry *entry;
 
-       if (!(error = git_buf_sets(&pfx, dir)) &&
-               !(error = git_path_to_dir(&pfx)))
+       if (!(error = git_str_sets(&pfx, dir)) &&
+               !(error = git_fs_path_to_dir(&pfx)))
                index_find(&pos, index, pfx.ptr, pfx.size, GIT_INDEX_STAGE_ANY);
 
        while (!error) {
@@ -1746,7 +1739,7 @@ int git_index_remove_directory(git_index *index, const char *dir, int stage)
                /* removed entry at 'pos' so we don't need to increment */
        }
 
-       git_buf_dispose(&pfx);
+       git_str_dispose(&pfx);
 
        return error;
 }
@@ -2469,8 +2462,9 @@ static int read_entry(
        git_index_entry entry = {{0}};
        bool compressed = index->version >= INDEX_VERSION_NUMBER_COMP;
        char *tmp_path = NULL;
+       size_t checksum_size = GIT_HASH_SHA1_SIZE;
 
-       if (INDEX_FOOTER_SIZE + minimal_entry_size > buffer_size)
+       if (checksum_size + minimal_entry_size > buffer_size)
                return -1;
 
        /* buffer is not guaranteed to be aligned */
@@ -2551,7 +2545,7 @@ static int read_entry(
        if (entry_size == 0)
                return -1;
 
-       if (INDEX_FOOTER_SIZE + entry_size > buffer_size)
+       if (checksum_size + entry_size > buffer_size)
                return -1;
 
        if (index_entry_dup(out, index, &entry) < 0) {
@@ -2585,6 +2579,7 @@ static int read_extension(size_t *read_len, git_index *index, const char *buffer
 {
        struct index_extension dest;
        size_t total_size;
+       size_t checksum_size = GIT_HASH_SHA1_SIZE;
 
        /* buffer is not guaranteed to be aligned */
        memcpy(&dest, buffer, sizeof(struct index_extension));
@@ -2594,7 +2589,7 @@ static int read_extension(size_t *read_len, git_index *index, const char *buffer
 
        if (dest.extension_size > total_size ||
                buffer_size < total_size ||
-               buffer_size - total_size < INDEX_FOOTER_SIZE) {
+               buffer_size - total_size < checksum_size) {
                index_error_invalid("extension is truncated");
                return -1;
        }
@@ -2631,7 +2626,8 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
        int error = 0;
        unsigned int i;
        struct index_header header = { 0 };
-       git_oid checksum_calculated, checksum_expected;
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
+       size_t checksum_size = GIT_HASH_SHA1_SIZE;
        const char *last = NULL;
        const char *empty = "";
 
@@ -2643,12 +2639,12 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
        buffer_size -= _increase;\
 }
 
-       if (buffer_size < INDEX_HEADER_SIZE + INDEX_FOOTER_SIZE)
+       if (buffer_size < INDEX_HEADER_SIZE + checksum_size)
                return index_error_invalid("insufficient buffer space");
 
        /* Precalculate the SHA1 of the files's contents -- we'll match it to
         * the provided SHA1 in the footer */
-       git_hash_buf(&checksum_calculated, buffer, buffer_size - INDEX_FOOTER_SIZE);
+       git_hash_buf(checksum, buffer, buffer_size - checksum_size, GIT_HASH_ALGORITHM_SHA1);
 
        /* Parse header */
        if ((error = read_header(&header, buffer)) < 0)
@@ -2666,7 +2662,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
                return error;
 
        /* Parse all the entries */
-       for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) {
+       for (i = 0; i < header.entry_count && buffer_size > checksum_size; ++i) {
                git_index_entry *entry = NULL;
                size_t entry_size;
 
@@ -2698,7 +2694,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
        }
 
        /* There's still space for some extensions! */
-       while (buffer_size > INDEX_FOOTER_SIZE) {
+       while (buffer_size > checksum_size) {
                size_t extension_size;
 
                if ((error = read_extension(&extension_size, index, buffer, buffer_size)) < 0) {
@@ -2708,22 +2704,20 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
                seek_forward(extension_size);
        }
 
-       if (buffer_size != INDEX_FOOTER_SIZE) {
+       if (buffer_size != checksum_size) {
                error = index_error_invalid(
                        "buffer size does not match index footer size");
                goto done;
        }
 
        /* 160-bit SHA-1 over the content of the index file before this checksum. */
-       git_oid_fromraw(&checksum_expected, (const unsigned char *)buffer);
-
-       if (git_oid__cmp(&checksum_calculated, &checksum_expected) != 0) {
+       if (memcmp(checksum, buffer, checksum_size) != 0) {
                error = index_error_invalid(
                        "calculated checksum does not match expected");
                goto done;
        }
 
-       git_oid_cpy(&index->checksum, &checksum_calculated);
+       memcpy(index->checksum, checksum, checksum_size);
 
 #undef seek_forward
 
@@ -2892,7 +2886,7 @@ done:
        return error;
 }
 
-static int write_extension(git_filebuf *file, struct index_extension *header, git_buf *data)
+static int write_extension(git_filebuf *file, struct index_extension *header, git_str *data)
 {
        struct index_extension ondisk;
 
@@ -2904,30 +2898,30 @@ static int write_extension(git_filebuf *file, struct index_extension *header, gi
        return git_filebuf_write(file, data->ptr, data->size);
 }
 
-static int create_name_extension_data(git_buf *name_buf, git_index_name_entry *conflict_name)
+static int create_name_extension_data(git_str *name_buf, git_index_name_entry *conflict_name)
 {
        int error = 0;
 
        if (conflict_name->ancestor == NULL)
-               error = git_buf_put(name_buf, "\0", 1);
+               error = git_str_put(name_buf, "\0", 1);
        else
-               error = git_buf_put(name_buf, conflict_name->ancestor, strlen(conflict_name->ancestor) + 1);
+               error = git_str_put(name_buf, conflict_name->ancestor, strlen(conflict_name->ancestor) + 1);
 
        if (error != 0)
                goto on_error;
 
        if (conflict_name->ours == NULL)
-               error = git_buf_put(name_buf, "\0", 1);
+               error = git_str_put(name_buf, "\0", 1);
        else
-               error = git_buf_put(name_buf, conflict_name->ours, strlen(conflict_name->ours) + 1);
+               error = git_str_put(name_buf, conflict_name->ours, strlen(conflict_name->ours) + 1);
 
        if (error != 0)
                goto on_error;
 
        if (conflict_name->theirs == NULL)
-               error = git_buf_put(name_buf, "\0", 1);
+               error = git_str_put(name_buf, "\0", 1);
        else
-               error = git_buf_put(name_buf, conflict_name->theirs, strlen(conflict_name->theirs) + 1);
+               error = git_str_put(name_buf, conflict_name->theirs, strlen(conflict_name->theirs) + 1);
 
 on_error:
        return error;
@@ -2935,7 +2929,7 @@ on_error:
 
 static int write_name_extension(git_index *index, git_filebuf *file)
 {
-       git_buf name_buf = GIT_BUF_INIT;
+       git_str name_buf = GIT_STR_INIT;
        git_vector *out = &index->names;
        git_index_name_entry *conflict_name;
        struct index_extension extension;
@@ -2953,28 +2947,28 @@ static int write_name_extension(git_index *index, git_filebuf *file)
 
        error = write_extension(file, &extension, &name_buf);
 
-       git_buf_dispose(&name_buf);
+       git_str_dispose(&name_buf);
 
 done:
        return error;
 }
 
-static int create_reuc_extension_data(git_buf *reuc_buf, git_index_reuc_entry *reuc)
+static int create_reuc_extension_data(git_str *reuc_buf, git_index_reuc_entry *reuc)
 {
        int i;
        int error = 0;
 
-       if ((error = git_buf_put(reuc_buf, reuc->path, strlen(reuc->path) + 1)) < 0)
+       if ((error = git_str_put(reuc_buf, reuc->path, strlen(reuc->path) + 1)) < 0)
                return error;
 
        for (i = 0; i < 3; i++) {
-               if ((error = git_buf_printf(reuc_buf, "%o", reuc->mode[i])) < 0 ||
-                       (error = git_buf_put(reuc_buf, "\0", 1)) < 0)
+               if ((error = git_str_printf(reuc_buf, "%o", reuc->mode[i])) < 0 ||
+                       (error = git_str_put(reuc_buf, "\0", 1)) < 0)
                        return error;
        }
 
        for (i = 0; i < 3; i++) {
-               if (reuc->mode[i] && (error = git_buf_put(reuc_buf, (char *)&reuc->oid[i].id, GIT_OID_RAWSZ)) < 0)
+               if (reuc->mode[i] && (error = git_str_put(reuc_buf, (char *)&reuc->oid[i].id, GIT_OID_RAWSZ)) < 0)
                        return error;
        }
 
@@ -2983,7 +2977,7 @@ static int create_reuc_extension_data(git_buf *reuc_buf, git_index_reuc_entry *r
 
 static int write_reuc_extension(git_index *index, git_filebuf *file)
 {
-       git_buf reuc_buf = GIT_BUF_INIT;
+       git_str reuc_buf = GIT_STR_INIT;
        git_vector *out = &index->reuc;
        git_index_reuc_entry *reuc;
        struct index_extension extension;
@@ -3001,7 +2995,7 @@ static int write_reuc_extension(git_index *index, git_filebuf *file)
 
        error = write_extension(file, &extension, &reuc_buf);
 
-       git_buf_dispose(&reuc_buf);
+       git_str_dispose(&reuc_buf);
 
 done:
        return error;
@@ -3010,7 +3004,7 @@ done:
 static int write_tree_extension(git_index *index, git_filebuf *file)
 {
        struct index_extension extension;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        int error;
 
        if (index->tree == NULL)
@@ -3025,7 +3019,7 @@ static int write_tree_extension(git_index *index, git_filebuf *file)
 
        error = write_extension(file, &extension, &buf);
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        return error;
 }
@@ -3039,9 +3033,12 @@ static void clear_uptodate(git_index *index)
                entry->flags_extended &= ~GIT_INDEX_ENTRY_UPTODATE;
 }
 
-static int write_index(git_oid *checksum, git_index *index, git_filebuf *file)
+static int write_index(
+       unsigned char checksum[GIT_HASH_SHA1_SIZE],
+       size_t *checksum_size,
+       git_index *index,
+       git_filebuf *file)
 {
-       git_oid hash_final;
        struct index_header header;
        bool is_extended;
        uint32_t index_version_number;
@@ -3049,6 +3046,8 @@ static int write_index(git_oid *checksum, git_index *index, git_filebuf *file)
        GIT_ASSERT_ARG(index);
        GIT_ASSERT_ARG(file);
 
+       *checksum_size = GIT_HASH_SHA1_SIZE;
+
        if (index->version <= INDEX_VERSION_NUMBER_EXT)  {
                is_extended = is_index_extended(index);
                index_version_number = is_extended ? INDEX_VERSION_NUMBER_EXT : INDEX_VERSION_NUMBER_LB;
@@ -3079,11 +3078,10 @@ static int write_index(git_oid *checksum, git_index *index, git_filebuf *file)
                return -1;
 
        /* get out the hash for all the contents we've appended to the file */
-       git_filebuf_hash(&hash_final, file);
-       git_oid_cpy(checksum, &hash_final);
+       git_filebuf_hash(checksum, file);
 
        /* write it at the end of the file */
-       if (git_filebuf_write(file, hash_final.id, GIT_OID_RAWSZ) < 0)
+       if (git_filebuf_write(file, checksum, *checksum_size) < 0)
                return -1;
 
        /* file entries are no longer up to date */
@@ -3115,13 +3113,13 @@ static int read_tree_cb(
 {
        read_tree_data *data = payload;
        git_index_entry *entry = NULL, *old_entry;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        size_t pos;
 
        if (git_tree_entry__is_tree(tentry))
                return 0;
 
-       if (git_buf_joinpath(&path, root, tentry->filename) < 0)
+       if (git_str_joinpath(&path, root, tentry->filename) < 0)
                return -1;
 
        if (index_entry_create(&entry, INDEX_OWNER(data->index), path.ptr, NULL, false) < 0)
@@ -3143,7 +3141,7 @@ static int read_tree_cb(
        }
 
        index_entry_adjust_namemask(entry, path.size);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        if (git_vector_insert(data->new_entries, entry) < 0) {
                index_entry_free(entry);
@@ -3385,7 +3383,7 @@ enum {
        INDEX_ACTION_NONE = 0,
        INDEX_ACTION_UPDATE = 1,
        INDEX_ACTION_REMOVE = 2,
-       INDEX_ACTION_ADDALL = 3,
+       INDEX_ACTION_ADDALL = 3
 };
 
 int git_index_add_all(
@@ -3498,7 +3496,7 @@ static int index_apply_to_wd_diff(git_index *index, int action, const git_strarr
        }
 
        /*
-        * We do the matching ourselves intead of passing the list to
+        * We do the matching ourselves instead of passing the list to
         * diff because we want to tell the callback which one
         * matched, which we do not know if we ask diff to filter for us.
         */
@@ -3540,7 +3538,7 @@ static int index_apply_to_all(
        size_t i;
        git_pathspec ps;
        const char *match;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        GIT_ASSERT_ARG(index);
 
@@ -3569,7 +3567,7 @@ static int index_apply_to_all(
                }
 
                /* index manipulation may alter entry, so don't depend on it */
-               if ((error = git_buf_sets(&path, entry->path)) < 0)
+               if ((error = git_str_sets(&path, entry->path)) < 0)
                        break;
 
                switch (action) {
@@ -3598,7 +3596,7 @@ static int index_apply_to_all(
                }
        }
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_pathspec__clear(&ps);
 
        return error;
@@ -3713,8 +3711,9 @@ int git_indexwriter_init_for_operation(
 
 int git_indexwriter_commit(git_indexwriter *writer)
 {
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
+       size_t checksum_size;
        int error;
-       git_oid checksum = {{ 0 }};
 
        if (!writer->should_write)
                return 0;
@@ -3722,7 +3721,7 @@ int git_indexwriter_commit(git_indexwriter *writer)
        git_vector_sort(&writer->index->entries);
        git_vector_sort(&writer->index->reuc);
 
-       if ((error = write_index(&checksum, writer->index, &writer->file)) < 0) {
+       if ((error = write_index(checksum, &checksum_size, writer->index, &writer->file)) < 0) {
                git_indexwriter_cleanup(writer);
                return error;
        }
@@ -3738,7 +3737,7 @@ int git_indexwriter_commit(git_indexwriter *writer)
 
        writer->index->dirty = 0;
        writer->index->on_disk = 1;
-       git_oid_cpy(&writer->index->checksum, &checksum);
+       memcpy(writer->index->checksum, checksum, checksum_size);
 
        git_index_free(writer->index);
        writer->index = NULL;
index a365867d0bf6cb9dbc8c148d1cef259dc9cac213..71bb096f738e06599055ddfbf2fc13a2e11965e0 100644 (file)
@@ -27,7 +27,7 @@ struct git_index {
 
        char *index_file_path;
        git_futils_filestamp stamp;
-       git_oid checksum;   /* checksum at the end of the file */
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
 
        git_vector entries;
        git_idxmap *entries_map;
@@ -133,10 +133,13 @@ extern unsigned int git_index__create_mode(unsigned int mode);
 
 GIT_INLINE(const git_futils_filestamp *) git_index__filestamp(git_index *index)
 {
-   return &index->stamp;
+       return &index->stamp;
 }
 
-extern int git_index__changed_relative_to(git_index *index, const git_oid *checksum);
+GIT_INLINE(unsigned char *) git_index__checksum(git_index *index)
+{
+       return index->checksum;
+}
 
 /* Copy the current entries vector *and* increment the index refcount.
  * Call `git_index__release_snapshot` when done.
index ce77375007c75909227c6d5de27e6c0e2fece199..f9a32e7ac64115a7c63beb5ab1f13c1cda02e7af 100644 (file)
@@ -48,14 +48,15 @@ struct git_indexer {
        off64_t off;
        off64_t entry_start;
        git_object_t entry_type;
-       git_buf entry_data;
+       git_str entry_data;
        git_packfile_stream stream;
        size_t nr_objects;
        git_vector objects;
        git_vector deltas;
        unsigned int fanout[256];
        git_hash_ctx hash_ctx;
-       git_oid hash;
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
+       char name[(GIT_HASH_SHA1_SIZE * 2) + 1];
        git_indexer_progress_cb progress_cb;
        void *progress_payload;
        char objbuf[8*1024];
@@ -76,9 +77,16 @@ struct delta_info {
        off64_t delta_off;
 };
 
+#ifndef GIT_DEPRECATE_HARD
 const git_oid *git_indexer_hash(const git_indexer *idx)
 {
-       return &idx->hash;
+       return (git_oid *)idx->checksum;
+}
+#endif
+
+const char *git_indexer_name(const git_indexer *idx)
+{
+       return idx->name;
 }
 
 static int parse_header(struct git_pack_header *hdr, struct git_pack_file *pack)
@@ -137,7 +145,7 @@ int git_indexer_new(
 {
        git_indexer_options opts = GIT_INDEXER_OPTIONS_INIT;
        git_indexer *idx;
-       git_buf path = GIT_BUF_INIT, tmp_path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT, tmp_path = GIT_STR_INIT;
        static const char suff[] = "/pack";
        int error, fd = -1;
 
@@ -150,10 +158,10 @@ int git_indexer_new(
        idx->progress_cb = opts.progress_cb;
        idx->progress_payload = opts.progress_cb_payload;
        idx->mode = mode ? mode : GIT_PACK_FILE_MODE;
-       git_buf_init(&idx->entry_data, 0);
+       git_str_init(&idx->entry_data, 0);
 
-       if ((error = git_hash_ctx_init(&idx->hash_ctx)) < 0 ||
-           (error = git_hash_ctx_init(&idx->trailer)) < 0 ||
+       if ((error = git_hash_ctx_init(&idx->hash_ctx, GIT_HASH_ALGORITHM_SHA1)) < 0 ||
+           (error = git_hash_ctx_init(&idx->trailer, GIT_HASH_ALGORITHM_SHA1)) < 0 ||
            (error = git_oidmap_new(&idx->expected_oids)) < 0)
                goto cleanup;
 
@@ -162,17 +170,17 @@ int git_indexer_new(
        if (git_repository__fsync_gitdir)
                idx->do_fsync = 1;
 
-       error = git_buf_joinpath(&path, prefix, suff);
+       error = git_str_joinpath(&path, prefix, suff);
        if (error < 0)
                goto cleanup;
 
-       fd = git_futils_mktmp(&tmp_path, git_buf_cstr(&path), idx->mode);
-       git_buf_dispose(&path);
+       fd = git_futils_mktmp(&tmp_path, git_str_cstr(&path), idx->mode);
+       git_str_dispose(&path);
        if (fd < 0)
                goto cleanup;
 
-       error = git_packfile_alloc(&idx->pack, git_buf_cstr(&tmp_path));
-       git_buf_dispose(&tmp_path);
+       error = git_packfile_alloc(&idx->pack, git_str_cstr(&tmp_path));
+       git_str_dispose(&tmp_path);
 
        if (error < 0)
                goto cleanup;
@@ -188,14 +196,14 @@ cleanup:
        if (fd != -1)
                p_close(fd);
 
-       if (git_buf_len(&tmp_path) > 0)
-               p_unlink(git_buf_cstr(&tmp_path));
+       if (git_str_len(&tmp_path) > 0)
+               p_unlink(git_str_cstr(&tmp_path));
 
        if (idx->pack != NULL)
                p_unlink(idx->pack->pack_name);
 
-       git_buf_dispose(&path);
-       git_buf_dispose(&tmp_path);
+       git_str_dispose(&path);
+       git_str_dispose(&tmp_path);
        git__free(idx);
        return -1;
 }
@@ -245,7 +253,7 @@ static int hash_object_stream(git_indexer*idx, git_packfile_stream *stream)
                        break;
 
                if (idx->do_verify)
-                       git_buf_put(&idx->entry_data, idx->objbuf, read);
+                       git_str_put(&idx->entry_data, idx->objbuf, read);
 
                git_hash_update(&idx->hash_ctx, idx->objbuf, read);
        } while (read > 0);
@@ -340,7 +348,7 @@ static int check_object_connectivity(git_indexer *idx, const git_rawobj *obj)
 {
        git_object *object;
        git_oid *expected;
-       int error;
+       int error = 0;
 
        if (obj->type != GIT_OBJECT_BLOB &&
            obj->type != GIT_OBJECT_TREE &&
@@ -348,8 +356,14 @@ static int check_object_connectivity(git_indexer *idx, const git_rawobj *obj)
            obj->type != GIT_OBJECT_TAG)
                return 0;
 
-       if ((error = git_object__from_raw(&object, obj->data, obj->len, obj->type)) < 0)
+       if (git_object__from_raw(&object, obj->data, obj->len, obj->type) < 0) {
+               /*
+                * parse_raw returns EINVALID on invalid data; downgrade
+                * that to a normal -1 error code.
+                */
+               error = -1;
                goto out;
+       }
 
        if ((expected = git_oidmap_get(idx->expected_oids, &object->cached.oid)) != NULL) {
                git_oidmap_delete(idx->expected_oids, &object->cached.oid);
@@ -426,7 +440,7 @@ static int store_object(git_indexer *idx)
        pentry = git__calloc(1, sizeof(struct git_pack_entry));
        GIT_ERROR_CHECK_ALLOC(pentry);
 
-       if (git_hash_final(&oid, &idx->hash_ctx)) {
+       if (git_hash_final(oid.id, &idx->hash_ctx)) {
                git__free(pentry);
                goto on_error;
        }
@@ -730,7 +744,7 @@ static int read_stream_object(git_indexer *idx, git_indexer_progress *stats)
                git_mwindow_close(&w);
                idx->entry_start = entry_start;
                git_hash_init(&idx->hash_ctx);
-               git_buf_clear(&idx->entry_data);
+               git_str_clear(&idx->entry_data);
 
                if (type == GIT_OBJECT_REF_DELTA || type == GIT_OBJECT_OFS_DELTA) {
                        error = advance_delta_offset(idx, type);
@@ -876,7 +890,7 @@ on_error:
        return error;
 }
 
-static int index_path(git_buf *path, git_indexer *idx, const char *suffix)
+static int index_path(git_str *path, git_indexer *idx, const char *suffix)
 {
        const char prefix[] = "pack-";
        size_t slash = (size_t)path->size;
@@ -885,17 +899,16 @@ static int index_path(git_buf *path, git_indexer *idx, const char *suffix)
        while (slash > 0 && path->ptr[slash - 1] != '/')
                slash--;
 
-       if (git_buf_grow(path, slash + 1 + strlen(prefix) +
+       if (git_str_grow(path, slash + 1 + strlen(prefix) +
                                         GIT_OID_HEXSZ + strlen(suffix) + 1) < 0)
                return -1;
 
-       git_buf_truncate(path, slash);
-       git_buf_puts(path, prefix);
-       git_oid_fmt(path->ptr + git_buf_len(path), &idx->hash);
-       path->size += GIT_OID_HEXSZ;
-       git_buf_puts(path, suffix);
+       git_str_truncate(path, slash);
+       git_str_puts(path, prefix);
+       git_str_puts(path, idx->name);
+       git_str_puts(path, suffix);
 
-       return git_buf_oom(path) ? -1 : 0;
+       return git_str_oom(path) ? -1 : 0;
 }
 
 /**
@@ -913,12 +926,13 @@ static int inject_object(git_indexer *idx, git_oid *id)
        git_odb_object *obj = NULL;
        struct entry *entry = NULL;
        struct git_pack_entry *pentry = NULL;
-       git_oid foo = {{0}};
+       unsigned char empty_checksum[GIT_HASH_SHA1_SIZE] = {0};
        unsigned char hdr[64];
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        off64_t entry_start;
        const void *data;
        size_t len, hdr_len;
+       size_t checksum_size = GIT_HASH_SHA1_SIZE;
        int error;
 
        if ((error = seek_back_trailer(idx)) < 0)
@@ -956,11 +970,11 @@ static int inject_object(git_indexer *idx, git_oid *id)
 
        idx->pack->mwf.size += buf.size;
        entry->crc = htonl(crc32(entry->crc, (unsigned char *)buf.ptr, (uInt)buf.size));
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        /* Write a fake trailer so the pack functions play ball */
 
-       if ((error = append_to_pack(idx, &foo, GIT_OID_RAWSZ)) < 0)
+       if ((error = append_to_pack(idx, empty_checksum, checksum_size)) < 0)
                goto cleanup;
 
        idx->pack->mwf.size += GIT_OID_RAWSZ;
@@ -1117,7 +1131,7 @@ static int update_header_and_rehash(git_indexer *idx, git_indexer_progress *stat
        git_hash_init(&idx->trailer);
 
 
-       /* Update the header to include the numer of local objects we injected */
+       /* Update the header to include the number of local objects we injected */
        idx->hdr.hdr_entries = htonl(stats->total_objects + stats->local_objects);
        if (write_at(idx, &idx->hdr, 0, sizeof(struct git_pack_header)) < 0)
                return -1;
@@ -1152,11 +1166,13 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
        unsigned int i, long_offsets = 0, left;
        int error;
        struct git_pack_idx_header hdr;
-       git_buf filename = GIT_BUF_INIT;
+       git_str filename = GIT_STR_INIT;
        struct entry *entry;
-       git_oid trailer_hash, file_hash;
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
        git_filebuf index_file = {0};
        void *packfile_trailer;
+       size_t checksum_size = GIT_HASH_SHA1_SIZE;
+       bool mismatch;
 
        if (!idx->parsed_header) {
                git_error_set(GIT_ERROR_INDEXER, "incomplete pack header");
@@ -1164,27 +1180,27 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
        }
 
        /* Test for this before resolve_deltas(), as it plays with idx->off */
-       if (idx->off + 20 < idx->pack->mwf.size) {
+       if (idx->off + (ssize_t)checksum_size < idx->pack->mwf.size) {
                git_error_set(GIT_ERROR_INDEXER, "unexpected data at the end of the pack");
                return -1;
        }
-       if (idx->off + 20 > idx->pack->mwf.size) {
+       if (idx->off + (ssize_t)checksum_size > idx->pack->mwf.size) {
                git_error_set(GIT_ERROR_INDEXER, "missing trailer at the end of the pack");
                return -1;
        }
 
-       packfile_trailer = git_mwindow_open(&idx->pack->mwf, &w, idx->pack->mwf.size - GIT_OID_RAWSZ, GIT_OID_RAWSZ, &left);
+       packfile_trailer = git_mwindow_open(&idx->pack->mwf, &w, idx->pack->mwf.size - checksum_size, checksum_size, &left);
        if (packfile_trailer == NULL) {
                git_mwindow_close(&w);
                goto on_error;
        }
 
        /* Compare the packfile trailer as it was sent to us and what we calculated */
-       git_oid_fromraw(&file_hash, packfile_trailer);
+       git_hash_final(checksum, &idx->trailer);
+       mismatch = !!memcmp(checksum, packfile_trailer, checksum_size);
        git_mwindow_close(&w);
 
-       git_hash_final(&trailer_hash, &idx->trailer);
-       if (git_oid_cmp(&file_hash, &trailer_hash)) {
+       if (mismatch) {
                git_error_set(GIT_ERROR_INDEXER, "packfile trailer mismatch");
                return -1;
        }
@@ -1204,8 +1220,8 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
                if (update_header_and_rehash(idx, stats) < 0)
                        return -1;
 
-               git_hash_final(&trailer_hash, &idx->trailer);
-               write_at(idx, &trailer_hash, idx->pack->mwf.size - GIT_OID_RAWSZ, GIT_OID_RAWSZ);
+               git_hash_final(checksum, &idx->trailer);
+               write_at(idx, checksum, idx->pack->mwf.size - checksum_size, checksum_size);
        }
 
        /*
@@ -1224,12 +1240,14 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
 
        /* Use the trailer hash as the pack file name to ensure
         * files with different contents have different names */
-       git_oid_cpy(&idx->hash, &trailer_hash);
+       memcpy(idx->checksum, checksum, checksum_size);
+       if (git_hash_fmt(idx->name, checksum, checksum_size) < 0)
+               return -1;
 
-       git_buf_sets(&filename, idx->pack->pack_name);
-       git_buf_shorten(&filename, strlen("pack"));
-       git_buf_puts(&filename, "idx");
-       if (git_buf_oom(&filename))
+       git_str_sets(&filename, idx->pack->pack_name);
+       git_str_shorten(&filename, strlen("pack"));
+       git_str_puts(&filename, "idx");
+       if (git_str_oom(&filename))
                return -1;
 
        if (git_filebuf_open(&index_file, filename.ptr,
@@ -1285,14 +1303,14 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
        }
 
        /* Write out the packfile trailer to the index */
-       if (git_filebuf_write(&index_file, &trailer_hash, GIT_OID_RAWSZ) < 0)
+       if (git_filebuf_write(&index_file, checksum, checksum_size) < 0)
                goto on_error;
 
        /* Write out the hash of the idx */
-       if (git_filebuf_hash(&trailer_hash, &index_file) < 0)
+       if (git_filebuf_hash(checksum, &index_file) < 0)
                goto on_error;
 
-       git_filebuf_write(&index_file, &trailer_hash, sizeof(git_oid));
+       git_filebuf_write(&index_file, checksum, checksum_size);
 
        /* Figure out what the final name should be */
        if (index_path(&filename, idx, ".idx") < 0)
@@ -1336,23 +1354,23 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
                goto on_error;
 
        /* And don't forget to rename the packfile to its new place. */
-       if (p_rename(idx->pack->pack_name, git_buf_cstr(&filename)) < 0)
+       if (p_rename(idx->pack->pack_name, git_str_cstr(&filename)) < 0)
                goto on_error;
 
        /* And fsync the parent directory if we're asked to. */
        if (idx->do_fsync &&
-               git_futils_fsync_parent(git_buf_cstr(&filename)) < 0)
+               git_futils_fsync_parent(git_str_cstr(&filename)) < 0)
                goto on_error;
 
        idx->pack_committed = 1;
 
-       git_buf_dispose(&filename);
+       git_str_dispose(&filename);
        return 0;
 
 on_error:
        git_mwindow_free_all(&idx->pack->mwf);
        git_filebuf_cleanup(&index_file);
-       git_buf_dispose(&filename);
+       git_str_dispose(&filename);
        return -1;
 }
 
@@ -1389,7 +1407,7 @@ void git_indexer_free(git_indexer *idx)
 
        git_hash_ctx_cleanup(&idx->trailer);
        git_hash_ctx_cleanup(&idx->hash_ctx);
-       git_buf_dispose(&idx->entry_data);
+       git_str_dispose(&idx->entry_data);
        git_oidmap_free(idx->expected_oids);
        git__free(idx);
 }
index ce9f305ef28c7519b6c5447f58c28d2eeeef2da4..15bb63dc83d2883e03a36564b05ae003459cfb75 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "tree.h"
 #include "index.h"
+#include "path.h"
 
 #define GIT_ITERATOR_FIRST_ACCESS   (1 << 15)
 #define GIT_ITERATOR_HONOR_IGNORES  (1 << 16)
@@ -292,7 +293,7 @@ typedef enum {
        ITERATOR_PATHLIST_IS_FILE = 1,
        ITERATOR_PATHLIST_IS_DIR = 2,
        ITERATOR_PATHLIST_IS_PARENT = 3,
-       ITERATOR_PATHLIST_FULL = 4,
+       ITERATOR_PATHLIST_FULL = 4
 } iterator_pathlist_search_t;
 
 static iterator_pathlist_search_t iterator_pathlist_search(
@@ -424,7 +425,7 @@ typedef struct {
        git_tree *tree;
 
        /* path to this particular frame (folder) */
-       git_buf path;
+       git_str path;
 
        /* a sorted list of the entries for this frame (folder), these are
         * actually pointers to the iterator's entry pool.
@@ -441,7 +442,7 @@ typedef struct {
         * parent path.
         */
        git_vector similar_trees;
-       git_array_t(git_buf) similar_paths;
+       git_array_t(git_str) similar_paths;
 } tree_iterator_frame;
 
 typedef struct {
@@ -450,7 +451,7 @@ typedef struct {
        git_array_t(tree_iterator_frame) frames;
 
        git_index_entry entry;
-       git_buf entry_path;
+       git_str entry_path;
 
        /* a pool of entries to reduce the number of allocations */
        git_pool entry_pool;
@@ -472,7 +473,7 @@ GIT_INLINE(tree_iterator_frame *) tree_iterator_current_frame(
 GIT_INLINE(int) tree_entry_cmp(
        const git_tree_entry *a, const git_tree_entry *b, bool icase)
 {
-       return git_path_cmp(
+       return git_fs_path_cmp(
                a->filename, a->filename_len, a->attr == GIT_FILEMODE_TREE,
                b->filename, b->filename_len, b->attr == GIT_FILEMODE_TREE,
                icase ? git__strncasecmp : git__strncmp);
@@ -508,20 +509,20 @@ static int tree_iterator_entry_sort_icase(const void *ptr_a, const void *ptr_b)
 }
 
 static int tree_iterator_compute_path(
-       git_buf *out,
+       git_str *out,
        tree_iterator_entry *entry)
 {
-       git_buf_clear(out);
+       git_str_clear(out);
 
        if (entry->parent_path)
-               git_buf_joinpath(out, entry->parent_path, entry->tree_entry->filename);
+               git_str_joinpath(out, entry->parent_path, entry->tree_entry->filename);
        else
-               git_buf_puts(out, entry->tree_entry->filename);
+               git_str_puts(out, entry->tree_entry->filename);
 
        if (git_tree_entry__is_tree(entry->tree_entry))
-               git_buf_putc(out, '/');
+               git_str_putc(out, '/');
 
-       if (git_buf_oom(out))
+       if (git_str_oom(out))
                return -1;
 
        return 0;
@@ -601,7 +602,7 @@ GIT_INLINE(int) tree_iterator_frame_push_neighbors(
        tree_iterator_entry *entry, *new_entry;
        git_tree *tree = NULL;
        git_tree_entry *tree_entry;
-       git_buf *path;
+       git_str *path;
        size_t new_size, i;
        int error = 0;
 
@@ -621,7 +622,7 @@ GIT_INLINE(int) tree_iterator_frame_push_neighbors(
                path = git_array_alloc(parent_frame->similar_paths);
                GIT_ERROR_CHECK_ALLOC(path);
 
-               memset(path, 0, sizeof(git_buf));
+               memset(path, 0, sizeof(git_str));
 
                if ((error = tree_iterator_compute_path(path, entry)) < 0)
                        break;
@@ -681,7 +682,7 @@ done:
 static int tree_iterator_frame_pop(tree_iterator *iter)
 {
        tree_iterator_frame *frame;
-       git_buf *buf = NULL;
+       git_str *buf = NULL;
        git_tree *tree;
        size_t i;
 
@@ -694,7 +695,7 @@ static int tree_iterator_frame_pop(tree_iterator *iter)
 
        do {
                buf = git_array_pop(frame->similar_paths);
-               git_buf_dispose(buf);
+               git_str_dispose(buf);
        } while (buf != NULL);
 
        git_array_clear(frame->similar_paths);
@@ -704,7 +705,7 @@ static int tree_iterator_frame_pop(tree_iterator *iter)
 
        git_vector_free(&frame->similar_trees);
 
-       git_buf_dispose(&frame->path);
+       git_str_dispose(&frame->path);
 
        return 0;
 }
@@ -892,7 +893,7 @@ static void tree_iterator_clear(tree_iterator *iter)
        git_array_clear(iter->frames);
 
        git_pool_clear(&iter->entry_pool);
-       git_buf_clear(&iter->entry_path);
+       git_str_clear(&iter->entry_path);
 
        iterator_clear(&iter->base);
 }
@@ -925,7 +926,7 @@ static void tree_iterator_free(git_iterator *i)
        tree_iterator_clear(iter);
 
        git_tree_free(iter->root);
-       git_buf_dispose(&iter->entry_path);
+       git_str_dispose(&iter->entry_path);
 }
 
 int git_iterator_for_tree(
@@ -1040,11 +1041,11 @@ typedef struct {
 
        /* info about the current entry */
        git_index_entry entry;
-       git_buf current_path;
+       git_str current_path;
        int current_is_ignored;
 
        /* temporary buffer for advance_over */
-       git_buf tmp_buf;
+       git_str tmp_buf;
 } filesystem_iterator;
 
 
@@ -1266,7 +1267,7 @@ static int filesystem_iterator_entry_hash(
        filesystem_iterator *iter,
        filesystem_iterator_entry *entry)
 {
-       git_buf fullpath = GIT_BUF_INIT;
+       git_str fullpath = GIT_STR_INIT;
        int error;
 
        if (S_ISDIR(entry->st.st_mode)) {
@@ -1278,11 +1279,11 @@ static int filesystem_iterator_entry_hash(
                return git_repository_hashfile(&entry->id,
                        iter->base.repo, entry->path, GIT_OBJECT_BLOB, NULL);
 
-       if (!(error = git_buf_joinpath(&fullpath, iter->root, entry->path)) &&
-           !(error = git_path_validate_workdir_buf(iter->base.repo, &fullpath)))
+       if (!(error = git_str_joinpath(&fullpath, iter->root, entry->path)) &&
+           !(error = git_path_validate_str_length(iter->base.repo, &fullpath)))
                error = git_odb_hashfile(&entry->id, fullpath.ptr, GIT_OBJECT_BLOB);
 
-       git_buf_dispose(&fullpath);
+       git_str_dispose(&fullpath);
        return error;
 }
 
@@ -1336,8 +1337,8 @@ static int filesystem_iterator_frame_push(
        filesystem_iterator_entry *frame_entry)
 {
        filesystem_iterator_frame *new_frame = NULL;
-       git_path_diriter diriter = GIT_PATH_DIRITER_INIT;
-       git_buf root = GIT_BUF_INIT;
+       git_fs_path_diriter diriter = GIT_FS_PATH_DIRITER_INIT;
+       git_str root = GIT_STR_INIT;
        const char *path;
        filesystem_iterator_entry *entry;
        struct stat statbuf;
@@ -1356,12 +1357,12 @@ static int filesystem_iterator_frame_push(
        memset(new_frame, 0, sizeof(filesystem_iterator_frame));
 
        if (frame_entry)
-               git_buf_joinpath(&root, iter->root, frame_entry->path);
+               git_str_joinpath(&root, iter->root, frame_entry->path);
        else
-               git_buf_puts(&root, iter->root);
+               git_str_puts(&root, iter->root);
 
-       if (git_buf_oom(&root) ||
-           git_path_validate_workdir_buf(iter->base.repo, &root) < 0) {
+       if (git_str_oom(&root) ||
+           git_path_validate_str_length(iter->base.repo, &root) < 0) {
                error = -1;
                goto done;
        }
@@ -1369,7 +1370,7 @@ static int filesystem_iterator_frame_push(
        new_frame->path_len = frame_entry ? frame_entry->path_len : 0;
 
        /* Any error here is equivalent to the dir not existing, skip over it */
-       if ((error = git_path_diriter_init(
+       if ((error = git_fs_path_diriter_init(
                        &diriter, root.ptr, iter->dirload_flags)) < 0) {
                error = GIT_ENOTFOUND;
                goto done;
@@ -1387,12 +1388,18 @@ static int filesystem_iterator_frame_push(
        /* check if this directory is ignored */
        filesystem_iterator_frame_push_ignores(iter, frame_entry, new_frame);
 
-       while ((error = git_path_diriter_next(&diriter)) == 0) {
+       while ((error = git_fs_path_diriter_next(&diriter)) == 0) {
                iterator_pathlist_search_t pathlist_match = ITERATOR_PATHLIST_FULL;
+               git_str path_str = GIT_STR_INIT;
                bool dir_expected = false;
 
-               if ((error = git_path_diriter_fullpath(&path, &path_len, &diriter)) < 0 ||
-                   (error = git_path_validate_workdir_with_len(iter->base.repo, path, path_len)) < 0)
+               if ((error = git_fs_path_diriter_fullpath(&path, &path_len, &diriter)) < 0)
+                       goto done;
+
+               path_str.ptr = (char *)path;
+               path_str.size = path_len;
+
+               if ((error = git_path_validate_str_length(iter->base.repo, &path_str)) < 0)
                        goto done;
 
                GIT_ASSERT(path_len > iter->root_len);
@@ -1414,7 +1421,7 @@ static int filesystem_iterator_frame_push(
                 * we have an index, we can just copy the data out of it.
                 */
 
-               if ((error = git_path_diriter_stat(&statbuf, &diriter)) < 0) {
+               if ((error = git_fs_path_diriter_stat(&statbuf, &diriter)) < 0) {
                        /* file was removed between readdir and lstat */
                        if (error == GIT_ENOTFOUND)
                                continue;
@@ -1471,8 +1478,8 @@ done:
        if (error < 0)
                git_array_pop(iter->frames);
 
-       git_buf_dispose(&root);
-       git_path_diriter_free(&diriter);
+       git_str_dispose(&root);
+       git_fs_path_diriter_free(&diriter);
        return error;
 }
 
@@ -1551,7 +1558,7 @@ static int filesystem_iterator_is_dir(
        const filesystem_iterator_entry *entry)
 {
        struct stat st;
-       git_buf fullpath = GIT_BUF_INIT;
+       git_str fullpath = GIT_STR_INIT;
        int error = 0;
 
        if (S_ISDIR(entry->st.st_mode)) {
@@ -1564,15 +1571,15 @@ static int filesystem_iterator_is_dir(
                goto done;
        }
 
-       if ((error = git_buf_joinpath(&fullpath, iter->root, entry->path)) < 0 ||
-           (error = git_path_validate_workdir_buf(iter->base.repo, &fullpath)) < 0 ||
+       if ((error = git_str_joinpath(&fullpath, iter->root, entry->path)) < 0 ||
+           (error = git_path_validate_str_length(iter->base.repo, &fullpath)) < 0 ||
            (error = p_stat(fullpath.ptr, &st)) < 0)
                goto done;
 
        *is_dir = S_ISDIR(st.st_mode);
 
 done:
-       git_buf_dispose(&fullpath);
+       git_str_dispose(&fullpath);
        return error;
 }
 
@@ -1673,7 +1680,7 @@ static int filesystem_iterator_advance_into(
        return filesystem_iterator_advance(out, i);
 }
 
-int git_iterator_current_workdir_path(git_buf **out, git_iterator *i)
+int git_iterator_current_workdir_path(git_str **out, git_iterator *i)
 {
        filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base);
        const git_index_entry *entry;
@@ -1684,10 +1691,10 @@ int git_iterator_current_workdir_path(git_buf **out, git_iterator *i)
                return 0;
        }
 
-       git_buf_truncate(&iter->current_path, iter->root_len);
+       git_str_truncate(&iter->current_path, iter->root_len);
 
        if (git_iterator_current(&entry, i) < 0 ||
-               git_buf_puts(&iter->current_path, entry->path) < 0)
+               git_str_puts(&iter->current_path, entry->path) < 0)
                return -1;
 
        *out = &iter->current_path;
@@ -1790,8 +1797,8 @@ static int filesystem_iterator_advance_over(
                return filesystem_iterator_advance(out, i);
        }
 
-       git_buf_clear(&iter->tmp_buf);
-       if ((error = git_buf_puts(&iter->tmp_buf, entry->path)) < 0)
+       git_str_clear(&iter->tmp_buf);
+       if ((error = git_str_puts(&iter->tmp_buf, entry->path)) < 0)
                return error;
 
        base = iter->tmp_buf.ptr;
@@ -1858,7 +1865,7 @@ static void filesystem_iterator_clear(filesystem_iterator *iter)
        git_array_clear(iter->frames);
        git_ignore__free(&iter->ignores);
 
-       git_buf_dispose(&iter->tmp_buf);
+       git_str_dispose(&iter->tmp_buf);
 
        iterator_clear(&iter->base);
 }
@@ -1892,7 +1899,7 @@ static void filesystem_iterator_free(git_iterator *i)
 {
        filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base);
        git__free(iter->root);
-       git_buf_dispose(&iter->current_path);
+       git_str_dispose(&iter->current_path);
        git_tree_free(iter->tree);
        if (iter->index)
                git_index_snapshot_release(&iter->index_snapshot, iter->index);
@@ -1946,7 +1953,7 @@ static int iterator_for_filesystem(
        iter->root[root_len] = '\0';
        iter->root_len = root_len;
 
-       if ((error = git_buf_puts(&iter->current_path, iter->root)) < 0)
+       if ((error = git_str_puts(&iter->current_path, iter->root)) < 0)
                goto on_error;
 
        if ((error = iterator_init_common(&iter->base, repo, index, options)) < 0)
@@ -1961,9 +1968,10 @@ static int iterator_for_filesystem(
 
        iter->index = index;
        iter->dirload_flags =
-               (iterator__ignore_case(&iter->base) ? GIT_PATH_DIR_IGNORE_CASE : 0) |
+               (iterator__ignore_case(&iter->base) ?
+                       GIT_FS_PATH_DIR_IGNORE_CASE : 0) |
                (iterator__flag(&iter->base, PRECOMPOSE_UNICODE) ?
-                        GIT_PATH_DIR_PRECOMPOSE_UNICODE : 0);
+                       GIT_FS_PATH_DIR_PRECOMPOSE_UNICODE : 0);
 
        if ((error = filesystem_iterator_init(iter)) < 0)
                goto on_error;
@@ -2024,7 +2032,7 @@ typedef struct {
 
        /* the pseudotree entry */
        git_index_entry tree_entry;
-       git_buf tree_buf;
+       git_str tree_buf;
        bool skip_tree;
 
        const git_index_entry *entry;
@@ -2058,14 +2066,14 @@ static bool index_iterator_create_pseudotree(
        prev_path = iter->entry ? iter->entry->path : "";
 
        /* determine if the new path is in a different directory from the old */
-       common_len = git_path_common_dirlen(prev_path, path);
+       common_len = git_fs_path_common_dirlen(prev_path, path);
        relative_path = path + common_len;
 
        if ((dirsep = strchr(relative_path, '/')) == NULL)
                return false;
 
-       git_buf_clear(&iter->tree_buf);
-       git_buf_put(&iter->tree_buf, path, (dirsep - path) + 1);
+       git_str_clear(&iter->tree_buf);
+       git_str_put(&iter->tree_buf, path, (dirsep - path) + 1);
 
        iter->tree_entry.mode = GIT_FILEMODE_TREE;
        iter->tree_entry.path = iter->tree_buf.ptr;
@@ -2230,7 +2238,7 @@ static void index_iterator_free(git_iterator *i)
        index_iterator *iter = GIT_CONTAINER_OF(i, index_iterator, base);
 
        git_index_snapshot_release(&iter->entries, iter->base.index);
-       git_buf_dispose(&iter->tree_buf);
+       git_str_dispose(&iter->tree_buf);
 }
 
 int git_iterator_for_index(
index 30465df2f033ded1ece4b82cd2655d60eb312402..6bb8489d035408dcfd6a2cd3574370a18097c65e 100644 (file)
@@ -11,7 +11,7 @@
 
 #include "git2/index.h"
 #include "vector.h"
-#include "buffer.h"
+#include "str.h"
 #include "ignore.h"
 
 typedef struct git_iterator git_iterator;
@@ -21,7 +21,7 @@ typedef enum {
        GIT_ITERATOR_TREE = 1,
        GIT_ITERATOR_INDEX = 2,
        GIT_ITERATOR_WORKDIR = 3,
-       GIT_ITERATOR_FS = 4,
+       GIT_ITERATOR_FS = 4
 } git_iterator_t;
 
 typedef enum {
@@ -42,7 +42,7 @@ typedef enum {
        /** descend into symlinked directories */
        GIT_ITERATOR_DESCEND_SYMLINKS = (1u << 7),
        /** hash files in workdir or filesystem iterators */
-       GIT_ITERATOR_INCLUDE_HASH = (1u << 8),
+       GIT_ITERATOR_INCLUDE_HASH = (1u << 8)
 } git_iterator_flag_t;
 
 typedef enum {
@@ -278,11 +278,11 @@ extern bool git_iterator_current_tree_is_ignored(git_iterator *iter);
 
 /**
  * Get full path of the current item from a workdir iterator.  This will
- * return NULL for a non-workdir iterator.  The git_buf is still owned by
+ * return NULL for a non-workdir iterator.  The git_str is still owned by
  * the iterator; this is exposed just for efficiency.
  */
 extern int git_iterator_current_workdir_path(
-       git_buf **path, git_iterator *iter);
+       git_str **path, git_iterator *iter);
 
 /**
  * Retrieve the index stored in the iterator.
index 7adccdb00652b642182e83e4c0894085cdd1565e..c9b7f131f0a10a708807f07c8daf1cea420bcfb3 100644 (file)
@@ -564,7 +564,7 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key)
                code;                                                                                           \
        } }
 
-/* More conenient interfaces */
+/* More convenient interfaces */
 
 /*! @function
   @abstract     Instantiate a hash set containing integer keys
index cc793b4587f252c3afd8ac71862d36920670945a..c99d5b942754bd855cdce6f7faa8a55033cd80bd 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <git2.h>
 #include "alloc.h"
+#include "buf.h"
 #include "cache.h"
 #include "common.h"
 #include "filter.h"
@@ -19,6 +20,7 @@
 #include "mwindow.h"
 #include "object.h"
 #include "odb.h"
+#include "rand.h"
 #include "refs.h"
 #include "runtime.h"
 #include "sysdir.h"
@@ -69,6 +71,7 @@ int git_libgit2_init(void)
                git_allocator_global_init,
                git_threadstate_global_init,
                git_threads_global_init,
+               git_rand_global_init,
                git_hash_global_init,
                git_sysdir_global_init,
                git_filter_global_init,
@@ -192,15 +195,17 @@ int git_libgit2_opts(int key, ...)
                {
                        int sysdir = va_arg(ap, int);
                        git_buf *out = va_arg(ap, git_buf *);
-                       const git_buf *tmp;
+                       git_str str = GIT_STR_INIT;
+                       const git_str *tmp;
                        int level;
 
-                       if ((error = config_level_to_sysdir(&level, sysdir)) < 0 ||
-                           (error = git_buf_sanitize(out)) < 0 ||
-                           (error = git_sysdir_get(&tmp, level)) < 0)
+                       if ((error = git_buf_tostr(&str, out)) < 0 ||
+                           (error = config_level_to_sysdir(&level, sysdir)) < 0 ||
+                           (error = git_sysdir_get(&tmp, level)) < 0 ||
+                           (error = git_str_put(&str, tmp->ptr, tmp->size)) < 0)
                                break;
 
-                       error = git_buf_sets(out, tmp->ptr);
+                       error = git_buf_fromstr(out, &str);
                }
                break;
 
@@ -237,13 +242,15 @@ int git_libgit2_opts(int key, ...)
        case GIT_OPT_GET_TEMPLATE_PATH:
                {
                        git_buf *out = va_arg(ap, git_buf *);
-                       const git_buf *tmp;
+                       git_str str = GIT_STR_INIT;
+                       const git_str *tmp;
 
-                       if ((error = git_buf_sanitize(out)) < 0 ||
-                           (error = git_sysdir_get(&tmp, GIT_SYSDIR_TEMPLATE)) < 0)
+                       if ((error = git_buf_tostr(&str, out)) < 0 ||
+                           (error = git_sysdir_get(&tmp, GIT_SYSDIR_TEMPLATE)) < 0 ||
+                           (error = git_str_put(&str, tmp->ptr, tmp->size)) < 0)
                                break;
 
-                       error = git_buf_sets(out, tmp->ptr);
+                       error = git_buf_fromstr(out, &str);
                }
                break;
 
@@ -306,9 +313,13 @@ int git_libgit2_opts(int key, ...)
        case GIT_OPT_GET_USER_AGENT:
                {
                        git_buf *out = va_arg(ap, git_buf *);
-                       if ((error = git_buf_sanitize(out)) < 0)
+                       git_str str = GIT_STR_INIT;
+
+                       if ((error = git_buf_tostr(&str, out)) < 0 ||
+                           (error = git_str_puts(&str, git__user_agent)) < 0)
                                break;
-                       error = git_buf_sets(out, git__user_agent);
+
+                       error = git_buf_fromstr(out, &str);
                }
                break;
 
@@ -390,6 +401,14 @@ int git_libgit2_opts(int key, ...)
                }
                break;
 
+       case GIT_OPT_GET_OWNER_VALIDATION:
+               *(va_arg(ap, int *)) = git_repository__validate_ownership;
+               break;
+
+       case GIT_OPT_SET_OWNER_VALIDATION:
+               git_repository__validate_ownership = (va_arg(ap, int) != 0);
+               break;
+
        default:
                git_error_set(GIT_ERROR_INVALID, "invalid option key");
                error = -1;
index b69d55e2ee2b23e7591d5e3627b012697179a199..4336fe3e54922de14e273806f79edae46ab8e02b 100644 (file)
@@ -8,13 +8,15 @@
 #include "mailmap.h"
 
 #include "common.h"
-#include "path.h"
+#include "config.h"
+#include "fs_path.h"
 #include "repository.h"
 #include "signature.h"
 #include "git2/config.h"
 #include "git2/revparse.h"
 #include "blob.h"
 #include "parse.h"
+#include "path.h"
 
 #define MM_FILE ".mailmap"
 #define MM_FILE_CONFIG "mailmap.file"
@@ -90,21 +92,21 @@ static int advance_until(
 /*
  * Parse a single entry from a mailmap file.
  *
- * The output git_bufs will be non-owning, and should be copied before being
+ * The output git_strs will be non-owning, and should be copied before being
  * persisted.
  */
 static int parse_mailmap_entry(
-       git_buf *real_name, git_buf *real_email,
-       git_buf *replace_name, git_buf *replace_email,
+       git_str *real_name, git_str *real_email,
+       git_str *replace_name, git_str *replace_email,
        git_parse_ctx *ctx)
 {
        const char *start;
        size_t len;
 
-       git_buf_clear(real_name);
-       git_buf_clear(real_email);
-       git_buf_clear(replace_name);
-       git_buf_clear(replace_email);
+       git_str_clear(real_name);
+       git_str_clear(real_email);
+       git_str_clear(replace_name);
+       git_str_clear(replace_email);
 
        git_parse_advance_ws(ctx);
        if (is_eol(ctx))
@@ -114,8 +116,8 @@ static int parse_mailmap_entry(
        if (advance_until(&start, &len, ctx, '<') < 0)
                return -1;
 
-       git_buf_attach_notowned(real_name, start, len);
-       git_buf_rtrim(real_name);
+       git_str_attach_notowned(real_name, start, len);
+       git_str_rtrim(real_name);
 
        /*
         * If this is the last email in the line, this is the email to replace,
@@ -126,19 +128,19 @@ static int parse_mailmap_entry(
 
        /* If we aren't at the end of the line, parse a second name and email */
        if (!is_eol(ctx)) {
-               git_buf_attach_notowned(real_email, start, len);
+               git_str_attach_notowned(real_email, start, len);
 
                git_parse_advance_ws(ctx);
                if (advance_until(&start, &len, ctx, '<') < 0)
                        return -1;
-               git_buf_attach_notowned(replace_name, start, len);
-               git_buf_rtrim(replace_name);
+               git_str_attach_notowned(replace_name, start, len);
+               git_str_rtrim(replace_name);
 
                if (advance_until(&start, &len, ctx, '>') < 0)
                        return -1;
        }
 
-       git_buf_attach_notowned(replace_email, start, len);
+       git_str_attach_notowned(replace_email, start, len);
 
        if (!is_eol(ctx))
                return -1;
@@ -231,10 +233,10 @@ static int mailmap_add_buffer(git_mailmap *mm, const char *buf, size_t len)
        git_parse_ctx ctx;
 
        /* Scratch buffers containing the real parsed names & emails */
-       git_buf real_name = GIT_BUF_INIT;
-       git_buf real_email = GIT_BUF_INIT;
-       git_buf replace_name = GIT_BUF_INIT;
-       git_buf replace_email = GIT_BUF_INIT;
+       git_str real_name = GIT_STR_INIT;
+       git_str real_email = GIT_STR_INIT;
+       git_str replace_name = GIT_STR_INIT;
+       git_str replace_email = GIT_STR_INIT;
 
        /* Buffers may not contain '\0's. */
        if (memchr(buf, '\0', len) != NULL)
@@ -263,10 +265,10 @@ static int mailmap_add_buffer(git_mailmap *mm, const char *buf, size_t len)
        }
 
 cleanup:
-       git_buf_dispose(&real_name);
-       git_buf_dispose(&real_email);
-       git_buf_dispose(&replace_name);
-       git_buf_dispose(&replace_email);
+       git_str_dispose(&real_name);
+       git_str_dispose(&real_email);
+       git_str_dispose(&replace_name);
+       git_str_dispose(&replace_email);
        return error;
 }
 
@@ -289,7 +291,7 @@ static int mailmap_add_blob(
 {
        git_object *object = NULL;
        git_blob *blob = NULL;
-       git_buf content = GIT_BUF_INIT;
+       git_str content = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(mm);
@@ -312,7 +314,7 @@ static int mailmap_add_blob(
                goto cleanup;
 
 cleanup:
-       git_buf_dispose(&content);
+       git_str_dispose(&content);
        git_blob_free(blob);
        git_object_free(object);
        return error;
@@ -322,15 +324,15 @@ static int mailmap_add_file_ondisk(
        git_mailmap *mm, const char *path, git_repository *repo)
 {
        const char *base = repo ? git_repository_workdir(repo) : NULL;
-       git_buf fullpath = GIT_BUF_INIT;
-       git_buf content = GIT_BUF_INIT;
+       git_str fullpath = GIT_STR_INIT;
+       git_str content = GIT_STR_INIT;
        int error;
 
-       error = git_path_join_unrooted(&fullpath, path, base, NULL);
+       error = git_fs_path_join_unrooted(&fullpath, path, base, NULL);
        if (error < 0)
                goto cleanup;
 
-       error = git_path_validate_workdir_buf(repo, &fullpath);
+       error = git_path_validate_str_length(repo, &fullpath);
        if (error < 0)
                goto cleanup;
 
@@ -343,8 +345,8 @@ static int mailmap_add_file_ondisk(
                goto cleanup;
 
 cleanup:
-       git_buf_dispose(&fullpath);
-       git_buf_dispose(&content);
+       git_str_dispose(&fullpath);
+       git_str_dispose(&content);
        return error;
 }
 
@@ -352,8 +354,8 @@ cleanup:
 static void mailmap_add_from_repository(git_mailmap *mm, git_repository *repo)
 {
        git_config *config = NULL;
-       git_buf rev_buf = GIT_BUF_INIT;
-       git_buf path_buf = GIT_BUF_INIT;
+       git_str rev_buf = GIT_STR_INIT;
+       git_str path_buf = GIT_STR_INIT;
        const char *rev = NULL;
        const char *path = NULL;
 
@@ -363,9 +365,9 @@ static void mailmap_add_from_repository(git_mailmap *mm, git_repository *repo)
 
        /* Try to load 'mailmap.file' and 'mailmap.blob' cfgs from the repo */
        if (git_repository_config(&config, repo) == 0) {
-               if (git_config_get_string_buf(&rev_buf, config, MM_BLOB_CONFIG) == 0)
+               if (git_config__get_string_buf(&rev_buf, config, MM_BLOB_CONFIG) == 0)
                        rev = rev_buf.ptr;
-               if (git_config_get_path(&path_buf, config, MM_FILE_CONFIG) == 0)
+               if (git_config__get_path(&path_buf, config, MM_FILE_CONFIG) == 0)
                        path = path_buf.ptr;
        }
 
@@ -387,8 +389,8 @@ static void mailmap_add_from_repository(git_mailmap *mm, git_repository *repo)
        if (path != NULL)
                mailmap_add_file_ondisk(mm, path, repo);
 
-       git_buf_dispose(&rev_buf);
-       git_buf_dispose(&path_buf);
+       git_str_dispose(&rev_buf);
+       git_str_dispose(&path_buf);
        git_config_free(config);
 }
 
index d838e4ba92ca5ab3bb53311316f5df8d0393e315..641b32632b14659fb295d31573936ac274567fbc 100644 (file)
@@ -8,11 +8,11 @@
 #include "merge.h"
 
 #include "posix.h"
-#include "buffer.h"
+#include "str.h"
 #include "repository.h"
 #include "revwalk.h"
 #include "commit_list.h"
-#include "path.h"
+#include "fs_path.h"
 #include "refs.h"
 #include "object.h"
 #include "iterator.h"
@@ -591,7 +591,7 @@ int git_repository_mergehead_foreach(
        git_repository_mergehead_foreach_cb cb,
        void *payload)
 {
-       git_buf merge_head_path = GIT_BUF_INIT, merge_head_file = GIT_BUF_INIT;
+       git_str merge_head_path = GIT_STR_INIT, merge_head_file = GIT_STR_INIT;
        char *buffer, *line;
        size_t line_num = 1;
        git_oid oid;
@@ -600,12 +600,12 @@ int git_repository_mergehead_foreach(
        GIT_ASSERT_ARG(repo);
        GIT_ASSERT_ARG(cb);
 
-       if ((error = git_buf_joinpath(&merge_head_path, repo->gitdir,
+       if ((error = git_str_joinpath(&merge_head_path, repo->gitdir,
                GIT_MERGE_HEAD_FILE)) < 0)
                return error;
 
        if ((error = git_futils_readbuffer(&merge_head_file,
-               git_buf_cstr(&merge_head_path))) < 0)
+               git_str_cstr(&merge_head_path))) < 0)
                goto cleanup;
 
        buffer = merge_head_file.ptr;
@@ -635,8 +635,8 @@ int git_repository_mergehead_foreach(
        }
 
 cleanup:
-       git_buf_dispose(&merge_head_path);
-       git_buf_dispose(&merge_head_file);
+       git_str_dispose(&merge_head_path);
+       git_str_dispose(&merge_head_file);
 
        return error;
 }
@@ -893,7 +893,7 @@ static int merge_conflict_invoke_driver(
        git_merge_driver_source *src)
 {
        git_index_entry *result;
-       git_buf buf = GIT_BUF_INIT;
+       git_buf buf = {0};
        const char *path;
        uint32_t mode;
        git_odb *odb = NULL;
@@ -2116,11 +2116,11 @@ int git_merge__iterators(
        file_opts.flags = opts.file_flags;
 
        /* use the git-inspired labels when virtual base building */
-       if (opts.flags & GIT_MERGE__VIRTUAL_BASE) {
+       if (opts.flags & GIT_MERGE_VIRTUAL_BASE) {
                file_opts.ancestor_label = "merged common ancestors";
                file_opts.our_label = "Temporary merge branch 1";
                file_opts.their_label = "Temporary merge branch 2";
-               file_opts.flags |= GIT_MERGE_FILE_FAVOR__CONFLICTED;
+               file_opts.flags |= GIT_MERGE_FILE_ACCEPT_CONFLICTS;
                file_opts.marker_size = GIT_MERGE_CONFLICT_MARKER_SIZE + 2;
        }
 
@@ -2280,7 +2280,7 @@ static int create_virtual_base(
                memcpy(&virtual_opts, opts, sizeof(git_merge_options));
 
        virtual_opts.flags &= ~GIT_MERGE_FAIL_ON_CONFLICT;
-       virtual_opts.flags |= GIT_MERGE__VIRTUAL_BASE;
+       virtual_opts.flags |= GIT_MERGE_VIRTUAL_BASE;
 
        if ((merge_annotated_commits(&index, NULL, repo, one, two,
                        recursion_level + 1, &virtual_opts)) < 0)
@@ -2473,14 +2473,14 @@ static int write_merge_head(
        size_t heads_len)
 {
        git_filebuf file = GIT_FILEBUF_INIT;
-       git_buf file_path = GIT_BUF_INIT;
+       git_str file_path = GIT_STR_INIT;
        size_t i;
        int error = 0;
 
        GIT_ASSERT_ARG(repo);
        GIT_ASSERT_ARG(heads);
 
-       if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_HEAD_FILE)) < 0 ||
+       if ((error = git_str_joinpath(&file_path, repo->gitdir, GIT_MERGE_HEAD_FILE)) < 0 ||
                (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_MERGE_FILE_MODE)) < 0)
                goto cleanup;
 
@@ -2495,7 +2495,7 @@ cleanup:
        if (error < 0)
                git_filebuf_cleanup(&file);
 
-       git_buf_dispose(&file_path);
+       git_str_dispose(&file_path);
 
        return error;
 }
@@ -2503,12 +2503,12 @@ cleanup:
 static int write_merge_mode(git_repository *repo)
 {
        git_filebuf file = GIT_FILEBUF_INIT;
-       git_buf file_path = GIT_BUF_INIT;
+       git_str file_path = GIT_STR_INIT;
        int error = 0;
 
        GIT_ASSERT_ARG(repo);
 
-       if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MODE_FILE)) < 0 ||
+       if ((error = git_str_joinpath(&file_path, repo->gitdir, GIT_MERGE_MODE_FILE)) < 0 ||
                (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_MERGE_FILE_MODE)) < 0)
                goto cleanup;
 
@@ -2521,7 +2521,7 @@ cleanup:
        if (error < 0)
                git_filebuf_cleanup(&file);
 
-       git_buf_dispose(&file_path);
+       git_str_dispose(&file_path);
 
        return error;
 }
@@ -2719,7 +2719,7 @@ static int write_merge_msg(
        size_t heads_len)
 {
        git_filebuf file = GIT_FILEBUF_INIT;
-       git_buf file_path = GIT_BUF_INIT;
+       git_str file_path = GIT_STR_INIT;
        struct merge_msg_entry *entries;
        git_vector matching = GIT_VECTOR_INIT;
        size_t i;
@@ -2740,7 +2740,7 @@ static int write_merge_msg(
        for (i = 0; i < heads_len; i++)
                entries[i].merge_head = heads[i];
 
-       if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
+       if ((error = git_str_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
                (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_MERGE_FILE_MODE)) < 0 ||
                (error = git_filebuf_write(&file, "Merge ", 6)) < 0)
                goto cleanup;
@@ -2822,7 +2822,7 @@ cleanup:
        if (error < 0)
                git_filebuf_cleanup(&file);
 
-       git_buf_dispose(&file_path);
+       git_str_dispose(&file_path);
 
        git_vector_free(&matching);
        git__free(entries);
@@ -3019,10 +3019,10 @@ 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
+        * have conflicts with the workdir. Passing 0 as the pathspec count parameter
         * 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
+        * the merge. This typically happens when cherry-picking a commit whose
         * changes have already been applied.
         */
        if (merged_paths->length == 0)
@@ -3114,7 +3114,7 @@ int git_merge__append_conflicts_to_merge_msg(
        git_index *index)
 {
        git_filebuf file = GIT_FILEBUF_INIT;
-       git_buf file_path = GIT_BUF_INIT;
+       git_str file_path = GIT_STR_INIT;
        const char *last = NULL;
        size_t i;
        int error;
@@ -3122,11 +3122,11 @@ int git_merge__append_conflicts_to_merge_msg(
        if (!git_index_has_conflicts(index))
                return 0;
 
-       if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
+       if ((error = git_str_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
                (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_APPEND, GIT_MERGE_FILE_MODE)) < 0)
                goto cleanup;
 
-       git_filebuf_printf(&file, "\nConflicts:\n");
+       git_filebuf_printf(&file, "\n#Conflicts:\n");
 
        for (i = 0; i < git_index_entrycount(index); i++) {
                const git_index_entry *e = git_index_get_byindex(index, i);
@@ -3135,7 +3135,7 @@ int git_merge__append_conflicts_to_merge_msg(
                        continue;
 
                if (last == NULL || strcmp(e->path, last) != 0)
-                       git_filebuf_printf(&file, "\t%s\n", e->path);
+                       git_filebuf_printf(&file, "#\t%s\n", e->path);
 
                last = e->path;
        }
@@ -3146,7 +3146,7 @@ cleanup:
        if (error < 0)
                git_filebuf_cleanup(&file);
 
-       git_buf_dispose(&file_path);
+       git_str_dispose(&file_path);
 
        return error;
 }
index 3e7f80c6ee2a80a6e115c7e72e589162c9b3c495..23932905e8089ca94d2935f193d6d8008eb0916f 100644 (file)
 #define GIT_MERGE_DEFAULT_RENAME_THRESHOLD     50
 #define GIT_MERGE_DEFAULT_TARGET_LIMIT         1000
 
-
-/** Internal merge flags. */
-enum {
-       /** The merge is for a virtual base in a recursive merge. */
-       GIT_MERGE__VIRTUAL_BASE = (1 << 31),
-};
-
-enum {
-       /** Accept the conflict file, staging it as the merge result. */
-       GIT_MERGE_FILE_FAVOR__CONFLICTED = 4,
-};
-
-
 /** Types of changes when files are merged from branch to branch. */
 typedef enum {
        /* No conflict - a change only occurs in one branch. */
@@ -83,7 +70,7 @@ typedef enum {
        GIT_MERGE_DIFF_DIRECTORY_FILE = (1 << 10),
 
        /* The child of a folder that is in a directory/file conflict. */
-       GIT_MERGE_DIFF_DF_CHILD = (1 << 11),
+       GIT_MERGE_DIFF_DF_CHILD = (1 << 11)
 } git_merge_diff_t;
 
 typedef struct {
index 17c386a143c738ee18df5bd41ec62bb434dfa7e1..19b35ac0ea6a85a10caa1a2a4ebac36804565318 100644 (file)
@@ -93,7 +93,7 @@ int git_merge_driver__builtin_apply(
                goto done;
 
        if (!result.automergeable &&
-               !(file_opts.flags & GIT_MERGE_FILE_FAVOR__CONFLICTED)) {
+               !(file_opts.flags & GIT_MERGE_FILE_ACCEPT_CONFLICTS)) {
                error = GIT_EMERGECONFLICT;
                goto done;
        }
@@ -110,7 +110,7 @@ int git_merge_driver__builtin_apply(
 
        merged_out->ptr = (char *)result.ptr;
        merged_out->size = result.len;
-       merged_out->asize = result.len;
+       merged_out->reserved = 0;
        result.ptr = NULL;
 
 done:
index bfa3ec52e488b03cd00e150ad8937ecee42af022..732a047b1c90aab5af354e24d609487623a5e15c 100644 (file)
@@ -86,22 +86,30 @@ static int merge_file__xdiff(
 
        memset(&xmparam, 0x0, sizeof(xmparam_t));
 
+       if (ours->size > LONG_MAX ||
+           theirs->size > LONG_MAX ||
+           (ancestor && ancestor->size > LONG_MAX)) {
+               git_error_set(GIT_ERROR_MERGE, "failed to merge files");
+               error = -1;
+               goto done;
+       }
+
        if (ancestor) {
                xmparam.ancestor = (options.ancestor_label) ?
                        options.ancestor_label : ancestor->path;
                ancestor_mmfile.ptr = (char *)ancestor->ptr;
-               ancestor_mmfile.size = ancestor->size;
+               ancestor_mmfile.size = (long)ancestor->size;
        }
 
        xmparam.file1 = (options.our_label) ?
                options.our_label : ours->path;
        our_mmfile.ptr = (char *)ours->ptr;
-       our_mmfile.size = ours->size;
+       our_mmfile.size = (long)ours->size;
 
        xmparam.file2 = (options.their_label) ?
                options.their_label : theirs->path;
        their_mmfile.ptr = (char *)theirs->ptr;
-       their_mmfile.size = theirs->size;
+       their_mmfile.size = (long)theirs->size;
 
        if (options.favor == GIT_MERGE_FILE_FAVOR_OURS)
                xmparam.favor = XDL_MERGE_FAVOR_OURS;
@@ -115,6 +123,8 @@ static int merge_file__xdiff(
 
        if (options.flags & GIT_MERGE_FILE_STYLE_DIFF3)
                xmparam.style = XDL_MERGE_DIFF3;
+       if (options.flags & GIT_MERGE_FILE_STYLE_ZDIFF3)
+               xmparam.style = XDL_MERGE_ZEALOUS_DIFF3;
 
        if (options.flags & GIT_MERGE_FILE_IGNORE_WHITESPACE)
                xmparam.xpp.flags |= XDF_IGNORE_WHITESPACE;
index 327b984fc7ce4df1993aafa2185aab91fe99621e..ec0103a339fe15bae684eac1c8107c040cbda023 100644 (file)
@@ -5,7 +5,9 @@
  * a Linking Exception. For full terms see the included COPYING file.
  */
 
-#include "message.h"
+#include "buf.h"
+
+#include "git2/message.h"
 
 static size_t line_length_without_trailing_spaces(const char *line, size_t len)
 {
@@ -21,17 +23,17 @@ static size_t line_length_without_trailing_spaces(const char *line, size_t len)
 
 /* Greatly inspired from git.git "stripspace" */
 /* see https://github.com/git/git/blob/497215d8811ac7b8955693ceaad0899ecd894ed2/builtin/stripspace.c#L4-67 */
-int git_message_prettify(git_buf *message_out, const char *message, int strip_comments, char comment_char)
+static int git_message__prettify(
+       git_str *message_out,
+       const char *message,
+       int strip_comments,
+       char comment_char)
 {
        const size_t message_len = strlen(message);
 
        int consecutive_empty_lines = 0;
        size_t i, line_length, rtrimmed_line_length;
        char *next_newline;
-       int error;
-
-       if ((error = git_buf_sanitize(message_out)) < 0)
-               return error;
 
        for (i = 0; i < strlen(message); i += line_length) {
                next_newline = memchr(message + i, '\n', message_len - i);
@@ -53,12 +55,21 @@ int git_message_prettify(git_buf *message_out, const char *message, int strip_co
                }
 
                if (consecutive_empty_lines > 0 && message_out->size > 0)
-                       git_buf_putc(message_out, '\n');
+                       git_str_putc(message_out, '\n');
 
                consecutive_empty_lines = 0;
-               git_buf_put(message_out, message + i, rtrimmed_line_length);
-               git_buf_putc(message_out, '\n');
+               git_str_put(message_out, message + i, rtrimmed_line_length);
+               git_str_putc(message_out, '\n');
        }
 
-       return git_buf_oom(message_out) ? -1 : 0;
+       return git_str_oom(message_out) ? -1 : 0;
+}
+
+int git_message_prettify(
+       git_buf *message_out,
+       const char *message,
+       int strip_comments,
+       char comment_char)
+{
+       GIT_BUF_WRAP_PRIVATE(message_out, git_message__prettify, message, strip_comments, comment_char);
 }
diff --git a/src/message.h b/src/message.h
deleted file mode 100644 (file)
index 251727b..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * 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_message_h__
-#define INCLUDE_message_h__
-
-#include "common.h"
-
-#include "git2/message.h"
-#include "buffer.h"
-
-int git_message__prettify(git_buf *message_out, const char *message, int strip_comments);
-
-#endif
index 6a885eddca57a17984f88f6670f949b242bcfc32..0092601f6eb1de9699728084cfb2a0eecb161b38 100644 (file)
@@ -8,14 +8,15 @@
 #include "midx.h"
 
 #include "array.h"
-#include "buffer.h"
+#include "buf.h"
 #include "filebuf.h"
 #include "futils.h"
 #include "hash.h"
 #include "odb.h"
 #include "pack.h"
-#include "path.h"
+#include "fs_path.h"
 #include "repository.h"
+#include "str.h"
 
 #define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
 #define MIDX_VERSION 1
@@ -177,7 +178,8 @@ int git_midx_parse(
        struct git_midx_chunk *last_chunk;
        uint32_t i;
        off64_t last_chunk_offset, chunk_offset, trailer_offset;
-       git_oid idx_checksum = {{0}};
+       size_t checksum_size;
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
        int error;
        struct git_midx_chunk chunk_packfile_names = {0},
                                         chunk_oid_fanout = {0},
@@ -207,21 +209,29 @@ int git_midx_parse(
        last_chunk_offset =
                        sizeof(struct git_midx_header) +
                        (1 + hdr->chunks) * 12;
-       trailer_offset = size - GIT_OID_RAWSZ;
+
+       checksum_size = GIT_HASH_SHA1_SIZE;
+       trailer_offset = size - checksum_size;
+
        if (trailer_offset < last_chunk_offset)
                return midx_error("wrong index size");
-       git_oid_cpy(&idx->checksum, (git_oid *)(data + trailer_offset));
+       memcpy(idx->checksum, data + trailer_offset, checksum_size);
 
-       if (git_hash_buf(&idx_checksum, data, (size_t)trailer_offset) < 0)
+       if (git_hash_buf(checksum, data, (size_t)trailer_offset, GIT_HASH_ALGORITHM_SHA1) < 0)
                return midx_error("could not calculate signature");
-       if (!git_oid_equal(&idx_checksum, &idx->checksum))
+       if (memcmp(checksum, idx->checksum, checksum_size) != 0)
                return midx_error("index signature mismatch");
 
        chunk_hdr = data + sizeof(struct git_midx_header);
        last_chunk = NULL;
        for (i = 0; i < hdr->chunks; ++i, chunk_hdr += 12) {
-               chunk_offset = ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 4)))) << 32 |
-                               ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 8))));
+               uint32_t chunk_id = ntohl(*((uint32_t *)(chunk_hdr + 0)));
+               uint64_t high_offset = ((uint64_t)ntohl(*((uint32_t *)(chunk_hdr + 4)))) & 0xffffffffu;
+               uint64_t low_offset = ((uint64_t)ntohl(*((uint32_t *)(chunk_hdr + 8)))) & 0xffffffffu;
+
+               if (high_offset >= INT32_MAX)
+                       return midx_error("chunk offset out of range");
+               chunk_offset = (off64_t)(high_offset << 32 | low_offset);
                if (chunk_offset < last_chunk_offset)
                        return midx_error("chunks are non-monotonic");
                if (chunk_offset >= trailer_offset)
@@ -230,7 +240,7 @@ int git_midx_parse(
                        last_chunk->length = (size_t)(chunk_offset - last_chunk_offset);
                last_chunk_offset = chunk_offset;
 
-               switch (ntohl(*((uint32_t *)(chunk_hdr + 0)))) {
+               switch (chunk_id) {
                case MIDX_PACKFILE_NAMES_ID:
                        chunk_packfile_names.offset = last_chunk_offset;
                        last_chunk = &chunk_packfile_names;
@@ -313,7 +323,7 @@ int git_midx_open(
        idx = git__calloc(1, sizeof(git_midx_file));
        GIT_ERROR_CHECK_ALLOC(idx);
 
-       error = git_buf_sets(&idx->filename, path);
+       error = git_str_sets(&idx->filename, path);
        if (error < 0)
                return error;
 
@@ -340,7 +350,8 @@ bool git_midx_needs_refresh(
        git_file fd = -1;
        struct stat st;
        ssize_t bytes_read;
-       git_oid idx_checksum = {{0}};
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
+       size_t checksum_size;
 
        /* TODO: properly open the file without access time using O_NOATIME */
        fd = git_futils_open_ro(path);
@@ -359,13 +370,14 @@ bool git_midx_needs_refresh(
                return true;
        }
 
-       bytes_read = p_pread(fd, &idx_checksum, GIT_OID_RAWSZ, st.st_size - GIT_OID_RAWSZ);
+       checksum_size = GIT_HASH_SHA1_SIZE;
+       bytes_read = p_pread(fd, checksum, checksum_size, st.st_size - GIT_OID_RAWSZ);
        p_close(fd);
 
-       if (bytes_read != GIT_OID_RAWSZ)
+       if (bytes_read != (ssize_t)checksum_size)
                return true;
 
-       return !git_oid_equal(&idx_checksum, &idx->checksum);
+       return (memcmp(checksum, idx->checksum, checksum_size) != 0);
 }
 
 int git_midx_entry_find(
@@ -477,7 +489,7 @@ void git_midx_free(git_midx_file *idx)
        if (!idx)
                return;
 
-       git_buf_dispose(&idx->filename);
+       git_str_dispose(&idx->filename);
        git_midx_close(idx);
        git__free(idx);
 }
@@ -497,14 +509,14 @@ int git_midx_writer_new(
        git_midx_writer *w = git__calloc(1, sizeof(git_midx_writer));
        GIT_ERROR_CHECK_ALLOC(w);
 
-       if (git_buf_sets(&w->pack_dir, pack_dir) < 0) {
+       if (git_str_sets(&w->pack_dir, pack_dir) < 0) {
                git__free(w);
                return -1;
        }
-       git_path_squash_slashes(&w->pack_dir);
+       git_fs_path_squash_slashes(&w->pack_dir);
 
        if (git_vector_init(&w->packs, 0, packfile__cmp) < 0) {
-               git_buf_dispose(&w->pack_dir);
+               git_str_dispose(&w->pack_dir);
                git__free(w);
                return -1;
        }
@@ -524,7 +536,7 @@ void git_midx_writer_free(git_midx_writer *w)
        git_vector_foreach (&w->packs, i, p)
                git_mwindow_put_pack(p);
        git_vector_free(&w->packs);
-       git_buf_dispose(&w->pack_dir);
+       git_str_dispose(&w->pack_dir);
        git__free(w);
 }
 
@@ -532,16 +544,16 @@ int git_midx_writer_add(
                git_midx_writer *w,
                const char *idx_path)
 {
-       git_buf idx_path_buf = GIT_BUF_INIT;
+       git_str idx_path_buf = GIT_STR_INIT;
        int error;
        struct git_pack_file *p;
 
-       error = git_path_prettify(&idx_path_buf, idx_path, git_buf_cstr(&w->pack_dir));
+       error = git_fs_path_prettify(&idx_path_buf, idx_path, git_str_cstr(&w->pack_dir));
        if (error < 0)
                return error;
 
-       error = git_mwindow_get_pack(&p, git_buf_cstr(&idx_path_buf));
-       git_buf_dispose(&idx_path_buf);
+       error = git_mwindow_get_pack(&p, git_str_cstr(&idx_path_buf));
+       git_str_dispose(&idx_path_buf);
        if (error < 0)
                return error;
 
@@ -613,8 +625,8 @@ static int write_chunk_header(int chunk_id, off64_t offset, midx_write_cb write_
 
 static int midx_write_buf(const char *buf, size_t size, void *data)
 {
-       git_buf *b = (git_buf *)data;
-       return git_buf_put(b, buf, size);
+       git_str *b = (git_str *)data;
+       return git_str_put(b, buf, size);
 }
 
 struct midx_write_hash_context {
@@ -648,11 +660,12 @@ static int midx_write(
        uint32_t object_large_offsets_count;
        uint32_t oid_fanout[256];
        off64_t offset;
-       git_buf packfile_names = GIT_BUF_INIT,
-               oid_lookup = GIT_BUF_INIT,
-               object_offsets = GIT_BUF_INIT,
-               object_large_offsets = GIT_BUF_INIT;
-       git_oid idx_checksum = {{0}};
+       git_str packfile_names = GIT_STR_INIT,
+               oid_lookup = GIT_STR_INIT,
+               object_offsets = GIT_STR_INIT,
+               object_large_offsets = GIT_STR_INIT;
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
+       size_t checksum_size;
        git_midx_entry *entry;
        object_entry_array_t object_entries_array = GIT_ARRAY_INIT;
        git_vector object_entries = GIT_VECTOR_INIT;
@@ -668,7 +681,8 @@ static int midx_write(
        hash_cb_data.cb_data = cb_data;
        hash_cb_data.ctx = &ctx;
 
-       error = git_hash_ctx_init(&ctx);
+       checksum_size = GIT_HASH_SHA1_SIZE;
+       error = git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA1);
        if (error < 0)
                return error;
        cb_data = &hash_cb_data;
@@ -676,34 +690,34 @@ static int midx_write(
 
        git_vector_sort(&w->packs);
        git_vector_foreach (&w->packs, i, p) {
-               git_buf relative_index = GIT_BUF_INIT;
+               git_str relative_index = GIT_STR_INIT;
                struct object_entry_cb_state state = {0};
                size_t path_len;
 
                state.pack_index = (uint32_t)i;
                state.object_entries_array = &object_entries_array;
 
-               error = git_buf_sets(&relative_index, p->pack_name);
+               error = git_str_sets(&relative_index, p->pack_name);
                if (error < 0)
                        goto cleanup;
-               error = git_path_make_relative(&relative_index, git_buf_cstr(&w->pack_dir));
+               error = git_fs_path_make_relative(&relative_index, git_str_cstr(&w->pack_dir));
                if (error < 0) {
-                       git_buf_dispose(&relative_index);
+                       git_str_dispose(&relative_index);
                        goto cleanup;
                }
-               path_len = git_buf_len(&relative_index);
-               if (path_len <= strlen(".pack") || git__suffixcmp(git_buf_cstr(&relative_index), ".pack") != 0) {
-                       git_buf_dispose(&relative_index);
+               path_len = git_str_len(&relative_index);
+               if (path_len <= strlen(".pack") || git__suffixcmp(git_str_cstr(&relative_index), ".pack") != 0) {
+                       git_str_dispose(&relative_index);
                        git_error_set(GIT_ERROR_INVALID, "invalid packfile name: '%s'", p->pack_name);
                        error = -1;
                        goto cleanup;
                }
                path_len -= strlen(".pack");
 
-               git_buf_put(&packfile_names, git_buf_cstr(&relative_index), path_len);
-               git_buf_puts(&packfile_names, ".idx");
-               git_buf_putc(&packfile_names, '\0');
-               git_buf_dispose(&relative_index);
+               git_str_put(&packfile_names, git_str_cstr(&relative_index), path_len);
+               git_str_puts(&packfile_names, ".idx");
+               git_str_putc(&packfile_names, '\0');
+               git_str_dispose(&relative_index);
 
                error = git_pack_foreach_entry_offset(p, object_entry__cb, &state);
                if (error < 0)
@@ -723,8 +737,8 @@ static int midx_write(
        git_vector_uniq(&object_entries, NULL);
 
        /* Pad the packfile names so it is a multiple of four. */
-       while (git_buf_len(&packfile_names) & 3)
-               git_buf_putc(&packfile_names, '\0');
+       while (git_str_len(&packfile_names) & 3)
+               git_str_putc(&packfile_names, '\0');
 
        /* Fill the OID Fanout table. */
        oid_fanout_count = 0;
@@ -737,7 +751,7 @@ static int midx_write(
 
        /* Fill the OID Lookup table. */
        git_vector_foreach (&object_entries, i, entry) {
-               error = git_buf_put(&oid_lookup, (const char *)&entry->sha1, sizeof(entry->sha1));
+               error = git_str_put(&oid_lookup, (const char *)&entry->sha1, sizeof(entry->sha1));
                if (error < 0)
                        goto cleanup;
        }
@@ -748,7 +762,7 @@ static int midx_write(
                uint32_t word;
 
                word = htonl((uint32_t)entry->pack_index);
-               error = git_buf_put(&object_offsets, (const char *)&word, sizeof(word));
+               error = git_str_put(&object_offsets, (const char *)&word, sizeof(word));
                if (error < 0)
                        goto cleanup;
                if (entry->offset >= 0x80000000l) {
@@ -759,7 +773,7 @@ static int midx_write(
                        word = htonl((uint32_t)entry->offset & 0x7fffffffu);
                }
 
-               error = git_buf_put(&object_offsets, (const char *)&word, sizeof(word));
+               error = git_str_put(&object_offsets, (const char *)&word, sizeof(word));
                if (error < 0)
                        goto cleanup;
        }
@@ -767,7 +781,7 @@ static int midx_write(
        /* Write the header. */
        hdr.packfiles = htonl((uint32_t)git_vector_length(&w->packs));
        hdr.chunks = 4;
-       if (git_buf_len(&object_large_offsets) > 0)
+       if (git_str_len(&object_large_offsets) > 0)
                hdr.chunks++;
        error = write_cb((const char *)&hdr, sizeof(hdr), cb_data);
        if (error < 0)
@@ -778,7 +792,7 @@ static int midx_write(
        error = write_chunk_header(MIDX_PACKFILE_NAMES_ID, offset, write_cb, cb_data);
        if (error < 0)
                goto cleanup;
-       offset += git_buf_len(&packfile_names);
+       offset += git_str_len(&packfile_names);
        error = write_chunk_header(MIDX_OID_FANOUT_ID, offset, write_cb, cb_data);
        if (error < 0)
                goto cleanup;
@@ -786,53 +800,53 @@ static int midx_write(
        error = write_chunk_header(MIDX_OID_LOOKUP_ID, offset, write_cb, cb_data);
        if (error < 0)
                goto cleanup;
-       offset += git_buf_len(&oid_lookup);
+       offset += git_str_len(&oid_lookup);
        error = write_chunk_header(MIDX_OBJECT_OFFSETS_ID, offset, write_cb, cb_data);
        if (error < 0)
                goto cleanup;
-       offset += git_buf_len(&object_offsets);
-       if (git_buf_len(&object_large_offsets) > 0) {
+       offset += git_str_len(&object_offsets);
+       if (git_str_len(&object_large_offsets) > 0) {
                error = write_chunk_header(MIDX_OBJECT_LARGE_OFFSETS_ID, offset, write_cb, cb_data);
                if (error < 0)
                        goto cleanup;
-               offset += git_buf_len(&object_large_offsets);
+               offset += git_str_len(&object_large_offsets);
        }
        error = write_chunk_header(0, offset, write_cb, cb_data);
        if (error < 0)
                goto cleanup;
 
        /* Write all the chunks. */
-       error = write_cb(git_buf_cstr(&packfile_names), git_buf_len(&packfile_names), cb_data);
+       error = write_cb(git_str_cstr(&packfile_names), git_str_len(&packfile_names), cb_data);
        if (error < 0)
                goto cleanup;
        error = write_cb((const char *)oid_fanout, sizeof(oid_fanout), cb_data);
        if (error < 0)
                goto cleanup;
-       error = write_cb(git_buf_cstr(&oid_lookup), git_buf_len(&oid_lookup), cb_data);
+       error = write_cb(git_str_cstr(&oid_lookup), git_str_len(&oid_lookup), cb_data);
        if (error < 0)
                goto cleanup;
-       error = write_cb(git_buf_cstr(&object_offsets), git_buf_len(&object_offsets), cb_data);
+       error = write_cb(git_str_cstr(&object_offsets), git_str_len(&object_offsets), cb_data);
        if (error < 0)
                goto cleanup;
-       error = write_cb(git_buf_cstr(&object_large_offsets), git_buf_len(&object_large_offsets), cb_data);
+       error = write_cb(git_str_cstr(&object_large_offsets), git_str_len(&object_large_offsets), cb_data);
        if (error < 0)
                goto cleanup;
 
        /* Finalize the checksum and write the trailer. */
-       error = git_hash_final(&idx_checksum, &ctx);
+       error = git_hash_final(checksum, &ctx);
        if (error < 0)
                goto cleanup;
-       error = write_cb((const char *)&idx_checksum, sizeof(idx_checksum), cb_data);
+       error = write_cb((char *)checksum, checksum_size, cb_data);
        if (error < 0)
                goto cleanup;
 
 cleanup:
        git_array_clear(object_entries_array);
        git_vector_free(&object_entries);
-       git_buf_dispose(&packfile_names);
-       git_buf_dispose(&oid_lookup);
-       git_buf_dispose(&object_offsets);
-       git_buf_dispose(&object_large_offsets);
+       git_str_dispose(&packfile_names);
+       git_str_dispose(&oid_lookup);
+       git_str_dispose(&object_offsets);
+       git_str_dispose(&object_large_offsets);
        git_hash_ctx_cleanup(&ctx);
        return error;
 }
@@ -848,17 +862,17 @@ int git_midx_writer_commit(
 {
        int error;
        int filebuf_flags = GIT_FILEBUF_DO_NOT_BUFFER;
-       git_buf midx_path = GIT_BUF_INIT;
+       git_str midx_path = GIT_STR_INIT;
        git_filebuf output = GIT_FILEBUF_INIT;
 
-       error = git_buf_joinpath(&midx_path, git_buf_cstr(&w->pack_dir), "multi-pack-index");
+       error = git_str_joinpath(&midx_path, git_str_cstr(&w->pack_dir), "multi-pack-index");
        if (error < 0)
                return error;
 
        if (git_repository__fsync_gitdir)
                filebuf_flags |= GIT_FILEBUF_FSYNC;
-       error = git_filebuf_open(&output, git_buf_cstr(&midx_path), filebuf_flags, 0644);
-       git_buf_dispose(&midx_path);
+       error = git_filebuf_open(&output, git_str_cstr(&midx_path), filebuf_flags, 0644);
+       git_str_dispose(&midx_path);
        if (error < 0)
                return error;
 
@@ -875,5 +889,13 @@ int git_midx_writer_dump(
                git_buf *midx,
                git_midx_writer *w)
 {
-       return midx_write(w, midx_write_buf, midx);
+       git_str str = GIT_STR_INIT;
+       int error;
+
+       if ((error = git_buf_tostr(&str, midx)) < 0 ||
+           (error = midx_write(w, midx_write_buf, &str)) == 0)
+               error = git_buf_fromstr(midx, &str);
+
+       git_str_dispose(&str);
+       return error;
 }
index 4ce17ce73a8f30055fcb5acaae2cf89117afd484..7dd851bd36b6bdbb3fe7cb08b2b209a91851c739 100644 (file)
@@ -51,10 +51,10 @@ typedef struct git_midx_file {
        size_t num_object_large_offsets;
 
        /* The trailer of the file. Contains the SHA1-checksum of the whole file. */
-       git_oid checksum;
+       unsigned char checksum[GIT_HASH_SHA1_SIZE];
 
        /* something like ".git/objects/pack/multi-pack-index". */
-       git_buf filename;
+       git_str filename;
 } git_midx_file;
 
 /*
@@ -77,7 +77,7 @@ struct git_midx_writer {
         * The path of the directory where the .pack/.idx files are stored. The
         * `multi-pack-index` file will be written to the same directory.
         */
-       git_buf pack_dir;
+       git_str pack_dir;
 
        /* The list of `git_pack_file`s. */
        git_vector packs;
index da2dae2b9d6869a145ec12c77fec445d146c1465..d06b7a80e28734e0f68137fc50be900d9106f1fe 100644 (file)
@@ -473,7 +473,7 @@ int git_mwindow_file_register(git_mwindow_file *mwf)
                                git_mwindow_find_lru_file_locked(&lru_file) == 0) {
                        if ((error = git_vector_insert(&closed_files, lru_file)) < 0) {
                                /*
-                                * Exceeding the file limit seems preferrable to being open to
+                                * Exceeding the file limit seems preferable to being open to
                                 * data races that can end up corrupting the heap.
                                 */
                                break;
index 361e40e7b05f5577f5ef93efd04ba0afe462acd4..a76fd1d7c5bfc570cf1755c606fa1e2e2782908a 100644 (file)
--- a/src/net.c
+++ b/src/net.c
@@ -9,10 +9,9 @@
 #include "netops.h"
 
 #include <ctype.h>
-#include "git2/errors.h"
 
 #include "posix.h"
-#include "buffer.h"
+#include "str.h"
 #include "http_parser.h"
 #include "runtime.h"
 
 #define DEFAULT_PORT_GIT   "9418"
 #define DEFAULT_PORT_SSH   "22"
 
+bool git_net_str_is_url(const char *str)
+{
+       const char *c;
+
+       for (c = str; *c; c++) {
+               if (*c == ':' && *(c+1) == '/' && *(c+2) == '/')
+                       return true;
+
+               if ((*c < 'a' || *c > 'z') &&
+                   (*c < 'A' || *c > 'Z') &&
+                   (*c < '0' || *c > '9') &&
+                   (*c != '+' && *c != '-' && *c != '.'))
+                       break;
+       }
+
+       return false;
+}
+
 static const char *default_port_for_scheme(const char *scheme)
 {
        if (strcmp(scheme, "http") == 0)
@@ -29,7 +46,9 @@ static const char *default_port_for_scheme(const char *scheme)
                return DEFAULT_PORT_HTTPS;
        else if (strcmp(scheme, "git") == 0)
                return DEFAULT_PORT_GIT;
-       else if (strcmp(scheme, "ssh") == 0)
+       else if (strcmp(scheme, "ssh") == 0 ||
+                strcmp(scheme, "ssh+git") == 0 ||
+                strcmp(scheme, "git+ssh") == 0)
                return DEFAULT_PORT_SSH;
 
        return NULL;
@@ -79,13 +98,13 @@ int git_net_url_parse(git_net_url *url, const char *given)
 {
        struct http_parser_url u = {0};
        bool has_scheme, has_host, has_port, has_path, has_query, has_userinfo;
-       git_buf scheme = GIT_BUF_INIT,
-               host = GIT_BUF_INIT,
-               port = GIT_BUF_INIT,
-               path = GIT_BUF_INIT,
-               username = GIT_BUF_INIT,
-               password = GIT_BUF_INIT,
-               query = GIT_BUF_INIT;
+       git_str scheme = GIT_STR_INIT,
+               host = GIT_STR_INIT,
+               port = GIT_STR_INIT,
+               path = GIT_STR_INIT,
+               username = GIT_STR_INIT,
+               password = GIT_STR_INIT,
+               query = GIT_STR_INIT;
        int error = GIT_EINVALIDSPEC;
 
        if (http_parser_parse_url(given, strlen(given), false, &u)) {
@@ -103,7 +122,7 @@ int git_net_url_parse(git_net_url *url, const char *given)
        if (has_scheme) {
                const char *url_scheme = given + u.field_data[UF_SCHEMA].off;
                size_t url_scheme_len = u.field_data[UF_SCHEMA].len;
-               git_buf_put(&scheme, url_scheme, url_scheme_len);
+               git_str_put(&scheme, url_scheme, url_scheme_len);
                git__strntolower(scheme.ptr, scheme.size);
        } else {
                git_error_set(GIT_ERROR_NET, "malformed URL '%s'", given);
@@ -113,13 +132,13 @@ int git_net_url_parse(git_net_url *url, const char *given)
        if (has_host) {
                const char *url_host = given + u.field_data[UF_HOST].off;
                size_t url_host_len = u.field_data[UF_HOST].len;
-               git_buf_decode_percent(&host, url_host, url_host_len);
+               git_str_decode_percent(&host, url_host, url_host_len);
        }
 
        if (has_port) {
                const char *url_port = given + u.field_data[UF_PORT].off;
                size_t url_port_len = u.field_data[UF_PORT].len;
-               git_buf_put(&port, url_port, url_port_len);
+               git_str_put(&port, url_port, url_port_len);
        } else {
                const char *default_port = default_port_for_scheme(scheme.ptr);
 
@@ -128,21 +147,21 @@ int git_net_url_parse(git_net_url *url, const char *given)
                        goto done;
                }
 
-               git_buf_puts(&port, default_port);
+               git_str_puts(&port, default_port);
        }
 
        if (has_path) {
                const char *url_path = given + u.field_data[UF_PATH].off;
                size_t url_path_len = u.field_data[UF_PATH].len;
-               git_buf_put(&path, url_path, url_path_len);
+               git_str_put(&path, url_path, url_path_len);
        } else {
-               git_buf_puts(&path, "/");
+               git_str_puts(&path, "/");
        }
 
        if (has_query) {
                const char *url_query = given + u.field_data[UF_QUERY].off;
                size_t url_query_len = u.field_data[UF_QUERY].len;
-               git_buf_decode_percent(&query, url_query, url_query_len);
+               git_str_decode_percent(&query, url_query, url_query_len);
        }
 
        if (has_userinfo) {
@@ -156,49 +175,238 @@ int git_net_url_parse(git_net_url *url, const char *given)
                        const char *url_password = colon + 1;
                        size_t url_password_len = url_userinfo_len - (url_username_len + 1);
 
-                       git_buf_decode_percent(&username, url_username, url_username_len);
-                       git_buf_decode_percent(&password, url_password, url_password_len);
+                       git_str_decode_percent(&username, url_username, url_username_len);
+                       git_str_decode_percent(&password, url_password, url_password_len);
                } else {
-                       git_buf_decode_percent(&username, url_userinfo, url_userinfo_len);
+                       git_str_decode_percent(&username, url_userinfo, url_userinfo_len);
                }
        }
 
-       if (git_buf_oom(&scheme) ||
-           git_buf_oom(&host) ||
-           git_buf_oom(&port) ||
-           git_buf_oom(&path) ||
-           git_buf_oom(&query) ||
-           git_buf_oom(&username) ||
-           git_buf_oom(&password))
+       if (git_str_oom(&scheme) ||
+           git_str_oom(&host) ||
+           git_str_oom(&port) ||
+           git_str_oom(&path) ||
+           git_str_oom(&query) ||
+           git_str_oom(&username) ||
+           git_str_oom(&password))
                return -1;
 
-       url->scheme = git_buf_detach(&scheme);
-       url->host = git_buf_detach(&host);
-       url->port = git_buf_detach(&port);
-       url->path = git_buf_detach(&path);
-       url->query = git_buf_detach(&query);
-       url->username = git_buf_detach(&username);
-       url->password = git_buf_detach(&password);
+       url->scheme = git_str_detach(&scheme);
+       url->host = git_str_detach(&host);
+       url->port = git_str_detach(&port);
+       url->path = git_str_detach(&path);
+       url->query = git_str_detach(&query);
+       url->username = git_str_detach(&username);
+       url->password = git_str_detach(&password);
 
        error = 0;
 
 done:
-       git_buf_dispose(&scheme);
-       git_buf_dispose(&host);
-       git_buf_dispose(&port);
-       git_buf_dispose(&path);
-       git_buf_dispose(&query);
-       git_buf_dispose(&username);
-       git_buf_dispose(&password);
+       git_str_dispose(&scheme);
+       git_str_dispose(&host);
+       git_str_dispose(&port);
+       git_str_dispose(&path);
+       git_str_dispose(&query);
+       git_str_dispose(&username);
+       git_str_dispose(&password);
        return error;
 }
 
+static int scp_invalid(const char *message)
+{
+       git_error_set(GIT_ERROR_NET, "invalid scp-style path: %s", message);
+       return GIT_EINVALIDSPEC;
+}
+
+static bool is_ipv6(const char *str)
+{
+       const char *c;
+       size_t colons = 0;
+
+       if (*str++ != '[')
+               return false;
+
+       for (c = str; *c; c++) {
+               if (*c  == ':')
+                       colons++;
+
+               if (*c == ']')
+                       return (colons > 1);
+
+               if (*c != ':' &&
+                   (*c < '0' || *c > '9') &&
+                   (*c < 'a' || *c > 'f') &&
+                   (*c < 'A' || *c > 'F'))
+                       return false;
+       }
+
+       return false;
+}
+
+static bool has_at(const char *str)
+{
+       const char *c;
+
+       for (c = str; *c; c++) {
+               if (*c == '@')
+                       return true;
+
+               if (*c == ':')
+                       break;
+       }
+
+       return false;
+}
+
+int git_net_url_parse_scp(git_net_url *url, const char *given)
+{
+       const char *default_port = default_port_for_scheme("ssh");
+       const char *c, *user, *host, *port, *path = NULL;
+       size_t user_len = 0, host_len = 0, port_len = 0;
+       unsigned short bracket = 0;
+
+       enum {
+               NONE,
+               USER,
+               HOST_START, HOST, HOST_END,
+               IPV6, IPV6_END,
+               PORT_START, PORT, PORT_END,
+               PATH_START
+       } state = NONE;
+
+       memset(url, 0, sizeof(git_net_url));
+
+       for (c = given; *c && !path; c++) {
+               switch (state) {
+               case NONE:
+                       switch (*c) {
+                       case '@':
+                               return scp_invalid("unexpected '@'");
+                       case ':':
+                               return scp_invalid("unexpected ':'");
+                       case '[':
+                               if (is_ipv6(c)) {
+                                       state = IPV6;
+                                       host = c;
+                               } else if (bracket++ > 1) {
+                                       return scp_invalid("unexpected '['");
+                               }
+                               break;
+                       default:
+                               if (has_at(c)) {
+                                       state = USER;
+                                       user = c;
+                               } else {
+                                       state = HOST;
+                                       host = c;
+                               }
+                               break;
+                       }
+                       break;
+
+               case USER:
+                       if (*c == '@') {
+                               user_len = (c - user);
+                               state = HOST_START;
+                       }
+                       break;
+
+               case HOST_START:
+                       state = (*c == '[') ? IPV6 : HOST;
+                       host = c;
+                       break;
+
+               case HOST:
+                       if (*c == ':') {
+                               host_len = (c - host);
+                               state = bracket ? PORT_START : PATH_START;
+                       } else if (*c == ']') {
+                               if (bracket-- == 0)
+                                       return scp_invalid("unexpected ']'");
+
+                               host_len = (c - host);
+                               state = HOST_END;
+                       }
+                       break;
+
+               case HOST_END:
+                       if (*c != ':')
+                               return scp_invalid("unexpected character after hostname");
+                       state = PATH_START;
+                       break;
+
+               case IPV6:
+                       if (*c == ']')
+                               state = IPV6_END;
+                       break;
+
+               case IPV6_END:
+                       if (*c != ':')
+                               return scp_invalid("unexpected character after ipv6 address");
+
+                       host_len = (c - host);
+                       state = bracket ? PORT_START : PATH_START;
+                       break;
+
+               case PORT_START:
+                       port = c;
+                       state = PORT;
+                       break;
+
+               case PORT:
+                       if (*c == ']') {
+                               if (bracket-- == 0)
+                                       return scp_invalid("unexpected ']'");
+
+                               port_len = c - port;
+                               state = PORT_END;
+                       }
+                       break;
+
+               case PORT_END:
+                       if (*c != ':')
+                               return scp_invalid("unexpected character after ipv6 address");
+
+                       state = PATH_START;
+                       break;
+
+               case PATH_START:
+                       path = c;
+                       break;
+
+               default:
+                       GIT_ASSERT("unhandled state");
+               }
+       }
+
+       if (!path)
+               return scp_invalid("path is required");
+
+       GIT_ERROR_CHECK_ALLOC(url->scheme = git__strdup("ssh"));
+
+       if (user_len)
+               GIT_ERROR_CHECK_ALLOC(url->username = git__strndup(user, user_len));
+
+       GIT_ASSERT(host_len);
+       GIT_ERROR_CHECK_ALLOC(url->host = git__strndup(host, host_len));
+
+       if (port_len)
+               GIT_ERROR_CHECK_ALLOC(url->port = git__strndup(port, port_len));
+       else
+               GIT_ERROR_CHECK_ALLOC(url->port = git__strdup(default_port));
+
+       GIT_ASSERT(path);
+       GIT_ERROR_CHECK_ALLOC(url->path = git__strdup(path));
+
+       return 0;
+}
+
 int git_net_url_joinpath(
        git_net_url *out,
        git_net_url *one,
        const char *two)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        const char *query;
        size_t one_len, two_len;
 
@@ -226,14 +434,14 @@ int git_net_url_joinpath(
                two_len--;
        }
 
-       git_buf_put(&path, one->path, one_len);
-       git_buf_putc(&path, '/');
-       git_buf_put(&path, two, two_len);
+       git_str_put(&path, one->path, one_len);
+       git_str_putc(&path, '/');
+       git_str_put(&path, two, two_len);
 
-       if (git_buf_oom(&path))
+       if (git_str_oom(&path))
                return -1;
 
-       out->path = git_buf_detach(&path);
+       out->path = git_str_detach(&path);
 
        if (one->scheme) {
                out->scheme = git__strdup(one->scheme);
@@ -316,6 +524,7 @@ static void remove_service_suffix(
 int git_net_url_apply_redirect(
        git_net_url *url,
        const char *redirect_location,
+       bool allow_offsite,
        const char *service_suffix)
 {
        git_net_url tmp = GIT_NET_URL_INIT;
@@ -340,8 +549,8 @@ int git_net_url_apply_redirect(
                /* Validate that this is a legal redirection */
 
                if (original->scheme &&
-                       strcmp(original->scheme, tmp.scheme) != 0 &&
-                       strcmp(tmp.scheme, "https") != 0) {
+                   strcmp(original->scheme, tmp.scheme) != 0 &&
+                   strcmp(tmp.scheme, "https") != 0) {
                        git_error_set(GIT_ERROR_NET, "cannot redirect from '%s' to '%s'",
                                original->scheme, tmp.scheme);
 
@@ -350,6 +559,7 @@ int git_net_url_apply_redirect(
                }
 
                if (original->host &&
+                   !allow_offsite &&
                    git__strcasecmp(original->host, tmp.host) != 0) {
                        git_error_set(GIT_ERROR_NET, "cannot redirect from '%s' to '%s'",
                                original->host, tmp.host);
@@ -399,53 +609,53 @@ void git_net_url_swap(git_net_url *a, git_net_url *b)
        memcpy(b, &tmp, sizeof(git_net_url));
 }
 
-int git_net_url_fmt(git_buf *buf, git_net_url *url)
+int git_net_url_fmt(git_str *buf, git_net_url *url)
 {
        GIT_ASSERT_ARG(url);
        GIT_ASSERT_ARG(url->scheme);
        GIT_ASSERT_ARG(url->host);
 
-       git_buf_puts(buf, url->scheme);
-       git_buf_puts(buf, "://");
+       git_str_puts(buf, url->scheme);
+       git_str_puts(buf, "://");
 
        if (url->username) {
-               git_buf_puts(buf, url->username);
+               git_str_puts(buf, url->username);
 
                if (url->password) {
-                       git_buf_puts(buf, ":");
-                       git_buf_puts(buf, url->password);
+                       git_str_puts(buf, ":");
+                       git_str_puts(buf, url->password);
                }
 
-               git_buf_putc(buf, '@');
+               git_str_putc(buf, '@');
        }
 
-       git_buf_puts(buf, url->host);
+       git_str_puts(buf, url->host);
 
        if (url->port && !git_net_url_is_default_port(url)) {
-               git_buf_putc(buf, ':');
-               git_buf_puts(buf, url->port);
+               git_str_putc(buf, ':');
+               git_str_puts(buf, url->port);
        }
 
-       git_buf_puts(buf, url->path ? url->path : "/");
+       git_str_puts(buf, url->path ? url->path : "/");
 
        if (url->query) {
-               git_buf_putc(buf, '?');
-               git_buf_puts(buf, url->query);
+               git_str_putc(buf, '?');
+               git_str_puts(buf, url->query);
        }
 
-       return git_buf_oom(buf) ? -1 : 0;
+       return git_str_oom(buf) ? -1 : 0;
 }
 
-int git_net_url_fmt_path(git_buf *buf, git_net_url *url)
+int git_net_url_fmt_path(git_str *buf, git_net_url *url)
 {
-       git_buf_puts(buf, url->path ? url->path : "/");
+       git_str_puts(buf, url->path ? url->path : "/");
 
        if (url->query) {
-               git_buf_putc(buf, '?');
-               git_buf_puts(buf, url->query);
+               git_str_putc(buf, '?');
+               git_str_puts(buf, url->query);
        }
 
-       return git_buf_oom(buf) ? -1 : 0;
+       return git_str_oom(buf) ? -1 : 0;
 }
 
 static bool matches_pattern(
index 322d0bda908a7cf68329120a59410b8b3d60204f..499315e6ce2b37987edaa083094635766d7e4eaf 100644 (file)
--- a/src/net.h
+++ b/src/net.h
@@ -21,12 +21,18 @@ typedef struct git_net_url {
 
 #define GIT_NET_URL_INIT { NULL }
 
+/** Is a given string a url? */
+extern bool git_net_str_is_url(const char *str);
+
 /** Duplicate a URL */
 extern int git_net_url_dup(git_net_url *out, git_net_url *in);
 
-/** Parses a string containing a URL into a structure.  */
+/** Parses a string containing a URL into a structure. */
 extern int git_net_url_parse(git_net_url *url, const char *str);
 
+/** Parses a string containing an SCP style path into a URL structure. */
+extern int git_net_url_parse_scp(git_net_url *url, const char *str);
+
 /** Appends a path and/or query string to the given URL */
 extern int git_net_url_joinpath(
        git_net_url *out,
@@ -46,16 +52,17 @@ extern bool git_net_url_is_ipv6(git_net_url *url);
 extern int git_net_url_apply_redirect(
        git_net_url *url,
        const char *redirect_location,
+       bool allow_offsite,
        const char *service_suffix);
 
 /** Swaps the contents of one URL for another.  */
 extern void git_net_url_swap(git_net_url *a, git_net_url *b);
 
 /** Places the URL into the given buffer. */
-extern int git_net_url_fmt(git_buf *out, git_net_url *url);
+extern int git_net_url_fmt(git_str *out, git_net_url *url);
 
 /** Place the path and query string into the given buffer. */
-extern int git_net_url_fmt_path(git_buf *buf, git_net_url *url);
+extern int git_net_url_fmt_path(git_str *buf, git_net_url *url);
 
 /** Determines if the url matches given pattern or pattern list */
 extern bool git_net_url_matches_pattern(
index a1ee2927cd9f2b43ab87ee1529fde40d397724ff..0a27365b8aec8b2051d1849d76768e808c6d1710 100644 (file)
@@ -11,7 +11,7 @@
 #include "git2/errors.h"
 
 #include "posix.h"
-#include "buffer.h"
+#include "str.h"
 #include "http_parser.h"
 #include "runtime.h"
 
index 7140b39bc45c933d001d333fc7c8046e1c918f7b..56f96853459995d98a5e1f7802a7176650fe1e9f 100644 (file)
@@ -42,7 +42,7 @@ typedef struct gitno_buffer {
 /* Flags to gitno_connect */
 enum {
        /* Attempt to create an SSL connection. */
-       GITNO_CONNECT_SSL = 1,
+       GITNO_CONNECT_SSL = 1
 };
 
 /**
index 95db334fb83937a059780ee8d8ddcdc6c9e7c560..d1a2b0f64293780742294f5676933d57be3ff4e5 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "notes.h"
 
-#include "git2.h"
+#include "buf.h"
 #include "refs.h"
 #include "config.h"
 #include "iterator.h"
@@ -407,7 +407,7 @@ cleanup:
        return error;
 }
 
-static int note_get_default_ref(git_buf *out, git_repository *repo)
+static int note_get_default_ref(git_str *out, git_repository *repo)
 {
        git_config *cfg;
        int error;
@@ -415,25 +415,25 @@ static int note_get_default_ref(git_buf *out, git_repository *repo)
        if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
                return error;
 
-       error = git_config_get_string_buf(out, cfg, "core.notesref");
+       error = git_config__get_string_buf(out, cfg, "core.notesref");
 
        if (error == GIT_ENOTFOUND)
-               error = git_buf_puts(out, GIT_NOTES_DEFAULT_REF);
+               error = git_str_puts(out, GIT_NOTES_DEFAULT_REF);
 
        return error;
 }
 
-static int normalize_namespace(git_buf *out, git_repository *repo, const char *notes_ref)
+static int normalize_namespace(git_str *out, git_repository *repo, const char *notes_ref)
 {
        if (notes_ref)
-               return git_buf_puts(out, notes_ref);
+               return git_str_puts(out, notes_ref);
 
        return note_get_default_ref(out, repo);
 }
 
 static int retrieve_note_commit(
        git_commit **commit_out,
-       git_buf *notes_ref_out,
+       git_str *notes_ref_out,
        git_repository *repo,
        const char *notes_ref)
 {
@@ -478,7 +478,7 @@ int git_note_read(git_note **out, git_repository *repo,
                  const char *notes_ref_in, const git_oid *oid)
 {
        int error;
-       git_buf notes_ref = GIT_BUF_INIT;
+       git_str notes_ref = GIT_STR_INIT;
        git_commit *commit = NULL;
 
        error = retrieve_note_commit(&commit, &notes_ref, repo, notes_ref_in);
@@ -489,7 +489,7 @@ int git_note_read(git_note **out, git_repository *repo,
        error = git_note_commit_read(out, repo, commit, oid);
 
 cleanup:
-       git_buf_dispose(&notes_ref);
+       git_str_dispose(&notes_ref);
        git_commit_free(commit);
        return error;
 }
@@ -536,7 +536,7 @@ int git_note_create(
        int allow_note_overwrite)
 {
        int error;
-       git_buf notes_ref = GIT_BUF_INIT;
+       git_str notes_ref = GIT_STR_INIT;
        git_commit *existing_notes_commit = NULL;
        git_reference *ref = NULL;
        git_oid notes_blob_oid, notes_commit_oid;
@@ -562,7 +562,7 @@ int git_note_create(
                git_oid_cpy(out, &notes_blob_oid);
 
 cleanup:
-       git_buf_dispose(&notes_ref);
+       git_str_dispose(&notes_ref);
        git_commit_free(existing_notes_commit);
        git_reference_free(ref);
        return error;
@@ -598,7 +598,7 @@ int git_note_remove(git_repository *repo, const char *notes_ref_in,
                const git_oid *oid)
 {
        int error;
-       git_buf notes_ref_target = GIT_BUF_INIT;
+       git_str notes_ref_target = GIT_STR_INIT;
        git_commit *existing_notes_commit = NULL;
        git_oid new_notes_commit;
        git_reference *notes_ref = NULL;
@@ -618,7 +618,7 @@ int git_note_remove(git_repository *repo, const char *notes_ref_in,
                        &new_notes_commit, 1, NULL);
 
 cleanup:
-       git_buf_dispose(&notes_ref_target);
+       git_str_dispose(&notes_ref_target);
        git_reference_free(notes_ref);
        git_commit_free(existing_notes_commit);
        return error;
@@ -626,16 +626,7 @@ cleanup:
 
 int git_note_default_ref(git_buf *out, git_repository *repo)
 {
-       int error;
-
-       GIT_ASSERT_ARG(out);
-       GIT_ASSERT_ARG(repo);
-
-       if ((error = git_buf_sanitize(out)) < 0 ||
-           (error = note_get_default_ref(out, repo)) < 0)
-               git_buf_dispose(out);
-
-       return error;
+       GIT_BUF_WRAP_PRIVATE(out, note_get_default_ref, repo);
 }
 
 const git_signature *git_note_committer(const git_note *note)
@@ -679,12 +670,12 @@ static int process_entry_path(
 {
        int error = 0;
        size_t i = 0, j = 0, len;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
-       if ((error = git_buf_puts(&buf, entry_path)) < 0)
+       if ((error = git_str_puts(&buf, entry_path)) < 0)
                goto cleanup;
 
-       len = git_buf_len(&buf);
+       len = git_str_len(&buf);
 
        while (i < len) {
                if (buf.ptr[i] == '/') {
@@ -715,7 +706,7 @@ static int process_entry_path(
        error = git_oid_fromstr(annotated_object_id, buf.ptr);
 
 cleanup:
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
@@ -780,7 +771,7 @@ int git_note_iterator_new(
 {
        int error;
        git_commit *commit = NULL;
-       git_buf notes_ref = GIT_BUF_INIT;
+       git_str notes_ref = GIT_STR_INIT;
 
        error = retrieve_note_commit(&commit, &notes_ref, repo, notes_ref_in);
        if (error < 0)
@@ -789,7 +780,7 @@ int git_note_iterator_new(
        error = git_note_commit_iterator_new(it, commit);
 
 cleanup:
-       git_buf_dispose(&notes_ref);
+       git_str_dispose(&notes_ref);
        git_commit_free(commit);
 
        return error;
index 42e1e46bcc515f143eeba9279a366e5790feac80..7bc256fcebd68fa0cb54688f71e0081879269e42 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "repository.h"
 
+#include "buf.h"
 #include "commit.h"
 #include "hash.h"
 #include "tree.h"
@@ -143,12 +144,17 @@ int git_object__from_odb_object(
        def = &git_objects_table[odb_obj->cached.type];
        GIT_ASSERT(def->free && def->parse);
 
-       if ((error = def->parse(object, odb_obj)) < 0)
+       if ((error = def->parse(object, odb_obj)) < 0) {
+               /*
+                * parse returns EINVALID on invalid data; downgrade
+                * that to a normal -1 error code.
+                */
                def->free(object);
-       else
-               *object_out = git_cache_store_parsed(&repo->objects, object);
+               return -1;
+       }
 
-       return error;
+       *object_out = git_cache_store_parsed(&repo->objects, object);
+       return 0;
 }
 
 void git_object__free(void *obj)
@@ -491,7 +497,7 @@ cleanup:
        return error;
 }
 
-int git_object_short_id(git_buf *out, const git_object *obj)
+static int git_object__short_id(git_str *out, const git_object *obj)
 {
        git_repository *repo;
        int len = GIT_ABBREV_DEFAULT, error;
@@ -501,9 +507,6 @@ int git_object_short_id(git_buf *out, const git_object *obj)
        GIT_ASSERT_ARG(out);
        GIT_ASSERT_ARG(obj);
 
-       if ((error = git_buf_sanitize(out)) < 0)
-               return error;
-
        repo = git_object_owner(obj);
 
        if ((error = git_repository__configmap_lookup(&len, repo, GIT_CONFIGMAP_ABBREV)) < 0)
@@ -526,7 +529,7 @@ int git_object_short_id(git_buf *out, const git_object *obj)
                len++;
        }
 
-       if (!error && !(error = git_buf_grow(out, len + 1))) {
+       if (!error && !(error = git_str_grow(out, len + 1))) {
                git_oid_tostr(out->ptr, len + 1, &id);
                out->size = len;
        }
@@ -536,6 +539,11 @@ int git_object_short_id(git_buf *out, const git_object *obj)
        return error;
 }
 
+int git_object_short_id(git_buf *out, const git_object *obj)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_object__short_id, obj);
+}
+
 bool git_object__is_valid(
        git_repository *repo, const git_oid *id, git_object_t expected_type)
 {
@@ -559,3 +567,35 @@ bool git_object__is_valid(
 
        return true;
 }
+
+int git_object_rawcontent_is_valid(
+       int *valid,
+       const char *buf,
+       size_t len,
+       git_object_t type)
+{
+       git_object *obj = NULL;
+       int error;
+
+       GIT_ASSERT_ARG(valid);
+       GIT_ASSERT_ARG(buf);
+
+       /* Blobs are always valid; don't bother parsing. */
+       if (type == GIT_OBJECT_BLOB) {
+               *valid = 1;
+               return 0;
+       }
+
+       error = git_object__from_raw(&obj, buf, len, type);
+       git_object_free(obj);
+
+       if (error == 0) {
+               *valid = 1;
+               return 0;
+       } else if (error == GIT_EINVALID) {
+               *valid = 0;
+               return 0;
+       }
+
+       return error;
+}
index 4b67936127e890ecac00aa59c1e2048dfcffd9bb..66be57557e774135eea70c9939c12181b71d65fa 100644 (file)
@@ -47,7 +47,7 @@ git_object_t git_object_stringn2type(const char *str, size_t len);
 
 int git_oid__parse(git_oid *oid, const char **buffer_out, const char *buffer_end, const char *header);
 
-void git_oid__writebuf(git_buf *buf, const char *header, const git_oid *oid);
+void git_oid__writebuf(git_str *buf, const char *header, const git_oid *oid);
 
 bool git_object__is_valid(
        git_repository *repo, const git_oid *id, git_object_t expected_type);
index 7834e5f15cff9c9bc487efc03b5d061b0dc390c1..14eff53c7b88d57ea9055762ab5f818234444829 100644 (file)
--- a/src/odb.c
+++ b/src/odb.c
@@ -16,6 +16,7 @@
 #include "filter.h"
 #include "repository.h"
 #include "blob.h"
+#include "oid.h"
 
 #include "git2/odb_backend.h"
 #include "git2/oid.h"
@@ -58,10 +59,7 @@ static int error_null_oid(int error, const char *message);
 
 static git_object_t odb_hardcoded_type(const git_oid *id)
 {
-       static git_oid empty_tree = {{ 0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
-                                          0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04 }};
-
-       if (!git_oid_cmp(id, &empty_tree))
+       if (!git_oid_cmp(id, &git_oid__empty_tree_sha1))
                return GIT_OBJECT_TREE;
 
        return GIT_OBJECT_INVALID;
@@ -109,7 +107,7 @@ int git_odb__format_object_header(
 
 int git_odb__hashobj(git_oid *id, git_rawobj *obj)
 {
-       git_buf_vec vec[2];
+       git_str_vec vec[2];
        char header[64];
        size_t hdrlen;
        int error;
@@ -136,7 +134,7 @@ int git_odb__hashobj(git_oid *id, git_rawobj *obj)
        vec[1].data = obj->data;
        vec[1].len = obj->len;
 
-       return git_hash_vec(id, vec, 2);
+       return git_hash_vec(id->id, vec, 2, GIT_HASH_ALGORITHM_SHA1);
 }
 
 
@@ -210,7 +208,7 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_object_t type)
                return -1;
        }
 
-       if ((error = git_hash_ctx_init(&ctx)) < 0)
+       if ((error = git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA1)) < 0)
                return error;
 
        if ((error = git_odb__format_object_header(&hdr_len, hdr,
@@ -237,7 +235,7 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_object_t type)
                goto done;
        }
 
-       error = git_hash_final(out, &ctx);
+       error = git_hash_final(out->id, &ctx);
 
 done:
        git_hash_ctx_cleanup(&ctx);
@@ -248,7 +246,7 @@ int git_odb__hashfd_filtered(
        git_oid *out, git_file fd, size_t size, git_object_t type, git_filter_list *fl)
 {
        int error;
-       git_buf raw = GIT_BUF_INIT;
+       git_str raw = GIT_STR_INIT;
 
        if (!fl)
                return git_odb__hashfd(out, fd, size, type);
@@ -258,14 +256,14 @@ int git_odb__hashfd_filtered(
         */
 
        if (!(error = git_futils_readbuffer_fd(&raw, fd, size))) {
-               git_buf post = GIT_BUF_INIT;
+               git_str post = GIT_STR_INIT;
 
                error = git_filter_list__convert_buf(&post, fl, &raw);
 
                if (!error)
                        error = git_odb_hash(out, post.ptr, post.size, type);
 
-               git_buf_dispose(&post);
+               git_str_dispose(&post);
        }
 
        return error;
@@ -277,7 +275,7 @@ int git_odb__hashlink(git_oid *out, const char *path)
        int size;
        int result;
 
-       if (git_path_lstat(path, &st) < 0)
+       if (git_fs_path_lstat(path, &st) < 0)
                return -1;
 
        if (!git__is_int(st.st_size) || (int)st.st_size < 0) {
@@ -636,8 +634,8 @@ int git_odb__add_default_backends(
 
 static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_depth)
 {
-       git_buf alternates_path = GIT_BUF_INIT;
-       git_buf alternates_buf = GIT_BUF_INIT;
+       git_str alternates_path = GIT_STR_INIT;
+       git_str alternates_buf = GIT_STR_INIT;
        char *buffer;
        const char *alternate;
        int result = 0;
@@ -646,16 +644,16 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_
        if (alternate_depth > GIT_ALTERNATES_MAX_DEPTH)
                return 0;
 
-       if (git_buf_joinpath(&alternates_path, objects_dir, GIT_ALTERNATES_FILE) < 0)
+       if (git_str_joinpath(&alternates_path, objects_dir, GIT_ALTERNATES_FILE) < 0)
                return -1;
 
-       if (git_path_exists(alternates_path.ptr) == false) {
-               git_buf_dispose(&alternates_path);
+       if (git_fs_path_exists(alternates_path.ptr) == false) {
+               git_str_dispose(&alternates_path);
                return 0;
        }
 
        if (git_futils_readbuffer(&alternates_buf, alternates_path.ptr) < 0) {
-               git_buf_dispose(&alternates_path);
+               git_str_dispose(&alternates_path);
                return -1;
        }
 
@@ -672,17 +670,17 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_
                 * the current repository.
                 */
                if (*alternate == '.' && !alternate_depth) {
-                       if ((result = git_buf_joinpath(&alternates_path, objects_dir, alternate)) < 0)
+                       if ((result = git_str_joinpath(&alternates_path, objects_dir, alternate)) < 0)
                                break;
-                       alternate = git_buf_cstr(&alternates_path);
+                       alternate = git_str_cstr(&alternates_path);
                }
 
                if ((result = git_odb__add_default_backends(odb, alternate, true, alternate_depth + 1)) < 0)
                        break;
        }
 
-       git_buf_dispose(&alternates_path);
-       git_buf_dispose(&alternates_buf);
+       git_str_dispose(&alternates_path);
+       git_str_dispose(&alternates_buf);
 
        return result;
 }
@@ -882,6 +880,11 @@ int git_odb__freshen(git_odb *db, const git_oid *id)
 }
 
 int git_odb_exists(git_odb *db, const git_oid *id)
+{
+    return git_odb_exists_ext(db, id, 0);
+}
+
+int git_odb_exists_ext(git_odb *db, const git_oid *id, unsigned int flags)
 {
        git_odb_object *object;
 
@@ -899,7 +902,7 @@ int git_odb_exists(git_odb *db, const git_oid *id)
        if (odb_exists_1(db, id, false))
                return 1;
 
-       if (!git_odb_refresh(db))
+       if (!(flags & GIT_ODB_LOOKUP_NO_REFRESH) && !git_odb_refresh(db))
                return odb_exists_1(db, id, true);
 
        /* Failed to refresh, hence not found */
@@ -1337,15 +1340,15 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
                        data = raw.data;
 
                        if (found && git_oid__cmp(&full_oid, &found_full_oid)) {
-                               git_buf buf = GIT_BUF_INIT;
+                               git_str buf = GIT_STR_INIT;
 
-                               git_buf_printf(&buf, "multiple matches for prefix: %s",
+                               git_str_printf(&buf, "multiple matches for prefix: %s",
                                        git_oid_tostr_s(&full_oid));
-                               git_buf_printf(&buf, " %s",
+                               git_str_printf(&buf, " %s",
                                        git_oid_tostr_s(&found_full_oid));
 
                                error = git_odb__error_ambiguous(buf.ptr);
-                               git_buf_dispose(&buf);
+                               git_str_dispose(&buf);
                                git_mutex_unlock(&db->lock);
                                goto out;
                        }
@@ -1496,10 +1499,10 @@ int git_odb_write(
        if ((error = git_odb_open_wstream(&stream, db, len, type)) != 0)
                return error;
 
-       stream->write(stream, data, len);
-       error = stream->finalize_write(stream, oid);
-       git_odb_stream_free(stream);
+       if ((error = stream->write(stream, data, len)) == 0)
+               error = stream->finalize_write(stream, oid);
 
+       git_odb_stream_free(stream);
        return error;
 }
 
@@ -1561,7 +1564,7 @@ int git_odb_open_wstream(
        ctx = git__malloc(sizeof(git_hash_ctx));
        GIT_ERROR_CHECK_ALLOC(ctx);
 
-       if ((error = git_hash_ctx_init(ctx)) < 0 ||
+       if ((error = git_hash_ctx_init(ctx, GIT_HASH_ALGORITHM_SHA1)) < 0 ||
                (error = hash_header(ctx, size, type)) < 0)
                goto done;
 
@@ -1607,7 +1610,7 @@ int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream)
                return git_odb_stream__invalid_length(stream,
                        "stream_finalize_write()");
 
-       git_hash_final(out, stream->hash_ctx);
+       git_hash_final(out->id, stream->hash_ctx);
 
        if (git_odb__freshen(stream->backend->odb, out))
                return 0;
index 4a8ebff191386dd51ee627300e95a397b18a9669..5aa4cc84a4ce3ced2d5a49741c6854353eff5c73 100644 (file)
--- a/src/odb.h
+++ b/src/odb.h
@@ -53,7 +53,7 @@ struct git_odb {
 };
 
 typedef enum {
-       GIT_ODB_CAP_FROM_OWNER = -1,
+       GIT_ODB_CAP_FROM_OWNER = -1
 } git_odb_cap_t;
 
 /*
index b0abbbf4c2731372c8c66440a461477c8e56b5e5..463e24fa52b21f0e6188ddfe43c09201eab34254 100644 (file)
@@ -76,18 +76,18 @@ typedef struct {
  ***********************************************************/
 
 static int object_file_name(
-       git_buf *name, const loose_backend *be, const git_oid *id)
+       git_str *name, const loose_backend *be, const git_oid *id)
 {
        size_t alloclen;
 
        /* expand length for object root + 40 hex sha1 chars + 2 * '/' + '\0' */
        GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, be->objects_dirlen, GIT_OID_HEXSZ);
        GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 3);
-       if (git_buf_grow(name, alloclen) < 0)
+       if (git_str_grow(name, alloclen) < 0)
                return -1;
 
-       git_buf_set(name, be->objects_dir, be->objects_dirlen);
-       git_path_to_dir(name);
+       git_str_set(name, be->objects_dir, be->objects_dirlen);
+       git_fs_path_to_dir(name);
 
        /* loose object filename: aa/aaa... (41 bytes) */
        git_oid_pathfmt(name->ptr + name->size, id);
@@ -97,7 +97,7 @@ static int object_file_name(
        return 0;
 }
 
-static int object_mkdir(const git_buf *name, const loose_backend *be)
+static int object_mkdir(const git_str *name, const loose_backend *be)
 {
        return git_futils_mkdir_relative(
                name->ptr + be->objects_dirlen, be->objects_dir, be->object_dir_mode,
@@ -222,9 +222,9 @@ static int is_zlib_compressed_data(unsigned char *data, size_t data_len)
  * of loose object data into packs. This format is no longer used, but
  * we must still read it.
  */
-static int read_loose_packlike(git_rawobj *out, git_buf *obj)
+static int read_loose_packlike(git_rawobj *out, git_str *obj)
 {
-       git_buf body = GIT_BUF_INIT;
+       git_str body = GIT_STR_INIT;
        const unsigned char *obj_data;
        obj_hdr hdr;
        size_t obj_len, head_len, alloc_size;
@@ -253,7 +253,7 @@ static int read_loose_packlike(git_rawobj *out, git_buf *obj)
         * allocate a buffer and inflate the data into it
         */
        if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, hdr.size, 1) ||
-               git_buf_init(&body, alloc_size) < 0) {
+               git_str_init(&body, alloc_size) < 0) {
                error = -1;
                goto done;
        }
@@ -263,14 +263,14 @@ static int read_loose_packlike(git_rawobj *out, git_buf *obj)
 
        out->len = hdr.size;
        out->type = hdr.type;
-       out->data = git_buf_detach(&body);
+       out->data = git_str_detach(&body);
 
 done:
-       git_buf_dispose(&body);
+       git_str_dispose(&body);
        return error;
 }
 
-static int read_loose_standard(git_rawobj *out, git_buf *obj)
+static int read_loose_standard(git_rawobj *out, git_str *obj)
 {
        git_zstream zstream = GIT_ZSTREAM_INIT;
        unsigned char head[MAX_HEADER_LEN], *body = NULL;
@@ -279,7 +279,7 @@ static int read_loose_standard(git_rawobj *out, git_buf *obj)
        int error;
 
        if ((error = git_zstream_init(&zstream, GIT_ZSTREAM_INFLATE)) < 0 ||
-               (error = git_zstream_set_input(&zstream, git_buf_cstr(obj), git_buf_len(obj))) < 0)
+               (error = git_zstream_set_input(&zstream, git_str_cstr(obj), git_str_len(obj))) < 0)
                goto done;
 
        decompressed = sizeof(head);
@@ -339,15 +339,15 @@ done:
        return error;
 }
 
-static int read_loose(git_rawobj *out, git_buf *loc)
+static int read_loose(git_rawobj *out, git_str *loc)
 {
        int error;
-       git_buf obj = GIT_BUF_INIT;
+       git_str obj = GIT_STR_INIT;
 
        GIT_ASSERT_ARG(out);
        GIT_ASSERT_ARG(loc);
 
-       if (git_buf_oom(loc))
+       if (git_str_oom(loc))
                return -1;
 
        out->data = NULL;
@@ -363,7 +363,7 @@ static int read_loose(git_rawobj *out, git_buf *loc)
                error = read_loose_standard(out, &obj);
 
 done:
-       git_buf_dispose(&obj);
+       git_str_dispose(&obj);
        return error;
 }
 
@@ -406,7 +406,7 @@ done:
        return error;
 }
 
-static int read_header_loose(git_rawobj *out, git_buf *loc)
+static int read_header_loose(git_rawobj *out, git_str *loc)
 {
        unsigned char obj[1024];
        ssize_t obj_len;
@@ -415,7 +415,7 @@ static int read_header_loose(git_rawobj *out, git_buf *loc)
        GIT_ASSERT_ARG(out);
        GIT_ASSERT_ARG(loc);
 
-       if (git_buf_oom(loc))
+       if (git_str_oom(loc))
                return -1;
 
        out->data = NULL;
@@ -446,28 +446,28 @@ done:
 }
 
 static int locate_object(
-       git_buf *object_location,
+       git_str *object_location,
        loose_backend *backend,
        const git_oid *oid)
 {
        int error = object_file_name(object_location, backend, oid);
 
-       if (!error && !git_path_exists(object_location->ptr))
+       if (!error && !git_fs_path_exists(object_location->ptr))
                return GIT_ENOTFOUND;
 
        return error;
 }
 
 /* Explore an entry of a directory and see if it matches a short oid */
-static int fn_locate_object_short_oid(void *state, git_buf *pathbuf) {
+static int fn_locate_object_short_oid(void *state, git_str *pathbuf) {
        loose_locate_object_state *sstate = (loose_locate_object_state *)state;
 
-       if (git_buf_len(pathbuf) - sstate->dir_len != GIT_OID_HEXSZ - 2) {
+       if (git_str_len(pathbuf) - sstate->dir_len != GIT_OID_HEXSZ - 2) {
                /* Entry cannot be an object. Continue to next entry */
                return 0;
        }
 
-       if (git_path_isdir(pathbuf->ptr) == false) {
+       if (git_fs_path_isdir(pathbuf->ptr) == false) {
                /* We are already in the directory matching the 2 first hex characters,
                 * compare the first ncmp characters of the oids */
                if (!memcmp(sstate->short_oid + 2,
@@ -491,7 +491,7 @@ static int fn_locate_object_short_oid(void *state, git_buf *pathbuf) {
 
 /* Locate an object matching a given short oid */
 static int locate_object_short_oid(
-       git_buf *object_location,
+       git_str *object_location,
        git_oid *res_oid,
        loose_backend *backend,
        const git_oid *short_oid,
@@ -505,34 +505,34 @@ static int locate_object_short_oid(
        /* prealloc memory for OBJ_DIR/xx/xx..38x..xx */
        GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, dir_len, GIT_OID_HEXSZ);
        GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 3);
-       if (git_buf_grow(object_location, alloc_len) < 0)
+       if (git_str_grow(object_location, alloc_len) < 0)
                return -1;
 
-       git_buf_set(object_location, objects_dir, dir_len);
-       git_path_to_dir(object_location);
+       git_str_set(object_location, objects_dir, dir_len);
+       git_fs_path_to_dir(object_location);
 
        /* save adjusted position at end of dir so it can be restored later */
-       dir_len = git_buf_len(object_location);
+       dir_len = git_str_len(object_location);
 
        /* Convert raw oid to hex formatted oid */
        git_oid_fmt((char *)state.short_oid, short_oid);
 
        /* Explore OBJ_DIR/xx/ where xx is the beginning of hex formatted short oid */
-       if (git_buf_put(object_location, (char *)state.short_oid, 3) < 0)
+       if (git_str_put(object_location, (char *)state.short_oid, 3) < 0)
                return -1;
        object_location->ptr[object_location->size - 1] = '/';
 
        /* Check that directory exists */
-       if (git_path_isdir(object_location->ptr) == false)
+       if (git_fs_path_isdir(object_location->ptr) == false)
                return git_odb__error_notfound("no matching loose object for prefix",
                        short_oid, len);
 
-       state.dir_len = git_buf_len(object_location);
+       state.dir_len = git_str_len(object_location);
        state.short_oid_len = len;
        state.found = 0;
 
        /* Explore directory to find a unique object matching short_oid */
-       error = git_path_direach(
+       error = git_fs_path_direach(
                object_location, 0, fn_locate_object_short_oid, &state);
        if (error < 0 && error != GIT_EAMBIGUOUS)
                return error;
@@ -553,8 +553,8 @@ static int locate_object_short_oid(
        GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, dir_len, GIT_OID_HEXSZ);
        GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
 
-       git_buf_truncate(object_location, dir_len);
-       if (git_buf_grow(object_location, alloc_len) < 0)
+       git_str_truncate(object_location, dir_len);
+       if (git_str_grow(object_location, alloc_len) < 0)
                return -1;
 
        git_oid_pathfmt(object_location->ptr + dir_len, res_oid);
@@ -583,7 +583,7 @@ static int locate_object_short_oid(
 
 static int loose_backend__read_header(size_t *len_p, git_object_t *type_p, git_odb_backend *backend, const git_oid *oid)
 {
-       git_buf object_path = GIT_BUF_INIT;
+       git_str object_path = GIT_STR_INIT;
        git_rawobj raw;
        int error;
 
@@ -601,14 +601,14 @@ static int loose_backend__read_header(size_t *len_p, git_object_t *type_p, git_o
                *type_p = raw.type;
        }
 
-       git_buf_dispose(&object_path);
+       git_str_dispose(&object_path);
 
        return error;
 }
 
 static int loose_backend__read(void **buffer_p, size_t *len_p, git_object_t *type_p, git_odb_backend *backend, const git_oid *oid)
 {
-       git_buf object_path = GIT_BUF_INIT;
+       git_str object_path = GIT_STR_INIT;
        git_rawobj raw;
        int error = 0;
 
@@ -624,7 +624,7 @@ static int loose_backend__read(void **buffer_p, size_t *len_p, git_object_t *typ
                *type_p = raw.type;
        }
 
-       git_buf_dispose(&object_path);
+       git_str_dispose(&object_path);
 
        return error;
 }
@@ -648,7 +648,7 @@ static int loose_backend__read_prefix(
                if (!error)
                        git_oid_cpy(out_oid, short_oid);
        } else {
-               git_buf object_path = GIT_BUF_INIT;
+               git_str object_path = GIT_STR_INIT;
                git_rawobj raw;
 
                GIT_ASSERT_ARG(backend && short_oid);
@@ -662,7 +662,7 @@ static int loose_backend__read_prefix(
                        *type_p = raw.type;
                }
 
-               git_buf_dispose(&object_path);
+               git_str_dispose(&object_path);
        }
 
        return error;
@@ -670,7 +670,7 @@ static int loose_backend__read_prefix(
 
 static int loose_backend__exists(git_odb_backend *backend, const git_oid *oid)
 {
-       git_buf object_path = GIT_BUF_INIT;
+       git_str object_path = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(backend);
@@ -678,7 +678,7 @@ static int loose_backend__exists(git_odb_backend *backend, const git_oid *oid)
 
        error = locate_object(&object_path, (loose_backend *)backend, oid);
 
-       git_buf_dispose(&object_path);
+       git_str_dispose(&object_path);
 
        return !error;
 }
@@ -686,7 +686,7 @@ static int loose_backend__exists(git_odb_backend *backend, const git_oid *oid)
 static int loose_backend__exists_prefix(
        git_oid *out, git_odb_backend *backend, const git_oid *short_id, size_t len)
 {
-       git_buf object_path = GIT_BUF_INIT;
+       git_str object_path = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(backend);
@@ -697,7 +697,7 @@ static int loose_backend__exists_prefix(
        error = locate_object_short_oid(
                &object_path, out, (loose_backend *)backend, short_id, len);
 
-       git_buf_dispose(&object_path);
+       git_str_dispose(&object_path);
 
        return error;
 }
@@ -736,7 +736,7 @@ GIT_INLINE(int) filename_to_oid(git_oid *oid, const char *ptr)
        return 0;
 }
 
-static int foreach_object_dir_cb(void *_state, git_buf *path)
+static int foreach_object_dir_cb(void *_state, git_str *path)
 {
        git_oid oid;
        struct foreach_state *state = (struct foreach_state *) _state;
@@ -748,22 +748,22 @@ static int foreach_object_dir_cb(void *_state, git_buf *path)
                state->cb(&oid, state->data), "git_odb_foreach");
 }
 
-static int foreach_cb(void *_state, git_buf *path)
+static int foreach_cb(void *_state, git_str *path)
 {
        struct foreach_state *state = (struct foreach_state *) _state;
 
        /* non-dir is some stray file, ignore it */
-       if (!git_path_isdir(git_buf_cstr(path)))
+       if (!git_fs_path_isdir(git_str_cstr(path)))
                return 0;
 
-       return git_path_direach(path, 0, foreach_object_dir_cb, state);
+       return git_fs_path_direach(path, 0, foreach_object_dir_cb, state);
 }
 
 static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb cb, void *data)
 {
        char *objects_dir;
        int error;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        struct foreach_state state;
        loose_backend *backend = (loose_backend *) _backend;
 
@@ -772,19 +772,19 @@ static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb
 
        objects_dir = backend->objects_dir;
 
-       git_buf_sets(&buf, objects_dir);
-       git_path_to_dir(&buf);
-       if (git_buf_oom(&buf))
+       git_str_sets(&buf, objects_dir);
+       git_fs_path_to_dir(&buf);
+       if (git_str_oom(&buf))
                return -1;
 
        memset(&state, 0, sizeof(state));
        state.cb = cb;
        state.data = data;
-       state.dir_len = git_buf_len(&buf);
+       state.dir_len = git_str_len(&buf);
 
-       error = git_path_direach(&buf, 0, foreach_cb, &state);
+       error = git_fs_path_direach(&buf, 0, foreach_cb, &state);
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        return error;
 }
@@ -793,7 +793,7 @@ static int loose_backend__writestream_finalize(git_odb_stream *_stream, const gi
 {
        loose_writestream *stream = (loose_writestream *)_stream;
        loose_backend *backend = (loose_backend *)_stream->backend;
-       git_buf final_path = GIT_BUF_INIT;
+       git_str final_path = GIT_STR_INIT;
        int error = 0;
 
        if (object_file_name(&final_path, backend, oid) < 0 ||
@@ -803,7 +803,7 @@ static int loose_backend__writestream_finalize(git_odb_stream *_stream, const gi
                error = git_filebuf_commit_at(
                        &stream->fbuf, final_path.ptr);
 
-       git_buf_dispose(&final_path);
+       git_str_dispose(&final_path);
 
        return error;
 }
@@ -838,7 +838,7 @@ static int loose_backend__writestream(git_odb_stream **stream_out, git_odb_backe
        loose_backend *backend;
        loose_writestream *stream = NULL;
        char hdr[MAX_HEADER_LEN];
-       git_buf tmp_path = GIT_BUF_INIT;
+       git_str tmp_path = GIT_STR_INIT;
        size_t hdrlen;
        int error;
 
@@ -861,7 +861,7 @@ static int loose_backend__writestream(git_odb_stream **stream_out, git_odb_backe
        stream->stream.free = &loose_backend__writestream_free;
        stream->stream.mode = GIT_STREAM_WRONLY;
 
-       if (git_buf_joinpath(&tmp_path, backend->objects_dir, "tmp_object") < 0 ||
+       if (git_str_joinpath(&tmp_path, backend->objects_dir, "tmp_object") < 0 ||
                git_filebuf_open(&stream->fbuf, tmp_path.ptr, filebuf_flags(backend),
                        backend->object_file_mode) < 0 ||
                stream->stream.write((git_odb_stream *)stream, hdr, hdrlen) < 0)
@@ -870,7 +870,7 @@ static int loose_backend__writestream(git_odb_stream **stream_out, git_odb_backe
                git__free(stream);
                stream = NULL;
        }
-       git_buf_dispose(&tmp_path);
+       git_str_dispose(&tmp_path);
        *stream_out = (git_odb_stream *)stream;
 
        return !stream ? -1 : 0;
@@ -996,7 +996,7 @@ static int loose_backend__readstream(
        loose_backend *backend;
        loose_readstream *stream = NULL;
        git_hash_ctx *hash_ctx = NULL;
-       git_buf object_path = GIT_BUF_INIT;
+       git_str object_path = GIT_STR_INIT;
        obj_hdr hdr;
        int error = 0;
 
@@ -1023,7 +1023,7 @@ static int loose_backend__readstream(
        hash_ctx = git__malloc(sizeof(git_hash_ctx));
        GIT_ERROR_CHECK_ALLOC(hash_ctx);
 
-       if ((error = git_hash_ctx_init(hash_ctx)) < 0 ||
+       if ((error = git_hash_ctx_init(hash_ctx, GIT_HASH_ALGORITHM_SHA1)) < 0 ||
                (error = git_futils_mmap_ro_file(&stream->map, object_path.ptr)) < 0 ||
                (error = git_zstream_init(&stream->zstream, GIT_ZSTREAM_INFLATE)) < 0)
                goto done;
@@ -1059,14 +1059,14 @@ done:
                }
        }
 
-       git_buf_dispose(&object_path);
+       git_str_dispose(&object_path);
        return error;
 }
 
 static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, const void *data, size_t len, git_object_t type)
 {
        int error = 0;
-       git_buf final_path = GIT_BUF_INIT;
+       git_str final_path = GIT_STR_INIT;
        char header[MAX_HEADER_LEN];
        size_t header_len;
        git_filebuf fbuf = GIT_FILEBUF_INIT;
@@ -1079,7 +1079,7 @@ static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, c
                header, sizeof(header), len, type)) < 0)
                goto cleanup;
 
-       if (git_buf_joinpath(&final_path, backend->objects_dir, "tmp_object") < 0 ||
+       if (git_str_joinpath(&final_path, backend->objects_dir, "tmp_object") < 0 ||
                git_filebuf_open(&fbuf, final_path.ptr, filebuf_flags(backend),
                        backend->object_file_mode) < 0)
        {
@@ -1098,7 +1098,7 @@ static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, c
 cleanup:
        if (error < 0)
                git_filebuf_cleanup(&fbuf);
-       git_buf_dispose(&final_path);
+       git_str_dispose(&final_path);
        return error;
 }
 
@@ -1107,14 +1107,14 @@ static int loose_backend__freshen(
        const git_oid *oid)
 {
        loose_backend *backend = (loose_backend *)_backend;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        int error;
 
        if (object_file_name(&path, backend, oid) < 0)
                return -1;
 
        error = git_futils_touch(path.ptr, NULL);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return error;
 }
index d08356a8d44ad2c16ad9998df9d3bd52edcde3ac..6f27f45f870975f4ec53879e5d680db7101c0f35 100644 (file)
@@ -7,18 +7,20 @@
 
 #include "common.h"
 
-#include "git2/object.h"
-#include "git2/sys/odb_backend.h"
-#include "git2/sys/mempack.h"
+#include "buf.h"
 #include "futils.h"
 #include "hash.h"
 #include "odb.h"
 #include "array.h"
 #include "oidmap.h"
+#include "pack-objects.h"
 
 #include "git2/odb_backend.h"
+#include "git2/object.h"
 #include "git2/types.h"
 #include "git2/pack.h"
+#include "git2/sys/odb_backend.h"
+#include "git2/sys/mempack.h"
 
 struct memobject {
        git_oid oid;
@@ -100,7 +102,10 @@ static int impl__read_header(size_t *len_p, git_object_t *type_p, git_odb_backen
        return 0;
 }
 
-int git_mempack_dump(git_buf *pack, git_repository *repo, git_odb_backend *_backend)
+static int git_mempack__dump(
+       git_str *pack,
+       git_repository *repo,
+       git_odb_backend *_backend)
 {
        struct memory_packer_db *db = (struct memory_packer_db *)_backend;
        git_packbuilder *packbuilder;
@@ -120,13 +125,21 @@ int git_mempack_dump(git_buf *pack, git_repository *repo, git_odb_backend *_back
                        goto cleanup;
        }
 
-       err = git_packbuilder_write_buf(pack, packbuilder);
+       err = git_packbuilder__write_buf(pack, packbuilder);
 
 cleanup:
        git_packbuilder_free(packbuilder);
        return err;
 }
 
+int git_mempack_dump(
+       git_buf *pack,
+       git_repository *repo,
+       git_odb_backend *_backend)
+{
+       GIT_BUF_WRAP_PRIVATE(pack, git_mempack__dump, repo, _backend);
+}
+
 int git_mempack_reset(git_odb_backend *_backend)
 {
        struct memory_packer_db *db = (struct memory_packer_db *)_backend;
index f4cb9a558b7b5cc2f0c60a77b8f73469ee87d73c..818cc6125d576b91e07be333db7b75cfbb2042da 100644 (file)
@@ -115,7 +115,7 @@ struct pack_writepack {
  *     | OID can be found. If we can find the offset to that SHA1 inside of the
  *     | index, that means the object is contained inside of the packfile and
  *     | we can stop searching. Before returning, we verify that the
- *     | packfile behing the index we are searching still exists on disk.
+ *     | packfile behind the index we are searching still exists on disk.
  *     |
  *     |-# pack_entry_find_offset
  *       | Mmap the actual index file to disk if it hasn't been opened
@@ -166,7 +166,7 @@ struct pack_writepack {
 
 static int packfile_sort__cb(const void *a_, const void *b_);
 
-static int packfile_load__cb(void *_data, git_buf *path);
+static int packfile_load__cb(void *_data, git_str *path);
 
 static int packfile_byname_search_cmp(const void *path, const void *pack_entry);
 
@@ -195,10 +195,10 @@ static int pack_entry_find_prefix(
 
 static int packfile_byname_search_cmp(const void *path_, const void *p_)
 {
-       const git_buf *path = (const git_buf *)path_;
+       const git_str *path = (const git_str *)path_;
        const struct git_pack_file *p = (const struct git_pack_file *)p_;
 
-       return strncmp(p->pack_name, git_buf_cstr(path), git_buf_len(path));
+       return strncmp(p->pack_name, git_str_cstr(path), git_str_len(path));
 }
 
 static int packfile_sort__cb(const void *a_, const void *b_)
@@ -231,20 +231,20 @@ static int packfile_sort__cb(const void *a_, const void *b_)
 }
 
 
-static int packfile_load__cb(void *data, git_buf *path)
+static int packfile_load__cb(void *data, git_str *path)
 {
        struct pack_backend *backend = data;
        struct git_pack_file *pack;
-       const char *path_str = git_buf_cstr(path);
-       git_buf index_prefix = GIT_BUF_INIT;
-       size_t cmp_len = git_buf_len(path);
+       const char *path_str = git_str_cstr(path);
+       git_str index_prefix = GIT_STR_INIT;
+       size_t cmp_len = git_str_len(path);
        int error;
 
        if (cmp_len <= strlen(".idx") || git__suffixcmp(path_str, ".idx") != 0)
                return 0; /* not an index */
 
        cmp_len -= strlen(".idx");
-       git_buf_attach_notowned(&index_prefix, path_str, cmp_len);
+       git_str_attach_notowned(&index_prefix, path_str, cmp_len);
 
        if (git_vector_search2(NULL, &backend->midx_packs, packfile_byname_search_cmp, &index_prefix) == 0)
                return 0;
@@ -404,29 +404,29 @@ static int process_multi_pack_index_pack(
        int error;
        struct git_pack_file *pack;
        size_t found_position;
-       git_buf pack_path = GIT_BUF_INIT, index_prefix = GIT_BUF_INIT;
+       git_str pack_path = GIT_STR_INIT, index_prefix = GIT_STR_INIT;
 
-       error = git_buf_joinpath(&pack_path, backend->pack_folder, packfile_name);
+       error = git_str_joinpath(&pack_path, backend->pack_folder, packfile_name);
        if (error < 0)
                return error;
 
        /* This is ensured by midx_parse_packfile_name() */
-       if (git_buf_len(&pack_path) <= strlen(".idx") || git__suffixcmp(git_buf_cstr(&pack_path), ".idx") != 0)
+       if (git_str_len(&pack_path) <= strlen(".idx") || git__suffixcmp(git_str_cstr(&pack_path), ".idx") != 0)
                return git_odb__error_notfound("midx file contained a non-index", NULL, 0);
 
-       git_buf_attach_notowned(&index_prefix, git_buf_cstr(&pack_path), git_buf_len(&pack_path) - strlen(".idx"));
+       git_str_attach_notowned(&index_prefix, git_str_cstr(&pack_path), git_str_len(&pack_path) - strlen(".idx"));
 
        if (git_vector_search2(&found_position, &backend->packs, packfile_byname_search_cmp, &index_prefix) == 0) {
                /* Pack was found in the packs list. Moving it to the midx_packs list. */
-               git_buf_dispose(&pack_path);
+               git_str_dispose(&pack_path);
                git_vector_set(NULL, &backend->midx_packs, i, git_vector_get(&backend->packs, found_position));
                git_vector_remove(&backend->packs, found_position);
                return 0;
        }
 
        /* Pack was not found. Allocate a new one. */
-       error = git_mwindow_get_pack(&pack, git_buf_cstr(&pack_path));
-       git_buf_dispose(&pack_path);
+       error = git_mwindow_get_pack(&pack, git_str_cstr(&pack_path));
+       git_str_dispose(&pack_path);
        if (error < 0)
                return error;
 
@@ -442,11 +442,11 @@ static int process_multi_pack_index_pack(
 static int refresh_multi_pack_index(struct pack_backend *backend)
 {
        int error;
-       git_buf midx_path = GIT_BUF_INIT;
+       git_str midx_path = GIT_STR_INIT;
        const char *packfile_name;
        size_t i;
 
-       error = git_buf_joinpath(&midx_path, backend->pack_folder, "multi-pack-index");
+       error = git_str_joinpath(&midx_path, backend->pack_folder, "multi-pack-index");
        if (error < 0)
                return error;
 
@@ -457,19 +457,19 @@ static int refresh_multi_pack_index(struct pack_backend *backend)
         * refreshing the new multi-pack-index fails, or the file is deleted.
         */
        if (backend->midx) {
-               if (!git_midx_needs_refresh(backend->midx, git_buf_cstr(&midx_path))) {
-                       git_buf_dispose(&midx_path);
+               if (!git_midx_needs_refresh(backend->midx, git_str_cstr(&midx_path))) {
+                       git_str_dispose(&midx_path);
                        return 0;
                }
                error = remove_multi_pack_index(backend);
                if (error < 0) {
-                       git_buf_dispose(&midx_path);
+                       git_str_dispose(&midx_path);
                        return error;
                }
        }
 
-       error = git_midx_open(&backend->midx, git_buf_cstr(&midx_path));
-       git_buf_dispose(&midx_path);
+       error = git_midx_open(&backend->midx, git_str_cstr(&midx_path));
+       git_str_dispose(&midx_path);
        if (error < 0)
                return error;
 
@@ -505,7 +505,7 @@ static int pack_backend__refresh(git_odb_backend *backend_)
 {
        int error;
        struct stat st;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        struct pack_backend *backend = (struct pack_backend *)backend_;
 
        if (backend->pack_folder == NULL)
@@ -523,10 +523,10 @@ static int pack_backend__refresh(git_odb_backend *backend_)
        }
 
        /* reload all packs */
-       git_buf_sets(&path, backend->pack_folder);
-       error = git_path_direach(&path, 0, packfile_load__cb, backend);
+       git_str_sets(&path, backend->pack_folder);
+       error = git_fs_path_direach(&path, 0, packfile_load__cb, backend);
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_vector_sort(&backend->packs);
 
        return error;
@@ -743,21 +743,21 @@ static int pack_backend__writepack(struct git_odb_writepack **out,
 }
 
 static int get_idx_path(
-               git_buf *idx_path,
+               git_str *idx_path,
                struct pack_backend *backend,
                struct git_pack_file *p)
 {
        size_t path_len;
        int error;
 
-       error = git_path_prettify(idx_path, p->pack_name, backend->pack_folder);
+       error = git_fs_path_prettify(idx_path, p->pack_name, backend->pack_folder);
        if (error < 0)
                return error;
-       path_len = git_buf_len(idx_path);
-       if (path_len <= strlen(".pack") || git__suffixcmp(git_buf_cstr(idx_path), ".pack") != 0)
+       path_len = git_str_len(idx_path);
+       if (path_len <= strlen(".pack") || git__suffixcmp(git_str_cstr(idx_path), ".pack") != 0)
                return git_odb__error_notfound("packfile does not end in .pack", NULL, 0);
        path_len -= strlen(".pack");
-       error = git_buf_splice(idx_path, path_len, strlen(".pack"), ".idx", strlen(".idx"));
+       error = git_str_splice(idx_path, path_len, strlen(".pack"), ".idx", strlen(".idx"));
        if (error < 0)
                return error;
 
@@ -781,22 +781,22 @@ static int pack_backend__writemidx(git_odb_backend *_backend)
                return error;
 
        git_vector_foreach(&backend->midx_packs, i, p) {
-               git_buf idx_path = GIT_BUF_INIT;
+               git_str idx_path = GIT_STR_INIT;
                error = get_idx_path(&idx_path, backend, p);
                if (error < 0)
                        goto cleanup;
-               error = git_midx_writer_add(w, git_buf_cstr(&idx_path));
-               git_buf_dispose(&idx_path);
+               error = git_midx_writer_add(w, git_str_cstr(&idx_path));
+               git_str_dispose(&idx_path);
                if (error < 0)
                        goto cleanup;
        }
        git_vector_foreach(&backend->packs, i, p) {
-               git_buf idx_path = GIT_BUF_INIT;
+               git_str idx_path = GIT_STR_INIT;
                error = get_idx_path(&idx_path, backend, p);
                if (error < 0)
                        goto cleanup;
-               error = git_midx_writer_add(w, git_buf_cstr(&idx_path));
-               git_buf_dispose(&idx_path);
+               error = git_midx_writer_add(w, git_str_cstr(&idx_path));
+               git_str_dispose(&idx_path);
                if (error < 0)
                        goto cleanup;
        }
@@ -896,15 +896,15 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
 {
        int error = 0;
        struct pack_backend *backend = NULL;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        if (pack_backend__alloc(&backend, 8) < 0)
                return -1;
 
-       if (!(error = git_buf_joinpath(&path, objects_dir, "pack")) &&
-               git_path_isdir(git_buf_cstr(&path)))
+       if (!(error = git_str_joinpath(&path, objects_dir, "pack")) &&
+               git_fs_path_isdir(git_str_cstr(&path)))
        {
-               backend->pack_folder = git_buf_detach(&path);
+               backend->pack_folder = git_str_detach(&path);
                error = pack_backend__refresh((git_odb_backend *)backend);
        }
 
@@ -915,7 +915,7 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
 
        *backend_out = (git_odb_backend *)backend;
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return error;
 }
index 893e2fc0fb0620ea03a5e8cb7cbaa8be71ae89c6..19061e899f7749ae0468b271646bbf57c55fe9e6 100644 (file)
--- a/src/oid.c
+++ b/src/oid.c
 #include <string.h>
 #include <limits.h>
 
+const git_oid git_oid__empty_blob_sha1 =
+       {{ 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,
+          0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91 }};
+const git_oid git_oid__empty_tree_sha1 =
+       {{ 0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
+          0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04 }};
+
 static char to_hex[] = "0123456789abcdef";
 
 static int oid_error_invalid(const char *msg)
@@ -162,14 +169,14 @@ int git_oid__parse(
        return 0;
 }
 
-void git_oid__writebuf(git_buf *buf, const char *header, const git_oid *oid)
+void git_oid__writebuf(git_str *buf, const char *header, const git_oid *oid)
 {
        char hex_oid[GIT_OID_HEXSZ];
 
        git_oid_fmt(hex_oid, oid);
-       git_buf_puts(buf, header);
-       git_buf_put(buf, hex_oid, GIT_OID_HEXSZ);
-       git_buf_putc(buf, '\n');
+       git_str_puts(buf, header);
+       git_str_put(buf, hex_oid, GIT_OID_HEXSZ);
+       git_str_putc(buf, '\n');
 }
 
 int git_oid_fromraw(git_oid *out, const unsigned char *raw)
index 84231ffca905f84f2810a3ed1ef94950c241ea69..5baec33e5cd055b213bda9b65c44c5f4172d6016 100644 (file)
--- a/src/oid.h
+++ b/src/oid.h
@@ -11,6 +11,9 @@
 
 #include "git2/oid.h"
 
+extern const git_oid git_oid__empty_blob_sha1;
+extern const git_oid git_oid__empty_tree_sha1;
+
 /**
  * Format a git_oid into a newly allocated c-string.
  *
@@ -48,4 +51,16 @@ GIT_INLINE(void) git_oid__cpy_prefix(
                out->id[len / 2] &= 0xF0;
 }
 
+GIT_INLINE(bool) git_oid__is_hexstr(const char *str)
+{
+       size_t i;
+
+       for (i = 0; str[i] != '\0'; i++) {
+               if (git__fromhex(str[i]) < 0)
+                       return false;
+       }
+
+       return (i == GIT_OID_HEXSZ);
+}
+
 #endif
index faff310b40b57deb36618e08151f155f945293a4..1aa6731b33ea84abacae5fae50e698d6a4251a84 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "pack-objects.h"
 
+#include "buf.h"
 #include "zstream.h"
 #include "delta.h"
 #include "iterator.h"
@@ -33,7 +34,7 @@ struct unpacked {
 
 struct tree_walk_context {
        git_packbuilder *pb;
-       git_buf buf;
+       git_str buf;
 };
 
 struct pack_write_context {
@@ -141,7 +142,7 @@ int git_packbuilder_new(git_packbuilder **out, git_repository *repo)
        pb->repo = repo;
        pb->nr_threads = 1; /* do not spawn any thread by default */
 
-       if (git_hash_ctx_init(&pb->ctx) < 0 ||
+       if (git_hash_ctx_init(&pb->ctx, GIT_HASH_ALGORITHM_SHA1) < 0 ||
                git_zstream_init(&pb->zstream, GIT_ZSTREAM_DEFLATE) < 0 ||
                git_repository_odb(&pb->odb, repo) < 0 ||
                packbuilder_config(pb) < 0)
@@ -664,7 +665,7 @@ static int write_pack(git_packbuilder *pb,
                pb->nr_remaining -= pb->nr_written;
        } while (pb->nr_remaining && i < pb->nr_objects);
 
-       if ((error = git_hash_final(&entry_oid, &pb->ctx)) < 0)
+       if ((error = git_hash_final(entry_oid.id, &pb->ctx)) < 0)
                goto done;
 
        error = write_cb(entry_oid.id, GIT_OID_RAWSZ, cb_data);
@@ -685,8 +686,8 @@ done:
 
 static int write_pack_buf(void *buf, size_t size, void *data)
 {
-       git_buf *b = (git_buf *)data;
-       return git_buf_put(b, buf, size);
+       git_str *b = (git_str *)data;
+       return git_str_put(b, buf, size);
 }
 
 static int type_size_sort(const void *_a, const void *_b)
@@ -947,7 +948,7 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list,
        size_t *list_size, size_t window, size_t depth)
 {
        git_pobject *po;
-       git_buf zbuf = GIT_BUF_INIT;
+       git_str zbuf = GIT_STR_INIT;
        struct unpacked *array;
        size_t idx = 0, count = 0;
        size_t mem_usage = 0;
@@ -1045,7 +1046,7 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list,
 
                        memcpy(po->delta_data, zbuf.ptr, zbuf.size);
                        po->z_delta_size = zbuf.size;
-                       git_buf_clear(&zbuf);
+                       git_str_clear(&zbuf);
 
                        GIT_ASSERT(git_packbuilder__cache_lock(pb) == 0);
                        pb->delta_cache_size -= po->delta_size;
@@ -1093,7 +1094,7 @@ on_error:
                git__free(array[i].data);
        }
        git__free(array);
-       git_buf_dispose(&zbuf);
+       git_str_dispose(&zbuf);
 
        return error;
 }
@@ -1307,7 +1308,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
 #define ll_find_deltas(pb, l, ls, w, d) find_deltas(pb, l, &ls, w, d)
 #endif
 
-static int prepare_pack(git_packbuilder *pb)
+int git_packbuilder__prepare(git_packbuilder *pb)
 {
        git_pobject **delta_list;
        size_t i, n = 0;
@@ -1352,7 +1353,7 @@ static int prepare_pack(git_packbuilder *pb)
        return 0;
 }
 
-#define PREPARE_PACK if (prepare_pack(pb) < 0) { return -1; }
+#define PREPARE_PACK if (git_packbuilder__prepare(pb) < 0) { return -1; }
 
 int git_packbuilder_foreach(git_packbuilder *pb, int (*cb)(void *buf, size_t size, void *payload), void *payload)
 {
@@ -1360,18 +1361,18 @@ int git_packbuilder_foreach(git_packbuilder *pb, int (*cb)(void *buf, size_t siz
        return write_pack(pb, cb, payload);
 }
 
-int git_packbuilder_write_buf(git_buf *buf, git_packbuilder *pb)
+int git_packbuilder__write_buf(git_str *buf, git_packbuilder *pb)
 {
-       int error;
-
-       if ((error = git_buf_sanitize(buf)) < 0)
-               return error;
-
        PREPARE_PACK;
 
        return write_pack(pb, &write_pack_buf, buf);
 }
 
+int git_packbuilder_write_buf(git_buf *buf, git_packbuilder *pb)
+{
+       GIT_BUF_WRAP_PRIVATE(buf, git_packbuilder__write_buf, pb);
+}
+
 static int write_cb(void *buf, size_t len, void *payload)
 {
        struct pack_write_context *ctx = payload;
@@ -1386,7 +1387,7 @@ int git_packbuilder_write(
        void *progress_cb_payload)
 {
        int error = -1;
-       git_buf object_path = GIT_BUF_INIT;
+       git_str object_path = GIT_STR_INIT;
        git_indexer_options opts = GIT_INDEXER_OPTIONS_INIT;
        git_indexer *indexer = NULL;
        git_indexer_progress stats;
@@ -1396,11 +1397,11 @@ int git_packbuilder_write(
        PREPARE_PACK;
 
        if (path == NULL) {
-               if ((error = git_repository_item_path(&object_path, pb->repo, GIT_REPOSITORY_ITEM_OBJECTS)) < 0)
+               if ((error = git_repository__item_path(&object_path, pb->repo, GIT_REPOSITORY_ITEM_OBJECTS)) < 0)
                        goto cleanup;
-               if ((error = git_buf_joinpath(&object_path, git_buf_cstr(&object_path), "pack")) < 0)
+               if ((error = git_str_joinpath(&object_path, git_str_cstr(&object_path), "pack")) < 0)
                        goto cleanup;
-               path = git_buf_cstr(&object_path);
+               path = git_str_cstr(&object_path);
        }
 
        opts.progress_cb = progress_cb;
@@ -1421,20 +1422,32 @@ int git_packbuilder_write(
        if ((error = git_indexer_commit(indexer, &stats)) < 0)
                goto cleanup;
 
+#ifndef GIT_DEPRECATE_HARD
        git_oid_cpy(&pb->pack_oid, git_indexer_hash(indexer));
+#endif
+
+       pb->pack_name = git__strdup(git_indexer_name(indexer));
+       GIT_ERROR_CHECK_ALLOC(pb->pack_name);
 
 cleanup:
        git_indexer_free(indexer);
-       git_buf_dispose(&object_path);
+       git_str_dispose(&object_path);
        return error;
 }
 
 #undef PREPARE_PACK
 
+#ifndef GIT_DEPRECATE_HARD
 const git_oid *git_packbuilder_hash(git_packbuilder *pb)
 {
        return &pb->pack_oid;
 }
+#endif
+
+const char *git_packbuilder_name(git_packbuilder *pb)
+{
+       return pb->pack_name;
+}
 
 
 static int cb_tree_walk(
@@ -1447,10 +1460,10 @@ static int cb_tree_walk(
        if (git_tree_entry_type(entry) == GIT_OBJECT_COMMIT)
                return 0;
 
-       if (!(error = git_buf_sets(&ctx->buf, root)) &&
-               !(error = git_buf_puts(&ctx->buf, git_tree_entry_name(entry))))
+       if (!(error = git_str_sets(&ctx->buf, root)) &&
+               !(error = git_str_puts(&ctx->buf, git_tree_entry_name(entry))))
                error = git_packbuilder_insert(
-                       ctx->pb, git_tree_entry_id(entry), git_buf_cstr(&ctx->buf));
+                       ctx->pb, git_tree_entry_id(entry), git_str_cstr(&ctx->buf));
 
        return error;
 }
@@ -1474,14 +1487,14 @@ int git_packbuilder_insert_tree(git_packbuilder *pb, const git_oid *oid)
 {
        int error;
        git_tree *tree = NULL;
-       struct tree_walk_context context = { pb, GIT_BUF_INIT };
+       struct tree_walk_context context = { pb, GIT_STR_INIT };
 
        if (!(error = git_tree_lookup(&tree, pb->repo, oid)) &&
            !(error = git_packbuilder_insert(pb, oid, NULL)))
                error = git_tree_walk(tree, GIT_TREEWALK_PRE, cb_tree_walk, &context);
 
        git_tree_free(tree);
-       git_buf_dispose(&context.buf);
+       git_str_dispose(&context.buf);
        return error;
 }
 
@@ -1802,5 +1815,7 @@ void git_packbuilder_free(git_packbuilder *pb)
        git_hash_ctx_cleanup(&pb->ctx);
        git_zstream_free(&pb->zstream);
 
+       git__free(pb->pack_name);
+
        git__free(pb);
 }
index 04514daa6e124837d6d98f37fdfabb0650009f50..2faa3ec7f514bc533c0bb2cd9b0a0502c348dfd7 100644 (file)
@@ -10,7 +10,7 @@
 
 #include "common.h"
 
-#include "buffer.h"
+#include "str.h"
 #include "hash.h"
 #include "oidmap.h"
 #include "netops.h"
@@ -46,10 +46,10 @@ typedef struct git_pobject {
        size_t delta_size;
        size_t z_delta_size;
 
-       int written:1,
-           recursing:1,
-           tagged:1,
-           filled:1;
+       unsigned int written:1,
+                    recursing:1,
+                    tagged:1,
+                    filled:1;
 } git_pobject;
 
 struct git_packbuilder {
@@ -73,7 +73,10 @@ struct git_packbuilder {
        git_oidmap *walk_objects;
        git_pool object_pool;
 
+#ifndef GIT_DEPRECATE_HARD
        git_oid pack_oid; /* hash of written pack */
+#endif
+       char *pack_name; /* name of written pack */
 
        /* synchronization objects */
        git_mutex cache_mutex;
@@ -96,6 +99,8 @@ struct git_packbuilder {
        bool done;
 };
 
-int git_packbuilder_write_buf(git_buf *buf, git_packbuilder *pb);
+int git_packbuilder__write_buf(git_str *buf, git_packbuilder *pb);
+int git_packbuilder__prepare(git_packbuilder *pb);
+
 
 #endif
index aadf3f2be7c74eb84ea488de08fd6c1b9fbd3c16..5c0cba7e892487d182e17770a8c884444350c0b3 100644 (file)
@@ -308,7 +308,7 @@ static int pack_index_open_locked(struct git_pack_file *p)
 {
        int error = 0;
        size_t name_len;
-       git_buf idx_name = GIT_BUF_INIT;
+       git_str idx_name = GIT_STR_INIT;
 
        if (p->index_version > -1)
                goto cleanup;
@@ -317,12 +317,12 @@ static int pack_index_open_locked(struct git_pack_file *p)
        name_len = strlen(p->pack_name);
        GIT_ASSERT(name_len > strlen(".pack"));
 
-       if ((error = git_buf_init(&idx_name, name_len)) < 0)
+       if ((error = git_str_init(&idx_name, name_len)) < 0)
                goto cleanup;
 
-       git_buf_put(&idx_name, p->pack_name, name_len - strlen(".pack"));
-       git_buf_puts(&idx_name, ".idx");
-       if (git_buf_oom(&idx_name)) {
+       git_str_put(&idx_name, p->pack_name, name_len - strlen(".pack"));
+       git_str_puts(&idx_name, ".idx");
+       if (git_str_oom(&idx_name)) {
                error = -1;
                goto cleanup;
        }
@@ -331,7 +331,7 @@ static int pack_index_open_locked(struct git_pack_file *p)
                error = pack_index_check_locked(idx_name.ptr, p);
 
 cleanup:
-       git_buf_dispose(&idx_name);
+       git_str_dispose(&idx_name);
 
        return error;
 }
@@ -1156,17 +1156,17 @@ cleanup:
 int git_packfile__name(char **out, const char *path)
 {
        size_t path_len;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        path_len = strlen(path);
 
        if (path_len < strlen(".idx"))
                return git_odb__error_notfound("invalid packfile path", NULL, 0);
 
-       if (git_buf_printf(&buf, "%.*s.pack", (int)(path_len - strlen(".idx")), path) < 0)
+       if (git_str_printf(&buf, "%.*s.pack", (int)(path_len - strlen(".idx")), path) < 0)
                return -1;
 
-       *out = git_buf_detach(&buf);
+       *out = git_str_detach(&buf);
        return 0;
 }
 
@@ -1198,7 +1198,7 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
 
                if (!git_disable_pack_keep_file_checks) {
                        memcpy(p->pack_name + root_len, ".keep", sizeof(".keep"));
-                       if (git_path_exists(p->pack_name) == true)
+                       if (git_fs_path_exists(p->pack_name) == true)
                                p->pack_keep = 1;
                }
 
index f02c928de255e78742241d464bb1d1e3530b63b8..a30546f3ce6aa74431c7070fcb256d02556259b7 100644 (file)
@@ -76,15 +76,15 @@ size_t git_patch_size(
                out += patch->header_size;
 
        if (include_file_headers) {
-               git_buf file_header = GIT_BUF_INIT;
+               git_str file_header = GIT_STR_INIT;
 
                if (git_diff_delta__format_file_header(
                        &file_header, patch->delta, NULL, NULL, 0, true) < 0)
                        git_error_clear();
                else
-                       out += git_buf_len(&file_header);
+                       out += git_str_len(&file_header);
 
-               git_buf_dispose(&file_header);
+               git_str_dispose(&file_header);
        }
 
        return out;
index 156d1310e793cfbafcfbd5584941d2cbc843b7e7..1e1471ed613abe8f11a0bbc6479e6753bd6bfd10 100644 (file)
@@ -63,6 +63,7 @@ typedef struct {
 
 #define GIT_PATCH_OPTIONS_INIT { 1 }
 
+extern int git_patch__to_buf(git_str *out, git_patch *patch);
 extern void git_patch_free(git_patch *patch);
 
 #endif
index 38cd714a9804f067c2d3c903610e00d1c06f16b9..bc598fea870123b5e771c6cd53e8000918cc6cc6 100644 (file)
@@ -261,7 +261,7 @@ static int create_binary(
        const char *b_data,
        size_t b_datalen)
 {
-       git_buf deflate = GIT_BUF_INIT, delta = GIT_BUF_INIT;
+       git_str deflate = GIT_STR_INIT, delta = GIT_STR_INIT;
        size_t delta_data_len = 0;
        int error;
 
@@ -302,18 +302,18 @@ static int create_binary(
        if (delta.size && delta.size < deflate.size) {
                *out_type = GIT_DIFF_BINARY_DELTA;
                *out_datalen = delta.size;
-               *out_data = git_buf_detach(&delta);
+               *out_data = git_str_detach(&delta);
                *out_inflatedlen = delta_data_len;
        } else {
                *out_type = GIT_DIFF_BINARY_LITERAL;
                *out_datalen = deflate.size;
-               *out_data = git_buf_detach(&deflate);
+               *out_data = git_str_detach(&deflate);
                *out_inflatedlen = b_datalen;
        }
 
 done:
-       git_buf_dispose(&deflate);
-       git_buf_dispose(&delta);
+       git_str_dispose(&deflate);
+       git_str_dispose(&delta);
 
        return error;
 }
@@ -750,18 +750,34 @@ git_diff_driver *git_patch_generated_driver(git_patch_generated *patch)
        return patch->ofile.driver;
 }
 
-void git_patch_generated_old_data(
-       char **ptr, size_t *len, git_patch_generated *patch)
+int git_patch_generated_old_data(
+       char **ptr, long *len, git_patch_generated *patch)
 {
+       if (patch->ofile.map.len > LONG_MAX ||
+           patch->ofile.map.len > GIT_XDIFF_MAX_SIZE) {
+               git_error_set(GIT_ERROR_INVALID, "files too large for diff");
+               return -1;
+       }
+
        *ptr = patch->ofile.map.data;
-       *len = patch->ofile.map.len;
+       *len = (long)patch->ofile.map.len;
+
+       return 0;
 }
 
-void git_patch_generated_new_data(
-       char **ptr, size_t *len, git_patch_generated *patch)
+int git_patch_generated_new_data(
+       char **ptr, long *len, git_patch_generated *patch)
 {
+       if (patch->ofile.map.len > LONG_MAX ||
+           patch->ofile.map.len > GIT_XDIFF_MAX_SIZE) {
+               git_error_set(GIT_ERROR_INVALID, "files too large for diff");
+               return -1;
+       }
+
        *ptr = patch->nfile.map.data;
-       *len = patch->nfile.map.len;
+       *len = (long)patch->nfile.map.len;
+
+       return 0;
 }
 
 static int patch_generated_file_cb(
index 20f78cbfab82cb9aeaf4d1c4074b400225df025b..56e3e9df4753607be5b033876e22a8628b7471b1 100644 (file)
@@ -21,7 +21,7 @@ enum {
        GIT_PATCH_GENERATED_DIFFABLE = (1 << 3),
        /* the difference between the two sides has been computed */
        GIT_PATCH_GENERATED_DIFFED = (1 << 4),
-       GIT_PATCH_GENERATED_FLATTENED = (1 << 5),
+       GIT_PATCH_GENERATED_FLATTENED = (1 << 5)
 };
 
 struct git_patch_generated {
@@ -39,10 +39,10 @@ typedef struct git_patch_generated git_patch_generated;
 
 extern git_diff_driver *git_patch_generated_driver(git_patch_generated *);
 
-extern void git_patch_generated_old_data(
-       char **, size_t *, git_patch_generated *);
-extern void git_patch_generated_new_data(
-       char **, size_t *, git_patch_generated *);
+extern int git_patch_generated_old_data(
+       char **, long *, git_patch_generated *);
+extern int git_patch_generated_new_data(
+       char **, long *, git_patch_generated *);
 extern int git_patch_generated_from_diff(
        git_patch **, git_diff *, size_t);
 
index 2cc5c5995171086bd2d5bbe716d957b0b4f384ea..78cd96252f8b3edc19d7a70711db19dc3ec94038 100644 (file)
@@ -10,7 +10,7 @@
 #include "git2/patch.h"
 #include "patch.h"
 #include "diff_parse.h"
-#include "path.h"
+#include "fs_path.h"
 
 typedef struct {
        git_patch base;
@@ -65,22 +65,22 @@ static size_t header_path_len(git_patch_parse_ctx *ctx)
        return len;
 }
 
-static int parse_header_path_buf(git_buf *path, git_patch_parse_ctx *ctx, size_t path_len)
+static int parse_header_path_buf(git_str *path, git_patch_parse_ctx *ctx, size_t path_len)
 {
        int error;
 
-       if ((error = git_buf_put(path, ctx->parse_ctx.line, path_len)) < 0)
+       if ((error = git_str_put(path, ctx->parse_ctx.line, path_len)) < 0)
                return error;
 
        git_parse_advance_chars(&ctx->parse_ctx, path_len);
 
-       git_buf_rtrim(path);
+       git_str_rtrim(path);
 
        if (path->size > 0 && path->ptr[0] == '"' &&
-           (error = git_buf_unquote(path)) < 0)
+           (error = git_str_unquote(path)) < 0)
                return error;
 
-       git_path_squash_slashes(path);
+       git_fs_path_squash_slashes(path);
 
        if (!path->size)
                return git_parse_err("patch contains empty path at line %"PRIuZ,
@@ -91,22 +91,22 @@ static int parse_header_path_buf(git_buf *path, git_patch_parse_ctx *ctx, size_t
 
 static int parse_header_path(char **out, git_patch_parse_ctx *ctx)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        int error;
 
        if ((error = parse_header_path_buf(&path, ctx, header_path_len(ctx))) < 0)
                goto out;
-       *out = git_buf_detach(&path);
+       *out = git_str_detach(&path);
 
 out:
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        return error;
 }
 
 static int parse_header_git_oldpath(
        git_patch_parsed *patch, git_patch_parse_ctx *ctx)
 {
-       git_buf old_path = GIT_BUF_INIT;
+       git_str old_path = GIT_STR_INIT;
        int error;
 
        if (patch->old_path) {
@@ -118,17 +118,17 @@ static int parse_header_git_oldpath(
        if ((error = parse_header_path_buf(&old_path, ctx, ctx->parse_ctx.line_len - 1)) <  0)
                goto out;
 
-       patch->old_path = git_buf_detach(&old_path);
+       patch->old_path = git_str_detach(&old_path);
 
 out:
-       git_buf_dispose(&old_path);
+       git_str_dispose(&old_path);
        return error;
 }
 
 static int parse_header_git_newpath(
        git_patch_parsed *patch, git_patch_parse_ctx *ctx)
 {
-       git_buf new_path = GIT_BUF_INIT;
+       git_str new_path = GIT_STR_INIT;
        int error;
 
        if (patch->new_path) {
@@ -139,10 +139,10 @@ static int parse_header_git_newpath(
 
        if ((error = parse_header_path_buf(&new_path, ctx, ctx->parse_ctx.line_len - 1)) <  0)
                goto out;
-       patch->new_path = git_buf_detach(&new_path);
+       patch->new_path = git_str_detach(&new_path);
 
 out:
-       git_buf_dispose(&new_path);
+       git_str_dispose(&new_path);
        return error;
 }
 
@@ -257,7 +257,7 @@ static int parse_header_rename(
        char **out,
        git_patch_parse_ctx *ctx)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        if (parse_header_path_buf(&path, ctx, header_path_len(ctx)) < 0)
                return -1;
@@ -265,7 +265,7 @@ static int parse_header_rename(
        /* Note: the `rename from` and `rename to` lines include the literal
         * filename.  They do *not* include the prefix.  (Who needs consistency?)
         */
-       *out = git_buf_detach(&path);
+       *out = git_str_detach(&path);
        return 0;
 }
 
@@ -353,7 +353,7 @@ static int parse_header_start(git_patch_parsed *patch, git_patch_parse_ctx *ctx)
         * We cannot expect to be able to always parse paths correctly at this
         * point. Due to the possibility of unquoted names, whitespaces in
         * filenames and custom prefixes we have to allow that, though, and just
-        * proceeed here. We then hope for the "---" and "+++" lines to fix that
+        * proceed here. We then hope for the "---" and "+++" lines to fix that
         * for us.
         */
        if (!git_parse_ctx_contains(&ctx->parse_ctx, "\n", 1) &&
@@ -382,7 +382,7 @@ typedef enum {
        STATE_RENAME,
        STATE_COPY,
 
-       STATE_END,
+       STATE_END
 } parse_header_state;
 
 typedef struct {
@@ -766,7 +766,7 @@ static int parse_patch_binary_side(
        git_patch_parse_ctx *ctx)
 {
        git_diff_binary_t type = GIT_DIFF_BINARY_NONE;
-       git_buf base85 = GIT_BUF_INIT, decoded = GIT_BUF_INIT;
+       git_str base85 = GIT_STR_INIT, decoded = GIT_STR_INIT;
        int64_t len;
        int error = 0;
 
@@ -815,7 +815,7 @@ static int parse_patch_binary_side(
                        goto done;
                }
 
-               if ((error = git_buf_decode_base85(
+               if ((error = git_str_decode_base85(
                        &decoded, ctx->parse_ctx.line, encoded_len, decoded_len)) < 0)
                        goto done;
 
@@ -835,11 +835,11 @@ static int parse_patch_binary_side(
        binary->type = type;
        binary->inflatedlen = (size_t)len;
        binary->datalen = decoded.size;
-       binary->data = git_buf_detach(&decoded);
+       binary->data = git_str_detach(&decoded);
 
 done:
-       git_buf_dispose(&base85);
-       git_buf_dispose(&decoded);
+       git_str_dispose(&base85);
+       git_str_dispose(&decoded);
        return error;
 }
 
index c444b31a7716572960f4a5de17e945a5287d53b0..05a3dc2cf901a9c26d33b3fa1100b06283b1516f 100644 (file)
 
 #include "path.h"
 
-#include "posix.h"
 #include "repository.h"
-#ifdef GIT_WIN32
-#include "win32/posix.h"
-#include "win32/w32_buffer.h"
-#include "win32/w32_util.h"
-#include "win32/version.h"
-#include <aclapi.h>
-#else
-#include <dirent.h>
-#endif
-#include <stdio.h>
-#include <ctype.h>
-
-static int dos_drive_prefix_length(const char *path)
-{
-       int i;
-
-       /*
-        * Does it start with an ASCII letter (i.e. highest bit not set),
-        * followed by a colon?
-        */
-       if (!(0x80 & (unsigned char)*path))
-               return *path && path[1] == ':' ? 2 : 0;
-
-       /*
-        * While drive letters must be letters of the English alphabet, it is
-        * possible to assign virtually _any_ Unicode character via `subst` as
-        * a drive letter to "virtual drives". Even `1`, or `ä`. Or fun stuff
-        * like this:
-        *
-        *      subst ֍: %USERPROFILE%\Desktop
-        */
-       for (i = 1; i < 4 && (0x80 & (unsigned char)path[i]); i++)
-               ; /* skip first UTF-8 character */
-       return path[i] == ':' ? i + 1 : 0;
-}
-
-#ifdef GIT_WIN32
-static bool looks_like_network_computer_name(const char *path, int pos)
-{
-       if (pos < 3)
-               return false;
-
-       if (path[0] != '/' || path[1] != '/')
-               return false;
-
-       while (pos-- > 2) {
-               if (path[pos] == '/')
-                       return false;
-       }
-
-       return true;
-}
-#endif
-
-/*
- * Based on the Android implementation, BSD licensed.
- * http://android.git.kernel.org/
- *
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in
- *   the documentation and/or other materials provided with the
- *   distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-int git_path_basename_r(git_buf *buffer, const char *path)
-{
-       const char *endp, *startp;
-       int len, result;
-
-       /* Empty or NULL string gets treated as "." */
-       if (path == NULL || *path == '\0') {
-               startp = ".";
-               len             = 1;
-               goto Exit;
-       }
-
-       /* Strip trailing slashes */
-       endp = path + strlen(path) - 1;
-       while (endp > path && *endp == '/')
-               endp--;
-
-       /* All slashes becomes "/" */
-       if (endp == path && *endp == '/') {
-               startp = "/";
-               len     = 1;
-               goto Exit;
-       }
-
-       /* Find the start of the base */
-       startp = endp;
-       while (startp > path && *(startp - 1) != '/')
-               startp--;
-
-       /* Cast is safe because max path < max int */
-       len = (int)(endp - startp + 1);
-
-Exit:
-       result = len;
-
-       if (buffer != NULL && git_buf_set(buffer, startp, len) < 0)
-               return -1;
-
-       return result;
-}
-
-/*
- * Determine if the path is a Windows prefix and, if so, returns
- * its actual lentgh. If it is not a prefix, returns -1.
- */
-static int win32_prefix_length(const char *path, int len)
-{
-#ifndef GIT_WIN32
-       GIT_UNUSED(path);
-       GIT_UNUSED(len);
-#else
-       /*
-        * Mimic unix behavior where '/.git' returns '/': 'C:/.git'
-        * will return 'C:/' here
-        */
-       if (dos_drive_prefix_length(path) == len)
-               return len;
-
-       /*
-        * Similarly checks if we're dealing with a network computer name
-        * '//computername/.git' will return '//computername/'
-        */
-       if (looks_like_network_computer_name(path, len))
-               return len;
-#endif
-
-       return -1;
-}
-
-/*
- * Based on the Android implementation, BSD licensed.
- * Check http://android.git.kernel.org/
- */
-int git_path_dirname_r(git_buf *buffer, const char *path)
-{
-       const char *endp;
-       int is_prefix = 0, len;
-
-       /* Empty or NULL string gets treated as "." */
-       if (path == NULL || *path == '\0') {
-               path = ".";
-               len = 1;
-               goto Exit;
-       }
-
-       /* Strip trailing slashes */
-       endp = path + strlen(path) - 1;
-       while (endp > path && *endp == '/')
-               endp--;
-
-       if (endp - path + 1 > INT_MAX) {
-               git_error_set(GIT_ERROR_INVALID, "path too long");
-               len = -1;
-               goto Exit;
-       }
-
-       if ((len = win32_prefix_length(path, (int)(endp - path + 1))) > 0) {
-               is_prefix = 1;
-               goto Exit;
-       }
-
-       /* Find the start of the dir */
-       while (endp > path && *endp != '/')
-               endp--;
-
-       /* Either the dir is "/" or there are no slashes */
-       if (endp == path) {
-               path = (*endp == '/') ? "/" : ".";
-               len = 1;
-               goto Exit;
-       }
-
-       do {
-               endp--;
-       } while (endp > path && *endp == '/');
-
-       if (endp - path + 1 > INT_MAX) {
-               git_error_set(GIT_ERROR_INVALID, "path too long");
-               len = -1;
-               goto Exit;
-       }
-
-       if ((len = win32_prefix_length(path, (int)(endp - path + 1))) > 0) {
-               is_prefix = 1;
-               goto Exit;
-       }
-
-       /* Cast is safe because max path < max int */
-       len = (int)(endp - path + 1);
-
-Exit:
-       if (buffer) {
-               if (git_buf_set(buffer, path, len) < 0)
-                       return -1;
-               if (is_prefix && git_buf_putc(buffer, '/') < 0)
-                       return -1;
-       }
-
-       return len;
-}
-
-
-char *git_path_dirname(const char *path)
-{
-       git_buf buf = GIT_BUF_INIT;
-       char *dirname;
-
-       git_path_dirname_r(&buf, path);
-       dirname = git_buf_detach(&buf);
-       git_buf_dispose(&buf); /* avoid memleak if error occurs */
-
-       return dirname;
-}
-
-char *git_path_basename(const char *path)
-{
-       git_buf buf = GIT_BUF_INIT;
-       char *basename;
-
-       git_path_basename_r(&buf, path);
-       basename = git_buf_detach(&buf);
-       git_buf_dispose(&buf); /* avoid memleak if error occurs */
-
-       return basename;
-}
-
-size_t git_path_basename_offset(git_buf *buffer)
-{
-       ssize_t slash;
-
-       if (!buffer || buffer->size <= 0)
-               return 0;
-
-       slash = git_buf_rfind_next(buffer, '/');
-
-       if (slash >= 0 && buffer->ptr[slash] == '/')
-               return (size_t)(slash + 1);
-
-       return 0;
-}
-
-int git_path_root(const char *path)
-{
-       int offset = 0, prefix_len;
-
-       /* Does the root of the path look like a windows drive ? */
-       if ((prefix_len = dos_drive_prefix_length(path)))
-               offset += prefix_len;
-
-#ifdef GIT_WIN32
-       /* Are we dealing with a windows network path? */
-       else if ((path[0] == '/' && path[1] == '/' && path[2] != '/') ||
-               (path[0] == '\\' && path[1] == '\\' && path[2] != '\\'))
-       {
-               offset += 2;
-
-               /* Skip the computer name segment */
-               while (path[offset] && path[offset] != '/' && path[offset] != '\\')
-                       offset++;
-       }
-
-       if (path[offset] == '\\')
-               return offset;
-#endif
-
-       if (path[offset] == '/')
-               return offset;
-
-       return -1;      /* Not a real error - signals that path is not rooted */
-}
-
-static void path_trim_slashes(git_buf *path)
-{
-       int ceiling = git_path_root(path->ptr) + 1;
-
-       if (ceiling < 0)
-               return;
-
-       while (path->size > (size_t)ceiling) {
-               if (path->ptr[path->size-1] != '/')
-                       break;
-
-               path->ptr[path->size-1] = '\0';
-               path->size--;
-       }
-}
-
-int git_path_join_unrooted(
-       git_buf *path_out, const char *path, const char *base, ssize_t *root_at)
-{
-       ssize_t root;
-
-       GIT_ASSERT_ARG(path_out);
-       GIT_ASSERT_ARG(path);
-
-       root = (ssize_t)git_path_root(path);
-
-       if (base != NULL && root < 0) {
-               if (git_buf_joinpath(path_out, base, path) < 0)
-                       return -1;
-
-               root = (ssize_t)strlen(base);
-       } else {
-               if (git_buf_sets(path_out, path) < 0)
-                       return -1;
-
-               if (root < 0)
-                       root = 0;
-               else if (base)
-                       git_path_equal_or_prefixed(base, path, &root);
-       }
-
-       if (root_at)
-               *root_at = root;
-
-       return 0;
-}
-
-void git_path_squash_slashes(git_buf *path)
-{
-       char *p, *q;
-
-       if (path->size == 0)
-               return;
-
-       for (p = path->ptr, q = path->ptr; *q; p++, q++) {
-               *p = *q;
-
-               while (*q == '/' && *(q+1) == '/') {
-                       path->size--;
-                       q++;
-               }
-       }
-
-       *p = '\0';
-}
-
-int git_path_prettify(git_buf *path_out, const char *path, const char *base)
-{
-       char buf[GIT_PATH_MAX];
-
-       GIT_ASSERT_ARG(path_out);
-       GIT_ASSERT_ARG(path);
-
-       /* construct path if needed */
-       if (base != NULL && git_path_root(path) < 0) {
-               if (git_buf_joinpath(path_out, base, path) < 0)
-                       return -1;
-               path = path_out->ptr;
-       }
-
-       if (p_realpath(path, buf) == NULL) {
-               /* git_error_set resets the errno when dealing with a GIT_ERROR_OS kind of error */
-               int error = (errno == ENOENT || errno == ENOTDIR) ? GIT_ENOTFOUND : -1;
-               git_error_set(GIT_ERROR_OS, "failed to resolve path '%s'", path);
-
-               git_buf_clear(path_out);
-
-               return error;
-       }
-
-       return git_buf_sets(path_out, buf);
-}
-
-int git_path_prettify_dir(git_buf *path_out, const char *path, const char *base)
-{
-       int error = git_path_prettify(path_out, path, base);
-       return (error < 0) ? error : git_path_to_dir(path_out);
-}
-
-int git_path_to_dir(git_buf *path)
-{
-       if (path->asize > 0 &&
-               git_buf_len(path) > 0 &&
-               path->ptr[git_buf_len(path) - 1] != '/')
-               git_buf_putc(path, '/');
-
-       return git_buf_oom(path) ? -1 : 0;
-}
-
-void git_path_string_to_dir(char *path, size_t size)
-{
-       size_t end = strlen(path);
-
-       if (end && path[end - 1] != '/' && end < size) {
-               path[end] = '/';
-               path[end + 1] = '\0';
-       }
-}
-
-int git__percent_decode(git_buf *decoded_out, const char *input)
-{
-       int len, hi, lo, i;
-
-       GIT_ASSERT_ARG(decoded_out);
-       GIT_ASSERT_ARG(input);
-
-       len = (int)strlen(input);
-       git_buf_clear(decoded_out);
-
-       for(i = 0; i < len; i++)
-       {
-               char c = input[i];
-
-               if (c != '%')
-                       goto append;
-
-               if (i >= len - 2)
-                       goto append;
-
-               hi = git__fromhex(input[i + 1]);
-               lo = git__fromhex(input[i + 2]);
-
-               if (hi < 0 || lo < 0)
-                       goto append;
-
-               c = (char)(hi << 4 | lo);
-               i += 2;
-
-append:
-               if (git_buf_putc(decoded_out, c) < 0)
-                       return -1;
-       }
-
-       return 0;
-}
-
-static int error_invalid_local_file_uri(const char *uri)
-{
-       git_error_set(GIT_ERROR_CONFIG, "'%s' is not a valid local file URI", uri);
-       return -1;
-}
-
-static int local_file_url_prefixlen(const char *file_url)
-{
-       int len = -1;
-
-       if (git__prefixcmp(file_url, "file://") == 0) {
-               if (file_url[7] == '/')
-                       len = 8;
-               else if (git__prefixcmp(file_url + 7, "localhost/") == 0)
-                       len = 17;
-       }
-
-       return len;
-}
-
-bool git_path_is_local_file_url(const char *file_url)
-{
-       return (local_file_url_prefixlen(file_url) > 0);
-}
-
-int git_path_fromurl(git_buf *local_path_out, const char *file_url)
-{
-       int offset;
-
-       GIT_ASSERT_ARG(local_path_out);
-       GIT_ASSERT_ARG(file_url);
-
-       if ((offset = local_file_url_prefixlen(file_url)) < 0 ||
-               file_url[offset] == '\0' || file_url[offset] == '/')
-               return error_invalid_local_file_uri(file_url);
-
-#ifndef GIT_WIN32
-       offset--;       /* A *nix absolute path starts with a forward slash */
-#endif
-
-       git_buf_clear(local_path_out);
-       return git__percent_decode(local_path_out, file_url + offset);
-}
-
-int git_path_walk_up(
-       git_buf *path,
-       const char *ceiling,
-       int (*cb)(void *data, const char *),
-       void *data)
-{
-       int error = 0;
-       git_buf iter;
-       ssize_t stop = 0, scan;
-       char oldc = '\0';
-
-       GIT_ASSERT_ARG(path);
-       GIT_ASSERT_ARG(cb);
-
-       if (ceiling != NULL) {
-               if (git__prefixcmp(path->ptr, ceiling) == 0)
-                       stop = (ssize_t)strlen(ceiling);
-               else
-                       stop = git_buf_len(path);
-       }
-       scan = git_buf_len(path);
-
-       /* empty path: yield only once */
-       if (!scan) {
-               error = cb(data, "");
-               if (error)
-                       git_error_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.ptr);
-               iter.ptr[scan] = oldc;
-
-               if (error) {
-                       git_error_set_after_callback(error);
-                       break;
-               }
-
-               scan = git_buf_rfind_next(&iter, '/');
-               if (scan >= 0) {
-                       scan++;
-                       oldc = iter.ptr[scan];
-                       iter.size = scan;
-                       iter.ptr[scan] = '\0';
-               }
-       }
-
-       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)
-                       git_error_set_after_callback(error);
-       }
-
-       return error;
-}
-
-bool git_path_exists(const char *path)
-{
-       GIT_ASSERT_ARG_WITH_RETVAL(path, false);
-       return p_access(path, F_OK) == 0;
-}
-
-bool git_path_isdir(const char *path)
-{
-       struct stat st;
-       if (p_stat(path, &st) < 0)
-               return false;
-
-       return S_ISDIR(st.st_mode) != 0;
-}
-
-bool git_path_isfile(const char *path)
-{
-       struct stat st;
-
-       GIT_ASSERT_ARG_WITH_RETVAL(path, false);
-       if (p_stat(path, &st) < 0)
-               return false;
-
-       return S_ISREG(st.st_mode) != 0;
-}
-
-bool git_path_islink(const char *path)
-{
-       struct stat st;
-
-       GIT_ASSERT_ARG_WITH_RETVAL(path, false);
-       if (p_lstat(path, &st) < 0)
-               return false;
-
-       return S_ISLNK(st.st_mode) != 0;
-}
-
-#ifdef GIT_WIN32
-
-bool git_path_is_empty_dir(const char *path)
-{
-       git_win32_path filter_w;
-       bool empty = false;
-
-       if (git_win32__findfirstfile_filter(filter_w, path)) {
-               WIN32_FIND_DATAW findData;
-               HANDLE hFind = FindFirstFileW(filter_w, &findData);
-
-               /* FindFirstFile will fail if there are no children to the given
-                * path, which can happen if the given path is a file (and obviously
-                * has no children) or if the given path is an empty mount point.
-                * (Most directories have at least directory entries '.' and '..',
-                * but ridiculously another volume mounted in another drive letter's
-                * path space do not, and thus have nothing to enumerate.)  If
-                * FindFirstFile fails, check if this is a directory-like thing
-                * (a mount point).
-                */
-               if (hFind == INVALID_HANDLE_VALUE)
-                       return git_path_isdir(path);
-
-               /* If the find handle was created successfully, then it's a directory */
-               empty = true;
-
-               do {
-                       /* Allow the enumeration to return . and .. and still be considered
-                        * empty. In the special case of drive roots (i.e. C:\) where . and
-                        * .. do not occur, we can still consider the path to be an empty
-                        * directory if there's nothing there. */
-                       if (!git_path_is_dot_or_dotdotW(findData.cFileName)) {
-                               empty = false;
-                               break;
-                       }
-               } while (FindNextFileW(hFind, &findData));
-
-               FindClose(hFind);
-       }
-
-       return empty;
-}
-
-#else
-
-static int path_found_entry(void *payload, git_buf *path)
-{
-       GIT_UNUSED(payload);
-       return !git_path_is_dot_or_dotdot(path->ptr);
-}
-
-bool git_path_is_empty_dir(const char *path)
-{
-       int error;
-       git_buf dir = GIT_BUF_INIT;
-
-       if (!git_path_isdir(path))
-               return false;
-
-       if ((error = git_buf_sets(&dir, path)) != 0)
-               git_error_clear();
-       else
-               error = git_path_direach(&dir, 0, path_found_entry, NULL);
-
-       git_buf_dispose(&dir);
-
-       return !error;
-}
-
-#endif
-
-int git_path_set_error(int errno_value, const char *path, const char *action)
-{
-       switch (errno_value) {
-       case ENOENT:
-       case ENOTDIR:
-               git_error_set(GIT_ERROR_OS, "could not find '%s' to %s", path, action);
-               return GIT_ENOTFOUND;
-
-       case EINVAL:
-       case ENAMETOOLONG:
-               git_error_set(GIT_ERROR_OS, "invalid path for filesystem '%s'", path);
-               return GIT_EINVALIDSPEC;
-
-       case EEXIST:
-               git_error_set(GIT_ERROR_OS, "failed %s - '%s' already exists", action, path);
-               return GIT_EEXISTS;
-
-       case EACCES:
-               git_error_set(GIT_ERROR_OS, "failed %s - '%s' is locked", action, path);
-               return GIT_ELOCKED;
-
-       default:
-               git_error_set(GIT_ERROR_OS, "could not %s '%s'", action, path);
-               return -1;
-       }
-}
-
-int git_path_lstat(const char *path, struct stat *st)
-{
-       if (p_lstat(path, st) == 0)
-               return 0;
-
-       return git_path_set_error(errno, path, "stat");
-}
-
-static bool _check_dir_contents(
-       git_buf *dir,
-       const char *sub,
-       bool (*predicate)(const char *))
-{
-       bool result;
-       size_t dir_size = git_buf_len(dir);
-       size_t sub_size = strlen(sub);
-       size_t alloc_size;
-
-       /* leave base valid even if we could not make space for subdir */
-       if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, dir_size, sub_size) ||
-               GIT_ADD_SIZET_OVERFLOW(&alloc_size, alloc_size, 2) ||
-               git_buf_try_grow(dir, alloc_size, false) < 0)
-               return false;
-
-       /* save excursion */
-       if (git_buf_joinpath(dir, dir->ptr, sub) < 0)
-               return false;
-
-       result = predicate(dir->ptr);
-
-       /* restore path */
-       git_buf_truncate(dir, dir_size);
-       return result;
-}
-
-bool git_path_contains(git_buf *dir, const char *item)
-{
-       return _check_dir_contents(dir, item, &git_path_exists);
-}
-
-bool git_path_contains_dir(git_buf *base, const char *subdir)
-{
-       return _check_dir_contents(base, subdir, &git_path_isdir);
-}
-
-bool git_path_contains_file(git_buf *base, const char *file)
-{
-       return _check_dir_contents(base, file, &git_path_isfile);
-}
-
-int git_path_find_dir(git_buf *dir)
-{
-       int error = 0;
-       char buf[GIT_PATH_MAX];
-
-       if (p_realpath(dir->ptr, buf) != NULL)
-               error = git_buf_sets(dir, buf);
-
-       /* call dirname if this is not a directory */
-       if (!error) /* && git_path_isdir(dir->ptr) == false) */
-               error = (git_path_dirname_r(dir, dir->ptr) < 0) ? -1 : 0;
-
-       if (!error)
-               error = git_path_to_dir(dir);
-
-       return error;
-}
-
-int git_path_resolve_relative(git_buf *path, size_t ceiling)
-{
-       char *base, *to, *from, *next;
-       size_t len;
-
-       GIT_ERROR_CHECK_ALLOC_BUF(path);
-
-       if (ceiling > path->size)
-               ceiling = path->size;
-
-       /* recognize drive prefixes, etc. that should not be backed over */
-       if (ceiling == 0)
-               ceiling = git_path_root(path->ptr) + 1;
-
-       /* recognize URL prefixes that should not be backed over */
-       if (ceiling == 0) {
-               for (next = path->ptr; *next && git__isalpha(*next); ++next);
-               if (next[0] == ':' && next[1] == '/' && next[2] == '/')
-                       ceiling = (next + 3) - path->ptr;
-       }
-
-       base = to = from = path->ptr + ceiling;
-
-       while (*from) {
-               for (next = from; *next && *next != '/'; ++next);
-
-               len = next - from;
-
-               if (len == 1 && from[0] == '.')
-                       /* do nothing with singleton dot */;
-
-               else if (len == 2 && from[0] == '.' && from[1] == '.') {
-                       /* error out if trying to up one from a hard base */
-                       if (to == base && ceiling != 0) {
-                               git_error_set(GIT_ERROR_INVALID,
-                                       "cannot strip root component off url");
-                               return -1;
-                       }
-
-                       /* no more path segments to strip,
-                        * use '../' as a new base path */
-                       if (to == base) {
-                               if (*next == '/')
-                                       len++;
-
-                               if (to != from)
-                                       memmove(to, from, len);
-
-                               to += len;
-                               /* this is now the base, can't back up from a
-                                * relative prefix */
-                               base = to;
-                       } else {
-                               /* back up a path segment */
-                               while (to > base && to[-1] == '/') to--;
-                               while (to > base && to[-1] != '/') to--;
-                       }
-               } else {
-                       if (*next == '/' && *from != '/')
-                               len++;
-
-                       if (to != from)
-                               memmove(to, from, len);
-
-                       to += len;
-               }
-
-               from += len;
-
-               while (*from == '/') from++;
-       }
-
-       *to = '\0';
-
-       path->size = to - path->ptr;
-
-       return 0;
-}
-
-int git_path_apply_relative(git_buf *target, const char *relpath)
-{
-       return git_buf_joinpath(target, git_buf_cstr(target), relpath) ||
-           git_path_resolve_relative(target, 0);
-}
-
-int git_path_cmp(
-       const char *name1, size_t len1, int isdir1,
-       const char *name2, size_t len2, int isdir2,
-       int (*compare)(const char *, const char *, size_t))
-{
-       unsigned char c1, c2;
-       size_t len = len1 < len2 ? len1 : len2;
-       int cmp;
-
-       cmp = compare(name1, name2, len);
-       if (cmp)
-               return cmp;
-
-       c1 = name1[len];
-       c2 = name2[len];
-
-       if (c1 == '\0' && isdir1)
-               c1 = '/';
-
-       if (c2 == '\0' && isdir2)
-               c2 = '/';
-
-       return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
-}
-
-size_t git_path_common_dirlen(const char *one, const char *two)
-{
-       const char *p, *q, *dirsep = NULL;
-
-       for (p = one, q = two; *p && *q; p++, q++) {
-               if (*p == '/' && *q == '/')
-                       dirsep = p;
-               else if (*p != *q)
-                       break;
-       }
-
-       return dirsep ? (dirsep - one) + 1 : 0;
-}
-
-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, alloclen, depth = 1, i, offset;
-
-       for (p_dirsep = p = path->ptr, q_dirsep = q = parent; *p && *q; p++, q++) {
-               if (*p == '/' && *q == '/') {
-                       p_dirsep = p;
-                       q_dirsep = q;
-               }
-               else if (*p != *q)
-                       break;
-       }
-
-       /* need at least 1 common path segment */
-       if ((p_dirsep == path->ptr || q_dirsep == parent) &&
-               (*p_dirsep != '/' || *q_dirsep != '/')) {
-               git_error_set(GIT_ERROR_INVALID,
-                       "%s is not a parent of %s", parent, path->ptr);
-               return GIT_ENOTFOUND;
-       }
-
-       if (*p == '/' && !*q)
-               p++;
-       else if (!*p && *q == '/')
-               q++;
-       else if (!*p && !*q)
-               return git_buf_clear(path), 0;
-       else {
-               p = p_dirsep + 1;
-               q = q_dirsep + 1;
-       }
-
-       plen -= (p - path->ptr);
-
-       if (!*q)
-               return git_buf_set(path, p, plen);
-
-       for (; (q = strchr(q, '/')) && *(q + 1); q++)
-               depth++;
-
-       GIT_ERROR_CHECK_ALLOC_MULTIPLY(&newlen, depth, 3);
-       GIT_ERROR_CHECK_ALLOC_ADD(&newlen, newlen, plen);
-
-       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, newlen, 1);
-
-       /* save the offset as we might realllocate the pointer */
-       offset = p - path->ptr;
-       if (git_buf_try_grow(path, alloclen, 1) < 0)
-               return -1;
-       p = path->ptr + offset;
-
-       memmove(path->ptr + (depth * 3), p, plen + 1);
-
-       for (i = 0; i < depth; i++)
-               memcpy(path->ptr + (i * 3), "../", 3);
-
-       path->size = newlen;
-       return 0;
-}
-
-bool git_path_has_non_ascii(const char *path, size_t pathlen)
-{
-       const uint8_t *scan = (const uint8_t *)path, *end;
-
-       for (end = scan + pathlen; scan < end; ++scan)
-               if (*scan & 0x80)
-                       return true;
-
-       return false;
-}
-
-#ifdef GIT_USE_ICONV
-
-int git_path_iconv_init_precompose(git_path_iconv_t *ic)
-{
-       git_buf_init(&ic->buf, 0);
-       ic->map = iconv_open(GIT_PATH_REPO_ENCODING, GIT_PATH_NATIVE_ENCODING);
-       return 0;
-}
-
-void git_path_iconv_clear(git_path_iconv_t *ic)
-{
-       if (ic) {
-               if (ic->map != (iconv_t)-1)
-                       iconv_close(ic->map);
-               git_buf_dispose(&ic->buf);
-       }
-}
-
-int git_path_iconv(git_path_iconv_t *ic, const char **in, size_t *inlen)
-{
-       char *nfd = (char*)*in, *nfc;
-       size_t nfdlen = *inlen, nfclen, wantlen = nfdlen, alloclen, rv;
-       int retry = 1;
-
-       if (!ic || ic->map == (iconv_t)-1 ||
-               !git_path_has_non_ascii(*in, *inlen))
-               return 0;
-
-       git_buf_clear(&ic->buf);
-
-       while (1) {
-               GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, wantlen, 1);
-               if (git_buf_grow(&ic->buf, alloclen) < 0)
-                       return -1;
-
-               nfc    = ic->buf.ptr   + ic->buf.size;
-               nfclen = ic->buf.asize - ic->buf.size;
-
-               rv = iconv(ic->map, &nfd, &nfdlen, &nfc, &nfclen);
-
-               ic->buf.size = (nfc - ic->buf.ptr);
-
-               if (rv != (size_t)-1)
-                       break;
-
-               /* if we cannot convert the data (probably because iconv thinks
-                * it is not valid UTF-8 source data), then use original data
-                */
-               if (errno != E2BIG)
-                       return 0;
-
-               /* make space for 2x the remaining data to be converted
-                * (with per retry overhead to avoid infinite loops)
-                */
-               wantlen = ic->buf.size + max(nfclen, nfdlen) * 2 + (size_t)(retry * 4);
-
-               if (retry++ > 4)
-                       goto fail;
-       }
-
-       ic->buf.ptr[ic->buf.size] = '\0';
-
-       *in    = ic->buf.ptr;
-       *inlen = ic->buf.size;
-
-       return 0;
-
-fail:
-       git_error_set(GIT_ERROR_OS, "unable to convert unicode path data");
-       return -1;
-}
-
-static const char *nfc_file = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D.XXXXXX";
-static const char *nfd_file = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D.XXXXXX";
-
-/* Check if the platform is decomposing unicode data for us.  We will
- * emulate core Git and prefer to use precomposed unicode data internally
- * on these platforms, composing the decomposed unicode on the fly.
- *
- * This mainly happens on the Mac where HDFS stores filenames as
- * decomposed unicode.  Even on VFAT and SAMBA file systems, the Mac will
- * return decomposed unicode from readdir() even when the actual
- * filesystem is storing precomposed unicode.
- */
-bool git_path_does_fs_decompose_unicode(const char *root)
-{
-       git_buf path = GIT_BUF_INIT;
-       int fd;
-       bool found_decomposed = false;
-       char tmp[6];
-
-       /* Create a file using a precomposed path and then try to find it
-        * using the decomposed name.  If the lookup fails, then we will mark
-        * that we should precompose unicode for this repository.
-        */
-       if (git_buf_joinpath(&path, root, nfc_file) < 0 ||
-               (fd = p_mkstemp(path.ptr)) < 0)
-               goto done;
-       p_close(fd);
-
-       /* record trailing digits generated by mkstemp */
-       memcpy(tmp, path.ptr + path.size - sizeof(tmp), sizeof(tmp));
-
-       /* try to look up as NFD path */
-       if (git_buf_joinpath(&path, root, nfd_file) < 0)
-               goto done;
-       memcpy(path.ptr + path.size - sizeof(tmp), tmp, sizeof(tmp));
-
-       found_decomposed = git_path_exists(path.ptr);
-
-       /* remove temporary file (using original precomposed path) */
-       if (git_buf_joinpath(&path, root, nfc_file) < 0)
-               goto done;
-       memcpy(path.ptr + path.size - sizeof(tmp), tmp, sizeof(tmp));
-
-       (void)p_unlink(path.ptr);
-
-done:
-       git_buf_dispose(&path);
-       return found_decomposed;
-}
-
-#else
-
-bool git_path_does_fs_decompose_unicode(const char *root)
-{
-       GIT_UNUSED(root);
-       return false;
-}
-
-#endif
-
-#if defined(__sun) || defined(__GNU__)
-typedef char path_dirent_data[sizeof(struct dirent) + FILENAME_MAX + 1];
-#else
-typedef struct dirent path_dirent_data;
-#endif
-
-int git_path_direach(
-       git_buf *path,
-       uint32_t flags,
-       int (*fn)(void *, git_buf *),
-       void *arg)
-{
-       int error = 0;
-       ssize_t wd_len;
-       DIR *dir;
-       struct dirent *de;
-
-#ifdef GIT_USE_ICONV
-       git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
-#endif
-
-       GIT_UNUSED(flags);
-
-       if (git_path_to_dir(path) < 0)
-               return -1;
-
-       wd_len = git_buf_len(path);
-
-       if ((dir = opendir(path->ptr)) == NULL) {
-               git_error_set(GIT_ERROR_OS, "failed to open directory '%s'", path->ptr);
-               if (errno == ENOENT)
-                       return GIT_ENOTFOUND;
-
-               return -1;
-       }
-
-#ifdef GIT_USE_ICONV
-       if ((flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0)
-               (void)git_path_iconv_init_precompose(&ic);
-#endif
-
-       while ((de = readdir(dir)) != NULL) {
-               const char *de_path = de->d_name;
-               size_t de_len = strlen(de_path);
-
-               if (git_path_is_dot_or_dotdot(de_path))
-                       continue;
-
-#ifdef GIT_USE_ICONV
-               if ((error = git_path_iconv(&ic, &de_path, &de_len)) < 0)
-                       break;
-#endif
-
-               if ((error = git_buf_put(path, de_path, de_len)) < 0)
-                       break;
-
-               git_error_clear();
-               error = fn(arg, path);
-
-               git_buf_truncate(path, wd_len); /* restore path */
-
-               /* Only set our own error if the callback did not set one already */
-               if (error != 0) {
-                       if (!git_error_last())
-                               git_error_set_after_callback(error);
-
-                       break;
-               }
-       }
-
-       closedir(dir);
-
-#ifdef GIT_USE_ICONV
-       git_path_iconv_clear(&ic);
-#endif
-
-       return error;
-}
-
-#if defined(GIT_WIN32) && !defined(__MINGW32__)
-
-/* Using _FIND_FIRST_EX_LARGE_FETCH may increase performance in Windows 7
- * and better.
- */
-#ifndef FIND_FIRST_EX_LARGE_FETCH
-# define FIND_FIRST_EX_LARGE_FETCH 2
-#endif
-
-int git_path_diriter_init(
-       git_path_diriter *diriter,
-       const char *path,
-       unsigned int flags)
-{
-       git_win32_path path_filter;
-
-       static int is_win7_or_later = -1;
-       if (is_win7_or_later < 0)
-               is_win7_or_later = git_has_win32_version(6, 1, 0);
+#include "fs_path.h"
 
-       GIT_ASSERT_ARG(diriter);
-       GIT_ASSERT_ARG(path);
-
-       memset(diriter, 0, sizeof(git_path_diriter));
-       diriter->handle = INVALID_HANDLE_VALUE;
-
-       if (git_buf_puts(&diriter->path_utf8, path) < 0)
-               return -1;
-
-       path_trim_slashes(&diriter->path_utf8);
-
-       if (diriter->path_utf8.size == 0) {
-               git_error_set(GIT_ERROR_FILESYSTEM, "could not open directory '%s'", path);
-               return -1;
-       }
-
-       if ((diriter->parent_len = git_win32_path_from_utf8(diriter->path, diriter->path_utf8.ptr)) < 0 ||
-                       !git_win32__findfirstfile_filter(path_filter, diriter->path_utf8.ptr)) {
-               git_error_set(GIT_ERROR_OS, "could not parse the directory path '%s'", path);
-               return -1;
-       }
-
-       diriter->handle = FindFirstFileExW(
-               path_filter,
-               is_win7_or_later ? FindExInfoBasic : FindExInfoStandard,
-               &diriter->current,
-               FindExSearchNameMatch,
-               NULL,
-               is_win7_or_later ? FIND_FIRST_EX_LARGE_FETCH : 0);
-
-       if (diriter->handle == INVALID_HANDLE_VALUE) {
-               git_error_set(GIT_ERROR_OS, "could not open directory '%s'", path);
-               return -1;
-       }
-
-       diriter->parent_utf8_len = diriter->path_utf8.size;
-       diriter->flags = flags;
-       return 0;
-}
-
-static int diriter_update_paths(git_path_diriter *diriter)
-{
-       size_t filename_len, path_len;
-
-       filename_len = wcslen(diriter->current.cFileName);
-
-       if (GIT_ADD_SIZET_OVERFLOW(&path_len, diriter->parent_len, filename_len) ||
-               GIT_ADD_SIZET_OVERFLOW(&path_len, path_len, 2))
-               return -1;
-
-       if (path_len > GIT_WIN_PATH_UTF16) {
-               git_error_set(GIT_ERROR_FILESYSTEM,
-                       "invalid path '%.*ls\\%ls' (path too long)",
-                       diriter->parent_len, diriter->path, diriter->current.cFileName);
-               return -1;
-       }
-
-       diriter->path[diriter->parent_len] = L'\\';
-       memcpy(&diriter->path[diriter->parent_len+1],
-               diriter->current.cFileName, filename_len * sizeof(wchar_t));
-       diriter->path[path_len-1] = L'\0';
-
-       git_buf_truncate(&diriter->path_utf8, diriter->parent_utf8_len);
-
-       if (diriter->parent_utf8_len > 0 &&
-               diriter->path_utf8.ptr[diriter->parent_utf8_len-1] != '/')
-               git_buf_putc(&diriter->path_utf8, '/');
-
-       git_buf_put_w(&diriter->path_utf8, diriter->current.cFileName, filename_len);
-
-       if (git_buf_oom(&diriter->path_utf8))
-               return -1;
-
-       return 0;
-}
-
-int git_path_diriter_next(git_path_diriter *diriter)
-{
-       bool skip_dot = !(diriter->flags & GIT_PATH_DIR_INCLUDE_DOT_AND_DOTDOT);
-
-       do {
-               /* Our first time through, we already have the data from
-                * FindFirstFileW.  Use it, otherwise get the next file.
-                */
-               if (!diriter->needs_next)
-                       diriter->needs_next = 1;
-               else if (!FindNextFileW(diriter->handle, &diriter->current))
-                       return GIT_ITEROVER;
-       } while (skip_dot && git_path_is_dot_or_dotdotW(diriter->current.cFileName));
-
-       if (diriter_update_paths(diriter) < 0)
-               return -1;
-
-       return 0;
-}
-
-int git_path_diriter_filename(
-       const char **out,
-       size_t *out_len,
-       git_path_diriter *diriter)
-{
-       GIT_ASSERT_ARG(out);
-       GIT_ASSERT_ARG(out_len);
-       GIT_ASSERT_ARG(diriter);
-       GIT_ASSERT(diriter->path_utf8.size > diriter->parent_utf8_len);
-
-       *out = &diriter->path_utf8.ptr[diriter->parent_utf8_len+1];
-       *out_len = diriter->path_utf8.size - diriter->parent_utf8_len - 1;
-       return 0;
-}
-
-int git_path_diriter_fullpath(
-       const char **out,
-       size_t *out_len,
-       git_path_diriter *diriter)
-{
-       GIT_ASSERT_ARG(out);
-       GIT_ASSERT_ARG(out_len);
-       GIT_ASSERT_ARG(diriter);
-
-       *out = diriter->path_utf8.ptr;
-       *out_len = diriter->path_utf8.size;
-       return 0;
-}
-
-int git_path_diriter_stat(struct stat *out, git_path_diriter *diriter)
-{
-       GIT_ASSERT_ARG(out);
-       GIT_ASSERT_ARG(diriter);
-
-       return git_win32__file_attribute_to_stat(out,
-               (WIN32_FILE_ATTRIBUTE_DATA *)&diriter->current,
-               diriter->path);
-}
-
-void git_path_diriter_free(git_path_diriter *diriter)
-{
-       if (diriter == NULL)
-               return;
-
-       git_buf_dispose(&diriter->path_utf8);
-
-       if (diriter->handle != INVALID_HANDLE_VALUE) {
-               FindClose(diriter->handle);
-               diriter->handle = INVALID_HANDLE_VALUE;
-       }
-}
-
-#else
-
-int git_path_diriter_init(
-       git_path_diriter *diriter,
-       const char *path,
-       unsigned int flags)
-{
-       GIT_ASSERT_ARG(diriter);
-       GIT_ASSERT_ARG(path);
-
-       memset(diriter, 0, sizeof(git_path_diriter));
-
-       if (git_buf_puts(&diriter->path, path) < 0)
-               return -1;
-
-       path_trim_slashes(&diriter->path);
-
-       if (diriter->path.size == 0) {
-               git_error_set(GIT_ERROR_FILESYSTEM, "could not open directory '%s'", path);
-               return -1;
-       }
-
-       if ((diriter->dir = opendir(diriter->path.ptr)) == NULL) {
-               git_buf_dispose(&diriter->path);
-
-               git_error_set(GIT_ERROR_OS, "failed to open directory '%s'", path);
-               return -1;
-       }
-
-#ifdef GIT_USE_ICONV
-       if ((flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0)
-               (void)git_path_iconv_init_precompose(&diriter->ic);
-#endif
-
-       diriter->parent_len = diriter->path.size;
-       diriter->flags = flags;
-
-       return 0;
-}
-
-int git_path_diriter_next(git_path_diriter *diriter)
-{
-       struct dirent *de;
-       const char *filename;
-       size_t filename_len;
-       bool skip_dot = !(diriter->flags & GIT_PATH_DIR_INCLUDE_DOT_AND_DOTDOT);
-       int error = 0;
-
-       GIT_ASSERT_ARG(diriter);
-
-       errno = 0;
-
-       do {
-               if ((de = readdir(diriter->dir)) == NULL) {
-                       if (!errno)
-                               return GIT_ITEROVER;
-
-                       git_error_set(GIT_ERROR_OS,
-                               "could not read directory '%s'", diriter->path.ptr);
-                       return -1;
-               }
-       } while (skip_dot && git_path_is_dot_or_dotdot(de->d_name));
-
-       filename = de->d_name;
-       filename_len = strlen(filename);
-
-#ifdef GIT_USE_ICONV
-       if ((diriter->flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0 &&
-               (error = git_path_iconv(&diriter->ic, &filename, &filename_len)) < 0)
-               return error;
-#endif
-
-       git_buf_truncate(&diriter->path, diriter->parent_len);
-
-       if (diriter->parent_len > 0 &&
-               diriter->path.ptr[diriter->parent_len-1] != '/')
-               git_buf_putc(&diriter->path, '/');
-
-       git_buf_put(&diriter->path, filename, filename_len);
-
-       if (git_buf_oom(&diriter->path))
-               return -1;
-
-       return error;
-}
-
-int git_path_diriter_filename(
-       const char **out,
-       size_t *out_len,
-       git_path_diriter *diriter)
-{
-       GIT_ASSERT_ARG(out);
-       GIT_ASSERT_ARG(out_len);
-       GIT_ASSERT_ARG(diriter);
-       GIT_ASSERT(diriter->path.size > diriter->parent_len);
-
-       *out = &diriter->path.ptr[diriter->parent_len+1];
-       *out_len = diriter->path.size - diriter->parent_len - 1;
-       return 0;
-}
-
-int git_path_diriter_fullpath(
-       const char **out,
-       size_t *out_len,
-       git_path_diriter *diriter)
-{
-       GIT_ASSERT_ARG(out);
-       GIT_ASSERT_ARG(out_len);
-       GIT_ASSERT_ARG(diriter);
-
-       *out = diriter->path.ptr;
-       *out_len = diriter->path.size;
-       return 0;
-}
-
-int git_path_diriter_stat(struct stat *out, git_path_diriter *diriter)
-{
-       GIT_ASSERT_ARG(out);
-       GIT_ASSERT_ARG(diriter);
-
-       return git_path_lstat(diriter->path.ptr, out);
-}
-
-void git_path_diriter_free(git_path_diriter *diriter)
-{
-       if (diriter == NULL)
-               return;
-
-       if (diriter->dir) {
-               closedir(diriter->dir);
-               diriter->dir = NULL;
-       }
-
-#ifdef GIT_USE_ICONV
-       git_path_iconv_clear(&diriter->ic);
-#endif
-
-       git_buf_dispose(&diriter->path);
-}
-
-#endif
-
-int git_path_dirload(
-       git_vector *contents,
-       const char *path,
-       size_t prefix_len,
-       uint32_t flags)
-{
-       git_path_diriter iter = GIT_PATH_DIRITER_INIT;
-       const char *name;
-       size_t name_len;
-       char *dup;
-       int error;
-
-       GIT_ASSERT_ARG(contents);
-       GIT_ASSERT_ARG(path);
-
-       if ((error = git_path_diriter_init(&iter, path, flags)) < 0)
-               return error;
-
-       while ((error = git_path_diriter_next(&iter)) == 0) {
-               if ((error = git_path_diriter_fullpath(&name, &name_len, &iter)) < 0)
-                       break;
-
-               GIT_ASSERT(name_len > prefix_len);
-
-               dup = git__strndup(name + prefix_len, name_len - prefix_len);
-               GIT_ERROR_CHECK_ALLOC(dup);
-
-               if ((error = git_vector_insert(contents, dup)) < 0)
-                       break;
-       }
-
-       if (error == GIT_ITEROVER)
-               error = 0;
-
-       git_path_diriter_free(&iter);
-       return error;
-}
-
-int git_path_from_url_or_path(git_buf *local_path_out, const char *url_or_path)
-{
-       if (git_path_is_local_file_url(url_or_path))
-               return git_path_fromurl(local_path_out, url_or_path);
-       else
-               return git_buf_sets(local_path_out, url_or_path);
-}
-
-/* Reject paths like AUX or COM1, or those versions that end in a dot or
- * colon.  ("AUX." or "AUX:")
- */
-GIT_INLINE(bool) verify_dospath(
-       const char *component,
-       size_t len,
-       const char dospath[3],
-       bool trailing_num)
-{
-       size_t last = trailing_num ? 4 : 3;
-
-       if (len < last || git__strncasecmp(component, dospath, 3) != 0)
-               return true;
-
-       if (trailing_num && (component[3] < '1' || component[3] > '9'))
-               return true;
-
-       return (len > last &&
-               component[last] != '.' &&
-               component[last] != ':');
-}
+typedef struct {
+       git_repository *repo;
+       uint16_t file_mode;
+       unsigned int flags;
+} repository_path_validate_data;
 
 static int32_t next_hfs_char(const char **in, size_t *len)
 {
@@ -1598,7 +57,11 @@ static int32_t next_hfs_char(const char **in, size_t *len)
        return 0; /* NULL byte -- end of string */
 }
 
-static bool verify_dotgit_hfs_generic(const char *path, size_t len, const char *needle, size_t needle_len)
+static bool validate_dotgit_hfs_generic(
+       const char *path,
+       size_t len,
+       const char *needle,
+       size_t needle_len)
 {
        size_t i;
        char c;
@@ -1618,14 +81,17 @@ static bool verify_dotgit_hfs_generic(const char *path, size_t len, const char *
        return false;
 }
 
-static bool verify_dotgit_hfs(const char *path, size_t len)
+static bool validate_dotgit_hfs(const char *path, size_t len)
 {
-       return verify_dotgit_hfs_generic(path, len, "git", CONST_STRLEN("git"));
+       return validate_dotgit_hfs_generic(path, len, "git", CONST_STRLEN("git"));
 }
 
-GIT_INLINE(bool) verify_dotgit_ntfs(git_repository *repo, const char *path, size_t len)
+GIT_INLINE(bool) validate_dotgit_ntfs(
+       git_repository *repo,
+       const char *path,
+       size_t len)
 {
-       git_buf *reserved = git_repository__reserved_names_win32;
+       git_str *reserved = git_repository__reserved_names_win32;
        size_t reserved_len = git_repository__reserved_names_win32_len;
        size_t start = 0, i;
 
@@ -1633,7 +99,7 @@ GIT_INLINE(bool) verify_dotgit_ntfs(git_repository *repo, const char *path, size
                git_repository__reserved_names(&reserved, &reserved_len, repo, true);
 
        for (i = 0; i < reserved_len; i++) {
-               git_buf *r = &reserved[i];
+               git_str *r = &reserved[i];
 
                if (len >= r->size &&
                        strncasecmp(path, r->ptr, r->size) == 0) {
@@ -1685,7 +151,12 @@ GIT_INLINE(bool) ntfs_end_of_filename(const char *path)
        return true;
 }
 
-GIT_INLINE(bool) verify_dotgit_ntfs_generic(const char *name, size_t len, const char *dotgit_name, size_t dotgit_len, const char *shortname_pfix)
+GIT_INLINE(bool) validate_dotgit_ntfs_generic(
+       const char *name,
+       size_t len,
+       const char *dotgit_name,
+       size_t dotgit_len,
+       const char *shortname_pfix)
 {
        int i, saw_tilde;
 
@@ -1722,33 +193,6 @@ GIT_INLINE(bool) verify_dotgit_ntfs_generic(const char *name, size_t len, const
        return !ntfs_end_of_filename(name + i);
 }
 
-GIT_INLINE(bool) verify_char(unsigned char c, unsigned int flags)
-{
-       if ((flags & GIT_PATH_REJECT_BACKSLASH) && c == '\\')
-               return false;
-
-       if ((flags & GIT_PATH_REJECT_SLASH) && c == '/')
-               return false;
-
-       if (flags & GIT_PATH_REJECT_NT_CHARS) {
-               if (c < 32)
-                       return false;
-
-               switch (c) {
-               case '<':
-               case '>':
-               case ':':
-               case '"':
-               case '|':
-               case '?':
-               case '*':
-                       return false;
-               }
-       }
-
-       return true;
-}
-
 /*
  * Return the length of the common prefix between str and prefix, comparing them
  * case-insensitively (must be ASCII to match).
@@ -1757,7 +201,7 @@ GIT_INLINE(size_t) common_prefix_icase(const char *str, size_t len, const char *
 {
        size_t count = 0;
 
-       while (len >0 && tolower(*str) == tolower(*prefix)) {
+       while (len > 0 && tolower(*str) == tolower(*prefix)) {
                count++;
                str++;
                prefix++;
@@ -1767,72 +211,37 @@ GIT_INLINE(size_t) common_prefix_icase(const char *str, size_t len, const char *
        return count;
 }
 
-/*
- * We fundamentally don't like some paths when dealing with user-inputted
- * strings (in checkout or ref names): we don't want dot or dot-dot
- * anywhere, we want to avoid writing weird paths on Windows that can't
- * be handled by tools that use the non-\\?\ APIs, we don't want slashes
- * or double slashes at the end of paths that can make them ambiguous.
- *
- * For checkout, we don't want to recurse into ".git" either.
- */
-static bool verify_component(
-       git_repository *repo,
+static bool validate_repo_component(
        const char *component,
        size_t len,
-       uint16_t mode,
-       unsigned int flags)
+       void *payload)
 {
-       if (len == 0)
-               return false;
-
-       if ((flags & GIT_PATH_REJECT_TRAVERSAL) &&
-               len == 1 && component[0] == '.')
-               return false;
-
-       if ((flags & GIT_PATH_REJECT_TRAVERSAL) &&
-               len == 2 && component[0] == '.' && component[1] == '.')
-               return false;
-
-       if ((flags & GIT_PATH_REJECT_TRAILING_DOT) && component[len-1] == '.')
-               return false;
-
-       if ((flags & GIT_PATH_REJECT_TRAILING_SPACE) && component[len-1] == ' ')
-               return false;
-
-       if ((flags & GIT_PATH_REJECT_TRAILING_COLON) && component[len-1] == ':')
-               return false;
+       repository_path_validate_data *data = (repository_path_validate_data *)payload;
 
-       if (flags & GIT_PATH_REJECT_DOS_PATHS) {
-               if (!verify_dospath(component, len, "CON", false) ||
-                       !verify_dospath(component, len, "PRN", false) ||
-                       !verify_dospath(component, len, "AUX", false) ||
-                       !verify_dospath(component, len, "NUL", false) ||
-                       !verify_dospath(component, len, "COM", true)  ||
-                       !verify_dospath(component, len, "LPT", true))
+       if (data->flags & GIT_PATH_REJECT_DOT_GIT_HFS) {
+               if (!validate_dotgit_hfs(component, len))
                        return false;
-       }
 
-       if (flags & GIT_PATH_REJECT_DOT_GIT_HFS) {
-               if (!verify_dotgit_hfs(component, len))
-                       return false;
-               if (S_ISLNK(mode) && git_path_is_gitfile(component, len, GIT_PATH_GITFILE_GITMODULES, GIT_PATH_FS_HFS))
+               if (S_ISLNK(data->file_mode) &&
+                   git_path_is_gitfile(component, len, GIT_PATH_GITFILE_GITMODULES, GIT_PATH_FS_HFS))
                        return false;
        }
 
-       if (flags & GIT_PATH_REJECT_DOT_GIT_NTFS) {
-               if (!verify_dotgit_ntfs(repo, component, len))
+       if (data->flags & GIT_PATH_REJECT_DOT_GIT_NTFS) {
+               if (!validate_dotgit_ntfs(data->repo, component, len))
                        return false;
-               if (S_ISLNK(mode) && git_path_is_gitfile(component, len, GIT_PATH_GITFILE_GITMODULES, GIT_PATH_FS_NTFS))
+
+               if (S_ISLNK(data->file_mode) &&
+                   git_path_is_gitfile(component, len, GIT_PATH_GITFILE_GITMODULES, GIT_PATH_FS_NTFS))
                        return false;
        }
 
        /* don't bother rerunning the `.git` test if we ran the HFS or NTFS
         * specific tests, they would have already rejected `.git`.
         */
-       if ((flags & GIT_PATH_REJECT_DOT_GIT_HFS) == 0 &&
-           (flags & GIT_PATH_REJECT_DOT_GIT_NTFS) == 0 &&
-           (flags & GIT_PATH_REJECT_DOT_GIT_LITERAL)) {
+       if ((data->flags & GIT_PATH_REJECT_DOT_GIT_HFS) == 0 &&
+           (data->flags & GIT_PATH_REJECT_DOT_GIT_NTFS) == 0 &&
+           (data->flags & GIT_PATH_REJECT_DOT_GIT_LITERAL)) {
                if (len >= 4 &&
                    component[0] == '.' &&
                    (component[1] == 'g' || component[1] == 'G') &&
@@ -1841,10 +250,11 @@ static bool verify_component(
                        if (len == 4)
                                return false;
 
-                       if (S_ISLNK(mode) && common_prefix_icase(component, len, ".gitmodules") == len)
+                       if (S_ISLNK(data->file_mode) &&
+                           common_prefix_icase(component, len, ".gitmodules") == len)
                                return false;
                }
-           }
+       }
 
        return true;
 }
@@ -1875,93 +285,49 @@ GIT_INLINE(unsigned int) dotgit_flags(
        return flags;
 }
 
-bool git_path_validate(
+GIT_INLINE(unsigned int) length_flags(
        git_repository *repo,
-       const char *path,
-       uint16_t mode,
        unsigned int flags)
 {
-       const char *start, *c;
-
-       /* Upgrade the ".git" checks based on platform */
-       if ((flags & GIT_PATH_REJECT_DOT_GIT))
-               flags = dotgit_flags(repo, flags);
-
-       for (start = c = path; *c; c++) {
-               if (!verify_char(*c, flags))
-                       return false;
-
-               if (*c == '/') {
-                       if (!verify_component(repo, start, (c - start), mode, flags))
-                               return false;
-
-                       start = c+1;
-               }
-       }
-
-       return verify_component(repo, start, (c - start), mode, flags);
-}
-
 #ifdef GIT_WIN32
-GIT_INLINE(bool) should_validate_longpaths(git_repository *repo)
-{
-       int longpaths = 0;
+       int allow = 0;
 
        if (repo &&
-           git_repository__configmap_lookup(&longpaths, repo, GIT_CONFIGMAP_LONGPATHS) < 0)
-               longpaths = 0;
+           git_repository__configmap_lookup(&allow, repo, GIT_CONFIGMAP_LONGPATHS) < 0)
+               allow = 0;
 
-       return (longpaths == 0);
-}
+       if (allow)
+               flags &= ~GIT_FS_PATH_REJECT_LONG_PATHS;
 
 #else
-
-GIT_INLINE(bool) should_validate_longpaths(git_repository *repo)
-{
        GIT_UNUSED(repo);
-
-       return false;
-}
+       flags &= ~GIT_FS_PATH_REJECT_LONG_PATHS;
 #endif
 
-int git_path_validate_workdir(git_repository *repo, const char *path)
-{
-       if (should_validate_longpaths(repo))
-               return git_path_validate_filesystem(path, strlen(path));
-
-       return 0;
+       return flags;
 }
 
-int git_path_validate_workdir_with_len(
+bool git_path_str_is_valid(
        git_repository *repo,
-       const char *path,
-       size_t path_len)
-{
-       if (should_validate_longpaths(repo))
-               return git_path_validate_filesystem(path, path_len);
-
-       return 0;
-}
-
-int git_path_validate_workdir_buf(git_repository *repo, git_buf *path)
+       const git_str *path,
+       uint16_t file_mode,
+       unsigned int flags)
 {
-       return git_path_validate_workdir_with_len(repo, path->ptr, path->size);
-}
+       repository_path_validate_data data = {0};
 
-int git_path_normalize_slashes(git_buf *out, const char *path)
-{
-       int error;
-       char *p;
+       /* Upgrade the ".git" checks based on platform */
+       if ((flags & GIT_PATH_REJECT_DOT_GIT))
+               flags = dotgit_flags(repo, flags);
 
-       if ((error = git_buf_puts(out, path)) < 0)
-               return error;
+       /* Update the length checks based on platform */
+       if ((flags & GIT_FS_PATH_REJECT_LONG_PATHS))
+               flags = length_flags(repo, flags);
 
-       for (p = out->ptr; *p; p++) {
-               if (*p == '\\')
-                       *p = '/';
-       }
+       data.repo = repo;
+       data.file_mode = file_mode;
+       data.flags = flags;
 
-       return 0;
+       return git_fs_path_str_is_valid_ext(path, flags, NULL, validate_repo_component, NULL, &data);
 }
 
 static const struct {
@@ -1974,7 +340,11 @@ static const struct {
        { "gitattributes", "gi7d29", CONST_STRLEN("gitattributes") }
 };
 
-extern int git_path_is_gitfile(const char *path, size_t pathlen, git_path_gitfile gitfile, git_path_fs fs)
+extern int git_path_is_gitfile(
+       const char *path,
+       size_t pathlen,
+       git_path_gitfile gitfile,
+       git_path_fs fs)
 {
        const char *file, *hash;
        size_t filelen;
@@ -1990,112 +360,15 @@ extern int git_path_is_gitfile(const char *path, size_t pathlen, git_path_gitfil
 
        switch (fs) {
        case GIT_PATH_FS_GENERIC:
-               return !verify_dotgit_ntfs_generic(path, pathlen, file, filelen, hash) ||
-                      !verify_dotgit_hfs_generic(path, pathlen, file, filelen);
+               return !validate_dotgit_ntfs_generic(path, pathlen, file, filelen, hash) ||
+                      !validate_dotgit_hfs_generic(path, pathlen, file, filelen);
        case GIT_PATH_FS_NTFS:
-               return !verify_dotgit_ntfs_generic(path, pathlen, file, filelen, hash);
+               return !validate_dotgit_ntfs_generic(path, pathlen, file, filelen, hash);
        case GIT_PATH_FS_HFS:
-               return !verify_dotgit_hfs_generic(path, pathlen, file, filelen);
+               return !validate_dotgit_hfs_generic(path, pathlen, file, filelen);
        default:
                git_error_set(GIT_ERROR_OS, "invalid filesystem for path validation");
                return -1;
        }
 }
 
-bool git_path_supports_symlinks(const char *dir)
-{
-       git_buf path = GIT_BUF_INIT;
-       bool supported = false;
-       struct stat st;
-       int fd;
-
-       if ((fd = git_futils_mktmp(&path, dir, 0666)) < 0 ||
-           p_close(fd) < 0 ||
-           p_unlink(path.ptr) < 0 ||
-           p_symlink("testing", path.ptr) < 0 ||
-           p_lstat(path.ptr, &st) < 0)
-               goto done;
-
-       supported = (S_ISLNK(st.st_mode) != 0);
-done:
-       if (path.size)
-               (void)p_unlink(path.ptr);
-       git_buf_dispose(&path);
-       return supported;
-}
-
-int git_path_validate_system_file_ownership(const char *path)
-{
-#ifndef GIT_WIN32
-       GIT_UNUSED(path);
-       return GIT_OK;
-#else
-       git_win32_path buf;
-       PSID owner_sid;
-       PSECURITY_DESCRIPTOR descriptor = NULL;
-       HANDLE token;
-       TOKEN_USER *info = NULL;
-       DWORD err, len;
-       int ret;
-
-       if (git_win32_path_from_utf8(buf, path) < 0)
-               return -1;
-
-       err = GetNamedSecurityInfoW(buf, SE_FILE_OBJECT,
-                                   OWNER_SECURITY_INFORMATION |
-                                           DACL_SECURITY_INFORMATION,
-                                   &owner_sid, NULL, NULL, NULL, &descriptor);
-
-       if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
-               ret = GIT_ENOTFOUND;
-               goto cleanup;
-       }
-
-       if (err != ERROR_SUCCESS) {
-               git_error_set(GIT_ERROR_OS, "failed to get security information");
-               ret = GIT_ERROR;
-               goto cleanup;
-       }
-
-       if (!IsValidSid(owner_sid)) {
-               git_error_set(GIT_ERROR_INVALID, "programdata configuration file owner is unknown");
-               ret = GIT_ERROR;
-               goto cleanup;
-       }
-
-       if (IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
-           IsWellKnownSid(owner_sid, WinLocalSystemSid)) {
-               ret = GIT_OK;
-               goto cleanup;
-       }
-
-       /* Obtain current user's SID */
-       if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) &&
-           !GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
-               info = git__malloc(len);
-               GIT_ERROR_CHECK_ALLOC(info);
-               if (!GetTokenInformation(token, TokenUser, info, len, &len)) {
-                       git__free(info);
-                       info = NULL;
-               }
-       }
-
-       /*
-        * If the file is owned by the same account that is running the current
-        * process, it's okay to read from that file.
-        */
-       if (info && EqualSid(owner_sid, info->User.Sid))
-               ret = GIT_OK;
-       else {
-               git_error_set(GIT_ERROR_INVALID, "programdata configuration file owner is not valid");
-               ret = GIT_ERROR;
-       }
-       git__free(info);
-
-cleanup:
-       if (descriptor)
-               LocalFree(descriptor);
-
-       return ret;
-#endif
-}
index de6ec8ff2483ab8f567934a88f3b83a6f918848f..c4a2c425021604ddafae08f778b945af2396c371 100644 (file)
 
 #include "common.h"
 
-#include "posix.h"
-#include "buffer.h"
-#include "vector.h"
+#include "fs_path.h"
+#include <git2/sys/path.h>
 
-#include "git2/sys/path.h"
+#define GIT_PATH_REJECT_DOT_GIT            (GIT_FS_PATH_REJECT_MAX << 1)
+#define GIT_PATH_REJECT_DOT_GIT_LITERAL    (GIT_FS_PATH_REJECT_MAX << 2)
+#define GIT_PATH_REJECT_DOT_GIT_HFS        (GIT_FS_PATH_REJECT_MAX << 3)
+#define GIT_PATH_REJECT_DOT_GIT_NTFS       (GIT_FS_PATH_REJECT_MAX << 4)
 
-/**
- * Path manipulation utils
- *
- * These are path utilities that munge paths without actually
- * looking at the real filesystem.
- */
-
-/*
- * The dirname() function shall take a pointer to a character string
- * that contains a pathname, and return a pointer to a string that is a
- * pathname of the parent directory of that file. Trailing '/' characters
- * in the path are not counted as part of the path.
- *
- * If path does not contain a '/', then dirname() shall return a pointer to
- * the string ".". If path is a null pointer or points to an empty string,
- * dirname() shall return a pointer to the string "." .
- *
- * The `git_path_dirname` implementation is thread safe. The returned
- * string must be manually free'd.
- *
- * The `git_path_dirname_r` implementation writes the dirname to a `git_buf`
- * if the buffer pointer is not NULL.
- * It returns an error code < 0 if there is an allocation error, otherwise
- * the length of the dirname (which will be > 0).
- */
-extern char *git_path_dirname(const char *path);
-extern int git_path_dirname_r(git_buf *buffer, const char *path);
-
-/*
- * This function returns the basename of the file, which is the last
- * part of its full name given by fname, with the drive letter and
- * leading directories stripped off. For example, the basename of
- * c:/foo/bar/file.ext is file.ext, and the basename of a:foo is foo.
- *
- * Trailing slashes and backslashes are significant: the basename of
- * c:/foo/bar/ is an empty string after the rightmost slash.
- *
- * The `git_path_basename` implementation is thread safe. The returned
- * string must be manually free'd.
- *
- * The `git_path_basename_r` implementation writes the basename to a `git_buf`.
- * It returns an error code < 0 if there is an allocation error, otherwise
- * the length of the basename (which will be >= 0).
- */
-extern char *git_path_basename(const char *path);
-extern int git_path_basename_r(git_buf *buffer, const char *path);
-
-/* Return the offset of the start of the basename.  Unlike the other
- * basename functions, this returns 0 if the path is empty.
- */
-extern size_t git_path_basename_offset(git_buf *buffer);
-
-/**
- * Find offset to root of path if path has one.
- *
- * This will return a number >= 0 which is the offset to the start of the
- * path, if the path is rooted (i.e. "/rooted/path" returns 0 and
- * "c:/windows/rooted/path" returns 2).  If the path is not rooted, this
- * returns -1.
- */
-extern int git_path_root(const char *path);
-
-/**
- * Ensure path has a trailing '/'.
- */
-extern int git_path_to_dir(git_buf *path);
-
-/**
- * Ensure string has a trailing '/' if there is space for it.
- */
-extern void git_path_string_to_dir(char *path, size_t size);
-
-/**
- * Taken from git.git; returns nonzero if the given path is "." or "..".
- */
-GIT_INLINE(int) git_path_is_dot_or_dotdot(const char *name)
-{
-       return (name[0] == '.' &&
-                         (name[1] == '\0' ||
-                               (name[1] == '.' && name[2] == '\0')));
-}
-
-#ifdef GIT_WIN32
-GIT_INLINE(int) git_path_is_dot_or_dotdotW(const wchar_t *name)
-{
-       return (name[0] == L'.' &&
-                         (name[1] == L'\0' ||
-                               (name[1] == L'.' && name[2] == L'\0')));
-}
-
-#define git_path_is_absolute(p) \
-       (git__isalpha((p)[0]) && (p)[1] == ':' && ((p)[2] == '\\' || (p)[2] == '/'))
-
-#define git_path_is_dirsep(p) \
-       ((p) == '/' || (p) == '\\')
-
-/**
- * Convert backslashes in path to forward slashes.
- */
-GIT_INLINE(void) git_path_mkposix(char *path)
-{
-       while (*path) {
-               if (*path == '\\')
-                       *path = '/';
-
-               path++;
-       }
-}
-#else
-#      define git_path_mkposix(p) /* blank */
-
-#define git_path_is_absolute(p) \
-       ((p)[0] == '/')
-
-#define git_path_is_dirsep(p) \
-       ((p) == '/')
-
-#endif
-
-/**
- * Check if string is a relative path (i.e. starts with "./" or "../")
- */
-GIT_INLINE(int) git_path_is_relative(const char *p)
-{
-       return (p[0] == '.' && (p[1] == '/' || (p[1] == '.' && p[2] == '/')));
-}
-
-/**
- * Check if string is at end of path segment (i.e. looking at '/' or '\0')
- */
-GIT_INLINE(int) git_path_at_end_of_segment(const char *p)
-{
-       return !*p || *p == '/';
-}
-
-extern int git__percent_decode(git_buf *decoded_out, const char *input);
-
-/**
- * Extract path from file:// URL.
- */
-extern int git_path_fromurl(git_buf *local_path_out, const char *file_url);
-
-
-/**
- * Path filesystem utils
- *
- * These are path utilities that actually access the filesystem.
- */
-
-/**
- * Check if a file exists and can be accessed.
- * @return true or false
- */
-extern bool git_path_exists(const char *path);
-
-/**
- * Check if the given path points to a directory.
- * @return true or false
- */
-extern bool git_path_isdir(const char *path);
-
-/**
- * Check if the given path points to a regular file.
- * @return true or false
- */
-extern bool git_path_isfile(const char *path);
-
-/**
- * Check if the given path points to a symbolic link.
- * @return true or false
- */
-extern bool git_path_islink(const char *path);
-
-/**
- * Check if the given path is a directory, and is empty.
- */
-extern bool git_path_is_empty_dir(const char *path);
-
-/**
- * Stat a file and/or link and set error if needed.
- */
-extern int git_path_lstat(const char *path, struct stat *st);
-
-/**
- * Check if the parent directory contains the item.
- *
- * @param dir Directory to check.
- * @param item Item that might be in the directory.
- * @return 0 if item exists in directory, <0 otherwise.
- */
-extern bool git_path_contains(git_buf *dir, const char *item);
-
-/**
- * Check if the given path contains the given subdirectory.
- *
- * @param parent Directory path that might contain subdir
- * @param subdir Subdirectory name to look for in parent
- * @return true if subdirectory exists, false otherwise.
- */
-extern bool git_path_contains_dir(git_buf *parent, const char *subdir);
-
-/**
- * Determine the common directory length between two paths, including
- * the final path separator.  For example, given paths 'a/b/c/1.txt
- * and 'a/b/c/d/2.txt', the common directory is 'a/b/c/', and this
- * will return the length of the string 'a/b/c/', which is 6.
- *
- * @param one The first path
- * @param two The second path
- * @return The length of the common directory
- */
-extern size_t git_path_common_dirlen(const char *one, const char *two);
-
-/**
- * Make the path relative to the given parent path.
- *
- * @param path The path to make relative
- * @param parent The parent path to make path relative to
- * @return 0 if path was made relative, GIT_ENOTFOUND
- *         if there was not common root between the paths,
- *         or <0.
- */
-extern int git_path_make_relative(git_buf *path, const char *parent);
-
-/**
- * Check if the given path contains the given file.
- *
- * @param dir Directory path that might contain file
- * @param file File name to look for in parent
- * @return true if file exists, false otherwise.
- */
-extern bool git_path_contains_file(git_buf *dir, const char *file);
-
-/**
- * Prepend base to unrooted path or just copy path over.
- *
- * This will optionally return the index into the path where the "root"
- * is, either the end of the base directory prefix or the path root.
- */
-extern int git_path_join_unrooted(
-       git_buf *path_out, const char *path, const char *base, ssize_t *root_at);
-
-/**
- * Removes multiple occurrences of '/' in a row, squashing them into a
- * single '/'.
- */
-extern void git_path_squash_slashes(git_buf *path);
-
-/**
- * Clean up path, prepending base if it is not already rooted.
- */
-extern int git_path_prettify(git_buf *path_out, const char *path, const char *base);
-
-/**
- * Clean up path, prepending base if it is not already rooted and
- * appending a slash.
- */
-extern int git_path_prettify_dir(git_buf *path_out, const char *path, const char *base);
-
-/**
- * Get a directory from a path.
- *
- * If path is a directory, this acts like `git_path_prettify_dir`
- * (cleaning up path and appending a '/').  If path is a normal file,
- * this prettifies it, then removed the filename a la dirname and
- * appends the trailing '/'.  If the path does not exist, it is
- * treated like a regular filename.
- */
-extern int git_path_find_dir(git_buf *dir);
-
-/**
- * Resolve relative references within a path.
- *
- * This eliminates "./" and "../" relative references inside a path,
- * as well as condensing multiple slashes into single ones.  It will
- * not touch the path before the "ceiling" length.
- *
- * Additionally, this will recognize an "c:/" drive prefix or a "xyz://" URL
- * prefix and not touch that part of the path.
- */
-extern int git_path_resolve_relative(git_buf *path, size_t ceiling);
-
-/**
- * Apply a relative path to base path.
- *
- * Note that the base path could be a filename or a URL and this
- * should still work.  The relative path is walked segment by segment
- * with three rules: series of slashes will be condensed to a single
- * slash, "." will be eaten with no change, and ".." will remove a
- * segment from the base path.
- */
-extern int git_path_apply_relative(git_buf *target, const char *relpath);
-
-enum {
-       GIT_PATH_DIR_IGNORE_CASE = (1u << 0),
-       GIT_PATH_DIR_PRECOMPOSE_UNICODE = (1u << 1),
-       GIT_PATH_DIR_INCLUDE_DOT_AND_DOTDOT = (1u << 2),
-};
-
-/**
- * Walk each directory entry, except '.' and '..', calling fn(state).
- *
- * @param pathbuf Buffer the function reads the initial directory
- *             path from, and updates with each successive entry's name.
- * @param flags Combination of GIT_PATH_DIR flags.
- * @param callback Callback for each entry. Passed the `payload` and each
- *             successive path inside the directory as a full path.  This may
- *             safely append text to the pathbuf if needed.  Return non-zero to
- *             cancel iteration (and return value will be propagated back).
- * @param payload Passed to callback as first argument.
- * @return 0 on success or error code from OS error or from callback
- */
-extern int git_path_direach(
-       git_buf *pathbuf,
-       uint32_t flags,
-       int (*callback)(void *payload, git_buf *path),
-       void *payload);
-
-/**
- * Sort function to order two paths
- */
-extern int git_path_cmp(
-       const char *name1, size_t len1, int isdir1,
-       const char *name2, size_t len2, int isdir2,
-       int (*compare)(const char *, const char *, size_t));
-
-/**
- * Invoke callback up path directory by directory until the ceiling is
- * reached (inclusive of a final call at the root_path).
- *
- * Returning anything other than 0 from the callback function
- * will stop the iteration and propagate the error to the caller.
- *
- * @param pathbuf Buffer the function reads the directory from and
- *             and updates with each successive name.
- * @param ceiling Prefix of path at which to stop walking up.  If NULL,
- *             this will walk all the way up to the root.  If not a prefix of
- *             pathbuf, the callback will be invoked a single time on the
- *             original input path.
- * @param callback Function to invoke on each path.  Passed the `payload`
- *             and the buffer containing the current path.  The path should not
- *             be modified in any way. Return non-zero to stop iteration.
- * @param payload Passed to fn as the first ath.
- */
-extern int git_path_walk_up(
-       git_buf *pathbuf,
-       const char *ceiling,
-       int (*callback)(void *payload, const char *path),
-       void *payload);
-
-
-enum { GIT_PATH_NOTEQUAL = 0, GIT_PATH_EQUAL = 1, GIT_PATH_PREFIX = 2 };
-
-/*
- * Determines if a path is equal to or potentially a child of another.
- * @param parent The possible parent
- * @param child The possible child
- */
-GIT_INLINE(int) git_path_equal_or_prefixed(
-       const char *parent,
-       const char *child,
-       ssize_t *prefixlen)
-{
-       const char *p = parent, *c = child;
-       int lastslash = 0;
-
-       while (*p && *c) {
-               lastslash = (*p == '/');
-
-               if (*p++ != *c++)
-                       return GIT_PATH_NOTEQUAL;
-       }
-
-       if (*p != '\0')
-               return GIT_PATH_NOTEQUAL;
-
-       if (*c == '\0') {
-               if (prefixlen)
-                       *prefixlen = p - parent;
-
-               return GIT_PATH_EQUAL;
-       }
-
-       if (*c == '/' || lastslash) {
-               if (prefixlen)
-                       *prefixlen = (p - parent) - lastslash;
-
-               return GIT_PATH_PREFIX;
-       }
-
-       return GIT_PATH_NOTEQUAL;
-}
-
-/* translate errno to libgit2 error code and set error message */
-extern int git_path_set_error(
-       int errno_value, const char *path, const char *action);
-
-/* check if non-ascii characters are present in filename */
-extern bool git_path_has_non_ascii(const char *path, size_t pathlen);
-
-#define GIT_PATH_REPO_ENCODING "UTF-8"
-
-#ifdef __APPLE__
-#define GIT_PATH_NATIVE_ENCODING "UTF-8-MAC"
-#else
-#define GIT_PATH_NATIVE_ENCODING "UTF-8"
-#endif
-
-#ifdef GIT_USE_ICONV
-
-#include <iconv.h>
-
-typedef struct {
-       iconv_t map;
-       git_buf buf;
-} git_path_iconv_t;
-
-#define GIT_PATH_ICONV_INIT { (iconv_t)-1, GIT_BUF_INIT }
-
-/* Init iconv data for converting decomposed UTF-8 to precomposed */
-extern int git_path_iconv_init_precompose(git_path_iconv_t *ic);
-
-/* Clear allocated iconv data */
-extern void git_path_iconv_clear(git_path_iconv_t *ic);
-
-/*
- * Rewrite `in` buffer using iconv map if necessary, replacing `in`
- * pointer internal iconv buffer if rewrite happened.  The `in` pointer
- * will be left unchanged if no rewrite was needed.
- */
-extern int git_path_iconv(git_path_iconv_t *ic, const char **in, size_t *inlen);
-
-#endif /* GIT_USE_ICONV */
-
-extern bool git_path_does_fs_decompose_unicode(const char *root);
-
-
-typedef struct git_path_diriter git_path_diriter;
-
-#if defined(GIT_WIN32) && !defined(__MINGW32__)
-
-struct git_path_diriter
-{
-       git_win32_path path;
-       size_t parent_len;
-
-       git_buf path_utf8;
-       size_t parent_utf8_len;
-
-       HANDLE handle;
-
-       unsigned int flags;
-
-       WIN32_FIND_DATAW current;
-       unsigned int needs_next;
-};
-
-#define GIT_PATH_DIRITER_INIT { {0}, 0, GIT_BUF_INIT, 0, INVALID_HANDLE_VALUE }
-
-#else
-
-struct git_path_diriter
-{
-       git_buf path;
-       size_t parent_len;
-
-       unsigned int flags;
-
-       DIR *dir;
-
-#ifdef GIT_USE_ICONV
-       git_path_iconv_t ic;
-#endif
-};
-
-#define GIT_PATH_DIRITER_INIT { GIT_BUF_INIT }
-
-#endif
-
-/**
- * Initialize a directory iterator.
- *
- * @param diriter Pointer to a diriter structure that will be setup.
- * @param path The path that will be iterated over
- * @param flags Directory reader flags
- * @return 0 or an error code
- */
-extern int git_path_diriter_init(
-       git_path_diriter *diriter,
-       const char *path,
-       unsigned int flags);
-
-/**
- * Advance the directory iterator.  Will return GIT_ITEROVER when
- * the iteration has completed successfully.
- *
- * @param diriter The directory iterator
- * @return 0, GIT_ITEROVER, or an error code
- */
-extern int git_path_diriter_next(git_path_diriter *diriter);
-
-/**
- * Returns the file name of the current item in the iterator.
- *
- * @param out Pointer to store the path in
- * @param out_len Pointer to store the length of the path in
- * @param diriter The directory iterator
- * @return 0 or an error code
- */
-extern int git_path_diriter_filename(
-       const char **out,
-       size_t *out_len,
-       git_path_diriter *diriter);
-
-/**
- * Returns the full path of the current item in the iterator; that
- * is the current filename plus the path of the directory that the
- * iterator was constructed with.
- *
- * @param out Pointer to store the path in
- * @param out_len Pointer to store the length of the path in
- * @param diriter The directory iterator
- * @return 0 or an error code
- */
-extern int git_path_diriter_fullpath(
-       const char **out,
-       size_t *out_len,
-       git_path_diriter *diriter);
-
-/**
- * Performs an `lstat` on the current item in the iterator.
- *
- * @param out Pointer to store the stat data in
- * @param diriter The directory iterator
- * @return 0 or an error code
- */
-extern int git_path_diriter_stat(struct stat *out, git_path_diriter *diriter);
-
-/**
- * Closes the directory iterator.
- *
- * @param diriter The directory iterator
- */
-extern void git_path_diriter_free(git_path_diriter *diriter);
-
-/**
- * Load all directory entries (except '.' and '..') into a vector.
- *
- * For cases where `git_path_direach()` is not appropriate, this
- * allows you to load the filenames in a directory into a vector
- * of strings. That vector can then be sorted, iterated, or whatever.
- * Remember to free alloc of the allocated strings when you are done.
- *
- * @param contents Vector to fill with directory entry names.
- * @param path The directory to read from.
- * @param prefix_len When inserting entries, the trailing part of path
- *             will be prefixed after this length.  I.e. given path "/a/b" and
- *             prefix_len 3, the entries will look like "b/e1", "b/e2", etc.
- * @param flags Combination of GIT_PATH_DIR flags.
- */
-extern int git_path_dirload(
-       git_vector *contents,
-       const char *path,
-       size_t prefix_len,
-       uint32_t flags);
-
-
-/* Used for paths to repositories on the filesystem */
-extern bool git_path_is_local_file_url(const char *file_url);
-extern int git_path_from_url_or_path(git_buf *local_path_out, const char *url_or_path);
-
-/* Flags to determine path validity in `git_path_isvalid` */
-#define GIT_PATH_REJECT_TRAVERSAL          (1 << 0)
-#define GIT_PATH_REJECT_DOT_GIT            (1 << 1)
-#define GIT_PATH_REJECT_SLASH              (1 << 2)
-#define GIT_PATH_REJECT_BACKSLASH          (1 << 3)
-#define GIT_PATH_REJECT_TRAILING_DOT       (1 << 4)
-#define GIT_PATH_REJECT_TRAILING_SPACE     (1 << 5)
-#define GIT_PATH_REJECT_TRAILING_COLON     (1 << 6)
-#define GIT_PATH_REJECT_DOS_PATHS          (1 << 7)
-#define GIT_PATH_REJECT_NT_CHARS           (1 << 8)
-#define GIT_PATH_REJECT_DOT_GIT_LITERAL    (1 << 9)
-#define GIT_PATH_REJECT_DOT_GIT_HFS        (1 << 10)
-#define GIT_PATH_REJECT_DOT_GIT_NTFS       (1 << 11)
-
-/* Default path safety for writing files to disk: since we use the
- * Win32 "File Namespace" APIs ("\\?\") we need to protect from
- * paths that the normal Win32 APIs would not write.
- */
-#ifdef GIT_WIN32
-# define GIT_PATH_REJECT_FILESYSTEM_DEFAULTS \
-       GIT_PATH_REJECT_TRAVERSAL | \
-       GIT_PATH_REJECT_BACKSLASH | \
-       GIT_PATH_REJECT_TRAILING_DOT | \
-       GIT_PATH_REJECT_TRAILING_SPACE | \
-       GIT_PATH_REJECT_TRAILING_COLON | \
-       GIT_PATH_REJECT_DOS_PATHS | \
-       GIT_PATH_REJECT_NT_CHARS
-#else
-# define GIT_PATH_REJECT_FILESYSTEM_DEFAULTS \
-       GIT_PATH_REJECT_TRAVERSAL
-#endif
-
- /* Paths that should never be written into the working directory. */
+/* Paths that should never be written into the working directory. */
 #define GIT_PATH_REJECT_WORKDIR_DEFAULTS \
-       GIT_PATH_REJECT_FILESYSTEM_DEFAULTS | GIT_PATH_REJECT_DOT_GIT
+       GIT_FS_PATH_REJECT_FILESYSTEM_DEFAULTS | GIT_PATH_REJECT_DOT_GIT
 
 /* Paths that should never be written to the index. */
 #define GIT_PATH_REJECT_INDEX_DEFAULTS \
-       GIT_PATH_REJECT_TRAVERSAL | GIT_PATH_REJECT_DOT_GIT
+       GIT_FS_PATH_REJECT_TRAVERSAL | GIT_PATH_REJECT_DOT_GIT
 
-/**
- * Validate a "bare" git path.  This ensures that the given path is legal
- * to place in the index or a tree.  This should be checked by mechanisms
- * like `git_index_add` and `git_treebuilder_insert` when taking user
- * data, and by `git_checkout` before constructing on-disk paths.
- *
- * This will ensure that a git path does not contain any "unsafe" components,
- * a '.' or '..' component, or a component that is ".git" (in any case).
- *
- * (Note: if you take or construct an on-disk path -- a workdir path,
- * a path to a git repository or a reference name that could be a loose
- * ref -- you should _also_ validate that with `git_path_validate_workdir`.)
- *
- * `repo` is optional.  If specified, it will be used to determine the short
- * path name to reject (if `GIT_PATH_REJECT_DOS_SHORTNAME` is specified),
- * in addition to the default of "git~1".
- */
-extern bool git_path_validate(
+extern bool git_path_str_is_valid(
        git_repository *repo,
-       const char *path,
-       uint16_t mode,
+       const git_str *path,
+       uint16_t file_mode,
        unsigned int flags);
 
-/**
- * Validate an on-disk path, taking into account that it will have a
- * suffix appended (eg, `.lock`).
- */
-GIT_INLINE(int) git_path_validate_filesystem_with_suffix(
+GIT_INLINE(bool) git_path_is_valid(
+       git_repository *repo,
        const char *path,
-       size_t path_len,
-       size_t suffix_len)
+       uint16_t file_mode,
+       unsigned int flags)
 {
-#ifdef GIT_WIN32
-       size_t path_chars, total_chars;
+       git_str str = GIT_STR_INIT_CONST(path, SIZE_MAX);
+       return git_path_str_is_valid(repo, &str, file_mode, flags);
+}
 
-       path_chars = git_utf8_char_length(path, path_len);
+GIT_INLINE(int) git_path_validate_str_length(
+       git_repository *repo,
+       const git_str *path)
+{
+       if (!git_path_str_is_valid(repo, path, 0, GIT_FS_PATH_REJECT_LONG_PATHS)) {
+               if (path->size == SIZE_MAX)
+                       git_error_set(GIT_ERROR_FILESYSTEM, "path too long: '%s'", path->ptr);
+               else
+                       git_error_set(GIT_ERROR_FILESYSTEM, "path too long: '%.*s'", (int)path->size, path->ptr);
 
-       if (GIT_ADD_SIZET_OVERFLOW(&total_chars, path_chars, suffix_len) ||
-           total_chars > MAX_PATH) {
-               git_error_set(GIT_ERROR_FILESYSTEM, "path too long: '%s'", path);
                return -1;
        }
+
        return 0;
-#else
-       GIT_UNUSED(path);
-       GIT_UNUSED(path_len);
-       GIT_UNUSED(suffix_len);
-       return 0;
-#endif
 }
 
-/**
- * Validate an path on the filesystem.  This ensures that the given
- * path is valid for the operating system/platform; for example, this
- * will ensure that the given absolute path is smaller than MAX_PATH on
- * Windows.
- *
- * For paths within the working directory, you should use ensure that
- * `core.longpaths` is obeyed.  Use `git_path_validate_workdir`.
- */
-GIT_INLINE(int) git_path_validate_filesystem(
-       const char *path,
-       size_t path_len)
+GIT_INLINE(int) git_path_validate_length(
+       git_repository *repo,
+       const char *path)
 {
-       return git_path_validate_filesystem_with_suffix(path, path_len, 0);
+       git_str str = GIT_STR_INIT_CONST(path, SIZE_MAX);
+       return git_path_validate_str_length(repo, &str);
 }
 
-/**
- * Validate a path relative to the repo's worktree.  This ensures that
- * the given working tree path is valid for the operating system/platform.
- * This will ensure that an absolute path is smaller than MAX_PATH on
- * Windows, while keeping `core.longpaths` configuration settings in mind.
- *
- * This should be checked by mechamisms like `git_checkout` after
- * contructing on-disk paths and before trying to write them.
- *
- * If the repository is null, no repository configuration is applied.
- */
-extern int git_path_validate_workdir(
-       git_repository *repo,
-       const char *path);
-extern int git_path_validate_workdir_with_len(
-       git_repository *repo,
-       const char *path,
-       size_t path_len);
-extern int git_path_validate_workdir_buf(
-       git_repository *repo,
-       git_buf *buf);
-
-/**
- * Convert any backslashes into slashes
- */
-int git_path_normalize_slashes(git_buf *out, const char *path);
-
-bool git_path_supports_symlinks(const char *dir);
-
-/**
- * Validate a system file's ownership
- *
- * Verify that the file in question is owned by an administrator or system
- * account, or at least by the current user.
- *
- * This function returns 0 if successful. If the file is not owned by any of
- * these, or any other if there have been problems determining the file
- * ownership, it returns -1.
- */
-int git_path_validate_system_file_ownership(const char *path);
-
 #endif
index c6ad16571ecaad30d5008d98d152ed8186286fbe..3e44643c6759a89443a65baae10f249482621f31 100644 (file)
 /* what is the common non-wildcard prefix for all items in the pathspec */
 char *git_pathspec_prefix(const git_strarray *pathspec)
 {
-       git_buf prefix = GIT_BUF_INIT;
+       git_str prefix = GIT_STR_INIT;
        const char *scan;
 
        if (!pathspec || !pathspec->count ||
-               git_buf_common_prefix(&prefix, pathspec->strings, pathspec->count) < 0)
+               git_str_common_prefix(&prefix, pathspec->strings, pathspec->count) < 0)
                return NULL;
 
        /* diff prefix will only be leading non-wildcards */
@@ -33,16 +33,16 @@ char *git_pathspec_prefix(const git_strarray *pathspec)
                        (scan == prefix.ptr || (*(scan - 1) != '\\')))
                        break;
        }
-       git_buf_truncate(&prefix, scan - prefix.ptr);
+       git_str_truncate(&prefix, scan - prefix.ptr);
 
        if (prefix.size <= 0) {
-               git_buf_dispose(&prefix);
+               git_str_dispose(&prefix);
                return NULL;
        }
 
-       git_buf_unescape(&prefix);
+       git_str_unescape(&prefix);
 
-       return git_buf_detach(&prefix);
+       return git_str_detach(&prefix);
 }
 
 /* is there anything in the spec that needs to be filtered on */
index c4d1a83d3b626e401a1915ce6b548cf3a89fe216..0256cb92775df538031099fb3df250f7db227469 100644 (file)
@@ -10,7 +10,7 @@
 #include "common.h"
 
 #include "git2/pathspec.h"
-#include "buffer.h"
+#include "str.h"
 #include "vector.h"
 #include "pool.h"
 #include "array.h"
@@ -25,7 +25,7 @@ struct git_pathspec {
 
 enum {
        PATHSPEC_DATATYPE_STRINGS = 0,
-       PATHSPEC_DATATYPE_DIFF = 1,
+       PATHSPEC_DATATYPE_DIFF = 1
 };
 
 typedef git_array_t(char *) git_pathspec_string_array_t;
index c40134824a4a38f43cca6ecb0cc885af5c726770..b1f85dc9412bddb2f7c37393a94b98795656101b 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "posix.h"
 
-#include "path.h"
+#include "fs_path.h"
 #include <stdio.h>
 #include <ctype.h>
 
@@ -144,8 +144,8 @@ int p_getcwd(char *buffer_out, size_t size)
        if (cwd_buffer == NULL)
                return -1;
 
-       git_path_mkposix(buffer_out);
-       git_path_string_to_dir(buffer_out, size); /* append trailing slash */
+       git_fs_path_mkposix(buffer_out);
+       git_fs_path_string_to_dir(buffer_out, size); /* append trailing slash */
 
        return 0;
 }
index d98bc82ca80c1bbc2e22087a1876a54cb72f1b83..e6f60307811e70ef91a96d93f0e9f255d28deab3 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "common.h"
 
+#include <stdlib.h>
 #include <fcntl.h>
 #include <time.h>
 
index c0a6cd49e4788a3239468cb596cd8b13f052dc98..4db74ea0371f9a3aee19fce13a3d42d0732c340d 100644 (file)
@@ -15,7 +15,7 @@ typedef git_vector git_pqueue;
 
 enum {
        /* flag meaning: don't grow heap, keep highest values only */
-       GIT_PQUEUE_FIXED_SIZE = (GIT_VECTOR_FLAG_MAX << 1),
+       GIT_PQUEUE_FIXED_SIZE = (GIT_VECTOR_FLAG_MAX << 1)
 };
 
 /**
index 78a4c5535b6a5677de1bb21d1ace092457922c93..ef91ad6eaaab2dd77d9585fcf2ed6cad21951fa7 100644 (file)
@@ -39,8 +39,11 @@ int git_proxy_options_dup(git_proxy_options *tgt, const git_proxy_options *src)
        return 0;
 }
 
-void git_proxy_options_clear(git_proxy_options *opts)
+void git_proxy_options_dispose(git_proxy_options *opts)
 {
+       if (!opts)
+               return;
+
        git__free((char *) opts->url);
        opts->url = NULL;
 }
index f8b5c4b50f9d0db8c86eadbcd3fb89ca36825693..7c0ab598d9ac2b9e096486bde1d7e1d3e8ae1f6b 100644 (file)
@@ -12,6 +12,6 @@
 #include "git2/proxy.h"
 
 extern int git_proxy_options_dup(git_proxy_options *tgt, const git_proxy_options *src);
-extern void git_proxy_options_clear(git_proxy_options *opts);
+extern void git_proxy_options_dispose(git_proxy_options *opts);
 
 #endif
index b724188f97790fcb895e4c8dd99854600c55db73..da8aebadd14b2537220896c62e21887ae2c05480 100644 (file)
@@ -29,19 +29,26 @@ static int push_status_ref_cmp(const void *a, const void *b)
        return strcmp(push_status_a->ref, push_status_b->ref);
 }
 
-int git_push_new(git_push **out, git_remote *remote)
+int git_push_new(git_push **out, git_remote *remote, const git_push_options *opts)
 {
        git_push *p;
 
        *out = NULL;
 
+       GIT_ERROR_CHECK_VERSION(opts, GIT_PUSH_OPTIONS_VERSION, "git_push_options");
+
        p = git__calloc(1, sizeof(*p));
        GIT_ERROR_CHECK_ALLOC(p);
 
        p->repo = remote->repo;
        p->remote = remote;
        p->report_status = 1;
-       p->pb_parallelism = 1;
+       p->pb_parallelism = opts ? opts->pb_parallelism : 1;
+
+       if (opts) {
+               GIT_ERROR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
+               memcpy(&p->callbacks, &opts->callbacks, sizeof(git_remote_callbacks));
+       }
 
        if (git_vector_init(&p->specs, 0, push_spec_rref_cmp) < 0) {
                git__free(p);
@@ -65,20 +72,6 @@ int git_push_new(git_push **out, git_remote *remote)
        return 0;
 }
 
-int git_push_set_options(git_push *push, const git_push_options *opts)
-{
-       if (!push || !opts)
-               return -1;
-
-       GIT_ERROR_CHECK_VERSION(opts, GIT_PUSH_OPTIONS_VERSION, "git_push_options");
-
-       push->pb_parallelism = opts->pb_parallelism;
-       push->connection.custom_headers = &opts->custom_headers;
-       push->connection.proxy = &opts->proxy_opts;
-
-       return 0;
-}
-
 static void free_refspec(push_spec *spec)
 {
        if (spec == NULL)
@@ -159,7 +152,7 @@ int git_push_add_refspec(git_push *push, const char *refspec)
 
 int git_push_update_tips(git_push *push, const git_remote_callbacks *callbacks)
 {
-       git_buf remote_ref_name = GIT_BUF_INIT;
+       git_str remote_ref_name = GIT_STR_INIT;
        size_t i, j;
        git_refspec *fetch_spec;
        push_spec *push_spec = NULL;
@@ -180,9 +173,9 @@ int git_push_update_tips(git_push *push, const git_remote_callbacks *callbacks)
                        continue;
 
                /* Clear the buffer which can be dirty from previous iteration */
-               git_buf_clear(&remote_ref_name);
+               git_str_clear(&remote_ref_name);
 
-               if ((error = git_refspec_transform(&remote_ref_name, fetch_spec, status->ref)) < 0)
+               if ((error = git_refspec__transform(&remote_ref_name, fetch_spec, status->ref)) < 0)
                        goto on_error;
 
                /* Find matching  push ref spec */
@@ -197,7 +190,7 @@ int git_push_update_tips(git_push *push, const git_remote_callbacks *callbacks)
 
                /* Update the remote ref */
                if (git_oid_is_zero(&push_spec->loid)) {
-                       error = git_reference_lookup(&remote_ref, push->remote->repo, git_buf_cstr(&remote_ref_name));
+                       error = git_reference_lookup(&remote_ref, push->remote->repo, git_str_cstr(&remote_ref_name));
 
                        if (error >= 0) {
                                error = git_reference_delete(remote_ref);
@@ -205,7 +198,7 @@ int git_push_update_tips(git_push *push, const git_remote_callbacks *callbacks)
                        }
                } else {
                        error = git_reference_create(NULL, push->remote->repo,
-                                               git_buf_cstr(&remote_ref_name), &push_spec->loid, 1,
+                                               git_str_cstr(&remote_ref_name), &push_spec->loid, 1,
                                                "update by push");
                }
 
@@ -218,7 +211,7 @@ int git_push_update_tips(git_push *push, const git_remote_callbacks *callbacks)
                }
 
                if (fire_callback && callbacks && callbacks->update_tips) {
-                       error = callbacks->update_tips(git_buf_cstr(&remote_ref_name),
+                       error = callbacks->update_tips(git_str_cstr(&remote_ref_name),
                                                &push_spec->roid, &push_spec->loid, callbacks->payload);
 
                        if (error < 0)
@@ -229,7 +222,7 @@ int git_push_update_tips(git_push *push, const git_remote_callbacks *callbacks)
        error = 0;
 
 on_error:
-       git_buf_dispose(&remote_ref_name);
+       git_str_dispose(&remote_ref_name);
        return error;
 }
 
@@ -291,7 +284,7 @@ static int queue_objects(git_push *push)
                if (git_oid_equal(&spec->loid, &spec->roid))
                        continue; /* up-to-date */
 
-               if (git_odb_read_header(&size, &type, push->repo->_odb, &spec->loid) < 0)
+               if ((error = git_odb_read_header(&size, &type, push->repo->_odb, &spec->loid)) < 0)
                        goto on_error;
 
                if (type == GIT_OBJECT_TAG) {
@@ -301,19 +294,19 @@ static int queue_objects(git_push *push)
                                goto on_error;
 
                        if (git_object_type(target) == GIT_OBJECT_COMMIT) {
-                               if (git_revwalk_push(rw, git_object_id(target)) < 0) {
+                               if ((error = git_revwalk_push(rw, git_object_id(target))) < 0) {
                                        git_object_free(target);
                                        goto on_error;
                                }
                        } else {
-                               if (git_packbuilder_insert(
-                                       push->pb, git_object_id(target), NULL) < 0) {
+                               if ((error = git_packbuilder_insert(
+                                       push->pb, git_object_id(target), NULL)) < 0) {
                                        git_object_free(target);
                                        goto on_error;
                                }
                        }
                        git_object_free(target);
-               } else if (git_revwalk_push(rw, &spec->loid) < 0)
+               } else if ((error = git_revwalk_push(rw, &spec->loid)) < 0)
                        goto on_error;
 
                if (!spec->refspec.force) {
@@ -411,10 +404,11 @@ static int calculate_work(git_push *push)
        return 0;
 }
 
-static int do_push(git_push *push, const git_remote_callbacks *callbacks)
+static int do_push(git_push *push)
 {
        int error = 0;
        git_transport *transport = push->remote->transport;
+       git_remote_callbacks *callbacks = &push->callbacks;
 
        if (!transport->push) {
                git_error_set(GIT_ERROR_NET, "remote transport doesn't support push");
@@ -446,7 +440,7 @@ static int do_push(git_push *push, const git_remote_callbacks *callbacks)
            goto on_error;
 
        if ((error = queue_objects(push)) < 0 ||
-           (error = transport->push(transport, push, callbacks)) < 0)
+           (error = transport->push(transport, push)) < 0)
                goto on_error;
 
 on_error:
@@ -472,16 +466,17 @@ static int filter_refs(git_remote *remote)
        return 0;
 }
 
-int git_push_finish(git_push *push, const git_remote_callbacks *callbacks)
+int git_push_finish(git_push *push)
 {
        int error;
 
-       if (!git_remote_connected(push->remote) &&
-           (error = git_remote__connect(push->remote, GIT_DIRECTION_PUSH, callbacks, &push->connection)) < 0)
-               return error;
+       if (!git_remote_connected(push->remote)) {
+               git_error_set(GIT_ERROR_NET, "remote is disconnected");
+               return -1;
+       }
 
        if ((error = filter_refs(push->remote)) < 0 ||
-           (error = do_push(push, callbacks)) < 0)
+           (error = do_push(push)) < 0)
                return error;
 
        if (!push->unpack_ok) {
index 86756394055788cb0349a2509cf3661358f9e687..fc72e845eee9b35774a4cdd313fc184acfea5547 100644 (file)
@@ -41,7 +41,7 @@ struct git_push {
 
        /* options */
        unsigned pb_parallelism;
-       git_remote_connection_opts connection;
+       git_remote_callbacks callbacks;
 };
 
 /**
@@ -56,22 +56,11 @@ void git_push_status_free(push_status *status);
  *
  * @param out New push object
  * @param remote Remote instance
+ * @param opts Push options or NULL
  *
  * @return 0 or an error code
  */
-int git_push_new(git_push **out, git_remote *remote);
-
-/**
- * Set options on a push object
- *
- * @param push The push object
- * @param opts The options to set on the push object
- *
- * @return 0 or an error code
- */
-int git_push_set_options(
-       git_push *push,
-       const git_push_options *opts);
+int git_push_new(git_push **out, git_remote *remote, const git_push_options *opts);
 
 /**
  * Add a refspec to be pushed
@@ -104,11 +93,10 @@ int git_push_update_tips(git_push *push, const git_remote_callbacks *callbacks);
  * order to find out which updates were accepted or rejected.
  *
  * @param push The push object
- * @param callbacks the callbacks to use for this connection
  *
  * @return 0 or an error code
  */
-int git_push_finish(git_push *push, const git_remote_callbacks *callbacks);
+int git_push_finish(git_push *push);
 
 /**
  * Invoke callback `cb' on each status entry
diff --git a/src/rand.c b/src/rand.c
new file mode 100644 (file)
index 0000000..0a20813
--- /dev/null
@@ -0,0 +1,226 @@
+/*  Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
+
+To the extent possible under law, the author has dedicated all copyright
+and related and neighboring rights to this software to the public domain
+worldwide. This software is distributed without any warranty.
+
+See <http://creativecommons.org/publicdomain/zero/1.0/>. */
+
+#include "common.h"
+#include "rand.h"
+#include "runtime.h"
+
+#if defined(GIT_RAND_GETENTROPY)
+# include <sys/random.h>
+#endif
+
+static uint64_t state[4];
+static git_mutex state_lock;
+
+typedef union {
+       double f;
+       uint64_t d;
+} bits;
+
+#if defined(GIT_WIN32)
+GIT_INLINE(int) getseed(uint64_t *seed)
+{
+       HCRYPTPROV provider;
+       SYSTEMTIME systemtime;
+       FILETIME filetime, idletime, kerneltime, usertime;
+       bits convert;
+
+       if (CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL,
+                               CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) {
+               BOOL success = CryptGenRandom(provider, sizeof(uint64_t), (void *)seed);
+               CryptReleaseContext(provider, 0);
+
+               if (success)
+                       return 0;
+       }
+
+       GetSystemTime(&systemtime);
+       if (!SystemTimeToFileTime(&systemtime, &filetime)) {
+               git_error_set(GIT_ERROR_OS, "could not get time for random seed");
+               return -1;
+       }
+
+       /* Fall-through: generate a seed from the time and system state */
+       *seed = 0;
+       *seed |= ((uint64_t)filetime.dwLowDateTime << 32);
+       *seed |= ((uint64_t)filetime.dwHighDateTime);
+
+       GetSystemTimes(&idletime, &kerneltime, &usertime);
+
+       *seed ^= ((uint64_t)idletime.dwLowDateTime << 32);
+       *seed ^= ((uint64_t)kerneltime.dwLowDateTime);
+       *seed ^= ((uint64_t)usertime.dwLowDateTime << 32);
+
+       *seed ^= ((uint64_t)idletime.dwHighDateTime);
+       *seed ^= ((uint64_t)kerneltime.dwHighDateTime << 12);
+       *seed ^= ((uint64_t)usertime.dwHighDateTime << 24);
+
+       *seed ^= ((uint64_t)GetCurrentProcessId() << 32);
+       *seed ^= ((uint64_t)GetCurrentThreadId() << 48);
+
+       convert.f = git__timer(); *seed ^= (convert.d);
+
+       /* Mix in the addresses of some functions and variables */
+       *seed ^= (((uint64_t)((uintptr_t)seed) << 32));
+       *seed ^= (((uint64_t)((uintptr_t)&errno)));
+
+       return 0;
+}
+
+#else
+
+GIT_INLINE(int) getseed(uint64_t *seed)
+{
+       struct timeval tv;
+       double loadavg[3];
+       bits convert;
+       int fd;
+
+# if defined(GIT_RAND_GETENTROPY)
+       GIT_UNUSED((fd = 0));
+
+       if (getentropy(seed, sizeof(uint64_t)) == 0)
+               return 0;
+# else
+       /*
+        * Try to read from /dev/urandom; most modern systems will have
+        * this, but we may be chrooted, etc, so it's not a fatal error
+        */
+       if ((fd = open("/dev/urandom", O_RDONLY)) >= 0) {
+               ssize_t ret = read(fd, seed, sizeof(uint64_t));
+               close(fd);
+
+               if (ret == (ssize_t)sizeof(uint64_t))
+                       return 0;
+       }
+# endif
+
+       /* Fall-through: generate a seed from the time and system state */
+       if (gettimeofday(&tv, NULL) < 0) {
+               git_error_set(GIT_ERROR_OS, "could get time for random seed");
+               return -1;
+       }
+
+       getloadavg(loadavg, 3);
+
+       *seed = 0;
+       *seed |= ((uint64_t)tv.tv_usec << 40);
+       *seed |= ((uint64_t)tv.tv_sec);
+
+       *seed ^= ((uint64_t)getpid() << 48);
+       *seed ^= ((uint64_t)getppid() << 32);
+       *seed ^= ((uint64_t)getpgid(0) << 28);
+       *seed ^= ((uint64_t)getsid(0) << 16);
+       *seed ^= ((uint64_t)getuid() << 8);
+       *seed ^= ((uint64_t)getgid());
+
+       convert.f = loadavg[0]; *seed ^= (convert.d >> 36);
+       convert.f = loadavg[1]; *seed ^= (convert.d);
+       convert.f = loadavg[2]; *seed ^= (convert.d >> 16);
+
+       convert.f = git__timer(); *seed ^= (convert.d);
+
+       /* Mix in the addresses of some variables */
+       *seed ^= ((uint64_t)((size_t)((void *)seed)) << 32);
+       *seed ^= ((uint64_t)((size_t)((void *)&errno)));
+
+       return 0;
+}
+#endif
+
+static void git_rand_global_shutdown(void)
+{
+       git_mutex_free(&state_lock);
+}
+
+int git_rand_global_init(void)
+{
+       uint64_t seed = 0;
+
+       if (git_mutex_init(&state_lock) < 0 || getseed(&seed) < 0)
+               return -1;
+
+       if (!seed) {
+               git_error_set(GIT_ERROR_INTERNAL, "failed to generate random seed");
+               return -1;
+       }
+
+       git_rand_seed(seed);
+       git_runtime_shutdown_register(git_rand_global_shutdown);
+
+       return 0;
+}
+
+/*
+ * This is splitmix64. xoroshiro256** uses 256 bit seed; this is used
+ * to generate 256 bits of seed from the given 64, per the author's
+ * recommendation.
+ */
+GIT_INLINE(uint64_t) splitmix64(uint64_t *in)
+{
+       uint64_t z;
+
+       *in += 0x9e3779b97f4a7c15;
+
+       z = *in;
+       z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
+       z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
+       return z ^ (z >> 31);
+}
+
+void git_rand_seed(uint64_t seed)
+{
+       uint64_t mixer;
+
+       mixer = seed;
+
+       git_mutex_lock(&state_lock);
+       state[0] = splitmix64(&mixer);
+       state[1] = splitmix64(&mixer);
+       state[2] = splitmix64(&mixer);
+       state[3] = splitmix64(&mixer);
+       git_mutex_unlock(&state_lock);
+}
+
+/* This is xoshiro256** 1.0, one of our all-purpose, rock-solid
+   generators. It has excellent (sub-ns) speed, a state (256 bits) that is
+   large enough for any parallel application, and it passes all tests we
+   are aware of.
+
+   For generating just floating-point numbers, xoshiro256+ is even faster.
+
+   The state must be seeded so that it is not everywhere zero. If you have
+   a 64-bit seed, we suggest to seed a splitmix64 generator and use its
+   output to fill s. */
+
+GIT_INLINE(uint64_t) rotl(const uint64_t x, int k) {
+       return (x << k) | (x >> (64 - k));
+}
+
+uint64_t git_rand_next(void) {
+       uint64_t t, result;
+
+       git_mutex_lock(&state_lock);
+
+       result = rotl(state[1] * 5, 7) * 9;
+
+       t = state[1] << 17;
+
+       state[2] ^= state[0];
+       state[3] ^= state[1];
+       state[1] ^= state[2];
+       state[0] ^= state[3];
+
+       state[2] ^= t;
+
+       state[3] = rotl(state[3], 45);
+
+       git_mutex_unlock(&state_lock);
+
+       return result;
+}
diff --git a/src/rand.h b/src/rand.h
new file mode 100644 (file)
index 0000000..2e60561
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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_rand_h__
+#define INCLUDE_rand_h__
+
+#include "common.h"
+
+/**
+ * Initialize the random number generation subsystem.  This will
+ * seed the random number generator with the system's entropy pool,
+ * if available, and will fall back to the current time and
+ * system information if not.
+ */
+int git_rand_global_init(void);
+
+/**
+ * Seed the pseudo-random number generator.  This is not needed to be
+ * called; the PRNG is seeded by `git_rand_global_init`, but it may
+ * be useful for testing.  When the same seed is specified, the same
+ * sequence of random numbers from `git_rand_next` is emitted.
+ *
+ * @param seed the seed to use
+ */
+void git_rand_seed(uint64_t seed);
+
+/**
+ * Get the next pseudo-random number in the sequence.
+ *
+ * @return a 64-bit pseudo-random number
+ */
+uint64_t git_rand_next(void);
+
+#endif
index 48928940dbc7f1ff52558513d812cb170162b6f9..ba9775240d0b6bd67f021247f2c8fc2dfc061820 100644 (file)
@@ -23,7 +23,7 @@ typedef struct {
 } tree_reader;
 
 static int tree_reader_read(
-       git_buf *out,
+       git_str *out,
        git_oid *out_id,
        git_filemode_t *out_filemode,
        git_reader *_reader,
@@ -42,7 +42,7 @@ static int tree_reader_read(
        blobsize = git_blob_rawsize(blob);
        GIT_ERROR_CHECK_BLOBSIZE(blobsize);
 
-       if ((error = git_buf_set(out, git_blob_rawcontent(blob), (size_t)blobsize)) < 0)
+       if ((error = git_str_set(out, git_blob_rawcontent(blob), (size_t)blobsize)) < 0)
                goto done;
 
        if (out_id)
@@ -83,14 +83,14 @@ typedef struct {
 } workdir_reader;
 
 static int workdir_reader_read(
-       git_buf *out,
+       git_str *out,
        git_oid *out_id,
        git_filemode_t *out_filemode,
        git_reader *_reader,
        const char *filename)
 {
        workdir_reader *reader = (workdir_reader *)_reader;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        struct stat st;
        git_filemode_t filemode;
        git_filter_list *filters = NULL;
@@ -120,7 +120,7 @@ static int workdir_reader_read(
                GIT_FILTER_TO_ODB, GIT_FILTER_DEFAULT)) < 0)
                goto done;
 
-       if ((error = git_filter_list_apply_to_file(out,
+       if ((error = git_filter_list__apply_to_file(out,
            filters, reader->repo, path.ptr)) < 0)
                goto done;
 
@@ -146,7 +146,7 @@ static int workdir_reader_read(
 
 done:
        git_filter_list_free(filters);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        return error;
 }
 
@@ -186,7 +186,7 @@ typedef struct {
 } index_reader;
 
 static int index_reader_read(
-       git_buf *out,
+       git_str *out,
        git_oid *out_id,
        git_filemode_t *out_filemode,
        git_reader *_reader,
@@ -247,7 +247,7 @@ int git_reader_for_index(
 /* generic */
 
 int git_reader_read(
-       git_buf *out,
+       git_str *out,
        git_oid *out_id,
        git_filemode_t *out_filemode,
        git_reader *reader,
index 18a6a1103d7be2a86f5bd4f4f634be74ef567656..b58dc93f673b546d45d37deeb229cb91612c26d2 100644 (file)
@@ -25,7 +25,7 @@ typedef struct git_reader git_reader;
  * reader after disposing the underlying object that it reads.
  */
 struct git_reader {
-       int (*read)(git_buf *out, git_oid *out_oid, git_filemode_t *mode, git_reader *reader, const char *filename);
+       int (*read)(git_str *out, git_oid *out_oid, git_filemode_t *mode, git_reader *reader, const char *filename);
 };
 
 /**
@@ -91,7 +91,7 @@ extern int git_reader_for_workdir(
  * @param filename The filename to read from the reader
  */
 extern int git_reader_read(
-       git_buf *out,
+       git_str *out,
        git_oid *out_id,
        git_filemode_t *out_filemode,
        git_reader *reader,
index 4f10c296bdd294e6ee802965cae0a1cbb74bdf85..6f01d3990575bcf503947818caeac598117f816f 100644 (file)
@@ -7,10 +7,11 @@
 
 #include "common.h"
 
-#include "buffer.h"
+#include "str.h"
 #include "repository.h"
 #include "posix.h"
 #include "filebuf.h"
+#include "commit.h"
 #include "merge.h"
 #include "array.h"
 #include "config.h"
@@ -52,7 +53,7 @@ typedef enum {
        GIT_REBASE_NONE = 0,
        GIT_REBASE_APPLY = 1,
        GIT_REBASE_MERGE = 2,
-       GIT_REBASE_INTERACTIVE = 3,
+       GIT_REBASE_INTERACTIVE = 3
 } git_rebase_t;
 
 struct git_rebase {
@@ -63,10 +64,10 @@ struct git_rebase {
        git_rebase_t type;
        char *state_path;
 
-       int head_detached : 1,
-               inmemory : 1,
-               quiet : 1,
-               started : 1;
+       unsigned int head_detached:1,
+                    inmemory:1,
+                    quiet:1,
+                    started:1;
 
        git_array_t(git_rebase_operation) operations;
        size_t current;
@@ -90,22 +91,22 @@ static int rebase_state_type(
        char **path_out,
        git_repository *repo)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_rebase_t type = GIT_REBASE_NONE;
 
-       if (git_buf_joinpath(&path, repo->gitdir, REBASE_APPLY_DIR) < 0)
+       if (git_str_joinpath(&path, repo->gitdir, REBASE_APPLY_DIR) < 0)
                return -1;
 
-       if (git_path_isdir(git_buf_cstr(&path))) {
+       if (git_fs_path_isdir(git_str_cstr(&path))) {
                type = GIT_REBASE_APPLY;
                goto done;
        }
 
-       git_buf_clear(&path);
-       if (git_buf_joinpath(&path, repo->gitdir, REBASE_MERGE_DIR) < 0)
+       git_str_clear(&path);
+       if (git_str_joinpath(&path, repo->gitdir, REBASE_MERGE_DIR) < 0)
                return -1;
 
-       if (git_path_isdir(git_buf_cstr(&path))) {
+       if (git_fs_path_isdir(git_str_cstr(&path))) {
                type = GIT_REBASE_MERGE;
                goto done;
        }
@@ -114,36 +115,36 @@ done:
        *type_out = type;
 
        if (type != GIT_REBASE_NONE && path_out)
-               *path_out = git_buf_detach(&path);
+               *path_out = git_str_detach(&path);
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return 0;
 }
 
 GIT_INLINE(int) rebase_readfile(
-       git_buf *out,
-       git_buf *state_path,
+       git_str *out,
+       git_str *state_path,
        const char *filename)
 {
        size_t state_path_len = state_path->size;
        int error;
 
-       git_buf_clear(out);
+       git_str_clear(out);
 
-       if ((error = git_buf_joinpath(state_path, state_path->ptr, filename)) < 0 ||
+       if ((error = git_str_joinpath(state_path, state_path->ptr, filename)) < 0 ||
                (error = git_futils_readbuffer(out, state_path->ptr)) < 0)
                goto done;
 
-       git_buf_rtrim(out);
+       git_str_rtrim(out);
 
 done:
-       git_buf_truncate(state_path, state_path_len);
+       git_str_truncate(state_path, state_path_len);
        return error;
 }
 
 GIT_INLINE(int) rebase_readint(
-       size_t *out, git_buf *asc_out, git_buf *state_path, const char *filename)
+       size_t *out, git_str *asc_out, git_str *state_path, const char *filename)
 {
        int32_t num;
        const char *eol;
@@ -163,7 +164,7 @@ GIT_INLINE(int) rebase_readint(
 }
 
 GIT_INLINE(int) rebase_readoid(
-       git_oid *out, git_buf *str_out, git_buf *state_path, const char *filename)
+       git_oid *out, git_str *str_out, git_str *state_path, const char *filename)
 {
        int error;
 
@@ -201,13 +202,13 @@ static git_rebase_operation *rebase_operation_alloc(
 
 static int rebase_open_merge(git_rebase *rebase)
 {
-       git_buf state_path = GIT_BUF_INIT, buf = GIT_BUF_INIT, cmt = GIT_BUF_INIT;
+       git_str state_path = GIT_STR_INIT, buf = GIT_STR_INIT, cmt = GIT_STR_INIT;
        git_oid id;
        git_rebase_operation *operation;
        size_t i, msgnum = 0, end;
        int error;
 
-       if ((error = git_buf_puts(&state_path, rebase->state_path)) < 0)
+       if ((error = git_str_puts(&state_path, rebase->state_path)) < 0)
                goto done;
 
        /* Read 'msgnum' if it exists (otherwise, let msgnum = 0) */
@@ -234,9 +235,9 @@ static int rebase_open_merge(git_rebase *rebase)
        GIT_ERROR_CHECK_ARRAY(rebase->operations);
 
        for (i = 0; i < end; i++) {
-               git_buf_clear(&cmt);
+               git_str_clear(&cmt);
 
-               if ((error = git_buf_printf(&cmt, "cmt.%" PRIuZ, (i+1))) < 0 ||
+               if ((error = git_str_printf(&cmt, "cmt.%" PRIuZ, (i+1))) < 0 ||
                        (error = rebase_readoid(&id, &buf, &state_path, cmt.ptr)) < 0)
                        goto done;
 
@@ -248,12 +249,12 @@ static int rebase_open_merge(git_rebase *rebase)
        if ((error = rebase_readfile(&buf, &state_path, ONTO_NAME_FILE)) < 0)
                goto done;
 
-       rebase->onto_name = git_buf_detach(&buf);
+       rebase->onto_name = git_str_detach(&buf);
 
 done:
-       git_buf_dispose(&cmt);
-       git_buf_dispose(&state_path);
-       git_buf_dispose(&buf);
+       git_str_dispose(&cmt);
+       git_str_dispose(&state_path);
+       git_str_dispose(&buf);
 
        return error;
 }
@@ -296,8 +297,8 @@ int git_rebase_open(
        const git_rebase_options *given_opts)
 {
        git_rebase *rebase;
-       git_buf path = GIT_BUF_INIT, orig_head_name = GIT_BUF_INIT,
-               orig_head_id = GIT_BUF_INIT, onto_id = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT, orig_head_name = GIT_STR_INIT,
+               orig_head_id = GIT_STR_INIT, onto_id = GIT_STR_INIT;
        size_t state_path_len;
        int error;
 
@@ -320,54 +321,54 @@ int git_rebase_open(
                goto done;
        }
 
-       if ((error = git_buf_puts(&path, rebase->state_path)) < 0)
+       if ((error = git_str_puts(&path, rebase->state_path)) < 0)
                goto done;
 
-       state_path_len = git_buf_len(&path);
+       state_path_len = git_str_len(&path);
 
-       if ((error = git_buf_joinpath(&path, path.ptr, HEAD_NAME_FILE)) < 0 ||
+       if ((error = git_str_joinpath(&path, path.ptr, HEAD_NAME_FILE)) < 0 ||
                (error = git_futils_readbuffer(&orig_head_name, path.ptr)) < 0)
                goto done;
 
-       git_buf_rtrim(&orig_head_name);
+       git_str_rtrim(&orig_head_name);
 
        if (strcmp(ORIG_DETACHED_HEAD, orig_head_name.ptr) == 0)
                rebase->head_detached = 1;
 
-       git_buf_truncate(&path, state_path_len);
+       git_str_truncate(&path, state_path_len);
 
-       if ((error = git_buf_joinpath(&path, path.ptr, ORIG_HEAD_FILE)) < 0)
+       if ((error = git_str_joinpath(&path, path.ptr, ORIG_HEAD_FILE)) < 0)
                goto done;
 
-       if (!git_path_isfile(path.ptr)) {
+       if (!git_fs_path_isfile(path.ptr)) {
                /* Previous versions of git.git used 'head' here; support that. */
-               git_buf_truncate(&path, state_path_len);
+               git_str_truncate(&path, state_path_len);
 
-               if ((error = git_buf_joinpath(&path, path.ptr, HEAD_FILE)) < 0)
+               if ((error = git_str_joinpath(&path, path.ptr, HEAD_FILE)) < 0)
                        goto done;
        }
 
        if ((error = git_futils_readbuffer(&orig_head_id, path.ptr)) < 0)
                goto done;
 
-       git_buf_rtrim(&orig_head_id);
+       git_str_rtrim(&orig_head_id);
 
        if ((error = git_oid_fromstr(&rebase->orig_head_id, orig_head_id.ptr)) < 0)
                goto done;
 
-       git_buf_truncate(&path, state_path_len);
+       git_str_truncate(&path, state_path_len);
 
-       if ((error = git_buf_joinpath(&path, path.ptr, ONTO_FILE)) < 0 ||
+       if ((error = git_str_joinpath(&path, path.ptr, ONTO_FILE)) < 0 ||
                (error = git_futils_readbuffer(&onto_id, path.ptr)) < 0)
                goto done;
 
-       git_buf_rtrim(&onto_id);
+       git_str_rtrim(&onto_id);
 
        if ((error = git_oid_fromstr(&rebase->onto_id, onto_id.ptr)) < 0)
                goto done;
 
        if (!rebase->head_detached)
-               rebase->orig_head_name = git_buf_detach(&orig_head_name);
+               rebase->orig_head_name = git_str_detach(&orig_head_name);
 
        switch (rebase->type) {
        case GIT_REBASE_INTERACTIVE:
@@ -391,10 +392,10 @@ done:
        else
                git_rebase_free(rebase);
 
-       git_buf_dispose(&path);
-       git_buf_dispose(&orig_head_name);
-       git_buf_dispose(&orig_head_id);
-       git_buf_dispose(&onto_id);
+       git_str_dispose(&path);
+       git_str_dispose(&orig_head_name);
+       git_str_dispose(&orig_head_id);
+       git_str_dispose(&onto_id);
        return error;
 }
 
@@ -403,27 +404,27 @@ static int rebase_cleanup(git_rebase *rebase)
        if (!rebase || rebase->inmemory)
                return 0;
 
-       return git_path_isdir(rebase->state_path) ?
+       return git_fs_path_isdir(rebase->state_path) ?
                git_futils_rmdir_r(rebase->state_path, NULL, GIT_RMDIR_REMOVE_FILES) :
                0;
 }
 
 static int rebase_setupfile(git_rebase *rebase, const char *filename, int flags, const char *fmt, ...)
 {
-       git_buf path = GIT_BUF_INIT,
-               contents = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT,
+               contents = GIT_STR_INIT;
        va_list ap;
        int error;
 
        va_start(ap, fmt);
-       git_buf_vprintf(&contents, fmt, ap);
+       git_str_vprintf(&contents, fmt, ap);
        va_end(ap);
 
-       if ((error = git_buf_joinpath(&path, rebase->state_path, filename)) == 0)
+       if ((error = git_str_joinpath(&path, rebase->state_path, filename)) == 0)
                error = git_futils_writebuffer(&contents, path.ptr, flags, REBASE_FILE_MODE);
 
-       git_buf_dispose(&path);
-       git_buf_dispose(&contents);
+       git_str_dispose(&path);
+       git_str_dispose(&contents);
 
        return error;
 }
@@ -440,7 +441,7 @@ static const char *rebase_onto_name(const git_annotated_commit *onto)
 
 static int rebase_setupfiles_merge(git_rebase *rebase)
 {
-       git_buf commit_filename = GIT_BUF_INIT;
+       git_str commit_filename = GIT_STR_INIT;
        char id_str[GIT_OID_HEXSZ];
        git_rebase_operation *operation;
        size_t i;
@@ -453,8 +454,8 @@ static int rebase_setupfiles_merge(git_rebase *rebase)
        for (i = 0; i < git_array_size(rebase->operations); i++) {
                operation = git_array_get(rebase->operations, i);
 
-               git_buf_clear(&commit_filename);
-               git_buf_printf(&commit_filename, CMT_FILE_FMT, i+1);
+               git_str_clear(&commit_filename);
+               git_str_printf(&commit_filename, CMT_FILE_FMT, i+1);
 
                git_oid_fmt(id_str, &operation->id);
 
@@ -464,7 +465,7 @@ static int rebase_setupfiles_merge(git_rebase *rebase)
        }
 
 done:
-       git_buf_dispose(&commit_filename);
+       git_str_dispose(&commit_filename);
        return error;
 }
 
@@ -626,16 +627,16 @@ static int rebase_init_merge(
 {
        git_reference *head_ref = NULL;
        git_commit *onto_commit = NULL;
-       git_buf reflog = GIT_BUF_INIT;
-       git_buf state_path = GIT_BUF_INIT;
+       git_str reflog = GIT_STR_INIT;
+       git_str state_path = GIT_STR_INIT;
        int error;
 
        GIT_UNUSED(upstream);
 
-       if ((error = git_buf_joinpath(&state_path, repo->gitdir, REBASE_MERGE_DIR)) < 0)
+       if ((error = git_str_joinpath(&state_path, repo->gitdir, REBASE_MERGE_DIR)) < 0)
                goto done;
 
-       rebase->state_path = git_buf_detach(&state_path);
+       rebase->state_path = git_str_detach(&state_path);
        GIT_ERROR_CHECK_ALLOC(rebase->state_path);
 
        if (branch->ref_name && strcmp(branch->ref_name, "HEAD")) {
@@ -654,7 +655,7 @@ static int rebase_init_merge(
        git_oid_cpy(&rebase->onto_id, git_annotated_commit_id(onto));
 
        if ((error = rebase_setupfiles(rebase)) < 0 ||
-               (error = git_buf_printf(&reflog,
+               (error = git_str_printf(&reflog,
                        "rebase: checkout %s", rebase_onto_name(onto))) < 0 ||
                (error = git_commit_lookup(
                        &onto_commit, repo, git_annotated_commit_id(onto))) < 0 ||
@@ -667,8 +668,8 @@ static int rebase_init_merge(
 done:
        git_reference_free(head_ref);
        git_commit_free(onto_commit);
-       git_buf_dispose(&reflog);
-       git_buf_dispose(&state_path);
+       git_str_dispose(&reflog);
+       git_str_dispose(&state_path);
 
        return error;
 }
@@ -795,7 +796,7 @@ static int rebase_next_merge(
        git_rebase_operation **out,
        git_rebase *rebase)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_commit *current_commit = NULL, *parent_commit = NULL;
        git_tree *current_tree = NULL, *head_tree = NULL, *parent_tree = NULL;
        git_index *index = NULL;
@@ -848,7 +849,7 @@ done:
        git_tree_free(parent_tree);
        git_commit_free(parent_commit);
        git_commit_free(current_commit);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return error;
 }
@@ -955,14 +956,14 @@ static int create_signed(
        size_t parent_count,
        const git_commit **parents)
 {
-       git_buf commit_content = GIT_BUF_INIT,
-               commit_signature = GIT_BUF_INIT,
-               signature_field = GIT_BUF_INIT;
+       git_str commit_content = GIT_STR_INIT;
+       git_buf commit_signature = { NULL, 0, 0 },
+               signature_field = { NULL, 0, 0 };
        int error;
 
        git_error_clear();
 
-       if ((error = git_commit_create_buffer(&commit_content,
+       if ((error = git_commit__create_buffer(&commit_content,
                rebase->repo, author, committer, message_encoding,
                message, tree, parent_count, parents)) < 0)
                goto done;
@@ -986,7 +987,7 @@ static int create_signed(
 done:
        git_buf_dispose(&commit_signature);
        git_buf_dispose(&signature_field);
-       git_buf_dispose(&commit_content);
+       git_str_dispose(&commit_content);
        return error;
 }
 #endif
@@ -1216,13 +1217,13 @@ done:
        return error;
 }
 
-static int notes_ref_lookup(git_buf *out, git_rebase *rebase)
+static int notes_ref_lookup(git_str *out, git_rebase *rebase)
 {
        git_config *config = NULL;
        int do_rewrite, error;
 
        if (rebase->options.rewrite_notes_ref) {
-               git_buf_attach_notowned(out,
+               git_str_attach_notowned(out,
                        rebase->options.rewrite_notes_ref,
                        strlen(rebase->options.rewrite_notes_ref));
                return 0;
@@ -1239,7 +1240,7 @@ static int notes_ref_lookup(git_buf *out, git_rebase *rebase)
        }
 
        error = do_rewrite ?
-               git_config_get_string_buf(out, config, "notes.rewriteref") :
+               git_config__get_string_buf(out, config, "notes.rewriteref") :
                GIT_ENOTFOUND;
 
 done:
@@ -1294,7 +1295,7 @@ static int rebase_copy_notes(
        git_rebase *rebase,
        const git_signature *committer)
 {
-       git_buf path = GIT_BUF_INIT, rewritten = GIT_BUF_INIT, notes_ref = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT, rewritten = GIT_STR_INIT, notes_ref = GIT_STR_INIT;
        char *pair_list, *fromstr, *tostr, *end;
        git_oid from, to;
        unsigned int linenum = 1;
@@ -1309,7 +1310,7 @@ static int rebase_copy_notes(
                goto done;
        }
 
-       if ((error = git_buf_joinpath(&path, rebase->state_path, REWRITTEN_FILE)) < 0 ||
+       if ((error = git_str_joinpath(&path, rebase->state_path, REWRITTEN_FILE)) < 0 ||
                (error = git_futils_readbuffer(&rewritten, path.ptr)) < 0)
                goto done;
 
@@ -1349,9 +1350,9 @@ on_error:
        error = -1;
 
 done:
-       git_buf_dispose(&rewritten);
-       git_buf_dispose(&path);
-       git_buf_dispose(&notes_ref);
+       git_str_dispose(&rewritten);
+       git_str_dispose(&path);
+       git_str_dispose(&notes_ref);
 
        return error;
 }
@@ -1360,16 +1361,16 @@ static int return_to_orig_head(git_rebase *rebase)
 {
        git_reference *terminal_ref = NULL, *branch_ref = NULL, *head_ref = NULL;
        git_commit *terminal_commit = NULL;
-       git_buf branch_msg = GIT_BUF_INIT, head_msg = GIT_BUF_INIT;
+       git_str branch_msg = GIT_STR_INIT, head_msg = GIT_STR_INIT;
        char onto[GIT_OID_HEXSZ];
        int error = 0;
 
        git_oid_fmt(onto, &rebase->onto_id);
 
-       if ((error = git_buf_printf(&branch_msg,
+       if ((error = git_str_printf(&branch_msg,
                        "rebase finished: %s onto %.*s",
                        rebase->orig_head_name, GIT_OID_HEXSZ, onto)) == 0 &&
-               (error = git_buf_printf(&head_msg,
+               (error = git_str_printf(&head_msg,
                        "rebase finished: returning to %s",
                        rebase->orig_head_name)) == 0 &&
                (error = git_repository_head(&terminal_ref, rebase->repo)) == 0 &&
@@ -1383,8 +1384,8 @@ static int return_to_orig_head(git_rebase *rebase)
                        rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1,
                        head_msg.ptr);
 
-       git_buf_dispose(&head_msg);
-       git_buf_dispose(&branch_msg);
+       git_str_dispose(&head_msg);
+       git_str_dispose(&branch_msg);
        git_commit_free(terminal_commit);
        git_reference_free(head_ref);
        git_reference_free(branch_ref);
index 24cb22fb06f7bf92a53a4f52639d6668f804f652..95bda940472f6a8146cc77a88bec2de30e2bed07 100644 (file)
@@ -18,6 +18,7 @@
 #include "sortedcache.h"
 #include "signature.h"
 #include "wildmatch.h"
+#include "path.h"
 
 #include <git2/tag.h>
 #include <git2/object.h>
@@ -34,7 +35,7 @@ enum {
        PACKREF_HAS_PEEL = 1,
        PACKREF_WAS_LOOSE = 2,
        PACKREF_CANNOT_PEEL = 4,
-       PACKREF_SHADOWED = 8,
+       PACKREF_SHADOWED = 8
 };
 
 enum {
@@ -64,24 +65,29 @@ typedef struct refdb_fs_backend {
        git_iterator_flag_t iterator_flags;
        uint32_t direach_flags;
        int fsync;
+       git_map packed_refs_map;
+       git_mutex prlock; /* protect packed_refs_map */
+       git_futils_filestamp packed_refs_stamp;
+       bool sorted;
 } refdb_fs_backend;
 
 static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name);
+static char *packed_set_peeling_mode(char *data, size_t data_sz, refdb_fs_backend *backend);
 
 GIT_INLINE(int) loose_path(
-       git_buf *out,
+       git_str *out,
        const char *base,
        const char *refname)
 {
-       if (git_buf_joinpath(out, base, refname) < 0)
+       if (git_str_joinpath(out, base, refname) < 0)
                return -1;
 
-       return git_path_validate_filesystem_with_suffix(out->ptr, out->size,
+       return git_fs_path_validate_str_length_with_suffix(out,
                CONST_STRLEN(".lock"));
 }
 
 GIT_INLINE(int) reflog_path(
-       git_buf *out,
+       git_str *out,
        git_repository *repo,
        const char *refname)
 {
@@ -91,7 +97,7 @@ GIT_INLINE(int) reflog_path(
        base = (strcmp(refname, GIT_HEAD_FILE) == 0) ? repo->gitdir :
                repo->commondir;
 
-       if ((error = git_buf_joinpath(out, base, GIT_REFLOG_DIR)) < 0)
+       if ((error = git_str_joinpath(out, base, GIT_REFLOG_DIR)) < 0)
                return error;
 
        return loose_path(out, out->ptr, refname);
@@ -106,7 +112,7 @@ static int packref_cmp(const void *a_, const void *b_)
 static int packed_reload(refdb_fs_backend *backend)
 {
        int error;
-       git_buf packedrefs = GIT_BUF_INIT;
+       git_str packedrefs = GIT_STR_INIT;
        char *scan, *eof, *eol;
 
        if (!backend->gitpath)
@@ -133,31 +139,12 @@ static int packed_reload(refdb_fs_backend *backend)
 
        GIT_UNUSED(git_sortedcache_clear(backend->refcache, false));
 
-       scan = (char *)packedrefs.ptr;
+       scan = packedrefs.ptr;
        eof  = scan + packedrefs.size;
 
-       backend->peeling_mode = PEELING_NONE;
-
-       if (*scan == '#') {
-               static const char *traits_header = "# pack-refs with: ";
-
-               if (git__prefixcmp(scan, traits_header) == 0) {
-                       scan += strlen(traits_header);
-                       eol = strchr(scan, '\n');
-
-                       if (!eol)
-                               goto parse_failed;
-                       *eol = '\0';
-
-                       if (strstr(scan, " fully-peeled ") != NULL) {
-                               backend->peeling_mode = PEELING_FULL;
-                       } else if (strstr(scan, " peeled ") != NULL) {
-                               backend->peeling_mode = PEELING_STANDARD;
-                       }
-
-                       scan = eol + 1;
-               }
-       }
+       scan = packed_set_peeling_mode(scan, packedrefs.size, backend);
+       if (!scan)
+               goto parse_failed;
 
        while (scan < eof && *scan == '#') {
                if (!(eol = strchr(scan, '\n')))
@@ -212,7 +199,7 @@ static int packed_reload(refdb_fs_backend *backend)
        }
 
        git_sortedcache_wunlock(backend->refcache);
-       git_buf_dispose(&packedrefs);
+       git_str_dispose(&packedrefs);
 
        return 0;
 
@@ -221,17 +208,17 @@ parse_failed:
 
        GIT_UNUSED(git_sortedcache_clear(backend->refcache, false));
        git_sortedcache_wunlock(backend->refcache);
-       git_buf_dispose(&packedrefs);
+       git_str_dispose(&packedrefs);
 
        return -1;
 }
 
 static int loose_parse_oid(
-       git_oid *oid, const char *filename, git_buf *file_content)
+       git_oid *oid, const char *filename, git_str *file_content)
 {
-       const char *str = git_buf_cstr(file_content);
+       const char *str = git_str_cstr(file_content);
 
-       if (git_buf_len(file_content) < GIT_OID_HEXSZ)
+       if (git_str_len(file_content) < GIT_OID_HEXSZ)
                goto corrupted;
 
        /* we need to get 40 OID characters from the file */
@@ -248,13 +235,13 @@ corrupted:
        return -1;
 }
 
-static int loose_readbuffer(git_buf *buf, const char *base, const char *path)
+static int loose_readbuffer(git_str *buf, const char *base, const char *path)
 {
        int error;
 
        if ((error = loose_path(buf, base, path)) < 0 ||
            (error = git_futils_readbuffer(buf, buf->ptr)) < 0)
-               git_buf_dispose(buf);
+               git_str_dispose(buf);
 
        return error;
 }
@@ -262,7 +249,7 @@ static int loose_readbuffer(git_buf *buf, const char *base, const char *path)
 static int loose_lookup_to_packfile(refdb_fs_backend *backend, const char *name)
 {
        int error = 0;
-       git_buf ref_file = GIT_BUF_INIT;
+       git_str ref_file = GIT_STR_INIT;
        struct packref *ref = NULL;
        git_oid oid;
 
@@ -275,7 +262,7 @@ static int loose_lookup_to_packfile(refdb_fs_backend *backend, const char *name)
        }
 
        /* skip symbolic refs */
-       if (!git__prefixcmp(git_buf_cstr(&ref_file), GIT_SYMREF))
+       if (!git__prefixcmp(git_str_cstr(&ref_file), GIT_SYMREF))
                goto done;
 
        /* parse OID from file */
@@ -295,11 +282,11 @@ static int loose_lookup_to_packfile(refdb_fs_backend *backend, const char *name)
        git_sortedcache_wunlock(backend->refcache);
 
 done:
-       git_buf_dispose(&ref_file);
+       git_str_dispose(&ref_file);
        return error;
 }
 
-static int _dirent_loose_load(void *payload, git_buf *full_path)
+static int _dirent_loose_load(void *payload, git_str *full_path)
 {
        refdb_fs_backend *backend = payload;
        const char *file_path;
@@ -307,8 +294,8 @@ static int _dirent_loose_load(void *payload, git_buf *full_path)
        if (git__suffixcmp(full_path->ptr, ".lock") == 0)
                return 0;
 
-       if (git_path_isdir(full_path->ptr)) {
-               int error = git_path_direach(
+       if (git_fs_path_isdir(full_path->ptr)) {
+               int error = git_fs_path_direach(
                        full_path, backend->direach_flags, _dirent_loose_load, backend);
                /* Race with the filesystem, ignore it */
                if (error == GIT_ENOTFOUND) {
@@ -333,9 +320,9 @@ static int _dirent_loose_load(void *payload, git_buf *full_path)
 static int packed_loadloose(refdb_fs_backend *backend)
 {
        int error;
-       git_buf refs_path = GIT_BUF_INIT;
+       git_str refs_path = GIT_STR_INIT;
 
-       if (git_buf_joinpath(&refs_path, backend->gitpath, GIT_REFS_DIR) < 0)
+       if (git_str_joinpath(&refs_path, backend->gitpath, GIT_REFS_DIR) < 0)
                return -1;
 
        /*
@@ -343,10 +330,10 @@ static int packed_loadloose(refdb_fs_backend *backend)
         * This will overwrite any old packed entries with their
         * updated loose versions
         */
-       error = git_path_direach(
+       error = git_fs_path_direach(
                &refs_path, backend->direach_flags, _dirent_loose_load, backend);
 
-       git_buf_dispose(&refs_path);
+       git_str_dispose(&refs_path);
 
        return error;
 }
@@ -357,7 +344,7 @@ static int refdb_fs_backend__exists(
        const char *ref_name)
 {
        refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
-       git_buf ref_path = GIT_BUF_INIT;
+       git_str ref_path = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(backend);
@@ -367,7 +354,7 @@ static int refdb_fs_backend__exists(
        if ((error = loose_path(&ref_path, backend->gitpath, ref_name)) < 0)
                goto out;
 
-       if (git_path_isfile(ref_path.ptr)) {
+       if (git_fs_path_isfile(ref_path.ptr)) {
                *exists = 1;
                goto out;
        }
@@ -381,18 +368,18 @@ static int refdb_fs_backend__exists(
        }
 
 out:
-       git_buf_dispose(&ref_path);
+       git_str_dispose(&ref_path);
        return error;
 }
 
-static const char *loose_parse_symbolic(git_buf *file_content)
+static const char *loose_parse_symbolic(git_str *file_content)
 {
        const unsigned int header_len = (unsigned int)strlen(GIT_SYMREF);
        const char *refname_start;
 
        refname_start = (const char *)file_content->ptr;
 
-       if (git_buf_len(file_content) < header_len + 1) {
+       if (git_str_len(file_content) < header_len + 1) {
                git_error_set(GIT_ERROR_REFERENCE, "corrupted loose reference file");
                return NULL;
        }
@@ -424,7 +411,7 @@ static int loose_lookup(
        refdb_fs_backend *backend,
        const char *ref_name)
 {
-       git_buf ref_file = GIT_BUF_INIT;
+       git_str ref_file = GIT_STR_INIT;
        int error = 0;
        const char *ref_dir;
 
@@ -438,10 +425,10 @@ static int loose_lookup(
 
        if ((error = loose_readbuffer(&ref_file, ref_dir, ref_name)) < 0)
                /* cannot read loose ref file - gah */;
-       else if (git__prefixcmp(git_buf_cstr(&ref_file), GIT_SYMREF) == 0) {
+       else if (git__prefixcmp(git_str_cstr(&ref_file), GIT_SYMREF) == 0) {
                const char *target;
 
-               git_buf_rtrim(&ref_file);
+               git_str_rtrim(&ref_file);
 
                if (!(target = loose_parse_symbolic(&ref_file)))
                        error = -1;
@@ -455,7 +442,7 @@ static int loose_lookup(
                        *out = git_reference__alloc(ref_name, &oid, NULL);
        }
 
-       git_buf_dispose(&ref_file);
+       git_str_dispose(&ref_file);
        return error;
 }
 
@@ -465,10 +452,198 @@ static int ref_error_notfound(const char *name)
        return GIT_ENOTFOUND;
 }
 
-static int packed_lookup(
-       git_reference **out,
-       refdb_fs_backend *backend,
-       const char *ref_name)
+static char *packed_set_peeling_mode(
+        char *data,
+        size_t data_sz,
+        refdb_fs_backend *backend)
+{
+       static const char *traits_header = "# pack-refs with:";
+       char *eol;
+       backend->peeling_mode = PEELING_NONE;
+
+       if (git__prefixncmp(data, data_sz, traits_header) == 0) {
+               size_t hdr_sz = strlen(traits_header);
+               const char *sorted = " sorted ";
+               const char *peeled = " peeled ";
+               const char *fully_peeled = " fully-peeled ";
+               data += hdr_sz;
+               data_sz -= hdr_sz;
+
+               eol = memchr(data, '\n', data_sz);
+
+               if (!eol)
+                       return NULL;
+
+               if (git__memmem(data, eol - data, fully_peeled, strlen(fully_peeled)))
+                       backend->peeling_mode = PEELING_FULL;
+               else if (git__memmem(data, eol - data, peeled, strlen(peeled)))
+                       backend->peeling_mode = PEELING_STANDARD;
+
+               backend->sorted = NULL != git__memmem(data, eol - data, sorted, strlen(sorted));
+
+               return eol + 1;
+       }
+       return data;
+}
+
+static void packed_map_free(refdb_fs_backend *backend)
+{
+       if (backend->packed_refs_map.data) {
+#ifdef GIT_WIN32
+               git__free(backend->packed_refs_map.data);
+#else
+               git_futils_mmap_free(&backend->packed_refs_map);
+#endif
+               backend->packed_refs_map.data = NULL;
+               backend->packed_refs_map.len = 0;
+               git_futils_filestamp_set(&backend->packed_refs_stamp, NULL);
+       }
+}
+
+static int packed_map_check(refdb_fs_backend *backend)
+{
+       int error = 0;
+       git_file fd = -1;
+       struct stat st;
+
+       if ((error = git_mutex_lock(&backend->prlock)) < 0)
+               return error;
+
+       if (backend->packed_refs_map.data &&
+           !git_futils_filestamp_check(
+                   &backend->packed_refs_stamp, backend->refcache->path)) {
+               git_mutex_unlock(&backend->prlock);
+               return error;
+       }
+       packed_map_free(backend);
+
+       fd = git_futils_open_ro(backend->refcache->path);
+       if (fd < 0) {
+               git_mutex_unlock(&backend->prlock);
+               if (fd == GIT_ENOTFOUND) {
+                       git_error_clear();
+                       return 0;
+               }
+               return fd;
+       }
+
+       if (p_fstat(fd, &st) < 0) {
+               p_close(fd);
+               git_mutex_unlock(&backend->prlock);
+               git_error_set(GIT_ERROR_OS, "unable to stat packed-refs '%s'", backend->refcache->path);
+               return -1;
+       }
+
+       if (st.st_size == 0) {
+               p_close(fd);
+               git_mutex_unlock(&backend->prlock);
+               return 0;
+       }
+
+       git_futils_filestamp_set_from_stat(&backend->packed_refs_stamp, &st);
+
+#ifdef GIT_WIN32
+       /* on windows, we copy the entire file into memory rather than using
+        * mmap() because using mmap() on windows also locks the file and this
+        * map is long-lived. */
+       backend->packed_refs_map.len = (size_t)st.st_size;
+       backend->packed_refs_map.data =
+               git__malloc(backend->packed_refs_map.len);
+       GIT_ERROR_CHECK_ALLOC(backend->packed_refs_map.data);
+       {
+               ssize_t bytesread =
+                       p_read(fd, backend->packed_refs_map.data,
+                              backend->packed_refs_map.len);
+               error = (bytesread == (ssize_t)backend->packed_refs_map.len) ?  0 : -1;
+       }
+#else
+       error = git_futils_mmap_ro(&backend->packed_refs_map, fd, 0, (size_t)st.st_size);
+#endif
+       p_close(fd);
+       if (error < 0) {
+               git_mutex_unlock(&backend->prlock);
+               return error;
+       }
+
+       packed_set_peeling_mode(
+               backend->packed_refs_map.data, backend->packed_refs_map.len,
+               backend);
+
+       git_mutex_unlock(&backend->prlock);
+       return error;
+}
+
+/*
+ * Find beginning of packed-ref record pointed to by p.
+ *   buf - a lower-bound pointer to some memory buffer
+ *   p - an upper-bound pointer to the same memory buffer
+ */
+static const char *start_of_record(const char *buf, const char *p)
+{
+       const char *nl = p;
+       while (true) {
+               nl = git__memrchr(buf, '\n', nl - buf);
+               if (!nl)
+                       return buf;
+
+               if (nl[1] == '^' && nl > buf)
+                       --nl;
+               else
+                       break;
+       };
+       return nl + 1;
+}
+
+/*
+ * Find end of packed-ref record pointed to by p.
+ *   end - an upper-bound pointer to some memory buffer
+ *   p - a lower-bound pointer to the same memory buffer
+ */
+static const char *end_of_record(const char *p, const char *end)
+{
+       while (1) {
+               size_t sz = end - p;
+               p = memchr(p, '\n', sz);
+               if (!p)
+                       return end;
+               ++p;
+               if (p < end && p[0] == '^')
+                       ++p;
+               else
+                       break;
+       }
+       return p;
+}
+
+static int
+cmp_record_to_refname(const char *rec, size_t data_end, const char *ref_name)
+{
+       const size_t ref_len = strlen(ref_name);
+       int cmp_val;
+       const char *end;
+
+       rec += GIT_OID_HEXSZ + 1; /* <oid> + space */
+       if (data_end < GIT_OID_HEXSZ + 3) {
+               /* an incomplete (corrupt) record is treated as less than ref_name */
+               return -1;
+       }
+       data_end -= GIT_OID_HEXSZ + 1;
+
+       end = memchr(rec, '\n', data_end);
+       if (end)
+               data_end = end - rec;
+
+       cmp_val = memcmp(rec, ref_name, min(ref_len, data_end));
+
+       if (cmp_val == 0 && data_end != ref_len)
+               return (data_end > ref_len) ? 1 : -1;
+       return cmp_val;
+}
+
+static int packed_unsorted_lookup(
+        git_reference **out,
+        refdb_fs_backend *backend,
+        const char *ref_name)
 {
        int error = 0;
        struct packref *entry;
@@ -493,6 +668,85 @@ static int packed_lookup(
        return error;
 }
 
+static int packed_lookup(
+        git_reference **out,
+        refdb_fs_backend *backend,
+        const char *ref_name)
+{
+       int error = 0;
+       const char *left, *right, *data_end;
+
+       if ((error = packed_map_check(backend)) < 0)
+               return error;
+
+       if (!backend->sorted)
+               return packed_unsorted_lookup(out, backend, ref_name);
+
+       left = backend->packed_refs_map.data;
+       right = data_end = (const char *) backend->packed_refs_map.data +
+                          backend->packed_refs_map.len;
+
+       while (left < right && *left == '#') {
+               if (!(left = memchr(left, '\n', data_end - left)))
+                       goto parse_failed;
+               left++;
+       }
+
+       while (left < right) {
+               const char *mid, *rec;
+               int compare;
+
+               mid = left + (right - left) / 2;
+               rec = start_of_record(left, mid);
+               compare = cmp_record_to_refname(rec, data_end - rec, ref_name);
+
+               if (compare < 0) {
+                       left = end_of_record(mid, right);
+               } else if (compare > 0) {
+                       right = rec;
+               } else {
+                       const char *eol;
+                       git_oid oid, peel, *peel_ptr = NULL;
+
+                       if (data_end - rec < GIT_OID_HEXSZ ||
+                           git_oid_fromstr(&oid, rec) < 0) {
+                               goto parse_failed;
+                       }
+                       rec += GIT_OID_HEXSZ + 1;
+                       if (!(eol = memchr(rec, '\n', data_end - rec))) {
+                               goto parse_failed;
+                       }
+
+                       /* look for optional "^<OID>\n" */
+
+                       if (eol + 1 < data_end) {
+                               rec = eol + 1;
+
+                               if (*rec == '^') {
+                                       rec++;
+                                       if (data_end - rec < GIT_OID_HEXSZ ||
+                                               git_oid_fromstr(&peel, rec) < 0) {
+                                               goto parse_failed;
+                                       }
+                                       peel_ptr = &peel;
+                               }
+                       }
+
+                       *out = git_reference__alloc(ref_name, &oid, peel_ptr);
+                       if (!*out) {
+                               return -1;
+                       }
+
+                       return 0;
+               }
+       }
+       return GIT_ENOTFOUND;
+
+parse_failed:
+       git_error_set(GIT_ERROR_REFERENCE, "corrupted packed references file");
+       return -1;
+}
+
 static int refdb_fs_backend__lookup(
        git_reference **out,
        git_refdb_backend *_backend,
@@ -512,7 +766,6 @@ static int refdb_fs_backend__lookup(
                git_error_clear();
                error = packed_lookup(out, backend, ref_name);
        }
-
        return error;
 }
 
@@ -542,7 +795,7 @@ static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter)
 static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter)
 {
        int error = 0;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_iterator *fsit = NULL;
        git_iterator_options fsit_opts = GIT_ITERATOR_OPTIONS_INIT;
        const git_index_entry *entry = NULL;
@@ -578,26 +831,26 @@ static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter)
                }
        }
 
-       if ((error = git_buf_puts(&path, backend->commonpath)) < 0 ||
-               (error = git_buf_put(&path, ref_prefix, ref_prefix_len)) < 0) {
-               git_buf_dispose(&path);
+       if ((error = git_str_puts(&path, backend->commonpath)) < 0 ||
+               (error = git_str_put(&path, ref_prefix, ref_prefix_len)) < 0) {
+               git_str_dispose(&path);
                return error;
        }
 
        if ((error = git_iterator_for_filesystem(&fsit, path.ptr, &fsit_opts)) < 0) {
-               git_buf_dispose(&path);
+               git_str_dispose(&path);
                return (iter->glob && error == GIT_ENOTFOUND)? 0 : error;
        }
 
-       error = git_buf_sets(&path, ref_prefix);
+       error = git_str_sets(&path, ref_prefix);
 
        while (!error && !git_iterator_advance(&entry, fsit)) {
                const char *ref_name;
                char *ref_dup;
 
-               git_buf_truncate(&path, ref_prefix_len);
-               git_buf_puts(&path, entry->path);
-               ref_name = git_buf_cstr(&path);
+               git_str_truncate(&path, ref_prefix_len);
+               git_str_puts(&path, entry->path);
+               ref_name = git_str_cstr(&path);
 
                if (git__suffixcmp(ref_name, ".lock") == 0 ||
                        (iter->glob && wildmatch(iter->glob, ref_name, 0) != 0))
@@ -611,7 +864,7 @@ static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter)
        }
 
        git_iterator_free(fsit);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return error;
 }
@@ -810,14 +1063,14 @@ static int reference_path_available(
 static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *name)
 {
        int error, filebuf_flags;
-       git_buf ref_path = GIT_BUF_INIT;
+       git_str ref_path = GIT_STR_INIT;
        const char *basedir;
 
        GIT_ASSERT_ARG(file);
        GIT_ASSERT_ARG(backend);
        GIT_ASSERT_ARG(name);
 
-       if (!git_path_validate(backend->repo, name, 0, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
+       if (!git_path_is_valid(backend->repo, name, 0, GIT_FS_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
                git_error_set(GIT_ERROR_INVALID, "invalid reference name '%s'", name);
                return GIT_EINVALIDSPEC;
        }
@@ -845,7 +1098,7 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *
        if (error == GIT_EDIRECTORY)
                git_error_set(GIT_ERROR_REFERENCE, "cannot lock ref '%s', there are refs beneath that folder", name);
 
-       git_buf_dispose(&ref_path);
+       git_str_dispose(&ref_path);
        return error;
 }
 
@@ -1013,7 +1266,7 @@ static int packed_remove_loose(refdb_fs_backend *backend)
 {
        size_t i;
        git_filebuf lock = GIT_FILEBUF_INIT;
-       git_buf ref_content = GIT_BUF_INIT;
+       git_str ref_content = GIT_STR_INIT;
        int error = 0;
 
        /* backend->refcache is already locked when this is called */
@@ -1034,7 +1287,7 @@ static int packed_remove_loose(refdb_fs_backend *backend)
                        continue;
 
                if (error < 0) {
-                       git_buf_dispose(&ref_content);
+                       git_str_dispose(&ref_content);
                        git_error_set(GIT_ERROR_REFERENCE, "failed to lock loose reference '%s'", ref->name);
                        return error;
                }
@@ -1065,7 +1318,7 @@ static int packed_remove_loose(refdb_fs_backend *backend)
                p_unlink(lock.path_original);
        }
 
-       git_buf_dispose(&ref_content);
+       git_str_dispose(&ref_content);
        git_filebuf_cleanup(&lock);
        return 0;
 }
@@ -1080,6 +1333,15 @@ static int packed_write(refdb_fs_backend *backend)
        int error, open_flags = 0;
        size_t i;
 
+       /* take lock and close up packed-refs mmap if open */
+       if ((error = git_mutex_lock(&backend->prlock)) < 0) {
+               return error;
+       }
+
+       packed_map_free(backend);
+
+       git_mutex_unlock(&backend->prlock);
+
        /* lock the cache to updates while we do this */
        if ((error = git_sortedcache_wlock(refcache)) < 0)
                return error;
@@ -1333,41 +1595,41 @@ static int refdb_fs_backend__prune_refs(
        const char *ref_name,
        const char *prefix)
 {
-       git_buf relative_path = GIT_BUF_INIT;
-       git_buf base_path = GIT_BUF_INIT;
+       git_str relative_path = GIT_STR_INIT;
+       git_str base_path = GIT_STR_INIT;
        size_t commonlen;
        int error;
 
        GIT_ASSERT_ARG(backend);
        GIT_ASSERT_ARG(ref_name);
 
-       if ((error = git_buf_sets(&relative_path, ref_name)) < 0)
+       if ((error = git_str_sets(&relative_path, ref_name)) < 0)
                goto cleanup;
 
-       git_path_squash_slashes(&relative_path);
-       if ((commonlen = git_path_common_dirlen("refs/heads/", git_buf_cstr(&relative_path))) == strlen("refs/heads/") ||
-               (commonlen = git_path_common_dirlen("refs/tags/", git_buf_cstr(&relative_path))) == strlen("refs/tags/") ||
-               (commonlen = git_path_common_dirlen("refs/remotes/", git_buf_cstr(&relative_path))) == strlen("refs/remotes/")) {
+       git_fs_path_squash_slashes(&relative_path);
+       if ((commonlen = git_fs_path_common_dirlen("refs/heads/", git_str_cstr(&relative_path))) == strlen("refs/heads/") ||
+               (commonlen = git_fs_path_common_dirlen("refs/tags/", git_str_cstr(&relative_path))) == strlen("refs/tags/") ||
+               (commonlen = git_fs_path_common_dirlen("refs/remotes/", git_str_cstr(&relative_path))) == strlen("refs/remotes/")) {
 
-               git_buf_truncate(&relative_path, commonlen);
+               git_str_truncate(&relative_path, commonlen);
 
                if (prefix)
-                       error = git_buf_join3(&base_path, '/',
+                       error = git_str_join3(&base_path, '/',
                                backend->commonpath, prefix,
-                               git_buf_cstr(&relative_path));
+                               git_str_cstr(&relative_path));
                else
-                       error = git_buf_joinpath(&base_path,
+                       error = git_str_joinpath(&base_path,
                                backend->commonpath,
-                               git_buf_cstr(&relative_path));
+                               git_str_cstr(&relative_path));
 
                if (!error)
-                       error = git_path_validate_filesystem(base_path.ptr, base_path.size);
+                       error = git_path_validate_str_length(NULL, &base_path);
 
                if (error < 0)
                        goto cleanup;
 
                error = git_futils_rmdir_r(ref_name + commonlen,
-                       git_buf_cstr(&base_path),
+                       git_str_cstr(&base_path),
                        GIT_RMDIR_EMPTY_PARENTS | GIT_RMDIR_SKIP_ROOT);
 
                if (error == GIT_ENOTFOUND)
@@ -1375,8 +1637,8 @@ static int refdb_fs_backend__prune_refs(
        }
 
 cleanup:
-       git_buf_dispose(&relative_path);
-       git_buf_dispose(&base_path);
+       git_str_dispose(&relative_path);
+       git_str_dispose(&base_path);
        return error;
 }
 
@@ -1405,7 +1667,7 @@ static int refdb_fs_backend__delete(
 
 static int loose_delete(refdb_fs_backend *backend, const char *ref_name)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        int error = 0;
 
        if ((error = loose_path(&path, backend->commonpath, ref_name)) < 0)
@@ -1417,7 +1679,7 @@ static int loose_delete(refdb_fs_backend *backend, const char *ref_name)
        else if (error != 0)
                error = -1;
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return error;
 }
@@ -1567,6 +1829,12 @@ static void refdb_fs_backend__free(git_refdb_backend *_backend)
                return;
 
        git_sortedcache_free(backend->refcache);
+
+       git_mutex_lock(&backend->prlock);
+       packed_map_free(backend);
+       git_mutex_unlock(&backend->prlock);
+       git_mutex_free(&backend->prlock);
+
        git__free(backend->gitpath);
        git__free(backend->commonpath);
        git__free(backend);
@@ -1574,17 +1842,17 @@ static void refdb_fs_backend__free(git_refdb_backend *_backend)
 
 static char *setup_namespace(git_repository *repo, const char *in)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        char *parts, *start, *end, *out = NULL;
 
        if (!in)
                goto done;
 
-       git_buf_puts(&path, in);
+       git_str_puts(&path, in);
 
        /* if the repo is not namespaced, nothing else to do */
        if (repo->namespace == NULL) {
-               out = git_buf_detach(&path);
+               out = git_str_detach(&path);
                goto done;
        }
 
@@ -1599,23 +1867,23 @@ static char *setup_namespace(git_repository *repo, const char *in)
         *  refs under refs/namespaces/foo/refs/namespaces/bar/
         */
        while ((start = git__strsep(&end, "/")) != NULL)
-               git_buf_printf(&path, "refs/namespaces/%s/", start);
+               git_str_printf(&path, "refs/namespaces/%s/", start);
 
-       git_buf_printf(&path, "refs/namespaces/%s/refs", end);
+       git_str_printf(&path, "refs/namespaces/%s/refs", end);
        git__free(parts);
 
        /* Make sure that the folder with the namespace exists */
-       if (git_futils_mkdir_relative(git_buf_cstr(&path), in, 0777,
+       if (git_futils_mkdir_relative(git_str_cstr(&path), in, 0777,
                        GIT_MKDIR_PATH, NULL) < 0)
                goto done;
 
        /* Return root of the namespaced gitpath, i.e. without the trailing 'refs' */
-       git_buf_rtruncate_at_char(&path, '/');
-       git_buf_putc(&path, '/');
-       out = git_buf_detach(&path);
+       git_str_rtruncate_at_char(&path, '/');
+       git_str_putc(&path, '/');
+       out = git_str_detach(&path);
 
 done:
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        return out;
 }
 
@@ -1716,7 +1984,7 @@ static int refdb_reflog_fs__ensure_log(git_refdb_backend *_backend, const char *
 {
        refdb_fs_backend *backend;
        git_repository *repo;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(_backend && name);
@@ -1727,8 +1995,8 @@ static int refdb_reflog_fs__ensure_log(git_refdb_backend *_backend, const char *
        if ((error = reflog_path(&path, repo, name)) < 0)
                return error;
 
-       error = create_new_reflog_file(git_buf_cstr(&path));
-       git_buf_dispose(&path);
+       error = create_new_reflog_file(git_str_cstr(&path));
+       git_str_dispose(&path);
 
        return error;
 }
@@ -1736,15 +2004,15 @@ static int refdb_reflog_fs__ensure_log(git_refdb_backend *_backend, const char *
 static int has_reflog(git_repository *repo, const char *name)
 {
        int ret = 0;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        if (reflog_path(&path, repo, name) < 0)
                goto cleanup;
 
-       ret = git_path_isfile(git_buf_cstr(&path));
+       ret = git_fs_path_isfile(git_str_cstr(&path));
 
 cleanup:
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        return ret;
 }
 
@@ -1763,8 +2031,8 @@ static int refdb_reflog_fs__has_log(git_refdb_backend *_backend, const char *nam
 static int refdb_reflog_fs__read(git_reflog **out, git_refdb_backend *_backend, const char *name)
 {
        int error = -1;
-       git_buf log_path = GIT_BUF_INIT;
-       git_buf log_file = GIT_BUF_INIT;
+       git_str log_path = GIT_STR_INIT;
+       git_str log_file = GIT_STR_INIT;
        git_reflog *log = NULL;
        git_repository *repo;
        refdb_fs_backend *backend;
@@ -1782,16 +2050,16 @@ static int refdb_reflog_fs__read(git_reflog **out, git_refdb_backend *_backend,
        if (reflog_path(&log_path, repo, name) < 0)
                goto cleanup;
 
-       error = git_futils_readbuffer(&log_file, git_buf_cstr(&log_path));
+       error = git_futils_readbuffer(&log_file, git_str_cstr(&log_path));
        if (error < 0 && error != GIT_ENOTFOUND)
                goto cleanup;
 
        if ((error == GIT_ENOTFOUND) &&
-               ((error = create_new_reflog_file(git_buf_cstr(&log_path))) < 0))
+               ((error = create_new_reflog_file(git_str_cstr(&log_path))) < 0))
                goto cleanup;
 
        if ((error = reflog_parse(log,
-               git_buf_cstr(&log_file), git_buf_len(&log_file))) < 0)
+               git_str_cstr(&log_file), git_str_len(&log_file))) < 0)
                goto cleanup;
 
        *out = log;
@@ -1801,14 +2069,14 @@ cleanup:
        git_reflog_free(log);
 
 success:
-       git_buf_dispose(&log_file);
-       git_buf_dispose(&log_path);
+       git_str_dispose(&log_file);
+       git_str_dispose(&log_path);
 
        return error;
 }
 
 static int serialize_reflog_entry(
-       git_buf *buf,
+       git_str *buf,
        const git_oid *oid_old,
        const git_oid *oid_new,
        const git_signature *committer,
@@ -1820,43 +2088,43 @@ static int serialize_reflog_entry(
        git_oid_tostr(raw_old, GIT_OID_HEXSZ+1, oid_old);
        git_oid_tostr(raw_new, GIT_OID_HEXSZ+1, oid_new);
 
-       git_buf_clear(buf);
+       git_str_clear(buf);
 
-       git_buf_puts(buf, raw_old);
-       git_buf_putc(buf, ' ');
-       git_buf_puts(buf, raw_new);
+       git_str_puts(buf, raw_old);
+       git_str_putc(buf, ' ');
+       git_str_puts(buf, raw_new);
 
        git_signature__writebuf(buf, " ", committer);
 
        /* drop trailing LF */
-       git_buf_rtrim(buf);
+       git_str_rtrim(buf);
 
        if (msg) {
                size_t i;
 
-               git_buf_putc(buf, '\t');
-               git_buf_puts(buf, msg);
+               git_str_putc(buf, '\t');
+               git_str_puts(buf, msg);
 
                for (i = 0; i < buf->size - 2; i++)
                        if (buf->ptr[i] == '\n')
                                buf->ptr[i] = ' ';
-               git_buf_rtrim(buf);
+               git_str_rtrim(buf);
        }
 
-       git_buf_putc(buf, '\n');
+       git_str_putc(buf, '\n');
 
-       return git_buf_oom(buf);
+       return git_str_oom(buf);
 }
 
 static int lock_reflog(git_filebuf *file, refdb_fs_backend *backend, const char *refname)
 {
        git_repository *repo;
-       git_buf log_path = GIT_BUF_INIT;
+       git_str log_path = GIT_STR_INIT;
        int error;
 
        repo = backend->repo;
 
-       if (!git_path_validate(backend->repo, refname, 0, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
+       if (!git_path_is_valid(backend->repo, refname, 0, GIT_FS_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
                git_error_set(GIT_ERROR_INVALID, "invalid reference name '%s'", refname);
                return GIT_EINVALIDSPEC;
        }
@@ -1864,17 +2132,17 @@ static int lock_reflog(git_filebuf *file, refdb_fs_backend *backend, const char
        if (reflog_path(&log_path, repo, refname) < 0)
                return -1;
 
-       if (!git_path_isfile(git_buf_cstr(&log_path))) {
+       if (!git_fs_path_isfile(git_str_cstr(&log_path))) {
                git_error_set(GIT_ERROR_INVALID,
                        "log file for reference '%s' doesn't exist", refname);
                error = -1;
                goto cleanup;
        }
 
-       error = git_filebuf_open(file, git_buf_cstr(&log_path), 0, GIT_REFLOG_FILE_MODE);
+       error = git_filebuf_open(file, git_str_cstr(&log_path), 0, GIT_REFLOG_FILE_MODE);
 
 cleanup:
-       git_buf_dispose(&log_path);
+       git_str_dispose(&log_path);
 
        return error;
 }
@@ -1885,7 +2153,7 @@ static int refdb_reflog_fs__write(git_refdb_backend *_backend, git_reflog *reflo
        unsigned int i;
        git_reflog_entry *entry;
        refdb_fs_backend *backend;
-       git_buf log = GIT_BUF_INIT;
+       git_str log = GIT_STR_INIT;
        git_filebuf fbuf = GIT_FILEBUF_INIT;
 
        GIT_ASSERT_ARG(_backend);
@@ -1911,7 +2179,7 @@ cleanup:
        git_filebuf_cleanup(&fbuf);
 
 success:
-       git_buf_dispose(&log);
+       git_str_dispose(&log);
 
        return error;
 }
@@ -1921,7 +2189,7 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co
 {
        int error, is_symbolic, open_flags;
        git_oid old_id = {{0}}, new_id = {{0}};
-       git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT, path = GIT_STR_INIT;
        git_repository *repo = backend->repo;
 
        is_symbolic = ref->type == GIT_REFERENCE_SYMBOLIC;
@@ -1965,7 +2233,7 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co
        if ((error = reflog_path(&path, repo, ref->name)) < 0)
                goto cleanup;
 
-       if (((error = git_futils_mkpath2file(git_buf_cstr(&path), 0777)) < 0) &&
+       if (((error = git_futils_mkpath2file(git_str_cstr(&path), 0777)) < 0) &&
            (error != GIT_EEXISTS)) {
                goto cleanup;
        }
@@ -1973,11 +2241,11 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co
        /* If the new branch matches part of the namespace of a previously deleted branch,
         * there maybe an obsolete/unused directory (or directory hierarchy) in the way.
         */
-       if (git_path_isdir(git_buf_cstr(&path))) {
-               if ((error = git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_SKIP_NONEMPTY)) < 0) {
+       if (git_fs_path_isdir(git_str_cstr(&path))) {
+               if ((error = git_futils_rmdir_r(git_str_cstr(&path), NULL, GIT_RMDIR_SKIP_NONEMPTY)) < 0) {
                        if (error == GIT_ENOTFOUND)
                                error = 0;
-               } else if (git_path_isdir(git_buf_cstr(&path))) {
+               } else if (git_fs_path_isdir(git_str_cstr(&path))) {
                        git_error_set(GIT_ERROR_REFERENCE, "cannot create reflog at '%s', there are reflogs beneath that folder",
                                ref->name);
                        error = GIT_EDIRECTORY;
@@ -1992,11 +2260,11 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co
        if (backend->fsync)
                open_flags |= O_FSYNC;
 
-       error = git_futils_writebuffer(&buf, git_buf_cstr(&path), open_flags, GIT_REFLOG_FILE_MODE);
+       error = git_futils_writebuffer(&buf, git_str_cstr(&path), open_flags, GIT_REFLOG_FILE_MODE);
 
 cleanup:
-       git_buf_dispose(&buf);
-       git_buf_dispose(&path);
+       git_str_dispose(&buf);
+       git_str_dispose(&path);
 
        return error;
 }
@@ -2004,10 +2272,10 @@ cleanup:
 static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_name, const char *new_name)
 {
        int error = 0, fd;
-       git_buf old_path = GIT_BUF_INIT;
-       git_buf new_path = GIT_BUF_INIT;
-       git_buf temp_path = GIT_BUF_INIT;
-       git_buf normalized = GIT_BUF_INIT;
+       git_str old_path = GIT_STR_INIT;
+       git_str new_path = GIT_STR_INIT;
+       git_str temp_path = GIT_STR_INIT;
+       git_str normalized = GIT_STR_INIT;
        git_repository *repo;
        refdb_fs_backend *backend;
 
@@ -2022,16 +2290,16 @@ static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_
                &normalized, new_name, GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL)) < 0)
                        return error;
 
-       if (git_buf_joinpath(&temp_path, repo->gitdir, GIT_REFLOG_DIR) < 0)
+       if (git_str_joinpath(&temp_path, repo->gitdir, GIT_REFLOG_DIR) < 0)
                return -1;
 
-       if ((error = loose_path(&old_path, git_buf_cstr(&temp_path), old_name)) < 0)
+       if ((error = loose_path(&old_path, git_str_cstr(&temp_path), old_name)) < 0)
                return error;
 
-       if ((error = loose_path(&new_path, git_buf_cstr(&temp_path), git_buf_cstr(&normalized))) < 0)
+       if ((error = loose_path(&new_path, git_str_cstr(&temp_path), git_str_cstr(&normalized))) < 0)
                return error;
 
-       if (!git_path_exists(git_buf_cstr(&old_path))) {
+       if (!git_fs_path_exists(git_str_cstr(&old_path))) {
                error = GIT_ENOTFOUND;
                goto cleanup;
        }
@@ -2043,43 +2311,43 @@ static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_
         *  - a/b -> a/b/c
         *  - a/b/c/d -> a/b/c
         */
-       if ((error = loose_path(&temp_path, git_buf_cstr(&temp_path), "temp_reflog")) < 0)
+       if ((error = loose_path(&temp_path, git_str_cstr(&temp_path), "temp_reflog")) < 0)
                return error;
 
-       if ((fd = git_futils_mktmp(&temp_path, git_buf_cstr(&temp_path), GIT_REFLOG_FILE_MODE)) < 0) {
+       if ((fd = git_futils_mktmp(&temp_path, git_str_cstr(&temp_path), GIT_REFLOG_FILE_MODE)) < 0) {
                error = -1;
                goto cleanup;
        }
 
        p_close(fd);
 
-       if (p_rename(git_buf_cstr(&old_path), git_buf_cstr(&temp_path)) < 0) {
+       if (p_rename(git_str_cstr(&old_path), git_str_cstr(&temp_path)) < 0) {
                git_error_set(GIT_ERROR_OS, "failed to rename reflog for %s", new_name);
                error = -1;
                goto cleanup;
        }
 
-       if (git_path_isdir(git_buf_cstr(&new_path)) &&
-               (git_futils_rmdir_r(git_buf_cstr(&new_path), NULL, GIT_RMDIR_SKIP_NONEMPTY) < 0)) {
+       if (git_fs_path_isdir(git_str_cstr(&new_path)) &&
+               (git_futils_rmdir_r(git_str_cstr(&new_path), NULL, GIT_RMDIR_SKIP_NONEMPTY) < 0)) {
                error = -1;
                goto cleanup;
        }
 
-       if (git_futils_mkpath2file(git_buf_cstr(&new_path), GIT_REFLOG_DIR_MODE) < 0) {
+       if (git_futils_mkpath2file(git_str_cstr(&new_path), GIT_REFLOG_DIR_MODE) < 0) {
                error = -1;
                goto cleanup;
        }
 
-       if (p_rename(git_buf_cstr(&temp_path), git_buf_cstr(&new_path)) < 0) {
+       if (p_rename(git_str_cstr(&temp_path), git_str_cstr(&new_path)) < 0) {
                git_error_set(GIT_ERROR_OS, "failed to rename reflog for %s", new_name);
                error = -1;
        }
 
 cleanup:
-       git_buf_dispose(&temp_path);
-       git_buf_dispose(&old_path);
-       git_buf_dispose(&new_path);
-       git_buf_dispose(&normalized);
+       git_str_dispose(&temp_path);
+       git_str_dispose(&old_path);
+       git_str_dispose(&new_path);
+       git_str_dispose(&normalized);
 
        return error;
 }
@@ -2087,7 +2355,7 @@ cleanup:
 static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name)
 {
        refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(_backend);
@@ -2096,7 +2364,7 @@ static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name
        if ((error = reflog_path(&path, backend->repo, name)) < 0)
                goto out;
 
-       if (!git_path_exists(path.ptr))
+       if (!git_fs_path_exists(path.ptr))
                goto out;
 
        if ((error = p_unlink(path.ptr)) < 0)
@@ -2105,7 +2373,7 @@ static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name
        error = refdb_fs_backend__prune_refs(backend, name, GIT_REFLOG_DIR);
 
 out:
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return error;
 }
@@ -2115,11 +2383,16 @@ int git_refdb_backend_fs(
        git_repository *repository)
 {
        int t = 0;
-       git_buf gitpath = GIT_BUF_INIT;
+       git_str gitpath = GIT_STR_INIT;
        refdb_fs_backend *backend;
 
        backend = git__calloc(1, sizeof(refdb_fs_backend));
        GIT_ERROR_CHECK_ALLOC(backend);
+       if (git_mutex_init(&backend->prlock) < 0) {
+               git__free(backend);
+               return -1;
+       }
+
 
        if (git_refdb_init_backend(&backend->parent, GIT_REFDB_BACKEND_VERSION) < 0)
                goto fail;
@@ -2140,21 +2413,21 @@ int git_refdb_backend_fs(
                        goto fail;
        }
 
-       if (git_buf_joinpath(&gitpath, backend->commonpath, GIT_PACKEDREFS_FILE) < 0 ||
+       if (git_str_joinpath(&gitpath, backend->commonpath, GIT_PACKEDREFS_FILE) < 0 ||
                git_sortedcache_new(
                        &backend->refcache, offsetof(struct packref, name),
-                       NULL, NULL, packref_cmp, git_buf_cstr(&gitpath)) < 0)
+                       NULL, NULL, packref_cmp, git_str_cstr(&gitpath)) < 0)
                goto fail;
 
-       git_buf_dispose(&gitpath);
+       git_str_dispose(&gitpath);
 
        if (!git_repository__configmap_lookup(&t, backend->repo, GIT_CONFIGMAP_IGNORECASE) && t) {
                backend->iterator_flags |= GIT_ITERATOR_IGNORE_CASE;
-               backend->direach_flags  |= GIT_PATH_DIR_IGNORE_CASE;
+               backend->direach_flags  |= GIT_FS_PATH_DIR_IGNORE_CASE;
        }
        if (!git_repository__configmap_lookup(&t, backend->repo, GIT_CONFIGMAP_PRECOMPOSE) && t) {
                backend->iterator_flags |= GIT_ITERATOR_PRECOMPOSE_UNICODE;
-               backend->direach_flags  |= GIT_PATH_DIR_PRECOMPOSE_UNICODE;
+               backend->direach_flags  |= GIT_FS_PATH_DIR_PRECOMPOSE_UNICODE;
        }
        if ((!git_repository__configmap_lookup(&t, backend->repo, GIT_CONFIGMAP_FSYNCOBJECTFILES) && t) ||
                git_repository__fsync_gitdir)
@@ -2182,7 +2455,8 @@ int git_refdb_backend_fs(
        return 0;
 
 fail:
-       git_buf_dispose(&gitpath);
+       git_mutex_free(&backend->prlock);
+       git_str_dispose(&gitpath);
        git__free(backend->gitpath);
        git__free(backend->commonpath);
        git__free(backend);
index 8acfa84a5a66ba116bc6b20138015eda89748aed..5c875b95b231d0fcff95102c752af4d6a3502c40 100644 (file)
@@ -247,7 +247,7 @@ int git_reference_dwim(git_reference **out, git_repository *repo, const char *re
        int error = 0, i, valid;
        bool fallbackmode = true, foundvalid = false;
        git_reference *ref;
-       git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT;
+       git_str refnamebuf = GIT_STR_INIT, name = GIT_STR_INIT;
 
        static const char *formatters[] = {
                "%s",
@@ -260,18 +260,18 @@ int git_reference_dwim(git_reference **out, git_repository *repo, const char *re
        };
 
        if (*refname)
-               git_buf_puts(&name, refname);
+               git_str_puts(&name, refname);
        else {
-               git_buf_puts(&name, GIT_HEAD_FILE);
+               git_str_puts(&name, GIT_HEAD_FILE);
                fallbackmode = false;
        }
 
        for (i = 0; formatters[i] && (fallbackmode || i == 0); i++) {
 
-               git_buf_clear(&refnamebuf);
+               git_str_clear(&refnamebuf);
 
-               if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0 ||
-                   (error = git_reference_name_is_valid(&valid, git_buf_cstr(&refnamebuf))) < 0)
+               if ((error = git_str_printf(&refnamebuf, formatters[i], git_str_cstr(&name))) < 0 ||
+                   (error = git_reference_name_is_valid(&valid, git_str_cstr(&refnamebuf))) < 0)
                        goto cleanup;
 
                if (!valid) {
@@ -280,7 +280,7 @@ int git_reference_dwim(git_reference **out, git_repository *repo, const char *re
                }
                foundvalid = true;
 
-               error = git_reference_lookup_resolved(&ref, repo, git_buf_cstr(&refnamebuf), -1);
+               error = git_reference_lookup_resolved(&ref, repo, git_str_cstr(&refnamebuf), -1);
 
                if (!error) {
                        *out = ref;
@@ -296,14 +296,14 @@ cleanup:
        if (error && !foundvalid) {
                /* never found a valid reference name */
                git_error_set(GIT_ERROR_REFERENCE,
-                       "could not use '%s' as valid reference name", git_buf_cstr(&name));
+                       "could not use '%s' as valid reference name", git_str_cstr(&name));
        }
 
        if (error == GIT_ENOTFOUND)
                git_error_set(GIT_ERROR_REFERENCE, "no reference found for shorthand '%s'", refname);
 
-       git_buf_dispose(&name);
-       git_buf_dispose(&refnamebuf);
+       git_str_dispose(&name);
+       git_str_dispose(&refnamebuf);
        return error;
 }
 
@@ -891,7 +891,7 @@ static bool is_all_caps_and_underscore(const char *name, size_t len)
 
 /* Inspired from https://github.com/git/git/blob/f06d47e7e0d9db709ee204ed13a8a7486149f494/refs.c#L36-100 */
 int git_reference__normalize_name(
-       git_buf *buf,
+       git_str *buf,
        const char *name,
        unsigned int flags)
 {
@@ -902,7 +902,7 @@ int git_reference__normalize_name(
        bool validate = (flags & GIT_REFERENCE_FORMAT__VALIDATION_DISABLE) == 0;
 
 #ifdef GIT_USE_ICONV
-       git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
+       git_fs_path_iconv_t ic = GIT_PATH_ICONV_INIT;
 #endif
 
        GIT_ASSERT_ARG(name);
@@ -914,22 +914,22 @@ int git_reference__normalize_name(
                goto cleanup;
 
        if (normalize)
-               git_buf_clear(buf);
+               git_str_clear(buf);
 
 #ifdef GIT_USE_ICONV
        if ((flags & GIT_REFERENCE_FORMAT__PRECOMPOSE_UNICODE) != 0) {
                size_t namelen = strlen(current);
-               if ((error = git_path_iconv_init_precompose(&ic)) < 0 ||
-                       (error = git_path_iconv(&ic, &current, &namelen)) < 0)
+               if ((error = git_fs_path_iconv_init_precompose(&ic)) < 0 ||
+                       (error = git_fs_path_iconv(&ic, &current, &namelen)) < 0)
                        goto cleanup;
                error = GIT_EINVALIDSPEC;
        }
 #endif
 
        if (!validate) {
-               git_buf_sets(buf, current);
+               git_str_sets(buf, current);
 
-               error = git_buf_oom(buf) ? -1 : 0;
+               error = git_str_oom(buf) ? -1 : 0;
                goto cleanup;
        }
 
@@ -949,13 +949,13 @@ int git_reference__normalize_name(
                                process_flags &= ~GIT_REFERENCE_FORMAT_REFSPEC_PATTERN;
 
                        if (normalize) {
-                               size_t cur_len = git_buf_len(buf);
+                               size_t cur_len = git_str_len(buf);
 
-                               git_buf_joinpath(buf, git_buf_cstr(buf), current);
-                               git_buf_truncate(buf,
+                               git_str_joinpath(buf, git_str_cstr(buf), current);
+                               git_str_truncate(buf,
                                        cur_len + segment_len + (segments_count ? 1 : 0));
 
-                               if (git_buf_oom(buf)) {
+                               if (git_str_oom(buf)) {
                                        error = -1;
                                        goto cleanup;
                                }
@@ -1008,10 +1008,10 @@ cleanup:
                        "the given reference name '%s' is not valid", name);
 
        if (error && normalize)
-               git_buf_dispose(buf);
+               git_str_dispose(buf);
 
 #ifdef GIT_USE_ICONV
-       git_path_iconv_clear(&ic);
+       git_fs_path_iconv_clear(&ic);
 #endif
 
        return error;
@@ -1023,13 +1023,13 @@ int git_reference_normalize_name(
        const char *name,
        unsigned int flags)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        int error;
 
        if ((error = git_reference__normalize_name(&buf, name, flags)) < 0)
                goto cleanup;
 
-       if (git_buf_len(&buf) > buffer_size - 1) {
+       if (git_str_len(&buf) > buffer_size - 1) {
                git_error_set(
                GIT_ERROR_REFERENCE,
                "the provided buffer is too short to hold the normalization of '%s'", name);
@@ -1037,13 +1037,13 @@ int git_reference_normalize_name(
                goto cleanup;
        }
 
-       if ((error = git_buf_copy_cstr(buffer_out, buffer_size, &buf)) < 0)
+       if ((error = git_str_copy_cstr(buffer_out, buffer_size, &buf)) < 0)
                goto cleanup;
 
        error = 0;
 
 cleanup:
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
@@ -1143,12 +1143,12 @@ int git_reference__update_for_commit(
 {
        git_reference *ref_new = NULL;
        git_commit *commit = NULL;
-       git_buf reflog_msg = GIT_BUF_INIT;
+       git_str reflog_msg = GIT_STR_INIT;
        const git_signature *who;
        int error;
 
        if ((error = git_commit_lookup(&commit, repo, id)) < 0 ||
-               (error = git_buf_printf(&reflog_msg, "%s%s: %s",
+               (error = git_str_printf(&reflog_msg, "%s%s: %s",
                        operation ? operation : "commit",
                        commit_type(commit),
                        git_commit_summary(commit))) < 0)
@@ -1161,15 +1161,15 @@ int git_reference__update_for_commit(
                        return error;
 
                error = reference__create(&ref_new, repo, ref->name, id, NULL, 1, who,
-                                         git_buf_cstr(&reflog_msg), &ref->target.oid, NULL);
+                                         git_str_cstr(&reflog_msg), &ref->target.oid, NULL);
        }
        else
                error = git_reference__update_terminal(
-                       repo, ref_name, id, who, git_buf_cstr(&reflog_msg));
+                       repo, ref_name, id, who, git_str_cstr(&reflog_msg));
 
 done:
        git_reference_free(ref_new);
-       git_buf_dispose(&reflog_msg);
+       git_str_dispose(&reflog_msg);
        git_commit_free(commit);
        return error;
 }
index 376a512f85dfcfb71d670bf57fb597a8a8b0ad50..cb888bf8f49ff2b9b2b5f3f5d76c6999addc1613 100644 (file)
@@ -13,7 +13,7 @@
 #include "git2/refs.h"
 #include "git2/refdb.h"
 #include "strmap.h"
-#include "buffer.h"
+#include "str.h"
 #include "oid.h"
 
 extern bool git_reference__enable_symbolic_ref_target_validation;
@@ -83,7 +83,7 @@ struct git_reference {
  */
 git_reference *git_reference__realloc(git_reference **ptr_to_ref, const char *name);
 
-int git_reference__normalize_name(git_buf *buf, const char *name, unsigned int flags);
+int git_reference__normalize_name(git_str *buf, const char *name, unsigned int flags);
 int git_reference__update_terminal(git_repository *repo, const char *ref_name, const git_oid *oid, const git_signature *sig, const char *log_message);
 int git_reference__name_is_valid(int *valid, const char *name, unsigned int flags);
 int git_reference__is_branch(const char *ref_name);
index c72721a437300f64709e102a374730ba407ddf9f..f0a0c2bfb3eaeefe4060bae35086c2655abda929 100644 (file)
@@ -7,8 +7,7 @@
 
 #include "refspec.h"
 
-#include "git2/errors.h"
-
+#include "buf.h"
 #include "refs.h"
 #include "util.h"
 #include "vector.h"
@@ -243,16 +242,12 @@ int git_refspec_dst_matches(const git_refspec *refspec, const char *refname)
 }
 
 static int refspec_transform(
-       git_buf *out, const char *from, const char *to, const char *name)
+       git_str *out, const char *from, const char *to, const char *name)
 {
        const char *from_star, *to_star;
        size_t replacement_len, star_offset;
-       int error;
-
-       if ((error = git_buf_sanitize(out)) < 0)
-               return error;
 
-       git_buf_clear(out);
+       git_str_clear(out);
 
        /*
         * There are two parts to each side of a refspec, the bit
@@ -269,72 +264,72 @@ static int refspec_transform(
        star_offset = from_star - from;
 
        /* the first half is copied over */
-       git_buf_put(out, to, to_star - to);
+       git_str_put(out, to, to_star - to);
 
        /*
         * Copy over the name, but exclude the trailing part in "from" starting
         * after the glob
         */
        replacement_len = strlen(name + star_offset) - strlen(from_star + 1);
-       git_buf_put(out, name + star_offset, replacement_len);
+       git_str_put(out, name + star_offset, replacement_len);
 
-       return git_buf_puts(out, to_star + 1);
+       return git_str_puts(out, to_star + 1);
 }
 
 int git_refspec_transform(git_buf *out, const git_refspec *spec, const char *name)
 {
-       int error;
+       GIT_BUF_WRAP_PRIVATE(out, git_refspec__transform, spec, name);
+}
 
+int git_refspec__transform(git_str *out, const git_refspec *spec, const char *name)
+{
        GIT_ASSERT_ARG(out);
        GIT_ASSERT_ARG(spec);
        GIT_ASSERT_ARG(name);
 
-       if ((error = git_buf_sanitize(out)) < 0)
-               return error;
-
        if (!git_refspec_src_matches(spec, name)) {
                git_error_set(GIT_ERROR_INVALID, "ref '%s' doesn't match the source", name);
                return -1;
        }
 
        if (!spec->pattern)
-               return git_buf_puts(out, spec->dst ? spec->dst : "");
+               return git_str_puts(out, spec->dst ? spec->dst : "");
 
        return refspec_transform(out, spec->src, spec->dst, name);
 }
 
 int git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name)
 {
-       int error;
+       GIT_BUF_WRAP_PRIVATE(out, git_refspec__rtransform, spec, name);
+}
 
+int git_refspec__rtransform(git_str *out, const git_refspec *spec, const char *name)
+{
        GIT_ASSERT_ARG(out);
        GIT_ASSERT_ARG(spec);
        GIT_ASSERT_ARG(name);
 
-       if ((error = git_buf_sanitize(out)) < 0)
-               return error;
-
        if (!git_refspec_dst_matches(spec, name)) {
                git_error_set(GIT_ERROR_INVALID, "ref '%s' doesn't match the destination", name);
                return -1;
        }
 
        if (!spec->pattern)
-               return git_buf_puts(out, spec->src);
+               return git_str_puts(out, spec->src);
 
        return refspec_transform(out, spec->dst, spec->src, name);
 }
 
-int git_refspec__serialize(git_buf *out, const git_refspec *refspec)
+int git_refspec__serialize(git_str *out, const git_refspec *refspec)
 {
        if (refspec->force)
-               git_buf_putc(out, '+');
+               git_str_putc(out, '+');
 
-       git_buf_printf(out, "%s:%s",
+       git_str_printf(out, "%s:%s",
                refspec->src != NULL ? refspec->src : "",
                refspec->dst != NULL ? refspec->dst : "");
 
-       return git_buf_oom(out) == false;
+       return git_str_oom(out) == false;
 }
 
 int git_refspec_is_wildcard(const git_refspec *spec)
@@ -354,7 +349,7 @@ git_direction git_refspec_direction(const git_refspec *spec)
 
 int git_refspec__dwim_one(git_vector *out, git_refspec *spec, git_vector *refs)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        size_t j, pos;
        git_remote_head key;
        git_refspec *cur;
@@ -382,14 +377,14 @@ int git_refspec__dwim_one(git_vector *out, git_refspec *spec, git_vector *refs)
        /* shorthand on the lhs */
        if (git__prefixcmp(spec->src, GIT_REFS_DIR)) {
                for (j = 0; formatters[j]; j++) {
-                       git_buf_clear(&buf);
-                       git_buf_printf(&buf, formatters[j], spec->src);
-                       GIT_ERROR_CHECK_ALLOC_BUF(&buf);
+                       git_str_clear(&buf);
+                       git_str_printf(&buf, formatters[j], spec->src);
+                       GIT_ERROR_CHECK_ALLOC_STR(&buf);
 
-                       key.name = (char *) git_buf_cstr(&buf);
+                       key.name = (char *) git_str_cstr(&buf);
                        if (!git_vector_search(&pos, refs, &key)) {
                                /* we found something to match the shorthand, set src to that */
-                               cur->src = git_buf_detach(&buf);
+                               cur->src = git_str_detach(&buf);
                        }
                }
        }
@@ -403,18 +398,18 @@ int git_refspec__dwim_one(git_vector *out, git_refspec *spec, git_vector *refs)
        if (spec->dst && git__prefixcmp(spec->dst, GIT_REFS_DIR)) {
                /* if it starts with "remotes" then we just prepend "refs/" */
                if (!git__prefixcmp(spec->dst, "remotes/")) {
-                       git_buf_puts(&buf, GIT_REFS_DIR);
+                       git_str_puts(&buf, GIT_REFS_DIR);
                } else {
-                       git_buf_puts(&buf, GIT_REFS_HEADS_DIR);
+                       git_str_puts(&buf, GIT_REFS_HEADS_DIR);
                }
 
-               git_buf_puts(&buf, spec->dst);
-               GIT_ERROR_CHECK_ALLOC_BUF(&buf);
+               git_str_puts(&buf, spec->dst);
+               GIT_ERROR_CHECK_ALLOC_STR(&buf);
 
-               cur->dst = git_buf_detach(&buf);
+               cur->dst = git_str_detach(&buf);
        }
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        if (cur->dst == NULL && spec->dst != NULL) {
                cur->dst = git__strdup(spec->dst);
index 2b4111f0419f7736b2d20fba63c27d5b4e7542c2..bf4f7fcfbbcf2c1c2cb1cef28fe846a6a9ffef8e 100644 (file)
@@ -10,7 +10,7 @@
 #include "common.h"
 
 #include "git2/refspec.h"
-#include "buffer.h"
+#include "str.h"
 #include "vector.h"
 
 struct git_refspec {
@@ -25,6 +25,9 @@ struct git_refspec {
 
 #define GIT_REFSPEC_TAGS "refs/tags/*:refs/tags/*"
 
+int git_refspec__transform(git_str *out, const git_refspec *spec, const char *name);
+int git_refspec__rtransform(git_str *out, const git_refspec *spec, const char *name);
+
 int git_refspec__parse(
        struct git_refspec *refspec,
        const char *str,
@@ -32,7 +35,7 @@ int git_refspec__parse(
 
 void git_refspec__dispose(git_refspec *refspec);
 
-int git_refspec__serialize(git_buf *out, const git_refspec *refspec);
+int git_refspec__serialize(git_str *out, const git_refspec *refspec);
 
 /**
  * Determines if a refspec is a wildcard refspec.
index c1b9ef4cdb6acf0d93e45da9194354a2cdd3517f..2569dea0a9d04d75b3018b33ce04affa578cdd3d 100644 (file)
@@ -45,7 +45,7 @@ int git_regexp_search(const git_regexp *r, const char *string, size_t nmatches,
        int error;
        size_t i;
 
-       /* The ovec array always needs to be a mutiple of three */
+       /* The ovec array always needs to be a multiple of three */
        if (nmatches <= ARRAY_SIZE(static_ovec) / 3)
                ovec = static_ovec;
        else
index 56d7e42db0b5272f0c5fe766a4158be8e092cd4b..1a79faaab451b870234bac0dc68bb9dd4be0b734 100644 (file)
@@ -7,11 +7,8 @@
 
 #include "remote.h"
 
-#include "git2/config.h"
-#include "git2/types.h"
-#include "git2/oid.h"
-#include "git2/net.h"
-
+#include "buf.h"
+#include "branch.h"
 #include "config.h"
 #include "repository.h"
 #include "fetch.h"
 #include "refspec.h"
 #include "fetchhead.h"
 #include "push.h"
+#include "proxy.h"
+
+#include "git2/config.h"
+#include "git2/types.h"
+#include "git2/oid.h"
+#include "git2/net.h"
 
 #define CONFIG_URL_FMT "remote.%s.url"
 #define CONFIG_PUSHURL_FMT "remote.%s.pushurl"
@@ -28,7 +31,7 @@
 
 static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs);
 static int lookup_remote_prune_config(git_remote *remote, git_config *config, const char *name);
-char *apply_insteadof(git_config *config, const char *url, int direction);
+static int apply_insteadof(char **out, git_config *config, const char *url, int direction, bool use_default_if_empty);
 
 static int add_refspec_to(git_vector *vector, const char *string, bool is_fetch)
 {
@@ -60,14 +63,14 @@ static int add_refspec(git_remote *remote, const char *string, bool is_fetch)
 static int download_tags_value(git_remote *remote, git_config *cfg)
 {
        git_config_entry *ce;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        int error;
 
-       if (git_buf_printf(&buf, "remote.%s.tagopt", remote->name) < 0)
+       if (git_str_printf(&buf, "remote.%s.tagopt", remote->name) < 0)
                return -1;
 
-       error = git_config__lookup_entry(&ce, cfg, git_buf_cstr(&buf), false);
-       git_buf_dispose(&buf);
+       error = git_config__lookup_entry(&ce, cfg, git_str_cstr(&buf), false);
+       git_str_dispose(&buf);
 
        if (!error && ce && ce->value) {
                if (!strcmp(ce->value, "--no-tags"))
@@ -99,7 +102,7 @@ static int ensure_remote_name_is_valid(const char *name)
 static int write_add_refspec(git_repository *repo, const char *name, const char *refspec, bool fetch)
 {
        git_config *cfg;
-       git_buf var = GIT_BUF_INIT;
+       git_str var = GIT_STR_INIT;
        git_refspec spec;
        const char *fmt;
        int error;
@@ -117,7 +120,7 @@ static int write_add_refspec(git_repository *repo, const char *name, const char
 
        git_refspec__dispose(&spec);
 
-       if ((error = git_buf_printf(&var, fmt, name)) < 0)
+       if ((error = git_str_printf(&var, fmt, name)) < 0)
                return error;
 
        /*
@@ -130,11 +133,11 @@ static int write_add_refspec(git_repository *repo, const char *name, const char
        }
 
 cleanup:
-       git_buf_dispose(&var);
+       git_str_dispose(&var);
        return 0;
 }
 
-static int canonicalize_url(git_buf *out, const char *in)
+static int canonicalize_url(git_str *out, const char *in)
 {
        if (in == NULL || strlen(in) == 0) {
                git_error_set(GIT_ERROR_INVALID, "cannot set empty URL");
@@ -149,18 +152,18 @@ static int canonicalize_url(git_buf *out, const char *in)
                (git__isalpha(in[2]) || git__isdigit(in[2]))) {
                const char *c;
                for (c = in; *c; c++)
-                       git_buf_putc(out, *c == '\\' ? '/' : *c);
+                       git_str_putc(out, *c == '\\' ? '/' : *c);
 
-               return git_buf_oom(out) ? -1 : 0;
+               return git_str_oom(out) ? -1 : 0;
        }
 #endif
 
-       return git_buf_puts(out, in);
+       return git_str_puts(out, in);
 }
 
-static int default_fetchspec_for_name(git_buf *buf, const char *name)
+static int default_fetchspec_for_name(git_str *buf, const char *name)
 {
-       if (git_buf_printf(buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0)
+       if (git_str_printf(buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0)
                return -1;
 
        return 0;
@@ -204,9 +207,9 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
 {
        git_remote *remote = NULL;
        git_config *config_ro = NULL, *config_rw;
-       git_buf canonical_url = GIT_BUF_INIT;
-       git_buf var = GIT_BUF_INIT;
-       git_buf specbuf = GIT_BUF_INIT;
+       git_str canonical_url = GIT_STR_INIT;
+       git_str var = GIT_STR_INIT;
+       git_str specbuf = GIT_STR_INIT;
        const git_remote_create_options dummy_opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
        int error = -1;
 
@@ -243,18 +246,20 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
                goto on_error;
 
        if (opts->repository && !(opts->flags & GIT_REMOTE_CREATE_SKIP_INSTEADOF)) {
-               remote->url = apply_insteadof(config_ro, canonical_url.ptr, GIT_DIRECTION_FETCH);
+               if ((error = apply_insteadof(&remote->url, config_ro, canonical_url.ptr, GIT_DIRECTION_FETCH, true)) < 0 ||
+                   (error = apply_insteadof(&remote->pushurl, config_ro, canonical_url.ptr, GIT_DIRECTION_PUSH, false)) < 0)
+                       goto on_error;
        } else {
                remote->url = git__strdup(canonical_url.ptr);
+               GIT_ERROR_CHECK_ALLOC(remote->url);
        }
-       GIT_ERROR_CHECK_ALLOC(remote->url);
 
        if (opts->name != NULL) {
                remote->name = git__strdup(opts->name);
                GIT_ERROR_CHECK_ALLOC(remote->name);
 
                if (opts->repository &&
-                   ((error = git_buf_printf(&var, CONFIG_URL_FMT, opts->name)) < 0 ||
+                   ((error = git_str_printf(&var, CONFIG_URL_FMT, opts->name)) < 0 ||
                    (error = git_repository_config__weakptr(&config_rw, opts->repository)) < 0 ||
                    (error = git_config_set_string(config_rw, var.ptr, canonical_url.ptr)) < 0))
                        goto on_error;
@@ -269,7 +274,7 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
                        if ((error = default_fetchspec_for_name(&specbuf, opts->name)) < 0)
                                goto on_error;
 
-                       fetch = git_buf_cstr(&specbuf);
+                       fetch = git_str_cstr(&specbuf);
                }
 
                if ((error = add_refspec(remote, fetch, true)) < 0)
@@ -293,7 +298,7 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
                remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO;
 
 
-       git_buf_dispose(&var);
+       git_str_dispose(&var);
 
        *out = remote;
        error = 0;
@@ -303,15 +308,15 @@ on_error:
                git_remote_free(remote);
 
        git_config_free(config_ro);
-       git_buf_dispose(&specbuf);
-       git_buf_dispose(&canonical_url);
-       git_buf_dispose(&var);
+       git_str_dispose(&specbuf);
+       git_str_dispose(&canonical_url);
+       git_str_dispose(&var);
        return error;
 }
 
 int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        int error;
        git_remote_create_options opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
 
@@ -322,14 +327,14 @@ int git_remote_create(git_remote **out, git_repository *repo, const char *name,
        if (canonicalize_url(&buf, url) < 0)
                return GIT_ERROR;
 
-       git_buf_clear(&buf);
+       git_str_clear(&buf);
 
        opts.repository = repo;
        opts.name = name;
 
        error = git_remote_create_with_opts(out, url, &opts);
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        return error;
 }
@@ -425,13 +430,13 @@ static int refspec_cb(const git_config_entry *entry, void *payload)
 }
 
 static int get_optional_config(
-       bool *found, git_config *config, git_buf *buf,
+       bool *found, git_config *config, git_str *buf,
        git_config_foreach_cb cb, void *payload)
 {
        int error = 0;
-       const char *key = git_buf_cstr(buf);
+       const char *key = git_str_cstr(buf);
 
-       if (git_buf_oom(buf))
+       if (git_str_oom(buf))
                return -1;
 
        if (cb != NULL)
@@ -453,7 +458,7 @@ static int get_optional_config(
 int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
 {
        git_remote *remote = NULL;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        const char *val;
        int error = 0;
        git_config *config;
@@ -484,7 +489,7 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
                goto cleanup;
        }
 
-       if ((error = git_buf_printf(&buf, "remote.%s.url", name)) < 0)
+       if ((error = git_str_printf(&buf, "remote.%s.url", name)) < 0)
                goto cleanup;
 
        if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
@@ -496,13 +501,14 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
        remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO;
 
        if (found && strlen(val) > 0) {
-               remote->url = apply_insteadof(config, val, GIT_DIRECTION_FETCH);
-               GIT_ERROR_CHECK_ALLOC(remote->url);
+               if ((error = apply_insteadof(&remote->url, config, val, GIT_DIRECTION_FETCH, true)) < 0 ||
+                   (error = apply_insteadof(&remote->pushurl, config, val, GIT_DIRECTION_PUSH, false)) < 0)
+                       goto cleanup;
        }
 
        val = NULL;
-       git_buf_clear(&buf);
-       git_buf_printf(&buf, "remote.%s.pushurl", name);
+       git_str_clear(&buf);
+       git_str_printf(&buf, "remote.%s.pushurl", name);
 
        if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
                goto cleanup;
@@ -516,22 +522,25 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
        }
 
        if (found && strlen(val) > 0) {
-               remote->pushurl = apply_insteadof(config, val, GIT_DIRECTION_PUSH);
-               GIT_ERROR_CHECK_ALLOC(remote->pushurl);
+               if (remote->pushurl)
+                       git__free(remote->pushurl);
+
+               if ((error = apply_insteadof(&remote->pushurl, config, val, GIT_DIRECTION_FETCH, true)) < 0)
+                       goto cleanup;
        }
 
        data.remote = remote;
        data.fetch = true;
 
-       git_buf_clear(&buf);
-       git_buf_printf(&buf, "remote.%s.fetch", name);
+       git_str_clear(&buf);
+       git_str_printf(&buf, "remote.%s.fetch", name);
 
        if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
                goto cleanup;
 
        data.fetch = false;
-       git_buf_clear(&buf);
-       git_buf_printf(&buf, "remote.%s.push", name);
+       git_str_clear(&buf);
+       git_str_printf(&buf, "remote.%s.push", name);
 
        if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
                goto cleanup;
@@ -550,7 +559,7 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
 
 cleanup:
        git_config_free(config);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        if (error < 0)
                git_remote_free(remote);
@@ -560,12 +569,12 @@ cleanup:
 
 static int lookup_remote_prune_config(git_remote *remote, git_config *config, const char *name)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        int error = 0;
 
-       git_buf_printf(&buf, "remote.%s.prune", name);
+       git_str_printf(&buf, "remote.%s.prune", name);
 
-       if ((error = git_config_get_bool(&remote->prune_refs, config, git_buf_cstr(&buf))) < 0) {
+       if ((error = git_config_get_bool(&remote->prune_refs, config, git_str_cstr(&buf))) < 0) {
                if (error == GIT_ENOTFOUND) {
                        git_error_clear();
 
@@ -578,7 +587,7 @@ static int lookup_remote_prune_config(git_remote *remote, git_config *config, co
                }
        }
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
@@ -619,7 +628,7 @@ int git_remote_set_instance_url(git_remote *remote, const char *url)
 static int set_url(git_repository *repo, const char *remote, const char *pattern, const char *url)
 {
        git_config *cfg;
-       git_buf buf = GIT_BUF_INIT, canonical_url = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT, canonical_url = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(repo);
@@ -631,7 +640,7 @@ static int set_url(git_repository *repo, const char *remote, const char *pattern
        if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
                return error;
 
-       if ((error = git_buf_printf(&buf, pattern, remote)) < 0)
+       if ((error = git_str_printf(&buf, pattern, remote)) < 0)
                return error;
 
        if (url) {
@@ -644,8 +653,8 @@ static int set_url(git_repository *repo, const char *remote, const char *pattern
        }
 
 cleanup:
-       git_buf_dispose(&canonical_url);
-       git_buf_dispose(&buf);
+       git_str_dispose(&canonical_url);
+       git_str_dispose(&buf);
 
        return error;
 }
@@ -683,7 +692,7 @@ int git_remote_set_pushurl(git_repository *repo, const char *remote, const char
 }
 
 static int resolve_url(
-       git_buf *resolved_url,
+       git_str *resolved_url,
        const char *url,
        int direction,
        const git_remote_callbacks *callbacks)
@@ -692,27 +701,28 @@ static int resolve_url(
        GIT_UNUSED(direction);
        GIT_UNUSED(callbacks);
 #else
-       int status, error;
+       git_buf buf = GIT_BUF_INIT;
+       int error;
 
        if (callbacks && callbacks->resolve_url) {
-               git_buf_clear(resolved_url);
-               status = callbacks->resolve_url(resolved_url, url, direction, callbacks->payload);
-               if (status != GIT_PASSTHROUGH) {
-                       git_error_set_after_callback_function(status, "git_resolve_url_cb");
+               error = callbacks->resolve_url(&buf, url, direction, callbacks->payload);
 
-                       if ((error = git_buf_sanitize(resolved_url)) < 0)
-                               return error;
+               if (error != GIT_PASSTHROUGH) {
+                       git_error_set_after_callback_function(error, "git_resolve_url_cb");
 
-                       return status;
+                       git_str_set(resolved_url, buf.ptr, buf.size);
+                       git_buf_dispose(&buf);
+
+                       return error;
                }
        }
 #endif
 
-       return git_buf_sets(resolved_url, url);
+       return git_str_sets(resolved_url, url);
 }
 
 int git_remote__urlfordirection(
-       git_buf *url_out,
+       git_str *url_out,
        struct git_remote *remote,
        int direction,
        const git_remote_callbacks *callbacks)
@@ -747,54 +757,200 @@ int git_remote__urlfordirection(
        return resolve_url(url_out, url, direction, callbacks);
 }
 
-static int remote_transport_set_callbacks(git_transport *t, const git_remote_callbacks *cbs)
+int git_remote_connect_options_init(
+       git_remote_connect_options *opts,
+       unsigned int version)
+{
+       GIT_INIT_STRUCTURE_FROM_TEMPLATE(
+               opts, version, git_remote_connect_options, GIT_REMOTE_CONNECT_OPTIONS_INIT);
+       return 0;
+}
+
+int git_remote_connect_options_dup(
+       git_remote_connect_options *dst,
+       const git_remote_connect_options *src)
 {
-       if (!t->set_callbacks || !cbs)
+       memcpy(dst, src, sizeof(git_remote_connect_options));
+
+       if (git_proxy_options_dup(&dst->proxy_opts, &src->proxy_opts) < 0 ||
+           git_strarray_copy(&dst->custom_headers, &src->custom_headers) < 0)
+               return -1;
+
+       return 0;
+}
+
+void git_remote_connect_options_dispose(git_remote_connect_options *opts)
+{
+       if (!opts)
+               return;
+
+       git_strarray_dispose(&opts->custom_headers);
+       git_proxy_options_dispose(&opts->proxy_opts);
+}
+
+static size_t http_header_name_length(const char *http_header)
+{
+       const char *colon = strchr(http_header, ':');
+       if (!colon)
                return 0;
+       return colon - http_header;
+}
+
+static bool is_malformed_http_header(const char *http_header)
+{
+       const char *c;
+       size_t name_len;
 
-       return t->set_callbacks(t, cbs->sideband_progress, NULL,
-                               cbs->certificate_check, cbs->payload);
+       /* Disallow \r and \n */
+       if ((c = strchr(http_header, '\r')) != NULL)
+               return true;
+       if ((c = strchr(http_header, '\n')) != NULL)
+               return true;
+
+       /* Require a header name followed by : */
+       if ((name_len = http_header_name_length(http_header)) < 1)
+               return true;
+
+       return false;
+}
+
+static char *forbidden_custom_headers[] = {
+       "User-Agent",
+       "Host",
+       "Accept",
+       "Content-Type",
+       "Transfer-Encoding",
+       "Content-Length",
+};
+
+static bool is_forbidden_custom_header(const char *custom_header)
+{
+       unsigned long i;
+       size_t name_len = http_header_name_length(custom_header);
+
+       /* Disallow headers that we set */
+       for (i = 0; i < ARRAY_SIZE(forbidden_custom_headers); i++)
+               if (strncmp(forbidden_custom_headers[i], custom_header, name_len) == 0)
+                       return true;
+
+       return false;
+}
+
+static int validate_custom_headers(const git_strarray *custom_headers)
+{
+       size_t i;
+
+       if (!custom_headers)
+               return 0;
+
+       for (i = 0; i < custom_headers->count; i++) {
+               if (is_malformed_http_header(custom_headers->strings[i])) {
+                       git_error_set(GIT_ERROR_INVALID, "custom HTTP header '%s' is malformed", custom_headers->strings[i]);
+                       return -1;
+               }
+
+               if (is_forbidden_custom_header(custom_headers->strings[i])) {
+                       git_error_set(GIT_ERROR_INVALID, "custom HTTP header '%s' is already set by libgit2", custom_headers->strings[i]);
+                       return -1;
+               }
+       }
+
+       return 0;
 }
 
-static int set_transport_custom_headers(git_transport *t, const git_strarray *custom_headers)
+static int lookup_redirect_config(
+       git_remote_redirect_t *out,
+       git_repository *repo)
 {
-       if (!t->set_custom_headers)
+       git_config *config;
+       const char *value;
+       int bool_value, error = 0;
+
+       if (!repo) {
+               *out = GIT_REMOTE_REDIRECT_INITIAL;
                return 0;
+       }
+
+       if ((error = git_repository_config_snapshot(&config, repo)) < 0)
+               goto done;
+
+       if ((error = git_config_get_string(&value, config, "http.followRedirects")) < 0) {
+               if (error == GIT_ENOTFOUND) {
+                       *out = GIT_REMOTE_REDIRECT_INITIAL;
+                       error = 0;
+               }
 
-       return t->set_custom_headers(t, custom_headers);
+               goto done;
+       }
+
+       if (git_config_parse_bool(&bool_value, value) == 0) {
+               *out = bool_value ? GIT_REMOTE_REDIRECT_ALL :
+                                   GIT_REMOTE_REDIRECT_NONE;
+       } else if (strcasecmp(value, "initial") == 0) {
+               *out = GIT_REMOTE_REDIRECT_INITIAL;
+       } else {
+               git_error_set(GIT_ERROR_CONFIG, "invalid configuration setting '%s' for 'http.followRedirects'", value);
+               error = -1;
+       }
+
+done:
+       git_config_free(config);
+       return error;
 }
 
-int git_remote__connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_remote_connection_opts *conn)
+int git_remote_connect_options_normalize(
+       git_remote_connect_options *dst,
+       git_repository *repo,
+       const git_remote_connect_options *src)
 {
+       git_remote_connect_options_dispose(dst);
+       git_remote_connect_options_init(dst, GIT_REMOTE_CONNECT_OPTIONS_VERSION);
+
+       if (src) {
+               GIT_ERROR_CHECK_VERSION(src, GIT_REMOTE_CONNECT_OPTIONS_VERSION, "git_remote_connect_options");
+               GIT_ERROR_CHECK_VERSION(&src->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
+               GIT_ERROR_CHECK_VERSION(&src->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
+
+               if (validate_custom_headers(&src->custom_headers) < 0 ||
+                   git_remote_connect_options_dup(dst, src) < 0)
+                       return -1;
+       }
+
+       if (dst->follow_redirects == 0) {
+               if (lookup_redirect_config(&dst->follow_redirects, repo) < 0)
+                       return -1;
+       }
+
+       return 0;
+}
+
+int git_remote_connect_ext(
+       git_remote *remote,
+       git_direction direction,
+       const git_remote_connect_options *given_opts)
+{
+       git_remote_connect_options opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
+       git_str url = GIT_STR_INIT;
        git_transport *t;
-       git_buf url = GIT_BUF_INIT;
-       int flags = GIT_TRANSPORTFLAGS_NONE;
        int error;
-       void *payload = NULL;
-       git_credential_acquire_cb credentials = NULL;
-       git_transport_cb transport = NULL;
 
        GIT_ASSERT_ARG(remote);
 
-       if (callbacks) {
-               GIT_ERROR_CHECK_VERSION(callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
-               credentials = callbacks->credentials;
-               transport   = callbacks->transport;
-               payload     = callbacks->payload;
-       }
+       if (given_opts)
+               memcpy(&opts, given_opts, sizeof(git_remote_connect_options));
 
-       if (conn->proxy)
-               GIT_ERROR_CHECK_VERSION(conn->proxy, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
+       GIT_ERROR_CHECK_VERSION(&opts.callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
+       GIT_ERROR_CHECK_VERSION(&opts.proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
 
        t = remote->transport;
 
-       if ((error = git_remote__urlfordirection(&url, remote, direction, callbacks)) < 0)
+       if ((error = git_remote__urlfordirection(&url, remote, direction, &opts.callbacks)) < 0)
                goto on_error;
 
        /* If we don't have a transport object yet, and the caller specified a
         * custom transport factory, use that */
-       if (!t && transport &&
-               (error = transport(&t, remote, payload)) < 0)
+       if (!t && opts.callbacks.transport &&
+           (error = opts.callbacks.transport(&t, remote, opts.callbacks.payload)) < 0)
                goto on_error;
 
        /* If we still don't have a transport, then use the global
@@ -802,16 +958,12 @@ int git_remote__connect(git_remote *remote, git_direction direction, const git_r
        if (!t && (error = git_transport_new(&t, remote, url.ptr)) < 0)
                goto on_error;
 
-       if ((error = set_transport_custom_headers(t, conn->custom_headers)) != 0)
-               goto on_error;
-
-       if ((error = remote_transport_set_callbacks(t, callbacks)) < 0 ||
-           (error = t->connect(t, url.ptr, credentials, payload, conn->proxy, direction, flags)) != 0)
+       if ((error = t->connect(t, url.ptr, direction, &opts)) != 0)
                goto on_error;
 
        remote->transport = t;
 
-       git_buf_dispose(&url);
+       git_str_dispose(&url);
 
        return 0;
 
@@ -819,7 +971,7 @@ on_error:
        if (t)
                t->free(t);
 
-       git_buf_dispose(&url);
+       git_str_dispose(&url);
 
        if (t == remote->transport)
                remote->transport = NULL;
@@ -827,14 +979,25 @@ on_error:
        return error;
 }
 
-int git_remote_connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_proxy_options *proxy, const git_strarray *custom_headers)
+int git_remote_connect(
+       git_remote *remote,
+       git_direction direction,
+       const git_remote_callbacks *callbacks,
+       const git_proxy_options *proxy,
+       const git_strarray *custom_headers)
 {
-       git_remote_connection_opts conn;
+       git_remote_connect_options opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
+
+       if (callbacks)
+               memcpy(&opts.callbacks, callbacks, sizeof(git_remote_callbacks));
+
+       if (proxy)
+               memcpy(&opts.proxy_opts, proxy, sizeof(git_proxy_options));
 
-       conn.proxy = proxy;
-       conn.custom_headers = custom_headers;
+       if (custom_headers)
+               memcpy(&opts.custom_headers, custom_headers, sizeof(git_strarray));
 
-       return git_remote__connect(remote, direction, callbacks, &conn);
+       return git_remote_connect_ext(remote, direction, &opts);
 }
 
 int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote)
@@ -849,6 +1012,20 @@ int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote
        return remote->transport->ls(out, size, remote->transport);
 }
 
+int git_remote_capabilities(unsigned int *out, git_remote *remote)
+{
+       GIT_ASSERT_ARG(remote);
+
+       *out = 0;
+
+       if (!remote->transport) {
+               git_error_set(GIT_ERROR_NET, "this remote has never connected");
+               return -1;
+       }
+
+       return remote->transport->capabilities(out, remote->transport);
+}
+
 static int lookup_config(char **out, git_config *cfg, const char *name)
 {
        git_config_entry *ce = NULL;
@@ -885,7 +1062,7 @@ static void url_config_trim(git_net_url *url)
 static int http_proxy_config(char **out, git_remote *remote, git_net_url *url)
 {
        git_config *cfg = NULL;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_net_url lookup_url = GIT_NET_URL_INIT;
        int error;
 
@@ -902,19 +1079,19 @@ static int http_proxy_config(char **out, git_remote *remote, git_net_url *url)
 
        /* remote.<name>.proxy config setting */
        if (remote->name && remote->name[0]) {
-               git_buf_clear(&buf);
+               git_str_clear(&buf);
 
-               if ((error = git_buf_printf(&buf, "remote.%s.proxy", remote->name)) < 0 ||
+               if ((error = git_str_printf(&buf, "remote.%s.proxy", remote->name)) < 0 ||
                    (error = lookup_config(out, cfg, buf.ptr)) != GIT_ENOTFOUND)
                        goto done;
        }
 
        while (true) {
-               git_buf_clear(&buf);
+               git_str_clear(&buf);
 
-               if ((error = git_buf_puts(&buf, "http.")) < 0 ||
+               if ((error = git_str_puts(&buf, "http.")) < 0 ||
                    (error = git_net_url_fmt(&buf, &lookup_url)) < 0 ||
-                   (error = git_buf_puts(&buf, ".proxy")) < 0 ||
+                   (error = git_str_puts(&buf, ".proxy")) < 0 ||
                    (error = lookup_config(out, cfg, buf.ptr)) != GIT_ENOTFOUND)
                        goto done;
 
@@ -924,20 +1101,20 @@ static int http_proxy_config(char **out, git_remote *remote, git_net_url *url)
                url_config_trim(&lookup_url);
        }
 
-       git_buf_clear(&buf);
+       git_str_clear(&buf);
 
        error = lookup_config(out, cfg, "http.proxy");
 
 done:
        git_config_free(cfg);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        git_net_url_dispose(&lookup_url);
        return error;
 }
 
 static int http_proxy_env(char **out, git_remote *remote, git_net_url *url)
 {
-       git_buf proxy_env = GIT_BUF_INIT, no_proxy_env = GIT_BUF_INIT;
+       git_str proxy_env = GIT_STR_INIT, no_proxy_env = GIT_STR_INIT;
        bool use_ssl = (strcmp(url->scheme, "https") == 0);
        int error;
 
@@ -963,13 +1140,13 @@ static int http_proxy_env(char **out, git_remote *remote, git_net_url *url)
                goto done;
 
        if (!git_net_url_matches_pattern_list(url, no_proxy_env.ptr))
-               *out = git_buf_detach(&proxy_env);
+               *out = git_str_detach(&proxy_env);
        else
                error = GIT_ENOTFOUND;
 
 done:
-       git_buf_dispose(&proxy_env);
-       git_buf_dispose(&no_proxy_env);
+       git_str_dispose(&proxy_env);
+       git_str_dispose(&no_proxy_env);
        return error;
 }
 
@@ -1048,38 +1225,50 @@ static int ls_to_vector(git_vector *out, git_remote *remote)
        return 0;
 }
 
-int git_remote_download(git_remote *remote, const git_strarray *refspecs, const git_fetch_options *opts)
-{
-       int error = -1;
-       size_t i;
-       git_vector *to_active, specs = GIT_VECTOR_INIT, refs = GIT_VECTOR_INIT;
-       const git_remote_callbacks *cbs = NULL;
-       const git_strarray *custom_headers = NULL;
-       const git_proxy_options *proxy = NULL;
-
-       GIT_ASSERT_ARG(remote);
-
-       if (!remote->repo) {
-               git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
-               return -1;
+#define copy_opts(out, in) \
+       if (in) { \
+               (out)->callbacks = (in)->callbacks; \
+               (out)->proxy_opts = (in)->proxy_opts; \
+               (out)->custom_headers = (in)->custom_headers; \
+               (out)->follow_redirects = (in)->follow_redirects; \
        }
 
-       if (opts) {
-               GIT_ERROR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
-               cbs = &opts->callbacks;
-               custom_headers = &opts->custom_headers;
-               GIT_ERROR_CHECK_VERSION(&opts->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
-               proxy = &opts->proxy_opts;
+GIT_INLINE(int) connect_opts_from_fetch_opts(
+       git_remote_connect_options *out,
+       git_remote *remote,
+       const git_fetch_options *fetch_opts)
+{
+       git_remote_connect_options tmp = GIT_REMOTE_CONNECT_OPTIONS_INIT;
+       copy_opts(&tmp, fetch_opts);
+       return git_remote_connect_options_normalize(out, remote->repo, &tmp);
+}
+
+static int connect_or_reset_options(
+       git_remote *remote,
+       int direction,
+       git_remote_connect_options *opts)
+{
+       if (!git_remote_connected(remote)) {
+               return git_remote_connect_ext(remote, direction, opts);
+       } else {
+               return remote->transport->set_connect_opts(remote->transport, opts);
        }
+}
 
-       if (!git_remote_connected(remote) &&
-           (error = git_remote_connect(remote, GIT_DIRECTION_FETCH, cbs, proxy, custom_headers)) < 0)
-               goto on_error;
+/* Download from an already connected remote. */
+static int git_remote__download(
+       git_remote *remote,
+       const git_strarray *refspecs,
+       const git_fetch_options *opts)
+{
+       git_vector *to_active, specs = GIT_VECTOR_INIT, refs = GIT_VECTOR_INIT;
+       size_t i;
+       int error;
 
        if (ls_to_vector(&refs, remote) < 0)
                return -1;
 
-       if ((git_vector_init(&specs, 0, NULL)) < 0)
+       if ((error = git_vector_init(&specs, 0, NULL)) < 0)
                goto on_error;
 
        remote->passed_refspecs = 0;
@@ -1107,7 +1296,7 @@ int git_remote_download(git_remote *remote, const git_strarray *refspecs, const
        git_vector_free(&specs);
 
        if (error < 0)
-               return error;
+               goto on_error;
 
        if (remote->push) {
                git_push_free(remote->push);
@@ -1115,9 +1304,9 @@ int git_remote_download(git_remote *remote, const git_strarray *refspecs, const
        }
 
        if ((error = git_fetch_negotiate(remote, opts)) < 0)
-               return error;
+               goto on_error;
 
-       return git_fetch_download_pack(remote, cbs);
+       error = git_fetch_download_pack(remote);
 
 on_error:
        git_vector_free(&refs);
@@ -1126,55 +1315,83 @@ on_error:
        return error;
 }
 
+int git_remote_download(
+       git_remote *remote,
+       const git_strarray *refspecs,
+       const git_fetch_options *opts)
+{
+       git_remote_connect_options connect_opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
+       int error;
+
+       GIT_ASSERT_ARG(remote);
+
+       if (!remote->repo) {
+               git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
+               return -1;
+       }
+
+       if (connect_opts_from_fetch_opts(&connect_opts, remote, opts) < 0)
+               return -1;
+
+       if ((error = connect_or_reset_options(remote, GIT_DIRECTION_FETCH, &connect_opts)) < 0)
+               return error;
+
+       return git_remote__download(remote, refspecs, opts);
+}
+
 int git_remote_fetch(
-               git_remote *remote,
-               const git_strarray *refspecs,
-               const git_fetch_options *opts,
-               const char *reflog_message)
+       git_remote *remote,
+       const git_strarray *refspecs,
+       const git_fetch_options *opts,
+       const char *reflog_message)
 {
        int error, update_fetchhead = 1;
        git_remote_autotag_option_t tagopt = remote->download_tags;
        bool prune = false;
-       git_buf reflog_msg_buf = GIT_BUF_INIT;
-       const git_remote_callbacks *cbs = NULL;
-       git_remote_connection_opts conn = GIT_REMOTE_CONNECTION_OPTIONS_INIT;
+       git_str reflog_msg_buf = GIT_STR_INIT;
+       git_remote_connect_options connect_opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
+
+       GIT_ASSERT_ARG(remote);
+
+       if (!remote->repo) {
+               git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
+               return -1;
+       }
+
+       if (connect_opts_from_fetch_opts(&connect_opts, remote, opts) < 0)
+               return -1;
+
+       if ((error = connect_or_reset_options(remote, GIT_DIRECTION_FETCH, &connect_opts)) < 0)
+               return error;
 
        if (opts) {
-               GIT_ERROR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
-               cbs = &opts->callbacks;
-               conn.custom_headers = &opts->custom_headers;
                update_fetchhead = opts->update_fetchhead;
                tagopt = opts->download_tags;
-               GIT_ERROR_CHECK_VERSION(&opts->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
-               conn.proxy = &opts->proxy_opts;
        }
 
        /* Connect and download everything */
-       if ((error = git_remote__connect(remote, GIT_DIRECTION_FETCH, cbs, &conn)) != 0)
-               return error;
-
-       error = git_remote_download(remote, refspecs, opts);
+       error = git_remote__download(remote, refspecs, opts);
 
        /* We don't need to be connected anymore */
        git_remote_disconnect(remote);
 
        /* If the download failed, return the error */
        if (error != 0)
-               return error;
+               goto done;
 
        /* Default reflog message */
        if (reflog_message)
-               git_buf_sets(&reflog_msg_buf, reflog_message);
+               git_str_sets(&reflog_msg_buf, reflog_message);
        else {
-               git_buf_printf(&reflog_msg_buf, "fetch %s",
+               git_str_printf(&reflog_msg_buf, "fetch %s",
                                remote->name ? remote->name : remote->url);
        }
 
        /* Create "remote/foo" branches for all remote branches */
-       error = git_remote_update_tips(remote, cbs, update_fetchhead, tagopt, git_buf_cstr(&reflog_msg_buf));
-       git_buf_dispose(&reflog_msg_buf);
+       error = git_remote_update_tips(remote, &connect_opts.callbacks, update_fetchhead, tagopt, git_str_cstr(&reflog_msg_buf));
+       git_str_dispose(&reflog_msg_buf);
        if (error < 0)
-               return error;
+               goto done;
 
        if (opts && opts->prune == GIT_FETCH_PRUNE)
                prune = true;
@@ -1186,8 +1403,10 @@ int git_remote_fetch(
                prune = remote->prune_refs;
 
        if (prune)
-               error = git_remote_prune(remote, cbs);
+               error = git_remote_prune(remote, &connect_opts.callbacks);
 
+done:
+       git_remote_connect_options_dispose(&connect_opts);
        return error;
 }
 
@@ -1211,22 +1430,22 @@ static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *upda
        return 0;
 }
 
-static int ref_to_update(int *update, git_buf *remote_name, git_remote *remote, git_refspec *spec, const char *ref_name)
+static int ref_to_update(int *update, git_str *remote_name, git_remote *remote, git_refspec *spec, const char *ref_name)
 {
        int error = 0;
        git_repository *repo;
-       git_buf upstream_remote = GIT_BUF_INIT;
-       git_buf upstream_name = GIT_BUF_INIT;
+       git_str upstream_remote = GIT_STR_INIT;
+       git_str upstream_name = GIT_STR_INIT;
 
        repo = git_remote_owner(remote);
 
        if ((!git_reference__is_branch(ref_name)) ||
            !git_remote_name(remote) ||
-           (error = git_branch_upstream_remote(&upstream_remote, repo, ref_name) < 0) ||
-           git__strcmp(git_remote_name(remote), git_buf_cstr(&upstream_remote)) ||
-           (error = git_branch_upstream_name(&upstream_name, repo, ref_name)) < 0 ||
-           !git_refspec_dst_matches(spec, git_buf_cstr(&upstream_name)) ||
-           (error = git_refspec_rtransform(remote_name, spec, upstream_name.ptr)) < 0) {
+           (error = git_branch__upstream_remote(&upstream_remote, repo, ref_name) < 0) ||
+           git__strcmp(git_remote_name(remote), git_str_cstr(&upstream_remote)) ||
+           (error = git_branch__upstream_name(&upstream_name, repo, ref_name)) < 0 ||
+           !git_refspec_dst_matches(spec, git_str_cstr(&upstream_name)) ||
+           (error = git_refspec__rtransform(remote_name, spec, upstream_name.ptr)) < 0) {
                /* Not an error if there is no upstream */
                if (error == GIT_ENOTFOUND) {
                        git_error_clear();
@@ -1238,15 +1457,15 @@ static int ref_to_update(int *update, git_buf *remote_name, git_remote *remote,
                *update = 1;
        }
 
-       git_buf_dispose(&upstream_remote);
-       git_buf_dispose(&upstream_name);
+       git_str_dispose(&upstream_remote);
+       git_str_dispose(&upstream_name);
        return error;
 }
 
 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_str remote_name = GIT_STR_INIT;
        git_config *config = NULL;
        const char *ref_name;
        int error = 0, update;
@@ -1281,10 +1500,10 @@ static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_re
                goto cleanup;
 
        if (update)
-               error = remote_head_for_fetchspec_src(out, update_heads, git_buf_cstr(&remote_name));
+               error = remote_head_for_fetchspec_src(out, update_heads, git_str_cstr(&remote_name));
 
 cleanup:
-       git_buf_dispose(&remote_name);
+       git_str_dispose(&remote_name);
        git_reference_free(resolved_ref);
        git_config_free(config);
        return error;
@@ -1422,7 +1641,7 @@ int git_remote_prune(git_remote *remote, const git_remote_callbacks *callbacks)
         */
        git_vector_foreach(&candidates, i, refname) {
                git_vector_foreach(&remote->active_refspecs, j, spec) {
-                       git_buf buf = GIT_BUF_INIT;
+                       git_str buf = GIT_STR_INIT;
                        size_t pos;
                        char *src_name;
                        git_remote_head key = {0};
@@ -1430,12 +1649,12 @@ int git_remote_prune(git_remote *remote, const git_remote_callbacks *callbacks)
                        if (!git_refspec_dst_matches(spec, refname))
                                continue;
 
-                       if ((error = git_refspec_rtransform(&buf, spec, refname)) < 0)
+                       if ((error = git_refspec__rtransform(&buf, spec, refname)) < 0)
                                goto cleanup;
 
-                       key.name = (char *) git_buf_cstr(&buf);
+                       key.name = (char *) git_str_cstr(&buf);
                        error = git_vector_bsearch(&pos, &remote_refs, &key);
-                       git_buf_dispose(&buf);
+                       git_str_dispose(&buf);
 
                        if (error < 0 && error != GIT_ENOTFOUND)
                                goto cleanup;
@@ -1497,141 +1716,210 @@ cleanup:
        return error;
 }
 
-static int update_tips_for_spec(
-               git_remote *remote,
-               const git_remote_callbacks *callbacks,
-               int update_fetchhead,
-               git_remote_autotag_option_t tagopt,
-               git_refspec *spec,
-               git_vector *refs,
-               const char *log_message)
+static int update_ref(
+       const git_remote *remote,
+       const char *ref_name,
+       git_oid *id,
+       const char *msg,
+       const git_remote_callbacks *callbacks)
 {
-       int error = 0, autotag, valid;
-       unsigned int i = 0;
-       git_buf refname = GIT_BUF_INIT;
-       git_oid old;
-       git_odb *odb;
-       git_remote_head *head;
        git_reference *ref;
-       git_refspec tagspec;
-       git_vector update_heads;
+       git_oid old_id;
+       int error;
 
-       GIT_ASSERT_ARG(remote);
+       error = git_reference_name_to_id(&old_id, remote->repo, ref_name);
 
-       if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
-               return -1;
+       if (error < 0 && error != GIT_ENOTFOUND)
+               return error;
+       else if (error == 0 && git_oid_equal(&old_id, id))
+               return 0;
 
-       if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
-               return -1;
+       /* If we did find a current reference, make sure we haven't lost a race */
+       if (error)
+               error = git_reference_create(&ref, remote->repo, ref_name, id, true, msg);
+       else
+               error = git_reference_create_matching(&ref, remote->repo, ref_name, id, true, &old_id, msg);
 
-       /* Make a copy of the transport's refs */
-       if (git_vector_init(&update_heads, 16, NULL) < 0)
-               return -1;
+       git_reference_free(ref);
 
-       for (; i < refs->length; ++i) {
-               head = git_vector_get(refs, i);
-               autotag = 0;
-               git_buf_clear(&refname);
+       if (error < 0)
+               return error;
 
-               /* Ignore malformed ref names (which also saves us from tag^{} */
-               if (git_reference_name_is_valid(&valid, head->name) < 0)
-                       goto on_error;
+       if (callbacks && callbacks->update_tips &&
+           (error = callbacks->update_tips(ref_name, &old_id, id, callbacks->payload)) < 0)
+               return error;
 
-               if (!valid)
-                       continue;
+       return 0;
+}
 
-               /* If we have a tag, see if the auto-follow rules say to update it */
-               if (git_refspec_src_matches(&tagspec, head->name)) {
-                       if (tagopt != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
+static int update_one_tip(
+       git_vector *update_heads,
+       git_remote *remote,
+       git_refspec *spec,
+       git_remote_head *head,
+       git_refspec *tagspec,
+       git_remote_autotag_option_t tagopt,
+       const char *log_message,
+       const git_remote_callbacks *callbacks)
+{
+       git_odb *odb;
+       git_str refname = GIT_STR_INIT;
+       git_reference *ref = NULL;
+       bool autotag = false;
+       git_oid old;
+       int valid;
+       int error;
 
-                               if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO)
-                                       autotag = 1;
+       if ((error = git_repository_odb__weakptr(&odb, remote->repo)) < 0)
+               goto done;
 
-                               git_buf_clear(&refname);
-                               if (git_buf_puts(&refname, head->name) < 0)
-                                       goto on_error;
-                       }
-               }
+       /* Ignore malformed ref names (which also saves us from tag^{} */
+       if ((error = git_reference_name_is_valid(&valid, head->name)) < 0)
+               goto done;
 
-               /* If we didn't want to auto-follow the tag, check if the refspec matches */
-               if (!autotag && git_refspec_src_matches(spec, head->name)) {
-                       if (spec->dst) {
-                               if (git_refspec_transform(&refname, spec, head->name) < 0)
-                                       goto on_error;
-                       } else {
-                               /*
-                                * no rhs mans store it in FETCH_HEAD, even if we don't
-                                update anything else.
-                                */
-                               if ((error = git_vector_insert(&update_heads, head)) < 0)
-                                       goto on_error;
+       if (!valid)
+               goto done;
 
-                               continue;
-                       }
+       /* If we have a tag, see if the auto-follow rules say to update it */
+       if (git_refspec_src_matches(tagspec, head->name)) {
+               if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO)
+                       autotag = true;
+
+               if (tagopt != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
+                       if (git_str_puts(&refname, head->name) < 0)
+                               goto done;
                }
+       }
 
-               /* If we still don't have a refname, we don't want it */
-               if (git_buf_len(&refname) == 0) {
-                       continue;
+       /* If we didn't want to auto-follow the tag, check if the refspec matches */
+       if (!autotag && git_refspec_src_matches(spec, head->name)) {
+               if (spec->dst) {
+                       if ((error = git_refspec__transform(&refname, spec, head->name)) < 0)
+                               goto done;
+               } else {
+                       /*
+                        * no rhs means store it in FETCH_HEAD, even if we don't
+                        * update anything else.
+                        */
+                       error = git_vector_insert(update_heads, head);
+                       goto done;
                }
+       }
 
-               /* In autotag mode, only create tags for objects already in db */
-               if (autotag && !git_odb_exists(odb, &head->oid))
-                       continue;
+       /* If we still don't have a refname, we don't want it */
+       if (git_str_len(&refname) == 0)
+               goto done;
 
-               if (!autotag && git_vector_insert(&update_heads, head) < 0)
-                       goto on_error;
+       /* In autotag mode, only create tags for objects already in db */
+       if (autotag && !git_odb_exists(odb, &head->oid))
+               goto done;
 
-               error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
-               if (error < 0 && error != GIT_ENOTFOUND)
-                       goto on_error;
+       if (!autotag && (error = git_vector_insert(update_heads, head)) < 0)
+               goto done;
 
-               if (!(error || error == GIT_ENOTFOUND)
-                               && !spec->force
-                               && !git_graph_descendant_of(remote->repo, &head->oid, &old))
-                       continue;
+       error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
 
-               if (error == GIT_ENOTFOUND) {
-                       memset(&old, 0, GIT_OID_RAWSZ);
+       if (error < 0 && error != GIT_ENOTFOUND)
+               goto done;
 
-                       if (autotag && git_vector_insert(&update_heads, head) < 0)
-                               goto on_error;
-               }
+       if (!(error || error == GIT_ENOTFOUND) &&
+           !spec->force &&
+           !git_graph_descendant_of(remote->repo, &head->oid, &old)) {
+               error = 0;
+               goto done;
+       }
 
-               if (!git_oid__cmp(&old, &head->oid))
-                       continue;
+       if (error == GIT_ENOTFOUND) {
+               memset(&old, 0, GIT_OID_RAWSZ);
+               error = 0;
+
+               if (autotag && (error = git_vector_insert(update_heads, head)) < 0)
+                       goto done;
+       }
 
-               /* In autotag mode, don't overwrite any locally-existing tags */
-               error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
-                               log_message);
+       if (!git_oid__cmp(&old, &head->oid))
+               goto done;
+
+       /* In autotag mode, don't overwrite any locally-existing tags */
+       error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
+                       log_message);
 
+       if (error < 0) {
                if (error == GIT_EEXISTS)
-                       continue;
+                       error = 0;
 
-               if (error < 0)
+               goto done;
+       }
+
+       if (callbacks && callbacks->update_tips != NULL &&
+           (error = callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload)) < 0)
+               git_error_set_after_callback_function(error, "git_remote_fetch");
+
+done:
+       git_reference_free(ref);
+       git_str_dispose(&refname);
+       return error;
+}
+
+static int update_tips_for_spec(
+       git_remote *remote,
+       const git_remote_callbacks *callbacks,
+       int update_fetchhead,
+       git_remote_autotag_option_t tagopt,
+       git_refspec *spec,
+       git_vector *refs,
+       const char *log_message)
+{
+       git_refspec tagspec;
+       git_remote_head *head, oid_head;
+       git_vector update_heads;
+       int error = 0;
+       size_t i;
+
+       GIT_ASSERT_ARG(remote);
+
+       if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
+               return -1;
+
+       /* Make a copy of the transport's refs */
+       if (git_vector_init(&update_heads, 16, NULL) < 0)
+               return -1;
+
+       /* Update tips based on the remote heads */
+       git_vector_foreach(refs, i, head) {
+               if (update_one_tip(&update_heads, remote, spec, head, &tagspec, tagopt, log_message, callbacks) < 0)
                        goto on_error;
+       }
 
-               git_reference_free(ref);
+       /* Handle specified oid sources */
+       if (git_oid__is_hexstr(spec->src)) {
+               git_oid id;
 
-               if (callbacks && callbacks->update_tips != NULL) {
-                       if (callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0)
-                               goto on_error;
-               }
+               if ((error = git_oid_fromstr(&id, spec->src)) < 0)
+                       goto on_error;
+
+               if (spec->dst &&
+                    (error = update_ref(remote, spec->dst, &id, log_message, callbacks)) < 0)
+                       goto on_error;
+
+               git_oid_cpy(&oid_head.oid, &id);
+               oid_head.name = spec->src;
+
+               if ((error = git_vector_insert(&update_heads, &oid_head)) < 0)
+                       goto on_error;
        }
 
        if (update_fetchhead &&
            (error = git_remote_write_fetchhead(remote, spec, &update_heads)) < 0)
                goto on_error;
 
-       git_vector_free(&update_heads);
        git_refspec__dispose(&tagspec);
-       git_buf_dispose(&refname);
+       git_vector_free(&update_heads);
        return 0;
 
 on_error:
-       git_vector_free(&update_heads);
        git_refspec__dispose(&tagspec);
-       git_buf_dispose(&refname);
+       git_vector_free(&update_heads);
        return -1;
 
 }
@@ -1697,20 +1985,22 @@ static int next_head(const git_remote *remote, git_vector *refs,
        return GIT_ITEROVER;
 }
 
-static int opportunistic_updates(const git_remote *remote, const git_remote_callbacks *callbacks,
-                                git_vector *refs, const char *msg)
+static int opportunistic_updates(
+       const git_remote *remote,
+       const git_remote_callbacks *callbacks,
+        git_vector *refs,
+        const char *msg)
 {
        size_t i, j, k;
        git_refspec *spec;
        git_remote_head *head;
-       git_reference *ref;
-       git_buf refname = GIT_BUF_INIT;
+       git_str refname = GIT_STR_INIT;
        int error = 0;
 
        i = j = k = 0;
 
+       /* Handle refspecs matching remote heads */
        while ((error = next_head(remote, refs, &spec, &head, &i, &j, &k)) == 0) {
-               git_oid old = {{ 0 }};
                /*
                 * If we got here, there is a refspec which was used
                 * for fetching which matches the source of one of the
@@ -1719,50 +2009,32 @@ static int opportunistic_updates(const git_remote *remote, const git_remote_call
                 * FETCH_HEAD
                 */
 
-               git_buf_clear(&refname);
-               if ((error = git_refspec_transform(&refname, spec, head->name)) < 0)
-                       goto cleanup;
-
-               error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
-               if (error < 0 && error != GIT_ENOTFOUND)
+               git_str_clear(&refname);
+               if ((error = git_refspec__transform(&refname, spec, head->name)) < 0 ||
+                   (error = update_ref(remote, refname.ptr, &head->oid, msg, callbacks)) < 0)
                        goto cleanup;
-
-               if (!git_oid_cmp(&old, &head->oid))
-                       continue;
-
-               /* If we did find a current reference, make sure we haven't lost a race */
-               if (error)
-                       error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, true, msg);
-               else
-                       error = git_reference_create_matching(&ref, remote->repo, refname.ptr, &head->oid, true, &old, msg);
-               git_reference_free(ref);
-               if (error < 0)
-                       goto cleanup;
-
-               if (callbacks && callbacks->update_tips != NULL) {
-                       if (callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0)
-                               goto cleanup;
-               }
        }
 
-       if (error == GIT_ITEROVER)
-               error = 0;
+       if (error != GIT_ITEROVER)
+               goto cleanup;
+
+       error = 0;
 
 cleanup:
-       git_buf_dispose(&refname);
+       git_str_dispose(&refname);
        return error;
 }
 
 static int truncate_fetch_head(const char *gitdir)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        int error;
 
-       if ((error = git_buf_joinpath(&path, gitdir, GIT_FETCH_HEAD_FILE)) < 0)
+       if ((error = git_str_joinpath(&path, gitdir, GIT_FETCH_HEAD_FILE)) < 0)
                return error;
 
        error = git_futils_truncate(path.ptr, GIT_REFS_FILE_MODE);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return error;
 }
@@ -1813,7 +2085,7 @@ int git_remote_update_tips(
                        goto out;
        }
 
-       /* Only try to do opportunistic updates if the refpec lists differ. */
+       /* Only try to do opportunistic updates if the refspec lists differ. */
        if (remote->passed_refspecs)
                error = opportunistic_updates(remote, callbacks, &refs, reflog_message);
 
@@ -1854,6 +2126,17 @@ int git_remote_disconnect(git_remote *remote)
        return 0;
 }
 
+static void free_heads(git_vector *heads)
+{
+       git_remote_head *head;
+       size_t i;
+
+       git_vector_foreach(heads, i, head) {
+               git__free(head->name);
+               git__free(head);
+       }
+}
+
 void git_remote_free(git_remote *remote)
 {
        if (remote == NULL)
@@ -1877,6 +2160,9 @@ void git_remote_free(git_remote *remote)
        free_refspecs(&remote->passive_refspecs);
        git_vector_free(&remote->passive_refspecs);
 
+       free_heads(&remote->local_heads);
+       git_vector_free(&remote->local_heads);
+
        git_push_free(remote->push);
        git__free(remote->url);
        git__free(remote->pushurl);
@@ -1943,7 +2229,7 @@ git_remote_autotag_option_t git_remote_autotag(const git_remote *remote)
 
 int git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_autotag_option_t value)
 {
-       git_buf var = GIT_BUF_INIT;
+       git_str var = GIT_STR_INIT;
        git_config *config;
        int error;
 
@@ -1955,7 +2241,7 @@ int git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_
        if ((error = git_repository_config__weakptr(&config, repo)) < 0)
                return error;
 
-       if ((error = git_buf_printf(&var, CONFIG_TAGOPT_FMT, remote)))
+       if ((error = git_str_printf(&var, CONFIG_TAGOPT_FMT, remote)))
                return error;
 
        switch (value) {
@@ -1975,7 +2261,7 @@ int git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_
                error = -1;
        }
 
-       git_buf_dispose(&var);
+       git_str_dispose(&var);
        return error;
 }
 
@@ -1989,25 +2275,25 @@ static int rename_remote_config_section(
        const char *old_name,
        const char *new_name)
 {
-       git_buf old_section_name = GIT_BUF_INIT,
-               new_section_name = GIT_BUF_INIT;
+       git_str old_section_name = GIT_STR_INIT,
+               new_section_name = GIT_STR_INIT;
        int error = -1;
 
-       if (git_buf_printf(&old_section_name, "remote.%s", old_name) < 0)
+       if (git_str_printf(&old_section_name, "remote.%s", old_name) < 0)
                goto cleanup;
 
        if (new_name &&
-               (git_buf_printf(&new_section_name, "remote.%s", new_name) < 0))
+               (git_str_printf(&new_section_name, "remote.%s", new_name) < 0))
                        goto cleanup;
 
        error = git_config_rename_section(
                repo,
-               git_buf_cstr(&old_section_name),
-               new_name ? git_buf_cstr(&new_section_name) : NULL);
+               git_str_cstr(&old_section_name),
+               new_name ? git_str_cstr(&new_section_name) : NULL);
 
 cleanup:
-       git_buf_dispose(&old_section_name);
-       git_buf_dispose(&new_section_name);
+       git_str_dispose(&old_section_name);
+       git_str_dispose(&new_section_name);
 
        return error;
 }
@@ -2056,27 +2342,27 @@ static int rename_one_remote_reference(
 {
        int error;
        git_reference *ref = NULL, *dummy = NULL;
-       git_buf namespace = GIT_BUF_INIT, old_namespace = GIT_BUF_INIT;
-       git_buf new_name = GIT_BUF_INIT;
-       git_buf log_message = GIT_BUF_INIT;
+       git_str namespace = GIT_STR_INIT, old_namespace = GIT_STR_INIT;
+       git_str new_name = GIT_STR_INIT;
+       git_str log_message = GIT_STR_INIT;
        size_t pfx_len;
        const char *target;
 
-       if ((error = git_buf_printf(&namespace, GIT_REFS_REMOTES_DIR "%s/", new_remote_name)) < 0)
+       if ((error = git_str_printf(&namespace, GIT_REFS_REMOTES_DIR "%s/", new_remote_name)) < 0)
                return error;
 
        pfx_len = strlen(GIT_REFS_REMOTES_DIR) + strlen(old_remote_name) + 1;
-       git_buf_puts(&new_name, namespace.ptr);
-       if ((error = git_buf_puts(&new_name, git_reference_name(reference_in) + pfx_len)) < 0)
+       git_str_puts(&new_name, namespace.ptr);
+       if ((error = git_str_puts(&new_name, git_reference_name(reference_in) + pfx_len)) < 0)
                goto cleanup;
 
-       if ((error = git_buf_printf(&log_message,
+       if ((error = git_str_printf(&log_message,
                                        "renamed remote %s to %s",
                                        old_remote_name, new_remote_name)) < 0)
                goto cleanup;
 
-       if ((error = git_reference_rename(&ref, reference_in, git_buf_cstr(&new_name), 1,
-                                         git_buf_cstr(&log_message))) < 0)
+       if ((error = git_reference_rename(&ref, reference_in, git_str_cstr(&new_name), 1,
+                                         git_str_cstr(&log_message))) < 0)
                goto cleanup;
 
        if (git_reference_type(ref) != GIT_REFERENCE_SYMBOLIC)
@@ -2084,29 +2370,29 @@ static int rename_one_remote_reference(
 
        /* Handle refs like origin/HEAD -> origin/master */
        target = git_reference_symbolic_target(ref);
-       if ((error = git_buf_printf(&old_namespace, GIT_REFS_REMOTES_DIR "%s/", old_remote_name)) < 0)
+       if ((error = git_str_printf(&old_namespace, GIT_REFS_REMOTES_DIR "%s/", old_remote_name)) < 0)
                goto cleanup;
 
        if (git__prefixcmp(target, old_namespace.ptr))
                goto cleanup;
 
-       git_buf_clear(&new_name);
-       git_buf_puts(&new_name, namespace.ptr);
-       if ((error = git_buf_puts(&new_name, target + pfx_len)) < 0)
+       git_str_clear(&new_name);
+       git_str_puts(&new_name, namespace.ptr);
+       if ((error = git_str_puts(&new_name, target + pfx_len)) < 0)
                goto cleanup;
 
-       error = git_reference_symbolic_set_target(&dummy, ref, git_buf_cstr(&new_name),
-                                                 git_buf_cstr(&log_message));
+       error = git_reference_symbolic_set_target(&dummy, ref, git_str_cstr(&new_name),
+                                                 git_str_cstr(&log_message));
 
        git_reference_free(dummy);
 
 cleanup:
        git_reference_free(reference_in);
        git_reference_free(ref);
-       git_buf_dispose(&namespace);
-       git_buf_dispose(&old_namespace);
-       git_buf_dispose(&new_name);
-       git_buf_dispose(&log_message);
+       git_str_dispose(&namespace);
+       git_str_dispose(&old_namespace);
+       git_str_dispose(&new_name);
+       git_str_dispose(&log_message);
        return error;
 }
 
@@ -2116,15 +2402,15 @@ static int rename_remote_references(
        const char *new_name)
 {
        int error;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_reference *ref;
        git_reference_iterator *iter;
 
-       if ((error = git_buf_printf(&buf, GIT_REFS_REMOTES_DIR "%s/*", old_name)) < 0)
+       if ((error = git_str_printf(&buf, GIT_REFS_REMOTES_DIR "%s/*", old_name)) < 0)
                return error;
 
-       error = git_reference_iterator_glob_new(&iter, repo, git_buf_cstr(&buf));
-       git_buf_dispose(&buf);
+       error = git_reference_iterator_glob_new(&iter, repo, git_str_cstr(&buf));
+       git_str_dispose(&buf);
 
        if (error < 0)
                return error;
@@ -2142,7 +2428,7 @@ static int rename_remote_references(
 static int rename_fetch_refspecs(git_vector *problems, git_remote *remote, const char *new_name)
 {
        git_config *config;
-       git_buf base = GIT_BUF_INIT, var = GIT_BUF_INIT, val = GIT_BUF_INIT;
+       git_str base = GIT_STR_INIT, var = GIT_STR_INIT, val = GIT_STR_INIT;
        const git_refspec *spec;
        size_t i;
        int error = 0;
@@ -2161,7 +2447,7 @@ static int rename_fetch_refspecs(git_vector *problems, git_remote *remote, const
                        continue;
 
                /* Does the dst part of the refspec follow the expected format? */
-               if (strcmp(git_buf_cstr(&base), spec->string)) {
+               if (strcmp(git_str_cstr(&base), spec->string)) {
                        char *dup;
 
                        dup = git__strdup(spec->string);
@@ -2175,24 +2461,24 @@ static int rename_fetch_refspecs(git_vector *problems, git_remote *remote, const
 
                /* If we do want to move it to the new section */
 
-               git_buf_clear(&val);
-               git_buf_clear(&var);
+               git_str_clear(&val);
+               git_str_clear(&var);
 
                if (default_fetchspec_for_name(&val, new_name) < 0 ||
-                       git_buf_printf(&var, "remote.%s.fetch", new_name) < 0)
+                       git_str_printf(&var, "remote.%s.fetch", new_name) < 0)
                {
                        error = -1;
                        break;
                }
 
                if ((error = git_config_set_string(
-                               config, git_buf_cstr(&var), git_buf_cstr(&val))) < 0)
+                               config, git_str_cstr(&var), git_str_cstr(&val))) < 0)
                        break;
        }
 
-       git_buf_dispose(&base);
-       git_buf_dispose(&var);
-       git_buf_dispose(&val);
+       git_str_dispose(&base);
+       git_str_dispose(&var);
+       git_str_dispose(&val);
 
        if (error < 0) {
                char *str;
@@ -2247,7 +2533,7 @@ cleanup:
 
 int git_remote_name_is_valid(int *valid, const char *remote_name)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_refspec refspec = {0};
        int error;
 
@@ -2258,10 +2544,10 @@ int git_remote_name_is_valid(int *valid, const char *remote_name)
        if (!remote_name || *remote_name == '\0')
                return 0;
 
-       if ((error = git_buf_printf(&buf, "refs/heads/test:refs/remotes/%s/test", remote_name)) < 0)
+       if ((error = git_str_printf(&buf, "refs/heads/test:refs/remotes/%s/test", remote_name)) < 0)
                goto done;
 
-       error = git_refspec__parse(&refspec, git_buf_cstr(&buf), true);
+       error = git_refspec__parse(&refspec, git_str_cstr(&buf), true);
 
        if (!error)
                *valid = 1;
@@ -2269,7 +2555,7 @@ int git_remote_name_is_valid(int *valid, const char *remote_name)
                error = 0;
 
 done:
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        git_refspec__dispose(&refspec);
 
        return error;
@@ -2401,7 +2687,7 @@ static int remove_branch_config_related_entries(
        git_config *config;
        git_config_entry *entry;
        git_config_iterator *iter;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        if ((error = git_repository_config__weakptr(&config, repo)) < 0)
                return error;
@@ -2422,21 +2708,21 @@ static int remove_branch_config_related_entries(
                        break;
                }
 
-               git_buf_clear(&buf);
-               if ((error = git_buf_printf(&buf, "branch.%.*s.merge", (int)branch_len, branch)) < 0)
+               git_str_clear(&buf);
+               if ((error = git_str_printf(&buf, "branch.%.*s.merge", (int)branch_len, branch)) < 0)
                        break;
 
-               if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) {
+               if ((error = git_config_delete_entry(config, git_str_cstr(&buf))) < 0) {
                        if (error != GIT_ENOTFOUND)
                                break;
                        git_error_clear();
                }
 
-               git_buf_clear(&buf);
-               if ((error = git_buf_printf(&buf, "branch.%.*s.remote", (int)branch_len, branch)) < 0)
+               git_str_clear(&buf);
+               if ((error = git_str_printf(&buf, "branch.%.*s.remote", (int)branch_len, branch)) < 0)
                        break;
 
-               if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) {
+               if ((error = git_config_delete_entry(config, git_str_cstr(&buf))) < 0) {
                        if (error != GIT_ENOTFOUND)
                                break;
                        git_error_clear();
@@ -2446,7 +2732,7 @@ static int remove_branch_config_related_entries(
        if (error == GIT_ITEROVER)
                error = 0;
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        git_config_iterator_free(iter);
        return error;
 }
@@ -2540,12 +2826,17 @@ int git_remote_delete(git_repository *repo, const char *name)
 }
 
 int git_remote_default_branch(git_buf *out, git_remote *remote)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_remote__default_branch, remote);
+}
+
+int git_remote__default_branch(git_str *out, git_remote *remote)
 {
        const git_remote_head **heads;
        const git_remote_head *guess = NULL;
        const git_oid *head_id;
        size_t heads_len, i;
-       git_buf local_default = GIT_BUF_INIT;
+       git_str local_default = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(out);
@@ -2558,12 +2849,9 @@ int git_remote_default_branch(git_buf *out, git_remote *remote)
                goto done;
        }
 
-       if ((error = git_buf_sanitize(out)) < 0)
-               return error;
-
        /* the first one must be HEAD so if that has the symref info, we're done */
        if (heads[0]->symref_target) {
-               error = git_buf_puts(out, heads[0]->symref_target);
+               error = git_str_puts(out, heads[0]->symref_target);
                goto done;
        }
 
@@ -2601,21 +2889,33 @@ int git_remote_default_branch(git_buf *out, git_remote *remote)
                goto done;
        }
 
-       error = git_buf_puts(out, guess->name);
+       error = git_str_puts(out, guess->name);
 
 done:
-       git_buf_dispose(&local_default);
+       git_str_dispose(&local_default);
        return error;
 }
 
-int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts)
+GIT_INLINE(int) connect_opts_from_push_opts(
+       git_remote_connect_options *out,
+       git_remote *remote,
+       const git_push_options *push_opts)
 {
-       size_t i;
-       int error;
+       git_remote_connect_options tmp = GIT_REMOTE_CONNECT_OPTIONS_INIT;
+       copy_opts(&tmp, push_opts);
+       return git_remote_connect_options_normalize(out, remote->repo, &tmp);
+}
+
+int git_remote_upload(
+       git_remote *remote,
+       const git_strarray *refspecs,
+       const git_push_options *opts)
+{
+       git_remote_connect_options connect_opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
        git_push *push;
        git_refspec *spec;
-       const git_remote_callbacks *cbs = NULL;
-       git_remote_connection_opts conn = GIT_REMOTE_CONNECTION_OPTIONS_INIT;
+       size_t i;
+       int error;
 
        GIT_ASSERT_ARG(remote);
 
@@ -2624,14 +2924,10 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
                return -1;
        }
 
-       if (opts) {
-               cbs = &opts->callbacks;
-               conn.custom_headers = &opts->custom_headers;
-               conn.proxy = &opts->proxy_opts;
-       }
+       if ((error = connect_opts_from_push_opts(&connect_opts, remote, opts)) < 0)
+               goto cleanup;
 
-       if (!git_remote_connected(remote) &&
-           (error = git_remote__connect(remote, GIT_DIRECTION_PUSH, cbs, &conn)) < 0)
+       if ((error = connect_or_reset_options(remote, GIT_DIRECTION_PUSH, &connect_opts)) < 0)
                goto cleanup;
 
        free_refspecs(&remote->active_refspecs);
@@ -2643,14 +2939,11 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
                remote->push = NULL;
        }
 
-       if ((error = git_push_new(&remote->push, remote)) < 0)
-               return error;
+       if ((error = git_push_new(&remote->push, remote, opts)) < 0)
+               goto cleanup;
 
        push = remote->push;
 
-       if (opts && (error = git_push_set_options(push, opts)) < 0)
-               goto cleanup;
-
        if (refspecs && refspecs->count > 0) {
                for (i = 0; i < refspecs->count; i++) {
                        if ((error = git_push_add_refspec(push, refspecs->strings[i])) < 0)
@@ -2665,23 +2958,25 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
                }
        }
 
-       if ((error = git_push_finish(push, cbs)) < 0)
+       if ((error = git_push_finish(push)) < 0)
                goto cleanup;
 
-       if (cbs && cbs->push_update_reference &&
-           (error = git_push_status_foreach(push, cbs->push_update_reference, cbs->payload)) < 0)
+       if (connect_opts.callbacks.push_update_reference &&
+           (error = git_push_status_foreach(push, connect_opts.callbacks.push_update_reference, connect_opts.callbacks.payload)) < 0)
                goto cleanup;
 
 cleanup:
+       git_remote_connect_options_dispose(&connect_opts);
        return error;
 }
 
-int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts)
+int git_remote_push(
+       git_remote *remote,
+       const git_strarray *refspecs,
+       const git_push_options *opts)
 {
+       git_remote_connect_options connect_opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
        int error;
-       const git_remote_callbacks *cbs = NULL;
-       const git_strarray *custom_headers = NULL;
-       const git_proxy_options *proxy = NULL;
 
        GIT_ASSERT_ARG(remote);
 
@@ -2690,23 +2985,17 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_
                return -1;
        }
 
-       if (opts) {
-               GIT_ERROR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
-               cbs = &opts->callbacks;
-               custom_headers = &opts->custom_headers;
-               GIT_ERROR_CHECK_VERSION(&opts->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
-               proxy = &opts->proxy_opts;
-       }
-
-       if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs, proxy, custom_headers)) < 0)
-               return error;
+       if (connect_opts_from_push_opts(&connect_opts, remote, opts) < 0)
+               return -1;
 
        if ((error = git_remote_upload(remote, refspecs, opts)) < 0)
-               return error;
+               goto done;
 
-       error = git_remote_update_tips(remote, cbs, 0, 0, NULL);
+       error = git_remote_update_tips(remote, &connect_opts.callbacks, 0, 0, NULL);
 
+done:
        git_remote_disconnect(remote);
+       git_remote_connect_options_dispose(&connect_opts);
        return error;
 }
 
@@ -2714,19 +3003,20 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_
 #define SUFFIX_FETCH "insteadof"
 #define SUFFIX_PUSH "pushinsteadof"
 
-char *apply_insteadof(git_config *config, const char *url, int direction)
+static int apply_insteadof(char **out, git_config *config, const char *url, int direction, bool use_default_if_empty)
 {
        size_t match_length, prefix_length, suffix_length;
        char *replacement = NULL;
        const char *regexp;
 
-       git_buf result = GIT_BUF_INIT;
+       git_str result = GIT_STR_INIT;
        git_config_entry *entry;
        git_config_iterator *iter;
 
-       GIT_ASSERT_ARG_WITH_RETVAL(config, NULL);
-       GIT_ASSERT_ARG_WITH_RETVAL(url, NULL);
-       GIT_ASSERT_ARG_WITH_RETVAL(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH, NULL);
+       GIT_ASSERT_ARG(out);
+       GIT_ASSERT_ARG(config);
+       GIT_ASSERT_ARG(url);
+       GIT_ASSERT_ARG(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH);
 
        /* Add 1 to prefix/suffix length due to the additional escaped dot */
        prefix_length = strlen(PREFIX) + 1;
@@ -2739,7 +3029,7 @@ char *apply_insteadof(git_config *config, const char *url, int direction)
        }
 
        if (git_config_iterator_glob_new(&iter, config, regexp) < 0)
-               return NULL;
+               return -1;
 
        match_length = 0;
        while (git_config_next(&entry, iter) == 0) {
@@ -2748,6 +3038,7 @@ char *apply_insteadof(git_config *config, const char *url, int direction)
                /* Check if entry value is a prefix of URL */
                if (git__prefixcmp(url, entry->value))
                        continue;
+
                /* Check if entry value is longer than previous
                 * prefixes */
                if ((n = strlen(entry->value)) <= match_length)
@@ -2765,14 +3056,20 @@ char *apply_insteadof(git_config *config, const char *url, int direction)
 
        git_config_iterator_free(iter);
 
-       if (match_length == 0)
-               return git__strdup(url);
+       if (match_length == 0 && use_default_if_empty) {
+               *out = git__strdup(url);
+               return *out ? 0 : -1;
+       } else if (match_length == 0) {
+               *out = NULL;
+               return 0;
+       }
 
-       git_buf_printf(&result, "%s%s", replacement, url + match_length);
+       git_str_printf(&result, "%s%s", replacement, url + match_length);
 
        git__free(replacement);
 
-       return result.ptr;
+       *out = git_str_detach(&result);
+       return 0;
 }
 
 /* Deprecated functions */
index ce92db76aa5b16e391415873443957e5ca3aff81..ea9c7d17ff869f1a734f966fbb462accb9ca7d39 100644 (file)
@@ -27,6 +27,7 @@ struct git_remote {
        git_vector refspecs;
        git_vector active_refspecs;
        git_vector passive_refspecs;
+       git_vector local_heads;
        git_transport *transport;
        git_repository *repo;
        git_push *push;
@@ -37,19 +38,23 @@ struct git_remote {
        int passed_refspecs;
 };
 
-typedef struct git_remote_connection_opts {
-       const git_strarray *custom_headers;
-       const git_proxy_options *proxy;
-} git_remote_connection_opts;
-
-#define GIT_REMOTE_CONNECTION_OPTIONS_INIT { NULL, NULL }
-
-int git_remote__connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_remote_connection_opts *conn);
-
-int git_remote__urlfordirection(git_buf *url_out, struct git_remote *remote, int direction, const git_remote_callbacks *callbacks);
+int git_remote__urlfordirection(git_str *url_out, struct git_remote *remote, int direction, const git_remote_callbacks *callbacks);
 int git_remote__http_proxy(char **out, git_remote *remote, git_net_url *url);
 
 git_refspec *git_remote__matching_refspec(git_remote *remote, const char *refname);
 git_refspec *git_remote__matching_dst_refspec(git_remote *remote, const char *refname);
 
+int git_remote__default_branch(git_str *out, git_remote *remote);
+
+int git_remote_connect_options_dup(
+       git_remote_connect_options *dst,
+       const git_remote_connect_options *src);
+int git_remote_connect_options_normalize(
+       git_remote_connect_options *dst,
+       git_repository *repo,
+       const git_remote_connect_options *src);
+void git_remote_connect_options_dispose(git_remote_connect_options *opts);
+
+int git_remote_capabilities(unsigned int *out, git_remote *remote);
+
 #endif
index 9b3e9c9e3b13b0ecf0637e6edd579a551d5038f5..6119c1c70b39fac624470a9a76c246a8a8f74d89 100644 (file)
@@ -12,6 +12,7 @@
 #include "git2/object.h"
 #include "git2/sys/repository.h"
 
+#include "buf.h"
 #include "common.h"
 #include "commit.h"
 #include "tag.h"
 #include "annotated_commit.h"
 #include "submodule.h"
 #include "worktree.h"
-
+#include "path.h"
 #include "strmap.h"
 
 #ifdef GIT_WIN32
 # include "win32/w32_util.h"
 #endif
 
+bool git_repository__validate_ownership = true;
 bool git_repository__fsync_gitdir = false;
 
 static const struct {
@@ -64,6 +66,7 @@ static const struct {
 
 static int check_repositoryformatversion(int *version, git_config *config);
 static int check_extensions(git_config *config, int version);
+static int load_global_config(git_config **config);
 
 #define GIT_COMMONDIR_FILE "commondir"
 #define GIT_GITDIR_FILE "gitdir"
@@ -75,13 +78,13 @@ static int check_extensions(git_config *config, int version);
 #define GIT_REPO_VERSION 0
 #define GIT_REPO_MAX_VERSION 1
 
-git_buf git_repository__reserved_names_win32[] = {
+git_str git_repository__reserved_names_win32[] = {
        { DOT_GIT, 0, CONST_STRLEN(DOT_GIT) },
        { GIT_DIR_SHORTNAME, 0, CONST_STRLEN(GIT_DIR_SHORTNAME) }
 };
 size_t git_repository__reserved_names_win32_len = 2;
 
-git_buf git_repository__reserved_names_posix[] = {
+git_str git_repository__reserved_names_posix[] = {
        { DOT_GIT, 0, CONST_STRLEN(DOT_GIT) },
 };
 size_t git_repository__reserved_names_posix_len = 1;
@@ -171,7 +174,7 @@ void git_repository_free(git_repository *repo)
        repo->diff_drivers = NULL;
 
        for (i = 0; i < repo->reserved_names.size; i++)
-               git_buf_dispose(git_array_get(repo->reserved_names, i));
+               git_str_dispose(git_array_get(repo->reserved_names, i));
        git_array_clear(repo->reserved_names);
 
        git__free(repo->gitlink);
@@ -187,18 +190,18 @@ void git_repository_free(git_repository *repo)
 }
 
 /* Check if we have a separate commondir (e.g. we have a worktree) */
-static int lookup_commondir(bool *separate, git_buf *commondir, git_buf *repository_path)
+static int lookup_commondir(bool *separate, git_str *commondir, git_str *repository_path)
 {
-       git_buf common_link  = GIT_BUF_INIT;
+       git_str common_link  = GIT_STR_INIT;
        int error;
 
        /*
         * If there's no commondir file, the repository path is the
         * common path, but it needs a trailing slash.
         */
-       if (!git_path_contains_file(repository_path, GIT_COMMONDIR_FILE)) {
-               if ((error = git_buf_set(commondir, repository_path->ptr, repository_path->size)) == 0)
-                   error = git_path_to_dir(commondir);
+       if (!git_fs_path_contains_file(repository_path, GIT_COMMONDIR_FILE)) {
+               if ((error = git_str_set(commondir, repository_path->ptr, repository_path->size)) == 0)
+                   error = git_fs_path_to_dir(commondir);
 
                *separate = false;
                goto done;
@@ -206,28 +209,28 @@ static int lookup_commondir(bool *separate, git_buf *commondir, git_buf *reposit
 
        *separate = true;
 
-       if ((error = git_buf_joinpath(&common_link, repository_path->ptr, GIT_COMMONDIR_FILE)) < 0 ||
+       if ((error = git_str_joinpath(&common_link, repository_path->ptr, GIT_COMMONDIR_FILE)) < 0 ||
            (error = git_futils_readbuffer(&common_link, common_link.ptr)) < 0)
                goto done;
 
-       git_buf_rtrim(&common_link);
-       if (git_path_is_relative(common_link.ptr)) {
-               if ((error = git_buf_joinpath(commondir, repository_path->ptr, common_link.ptr)) < 0)
+       git_str_rtrim(&common_link);
+       if (git_fs_path_is_relative(common_link.ptr)) {
+               if ((error = git_str_joinpath(commondir, repository_path->ptr, common_link.ptr)) < 0)
                        goto done;
        } else {
-               git_buf_swap(commondir, &common_link);
+               git_str_swap(commondir, &common_link);
        }
 
-       git_buf_dispose(&common_link);
+       git_str_dispose(&common_link);
 
        /* Make sure the commondir path always has a trailing slash */
-       error = git_path_prettify_dir(commondir, commondir->ptr, NULL);
+       error = git_fs_path_prettify_dir(commondir, commondir->ptr, NULL);
 
 done:
        return error;
 }
 
-GIT_INLINE(int) validate_repo_path(git_buf *path)
+GIT_INLINE(int) validate_repo_path(git_str *path)
 {
        /*
         * The longest static path in a repository (or commondir) is the
@@ -239,8 +242,8 @@ GIT_INLINE(int) validate_repo_path(git_buf *path)
                CONST_STRLEN("objects/pack/pack-.pack.lock") +
                GIT_OID_HEXSZ;
 
-       return git_path_validate_filesystem_with_suffix(
-               path->ptr, path->size, suffix_len);
+       return git_fs_path_validate_str_length_with_suffix(
+               path, suffix_len);
 }
 
 /*
@@ -248,7 +251,7 @@ GIT_INLINE(int) validate_repo_path(git_buf *path)
  *
  * Open a repository object from its path
  */
-static int is_valid_repository_path(bool *out, git_buf *repository_path, git_buf *common_path)
+static int is_valid_repository_path(bool *out, git_str *repository_path, git_str *common_path)
 {
        bool separate_commondir = false;
        int error;
@@ -259,13 +262,13 @@ static int is_valid_repository_path(bool *out, git_buf *repository_path, git_buf
                return error;
 
        /* Ensure HEAD file exists */
-       if (git_path_contains_file(repository_path, GIT_HEAD_FILE) == false)
+       if (git_fs_path_contains_file(repository_path, GIT_HEAD_FILE) == false)
                return 0;
 
        /* Check files in common dir */
-       if (git_path_contains_dir(common_path, GIT_OBJECTS_DIR) == false)
+       if (git_fs_path_contains_dir(common_path, GIT_OBJECTS_DIR) == false)
                return 0;
-       if (git_path_contains_dir(common_path, GIT_REFS_DIR) == false)
+       if (git_fs_path_contains_dir(common_path, GIT_REFS_DIR) == false)
                return 0;
 
        /* Ensure the repo (and commondir) are valid paths */
@@ -333,12 +336,12 @@ static int load_config_data(git_repository *repo, const git_config *config)
        return 0;
 }
 
-static int load_workdir(git_repository *repo, git_config *config, git_buf *parent_path)
+static int load_workdir(git_repository *repo, git_config *config, git_str *parent_path)
 {
        int error;
        git_config_entry *ce;
-       git_buf worktree = GIT_BUF_INIT;
-       git_buf path = GIT_BUF_INIT;
+       git_str worktree = GIT_STR_INIT;
+       git_str path = GIT_STR_INIT;
 
        if (repo->is_bare)
                return 0;
@@ -354,38 +357,38 @@ static int load_workdir(git_repository *repo, git_config *config, git_buf *paren
                        goto cleanup;
                }
 
-               git_buf_attach(&worktree, gitlink, 0);
+               git_str_attach(&worktree, gitlink, 0);
 
-               if ((git_path_dirname_r(&worktree, worktree.ptr)) < 0 ||
-                   git_path_to_dir(&worktree) < 0) {
+               if ((git_fs_path_dirname_r(&worktree, worktree.ptr)) < 0 ||
+                   git_fs_path_to_dir(&worktree) < 0) {
                        error = -1;
                        goto cleanup;
                }
 
-               repo->workdir = git_buf_detach(&worktree);
+               repo->workdir = git_str_detach(&worktree);
        }
        else if (ce && ce->value) {
-               if ((error = git_path_prettify_dir(
+               if ((error = git_fs_path_prettify_dir(
                                &worktree, ce->value, repo->gitdir)) < 0)
                        goto cleanup;
 
-               repo->workdir = git_buf_detach(&worktree);
+               repo->workdir = git_str_detach(&worktree);
        }
-       else if (parent_path && git_path_isdir(parent_path->ptr))
-               repo->workdir = git_buf_detach(parent_path);
+       else if (parent_path && git_fs_path_isdir(parent_path->ptr))
+               repo->workdir = git_str_detach(parent_path);
        else {
-               if (git_path_dirname_r(&worktree, repo->gitdir) < 0 ||
-                   git_path_to_dir(&worktree) < 0) {
+               if (git_fs_path_dirname_r(&worktree, repo->gitdir) < 0 ||
+                   git_fs_path_to_dir(&worktree) < 0) {
                        error = -1;
                        goto cleanup;
                }
 
-               repo->workdir = git_buf_detach(&worktree);
+               repo->workdir = git_str_detach(&worktree);
        }
 
        GIT_ERROR_CHECK_ALLOC(repo->workdir);
 cleanup:
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_config_entry_free(ce);
        return error;
 }
@@ -394,7 +397,7 @@ cleanup:
  * This function returns furthest offset into path where a ceiling dir
  * is found, so we can stop processing the path at that point.
  *
- * Note: converting this to use git_bufs instead of GIT_PATH_MAX buffers on
+ * Note: converting this to use git_strs instead of GIT_PATH_MAX buffers on
  * the stack could remove directories name limits, but at the cost of doing
  * repeated malloc/frees inside the loop below, so let's not do it now.
  */
@@ -409,7 +412,7 @@ static size_t find_ceiling_dir_offset(
 
        GIT_ASSERT_ARG(path);
 
-       min_len = (size_t)(git_path_root(path) + 1);
+       min_len = (size_t)(git_fs_path_root(path) + 1);
 
        if (ceiling_directories == NULL || min_len == 0)
                return min_len;
@@ -418,7 +421,7 @@ static size_t find_ceiling_dir_offset(
                for (sep = ceil; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++);
                len = sep - ceil;
 
-               if (len == 0 || len >= sizeof(buf) || git_path_root(ceil) == -1)
+               if (len == 0 || len >= sizeof(buf) || git_fs_path_root(ceil) == -1)
                        continue;
 
                strncpy(buf, ceil, len);
@@ -447,10 +450,10 @@ static size_t find_ceiling_dir_offset(
  * it points to.  Before calling, set `path_out` to the base directory that
  * should be used if the contents of `file_path` are a relative path.
  */
-static int read_gitfile(git_buf *path_out, const char *file_path)
+static int read_gitfile(git_str *path_out, const char *file_path)
 {
        int     error = 0;
-       git_buf file = GIT_BUF_INIT;
+       git_str file = GIT_STR_INIT;
        size_t  prefix_len = strlen(GIT_FILE_CONTENT_PREFIX);
 
        GIT_ASSERT_ARG(path_out);
@@ -459,41 +462,98 @@ static int read_gitfile(git_buf *path_out, const char *file_path)
        if (git_futils_readbuffer(&file, file_path) < 0)
                return -1;
 
-       git_buf_rtrim(&file);
+       git_str_rtrim(&file);
        /* apparently on Windows, some people use backslashes in paths */
-       git_path_mkposix(file.ptr);
+       git_fs_path_mkposix(file.ptr);
 
-       if (git_buf_len(&file) <= prefix_len ||
-               memcmp(git_buf_cstr(&file), GIT_FILE_CONTENT_PREFIX, prefix_len) != 0)
+       if (git_str_len(&file) <= prefix_len ||
+               memcmp(git_str_cstr(&file), GIT_FILE_CONTENT_PREFIX, prefix_len) != 0)
        {
                git_error_set(GIT_ERROR_REPOSITORY,
                        "the `.git` file at '%s' is malformed", file_path);
                error = -1;
        }
-       else if ((error = git_path_dirname_r(path_out, file_path)) >= 0) {
-               const char *gitlink = git_buf_cstr(&file) + prefix_len;
+       else if ((error = git_fs_path_dirname_r(path_out, file_path)) >= 0) {
+               const char *gitlink = git_str_cstr(&file) + prefix_len;
                while (*gitlink && git__isspace(*gitlink)) gitlink++;
 
-               error = git_path_prettify_dir(
-                       path_out, gitlink, git_buf_cstr(path_out));
+               error = git_fs_path_prettify_dir(
+                       path_out, gitlink, git_str_cstr(path_out));
+       }
+
+       git_str_dispose(&file);
+       return error;
+}
+
+typedef struct {
+       const char *repo_path;
+       git_str tmp;
+       bool is_safe;
+} validate_ownership_data;
+
+static int validate_ownership_cb(const git_config_entry *entry, void *payload)
+{
+       validate_ownership_data *data = payload;
+
+       if (strcmp(entry->value, "") == 0)
+               data->is_safe = false;
+
+       if (git_fs_path_prettify_dir(&data->tmp, entry->value, NULL) == 0 &&
+           strcmp(data->tmp.ptr, data->repo_path) == 0)
+               data->is_safe = true;
+
+       return 0;
+}
+
+static int validate_ownership(const char *repo_path)
+{
+       git_config *config = NULL;
+       validate_ownership_data data = { repo_path, GIT_STR_INIT, false };
+       bool is_safe;
+       int error;
+
+       if ((error = git_fs_path_owner_is_current_user(&is_safe, repo_path)) < 0) {
+               if (error == GIT_ENOTFOUND)
+                       error = 0;
+
+               goto done;
        }
 
-       git_buf_dispose(&file);
+       if (is_safe) {
+               error = 0;
+               goto done;
+       }
+
+       if (load_global_config(&config) == 0) {
+               error = git_config_get_multivar_foreach(config, "safe.directory", NULL, validate_ownership_cb, &data);
+
+               if (!error && data.is_safe)
+                       goto done;
+       }
+
+       git_error_set(GIT_ERROR_CONFIG,
+               "repository path '%s' is not owned by current user",
+               repo_path);
+       error = GIT_EOWNER;
+
+done:
+       git_config_free(config);
+       git_str_dispose(&data.tmp);
        return error;
 }
 
 static int find_repo(
-       git_buf *gitdir_path,
-       git_buf *workdir_path,
-       git_buf *gitlink_path,
-       git_buf *commondir_path,
+       git_str *gitdir_path,
+       git_str *workdir_path,
+       git_str *gitlink_path,
+       git_str *commondir_path,
        const char *start_path,
        uint32_t flags,
        const char *ceiling_dirs)
 {
-       git_buf path = GIT_BUF_INIT;
-       git_buf repo_link = GIT_BUF_INIT;
-       git_buf common_link = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
+       git_str repo_link = GIT_STR_INIT;
+       git_str common_link = GIT_STR_INIT;
        struct stat st;
        dev_t initial_device = 0;
        int min_iterations;
@@ -501,9 +561,9 @@ static int find_repo(
        size_t ceiling_offset = 0;
        int error;
 
-       git_buf_clear(gitdir_path);
+       git_str_clear(gitdir_path);
 
-       error = git_path_prettify(&path, start_path, NULL);
+       error = git_fs_path_prettify(&path, start_path, NULL);
        if (error < 0)
                return error;
 
@@ -525,7 +585,7 @@ static int find_repo(
        for (;;) {
                if (!(flags & GIT_REPOSITORY_OPEN_NO_DOTGIT)) {
                        if (!in_dot_git) {
-                               if ((error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
+                               if ((error = git_str_joinpath(&path, path.ptr, DOT_GIT)) < 0)
                                        goto out;
                        }
                        in_dot_git = !in_dot_git;
@@ -544,15 +604,15 @@ static int find_repo(
                                        goto out;
 
                                if (is_valid) {
-                                       if ((error = git_path_to_dir(&path)) < 0 ||
-                                           (error = git_buf_set(gitdir_path, path.ptr, path.size)) < 0)
+                                       if ((error = git_fs_path_to_dir(&path)) < 0 ||
+                                           (error = git_str_set(gitdir_path, path.ptr, path.size)) < 0)
                                                goto out;
 
                                        if (gitlink_path)
-                                               if ((error = git_buf_attach(gitlink_path, git_worktree__read_link(path.ptr, GIT_GITDIR_FILE), 0)) < 0)
+                                               if ((error = git_str_attach(gitlink_path, git_worktree__read_link(path.ptr, GIT_GITDIR_FILE), 0)) < 0)
                                                        goto out;
                                        if (commondir_path)
-                                               git_buf_swap(&common_link, commondir_path);
+                                               git_str_swap(&common_link, commondir_path);
 
                                        break;
                                }
@@ -562,13 +622,13 @@ static int find_repo(
                                        goto out;
 
                                if (is_valid) {
-                                       git_buf_swap(gitdir_path, &repo_link);
+                                       git_str_swap(gitdir_path, &repo_link);
 
                                        if (gitlink_path)
-                                               if ((error = git_buf_put(gitlink_path, path.ptr, path.size)) < 0)
+                                               if ((error = git_str_put(gitlink_path, path.ptr, path.size)) < 0)
                                                        goto out;
                                        if (commondir_path)
-                                               git_buf_swap(&common_link, commondir_path);
+                                               git_str_swap(&common_link, commondir_path);
                                }
                                break;
                        }
@@ -577,7 +637,7 @@ static int find_repo(
                /* Move up one directory. If we're in_dot_git, we'll search the
                 * parent itself next. If we're !in_dot_git, we'll search .git
                 * in the parent directory next (added at the top of the loop). */
-               if ((error = git_path_dirname_r(&path, path.ptr)) < 0)
+               if ((error = git_fs_path_dirname_r(&path, path.ptr)) < 0)
                        goto out;
 
                /* Once we've checked the directory (and .git if applicable),
@@ -592,25 +652,25 @@ static int find_repo(
        }
 
        if (workdir_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
-               if (!git_buf_len(gitdir_path))
-                       git_buf_clear(workdir_path);
-               else if ((error = git_path_dirname_r(workdir_path, path.ptr)) < 0 ||
-                        (error = git_path_to_dir(workdir_path)) < 0)
+               if (!git_str_len(gitdir_path))
+                       git_str_clear(workdir_path);
+               else if ((error = git_fs_path_dirname_r(workdir_path, path.ptr)) < 0 ||
+                        (error = git_fs_path_to_dir(workdir_path)) < 0)
                        goto out;
        }
 
        /* If we didn't find the repository, and we don't have any other error
         * to report, report that. */
-       if (!git_buf_len(gitdir_path)) {
+       if (!git_str_len(gitdir_path)) {
                git_error_set(GIT_ERROR_REPOSITORY, "could not find repository from '%s'", start_path);
                error = GIT_ENOTFOUND;
                goto out;
        }
 
 out:
-       git_buf_dispose(&path);
-       git_buf_dispose(&repo_link);
-       git_buf_dispose(&common_link);
+       git_str_dispose(&path);
+       git_str_dispose(&repo_link);
+       git_str_dispose(&common_link);
        return error;
 }
 
@@ -618,18 +678,18 @@ int git_repository_open_bare(
        git_repository **repo_ptr,
        const char *bare_path)
 {
-       git_buf path = GIT_BUF_INIT, common_path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT, common_path = GIT_STR_INIT;
        git_repository *repo = NULL;
        bool is_valid;
        int error;
 
-       if ((error = git_path_prettify_dir(&path, bare_path, NULL)) < 0 ||
+       if ((error = git_fs_path_prettify_dir(&path, bare_path, NULL)) < 0 ||
            (error = is_valid_repository_path(&is_valid, &path, &common_path)) < 0)
                return error;
 
        if (!is_valid) {
-               git_buf_dispose(&path);
-               git_buf_dispose(&common_path);
+               git_str_dispose(&path);
+               git_str_dispose(&common_path);
                git_error_set(GIT_ERROR_REPOSITORY, "path is not a repository: %s", bare_path);
                return GIT_ENOTFOUND;
        }
@@ -637,9 +697,9 @@ int git_repository_open_bare(
        repo = repository_alloc();
        GIT_ERROR_CHECK_ALLOC(repo);
 
-       repo->gitdir = git_buf_detach(&path);
+       repo->gitdir = git_str_detach(&path);
        GIT_ERROR_CHECK_ALLOC(repo->gitdir);
-       repo->commondir = git_buf_detach(&common_path);
+       repo->commondir = git_str_detach(&common_path);
        GIT_ERROR_CHECK_ALLOC(repo->commondir);
 
        /* of course we're bare! */
@@ -658,15 +718,15 @@ static int _git_repository_open_ext_from_env(
        git_repository *repo = NULL;
        git_index *index = NULL;
        git_odb *odb = NULL;
-       git_buf dir_buf = GIT_BUF_INIT;
-       git_buf ceiling_dirs_buf = GIT_BUF_INIT;
-       git_buf across_fs_buf = GIT_BUF_INIT;
-       git_buf index_file_buf = GIT_BUF_INIT;
-       git_buf namespace_buf = GIT_BUF_INIT;
-       git_buf object_dir_buf = GIT_BUF_INIT;
-       git_buf alts_buf = GIT_BUF_INIT;
-       git_buf work_tree_buf = GIT_BUF_INIT;
-       git_buf common_dir_buf = GIT_BUF_INIT;
+       git_str dir_buf = GIT_STR_INIT;
+       git_str ceiling_dirs_buf = GIT_STR_INIT;
+       git_str across_fs_buf = GIT_STR_INIT;
+       git_str index_file_buf = GIT_STR_INIT;
+       git_str namespace_buf = GIT_STR_INIT;
+       git_str object_dir_buf = GIT_STR_INIT;
+       git_str alts_buf = GIT_STR_INIT;
+       git_str work_tree_buf = GIT_STR_INIT;
+       git_str common_dir_buf = GIT_STR_INIT;
        const char *ceiling_dirs = NULL;
        unsigned flags = 0;
        int error;
@@ -679,7 +739,7 @@ static int _git_repository_open_ext_from_env(
                } else if (error < 0)
                        goto error;
                else {
-                       start_path = git_buf_cstr(&dir_buf);
+                       start_path = git_str_cstr(&dir_buf);
                        flags |= GIT_REPOSITORY_OPEN_NO_SEARCH;
                        flags |= GIT_REPOSITORY_OPEN_NO_DOTGIT;
                }
@@ -691,7 +751,7 @@ static int _git_repository_open_ext_from_env(
        else if (error < 0)
                goto error;
        else
-               ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
+               ceiling_dirs = git_str_cstr(&ceiling_dirs_buf);
 
        error = git__getenv(&across_fs_buf, "GIT_DISCOVERY_ACROSS_FILESYSTEM");
        if (error == GIT_ENOTFOUND)
@@ -700,7 +760,7 @@ static int _git_repository_open_ext_from_env(
                goto error;
        else {
                int across_fs = 0;
-               error = git_config_parse_bool(&across_fs, git_buf_cstr(&across_fs_buf));
+               error = git_config_parse_bool(&across_fs, git_str_cstr(&across_fs_buf));
                if (error < 0)
                        goto error;
                if (across_fs)
@@ -713,7 +773,7 @@ static int _git_repository_open_ext_from_env(
        else if (error < 0)
                goto error;
        else {
-               error = git_index_open(&index, git_buf_cstr(&index_file_buf));
+               error = git_index_open(&index, git_str_cstr(&index_file_buf));
                if (error < 0)
                        goto error;
        }
@@ -730,7 +790,7 @@ static int _git_repository_open_ext_from_env(
        else if (error < 0)
                goto error;
        else {
-               error = git_odb_open(&odb, git_buf_cstr(&object_dir_buf));
+               error = git_odb_open(&odb, git_str_cstr(&object_dir_buf));
                if (error < 0)
                        goto error;
        }
@@ -779,7 +839,7 @@ static int _git_repository_open_ext_from_env(
                                goto error;
                }
 
-               end = git_buf_cstr(&alts_buf) + git_buf_len(&alts_buf);
+               end = git_str_cstr(&alts_buf) + git_str_len(&alts_buf);
                for (sep = alt = alts_buf.ptr; sep != end; alt = sep+1) {
                        for (sep = alt; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++)
                                ;
@@ -791,8 +851,8 @@ static int _git_repository_open_ext_from_env(
                }
        }
 
-       if (git_buf_len(&namespace_buf)) {
-               error = git_repository_set_namespace(repo, git_buf_cstr(&namespace_buf));
+       if (git_str_len(&namespace_buf)) {
+               error = git_repository_set_namespace(repo, git_str_cstr(&namespace_buf));
                if (error < 0)
                        goto error;
        }
@@ -808,21 +868,21 @@ error:
 success:
        git_odb_free(odb);
        git_index_free(index);
-       git_buf_dispose(&common_dir_buf);
-       git_buf_dispose(&work_tree_buf);
-       git_buf_dispose(&alts_buf);
-       git_buf_dispose(&object_dir_buf);
-       git_buf_dispose(&namespace_buf);
-       git_buf_dispose(&index_file_buf);
-       git_buf_dispose(&across_fs_buf);
-       git_buf_dispose(&ceiling_dirs_buf);
-       git_buf_dispose(&dir_buf);
+       git_str_dispose(&common_dir_buf);
+       git_str_dispose(&work_tree_buf);
+       git_str_dispose(&alts_buf);
+       git_str_dispose(&object_dir_buf);
+       git_str_dispose(&namespace_buf);
+       git_str_dispose(&index_file_buf);
+       git_str_dispose(&across_fs_buf);
+       git_str_dispose(&ceiling_dirs_buf);
+       git_str_dispose(&dir_buf);
        return error;
 }
 
 static int repo_is_worktree(unsigned *out, const git_repository *repo)
 {
-       git_buf gitdir_link = GIT_BUF_INIT;
+       git_str gitdir_link = GIT_STR_INIT;
        int error;
 
        /* Worktrees cannot have the same commondir and gitdir */
@@ -832,14 +892,14 @@ static int repo_is_worktree(unsigned *out, const git_repository *repo)
                return 0;
        }
 
-       if ((error = git_buf_joinpath(&gitdir_link, repo->gitdir, "gitdir")) < 0)
+       if ((error = git_str_joinpath(&gitdir_link, repo->gitdir, "gitdir")) < 0)
                return -1;
 
        /* A 'gitdir' file inside a git directory is currently
         * only used when the repository is a working tree. */
-       *out = !!git_path_exists(gitdir_link.ptr);
+       *out = !!git_fs_path_exists(gitdir_link.ptr);
 
-       git_buf_dispose(&gitdir_link);
+       git_str_dispose(&gitdir_link);
        return error;
 }
 
@@ -851,10 +911,11 @@ int git_repository_open_ext(
 {
        int error;
        unsigned is_worktree;
-       git_buf gitdir = GIT_BUF_INIT, workdir = GIT_BUF_INIT,
-               gitlink = GIT_BUF_INIT, commondir = GIT_BUF_INIT;
+       git_str gitdir = GIT_STR_INIT, workdir = GIT_STR_INIT,
+               gitlink = GIT_STR_INIT, commondir = GIT_STR_INIT;
        git_repository *repo = NULL;
        git_config *config = NULL;
+       const char *validation_path;
        int version = 0;
 
        if (flags & GIT_REPOSITORY_OPEN_FROM_ENV)
@@ -872,15 +933,15 @@ int git_repository_open_ext(
        repo = repository_alloc();
        GIT_ERROR_CHECK_ALLOC(repo);
 
-       repo->gitdir = git_buf_detach(&gitdir);
+       repo->gitdir = git_str_detach(&gitdir);
        GIT_ERROR_CHECK_ALLOC(repo->gitdir);
 
        if (gitlink.size) {
-               repo->gitlink = git_buf_detach(&gitlink);
+               repo->gitlink = git_str_detach(&gitlink);
                GIT_ERROR_CHECK_ALLOC(repo->gitlink);
        }
        if (commondir.size) {
-               repo->commondir = git_buf_detach(&commondir);
+               repo->commondir = git_str_detach(&commondir);
                GIT_ERROR_CHECK_ALLOC(repo->commondir);
        }
 
@@ -903,21 +964,29 @@ int git_repository_open_ext(
        if ((error = check_extensions(config, version)) < 0)
                goto cleanup;
 
-       if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0)
+       if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) {
                repo->is_bare = 1;
-       else {
-
+       } else {
                if (config &&
                    ((error = load_config_data(repo, config)) < 0 ||
                     (error = load_workdir(repo, config, &workdir)) < 0))
                        goto cleanup;
        }
 
+       /*
+        * Ensure that the git directory is owned by the current user.
+        */
+       validation_path = repo->is_bare ? repo->gitdir : repo->workdir;
+
+       if (git_repository__validate_ownership &&
+           (error = validate_ownership(validation_path)) < 0)
+               goto cleanup;
+
 cleanup:
-       git_buf_dispose(&gitdir);
-       git_buf_dispose(&workdir);
-       git_buf_dispose(&gitlink);
-       git_buf_dispose(&commondir);
+       git_str_dispose(&gitdir);
+       git_str_dispose(&workdir);
+       git_str_dispose(&gitlink);
+       git_str_dispose(&commondir);
        git_config_free(config);
 
        if (error < 0)
@@ -936,7 +1005,7 @@ int git_repository_open(git_repository **repo_out, const char *path)
 
 int git_repository_open_from_worktree(git_repository **repo_out, git_worktree *wt)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_repository *repo = NULL;
        size_t len;
        int err;
@@ -952,7 +1021,7 @@ int git_repository_open_from_worktree(git_repository **repo_out, git_worktree *w
                goto out;
        }
 
-       if ((err = git_buf_set(&path, wt->gitlink_path, len - 4)) < 0)
+       if ((err = git_str_set(&path, wt->gitlink_path, len - 4)) < 0)
                goto out;
 
        if ((err = git_repository_open(&repo, path.ptr)) < 0)
@@ -961,7 +1030,7 @@ int git_repository_open_from_worktree(git_repository **repo_out, git_worktree *w
        *repo_out = repo;
 
 out:
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return err;
 }
@@ -986,14 +1055,10 @@ int git_repository_discover(
        const char *ceiling_dirs)
 {
        uint32_t flags = across_fs ? GIT_REPOSITORY_OPEN_CROSS_FS : 0;
-       int error;
 
        GIT_ASSERT_ARG(start_path);
 
-       if ((error = git_buf_sanitize(out)) < 0)
-               return error;
-
-       return find_repo(out, NULL, NULL, NULL, start_path, flags, ceiling_dirs);
+       GIT_BUF_WRAP_PRIVATE(out, find_repo, NULL, NULL, NULL, start_path, flags, ceiling_dirs);
 }
 
 static int load_config(
@@ -1005,7 +1070,7 @@ static int load_config(
        const char *programdata_path)
 {
        int error;
-       git_buf config_path = GIT_BUF_INIT;
+       git_str config_path = GIT_STR_INIT;
        git_config *cfg = NULL;
 
        GIT_ASSERT_ARG(out);
@@ -1014,13 +1079,13 @@ static int load_config(
                return error;
 
        if (repo) {
-               if ((error = git_repository_item_path(&config_path, repo, GIT_REPOSITORY_ITEM_CONFIG)) == 0)
+               if ((error = git_repository__item_path(&config_path, repo, GIT_REPOSITORY_ITEM_CONFIG)) == 0)
                        error = git_config_add_file_ondisk(cfg, config_path.ptr, GIT_CONFIG_LEVEL_LOCAL, repo, 0);
 
                if (error && error != GIT_ENOTFOUND)
                        goto on_error;
 
-               git_buf_dispose(&config_path);
+               git_str_dispose(&config_path);
        }
 
        if (global_config_path != NULL &&
@@ -1053,15 +1118,15 @@ static int load_config(
        return 0;
 
 on_error:
-       git_buf_dispose(&config_path);
+       git_str_dispose(&config_path);
        git_config_free(cfg);
        *out = NULL;
        return error;
 }
 
-static const char *path_unless_empty(git_buf *buf)
+static const char *path_unless_empty(git_str *buf)
 {
-       return git_buf_len(buf) > 0 ? git_buf_cstr(buf) : NULL;
+       return git_str_len(buf) > 0 ? git_str_cstr(buf) : NULL;
 }
 
 int git_repository_config__weakptr(git_config **out, git_repository *repo)
@@ -1069,19 +1134,19 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo)
        int error = 0;
 
        if (repo->_config == NULL) {
-               git_buf global_buf = GIT_BUF_INIT;
-               git_buf xdg_buf = GIT_BUF_INIT;
-               git_buf system_buf = GIT_BUF_INIT;
-               git_buf programdata_buf = GIT_BUF_INIT;
+               git_str global_buf = GIT_STR_INIT;
+               git_str xdg_buf = GIT_STR_INIT;
+               git_str system_buf = GIT_STR_INIT;
+               git_str programdata_buf = GIT_STR_INIT;
                git_config *config;
 
-               git_config_find_global(&global_buf);
-               git_config_find_xdg(&xdg_buf);
-               git_config_find_system(&system_buf);
-               git_config_find_programdata(&programdata_buf);
+               git_config__find_global(&global_buf);
+               git_config__find_xdg(&xdg_buf);
+               git_config__find_system(&system_buf);
+               git_config__find_programdata(&programdata_buf);
 
                /* If there is no global file, open a backend for it anyway */
-               if (git_buf_len(&global_buf) == 0)
+               if (git_str_len(&global_buf) == 0)
                        git_config__global_location(&global_buf);
 
                error = load_config(
@@ -1099,10 +1164,10 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo)
                        }
                }
 
-               git_buf_dispose(&global_buf);
-               git_buf_dispose(&xdg_buf);
-               git_buf_dispose(&system_buf);
-               git_buf_dispose(&programdata_buf);
+               git_str_dispose(&global_buf);
+               git_str_dispose(&xdg_buf);
+               git_str_dispose(&system_buf);
+               git_str_dispose(&programdata_buf);
        }
 
        *out = repo->_config;
@@ -1147,10 +1212,10 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
 
        *out = git_atomic_load(repo->_odb);
        if (*out == NULL) {
-               git_buf odb_path = GIT_BUF_INIT;
+               git_str odb_path = GIT_STR_INIT;
                git_odb *odb;
 
-               if ((error = git_repository_item_path(&odb_path, repo,
+               if ((error = git_repository__item_path(&odb_path, repo,
                                GIT_REPOSITORY_ITEM_OBJECTS)) < 0 ||
                        (error = git_odb_new(&odb)) < 0)
                        return error;
@@ -1168,7 +1233,7 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
                        git_odb_free(odb);
                }
 
-               git_buf_dispose(&odb_path);
+               git_str_dispose(&odb_path);
                *out = git_atomic_load(repo->_odb);
        }
 
@@ -1244,10 +1309,10 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
        GIT_ASSERT_ARG(repo);
 
        if (repo->_index == NULL) {
-               git_buf index_path = GIT_BUF_INIT;
+               git_str index_path = GIT_STR_INIT;
                git_index *index;
 
-               if ((error = git_buf_joinpath(&index_path, repo->gitdir, GIT_INDEX_FILE)) < 0)
+               if ((error = git_str_joinpath(&index_path, repo->gitdir, GIT_INDEX_FILE)) < 0)
                        return error;
 
                error = git_index_open(&index, index_path.ptr);
@@ -1263,7 +1328,7 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
                                                   GIT_INDEX_CAPABILITY_FROM_OWNER);
                }
 
-               git_buf_dispose(&index_path);
+               git_str_dispose(&index_path);
        }
 
        *out = repo->_index;
@@ -1311,7 +1376,7 @@ static int reserved_names_add8dot3(git_repository *repo, const char *path)
        const char *def_dot_git = DOT_GIT;
        size_t name_len, def_len = CONST_STRLEN(GIT_DIR_SHORTNAME);
        size_t def_dot_git_len = CONST_STRLEN(DOT_GIT);
-       git_buf *buf;
+       git_str *buf;
 
        if (!name)
                return 0;
@@ -1327,17 +1392,17 @@ static int reserved_names_add8dot3(git_repository *repo, const char *path)
        if ((buf = git_array_alloc(repo->reserved_names)) == NULL)
                return -1;
 
-       git_buf_attach(buf, name, name_len);
+       git_str_attach(buf, name, name_len);
        return true;
 }
 
 bool git_repository__reserved_names(
-       git_buf **out, size_t *outlen, git_repository *repo, bool include_ntfs)
+       git_str **out, size_t *outlen, git_repository *repo, bool include_ntfs)
 {
        GIT_UNUSED(include_ntfs);
 
        if (repo->reserved_names.size == 0) {
-               git_buf *buf;
+               git_str *buf;
                size_t i;
 
                /* Add the static defaults */
@@ -1389,7 +1454,7 @@ on_error:
 }
 #else
 bool git_repository__reserved_names(
-       git_buf **out, size_t *outlen, git_repository *repo, bool include_ntfs)
+       git_str **out, size_t *outlen, git_repository *repo, bool include_ntfs)
 {
        GIT_UNUSED(repo);
 
@@ -1435,7 +1500,7 @@ static git_vector user_extensions = GIT_VECTOR_INIT;
 
 static int check_valid_extension(const git_config_entry *entry, void *payload)
 {
-       git_buf cfg = GIT_BUF_INIT;
+       git_str cfg = GIT_STR_INIT;
        bool reject;
        const char *extension;
        size_t i;
@@ -1444,7 +1509,7 @@ static int check_valid_extension(const git_config_entry *entry, void *payload)
        GIT_UNUSED(payload);
 
        git_vector_foreach (&user_extensions, i, extension) {
-               git_buf_clear(&cfg);
+               git_str_clear(&cfg);
 
                /*
                 * Users can specify that they don't want to support an
@@ -1453,7 +1518,7 @@ static int check_valid_extension(const git_config_entry *entry, void *payload)
                if ((reject = (extension[0] == '!')) == true)
                        extension = &extension[1];
 
-               if ((error = git_buf_printf(&cfg, "extensions.%s", extension)) < 0)
+               if ((error = git_str_printf(&cfg, "extensions.%s", extension)) < 0)
                        goto done;
 
                if (strcmp(entry->name, cfg.ptr) == 0) {
@@ -1467,7 +1532,7 @@ static int check_valid_extension(const git_config_entry *entry, void *payload)
        for (i = 0; i < ARRAY_SIZE(builtin_extensions); i++) {
                extension = builtin_extensions[i];
 
-               if ((error = git_buf_printf(&cfg, "extensions.%s", extension)) < 0)
+               if ((error = git_str_printf(&cfg, "extensions.%s", extension)) < 0)
                        goto done;
 
                if (strcmp(entry->name, cfg.ptr) == 0)
@@ -1479,7 +1544,7 @@ fail:
        error = -1;
 
 done:
-       git_buf_dispose(&cfg);
+       git_str_dispose(&cfg);
        return error;
 }
 
@@ -1557,12 +1622,12 @@ void git_repository__free_extensions(void)
 
 int git_repository_create_head(const char *git_dir, const char *ref_name)
 {
-       git_buf ref_path = GIT_BUF_INIT;
+       git_str ref_path = GIT_STR_INIT;
        git_filebuf ref = GIT_FILEBUF_INIT;
        const char *fmt;
        int error;
 
-       if ((error = git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE)) < 0 ||
+       if ((error = git_str_joinpath(&ref_path, git_dir, GIT_HEAD_FILE)) < 0 ||
            (error = git_filebuf_open(&ref, ref_path.ptr, 0, GIT_REFS_FILE_MODE)) < 0)
                goto out;
 
@@ -1576,7 +1641,7 @@ int git_repository_create_head(const char *git_dir, const char *ref_name)
                goto out;
 
 out:
-       git_buf_dispose(&ref_path);
+       git_str_dispose(&ref_path);
        git_filebuf_cleanup(&ref);
        return error;
 }
@@ -1599,23 +1664,50 @@ static bool is_chmod_supported(const char *file_path)
 
 static bool is_filesystem_case_insensitive(const char *gitdir_path)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        int is_insensitive = -1;
 
-       if (!git_buf_joinpath(&path, gitdir_path, "CoNfIg"))
-               is_insensitive = git_path_exists(git_buf_cstr(&path));
+       if (!git_str_joinpath(&path, gitdir_path, "CoNfIg"))
+               is_insensitive = git_fs_path_exists(git_str_cstr(&path));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        return is_insensitive;
 }
 
+/*
+ * Return a configuration object with only the global and system
+ * configurations; no repository-level configuration.
+ */
+static int load_global_config(git_config **config)
+{
+       git_str global_buf = GIT_STR_INIT;
+       git_str xdg_buf = GIT_STR_INIT;
+       git_str system_buf = GIT_STR_INIT;
+       git_str programdata_buf = GIT_STR_INIT;
+       int error;
+
+       git_config__find_global(&global_buf);
+       git_config__find_xdg(&xdg_buf);
+       git_config__find_system(&system_buf);
+       git_config__find_programdata(&programdata_buf);
+
+       error = load_config(config, NULL,
+                           path_unless_empty(&global_buf),
+                           path_unless_empty(&xdg_buf),
+                           path_unless_empty(&system_buf),
+                           path_unless_empty(&programdata_buf));
+
+       git_str_dispose(&global_buf);
+       git_str_dispose(&xdg_buf);
+       git_str_dispose(&system_buf);
+       git_str_dispose(&programdata_buf);
+
+       return error;
+}
+
 static bool are_symlinks_supported(const char *wd_path)
 {
        git_config *config = NULL;
-       git_buf global_buf = GIT_BUF_INIT;
-       git_buf xdg_buf = GIT_BUF_INIT;
-       git_buf system_buf = GIT_BUF_INIT;
-       git_buf programdata_buf = GIT_BUF_INIT;
        int symlinks = 0;
 
        /*
@@ -1626,30 +1718,16 @@ static bool are_symlinks_supported(const char *wd_path)
         * _not_ set, then we do not test or enable symlink support.
         */
 #ifdef GIT_WIN32
-       git_config_find_global(&global_buf);
-       git_config_find_xdg(&xdg_buf);
-       git_config_find_system(&system_buf);
-       git_config_find_programdata(&programdata_buf);
-
-       if (load_config(&config, NULL,
-           path_unless_empty(&global_buf),
-           path_unless_empty(&xdg_buf),
-           path_unless_empty(&system_buf),
-           path_unless_empty(&programdata_buf)) < 0)
-               goto done;
-
-       if (git_config_get_bool(&symlinks, config, "core.symlinks") < 0 || !symlinks)
+       if (load_global_config(&config) < 0 ||
+           git_config_get_bool(&symlinks, config, "core.symlinks") < 0 ||
+           !symlinks)
                goto done;
 #endif
 
-       if (!(symlinks = git_path_supports_symlinks(wd_path)))
+       if (!(symlinks = git_fs_path_supports_symlinks(wd_path)))
                goto done;
 
 done:
-       git_buf_dispose(&global_buf);
-       git_buf_dispose(&xdg_buf);
-       git_buf_dispose(&system_buf);
-       git_buf_dispose(&programdata_buf);
        git_config_free(config);
        return symlinks != 0;
 }
@@ -1673,7 +1751,7 @@ static int create_empty_file(const char *path, mode_t mode)
 
 static int repo_local_config(
        git_config **out,
-       git_buf *config_dir,
+       git_str *config_dir,
        git_repository *repo,
        const char *repo_dir)
 {
@@ -1681,12 +1759,12 @@ static int repo_local_config(
        git_config *parent;
        const char *cfg_path;
 
-       if (git_buf_joinpath(config_dir, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0)
+       if (git_str_joinpath(config_dir, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0)
                return -1;
-       cfg_path = git_buf_cstr(config_dir);
+       cfg_path = git_str_cstr(config_dir);
 
        /* make LOCAL config if missing */
-       if (!git_path_isfile(cfg_path) &&
+       if (!git_fs_path_isfile(cfg_path) &&
                (error = create_empty_file(cfg_path, GIT_CONFIG_FILE_MODE)) < 0)
                return error;
 
@@ -1744,7 +1822,7 @@ static int repo_init_fs_configs(
 #ifdef GIT_USE_ICONV
        if ((error = git_config_set_bool(
                        cfg, "core.precomposeunicode",
-                       git_path_does_fs_decompose_unicode(work_dir))) < 0)
+                       git_fs_path_does_decompose_unicode(work_dir))) < 0)
                return error;
        /* on non-iconv platforms, don't even set core.precomposeunicode */
 #endif
@@ -1759,7 +1837,7 @@ static int repo_init_config(
        uint32_t mode)
 {
        int error = 0;
-       git_buf cfg_path = GIT_BUF_INIT, worktree_path = GIT_BUF_INIT;
+       git_str cfg_path = GIT_STR_INIT, worktree_path = GIT_STR_INIT;
        git_config *config = NULL;
        bool is_bare = ((flags & GIT_REPOSITORY_INIT_BARE) != 0);
        bool is_reinit = ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0);
@@ -1789,11 +1867,11 @@ static int repo_init_config(
                SET_REPO_CONFIG(bool, "core.logallrefupdates", true);
 
                if (!(flags & GIT_REPOSITORY_INIT__NATURAL_WD)) {
-                       if ((error = git_buf_sets(&worktree_path, work_dir)) < 0)
+                       if ((error = git_str_sets(&worktree_path, work_dir)) < 0)
                                goto cleanup;
 
                        if ((flags & GIT_REPOSITORY_INIT_RELATIVE_GITLINK))
-                               if ((error = git_path_make_relative(&worktree_path, repo_dir)) < 0)
+                               if ((error = git_fs_path_make_relative(&worktree_path, repo_dir)) < 0)
                                        goto cleanup;
 
                        SET_REPO_CONFIG(string, "core.worktree", worktree_path.ptr);
@@ -1813,8 +1891,8 @@ static int repo_init_config(
        }
 
 cleanup:
-       git_buf_dispose(&cfg_path);
-       git_buf_dispose(&worktree_path);
+       git_str_dispose(&cfg_path);
+       git_str_dispose(&worktree_path);
        git_config_free(config);
 
        return error;
@@ -1836,7 +1914,7 @@ static int repo_reinit_submodule_fs(git_submodule *sm, const char *n, void *p)
 int git_repository_reinit_filesystem(git_repository *repo, int recurse)
 {
        int error = 0;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_config *config = NULL;
        const char *repo_dir = git_repository_path(repo);
 
@@ -1845,7 +1923,7 @@ int git_repository_reinit_filesystem(git_repository *repo, int recurse)
                        config, path.ptr, repo_dir, git_repository_workdir(repo), true);
 
        git_config_free(config);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        git_repository__configmap_lookup_cache_clear(repo);
 
@@ -1863,10 +1941,10 @@ static int repo_write_template(
        bool hidden,
        const char *content)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        int fd, error = 0, flags;
 
-       if (git_buf_joinpath(&path, git_dir, file) < 0)
+       if (git_str_joinpath(&path, git_dir, file) < 0)
                return -1;
 
        if (allow_overwrite)
@@ -1874,7 +1952,7 @@ static int repo_write_template(
        else
                flags = O_WRONLY | O_CREAT | O_EXCL;
 
-       fd = p_open(git_buf_cstr(&path), flags, mode);
+       fd = p_open(git_str_cstr(&path), flags, mode);
 
        if (fd >= 0) {
                error = p_write(fd, content, strlen(content));
@@ -1893,7 +1971,7 @@ static int repo_write_template(
        GIT_UNUSED(hidden);
 #endif
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        if (error)
                git_error_set(GIT_ERROR_OS,
@@ -1906,13 +1984,13 @@ static int repo_write_gitlink(
        const char *in_dir, const char *to_repo, bool use_relative_path)
 {
        int error;
-       git_buf buf = GIT_BUF_INIT;
-       git_buf path_to_repo = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
+       git_str path_to_repo = GIT_STR_INIT;
        struct stat st;
 
-       git_path_dirname_r(&buf, to_repo);
-       git_path_to_dir(&buf);
-       if (git_buf_oom(&buf))
+       git_fs_path_dirname_r(&buf, to_repo);
+       git_fs_path_to_dir(&buf);
+       if (git_str_oom(&buf))
                return -1;
 
        /* don't write gitlink to natural workdir */
@@ -1923,7 +2001,7 @@ static int repo_write_gitlink(
                goto cleanup;
        }
 
-       if ((error = git_buf_joinpath(&buf, in_dir, DOT_GIT)) < 0)
+       if ((error = git_str_joinpath(&buf, in_dir, DOT_GIT)) < 0)
                goto cleanup;
 
        if (!p_stat(buf.ptr, &st) && !S_ISREG(st.st_mode)) {
@@ -1933,22 +2011,22 @@ static int repo_write_gitlink(
                goto cleanup;
        }
 
-       git_buf_clear(&buf);
+       git_str_clear(&buf);
 
-       error = git_buf_sets(&path_to_repo, to_repo);
+       error = git_str_sets(&path_to_repo, to_repo);
 
        if (!error && use_relative_path)
-               error = git_path_make_relative(&path_to_repo, in_dir);
+               error = git_fs_path_make_relative(&path_to_repo, in_dir);
 
        if (!error)
-               error = git_buf_join(&buf, ' ', GIT_FILE_CONTENT_PREFIX, path_to_repo.ptr);
+               error = git_str_join(&buf, ' ', GIT_FILE_CONTENT_PREFIX, path_to_repo.ptr);
 
        if (!error)
                error = repo_write_template(in_dir, true, DOT_GIT, 0666, true, buf.ptr);
 
 cleanup:
-       git_buf_dispose(&buf);
-       git_buf_dispose(&path_to_repo);
+       git_str_dispose(&buf);
+       git_str_dispose(&path_to_repo);
        return error;
 }
 
@@ -2001,12 +2079,12 @@ static int repo_init_structure(
                git_config *cfg = NULL;
                const char *tdir = NULL;
                bool default_template = false;
-               git_buf template_buf = GIT_BUF_INIT;
+               git_str template_buf = GIT_STR_INIT;
 
                if (opts->template_path)
                        tdir = opts->template_path;
                else if ((error = git_config_open_default(&cfg)) >= 0) {
-                       if (!git_config_get_path(&template_buf, cfg, "init.templatedir"))
+                       if (!git_config__get_path(&template_buf, cfg, "init.templatedir"))
                                tdir = template_buf.ptr;
                        git_error_clear();
                }
@@ -2032,11 +2110,16 @@ static int repo_init_structure(
                        error = git_futils_cp_r(tdir, repo_dir, cpflags, dmode);
                }
 
-               git_buf_dispose(&template_buf);
+               git_str_dispose(&template_buf);
                git_config_free(cfg);
 
+               /* If tdir does not exist, then do not error out. This matches the
+                * behaviour of git(1), which just prints a warning and continues.
+                * TODO: issue warning when warning API is available.
+                * `git` prints to stderr: 'warning: templates not found in /path/to/tdir'
+                */
                if (error < 0) {
-                       if (!default_template)
+                       if (!default_template && error != GIT_ENOTFOUND)
                                return error;
 
                        /* if template was default, ignore error and use internal */
@@ -2073,7 +2156,7 @@ static int repo_init_structure(
        return error;
 }
 
-static int mkdir_parent(git_buf *buf, uint32_t mode, bool skip2)
+static int mkdir_parent(git_str *buf, uint32_t mode, bool skip2)
 {
        /* When making parent directories during repository initialization
         * don't try to set gid or grant world write access
@@ -2085,8 +2168,8 @@ static int mkdir_parent(git_buf *buf, uint32_t mode, bool skip2)
 }
 
 static int repo_init_directories(
-       git_buf *repo_path,
-       git_buf *wd_path,
+       git_str *repo_path,
+       git_str *wd_path,
        const char *given_repo,
        git_repository_init_options *opts)
 {
@@ -2124,7 +2207,7 @@ static int repo_init_directories(
                git__suffixcmp(given_repo, "/" DOT_GIT) != 0 &&
                git__suffixcmp(given_repo, "/" GIT_DIR) != 0;
 
-       if (git_buf_joinpath(repo_path, given_repo, add_dotgit ? GIT_DIR : "") < 0)
+       if (git_str_joinpath(repo_path, given_repo, add_dotgit ? GIT_DIR : "") < 0)
                return -1;
 
        has_dotgit = (git__suffixcmp(repo_path->ptr, "/" GIT_DIR) == 0);
@@ -2135,11 +2218,11 @@ static int repo_init_directories(
 
        if (!is_bare) {
                if (opts->workdir_path) {
-                       if (git_path_join_unrooted(
+                       if (git_fs_path_join_unrooted(
                                        wd_path, opts->workdir_path, repo_path->ptr, NULL) < 0)
                                return -1;
                } else if (has_dotgit) {
-                       if (git_path_dirname_r(wd_path, repo_path->ptr) < 0)
+                       if (git_fs_path_dirname_r(wd_path, repo_path->ptr) < 0)
                                return -1;
                } else {
                        git_error_set(GIT_ERROR_REPOSITORY, "cannot pick working directory"
@@ -2147,10 +2230,10 @@ static int repo_init_directories(
                        return -1;
                }
 
-               if (git_path_to_dir(wd_path) < 0)
+               if (git_fs_path_to_dir(wd_path) < 0)
                        return -1;
        } else {
-               git_buf_clear(wd_path);
+               git_str_clear(wd_path);
        }
 
        natural_wd =
@@ -2207,10 +2290,10 @@ static int repo_init_directories(
        /* prettify both directories now that they are created */
 
        if (!error) {
-               error = git_path_prettify_dir(repo_path, repo_path->ptr, NULL);
+               error = git_fs_path_prettify_dir(repo_path, repo_path->ptr, NULL);
 
                if (!error && wd_path->size > 0)
-                       error = git_path_prettify_dir(wd_path, wd_path->ptr, NULL);
+                       error = git_fs_path_prettify_dir(wd_path, wd_path->ptr, NULL);
        }
 
        return error;
@@ -2219,24 +2302,24 @@ static int repo_init_directories(
 static int repo_init_head(const char *repo_dir, const char *given)
 {
        git_config *cfg = NULL;
-       git_buf head_path = GIT_BUF_INIT, cfg_branch = GIT_BUF_INIT;
+       git_str head_path = GIT_STR_INIT, cfg_branch = GIT_STR_INIT;
        const char *initial_head = NULL;
        int error;
 
-       if ((error = git_buf_joinpath(&head_path, repo_dir, GIT_HEAD_FILE)) < 0)
+       if ((error = git_str_joinpath(&head_path, repo_dir, GIT_HEAD_FILE)) < 0)
                goto out;
 
        /*
         * A template may have set a HEAD; use that unless it's been
         * overridden by the caller's given initial head setting.
         */
-       if (git_path_exists(head_path.ptr) && !given)
+       if (git_fs_path_exists(head_path.ptr) && !given)
                goto out;
 
        if (given) {
                initial_head = given;
        } else if ((error = git_config_open_default(&cfg)) >= 0 &&
-                  (error = git_config_get_string_buf(&cfg_branch, cfg, "init.defaultbranch")) >= 0 &&
+                  (error = git_config__get_string_buf(&cfg_branch, cfg, "init.defaultbranch")) >= 0 &&
                   *cfg_branch.ptr) {
                initial_head = cfg_branch.ptr;
        }
@@ -2248,8 +2331,8 @@ static int repo_init_head(const char *repo_dir, const char *given)
 
 out:
        git_config_free(cfg);
-       git_buf_dispose(&head_path);
-       git_buf_dispose(&cfg_branch);
+       git_str_dispose(&head_path);
+       git_str_dispose(&cfg_branch);
 
        return error;
 }
@@ -2283,8 +2366,8 @@ int git_repository_init_ext(
        const char *given_repo,
        git_repository_init_options *opts)
 {
-       git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT,
-               common_path = GIT_BUF_INIT;
+       git_str repo_path = GIT_STR_INIT, wd_path = GIT_STR_INIT,
+               common_path = GIT_STR_INIT;
        const char *wd;
        bool is_valid;
        int error;
@@ -2298,7 +2381,7 @@ int git_repository_init_ext(
        if ((error = repo_init_directories(&repo_path, &wd_path, given_repo, opts)) < 0)
                goto out;
 
-       wd = (opts->flags & GIT_REPOSITORY_INIT_BARE) ? NULL : git_buf_cstr(&wd_path);
+       wd = (opts->flags & GIT_REPOSITORY_INIT_BARE) ? NULL : git_str_cstr(&wd_path);
 
        if ((error = is_valid_repository_path(&is_valid, &repo_path, &common_path)) < 0)
                goto out;
@@ -2332,9 +2415,9 @@ int git_repository_init_ext(
                goto out;
 
 out:
-       git_buf_dispose(&common_path);
-       git_buf_dispose(&repo_path);
-       git_buf_dispose(&wd_path);
+       git_str_dispose(&common_path);
+       git_str_dispose(&repo_path);
+       git_str_dispose(&wd_path);
 
        return error;
 }
@@ -2522,7 +2605,7 @@ static int repo_contains_no_reference(git_repository *repo)
        return error;
 }
 
-int git_repository_initialbranch(git_buf *out, git_repository *repo)
+int git_repository_initialbranch(git_str *out, git_repository *repo)
 {
        git_config *config;
        git_config_entry *entry = NULL;
@@ -2543,8 +2626,8 @@ int git_repository_initialbranch(git_buf *out, git_repository *repo)
                goto done;
        }
 
-       if ((error = git_buf_puts(out, GIT_REFS_HEADS_DIR)) < 0 ||
-           (error = git_buf_puts(out, branch)) < 0 ||
+       if ((error = git_str_puts(out, GIT_REFS_HEADS_DIR)) < 0 ||
+           (error = git_str_puts(out, branch)) < 0 ||
            (error = git_reference_name_is_valid(&valid, out->ptr)) < 0)
            goto done;
 
@@ -2561,7 +2644,7 @@ done:
 int git_repository_is_empty(git_repository *repo)
 {
        git_reference *head = NULL;
-       git_buf initialbranch = GIT_BUF_INIT;
+       git_str initialbranch = GIT_STR_INIT;
        int result = 0;
 
        if ((result = git_reference_lookup(&head, repo, GIT_HEAD_FILE)) < 0 ||
@@ -2574,7 +2657,7 @@ int git_repository_is_empty(git_repository *repo)
 
 done:
        git_reference_free(head);
-       git_buf_dispose(&initialbranch);
+       git_str_dispose(&initialbranch);
 
        return result;
 }
@@ -2603,7 +2686,18 @@ static const char *resolved_parent_path(const git_repository *repo, git_reposito
        return parent;
 }
 
-int git_repository_item_path(git_buf *out, const git_repository *repo, git_repository_item_t item)
+int git_repository_item_path(
+       git_buf *out,
+       const git_repository *repo,
+       git_repository_item_t item)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_repository__item_path, repo, item);
+}
+
+int git_repository__item_path(
+       git_str *out,
+       const git_repository *repo,
+       git_repository_item_t item)
 {
        const char *parent = resolved_parent_path(repo, items[item].parent, items[item].fallback);
        if (parent == NULL) {
@@ -2611,16 +2705,16 @@ int git_repository_item_path(git_buf *out, const git_repository *repo, git_repos
                return GIT_ENOTFOUND;
        }
 
-       if (git_buf_sets(out, parent) < 0)
+       if (git_str_sets(out, parent) < 0)
                return -1;
 
        if (items[item].name) {
-               if (git_buf_joinpath(out, parent, items[item].name) < 0)
+               if (git_str_joinpath(out, parent, items[item].name) < 0)
                        return -1;
        }
 
        if (items[item].directory) {
-               if (git_path_to_dir(out) < 0)
+               if (git_fs_path_to_dir(out) < 0)
                        return -1;
        }
 
@@ -2644,7 +2738,7 @@ const char *git_repository_workdir(const git_repository *repo)
 }
 
 int git_repository_workdir_path(
-       git_buf *out, git_repository *repo, const char *path)
+       git_str *out, git_repository *repo, const char *path)
 {
        int error;
 
@@ -2653,8 +2747,8 @@ int git_repository_workdir_path(
                return GIT_EBAREREPO;
        }
 
-       if (!(error = git_buf_joinpath(out, repo->workdir, path)))
-               error = git_path_validate_workdir_buf(repo, out);
+       if (!(error = git_str_joinpath(out, repo->workdir, path)))
+               error = git_path_validate_str_length(repo, out);
 
        return error;
 }
@@ -2669,12 +2763,12 @@ int git_repository_set_workdir(
        git_repository *repo, const char *workdir, int update_gitlink)
 {
        int error = 0;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        GIT_ASSERT_ARG(repo);
        GIT_ASSERT_ARG(workdir);
 
-       if (git_path_prettify_dir(&path, workdir, NULL) < 0)
+       if (git_fs_path_prettify_dir(&path, workdir, NULL) < 0)
                return -1;
 
        if (repo->workdir && strcmp(repo->workdir, path.ptr) == 0)
@@ -2701,7 +2795,7 @@ int git_repository_set_workdir(
        if (!error) {
                char *old_workdir = repo->workdir;
 
-               repo->workdir = git_buf_detach(&path);
+               repo->workdir = git_str_detach(&path);
                repo->is_bare = 0;
 
                git__free(old_workdir);
@@ -2770,13 +2864,13 @@ cleanup:
 int git_repository__set_orig_head(git_repository *repo, const git_oid *orig_head)
 {
        git_filebuf file = GIT_FILEBUF_INIT;
-       git_buf file_path = GIT_BUF_INIT;
+       git_str file_path = GIT_STR_INIT;
        char orig_head_str[GIT_OID_HEXSZ];
        int error = 0;
 
        git_oid_fmt(orig_head_str, orig_head);
 
-       if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_ORIG_HEAD_FILE)) == 0 &&
+       if ((error = git_str_joinpath(&file_path, repo->gitdir, GIT_ORIG_HEAD_FILE)) == 0 &&
                (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_MERGE_FILE_MODE)) == 0 &&
                (error = git_filebuf_printf(&file, "%.*s\n", GIT_OID_HEXSZ, orig_head_str)) == 0)
                error = git_filebuf_commit(&file);
@@ -2784,46 +2878,48 @@ int git_repository__set_orig_head(git_repository *repo, const git_oid *orig_head
        if (error < 0)
                git_filebuf_cleanup(&file);
 
-       git_buf_dispose(&file_path);
+       git_str_dispose(&file_path);
 
        return error;
 }
 
-int git_repository_message(git_buf *out, git_repository *repo)
+static int git_repository__message(git_str *out, git_repository *repo)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        struct stat st;
        int error;
 
-       if ((error = git_buf_sanitize(out)) < 0)
-               return error;
-
-       if (git_buf_joinpath(&path, repo->gitdir, GIT_MERGE_MSG_FILE) < 0)
+       if (git_str_joinpath(&path, repo->gitdir, GIT_MERGE_MSG_FILE) < 0)
                return -1;
 
-       if ((error = p_stat(git_buf_cstr(&path), &st)) < 0) {
+       if ((error = p_stat(git_str_cstr(&path), &st)) < 0) {
                if (errno == ENOENT)
                        error = GIT_ENOTFOUND;
                git_error_set(GIT_ERROR_OS, "could not access message file");
        } else {
-               error = git_futils_readbuffer(out, git_buf_cstr(&path));
+               error = git_futils_readbuffer(out, git_str_cstr(&path));
        }
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return error;
 }
 
+int git_repository_message(git_buf *out, git_repository *repo)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_repository__message, repo);
+}
+
 int git_repository_message_remove(git_repository *repo)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        int error;
 
-       if (git_buf_joinpath(&path, repo->gitdir, GIT_MERGE_MSG_FILE) < 0)
+       if (git_str_joinpath(&path, repo->gitdir, GIT_MERGE_MSG_FILE) < 0)
                return -1;
 
-       error = p_unlink(git_buf_cstr(&path));
-       git_buf_dispose(&path);
+       error = p_unlink(git_str_cstr(&path));
+       git_str_dispose(&path);
 
        return error;
 }
@@ -2839,7 +2935,7 @@ int git_repository_hashfile(
        git_filter_list *fl = NULL;
        git_file fd = -1;
        uint64_t len;
-       git_buf full_path = GIT_BUF_INIT;
+       git_str full_path = GIT_STR_INIT;
        const char *workdir = git_repository_workdir(repo);
 
         /* as_path can be NULL */
@@ -2847,8 +2943,8 @@ int git_repository_hashfile(
        GIT_ASSERT_ARG(path);
        GIT_ASSERT_ARG(repo);
 
-       if ((error = git_path_join_unrooted(&full_path, path, workdir, NULL)) < 0 ||
-           (error = git_path_validate_workdir_buf(repo, &full_path)) < 0)
+       if ((error = git_fs_path_join_unrooted(&full_path, path, workdir, NULL)) < 0 ||
+           (error = git_path_validate_str_length(repo, &full_path)) < 0)
                return error;
 
        /*
@@ -2895,30 +2991,30 @@ cleanup:
        if (fd >= 0)
                p_close(fd);
        git_filter_list_free(fl);
-       git_buf_dispose(&full_path);
+       git_str_dispose(&full_path);
 
        return error;
 }
 
-static int checkout_message(git_buf *out, git_reference *old, const char *new)
+static int checkout_message(git_str *out, git_reference *old, const char *new)
 {
-       git_buf_puts(out, "checkout: moving from ");
+       git_str_puts(out, "checkout: moving from ");
 
        if (git_reference_type(old) == GIT_REFERENCE_SYMBOLIC)
-               git_buf_puts(out, git_reference__shorthand(git_reference_symbolic_target(old)));
+               git_str_puts(out, git_reference__shorthand(git_reference_symbolic_target(old)));
        else
-               git_buf_puts(out, git_oid_tostr_s(git_reference_target(old)));
+               git_str_puts(out, git_oid_tostr_s(git_reference_target(old)));
 
-       git_buf_puts(out, " to ");
+       git_str_puts(out, " to ");
 
        if (git_reference__is_branch(new) ||
                git_reference__is_tag(new) ||
                git_reference__is_remote(new))
-               git_buf_puts(out, git_reference__shorthand(new));
+               git_str_puts(out, git_reference__shorthand(new));
        else
-               git_buf_puts(out, new);
+               git_str_puts(out, new);
 
-       if (git_buf_oom(out))
+       if (git_str_oom(out))
                return -1;
 
        return 0;
@@ -2927,7 +3023,7 @@ static int checkout_message(git_buf *out, git_reference *old, const char *new)
 static int detach(git_repository *repo, const git_oid *id, const char *new)
 {
        int error;
-       git_buf log_message = GIT_BUF_INIT;
+       git_str log_message = GIT_STR_INIT;
        git_object *object = NULL, *peeled = NULL;
        git_reference *new_head = NULL, *current = NULL;
 
@@ -2949,10 +3045,10 @@ static int detach(git_repository *repo, const git_oid *id, const char *new)
        if ((error = checkout_message(&log_message, current, new)) < 0)
                goto cleanup;
 
-       error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), true, git_buf_cstr(&log_message));
+       error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), true, git_str_cstr(&log_message));
 
 cleanup:
-       git_buf_dispose(&log_message);
+       git_str_dispose(&log_message);
        git_object_free(object);
        git_object_free(peeled);
        git_reference_free(current);
@@ -2965,7 +3061,7 @@ int git_repository_set_head(
        const char *refname)
 {
        git_reference *ref = NULL, *current = NULL, *new_head = NULL;
-       git_buf log_message = GIT_BUF_INIT;
+       git_str log_message = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(repo);
@@ -2992,18 +3088,18 @@ int git_repository_set_head(
        if (!error) {
                if (git_reference_is_branch(ref)) {
                        error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE,
-                                       git_reference_name(ref), true, git_buf_cstr(&log_message));
+                                       git_reference_name(ref), true, git_str_cstr(&log_message));
                } else {
                        error = detach(repo, git_reference_target(ref),
                                git_reference_is_tag(ref) || git_reference_is_remote(ref) ? refname : NULL);
                }
        } else if (git_reference__is_branch(refname)) {
                error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, refname,
-                               true, git_buf_cstr(&log_message));
+                               true, git_str_cstr(&log_message));
        }
 
 cleanup:
-       git_buf_dispose(&log_message);
+       git_str_dispose(&log_message);
        git_reference_free(current);
        git_reference_free(ref);
        git_reference_free(new_head);
@@ -3012,26 +3108,26 @@ cleanup:
 
 int git_repository_set_head_detached(
        git_repository *repo,
-       const git_oid *commitish)
+       const git_oid *committish)
 {
-       return detach(repo, commitish, NULL);
+       return detach(repo, committish, NULL);
 }
 
 int git_repository_set_head_detached_from_annotated(
        git_repository *repo,
-       const git_annotated_commit *commitish)
+       const git_annotated_commit *committish)
 {
        GIT_ASSERT_ARG(repo);
-       GIT_ASSERT_ARG(commitish);
+       GIT_ASSERT_ARG(committish);
 
-       return detach(repo, git_annotated_commit_id(commitish), commitish->description);
+       return detach(repo, git_annotated_commit_id(committish), committish->description);
 }
 
 int git_repository_detach_head(git_repository *repo)
 {
        git_reference *old_head = NULL, *new_head = NULL, *current = NULL;
        git_object *object = NULL;
-       git_buf log_message = GIT_BUF_INIT;
+       git_str log_message = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(repo);
@@ -3049,10 +3145,10 @@ int git_repository_detach_head(git_repository *repo)
                goto cleanup;
 
        error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_reference_target(old_head),
-                       1, git_buf_cstr(&log_message));
+                       1, git_str_cstr(&log_message));
 
 cleanup:
-       git_buf_dispose(&log_message);
+       git_str_dispose(&log_message);
        git_object_free(object);
        git_reference_free(old_head);
        git_reference_free(new_head);
@@ -3066,69 +3162,69 @@ cleanup:
  */
 int git_repository_state(git_repository *repo)
 {
-       git_buf repo_path = GIT_BUF_INIT;
+       git_str repo_path = GIT_STR_INIT;
        int state = GIT_REPOSITORY_STATE_NONE;
 
        GIT_ASSERT_ARG(repo);
 
-       if (git_buf_puts(&repo_path, repo->gitdir) < 0)
+       if (git_str_puts(&repo_path, repo->gitdir) < 0)
                return -1;
 
-       if (git_path_contains_file(&repo_path, GIT_REBASE_MERGE_INTERACTIVE_FILE))
+       if (git_fs_path_contains_file(&repo_path, GIT_REBASE_MERGE_INTERACTIVE_FILE))
                state = GIT_REPOSITORY_STATE_REBASE_INTERACTIVE;
-       else if (git_path_contains_dir(&repo_path, GIT_REBASE_MERGE_DIR))
+       else if (git_fs_path_contains_dir(&repo_path, GIT_REBASE_MERGE_DIR))
                state = GIT_REPOSITORY_STATE_REBASE_MERGE;
-       else if (git_path_contains_file(&repo_path, GIT_REBASE_APPLY_REBASING_FILE))
+       else if (git_fs_path_contains_file(&repo_path, GIT_REBASE_APPLY_REBASING_FILE))
                state = GIT_REPOSITORY_STATE_REBASE;
-       else if (git_path_contains_file(&repo_path, GIT_REBASE_APPLY_APPLYING_FILE))
+       else if (git_fs_path_contains_file(&repo_path, GIT_REBASE_APPLY_APPLYING_FILE))
                state = GIT_REPOSITORY_STATE_APPLY_MAILBOX;
-       else if (git_path_contains_dir(&repo_path, GIT_REBASE_APPLY_DIR))
+       else if (git_fs_path_contains_dir(&repo_path, GIT_REBASE_APPLY_DIR))
                state = GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE;
-       else if (git_path_contains_file(&repo_path, GIT_MERGE_HEAD_FILE))
+       else if (git_fs_path_contains_file(&repo_path, GIT_MERGE_HEAD_FILE))
                state = GIT_REPOSITORY_STATE_MERGE;
-       else if (git_path_contains_file(&repo_path, GIT_REVERT_HEAD_FILE)) {
+       else if (git_fs_path_contains_file(&repo_path, GIT_REVERT_HEAD_FILE)) {
                state = GIT_REPOSITORY_STATE_REVERT;
-               if (git_path_contains_file(&repo_path, GIT_SEQUENCER_TODO_FILE)) {
+               if (git_fs_path_contains_file(&repo_path, GIT_SEQUENCER_TODO_FILE)) {
                        state = GIT_REPOSITORY_STATE_REVERT_SEQUENCE;
                }
-       } else if (git_path_contains_file(&repo_path, GIT_CHERRYPICK_HEAD_FILE)) {
+       } else if (git_fs_path_contains_file(&repo_path, GIT_CHERRYPICK_HEAD_FILE)) {
                state = GIT_REPOSITORY_STATE_CHERRYPICK;
-               if (git_path_contains_file(&repo_path, GIT_SEQUENCER_TODO_FILE)) {
+               if (git_fs_path_contains_file(&repo_path, GIT_SEQUENCER_TODO_FILE)) {
                        state = GIT_REPOSITORY_STATE_CHERRYPICK_SEQUENCE;
                }
-       } else if (git_path_contains_file(&repo_path, GIT_BISECT_LOG_FILE))
+       } else if (git_fs_path_contains_file(&repo_path, GIT_BISECT_LOG_FILE))
                state = GIT_REPOSITORY_STATE_BISECT;
 
-       git_buf_dispose(&repo_path);
+       git_str_dispose(&repo_path);
        return state;
 }
 
 int git_repository__cleanup_files(
        git_repository *repo, const char *files[], size_t files_len)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        size_t i;
        int error;
 
        for (error = 0, i = 0; !error && i < files_len; ++i) {
                const char *path;
 
-               if (git_buf_joinpath(&buf, repo->gitdir, files[i]) < 0)
+               if (git_str_joinpath(&buf, repo->gitdir, files[i]) < 0)
                        return -1;
 
-               path = git_buf_cstr(&buf);
+               path = git_str_cstr(&buf);
 
-               if (git_path_isfile(path)) {
+               if (git_fs_path_isfile(path)) {
                        error = p_unlink(path);
-               } else if (git_path_isdir(path)) {
+               } else if (git_fs_path_isdir(path)) {
                        error = git_futils_rmdir_r(path, NULL,
                                GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_REMOVE_BLOCKERS);
                }
 
-               git_buf_clear(&buf);
+               git_str_clear(&buf);
        }
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
@@ -3153,15 +3249,15 @@ int git_repository_state_cleanup(git_repository *repo)
 
 int git_repository_is_shallow(git_repository *repo)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        struct stat st;
        int error;
 
-       if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0)
+       if ((error = git_str_joinpath(&path, repo->gitdir, "shallow")) < 0)
                return error;
 
-       error = git_path_lstat(path.ptr, &st);
-       git_buf_dispose(&path);
+       error = git_fs_path_lstat(path.ptr, &st);
+       git_str_dispose(&path);
 
        if (error == GIT_ENOTFOUND) {
                git_error_clear();
index cbc160140f39266268e4583369de407fb52e7e2b..a488f2bf2fed759ceab66906afd632407b9a8320 100644 (file)
@@ -19,7 +19,7 @@
 #include "array.h"
 #include "cache.h"
 #include "refs.h"
-#include "buffer.h"
+#include "str.h"
 #include "object.h"
 #include "attrcache.h"
 #include "submodule.h"
@@ -34,6 +34,7 @@
 #define GIT_DIR_SHORTNAME "GIT~1"
 
 extern bool git_repository__fsync_gitdir;
+extern bool git_repository__validate_ownership;
 
 /** Cvar cache identifiers */
 typedef enum {
@@ -118,14 +119,14 @@ typedef enum {
        /* core.fsyncObjectFiles */
        GIT_FSYNCOBJECTFILES_DEFAULT = GIT_CONFIGMAP_FALSE,
        /* core.longpaths */
-       GIT_LONGPATHS_DEFAULT = GIT_CONFIGMAP_FALSE,
+       GIT_LONGPATHS_DEFAULT = GIT_CONFIGMAP_FALSE
 } git_configmap_value;
 
 /* internal repository init flags */
 enum {
        GIT_REPOSITORY_INIT__HAS_DOTGIT = (1u << 16),
        GIT_REPOSITORY_INIT__NATURAL_WD = (1u << 17),
-       GIT_REPOSITORY_INIT__IS_REINIT  = (1u << 18),
+       GIT_REPOSITORY_INIT__IS_REINIT  = (1u << 18)
 };
 
 /** Internal structure for repository object */
@@ -148,7 +149,7 @@ struct git_repository {
        char *ident_name;
        char *ident_email;
 
-       git_array_t(git_buf) reserved_names;
+       git_array_t(git_str) reserved_names;
 
        unsigned is_bare:1;
        unsigned is_worktree:1;
@@ -196,6 +197,8 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo);
 int git_repository__configmap_lookup(int *out, git_repository *repo, git_configmap_item item);
 void git_repository__configmap_lookup_cache_clear(git_repository *repo);
 
+int git_repository__item_path(git_str *out, const git_repository *repo, git_repository_item_t item);
+
 GIT_INLINE(int) git_repository__ensure_not_bare(
        git_repository *repo,
        const char *operation_name)
@@ -216,10 +219,10 @@ int git_repository__set_orig_head(git_repository *repo, const git_oid *orig_head
 int git_repository__cleanup_files(git_repository *repo, const char *files[], size_t files_len);
 
 /* The default "reserved names" for a repository */
-extern git_buf git_repository__reserved_names_win32[];
+extern git_str git_repository__reserved_names_win32[];
 extern size_t git_repository__reserved_names_win32_len;
 
-extern git_buf git_repository__reserved_names_posix[];
+extern git_str git_repository__reserved_names_posix[];
 extern size_t git_repository__reserved_names_posix_len;
 
 /*
@@ -233,13 +236,13 @@ extern size_t git_repository__reserved_names_posix_len;
  * will still be populated with good defaults.
  */
 bool git_repository__reserved_names(
-       git_buf **out, size_t *outlen, git_repository *repo, bool include_ntfs);
+       git_str **out, size_t *outlen, git_repository *repo, bool include_ntfs);
 
 /*
  * The default branch for the repository; the `init.defaultBranch`
  * configuration option, if set, or `master` if it is not.
  */
-int git_repository_initialbranch(git_buf *out, git_repository *repo);
+int git_repository_initialbranch(git_str *out, git_repository *repo);
 
 /*
  * Given a relative `path`, this makes it absolute based on the
@@ -247,7 +250,7 @@ int git_repository_initialbranch(git_buf *out, git_repository *repo);
  * to ensure that the path is not longer than MAX_PATH on Windows
  * (unless `core.longpaths` is set in the repo config).
  */
-int git_repository_workdir_path(git_buf *out, git_repository *repo, const char *path);
+int git_repository_workdir_path(git_str *out, git_repository *repo, const char *path);
 
 int git_repository__extensions(char ***out, size_t *out_len);
 int git_repository__set_extensions(const char **extensions, size_t len);
index f21a620c653fedb8d8d465946a04e97c21909fa8..e0d942e5e17af662330574a8bcf81bbc4ebdb34d 100644 (file)
@@ -111,7 +111,7 @@ static int reset(
        git_tree *tree = NULL;
        int error = 0;
        git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
-       git_buf log_message = GIT_BUF_INIT;
+       git_str log_message = GIT_STR_INIT;
 
        GIT_ASSERT_ARG(repo);
        GIT_ASSERT_ARG(target);
@@ -144,7 +144,7 @@ static int reset(
                goto cleanup;
        }
 
-       if ((error = git_buf_printf(&log_message, "reset: moving to %s", to)) < 0)
+       if ((error = git_str_printf(&log_message, "reset: moving to %s", to)) < 0)
                return error;
 
        if (reset_type == GIT_RESET_HARD) {
@@ -157,7 +157,7 @@ static int reset(
 
        /* move HEAD to the new target */
        if ((error = git_reference__update_terminal(repo, GIT_HEAD_FILE,
-               git_object_id(commit), NULL, git_buf_cstr(&log_message))) < 0)
+               git_object_id(commit), NULL, git_str_cstr(&log_message))) < 0)
                goto cleanup;
 
        if (reset_type > GIT_RESET_SOFT) {
@@ -177,7 +177,7 @@ cleanup:
        git_object_free(commit);
        git_index_free(index);
        git_tree_free(tree);
-       git_buf_dispose(&log_message);
+       git_str_dispose(&log_message);
 
        return error;
 }
@@ -188,7 +188,10 @@ int git_reset(
        git_reset_t reset_type,
        const git_checkout_options *checkout_opts)
 {
-       return reset(repo, target, git_oid_tostr_s(git_object_id(target)), reset_type, checkout_opts);
+       char to[GIT_OID_HEXSZ + 1];
+
+       git_oid_tostr(to, GIT_OID_HEXSZ + 1, git_object_id(target));
+       return reset(repo, target, to, reset_type, checkout_opts);
 }
 
 int git_reset_from_annotated(
index 683f0d70d8b15f93f1770ac6a56c4c2d20756149..d6ab6ae3ce4125c81878b94a7f201e1eded38654 100644 (file)
@@ -25,10 +25,10 @@ static int write_revert_head(
        const char *commit_oidstr)
 {
        git_filebuf file = GIT_FILEBUF_INIT;
-       git_buf file_path = GIT_BUF_INIT;
+       git_str file_path = GIT_STR_INIT;
        int error = 0;
 
-       if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_REVERT_HEAD_FILE)) >= 0 &&
+       if ((error = git_str_joinpath(&file_path, repo->gitdir, GIT_REVERT_HEAD_FILE)) >= 0 &&
                (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_REVERT_FILE_MODE)) >= 0 &&
                (error = git_filebuf_printf(&file, "%s\n", commit_oidstr)) >= 0)
                error = git_filebuf_commit(&file);
@@ -36,7 +36,7 @@ static int write_revert_head(
        if (error < 0)
                git_filebuf_cleanup(&file);
 
-       git_buf_dispose(&file_path);
+       git_str_dispose(&file_path);
 
        return error;
 }
@@ -47,10 +47,10 @@ static int write_merge_msg(
        const char *commit_msgline)
 {
        git_filebuf file = GIT_FILEBUF_INIT;
-       git_buf file_path = GIT_BUF_INIT;
+       git_str file_path = GIT_STR_INIT;
        int error = 0;
 
-       if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
+       if ((error = git_str_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
                (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_REVERT_FILE_MODE)) < 0 ||
                (error = git_filebuf_printf(&file, "Revert \"%s\"\n\nThis reverts commit %s.\n",
                commit_msgline, commit_oidstr)) < 0)
@@ -62,7 +62,7 @@ cleanup:
        if (error < 0)
                git_filebuf_cleanup(&file);
 
-       git_buf_dispose(&file_path);
+       git_str_dispose(&file_path);
 
        return error;
 }
@@ -178,7 +178,7 @@ int git_revert(
        git_commit *our_commit = NULL;
        char commit_oidstr[GIT_OID_HEXSZ + 1];
        const char *commit_msg;
-       git_buf their_label = GIT_BUF_INIT;
+       git_str their_label = GIT_STR_INIT;
        git_index *index = NULL;
        git_indexwriter indexwriter = GIT_INDEXWRITER_INIT;
        int error;
@@ -199,8 +199,8 @@ int git_revert(
                goto on_error;
        }
 
-       if ((error = git_buf_printf(&their_label, "parent of %.7s... %s", commit_oidstr, commit_msg)) < 0 ||
-               (error = revert_normalize_opts(repo, &opts, given_opts, git_buf_cstr(&their_label))) < 0 ||
+       if ((error = git_str_printf(&their_label, "parent of %.7s... %s", commit_oidstr, commit_msg)) < 0 ||
+               (error = revert_normalize_opts(repo, &opts, given_opts, git_str_cstr(&their_label))) < 0 ||
                (error = git_indexwriter_init_for_operation(&indexwriter, repo, &opts.checkout_opts.checkout_strategy)) < 0 ||
                (error = write_revert_head(repo, commit_oidstr)) < 0 ||
                (error = write_merge_msg(repo, commit_oidstr, commit_msg)) < 0 ||
@@ -223,7 +223,7 @@ done:
        git_index_free(index);
        git_commit_free(our_commit);
        git_reference_free(our_ref);
-       git_buf_dispose(&their_label);
+       git_str_dispose(&their_label);
 
        return error;
 }
index b4d5d475938cc2df9d75cc9467b723205adda956..9bc28e9fcc8246733aad559916c36b4da2179657 100644 (file)
@@ -7,10 +7,11 @@
 
 #include "common.h"
 
-#include "buffer.h"
+#include "str.h"
 #include "tree.h"
 #include "refdb.h"
 #include "regexp.h"
+#include "date.h"
 
 #include "git2.h"
 
@@ -145,7 +146,7 @@ static int retrieve_previously_checked_out_branch_or_revision(git_object **out,
        size_t i, numentries, cur;
        const git_reflog_entry *entry;
        const char *msg;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        cur = position;
 
@@ -179,16 +180,16 @@ static int retrieve_previously_checked_out_branch_or_revision(git_object **out,
                if (cur > 0)
                        continue;
 
-               if ((git_buf_put(&buf, msg+regexmatches[1].start, regexmatches[1].end - regexmatches[1].start)) < 0)
+               if ((git_str_put(&buf, msg+regexmatches[1].start, regexmatches[1].end - regexmatches[1].start)) < 0)
                        goto cleanup;
 
-               if ((error = git_reference_dwim(base_ref, repo, git_buf_cstr(&buf))) == 0)
+               if ((error = git_reference_dwim(base_ref, repo, git_str_cstr(&buf))) == 0)
                        goto cleanup;
 
                if (error < 0 && error != GIT_ENOTFOUND)
                        goto cleanup;
 
-               error = maybe_abbrev(out, repo, git_buf_cstr(&buf));
+               error = maybe_abbrev(out, repo, git_str_cstr(&buf));
 
                goto cleanup;
        }
@@ -197,7 +198,7 @@ static int retrieve_previously_checked_out_branch_or_revision(git_object **out,
 
 cleanup:
        git_reference_free(ref);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        git_regexp_dispose(&preg);
        git_reflog_free(reflog);
        return error;
@@ -207,7 +208,7 @@ static int retrieve_oid_from_reflog(git_oid *oid, git_reference *ref, size_t ide
 {
        git_reflog *reflog;
        size_t numentries;
-       const git_reflog_entry *entry;
+       const git_reflog_entry *entry = NULL;
        bool search_by_pos = (identifier <= 100000000);
 
        if (git_reflog_read(&reflog, git_reference_owner(ref), git_reference_name(ref)) < 0)
@@ -236,8 +237,15 @@ static int retrieve_oid_from_reflog(git_oid *oid, git_reference *ref, size_t ide
                        break;
                }
 
-               if (i == numentries)
-                       goto notfound;
+               if (i == numentries) {
+                       if (entry == NULL)
+                               goto notfound;
+
+                       /*
+                        * TODO: emit a warning (log for 'branch' only goes back to ...)
+                        */
+                       git_oid_cpy(oid, git_reflog_entry_id_new(entry));
+               }
        }
 
        git_reflog_free(reflog);
@@ -314,12 +322,12 @@ static int handle_at_syntax(git_object **out, git_reference **ref, const char *s
 {
        bool is_numeric;
        int parsed = 0, error = -1;
-       git_buf identifier = GIT_BUF_INIT;
+       git_str identifier = GIT_STR_INIT;
        git_time_t timestamp;
 
        GIT_ASSERT(*out == NULL);
 
-       if (git_buf_put(&identifier, spec, identifier_len) < 0)
+       if (git_str_put(&identifier, spec, identifier_len) < 0)
                return -1;
 
        is_numeric = !try_parse_numeric(&parsed, curly_braces_content);
@@ -331,26 +339,28 @@ static int handle_at_syntax(git_object **out, git_reference **ref, const char *s
 
        if (is_numeric) {
                if (parsed < 0)
-                       error = retrieve_previously_checked_out_branch_or_revision(out, ref, repo, git_buf_cstr(&identifier), -parsed);
+                       error = retrieve_previously_checked_out_branch_or_revision(out, ref, repo, git_str_cstr(&identifier), -parsed);
                else
-                       error = retrieve_revobject_from_reflog(out, ref, repo, git_buf_cstr(&identifier), parsed);
+                       error = retrieve_revobject_from_reflog(out, ref, repo, git_str_cstr(&identifier), parsed);
 
                goto cleanup;
        }
 
        if (!strcmp(curly_braces_content, "u") || !strcmp(curly_braces_content, "upstream")) {
-               error = retrieve_remote_tracking_reference(ref, git_buf_cstr(&identifier), repo);
+               error = retrieve_remote_tracking_reference(ref, git_str_cstr(&identifier), repo);
 
                goto cleanup;
        }
 
-       if (git__date_parse(&timestamp, curly_braces_content) < 0)
+       if (git_date_parse(&timestamp, curly_braces_content) < 0) {
+               error = GIT_EINVALIDSPEC;
                goto cleanup;
+       }
 
-       error = retrieve_revobject_from_reflog(out, ref, repo, git_buf_cstr(&identifier), (size_t)timestamp);
+       error = retrieve_revobject_from_reflog(out, ref, repo, git_str_cstr(&identifier), (size_t)timestamp);
 
 cleanup:
-       git_buf_dispose(&identifier);
+       git_str_dispose(&identifier);
        return error;
 }
 
@@ -520,9 +530,9 @@ static int handle_caret_curly_syntax(git_object **out, git_object *obj, const ch
        return git_object_peel(out, obj, expected_type);
 }
 
-static int extract_curly_braces_content(git_buf *buf, const char *spec, size_t *pos)
+static int extract_curly_braces_content(git_str *buf, const char *spec, size_t *pos)
 {
-       git_buf_clear(buf);
+       git_str_clear(buf);
 
        GIT_ASSERT_ARG(spec[*pos] == '^' || spec[*pos] == '@');
 
@@ -537,7 +547,7 @@ static int extract_curly_braces_content(git_buf *buf, const char *spec, size_t *
                if (spec[*pos] == '\0')
                        return GIT_EINVALIDSPEC;
 
-               if (git_buf_putc(buf, spec[(*pos)++]) < 0)
+               if (git_str_putc(buf, spec[(*pos)++]) < 0)
                        return -1;
        }
 
@@ -546,18 +556,18 @@ static int extract_curly_braces_content(git_buf *buf, const char *spec, size_t *
        return 0;
 }
 
-static int extract_path(git_buf *buf, const char *spec, size_t *pos)
+static int extract_path(git_str *buf, const char *spec, size_t *pos)
 {
-       git_buf_clear(buf);
+       git_str_clear(buf);
 
        GIT_ASSERT_ARG(spec[*pos] == ':');
 
        (*pos)++;
 
-       if (git_buf_puts(buf, spec + *pos) < 0)
+       if (git_str_puts(buf, spec + *pos) < 0)
                return -1;
 
-       *pos += git_buf_len(buf);
+       *pos += git_str_len(buf);
 
        return 0;
 }
@@ -610,7 +620,7 @@ static int object_from_reference(git_object **object, git_reference *reference)
 static int ensure_base_rev_loaded(git_object **object, git_reference **reference, const char *spec, size_t identifier_len, git_repository *repo, bool allow_empty_identifier)
 {
        int error;
-       git_buf identifier = GIT_BUF_INIT;
+       git_str identifier = GIT_STR_INIT;
 
        if (*object != NULL)
                return 0;
@@ -621,11 +631,11 @@ static int ensure_base_rev_loaded(git_object **object, git_reference **reference
        if (!allow_empty_identifier && identifier_len == 0)
                return GIT_EINVALIDSPEC;
 
-       if (git_buf_put(&identifier, spec, identifier_len) < 0)
+       if (git_str_put(&identifier, spec, identifier_len) < 0)
                return -1;
 
-       error = revparse_lookup_object(object, reference, repo, git_buf_cstr(&identifier));
-       git_buf_dispose(&identifier);
+       error = revparse_lookup_object(object, reference, repo, git_str_cstr(&identifier));
+       git_str_dispose(&identifier);
 
        return error;
 }
@@ -669,7 +679,7 @@ static int revparse(
 {
        size_t pos = 0, identifier_len = 0;
        int error = -1, n;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        git_reference *reference = NULL;
        git_object *base_rev = NULL;
@@ -698,7 +708,7 @@ static int revparse(
                                if ((error = extract_curly_braces_content(&buf, spec, &pos)) < 0)
                                        goto cleanup;
 
-                               if ((error = handle_caret_curly_syntax(&temp_object, base_rev, git_buf_cstr(&buf))) < 0)
+                               if ((error = handle_caret_curly_syntax(&temp_object, base_rev, git_str_cstr(&buf))) < 0)
                                        goto cleanup;
 
                                git_object_free(base_rev);
@@ -750,11 +760,11 @@ static int revparse(
                                if ((error = ensure_base_rev_loaded(&base_rev, &reference, spec, identifier_len, repo, true)) < 0)
                                        goto cleanup;
 
-                               if ((error = handle_colon_syntax(&temp_object, base_rev, git_buf_cstr(&buf))) < 0)
+                               if ((error = handle_colon_syntax(&temp_object, base_rev, git_str_cstr(&buf))) < 0)
                                        goto cleanup;
                        } else {
-                               if (*git_buf_cstr(&buf) == '/') {
-                                       if ((error = handle_grep_syntax(&temp_object, repo, NULL, git_buf_cstr(&buf) + 1)) < 0)
+                               if (*git_str_cstr(&buf) == '/') {
+                                       if ((error = handle_grep_syntax(&temp_object, repo, NULL, git_str_cstr(&buf) + 1)) < 0)
                                                goto cleanup;
                                } else {
 
@@ -783,12 +793,15 @@ static int revparse(
                                if ((error = ensure_base_rev_is_not_known_yet(base_rev)) < 0)
                                        goto cleanup;
 
-                               if ((error = handle_at_syntax(&temp_object, &reference, spec, identifier_len, repo, git_buf_cstr(&buf))) < 0)
+                               if ((error = handle_at_syntax(&temp_object, &reference, spec, identifier_len, repo, git_str_cstr(&buf))) < 0)
                                        goto cleanup;
 
                                if (temp_object != NULL)
                                        base_rev = temp_object;
                                break;
+                       } else if (spec[pos+1] == '\0') {
+                               spec = "HEAD";
+                               break;
                        }
                        /* fall through */
 
@@ -824,7 +837,7 @@ cleanup:
                git_reference_free(reference);
        }
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
index a686a9f6fa91012de237b51b552930c4bf0f3a86..553e0497a14ec48f0cad0afc8f28133ab7e6c3df 100644 (file)
@@ -131,7 +131,7 @@ int git_revwalk__push_glob(git_revwalk *walk, const char *glob, const git_revwal
 {
        git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
        int error = 0;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_reference *ref;
        git_reference_iterator *iter;
        size_t wildcard;
@@ -144,15 +144,15 @@ int git_revwalk__push_glob(git_revwalk *walk, const char *glob, const git_revwal
 
        /* refs/ is implied if not given in the glob */
        if (git__prefixcmp(glob, GIT_REFS_DIR) != 0)
-               git_buf_joinpath(&buf, GIT_REFS_DIR, glob);
+               git_str_joinpath(&buf, GIT_REFS_DIR, glob);
        else
-               git_buf_puts(&buf, glob);
-       GIT_ERROR_CHECK_ALLOC_BUF(&buf);
+               git_str_puts(&buf, glob);
+       GIT_ERROR_CHECK_ALLOC_STR(&buf);
 
        /* If no '?', '*' or '[' exist, we append '/ *' to the glob */
        wildcard = strcspn(glob, "?*[");
        if (!glob[wildcard])
-               git_buf_put(&buf, "/*", 2);
+               git_str_put(&buf, "/*", 2);
 
        if ((error = git_reference_iterator_glob_new(&iter, walk->repo, buf.ptr)) < 0)
                goto out;
@@ -169,7 +169,7 @@ int git_revwalk__push_glob(git_revwalk *walk, const char *glob, const git_revwal
        if (error == GIT_ITEROVER)
                error = 0;
 out:
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
@@ -427,7 +427,7 @@ static int add_parents_to_list(git_revwalk *walk, git_commit_list_node *commit,
        return 0;
 }
 
-/* How many unintersting commits we want to look at after we run out of interesting ones */
+/* How many uninteresting commits we want to look at after we run out of interesting ones */
 #define SLOP 5
 
 static int still_interesting(git_commit_list *list, int64_t time, int slop)
index 1efda212a0adcbef76380ea7efc1a33667b25d35..5d6ab572cbf50962ec347c5dc1a38f61e7fcc4b2 100644 (file)
@@ -23,6 +23,12 @@ void git_signature_free(git_signature *sig)
        git__free(sig);
 }
 
+static int signature_parse_error(const char *msg)
+{
+       git_error_set(GIT_ERROR_INVALID, "failed to parse signature - %s", msg);
+       return GIT_EINVALID;
+}
+
 static int signature_error(const char *msg)
 {
        git_error_set(GIT_ERROR_INVALID, "failed to parse signature - %s", msg);
@@ -206,13 +212,13 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
 
        if (ender &&
                (buffer_end = memchr(buffer, ender, buffer_end - buffer)) == NULL)
-               return signature_error("no newline given");
+               return signature_parse_error("no newline given");
 
        if (header) {
                const size_t header_len = strlen(header);
 
                if (buffer + header_len >= buffer_end || memcmp(buffer, header, header_len) != 0)
-                       return signature_error("expected prefix doesn't match actual");
+                       return signature_parse_error("expected prefix doesn't match actual");
 
                buffer += header_len;
        }
@@ -221,7 +227,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
        email_end = git__memrchr(buffer, '>', buffer_end - buffer);
 
        if (!email_start || !email_end || email_end <= email_start)
-               return signature_error("malformed e-mail");
+               return signature_parse_error("malformed e-mail");
 
        email_start += 1;
        sig->name = extract_trimmed(buffer, email_start - buffer - 1);
@@ -237,7 +243,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
                        git__free(sig->name);
                        git__free(sig->email);
                        sig->name = sig->email = NULL;
-                       return signature_error("invalid Unix timestamp");
+                       return signature_parse_error("invalid Unix timestamp");
                }
 
                /* do we have a timezone? */
@@ -299,7 +305,7 @@ int git_signature_from_buffer(git_signature **out, const char *buf)
        return error;
 }
 
-void git_signature__writebuf(git_buf *buf, const char *header, const git_signature *sig)
+void git_signature__writebuf(git_str *buf, const char *header, const git_signature *sig)
 {
        int offset, hours, mins;
        char sign;
@@ -313,7 +319,7 @@ void git_signature__writebuf(git_buf *buf, const char *header, const git_signatu
        hours = offset / 60;
        mins = offset % 60;
 
-       git_buf_printf(buf, "%s%s <%s> %u %c%02d%02d\n",
+       git_str_printf(buf, "%s%s <%s> %u %c%02d%02d\n",
                        header ? header : "", sig->name, sig->email,
                        (unsigned)sig->when.time, sign, hours, mins);
 }
index 40d7c54f9c229918447009aea49e9ed799dc3269..5c8270954e72e3c536d3114e01ec65cca5d858ed 100644 (file)
@@ -15,7 +15,7 @@
 #include <time.h>
 
 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);
+void git_signature__writebuf(git_str *buf, const char *header, const git_signature *sig);
 bool git_signature__equal(const git_signature *one, const git_signature *two);
 
 int git_signature__pdup(git_signature **dest, const git_signature *source, git_pool *pool);
index ee6363f6d73d5ec30eb7a070f05b166b82f224e8..7ff900efe33335101f928b0b192174b3bef838ed 100644 (file)
@@ -201,7 +201,7 @@ void git_sortedcache_runlock(git_sortedcache *sc)
 /* if the file has changed, lock cache and load file contents into buf;
  * returns <0 on error, >0 if file has not changed
  */
-int git_sortedcache_lockandload(git_sortedcache *sc, git_buf *buf)
+int git_sortedcache_lockandload(git_sortedcache *sc, git_str *buf)
 {
        int error, fd;
        struct stat st;
index 0e1f63ceb00f2f516d34d0c6c4cc4969d3ee3a79..ef260a093a57db08a036dcfe95f27e75c2951e6f 100644 (file)
@@ -121,7 +121,7 @@ void git_sortedcache_wunlock(git_sortedcache *sc);
  * @return 0 if up-to-date, 1 if out-of-date, <0 on error
  */
 GIT_WARN_UNUSED_RESULT int git_sortedcache_lockandload(
-       git_sortedcache *sc, git_buf *buf);
+       git_sortedcache *sc, git_str *buf);
 
 /* Refresh file timestamp after write completes
  * You should already be holding the write lock when you call this.
index 49ea26fdd529243aa3da6224ab6b641b5ab808d4..5fc01ac36ddd2d3f86a3a329d03972e2bb2db9e9 100644 (file)
@@ -9,7 +9,6 @@
 
 #include "repository.h"
 #include "commit.h"
-#include "message.h"
 #include "tree.h"
 #include "reflog.h"
 #include "blob.h"
@@ -43,20 +42,20 @@ static int retrieve_head(git_reference **out, git_repository *repo)
        return error;
 }
 
-static int append_abbreviated_oid(git_buf *out, const git_oid *b_commit)
+static int append_abbreviated_oid(git_str *out, const git_oid *b_commit)
 {
        char *formatted_oid;
 
        formatted_oid = git_oid_allocfmt(b_commit);
        GIT_ERROR_CHECK_ALLOC(formatted_oid);
 
-       git_buf_put(out, formatted_oid, 7);
+       git_str_put(out, formatted_oid, 7);
        git__free(formatted_oid);
 
-       return git_buf_oom(out) ? -1 : 0;
+       return git_str_oom(out) ? -1 : 0;
 }
 
-static int append_commit_description(git_buf *out, git_commit *commit)
+static int append_commit_description(git_str *out, git_commit *commit)
 {
        const char *summary = git_commit_summary(commit);
        GIT_ERROR_CHECK_ALLOC(summary);
@@ -64,16 +63,16 @@ static int append_commit_description(git_buf *out, git_commit *commit)
        if (append_abbreviated_oid(out, git_commit_id(commit)) < 0)
                return -1;
 
-       git_buf_putc(out, ' ');
-       git_buf_puts(out, summary);
-       git_buf_putc(out, '\n');
+       git_str_putc(out, ' ');
+       git_str_puts(out, summary);
+       git_str_putc(out, '\n');
 
-       return git_buf_oom(out) ? -1 : 0;
+       return git_str_oom(out) ? -1 : 0;
 }
 
 static int retrieve_base_commit_and_message(
        git_commit **b_commit,
-       git_buf *stash_message,
+       git_str *stash_message,
        git_repository *repo)
 {
        git_reference *head = NULL;
@@ -83,9 +82,9 @@ static int retrieve_base_commit_and_message(
                return error;
 
        if (strcmp("HEAD", git_reference_name(head)) == 0)
-               error = git_buf_puts(stash_message, "(no branch): ");
+               error = git_str_puts(stash_message, "(no branch): ");
        else
-               error = git_buf_printf(
+               error = git_str_printf(
                        stash_message,
                        "%s: ",
                        git_reference_name(head) + strlen(GIT_REFS_HEADS_DIR));
@@ -128,13 +127,13 @@ static int commit_index(
 {
        git_tree *i_tree = NULL;
        git_oid i_commit_oid;
-       git_buf msg = GIT_BUF_INIT;
+       git_str msg = GIT_STR_INIT;
        int error;
 
        if ((error = build_tree_from_index(&i_tree, repo, index)) < 0)
                goto cleanup;
 
-       if ((error = git_buf_printf(&msg, "index on %s\n", message)) < 0)
+       if ((error = git_str_printf(&msg, "index on %s\n", message)) < 0)
                goto cleanup;
 
        if ((error = git_commit_create(
@@ -144,7 +143,7 @@ static int commit_index(
                stasher,
                stasher,
                NULL,
-               git_buf_cstr(&msg),
+               git_str_cstr(&msg),
                i_tree,
                1,
                &parent)) < 0)
@@ -154,7 +153,7 @@ static int commit_index(
 
 cleanup:
        git_tree_free(i_tree);
-       git_buf_dispose(&msg);
+       git_str_dispose(&msg);
        return error;
 }
 
@@ -303,13 +302,13 @@ static int commit_untracked(
 {
        git_tree *u_tree = NULL;
        git_oid u_commit_oid;
-       git_buf msg = GIT_BUF_INIT;
+       git_str msg = GIT_STR_INIT;
        int error;
 
        if ((error = build_untracked_tree(&u_tree, repo, i_commit, flags)) < 0)
                goto cleanup;
 
-       if ((error = git_buf_printf(&msg, "untracked files on %s\n", message)) < 0)
+       if ((error = git_str_printf(&msg, "untracked files on %s\n", message)) < 0)
                goto cleanup;
 
        if ((error = git_commit_create(
@@ -319,7 +318,7 @@ static int commit_untracked(
                stasher,
                stasher,
                NULL,
-               git_buf_cstr(&msg),
+               git_str_cstr(&msg),
                u_tree,
                0,
                NULL)) < 0)
@@ -329,7 +328,7 @@ static int commit_untracked(
 
 cleanup:
        git_tree_free(u_tree);
-       git_buf_dispose(&msg);
+       git_str_dispose(&msg);
        return error;
 }
 
@@ -437,33 +436,33 @@ cleanup:
        return error;
 }
 
-static int prepare_worktree_commit_message(git_buf *out, const char *user_message)
+static int prepare_worktree_commit_message(git_str *out, const char *user_message)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        int error = 0;
 
        if (!user_message) {
-               git_buf_printf(&buf, "WIP on %s", git_buf_cstr(out));
+               git_str_printf(&buf, "WIP on %s", git_str_cstr(out));
        } else {
                const char *colon;
 
-               if ((colon = strchr(git_buf_cstr(out), ':')) == NULL)
+               if ((colon = strchr(git_str_cstr(out), ':')) == NULL)
                        goto cleanup;
 
-               git_buf_puts(&buf, "On ");
-               git_buf_put(&buf, git_buf_cstr(out), colon - out->ptr);
-               git_buf_printf(&buf, ": %s\n", user_message);
+               git_str_puts(&buf, "On ");
+               git_str_put(&buf, git_str_cstr(out), colon - out->ptr);
+               git_str_printf(&buf, ": %s\n", user_message);
        }
 
-       if (git_buf_oom(&buf)) {
+       if (git_str_oom(&buf)) {
                error = -1;
                goto cleanup;
        }
 
-       git_buf_swap(out, &buf);
+       git_str_swap(out, &buf);
 
 cleanup:
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
@@ -543,7 +542,7 @@ int git_stash_save(
 {
        git_index *index = NULL;
        git_commit *b_commit = NULL, *i_commit = NULL, *u_commit = NULL;
-       git_buf msg = GIT_BUF_INIT;
+       git_str msg = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(out);
@@ -563,24 +562,24 @@ int git_stash_save(
                goto cleanup;
 
        if ((error = commit_index(&i_commit, repo, index, stasher,
-                                 git_buf_cstr(&msg), b_commit)) < 0)
+                                 git_str_cstr(&msg), b_commit)) < 0)
                goto cleanup;
 
        if ((flags & (GIT_STASH_INCLUDE_UNTRACKED | GIT_STASH_INCLUDE_IGNORED)) &&
            (error = commit_untracked(&u_commit, repo, stasher,
-                                     git_buf_cstr(&msg), i_commit, flags)) < 0)
+                                     git_str_cstr(&msg), i_commit, flags)) < 0)
                goto cleanup;
 
        if ((error = prepare_worktree_commit_message(&msg, message)) < 0)
                goto cleanup;
 
-       if ((error = commit_worktree(out, repo, stasher, git_buf_cstr(&msg),
+       if ((error = commit_worktree(out, repo, stasher, git_str_cstr(&msg),
                                     i_commit, b_commit, u_commit)) < 0)
                goto cleanup;
 
-       git_buf_rtrim(&msg);
+       git_str_rtrim(&msg);
 
-       if ((error = update_reflog(out, repo, git_buf_cstr(&msg))) < 0)
+       if ((error = update_reflog(out, repo, git_str_cstr(&msg))) < 0)
                goto cleanup;
 
        if ((error = reset_index_and_workdir(repo, (flags & GIT_STASH_KEEP_INDEX) ? i_commit : b_commit,
@@ -589,7 +588,7 @@ int git_stash_save(
 
 cleanup:
 
-       git_buf_dispose(&msg);
+       git_str_dispose(&msg);
        git_commit_free(i_commit);
        git_commit_free(b_commit);
        git_commit_free(u_commit);
index c98564643fc9bd5eff7380184f2e804b9122be02..df0f7450731b1e7ec4f6075e5c040367d5727d89 100644 (file)
@@ -84,7 +84,7 @@ static unsigned int workdir_delta2status(
 
                if (!git_oid_equal(&idx2wd->old_file.id, &idx2wd->new_file.id)) {
                        /* if OIDs don't match, we might need to calculate them now to
-                        * discern between RENAMED vs RENAMED+MODIFED
+                        * discern between RENAMED vs RENAMED+MODIFIED
                         */
                        if (git_oid_is_zero(&idx2wd->old_file.id) &&
                                diff->old_src == GIT_ITERATOR_WORKDIR &&
@@ -336,6 +336,9 @@ int git_status_list_new(
                        GIT_DIFF_FIND_RENAMES_FROM_REWRITES |
                        GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY;
 
+       if (opts != NULL && opts->rename_threshold != 0)
+               findopt.rename_threshold = opts->rename_threshold;
+
        if (show != GIT_STATUS_SHOW_WORKDIR_ONLY) {
                if ((error = git_diff_tree_to_index(
                                &status->head2idx, repo, head, index, &diffopt)) < 0)
diff --git a/src/str.c b/src/str.c
new file mode 100644 (file)
index 0000000..0d405bf
--- /dev/null
+++ b/src/str.c
@@ -0,0 +1,1372 @@
+/*
+ * 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 "str.h"
+#include "posix.h"
+#include <ctype.h>
+
+/* Used as default value for git_str->ptr so that people can always
+ * assume ptr is non-NULL and zero terminated even for new git_strs.
+ */
+char git_str__initstr[1];
+
+char git_str__oom[1];
+
+#define ENSURE_SIZE(b, d) \
+       if ((b)->ptr == git_str__oom || \
+           ((d) > (b)->asize && git_str_grow((b), (d)) < 0))\
+               return -1;
+
+
+int git_str_init(git_str *buf, size_t initial_size)
+{
+       buf->asize = 0;
+       buf->size = 0;
+       buf->ptr = git_str__initstr;
+
+       ENSURE_SIZE(buf, initial_size);
+
+       return 0;
+}
+
+int git_str_try_grow(
+       git_str *buf, size_t target_size, bool mark_oom)
+{
+       char *new_ptr;
+       size_t new_size;
+
+       if (buf->ptr == git_str__oom)
+               return -1;
+
+       if (buf->asize == 0 && buf->size != 0) {
+               git_error_set(GIT_ERROR_INVALID, "cannot grow a borrowed buffer");
+               return GIT_EINVALID;
+       }
+
+       if (!target_size)
+               target_size = buf->size;
+
+       if (target_size <= buf->asize)
+               return 0;
+
+       if (buf->asize == 0) {
+               new_size = target_size;
+               new_ptr = NULL;
+       } else {
+               new_size = buf->asize;
+               /*
+                * Grow the allocated buffer by 1.5 to allow
+                * re-use of memory holes resulting from the
+                * realloc. If this is still too small, then just
+                * use the target size.
+                */
+               if ((new_size = (new_size << 1) - (new_size >> 1)) < target_size)
+                       new_size = target_size;
+               new_ptr = buf->ptr;
+       }
+
+       /* round allocation up to multiple of 8 */
+       new_size = (new_size + 7) & ~7;
+
+       if (new_size < buf->size) {
+               if (mark_oom) {
+                       if (buf->ptr && buf->ptr != git_str__initstr)
+                               git__free(buf->ptr);
+                       buf->ptr = git_str__oom;
+               }
+
+               git_error_set_oom();
+               return -1;
+       }
+
+       new_ptr = git__realloc(new_ptr, new_size);
+
+       if (!new_ptr) {
+               if (mark_oom) {
+                       if (buf->ptr && (buf->ptr != git_str__initstr))
+                               git__free(buf->ptr);
+                       buf->ptr = git_str__oom;
+               }
+               return -1;
+       }
+
+       buf->asize = new_size;
+       buf->ptr   = new_ptr;
+
+       /* truncate the existing buffer size if necessary */
+       if (buf->size >= buf->asize)
+               buf->size = buf->asize - 1;
+       buf->ptr[buf->size] = '\0';
+
+       return 0;
+}
+
+int git_str_grow(git_str *buffer, size_t target_size)
+{
+       return git_str_try_grow(buffer, target_size, true);
+}
+
+int git_str_grow_by(git_str *buffer, size_t additional_size)
+{
+       size_t newsize;
+
+       if (GIT_ADD_SIZET_OVERFLOW(&newsize, buffer->size, additional_size)) {
+               buffer->ptr = git_str__oom;
+               return -1;
+       }
+
+       return git_str_try_grow(buffer, newsize, true);
+}
+
+void git_str_dispose(git_str *buf)
+{
+       if (!buf) return;
+
+       if (buf->asize > 0 && buf->ptr != NULL && buf->ptr != git_str__oom)
+               git__free(buf->ptr);
+
+       git_str_init(buf, 0);
+}
+
+void git_str_clear(git_str *buf)
+{
+       buf->size = 0;
+
+       if (!buf->ptr) {
+               buf->ptr = git_str__initstr;
+               buf->asize = 0;
+       }
+
+       if (buf->asize > 0)
+               buf->ptr[0] = '\0';
+}
+
+int git_str_set(git_str *buf, const void *data, size_t len)
+{
+       size_t alloclen;
+
+       if (len == 0 || data == NULL) {
+               git_str_clear(buf);
+       } else {
+               if (data != buf->ptr) {
+                       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, len, 1);
+                       ENSURE_SIZE(buf, alloclen);
+                       memmove(buf->ptr, data, len);
+               }
+
+               buf->size = len;
+               if (buf->asize > buf->size)
+                       buf->ptr[buf->size] = '\0';
+
+       }
+       return 0;
+}
+
+int git_str_sets(git_str *buf, const char *string)
+{
+       return git_str_set(buf, string, string ? strlen(string) : 0);
+}
+
+int git_str_putc(git_str *buf, char c)
+{
+       size_t new_size;
+       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, 2);
+       ENSURE_SIZE(buf, new_size);
+       buf->ptr[buf->size++] = c;
+       buf->ptr[buf->size] = '\0';
+       return 0;
+}
+
+int git_str_putcn(git_str *buf, char c, size_t len)
+{
+       size_t new_size;
+       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, len);
+       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
+       ENSURE_SIZE(buf, new_size);
+       memset(buf->ptr + buf->size, c, len);
+       buf->size += len;
+       buf->ptr[buf->size] = '\0';
+       return 0;
+}
+
+int git_str_put(git_str *buf, const char *data, size_t len)
+{
+       if (len) {
+               size_t new_size;
+
+               GIT_ASSERT_ARG(data);
+
+               GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, len);
+               GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
+               ENSURE_SIZE(buf, new_size);
+               memmove(buf->ptr + buf->size, data, len);
+               buf->size += len;
+               buf->ptr[buf->size] = '\0';
+       }
+       return 0;
+}
+
+int git_str_puts(git_str *buf, const char *string)
+{
+       GIT_ASSERT_ARG(string);
+
+       return git_str_put(buf, string, strlen(string));
+}
+
+static char hex_encode[] = "0123456789abcdef";
+
+int git_str_encode_hexstr(git_str *str, const char *data, size_t len)
+{
+       size_t new_size, i;
+       char *s;
+
+       GIT_ERROR_CHECK_ALLOC_MULTIPLY(&new_size, len, 2);
+       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
+
+       if (git_str_grow_by(str, new_size) < 0)
+               return -1;
+
+       s = str->ptr + str->size;
+
+       for (i = 0; i < len; i++) {
+               *s++ = hex_encode[(data[i] & 0xf0) >> 4];
+               *s++ = hex_encode[(data[i] & 0x0f)];
+       }
+
+       str->size += (len * 2);
+       str->ptr[str->size] = '\0';
+
+       return 0;
+}
+
+static const char base64_encode[] =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+int git_str_encode_base64(git_str *buf, const char *data, size_t len)
+{
+       size_t extra = len % 3;
+       uint8_t *write, a, b, c;
+       const uint8_t *read = (const uint8_t *)data;
+       size_t blocks = (len / 3) + !!extra, alloclen;
+
+       GIT_ERROR_CHECK_ALLOC_ADD(&blocks, blocks, 1);
+       GIT_ERROR_CHECK_ALLOC_MULTIPLY(&alloclen, blocks, 4);
+       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, buf->size);
+
+       ENSURE_SIZE(buf, alloclen);
+       write = (uint8_t *)&buf->ptr[buf->size];
+
+       /* convert each run of 3 bytes into 4 output bytes */
+       for (len -= extra; len > 0; len -= 3) {
+               a = *read++;
+               b = *read++;
+               c = *read++;
+
+               *write++ = base64_encode[a >> 2];
+               *write++ = base64_encode[(a & 0x03) << 4 | b >> 4];
+               *write++ = base64_encode[(b & 0x0f) << 2 | c >> 6];
+               *write++ = base64_encode[c & 0x3f];
+       }
+
+       if (extra > 0) {
+               a = *read++;
+               b = (extra > 1) ? *read++ : 0;
+
+               *write++ = base64_encode[a >> 2];
+               *write++ = base64_encode[(a & 0x03) << 4 | b >> 4];
+               *write++ = (extra > 1) ? base64_encode[(b & 0x0f) << 2] : '=';
+               *write++ = '=';
+       }
+
+       buf->size = ((char *)write) - buf->ptr;
+       buf->ptr[buf->size] = '\0';
+
+       return 0;
+}
+
+/* The inverse of base64_encode */
+static const int8_t base64_decode[] = {
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+       52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1,  0, -1, -1,
+       -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+       15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+       -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+int git_str_decode_base64(git_str *buf, const char *base64, size_t len)
+{
+       size_t i;
+       int8_t a, b, c, d;
+       size_t orig_size = buf->size, new_size;
+
+       if (len % 4) {
+               git_error_set(GIT_ERROR_INVALID, "invalid base64 input");
+               return -1;
+       }
+
+       GIT_ASSERT_ARG(len % 4 == 0);
+       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, (len / 4 * 3), buf->size);
+       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
+       ENSURE_SIZE(buf, new_size);
+
+       for (i = 0; i < len; i += 4) {
+               if ((a = base64_decode[(unsigned char)base64[i]]) < 0 ||
+                       (b = base64_decode[(unsigned char)base64[i+1]]) < 0 ||
+                       (c = base64_decode[(unsigned char)base64[i+2]]) < 0 ||
+                       (d = base64_decode[(unsigned char)base64[i+3]]) < 0) {
+                       buf->size = orig_size;
+                       buf->ptr[buf->size] = '\0';
+
+                       git_error_set(GIT_ERROR_INVALID, "invalid base64 input");
+                       return -1;
+               }
+
+               buf->ptr[buf->size++] = ((a << 2) | (b & 0x30) >> 4);
+               buf->ptr[buf->size++] = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2);
+               buf->ptr[buf->size++] = (c & 0x03) << 6 | (d & 0x3f);
+       }
+
+       buf->ptr[buf->size] = '\0';
+       return 0;
+}
+
+static const char base85_encode[] =
+       "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
+
+int git_str_encode_base85(git_str *buf, const char *data, size_t len)
+{
+       size_t blocks = (len / 4) + !!(len % 4), alloclen;
+
+       GIT_ERROR_CHECK_ALLOC_MULTIPLY(&alloclen, blocks, 5);
+       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, buf->size);
+       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
+
+       ENSURE_SIZE(buf, alloclen);
+
+       while (len) {
+               uint32_t acc = 0;
+               char b85[5];
+               int i;
+
+               for (i = 24; i >= 0; i -= 8) {
+                       uint8_t ch = *data++;
+                       acc |= (uint32_t)ch << i;
+
+                       if (--len == 0)
+                               break;
+               }
+
+               for (i = 4; i >= 0; i--) {
+                       int val = acc % 85;
+                       acc /= 85;
+
+                       b85[i] = base85_encode[val];
+               }
+
+               for (i = 0; i < 5; i++)
+                       buf->ptr[buf->size++] = b85[i];
+       }
+
+       buf->ptr[buf->size] = '\0';
+
+       return 0;
+}
+
+/* The inverse of base85_encode */
+static const int8_t base85_decode[] = {
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, 63, -1, 64, 65, 66, 67, -1, 68, 69, 70, 71, -1, 72, -1, -1,
+        1,  2,  3,  4,  5,  6,  7,  8,  9, 10, -1, 73, 74, 75, 76, 77,
+       78, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+       26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -1, -1, -1, 79, 80,
+       81, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+       52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 82, 83, 84, 85, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+int git_str_decode_base85(
+       git_str *buf,
+       const char *base85,
+       size_t base85_len,
+       size_t output_len)
+{
+       size_t orig_size = buf->size, new_size;
+
+       if (base85_len % 5 ||
+               output_len > base85_len * 4 / 5) {
+               git_error_set(GIT_ERROR_INVALID, "invalid base85 input");
+               return -1;
+       }
+
+       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, output_len, buf->size);
+       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
+       ENSURE_SIZE(buf, new_size);
+
+       while (output_len) {
+               unsigned acc = 0;
+               int de, cnt = 4;
+               unsigned char ch;
+               do {
+                       ch = *base85++;
+                       de = base85_decode[ch];
+                       if (--de < 0)
+                               goto on_error;
+
+                       acc = acc * 85 + de;
+               } while (--cnt);
+               ch = *base85++;
+               de = base85_decode[ch];
+               if (--de < 0)
+                       goto on_error;
+
+               /* Detect overflow. */
+               if (0xffffffff / 85 < acc ||
+                       0xffffffff - de < (acc *= 85))
+                       goto on_error;
+
+               acc += de;
+
+               cnt = (output_len < 4) ? (int)output_len : 4;
+               output_len -= cnt;
+               do {
+                       acc = (acc << 8) | (acc >> 24);
+                       buf->ptr[buf->size++] = acc;
+               } while (--cnt);
+       }
+
+       buf->ptr[buf->size] = 0;
+
+       return 0;
+
+on_error:
+       buf->size = orig_size;
+       buf->ptr[buf->size] = '\0';
+
+       git_error_set(GIT_ERROR_INVALID, "invalid base85 input");
+       return -1;
+}
+
+#define HEX_DECODE(c) ((c | 32) % 39 - 9)
+
+int git_str_decode_percent(
+       git_str *buf,
+       const char *str,
+       size_t str_len)
+{
+       size_t str_pos, new_size;
+
+       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, str_len);
+       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
+       ENSURE_SIZE(buf, new_size);
+
+       for (str_pos = 0; str_pos < str_len; buf->size++, str_pos++) {
+               if (str[str_pos] == '%' &&
+                       str_len > str_pos + 2 &&
+                       isxdigit(str[str_pos + 1]) &&
+                       isxdigit(str[str_pos + 2])) {
+                       buf->ptr[buf->size] = (HEX_DECODE(str[str_pos + 1]) << 4) +
+                               HEX_DECODE(str[str_pos + 2]);
+                       str_pos += 2;
+               } else {
+                       buf->ptr[buf->size] = str[str_pos];
+               }
+       }
+
+       buf->ptr[buf->size] = '\0';
+       return 0;
+}
+
+int git_str_vprintf(git_str *buf, const char *format, va_list ap)
+{
+       size_t expected_size, new_size;
+       int len;
+
+       GIT_ERROR_CHECK_ALLOC_MULTIPLY(&expected_size, strlen(format), 2);
+       GIT_ERROR_CHECK_ALLOC_ADD(&expected_size, expected_size, buf->size);
+       ENSURE_SIZE(buf, expected_size);
+
+       while (1) {
+               va_list args;
+               va_copy(args, ap);
+
+               len = p_vsnprintf(
+                       buf->ptr + buf->size,
+                       buf->asize - buf->size,
+                       format, args
+               );
+
+               va_end(args);
+
+               if (len < 0) {
+                       git__free(buf->ptr);
+                       buf->ptr = git_str__oom;
+                       return -1;
+               }
+
+               if ((size_t)len + 1 <= buf->asize - buf->size) {
+                       buf->size += len;
+                       break;
+               }
+
+               GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, len);
+               GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
+               ENSURE_SIZE(buf, new_size);
+       }
+
+       return 0;
+}
+
+int git_str_printf(git_str *buf, const char *format, ...)
+{
+       int r;
+       va_list ap;
+
+       va_start(ap, format);
+       r = git_str_vprintf(buf, format, ap);
+       va_end(ap);
+
+       return r;
+}
+
+int git_str_copy_cstr(char *data, size_t datasize, const git_str *buf)
+{
+       size_t copylen;
+
+       GIT_ASSERT_ARG(data);
+       GIT_ASSERT_ARG(datasize);
+       GIT_ASSERT_ARG(buf);
+
+       data[0] = '\0';
+
+       if (buf->size == 0 || buf->asize <= 0)
+               return 0;
+
+       copylen = buf->size;
+       if (copylen > datasize - 1)
+               copylen = datasize - 1;
+       memmove(data, buf->ptr, copylen);
+       data[copylen] = '\0';
+
+       return 0;
+}
+
+void git_str_consume_bytes(git_str *buf, size_t len)
+{
+       git_str_consume(buf, buf->ptr + len);
+}
+
+void git_str_consume(git_str *buf, const char *end)
+{
+       if (end > buf->ptr && end <= buf->ptr + buf->size) {
+               size_t consumed = end - buf->ptr;
+               memmove(buf->ptr, end, buf->size - consumed);
+               buf->size -= consumed;
+               buf->ptr[buf->size] = '\0';
+       }
+}
+
+void git_str_truncate(git_str *buf, size_t len)
+{
+       if (len >= buf->size)
+               return;
+
+       buf->size = len;
+       if (buf->size < buf->asize)
+               buf->ptr[buf->size] = '\0';
+}
+
+void git_str_shorten(git_str *buf, size_t amount)
+{
+       if (buf->size > amount)
+               git_str_truncate(buf, buf->size - amount);
+       else
+               git_str_clear(buf);
+}
+
+void git_str_truncate_at_char(git_str *buf, char separator)
+{
+       ssize_t idx = git_str_find(buf, separator);
+       if (idx >= 0)
+               git_str_truncate(buf, (size_t)idx);
+}
+
+void git_str_rtruncate_at_char(git_str *buf, char separator)
+{
+       ssize_t idx = git_str_rfind_next(buf, separator);
+       git_str_truncate(buf, idx < 0 ? 0 : (size_t)idx);
+}
+
+void git_str_swap(git_str *str_a, git_str *str_b)
+{
+       git_str t = *str_a;
+       *str_a = *str_b;
+       *str_b = t;
+}
+
+char *git_str_detach(git_str *buf)
+{
+       char *data = buf->ptr;
+
+       if (buf->asize == 0 || buf->ptr == git_str__oom)
+               return NULL;
+
+       git_str_init(buf, 0);
+
+       return data;
+}
+
+int git_str_attach(git_str *buf, char *ptr, size_t asize)
+{
+       git_str_dispose(buf);
+
+       if (ptr) {
+               buf->ptr = ptr;
+               buf->size = strlen(ptr);
+               if (asize)
+                       buf->asize = (asize < buf->size) ? buf->size + 1 : asize;
+               else /* pass 0 to fall back on strlen + 1 */
+                       buf->asize = buf->size + 1;
+       }
+
+       ENSURE_SIZE(buf, asize);
+       return 0;
+}
+
+void git_str_attach_notowned(git_str *buf, const char *ptr, size_t size)
+{
+       if (git_str_is_allocated(buf))
+               git_str_dispose(buf);
+
+       if (!size) {
+               git_str_init(buf, 0);
+       } else {
+               buf->ptr = (char *)ptr;
+               buf->asize = 0;
+               buf->size = size;
+       }
+}
+
+int git_str_join_n(git_str *buf, char separator, int nbuf, ...)
+{
+       va_list ap;
+       int i;
+       size_t total_size = 0, original_size = buf->size;
+       char *out, *original = buf->ptr;
+
+       if (buf->size > 0 && buf->ptr[buf->size - 1] != separator)
+               ++total_size; /* space for initial separator */
+
+       /* Make two passes to avoid multiple reallocation */
+
+       va_start(ap, nbuf);
+       for (i = 0; i < nbuf; ++i) {
+               const char *segment;
+               size_t segment_len;
+
+               segment = va_arg(ap, const char *);
+               if (!segment)
+                       continue;
+
+               segment_len = strlen(segment);
+
+               GIT_ERROR_CHECK_ALLOC_ADD(&total_size, total_size, segment_len);
+
+               if (segment_len == 0 || segment[segment_len - 1] != separator)
+                       GIT_ERROR_CHECK_ALLOC_ADD(&total_size, total_size, 1);
+       }
+       va_end(ap);
+
+       /* expand buffer if needed */
+       if (total_size == 0)
+               return 0;
+
+       GIT_ERROR_CHECK_ALLOC_ADD(&total_size, total_size, 1);
+       if (git_str_grow_by(buf, total_size) < 0)
+               return -1;
+
+       out = buf->ptr + buf->size;
+
+       /* append separator to existing buf if needed */
+       if (buf->size > 0 && out[-1] != separator)
+               *out++ = separator;
+
+       va_start(ap, nbuf);
+       for (i = 0; i < nbuf; ++i) {
+               const char *segment;
+               size_t segment_len;
+
+               segment = va_arg(ap, const char *);
+               if (!segment)
+                       continue;
+
+               /* deal with join that references buffer's original content */
+               if (segment >= original && segment < original + original_size) {
+                       size_t offset = (segment - original);
+                       segment = buf->ptr + offset;
+                       segment_len = original_size - offset;
+               } else {
+                       segment_len = strlen(segment);
+               }
+
+               /* skip leading separators */
+               if (out > buf->ptr && out[-1] == separator)
+                       while (segment_len > 0 && *segment == separator) {
+                               segment++;
+                               segment_len--;
+                       }
+
+               /* copy over next buffer */
+               if (segment_len > 0) {
+                       memmove(out, segment, segment_len);
+                       out += segment_len;
+               }
+
+               /* append trailing separator (except for last item) */
+               if (i < nbuf - 1 && out > buf->ptr && out[-1] != separator)
+                       *out++ = separator;
+       }
+       va_end(ap);
+
+       /* set size based on num characters actually written */
+       buf->size = out - buf->ptr;
+       buf->ptr[buf->size] = '\0';
+
+       return 0;
+}
+
+int git_str_join(
+       git_str *buf,
+       char separator,
+       const char *str_a,
+       const char *str_b)
+{
+       size_t strlen_a = str_a ? strlen(str_a) : 0;
+       size_t strlen_b = strlen(str_b);
+       size_t alloc_len;
+       int need_sep = 0;
+       ssize_t offset_a = -1;
+
+       /* not safe to have str_b point internally to the buffer */
+       if (buf->size)
+               GIT_ASSERT_ARG(str_b < buf->ptr || str_b >= buf->ptr + buf->size);
+
+       /* figure out if we need to insert a separator */
+       if (separator && strlen_a) {
+               while (*str_b == separator) { str_b++; strlen_b--; }
+               if (str_a[strlen_a - 1] != separator)
+                       need_sep = 1;
+       }
+
+       /* str_a could be part of the buffer */
+       if (buf->size && str_a >= buf->ptr && str_a < buf->ptr + buf->size)
+               offset_a = str_a - buf->ptr;
+
+       GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, strlen_a, strlen_b);
+       GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, need_sep);
+       GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 1);
+       ENSURE_SIZE(buf, alloc_len);
+
+       /* fix up internal pointers */
+       if (offset_a >= 0)
+               str_a = buf->ptr + offset_a;
+
+       /* do the actual copying */
+       if (offset_a != 0 && str_a)
+               memmove(buf->ptr, str_a, strlen_a);
+       if (need_sep)
+               buf->ptr[strlen_a] = separator;
+       memcpy(buf->ptr + strlen_a + need_sep, str_b, strlen_b);
+
+       buf->size = strlen_a + strlen_b + need_sep;
+       buf->ptr[buf->size] = '\0';
+
+       return 0;
+}
+
+int git_str_join3(
+       git_str *buf,
+       char separator,
+       const char *str_a,
+       const char *str_b,
+       const char *str_c)
+{
+       size_t len_a = strlen(str_a),
+               len_b = strlen(str_b),
+               len_c = strlen(str_c),
+               len_total;
+       int sep_a = 0, sep_b = 0;
+       char *tgt;
+
+       /* for this function, disallow pointers into the existing buffer */
+       GIT_ASSERT(str_a < buf->ptr || str_a >= buf->ptr + buf->size);
+       GIT_ASSERT(str_b < buf->ptr || str_b >= buf->ptr + buf->size);
+       GIT_ASSERT(str_c < buf->ptr || str_c >= buf->ptr + buf->size);
+
+       if (separator) {
+               if (len_a > 0) {
+                       while (*str_b == separator) { str_b++; len_b--; }
+                       sep_a = (str_a[len_a - 1] != separator);
+               }
+               if (len_a > 0 || len_b > 0)
+                       while (*str_c == separator) { str_c++; len_c--; }
+               if (len_b > 0)
+                       sep_b = (str_b[len_b - 1] != separator);
+       }
+
+       GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_a, sep_a);
+       GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_total, len_b);
+       GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_total, sep_b);
+       GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_total, len_c);
+       GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_total, 1);
+       ENSURE_SIZE(buf, len_total);
+
+       tgt = buf->ptr;
+
+       if (len_a) {
+               memcpy(tgt, str_a, len_a);
+               tgt += len_a;
+       }
+       if (sep_a)
+               *tgt++ = separator;
+       if (len_b) {
+               memcpy(tgt, str_b, len_b);
+               tgt += len_b;
+       }
+       if (sep_b)
+               *tgt++ = separator;
+       if (len_c)
+               memcpy(tgt, str_c, len_c);
+
+       buf->size = len_a + sep_a + len_b + sep_b + len_c;
+       buf->ptr[buf->size] = '\0';
+
+       return 0;
+}
+
+void git_str_rtrim(git_str *buf)
+{
+       while (buf->size > 0) {
+               if (!git__isspace(buf->ptr[buf->size - 1]))
+                       break;
+
+               buf->size--;
+       }
+
+       if (buf->asize > buf->size)
+               buf->ptr[buf->size] = '\0';
+}
+
+int git_str_cmp(const git_str *a, const git_str *b)
+{
+       int result = memcmp(a->ptr, b->ptr, min(a->size, b->size));
+       return (result != 0) ? result :
+               (a->size < b->size) ? -1 : (a->size > b->size) ? 1 : 0;
+}
+
+int git_str_splice(
+       git_str *buf,
+       size_t where,
+       size_t nb_to_remove,
+       const char *data,
+       size_t nb_to_insert)
+{
+       char *splice_loc;
+       size_t new_size, alloc_size;
+
+       GIT_ASSERT(buf);
+       GIT_ASSERT(where <= buf->size);
+       GIT_ASSERT(nb_to_remove <= buf->size - where);
+
+       splice_loc = buf->ptr + where;
+
+       /* Ported from git.git
+        * https://github.com/git/git/blob/16eed7c/strbuf.c#L159-176
+        */
+       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, (buf->size - nb_to_remove), nb_to_insert);
+       GIT_ERROR_CHECK_ALLOC_ADD(&alloc_size, new_size, 1);
+       ENSURE_SIZE(buf, alloc_size);
+
+       memmove(splice_loc + nb_to_insert,
+               splice_loc + nb_to_remove,
+               buf->size - where - nb_to_remove);
+
+       memcpy(splice_loc, data, nb_to_insert);
+
+       buf->size = new_size;
+       buf->ptr[buf->size] = '\0';
+       return 0;
+}
+
+/* Quote per http://marc.info/?l=git&m=112927316408690&w=2 */
+int git_str_quote(git_str *buf)
+{
+       const char whitespace[] = { 'a', 'b', 't', 'n', 'v', 'f', 'r' };
+       git_str quoted = GIT_STR_INIT;
+       size_t i = 0;
+       bool quote = false;
+       int error = 0;
+
+       /* walk to the first char that needs quoting */
+       if (buf->size && buf->ptr[0] == '!')
+               quote = true;
+
+       for (i = 0; !quote && i < buf->size; i++) {
+               if (buf->ptr[i] == '"' || buf->ptr[i] == '\\' ||
+                       buf->ptr[i] < ' ' || buf->ptr[i] > '~') {
+                       quote = true;
+                       break;
+               }
+       }
+
+       if (!quote)
+               goto done;
+
+       git_str_putc(&quoted, '"');
+       git_str_put(&quoted, buf->ptr, i);
+
+       for (; i < buf->size; i++) {
+               /* whitespace - use the map above, which is ordered by ascii value */
+               if (buf->ptr[i] >= '\a' && buf->ptr[i] <= '\r') {
+                       git_str_putc(&quoted, '\\');
+                       git_str_putc(&quoted, whitespace[buf->ptr[i] - '\a']);
+               }
+
+               /* double quote and backslash must be escaped */
+               else if (buf->ptr[i] == '"' || buf->ptr[i] == '\\') {
+                       git_str_putc(&quoted, '\\');
+                       git_str_putc(&quoted, buf->ptr[i]);
+               }
+
+               /* escape anything unprintable as octal */
+               else if (buf->ptr[i] != ' ' &&
+                               (buf->ptr[i] < '!' || buf->ptr[i] > '~')) {
+                       git_str_printf(&quoted, "\\%03o", (unsigned char)buf->ptr[i]);
+               }
+
+               /* yay, printable! */
+               else {
+                       git_str_putc(&quoted, buf->ptr[i]);
+               }
+       }
+
+       git_str_putc(&quoted, '"');
+
+       if (git_str_oom(&quoted)) {
+               error = -1;
+               goto done;
+       }
+
+       git_str_swap(&quoted, buf);
+
+done:
+       git_str_dispose(&quoted);
+       return error;
+}
+
+/* Unquote per http://marc.info/?l=git&m=112927316408690&w=2 */
+int git_str_unquote(git_str *buf)
+{
+       size_t i, j;
+       char ch;
+
+       git_str_rtrim(buf);
+
+       if (buf->size < 2 || buf->ptr[0] != '"' || buf->ptr[buf->size-1] != '"')
+               goto invalid;
+
+       for (i = 0, j = 1; j < buf->size-1; i++, j++) {
+               ch = buf->ptr[j];
+
+               if (ch == '\\') {
+                       if (j == buf->size-2)
+                               goto invalid;
+
+                       ch = buf->ptr[++j];
+
+                       switch (ch) {
+                       /* \" or \\ simply copy the char in */
+                       case '"': case '\\':
+                               break;
+
+                       /* add the appropriate escaped char */
+                       case 'a': ch = '\a'; break;
+                       case 'b': ch = '\b'; break;
+                       case 'f': ch = '\f'; break;
+                       case 'n': ch = '\n'; break;
+                       case 'r': ch = '\r'; break;
+                       case 't': ch = '\t'; break;
+                       case 'v': ch = '\v'; break;
+
+                       /* \xyz digits convert to the char*/
+                       case '0': case '1': case '2': case '3':
+                               if (j == buf->size-3) {
+                                       git_error_set(GIT_ERROR_INVALID,
+                                               "truncated quoted character \\%c", ch);
+                                       return -1;
+                               }
+
+                               if (buf->ptr[j+1] < '0' || buf->ptr[j+1] > '7' ||
+                                       buf->ptr[j+2] < '0' || buf->ptr[j+2] > '7') {
+                                       git_error_set(GIT_ERROR_INVALID,
+                                               "truncated quoted character \\%c%c%c",
+                                               buf->ptr[j], buf->ptr[j+1], buf->ptr[j+2]);
+                                       return -1;
+                               }
+
+                               ch = ((buf->ptr[j] - '0') << 6) |
+                                       ((buf->ptr[j+1] - '0') << 3) |
+                                       (buf->ptr[j+2] - '0');
+                               j += 2;
+                               break;
+
+                       default:
+                               git_error_set(GIT_ERROR_INVALID, "invalid quoted character \\%c", ch);
+                               return -1;
+                       }
+               }
+
+               buf->ptr[i] = ch;
+       }
+
+       buf->ptr[i] = '\0';
+       buf->size = i;
+
+       return 0;
+
+invalid:
+       git_error_set(GIT_ERROR_INVALID, "invalid quoted line");
+       return -1;
+}
+
+int git_str_puts_escaped(
+       git_str *buf,
+       const char *string,
+       const char *esc_chars,
+       const char *esc_with)
+{
+       const char *scan;
+       size_t total = 0, esc_len = strlen(esc_with), count, alloclen;
+
+       if (!string)
+               return 0;
+
+       for (scan = string; *scan; ) {
+               /* count run of non-escaped characters */
+               count = strcspn(scan, esc_chars);
+               total += count;
+               scan += count;
+               /* count run of escaped characters */
+               count = strspn(scan, esc_chars);
+               total += count * (esc_len + 1);
+               scan += count;
+       }
+
+       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, total, 1);
+       if (git_str_grow_by(buf, alloclen) < 0)
+               return -1;
+
+       for (scan = string; *scan; ) {
+               count = strcspn(scan, esc_chars);
+
+               memmove(buf->ptr + buf->size, scan, count);
+               scan += count;
+               buf->size += count;
+
+               for (count = strspn(scan, esc_chars); count > 0; --count) {
+                       /* copy escape sequence */
+                       memmove(buf->ptr + buf->size, esc_with, esc_len);
+                       buf->size += esc_len;
+                       /* copy character to be escaped */
+                       buf->ptr[buf->size] = *scan;
+                       buf->size++;
+                       scan++;
+               }
+       }
+
+       buf->ptr[buf->size] = '\0';
+
+       return 0;
+}
+
+void git_str_unescape(git_str *buf)
+{
+       buf->size = git__unescape(buf->ptr);
+}
+
+int git_str_crlf_to_lf(git_str *tgt, const git_str *src)
+{
+       const char *scan = src->ptr;
+       const char *scan_end = src->ptr + src->size;
+       const char *next = memchr(scan, '\r', src->size);
+       size_t new_size;
+       char *out;
+
+       GIT_ASSERT(tgt != src);
+
+       if (!next)
+               return git_str_set(tgt, src->ptr, src->size);
+
+       /* reduce reallocs while in the loop */
+       GIT_ERROR_CHECK_ALLOC_ADD(&new_size, src->size, 1);
+       if (git_str_grow(tgt, new_size) < 0)
+               return -1;
+
+       out = tgt->ptr;
+       tgt->size = 0;
+
+       /* Find the next \r and copy whole chunk up to there to tgt */
+       for (; next; scan = next + 1, next = memchr(scan, '\r', scan_end - scan)) {
+               if (next > scan) {
+                       size_t copylen = (size_t)(next - scan);
+                       memcpy(out, scan, copylen);
+                       out += copylen;
+               }
+
+               /* Do not drop \r unless it is followed by \n */
+               if (next + 1 == scan_end || next[1] != '\n')
+                       *out++ = '\r';
+       }
+
+       /* Copy remaining input into dest */
+       if (scan < scan_end) {
+               size_t remaining = (size_t)(scan_end - scan);
+               memcpy(out, scan, remaining);
+               out += remaining;
+       }
+
+       tgt->size = (size_t)(out - tgt->ptr);
+       tgt->ptr[tgt->size] = '\0';
+
+       return 0;
+}
+
+int git_str_lf_to_crlf(git_str *tgt, const git_str *src)
+{
+       const char *start = src->ptr;
+       const char *end = start + src->size;
+       const char *scan = start;
+       const char *next = memchr(scan, '\n', src->size);
+       size_t alloclen;
+
+       GIT_ASSERT(tgt != src);
+
+       if (!next)
+               return git_str_set(tgt, src->ptr, src->size);
+
+       /* attempt to reduce reallocs while in the loop */
+       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, src->size, src->size >> 4);
+       GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
+       if (git_str_grow(tgt, alloclen) < 0)
+               return -1;
+       tgt->size = 0;
+
+       for (; next; scan = next + 1, next = memchr(scan, '\n', end - scan)) {
+               size_t copylen = next - scan;
+
+               /* if we find mixed line endings, carry on */
+               if (copylen && next[-1] == '\r')
+                       copylen--;
+
+               GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, copylen, 3);
+               if (git_str_grow_by(tgt, alloclen) < 0)
+                       return -1;
+
+               if (copylen) {
+                       memcpy(tgt->ptr + tgt->size, scan, copylen);
+                       tgt->size += copylen;
+               }
+
+               tgt->ptr[tgt->size++] = '\r';
+               tgt->ptr[tgt->size++] = '\n';
+       }
+
+       tgt->ptr[tgt->size] = '\0';
+       return git_str_put(tgt, scan, end - scan);
+}
+
+int git_str_common_prefix(git_str *buf, char *const *const strings, size_t count)
+{
+       size_t i;
+       const char *str, *pfx;
+
+       git_str_clear(buf);
+
+       if (!strings || !count)
+               return 0;
+
+       /* initialize common prefix to first string */
+       if (git_str_sets(buf, strings[0]) < 0)
+               return -1;
+
+       /* go through the rest of the strings, truncating to shared prefix */
+       for (i = 1; i < count; ++i) {
+
+               for (str = strings[i], pfx = buf->ptr;
+                    *str && *str == *pfx;
+                    str++, pfx++)
+                       /* scanning */;
+
+               git_str_truncate(buf, pfx - buf->ptr);
+
+               if (!buf->size)
+                       break;
+       }
+
+       return 0;
+}
+
+int git_str_is_binary(const git_str *buf)
+{
+       const char *scan = buf->ptr, *end = buf->ptr + buf->size;
+       git_str_bom_t bom;
+       int printable = 0, nonprintable = 0;
+
+       scan += git_str_detect_bom(&bom, buf);
+
+       if (bom > GIT_STR_BOM_UTF8)
+               return 1;
+
+       while (scan < end) {
+               unsigned char c = *scan++;
+
+               /* Printable characters are those above SPACE (0x1F) excluding DEL,
+                * and including BS, ESC and FF.
+                */
+               if ((c > 0x1F && c != 127) || c == '\b' || c == '\033' || c == '\014')
+                       printable++;
+               else if (c == '\0')
+                       return true;
+               else if (!git__isspace(c))
+                       nonprintable++;
+       }
+
+       return ((printable >> 7) < nonprintable);
+}
+
+int git_str_contains_nul(const git_str *buf)
+{
+       return (memchr(buf->ptr, '\0', buf->size) != NULL);
+}
+
+int git_str_detect_bom(git_str_bom_t *bom, const git_str *buf)
+{
+       const char *ptr;
+       size_t len;
+
+       *bom = GIT_STR_BOM_NONE;
+       /* need at least 2 bytes to look for any BOM */
+       if (buf->size < 2)
+               return 0;
+
+       ptr = buf->ptr;
+       len = buf->size;
+
+       switch (*ptr++) {
+       case 0:
+               if (len >= 4 && ptr[0] == 0 && ptr[1] == '\xFE' && ptr[2] == '\xFF') {
+                       *bom = GIT_STR_BOM_UTF32_BE;
+                       return 4;
+               }
+               break;
+       case '\xEF':
+               if (len >= 3 && ptr[0] == '\xBB' && ptr[1] == '\xBF') {
+                       *bom = GIT_STR_BOM_UTF8;
+                       return 3;
+               }
+               break;
+       case '\xFE':
+               if (*ptr == '\xFF') {
+                       *bom = GIT_STR_BOM_UTF16_BE;
+                       return 2;
+               }
+               break;
+       case '\xFF':
+               if (*ptr != '\xFE')
+                       break;
+               if (len >= 4 && ptr[1] == 0 && ptr[2] == 0) {
+                       *bom = GIT_STR_BOM_UTF32_LE;
+                       return 4;
+               } else {
+                       *bom = GIT_STR_BOM_UTF16_LE;
+                       return 2;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+bool git_str_gather_text_stats(
+       git_str_text_stats *stats, const git_str *buf, bool skip_bom)
+{
+       const char *scan = buf->ptr, *end = buf->ptr + buf->size;
+       int skip;
+
+       memset(stats, 0, sizeof(*stats));
+
+       /* BOM detection */
+       skip = git_str_detect_bom(&stats->bom, buf);
+       if (skip_bom)
+               scan += skip;
+
+       /* Ignore EOF character */
+       if (buf->size > 0 && end[-1] == '\032')
+               end--;
+
+       /* Counting loop */
+       while (scan < end) {
+               unsigned char c = *scan++;
+
+               if (c > 0x1F && c != 0x7F)
+                       stats->printable++;
+               else switch (c) {
+                       case '\0':
+                               stats->nul++;
+                               stats->nonprintable++;
+                               break;
+                       case '\n':
+                               stats->lf++;
+                               break;
+                       case '\r':
+                               stats->cr++;
+                               if (scan < end && *scan == '\n')
+                                       stats->crlf++;
+                               break;
+                       case '\t': case '\f': case '\v': case '\b': case 0x1b: /*ESC*/
+                               stats->printable++;
+                               break;
+                       default:
+                               stats->nonprintable++;
+                               break;
+                       }
+       }
+
+       /* Treat files with a bare CR as binary */
+       return (stats->cr != stats->crlf || stats->nul > 0 ||
+               ((stats->printable >> 7) < stats->nonprintable));
+}
diff --git a/src/str.h b/src/str.h
new file mode 100644 (file)
index 0000000..ef769ce
--- /dev/null
+++ b/src/str.h
@@ -0,0 +1,357 @@
+/*
+ * 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_str_h__
+#define INCLUDE_str_h__
+
+#include "common.h"
+
+struct git_str {
+       char *ptr;
+       size_t asize;
+       size_t size;
+};
+
+typedef enum {
+       GIT_STR_BOM_NONE = 0,
+       GIT_STR_BOM_UTF8 = 1,
+       GIT_STR_BOM_UTF16_LE = 2,
+       GIT_STR_BOM_UTF16_BE = 3,
+       GIT_STR_BOM_UTF32_LE = 4,
+       GIT_STR_BOM_UTF32_BE = 5
+} git_str_bom_t;
+
+typedef struct {
+       git_str_bom_t bom; /* BOM found at head of text */
+       unsigned int nul, cr, lf, crlf; /* NUL, CR, LF and CRLF counts */
+       unsigned int printable, nonprintable; /* These are just approximations! */
+} git_str_text_stats;
+
+extern char git_str__initstr[];
+extern char git_str__oom[];
+
+/* Use to initialize string buffer structure when git_str is on stack */
+#define GIT_STR_INIT { git_str__initstr, 0, 0 }
+
+/**
+ * Static initializer for git_str from static string buffer
+ */
+#define GIT_STR_INIT_CONST(str, len) { (char *)(str), 0, (size_t)(len) }
+
+GIT_INLINE(bool) git_str_is_allocated(const git_str *str)
+{
+       return (str->ptr != NULL && str->asize > 0);
+}
+
+/**
+ * Initialize a git_str structure.
+ *
+ * For the cases where GIT_STR_INIT cannot be used to do static
+ * initialization.
+ */
+extern int git_str_init(git_str *str, size_t initial_size);
+
+extern void git_str_dispose(git_str *str);
+
+/**
+ * Resize the string buffer allocation to make more space.
+ *
+ * This will attempt to grow the string buffer to accommodate the target
+ * size.  The bstring buffer's `ptr` will be replaced with a newly
+ * allocated block of data.  Be careful so that memory allocated by the
+ * caller is not lost.  As a special variant, if you pass `target_size` as
+ * 0 and the memory is not allocated by libgit2, this will allocate a new
+ * buffer of size `size` and copy the external data into it.
+ *
+ * Currently, this will never shrink a buffer, only expand it.
+ *
+ * If the allocation fails, this will return an error and the buffer will be
+ * marked as invalid for future operations, invaliding the contents.
+ *
+ * @param str The buffer to be resized; may or may not be allocated yet
+ * @param target_size The desired available size
+ * @return 0 on success, -1 on allocation failure
+ */
+int git_str_grow(git_str *str, size_t target_size);
+
+/**
+ * Resize the buffer allocation to make more space.
+ *
+ * This will attempt to grow the string buffer to accommodate the
+ * additional size.  It is similar to `git_str_grow`, but performs the
+ * new size calculation, checking for overflow.
+ *
+ * Like `git_str_grow`, if this is a user-supplied string buffer,
+ * this will allocate a new string uffer.
+ */
+extern int git_str_grow_by(git_str *str, size_t additional_size);
+
+/**
+ * Attempt to grow the buffer to hold at least `target_size` bytes.
+ *
+ * If the allocation fails, this will return an error.  If `mark_oom` is
+ * true, this will mark the string buffer as invalid for future
+ * operations; if false, existing string buffer content will be preserved,
+ * but calling code must handle that string buffer was not expanded.  If
+ * `preserve_external` is true, then any existing data pointed to be
+ * `ptr` even if `asize` is zero will be copied into the newly allocated
+ * string buffer.
+ */
+extern int git_str_try_grow(
+       git_str *str, size_t target_size, bool mark_oom);
+
+extern void git_str_swap(git_str *str_a, git_str *str_b);
+extern char *git_str_detach(git_str *str);
+extern int git_str_attach(git_str *str, char *ptr, size_t asize);
+
+/* Populates a `git_str` where the contents are not "owned" by the string
+ * buffer, and calls to `git_str_dispose` will not free the given str.
+ */
+extern void git_str_attach_notowned(
+       git_str *str, const char *ptr, size_t size);
+
+/**
+ * Test if there have been any reallocation failures with this git_str.
+ *
+ * Any function that writes to a git_str can fail due to memory allocation
+ * issues.  If one fails, the git_str will be marked with an OOM error and
+ * further calls to modify the string buffer will fail.  Check
+ * git_str_oom() at the end of your sequence and it will be true if you
+ * ran out of memory at any point with that string buffer.
+ *
+ * @return false if no error, true if allocation error
+ */
+GIT_INLINE(bool) git_str_oom(const git_str *str)
+{
+       return (str->ptr == git_str__oom);
+}
+
+/*
+ * Functions below that return int value error codes will return 0 on
+ * success or -1 on failure (which generally means an allocation failed).
+ * Using a git_str where the allocation has failed with result in -1 from
+ * all further calls using that string buffer.  As a result, you can
+ * ignore the return code of these functions and call them in a series
+ * then just call git_str_oom at the end.
+ */
+
+int git_str_set(git_str *str, const void *data, size_t datalen);
+
+int git_str_sets(git_str *str, const char *string);
+int git_str_putc(git_str *str, char c);
+int git_str_putcn(git_str *str, char c, size_t len);
+int git_str_put(git_str *str, const char *data, size_t len);
+int git_str_puts(git_str *str, const char *string);
+int git_str_printf(git_str *str, const char *format, ...) GIT_FORMAT_PRINTF(2, 3);
+int git_str_vprintf(git_str *str, const char *format, va_list ap);
+void git_str_clear(git_str *str);
+void git_str_consume_bytes(git_str *str, size_t len);
+void git_str_consume(git_str *str, const char *end);
+void git_str_truncate(git_str *str, size_t len);
+void git_str_shorten(git_str *str, size_t amount);
+void git_str_truncate_at_char(git_str *path, char separator);
+void git_str_rtruncate_at_char(git_str *path, char separator);
+
+/** General join with separator */
+int git_str_join_n(git_str *str, char separator, int len, ...);
+/** Fast join of two strings - first may legally point into `str` data */
+int git_str_join(git_str *str, char separator, const char *str_a, const char *str_b);
+/** Fast join of three strings - cannot reference `str` data */
+int git_str_join3(git_str *str, char separator, const char *str_a, const char *str_b, const char *str_c);
+
+/**
+ * Join two strings as paths, inserting a slash between as needed.
+ * @return 0 on success, -1 on failure
+ */
+GIT_INLINE(int) git_str_joinpath(git_str *str, const char *a, const char *b)
+{
+       return git_str_join(str, '/', a, b);
+}
+
+GIT_INLINE(const char *) git_str_cstr(const git_str *str)
+{
+       return str->ptr;
+}
+
+GIT_INLINE(size_t) git_str_len(const git_str *str)
+{
+       return str->size;
+}
+
+int git_str_copy_cstr(char *data, size_t datasize, const git_str *str);
+
+#define git_str_PUTS(str, cstr) git_str_put(str, cstr, sizeof(cstr) - 1)
+
+GIT_INLINE(ssize_t) git_str_rfind_next(const git_str *str, char ch)
+{
+       ssize_t idx = (ssize_t)str->size - 1;
+       while (idx >= 0 && str->ptr[idx] == ch) idx--;
+       while (idx >= 0 && str->ptr[idx] != ch) idx--;
+       return idx;
+}
+
+GIT_INLINE(ssize_t) git_str_rfind(const git_str *str, char ch)
+{
+       ssize_t idx = (ssize_t)str->size - 1;
+       while (idx >= 0 && str->ptr[idx] != ch) idx--;
+       return idx;
+}
+
+GIT_INLINE(ssize_t) git_str_find(const git_str *str, char ch)
+{
+       void *found = memchr(str->ptr, ch, str->size);
+       return found ? (ssize_t)((const char *)found - str->ptr) : -1;
+}
+
+/* Remove whitespace from the end of the string buffer */
+void git_str_rtrim(git_str *str);
+
+int git_str_cmp(const git_str *a, const git_str *b);
+
+/* Quote and unquote a string buffer as specified in
+ * http://marc.info/?l=git&m=112927316408690&w=2
+ */
+int git_str_quote(git_str *str);
+int git_str_unquote(git_str *str);
+
+/* Write data as a hex string */
+int git_str_encode_hexstr(git_str *str, const char *data, size_t len);
+
+/* Write data as base64 encoded in string buffer */
+int git_str_encode_base64(git_str *str, const char *data, size_t len);
+/* Decode the given bas64 and write the result to the string buffer */
+int git_str_decode_base64(git_str *str, const char *base64, size_t len);
+
+/* Write data as "base85" encoded in string buffer */
+int git_str_encode_base85(git_str *str, const char *data, size_t len);
+/* Decode the given "base85" and write the result to the string buffer */
+int git_str_decode_base85(git_str *str, const char *base64, size_t len, size_t output_len);
+
+/*
+ * Decode the given percent-encoded string and write the result to the
+ * string buffer.
+ */
+int git_str_decode_percent(git_str *str, const char *encoded, size_t len);
+
+/*
+ * Insert, remove or replace a portion of the string buffer.
+ *
+ * @param str The string buffer to work with
+ *
+ * @param where The location in the string buffer where the transformation
+ * should be applied.
+ *
+ * @param nb_to_remove The number of chars to be removed. 0 to not
+ * remove any character in the string buffer.
+ *
+ * @param data A pointer to the data which should be inserted.
+ *
+ * @param nb_to_insert The number of chars to be inserted. 0 to not
+ * insert any character from the string buffer.
+ *
+ * @return 0 or an error code.
+ */
+int git_str_splice(
+       git_str *str,
+       size_t where,
+       size_t nb_to_remove,
+       const char *data,
+       size_t nb_to_insert);
+
+/**
+ * Append string to string buffer, prefixing each character from
+ * `esc_chars` with `esc_with` string.
+ *
+ * @param str String buffer to append data to
+ * @param string String to escape and append
+ * @param esc_chars Characters to be escaped
+ * @param esc_with String to insert in from of each found character
+ * @return 0 on success, <0 on failure (probably allocation problem)
+ */
+extern int git_str_puts_escaped(
+       git_str *str,
+       const char *string,
+       const char *esc_chars,
+       const char *esc_with);
+
+/**
+ * Append string escaping characters that are regex special
+ */
+GIT_INLINE(int) git_str_puts_escape_regex(git_str *str, const char *string)
+{
+       return git_str_puts_escaped(str, string, "^.[]$()|*+?{}\\", "\\");
+}
+
+/**
+ * Unescape all characters in a string buffer in place
+ *
+ * I.e. remove backslashes
+ */
+extern void git_str_unescape(git_str *str);
+
+/**
+ * Replace all \r\n with \n.
+ *
+ * @return 0 on success, -1 on memory error
+ */
+extern int git_str_crlf_to_lf(git_str *tgt, const git_str *src);
+
+/**
+ * Replace all \n with \r\n. Does not modify existing \r\n.
+ *
+ * @return 0 on success, -1 on memory error
+ */
+extern int git_str_lf_to_crlf(git_str *tgt, const git_str *src);
+
+/**
+ * Fill string buffer with the common prefix of a array of strings
+ *
+ * String buffer will be set to empty if there is no common prefix
+ */
+extern int git_str_common_prefix(git_str *buf, char *const *const strings, size_t count);
+
+/**
+ * Check if a string buffer begins with a UTF BOM
+ *
+ * @param bom Set to the type of BOM detected or GIT_BOM_NONE
+ * @param str String buffer in which to check the first bytes for a BOM
+ * @return Number of bytes of BOM data (or 0 if no BOM found)
+ */
+extern int git_str_detect_bom(git_str_bom_t *bom, const git_str *str);
+
+/**
+ * Gather stats for a piece of text
+ *
+ * Fill the `stats` structure with counts of unreadable characters, carriage
+ * returns, etc, so it can be used in heuristics.  This automatically skips
+ * a trailing EOF (\032 character).  Also it will look for a BOM at the
+ * start of the text and can be told to skip that as well.
+ *
+ * @param stats Structure to be filled in
+ * @param str Text to process
+ * @param skip_bom Exclude leading BOM from stats if true
+ * @return Does the string buffer heuristically look like binary data
+ */
+extern bool git_str_gather_text_stats(
+       git_str_text_stats *stats, const git_str *str, bool skip_bom);
+
+/**
+* Check quickly if string buffer looks like it contains binary data
+*
+* @param str string buffer to check
+* @return 1 if string buffer looks like non-text data
+*/
+int git_str_is_binary(const git_str *str);
+
+/**
+* Check quickly if buffer contains a NUL byte
+*
+* @param str string buffer to check
+* @return 1 if string buffer contains a NUL byte
+*/
+int git_str_contains_nul(const git_str *str);
+
+#endif
index b3a35ab0200a3a7bdabef4aec831e2c78f7545a9..0cf5c8af1fbe502a231ed05aa8ed8029506005bc 100644 (file)
 #endif
 
 /* Work around C90-conformance issues */
-#if defined(_MSC_VER)
-# define inline __inline
-#elif defined(__GNUC__)
-# define inline __inline__
-#else
-# define inline
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
+# if defined(_MSC_VER)
+#  define inline __inline
+# elif defined(__GNUC__)
+#  define inline __inline__
+# else
+#  define inline
+# endif
 #endif
 
 #include <mbedtls/config.h>
index 12d927a617f3149c8f13dd82bc98ff278789b07a..a9969191003ef1a2961649109c3ba4bf9b71faff 100644 (file)
@@ -13,7 +13,7 @@
  * The implementation was written so as to conform with Netscapes SSL.
  *
  * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
+ * the following conditions are adhered to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
@@ -38,7 +38,7 @@
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
+ *    The word 'cryptographic' can be left out if the routines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from
  *    the apps directory (application code) you must include an acknowledgement:
@@ -56,7 +56,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * The licence and distribution terms for any publically available version or
+ * The licence and distribution terms for any publicly available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
index 7cbb9fa3a1a2fff17d6b4eecced4fd725684c533..0f4f0726c9fe80b7800933e2b80efd9582f93eeb 100644 (file)
@@ -7,11 +7,8 @@
 
 #include "submodule.h"
 
-#include "git2/config.h"
-#include "git2/sys/config.h"
-#include "git2/types.h"
-#include "git2/index.h"
-#include "buffer.h"
+#include "buf.h"
+#include "branch.h"
 #include "vector.h"
 #include "posix.h"
 #include "config_backend.h"
 #include "repository.h"
 #include "tree.h"
 #include "iterator.h"
-#include "path.h"
+#include "fs_path.h"
+#include "str.h"
 #include "index.h"
 #include "worktree.h"
 #include "clone.h"
+#include "path.h"
+
+#include "git2/config.h"
+#include "git2/sys/config.h"
+#include "git2/types.h"
+#include "git2/index.h"
 
 #define GIT_MODULES_FILE ".gitmodules"
 
@@ -57,14 +61,14 @@ enum {
 };
 enum {
        GITMODULES_EXISTING = 0,
-       GITMODULES_CREATE = 1,
+       GITMODULES_CREATE = 1
 };
 
 static int submodule_alloc(git_submodule **out, git_repository *repo, const char *name);
 static git_config_backend *open_gitmodules(git_repository *repo, int gitmod);
 static int gitmodules_snapshot(git_config **snap, git_repository *repo);
-static int get_url_base(git_buf *url, git_repository *repo);
-static int lookup_head_remote_key(git_buf *remote_key, git_repository *repo);
+static int get_url_base(git_str *url, git_repository *repo);
+static int lookup_head_remote_key(git_str *remote_key, git_repository *repo);
 static int lookup_default_remote(git_remote **remote, git_repository *repo);
 static int submodule_load_each(const git_config_entry *entry, void *payload);
 static int submodule_read_config(git_submodule *sm, git_config *cfg);
@@ -79,11 +83,11 @@ static int submodule_cmp(const void *a, const void *b)
        return strcmp(((git_submodule *)a)->name, ((git_submodule *)b)->name);
 }
 
-static int submodule_config_key_trunc_puts(git_buf *key, const char *suffix)
+static int submodule_config_key_trunc_puts(git_str *key, const char *suffix)
 {
-       ssize_t idx = git_buf_rfind(key, '.');
-       git_buf_truncate(key, (size_t)(idx + 1));
-       return git_buf_puts(key, suffix);
+       ssize_t idx = git_str_rfind(key, '.');
+       git_str_truncate(key, (size_t)(idx + 1));
+       return git_str_puts(key, suffix);
 }
 
 /*
@@ -128,7 +132,7 @@ static int is_path_occupied(bool *occupied, git_repository *repo, const char *pa
 {
        int error = 0;
        git_index *index;
-       git_buf dir = GIT_BUF_INIT;
+       git_str dir = GIT_STR_INIT;
        *occupied = false;
 
        if ((error = git_repository_index__weakptr(&index, repo)) < 0)
@@ -143,10 +147,10 @@ static int is_path_occupied(bool *occupied, git_repository *repo, const char *pa
                goto out;
        }
 
-       if ((error = git_buf_sets(&dir, path)) < 0)
+       if ((error = git_str_sets(&dir, path)) < 0)
                goto out;
 
-       if ((error = git_path_to_dir(&dir)) < 0)
+       if ((error = git_fs_path_to_dir(&dir)) < 0)
                goto out;
 
        if ((error = git_index_find_prefix(NULL, index, dir.ptr)) != GIT_ENOTFOUND) {
@@ -161,7 +165,7 @@ static int is_path_occupied(bool *occupied, git_repository *repo, const char *pa
        error = 0;
 
 out:
-       git_buf_dispose(&dir);
+       git_str_dispose(&dir);
        return error;
 }
 
@@ -195,7 +199,7 @@ static int load_submodule_names(git_strmap **out, git_repository *repo, git_conf
        const char *key = "submodule\\..*\\.path";
        git_config_iterator *iter = NULL;
        git_config_entry *entry;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_strmap *names;
        int isvalid, error;
 
@@ -219,8 +223,8 @@ static int load_submodule_names(git_strmap **out, git_repository *repo, git_conf
                        goto out;
                }
 
-               git_buf_clear(&buf);
-               git_buf_put(&buf, fdot + 1, ldot - fdot - 1);
+               git_str_clear(&buf);
+               git_str_put(&buf, fdot + 1, ldot - fdot - 1);
                isvalid = git_submodule_name_is_valid(repo, buf.ptr, 0);
                if (isvalid < 0) {
                        error = isvalid;
@@ -229,7 +233,7 @@ static int load_submodule_names(git_strmap **out, git_repository *repo, git_conf
                if (!isvalid)
                        continue;
 
-               if ((error = git_strmap_set(names, git__strdup(entry->value), git_buf_detach(&buf))) < 0) {
+               if ((error = git_strmap_set(names, git__strdup(entry->value), git_str_detach(&buf))) < 0) {
                        git_error_set(GIT_ERROR_NOMEMORY, "error inserting submodule into hash table");
                        error = -1;
                        goto out;
@@ -243,7 +247,7 @@ static int load_submodule_names(git_strmap **out, git_repository *repo, git_conf
 
 out:
        free_submodule_names(names);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        git_config_iterator_free(iter);
        return error;
 }
@@ -329,10 +333,10 @@ int git_submodule__lookup_with_cache(
        if (location == 0 || location == GIT_SUBMODULE_STATUS_IN_WD) {
                git_config_backend *mods;
                const char *pattern = "submodule\\..*\\.path";
-               git_buf path = GIT_BUF_INIT;
+               git_str path = GIT_STR_INIT;
                fbp_data data = { NULL, NULL };
 
-               git_buf_puts(&path, name);
+               git_str_puts(&path, name);
                while (path.ptr[path.size-1] == '/') {
                        path.ptr[--path.size] = '\0';
                }
@@ -347,14 +351,14 @@ int git_submodule__lookup_with_cache(
 
                if (error < 0) {
                        git_submodule_free(sm);
-                       git_buf_dispose(&path);
+                       git_str_dispose(&path);
                        return error;
                }
 
                if (data.name) {
                        git__free(sm->name);
                        sm->name = data.name;
-                       sm->path = git_buf_detach(&path);
+                       sm->path = git_str_detach(&path);
 
                        /* Try to load again with the right name */
                        if ((error = git_submodule_reload(sm, false)) < 0) {
@@ -363,7 +367,7 @@ int git_submodule__lookup_with_cache(
                        }
                }
 
-               git_buf_dispose(&path);
+               git_str_dispose(&path);
        }
 
        if ((error = git_submodule_location(&location, sm)) < 0) {
@@ -378,17 +382,17 @@ int git_submodule__lookup_with_cache(
 
                /* If it's not configured, we still check if there's a repo at the path */
                if (git_repository_workdir(repo)) {
-                       git_buf path = GIT_BUF_INIT;
-                       if (git_buf_join3(&path, '/',
+                       git_str path = GIT_STR_INIT;
+                       if (git_str_join3(&path, '/',
                                          git_repository_workdir(repo),
                                          name, DOT_GIT) < 0 ||
-                           git_path_validate_workdir_buf(NULL, &path) < 0)
+                           git_path_validate_str_length(NULL, &path) < 0)
                                return -1;
 
-                       if (git_path_exists(path.ptr))
+                       if (git_fs_path_exists(path.ptr))
                                error = GIT_EEXISTS;
 
-                       git_buf_dispose(&path);
+                       git_str_dispose(&path);
                }
 
                submodule_set_lookup_error(error, name);
@@ -405,22 +409,22 @@ int git_submodule__lookup_with_cache(
 
 int git_submodule_name_is_valid(git_repository *repo, const char *name, int flags)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        int error, isvalid;
 
        if (flags == 0)
-               flags = GIT_PATH_REJECT_FILESYSTEM_DEFAULTS;
+               flags = GIT_FS_PATH_REJECT_FILESYSTEM_DEFAULTS;
 
        /* Avoid allocating a new string if we can avoid it */
        if (strchr(name, '\\') != NULL) {
-               if ((error = git_path_normalize_slashes(&buf, name)) < 0)
+               if ((error = git_fs_path_normalize_slashes(&buf, name)) < 0)
                        return error;
        } else {
-               git_buf_attach_notowned(&buf, name, strlen(name));
+               git_str_attach_notowned(&buf, name, strlen(name));
        }
 
-       isvalid =  git_path_validate(repo, buf.ptr, 0, flags);
-       git_buf_dispose(&buf);
+       isvalid = git_path_is_valid(repo, buf.ptr, 0, flags);
+       git_str_dispose(&buf);
 
        return isvalid;
 }
@@ -554,7 +558,7 @@ int git_submodule__map(git_repository *repo, git_strmap *map)
        int error = 0;
        git_index *idx = NULL;
        git_tree *head = NULL;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_submodule *sm;
        git_config *mods = NULL;
        bool has_workdir;
@@ -613,7 +617,7 @@ cleanup:
        /* TODO: if we got an error, mark submodule config as invalid? */
        git_index_free(idx);
        git_tree_free(head);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        return error;
 }
 
@@ -682,7 +686,7 @@ static int submodule_repo_init(
        bool use_gitlink)
 {
        int error = 0;
-       git_buf workdir = GIT_BUF_INIT, repodir = GIT_BUF_INIT;
+       git_str workdir = GIT_STR_INIT, repodir = GIT_STR_INIT;
        git_repository_init_options initopt = GIT_REPOSITORY_INIT_OPTIONS_INIT;
        git_repository *subrepo = NULL;
 
@@ -701,10 +705,10 @@ static int submodule_repo_init(
         * Old style: sub-repo goes directly into repo/<name>/.git/
         */
         if (use_gitlink) {
-               error = git_repository_item_path(&repodir, parent_repo, GIT_REPOSITORY_ITEM_MODULES);
+               error = git_repository__item_path(&repodir, parent_repo, GIT_REPOSITORY_ITEM_MODULES);
                if (error < 0)
                        goto cleanup;
-               error = git_buf_joinpath(&repodir, repodir.ptr, path);
+               error = git_str_joinpath(&repodir, repodir.ptr, path);
                if (error < 0)
                        goto cleanup;
 
@@ -718,14 +722,57 @@ static int submodule_repo_init(
                error = git_repository_init_ext(&subrepo, workdir.ptr, &initopt);
 
 cleanup:
-       git_buf_dispose(&workdir);
-       git_buf_dispose(&repodir);
+       git_str_dispose(&workdir);
+       git_str_dispose(&repodir);
 
        *out = subrepo;
 
        return error;
 }
 
+static int git_submodule__resolve_url(
+       git_str *out,
+       git_repository *repo,
+       const char *url)
+{
+       int error = 0;
+       git_str normalized = GIT_STR_INIT;
+
+       GIT_ASSERT_ARG(out);
+       GIT_ASSERT_ARG(repo);
+       GIT_ASSERT_ARG(url);
+
+       /* We do this in all platforms in case someone on Windows created the .gitmodules */
+       if (strchr(url, '\\')) {
+               if ((error = git_fs_path_normalize_slashes(&normalized, url)) < 0)
+                       return error;
+
+               url = normalized.ptr;
+       }
+
+
+       if (git_fs_path_is_relative(url)) {
+               if (!(error = get_url_base(out, repo)))
+                       error = git_fs_path_apply_relative(out, url);
+       } else if (strchr(url, ':') != NULL || url[0] == '/') {
+               error = git_str_sets(out, url);
+       } else {
+               git_error_set(GIT_ERROR_SUBMODULE, "invalid format for submodule URL");
+               error = -1;
+       }
+
+       git_str_dispose(&normalized);
+       return error;
+}
+
+int git_submodule_resolve_url(
+       git_buf *out,
+       git_repository *repo,
+       const char *url)
+{
+       GIT_BUF_WRAP_PRIVATE(out, git_submodule__resolve_url, repo, url);
+}
+
 int git_submodule_add_setup(
        git_submodule **out,
        git_repository *repo,
@@ -736,7 +783,7 @@ int git_submodule_add_setup(
        int error = 0;
        git_config_backend *mods = NULL;
        git_submodule *sm = NULL;
-       git_buf name = GIT_BUF_INIT, real_url = GIT_BUF_INIT;
+       git_str name = GIT_STR_INIT, real_url = GIT_STR_INIT;
        git_repository *subrepo = NULL;
        bool path_occupied;
 
@@ -759,7 +806,7 @@ int git_submodule_add_setup(
        if (git__prefixcmp(path, git_repository_workdir(repo)) == 0)
                path += strlen(git_repository_workdir(repo));
 
-       if (git_path_root(path) >= 0) {
+       if (git_fs_path_root(path) >= 0) {
                git_error_set(GIT_ERROR_SUBMODULE, "submodule path must be a relative path");
                error = -1;
                goto cleanup;
@@ -781,7 +828,7 @@ int git_submodule_add_setup(
                return -1;
        }
 
-       if ((error = git_buf_printf(&name, "submodule.%s.path", path)) < 0 ||
+       if ((error = git_str_printf(&name, "submodule.%s.path", path)) < 0 ||
                (error = git_config_backend_set_string(mods, name.ptr, path)) < 0)
                goto cleanup;
 
@@ -789,7 +836,7 @@ int git_submodule_add_setup(
                (error = git_config_backend_set_string(mods, name.ptr, url)) < 0)
                goto cleanup;
 
-       git_buf_clear(&name);
+       git_str_clear(&name);
 
        /* init submodule repository and add origin remote as needed */
 
@@ -800,11 +847,11 @@ int git_submodule_add_setup(
        /* if the repo does not already exist, then init a new repo and add it.
         * Otherwise, just add the existing repo.
         */
-       if (!(git_path_exists(name.ptr) &&
-               git_path_contains(&name, DOT_GIT))) {
+       if (!(git_fs_path_exists(name.ptr) &&
+               git_fs_path_contains(&name, DOT_GIT))) {
 
                /* resolve the actual URL to use */
-               if ((error = git_submodule_resolve_url(&real_url, repo, url)) < 0)
+               if ((error = git_submodule__resolve_url(&real_url, repo, url)) < 0)
                        goto cleanup;
 
                 if ((error = submodule_repo_init(&subrepo, repo, path, real_url.ptr, use_gitlink)) < 0)
@@ -826,8 +873,8 @@ cleanup:
 
        git_config_backend_free(mods);
        git_repository_free(subrepo);
-       git_buf_dispose(&real_url);
-       git_buf_dispose(&name);
+       git_str_dispose(&real_url);
+       git_str_dispose(&name);
 
        return error;
 }
@@ -841,13 +888,13 @@ int git_submodule_repo_init(
        git_repository *sub_repo = NULL;
        const char *configured_url;
        git_config *cfg = NULL;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        GIT_ASSERT_ARG(out);
        GIT_ASSERT_ARG(sm);
 
        /* get the configured remote url of the submodule */
-       if ((error = git_buf_printf(&buf, "submodule.%s.url", sm->name)) < 0 ||
+       if ((error = git_str_printf(&buf, "submodule.%s.url", sm->name)) < 0 ||
                (error = git_repository_config_snapshot(&cfg, sm->repo)) < 0 ||
                (error = git_config_get_string(&configured_url, cfg, buf.ptr)) < 0 ||
                (error = submodule_repo_init(&sub_repo, sm->repo, sm->path, configured_url, use_gitlink)) < 0)
@@ -857,7 +904,7 @@ int git_submodule_repo_init(
 
 done:
        git_config_free(cfg);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
@@ -881,7 +928,7 @@ int git_submodule_clone(git_repository **out, git_submodule *submodule, const gi
 {
        int error;
        git_repository *clone;
-       git_buf rel_path = GIT_BUF_INIT;
+       git_str rel_path = GIT_STR_INIT;
        git_submodule_update_options sub_opts = GIT_SUBMODULE_UPDATE_OPTIONS_INIT;
        git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
 
@@ -903,7 +950,7 @@ int git_submodule_clone(git_repository **out, git_submodule *submodule, const gi
        if (error < 0)
                goto cleanup;
 
-       error = git_clone__submodule(&clone, git_submodule_url(submodule), git_buf_cstr(&rel_path), &opts);
+       error = git_clone__submodule(&clone, git_submodule_url(submodule), git_str_cstr(&rel_path), &opts);
        if (error < 0)
                goto cleanup;
 
@@ -913,7 +960,7 @@ int git_submodule_clone(git_repository **out, git_submodule *submodule, const gi
                *out = clone;
 
 cleanup:
-       git_buf_dispose(&rel_path);
+       git_str_dispose(&rel_path);
 
        return error;
 }
@@ -937,7 +984,7 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index)
        int error;
        git_repository *sm_repo = NULL;
        git_index *index;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_commit *head;
        git_index_entry entry;
        struct stat st;
@@ -997,7 +1044,7 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index)
 
 cleanup:
        git_repository_free(sm_repo);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        return error;
 }
 
@@ -1034,44 +1081,9 @@ const char *git_submodule_url(git_submodule *submodule)
        return submodule->url;
 }
 
-int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *url)
-{
-       int error = 0;
-       git_buf normalized = GIT_BUF_INIT;
-
-       GIT_ASSERT_ARG(out);
-       GIT_ASSERT_ARG(repo);
-       GIT_ASSERT_ARG(url);
-
-       if ((error = git_buf_sanitize(out)) < 0)
-               return error;
-
-       /* We do this in all platforms in case someone on Windows created the .gitmodules */
-       if (strchr(url, '\\')) {
-               if ((error = git_path_normalize_slashes(&normalized, url)) < 0)
-                       return error;
-
-               url = normalized.ptr;
-       }
-
-
-       if (git_path_is_relative(url)) {
-               if (!(error = get_url_base(out, repo)))
-                       error = git_path_apply_relative(out, url);
-       } else if (strchr(url, ':') != NULL || url[0] == '/') {
-               error = git_buf_sets(out, url);
-       } else {
-               git_error_set(GIT_ERROR_SUBMODULE, "invalid format for submodule URL");
-               error = -1;
-       }
-
-       git_buf_dispose(&normalized);
-       return error;
-}
-
 static int write_var(git_repository *repo, const char *name, const char *var, const char *val)
 {
-       git_buf key = GIT_BUF_INIT;
+       git_str key = GIT_STR_INIT;
        git_config_backend *mods;
        int error;
 
@@ -1079,7 +1091,7 @@ static int write_var(git_repository *repo, const char *name, const char *var, co
        if (!mods)
                return -1;
 
-       if ((error = git_buf_printf(&key, "submodule.%s.%s", name, var)) < 0)
+       if ((error = git_str_printf(&key, "submodule.%s.%s", name, var)) < 0)
                goto cleanup;
 
        if (val)
@@ -1087,7 +1099,7 @@ static int write_var(git_repository *repo, const char *name, const char *var, co
        else
                error = git_config_backend_delete(mods, key.ptr);
 
-       git_buf_dispose(&key);
+       git_str_dispose(&key);
 
 cleanup:
        git_config_backend_free(mods);
@@ -1227,7 +1239,7 @@ static int submodule_repo_create(
        const char *path)
 {
        int error = 0;
-       git_buf workdir = GIT_BUF_INIT, repodir = GIT_BUF_INIT;
+       git_str workdir = GIT_STR_INIT, repodir = GIT_STR_INIT;
        git_repository_init_options initopt = GIT_REPOSITORY_INIT_OPTIONS_INIT;
        git_repository *subrepo = NULL;
 
@@ -1249,18 +1261,18 @@ static int submodule_repo_create(
         * <repo-dir>/modules/<name>/ with a gitlink in the
         * sub-repo workdir directory to that repository.
         */
-       error = git_repository_item_path(&repodir, parent_repo, GIT_REPOSITORY_ITEM_MODULES);
+       error = git_repository__item_path(&repodir, parent_repo, GIT_REPOSITORY_ITEM_MODULES);
        if (error < 0)
                goto cleanup;
-       error = git_buf_joinpath(&repodir, repodir.ptr, path);
+       error = git_str_joinpath(&repodir, repodir.ptr, path);
        if (error < 0)
                goto cleanup;
 
        error = git_repository_init_ext(&subrepo, repodir.ptr, &initopt);
 
 cleanup:
-       git_buf_dispose(&workdir);
-       git_buf_dispose(&repodir);
+       git_str_dispose(&workdir);
+       git_str_dispose(&repodir);
 
        *out = subrepo;
 
@@ -1309,7 +1321,7 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio
        git_repository *sub_repo = NULL;
        git_remote *remote = NULL;
        git_object *target_commit = NULL;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_submodule_update_options update_options = GIT_SUBMODULE_UPDATE_OPTIONS_INIT;
        git_clone_options clone_options = GIT_CLONE_OPTIONS_INIT;
 
@@ -1337,10 +1349,10 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio
                 * info has been copied into .git/config
                 */
                if ((error = git_repository_config_snapshot(&config, sm->repo)) < 0 ||
-                       (error = git_buf_printf(&buf, "submodule.%s.url", git_submodule_name(sm))) < 0)
+                       (error = git_str_printf(&buf, "submodule.%s.url", git_submodule_name(sm))) < 0)
                        goto done;
 
-               if ((error = git_config_get_string(&submodule_url, config, git_buf_cstr(&buf))) < 0) {
+               if ((error = git_config_get_string(&submodule_url, config, git_str_cstr(&buf))) < 0) {
                        /*
                         * If the error is not "not found" or if it is "not found" and we are not
                         * initializing the submodule, then return error.
@@ -1362,7 +1374,7 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio
                        config = NULL;
 
                        if ((error = git_repository_config_snapshot(&config, sm->repo)) < 0 ||
-                               (error = git_config_get_string(&submodule_url, config, git_buf_cstr(&buf))) < 0)
+                               (error = git_config_get_string(&submodule_url, config, git_str_cstr(&buf))) < 0)
                                goto done;
                }
 
@@ -1420,7 +1432,7 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio
        }
 
 done:
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        git_config_free(config);
        git_object_free(target_commit);
        git_remote_free(remote);
@@ -1433,7 +1445,7 @@ int git_submodule_init(git_submodule *sm, int overwrite)
 {
        int error;
        const char *val;
-       git_buf key = GIT_BUF_INIT, effective_submodule_url = GIT_BUF_INIT;
+       git_str key = GIT_STR_INIT, effective_submodule_url = GIT_STR_INIT;
        git_config *cfg = NULL;
 
        if (!sm->url) {
@@ -1447,8 +1459,8 @@ int git_submodule_init(git_submodule *sm, int overwrite)
 
        /* write "submodule.NAME.url" */
 
-       if ((error = git_submodule_resolve_url(&effective_submodule_url, sm->repo, sm->url)) < 0 ||
-               (error = git_buf_printf(&key, "submodule.%s.url", sm->name)) < 0 ||
+       if ((error = git_submodule__resolve_url(&effective_submodule_url, sm->repo, sm->url)) < 0 ||
+               (error = git_str_printf(&key, "submodule.%s.url", sm->name)) < 0 ||
                (error = git_config__update_entry(
                        cfg, key.ptr, effective_submodule_url.ptr, overwrite != 0, false)) < 0)
                goto cleanup;
@@ -1458,7 +1470,7 @@ int git_submodule_init(git_submodule *sm, int overwrite)
        val = (sm->update == GIT_SUBMODULE_UPDATE_CHECKOUT) ?
                NULL : submodule_update_to_str(sm->update);
 
-       if ((error = git_buf_printf(&key, "submodule.%s.update", sm->name)) < 0 ||
+       if ((error = git_str_printf(&key, "submodule.%s.update", sm->name)) < 0 ||
                (error = git_config__update_entry(
                        cfg, key.ptr, val, overwrite != 0, false)) < 0)
                goto cleanup;
@@ -1467,15 +1479,15 @@ int git_submodule_init(git_submodule *sm, int overwrite)
 
 cleanup:
        git_config_free(cfg);
-       git_buf_dispose(&key);
-       git_buf_dispose(&effective_submodule_url);
+       git_str_dispose(&key);
+       git_str_dispose(&effective_submodule_url);
 
        return error;
 }
 
 int git_submodule_sync(git_submodule *sm)
 {
-       git_buf key = GIT_BUF_INIT, url = GIT_BUF_INIT, remote_name = GIT_BUF_INIT;
+       git_str key = GIT_STR_INIT, url = GIT_STR_INIT, remote_name = GIT_STR_INIT;
        git_repository *smrepo = NULL;
        git_config *cfg = NULL;
        int error = 0;
@@ -1487,8 +1499,8 @@ int git_submodule_sync(git_submodule *sm)
 
        /* copy URL over to config only if it already exists */
        if ((error = git_repository_config__weakptr(&cfg, sm->repo)) < 0 ||
-           (error = git_buf_printf(&key, "submodule.%s.url", sm->name)) < 0 ||
-           (error = git_submodule_resolve_url(&url, sm->repo, sm->url)) < 0 ||
+           (error = git_str_printf(&key, "submodule.%s.url", sm->name)) < 0 ||
+           (error = git_submodule__resolve_url(&url, sm->repo, sm->url)) < 0 ||
            (error = git_config__update_entry(cfg, key.ptr, url.ptr, true, true)) < 0)
                goto out;
 
@@ -1501,9 +1513,9 @@ int git_submodule_sync(git_submodule *sm)
                goto out;
 
        if (lookup_head_remote_key(&remote_name, smrepo) == 0) {
-               if ((error = git_buf_join3(&key, '.', "remote", remote_name.ptr, "url")) < 0)
+               if ((error = git_str_join3(&key, '.', "remote", remote_name.ptr, "url")) < 0)
                        goto out;
-       } else if ((error = git_buf_sets(&key, "remote.origin.url")) < 0) {
+       } else if ((error = git_str_sets(&key, "remote.origin.url")) < 0) {
                goto out;
        }
 
@@ -1512,9 +1524,9 @@ int git_submodule_sync(git_submodule *sm)
 
 out:
        git_repository_free(smrepo);
-       git_buf_dispose(&remote_name);
-       git_buf_dispose(&key);
-       git_buf_dispose(&url);
+       git_str_dispose(&remote_name);
+       git_str_dispose(&key);
+       git_str_dispose(&url);
        return error;
 }
 
@@ -1522,7 +1534,7 @@ static int git_submodule__open(
        git_repository **subrepo, git_submodule *sm, bool bare)
 {
        int error;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        unsigned int flags = GIT_REPOSITORY_OPEN_NO_SEARCH;
        const char *wd;
 
@@ -1535,7 +1547,7 @@ static int git_submodule__open(
 
        wd = git_repository_workdir(sm->repo);
 
-       if (git_buf_join3(&path, '/', wd, sm->path, DOT_GIT) < 0)
+       if (git_str_join3(&path, '/', wd, sm->path, DOT_GIT) < 0)
                return -1;
 
        sm->flags = sm->flags &
@@ -1557,17 +1569,17 @@ static int git_submodule__open(
                        sm->flags |= GIT_SUBMODULE_STATUS__WD_OID_VALID;
                else
                        git_error_clear();
-       } else if (git_path_exists(path.ptr)) {
+       } else if (git_fs_path_exists(path.ptr)) {
                sm->flags |= GIT_SUBMODULE_STATUS__WD_SCANNED |
                        GIT_SUBMODULE_STATUS_IN_WD;
        } else {
-               git_buf_rtruncate_at_char(&path, '/'); /* remove "/.git" */
+               git_str_rtruncate_at_char(&path, '/'); /* remove "/.git" */
 
-               if (git_path_isdir(path.ptr))
+               if (git_fs_path_isdir(path.ptr))
                        sm->flags |= GIT_SUBMODULE_STATUS__WD_SCANNED;
        }
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return error;
 }
@@ -1921,13 +1933,13 @@ static int submodule_parse_recurse(git_submodule_recurse_t *out, const char *val
        return 0;
 }
 
-static int get_value(const char **out, git_config *cfg, git_buf *buf, const char *name, const char *field)
+static int get_value(const char **out, git_config *cfg, git_str *buf, const char *name, const char *field)
 {
        int error;
 
-       git_buf_clear(buf);
+       git_str_clear(buf);
 
-       if ((error = git_buf_printf(buf, "submodule.%s.%s", name, field)) < 0 ||
+       if ((error = git_str_printf(buf, "submodule.%s.%s", name, field)) < 0 ||
            (error = git_config_get_string(out, cfg, buf->ptr)) < 0)
                return error;
 
@@ -1944,7 +1956,7 @@ static bool looks_like_command_line_option(const char *s)
 
 static int submodule_read_config(git_submodule *sm, git_config *cfg)
 {
-       git_buf key = GIT_BUF_INIT;
+       git_str key = GIT_STR_INIT;
        const char *value;
        int error, in_config = 0;
 
@@ -2025,7 +2037,7 @@ static int submodule_read_config(git_submodule *sm, git_config *cfg)
        error = 0;
 
 cleanup:
-       git_buf_dispose(&key);
+       git_str_dispose(&key);
        return error;
 }
 
@@ -2034,7 +2046,7 @@ static int submodule_load_each(const git_config_entry *entry, void *payload)
        lfc_data *data = payload;
        const char *namestart, *property;
        git_strmap *map = data->map;
-       git_buf name = GIT_BUF_INIT;
+       git_str name = GIT_STR_INIT;
        git_submodule *sm;
        int error, isvalid;
 
@@ -2049,7 +2061,7 @@ static int submodule_load_each(const git_config_entry *entry, void *payload)
 
        property++;
 
-       if ((error = git_buf_set(&name, namestart, property - namestart -1)) < 0)
+       if ((error = git_str_set(&name, namestart, property - namestart -1)) < 0)
                return error;
 
        isvalid = git_submodule_name_is_valid(data->repo, name.ptr, 0);
@@ -2083,24 +2095,24 @@ static int submodule_load_each(const git_config_entry *entry, void *payload)
        error = 0;
 
 done:
-       git_buf_dispose(&name);
+       git_str_dispose(&name);
        return error;
 }
 
 static int submodule_load_from_wd_lite(git_submodule *sm)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        if (git_repository_workdir_path(&path, sm->repo, sm->path) < 0)
                return -1;
 
-       if (git_path_isdir(path.ptr))
+       if (git_fs_path_isdir(path.ptr))
                sm->flags |= GIT_SUBMODULE_STATUS__WD_SCANNED;
 
-       if (git_path_contains(&path, DOT_GIT))
+       if (git_fs_path_contains(&path, DOT_GIT))
                sm->flags |= GIT_SUBMODULE_STATUS_IN_WD;
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        return 0;
 }
 
@@ -2112,7 +2124,7 @@ static int submodule_load_from_wd_lite(git_submodule *sm)
 static int gitmodules_snapshot(git_config **snap, git_repository *repo)
 {
        git_config *mods = NULL;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        int error;
 
        if (git_repository_workdir(repo) == NULL)
@@ -2123,7 +2135,7 @@ static int gitmodules_snapshot(git_config **snap, git_repository *repo)
 
        if ((error = git_config_open_ondisk(&mods, path.ptr)) < 0)
                goto cleanup;
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        if ((error = git_config_snapshot(snap, mods)) < 0)
                goto cleanup;
@@ -2133,7 +2145,7 @@ static int gitmodules_snapshot(git_config **snap, git_repository *repo)
 cleanup:
        if (mods)
                git_config_free(mods);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return error;
 }
@@ -2142,14 +2154,14 @@ static git_config_backend *open_gitmodules(
        git_repository *repo,
        int okay_to_create)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_config_backend *mods = NULL;
 
        if (git_repository_workdir(repo) != NULL) {
                if (git_repository_workdir_path(&path, repo, GIT_MODULES_FILE) != 0)
                        return NULL;
 
-               if (okay_to_create || git_path_isfile(path.ptr)) {
+               if (okay_to_create || git_fs_path_isfile(path.ptr)) {
                        /* git_config_backend_from_file should only fail if OOM */
                        if (git_config_backend_from_file(&mods, path.ptr) < 0)
                                mods = NULL;
@@ -2161,17 +2173,17 @@ static git_config_backend *open_gitmodules(
                }
        }
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return mods;
 }
 
 /* Lookup name of remote of the local tracking branch HEAD points to */
-static int lookup_head_remote_key(git_buf *remote_name, git_repository *repo)
+static int lookup_head_remote_key(git_str *remote_name, git_repository *repo)
 {
        int error;
        git_reference *head = NULL;
-       git_buf upstream_name = GIT_BUF_INIT;
+       git_str upstream_name = GIT_STR_INIT;
 
        /* lookup and dereference HEAD */
        if ((error = git_repository_head(&head, repo)) < 0)
@@ -2190,18 +2202,18 @@ static int lookup_head_remote_key(git_buf *remote_name, git_repository *repo)
        }
 
        /* lookup remote tracking branch of HEAD */
-       if ((error = git_branch_upstream_name(
+       if ((error = git_branch__upstream_name(
                &upstream_name,
                repo,
                git_reference_name(head))) < 0)
                goto done;
 
        /* lookup remote of remote tracking branch */
-       if ((error = git_branch_remote_name(remote_name, repo, upstream_name.ptr)) < 0)
+       if ((error = git_branch__remote_name(remote_name, repo, upstream_name.ptr)) < 0)
                goto done;
 
 done:
-       git_buf_dispose(&upstream_name);
+       git_str_dispose(&upstream_name);
        git_reference_free(head);
 
        return error;
@@ -2211,13 +2223,13 @@ done:
 static int lookup_head_remote(git_remote **remote, git_repository *repo)
 {
        int error;
-       git_buf remote_name = GIT_BUF_INIT;
+       git_str remote_name = GIT_STR_INIT;
 
        /* lookup remote of remote tracking branch name */
        if (!(error = lookup_head_remote_key(&remote_name, repo)))
                error = git_remote_lookup(remote, repo, remote_name.ptr);
 
-       git_buf_dispose(&remote_name);
+       git_str_dispose(&remote_name);
 
        return error;
 }
@@ -2240,14 +2252,14 @@ static int lookup_default_remote(git_remote **remote, git_repository *repo)
        return error;
 }
 
-static int get_url_base(git_buf *url, git_repository *repo)
+static int get_url_base(git_str *url, git_repository *repo)
 {
        int error;
        git_worktree *wt = NULL;
        git_remote *remote = NULL;
 
        if ((error = lookup_default_remote(&remote, repo)) == 0) {
-               error = git_buf_sets(url, git_remote_url(remote));
+               error = git_str_sets(url, git_remote_url(remote));
                goto out;
        } else if (error != GIT_ENOTFOUND)
                goto out;
@@ -2258,9 +2270,9 @@ static int get_url_base(git_buf *url, git_repository *repo)
        if (git_repository_is_worktree(repo)) {
                if ((error = git_worktree_open_from_repository(&wt, repo)) < 0)
                        goto out;
-               error = git_buf_sets(url, wt->parent_path);
+               error = git_str_sets(url, wt->parent_path);
        } else {
-               error = git_buf_sets(url, git_repository_workdir(repo));
+               error = git_str_sets(url, git_repository_workdir(repo));
        }
 
 out:
index b01ff68a203595d3430542d2d545b3b1ef4c401f..7fa98248620e7caf27bacbb34ac7c6566a3dc8c5 100644 (file)
@@ -110,7 +110,7 @@ enum {
        GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE  = (1u << 24),
        GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE = (1u << 25),
        GIT_SUBMODULE_STATUS__WD_NOT_SUBMODULE    = (1u << 26),
-       GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES = (1u << 27),
+       GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES = (1u << 27)
 };
 
 #define GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(S) \
index dcbd48bc3949d02dcb205436453f8dc0471afa6e..450cb509b814d060c95a9af5aa967d4e5402f680 100644 (file)
@@ -8,8 +8,8 @@
 #include "sysdir.h"
 
 #include "runtime.h"
-#include "buffer.h"
-#include "path.h"
+#include "str.h"
+#include "fs_path.h"
 #include <ctype.h>
 #if GIT_WIN32
 #include "win32/findfile.h"
 #include <pwd.h>
 #endif
 
-static int git_sysdir_guess_programdata_dirs(git_buf *out)
+static int git_sysdir_guess_programdata_dirs(git_str *out)
 {
 #ifdef GIT_WIN32
        return git_win32__find_programdata_dirs(out);
 #else
-       git_buf_clear(out);
+       git_str_clear(out);
        return 0;
 #endif
 }
 
-static int git_sysdir_guess_system_dirs(git_buf *out)
+static int git_sysdir_guess_system_dirs(git_str *out)
 {
 #ifdef GIT_WIN32
-       return git_win32__find_system_dirs(out, L"etc\\");
+       return git_win32__find_system_dirs(out, "etc");
 #else
-       return git_buf_sets(out, "/etc");
+       return git_str_sets(out, "/etc");
 #endif
 }
 
 #ifndef GIT_WIN32
-static int get_passwd_home(git_buf *out, uid_t uid)
+static int get_passwd_home(git_str *out, uid_t uid)
 {
        struct passwd pwd, *pwdptr;
        char *buf = NULL;
@@ -66,7 +66,7 @@ static int get_passwd_home(git_buf *out, uid_t uid)
                goto out;
        }
 
-       if ((error = git_buf_puts(out, pwdptr->pw_dir)) < 0)
+       if ((error = git_str_puts(out, pwdptr->pw_dir)) < 0)
                goto out;
 
 out:
@@ -75,7 +75,7 @@ out:
 }
 #endif
 
-static int git_sysdir_guess_global_dirs(git_buf *out)
+static int git_sysdir_guess_global_dirs(git_str *out)
 {
 #ifdef GIT_WIN32
        return git_win32__find_global_dirs(out);
@@ -114,12 +114,12 @@ static int git_sysdir_guess_global_dirs(git_buf *out)
 #endif
 }
 
-static int git_sysdir_guess_xdg_dirs(git_buf *out)
+static int git_sysdir_guess_xdg_dirs(git_str *out)
 {
 #ifdef GIT_WIN32
        return git_win32__find_xdg_dirs(out);
 #else
-       git_buf env = GIT_BUF_INIT;
+       git_str env = GIT_STR_INIT;
        int error;
        uid_t uid, euid;
 
@@ -132,13 +132,13 @@ static int git_sysdir_guess_xdg_dirs(git_buf *out)
         */
        if (uid == euid) {
                if ((error = git__getenv(&env, "XDG_CONFIG_HOME")) == 0)
-                       error = git_buf_joinpath(out, env.ptr, "git");
+                       error = git_str_joinpath(out, env.ptr, "git");
 
                if (error == GIT_ENOTFOUND && (error = git__getenv(&env, "HOME")) == 0)
-                       error = git_buf_joinpath(out, env.ptr, ".config/git");
+                       error = git_str_joinpath(out, env.ptr, ".config/git");
        } else {
                if ((error = get_passwd_home(&env, euid)) == 0)
-                       error = git_buf_joinpath(out, env.ptr, ".config/git");
+                       error = git_str_joinpath(out, env.ptr, ".config/git");
        }
 
        if (error == GIT_ENOTFOUND) {
@@ -146,31 +146,31 @@ static int git_sysdir_guess_xdg_dirs(git_buf *out)
                error = 0;
        }
 
-       git_buf_dispose(&env);
+       git_str_dispose(&env);
        return error;
 #endif
 }
 
-static int git_sysdir_guess_template_dirs(git_buf *out)
+static int git_sysdir_guess_template_dirs(git_str *out)
 {
 #ifdef GIT_WIN32
-       return git_win32__find_system_dirs(out, L"share\\git-core\\templates");
+       return git_win32__find_system_dirs(out, "share/git-core/templates");
 #else
-       return git_buf_sets(out, "/usr/share/git-core/templates");
+       return git_str_sets(out, "/usr/share/git-core/templates");
 #endif
 }
 
 struct git_sysdir__dir {
-       git_buf buf;
-       int (*guess)(git_buf *out);
+       git_str buf;
+       int (*guess)(git_str *out);
 };
 
 static struct git_sysdir__dir git_sysdir__dirs[] = {
-       { GIT_BUF_INIT, git_sysdir_guess_system_dirs },
-       { GIT_BUF_INIT, git_sysdir_guess_global_dirs },
-       { GIT_BUF_INIT, git_sysdir_guess_xdg_dirs },
-       { GIT_BUF_INIT, git_sysdir_guess_programdata_dirs },
-       { GIT_BUF_INIT, git_sysdir_guess_template_dirs },
+       { GIT_STR_INIT, git_sysdir_guess_system_dirs },
+       { GIT_STR_INIT, git_sysdir_guess_global_dirs },
+       { GIT_STR_INIT, git_sysdir_guess_xdg_dirs },
+       { GIT_STR_INIT, git_sysdir_guess_programdata_dirs },
+       { GIT_STR_INIT, git_sysdir_guess_template_dirs },
 };
 
 static void git_sysdir_global_shutdown(void)
@@ -178,7 +178,7 @@ static void git_sysdir_global_shutdown(void)
        size_t i;
 
        for (i = 0; i < ARRAY_SIZE(git_sysdir__dirs); ++i)
-               git_buf_dispose(&git_sysdir__dirs[i].buf);
+               git_str_dispose(&git_sysdir__dirs[i].buf);
 }
 
 int git_sysdir_global_init(void)
@@ -189,9 +189,25 @@ int git_sysdir_global_init(void)
        for (i = 0; !error && i < ARRAY_SIZE(git_sysdir__dirs); i++)
                error = git_sysdir__dirs[i].guess(&git_sysdir__dirs[i].buf);
 
+       if (error)
+               return error;
+
        return git_runtime_shutdown_register(git_sysdir_global_shutdown);
 }
 
+int git_sysdir_reset(void)
+{
+       size_t i;
+       int error = 0;
+
+       for (i = 0; !error && i < ARRAY_SIZE(git_sysdir__dirs); ++i) {
+               git_str_dispose(&git_sysdir__dirs[i].buf);
+               error = git_sysdir__dirs[i].guess(&git_sysdir__dirs[i].buf);
+       }
+
+       return error;
+}
+
 static int git_sysdir_check_selector(git_sysdir_t which)
 {
        if (which < ARRAY_SIZE(git_sysdir__dirs))
@@ -202,7 +218,7 @@ static int git_sysdir_check_selector(git_sysdir_t which)
 }
 
 
-int git_sysdir_get(const git_buf **out, git_sysdir_t which)
+int git_sysdir_get(const git_str **out, git_sysdir_t which)
 {
        GIT_ASSERT_ARG(out);
 
@@ -219,7 +235,7 @@ int git_sysdir_get(const git_buf **out, git_sysdir_t which)
 int git_sysdir_set(git_sysdir_t which, const char *search_path)
 {
        const char *expand_path = NULL;
-       git_buf merge = GIT_BUF_INIT;
+       git_str merge = GIT_STR_INIT;
 
        GIT_ERROR_CHECK_ERROR(git_sysdir_check_selector(which));
 
@@ -233,48 +249,48 @@ int git_sysdir_set(git_sysdir_t which, const char *search_path)
        /* if $PATH is not referenced, then just set the path */
        if (!expand_path) {
                if (search_path)
-                       git_buf_sets(&git_sysdir__dirs[which].buf, search_path);
+                       git_str_sets(&git_sysdir__dirs[which].buf, search_path);
 
                goto done;
        }
 
        /* otherwise set to join(before $PATH, old value, after $PATH) */
        if (expand_path > search_path)
-               git_buf_set(&merge, search_path, expand_path - search_path);
+               git_str_set(&merge, search_path, expand_path - search_path);
 
-       if (git_buf_len(&git_sysdir__dirs[which].buf))
-               git_buf_join(&merge, GIT_PATH_LIST_SEPARATOR,
+       if (git_str_len(&git_sysdir__dirs[which].buf))
+               git_str_join(&merge, GIT_PATH_LIST_SEPARATOR,
                        merge.ptr, git_sysdir__dirs[which].buf.ptr);
 
        expand_path += strlen(PATH_MAGIC);
        if (*expand_path)
-               git_buf_join(&merge, GIT_PATH_LIST_SEPARATOR, merge.ptr, expand_path);
+               git_str_join(&merge, GIT_PATH_LIST_SEPARATOR, merge.ptr, expand_path);
 
-       git_buf_swap(&git_sysdir__dirs[which].buf, &merge);
-       git_buf_dispose(&merge);
+       git_str_swap(&git_sysdir__dirs[which].buf, &merge);
+       git_str_dispose(&merge);
 
 done:
-       if (git_buf_oom(&git_sysdir__dirs[which].buf))
+       if (git_str_oom(&git_sysdir__dirs[which].buf))
                return -1;
 
        return 0;
 }
 
 static int git_sysdir_find_in_dirlist(
-       git_buf *path,
+       git_str *path,
        const char *name,
        git_sysdir_t which,
        const char *label)
 {
        size_t len;
        const char *scan, *next = NULL;
-       const git_buf *syspath;
+       const git_str *syspath;
 
        GIT_ERROR_CHECK_ERROR(git_sysdir_get(&syspath, which));
-       if (!syspath || !git_buf_len(syspath))
+       if (!syspath || !git_str_len(syspath))
                goto done;
 
-       for (scan = git_buf_cstr(syspath); scan; scan = next) {
+       for (scan = git_str_cstr(syspath); scan; scan = next) {
                /* find unescaped separator or end of string */
                for (next = scan; *next; ++next) {
                        if (*next == GIT_PATH_LIST_SEPARATOR &&
@@ -287,11 +303,11 @@ static int git_sysdir_find_in_dirlist(
                if (!len)
                        continue;
 
-               GIT_ERROR_CHECK_ERROR(git_buf_set(path, scan, len));
+               GIT_ERROR_CHECK_ERROR(git_str_set(path, scan, len));
                if (name)
-                       GIT_ERROR_CHECK_ERROR(git_buf_joinpath(path, path->ptr, name));
+                       GIT_ERROR_CHECK_ERROR(git_str_joinpath(path, path->ptr, name));
 
-               if (git_path_exists(path->ptr))
+               if (git_fs_path_exists(path->ptr))
                        return 0;
        }
 
@@ -300,47 +316,47 @@ done:
                git_error_set(GIT_ERROR_OS, "the %s file '%s' doesn't exist", label, name);
        else
                git_error_set(GIT_ERROR_OS, "the %s directory doesn't exist", label);
-       git_buf_dispose(path);
+       git_str_dispose(path);
        return GIT_ENOTFOUND;
 }
 
-int git_sysdir_find_system_file(git_buf *path, const char *filename)
+int git_sysdir_find_system_file(git_str *path, const char *filename)
 {
        return git_sysdir_find_in_dirlist(
                path, filename, GIT_SYSDIR_SYSTEM, "system");
 }
 
-int git_sysdir_find_global_file(git_buf *path, const char *filename)
+int git_sysdir_find_global_file(git_str *path, const char *filename)
 {
        return git_sysdir_find_in_dirlist(
                path, filename, GIT_SYSDIR_GLOBAL, "global");
 }
 
-int git_sysdir_find_xdg_file(git_buf *path, const char *filename)
+int git_sysdir_find_xdg_file(git_str *path, const char *filename)
 {
        return git_sysdir_find_in_dirlist(
                path, filename, GIT_SYSDIR_XDG, "global/xdg");
 }
 
-int git_sysdir_find_programdata_file(git_buf *path, const char *filename)
+int git_sysdir_find_programdata_file(git_str *path, const char *filename)
 {
        return git_sysdir_find_in_dirlist(
                path, filename, GIT_SYSDIR_PROGRAMDATA, "ProgramData");
 }
 
-int git_sysdir_find_template_dir(git_buf *path)
+int git_sysdir_find_template_dir(git_str *path)
 {
        return git_sysdir_find_in_dirlist(
                path, NULL, GIT_SYSDIR_TEMPLATE, "template");
 }
 
-int git_sysdir_expand_global_file(git_buf *path, const char *filename)
+int git_sysdir_expand_global_file(git_str *path, const char *filename)
 {
        int error;
 
        if ((error = git_sysdir_find_global_file(path, NULL)) == 0) {
                if (filename)
-                       error = git_buf_joinpath(path, path->ptr, filename);
+                       error = git_str_joinpath(path, path->ptr, filename);
        }
 
        return error;
index cc5599e383a10e7ef3f9db409c9cba728005db9a..568f27940c82191776b9d11b955149bbdf7d295f 100644 (file)
@@ -10,7 +10,7 @@
 #include "common.h"
 
 #include "posix.h"
-#include "buffer.h"
+#include "str.h"
 
 /**
  * Find a "global" file (i.e. one in a user's home directory).
@@ -19,7 +19,7 @@
  * @param filename name of file to find in the home directory
  * @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error
  */
-extern int git_sysdir_find_global_file(git_buf *path, const char *filename);
+extern int git_sysdir_find_global_file(git_str *path, const char *filename);
 
 /**
  * Find an "XDG" file (i.e. one in user's XDG config path).
@@ -28,7 +28,7 @@ extern int git_sysdir_find_global_file(git_buf *path, const char *filename);
  * @param filename name of file to find in the home directory
  * @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error
  */
-extern int git_sysdir_find_xdg_file(git_buf *path, const char *filename);
+extern int git_sysdir_find_xdg_file(git_str *path, const char *filename);
 
 /**
  * Find a "system" file (i.e. one shared for all users of the system).
@@ -37,7 +37,7 @@ extern int git_sysdir_find_xdg_file(git_buf *path, const char *filename);
  * @param filename name of file to find in the home directory
  * @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error
  */
-extern int git_sysdir_find_system_file(git_buf *path, const char *filename);
+extern int git_sysdir_find_system_file(git_str *path, const char *filename);
 
 /**
  * Find a "ProgramData" file (i.e. one in %PROGRAMDATA%)
@@ -46,7 +46,7 @@ extern int git_sysdir_find_system_file(git_buf *path, const char *filename);
  * @param filename name of file to find in the ProgramData directory
  * @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error
  */
-extern int git_sysdir_find_programdata_file(git_buf *path, const char *filename);
+extern int git_sysdir_find_programdata_file(git_str *path, const char *filename);
 
 /**
  * Find template directory.
@@ -54,7 +54,7 @@ extern int git_sysdir_find_programdata_file(git_buf *path, const char *filename)
  * @param path buffer to write the full path into
  * @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error
  */
-extern int git_sysdir_find_template_dir(git_buf *path);
+extern int git_sysdir_find_template_dir(git_str *path);
 
 /**
  * Expand the name of a "global" file (i.e. one in a user's home
@@ -66,7 +66,7 @@ extern int git_sysdir_find_template_dir(git_buf *path);
  * @param filename name of file in the home directory
  * @return 0 on success or -1 on error
  */
-extern int git_sysdir_expand_global_file(git_buf *path, const char *filename);
+extern int git_sysdir_expand_global_file(git_str *path, const char *filename);
 
 typedef enum {
        GIT_SYSDIR_SYSTEM = 0,
@@ -74,7 +74,7 @@ typedef enum {
        GIT_SYSDIR_XDG    = 2,
        GIT_SYSDIR_PROGRAMDATA = 3,
        GIT_SYSDIR_TEMPLATE = 4,
-       GIT_SYSDIR__MAX   = 5,
+       GIT_SYSDIR__MAX   = 5
 } git_sysdir_t;
 
 /**
@@ -87,11 +87,11 @@ extern int git_sysdir_global_init(void);
 /**
  * Get the search path for global/system/xdg files
  *
- * @param out pointer to git_buf containing search path
+ * @param out pointer to git_str containing search path
  * @param which which list of paths to return
  * @return 0 on success, <0 on failure
  */
-extern int git_sysdir_get(const git_buf **out, git_sysdir_t which);
+extern int git_sysdir_get(const git_str **out, git_sysdir_t which);
 
 /**
  * Set search paths for global/system/xdg files
@@ -105,4 +105,9 @@ extern int git_sysdir_get(const git_buf **out, git_sysdir_t which);
  */
 extern int git_sysdir_set(git_sysdir_t which, const char *paths);
 
+/**
+ * Reset search paths for global/system/xdg files.
+ */
+extern int git_sysdir_reset(void);
+
 #endif
index ee91e509162ca53b057e7c09cb07c1421933214c..5734106faebf072b75dcffbb778fa2d9155104cc 100644 (file)
--- a/src/tag.c
+++ b/src/tag.c
@@ -9,7 +9,6 @@
 
 #include "commit.h"
 #include "signature.h"
-#include "message.h"
 #include "wildmatch.h"
 #include "git2/object.h"
 #include "git2/repository.h"
@@ -63,7 +62,7 @@ const char *git_tag_message(const git_tag *t)
 static int tag_error(const char *str)
 {
        git_error_set(GIT_ERROR_TAG, "failed to parse tag: %s", str);
-       return -1;
+       return GIT_EINVALID;
 }
 
 static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
@@ -74,6 +73,7 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
        size_t text_len, alloc_len;
        const char *search;
        unsigned int i;
+       int error;
 
        if (git_oid__parse(&tag->target, &buffer, buffer_end, "object ") < 0)
                return tag_error("object field invalid");
@@ -131,8 +131,8 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
                tag->tagger = git__malloc(sizeof(git_signature));
                GIT_ERROR_CHECK_ALLOC(tag->tagger);
 
-               if (git_signature__parse(tag->tagger, &buffer, buffer_end, "tagger ", '\n') < 0)
-                       return -1;
+               if ((error = git_signature__parse(tag->tagger, &buffer, buffer_end, "tagger ", '\n')) < 0)
+                       return error;
        }
 
        tag->message = NULL;
@@ -176,7 +176,7 @@ int git_tag__parse(void *_tag, git_odb_object *odb_obj)
 
 static int retrieve_tag_reference(
        git_reference **tag_reference_out,
-       git_buf *ref_name_out,
+       git_str *ref_name_out,
        git_repository *repo,
        const char *tag_name)
 {
@@ -185,7 +185,7 @@ static int retrieve_tag_reference(
 
        *tag_reference_out = NULL;
 
-       if (git_buf_joinpath(ref_name_out, GIT_REFS_TAGS_DIR, tag_name) < 0)
+       if (git_str_joinpath(ref_name_out, GIT_REFS_TAGS_DIR, tag_name) < 0)
                return -1;
 
        error = git_reference_lookup(&tag_ref, repo, ref_name_out->ptr);
@@ -199,11 +199,11 @@ static int retrieve_tag_reference(
 
 static int retrieve_tag_reference_oid(
        git_oid *oid,
-       git_buf *ref_name_out,
+       git_str *ref_name_out,
        git_repository *repo,
        const char *tag_name)
 {
-       if (git_buf_joinpath(ref_name_out, GIT_REFS_TAGS_DIR, tag_name) < 0)
+       if (git_str_joinpath(ref_name_out, GIT_REFS_TAGS_DIR, tag_name) < 0)
                return -1;
 
        return git_reference_name_to_id(oid, repo, ref_name_out->ptr);
@@ -217,16 +217,16 @@ static int write_tag_annotation(
                const git_signature *tagger,
                const char *message)
 {
-       git_buf tag = GIT_BUF_INIT;
+       git_str tag = GIT_STR_INIT;
        git_odb *odb;
 
        git_oid__writebuf(&tag, "object ", git_object_id(target));
-       git_buf_printf(&tag, "type %s\n", git_object_type2string(git_object_type(target)));
-       git_buf_printf(&tag, "tag %s\n", tag_name);
+       git_str_printf(&tag, "type %s\n", git_object_type2string(git_object_type(target)));
+       git_str_printf(&tag, "tag %s\n", tag_name);
        git_signature__writebuf(&tag, "tagger ", tagger);
-       git_buf_putc(&tag, '\n');
+       git_str_putc(&tag, '\n');
 
-       if (git_buf_puts(&tag, message) < 0)
+       if (git_str_puts(&tag, message) < 0)
                goto on_error;
 
        if (git_repository_odb__weakptr(&odb, repo) < 0)
@@ -235,11 +235,11 @@ static int write_tag_annotation(
        if (git_odb_write(oid, odb, tag.ptr, tag.size, GIT_OBJECT_TAG) < 0)
                goto on_error;
 
-       git_buf_dispose(&tag);
+       git_str_dispose(&tag);
        return 0;
 
 on_error:
-       git_buf_dispose(&tag);
+       git_str_dispose(&tag);
        git_error_set(GIT_ERROR_OBJECT, "failed to create tag annotation");
        return -1;
 }
@@ -255,7 +255,7 @@ static int git_tag_create__internal(
                int create_tag_annotation)
 {
        git_reference *new_ref = NULL;
-       git_buf ref_name = GIT_BUF_INIT;
+       git_str ref_name = GIT_STR_INIT;
 
        int error;
 
@@ -276,7 +276,7 @@ static int git_tag_create__internal(
        /** Ensure the tag name doesn't conflict with an already existing
         *      reference unless overwriting has explicitly been requested **/
        if (error == 0 && !allow_ref_overwrite) {
-               git_buf_dispose(&ref_name);
+               git_str_dispose(&ref_name);
                git_error_set(GIT_ERROR_TAG, "tag already exists");
                return GIT_EEXISTS;
        }
@@ -291,7 +291,7 @@ static int git_tag_create__internal(
 
 cleanup:
        git_reference_free(new_ref);
-       git_buf_dispose(&ref_name);
+       git_str_dispose(&ref_name);
        return error;
 }
 
@@ -344,7 +344,7 @@ int git_tag_create_from_buffer(git_oid *oid, git_repository *repo, const char *b
        git_odb_object *target_obj;
 
        git_reference *new_ref = NULL;
-       git_buf ref_name = GIT_BUF_INIT;
+       git_str ref_name = GIT_STR_INIT;
 
        GIT_ASSERT_ARG(oid);
        GIT_ASSERT_ARG(buffer);
@@ -395,7 +395,7 @@ int git_tag_create_from_buffer(git_oid *oid, git_repository *repo, const char *b
        git_odb_stream_free(stream);
 
        if (error < 0) {
-               git_buf_dispose(&ref_name);
+               git_str_dispose(&ref_name);
                return error;
        }
 
@@ -403,7 +403,7 @@ int git_tag_create_from_buffer(git_oid *oid, git_repository *repo, const char *b
                &new_ref, repo, ref_name.ptr, oid, allow_ref_overwrite, NULL);
 
        git_reference_free(new_ref);
-       git_buf_dispose(&ref_name);
+       git_str_dispose(&ref_name);
 
        return error;
 
@@ -418,12 +418,12 @@ on_error:
 int git_tag_delete(git_repository *repo, const char *tag_name)
 {
        git_reference *tag_ref;
-       git_buf ref_name = GIT_BUF_INIT;
+       git_str ref_name = GIT_STR_INIT;
        int error;
 
        error = retrieve_tag_reference(&tag_ref, &ref_name, repo, tag_name);
 
-       git_buf_dispose(&ref_name);
+       git_str_dispose(&ref_name);
 
        if (error < 0)
                return error;
@@ -535,11 +535,13 @@ int git_tag_peel(git_object **tag_target, const git_tag *tag)
 
 int git_tag_name_is_valid(int *valid, const char *name)
 {
-       git_buf ref_name = GIT_BUF_INIT;
+       git_str ref_name = GIT_STR_INIT;
        int error = 0;
 
        GIT_ASSERT(valid);
 
+       *valid = 0;
+
        /*
         * Discourage tag name starting with dash,
         * https://github.com/git/git/commit/4f0accd638b8d2
@@ -547,14 +549,14 @@ int git_tag_name_is_valid(int *valid, const char *name)
        if (!name || name[0] == '-')
                goto done;
 
-       if ((error = git_buf_puts(&ref_name, GIT_REFS_TAGS_DIR)) < 0 ||
-           (error = git_buf_puts(&ref_name, name)) < 0)
+       if ((error = git_str_puts(&ref_name, GIT_REFS_TAGS_DIR)) < 0 ||
+           (error = git_str_puts(&ref_name, name)) < 0)
                goto done;
 
        error = git_reference_name_is_valid(valid, ref_name.ptr);
 
 done:
-       git_buf_dispose(&ref_name);
+       git_str_dispose(&ref_name);
        return error;
 }
 
index 4b091c0a29a8970fe17344d5cb330cdf753becfd..4bbac9fd8703339fc33a4151346741b89edc1505 100644 (file)
@@ -12,7 +12,7 @@
 #if defined(__clang__)
 
 # if (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 1))
-#  error Atomic primitives do not exist on this version of clang; configure libgit2 with -DTHREADSAFE=OFF
+#  error Atomic primitives do not exist on this version of clang; configure libgit2 with -DUSE_THREADS=OFF
 # else
 #  define GIT_BUILTIN_ATOMIC
 # endif
@@ -20,7 +20,7 @@
 #elif defined(__GNUC__)
 
 # if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1))
-#  error Atomic primitives do not exist on this version of gcc; configure libgit2 with -DTHREADSAFE=OFF
+#  error Atomic primitives do not exist on this version of gcc; configure libgit2 with -DUSE_THREADS=OFF
 # elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
 #  define GIT_BUILTIN_ATOMIC
 # else
@@ -180,7 +180,7 @@ GIT_INLINE(volatile void *) git_atomic__swap(
 #if defined(GIT_WIN32)
        return InterlockedExchangePointer(ptr, newval);
 #elif defined(GIT_BUILTIN_ATOMIC)
-       void * volatile foundval = NULL;
+       void * foundval = NULL;
        __atomic_exchange(ptr, &newval, &foundval, __ATOMIC_SEQ_CST);
        return foundval;
 #elif defined(GIT_BUILTIN_SYNC)
index e2c08975fd980eff8eb31eda3ce7b29f9562ac52..9e3ef5818496deb64a8648544c6d20555ed1b084 100644 (file)
@@ -36,8 +36,8 @@ static void threadstate_dispose(git_threadstate *threadstate)
        if (!threadstate)
                return;
 
-    if (threadstate->error_t.message != git_buf__initbuf)
-        git__free(threadstate->error_t.message);
+       if (threadstate->error_t.message != git_str__initstr)
+               git__free(threadstate->error_t.message);
        threadstate->error_t.message = NULL;
 }
 
@@ -76,7 +76,7 @@ git_threadstate *git_threadstate_get(void)
                return threadstate;
 
        if ((threadstate = git__calloc(1, sizeof(git_threadstate))) == NULL ||
-           git_buf_init(&threadstate->error_buf, 0) < 0)
+           git_str_init(&threadstate->error_buf, 0) < 0)
                return NULL;
 
        git_tlsdata_set(tls_key, threadstate);
index 51810a9390fd710073aef390294f8d96d5d7a65c..c10f26b5947cbf3700645c33f45dd5e8a1af61cb 100644 (file)
@@ -12,7 +12,7 @@
 typedef struct {
        git_error *last_error;
        git_error error_t;
-       git_buf error_buf;
+       git_str error_buf;
        char oid_fmt[GIT_OID_HEXSZ+1];
 } git_threadstate;
 
index efc7b01a2d8d0f0891abd302ee6de9f0af1e2ebd..b0c56c4dc668bbeb1bc0959e14f8fd8fbc3c8c78 100644 (file)
@@ -7,19 +7,14 @@
 
 #include "trace.h"
 
-#include "buffer.h"
+#include "str.h"
 #include "runtime.h"
 #include "git2/trace.h"
 
-#ifdef GIT_TRACE
-
 struct git_trace_data git_trace__data = {0};
 
-#endif
-
 int git_trace_set(git_trace_level_t level, git_trace_cb callback)
 {
-#ifdef GIT_TRACE
        GIT_ASSERT_ARG(level == 0 || callback != NULL);
 
        git_trace__data.level = level;
@@ -27,12 +22,4 @@ int git_trace_set(git_trace_level_t level, git_trace_cb callback)
        GIT_MEMORY_BARRIER;
 
        return 0;
-#else
-       GIT_UNUSED(level);
-       GIT_UNUSED(callback);
-
-       git_error_set(GIT_ERROR_INVALID,
-               "this version of libgit2 was not built with tracing.");
-       return -1;
-#endif
 }
index a233aa2257c3518f98c7eac699a3b644eb5b4efc..239928dcbce69cfc94e3667d34698acd1c084232 100644 (file)
@@ -10,9 +10,7 @@
 #include "common.h"
 
 #include <git2/trace.h>
-#include "buffer.h"
-
-#ifdef GIT_TRACE
+#include "str.h"
 
 struct git_trace_data {
        git_trace_level_t level;
@@ -27,13 +25,13 @@ GIT_INLINE(void) git_trace__write_fmt(
        va_list ap)
 {
        git_trace_cb callback = git_trace__data.callback;
-       git_buf message = GIT_BUF_INIT;
+       git_str message = GIT_STR_INIT;
 
-       git_buf_vprintf(&message, fmt, ap);
+       git_str_vprintf(&message, fmt, ap);
 
-       callback(level, git_buf_cstr(&message));
+       callback(level, git_str_cstr(&message));
 
-       git_buf_dispose(&message);
+       git_str_dispose(&message);
 }
 
 #define git_trace_level()      (git_trace__data.level)
@@ -50,19 +48,4 @@ GIT_INLINE(void) git_trace(git_trace_level_t level, const char *fmt, ...)
        }
 }
 
-#else
-
-GIT_INLINE(void) git_trace__null(
-       git_trace_level_t level,
-       const char *fmt, ...)
-{
-       GIT_UNUSED(level);
-       GIT_UNUSED(fmt);
-}
-
-#define git_trace_level()      ((git_trace_level_t)0)
-#define git_trace              git_trace__null
-
-#endif
-
 #endif
index 61cdd1ba170783a812689a4219508d8e86806784..4761c9922f23e43d896a1c66859b420dc6c96e9e 100644 (file)
@@ -286,7 +286,7 @@ enum trailer_state {
        S_VALUE = 4,
        S_VALUE_NL = 5,
        S_VALUE_END = 6,
-       S_IGNORE = 7,
+       S_IGNORE = 7
 };
 
 #define NEXT(st) { state = (st); ptr++; continue; }
index 98fa1ba900ca49173d30874110235695e8aa32f7..ccffa9984cceb2674529f37d3d5656b2b1e61bdc 100644 (file)
@@ -23,7 +23,7 @@
 typedef enum {
        TRANSACTION_NONE,
        TRANSACTION_REFS,
-       TRANSACTION_CONFIG,
+       TRANSACTION_CONFIG
 } transaction_t;
 
 typedef struct {
index e128aa6c724f2b43f266844c8eddb8dec62669f3..640ccacaee371c4fcd09853384fe9148d0efece8 100644 (file)
@@ -12,7 +12,7 @@
 #include "git2/net.h"
 #include "git2/transport.h"
 #include "git2/sys/transport.h"
-#include "path.h"
+#include "fs_path.h"
 
 typedef struct transport_definition {
        char *prefix;
@@ -82,7 +82,7 @@ static int transport_find_fn(
         * to a directory and if so assume local path, else assume SSH */
 
        /* Check to see if the path points to a file on the local file system */
-       if (!definition && git_path_exists(url) && git_path_isdir(url))
+       if (!definition && git_fs_path_exists(url) && git_fs_path_isdir(url))
                definition = &local_transport_definition;
 #endif
 
@@ -98,7 +98,7 @@ static int transport_find_fn(
 
 #ifndef GIT_WIN32
        /* Check to see if the path points to a file on the local file system */
-       if (!definition && git_path_exists(url) && git_path_isdir(url))
+       if (!definition && git_fs_path_exists(url) && git_fs_path_isdir(url))
                definition = &local_transport_definition;
 #endif
 
@@ -143,7 +143,7 @@ int git_transport_register(
        git_transport_cb cb,
        void *param)
 {
-       git_buf prefix = GIT_BUF_INIT;
+       git_str prefix = GIT_STR_INIT;
        transport_definition *d, *definition = NULL;
        size_t i;
        int error = 0;
@@ -151,7 +151,7 @@ int git_transport_register(
        GIT_ASSERT_ARG(scheme);
        GIT_ASSERT_ARG(cb);
 
-       if ((error = git_buf_printf(&prefix, "%s://", scheme)) < 0)
+       if ((error = git_str_printf(&prefix, "%s://", scheme)) < 0)
                goto on_error;
 
        git_vector_foreach(&custom_transports, i, d) {
@@ -164,7 +164,7 @@ int git_transport_register(
        definition = git__calloc(1, sizeof(transport_definition));
        GIT_ERROR_CHECK_ALLOC(definition);
 
-       definition->prefix = git_buf_detach(&prefix);
+       definition->prefix = git_str_detach(&prefix);
        definition->fn = cb;
        definition->param = param;
 
@@ -174,21 +174,21 @@ int git_transport_register(
        return 0;
 
 on_error:
-       git_buf_dispose(&prefix);
+       git_str_dispose(&prefix);
        git__free(definition);
        return error;
 }
 
 int git_transport_unregister(const char *scheme)
 {
-       git_buf prefix = GIT_BUF_INIT;
+       git_str prefix = GIT_STR_INIT;
        transport_definition *d;
        size_t i;
        int error = 0;
 
        GIT_ASSERT_ARG(scheme);
 
-       if ((error = git_buf_printf(&prefix, "%s://", scheme)) < 0)
+       if ((error = git_str_printf(&prefix, "%s://", scheme)) < 0)
                goto done;
 
        git_vector_foreach(&custom_transports, i, d) {
@@ -210,7 +210,7 @@ int git_transport_unregister(const char *scheme)
        error = GIT_ENOTFOUND;
 
 done:
-       git_buf_dispose(&prefix);
+       git_str_dispose(&prefix);
        return error;
 }
 
index 51763e35926fc9e28c87c1c91a5235216e07b017..90b6b124f0e55636a0f9e747486130c70ea8e1ab 100644 (file)
@@ -7,17 +7,15 @@
 
 #include "auth.h"
 
-#include "git2.h"
-#include "buffer.h"
 #include "git2/sys/credential.h"
 
 static int basic_next_token(
-       git_buf *out,
+       git_str *out,
        git_http_auth_context *ctx,
        git_credential *c)
 {
        git_credential_userpass_plaintext *cred;
-       git_buf raw = GIT_BUF_INIT;
+       git_str raw = GIT_STR_INIT;
        int error = GIT_EAUTH;
 
        GIT_UNUSED(ctx);
@@ -29,11 +27,11 @@ static int basic_next_token(
 
        cred = (git_credential_userpass_plaintext *)c;
 
-       git_buf_printf(&raw, "%s:%s", cred->username, cred->password);
+       git_str_printf(&raw, "%s:%s", cred->username, cred->password);
 
-       if (git_buf_oom(&raw) ||
-               git_buf_puts(out, "Basic ") < 0 ||
-               git_buf_encode_base64(out, git_buf_cstr(&raw), raw.size) < 0)
+       if (git_str_oom(&raw) ||
+               git_str_puts(out, "Basic ") < 0 ||
+               git_str_encode_base64(out, git_str_cstr(&raw), raw.size) < 0)
                goto on_error;
 
        error = 0;
@@ -42,7 +40,7 @@ on_error:
        if (raw.size)
                git__memzero(raw.ptr, raw.size);
 
-       git_buf_dispose(&raw);
+       git_str_dispose(&raw);
        return error;
 }
 
index 9caac4676fc67d813e1088623baaf925d02ebc36..64680cc5358851dcc1eb3ca0e9331cfc356dc653 100644 (file)
 
 #include "common.h"
 
-#include "git2.h"
 #include "netops.h"
 
 typedef enum {
        GIT_HTTP_AUTH_BASIC = 1,
        GIT_HTTP_AUTH_NEGOTIATE = 2,
-       GIT_HTTP_AUTH_NTLM = 4,
+       GIT_HTTP_AUTH_NTLM = 4
 } git_http_auth_t;
 
 typedef struct git_http_auth_context git_http_auth_context;
@@ -35,7 +34,7 @@ struct git_http_auth_context {
        int (*set_challenge)(git_http_auth_context *ctx, const char *challenge);
 
        /** Gets the next authentication token from the context */
-       int (*next_token)(git_buf *out, git_http_auth_context *ctx, git_credential *cred);
+       int (*next_token)(git_str *out, git_http_auth_context *ctx, git_credential *cred);
 
        /** Examines if all tokens have been presented. */
        int (*is_complete)(git_http_auth_context *ctx);
index 31469933e74825613657f64e4148f418ff54a26a..6380504be7e161455d37c2d3dc960da4f98da1b9 100644 (file)
@@ -10,7 +10,6 @@
 #if defined(GIT_GSSAPI) || defined(GIT_GSSFRAMEWORK)
 
 #include "git2.h"
-#include "buffer.h"
 #include "auth.h"
 #include "git2/sys/credential.h"
 
@@ -33,7 +32,7 @@ typedef struct {
        git_http_auth_context parent;
        unsigned configured : 1,
                complete : 1;
-       git_buf target;
+       git_str target;
        char *challenge;
        gss_ctx_id_t gss_context;
        gss_OID oid;
@@ -87,14 +86,14 @@ static void negotiate_context_dispose(http_auth_negotiate_context *ctx)
                ctx->gss_context = GSS_C_NO_CONTEXT;
        }
 
-       git_buf_dispose(&ctx->target);
+       git_str_dispose(&ctx->target);
 
        git__free(ctx->challenge);
        ctx->challenge = NULL;
 }
 
 static int negotiate_next_token(
-       git_buf *buf,
+       git_str *buf,
        git_http_auth_context *c,
        git_credential *cred)
 {
@@ -104,7 +103,7 @@ static int negotiate_next_token(
                input_token = GSS_C_EMPTY_BUFFER,
                output_token = GSS_C_EMPTY_BUFFER;
        gss_buffer_t input_token_ptr = GSS_C_NO_BUFFER;
-       git_buf input_buf = GIT_BUF_INIT;
+       git_str input_buf = GIT_STR_INIT;
        gss_name_t server = NULL;
        gss_OID mech;
        size_t challenge_len;
@@ -142,7 +141,7 @@ static int negotiate_next_token(
        }
 
        if (challenge_len > 9) {
-               if (git_buf_decode_base64(&input_buf,
+               if (git_str_decode_base64(&input_buf,
                                ctx->challenge + 10, challenge_len - 10) < 0) {
                        git_error_set(GIT_ERROR_NET, "invalid negotiate challenge from server");
                        error = -1;
@@ -192,16 +191,16 @@ static int negotiate_next_token(
                goto done;
        }
 
-       git_buf_puts(buf, "Negotiate ");
-       git_buf_encode_base64(buf, output_token.value, output_token.length);
+       git_str_puts(buf, "Negotiate ");
+       git_str_encode_base64(buf, output_token.value, output_token.length);
 
-       if (git_buf_oom(buf))
+       if (git_str_oom(buf))
                error = -1;
 
 done:
        gss_release_name(&status_minor, &server);
        gss_release_buffer(&status_minor, (gss_buffer_t) &output_token);
-       git_buf_dispose(&input_buf);
+       git_str_dispose(&input_buf);
        return error;
 }
 
@@ -270,10 +269,10 @@ static int negotiate_init_context(
                return GIT_EAUTH;
        }
 
-       git_buf_puts(&ctx->target, "HTTP@");
-       git_buf_puts(&ctx->target, url->host);
+       git_str_puts(&ctx->target, "HTTP@");
+       git_str_puts(&ctx->target, url->host);
 
-       if (git_buf_oom(&ctx->target))
+       if (git_str_oom(&ctx->target))
                return -1;
 
        ctx->gss_context = GSS_C_NO_CONTEXT;
index 742db75b3d33ba822f4107295d4b41316da8b344..f49ce101a56663ecffb92c39c60cbe7b28575a6c 100644 (file)
@@ -5,11 +5,11 @@
  * a Linking Exception. For full terms see the included COPYING file.
  */
 
-#include "git2.h"
+#include "auth_ntlm.h"
+
 #include "common.h"
-#include "buffer.h"
+#include "str.h"
 #include "auth.h"
-#include "auth_ntlm.h"
 #include "git2/sys/credential.h"
 
 #ifdef GIT_NTLM
@@ -77,12 +77,12 @@ done:
 }
 
 static int ntlm_next_token(
-       git_buf *buf,
+       git_str *buf,
        git_http_auth_context *c,
        git_credential *cred)
 {
        http_auth_ntlm_context *ctx = (http_auth_ntlm_context *)c;
-       git_buf input_buf = GIT_BUF_INIT;
+       git_str input_buf = GIT_STR_INIT;
        const unsigned char *msg;
        size_t challenge_len, msg_len;
        int error = GIT_EAUTH;
@@ -129,7 +129,7 @@ static int ntlm_next_token(
                        goto done;
                }
 
-               if (git_buf_decode_base64(&input_buf,
+               if (git_str_decode_base64(&input_buf,
                    ctx->challenge + 5, challenge_len - 5) < 0) {
                        git_error_set(GIT_ERROR_NET, "invalid NTLM challenge from server");
                        goto done;
@@ -149,16 +149,16 @@ static int ntlm_next_token(
                }
        }
 
-       git_buf_puts(buf, "NTLM ");
-       git_buf_encode_base64(buf, (const char *)msg, msg_len);
+       git_str_puts(buf, "NTLM ");
+       git_str_encode_base64(buf, (const char *)msg, msg_len);
 
-       if (git_buf_oom(buf))
+       if (git_str_oom(buf))
                goto done;
 
        error = 0;
 
 done:
-       git_buf_dispose(&input_buf);
+       git_str_dispose(&input_buf);
        return error;
 }
 
index a7cd6d795ddcadc13b51741c6d59fde28c97f118..40689498cae5579cc152238decb38245469adff5 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef INCLUDE_transports_auth_ntlm_h__
 #define INCLUDE_transports_auth_ntlm_h__
 
-#include "git2.h"
 #include "auth.h"
 
 /* NTLM requires a full request/challenge/response */
index 7c93155a8bf2928590226ea3a924cac8d3d24c34..591e2ab0352c570cf30c977aab849849ab4ded11 100644 (file)
@@ -7,12 +7,10 @@
 
 #include "common.h"
 
-#include "git2.h"
-#include "buffer.h"
 #include "netops.h"
-#include "git2/sys/transport.h"
 #include "stream.h"
 #include "streams/socket.h"
+#include "git2/sys/transport.h"
 
 #define OWNING_SUBTRANSPORT(s) ((git_subtransport *)(s)->parent.subtransport)
 
@@ -39,7 +37,7 @@ typedef struct {
  *
  * For example: 0035git-upload-pack /libgit2/libgit2\0host=github.com\0
  */
-static int gen_proto(git_buf *request, const char *cmd, const char *url)
+static int gen_proto(git_str *request, const char *cmd, const char *url)
 {
        char *delim, *repo;
        char host[] = "host=";
@@ -61,13 +59,13 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url)
 
        len = 4 + strlen(cmd) + 1 + strlen(repo) + 1 + strlen(host) + (delim - url) + 1;
 
-       git_buf_grow(request, len);
-       git_buf_printf(request, "%04x%s %s%c%s",
+       git_str_grow(request, len);
+       git_str_printf(request, "%04x%s %s%c%s",
                (unsigned int)(len & 0x0FFFF), cmd, repo, 0, host);
-       git_buf_put(request, url, delim - url);
-       git_buf_putc(request, '\0');
+       git_str_put(request, url, delim - url);
+       git_str_putc(request, '\0');
 
-       if (git_buf_oom(request))
+       if (git_str_oom(request))
                return -1;
 
        return 0;
@@ -75,7 +73,7 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url)
 
 static int send_command(git_proto_stream *s)
 {
-       git_buf request = GIT_BUF_INIT;
+       git_str request = GIT_STR_INIT;
        int error;
 
        if ((error = gen_proto(&request, s->cmd, s->url)) < 0)
@@ -87,7 +85,7 @@ static int send_command(git_proto_stream *s)
        s->sent_command = 1;
 
 cleanup:
-       git_buf_dispose(&request);
+       git_str_dispose(&request);
        return error;
 }
 
index 914335aba57e929b920051a943aea432dc4a25e0..7db5582cab4b3d0e34af3d8eabab4400b8d247ca 100644 (file)
@@ -9,13 +9,10 @@
 
 #ifndef GIT_WINHTTP
 
-#include "git2.h"
 #include "http_parser.h"
-#include "buffer.h"
 #include "net.h"
 #include "netops.h"
 #include "remote.h"
-#include "git2/sys/credential.h"
 #include "smart.h"
 #include "auth.h"
 #include "http.h"
@@ -25,6 +22,7 @@
 #include "streams/tls.h"
 #include "streams/socket.h"
 #include "httpclient.h"
+#include "git2/sys/credential.h"
 
 bool git_http__expect_continue = false;
 
@@ -40,7 +38,8 @@ typedef struct {
        const char *url;
        const char *request_type;
        const char *response_type;
-       unsigned chunked : 1;
+       unsigned int initial : 1,
+                    chunked : 1;
 } http_service;
 
 typedef struct {
@@ -72,24 +71,28 @@ static const http_service upload_pack_ls_service = {
        GIT_HTTP_METHOD_GET, "/info/refs?service=git-upload-pack",
        NULL,
        "application/x-git-upload-pack-advertisement",
+       1,
        0
 };
 static const http_service upload_pack_service = {
        GIT_HTTP_METHOD_POST, "/git-upload-pack",
        "application/x-git-upload-pack-request",
        "application/x-git-upload-pack-result",
+       0,
        0
 };
 static const http_service receive_pack_ls_service = {
        GIT_HTTP_METHOD_GET, "/info/refs?service=git-receive-pack",
        NULL,
        "application/x-git-receive-pack-advertisement",
+       1,
        0
 };
 static const http_service receive_pack_service = {
        GIT_HTTP_METHOD_POST, "/git-receive-pack",
        "application/x-git-receive-pack-request",
        "application/x-git-receive-pack-result",
+       0,
        1
 };
 
@@ -176,6 +179,7 @@ GIT_INLINE(int) handle_remote_auth(
        git_http_response *response)
 {
        http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
+       git_remote_connect_options *connect_opts = &transport->owner->connect_opts;
 
        if (response->server_auth_credtypes == 0) {
                git_error_set(GIT_ERROR_HTTP, "server requires authentication that we do not support");
@@ -189,8 +193,8 @@ GIT_INLINE(int) handle_remote_auth(
                transport->owner->url,
                response->server_auth_schemetypes,
                response->server_auth_credtypes,
-               transport->owner->cred_acquire_cb,
-               transport->owner->cred_acquire_payload);
+               connect_opts->callbacks.credentials,
+               connect_opts->callbacks.payload);
 }
 
 GIT_INLINE(int) handle_proxy_auth(
@@ -198,6 +202,7 @@ GIT_INLINE(int) handle_proxy_auth(
        git_http_response *response)
 {
        http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
+       git_remote_connect_options *connect_opts = &transport->owner->connect_opts;
 
        if (response->proxy_auth_credtypes == 0) {
                git_error_set(GIT_ERROR_HTTP, "proxy requires authentication that we do not support");
@@ -208,13 +213,26 @@ GIT_INLINE(int) handle_proxy_auth(
        return handle_auth(
                &transport->proxy,
                SERVER_TYPE_PROXY,
-               transport->owner->proxy.url,
+               connect_opts->proxy_opts.url,
                response->server_auth_schemetypes,
                response->proxy_auth_credtypes,
-               transport->owner->proxy.credentials,
-               transport->owner->proxy.payload);
+               connect_opts->proxy_opts.credentials,
+               connect_opts->proxy_opts.payload);
 }
 
+static bool allow_redirect(http_stream *stream)
+{
+       http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
+
+       switch (transport->owner->connect_opts.follow_redirects) {
+       case GIT_REMOTE_REDIRECT_INITIAL:
+               return (stream->service->initial == 1);
+       case GIT_REMOTE_REDIRECT_ALL:
+               return true;
+       default:
+               return false;
+       }
+}
 
 static int handle_response(
        bool *complete,
@@ -233,7 +251,7 @@ static int handle_response(
                        return -1;
                }
 
-               if (git_net_url_apply_redirect(&transport->server.url, response->location, stream->service->url) < 0) {
+               if (git_net_url_apply_redirect(&transport->server.url, response->location, allow_redirect(stream), stream->service->url) < 0) {
                        return -1;
                }
 
@@ -288,6 +306,7 @@ static int lookup_proxy(
        bool *out_use,
        http_subtransport *transport)
 {
+       git_remote_connect_options *connect_opts = &transport->owner->connect_opts;
        const char *proxy;
        git_remote *remote;
        char *config = NULL;
@@ -296,9 +315,9 @@ static int lookup_proxy(
        *out_use = false;
        git_net_url_dispose(&transport->proxy.url);
 
-       switch (transport->owner->proxy.type) {
+       switch (connect_opts->proxy_opts.type) {
        case GIT_PROXY_SPECIFIED:
-               proxy = transport->owner->proxy.url;
+               proxy = connect_opts->proxy_opts.url;
                break;
 
        case GIT_PROXY_AUTO:
@@ -347,7 +366,7 @@ static int generate_request(
        request->credentials = transport->server.cred;
        request->proxy = use_proxy ? &transport->proxy.url : NULL;
        request->proxy_credentials = transport->proxy.cred;
-       request->custom_headers = &transport->owner->custom_headers;
+       request->custom_headers = &transport->owner->connect_opts.custom_headers;
 
        if (stream->service->method == GIT_HTTP_METHOD_POST) {
                request->chunked = stream->service->chunked;
@@ -635,6 +654,7 @@ static int http_action(
        git_smart_service_t action)
 {
        http_subtransport *transport = GIT_CONTAINER_OF(t, http_subtransport, parent);
+       git_remote_connect_options *connect_opts = &transport->owner->connect_opts;
        http_stream *stream;
        const http_service *service;
        int error;
@@ -666,10 +686,10 @@ static int http_action(
        if (!transport->http_client) {
                git_http_client_options opts = {0};
 
-               opts.server_certificate_check_cb = transport->owner->certificate_check_cb;
-               opts.server_certificate_check_payload = transport->owner->message_cb_payload;
-               opts.proxy_certificate_check_cb = transport->owner->proxy.certificate_check;
-               opts.proxy_certificate_check_payload = transport->owner->proxy.payload;
+               opts.server_certificate_check_cb = connect_opts->callbacks.certificate_check;
+               opts.server_certificate_check_payload = connect_opts->callbacks.payload;
+               opts.proxy_certificate_check_cb = connect_opts->proxy_opts.certificate_check;
+               opts.proxy_certificate_check_payload = connect_opts->proxy_opts.payload;
 
                if (git_http_client_new(&transport->http_client, &opts) < 0)
                        return -1;
index 5c360b88387666456df9ee2c02a0981a01106421..8e8e7226ed2d2e7cff0916c16fb052cee3b93b6f 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef INCLUDE_transports_http_h__
 #define INCLUDE_transports_http_h__
 
-#include "buffer.h"
 #include "settings.h"
 #include "httpclient.h"
 
 
 extern bool git_http__expect_continue;
 
-GIT_INLINE(int) git_http__user_agent(git_buf *buf)
+GIT_INLINE(int) git_http__user_agent(git_str *buf)
 {
        const char *ua = git_libgit2__user_agent();
 
        if (!ua)
                ua = "libgit2 " LIBGIT2_VERSION;
 
-       return git_buf_printf(buf, "git/2.0 (%s)", ua);
+       return git_str_printf(buf, "git/2.0 (%s)", ua);
 }
 
 #endif
index 5b8949a04dd2ed0f6f06846abd0e4938bdf600fe..75782da82f9ab12aa1772454dd02758042a9263c 100644 (file)
@@ -84,8 +84,8 @@ typedef struct {
        git_http_response *response;
 
        /* Temporary buffers to avoid extra mallocs */
-       git_buf parse_header_name;
-       git_buf parse_header_value;
+       git_str parse_header_name;
+       git_str parse_header_value;
 
        /* Parser state */
        int error;
@@ -120,8 +120,8 @@ struct git_http_client {
                 request_chunked : 1;
 
        /* Temporary buffers to avoid extra mallocs */
-       git_buf request_msg;
-       git_buf read_buf;
+       git_str request_msg;
+       git_str read_buf;
 
        /* A subset of information from the request */
        size_t request_body_len,
@@ -160,8 +160,8 @@ static int on_header_complete(http_parser *parser)
        git_http_client *client = ctx->client;
        git_http_response *response = ctx->response;
 
-       git_buf *name = &ctx->parse_header_name;
-       git_buf *value = &ctx->parse_header_value;
+       git_str *name = &ctx->parse_header_name;
+       git_str *value = &ctx->parse_header_value;
 
        if (!strcasecmp("Content-Type", name->ptr)) {
                if (response->content_type) {
@@ -193,7 +193,7 @@ static int on_header_complete(http_parser *parser)
        } else if (!strcasecmp("Transfer-Encoding", name->ptr) &&
                   !strcasecmp("chunked", value->ptr)) {
                        ctx->response->chunked = 1;
-       } else if (!strcasecmp("Proxy-Authenticate", git_buf_cstr(name))) {
+       } else if (!strcasecmp("Proxy-Authenticate", git_str_cstr(name))) {
                char *dup = git__strndup(value->ptr, value->size);
                GIT_ERROR_CHECK_ALLOC(dup);
 
@@ -232,15 +232,15 @@ static int on_header_field(http_parser *parser, const char *str, size_t len)
                if (on_header_complete(parser) < 0)
                        return ctx->parse_status = PARSE_STATUS_ERROR;
 
-               git_buf_clear(&ctx->parse_header_name);
-               git_buf_clear(&ctx->parse_header_value);
+               git_str_clear(&ctx->parse_header_name);
+               git_str_clear(&ctx->parse_header_value);
                /* Fall through */
 
        case PARSE_HEADER_NONE:
        case PARSE_HEADER_NAME:
                ctx->parse_header_state = PARSE_HEADER_NAME;
 
-               if (git_buf_put(&ctx->parse_header_name, str, len) < 0)
+               if (git_str_put(&ctx->parse_header_name, str, len) < 0)
                        return ctx->parse_status = PARSE_STATUS_ERROR;
 
                break;
@@ -263,7 +263,7 @@ static int on_header_value(http_parser *parser, const char *str, size_t len)
        case PARSE_HEADER_VALUE:
                ctx->parse_header_state = PARSE_HEADER_VALUE;
 
-               if (git_buf_put(&ctx->parse_header_value, str, len) < 0)
+               if (git_str_put(&ctx->parse_header_value, str, len) < 0)
                        return ctx->parse_status = PARSE_STATUS_ERROR;
 
                break;
@@ -548,7 +548,7 @@ static void free_auth_context(git_http_server *server)
 }
 
 static int apply_credentials(
-       git_buf *buf,
+       git_str *buf,
        git_http_server *server,
        const char *header_name,
        git_credential *credentials)
@@ -556,7 +556,7 @@ static int apply_credentials(
        git_http_auth_context *auth = server->auth_context;
        git_vector *challenges = &server->auth_challenges;
        const char *challenge;
-       git_buf token = GIT_BUF_INIT;
+       git_str token = GIT_STR_INIT;
        int error = 0;
 
        /* We've started a new request without creds; free the context. */
@@ -602,15 +602,15 @@ static int apply_credentials(
        }
 
        if (token.size > 0)
-               error = git_buf_printf(buf, "%s: %s\r\n", header_name, token.ptr);
+               error = git_str_printf(buf, "%s: %s\r\n", header_name, token.ptr);
 
 done:
-       git_buf_dispose(&token);
+       git_str_dispose(&token);
        return error;
 }
 
 GIT_INLINE(int) apply_server_credentials(
-       git_buf *buf,
+       git_str *buf,
        git_http_client *client,
        git_http_request *request)
 {
@@ -621,7 +621,7 @@ GIT_INLINE(int) apply_server_credentials(
 }
 
 GIT_INLINE(int) apply_proxy_credentials(
-       git_buf *buf,
+       git_str *buf,
        git_http_client *client,
        git_http_request *request)
 {
@@ -631,54 +631,54 @@ GIT_INLINE(int) apply_proxy_credentials(
                                 request->proxy_credentials);
 }
 
-static int puts_host_and_port(git_buf *buf, git_net_url *url, bool force_port)
+static int puts_host_and_port(git_str *buf, git_net_url *url, bool force_port)
 {
        bool ipv6 = git_net_url_is_ipv6(url);
 
        if (ipv6)
-               git_buf_putc(buf, '[');
+               git_str_putc(buf, '[');
 
-       git_buf_puts(buf, url->host);
+       git_str_puts(buf, url->host);
 
        if (ipv6)
-               git_buf_putc(buf, ']');
+               git_str_putc(buf, ']');
 
        if (force_port || !git_net_url_is_default_port(url)) {
-               git_buf_putc(buf, ':');
-               git_buf_puts(buf, url->port);
+               git_str_putc(buf, ':');
+               git_str_puts(buf, url->port);
        }
 
-       return git_buf_oom(buf) ? -1 : 0;
+       return git_str_oom(buf) ? -1 : 0;
 }
 
 static int generate_connect_request(
        git_http_client *client,
        git_http_request *request)
 {
-       git_buf *buf;
+       git_str *buf;
        int error;
 
-       git_buf_clear(&client->request_msg);
+       git_str_clear(&client->request_msg);
        buf = &client->request_msg;
 
-       git_buf_puts(buf, "CONNECT ");
+       git_str_puts(buf, "CONNECT ");
        puts_host_and_port(buf, &client->server.url, true);
-       git_buf_puts(buf, " HTTP/1.1\r\n");
+       git_str_puts(buf, " HTTP/1.1\r\n");
 
-       git_buf_puts(buf, "User-Agent: ");
+       git_str_puts(buf, "User-Agent: ");
        git_http__user_agent(buf);
-       git_buf_puts(buf, "\r\n");
+       git_str_puts(buf, "\r\n");
 
-       git_buf_puts(buf, "Host: ");
+       git_str_puts(buf, "Host: ");
        puts_host_and_port(buf, &client->server.url, true);
-       git_buf_puts(buf, "\r\n");
+       git_str_puts(buf, "\r\n");
 
        if ((error = apply_proxy_credentials(buf, client, request) < 0))
                return -1;
 
-       git_buf_puts(buf, "\r\n");
+       git_str_puts(buf, "\r\n");
 
-       return git_buf_oom(buf) ? -1 : 0;
+       return git_str_oom(buf) ? -1 : 0;
 }
 
 static bool use_connect_proxy(git_http_client *client)
@@ -690,53 +690,53 @@ static int generate_request(
        git_http_client *client,
        git_http_request *request)
 {
-       git_buf *buf;
+       git_str *buf;
        size_t i;
        int error;
 
        GIT_ASSERT_ARG(client);
        GIT_ASSERT_ARG(request);
 
-       git_buf_clear(&client->request_msg);
+       git_str_clear(&client->request_msg);
        buf = &client->request_msg;
 
        /* GET|POST path HTTP/1.1 */
-       git_buf_puts(buf, name_for_method(request->method));
-       git_buf_putc(buf, ' ');
+       git_str_puts(buf, name_for_method(request->method));
+       git_str_putc(buf, ' ');
 
        if (request->proxy && strcmp(request->url->scheme, "https"))
                git_net_url_fmt(buf, request->url);
        else
                git_net_url_fmt_path(buf, request->url);
 
-       git_buf_puts(buf, " HTTP/1.1\r\n");
+       git_str_puts(buf, " HTTP/1.1\r\n");
 
-       git_buf_puts(buf, "User-Agent: ");
+       git_str_puts(buf, "User-Agent: ");
        git_http__user_agent(buf);
-       git_buf_puts(buf, "\r\n");
+       git_str_puts(buf, "\r\n");
 
-       git_buf_puts(buf, "Host: ");
+       git_str_puts(buf, "Host: ");
        puts_host_and_port(buf, request->url, false);
-       git_buf_puts(buf, "\r\n");
+       git_str_puts(buf, "\r\n");
 
        if (request->accept)
-               git_buf_printf(buf, "Accept: %s\r\n", request->accept);
+               git_str_printf(buf, "Accept: %s\r\n", request->accept);
        else
-               git_buf_puts(buf, "Accept: */*\r\n");
+               git_str_puts(buf, "Accept: */*\r\n");
 
        if (request->content_type)
-               git_buf_printf(buf, "Content-Type: %s\r\n",
+               git_str_printf(buf, "Content-Type: %s\r\n",
                        request->content_type);
 
        if (request->chunked)
-               git_buf_puts(buf, "Transfer-Encoding: chunked\r\n");
+               git_str_puts(buf, "Transfer-Encoding: chunked\r\n");
 
        if (request->content_length > 0)
-               git_buf_printf(buf, "Content-Length: %"PRIuZ "\r\n",
+               git_str_printf(buf, "Content-Length: %"PRIuZ "\r\n",
                        request->content_length);
 
        if (request->expect_continue)
-               git_buf_printf(buf, "Expect: 100-continue\r\n");
+               git_str_printf(buf, "Expect: 100-continue\r\n");
 
        if ((error = apply_server_credentials(buf, client, request)) < 0 ||
            (!use_connect_proxy(client) &&
@@ -748,13 +748,13 @@ static int generate_request(
                        const char *hdr = request->custom_headers->strings[i];
 
                        if (hdr)
-                               git_buf_printf(buf, "%s\r\n", hdr);
+                               git_str_printf(buf, "%s\r\n", hdr);
                }
        }
 
-       git_buf_puts(buf, "\r\n");
+       git_str_puts(buf, "\r\n");
 
-       if (git_buf_oom(buf))
+       if (git_str_oom(buf))
                return -1;
 
        return 0;
@@ -1077,7 +1077,7 @@ GIT_INLINE(int) client_read(git_http_client *client)
                client->proxy.stream : client->server.stream;
 
        /*
-        * We use a git_buf for convenience, but statically allocate it and
+        * We use a git_str for convenience, but statically allocate it and
         * don't resize.  Limit our consumption to INT_MAX since calling
         * functions use an int return type to return number of bytes read.
         */
@@ -1198,7 +1198,7 @@ GIT_INLINE(int) client_read_and_parse(git_http_client *client)
                return -1;
        }
 
-       git_buf_consume_bytes(&client->read_buf, parsed_len);
+       git_str_consume_bytes(&client->read_buf, parsed_len);
 
        return (int)parsed_len;
 }
@@ -1235,7 +1235,7 @@ static void complete_response_body(git_http_client *client)
        }
 
 done:
-       git_buf_clear(&client->read_buf);
+       git_str_clear(&client->read_buf);
 }
 
 int git_http_client_send_request(
@@ -1257,12 +1257,12 @@ int git_http_client_send_request(
                return 0;
 
        if (git_trace_level() >= GIT_TRACE_DEBUG) {
-               git_buf url = GIT_BUF_INIT;
+               git_str url = GIT_STR_INIT;
                git_net_url_fmt(&url, request->url);
                git_trace(GIT_TRACE_DEBUG, "Sending %s request to %s",
                          name_for_method(request->method),
                          url.ptr ? url.ptr : "<invalid>");
-               git_buf_dispose(&url);
+               git_str_dispose(&url);
        }
 
        if ((error = http_client_connect(client, request)) < 0 ||
@@ -1314,7 +1314,7 @@ int git_http_client_send_body(
        size_t buffer_len)
 {
        git_http_server *server;
-       git_buf hdr = GIT_BUF_INIT;
+       git_str hdr = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(client);
@@ -1341,7 +1341,7 @@ int git_http_client_send_body(
 
                client->request_body_remain -= buffer_len;
        } else {
-               if ((error = git_buf_printf(&hdr, "%" PRIxZ "\r\n", buffer_len)) < 0 ||
+               if ((error = git_str_printf(&hdr, "%" PRIxZ "\r\n", buffer_len)) < 0 ||
                    (error = stream_write(server, hdr.ptr, hdr.size)) < 0 ||
                    (error = stream_write(server, buffer, buffer_len)) < 0 ||
                    (error = stream_write(server, "\r\n", 2)) < 0)
@@ -1349,7 +1349,7 @@ int git_http_client_send_body(
        }
 
 done:
-       git_buf_dispose(&hdr);
+       git_str_dispose(&hdr);
        return error;
 }
 
@@ -1422,8 +1422,8 @@ int git_http_client_read_response(
        GIT_ASSERT(client->state == READING_BODY || client->state == DONE);
 
 done:
-       git_buf_dispose(&parser_context.parse_header_name);
-       git_buf_dispose(&parser_context.parse_header_value);
+       git_str_dispose(&parser_context.parse_header_name);
+       git_str_dispose(&parser_context.parse_header_value);
 
        return error;
 }
@@ -1531,7 +1531,7 @@ int git_http_client_new(
        client = git__calloc(1, sizeof(git_http_client));
        GIT_ERROR_CHECK_ALLOC(client);
 
-       git_buf_init(&client->read_buf, GIT_READ_BUFFER_SIZE);
+       git_str_init(&client->read_buf, GIT_READ_BUFFER_SIZE);
        GIT_ERROR_CHECK_ALLOC(client->read_buf.ptr);
 
        if (opts)
@@ -1560,7 +1560,7 @@ static void http_client_close(git_http_client *client)
        http_server_close(&client->server);
        http_server_close(&client->proxy);
 
-       git_buf_dispose(&client->request_msg);
+       git_str_dispose(&client->request_msg);
 
        client->state = 0;
        client->request_count = 0;
@@ -1574,6 +1574,6 @@ void git_http_client_free(git_http_client *client)
                return;
 
        http_client_close(client);
-       git_buf_dispose(&client->read_buf);
+       git_str_dispose(&client->read_buf);
        git__free(client);
 }
index bb31b1345809dfc2a28508ae47b02396601af2f0..6c754a034a4316524fe7e156a920502624d0fa74 100644 (file)
@@ -7,6 +7,16 @@
 
 #include "common.h"
 
+#include "pack-objects.h"
+#include "refs.h"
+#include "posix.h"
+#include "fs_path.h"
+#include "repository.h"
+#include "odb.h"
+#include "push.h"
+#include "remote.h"
+#include "proxy.h"
+
 #include "git2/types.h"
 #include "git2/net.h"
 #include "git2/repository.h"
 #include "git2/pack.h"
 #include "git2/commit.h"
 #include "git2/revparse.h"
-
-#include "pack-objects.h"
-#include "refs.h"
-#include "posix.h"
-#include "path.h"
-#include "buffer.h"
-#include "repository.h"
-#include "odb.h"
-#include "push.h"
-#include "remote.h"
-#include "proxy.h"
+#include "git2/sys/remote.h"
 
 typedef struct {
        git_transport parent;
        git_remote *owner;
        char *url;
        int direction;
-       int flags;
        git_atomic32 cancelled;
        git_repository *repo;
-       git_transport_message_cb progress_cb;
-       git_transport_message_cb error_cb;
-       void *message_cb_payload;
+       git_remote_connect_options connect_opts;
        git_vector refs;
        unsigned connected : 1,
                have_refs : 1;
@@ -71,7 +68,7 @@ static int add_ref(transport_local *t, const char *name)
        git_remote_head *head;
        git_oid obj_id;
        git_object *obj = NULL, *target = NULL;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        int error;
 
        if ((error = git_reference_lookup(&ref, t->repo, name)) < 0)
@@ -132,11 +129,11 @@ static int add_ref(transport_local *t, const char *name)
        head = git__calloc(1, sizeof(git_remote_head));
        GIT_ERROR_CHECK_ALLOC(head);
 
-       if (git_buf_join(&buf, 0, name, peeled) < 0) {
+       if (git_str_join(&buf, 0, name, peeled) < 0) {
                free_head(head);
                return -1;
        }
-       head->name = git_buf_detach(&buf);
+       head->name = git_str_detach(&buf);
 
        if (!(error = git_tag_peel(&target, (git_tag *)obj))) {
                git_oid_cpy(&head->oid, git_object_id(target));
@@ -201,41 +198,37 @@ on_error:
 static int local_connect(
        git_transport *transport,
        const char *url,
-       git_credential_acquire_cb cred_acquire_cb,
-       void *cred_acquire_payload,
-       const git_proxy_options *proxy,
-       int direction, int flags)
+       int direction,
+       const git_remote_connect_options *connect_opts)
 {
        git_repository *repo;
        int error;
-       transport_local *t = (transport_local *) transport;
+       transport_local *t = (transport_local *)transport;
        const char *path;
-       git_buf buf = GIT_BUF_INIT;
-
-       GIT_UNUSED(cred_acquire_cb);
-       GIT_UNUSED(cred_acquire_payload);
-       GIT_UNUSED(proxy);
+       git_str buf = GIT_STR_INIT;
 
        if (t->connected)
                return 0;
 
+       if (git_remote_connect_options_normalize(&t->connect_opts, t->owner->repo, connect_opts) < 0)
+               return -1;
+
        free_heads(&t->refs);
 
        t->url = git__strdup(url);
        GIT_ERROR_CHECK_ALLOC(t->url);
        t->direction = direction;
-       t->flags = flags;
 
        /* 'url' may be a url or path; convert to a path */
-       if ((error = git_path_from_url_or_path(&buf, url)) < 0) {
-               git_buf_dispose(&buf);
+       if ((error = git_fs_path_from_url_or_path(&buf, url)) < 0) {
+               git_str_dispose(&buf);
                return error;
        }
-       path = git_buf_cstr(&buf);
+       path = git_str_cstr(&buf);
 
        error = git_repository_open(&repo, path);
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        if (error < 0)
                return -1;
@@ -250,6 +243,29 @@ static int local_connect(
        return 0;
 }
 
+static int local_set_connect_opts(
+       git_transport *transport,
+       const git_remote_connect_options *connect_opts)
+{
+       transport_local *t = (transport_local *)transport;
+
+       if (!t->connected) {
+               git_error_set(GIT_ERROR_NET, "cannot reconfigure a transport that is not connected");
+               return -1;
+       }
+
+       return git_remote_connect_options_normalize(&t->connect_opts, t->owner->repo, connect_opts);
+}
+
+static int local_capabilities(unsigned int *capabilities, git_transport *transport)
+{
+       GIT_UNUSED(transport);
+
+       *capabilities = GIT_REMOTE_CAPABILITY_TIP_OID |
+                       GIT_REMOTE_CAPABILITY_REACHABLE_OID;
+       return 0;
+}
+
 static int local_ls(const git_remote_head ***out, size_t *size, git_transport *transport)
 {
        transport_local *t = (transport_local *)transport;
@@ -338,30 +354,28 @@ static int transfer_to_push_transfer(const git_indexer_progress *stats, void *pa
 
 static int local_push(
        git_transport *transport,
-       git_push *push,
-       const git_remote_callbacks *cbs)
+       git_push *push)
 {
        transport_local *t = (transport_local *)transport;
+       git_remote_callbacks *cbs = &t->connect_opts.callbacks;
        git_repository *remote_repo = NULL;
        push_spec *spec;
        char *url = NULL;
        const char *path;
-       git_buf buf = GIT_BUF_INIT, odb_path = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT, odb_path = GIT_STR_INIT;
        int error;
        size_t j;
 
-       GIT_UNUSED(cbs);
-
        /* 'push->remote->url' may be a url or path; convert to a path */
-       if ((error = git_path_from_url_or_path(&buf, push->remote->url)) < 0) {
-               git_buf_dispose(&buf);
+       if ((error = git_fs_path_from_url_or_path(&buf, push->remote->url)) < 0) {
+               git_str_dispose(&buf);
                return error;
        }
-       path = git_buf_cstr(&buf);
+       path = git_str_cstr(&buf);
 
        error = git_repository_open(&remote_repo, path);
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        if (error < 0)
                return error;
@@ -378,12 +392,12 @@ static int local_push(
                goto on_error;
        }
 
-       if ((error = git_repository_item_path(&odb_path, remote_repo, GIT_REPOSITORY_ITEM_OBJECTS)) < 0
-               || (error = git_buf_joinpath(&odb_path, odb_path.ptr, "pack")) < 0)
+       if ((error = git_repository__item_path(&odb_path, remote_repo, GIT_REPOSITORY_ITEM_OBJECTS)) < 0
+               || (error = git_str_joinpath(&odb_path, odb_path.ptr, "pack")) < 0)
                goto on_error;
 
        error = git_packbuilder_write(push->pb, odb_path.ptr, 0, transfer_to_push_transfer, (void *) cbs);
-       git_buf_dispose(&odb_path);
+       git_str_dispose(&odb_path);
 
        if (error < 0)
                goto on_error;
@@ -441,12 +455,11 @@ static int local_push(
        }
 
        if (push->specs.length) {
-               int flags = t->flags;
                url = git__strdup(t->url);
 
                if (!url || t->parent.close(&t->parent) < 0 ||
                        t->parent.connect(&t->parent, url,
-                       NULL, NULL, NULL, GIT_DIRECTION_PUSH, flags))
+                       GIT_DIRECTION_PUSH, NULL))
                        goto on_error;
        }
 
@@ -479,31 +492,41 @@ static const char *compressing_objects_fmt = "Compressing objects: %.0f%% (%d/%d
 
 static int local_counting(int stage, unsigned int current, unsigned int total, void *payload)
 {
-       git_buf progress_info = GIT_BUF_INIT;
+       git_str progress_info = GIT_STR_INIT;
        transport_local *t = payload;
        int error;
 
-       if (!t->progress_cb)
+       if (!t->connect_opts.callbacks.sideband_progress)
                return 0;
 
        if (stage == GIT_PACKBUILDER_ADDING_OBJECTS) {
-               git_buf_printf(&progress_info, counting_objects_fmt, current);
+               git_str_printf(&progress_info, counting_objects_fmt, current);
        } else if (stage == GIT_PACKBUILDER_DELTAFICATION) {
                float perc = (((float) current) / total) * 100;
-               git_buf_printf(&progress_info, compressing_objects_fmt, perc, current, total);
+               git_str_printf(&progress_info, compressing_objects_fmt, perc, current, total);
                if (current == total)
-                       git_buf_printf(&progress_info, ", done\n");
+                       git_str_printf(&progress_info, ", done\n");
                else
-                       git_buf_putc(&progress_info, '\r');
+                       git_str_putc(&progress_info, '\r');
 
        }
 
-       if (git_buf_oom(&progress_info))
+       if (git_str_oom(&progress_info))
+               return -1;
+
+       if (progress_info.size > INT_MAX) {
+               git_error_set(GIT_ERROR_NET, "remote sent overly large progress data");
+               git_str_dispose(&progress_info);
                return -1;
+       }
+
 
-       error = t->progress_cb(git_buf_cstr(&progress_info), (int)git_buf_len(&progress_info), t->message_cb_payload);
-       git_buf_dispose(&progress_info);
+       error = t->connect_opts.callbacks.sideband_progress(
+               progress_info.ptr,
+               (int)progress_info.size,
+               t->connect_opts.callbacks.payload);
 
+       git_str_dispose(&progress_info);
        return error;
 }
 
@@ -533,9 +556,7 @@ static int foreach_reference_cb(git_reference *reference, void *payload)
 static int local_download_pack(
                git_transport *transport,
                git_repository *repo,
-               git_indexer_progress *stats,
-               git_indexer_progress_cb progress_cb,
-               void *progress_payload)
+               git_indexer_progress *stats)
 {
        transport_local *t = (transport_local*)transport;
        git_revwalk *walk = NULL;
@@ -545,10 +566,12 @@ static int local_download_pack(
        git_packbuilder *pack = NULL;
        git_odb_writepack *writepack = NULL;
        git_odb *odb = NULL;
-       git_buf progress_info = GIT_BUF_INIT;
+       git_str progress_info = GIT_STR_INIT;
+       foreach_data data = {0};
 
        if ((error = git_revwalk_new(&walk, t->repo)) < 0)
                goto cleanup;
+
        git_revwalk_sorting(walk, GIT_SORT_TIME);
 
        if ((error = git_packbuilder_new(&pack, t->repo)) < 0)
@@ -584,73 +607,67 @@ static int local_download_pack(
        if ((error = git_packbuilder_insert_walk(pack, walk)))
                goto cleanup;
 
-       if ((error = git_buf_printf(&progress_info, counting_objects_fmt, git_packbuilder_object_count(pack))) < 0)
-               goto cleanup;
-
-       if (t->progress_cb &&
-           (error = t->progress_cb(git_buf_cstr(&progress_info), (int)git_buf_len(&progress_info), t->message_cb_payload)) < 0)
-               goto cleanup;
+       if (t->connect_opts.callbacks.sideband_progress) {
+               if ((error = git_str_printf(
+                               &progress_info,
+                               counting_objects_fmt,
+                               git_packbuilder_object_count(pack))) < 0 ||
+                   (error = t->connect_opts.callbacks.sideband_progress(
+                               progress_info.ptr,
+                               (int)progress_info.size,
+                               t->connect_opts.callbacks.payload)) < 0)
+                       goto cleanup;
+       }
 
        /* Walk the objects, building a packfile */
        if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
                goto cleanup;
 
        /* One last one with the newline */
-       git_buf_clear(&progress_info);
-       git_buf_printf(&progress_info, counting_objects_fmt, git_packbuilder_object_count(pack));
-       if ((error = git_buf_putc(&progress_info, '\n')) < 0)
-               goto cleanup;
-
-       if (t->progress_cb &&
-           (error = t->progress_cb(git_buf_cstr(&progress_info), (int)git_buf_len(&progress_info), t->message_cb_payload)) < 0)
-               goto cleanup;
+       if (t->connect_opts.callbacks.sideband_progress) {
+               git_str_clear(&progress_info);
+
+               if ((error = git_str_printf(
+                               &progress_info,
+                               counting_objects_fmt,
+                               git_packbuilder_object_count(pack))) < 0 ||
+                   (error = git_str_putc(&progress_info, '\n')) < 0 ||
+                   (error = t->connect_opts.callbacks.sideband_progress(
+                               progress_info.ptr,
+                               (int)progress_info.size,
+                               t->connect_opts.callbacks.payload)) < 0)
+                       goto cleanup;
+       }
 
-       if ((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) != 0)
+       if ((error = git_odb_write_pack(
+                       &writepack,
+                       odb,
+                       t->connect_opts.callbacks.transfer_progress,
+                       t->connect_opts.callbacks.payload)) < 0)
                goto cleanup;
 
        /* Write the data to the ODB */
-       {
-               foreach_data data = {0};
-               data.stats = stats;
-               data.progress_cb = progress_cb;
-               data.progress_payload = progress_payload;
-               data.writepack = writepack;
+       data.stats = stats;
+       data.progress_cb = t->connect_opts.callbacks.transfer_progress;
+       data.progress_payload = t->connect_opts.callbacks.payload;
+       data.writepack = writepack;
 
-               /* autodetect */
-               git_packbuilder_set_threads(pack, 0);
+       /* autodetect */
+       git_packbuilder_set_threads(pack, 0);
 
-               if ((error = git_packbuilder_foreach(pack, foreach_cb, &data)) != 0)
-                       goto cleanup;
-       }
+       if ((error = git_packbuilder_foreach(pack, foreach_cb, &data)) != 0)
+               goto cleanup;
 
        error = writepack->commit(writepack, stats);
 
 cleanup:
        if (writepack) writepack->free(writepack);
-       git_buf_dispose(&progress_info);
+       git_str_dispose(&progress_info);
        git_packbuilder_free(pack);
        git_revwalk_free(walk);
        return error;
 }
 
-static int local_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_local *t = (transport_local *)transport;
-
-       GIT_UNUSED(certificate_check_cb);
-
-       t->progress_cb = progress_cb;
-       t->error_cb = error_cb;
-       t->message_cb_payload = message_cb_payload;
-
-       return 0;
-}
-
 static int local_is_connected(git_transport *transport)
 {
        transport_local *t = (transport_local *)transport;
@@ -658,15 +675,6 @@ static int local_is_connected(git_transport *transport)
        return t->connected;
 }
 
-static int local_read_flags(git_transport *transport, int *flags)
-{
-       transport_local *t = (transport_local *)transport;
-
-       *flags = t->flags;
-
-       return 0;
-}
-
 static void local_cancel(git_transport *transport)
 {
        transport_local *t = (transport_local *)transport;
@@ -721,8 +729,9 @@ int git_transport_local(git_transport **out, git_remote *owner, void *param)
        GIT_ERROR_CHECK_ALLOC(t);
 
        t->parent.version = GIT_TRANSPORT_VERSION;
-       t->parent.set_callbacks = local_set_callbacks;
        t->parent.connect = local_connect;
+       t->parent.set_connect_opts = local_set_connect_opts;
+       t->parent.capabilities = local_capabilities;
        t->parent.negotiate_fetch = local_negotiate_fetch;
        t->parent.download_pack = local_download_pack;
        t->parent.push = local_push;
@@ -730,7 +739,6 @@ int git_transport_local(git_transport **out, git_remote *owner, void *param)
        t->parent.free = local_free;
        t->parent.ls = local_ls;
        t->parent.is_connected = local_is_connected;
-       t->parent.read_flags = local_read_flags;
        t->parent.cancel = local_cancel;
 
        if ((error = git_vector_init(&t->refs, 0, NULL)) < 0) {
index 587f14358896955a0d3886f5acf65d1efa3c63d6..801fcbe53bfa310d858f72d95d1d528eff85bb92 100644 (file)
@@ -8,6 +8,7 @@
 #include "smart.h"
 
 #include "git2.h"
+#include "git2/sys/remote.h"
 #include "refs.h"
 #include "refspec.h"
 #include "proxy.h"
@@ -56,101 +57,6 @@ GIT_INLINE(int) git_smart__reset_stream(transport_smart *t, bool close_subtransp
        return 0;
 }
 
-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 = GIT_CONTAINER_OF(transport, transport_smart, parent);
-
-       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;
-}
-
-static size_t http_header_name_length(const char *http_header)
-{
-       const char *colon = strchr(http_header, ':');
-       if (!colon)
-               return 0;
-       return colon - http_header;
-}
-
-static bool is_malformed_http_header(const char *http_header)
-{
-       const char *c;
-       size_t name_len;
-
-       /* Disallow \r and \n */
-       c = strchr(http_header, '\r');
-       if (c)
-               return true;
-       c = strchr(http_header, '\n');
-       if (c)
-               return true;
-
-       /* Require a header name followed by : */
-       name_len = http_header_name_length(http_header);
-       if (name_len < 1)
-               return true;
-
-       return false;
-}
-
-static char *forbidden_custom_headers[] = {
-       "User-Agent",
-       "Host",
-       "Accept",
-       "Content-Type",
-       "Transfer-Encoding",
-       "Content-Length",
-};
-
-static bool is_forbidden_custom_header(const char *custom_header)
-{
-       unsigned long i;
-       size_t name_len = http_header_name_length(custom_header);
-
-       /* Disallow headers that we set */
-       for (i = 0; i < ARRAY_SIZE(forbidden_custom_headers); i++)
-               if (strncmp(forbidden_custom_headers[i], custom_header, name_len) == 0)
-                       return true;
-
-       return false;
-}
-
-static int git_smart__set_custom_headers(
-       git_transport *transport,
-       const git_strarray *custom_headers)
-{
-       transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
-       size_t i;
-
-       if (t->custom_headers.count)
-               git_strarray_dispose(&t->custom_headers);
-
-       if (!custom_headers)
-               return 0;
-
-       for (i = 0; i < custom_headers->count; i++) {
-               if (is_malformed_http_header(custom_headers->strings[i])) {
-                       git_error_set(GIT_ERROR_INVALID, "custom HTTP header '%s' is malformed", custom_headers->strings[i]);
-                       return -1;
-               }
-               if (is_forbidden_custom_header(custom_headers->strings[i])) {
-                       git_error_set(GIT_ERROR_INVALID, "custom HTTP header '%s' is already set by libgit2", custom_headers->strings[i]);
-                       return -1;
-               }
-       }
-
-       return git_strarray_copy(&t->custom_headers, custom_headers);
-}
-
 int git_smart__update_heads(transport_smart *t, git_vector *symrefs)
 {
        size_t i;
@@ -164,20 +70,20 @@ int git_smart__update_heads(transport_smart *t, git_vector *symrefs)
 
                if (symrefs) {
                        git_refspec *spec;
-                       git_buf buf = GIT_BUF_INIT;
+                       git_str buf = GIT_STR_INIT;
                        size_t j;
                        int error = 0;
 
                        git_vector_foreach(symrefs, j, spec) {
-                               git_buf_clear(&buf);
+                               git_str_clear(&buf);
                                if (git_refspec_src_matches(spec, ref->head.name) &&
-                                   !(error = git_refspec_transform(&buf, spec, ref->head.name))) {
+                                   !(error = git_refspec__transform(&buf, spec, ref->head.name))) {
                                        git__free(ref->head.symref_target);
-                                       ref->head.symref_target = git_buf_detach(&buf);
+                                       ref->head.symref_target = git_str_detach(&buf);
                                }
                        }
 
-                       git_buf_dispose(&buf);
+                       git_str_dispose(&buf);
 
                        if (error < 0)
                                return error;
@@ -206,11 +112,8 @@ static void free_symrefs(git_vector *symrefs)
 static int git_smart__connect(
        git_transport *transport,
        const char *url,
-       git_credential_acquire_cb cred_acquire_cb,
-       void *cred_acquire_payload,
-       const git_proxy_options *proxy,
        int direction,
-       int flags)
+       const git_remote_connect_options *connect_opts)
 {
        transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
        git_smart_subtransport_stream *stream;
@@ -223,24 +126,19 @@ static int git_smart__connect(
        if (git_smart__reset_stream(t, true) < 0)
                return -1;
 
+       if (git_remote_connect_options_normalize(&t->connect_opts, t->owner->repo, connect_opts) < 0)
+               return -1;
+
        t->url = git__strdup(url);
        GIT_ERROR_CHECK_ALLOC(t->url);
 
-       git_proxy_options_clear(&t->proxy);
-
-       if (git_proxy_options_dup(&t->proxy, proxy) < 0)
-               return -1;
-
        t->direction = direction;
-       t->flags = flags;
-       t->cred_acquire_cb = cred_acquire_cb;
-       t->cred_acquire_payload = cred_acquire_payload;
 
-       if (GIT_DIRECTION_FETCH == t->direction)
+       if (GIT_DIRECTION_FETCH == t->direction) {
                service = GIT_SERVICE_UPLOADPACK_LS;
-       else if (GIT_DIRECTION_PUSH == t->direction)
+       } else if (GIT_DIRECTION_PUSH == t->direction) {
                service = GIT_SERVICE_RECEIVEPACK_LS;
-       else {
+       else {
                git_error_set(GIT_ERROR_NET, "invalid direction");
                return -1;
        }
@@ -315,6 +213,35 @@ cleanup:
        return error;
 }
 
+static int git_smart__set_connect_opts(
+       git_transport *transport,
+       const git_remote_connect_options *opts)
+{
+       transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
+
+       if (!t->connected) {
+               git_error_set(GIT_ERROR_NET, "cannot reconfigure a transport that is not connected");
+               return -1;
+       }
+
+       return git_remote_connect_options_normalize(&t->connect_opts, t->owner->repo, opts);
+}
+
+static int git_smart__capabilities(unsigned int *capabilities, git_transport *transport)
+{
+       transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
+
+       *capabilities = 0;
+
+       if (t->caps.want_tip_sha1)
+               *capabilities |= GIT_REMOTE_CAPABILITY_TIP_OID;
+
+       if (t->caps.want_reachable_sha1)
+               *capabilities |= GIT_REMOTE_CAPABILITY_REACHABLE_OID;
+
+       return 0;
+}
+
 static int git_smart__ls(const git_remote_head ***out, size_t *size, git_transport *transport)
 {
        transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
@@ -401,15 +328,6 @@ static int git_smart__is_connected(git_transport *transport)
        return t->connected;
 }
 
-static int git_smart__read_flags(git_transport *transport, int *flags)
-{
-       transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
-
-       *flags = t->flags;
-
-       return 0;
-}
-
 static int git_smart__close(git_transport *transport)
 {
        transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
@@ -465,9 +383,8 @@ static void git_smart__free(git_transport *transport)
                git_pkt_free(p);
 
        git_vector_free(refs);
-       git__free((char *)t->proxy.url);
 
-       git_strarray_dispose(&t->custom_headers);
+       git_remote_connect_options_dispose(&t->connect_opts);
 
        git__free(t);
 }
@@ -482,34 +399,30 @@ static int ref_name_cmp(const void *a, const void *b)
 int git_transport_smart_certificate_check(git_transport *transport, git_cert *cert, int valid, const char *hostname)
 {
        transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
+       git_remote_connect_options *connect_opts = &t->connect_opts;
 
        GIT_ASSERT_ARG(transport);
        GIT_ASSERT_ARG(cert);
        GIT_ASSERT_ARG(hostname);
 
-       if (!t->certificate_check_cb)
+       if (!connect_opts->callbacks.certificate_check)
                return GIT_PASSTHROUGH;
 
-       return t->certificate_check_cb(cert, valid, hostname, t->message_cb_payload);
+       return connect_opts->callbacks.certificate_check(cert, valid, hostname, connect_opts->callbacks.payload);
 }
 
 int git_transport_smart_credentials(git_credential **out, git_transport *transport, const char *user, int methods)
 {
        transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
+       git_remote_connect_options *connect_opts = &t->connect_opts;
 
        GIT_ASSERT_ARG(out);
        GIT_ASSERT_ARG(transport);
 
-       if (!t->cred_acquire_cb)
+       if (!connect_opts->callbacks.credentials)
                return GIT_PASSTHROUGH;
 
-       return t->cred_acquire_cb(out, t->url, user, methods, t->cred_acquire_payload);
-}
-
-int git_transport_smart_proxy_options(git_proxy_options *out, git_transport *transport)
-{
-       transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
-       return git_proxy_options_dup(out, &t->proxy);
+       return connect_opts->callbacks.credentials(out, t->url, user, methods, connect_opts->callbacks.payload);
 }
 
 int git_transport_smart(git_transport **out, git_remote *owner, void *param)
@@ -524,9 +437,9 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param)
        GIT_ERROR_CHECK_ALLOC(t);
 
        t->parent.version = GIT_TRANSPORT_VERSION;
-       t->parent.set_callbacks = git_smart__set_callbacks;
-       t->parent.set_custom_headers = git_smart__set_custom_headers;
        t->parent.connect = git_smart__connect;
+       t->parent.set_connect_opts = git_smart__set_connect_opts;
+       t->parent.capabilities = git_smart__capabilities;
        t->parent.close = git_smart__close;
        t->parent.free = git_smart__free;
        t->parent.negotiate_fetch = git_smart__negotiate_fetch;
@@ -534,7 +447,6 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param)
        t->parent.push = git_smart__push;
        t->parent.ls = git_smart__ls;
        t->parent.is_connected = git_smart__is_connected;
-       t->parent.read_flags = git_smart__read_flags;
        t->parent.cancel = git_smart__cancel;
 
        t->owner = owner;
index a05d4c9e3a287107eac80e9858c70061bd193b58..9323d6c444e372d7edc9942d54337861e4fb1ed9 100644 (file)
@@ -12,8 +12,8 @@
 #include "git2.h"
 #include "vector.h"
 #include "netops.h"
-#include "buffer.h"
 #include "push.h"
+#include "str.h"
 #include "git2/sys/transport.h"
 
 #define GIT_SIDE_BAND_DATA     1
@@ -30,6 +30,8 @@
 #define GIT_CAP_REPORT_STATUS "report-status"
 #define GIT_CAP_THIN_PACK "thin-pack"
 #define GIT_CAP_SYMREF "symref"
+#define GIT_CAP_WANT_TIP_SHA1 "allow-tip-sha1-in-want"
+#define GIT_CAP_WANT_REACHABLE_SHA1 "allow-reachable-sha1-in-want"
 
 extern bool git_smart__ofs_delta_enabled;
 
@@ -46,7 +48,7 @@ typedef enum {
        GIT_PKT_PROGRESS,
        GIT_PKT_OK,
        GIT_PKT_NG,
-       GIT_PKT_UNPACK,
+       GIT_PKT_UNPACK
 } git_pkt_type;
 
 /* Used for multi_ack and multi_ack_detailed */
@@ -119,16 +121,18 @@ typedef struct {
 } git_pkt_unpack;
 
 typedef struct transport_smart_caps {
-       int common:1,
-               ofs_delta:1,
-               multi_ack: 1,
-               multi_ack_detailed: 1,
-               side_band:1,
-               side_band_64k:1,
-               include_tag:1,
-               delete_refs:1,
-               report_status:1,
-               thin_pack:1;
+       unsigned int common:1,
+                    ofs_delta:1,
+                    multi_ack:1,
+                    multi_ack_detailed:1,
+                    side_band:1,
+                    side_band_64k:1,
+                    include_tag:1,
+                    delete_refs:1,
+                    report_status:1,
+                    thin_pack:1,
+                    want_tip_sha1:1,
+                    want_reachable_sha1:1;
 } transport_smart_caps;
 
 typedef int (*packetsize_cb)(size_t received, void *payload);
@@ -137,16 +141,8 @@ typedef struct {
        git_transport parent;
        git_remote *owner;
        char *url;
-       git_credential_acquire_cb cred_acquire_cb;
-       void *cred_acquire_payload;
-       git_proxy_options proxy;
+       git_remote_connect_options connect_opts;
        int direction;
-       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_strarray custom_headers;
        git_smart_subtransport *wrapped;
        git_smart_subtransport_stream *current_stream;
        transport_smart_caps caps;
@@ -157,8 +153,8 @@ typedef struct {
        packetsize_cb packetsize_cb;
        void *packetsize_payload;
        unsigned rpc : 1,
-               have_refs : 1,
-               connected : 1;
+                have_refs : 1,
+                connected : 1;
        gitno_buffer buffer;
        char buffer_data[65536];
 } transport_smart;
@@ -166,7 +162,7 @@ typedef struct {
 /* smart_protocol.c */
 int git_smart__store_refs(transport_smart *t, int flushes);
 int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps, git_vector *symrefs);
-int git_smart__push(git_transport *transport, git_push *push, const git_remote_callbacks *cbs);
+int git_smart__push(git_transport *transport, git_push *push);
 
 int git_smart__negotiate_fetch(
        git_transport *transport,
@@ -177,9 +173,7 @@ int git_smart__negotiate_fetch(
 int git_smart__download_pack(
        git_transport *transport,
        git_repository *repo,
-       git_indexer_progress *stats,
-       git_indexer_progress_cb progress_cb,
-       void *progress_payload);
+       git_indexer_progress *stats);
 
 /* smart.c */
 int git_smart__negotiation_step(git_transport *transport, void *data, size_t len);
@@ -189,11 +183,11 @@ int git_smart__update_heads(transport_smart *t, git_vector *symrefs);
 
 /* smart_pkt.c */
 int git_pkt_parse_line(git_pkt **head, const char **endptr, const char *line, size_t linelen);
-int git_pkt_buffer_flush(git_buf *buf);
+int git_pkt_buffer_flush(git_str *buf);
 int git_pkt_send_flush(GIT_SOCKET s);
-int git_pkt_buffer_done(git_buf *buf);
-int git_pkt_buffer_wants(const git_remote_head * const *refs, size_t count, transport_smart_caps *caps, git_buf *buf);
-int git_pkt_buffer_have(git_oid *oid, git_buf *buf);
+int git_pkt_buffer_done(git_str *buf);
+int git_pkt_buffer_wants(const git_remote_head * const *refs, size_t count, transport_smart_caps *caps, git_str *buf);
+int git_pkt_buffer_have(git_oid *oid, git_str *buf);
 void git_pkt_free(git_pkt *pkt);
 
 #endif
index 56b680d281eebda52a27adab2d0f0076a71335d3..b42edd0d6e55abfc2cb7e57fba2c1a2b7e24b695 100644 (file)
@@ -7,16 +7,16 @@
 
 #include "common.h"
 
-#include "git2/types.h"
-#include "git2/errors.h"
-#include "git2/refs.h"
-#include "git2/revwalk.h"
-
 #include "smart.h"
 #include "util.h"
 #include "netops.h"
 #include "posix.h"
-#include "buffer.h"
+#include "str.h"
+
+#include "git2/types.h"
+#include "git2/errors.h"
+#include "git2/refs.h"
+#include "git2/revwalk.h"
 
 #include <ctype.h>
 
@@ -522,43 +522,43 @@ void git_pkt_free(git_pkt *pkt)
        git__free(pkt);
 }
 
-int git_pkt_buffer_flush(git_buf *buf)
+int git_pkt_buffer_flush(git_str *buf)
 {
-       return git_buf_put(buf, pkt_flush_str, strlen(pkt_flush_str));
+       return git_str_put(buf, pkt_flush_str, strlen(pkt_flush_str));
 }
 
-static int buffer_want_with_caps(const git_remote_head *head, transport_smart_caps *caps, git_buf *buf)
+static int buffer_want_with_caps(const git_remote_head *head, transport_smart_caps *caps, git_str *buf)
 {
-       git_buf str = GIT_BUF_INIT;
+       git_str str = GIT_STR_INIT;
        char oid[GIT_OID_HEXSZ +1] = {0};
        size_t len;
 
        /* Prefer multi_ack_detailed */
        if (caps->multi_ack_detailed)
-               git_buf_puts(&str, GIT_CAP_MULTI_ACK_DETAILED " ");
+               git_str_puts(&str, GIT_CAP_MULTI_ACK_DETAILED " ");
        else if (caps->multi_ack)
-               git_buf_puts(&str, GIT_CAP_MULTI_ACK " ");
+               git_str_puts(&str, GIT_CAP_MULTI_ACK " ");
 
        /* Prefer side-band-64k if the server supports both */
        if (caps->side_band_64k)
-               git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND_64K);
+               git_str_printf(&str, "%s ", GIT_CAP_SIDE_BAND_64K);
        else if (caps->side_band)
-               git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND);
+               git_str_printf(&str, "%s ", GIT_CAP_SIDE_BAND);
 
        if (caps->include_tag)
-               git_buf_puts(&str, GIT_CAP_INCLUDE_TAG " ");
+               git_str_puts(&str, GIT_CAP_INCLUDE_TAG " ");
 
        if (caps->thin_pack)
-               git_buf_puts(&str, GIT_CAP_THIN_PACK " ");
+               git_str_puts(&str, GIT_CAP_THIN_PACK " ");
 
        if (caps->ofs_delta)
-               git_buf_puts(&str, GIT_CAP_OFS_DELTA " ");
+               git_str_puts(&str, GIT_CAP_OFS_DELTA " ");
 
-       if (git_buf_oom(&str))
+       if (git_str_oom(&str))
                return -1;
 
        len = strlen("XXXXwant ") + GIT_OID_HEXSZ + 1 /* NUL */ +
-                git_buf_len(&str) + 1 /* LF */;
+                git_str_len(&str) + 1 /* LF */;
 
        if (len > 0xffff) {
                git_error_set(GIT_ERROR_NET,
@@ -566,13 +566,13 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca
                return -1;
        }
 
-       git_buf_grow_by(buf, len);
+       git_str_grow_by(buf, len);
        git_oid_fmt(oid, &head->oid);
-       git_buf_printf(buf,
-               "%04xwant %s %s\n", (unsigned int)len, oid, git_buf_cstr(&str));
-       git_buf_dispose(&str);
+       git_str_printf(buf,
+               "%04xwant %s %s\n", (unsigned int)len, oid, git_str_cstr(&str));
+       git_str_dispose(&str);
 
-       GIT_ERROR_CHECK_ALLOC_BUF(buf);
+       GIT_ERROR_CHECK_ALLOC_STR(buf);
 
        return 0;
 }
@@ -586,7 +586,7 @@ int git_pkt_buffer_wants(
        const git_remote_head * const *refs,
        size_t count,
        transport_smart_caps *caps,
-       git_buf *buf)
+       git_str *buf)
 {
        size_t i = 0;
        const git_remote_head *head;
@@ -612,26 +612,26 @@ int git_pkt_buffer_wants(
                        continue;
 
                git_oid_fmt(oid, &head->oid);
-               git_buf_put(buf, pkt_want_prefix, strlen(pkt_want_prefix));
-               git_buf_put(buf, oid, GIT_OID_HEXSZ);
-               git_buf_putc(buf, '\n');
-               if (git_buf_oom(buf))
+               git_str_put(buf, pkt_want_prefix, strlen(pkt_want_prefix));
+               git_str_put(buf, oid, GIT_OID_HEXSZ);
+               git_str_putc(buf, '\n');
+               if (git_str_oom(buf))
                        return -1;
        }
 
        return git_pkt_buffer_flush(buf);
 }
 
-int git_pkt_buffer_have(git_oid *oid, git_buf *buf)
+int git_pkt_buffer_have(git_oid *oid, git_str *buf)
 {
        char oidhex[GIT_OID_HEXSZ + 1];
 
        memset(oidhex, 0x0, sizeof(oidhex));
        git_oid_fmt(oidhex, oid);
-       return git_buf_printf(buf, "%s%s\n", pkt_have_prefix, oidhex);
+       return git_str_printf(buf, "%s%s\n", pkt_have_prefix, oidhex);
 }
 
-int git_pkt_buffer_done(git_buf *buf)
+int git_pkt_buffer_done(git_str *buf)
 {
-       return git_buf_puts(buf, pkt_done_str);
+       return git_str_puts(buf, pkt_done_str);
 }
index 91de163e91f23636142c234b0d37bbe7f5aa2ac8..8cf027133e45eb1d1e8282182ad606e9419acae2 100644 (file)
@@ -89,7 +89,7 @@ static int append_symref(const char **out, git_vector *symrefs, const char *ptr)
 {
        int error;
        const char *end;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_refspec *mapping = NULL;
 
        ptr += strlen(GIT_CAP_SYMREF);
@@ -101,15 +101,15 @@ static int append_symref(const char **out, git_vector *symrefs, const char *ptr)
            !(end = strchr(ptr, '\0')))
                goto on_invalid;
 
-       if ((error = git_buf_put(&buf, ptr, end - ptr)) < 0)
+       if ((error = git_str_put(&buf, ptr, end - ptr)) < 0)
                return error;
 
        /* symref mapping has refspec format */
        mapping = git__calloc(1, sizeof(git_refspec));
        GIT_ERROR_CHECK_ALLOC(mapping);
 
-       error = git_refspec__parse(mapping, git_buf_cstr(&buf), true);
-       git_buf_dispose(&buf);
+       error = git_refspec__parse(mapping, git_str_cstr(&buf), true);
+       git_str_dispose(&buf);
 
        /* if the error isn't OOM, then it's a parse error; let's use a nicer message */
        if (error < 0) {
@@ -137,7 +137,7 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps, git_vec
 {
        const char *ptr;
 
-       /* No refs or capabilites, odd but not a problem */
+       /* No refs or capabilities, odd but not a problem */
        if (pkt == NULL || pkt->capabilities == NULL)
                return GIT_ENOTFOUND;
 
@@ -205,6 +205,18 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps, git_vec
                        continue;
                }
 
+               if (!git__prefixcmp(ptr, GIT_CAP_WANT_TIP_SHA1)) {
+                       caps->common = caps->want_tip_sha1 = 1;
+                       ptr += strlen(GIT_CAP_DELETE_REFS);
+                       continue;
+               }
+
+               if (!git__prefixcmp(ptr, GIT_CAP_WANT_REACHABLE_SHA1)) {
+                       caps->common = caps->want_reachable_sha1 = 1;
+                       ptr += strlen(GIT_CAP_DELETE_REFS);
+                       continue;
+               }
+
                /* We don't know this capability, so skip it */
                ptr = strchr(ptr, ' ');
        }
@@ -310,7 +322,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
        transport_smart *t = (transport_smart *)transport;
        git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
        gitno_buffer *buf = &t->buffer;
-       git_buf data = GIT_BUF_INIT;
+       git_str data = GIT_STR_INIT;
        git_revwalk *walk = NULL;
        int error = -1;
        git_pkt_type pkt_type;
@@ -354,7 +366,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
                        }
 
                        git_pkt_buffer_flush(&data);
-                       if (git_buf_oom(&data)) {
+                       if (git_str_oom(&data)) {
                                error = -1;
                                goto on_error;
                        }
@@ -362,7 +374,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
                        if ((error = git_smart__negotiation_step(&t->parent, data.ptr, data.size)) < 0)
                                goto on_error;
 
-                       git_buf_clear(&data);
+                       git_str_clear(&data);
                        if (t->caps.multi_ack || t->caps.multi_ack_detailed) {
                                if ((error = store_common(t)) < 0)
                                        goto on_error;
@@ -397,7 +409,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
                                        goto on_error;
                        }
 
-                       if (git_buf_oom(&data)) {
+                       if (git_str_oom(&data)) {
                                error = -1;
                                goto on_error;
                        }
@@ -417,7 +429,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
                                goto on_error;
                }
 
-               if (git_buf_oom(&data)) {
+               if (git_str_oom(&data)) {
                        error = -1;
                        goto on_error;
                }
@@ -434,7 +446,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
        if ((error = git_smart__negotiation_step(&t->parent, data.ptr, data.size)) < 0)
                goto on_error;
 
-       git_buf_dispose(&data);
+       git_str_dispose(&data);
        git_revwalk_free(walk);
 
        /* Now let's eat up whatever the server gives us */
@@ -454,7 +466,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
 
 on_error:
        git_revwalk_free(walk);
-       git_buf_dispose(&data);
+       git_str_dispose(&data);
        return error;
 }
 
@@ -512,9 +524,7 @@ static int network_packetsize(size_t received, void *payload)
 int git_smart__download_pack(
        git_transport *transport,
        git_repository *repo,
-       git_indexer_progress *stats,
-       git_indexer_progress_cb progress_cb,
-       void *progress_payload)
+       git_indexer_progress *stats)
 {
        transport_smart *t = (transport_smart *)transport;
        gitno_buffer *buf = &t->buffer;
@@ -523,6 +533,9 @@ int git_smart__download_pack(
        int error = 0;
        struct network_packetsize_payload npp = {0};
 
+       git_indexer_progress_cb progress_cb = t->connect_opts.callbacks.transfer_progress;
+       void *progress_payload = t->connect_opts.callbacks.payload;
+
        memset(stats, 0, sizeof(git_indexer_progress));
 
        if (progress_cb) {
@@ -568,7 +581,7 @@ int git_smart__download_pack(
                                git_error_clear();
                                error = GIT_EUSER;
                        } else if (pkt->type == GIT_PKT_PROGRESS) {
-                               if (t->progress_cb) {
+                               if (t->connect_opts.callbacks.sideband_progress) {
                                        git_pkt_progress *p = (git_pkt_progress *) pkt;
 
                                        if (p->len > INT_MAX) {
@@ -577,7 +590,7 @@ int git_smart__download_pack(
                                                goto done;
                                        }
 
-                                       error = t->progress_cb(p->data, (int)p->len, t->message_cb_payload);
+                                       error = t->connect_opts.callbacks.sideband_progress(p->data, (int)p->len, t->connect_opts.callbacks.payload);
                                }
                        } else if (pkt->type == GIT_PKT_DATA) {
                                git_pkt_data *p = (git_pkt_data *) pkt;
@@ -626,7 +639,7 @@ done:
        return error;
 }
 
-static int gen_pktline(git_buf *buf, git_push *push)
+static int gen_pktline(git_str *buf, git_push *push)
 {
        push_spec *spec;
        size_t i, len;
@@ -647,24 +660,24 @@ static int gen_pktline(git_buf *buf, git_push *push)
                git_oid_fmt(old_id, &spec->roid);
                git_oid_fmt(new_id, &spec->loid);
 
-               git_buf_printf(buf, "%04"PRIxZ"%s %s %s", len, old_id, new_id, spec->refspec.dst);
+               git_str_printf(buf, "%04"PRIxZ"%s %s %s", len, old_id, new_id, spec->refspec.dst);
 
                if (i == 0) {
-                       git_buf_putc(buf, '\0');
+                       git_str_putc(buf, '\0');
                        /* Core git always starts their capabilities string with a space */
                        if (push->report_status) {
-                               git_buf_putc(buf, ' ');
-                               git_buf_printf(buf, GIT_CAP_REPORT_STATUS);
+                               git_str_putc(buf, ' ');
+                               git_str_printf(buf, GIT_CAP_REPORT_STATUS);
                        }
-                       git_buf_putc(buf, ' ');
-                       git_buf_printf(buf, GIT_CAP_SIDE_BAND_64K);
+                       git_str_putc(buf, ' ');
+                       git_str_printf(buf, GIT_CAP_SIDE_BAND_64K);
                }
 
-               git_buf_putc(buf, '\n');
+               git_str_putc(buf, '\n');
        }
 
-       git_buf_puts(buf, "0000");
-       return git_buf_oom(buf) ? -1 : 0;
+       git_str_puts(buf, "0000");
+       return git_str_oom(buf) ? -1 : 0;
 }
 
 static int add_push_report_pkt(git_push *push, git_pkt *pkt)
@@ -707,7 +720,7 @@ static int add_push_report_pkt(git_push *push, git_pkt *pkt)
        return 0;
 }
 
-static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt, git_buf *data_pkt_buf)
+static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt, git_str *data_pkt_buf)
 {
        git_pkt *pkt;
        const char *line, *line_end = NULL;
@@ -718,7 +731,7 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt,
        if (reading_from_buf) {
                /* We had an existing partial packet, so add the new
                 * packet to the buffer and parse the whole thing */
-               git_buf_put(data_pkt_buf, data_pkt->data, data_pkt->len);
+               git_str_put(data_pkt_buf, data_pkt->data, data_pkt->len);
                line = data_pkt_buf->ptr;
                line_len = data_pkt_buf->size;
        }
@@ -734,7 +747,7 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt,
                        /* Buffer the data when the inner packet is split
                         * across multiple sideband packets */
                        if (!reading_from_buf)
-                               git_buf_put(data_pkt_buf, line, line_len);
+                               git_str_put(data_pkt_buf, line, line_len);
                        error = 0;
                        goto done;
                }
@@ -757,7 +770,7 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt,
 
 done:
        if (reading_from_buf)
-               git_buf_consume(data_pkt_buf, line_end);
+               git_str_consume(data_pkt_buf, line_end);
        return error;
 }
 
@@ -767,7 +780,7 @@ static int parse_report(transport_smart *transport, git_push *push)
        const char *line_end = NULL;
        gitno_buffer *buf = &transport->buffer;
        int error, recvd;
-       git_buf data_pkt_buf = GIT_BUF_INIT;
+       git_str data_pkt_buf = GIT_STR_INIT;
 
        for (;;) {
                if (buf->offset > 0)
@@ -811,7 +824,7 @@ static int parse_report(transport_smart *transport, git_push *push)
                                error = -1;
                                break;
                        case GIT_PKT_PROGRESS:
-                               if (transport->progress_cb) {
+                               if (transport->connect_opts.callbacks.sideband_progress) {
                                        git_pkt_progress *p = (git_pkt_progress *) pkt;
 
                                        if (p->len > INT_MAX) {
@@ -820,7 +833,7 @@ static int parse_report(transport_smart *transport, git_push *push)
                                                goto done;
                                        }
 
-                                       error = transport->progress_cb(p->data, (int)p->len, transport->message_cb_payload);
+                                       error = transport->connect_opts.callbacks.sideband_progress(p->data, (int)p->len, transport->connect_opts.callbacks.payload);
                                }
                                break;
                        default:
@@ -847,7 +860,7 @@ static int parse_report(transport_smart *transport, git_push *push)
                }
        }
 done:
-       git_buf_dispose(&data_pkt_buf);
+       git_str_dispose(&data_pkt_buf);
        return error;
 }
 
@@ -987,11 +1000,12 @@ static int stream_thunk(void *buf, size_t size, void *data)
        return error;
 }
 
-int git_smart__push(git_transport *transport, git_push *push, const git_remote_callbacks *cbs)
+int git_smart__push(git_transport *transport, git_push *push)
 {
        transport_smart *t = (transport_smart *)transport;
+       git_remote_callbacks *cbs = &t->connect_opts.callbacks;
        struct push_packbuilder_payload packbuilder_payload = {0};
-       git_buf pktline = GIT_BUF_INIT;
+       git_str pktline = GIT_STR_INIT;
        int error = 0, need_pack = 0;
        push_spec *spec;
        unsigned int i;
@@ -1034,9 +1048,13 @@ int git_smart__push(git_transport *transport, git_push *push, const git_remote_c
                }
        }
 
+       /* prepare pack before sending pack header to avoid timeouts */
+       if (need_pack && ((error = git_packbuilder__prepare(push->pb))) < 0)
+               goto done;
+
        if ((error = git_smart__get_push_stream(t, &packbuilder_payload.stream)) < 0 ||
                (error = gen_pktline(&pktline, push)) < 0 ||
-               (error = packbuilder_payload.stream->write(packbuilder_payload.stream, git_buf_cstr(&pktline), git_buf_len(&pktline))) < 0)
+               (error = packbuilder_payload.stream->write(packbuilder_payload.stream, git_str_cstr(&pktline), git_str_len(&pktline))) < 0)
                goto done;
 
        if (need_pack &&
@@ -1071,6 +1089,6 @@ int git_smart__push(git_transport *transport, git_push *push, const git_remote_c
        }
 
 done:
-       git_buf_dispose(&pktline);
+       git_str_dispose(&pktline);
        return error;
 }
index 1b00be79cd6bc04030a9b322526d58cd391a2c5c..89f085230a359d4c12dcae9f2879c06dae1803b7 100644 (file)
@@ -12,8 +12,6 @@
 #endif
 
 #include "runtime.h"
-#include "git2.h"
-#include "buffer.h"
 #include "net.h"
 #include "netops.h"
 #include "smart.h"
@@ -26,8 +24,6 @@
 
 #define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport)
 
-static const char *ssh_prefixes[] = { "ssh://", "ssh+git://", "git+ssh://" };
-
 static const char cmd_uploadpack[] = "git-upload-pack";
 static const char cmd_receivepack[] = "git-receive-pack";
 
@@ -37,7 +33,7 @@ typedef struct {
        LIBSSH2_SESSION *session;
        LIBSSH2_CHANNEL *channel;
        const char *cmd;
-       char *url;
+       git_net_url url;
        unsigned sent_command : 1;
 } ssh_stream;
 
@@ -65,42 +61,26 @@ static void ssh_error(LIBSSH2_SESSION *session, const char *errmsg)
  *
  * For example: git-upload-pack '/libgit2/libgit2'
  */
-static int gen_proto(git_buf *request, const char *cmd, const char *url)
+static int gen_proto(git_str *request, const char *cmd, git_net_url *url)
 {
        const char *repo;
-       int len;
-       size_t i;
-
-       for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
-               const char *p = ssh_prefixes[i];
 
-               if (!git__prefixcmp(url, p)) {
-                       url = url + strlen(p);
-                       repo = strchr(url, '/');
-                       if (repo && repo[1] == '~')
-                               ++repo;
+       repo = url->path;
 
-                       goto done;
-               }
-       }
-       repo = strchr(url, ':');
-       if (repo) repo++;
+       if (repo && repo[0] == '/' && repo[1] == '~')
+               repo++;
 
-done:
-       if (!repo) {
+       if (!repo || !repo[0]) {
                git_error_set(GIT_ERROR_NET, "malformed git protocol URL");
                return -1;
        }
 
-       len = strlen(cmd) + 1 /* Space */ + 1 /* Quote */ + strlen(repo) + 1 /* Quote */ + 1;
-
-       git_buf_grow(request, len);
-       git_buf_puts(request, cmd);
-       git_buf_puts(request, " '");
-       git_buf_decode_percent(request, repo, strlen(repo));
-       git_buf_puts(request, "'");
+       git_str_puts(request, cmd);
+       git_str_puts(request, " '");
+       git_str_puts(request, repo);
+       git_str_puts(request, "'");
 
-       if (git_buf_oom(request))
+       if (git_str_oom(request))
                return -1;
 
        return 0;
@@ -109,9 +89,9 @@ done:
 static int send_command(ssh_stream *s)
 {
        int error;
-       git_buf request = GIT_BUF_INIT;
+       git_str request = GIT_STR_INIT;
 
-       error = gen_proto(&request, s->cmd, s->url);
+       error = gen_proto(&request, s->cmd, &s->url);
        if (error < 0)
                goto cleanup;
 
@@ -124,7 +104,7 @@ static int send_command(ssh_stream *s)
        s->sent_command = 1;
 
 cleanup:
-       git_buf_dispose(&request);
+       git_str_dispose(&request);
        return error;
 }
 
@@ -226,13 +206,12 @@ static void ssh_stream_free(git_smart_subtransport_stream *stream)
                s->io = NULL;
        }
 
-       git__free(s->url);
+       git_net_url_dispose(&s->url);
        git__free(s);
 }
 
 static int ssh_stream_alloc(
        ssh_subtransport *t,
-       const char *url,
        const char *cmd,
        git_smart_subtransport_stream **stream)
 {
@@ -250,47 +229,10 @@ static int ssh_stream_alloc(
 
        s->cmd = cmd;
 
-       s->url = git__strdup(url);
-       if (!s->url) {
-               git__free(s);
-               return -1;
-       }
-
        *stream = &s->parent;
        return 0;
 }
 
-static int git_ssh_extract_url_parts(
-       git_net_url *urldata,
-       const char *url)
-{
-       char *colon, *at;
-       const char *start;
-
-       colon = strchr(url, ':');
-
-
-       at = strchr(url, '@');
-       if (at) {
-               start = at + 1;
-               urldata->username = git__substrdup(url, at - url);
-               GIT_ERROR_CHECK_ALLOC(urldata->username);
-       } else {
-               start = url;
-               urldata->username = NULL;
-       }
-
-       if (colon == NULL || (colon < start)) {
-               git_error_set(GIT_ERROR_NET, "malformed URL");
-               return -1;
-       }
-
-       urldata->host = git__substrdup(start, colon - start);
-       GIT_ERROR_CHECK_ALLOC(urldata->host);
-
-       return 0;
-}
-
 static int ssh_agent_auth(LIBSSH2_SESSION *session, git_credential_ssh_key *c) {
        int rc = LIBSSH2_ERROR_NONE;
 
@@ -443,11 +385,15 @@ static int request_creds(git_credential **out, ssh_subtransport *t, const char *
        int error, no_callback = 0;
        git_credential *cred = NULL;
 
-       if (!t->owner->cred_acquire_cb) {
+       if (!t->owner->connect_opts.callbacks.credentials) {
                no_callback = 1;
        } else {
-               error = t->owner->cred_acquire_cb(&cred, t->owner->url, user, auth_methods,
-                                                 t->owner->cred_acquire_payload);
+               error = t->owner->connect_opts.callbacks.credentials(
+                       &cred,
+                       t->owner->url,
+                       user,
+                       auth_methods,
+                       t->owner->connect_opts.callbacks.payload);
 
                if (error == GIT_PASSTHROUGH) {
                        no_callback = 1;
@@ -516,9 +462,7 @@ static int _git_ssh_setup_conn(
        const char *cmd,
        git_smart_subtransport_stream **stream)
 {
-       git_net_url urldata = GIT_NET_URL_INIT;
        int auth_methods, error = 0;
-       size_t i;
        ssh_stream *s;
        git_credential *cred = NULL;
        LIBSSH2_SESSION *session=NULL;
@@ -527,40 +471,29 @@ static int _git_ssh_setup_conn(
        t->current_stream = NULL;
 
        *stream = NULL;
-       if (ssh_stream_alloc(t, url, cmd, stream) < 0)
+       if (ssh_stream_alloc(t, cmd, stream) < 0)
                return -1;
 
        s = (ssh_stream *)*stream;
        s->session = NULL;
        s->channel = NULL;
 
-       for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
-               const char *p = ssh_prefixes[i];
-
-               if (!git__prefixcmp(url, p)) {
-                       if ((error = git_net_url_parse(&urldata, url)) < 0)
-                               goto done;
+       if (git_net_str_is_url(url))
+               error = git_net_url_parse(&s->url, url);
+       else
+               error = git_net_url_parse_scp(&s->url, url);
 
-                       goto post_extract;
-               }
-       }
-       if ((error = git_ssh_extract_url_parts(&urldata, url)) < 0)
+       if (error < 0)
                goto done;
 
-       if (urldata.port == NULL)
-               urldata.port = git__strdup(SSH_DEFAULT_PORT);
-
-       GIT_ERROR_CHECK_ALLOC(urldata.port);
-
-post_extract:
-       if ((error = git_socket_stream_new(&s->io, urldata.host, urldata.port)) < 0 ||
+       if ((error = git_socket_stream_new(&s->io, s->url.host, s->url.port)) < 0 ||
            (error = git_stream_connect(s->io)) < 0)
                goto done;
 
        if ((error = _git_ssh_session_create(&session, s->io)) < 0)
                goto done;
 
-       if (t->owner->certificate_check_cb != NULL) {
+       if (t->owner->connect_opts.callbacks.certificate_check != NULL) {
                git_cert_hostkey cert = {{ 0 }}, *cert_ptr;
                const char *key;
                size_t cert_len;
@@ -580,7 +513,7 @@ post_extract:
                                case LIBSSH2_HOSTKEY_TYPE_DSS:
                                        cert.raw_type = GIT_CERT_SSH_RAW_TYPE_DSS;
                                        break;
-                                       
+
 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_256
                                case LIBSSH2_HOSTKEY_TYPE_ECDSA_256:
                                        cert.raw_type = GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_256;
@@ -592,7 +525,7 @@ post_extract:
                                        cert.raw_type = GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_521;
                                        break;
 #endif
-                                       
+
 #ifdef LIBSSH2_HOSTKEY_TYPE_ED25519
                                case LIBSSH2_HOSTKEY_TYPE_ED25519:
                                        cert.raw_type = GIT_CERT_SSH_RAW_TYPE_KEY_ED25519;
@@ -634,7 +567,11 @@ post_extract:
 
                cert_ptr = &cert;
 
-               error = t->owner->certificate_check_cb((git_cert *) cert_ptr, 0, urldata.host, t->owner->message_cb_payload);
+               error = t->owner->connect_opts.callbacks.certificate_check(
+                       (git_cert *)cert_ptr,
+                       0,
+                       s->url.host,
+                       t->owner->connect_opts.callbacks.payload);
 
                if (error < 0 && error != GIT_PASSTHROUGH) {
                        if (!git_error_last())
@@ -645,21 +582,21 @@ post_extract:
        }
 
        /* we need the username to ask for auth methods */
-       if (!urldata.username) {
+       if (!s->url.username) {
                if ((error = request_creds(&cred, t, NULL, GIT_CREDENTIAL_USERNAME)) < 0)
                        goto done;
 
-               urldata.username = git__strdup(((git_credential_username *) cred)->username);
+               s->url.username = git__strdup(((git_credential_username *) cred)->username);
                cred->free(cred);
                cred = NULL;
-               if (!urldata.username)
+               if (!s->url.username)
                        goto done;
-       } else if (urldata.username && urldata.password) {
-               if ((error = git_credential_userpass_plaintext_new(&cred, urldata.username, urldata.password)) < 0)
+       } else if (s->url.username && s->url.password) {
+               if ((error = git_credential_userpass_plaintext_new(&cred, s->url.username, s->url.password)) < 0)
                        goto done;
        }
 
-       if ((error = list_auth_methods(&auth_methods, session, urldata.username)) < 0)
+       if ((error = list_auth_methods(&auth_methods, session, s->url.username)) < 0)
                goto done;
 
        error = GIT_EAUTH;
@@ -673,10 +610,10 @@ post_extract:
                        cred = NULL;
                }
 
-               if ((error = request_creds(&cred, t, urldata.username, auth_methods)) < 0)
+               if ((error = request_creds(&cred, t, s->url.username, auth_methods)) < 0)
                        goto done;
 
-               if (strcmp(urldata.username, git_credential_get_username(cred))) {
+               if (strcmp(s->url.username, git_credential_get_username(cred))) {
                        git_error_set(GIT_ERROR_SSH, "username does not match previous request");
                        error = -1;
                        goto done;
@@ -686,7 +623,7 @@ post_extract:
 
                if (error == GIT_EAUTH) {
                        /* refresh auth methods */
-                       if ((error = list_auth_methods(&auth_methods, session, urldata.username)) < 0)
+                       if ((error = list_auth_methods(&auth_methods, session, s->url.username)) < 0)
                                goto done;
                        else
                                error = GIT_EAUTH;
@@ -721,8 +658,6 @@ done:
        if (cred)
                cred->free(cred);
 
-       git_net_url_dispose(&urldata);
-
        return error;
 }
 
@@ -870,7 +805,7 @@ static int list_auth_methods(int *out, LIBSSH2_SESSION *session, const char *use
                        continue;
                }
 
-               /* Skipt it if we don't know it */
+               /* Skip it if we don't know it */
                ptr = strchr(ptr, ',');
        }
 
index f4801a4516b6384d5231297acc2ea85187be3375..8ec5b37c533ef8b9d75bb027e37ec46b71fae3ea 100644 (file)
@@ -11,8 +11,8 @@
 
 #include "git2.h"
 #include "git2/transport.h"
-#include "buffer.h"
 #include "posix.h"
+#include "str.h"
 #include "netops.h"
 #include "smart.h"
 #include "remote.h"
@@ -99,7 +99,7 @@ typedef enum {
        GIT_WINHTTP_AUTH_BASIC = 1,
        GIT_WINHTTP_AUTH_NTLM = 2,
        GIT_WINHTTP_AUTH_NEGOTIATE = 4,
-       GIT_WINHTTP_AUTH_DIGEST = 8,
+       GIT_WINHTTP_AUTH_DIGEST = 8
 } winhttp_authmechanism_t;
 
 typedef struct {
@@ -293,14 +293,14 @@ static int certificate_check(winhttp_stream *s, int valid)
        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) {
+       if (t->owner->connect_opts.callbacks.certificate_check == NULL && !valid) {
                if (!git_error_last())
                        git_error_set(GIT_ERROR_HTTP, "unknown certificate check failure");
 
                return GIT_ECERTIFICATE;
        }
 
-       if (t->owner->certificate_check_cb == NULL || git__strcmp(t->server.url.scheme, "https") != 0)
+       if (t->owner->connect_opts.callbacks.certificate_check == NULL || git__strcmp(t->server.url.scheme, "https") != 0)
                return 0;
 
        if (!WinHttpQueryOption(s->request, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert_ctx, &cert_ctx_size)) {
@@ -312,7 +312,7 @@ static int certificate_check(winhttp_stream *s, int valid)
        cert.parent.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->server.url.host, t->owner->message_cb_payload);
+       error = t->owner->connect_opts.callbacks.certificate_check((git_cert *) &cert, valid, t->server.url.host, t->owner->connect_opts.callbacks.payload);
        CertFreeCertificateContext(cert_ctx);
 
        if (error == GIT_PASSTHROUGH)
@@ -372,7 +372,7 @@ static int apply_credentials(
 static int winhttp_stream_connect(winhttp_stream *s)
 {
        winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        char *proxy_url = NULL;
        wchar_t ct[MAX_CONTENT_TYPE_LEN];
        LPCWSTR types[] = { L"*/*", NULL };
@@ -391,13 +391,13 @@ static int winhttp_stream_connect(winhttp_stream *s)
        if ((git__suffixcmp(t->server.url.path, "/") == 0) && (git__prefixcmp(service_url, "/") == 0))
                service_url++;
        /* Prepare URL */
-       git_buf_printf(&buf, "%s%s", t->server.url.path, service_url);
+       git_str_printf(&buf, "%s%s", t->server.url.path, service_url);
 
-       if (git_buf_oom(&buf))
+       if (git_str_oom(&buf))
                return -1;
 
        /* Convert URL to wide characters */
-       if (git__utf8_to_16_alloc(&s->request_uri, git_buf_cstr(&buf)) < 0) {
+       if (git__utf8_to_16_alloc(&s->request_uri, git_str_cstr(&buf)) < 0) {
                git_error_set(GIT_ERROR_OS, "failed to convert string to wide form");
                goto on_error;
        }
@@ -426,7 +426,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
                goto on_error;
        }
 
-       proxy_opts = &t->owner->proxy;
+       proxy_opts = &t->owner->connect_opts.proxy_opts;
        if (proxy_opts->type == GIT_PROXY_AUTO) {
                /* Set proxy if necessary */
                if (git_remote__http_proxy(&proxy_url, t->owner->owner, &t->server.url) < 0)
@@ -438,7 +438,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
        }
 
        if (proxy_url) {
-               git_buf processed_url = GIT_BUF_INIT;
+               git_str processed_url = GIT_STR_INIT;
                WINHTTP_PROXY_INFO proxy_info;
                wchar_t *proxy_wide;
 
@@ -453,28 +453,28 @@ static int winhttp_stream_connect(winhttp_stream *s)
                        goto on_error;
                }
 
-               git_buf_puts(&processed_url, t->proxy.url.scheme);
-               git_buf_PUTS(&processed_url, "://");
+               git_str_puts(&processed_url, t->proxy.url.scheme);
+               git_str_PUTS(&processed_url, "://");
 
                if (git_net_url_is_ipv6(&t->proxy.url))
-                       git_buf_putc(&processed_url, '[');
+                       git_str_putc(&processed_url, '[');
 
-               git_buf_puts(&processed_url, t->proxy.url.host);
+               git_str_puts(&processed_url, t->proxy.url.host);
 
                if (git_net_url_is_ipv6(&t->proxy.url))
-                       git_buf_putc(&processed_url, ']');
+                       git_str_putc(&processed_url, ']');
 
                if (!git_net_url_is_default_port(&t->proxy.url))
-                       git_buf_printf(&processed_url, ":%s", t->proxy.url.port);
+                       git_str_printf(&processed_url, ":%s", t->proxy.url.port);
 
-               if (git_buf_oom(&processed_url)) {
+               if (git_str_oom(&processed_url)) {
                        error = -1;
                        goto on_error;
                }
 
                /* Convert URL to wide characters */
                error = git__utf8_to_16_alloc(&proxy_wide, processed_url.ptr);
-               git_buf_dispose(&processed_url);
+               git_str_dispose(&processed_url);
                if (error < 0)
                        goto on_error;
 
@@ -525,13 +525,13 @@ static int winhttp_stream_connect(winhttp_stream *s)
 
        if (post_verb == s->verb) {
                /* Send Content-Type and Accept headers -- only necessary on a POST */
-               git_buf_clear(&buf);
-               if (git_buf_printf(&buf,
+               git_str_clear(&buf);
+               if (git_str_printf(&buf,
                        "Content-Type: application/x-git-%s-request",
                        s->service) < 0)
                        goto on_error;
 
-               if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
+               if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_str_cstr(&buf)) < 0) {
                        git_error_set(GIT_ERROR_OS, "failed to convert content-type to wide characters");
                        goto on_error;
                }
@@ -542,13 +542,13 @@ static int winhttp_stream_connect(winhttp_stream *s)
                        goto on_error;
                }
 
-               git_buf_clear(&buf);
-               if (git_buf_printf(&buf,
+               git_str_clear(&buf);
+               if (git_str_printf(&buf,
                        "Accept: application/x-git-%s-result",
                        s->service) < 0)
                        goto on_error;
 
-               if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
+               if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_str_cstr(&buf)) < 0) {
                        git_error_set(GIT_ERROR_OS, "failed to convert accept header to wide characters");
                        goto on_error;
                }
@@ -560,11 +560,11 @@ static int winhttp_stream_connect(winhttp_stream *s)
                }
        }
 
-       for (i = 0; i < t->owner->custom_headers.count; i++) {
-               if (t->owner->custom_headers.strings[i]) {
-                       git_buf_clear(&buf);
-                       git_buf_puts(&buf, t->owner->custom_headers.strings[i]);
-                       if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
+       for (i = 0; i < t->owner->connect_opts.custom_headers.count; i++) {
+               if (t->owner->connect_opts.custom_headers.strings[i]) {
+                       git_str_clear(&buf);
+                       git_str_puts(&buf, t->owner->connect_opts.custom_headers.strings[i]);
+                       if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_str_cstr(&buf)) < 0) {
                                git_error_set(GIT_ERROR_OS, "failed to convert custom header to wide characters");
                                goto on_error;
                        }
@@ -577,14 +577,6 @@ static int winhttp_stream_connect(winhttp_stream *s)
                }
        }
 
-       /* If requested, disable certificate validation */
-       if (strcmp(t->server.url.scheme, "https") == 0) {
-               int flags;
-
-               if (t->owner->parent.read_flags(&t->owner->parent, &flags) < 0)
-                       goto on_error;
-       }
-
        if ((error = apply_credentials(s->request, &t->server.url, WINHTTP_AUTH_TARGET_SERVER, t->server.cred, t->server.auth_mechanisms)) < 0)
                goto on_error;
 
@@ -597,7 +589,7 @@ on_error:
                winhttp_stream_close(s);
 
        git__free(proxy_url);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
@@ -646,23 +638,23 @@ static int parse_unauthorized_response(
 static int write_chunk(HINTERNET request, const char *buffer, size_t len)
 {
        DWORD bytes_written;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        /* Chunk header */
-       git_buf_printf(&buf, "%"PRIXZ"\r\n", len);
+       git_str_printf(&buf, "%"PRIXZ"\r\n", len);
 
-       if (git_buf_oom(&buf))
+       if (git_str_oom(&buf))
                return -1;
 
        if (!WinHttpWriteData(request,
-               git_buf_cstr(&buf),     (DWORD)git_buf_len(&buf),
+               git_str_cstr(&buf),     (DWORD)git_str_len(&buf),
                &bytes_written)) {
-               git_buf_dispose(&buf);
+               git_str_dispose(&buf);
                git_error_set(GIT_ERROR_OS, "failed to write chunk header");
                return -1;
        }
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        /* Chunk body */
        if (!WinHttpWriteData(request,
@@ -756,7 +748,7 @@ static int winhttp_connect(
        wchar_t *wide_host = NULL;
        int32_t port;
        wchar_t *wide_ua = NULL;
-       git_buf ipv6 = GIT_BUF_INIT, ua = GIT_BUF_INIT;
+       git_str ipv6 = GIT_STR_INIT, ua = GIT_STR_INIT;
        const char *host;
        int error = -1;
        int default_timeout = TIMEOUT_INFINITE;
@@ -777,7 +769,7 @@ static int winhttp_connect(
 
        /* IPv6? Add braces around the host. */
        if (git_net_url_is_ipv6(&t->server.url)) {
-               if (git_buf_printf(&ipv6, "[%s]", t->server.url.host) < 0)
+               if (git_str_printf(&ipv6, "[%s]", t->server.url.host) < 0)
                        goto on_error;
 
                host = ipv6.ptr;
@@ -795,7 +787,7 @@ static int winhttp_connect(
        if (git_http__user_agent(&ua) < 0)
                goto on_error;
 
-       if (git__utf8_to_16_alloc(&wide_ua, git_buf_cstr(&ua)) < 0) {
+       if (git__utf8_to_16_alloc(&wide_ua, git_str_cstr(&ua)) < 0) {
                git_error_set(GIT_ERROR_OS, "unable to convert host to wide characters");
                goto on_error;
        }
@@ -863,8 +855,8 @@ on_error:
        if (error < 0)
                winhttp_close_connection(t);
 
-       git_buf_dispose(&ua);
-       git_buf_dispose(&ipv6);
+       git_str_dispose(&ua);
+       git_str_dispose(&ipv6);
        git__free(wide_host);
        git__free(wide_ua);
 
@@ -1197,8 +1189,10 @@ replay:
                        winhttp_stream_close(s);
 
                        if (!git__prefixcmp_icase(location8, prefix_https)) {
+                               bool follow = (t->owner->connect_opts.follow_redirects != GIT_REMOTE_REDIRECT_NONE);
+
                                /* Upgrade to secure connection; disconnect and start over */
-                               if (git_net_url_apply_redirect(&t->server.url, location8, s->service_url) < 0) {
+                               if (git_net_url_apply_redirect(&t->server.url, location8, follow, s->service_url) < 0) {
                                        git__free(location8);
                                        return -1;
                                }
@@ -1218,8 +1212,8 @@ replay:
                        int error = acquire_credentials(s->request,
                                &t->server,
                                t->owner->url,
-                               t->owner->cred_acquire_cb,
-                               t->owner->cred_acquire_payload);
+                               t->owner->connect_opts.callbacks.credentials,
+                               t->owner->connect_opts.callbacks.payload);
 
                        if (error < 0) {
                                return error;
@@ -1231,9 +1225,9 @@ replay:
                } else if (status_code == HTTP_STATUS_PROXY_AUTH_REQ) {
                        int error = acquire_credentials(s->request,
                                &t->proxy,
-                               t->owner->proxy.url,
-                               t->owner->proxy.credentials,
-                               t->owner->proxy.payload);
+                               t->owner->connect_opts.proxy_opts.url,
+                               t->owner->connect_opts.proxy_opts.credentials,
+                               t->owner->connect_opts.proxy_opts.payload);
 
                        if (error < 0) {
                                return error;
index 04d86fd3691dfcf52b162b4a5dfc91af310c99fb..0977c92f331be52ea9338b209d2efb025855c2a3 100644 (file)
@@ -256,22 +256,22 @@ int git_tree_cache_new(git_tree_cache **out, const char *name, git_pool *pool)
        return 0;
 }
 
-static void write_tree(git_buf *out, git_tree_cache *tree)
+static void write_tree(git_str *out, git_tree_cache *tree)
 {
        size_t i;
 
-       git_buf_printf(out, "%s%c%"PRIdZ" %"PRIuZ"\n", tree->name, 0, tree->entry_count, tree->children_count);
+       git_str_printf(out, "%s%c%"PRIdZ" %"PRIuZ"\n", tree->name, 0, tree->entry_count, tree->children_count);
 
        if (tree->entry_count != -1)
-               git_buf_put(out, (const char *) &tree->oid, GIT_OID_RAWSZ);
+               git_str_put(out, (const char *) &tree->oid, GIT_OID_RAWSZ);
 
        for (i = 0; i < tree->children_count; i++)
                write_tree(out, tree->children[i]);
 }
 
-int git_tree_cache_write(git_buf *out, git_tree_cache *tree)
+int git_tree_cache_write(git_str *out, git_tree_cache *tree)
 {
        write_tree(out, tree);
 
-       return git_buf_oom(out) ? -1 : 0;
+       return git_str_oom(out) ? -1 : 0;
 }
index e02300e6e1963803d1b98c227c1070fcffeed67e..a27e3046614539ef2a675fac9640a7d7b53289d5 100644 (file)
@@ -11,7 +11,7 @@
 #include "common.h"
 
 #include "pool.h"
-#include "buffer.h"
+#include "str.h"
 #include "git2/oid.h"
 
 typedef struct git_tree_cache {
@@ -24,7 +24,7 @@ typedef struct git_tree_cache {
        char name[GIT_FLEX_ARRAY];
 } git_tree_cache;
 
-int git_tree_cache_write(git_buf *out, git_tree_cache *tree);
+int git_tree_cache_write(git_str *out, git_tree_cache *tree);
 int git_tree_cache_read(git_tree_cache **tree, const char *buffer, size_t buffer_size, git_pool *pool);
 void git_tree_cache_invalidate_path(git_tree_cache *tree, const char *path);
 const git_tree_cache *git_tree_cache_get(const git_tree_cache *tree, const char *path);
index b1df79eacfcf9e417027f144d9637407b9b96429..a1545dc2decf4f6a1d25b4fc0bd7917e75dab613 100644 (file)
@@ -13,6 +13,7 @@
 #include "futils.h"
 #include "tree-cache.h"
 #include "index.h"
+#include "path.h"
 
 #define DEFAULT_TREE_SIZE 16
 #define MAX_FILEMODE_BYTES 6
@@ -54,8 +55,8 @@ GIT_INLINE(git_filemode_t) normalize_filemode(git_filemode_t filemode)
 static int valid_entry_name(git_repository *repo, const char *filename)
 {
        return *filename != '\0' &&
-               git_path_validate(repo, filename, 0,
-               GIT_PATH_REJECT_TRAVERSAL | GIT_PATH_REJECT_DOT_GIT | GIT_PATH_REJECT_SLASH);
+               git_path_is_valid(repo, filename, 0,
+               GIT_FS_PATH_REJECT_TRAVERSAL | GIT_PATH_REJECT_DOT_GIT | GIT_FS_PATH_REJECT_SLASH);
 }
 
 static int entry_sort_cmp(const void *a, const void *b)
@@ -63,7 +64,7 @@ static int entry_sort_cmp(const void *a, const void *b)
        const git_tree_entry *e1 = (const git_tree_entry *)a;
        const git_tree_entry *e2 = (const git_tree_entry *)b;
 
-       return git_path_cmp(
+       return git_fs_path_cmp(
                e1->filename, e1->filename_len, git_tree_entry__is_tree(e1),
                e2->filename, e2->filename_len, git_tree_entry__is_tree(e2),
                git__strncmp);
@@ -350,15 +351,26 @@ size_t git_treebuilder_entrycount(git_treebuilder *bld)
        return git_strmap_size(bld->map);
 }
 
-static int tree_error(const char *str, const char *path)
+GIT_INLINE(void) set_error(const char *str, const char *path)
 {
        if (path)
                git_error_set(GIT_ERROR_TREE, "%s - %s", str, path);
        else
                git_error_set(GIT_ERROR_TREE, "%s", str);
+}
+
+static int tree_error(const char *str, const char *path)
+{
+       set_error(str, path);
        return -1;
 }
 
+static int tree_parse_error(const char *str, const char *path)
+{
+       set_error(str, path);
+       return GIT_EINVALID;
+}
+
 static int parse_mode(uint16_t *mode_out, const char *buffer, size_t buffer_len, const char **buffer_out)
 {
        int32_t mode;
@@ -398,19 +410,19 @@ int git_tree__parse_raw(void *_tree, const char *data, size_t size)
                uint16_t attr;
 
                if (parse_mode(&attr, buffer, buffer_end - buffer, &buffer) < 0 || !buffer)
-                       return tree_error("failed to parse tree: can't parse filemode", NULL);
+                       return tree_parse_error("failed to parse tree: can't parse filemode", NULL);
 
                if (buffer >= buffer_end || (*buffer++) != ' ')
-                       return tree_error("failed to parse tree: missing space after filemode", NULL);
+                       return tree_parse_error("failed to parse tree: missing space after filemode", NULL);
 
                if ((nul = memchr(buffer, 0, buffer_end - buffer)) == NULL)
-                       return tree_error("failed to parse tree: object is corrupted", NULL);
+                       return tree_parse_error("failed to parse tree: object is corrupted", NULL);
 
                if ((filename_len = nul - buffer) == 0 || filename_len > UINT16_MAX)
-                       return tree_error("failed to parse tree: can't parse filename", NULL);
+                       return tree_parse_error("failed to parse tree: can't parse filename", NULL);
 
                if ((buffer_end - (nul + 1)) < GIT_OID_RAWSZ)
-                       return tree_error("failed to parse tree: can't parse OID", NULL);
+                       return tree_parse_error("failed to parse tree: can't parse OID", NULL);
 
                /* Allocate the entry */
                {
@@ -433,16 +445,15 @@ int git_tree__parse_raw(void *_tree, const char *data, size_t size)
 int git_tree__parse(void *_tree, git_odb_object *odb_obj)
 {
        git_tree *tree = _tree;
+       const char *data = git_odb_object_data(odb_obj);
+       size_t size = git_odb_object_size(odb_obj);
+       int error;
 
-       if ((git_tree__parse_raw(tree,
-           git_odb_object_data(odb_obj),
-           git_odb_object_size(odb_obj))) < 0)
-               return -1;
-
-       if (git_odb_object_dup(&tree->odb_obj, odb_obj) < 0)
-               return -1;
+       if ((error = git_tree__parse_raw(tree, data, size)) < 0 ||
+           (error = git_odb_object_dup(&tree->odb_obj, odb_obj)) < 0)
+               return error;
 
-       return 0;
+       return error;
 }
 
 static size_t find_next_dir(const char *dirname, git_index *index, size_t start)
@@ -495,7 +506,7 @@ static int check_entry(git_repository *repo, const char *filename, const git_oid
 static int git_treebuilder__write_with_buffer(
        git_oid *oid,
        git_treebuilder *bld,
-       git_buf *buf)
+       git_str *buf)
 {
        int error = 0;
        size_t i, entrycount;
@@ -503,14 +514,14 @@ static int git_treebuilder__write_with_buffer(
        git_tree_entry *entry;
        git_vector entries = GIT_VECTOR_INIT;
 
-       git_buf_clear(buf);
+       git_str_clear(buf);
 
        entrycount = git_strmap_size(bld->map);
        if ((error = git_vector_init(&entries, entrycount, entry_sort_cmp)) < 0)
                goto out;
 
        if (buf->asize == 0 &&
-           (error = git_buf_grow(buf, entrycount * 72)) < 0)
+           (error = git_str_grow(buf, entrycount * 72)) < 0)
                goto out;
 
        git_strmap_foreach_value(bld->map, entry, {
@@ -523,11 +534,11 @@ static int git_treebuilder__write_with_buffer(
        for (i = 0; i < entries.length && !error; ++i) {
                entry = git_vector_get(&entries, i);
 
-               git_buf_printf(buf, "%o ", entry->attr);
-               git_buf_put(buf, entry->filename, entry->filename_len + 1);
-               git_buf_put(buf, (char *)entry->oid->id, GIT_OID_RAWSZ);
+               git_str_printf(buf, "%o ", entry->attr);
+               git_str_put(buf, entry->filename, entry->filename_len + 1);
+               git_str_put(buf, (char *)entry->oid->id, GIT_OID_RAWSZ);
 
-               if (git_buf_oom(buf)) {
+               if (git_str_oom(buf)) {
                        error = -1;
                        goto out;
                }
@@ -575,7 +586,7 @@ static int write_tree(
        git_index *index,
        const char *dirname,
        size_t start,
-       git_buf *shared_buf)
+       git_str *shared_buf)
 {
        git_treebuilder *bld = NULL;
        size_t i, entries = git_index_entrycount(index);
@@ -594,7 +605,7 @@ static int write_tree(
 
        /*
         * This loop is unfortunate, but necessary. The index doesn't have
-        * any directores, so we need to handle that manually, and we
+        * any directories, so we need to handle that manually, and we
         * need to keep track of the current position.
         */
        for (i = start; i < entries; ++i) {
@@ -676,7 +687,7 @@ int git_tree__write_index(
 {
        int ret;
        git_tree *tree;
-       git_buf shared_buf = GIT_BUF_INIT;
+       git_str shared_buf = GIT_STR_INIT;
        bool old_ignore_case = false;
 
        GIT_ASSERT_ARG(oid);
@@ -705,7 +716,7 @@ int git_tree__write_index(
        }
 
        ret = write_tree(oid, repo, index, "", 0, &shared_buf);
-       git_buf_dispose(&shared_buf);
+       git_str_dispose(&shared_buf);
 
        if (old_ignore_case)
                git_index__set_ignore_case(index, true);
@@ -879,7 +890,7 @@ void git_treebuilder_free(git_treebuilder *bld)
        if (bld == NULL)
                return;
 
-       git_buf_dispose(&bld->write_cache);
+       git_str_dispose(&bld->write_cache);
        git_treebuilder_clear(bld);
        git_strmap_free(bld->map);
        git__free(bld);
@@ -959,7 +970,7 @@ int git_tree_entry_bypath(
 static int tree_walk(
        const git_tree *tree,
        git_treewalk_cb callback,
-       git_buf *path,
+       git_str *path,
        void *payload,
        bool preorder)
 {
@@ -982,17 +993,17 @@ static int tree_walk(
 
                if (git_tree_entry__is_tree(entry)) {
                        git_tree *subtree;
-                       size_t path_len = git_buf_len(path);
+                       size_t path_len = git_str_len(path);
 
                        error = git_tree_lookup(&subtree, tree->object.repo, entry->oid);
                        if (error < 0)
                                break;
 
                        /* append the next entry to the path */
-                       git_buf_puts(path, entry->filename);
-                       git_buf_putc(path, '/');
+                       git_str_puts(path, entry->filename);
+                       git_str_putc(path, '/');
 
-                       if (git_buf_oom(path))
+                       if (git_str_oom(path))
                                error = -1;
                        else
                                error = tree_walk(subtree, callback, path, payload, preorder);
@@ -1001,7 +1012,7 @@ static int tree_walk(
                        if (error != 0)
                                break;
 
-                       git_buf_truncate(path, path_len);
+                       git_str_truncate(path, path_len);
                }
 
                if (!preorder) {
@@ -1024,7 +1035,7 @@ int git_tree_walk(
        void *payload)
 {
        int error = 0;
-       git_buf root_path = GIT_BUF_INIT;
+       git_str root_path = GIT_STR_INIT;
 
        if (mode != GIT_TREEWALK_POST && mode != GIT_TREEWALK_PRE) {
                git_error_set(GIT_ERROR_INVALID, "invalid walking mode for tree walk");
@@ -1034,7 +1045,7 @@ int git_tree_walk(
        error = tree_walk(
                tree, callback, &root_path, payload, (mode == GIT_TREEWALK_PRE));
 
-       git_buf_dispose(&root_path);
+       git_str_dispose(&root_path);
 
        return error;
 }
@@ -1080,19 +1091,19 @@ GIT_INLINE(size_t) count_slashes(const char *path)
        return count;
 }
 
-static bool next_component(git_buf *out, const char *in)
+static bool next_component(git_str *out, const char *in)
 {
        const char *slash = strchr(in, '/');
 
-       git_buf_clear(out);
+       git_str_clear(out);
 
        if (slash)
-               git_buf_put(out, in, slash - in);
+               git_str_put(out, in, slash - in);
 
        return !!slash;
 }
 
-static int create_popped_tree(tree_stack_entry *current, tree_stack_entry *popped, git_buf *component)
+static int create_popped_tree(tree_stack_entry *current, tree_stack_entry *popped, git_str *component)
 {
        int error;
        git_oid new_tree;
@@ -1116,8 +1127,8 @@ static int create_popped_tree(tree_stack_entry *current, tree_stack_entry *poppe
        }
 
        /* We've written out the tree, now we have to put the new value into its parent */
-       git_buf_clear(component);
-       git_buf_puts(component, popped->name);
+       git_str_clear(component);
+       git_str_puts(component, popped->name);
        git__free(popped->name);
 
        GIT_ERROR_CHECK_ALLOC(component->ptr);
@@ -1142,7 +1153,7 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli
        git_vector entries;
        int error;
        size_t i;
-       git_buf component = GIT_BUF_INIT;
+       git_str component = GIT_STR_INIT;
 
        if ((error = git_vector_init(&entries, nupdates, compare_entries)) < 0)
                return error;
@@ -1171,7 +1182,7 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli
 
                /* Figure out how much we need to change from the previous tree */
                if (last_update)
-                       common_prefix = git_path_common_dirlen(last_update->path, update->path);
+                       common_prefix = git_fs_path_common_dirlen(last_update->path, update->path);
 
                /*
                 * The entries are sorted, so when we find we're no
@@ -1233,7 +1244,7 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli
                        {
                                /* Make sure we're replacing something of the same type */
                                tree_stack_entry *last = git_array_last(stack);
-                               char *basename = git_path_basename(update->path);
+                               char *basename = git_fs_path_basename(update->path);
                                const git_tree_entry *e = git_treebuilder_get(last->bld, basename);
                                if (e && git_tree_entry_type(e) != git_object__type_from_filemode(update->filemode)) {
                                        git__free(basename);
@@ -1252,7 +1263,7 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli
                        case GIT_TREE_UPDATE_REMOVE:
                        {
                                tree_stack_entry *last = git_array_last(stack);
-                               char *basename = git_path_basename(update->path);
+                               char *basename = git_fs_path_basename(update->path);
                                error = git_treebuilder_remove(last->bld, basename);
                                git__free(basename);
                                break;
@@ -1300,7 +1311,7 @@ cleanup:
                }
        }
 
-       git_buf_dispose(&component);
+       git_str_dispose(&component);
        git_array_clear(stack);
        git_vector_free(&entries);
        return error;
index 2f3027b5a273b3cb44dc9187f3e89e913af1acd3..6bd9ed65248c7d933a9ffca92d4ac3ca20543b36 100644 (file)
@@ -32,7 +32,7 @@ struct git_tree {
 struct git_treebuilder {
        git_repository *repo;
        git_strmap *map;
-       git_buf write_cache;
+       git_str write_cache;
 };
 
 GIT_INLINE(bool) git_tree_entry__is_tree(const struct git_tree_entry *e)
index 88f283ce815f00a535d7709762a0bc2db4638dd4..23fcb786e5ab3a4d396a78f92025c868bf760885 100644 (file)
@@ -7,8 +7,6 @@
 
 #include "common.h"
 
-#include "git2/common.h"
-
 #if !defined(GIT_WIN32) && !defined(NO_MMAP)
 
 #include "map.h"
index 7b3325e78176dd385690fde2acad469d1e00cf05..49065e5336c03585f37161051a054fa10cf377b3 100644 (file)
@@ -7,9 +7,7 @@
 #ifndef INCLUDE_unix_posix_h__
 #define INCLUDE_unix_posix_h__
 
-#ifndef LIBGIT2_NO_FEATURES_H
-# include "git2/sys/features.h"
-#endif
+#include "common.h"
 
 #include <stdio.h>
 #include <dirent.h>
@@ -60,7 +58,6 @@ GIT_INLINE(int) p_fsync(int fd)
 #define p_strncasecmp(s1, s2, c) strncasecmp(s1, s2, c)
 #define p_vsnprintf(b, c, f, a) vsnprintf(b, c, f, a)
 #define p_snprintf snprintf
-#define p_mkstemp(p) mkstemp(p)
 #define p_chdir(p) chdir(p)
 #define p_rmdir(p) rmdir(p)
 #define p_access(p,m) access(p,m)
index 893bac87b3697ec3b0e6cf19b4a316ddae930e97..f1ca669f74d10c8256e05fdfe4a4acda8711feb8 100644 (file)
@@ -7,8 +7,6 @@
 
 #include "common.h"
 
-#include "git2/common.h"
-
 #ifndef GIT_WIN32
 
 #include <limits.h>
index 9b0c45ce82573a759d6f9c46e8eed0f096d99aff..e06d4ca09131ee88bc0d704cc56361dc5ad1c8d5 100644 (file)
@@ -18,7 +18,7 @@
 # endif
 # include <windows.h>
 
-# ifdef HAVE_QSORT_S
+# ifdef GIT_QSORT_S
 #  include <search.h>
 # endif
 #endif
@@ -673,7 +673,7 @@ size_t git__unescape(char *str)
        return (pos - str);
 }
 
-#if defined(HAVE_QSORT_S) || defined(HAVE_QSORT_R_BSD)
+#if defined(GIT_QSORT_S) || defined(GIT_QSORT_R_BSD)
 typedef struct {
        git__sort_r_cmp cmp;
        void *payload;
@@ -688,9 +688,9 @@ static int GIT_LIBGIT2_CALL git__qsort_r_glue_cmp(
 #endif
 
 
-#if !defined(HAVE_QSORT_R_BSD) && \
-       !defined(HAVE_QSORT_R_GNU) && \
-       !defined(HAVE_QSORT_S)
+#if !defined(GIT_QSORT_R_BSD) && \
+       !defined(GIT_QSORT_R_GNU) && \
+       !defined(GIT_QSORT_S)
 static void swap(uint8_t *a, uint8_t *b, size_t elsize)
 {
        char tmp[256];
@@ -721,12 +721,12 @@ static void insertsort(
 void git__qsort_r(
        void *els, size_t nel, size_t elsize, git__sort_r_cmp cmp, void *payload)
 {
-#if defined(HAVE_QSORT_R_BSD)
+#if defined(GIT_QSORT_R_BSD)
        git__qsort_r_glue glue = { cmp, payload };
        qsort_r(els, nel, elsize, &glue, git__qsort_r_glue_cmp);
-#elif defined(HAVE_QSORT_R_GNU)
+#elif defined(GIT_QSORT_R_GNU)
        qsort_r(els, nel, elsize, cmp, payload);
-#elif defined(HAVE_QSORT_S)
+#elif defined(GIT_QSORT_S)
        git__qsort_r_glue glue = { cmp, payload };
        qsort_s(els, nel, elsize, git__qsort_r_glue_cmp, &glue);
 #else
@@ -735,13 +735,13 @@ void git__qsort_r(
 }
 
 #ifdef GIT_WIN32
-int git__getenv(git_buf *out, const char *name)
+int git__getenv(git_str *out, const char *name)
 {
        wchar_t *wide_name = NULL, *wide_value = NULL;
        DWORD value_len;
        int error = -1;
 
-       git_buf_clear(out);
+       git_str_clear(out);
 
        if (git__utf8_to_16_alloc(&wide_name, name) < 0)
                return -1;
@@ -754,7 +754,7 @@ int git__getenv(git_buf *out, const char *name)
        }
 
        if (value_len)
-               error = git_buf_put_w(out, wide_value, value_len);
+               error = git_str_put_w(out, wide_value, value_len);
        else if (GetLastError() == ERROR_SUCCESS || GetLastError() == ERROR_ENVVAR_NOT_FOUND)
                error = GIT_ENOTFOUND;
        else
@@ -765,16 +765,16 @@ int git__getenv(git_buf *out, const char *name)
        return error;
 }
 #else
-int git__getenv(git_buf *out, const char *name)
+int git__getenv(git_str *out, const char *name)
 {
        const char *val = getenv(name);
 
-       git_buf_clear(out);
+       git_str_clear(out);
 
        if (!val)
                return GIT_ENOTFOUND;
 
-       return git_buf_puts(out, val);
+       return git_str_puts(out, val);
 }
 #endif
 
index e8074fcb9da2da3b22890a991943dfdbb04627f5..141779ade85f719709e609e979d0c0cc9f4307e0 100644 (file)
@@ -7,15 +7,11 @@
 #ifndef INCLUDE_util_h__
 #define INCLUDE_util_h__
 
-#include "common.h"
-
 #ifndef GIT_WIN32
 # include <ctype.h>
 #endif
 
-#include "git2/buffer.h"
-
-#include "buffer.h"
+#include "str.h"
 #include "common.h"
 #include "strnlen.h"
 #include "thread.h"
@@ -41,8 +37,6 @@
 # define GIT_CONTAINER_OF(ptr, type, member) (type *)(ptr)
 #endif
 
-#define GIT_DATE_RFC2822_SZ  32
-
 /**
  * Return the length of a constant string.
  * We are aware that `strlen` performs the same task and is usually
@@ -298,26 +292,6 @@ GIT_INLINE(bool) git__isxdigit(int c)
  */
 extern int git__parse_bool(int *out, const char *value);
 
-/*
- * Parse a string into a value as a git_time_t.
- *
- * Sample valid input:
- * - "yesterday"
- * - "July 17, 2003"
- * - "2003-7-17 08:23"
- */
-extern int git__date_parse(git_time_t *out, const char *date);
-
-/*
- * Format a git_time as a RFC2822 string
- *
- * @param out buffer to store formatted date; a '\\0' terminator will automatically be added.
- * @param len size of the buffer; should be atleast `GIT_DATE_RFC2822_SZ` in size;
- * @param date the date to be formatted
- * @return 0 if successful; -1 on error
- */
-extern int git__date_rfc2822_fmt(char *out, size_t len, const git_time *date);
-
 /*
  * Unescapes a string in-place.
  *
@@ -402,7 +376,7 @@ GIT_INLINE(double) git__timer(void)
 
 #endif
 
-extern int git__getenv(git_buf *out, const char *name);
+extern int git__getenv(git_str *out, const char *name);
 
 extern int git__online_cpus(void);
 
index 3dcec3d1319b78f6fcb63b768edfa0f728c327c2..ae3c79a4cdb2e01ecb9e1d73765633d1502ae2a5 100644 (file)
@@ -13,7 +13,7 @@ typedef int (*git_vector_cmp)(const void *, const void *);
 
 enum {
        GIT_VECTOR_SORTED = (1u << 0),
-       GIT_VECTOR_FLAG_MAX = (1u << 1),
+       GIT_VECTOR_FLAG_MAX = (1u << 1)
 };
 
 typedef struct git_vector {
index 40d2d518a182e6df80df65841aebded44e8a13d3..725a90167f260261cb70808abadd00fe91a4c33a 100644 (file)
@@ -9,32 +9,22 @@
 
 #include "path_w32.h"
 #include "utf-conv.h"
-#include "path.h"
+#include "fs_path.h"
 
-#define REG_MSYSGIT_INSTALL_LOCAL L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1"
+#define REG_GITFORWINDOWS_KEY       L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1"
+#define REG_GITFORWINDOWS_KEY_WOW64 L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1"
 
-#ifndef _WIN64
-#define REG_MSYSGIT_INSTALL REG_MSYSGIT_INSTALL_LOCAL
-#else
-#define REG_MSYSGIT_INSTALL L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1"
-#endif
-
-typedef struct {
-       git_win32_path path;
-       DWORD len;
-} _findfile_path;
-
-static int git_win32__expand_path(_findfile_path *dest, const wchar_t *src)
+static int git_win32__expand_path(git_win32_path dest, const wchar_t *src)
 {
-       dest->len = ExpandEnvironmentStringsW(src, dest->path, ARRAY_SIZE(dest->path));
+       DWORD len = ExpandEnvironmentStringsW(src, dest, GIT_WIN_PATH_UTF16);
 
-       if (!dest->len || dest->len > ARRAY_SIZE(dest->path))
+       if (!len || len > GIT_WIN_PATH_UTF16)
                return -1;
 
        return 0;
 }
 
-static int win32_path_to_8(git_buf *dest, const wchar_t *src)
+static int win32_path_to_8(git_str *dest, const wchar_t *src)
 {
        git_win32_utf8_path utf8_path;
 
@@ -44,155 +34,221 @@ static int win32_path_to_8(git_buf *dest, const wchar_t *src)
        }
 
        /* Convert backslashes to forward slashes */
-       git_path_mkposix(utf8_path);
+       git_fs_path_mkposix(utf8_path);
 
-       return git_buf_sets(dest, utf8_path);
+       return git_str_sets(dest, utf8_path);
 }
 
-static wchar_t *win32_walkpath(wchar_t *path, wchar_t *buf, size_t buflen)
-{
-       wchar_t term, *base = path;
-
-       GIT_ASSERT_ARG_WITH_RETVAL(path, NULL);
-       GIT_ASSERT_ARG_WITH_RETVAL(buf, NULL);
-       GIT_ASSERT_ARG_WITH_RETVAL(buflen, NULL);
-
-       term = (*path == L'"') ? *path++ : L';';
+static git_win32_path mock_registry;
+static bool mock_registry_set;
 
-       for (buflen--; *path && *path != term && buflen; buflen--)
-               *buf++ = *path++;
-
-       *buf = L'\0'; /* reserved a byte via initial subtract */
+extern int git_win32__set_registry_system_dir(const wchar_t *mock_sysdir)
+{
+       if (!mock_sysdir) {
+               mock_registry[0] = L'\0';
+               mock_registry_set = false;
+       } else {
+               size_t len = wcslen(mock_sysdir);
+
+               if (len > GIT_WIN_PATH_MAX) {
+                       git_error_set(GIT_ERROR_INVALID, "mock path too long");
+                       return -1;
+               }
 
-       while (*path == term || *path == L';')
-               path++;
+               wcscpy(mock_registry, mock_sysdir);
+               mock_registry_set = true;
+       }
 
-       return (path != base) ? path : NULL;
+       return 0;
 }
 
-static int win32_find_git_in_path(git_buf *buf, const wchar_t *gitexe, const wchar_t *subdir)
+static int lookup_registry_key(
+       git_win32_path out,
+       const HKEY hive,
+       const wchar_t* key,
+       const wchar_t *value)
 {
-       wchar_t *env = _wgetenv(L"PATH"), lastch;
-       _findfile_path root;
-       size_t gitexe_len = wcslen(gitexe);
+       HKEY hkey;
+       DWORD type, size;
+       int error = GIT_ENOTFOUND;
 
-       if (!env)
-               return -1;
+       /*
+        * Registry data may not be NUL terminated, provide room to do
+        * it ourselves.
+        */
+       size = (DWORD)((sizeof(git_win32_path) - 1) * sizeof(wchar_t));
+
+       if (RegOpenKeyExW(hive, key, 0, KEY_READ, &hkey) != 0)
+               return GIT_ENOTFOUND;
+
+       if (RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)out, &size) == 0 &&
+           type == REG_SZ &&
+           size > 0 &&
+           size < sizeof(git_win32_path)) {
+               size_t wsize = size / sizeof(wchar_t);
+               size_t len = wsize - 1;
+
+               if (out[wsize - 1] != L'\0') {
+                       len = wsize;
+                       out[wsize] = L'\0';
+               }
 
-       while ((env = win32_walkpath(env, root.path, MAX_PATH-1)) && *root.path) {
-               root.len = (DWORD)wcslen(root.path);
-               lastch = root.path[root.len - 1];
+               if (out[len - 1] == L'\\')
+                       out[len - 1] = L'\0';
 
-               /* ensure trailing slash (MAX_PATH-1 to walkpath guarantees space) */
-               if (lastch != L'/' && lastch != L'\\') {
-                       root.path[root.len++] = L'\\';
-                       root.path[root.len]   = L'\0';
-               }
+               if (_waccess(out, F_OK) == 0)
+                       error = 0;
+       }
 
-               if (root.len + gitexe_len >= MAX_PATH)
-                       continue;
-               wcscpy(&root.path[root.len], gitexe);
+       RegCloseKey(hkey);
+       return error;
+}
 
-               if (_waccess(root.path, F_OK) == 0 && root.len > 5) {
-                       /* replace "bin\\" or "cmd\\" with subdir */
-                       wcscpy(&root.path[root.len - 4], subdir);
+static int find_sysdir_in_registry(git_win32_path out)
+{
+       if (mock_registry_set) {
+               if (mock_registry[0] == L'\0')
+                       return GIT_ENOTFOUND;
 
-                       win32_path_to_8(buf, root.path);
-                       return 0;
-               }
+               wcscpy(out, mock_registry);
+               return 0;
        }
 
-       return GIT_ENOTFOUND;
+       if (lookup_registry_key(out, HKEY_CURRENT_USER, REG_GITFORWINDOWS_KEY, L"InstallLocation") == 0 ||
+           lookup_registry_key(out, HKEY_CURRENT_USER, REG_GITFORWINDOWS_KEY_WOW64, L"InstallLocation") == 0 ||
+           lookup_registry_key(out, HKEY_LOCAL_MACHINE, REG_GITFORWINDOWS_KEY, L"InstallLocation") == 0 ||
+           lookup_registry_key(out, HKEY_LOCAL_MACHINE, REG_GITFORWINDOWS_KEY_WOW64, L"InstallLocation") == 0)
+               return 0;
+
+    return GIT_ENOTFOUND;
 }
 
-static int win32_find_git_in_registry(
-       git_buf *buf, const HKEY hive, const wchar_t *key, const wchar_t *subdir)
+static int find_sysdir_in_path(git_win32_path out)
 {
-       HKEY hKey;
-       int error = GIT_ENOTFOUND;
+       size_t out_len;
 
-       GIT_ASSERT_ARG(buf);
+       if (git_win32_path_find_executable(out, L"git.exe") < 0 &&
+           git_win32_path_find_executable(out, L"git.cmd") < 0)
+               return GIT_ENOTFOUND;
 
-       if (!RegOpenKeyExW(hive, key, 0, KEY_READ, &hKey)) {
-               DWORD dwType, cbData;
-               git_win32_path path;
+       out_len = wcslen(out);
 
-               /* Ensure that the buffer is big enough to have the suffix attached
-                * after we receive the result. */
-               cbData = (DWORD)(sizeof(path) - wcslen(subdir) * sizeof(wchar_t));
+       /* Trim the file name */
+       if (out_len <= CONST_STRLEN(L"git.exe"))
+               return GIT_ENOTFOUND;
 
-               /* InstallLocation points to the root of the git directory */
-               if (!RegQueryValueExW(hKey, L"InstallLocation", NULL, &dwType, (LPBYTE)path, &cbData) &&
-                       dwType == REG_SZ) {
+       out_len -= CONST_STRLEN(L"git.exe");
 
-                       /* Append the suffix */
-                       wcscat(path, subdir);
+       if (out_len && out[out_len - 1] == L'\\')
+               out_len--;
 
-                       /* Convert to UTF-8, with forward slashes, and output the path
-                        * to the provided buffer */
-                       if (!win32_path_to_8(buf, path))
-                               error = 0;
-               }
+       /*
+        * Git for Windows usually places the command in a 'bin' or
+        * 'cmd' directory, trim that.
+        */
+       if (out_len >= CONST_STRLEN(L"\\bin") &&
+           wcsncmp(&out[out_len - CONST_STRLEN(L"\\bin")], L"\\bin", CONST_STRLEN(L"\\bin")) == 0)
+               out_len -= CONST_STRLEN(L"\\bin");
+       else if (out_len >= CONST_STRLEN(L"\\cmd") &&
+                wcsncmp(&out[out_len - CONST_STRLEN(L"\\cmd")], L"\\cmd", CONST_STRLEN(L"\\cmd")) == 0)
+               out_len -= CONST_STRLEN(L"\\cmd");
 
-               RegCloseKey(hKey);
-       }
+       if (!out_len)
+               return GIT_ENOTFOUND;
 
-       return error;
+       out[out_len] = L'\0';
+       return 0;
 }
 
 static int win32_find_existing_dirs(
-       git_buf *out, const wchar_t *tmpl[])
+    git_str* out,
+    const wchar_t* tmpl[])
 {
-       _findfile_path path16;
-       git_buf buf = GIT_BUF_INIT;
+       git_win32_path path16;
+       git_str buf = GIT_STR_INIT;
 
-       git_buf_clear(out);
+       git_str_clear(out);
 
        for (; *tmpl != NULL; tmpl++) {
-               if (!git_win32__expand_path(&path16, *tmpl) &&
-                       path16.path[0] != L'%' &&
-                       !_waccess(path16.path, F_OK))
-               {
-                       win32_path_to_8(&buf, path16.path);
+               if (!git_win32__expand_path(path16, *tmpl) &&
+                   path16[0] != L'%' &&
+                   !_waccess(path16, F_OK)) {
+                       win32_path_to_8(&buf, path16);
 
                        if (buf.size)
-                               git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr);
+                               git_str_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr);
                }
        }
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
-       return (git_buf_oom(out) ? -1 : 0);
+       return (git_str_oom(out) ? -1 : 0);
 }
 
-int git_win32__find_system_dirs(git_buf *out, const wchar_t *subdir)
+static int append_subdir(git_str *out, git_str *path, const char *subdir)
 {
-       git_buf buf = GIT_BUF_INIT;
+       static const char* architecture_roots[] = {
+               "",
+               "mingw64",
+               "mingw32",
+               NULL
+       };
+       const char **root;
+       size_t orig_path_len = path->size;
+
+       for (root = architecture_roots; *root; root++) {
+               if ((*root[0] && git_str_joinpath(path, path->ptr, *root) < 0) ||
+                   git_str_joinpath(path, path->ptr, subdir) < 0)
+                       return -1;
 
-       /* directories where git.exe & git.cmd are found */
-       if (!win32_find_git_in_path(&buf, L"git.exe", subdir) && buf.size)
-               git_buf_set(out, buf.ptr, buf.size);
-       else
-               git_buf_clear(out);
+               if (git_fs_path_exists(path->ptr) &&
+                   git_str_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, path->ptr) < 0)
+                       return -1;
 
-       if (!win32_find_git_in_path(&buf, L"git.cmd", subdir) && buf.size)
-               git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr);
+               git_str_truncate(path, orig_path_len);
+       }
 
-       /* directories where git is installed according to registry */
-       if (!win32_find_git_in_registry(
-                       &buf, HKEY_CURRENT_USER, REG_MSYSGIT_INSTALL_LOCAL, subdir) && buf.size)
-               git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr);
+       return 0;
+}
 
-       if (!win32_find_git_in_registry(
-                       &buf, HKEY_LOCAL_MACHINE, REG_MSYSGIT_INSTALL, subdir) && buf.size)
-               git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr);
+int git_win32__find_system_dirs(git_str *out, const char *subdir)
+{
+       git_win32_path pathdir, regdir;
+       git_str path8 = GIT_STR_INIT;
+       bool has_pathdir, has_regdir;
+       int error;
+
+       has_pathdir = (find_sysdir_in_path(pathdir) == 0);
+       has_regdir = (find_sysdir_in_registry(regdir) == 0);
+
+       if (!has_pathdir && !has_regdir)
+               return 0;
+
+       /*
+        * Usually the git in the path is the same git in the registry,
+        * in this case there's no need to duplicate the paths.
+        */
+       if (has_pathdir && has_regdir && wcscmp(pathdir, regdir) == 0)
+               has_regdir = false;
+
+       if (has_pathdir) {
+               if ((error = win32_path_to_8(&path8, pathdir)) < 0 ||
+                   (error = append_subdir(out, &path8, subdir)) < 0)
+                       goto done;
+       }
 
-       git_buf_dispose(&buf);
+       if (has_regdir) {
+               if ((error = win32_path_to_8(&path8, regdir)) < 0 ||
+                   (error = append_subdir(out, &path8, subdir)) < 0)
+                       goto done;
+       }
 
-       return (git_buf_oom(out) ? -1 : 0);
+done:
+    git_str_dispose(&path8);
+    return error;
 }
 
-int git_win32__find_global_dirs(git_buf *out)
+int git_win32__find_global_dirs(git_str *out)
 {
        static const wchar_t *global_tmpls[4] = {
                L"%HOME%\\",
@@ -204,7 +260,7 @@ int git_win32__find_global_dirs(git_buf *out)
        return win32_find_existing_dirs(out, global_tmpls);
 }
 
-int git_win32__find_xdg_dirs(git_buf *out)
+int git_win32__find_xdg_dirs(git_str *out)
 {
        static const wchar_t *global_tmpls[7] = {
                L"%XDG_CONFIG_HOME%\\git",
@@ -219,7 +275,7 @@ int git_win32__find_xdg_dirs(git_buf *out)
        return win32_find_existing_dirs(out, global_tmpls);
 }
 
-int git_win32__find_programdata_dirs(git_buf *out)
+int git_win32__find_programdata_dirs(git_str *out)
 {
        static const wchar_t *programdata_tmpls[2] = {
                L"%PROGRAMDATA%\\Git",
index e7bcf948a5c006691885d02fb18debe551406b03..61fb7dbad790f524a887f71f069620a453eec48c 100644 (file)
 
 #include "common.h"
 
-extern int git_win32__find_system_dirs(git_buf *out, const wchar_t *subpath);
-extern int git_win32__find_global_dirs(git_buf *out);
-extern int git_win32__find_xdg_dirs(git_buf *out);
-extern int git_win32__find_programdata_dirs(git_buf *out);
+/** Sets the mock registry root for Git for Windows for testing. */
+extern int git_win32__set_registry_system_dir(const wchar_t *mock_sysdir);
+
+extern int git_win32__find_system_dirs(git_str *out, const char *subpath);
+extern int git_win32__find_global_dirs(git_str *out);
+extern int git_win32__find_xdg_dirs(git_str *out);
+extern int git_win32__find_programdata_dirs(git_str *out);
 
 #endif
 
index e6640c85ed4ae499992509ba1bf47e7991034368..d9fc8292b0c47be9dfeabce3b99895932d826831 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "path_w32.h"
 
-#include "path.h"
+#include "fs_path.h"
 #include "utf-conv.h"
 #include "posix.h"
 #include "reparse.h"
@@ -41,7 +41,7 @@ GIT_INLINE(int) path__cwd(wchar_t *path, int size)
        }
 
        /* The Win32 APIs may return "\\?\" once you've used it first.
-        * But it may not.  What a gloriously predictible API!
+        * But it may not.  What a gloriously predictable API!
         */
        if (wcsncmp(path, PATH__NT_NAMESPACE, PATH__NT_NAMESPACE_LEN))
                return len;
@@ -57,7 +57,7 @@ static wchar_t *path__skip_server(wchar_t *path)
        wchar_t *c;
 
        for (c = path; *c; c++) {
-               if (git_path_is_dirsep(*c))
+               if (git_fs_path_is_dirsep(*c))
                        return c + 1;
        }
 
@@ -71,9 +71,9 @@ static wchar_t *path__skip_prefix(wchar_t *path)
 
                if (wcsncmp(path, L"UNC\\", 4) == 0)
                        path = path__skip_server(path + 4);
-               else if (git_path_is_absolute(path))
+               else if (git_fs_path_is_absolute(path))
                        path += PATH__ABSOLUTE_LEN;
-       } else if (git_path_is_absolute(path)) {
+       } else if (git_fs_path_is_absolute(path)) {
                path += PATH__ABSOLUTE_LEN;
        } else if (path__is_unc(path)) {
                path = path__skip_server(path + 2);
@@ -151,6 +151,137 @@ int git_win32_path_canonicalize(git_win32_path path)
        return (int)(to - path);
 }
 
+static int git_win32_path_join(
+       git_win32_path dest,
+       const wchar_t *one,
+       size_t one_len,
+       const wchar_t *two,
+       size_t two_len)
+{
+       size_t backslash = 0;
+
+       if (one_len && two_len && one[one_len - 1] != L'\\')
+               backslash = 1;
+
+       if (one_len + two_len + backslash > MAX_PATH) {
+               git_error_set(GIT_ERROR_INVALID, "path too long");
+               return -1;
+       }
+
+       memmove(dest, one, one_len * sizeof(wchar_t));
+
+       if (backslash)
+               dest[one_len] = L'\\';
+
+       memcpy(dest + one_len + backslash, two, two_len * sizeof(wchar_t));
+       dest[one_len + backslash + two_len] = L'\0';
+
+       return 0;
+}
+
+struct win32_path_iter {
+       wchar_t *env;
+       const wchar_t *current_dir;
+};
+
+static int win32_path_iter_init(struct win32_path_iter *iter)
+{
+       DWORD len = GetEnvironmentVariableW(L"PATH", NULL, 0);
+
+       if (!len && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
+               iter->env = NULL;
+               iter->current_dir = NULL;
+               return 0;
+       } else if (!len) {
+               git_error_set(GIT_ERROR_OS, "could not load PATH");
+               return -1;
+       }
+
+       iter->env = git__malloc(len * sizeof(wchar_t));
+       GIT_ERROR_CHECK_ALLOC(iter->env);
+
+       len = GetEnvironmentVariableW(L"PATH", iter->env, len);
+
+       if (len == 0) {
+               git_error_set(GIT_ERROR_OS, "could not load PATH");
+               return -1;
+       }
+
+       iter->current_dir = iter->env;
+       return 0;
+}
+
+static int win32_path_iter_next(
+       const wchar_t **out,
+       size_t *out_len,
+       struct win32_path_iter *iter)
+{
+       const wchar_t *start;
+       wchar_t term;
+       size_t len = 0;
+
+       if (!iter->current_dir || !*iter->current_dir)
+               return GIT_ITEROVER;
+
+       term = (*iter->current_dir == L'"') ? *iter->current_dir++ : L';';
+       start = iter->current_dir;
+
+       while (*iter->current_dir && *iter->current_dir != term) {
+               iter->current_dir++;
+               len++;
+       }
+
+       *out = start;
+       *out_len = len;
+
+       if (term == L'"' && *iter->current_dir)
+               iter->current_dir++;
+
+       while (*iter->current_dir == L';')
+               iter->current_dir++;
+
+       return 0;
+}
+
+static void win32_path_iter_dispose(struct win32_path_iter *iter)
+{
+       if (!iter)
+               return;
+
+       git__free(iter->env);
+       iter->env = NULL;
+       iter->current_dir = NULL;
+}
+
+int git_win32_path_find_executable(git_win32_path fullpath, wchar_t *exe)
+{
+       struct win32_path_iter path_iter;
+       const wchar_t *dir;
+       size_t dir_len, exe_len = wcslen(exe);
+       bool found = false;
+
+       if (win32_path_iter_init(&path_iter) < 0)
+               return -1;
+
+       while (win32_path_iter_next(&dir, &dir_len, &path_iter) != GIT_ITEROVER) {
+               if (git_win32_path_join(fullpath, dir, dir_len, exe, exe_len) < 0)
+                       continue;
+
+               if (_waccess(fullpath, 0) == 0) {
+                       found = true;
+                       break;
+               }
+       }
+
+       win32_path_iter_dispose(&path_iter);
+
+       if (found)
+               return 0;
+
+       fullpath[0] = L'\0';
+       return GIT_ENOTFOUND;
+}
+
 static int win32_path_cwd(wchar_t *out, size_t len)
 {
        int cwd_len;
@@ -204,7 +335,7 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
        dest += PATH__NT_NAMESPACE_LEN;
 
        /* See if this is an absolute path (beginning with a drive letter) */
-       if (git_path_is_absolute(src)) {
+       if (git_fs_path_is_absolute(src)) {
                if (git__utf8_to_16(dest, GIT_WIN_PATH_MAX, src) < 0)
                        goto on_error;
        }
@@ -228,7 +359,7 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
                if (path__cwd(dest, GIT_WIN_PATH_MAX) < 0)
                        goto on_error;
 
-               if (!git_path_is_absolute(dest)) {
+               if (!git_fs_path_is_absolute(dest)) {
                        errno = ENOENT;
                        goto on_error;
                }
@@ -266,7 +397,7 @@ int git_win32_path_relative_from_utf8(git_win32_path out, const char *src)
        int len;
 
        /* Handle absolute paths */
-       if (git_path_is_absolute(src) ||
+       if (git_fs_path_is_absolute(src) ||
            path__is_nt_namespace(src) ||
            path__is_unc(src) ||
            path__startswith_slash(src)) {
@@ -305,7 +436,7 @@ int git_win32_path_to_utf8(git_win32_utf8_path dest, const wchar_t *src)
        if ((len = git__utf16_to_8(out, GIT_WIN_PATH_UTF8, src)) < 0)
                return len;
 
-       git_path_mkposix(dest);
+       git_fs_path_mkposix(dest);
 
        return len;
 }
index 4fadf8d084820a7f721a1b09dd4431249456aff0..837b11ebd72fb26e57442d836894496b0ea2ca9d 100644 (file)
@@ -86,4 +86,6 @@ size_t git_win32_path_trim_end(wchar_t *str, size_t len);
  */
 size_t git_win32_path_remove_namespace(wchar_t *str, size_t len);
 
+int git_win32_path_find_executable(git_win32_path fullpath, wchar_t* exe);
+
 #endif
index 87c6b436ae7589d8a6dfe705cc76a7e432a83bfe..578347f15276edd92a57c20f79c34ec8df34e158 100644 (file)
@@ -42,7 +42,6 @@ extern int p_inet_pton(int af, const char *src, void* dst);
 
 extern int p_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr);
 extern int p_snprintf(char *buffer, size_t count, const char *format, ...) GIT_FORMAT_PRINTF(3, 4);
-extern int p_mkstemp(char *tmp_path);
 extern int p_chdir(const char *path);
 extern int p_chmod(const char *path, mode_t mode);
 extern int p_rmdir(const char *path);
index 8af07e6fa77defec3d06897c69d165e17af0f8b8..5f7cd0c26457b2b8624ae0560dfcfefa65bf0eb7 100644 (file)
@@ -9,12 +9,10 @@
 
 #include "../posix.h"
 #include "../futils.h"
-#include "path.h"
+#include "fs_path.h"
 #include "path_w32.h"
 #include "utf-conv.h"
-#include "repository.h"
 #include "reparse.h"
-#include "buffer.h"
 #include <errno.h>
 #include <io.h>
 #include <fcntl.h>
@@ -415,21 +413,21 @@ int p_readlink(const char *path, char *buf, size_t bufsiz)
 
 static bool target_is_dir(const char *target, const char *path)
 {
-       git_buf resolved = GIT_BUF_INIT;
+       git_str resolved = GIT_STR_INIT;
        git_win32_path resolved_w;
        bool isdir = true;
 
-       if (git_path_is_absolute(target))
+       if (git_fs_path_is_absolute(target))
                git_win32_path_from_utf8(resolved_w, target);
-       else if (git_path_dirname_r(&resolved, path) < 0 ||
-                git_path_apply_relative(&resolved, target) < 0 ||
+       else if (git_fs_path_dirname_r(&resolved, path) < 0 ||
+                git_fs_path_apply_relative(&resolved, target) < 0 ||
                 git_win32_path_from_utf8(resolved_w, resolved.ptr) < 0)
                goto out;
 
        isdir = GetFileAttributesW(resolved_w) & FILE_ATTRIBUTE_DIRECTORY;
 
 out:
-       git_buf_dispose(&resolved);
+       git_str_dispose(&resolved);
        return isdir;
 }
 
@@ -443,7 +441,7 @@ int p_symlink(const char *target, const char *path)
         * not want to use `git_win32_path_from_utf8` for converting the target,
         * as that function will automatically pre-pend the current working
         * directory in case the path is not absolute. As Git will instead use
-        * relative symlinks, this is not someting we want.
+        * relative symlinks, this is not something we want.
         */
        if (git_win32_path_from_utf8(path_w, path) < 0 ||
            git_win32_path_relative_from_utf8(target_w, target) < 0)
@@ -662,7 +660,7 @@ int p_getcwd(char *buffer_out, size_t size)
                return -1;
        }
 
-       git_path_mkposix(buffer_out);
+       git_fs_path_mkposix(buffer_out);
        return 0;
 }
 
@@ -822,7 +820,7 @@ char *p_realpath(const char *orig_path, char *buffer)
        if (git_win32_path_to_utf8(buffer, buffer_w) < 0)
                return NULL;
 
-       git_path_mkposix(buffer);
+       git_fs_path_mkposix(buffer);
 
        return buffer;
 }
@@ -862,20 +860,6 @@ int p_snprintf(char *buffer, size_t count, const char *format, ...)
        return r;
 }
 
-/* TODO: wut? */
-int p_mkstemp(char *tmp_path)
-{
-#if defined(_MSC_VER) && _MSC_VER >= 1500
-       if (_mktemp_s(tmp_path, strlen(tmp_path) + 1) != 0)
-               return -1;
-#else
-       if (_mktemp(tmp_path) == NULL)
-               return -1;
-#endif
-
-       return p_open(tmp_path, O_RDWR | O_CREAT | O_EXCL, 0744); /* -V536 */
-}
-
 int p_access(const char *path, mode_t mode)
 {
        git_win32_path buf;
@@ -1003,7 +987,7 @@ ssize_t p_pread(int fd, void *data, size_t size, off64_t offset)
        /* Fail if the final offset would have overflowed to match POSIX semantics. */
        if (!git__is_ssizet(size) || git__add_int64_overflow(&final_offset, offset, (int64_t)size)) {
                errno = EINVAL;
-               return -1;      
+               return -1;
        }
 
        /*
@@ -1038,7 +1022,7 @@ ssize_t p_pwrite(int fd, const void *data, size_t size, off64_t offset)
        /* Fail if the final offset would have overflowed to match POSIX semantics. */
        if (!git__is_ssizet(size) || git__add_int64_overflow(&final_offset, offset, (int64_t)size)) {
                errno = EINVAL;
-               return -1;      
+               return -1;
        }
 
        /*
index f270a1e6ac9192e204761b43e527d36eb5b963bf..6fee8203c24df71d6556bf1baa80ad8cb7785840 100644 (file)
@@ -7,7 +7,6 @@
 
 #include "w32_buffer.h"
 
-#include "../buffer.h"
 #include "utf-conv.h"
 
 GIT_INLINE(int) handle_wc_error(void)
@@ -20,7 +19,7 @@ GIT_INLINE(int) handle_wc_error(void)
        return -1;
 }
 
-int git_buf_put_w(git_buf *buf, const wchar_t *string_w, size_t len_w)
+int git_str_put_w(git_str *buf, const wchar_t *string_w, size_t len_w)
 {
        int utf8_len, utf8_write_len;
        size_t new_size;
@@ -43,7 +42,7 @@ int git_buf_put_w(git_buf *buf, const wchar_t *string_w, size_t len_w)
        GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, (size_t)utf8_len);
        GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
 
-       if (git_buf_grow(buf, new_size) < 0)
+       if (git_str_grow(buf, new_size) < 0)
                return -1;
 
        if ((utf8_write_len = WideCharToMultiByte(
index 43298e4a78a99ce72ff82b1010af596e3d132238..4227296d8f54932c9e2c03a7b8bf340c5d3df7a7 100644 (file)
@@ -8,13 +8,12 @@
 #define INCLUDE_win32_w32_buffer_h__
 
 #include "common.h"
-
-#include "../buffer.h"
+#include "str.h"
 
 /**
  * Convert a wide character string to UTF-8 and append the results to the
  * buffer.
  */
-int git_buf_put_w(git_buf *buf, const wchar_t *string_w, size_t len_w);
+int git_str_put_w(git_str *buf, const wchar_t *string_w, size_t len_w);
 
 #endif
index 5c8425be3acca6b265966a809609bf7578a29965..0f095de12d253b9547bfceb3a34a9892b908c75a 100644 (file)
@@ -199,7 +199,7 @@ int git_win32_leakcheck_stack(
        return 0;
 }
 
-/* Strack tracing */
+/* Stack tracing */
 
 #define STACKTRACE_UID_LEN (15)
 
index fe8db774305ba58c440574e349f768c78582ac1e..2ac2274f183fa48a3498a75dfa3b88c75149136d 100644 (file)
@@ -7,32 +7,34 @@
 
 #include "worktree.h"
 
+#include "buf.h"
+#include "repository.h"
+#include "path.h"
+
 #include "git2/branch.h"
 #include "git2/commit.h"
 #include "git2/worktree.h"
 
-#include "repository.h"
-
 static bool is_worktree_dir(const char *dir)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        int error;
 
-       if (git_buf_sets(&buf, dir) < 0)
+       if (git_str_sets(&buf, dir) < 0)
                return -1;
 
-       error = git_path_contains_file(&buf, "commondir")
-               && git_path_contains_file(&buf, "gitdir")
-               && git_path_contains_file(&buf, "HEAD");
+       error = git_fs_path_contains_file(&buf, "commondir")
+               && git_fs_path_contains_file(&buf, "gitdir")
+               && git_fs_path_contains_file(&buf, "HEAD");
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        return error;
 }
 
 int git_worktree_list(git_strarray *wts, git_repository *repo)
 {
        git_vector worktrees = GIT_VECTOR_INIT;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        char *worktree;
        size_t i, len;
        int error;
@@ -43,18 +45,18 @@ int git_worktree_list(git_strarray *wts, git_repository *repo)
        wts->count = 0;
        wts->strings = NULL;
 
-       if ((error = git_buf_joinpath(&path, repo->commondir, "worktrees/")) < 0)
+       if ((error = git_str_joinpath(&path, repo->commondir, "worktrees/")) < 0)
                goto exit;
-       if (!git_path_exists(path.ptr) || git_path_is_empty_dir(path.ptr))
+       if (!git_fs_path_exists(path.ptr) || git_fs_path_is_empty_dir(path.ptr))
                goto exit;
-       if ((error = git_path_dirload(&worktrees, path.ptr, path.size, 0x0)) < 0)
+       if ((error = git_fs_path_dirload(&worktrees, path.ptr, path.size, 0x0)) < 0)
                goto exit;
 
        len = path.size;
 
        git_vector_foreach(&worktrees, i, worktree) {
-               git_buf_truncate(&path, len);
-               git_buf_puts(&path, worktree);
+               git_str_truncate(&path, len);
+               git_str_puts(&path, worktree);
 
                if (!is_worktree_dir(path.ptr)) {
                        git_vector_remove(&worktrees, i);
@@ -65,68 +67,68 @@ int git_worktree_list(git_strarray *wts, git_repository *repo)
        wts->strings = (char **)git_vector_detach(&wts->count, NULL, &worktrees);
 
 exit:
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return error;
 }
 
 char *git_worktree__read_link(const char *base, const char *file)
 {
-       git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT, buf = GIT_STR_INIT;
 
        GIT_ASSERT_ARG_WITH_RETVAL(base, NULL);
        GIT_ASSERT_ARG_WITH_RETVAL(file, NULL);
 
-       if (git_buf_joinpath(&path, base, file) < 0)
+       if (git_str_joinpath(&path, base, file) < 0)
                goto err;
        if (git_futils_readbuffer(&buf, path.ptr) < 0)
                goto err;
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
-       git_buf_rtrim(&buf);
+       git_str_rtrim(&buf);
 
-       if (!git_path_is_relative(buf.ptr))
-               return git_buf_detach(&buf);
+       if (!git_fs_path_is_relative(buf.ptr))
+               return git_str_detach(&buf);
 
-       if (git_buf_sets(&path, base) < 0)
+       if (git_str_sets(&path, base) < 0)
                goto err;
-       if (git_path_apply_relative(&path, buf.ptr) < 0)
+       if (git_fs_path_apply_relative(&path, buf.ptr) < 0)
                goto err;
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
-       return git_buf_detach(&path);
+       return git_str_detach(&path);
 
 err:
-       git_buf_dispose(&buf);
-       git_buf_dispose(&path);
+       git_str_dispose(&buf);
+       git_str_dispose(&path);
 
        return NULL;
 }
 
-static int write_wtfile(const char *base, const char *file, const git_buf *buf)
+static int write_wtfile(const char *base, const char *file, const git_str *buf)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        int err;
 
        GIT_ASSERT_ARG(base);
        GIT_ASSERT_ARG(file);
        GIT_ASSERT_ARG(buf);
 
-       if ((err = git_buf_joinpath(&path, base, file)) < 0)
+       if ((err = git_str_joinpath(&path, base, file)) < 0)
                goto out;
 
        if ((err = git_futils_writebuffer(buf, path.ptr, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0)
                goto out;
 
 out:
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return err;
 }
 
 static int open_worktree_dir(git_worktree **out, const char *parent, const char *dir, const char *name)
 {
-       git_buf gitdir = GIT_BUF_INIT;
+       git_str gitdir = GIT_STR_INIT;
        git_worktree *wt = NULL;
        int error = 0;
 
@@ -135,7 +137,7 @@ static int open_worktree_dir(git_worktree **out, const char *parent, const char
                goto out;
        }
 
-       if ((error = git_path_validate_workdir(NULL, dir)) < 0)
+       if ((error = git_path_validate_length(NULL, dir)) < 0)
                goto out;
 
        if ((wt = git__calloc(1, sizeof(*wt))) == NULL) {
@@ -147,14 +149,14 @@ static int open_worktree_dir(git_worktree **out, const char *parent, const char
            (wt->commondir_path = git_worktree__read_link(dir, "commondir")) == NULL ||
            (wt->gitlink_path = git_worktree__read_link(dir, "gitdir")) == NULL ||
            (parent && (wt->parent_path = git__strdup(parent)) == NULL) ||
-           (wt->worktree_path = git_path_dirname(wt->gitlink_path)) == NULL) {
+           (wt->worktree_path = git_fs_path_dirname(wt->gitlink_path)) == NULL) {
                error = -1;
                goto out;
        }
 
-       if ((error = git_path_prettify_dir(&gitdir, dir, NULL)) < 0)
+       if ((error = git_fs_path_prettify_dir(&gitdir, dir, NULL)) < 0)
                goto out;
-       wt->gitdir_path = git_buf_detach(&gitdir);
+       wt->gitdir_path = git_str_detach(&gitdir);
 
        if ((error = git_worktree_is_locked(NULL, wt)) < 0)
                goto out;
@@ -166,14 +168,14 @@ static int open_worktree_dir(git_worktree **out, const char *parent, const char
 out:
        if (error)
                git_worktree_free(wt);
-       git_buf_dispose(&gitdir);
+       git_str_dispose(&gitdir);
 
        return error;
 }
 
 int git_worktree_lookup(git_worktree **out, git_repository *repo, const char *name)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_worktree *wt = NULL;
        int error;
 
@@ -182,14 +184,14 @@ int git_worktree_lookup(git_worktree **out, git_repository *repo, const char *na
 
        *out = NULL;
 
-       if ((error = git_buf_join3(&path, '/', repo->commondir, "worktrees", name)) < 0)
+       if ((error = git_str_join3(&path, '/', repo->commondir, "worktrees", name)) < 0)
                goto out;
 
        if ((error = (open_worktree_dir(out, git_repository_workdir(repo), path.ptr, name))) < 0)
                goto out;
 
 out:
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        if (error)
                git_worktree_free(wt);
@@ -199,7 +201,7 @@ out:
 
 int git_worktree_open_from_repository(git_worktree **out, git_repository *repo)
 {
-       git_buf parent = GIT_BUF_INIT;
+       git_str parent = GIT_STR_INIT;
        const char *gitdir, *commondir;
        char *name = NULL;
        int error = 0;
@@ -213,18 +215,18 @@ int git_worktree_open_from_repository(git_worktree **out, git_repository *repo)
        gitdir = git_repository_path(repo);
        commondir = git_repository_commondir(repo);
 
-       if ((error = git_path_prettify_dir(&parent, "..", commondir)) < 0)
+       if ((error = git_fs_path_prettify_dir(&parent, "..", commondir)) < 0)
                goto out;
 
        /* The name is defined by the last component in '.git/worktree/%s' */
-       name = git_path_basename(gitdir);
+       name = git_fs_path_basename(gitdir);
 
        if ((error = open_worktree_dir(out, parent.ptr, gitdir, name)) < 0)
                goto out;
 
 out:
        git__free(name);
-       git_buf_dispose(&parent);
+       git_str_dispose(&parent);
 
        return error;
 }
@@ -254,21 +256,21 @@ int git_worktree_validate(const git_worktree *wt)
                return GIT_ERROR;
        }
 
-       if (wt->parent_path && !git_path_exists(wt->parent_path)) {
+       if (wt->parent_path && !git_fs_path_exists(wt->parent_path)) {
                git_error_set(GIT_ERROR_WORKTREE,
                        "worktree parent directory ('%s') does not exist ",
                        wt->parent_path);
                return GIT_ERROR;
        }
 
-       if (!git_path_exists(wt->commondir_path)) {
+       if (!git_fs_path_exists(wt->commondir_path)) {
                git_error_set(GIT_ERROR_WORKTREE,
                        "worktree common directory ('%s') does not exist ",
                        wt->commondir_path);
                return GIT_ERROR;
        }
 
-       if (!git_path_exists(wt->worktree_path)) {
+       if (!git_fs_path_exists(wt->worktree_path)) {
                git_error_set(GIT_ERROR_WORKTREE,
                        "worktree directory '%s' does not exist",
                        wt->worktree_path);
@@ -298,20 +300,17 @@ int git_worktree_add(git_worktree **out, git_repository *repo,
        const char *name, const char *worktree,
        const git_worktree_add_options *opts)
 {
-       git_buf gitdir = GIT_BUF_INIT, wddir = GIT_BUF_INIT, buf = GIT_BUF_INIT;
+       git_str gitdir = GIT_STR_INIT, wddir = GIT_STR_INIT, buf = GIT_STR_INIT;
        git_reference *ref = NULL, *head = NULL;
        git_commit *commit = NULL;
        git_repository *wt = NULL;
-       git_checkout_options coopts = GIT_CHECKOUT_OPTIONS_INIT;
+       git_checkout_options coopts;
        git_worktree_add_options wtopts = GIT_WORKTREE_ADD_OPTIONS_INIT;
        int err;
 
        GIT_ERROR_CHECK_VERSION(
                opts, GIT_WORKTREE_ADD_OPTIONS_VERSION, "git_worktree_add_options");
 
-       if (opts)
-               memcpy(&wtopts, opts, sizeof(wtopts));
-
        GIT_ASSERT_ARG(out);
        GIT_ASSERT_ARG(repo);
        GIT_ASSERT_ARG(name);
@@ -319,6 +318,11 @@ int git_worktree_add(git_worktree **out, git_repository *repo,
 
        *out = NULL;
 
+       if (opts)
+               memcpy(&wtopts, opts, sizeof(wtopts));
+
+       memcpy(&coopts, &wtopts.checkout_options, sizeof(coopts));
+
        if (wtopts.ref) {
                if (!git_reference_is_branch(wtopts.ref)) {
                        git_error_set(GIT_ERROR_WORKTREE, "reference is not a branch");
@@ -334,28 +338,28 @@ int git_worktree_add(git_worktree **out, git_repository *repo,
        }
 
        /* Create gitdir directory ".git/worktrees/<name>" */
-       if ((err = git_buf_joinpath(&gitdir, repo->commondir, "worktrees")) < 0)
+       if ((err = git_str_joinpath(&gitdir, repo->commondir, "worktrees")) < 0)
                goto out;
-       if (!git_path_exists(gitdir.ptr))
+       if (!git_fs_path_exists(gitdir.ptr))
                if ((err = git_futils_mkdir(gitdir.ptr, 0755, GIT_MKDIR_EXCL)) < 0)
                        goto out;
-       if ((err = git_buf_joinpath(&gitdir, gitdir.ptr, name)) < 0)
+       if ((err = git_str_joinpath(&gitdir, gitdir.ptr, name)) < 0)
                goto out;
        if ((err = git_futils_mkdir(gitdir.ptr, 0755, GIT_MKDIR_EXCL)) < 0)
                goto out;
-       if ((err = git_path_prettify_dir(&gitdir, gitdir.ptr, NULL)) < 0)
+       if ((err = git_fs_path_prettify_dir(&gitdir, gitdir.ptr, NULL)) < 0)
                goto out;
 
        /* Create worktree work dir */
        if ((err = git_futils_mkdir(worktree, 0755, GIT_MKDIR_EXCL)) < 0)
                goto out;
-       if ((err = git_path_prettify_dir(&wddir, worktree, NULL)) < 0)
+       if ((err = git_fs_path_prettify_dir(&wddir, worktree, NULL)) < 0)
                goto out;
 
        if (wtopts.lock) {
                int fd;
 
-               if ((err = git_buf_joinpath(&buf, gitdir.ptr, "locked")) < 0)
+               if ((err = git_str_joinpath(&buf, gitdir.ptr, "locked")) < 0)
                        goto out;
 
                if ((fd = p_creat(buf.ptr, 0644)) < 0) {
@@ -364,22 +368,22 @@ int git_worktree_add(git_worktree **out, git_repository *repo,
                }
 
                p_close(fd);
-               git_buf_clear(&buf);
+               git_str_clear(&buf);
        }
 
        /* Create worktree .git file */
-       if ((err = git_buf_printf(&buf, "gitdir: %s\n", gitdir.ptr)) < 0)
+       if ((err = git_str_printf(&buf, "gitdir: %s\n", gitdir.ptr)) < 0)
                goto out;
        if ((err = write_wtfile(wddir.ptr, ".git", &buf)) < 0)
                goto out;
 
        /* Create gitdir files */
-       if ((err = git_path_prettify_dir(&buf, repo->commondir, NULL) < 0)
-           || (err = git_buf_putc(&buf, '\n')) < 0
+       if ((err = git_fs_path_prettify_dir(&buf, repo->commondir, NULL) < 0)
+           || (err = git_str_putc(&buf, '\n')) < 0
            || (err = write_wtfile(gitdir.ptr, "commondir", &buf)) < 0)
                goto out;
-       if ((err = git_buf_joinpath(&buf, wddir.ptr, ".git")) < 0
-           || (err = git_buf_putc(&buf, '\n')) < 0
+       if ((err = git_str_joinpath(&buf, wddir.ptr, ".git")) < 0
+           || (err = git_str_putc(&buf, '\n')) < 0
            || (err = write_wtfile(gitdir.ptr, "gitdir", &buf)) < 0)
                goto out;
 
@@ -403,7 +407,6 @@ int git_worktree_add(git_worktree **out, git_repository *repo,
                goto out;
 
        /* Checkout worktree's HEAD */
-       coopts.checkout_strategy = GIT_CHECKOUT_FORCE;
        if ((err = git_checkout_head(wt, &coopts)) < 0)
                goto out;
 
@@ -412,9 +415,9 @@ int git_worktree_add(git_worktree **out, git_repository *repo,
                goto out;
 
 out:
-       git_buf_dispose(&gitdir);
-       git_buf_dispose(&wddir);
-       git_buf_dispose(&buf);
+       git_str_dispose(&gitdir);
+       git_str_dispose(&wddir);
+       git_str_dispose(&buf);
        git_reference_free(ref);
        git_reference_free(head);
        git_commit_free(commit);
@@ -425,7 +428,7 @@ out:
 
 int git_worktree_lock(git_worktree *wt, const char *reason)
 {
-       git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT, path = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(wt);
@@ -437,11 +440,11 @@ int git_worktree_lock(git_worktree *wt, const char *reason)
                goto out;
        }
 
-       if ((error = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0)
+       if ((error = git_str_joinpath(&path, wt->gitdir_path, "locked")) < 0)
                goto out;
 
        if (reason)
-               git_buf_attach_notowned(&buf, reason, strlen(reason));
+               git_str_attach_notowned(&buf, reason, strlen(reason));
 
        if ((error = git_futils_writebuffer(&buf, path.ptr, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0)
                goto out;
@@ -449,14 +452,14 @@ int git_worktree_lock(git_worktree *wt, const char *reason)
        wt->locked = 1;
 
 out:
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return error;
 }
 
 int git_worktree_unlock(git_worktree *wt)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        int error;
 
        GIT_ASSERT_ARG(wt);
@@ -466,42 +469,61 @@ int git_worktree_unlock(git_worktree *wt)
        if (!error)
                return 1;
 
-       if (git_buf_joinpath(&path, wt->gitdir_path, "locked") < 0)
+       if (git_str_joinpath(&path, wt->gitdir_path, "locked") < 0)
                return -1;
 
        if (p_unlink(path.ptr) != 0) {
-               git_buf_dispose(&path);
+               git_str_dispose(&path);
                return -1;
        }
 
        wt->locked = 0;
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return 0;
 }
 
-int git_worktree_is_locked(git_buf *reason, const git_worktree *wt)
+static int git_worktree__is_locked(git_str *reason, const git_worktree *wt)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        int error, locked;
 
        GIT_ASSERT_ARG(wt);
 
        if (reason)
-               git_buf_clear(reason);
+               git_str_clear(reason);
 
-       if ((error = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0)
+       if ((error = git_str_joinpath(&path, wt->gitdir_path, "locked")) < 0)
                goto out;
-       locked = git_path_exists(path.ptr);
+       locked = git_fs_path_exists(path.ptr);
        if (locked && reason &&
            (error = git_futils_readbuffer(reason, path.ptr)) < 0)
                goto out;
 
        error = locked;
 out:
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
+
+       return error;
+}
+
+int git_worktree_is_locked(git_buf *reason, const git_worktree *wt)
+{
+       git_str str = GIT_STR_INIT;
+       int error = 0;
+
+       if (reason && (error = git_buf_tostr(&str, reason)) < 0)
+               return error;
+
+       error = git_worktree__is_locked(reason ? &str : NULL, wt);
+
+       if (error >= 0 && reason) {
+               if (git_buf_fromstr(reason, &str) < 0)
+                       error = -1;
+       }
 
+       git_str_dispose(&str);
        return error;
 }
 
@@ -547,17 +569,17 @@ int git_worktree_is_prunable(git_worktree *wt,
                memcpy(&popts, opts, sizeof(popts));
 
        if ((popts.flags & GIT_WORKTREE_PRUNE_LOCKED) == 0) {
-               git_buf reason = GIT_BUF_INIT;
+               git_str reason = GIT_STR_INIT;
                int error;
 
-               if ((error = git_worktree_is_locked(&reason, wt)) < 0)
+               if ((error = git_worktree__is_locked(&reason, wt)) < 0)
                        return error;
 
                if (error) {
                        if (!reason.size)
-                               git_buf_attach_notowned(&reason, "no reason given", 15);
+                               git_str_attach_notowned(&reason, "no reason given", 15);
                        git_error_set(GIT_ERROR_WORKTREE, "not pruning locked working tree: '%s'", reason.ptr);
-                       git_buf_dispose(&reason);
+                       git_str_dispose(&reason);
                        return 0;
                }
        }
@@ -575,7 +597,7 @@ int git_worktree_prune(git_worktree *wt,
        git_worktree_prune_options *opts)
 {
        git_worktree_prune_options popts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        char *wtpath;
        int err;
 
@@ -592,9 +614,9 @@ int git_worktree_prune(git_worktree *wt,
        }
 
        /* Delete gitdir in parent repository */
-       if ((err = git_buf_join3(&path, '/', wt->commondir_path, "worktrees", wt->name)) < 0)
+       if ((err = git_str_join3(&path, '/', wt->commondir_path, "worktrees", wt->name)) < 0)
                goto out;
-       if (!git_path_exists(path.ptr))
+       if (!git_fs_path_exists(path.ptr))
        {
                git_error_set(GIT_ERROR_WORKTREE, "worktree gitdir '%s' does not exist", path.ptr);
                err = -1;
@@ -606,15 +628,15 @@ int git_worktree_prune(git_worktree *wt,
        /* Skip deletion of the actual working tree if it does
         * not exist or deletion was not requested */
        if ((popts.flags & GIT_WORKTREE_PRUNE_WORKING_TREE) == 0 ||
-               !git_path_exists(wt->gitlink_path))
+               !git_fs_path_exists(wt->gitlink_path))
        {
                goto out;
        }
 
-       if ((wtpath = git_path_dirname(wt->gitlink_path)) == NULL)
+       if ((wtpath = git_fs_path_dirname(wt->gitlink_path)) == NULL)
                goto out;
-       git_buf_attach(&path, wtpath, 0);
-       if (!git_path_exists(path.ptr))
+       git_str_attach(&path, wtpath, 0);
+       if (!git_fs_path_exists(path.ptr))
        {
                git_error_set(GIT_ERROR_WORKTREE, "working tree '%s' does not exist", path.ptr);
                err = -1;
@@ -624,7 +646,7 @@ int git_worktree_prune(git_worktree *wt,
                goto out;
 
 out:
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        return err;
 }
index 1d40c3a5ddb3cd37537f504c442ca1e83ed1e76a..587189f81a2d762395a4d86e93cd59b24ac36d19 100644 (file)
@@ -31,7 +31,7 @@ struct git_worktree {
        /* Path to the parent's working directory */
        char *parent_path;
 
-       int locked:1;
+       unsigned int locked:1;
 };
 
 char *git_worktree__read_link(const char *base, const char *file);
diff --git a/src/xdiff/git-xdiff.h b/src/xdiff/git-xdiff.h
new file mode 100644 (file)
index 0000000..b75dba8
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file provides the necessary indirection between xdiff and
+ * libgit2.  libgit2-specific functionality should live here, so
+ * that git and libgit2 can share a common xdiff implementation.
+ */
+
+#ifndef INCLUDE_git_xdiff_h__
+#define INCLUDE_git_xdiff_h__
+
+#include "regexp.h"
+
+/* Work around C90-conformance issues */
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
+# if defined(_MSC_VER)
+#  define inline __inline
+# elif defined(__GNUC__)
+#  define inline __inline__
+# else
+#  define inline
+# endif
+#endif
+
+#define xdl_malloc(x) git__malloc(x)
+#define xdl_free(ptr) git__free(ptr)
+#define xdl_realloc(ptr, x) git__realloc(ptr, x)
+
+#define XDL_BUG(msg) GIT_ASSERT(msg)
+
+#define xdl_regex_t git_regexp
+#define xdl_regmatch_t git_regmatch
+
+GIT_INLINE(int) xdl_regexec_buf(
+       const xdl_regex_t *preg, const char *buf, size_t size,
+       size_t nmatch, xdl_regmatch_t pmatch[], int eflags)
+{
+       GIT_UNUSED(preg);
+       GIT_UNUSED(buf);
+       GIT_UNUSED(size);
+       GIT_UNUSED(nmatch);
+       GIT_UNUSED(pmatch);
+       GIT_UNUSED(eflags);
+       GIT_ASSERT("not implemented");
+       return -1;
+}
+
+#endif
index 5b13e77a0d3eda8e4f7a9192d62a712f3ccf567e..fb47f63fbf77119d15bc504bc4e087e94c1e4c24 100644 (file)
@@ -27,6 +27,8 @@
 extern "C" {
 #endif /* #ifdef __cplusplus */
 
+#include "git-xdiff.h"
+
 /* xpparm_t.flags */
 #define XDF_NEED_MINIMAL (1 << 0)
 
@@ -50,16 +52,9 @@ extern "C" {
 
 /* xdemitconf_t.flags */
 #define XDL_EMIT_FUNCNAMES (1 << 0)
+#define XDL_EMIT_NO_HUNK_HDR (1 << 1)
 #define XDL_EMIT_FUNCCONTEXT (1 << 2)
 
-#define XDL_MMB_READONLY (1 << 0)
-
-#define XDL_MMF_ATOMIC (1 << 0)
-
-#define XDL_BDOP_INS 1
-#define XDL_BDOP_CPY 2
-#define XDL_BDOP_INSB 3
-
 /* merge simplification levels */
 #define XDL_MERGE_MINIMAL 0
 #define XDL_MERGE_EAGER 1
@@ -73,20 +68,25 @@ extern "C" {
 
 /* merge output styles */
 #define XDL_MERGE_DIFF3 1
+#define XDL_MERGE_ZEALOUS_DIFF3 2
 
 typedef struct s_mmfile {
        char *ptr;
-       size_t size;
+       long size;
 } mmfile_t;
 
 typedef struct s_mmbuffer {
        char *ptr;
-       size_t size;
+       long size;
 } mmbuffer_t;
 
 typedef struct s_xpparam {
        unsigned long flags;
 
+       /* -I<regex> */
+       xdl_regex_t **ignore_regex;
+       size_t ignore_regex_nr;
+
        /* See Documentation/diff-options.txt. */
        char **anchors;
        size_t anchors_nr;
@@ -94,7 +94,11 @@ typedef struct s_xpparam {
 
 typedef struct s_xdemitcb {
        void *priv;
-       int (*outf)(void *, mmbuffer_t *, int);
+       int (*out_hunk)(void *,
+                       long old_begin, long old_nr,
+                       long new_begin, long new_nr,
+                       const char *func, long funclen);
+       int (*out_line)(void *, mmbuffer_t *, int);
 } xdemitcb_t;
 
 typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long buffer_size, void *priv);
@@ -117,10 +121,6 @@ typedef struct s_bdiffparam {
 } bdiffparam_t;
 
 
-#define xdl_malloc(x) git__malloc(x)
-#define xdl_free(ptr) git__free(ptr)
-#define xdl_realloc(ptr,x) git__realloc(ptr,x)
-
 void *xdl_mmfile_first(mmfile_t *mmf, long *size);
 long xdl_mmfile_size(mmfile_t *mmf);
 
index 916295b448f92b601bfd933ee8bf388100800fc9..af31b7f4b39d961faad642127a49383803516fb6 100644 (file)
@@ -21,8 +21,6 @@
  */
 
 #include "xinclude.h"
-#include "integer.h"
-
 
 #define XDL_MAX_COST_MIN 256
 #define XDL_HEUR_MIN_COST 256
 #define XDL_SNAKE_CNT 20
 #define XDL_K_HEUR 4
 
-/** Declare a function as always inlined. */
-#if defined(_MSC_VER)
-# define XDL_INLINE(type) static __inline type
-#elif defined(__GNUC__)
-# define XDL_INLINE(type) static __inline__ type
-#else
-# define XDL_INLINE(type) static type
-#endif
-
 typedef struct s_xdpsplit {
        long i1, i2;
        int min_lo, min_hi;
 } xdpsplit_t;
 
-
-
-
-static long xdl_split(unsigned long const *ha1, long off1, long lim1,
-                     unsigned long const *ha2, long off2, long lim2,
-                     long *kvdf, long *kvdb, int need_min, xdpsplit_t *spl,
-                     xdalgoenv_t *xenv);
-static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1, long chg2);
-
-
-
-
-
 /*
  * See "An O(ND) Difference Algorithm and its Variations", by Eugene Myers.
  * Basically considers a "box" (off1, off2, lim1, lim2) and scan from both
  * the forward diagonal starting from (off1, off2) and the backward diagonal
  * starting from (lim1, lim2). If the K values on the same diagonal crosses
- * returns the furthest point of reach. We might end up having to expensive
- * cases using this algorithm is full, so a little bit of heuristic is needed
- * to cut the search and to return a suboptimal point.
+ * returns the furthest point of reach. We might encounter expensive edge cases
+ * using this algorithm, so a little bit of heuristic is needed to cut the
+ * search and to return a suboptimal point.
  */
 static long xdl_split(unsigned long const *ha1, long off1, long lim1,
                      unsigned long const *ha2, long off2, long lim2,
@@ -87,11 +63,13 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
                int got_snake = 0;
 
                /*
-                * We need to extent the diagonal "domain" by one. If the next
+                * We need to extend the diagonal "domain" by one. If the next
                 * values exits the box boundaries we need to change it in the
-                * opposite direction because (max - min) must be a power of two.
+                * opposite direction because (max - min) must be a power of
+                * two.
+                *
                 * Also we initialize the external K value to -1 so that we can
-                * avoid extra conditions check inside the core loop.
+                * avoid extra conditions in the check inside the core loop.
                 */
                if (fmin > dmin)
                        kvdf[--fmin - 1] = -1;
@@ -122,11 +100,13 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
                }
 
                /*
-                * We need to extent the diagonal "domain" by one. If the next
+                * We need to extend the diagonal "domain" by one. If the next
                 * values exits the box boundaries we need to change it in the
-                * opposite direction because (max - min) must be a power of two.
+                * opposite direction because (max - min) must be a power of
+                * two.
+                *
                 * Also we initialize the external K value to -1 so that we can
-                * avoid extra conditions check inside the core loop.
+                * avoid extra conditions in the check inside the core loop.
                 */
                if (bmin > dmin)
                        kvdb[--bmin - 1] = XDL_LINE_MAX;
@@ -162,7 +142,7 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
                /*
                 * If the edit cost is above the heuristic trigger and if
                 * we got a good snake, we sample current diagonals to see
-                * if some of the, have reached an "interesting" path. Our
+                * if some of them have reached an "interesting" path. Our
                 * measure is a function of the distance from the diagonal
                 * corner (i1 + i2) penalized with the distance from the
                 * mid diagonal itself. If this value is above the current
@@ -220,8 +200,9 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
                }
 
                /*
-                * Enough is enough. We spent too much time here and now we collect
-                * the furthest reaching path using the (i1 + i2) measure.
+                * Enough is enough. We spent too much time here and now we
+                * collect the furthest reaching path using the (i1 + i2)
+                * measure.
                 */
                if (ec >= xenv->mxcost) {
                        long fbest, fbest1, bbest, bbest1;
@@ -268,9 +249,9 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
 
 
 /*
- * Rule: "Divide et Impera". Recursively split the box in sub-boxes by calling
- * the box splitting function. Note that the real job (marking changed lines)
- * is done in the two boundary reaching checks.
+ * Rule: "Divide et Impera" (divide & conquer). Recursively split the box in
+ * sub-boxes by calling the box splitting function. Note that the real job
+ * (marking changed lines) is done in the two boundary reaching checks.
  */
 int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1,
                 diffdata_t *dd2, long off2, long lim2,
@@ -330,7 +311,7 @@ int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1,
 
 int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
                xdfenv_t *xe) {
-       size_t ndiags, allocsize;
+       long ndiags;
        long *kvd, *kvdf, *kvdb;
        xdalgoenv_t xenv;
        diffdata_t dd1, dd2;
@@ -347,15 +328,14 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
        }
 
        /*
-        * Allocate and setup K vectors to be used by the differential algorithm.
+        * Allocate and setup K vectors to be used by the differential
+        * algorithm.
+        *
         * One is to store the forward path and one to store the backward path.
         */
-       GIT_ERROR_CHECK_ALLOC_ADD3(&ndiags, xe->xdf1.nreff, xe->xdf2.nreff, 3);
-       GIT_ERROR_CHECK_ALLOC_MULTIPLY(&allocsize, ndiags, 2);
-       GIT_ERROR_CHECK_ALLOC_ADD(&allocsize, allocsize, 2);
-       GIT_ERROR_CHECK_ALLOC_MULTIPLY(&allocsize, allocsize, sizeof(long));
+       ndiags = xe->xdf1.nreff + xe->xdf2.nreff + 3;
+       if (!(kvd = (long *) xdl_malloc((2 * ndiags + 2) * sizeof(long)))) {
 
-       if (!(kvd = (long *) xdl_malloc(allocsize))) {
                xdl_free_env(xe);
                return -1;
        }
@@ -410,19 +390,16 @@ static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1,
 }
 
 
-static int recs_match(xrecord_t *rec1, xrecord_t *rec2, long flags)
+static int recs_match(xrecord_t *rec1, xrecord_t *rec2)
 {
-       return (rec1->ha == rec2->ha &&
-               xdl_recmatch(rec1->ptr, rec1->size,
-                            rec2->ptr, rec2->size,
-                            flags));
+       return (rec1->ha == rec2->ha);
 }
 
 /*
  * If a line is indented more than this, get_indent() just returns this value.
  * This avoids having to do absurd amounts of work for data that are not
- * human-readable text, and also ensures that the output of get_indent fits within
- * an int.
+ * human-readable text, and also ensures that the output of get_indent fits
+ * within an int.
  */
 #define MAX_INDENT 200
 
@@ -456,9 +433,9 @@ static int get_indent(xrecord_t *rec)
 }
 
 /*
- * If more than this number of consecutive blank rows are found, just return this
- * value. This avoids requiring O(N^2) work for pathological cases, and also
- * ensures that the output of score_split fits in an int.
+ * If more than this number of consecutive blank rows are found, just return
+ * this value. This avoids requiring O(N^2) work for pathological cases, and
+ * also ensures that the output of score_split fits in an int.
  */
 #define MAX_BLANKS 20
 
@@ -470,8 +447,8 @@ struct split_measurement {
        int end_of_file;
 
        /*
-        * How much is the line immediately following the split indented (or -1 if
-        * the line is blank):
+        * How much is the line immediately following the split indented (or -1
+        * if the line is blank):
         */
        int indent;
 
@@ -481,8 +458,8 @@ struct split_measurement {
        int pre_blank;
 
        /*
-        * How much is the nearest non-blank line above the split indented (or -1
-        * if there is no such line)?
+        * How much is the nearest non-blank line above the split indented (or
+        * -1 if there is no such line)?
         */
        int pre_indent;
 
@@ -601,15 +578,20 @@ static void measure_split(const xdfile_t *xdf, long split,
  */
 #define INDENT_WEIGHT 60
 
+/*
+ * How far do we slide a hunk at most?
+ */
+#define INDENT_HEURISTIC_MAX_SLIDING 100
+
 /*
  * Compute a badness score for the hypothetical split whose measurements are
- * stored in m. The weight factors were determined empirically using the tools and
- * corpus described in
+ * stored in m. The weight factors were determined empirically using the tools
+ * and corpus described in
  *
  *     https://github.com/mhagger/diff-slider-tools
  *
- * Also see that project if you want to improve the weights based on, for example,
- * a larger or more diverse corpus.
+ * Also see that project if you want to improve the weights based on, for
+ * example, a larger or more diverse corpus.
  */
 static void score_add_split(const struct split_measurement *m, struct split_score *s)
 {
@@ -741,7 +723,7 @@ static void group_init(xdfile_t *xdf, struct xdlgroup *g)
  * Move g to describe the next (possibly empty) group in xdf and return 0. If g
  * is already at the end of the file, do nothing and return -1.
  */
-XDL_INLINE(int) group_next(xdfile_t *xdf, struct xdlgroup *g)
+static inline int group_next(xdfile_t *xdf, struct xdlgroup *g)
 {
        if (g->end == xdf->nrec)
                return -1;
@@ -757,7 +739,7 @@ XDL_INLINE(int) group_next(xdfile_t *xdf, struct xdlgroup *g)
  * Move g to describe the previous (possibly empty) group in xdf and return 0.
  * If g is already at the beginning of the file, do nothing and return -1.
  */
-XDL_INLINE(int) group_previous(xdfile_t *xdf, struct xdlgroup *g)
+static inline int group_previous(xdfile_t *xdf, struct xdlgroup *g)
 {
        if (g->start == 0)
                return -1;
@@ -774,10 +756,10 @@ XDL_INLINE(int) group_previous(xdfile_t *xdf, struct xdlgroup *g)
  * following group, expand this group to include it. Return 0 on success or -1
  * if g cannot be slid down.
  */
-static int group_slide_down(xdfile_t *xdf, struct xdlgroup *g, long flags)
+static int group_slide_down(xdfile_t *xdf, struct xdlgroup *g)
 {
        if (g->end < xdf->nrec &&
-           recs_match(xdf->recs[g->start], xdf->recs[g->end], flags)) {
+           recs_match(xdf->recs[g->start], xdf->recs[g->end])) {
                xdf->rchg[g->start++] = 0;
                xdf->rchg[g->end++] = 1;
 
@@ -795,10 +777,10 @@ static int group_slide_down(xdfile_t *xdf, struct xdlgroup *g, long flags)
  * into a previous group, expand this group to include it. Return 0 on success
  * or -1 if g cannot be slid up.
  */
-static int group_slide_up(xdfile_t *xdf, struct xdlgroup *g, long flags)
+static int group_slide_up(xdfile_t *xdf, struct xdlgroup *g)
 {
        if (g->start > 0 &&
-           recs_match(xdf->recs[g->start - 1], xdf->recs[g->end - 1], flags)) {
+           recs_match(xdf->recs[g->start - 1], xdf->recs[g->end - 1])) {
                xdf->rchg[--g->start] = 1;
                xdf->rchg[--g->end] = 0;
 
@@ -811,12 +793,6 @@ static int group_slide_up(xdfile_t *xdf, struct xdlgroup *g, long flags)
        }
 }
 
-static void xdl_bug(const char *msg)
-{
-       fprintf(stderr, "BUG: %s\n", msg);
-       exit(1);
-}
-
 /*
  * Move back and forward change groups for a consistent and pretty diff output.
  * This also helps in finding joinable change groups and reducing the diff
@@ -831,13 +807,16 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
        group_init(xdfo, &go);
 
        while (1) {
-               /* If the group is empty in the to-be-compacted file, skip it: */
+               /*
+                * If the group is empty in the to-be-compacted file, skip it:
+                */
                if (g.end == g.start)
                        goto next;
 
                /*
                 * Now shift the change up and then down as far as possible in
-                * each direction. If it bumps into any other changes, merge them.
+                * each direction. If it bumps into any other changes, merge
+                * them.
                 */
                do {
                        groupsize = g.end - g.start;
@@ -851,9 +830,9 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
                        end_matching_other = -1;
 
                        /* Shift the group backward as much as possible: */
-                       while (!group_slide_up(xdf, &g, flags))
+                       while (!group_slide_up(xdf, &g))
                                if (group_previous(xdfo, &go))
-                                       xdl_bug("group sync broken sliding up");
+                                       XDL_BUG("group sync broken sliding up");
 
                        /*
                         * This is this highest that this group can be shifted.
@@ -866,10 +845,10 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
 
                        /* Now shift the group forward as far as possible: */
                        while (1) {
-                               if (group_slide_down(xdf, &g, flags))
+                               if (group_slide_down(xdf, &g))
                                        break;
                                if (group_next(xdfo, &go))
-                                       xdl_bug("group sync broken sliding down");
+                                       XDL_BUG("group sync broken sliding down");
 
                                if (go.end > go.start)
                                        end_matching_other = g.end;
@@ -880,40 +859,46 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
                 * If the group can be shifted, then we can possibly use this
                 * freedom to produce a more intuitive diff.
                 *
-                * The group is currently shifted as far down as possible, so the
-                * heuristics below only have to handle upwards shifts.
+                * The group is currently shifted as far down as possible, so
+                * the heuristics below only have to handle upwards shifts.
                 */
 
                if (g.end == earliest_end) {
                        /* no shifting was possible */
                } else if (end_matching_other != -1) {
                        /*
-                        * Move the possibly merged group of changes back to line
-                        * up with the last group of changes from the other file
-                        * that it can align with.
+                        * Move the possibly merged group of changes back to
+                        * line up with the last group of changes from the
+                        * other file that it can align with.
                         */
                        while (go.end == go.start) {
-                               if (group_slide_up(xdf, &g, flags))
-                                       xdl_bug("match disappeared");
+                               if (group_slide_up(xdf, &g))
+                                       XDL_BUG("match disappeared");
                                if (group_previous(xdfo, &go))
-                                       xdl_bug("group sync broken sliding to match");
+                                       XDL_BUG("group sync broken sliding to match");
                        }
                } else if (flags & XDF_INDENT_HEURISTIC) {
                        /*
                         * Indent heuristic: a group of pure add/delete lines
-                        * implies two splits, one between the end of the "before"
-                        * context and the start of the group, and another between
-                        * the end of the group and the beginning of the "after"
-                        * context. Some splits are aesthetically better and some
-                        * are worse. We compute a badness "score" for each split,
-                        * and add the scores for the two splits to define a
-                        * "score" for each position that the group can be shifted
-                        * to. Then we pick the shift with the lowest score.
+                        * implies two splits, one between the end of the
+                        * "before" context and the start of the group, and
+                        * another between the end of the group and the
+                        * beginning of the "after" context. Some splits are
+                        * aesthetically better and some are worse. We compute
+                        * a badness "score" for each split, and add the scores
+                        * for the two splits to define a "score" for each
+                        * position that the group can be shifted to. Then we
+                        * pick the shift with the lowest score.
                         */
                        long shift, best_shift = -1;
                        struct split_score best_score;
 
-                       for (shift = earliest_end; shift <= g.end; shift++) {
+                       shift = earliest_end;
+                       if (g.end - groupsize - 1 > shift)
+                               shift = g.end - groupsize - 1;
+                       if (g.end - INDENT_HEURISTIC_MAX_SLIDING > shift)
+                               shift = g.end - INDENT_HEURISTIC_MAX_SLIDING;
+                       for (; shift <= g.end; shift++) {
                                struct split_measurement m;
                                struct split_score score = {0, 0};
 
@@ -930,10 +915,10 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
                        }
 
                        while (g.end > best_shift) {
-                               if (group_slide_up(xdf, &g, flags))
-                                       xdl_bug("best shift unreached");
+                               if (group_slide_up(xdf, &g))
+                                       XDL_BUG("best shift unreached");
                                if (group_previous(xdfo, &go))
-                                       xdl_bug("group sync broken sliding to blank line");
+                                       XDL_BUG("group sync broken sliding to blank line");
                        }
                }
 
@@ -942,11 +927,11 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
                if (group_next(xdf, &g))
                        break;
                if (group_next(xdfo, &go))
-                       xdl_bug("group sync broken moving to next group");
+                       XDL_BUG("group sync broken moving to next group");
        }
 
        if (!group_next(xdfo, &go))
-               xdl_bug("group sync broken at end of file");
+               XDL_BUG("group sync broken at end of file");
 
        return 0;
 }
@@ -992,8 +977,6 @@ static int xdl_call_hunk_func(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
 {
        xdchange_t *xch, *xche;
 
-       (void)xe;
-
        for (xch = xscr; xch; xch = xche->next) {
                xche = xdl_get_hunk(&xch, xecfg);
                if (!xch)
@@ -1006,7 +989,7 @@ static int xdl_call_hunk_func(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
        return 0;
 }
 
-static void xdl_mark_ignorable(xdchange_t *xscr, xdfenv_t *xe, long flags)
+static void xdl_mark_ignorable_lines(xdchange_t *xscr, xdfenv_t *xe, long flags)
 {
        xdchange_t *xch;
 
@@ -1027,6 +1010,46 @@ static void xdl_mark_ignorable(xdchange_t *xscr, xdfenv_t *xe, long flags)
        }
 }
 
+static int record_matches_regex(xrecord_t *rec, xpparam_t const *xpp) {
+       xdl_regmatch_t regmatch;
+       int i;
+
+       for (i = 0; i < xpp->ignore_regex_nr; i++)
+               if (!xdl_regexec_buf(xpp->ignore_regex[i], rec->ptr, rec->size, 1,
+                                &regmatch, 0))
+                       return 1;
+
+       return 0;
+}
+
+static void xdl_mark_ignorable_regex(xdchange_t *xscr, const xdfenv_t *xe,
+                                    xpparam_t const *xpp)
+{
+       xdchange_t *xch;
+
+       for (xch = xscr; xch; xch = xch->next) {
+               xrecord_t **rec;
+               int ignore = 1;
+               long i;
+
+               /*
+                * Do not override --ignore-blank-lines.
+                */
+               if (xch->ignore)
+                       continue;
+
+               rec = &xe->xdf1.recs[xch->i1];
+               for (i = 0; i < xch->chg1 && ignore; i++)
+                       ignore = record_matches_regex(rec[i], xpp);
+
+               rec = &xe->xdf2.recs[xch->i2];
+               for (i = 0; i < xch->chg2 && ignore; i++)
+                       ignore = record_matches_regex(rec[i], xpp);
+
+               xch->ignore = ignore;
+       }
+}
+
 int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
             xdemitconf_t const *xecfg, xdemitcb_t *ecb) {
        xdchange_t *xscr;
@@ -1046,7 +1069,10 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
        }
        if (xscr) {
                if (xpp->flags & XDF_IGNORE_BLANK_LINES)
-                       xdl_mark_ignorable(xscr, &xe, xpp->flags);
+                       xdl_mark_ignorable_lines(xscr, &xe, xpp->flags);
+
+               if (xpp->ignore_regex)
+                       xdl_mark_ignorable_regex(xscr, &xe, xpp);
 
                if (ef(&xe, xscr, ecb, xecfg) < 0) {
 
index 0ffa6553aa991946588c84ff8af3143ac24ec1f4..1cbf2b9829e759dd20f5e714d1390b26fe8cdd3d 100644 (file)
@@ -31,7 +31,7 @@ static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec) {
 
 
 static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb) {
-       long size, psize = (long)strlen(pre);
+       long size, psize = strlen(pre);
        char const *rec;
 
        size = xdl_get_rec(xdf, ri, &rec);
@@ -81,7 +81,7 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg)
                } else if (distance < max_ignorable && xch->ignore) {
                        ignored += xch->chg2;
                } else if (lxch != xchp &&
-                          xch->i1 + ignored - (lxch->i1 + lxch->chg1) > (unsigned long)max_common) {
+                          xch->i1 + ignored - (lxch->i1 + lxch->chg1) > max_common) {
                        break;
                } else if (!xch->ignore) {
                        lxch = xch;
@@ -97,8 +97,6 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg)
 
 static long def_ff(const char *rec, long len, char *buf, long sz, void *priv)
 {
-       (void)priv;
-
        if (len > 0 &&
                        (isalpha((unsigned char)*rec) || /* identifier? */
                         *rec == '_' || /* also identifier? */
@@ -174,10 +172,12 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
        struct func_line func_line = { 0 };
 
        for (xch = xscr; xch; xch = xche->next) {
+               xdchange_t *xchp = xch;
                xche = xdl_get_hunk(&xch, xecfg);
                if (!xch)
                        break;
 
+pre_context_calculation:
                s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0);
                s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0);
 
@@ -212,8 +212,23 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
                        if (fs1 < 0)
                                fs1 = 0;
                        if (fs1 < s1) {
-                               s2 -= s1 - fs1;
+                               s2 = XDL_MAX(s2 - (s1 - fs1), 0);
                                s1 = fs1;
+
+                               /*
+                                * Did we extend context upwards into an
+                                * ignored change?
+                                */
+                               while (xchp != xch &&
+                                      xchp->i1 + xchp->chg1 <= s1 &&
+                                      xchp->i2 + xchp->chg2 <= s2)
+                                       xchp = xchp->next;
+
+                               /* If so, show it after all. */
+                               if (xchp != xch) {
+                                       xch = xchp;
+                                       goto pre_context_calculation;
+                               }
                        }
                }
 
@@ -234,7 +249,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
                        if (fe1 < 0)
                                fe1 = xe->xdf1.nrec;
                        if (fe1 > e1) {
-                               e2 += fe1 - e1;
+                               e2 = XDL_MIN(e2 + (fe1 - e1), xe->xdf2.nrec);
                                e1 = fe1;
                        }
 
@@ -263,7 +278,8 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
                                      s1 - 1, funclineprev);
                        funclineprev = s1 - 1;
                }
-               if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2,
+               if (!(xecfg->flags & XDL_EMIT_NO_HUNK_HDR) &&
+                   xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2,
                                      func_line.buf, func_line.len, ecb) < 0)
                        return -1;
 
index 00bbfcec4f02103edff65ad35daef03c25a24129..80794748b0de6bb9176ce088c472d44c62b91e6d 100644 (file)
@@ -42,8 +42,6 @@
  */
 
 #include "xinclude.h"
-#include "xtypes.h"
-#include "xdiff.h"
 
 #define MAX_PTR        UINT_MAX
 #define MAX_CNT        UINT_MAX
@@ -90,27 +88,21 @@ struct region {
 #define REC(env, s, l) \
        (env->xdf##s.recs[l - 1])
 
-static int cmp_recs(xpparam_t const *xpp,
-       xrecord_t *r1, xrecord_t *r2)
+static int cmp_recs(xrecord_t *r1, xrecord_t *r2)
 {
-       return r1->ha == r2->ha &&
-               xdl_recmatch(r1->ptr, r1->size, r2->ptr, r2->size,
-                           xpp->flags);
-}
+       return r1->ha == r2->ha;
 
-#define CMP_ENV(xpp, env, s1, l1, s2, l2) \
-       (cmp_recs(xpp, REC(env, s1, l1), REC(env, s2, l2)))
+}
 
 #define CMP(i, s1, l1, s2, l2) \
-       (cmp_recs(i->xpp, REC(i->env, s1, l1), REC(i->env, s2, l2)))
+       (cmp_recs(REC(i->env, s1, l1), REC(i->env, s2, l2)))
 
 #define TABLE_HASH(index, side, line) \
        XDL_HASHLONG((REC(index->env, side, line))->ha, index->table_bits)
 
-static int scanA(struct histindex *index, unsigned int line1, unsigned int count1)
+static int scanA(struct histindex *index, int line1, int count1)
 {
-       unsigned int ptr;
-       unsigned int tbl_idx;
+       unsigned int ptr, tbl_idx;
        unsigned int chain_len;
        struct record **rec_chain, *rec;
 
@@ -161,10 +153,8 @@ continue_scan:
        return 0;
 }
 
-static int try_lcs(
-       struct histindex *index, struct region *lcs, unsigned int b_ptr,
-       unsigned int line1, unsigned int count1,
-       unsigned int line2, unsigned int count2)
+static int try_lcs(struct histindex *index, struct region *lcs, int b_ptr,
+       int line1, int count1, int line2, int count2)
 {
        unsigned int b_next = b_ptr + 1;
        struct record *rec = index->records[TABLE_HASH(index, 2, b_ptr)];
@@ -236,59 +226,33 @@ static int try_lcs(
        return b_next;
 }
 
-static int find_lcs(
-       struct histindex *index, struct region *lcs,
-       unsigned int line1, unsigned int count1,
-       unsigned int line2, unsigned int count2)
+static int fall_back_to_classic_diff(xpparam_t const *xpp, xdfenv_t *env,
+               int line1, int count1, int line2, int count2)
 {
-       unsigned int b_ptr;
-
-       if (scanA(index, line1, count1))
-               return -1;
-
-       index->cnt = index->max_chain_length + 1;
+       xpparam_t xpparam;
 
-       for (b_ptr = line2; b_ptr <= LINE_END(2); )
-               b_ptr = try_lcs(index, lcs, b_ptr, line1, count1, line2, count2);
+       memset(&xpparam, 0, sizeof(xpparam));
+       xpparam.flags = xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;
 
-       return index->has_common && index->max_chain_length < index->cnt;
+       return xdl_fall_back_diff(env, &xpparam,
+                                 line1, count1, line2, count2);
 }
 
-static int fall_back_to_classic_diff(struct histindex *index,
-               int line1, int count1, int line2, int count2)
+static inline void free_index(struct histindex *index)
 {
-       xpparam_t xpp;
-       xpp.flags = index->xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;
-
-       return xdl_fall_back_diff(index->env, &xpp,
-                                 line1, count1, line2, count2);
+       xdl_free(index->records);
+       xdl_free(index->line_map);
+       xdl_free(index->next_ptrs);
+       xdl_cha_free(&index->rcha);
 }
 
-static int histogram_diff(
-       xpparam_t const *xpp, xdfenv_t *env,
-       unsigned int line1, unsigned int count1,
-       unsigned int line2, unsigned int count2)
+static int find_lcs(xpparam_t const *xpp, xdfenv_t *env,
+                   struct region *lcs,
+                   int line1, int count1, int line2, int count2)
 {
+       int b_ptr;
+       int sz, ret = -1;
        struct histindex index;
-       struct region lcs;
-       size_t sz;
-       int result = -1;
-
-       if (count1 <= 0 && count2 <= 0)
-               return 0;
-
-       if (LINE_END(1) >= MAX_PTR)
-               return -1;
-
-       if (!count1) {
-               while(count2--)
-                       env->xdf2.rchg[line2++ - 1] = 1;
-               return 0;
-       } else if (!count2) {
-               while(count1--)
-                       env->xdf1.rchg[line1++ - 1] = 1;
-               return 0;
-       }
 
        memset(&index, 0, sizeof(index));
 
@@ -302,8 +266,7 @@ static int histogram_diff(
 
        index.table_bits = xdl_hashbits(count1);
        sz = index.records_size = 1 << index.table_bits;
-       GIT_ERROR_CHECK_ALLOC_MULTIPLY(&sz, sz, sizeof(struct record *));
-
+       sz *= sizeof(struct record *);
        if (!(index.records = (struct record **) xdl_malloc(sz)))
                goto cleanup;
        memset(index.records, 0, sz);
@@ -327,9 +290,55 @@ static int histogram_diff(
        index.ptr_shift = line1;
        index.max_chain_length = 64;
 
+       if (scanA(&index, line1, count1))
+               goto cleanup;
+
+       index.cnt = index.max_chain_length + 1;
+
+       for (b_ptr = line2; b_ptr <= LINE_END(2); )
+               b_ptr = try_lcs(&index, lcs, b_ptr, line1, count1, line2, count2);
+
+       if (index.has_common && index.max_chain_length < index.cnt)
+               ret = 1;
+       else
+               ret = 0;
+
+cleanup:
+       free_index(&index);
+       return ret;
+}
+
+static int histogram_diff(xpparam_t const *xpp, xdfenv_t *env,
+       int line1, int count1, int line2, int count2)
+{
+       struct region lcs;
+       int lcs_found;
+       int result;
+redo:
+       result = -1;
+
+       if (count1 <= 0 && count2 <= 0)
+               return 0;
+
+       if (LINE_END(1) >= MAX_PTR)
+               return -1;
+
+       if (!count1) {
+               while(count2--)
+                       env->xdf2.rchg[line2++ - 1] = 1;
+               return 0;
+       } else if (!count2) {
+               while(count1--)
+                       env->xdf1.rchg[line1++ - 1] = 1;
+               return 0;
+       }
+
        memset(&lcs, 0, sizeof(lcs));
-       if (find_lcs(&index, &lcs, line1, count1, line2, count2))
-               result = fall_back_to_classic_diff(&index, line1, count1, line2, count2);
+       lcs_found = find_lcs(xpp, env, &lcs, line1, count1, line2, count2);
+       if (lcs_found < 0)
+               goto out;
+       else if (lcs_found)
+               result = fall_back_to_classic_diff(xpp, env, line1, count1, line2, count2);
        else {
                if (lcs.begin1 == 0 && lcs.begin2 == 0) {
                        while (count1--)
@@ -342,21 +351,21 @@ static int histogram_diff(
                                                line1, lcs.begin1 - line1,
                                                line2, lcs.begin2 - line2);
                        if (result)
-                               goto cleanup;
-                       result = histogram_diff(xpp, env,
-                                               lcs.end1 + 1, LINE_END(1) - lcs.end1,
-                                               lcs.end2 + 1, LINE_END(2) - lcs.end2);
-                       if (result)
-                               goto cleanup;
+                               goto out;
+                       /*
+                        * result = histogram_diff(xpp, env,
+                        *            lcs.end1 + 1, LINE_END(1) - lcs.end1,
+                        *            lcs.end2 + 1, LINE_END(2) - lcs.end2);
+                        * but let's optimize tail recursion ourself:
+                       */
+                       count1 = LINE_END(1) - lcs.end1;
+                       line1 = lcs.end1 + 1;
+                       count2 = LINE_END(2) - lcs.end2;
+                       line2 = lcs.end2 + 1;
+                       goto redo;
                }
        }
-
-cleanup:
-       xdl_free(index.records);
-       xdl_free(index.line_map);
-       xdl_free(index.next_ptrs);
-       xdl_cha_free(&index.rcha);
-
+out:
        return result;
 }
 
index 068ce42f8e72d63486295ffb1692589381bbe7d7..75db1d8f357e5dc10a2d56a3d5951ba6f816cb41 100644 (file)
 #if !defined(XINCLUDE_H)
 #define XINCLUDE_H
 
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#ifdef _WIN32
-#else
-#include <unistd.h>
-#endif
-
+#include "git-xdiff.h"
 #include "xmacros.h"
 #include "xdiff.h"
 #include "xtypes.h"
@@ -42,6 +32,5 @@
 #include "xdiffi.h"
 #include "xemit.h"
 
-#include "common.h"
 
 #endif /* #if !defined(XINCLUDE_H) */
index 278cbe1242997ed2e3f062ea853fa152ddf4c9ad..433e2d7415748aaeb84cb1600ec3dcd20cde09c2 100644 (file)
@@ -88,7 +88,7 @@ static int xdl_cleanup_merge(xdmerge_t *c)
                if (c->mode == 0)
                        count++;
                next_c = c->next;
-               free(c);
+               xdl_free(c);
        }
        return count;
 }
@@ -109,53 +109,44 @@ static int xdl_merge_cmp_lines(xdfenv_t *xe1, int i1, xdfenv_t *xe2, int i2,
        return 0;
 }
 
-static int xdl_recs_copy_0(size_t *out, int use_orig, xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
+static int xdl_recs_copy_0(int use_orig, xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
 {
        xrecord_t **recs;
-       size_t size = 0;
-
-       *out = 0;
+       int size = 0;
 
        recs = (use_orig ? xe->xdf1.recs : xe->xdf2.recs) + i;
 
        if (count < 1)
                return 0;
 
-       for (i = 0; i < count; ) {
+       for (i = 0; i < count; size += recs[i++]->size)
                if (dest)
                        memcpy(dest + size, recs[i]->ptr, recs[i]->size);
-
-               GIT_ERROR_CHECK_ALLOC_ADD(&size, size, recs[i++]->size);
-       }
-
        if (add_nl) {
                i = recs[count - 1]->size;
                if (i == 0 || recs[count - 1]->ptr[i - 1] != '\n') {
                        if (needs_cr) {
                                if (dest)
                                        dest[size] = '\r';
-                               GIT_ERROR_CHECK_ALLOC_ADD(&size, size, 1);
+                               size++;
                        }
 
                        if (dest)
                                dest[size] = '\n';
-
-                       GIT_ERROR_CHECK_ALLOC_ADD(&size, size, 1);
+                       size++;
                }
        }
-
-       *out = size;
-       return 0;
+       return size;
 }
 
-static int xdl_recs_copy(size_t *out, xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
+static int xdl_recs_copy(xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
 {
-       return xdl_recs_copy_0(out, 0, xe, i, count, needs_cr, add_nl, dest);
+       return xdl_recs_copy_0(0, xe, i, count, needs_cr, add_nl, dest);
 }
 
-static int xdl_orig_copy(size_t *out, xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
+static int xdl_orig_copy(xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
 {
-       return xdl_recs_copy_0(out, 1, xe, i, count, needs_cr, add_nl, dest);
+       return xdl_recs_copy_0(1, xe, i, count, needs_cr, add_nl, dest);
 }
 
 /*
@@ -202,32 +193,26 @@ static int is_cr_needed(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m)
        return needs_cr < 0 ? 0 : needs_cr;
 }
 
-static int fill_conflict_hunk(size_t *out, xdfenv_t *xe1, const char *name1,
+static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
                              xdfenv_t *xe2, const char *name2,
                              const char *name3,
-                             size_t size, int i, int style,
+                             int size, int i, int style,
                              xdmerge_t *m, char *dest, int marker_size)
 {
-       int marker1_size = (name1 ? (int)strlen(name1) + 1 : 0);
-       int marker2_size = (name2 ? (int)strlen(name2) + 1 : 0);
-       int marker3_size = (name3 ? (int)strlen(name3) + 1 : 0);
+       int marker1_size = (name1 ? strlen(name1) + 1 : 0);
+       int marker2_size = (name2 ? strlen(name2) + 1 : 0);
+       int marker3_size = (name3 ? strlen(name3) + 1 : 0);
        int needs_cr = is_cr_needed(xe1, xe2, m);
-       size_t copied;
-
-       *out = 0;
 
        if (marker_size <= 0)
                marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
 
        /* Before conflicting part */
-       if (xdl_recs_copy(&copied, xe1, i, m->i1 - i, 0, 0,
-                             dest ? dest + size : NULL) < 0)
-               return -1;
-
-       GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
+       size += xdl_recs_copy(xe1, i, m->i1 - i, 0, 0,
+                             dest ? dest + size : NULL);
 
        if (!dest) {
-               GIT_ERROR_CHECK_ALLOC_ADD5(&size, size, marker_size, 1, needs_cr,  marker1_size);
+               size += marker_size + 1 + needs_cr + marker1_size;
        } else {
                memset(dest + size, '<', marker_size);
                size += marker_size;
@@ -242,16 +227,13 @@ static int fill_conflict_hunk(size_t *out, xdfenv_t *xe1, const char *name1,
        }
 
        /* Postimage from side #1 */
-       if (xdl_recs_copy(&copied, xe1, m->i1, m->chg1, needs_cr, 1,
-                             dest ? dest + size : NULL) < 0)
-               return -1;
+       size += xdl_recs_copy(xe1, m->i1, m->chg1, needs_cr, 1,
+                             dest ? dest + size : NULL);
 
-       GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
-
-       if (style == XDL_MERGE_DIFF3) {
+       if (style == XDL_MERGE_DIFF3 || style == XDL_MERGE_ZEALOUS_DIFF3) {
                /* Shared preimage */
                if (!dest) {
-                       GIT_ERROR_CHECK_ALLOC_ADD5(&size, size, marker_size, 1, needs_cr, marker3_size);
+                       size += marker_size + 1 + needs_cr + marker3_size;
                } else {
                        memset(dest + size, '|', marker_size);
                        size += marker_size;
@@ -264,15 +246,12 @@ static int fill_conflict_hunk(size_t *out, xdfenv_t *xe1, const char *name1,
                                dest[size++] = '\r';
                        dest[size++] = '\n';
                }
-
-               if (xdl_orig_copy(&copied, xe1, m->i0, m->chg0, needs_cr, 1,
-                                     dest ? dest + size : NULL) < 0)
-                       return -1;
-               GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
+               size += xdl_orig_copy(xe1, m->i0, m->chg0, needs_cr, 1,
+                                     dest ? dest + size : NULL);
        }
 
        if (!dest) {
-               GIT_ERROR_CHECK_ALLOC_ADD4(&size, size, marker_size, 1, needs_cr);
+               size += marker_size + 1 + needs_cr;
        } else {
                memset(dest + size, '=', marker_size);
                size += marker_size;
@@ -282,14 +261,10 @@ static int fill_conflict_hunk(size_t *out, xdfenv_t *xe1, const char *name1,
        }
 
        /* Postimage from side #2 */
-
-       if (xdl_recs_copy(&copied, xe2, m->i2, m->chg2, needs_cr, 1,
-                             dest ? dest + size : NULL) < 0)
-               return -1;
-       GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
-
+       size += xdl_recs_copy(xe2, m->i2, m->chg2, needs_cr, 1,
+                             dest ? dest + size : NULL);
        if (!dest) {
-               GIT_ERROR_CHECK_ALLOC_ADD5(&size, size, marker_size, 1, needs_cr, marker2_size);
+               size += marker_size + 1 + needs_cr + marker2_size;
        } else {
                memset(dest + size, '>', marker_size);
                size += marker_size;
@@ -302,71 +277,83 @@ static int fill_conflict_hunk(size_t *out, xdfenv_t *xe1, const char *name1,
                        dest[size++] = '\r';
                dest[size++] = '\n';
        }
-
-       *out = size;
-       return 0;
+       return size;
 }
 
-static int xdl_fill_merge_buffer(size_t *out,
-                                xdfenv_t *xe1, const char *name1,
+static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
                                 xdfenv_t *xe2, const char *name2,
                                 const char *ancestor_name,
                                 int favor,
                                 xdmerge_t *m, char *dest, int style,
                                 int marker_size)
 {
-       size_t size, copied;
-       int i;
-
-       *out = 0;
+       int size, i;
 
        for (size = i = 0; m; m = m->next) {
                if (favor && !m->mode)
                        m->mode = favor;
 
-               if (m->mode == 0) {
-                       if (fill_conflict_hunk(&size, xe1, name1, xe2, name2,
+               if (m->mode == 0)
+                       size = fill_conflict_hunk(xe1, name1, xe2, name2,
                                                  ancestor_name,
                                                  size, i, style, m, dest,
-                                                 marker_size) < 0)
-                               return -1;
-               }
+                                                 marker_size);
                else if (m->mode & 3) {
                        /* Before conflicting part */
-                       if (xdl_recs_copy(&copied, xe1, i, m->i1 - i, 0, 0,
-                                             dest ? dest + size : NULL) < 0)
-                               return -1;
-                       GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
-
+                       size += xdl_recs_copy(xe1, i, m->i1 - i, 0, 0,
+                                             dest ? dest + size : NULL);
                        /* Postimage from side #1 */
                        if (m->mode & 1) {
                                int needs_cr = is_cr_needed(xe1, xe2, m);
 
-                               if (xdl_recs_copy(&copied, xe1, m->i1, m->chg1, needs_cr, (m->mode & 2),
-                                                     dest ? dest + size : NULL) < 0)
-                                       return -1;
-                               GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
+                               size += xdl_recs_copy(xe1, m->i1, m->chg1, needs_cr, (m->mode & 2),
+                                                     dest ? dest + size : NULL);
                        }
-
                        /* Postimage from side #2 */
-                       if (m->mode & 2) {
-                               if (xdl_recs_copy(&copied, xe2, m->i2, m->chg2, 0, 0,
-                                                     dest ? dest + size : NULL) < 0)
-                                       return -1;
-                               GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
-                       }
+                       if (m->mode & 2)
+                               size += xdl_recs_copy(xe2, m->i2, m->chg2, 0, 0,
+                                                     dest ? dest + size : NULL);
                } else
                        continue;
                i = m->i1 + m->chg1;
        }
+       size += xdl_recs_copy(xe1, i, xe1->xdf2.nrec - i, 0, 0,
+                             dest ? dest + size : NULL);
+       return size;
+}
 
-       if (xdl_recs_copy(&copied, xe1, i, xe1->xdf2.nrec - i, 0, 0,
-                             dest ? dest + size : NULL) < 0)
-               return -1;
-       GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
+static int recmatch(xrecord_t *rec1, xrecord_t *rec2, unsigned long flags)
+{
+       return xdl_recmatch(rec1->ptr, rec1->size,
+                           rec2->ptr, rec2->size, flags);
+}
 
-       *out = size;
-       return 0;
+/*
+ * Remove any common lines from the beginning and end of the conflicted region.
+ */
+static void xdl_refine_zdiff3_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
+               xpparam_t const *xpp)
+{
+       xrecord_t **rec1 = xe1->xdf2.recs, **rec2 = xe2->xdf2.recs;
+       for (; m; m = m->next) {
+               /* let's handle just the conflicts */
+               if (m->mode)
+                       continue;
+
+               while(m->chg1 && m->chg2 &&
+                     recmatch(rec1[m->i1], rec2[m->i2], xpp->flags)) {
+                       m->chg1--;
+                       m->chg2--;
+                       m->i1++;
+                       m->i2++;
+               }
+               while (m->chg1 && m->chg2 &&
+                      recmatch(rec1[m->i1 + m->chg1 - 1],
+                               rec2[m->i2 + m->chg2 - 1], xpp->flags)) {
+                       m->chg1--;
+                       m->chg2--;
+               }
+       }
 }
 
 /*
@@ -469,7 +456,7 @@ static void xdl_merge_two_conflicts(xdmerge_t *m)
        m->chg1 = next_m->i1 + next_m->chg1 - m->i1;
        m->chg2 = next_m->i2 + next_m->chg2 - m->i2;
        m->next = next_m->next;
-       free(next_m);
+       xdl_free(next_m);
 }
 
 /*
@@ -529,7 +516,22 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1,
        int style = xmp->style;
        int favor = xmp->favor;
 
-       if (style == XDL_MERGE_DIFF3) {
+       /*
+        * XDL_MERGE_DIFF3 does not attempt to refine conflicts by looking
+        * at common areas of sides 1 & 2, because the base (side 0) does
+        * not match and is being shown.  Similarly, simplification of
+        * non-conflicts is also skipped due to the skipping of conflict
+        * refinement.
+        *
+        * XDL_MERGE_ZEALOUS_DIFF3, on the other hand, will attempt to
+        * refine conflicts looking for common areas of sides 1 & 2.
+        * However, since the base is being shown and does not match,
+        * it will only look for common areas at the beginning or end
+        * of the conflict block.  Since XDL_MERGE_ZEALOUS_DIFF3's
+        * conflict refinement is much more limited in this fashion, the
+        * conflict simplification will be skipped.
+        */
+       if (style == XDL_MERGE_DIFF3 || style == XDL_MERGE_ZEALOUS_DIFF3) {
                /*
                 * "diff3 -m" output does not make sense for anything
                 * more aggressive than XDL_MERGE_EAGER.
@@ -650,34 +652,31 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1,
        if (!changes)
                changes = c;
        /* refine conflicts */
-       if (XDL_MERGE_ZEALOUS <= level &&
-           (xdl_refine_conflicts(xe1, xe2, changes, xpp) < 0 ||
-            xdl_simplify_non_conflicts(xe1, changes,
-                                       XDL_MERGE_ZEALOUS < level) < 0)) {
+       if (style == XDL_MERGE_ZEALOUS_DIFF3) {
+               xdl_refine_zdiff3_conflicts(xe1, xe2, changes, xpp);
+       } else if (XDL_MERGE_ZEALOUS <= level &&
+                  (xdl_refine_conflicts(xe1, xe2, changes, xpp) < 0 ||
+                   xdl_simplify_non_conflicts(xe1, changes,
+                                              XDL_MERGE_ZEALOUS < level) < 0)) {
                xdl_cleanup_merge(changes);
                return -1;
        }
        /* output */
        if (result) {
                int marker_size = xmp->marker_size;
-               size_t size;
-
-               if (xdl_fill_merge_buffer(&size, xe1, name1, xe2, name2,
+               int size = xdl_fill_merge_buffer(xe1, name1, xe2, name2,
                                                 ancestor_name,
                                                 favor, changes, NULL, style,
-                                                marker_size) < 0)
-                       return -1;
-
+                                                marker_size);
                result->ptr = xdl_malloc(size);
                if (!result->ptr) {
                        xdl_cleanup_merge(changes);
                        return -1;
                }
                result->size = size;
-               if (xdl_fill_merge_buffer(&size, xe1, name1, xe2, name2,
+               xdl_fill_merge_buffer(xe1, name1, xe2, name2,
                                      ancestor_name, favor, changes,
-                                     result->ptr, style, marker_size) < 0)
-                       return -1;
+                                     result->ptr, style, marker_size);
        }
        return xdl_cleanup_merge(changes);
 }
@@ -717,22 +716,10 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, mmfile_t *mf2,
        status = 0;
        if (!xscr1) {
                result->ptr = xdl_malloc(mf2->size);
-               if (!result->ptr) {
-                       xdl_free_script(xscr2);
-                       xdl_free_env(&xe1);
-                       xdl_free_env(&xe2);
-                       return -1;
-               }
                memcpy(result->ptr, mf2->ptr, mf2->size);
                result->size = mf2->size;
        } else if (!xscr2) {
                result->ptr = xdl_malloc(mf1->size);
-               if (!result->ptr) {
-                       xdl_free_script(xscr1);
-                       xdl_free_env(&xe1);
-                       xdl_free_env(&xe2);
-                       return -1;
-               }
                memcpy(result->ptr, mf1->ptr, mf1->size);
                result->size = mf1->size;
        } else {
index 53b7d5fd17fb5ea67bdc226c9484de9afcdf6999..c5d48e80aefb33eddb4dbe4e359f2c598a5483d7 100644 (file)
@@ -20,8 +20,6 @@
  *
  */
 #include "xinclude.h"
-#include "xtypes.h"
-#include "xdiff.h"
 
 /*
  * The basic idea of patience diff is to find lines that are unique in
@@ -78,7 +76,7 @@ struct hashmap {
 
 static int is_anchor(xpparam_t const *xpp, const char *line)
 {
-       unsigned long i;
+       int i;
        for (i = 0; i < xpp->anchors_nr; i++) {
                if (!strncmp(line, xpp->anchors[i], strlen(xpp->anchors[i])))
                        return 1;
@@ -92,7 +90,7 @@ static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map,
 {
        xrecord_t **records = pass == 1 ?
                map->env->xdf1.recs : map->env->xdf2.recs;
-       xrecord_t *record = records[line - 1], *other;
+       xrecord_t *record = records[line - 1];
        /*
         * After xdl_prepare_env() (or more precisely, due to
         * xdl_classify_record()), the "ha" member of the records (AKA lines)
@@ -106,11 +104,7 @@ static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map,
        int index = (int)((record->ha << 1) % map->alloc);
 
        while (map->entries[index].line1) {
-               other = map->env->xdf1.recs[map->entries[index].line1 - 1];
-               if (map->entries[index].hash != record->ha ||
-                               !xdl_recmatch(record->ptr, record->size,
-                                       other->ptr, other->size,
-                                       map->xpp->flags)) {
+               if (map->entries[index].hash != record->ha) {
                        if (++index >= map->alloc)
                                index = 0;
                        continue;
@@ -217,9 +211,6 @@ static struct entry *find_longest_common_sequence(struct hashmap *map)
         */
        int anchor_i = -1;
 
-       if (!sequence)
-               return NULL;
-
        for (entry = map->first; entry; entry = entry->next) {
                if (!entry->line2 || entry->line2 == NON_UNIQUE)
                        continue;
@@ -258,8 +249,7 @@ static int match(struct hashmap *map, int line1, int line2)
 {
        xrecord_t *record1 = map->env->xdf1.recs[line1 - 1];
        xrecord_t *record2 = map->env->xdf2.recs[line2 - 1];
-       return xdl_recmatch(record1->ptr, record1->size,
-               record2->ptr, record2->size, map->xpp->flags);
+       return record1->ha == record2->ha;
 }
 
 static int patience_diff(mmfile_t *file1, mmfile_t *file2,
@@ -294,9 +284,6 @@ static int walk_common_sequence(struct hashmap *map, struct entry *first,
 
                /* Recurse */
                if (next1 > line1 || next2 > line2) {
-                       struct hashmap submap;
-
-                       memset(&submap, 0, sizeof(submap));
                        if (patience_diff(map->file1, map->file2,
                                        map->xpp, map->env,
                                        line1, next1 - line1,
@@ -323,6 +310,8 @@ static int fall_back_to_classic_diff(struct hashmap *map,
                int line1, int count1, int line2, int count2)
 {
        xpparam_t xpp;
+
+       memset(&xpp, 0, sizeof(xpp));
        xpp.flags = map->xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;
 
        return xdl_fall_back_diff(map->env, &xpp,
index abeb8fb84e6d73086d612b831963a227e35743b8..4527a4a07c4e0986cb377015d09f9a13309c04d8 100644 (file)
@@ -181,15 +181,11 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
        if (!(recs = (xrecord_t **) xdl_malloc(narec * sizeof(xrecord_t *))))
                goto abort;
 
-       if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF)
-               hbits = hsize = 0;
-       else {
-               hbits = xdl_hashbits((unsigned int) narec);
-               hsize = 1 << hbits;
-               if (!(rhash = (xrecord_t **) xdl_malloc(hsize * sizeof(xrecord_t *))))
-                       goto abort;
-               memset(rhash, 0, hsize * sizeof(xrecord_t *));
-       }
+       hbits = xdl_hashbits((unsigned int) narec);
+       hsize = 1 << hbits;
+       if (!(rhash = (xrecord_t **) xdl_malloc(hsize * sizeof(xrecord_t *))))
+               goto abort;
+       memset(rhash, 0, hsize * sizeof(xrecord_t *));
 
        nrec = 0;
        if ((cur = blk = xdl_mmfile_first(mf, &bsize)) != NULL) {
@@ -208,9 +204,7 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
                        crec->size = (long) (cur - prev);
                        crec->ha = hav;
                        recs[nrec++] = crec;
-
-                       if ((XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF) &&
-                           xdl_classify_record(pass, cf, rhash, hbits, crec) < 0)
+                       if (xdl_classify_record(pass, cf, rhash, hbits, crec) < 0)
                                goto abort;
                }
        }
@@ -219,10 +213,13 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
                goto abort;
        memset(rchg, 0, (nrec + 2) * sizeof(char));
 
-       if (!(rindex = (long *) xdl_malloc((nrec + 1) * sizeof(long))))
-               goto abort;
-       if (!(ha = (unsigned long *) xdl_malloc((nrec + 1) * sizeof(unsigned long))))
-               goto abort;
+       if ((XDF_DIFF_ALG(xpp->flags) != XDF_PATIENCE_DIFF) &&
+           (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF)) {
+               if (!(rindex = xdl_malloc((nrec + 1) * sizeof(*rindex))))
+                       goto abort;
+               if (!(ha = xdl_malloc((nrec + 1) * sizeof(*ha))))
+                       goto abort;
+       }
 
        xdf->nrec = nrec;
        xdf->recs = recs;
@@ -279,8 +276,7 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
        enl1 = xdl_guess_lines(mf1, sample) + 1;
        enl2 = xdl_guess_lines(mf2, sample) + 1;
 
-       if (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF &&
-           xdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0)
+       if (xdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0)
                return -1;
 
        if (xdl_prepare_ctx(1, mf1, enl1, xpp, &cf, &xe->xdf1) < 0) {
@@ -305,8 +301,7 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
                return -1;
        }
 
-       if (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF)
-               xdl_free_classifier(&cf);
+       xdl_free_classifier(&cf);
 
        return 0;
 }
index 17c9ae184b6f526069290a647cae236cb69c8ba5..cfa6e2220ffd0461ce3293911c86366f6ccb1b05 100644 (file)
@@ -23,8 +23,6 @@
 #include "xinclude.h"
 
 
-
-
 long xdl_bogosqrt(long n) {
        long i;
 
@@ -52,7 +50,7 @@ int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize,
                mb[2].size = strlen(mb[2].ptr);
                i++;
        }
-       if (ecb->outf(ecb->priv, mb, i) < 0) {
+       if (ecb->out_line(ecb->priv, mb, i) < 0) {
 
                return -1;
        }
@@ -342,8 +340,9 @@ int xdl_num_out(char *out, long val) {
        return str - out;
 }
 
-int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
-                     const char *func, long funclen, xdemitcb_t *ecb) {
+static int xdl_format_hunk_hdr(long s1, long c1, long s2, long c2,
+                              const char *func, long funclen,
+                              xdemitcb_t *ecb) {
        int nb = 0;
        mmbuffer_t mb;
        char buf[128];
@@ -376,7 +375,7 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
        nb += 3;
        if (func && funclen) {
                buf[nb++] = ' ';
-               if (funclen > (long)(sizeof(buf) - nb - 1))
+               if (funclen > sizeof(buf) - nb - 1)
                        funclen = sizeof(buf) - nb - 1;
                memcpy(buf + nb, func, funclen);
                nb += funclen;
@@ -385,9 +384,21 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
 
        mb.ptr = buf;
        mb.size = nb;
-       if (ecb->outf(ecb->priv, &mb, 1) < 0)
+       if (ecb->out_line(ecb->priv, &mb, 1) < 0)
                return -1;
+       return 0;
+}
 
+int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
+                     const char *func, long funclen,
+                     xdemitcb_t *ecb) {
+       if (!ecb->out_hunk)
+               return xdl_format_hunk_hdr(s1, c1, s2, c2, func, funclen, ecb);
+       if (ecb->out_hunk(ecb->priv,
+                         c1 ? s1 : s1 - 1, c1,
+                         c2 ? s2 : s2 - 1, c2,
+                         func, funclen) < 0)
+               return -1;
        return 0;
 }
 
index a5675676e903973a412f7aaa0a07ad45f586c02b..cb8b125ed5babf62b393359b92bf7bb65d30c61f 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <zlib.h>
 
-#include "buffer.h"
+#include "str.h"
 
 #define ZSTREAM_BUFFER_SIZE (1024 * 1024)
 #define ZSTREAM_BUFFER_MIN_EXTRA 8
@@ -164,7 +164,7 @@ int git_zstream_get_output(void *out, size_t *out_len, git_zstream *zstream)
        return 0;
 }
 
-static int zstream_buf(git_buf *out, const void *in, size_t in_len, git_zstream_t type)
+static int zstream_buf(git_str *out, const void *in, size_t in_len, git_zstream_t type)
 {
        git_zstream zs = GIT_ZSTREAM_INIT;
        int error = 0;
@@ -178,7 +178,7 @@ static int zstream_buf(git_buf *out, const void *in, size_t in_len, git_zstream_
        while (!git_zstream_done(&zs)) {
                size_t step = git_zstream_suggest_output_len(&zs), written;
 
-               if ((error = git_buf_grow_by(out, step)) < 0)
+               if ((error = git_str_grow_by(out, step)) < 0)
                        goto done;
 
                written = out->asize - out->size;
@@ -199,12 +199,12 @@ done:
        return error;
 }
 
-int git_zstream_deflatebuf(git_buf *out, const void *in, size_t in_len)
+int git_zstream_deflatebuf(git_str *out, const void *in, size_t in_len)
 {
        return zstream_buf(out, in, in_len, GIT_ZSTREAM_DEFLATE);
 }
 
-int git_zstream_inflatebuf(git_buf *out, const void *in, size_t in_len)
+int git_zstream_inflatebuf(git_str *out, const void *in, size_t in_len)
 {
        return zstream_buf(out, in, in_len, GIT_ZSTREAM_INFLATE);
 }
index db0cc477c38714c4ee77b0bf462a7b7156a066a2..3f8b1c72ff451b564479dd05f2f9e6a1c61285f3 100644 (file)
 
 #include <zlib.h>
 
-#include "buffer.h"
+#include "str.h"
 
 typedef enum {
        GIT_ZSTREAM_INFLATE,
-       GIT_ZSTREAM_DEFLATE,
+       GIT_ZSTREAM_DEFLATE
 } git_zstream_t;
 
 typedef struct {
@@ -48,7 +48,7 @@ bool git_zstream_eos(git_zstream *zstream);
 
 void git_zstream_reset(git_zstream *zstream);
 
-int git_zstream_deflatebuf(git_buf *out, const void *in, size_t in_len);
-int git_zstream_inflatebuf(git_buf *out, const void *in, size_t in_len);
+int git_zstream_deflatebuf(git_str *out, const void *in, size_t in_len);
+int git_zstream_inflatebuf(git_str *out, const void *in, size_t in_len);
 
 #endif
index 49999f4815e4a8ae40638fb68f1c2f890dd8ed93..f293c158da1086f82d3cc16db75c6eb540749b18 100644 (file)
@@ -1,73 +1,96 @@
-SET(Python_ADDITIONAL_VERSIONS 3 2.7)
-FIND_PACKAGE(PythonInterp)
+set(Python_ADDITIONAL_VERSIONS 3 2.7)
+find_package(PythonInterp)
 
-IF(NOT PYTHONINTERP_FOUND)
-  MESSAGE(FATAL_ERROR "Could not find a python interpeter, which is needed to build the tests. "
-    "Make sure python is available, or pass -DBUILD_CLAR=OFF to skip building the tests")
+if(NOT PYTHONINTERP_FOUND)
+       message(FATAL_ERROR "Could not find a python interpreter, which is needed to build the tests. "
+                            "Make sure python is available, or pass -DBUILD_TESTS=OFF to skip building the tests")
 ENDIF()
 
-SET(CLAR_FIXTURES "${CMAKE_CURRENT_SOURCE_DIR}/resources/")
-SET(CLAR_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
-ADD_DEFINITIONS(-DCLAR_FIXTURE_PATH=\"${CLAR_FIXTURES}\")
-ADD_DEFINITIONS(-DCLAR_TMPDIR=\"libgit2_tests\")
-ADD_DEFINITIONS(-DCLAR_WIN32_LONGPATHS)
-ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
+set(CLAR_FIXTURES "${CMAKE_CURRENT_SOURCE_DIR}/resources/")
+set(CLAR_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
+add_definitions(-DCLAR_FIXTURE_PATH=\"${CLAR_FIXTURES}\")
+add_definitions(-DCLAR_TMPDIR=\"libgit2_tests\")
+add_definitions(-DCLAR_WIN32_LONGPATHS)
+add_definitions(-D_FILE_OFFSET_BITS=64)
 
 # Ensure that we do not use deprecated functions internally
-ADD_DEFINITIONS(-DGIT_DEPRECATE_HARD)
+add_definitions(-DGIT_DEPRECATE_HARD)
 
-INCLUDE_DIRECTORIES(${CLAR_PATH} ${libgit2_BINARY_DIR}/src)
-FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c ${CLAR_PATH}/*/*.h)
-SET(SRC_CLAR "main.c" "clar_libgit2.c" "clar_libgit2_trace.c" "clar_libgit2_timer.c" "clar.c")
+set(TEST_INCLUDES "${CLAR_PATH}" "${CMAKE_CURRENT_BINARY_DIR}")
+file(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c ${CLAR_PATH}/*/*.h)
+set(SRC_CLAR "main.c" "clar_libgit2.c" "clar_libgit2_trace.c" "clar_libgit2_timer.c" "clar.c")
 
-IF(MSVC_IDE)
-       LIST(APPEND SRC_CLAR "precompiled.c")
-ENDIF()
+if(MSVC_IDE)
+       list(APPEND SRC_CLAR "precompiled.c")
+endif()
 
-ADD_CUSTOM_COMMAND(
-       OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/clar.suite
+add_custom_command(
+       OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/clar.suite ${CMAKE_CURRENT_BINARY_DIR}/clar_suite.h
        COMMAND ${PYTHON_EXECUTABLE} generate.py -o "${CMAKE_CURRENT_BINARY_DIR}" -f -xonline -xstress -xperf .
        DEPENDS ${SRC_TEST}
        WORKING_DIRECTORY ${CLAR_PATH}
 )
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
 
-SET_SOURCE_FILES_PROPERTIES(
+set_source_files_properties(
        ${CLAR_PATH}/clar.c
        PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/clar.suite)
 
-INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDES})
-INCLUDE_DIRECTORIES(SYSTEM ${LIBGIT2_SYSTEM_INCLUDES})
+add_executable(libgit2_tests ${SRC_CLAR} ${SRC_TEST} ${LIBGIT2_OBJECTS})
+
+set_target_properties(libgit2_tests PROPERTIES C_STANDARD 90)
+set_target_properties(libgit2_tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
 
-ADD_EXECUTABLE(libgit2_clar ${SRC_CLAR} ${SRC_TEST} ${LIBGIT2_OBJECTS})
+target_include_directories(libgit2_tests PRIVATE ${TEST_INCLUDES} ${LIBGIT2_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES})
+target_include_directories(libgit2_tests SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
+target_link_libraries(libgit2_tests ${LIBGIT2_SYSTEM_LIBS})
 
-SET_TARGET_PROPERTIES(libgit2_clar PROPERTIES C_STANDARD 90)
-SET_TARGET_PROPERTIES(libgit2_clar PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${libgit2_BINARY_DIR})
+ide_split_sources(libgit2_tests)
 
-TARGET_INCLUDE_DIRECTORIES(libgit2_clar PRIVATE ../src PUBLIC ../include)
-TARGET_LINK_LIBRARIES(libgit2_clar ${LIBGIT2_LIBS})
-IDE_SPLIT_SOURCES(libgit2_clar)
+#
+# Old versions of gcc require us to declare our test functions; don't do
+# this on newer compilers to avoid unnecessary recompilation.
+#
+if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
+       target_compile_options(libgit2_tests PRIVATE -include "clar_suite.h")
+endif()
 
-IF (MSVC_IDE)
+if(MSVC_IDE)
        # Precompiled headers
-       SET_TARGET_PROPERTIES(libgit2_clar PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
-       SET_SOURCE_FILES_PROPERTIES("precompiled.c" COMPILE_FLAGS "/Ycprecompiled.h")
-ENDIF ()
-
-FUNCTION(ADD_CLAR_TEST name)
-       IF (NOT USE_LEAK_CHECKER STREQUAL "OFF")
-               ADD_TEST(${name} "${libgit2_SOURCE_DIR}/script/${USE_LEAK_CHECKER}.sh" "${libgit2_BINARY_DIR}/libgit2_clar" ${ARGN})
-       ELSE()
-               ADD_TEST(${name} "${libgit2_BINARY_DIR}/libgit2_clar" ${ARGN})
-       ENDIF()
-ENDFUNCTION(ADD_CLAR_TEST)
-
-ADD_CLAR_TEST(offline             -v -xonline)
-ADD_CLAR_TEST(invasive            -v -score::ftruncate -sfilter::stream::bigfile -sodb::largefiles -siterator::workdir::filesystem_gunk -srepo::init -srepo::init::at_filesystem_root)
-ADD_CLAR_TEST(online              -v -sonline -xonline::customcert)
-ADD_CLAR_TEST(online_customcert   -v -sonline::customcert)
-ADD_CLAR_TEST(gitdaemon           -v -sonline::push)
-ADD_CLAR_TEST(ssh                 -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths -sonline::clone::path_whitespace_ssh)
-ADD_CLAR_TEST(proxy               -v -sonline::clone::proxy)
-ADD_CLAR_TEST(auth_clone          -v -sonline::clone::cred)
-ADD_CLAR_TEST(auth_clone_and_push -v -sonline::clone::push -sonline::push)
+       set_target_properties(libgit2_tests PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
+       set_source_files_properties("precompiled.c" COMPILE_FLAGS "/Ycprecompiled.h")
+endif()
+
+function(ADD_CLAR_TEST name)
+       if(NOT USE_LEAK_CHECKER STREQUAL "OFF")
+               add_test(${name} "${PROJECT_SOURCE_DIR}/script/${USE_LEAK_CHECKER}.sh" "${PROJECT_BINARY_DIR}/libgit2_tests" ${ARGN})
+       else()
+               add_test(${name} "${PROJECT_BINARY_DIR}/libgit2_tests" ${ARGN})
+       endif()
+endfunction(ADD_CLAR_TEST)
+
+add_clar_test(offline             -v -xonline)
+add_clar_test(invasive            -v -score::ftruncate -sfilter::stream::bigfile -sodb::largefiles -siterator::workdir::filesystem_gunk -srepo::init -srepo::init::at_filesystem_root)
+add_clar_test(online              -v -sonline -xonline::customcert)
+add_clar_test(online_customcert   -v -sonline::customcert)
+add_clar_test(gitdaemon           -v -sonline::push)
+add_clar_test(ssh                 -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths -sonline::clone::path_whitespace_ssh)
+add_clar_test(proxy               -v -sonline::clone::proxy)
+add_clar_test(auth_clone          -v -sonline::clone::cred)
+add_clar_test(auth_clone_and_push -v -sonline::clone::push -sonline::push)
+
+#
+# Header file validation project: ensure that we do not publish any sloppy
+# definitions in our headers and that a consumer can include <git2.dll>
+# even when they have aggressive C90 warnings enabled.
+#
+
+add_executable(headertest headertest.c)
+set_target_properties(headertest PROPERTIES C_STANDARD 90)
+set_target_properties(headertest PROPERTIES C_EXTENSIONS OFF)
+target_include_directories(headertest PRIVATE ${LIBGIT2_INCLUDES})
+
+if (MSVC)
+       target_compile_options(headertest PUBLIC /W4 /WX)
+else()
+       target_compile_options(headertest PUBLIC -Wall -Wextra -pedantic -Werror)
+endif()
index b1d70d3bc9330c1f7d6af2a0b1f6e665322f8fd5..4369a8f33818849b9ecb10142ab903a29d76b696 100644 (file)
@@ -11,11 +11,11 @@ https://github.com/vmg/clar
 
 * Make sure you actually build the tests by setting:
 
-        cmake -DBUILD_CLAR=ON build/
+        cmake -DBUILD_TESTS=ON build/
 
 * Test:
 
-        ./build/libgit2_clar
+        ./build/libgit2_tests
 
 * Make sure everything is fine.
 
@@ -32,10 +32,10 @@ These are automatically run as part of CI, but if you want to check locally:
 Uses [`valgrind`](http://www.valgrind.org/):
 
 ```console
-$ cmake -DBUILD_CLAR=ON -DVALGRIND=ON ..
+$ cmake -DBUILD_TESTS=ON -DVALGRIND=ON ..
 $ cmake --build .
-$ valgrind --leak-check=full --show-reachable=yes --num-callers=50 --suppressions=../libgit2_clar.supp \
-  ./libgit2_clar
+$ valgrind --leak-check=full --show-reachable=yes --num-callers=50 --suppressions=../libgit2_tests.supp \
+  ./libgit2_tests
 ```
 
 #### macOS
@@ -44,5 +44,5 @@ Uses [`leaks`](https://developer.apple.com/library/archive/documentation/Perform
 
 ```console
 $ MallocStackLogging=1 MallocScribble=1 MallocLogFile=/dev/null CLAR_AT_EXIT="leaks -quiet \$PPID" \
-  ./libgit2_clar
+  ./libgit2_tests
 ```
index 69dfe0987a8989deb4579749f85a31fb9262ca7e..9da6ac92374c65c11d464e70fdd8889f19f0e1b5 100644 (file)
@@ -22,15 +22,15 @@ void test_apply_fromdiff__cleanup(void)
 }
 
 static int apply_gitbuf(
-       const git_buf *old,
+       const git_str *old,
        const char *oldname,
-       const git_buf *new,
+       const git_str *new,
        const char *newname,
        const char *patch_expected,
        const git_diff_options *diff_opts)
 {
        git_patch *patch;
-       git_buf result = GIT_BUF_INIT;
+       git_str result = GIT_STR_INIT;
        git_buf patchbuf = GIT_BUF_INIT;
        char *filename;
        unsigned int mode;
@@ -62,7 +62,7 @@ static int apply_gitbuf(
        }
 
        git__free(filename);
-       git_buf_dispose(&result);
+       git_str_dispose(&result);
        git_buf_dispose(&patchbuf);
        git_patch_free(patch);
 
@@ -77,7 +77,7 @@ static int apply_buf(
        const char *patch_expected,
        const git_diff_options *diff_opts)
 {
-       git_buf o = GIT_BUF_INIT, n = GIT_BUF_INIT,
+       git_str o = GIT_STR_INIT, n = GIT_STR_INIT,
                *optr = NULL, *nptr = NULL;
 
        if (old) {
@@ -275,7 +275,7 @@ void test_apply_fromdiff__no_change(void)
 
 void test_apply_fromdiff__binary_add(void)
 {
-       git_buf newfile = GIT_BUF_INIT;
+       git_str newfile = GIT_STR_INIT;
 
        newfile.ptr = FILE_BINARY_DELTA_MODIFIED;
        newfile.size = FILE_BINARY_DELTA_MODIFIED_LEN;
@@ -288,7 +288,7 @@ void test_apply_fromdiff__binary_add(void)
 
 void test_apply_fromdiff__binary_no_change(void)
 {
-       git_buf original = GIT_BUF_INIT;
+       git_str original = GIT_STR_INIT;
 
        original.ptr = FILE_BINARY_DELTA_ORIGINAL;
        original.size = FILE_BINARY_DELTA_ORIGINAL_LEN;
@@ -301,7 +301,7 @@ void test_apply_fromdiff__binary_no_change(void)
 
 void test_apply_fromdiff__binary_change_delta(void)
 {
-       git_buf original = GIT_BUF_INIT, modified = GIT_BUF_INIT;
+       git_str original = GIT_STR_INIT, modified = GIT_STR_INIT;
 
        original.ptr = FILE_BINARY_DELTA_ORIGINAL;
        original.size = FILE_BINARY_DELTA_ORIGINAL_LEN;
@@ -317,7 +317,7 @@ void test_apply_fromdiff__binary_change_delta(void)
 
 void test_apply_fromdiff__binary_change_literal(void)
 {
-       git_buf original = GIT_BUF_INIT, modified = GIT_BUF_INIT;
+       git_str original = GIT_STR_INIT, modified = GIT_STR_INIT;
 
        original.ptr = FILE_BINARY_LITERAL_ORIGINAL;
        original.size = FILE_BINARY_LITERAL_ORIGINAL_LEN;
@@ -333,7 +333,7 @@ void test_apply_fromdiff__binary_change_literal(void)
 
 void test_apply_fromdiff__binary_delete(void)
 {
-       git_buf original = GIT_BUF_INIT;
+       git_str original = GIT_STR_INIT;
 
        original.ptr = FILE_BINARY_DELTA_MODIFIED;
        original.size = FILE_BINARY_DELTA_MODIFIED_LEN;
@@ -346,7 +346,7 @@ void test_apply_fromdiff__binary_delete(void)
 
 void test_apply_fromdiff__patching_correctly_truncates_source(void)
 {
-       git_buf original = GIT_BUF_INIT, patched = GIT_BUF_INIT;
+       git_str original = GIT_STR_INIT, patched = GIT_STR_INIT;
        git_patch *patch;
        unsigned int mode;
        char *path;
@@ -371,8 +371,8 @@ void test_apply_fromdiff__patching_correctly_truncates_source(void)
        cl_git_pass(git_apply__patch(&patched, &path, &mode,
                                     "foo\nbar\n", 7, patch, NULL));
 
-       git_buf_dispose(&original);
-       git_buf_dispose(&patched);
+       git_str_dispose(&original);
+       git_str_dispose(&patched);
        git_patch_free(patch);
        git__free(path);
 }
index ae519eab051098a9b759727bffa8f9290c10991a..8cde623928a89aed18a7cbfb62efc2c6fb507c1f 100644 (file)
@@ -30,8 +30,8 @@ static int apply_patchfile(
        unsigned int mode_expected)
 {
        git_patch *patch;
-       git_buf result = GIT_BUF_INIT;
-       git_buf patchbuf = GIT_BUF_INIT;
+       git_str result = GIT_STR_INIT;
+       git_str patchbuf = GIT_STR_INIT;
        char *filename;
        unsigned int mode;
        int error;
@@ -50,8 +50,8 @@ static int apply_patchfile(
        }
 
        git__free(filename);
-       git_buf_dispose(&result);
-       git_buf_dispose(&patchbuf);
+       git_str_dispose(&result);
+       git_str_dispose(&patchbuf);
        git_patch_free(patch);
 
        return error;
index 548faaadb14741205d10539d710080999383fc46..fd4908d4b1dc16a8f6fd2877d0b83d0f379a5149 100644 (file)
@@ -83,8 +83,8 @@ static int apply_buf(
        void *payload)
 {
        git_patch *patch;
-       git_buf result = GIT_BUF_INIT;
-       git_buf patchbuf = GIT_BUF_INIT;
+       git_str result = GIT_STR_INIT;
+       git_str patchbuf = GIT_STR_INIT;
        git_apply_options opts = GIT_APPLY_OPTIONS_INIT;
        char *filename;
        unsigned int mode;
@@ -103,8 +103,8 @@ static int apply_buf(
        }
 
        git__free(filename);
-       git_buf_dispose(&result);
-       git_buf_dispose(&patchbuf);
+       git_str_dispose(&result);
+       git_str_dispose(&patchbuf);
        git_patch_free(patch);
 
        return error;
index eabc033eb97efac039f3851c196ae54c03ced181..abd2381541d87f47deb2eabffdf101f0f8ebdc56 100644 (file)
@@ -230,12 +230,12 @@ void test_attr_repo__manpage_example(void)
 
 static void add_to_workdir(const char *filename, const char *content)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&buf, "attr", filename));
-       cl_git_rewritefile(git_buf_cstr(&buf), content);
+       cl_git_pass(git_str_joinpath(&buf, "attr", filename));
+       cl_git_rewritefile(git_str_cstr(&buf), content);
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 }
 
 static void assert_proper_normalization(git_index *index, const char *filename, const char *expected_sha)
@@ -283,7 +283,7 @@ void test_attr_repo__bare_repo_with_index(void)
        git_index_free(index);
 
        cl_must_pass(p_unlink("attr/.gitattributes"));
-       cl_assert(!git_path_exists("attr/.gitattributes"));
+       cl_assert(!git_fs_path_exists("attr/.gitattributes"));
 
        cl_git_pass(git_repository_set_bare(g_repo));
 
@@ -311,12 +311,12 @@ void test_attr_repo__bare_repo_with_index(void)
 
 void test_attr_repo__sysdir(void)
 {
-       git_buf sysdir = GIT_BUF_INIT;
+       git_str sysdir = GIT_STR_INIT;
        const char *value;
 
        cl_git_pass(p_mkdir("system", 0777));
        cl_git_rewritefile("system/gitattributes", "file merge=foo");
-       cl_git_pass(git_buf_joinpath(&sysdir, clar_sandbox_path(), "system"));
+       cl_git_pass(git_str_joinpath(&sysdir, clar_sandbox_path(), "system"));
        cl_git_pass(git_sysdir_set(GIT_SYSDIR_SYSTEM, sysdir.ptr));
        g_repo = cl_git_sandbox_reopen();
 
@@ -325,18 +325,18 @@ void test_attr_repo__sysdir(void)
 
        cl_git_pass(p_unlink("system/gitattributes"));
        cl_git_pass(p_rmdir("system"));
-       git_buf_dispose(&sysdir);
+       git_str_dispose(&sysdir);
 }
 
 void test_attr_repo__sysdir_with_session(void)
 {
        const char *values[2], *attrs[2] = { "foo", "bar" };
-       git_buf sysdir = GIT_BUF_INIT;
+       git_str sysdir = GIT_STR_INIT;
        git_attr_session session;
 
        cl_git_pass(p_mkdir("system", 0777));
        cl_git_rewritefile("system/gitattributes", "file foo=1 bar=2");
-       cl_git_pass(git_buf_joinpath(&sysdir, clar_sandbox_path(), "system"));
+       cl_git_pass(git_str_joinpath(&sysdir, clar_sandbox_path(), "system"));
        cl_git_pass(git_sysdir_set(GIT_SYSDIR_SYSTEM, sysdir.ptr));
        g_repo = cl_git_sandbox_reopen();
 
@@ -348,7 +348,7 @@ void test_attr_repo__sysdir_with_session(void)
 
        cl_git_pass(p_unlink("system/gitattributes"));
        cl_git_pass(p_rmdir("system"));
-       git_buf_dispose(&sysdir);
+       git_str_dispose(&sysdir);
        git_attr_session__free(&session);
 }
 
@@ -371,11 +371,11 @@ void test_attr_repo__rewrite(void)
 
 void test_attr_repo__rewrite_sysdir(void)
 {
-       git_buf sysdir = GIT_BUF_INIT;
+       git_str sysdir = GIT_STR_INIT;
        const char *value;
 
        cl_git_pass(p_mkdir("system", 0777));
-       cl_git_pass(git_buf_joinpath(&sysdir, clar_sandbox_path(), "system"));
+       cl_git_pass(git_str_joinpath(&sysdir, clar_sandbox_path(), "system"));
        cl_git_pass(git_sysdir_set(GIT_SYSDIR_SYSTEM, sysdir.ptr));
        g_repo = cl_git_sandbox_reopen();
 
@@ -387,7 +387,7 @@ void test_attr_repo__rewrite_sysdir(void)
        cl_git_pass(git_attr_get(&value, g_repo, 0, "file", "foo"));
        cl_assert_equal_s(value, "second");
 
-       git_buf_dispose(&sysdir);
+       git_str_dispose(&sysdir);
 }
 
 void test_attr_repo__unlink(void)
diff --git a/tests/buf/basic.c b/tests/buf/basic.c
deleted file mode 100644 (file)
index f90c4c6..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "clar_libgit2.h"
-#include "buffer.h"
-
-static const char *test_string = "Have you seen that? Have you seeeen that??";
-
-void test_buf_basic__resize(void)
-{
-       git_buf buf1 = GIT_BUF_INIT;
-       git_buf_puts(&buf1, test_string);
-       cl_assert(git_buf_oom(&buf1) == 0);
-       cl_assert_equal_s(git_buf_cstr(&buf1), test_string);
-
-       git_buf_puts(&buf1, test_string);
-       cl_assert(strlen(git_buf_cstr(&buf1)) == strlen(test_string) * 2);
-       git_buf_dispose(&buf1);
-}
-
-void test_buf_basic__resize_incremental(void)
-{
-       git_buf buf1 = GIT_BUF_INIT;
-
-       /* Presently, asking for 6 bytes will round up to 8. */
-       cl_git_pass(git_buf_puts(&buf1, "Hello"));
-       cl_assert_equal_i(5, buf1.size);
-       cl_assert_equal_i(8, buf1.asize);
-
-       /* Ensure an additional byte does not realloc. */
-       cl_git_pass(git_buf_grow_by(&buf1, 1));
-       cl_assert_equal_i(5, buf1.size);
-       cl_assert_equal_i(8, buf1.asize);
-
-       /* But requesting many does. */
-       cl_git_pass(git_buf_grow_by(&buf1, 16));
-       cl_assert_equal_i(5, buf1.size);
-       cl_assert(buf1.asize > 8);
-
-       git_buf_dispose(&buf1);
-}
-
-void test_buf_basic__printf(void)
-{
-       git_buf buf2 = GIT_BUF_INIT;
-       git_buf_printf(&buf2, "%s %s %d ", "shoop", "da", 23);
-       cl_assert(git_buf_oom(&buf2) == 0);
-       cl_assert_equal_s(git_buf_cstr(&buf2), "shoop da 23 ");
-
-       git_buf_printf(&buf2, "%s %d", "woop", 42);
-       cl_assert(git_buf_oom(&buf2) == 0);
-       cl_assert_equal_s(git_buf_cstr(&buf2), "shoop da 23 woop 42");
-       git_buf_dispose(&buf2);
-}
diff --git a/tests/buf/oom.c b/tests/buf/oom.c
deleted file mode 100644 (file)
index 726234e..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#include "clar_libgit2.h"
-#include "buffer.h"
-
-/* Override default allocators with ones that will fail predictably. */
-
-static git_allocator std_alloc;
-static git_allocator oom_alloc;
-
-static void *oom_malloc(size_t n, const char *file, int line)
-{
-       /* Reject any allocation of more than 100 bytes */
-       return (n > 100) ? NULL : std_alloc.gmalloc(n, file, line);
-}
-
-static void *oom_realloc(void *p, size_t n, const char *file, int line)
-{
-       /* Reject any allocation of more than 100 bytes */
-       return (n > 100) ? NULL : std_alloc.grealloc(p, n, file, line);
-}
-
-void test_buf_oom__initialize(void)
-{
-       git_stdalloc_init_allocator(&std_alloc);
-       git_stdalloc_init_allocator(&oom_alloc);
-
-       oom_alloc.gmalloc = oom_malloc;
-       oom_alloc.grealloc = oom_realloc;
-
-       cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ALLOCATOR, &oom_alloc));
-}
-
-void test_buf_oom__cleanup(void)
-{
-       cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ALLOCATOR, NULL));
-}
-
-void test_buf_oom__grow(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       cl_git_pass(git_buf_grow(&buf, 42));
-       cl_assert(!git_buf_oom(&buf));
-
-       cl_assert(git_buf_grow(&buf, 101) == -1);
-       cl_assert(git_buf_oom(&buf));
-
-       git_buf_dispose(&buf);
-}
-
-void test_buf_oom__grow_by(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       cl_git_pass(git_buf_grow_by(&buf, 42));
-       cl_assert(!git_buf_oom(&buf));
-
-       cl_assert(git_buf_grow_by(&buf, 101) == -1);
-       cl_assert(git_buf_oom(&buf));
-}
diff --git a/tests/buf/percent.c b/tests/buf/percent.c
deleted file mode 100644 (file)
index 8c47b83..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#include "clar_libgit2.h"
-#include "buffer.h"
-
-static void expect_decode_pass(const char *expected, const char *encoded)
-{
-       git_buf in = GIT_BUF_INIT, out = GIT_BUF_INIT;
-
-       /*
-        * ensure that we only read the given length of the input buffer
-        * by putting garbage at the end.  this will ensure that we do
-        * not, eg, rely on nul-termination or walk off the end of the buf.
-        */
-       cl_git_pass(git_buf_puts(&in, encoded));
-       cl_git_pass(git_buf_PUTS(&in, "TRAILER"));
-
-       cl_git_pass(git_buf_decode_percent(&out, in.ptr, strlen(encoded)));
-
-       cl_assert_equal_s(expected, git_buf_cstr(&out));
-       cl_assert_equal_i(strlen(expected), git_buf_len(&out));
-
-       git_buf_dispose(&in);
-       git_buf_dispose(&out);
-}
-
-void test_buf_percent__decode_succeeds(void)
-{
-       expect_decode_pass("", "");
-       expect_decode_pass(" ", "%20");
-       expect_decode_pass("a", "a");
-       expect_decode_pass(" a", "%20a");
-       expect_decode_pass("a ", "a%20");
-       expect_decode_pass("github.com", "github.com");
-       expect_decode_pass("github.com", "githu%62.com");
-       expect_decode_pass("github.com", "github%2ecom");
-       expect_decode_pass("foo bar baz", "foo%20bar%20baz");
-       expect_decode_pass("foo bar baz", "foo%20bar%20baz");
-       expect_decode_pass("foo bar ", "foo%20bar%20");
-}
-
-void test_buf_percent__ignores_invalid(void)
-{
-       expect_decode_pass("githu%%.com", "githu%%.com");
-       expect_decode_pass("github.co%2", "github.co%2");
-       expect_decode_pass("github%2.com", "github%2.com");
-       expect_decode_pass("githu%2z.com", "githu%2z.com");
-       expect_decode_pass("github.co%9z", "github.co%9z");
-       expect_decode_pass("github.co%2", "github.co%2");
-       expect_decode_pass("github.co%", "github.co%");
-}
diff --git a/tests/buf/quote.c b/tests/buf/quote.c
deleted file mode 100644 (file)
index 8867ae7..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-#include "clar_libgit2.h"
-#include "buffer.h"
-
-static void expect_quote_pass(const char *expected, const char *str)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       cl_git_pass(git_buf_puts(&buf, str));
-       cl_git_pass(git_buf_quote(&buf));
-
-       cl_assert_equal_s(expected, git_buf_cstr(&buf));
-       cl_assert_equal_i(strlen(expected), git_buf_len(&buf));
-
-       git_buf_dispose(&buf);
-}
-
-void test_buf_quote__quote_succeeds(void)
-{
-       expect_quote_pass("", "");
-       expect_quote_pass("foo", "foo");
-       expect_quote_pass("foo/bar/baz.c", "foo/bar/baz.c");
-       expect_quote_pass("foo bar", "foo bar");
-       expect_quote_pass("\"\\\"leading quote\"", "\"leading quote");
-       expect_quote_pass("\"slash\\\\y\"", "slash\\y");
-       expect_quote_pass("\"foo\\r\\nbar\"", "foo\r\nbar");
-       expect_quote_pass("\"foo\\177bar\"", "foo\177bar");
-       expect_quote_pass("\"foo\\001bar\"", "foo\001bar");
-       expect_quote_pass("\"foo\\377bar\"", "foo\377bar");
-}
-
-static void expect_unquote_pass(const char *expected, const char *quoted)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       cl_git_pass(git_buf_puts(&buf, quoted));
-       cl_git_pass(git_buf_unquote(&buf));
-
-       cl_assert_equal_s(expected, git_buf_cstr(&buf));
-       cl_assert_equal_i(strlen(expected), git_buf_len(&buf));
-
-       git_buf_dispose(&buf);
-}
-
-static void expect_unquote_fail(const char *quoted)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       cl_git_pass(git_buf_puts(&buf, quoted));
-       cl_git_fail(git_buf_unquote(&buf));
-
-       git_buf_dispose(&buf);
-}
-
-void test_buf_quote__unquote_succeeds(void)
-{
-       expect_unquote_pass("", "\"\"");
-       expect_unquote_pass(" ", "\" \"");
-       expect_unquote_pass("foo", "\"foo\"");
-       expect_unquote_pass("foo bar", "\"foo bar\"");
-       expect_unquote_pass("foo\"bar", "\"foo\\\"bar\"");
-       expect_unquote_pass("foo\\bar", "\"foo\\\\bar\"");
-       expect_unquote_pass("foo\tbar", "\"foo\\tbar\"");
-       expect_unquote_pass("\vfoo\tbar\n", "\"\\vfoo\\tbar\\n\"");
-       expect_unquote_pass("foo\nbar", "\"foo\\012bar\"");
-       expect_unquote_pass("foo\r\nbar", "\"foo\\015\\012bar\"");
-       expect_unquote_pass("foo\r\nbar", "\"\\146\\157\\157\\015\\012\\142\\141\\162\"");
-       expect_unquote_pass("newline: \n", "\"newline: \\012\"");
-       expect_unquote_pass("0xff: \377", "\"0xff: \\377\"");
-}
-
-void test_buf_quote__unquote_fails(void)
-{
-       expect_unquote_fail("no quotes at all");
-       expect_unquote_fail("\"no trailing quote");
-       expect_unquote_fail("no leading quote\"");
-       expect_unquote_fail("\"invalid \\z escape char\"");
-       expect_unquote_fail("\"\\q invalid escape char\"");
-       expect_unquote_fail("\"invalid escape char \\p\"");
-       expect_unquote_fail("\"invalid \\1 escape char \"");
-       expect_unquote_fail("\"invalid \\14 escape char \"");
-       expect_unquote_fail("\"invalid \\280 escape char\"");
-       expect_unquote_fail("\"invalid \\378 escape char\"");
-       expect_unquote_fail("\"invalid \\380 escape char\"");
-       expect_unquote_fail("\"invalid \\411 escape char\"");
-       expect_unquote_fail("\"truncated escape char \\\"");
-       expect_unquote_fail("\"truncated escape char \\0\"");
-       expect_unquote_fail("\"truncated escape char \\01\"");
-}
diff --git a/tests/buf/splice.c b/tests/buf/splice.c
deleted file mode 100644 (file)
index 18c7c3f..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-#include "clar_libgit2.h"
-#include "buffer.h"
-
-static git_buf _buf;
-
-void test_buf_splice__initialize(void) {
-   git_buf_init(&_buf, 16);
-}
-
-void test_buf_splice__cleanup(void) {
-   git_buf_dispose(&_buf);
-}
-
-void test_buf_splice__preprend(void)
-{
-       git_buf_sets(&_buf, "world!");
-
-       cl_git_pass(git_buf_splice(&_buf, 0, 0, "Hello Dolly", strlen("Hello ")));
-
-       cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf));
-}
-
-void test_buf_splice__append(void)
-{
-       git_buf_sets(&_buf, "Hello");
-
-       cl_git_pass(git_buf_splice(&_buf, git_buf_len(&_buf), 0, " world!", strlen(" world!")));
-
-       cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf));
-}
-
-void test_buf_splice__insert_at(void)
-{
-       git_buf_sets(&_buf, "Hell world!");
-
-       cl_git_pass(git_buf_splice(&_buf, strlen("Hell"), 0, "o", strlen("o")));
-
-       cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf));
-}
-
-void test_buf_splice__remove_at(void)
-{
-       git_buf_sets(&_buf, "Hello world of warcraft!");
-
-       cl_git_pass(git_buf_splice(&_buf, strlen("Hello world"), strlen(" of warcraft"), "", 0));
-
-       cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf));
-}
-
-void test_buf_splice__replace(void)
-{
-       git_buf_sets(&_buf, "Hell0 w0rld!");
-
-       cl_git_pass(git_buf_splice(&_buf, strlen("Hell"), strlen("0 w0"), "o wo", strlen("o wo")));
-
-       cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf));
-}
-
-void test_buf_splice__replace_with_longer(void)
-{
-       git_buf_sets(&_buf, "Hello you!");
-
-       cl_git_pass(git_buf_splice(&_buf, strlen("Hello "), strlen("you"), "world", strlen("world")));
-
-       cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf));
-}
-
-void test_buf_splice__replace_with_shorter(void)
-{
-       git_buf_sets(&_buf, "Brave new world!");
-
-       cl_git_pass(git_buf_splice(&_buf, 0, strlen("Brave new"), "Hello", strlen("Hello")));
-
-       cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf));
-}
-
-void test_buf_splice__truncate(void)
-{
-       git_buf_sets(&_buf, "Hello world!!");
-
-       cl_git_pass(git_buf_splice(&_buf, strlen("Hello world!"), strlen("!"), "", 0));
-
-       cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf));
-}
-
-void test_buf_splice__dont_do_anything(void)
-{
-       git_buf_sets(&_buf, "Hello world!");
-
-       cl_git_pass(git_buf_splice(&_buf, 3, 0, "Hello", 0));
-
-       cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf));
-}
index 95af5d3964c188e79f2847fc1fad8ee9566460e5..1e9c21bdc5c01f8f5e250ec652c7f5dfbaa35a3b 100644 (file)
@@ -7,16 +7,16 @@
 void assert_on_branch(git_repository *repo, const char *branch)
 {
        git_reference *head;
-       git_buf bname = GIT_BUF_INIT;
+       git_str bname = GIT_STR_INIT;
 
        cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE));
        cl_assert_(git_reference_type(head) == GIT_REFERENCE_SYMBOLIC, branch);
 
-       cl_git_pass(git_buf_joinpath(&bname, "refs/heads", branch));
+       cl_git_pass(git_str_joinpath(&bname, "refs/heads", branch));
        cl_assert_equal_s(bname.ptr, git_reference_symbolic_target(head));
 
        git_reference_free(head);
-       git_buf_dispose(&bname);
+       git_str_dispose(&bname);
 }
 
 void reset_index_to_treeish(git_object *treeish)
index 6058a196c7077fca71b6ae21a460c87bdee8075c..879b48b06d7d851cfb7d07aa34be893ec83a06b0 100644 (file)
@@ -1,4 +1,3 @@
-#include "buffer.h"
 #include "git2/object.h"
 #include "git2/repository.h"
 
index dae3f295e940ac560436dc5240fe612f6d77eefe..4a9e4b9fa9bba2fb749c63e6eb2bd045ae2f1de9 100644 (file)
@@ -85,14 +85,14 @@ void test_checkout_conflict__cleanup(void)
 
 static void create_index(struct checkout_index_entry *entries, size_t entries_len)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        size_t i;
 
        for (i = 0; i < entries_len; i++) {
-               git_buf_joinpath(&path, TEST_REPO_PATH, entries[i].path);
+               git_str_joinpath(&path, TEST_REPO_PATH, entries[i].path);
 
                if (entries[i].stage == 3 && (i == 0 || strcmp(entries[i-1].path, entries[i].path) != 0 || entries[i-1].stage != 2))
-                       p_unlink(git_buf_cstr(&path));
+                       p_unlink(git_str_cstr(&path));
 
                cl_git_pass(git_index_remove_bypath(g_index, entries[i].path));
        }
@@ -110,7 +110,7 @@ static void create_index(struct checkout_index_entry *entries, size_t entries_le
                cl_git_pass(git_index_add(g_index, &entry));
        }
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 static void create_index_names(struct checkout_name_entry *entries, size_t entries_len)
@@ -139,16 +139,16 @@ static void create_conflicting_index(void)
 
 static void ensure_workdir_contents(const char *path, const char *contents)
 {
-       git_buf fullpath = GIT_BUF_INIT, data_buf = GIT_BUF_INIT;
+       git_str fullpath = GIT_STR_INIT, data_buf = GIT_STR_INIT;
 
        cl_git_pass(
-               git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path));
+               git_str_joinpath(&fullpath, git_repository_workdir(g_repo), path));
 
-       cl_git_pass(git_futils_readbuffer(&data_buf, git_buf_cstr(&fullpath)));
-       cl_assert(strcmp(git_buf_cstr(&data_buf), contents) == 0);
+       cl_git_pass(git_futils_readbuffer(&data_buf, git_str_cstr(&fullpath)));
+       cl_assert(strcmp(git_str_cstr(&data_buf), contents) == 0);
 
-       git_buf_dispose(&fullpath);
-       git_buf_dispose(&data_buf);
+       git_str_dispose(&fullpath);
+       git_str_dispose(&data_buf);
 }
 
 static void ensure_workdir_oid(const char *path, const char *oid_str)
@@ -166,16 +166,16 @@ static void ensure_workdir_mode(const char *path, int mode)
        GIT_UNUSED(path);
        GIT_UNUSED(mode);
 #else
-       git_buf fullpath = GIT_BUF_INIT;
+       git_str fullpath = GIT_STR_INIT;
        struct stat st;
 
        cl_git_pass(
-               git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path));
+               git_str_joinpath(&fullpath, git_repository_workdir(g_repo), path));
 
-       cl_git_pass(p_stat(git_buf_cstr(&fullpath), &st));
+       cl_git_pass(p_stat(git_str_cstr(&fullpath), &st));
        cl_assert_equal_i((mode & S_IRWXU), (st.st_mode & S_IRWXU));
 
-       git_buf_dispose(&fullpath);
+       git_str_dispose(&fullpath);
 #endif
 }
 
@@ -197,22 +197,22 @@ static void ensure_workdir_link(
        if (!symlinks) {
                ensure_workdir_contents(path, target);
        } else {
-               git_buf fullpath = GIT_BUF_INIT;
+               git_str fullpath = GIT_STR_INIT;
                char actual[1024];
                struct stat st;
                int len;
 
                cl_git_pass(
-                       git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path));
+                       git_str_joinpath(&fullpath, git_repository_workdir(g_repo), path));
 
-               cl_git_pass(p_lstat(git_buf_cstr(&fullpath), &st));
+               cl_git_pass(p_lstat(git_str_cstr(&fullpath), &st));
                cl_assert(S_ISLNK(st.st_mode));
 
-               cl_assert((len = p_readlink(git_buf_cstr(&fullpath), actual, 1024)) > 0);
+               cl_assert((len = p_readlink(git_str_cstr(&fullpath), actual, 1024)) > 0);
                actual[len] = '\0';
                cl_assert(strcmp(actual, target) == 0);
 
-               git_buf_dispose(&fullpath);
+               git_str_dispose(&fullpath);
        }
 }
 
@@ -227,7 +227,7 @@ void test_checkout_conflict__ignored(void)
 
        cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
 
-       cl_assert(!git_path_exists(TEST_REPO_PATH "/conflicting.txt"));
+       cl_assert(!git_fs_path_exists(TEST_REPO_PATH "/conflicting.txt"));
 }
 
 void test_checkout_conflict__ours(void)
@@ -1030,15 +1030,15 @@ void test_checkout_conflict__update_only(void)
        ensure_workdir_contents("automergeable.txt", AUTOMERGEABLE_MERGED_FILE);
        ensure_workdir("directory_file-two/file", 0100644, CONFLICTING_OURS_OID);
 
-       cl_assert(!git_path_exists("merge-resolve/modify-delete"));
-       cl_assert(!git_path_exists("merge-resolve/test-one.txt"));
-       cl_assert(!git_path_exists("merge-resolve/test-one-side-one.txt"));
-       cl_assert(!git_path_exists("merge-resolve/test-one-side-two.txt"));
-       cl_assert(!git_path_exists("merge-resolve/test-one.txt~ours"));
-       cl_assert(!git_path_exists("merge-resolve/test-one.txt~theirs"));
-       cl_assert(!git_path_exists("merge-resolve/directory_file-one/file"));
-       cl_assert(!git_path_exists("merge-resolve/directory_file-one~ours"));
-       cl_assert(!git_path_exists("merge-resolve/directory_file-two~theirs"));
+       cl_assert(!git_fs_path_exists("merge-resolve/modify-delete"));
+       cl_assert(!git_fs_path_exists("merge-resolve/test-one.txt"));
+       cl_assert(!git_fs_path_exists("merge-resolve/test-one-side-one.txt"));
+       cl_assert(!git_fs_path_exists("merge-resolve/test-one-side-two.txt"));
+       cl_assert(!git_fs_path_exists("merge-resolve/test-one.txt~ours"));
+       cl_assert(!git_fs_path_exists("merge-resolve/test-one.txt~theirs"));
+       cl_assert(!git_fs_path_exists("merge-resolve/directory_file-one/file"));
+       cl_assert(!git_fs_path_exists("merge-resolve/directory_file-one~ours"));
+       cl_assert(!git_fs_path_exists("merge-resolve/directory_file-two~theirs"));
 }
 
 void test_checkout_conflict__path_filters(void)
@@ -1076,9 +1076,9 @@ void test_checkout_conflict__path_filters(void)
        cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
 
        ensure_workdir_contents("conflicting-1.txt", CONFLICTING_DIFF3_FILE);
-       cl_assert(!git_path_exists("merge-resolve/conflicting-2.txt"));
+       cl_assert(!git_fs_path_exists("merge-resolve/conflicting-2.txt"));
        ensure_workdir_contents("conflicting-3.txt", AUTOMERGEABLE_MERGED_FILE);
-       cl_assert(!git_path_exists("merge-resolve/conflicting-4.txt"));
+       cl_assert(!git_fs_path_exists("merge-resolve/conflicting-4.txt"));
 }
 
 static void collect_progress(
index 4950201615c1c4b7ccaa30af9511894c74800bdd..21f8a852a64b5e80ae10c1fc565bedcdd24efab0 100644 (file)
 static git_repository *g_repo;
 
 static const char *systype;
-static git_buf expected_fixture = GIT_BUF_INIT;
+static git_str expected_fixture = GIT_STR_INIT;
 
-static int unlink_file(void *payload, git_buf *path)
+static int unlink_file(void *payload, git_str *path)
 {
        char *fn;
 
-       cl_assert(fn = git_path_basename(path->ptr));
+       cl_assert(fn = git_fs_path_basename(path->ptr));
 
        GIT_UNUSED(payload);
 
@@ -30,7 +30,7 @@ static int unlink_file(void *payload, git_buf *path)
 
 void test_checkout_crlf__initialize(void)
 {
-       git_buf reponame = GIT_BUF_INIT;
+       git_str reponame = GIT_STR_INIT;
 
        g_repo = cl_git_sandbox_init("crlf");
 
@@ -38,15 +38,15 @@ void test_checkout_crlf__initialize(void)
         * remove the contents of the working directory so that we can
         * check out over it.
         */
-       cl_git_pass(git_buf_puts(&reponame, "crlf"));
-       cl_git_pass(git_path_direach(&reponame, 0, unlink_file, NULL));
+       cl_git_pass(git_str_puts(&reponame, "crlf"));
+       cl_git_pass(git_fs_path_direach(&reponame, 0, unlink_file, NULL));
 
        if (GIT_EOL_NATIVE == GIT_EOL_CRLF)
                systype = "windows";
        else
                systype = "posix";
 
-       git_buf_dispose(&reponame);
+       git_str_dispose(&reponame);
 }
 
 void test_checkout_crlf__cleanup(void)
@@ -55,7 +55,7 @@ void test_checkout_crlf__cleanup(void)
 
        if (expected_fixture.size) {
                cl_fixture_cleanup(expected_fixture.ptr);
-               git_buf_dispose(&expected_fixture);
+               git_str_dispose(&expected_fixture);
        }
 }
 
@@ -66,17 +66,17 @@ struct compare_data
        const char *attrs;
 };
 
-static int compare_file(void *payload, git_buf *actual_path)
+static int compare_file(void *payload, git_str *actual_path)
 {
-       git_buf expected_path = GIT_BUF_INIT;
-       git_buf actual_contents = GIT_BUF_INIT;
-       git_buf expected_contents = GIT_BUF_INIT;
+       git_str expected_path = GIT_STR_INIT;
+       git_str actual_contents = GIT_STR_INIT;
+       git_str expected_contents = GIT_STR_INIT;
        struct compare_data *cd = payload;
        bool failed = true;
        int cmp_git, cmp_gitattributes;
        char *basename;
 
-       basename = git_path_basename(actual_path->ptr);
+       basename = git_fs_path_basename(actual_path->ptr);
        cmp_git = strcmp(basename, ".git");
        cmp_gitattributes = strcmp(basename, ".gitattributes");
 
@@ -85,10 +85,10 @@ static int compare_file(void *payload, git_buf *actual_path)
                goto done;
        }
 
-       cl_git_pass(git_buf_joinpath(&expected_path, cd->dirname, basename));
+       cl_git_pass(git_str_joinpath(&expected_path, cd->dirname, basename));
 
-       if (!git_path_isfile(expected_path.ptr) ||
-               !git_path_isfile(actual_path->ptr))
+       if (!git_fs_path_isfile(expected_path.ptr) ||
+               !git_fs_path_isfile(actual_path->ptr))
                goto done;
 
        if (git_futils_readbuffer(&actual_contents, actual_path->ptr) < 0 ||
@@ -105,78 +105,78 @@ static int compare_file(void *payload, git_buf *actual_path)
 
 done:
        if (failed) {
-               git_buf details = GIT_BUF_INIT;
-               git_buf_printf(&details, "filename=%s, system=%s, autocrlf=%s, attrs={%s}",
-                       git_path_basename(actual_path->ptr), systype, cd->autocrlf, cd->attrs);
+               git_str details = GIT_STR_INIT;
+               git_str_printf(&details, "filename=%s, system=%s, autocrlf=%s, attrs={%s}",
+                       git_fs_path_basename(actual_path->ptr), systype, cd->autocrlf, cd->attrs);
                clar__fail(__FILE__, __func__, __LINE__,
                        "checked out contents did not match expected", details.ptr, 0);
-               git_buf_dispose(&details);
+               git_str_dispose(&details);
        }
 
        git__free(basename);
-       git_buf_dispose(&expected_contents);
-       git_buf_dispose(&actual_contents);
-       git_buf_dispose(&expected_path);
+       git_str_dispose(&expected_contents);
+       git_str_dispose(&actual_contents);
+       git_str_dispose(&expected_path);
 
        return 0;
 }
 
 static void test_checkout(const char *autocrlf, const char *attrs)
 {
-       git_buf attrbuf = GIT_BUF_INIT;
-       git_buf expected_dirname = GIT_BUF_INIT;
-       git_buf systype_and_direction = GIT_BUF_INIT;
-       git_buf sandboxname = GIT_BUF_INIT;
-       git_buf reponame = GIT_BUF_INIT;
+       git_str attrbuf = GIT_STR_INIT;
+       git_str expected_dirname = GIT_STR_INIT;
+       git_str systype_and_direction = GIT_STR_INIT;
+       git_str sandboxname = GIT_STR_INIT;
+       git_str reponame = GIT_STR_INIT;
        git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
        struct compare_data compare_data = { NULL, autocrlf, attrs };
        const char *c;
 
-       cl_git_pass(git_buf_puts(&reponame, "crlf"));
+       cl_git_pass(git_str_puts(&reponame, "crlf"));
 
-       cl_git_pass(git_buf_puts(&systype_and_direction, systype));
-       cl_git_pass(git_buf_puts(&systype_and_direction, "_to_workdir"));
+       cl_git_pass(git_str_puts(&systype_and_direction, systype));
+       cl_git_pass(git_str_puts(&systype_and_direction, "_to_workdir"));
 
-       cl_git_pass(git_buf_puts(&sandboxname, "autocrlf_"));
-       cl_git_pass(git_buf_puts(&sandboxname, autocrlf));
+       cl_git_pass(git_str_puts(&sandboxname, "autocrlf_"));
+       cl_git_pass(git_str_puts(&sandboxname, autocrlf));
 
        if (*attrs) {
-               cl_git_pass(git_buf_puts(&sandboxname, ","));
+               cl_git_pass(git_str_puts(&sandboxname, ","));
 
                for (c = attrs; *c; c++) {
                        if (*c == ' ')
-                               cl_git_pass(git_buf_putc(&sandboxname, ','));
+                               cl_git_pass(git_str_putc(&sandboxname, ','));
                        else if (*c == '=')
-                               cl_git_pass(git_buf_putc(&sandboxname, '_'));
+                               cl_git_pass(git_str_putc(&sandboxname, '_'));
                        else
-                               cl_git_pass(git_buf_putc(&sandboxname, *c));
+                               cl_git_pass(git_str_putc(&sandboxname, *c));
                }
 
-               cl_git_pass(git_buf_printf(&attrbuf, "* %s\n", attrs));
+               cl_git_pass(git_str_printf(&attrbuf, "* %s\n", attrs));
                cl_git_mkfile("crlf/.gitattributes", attrbuf.ptr);
        }
 
        cl_repo_set_string(g_repo, "core.autocrlf", autocrlf);
 
-       cl_git_pass(git_buf_joinpath(&expected_dirname, systype_and_direction.ptr, sandboxname.ptr));
-       cl_git_pass(git_buf_joinpath(&expected_fixture, "crlf_data", expected_dirname.ptr));
+       cl_git_pass(git_str_joinpath(&expected_dirname, systype_and_direction.ptr, sandboxname.ptr));
+       cl_git_pass(git_str_joinpath(&expected_fixture, "crlf_data", expected_dirname.ptr));
        cl_fixture_sandbox(expected_fixture.ptr);
 
        opts.checkout_strategy = GIT_CHECKOUT_FORCE;
        cl_git_pass(git_checkout_head(g_repo, &opts));
 
        compare_data.dirname = sandboxname.ptr;
-       cl_git_pass(git_path_direach(&reponame, 0, compare_file, &compare_data));
+       cl_git_pass(git_fs_path_direach(&reponame, 0, compare_file, &compare_data));
 
        cl_fixture_cleanup(expected_fixture.ptr);
-       git_buf_dispose(&expected_fixture);
-
-       git_buf_dispose(&attrbuf);
-       git_buf_dispose(&expected_fixture);
-       git_buf_dispose(&expected_dirname);
-       git_buf_dispose(&sandboxname);
-       git_buf_dispose(&systype_and_direction);
-       git_buf_dispose(&reponame);
+       git_str_dispose(&expected_fixture);
+
+       git_str_dispose(&attrbuf);
+       git_str_dispose(&expected_fixture);
+       git_str_dispose(&expected_dirname);
+       git_str_dispose(&sandboxname);
+       git_str_dispose(&systype_and_direction);
+       git_str_dispose(&reponame);
 }
 
 static void empty_workdir(const char *name)
@@ -187,9 +187,9 @@ static void empty_workdir(const char *name)
        size_t i;
        const char *fn;
 
-       cl_git_pass(git_path_dirload(&contents, name, 0, 0));
+       cl_git_pass(git_fs_path_dirload(&contents, name, 0, 0));
        git_vector_foreach(&contents, i, fn) {
-               cl_assert(basename = git_path_basename(fn));
+               cl_assert(basename = git_fs_path_basename(fn));
                cmp = strncasecmp(basename, ".git", 4);
 
                git__free(basename);
@@ -239,10 +239,10 @@ void test_checkout_crlf__autocrlf_false_index_size_is_unfiltered_size(void)
 
        cl_repo_set_bool(g_repo, "core.autocrlf", false);
 
-       git_repository_index(&index, g_repo);
+       cl_git_pass(git_repository_index(&index, g_repo));
        tick_index(index);
 
-       git_checkout_head(g_repo, &opts);
+       cl_git_pass(git_checkout_head(g_repo, &opts));
 
        cl_assert((entry = git_index_get_bypath(index, "all-lf", 0)) != NULL);
        cl_assert(entry->file_size == strlen(ALL_LF_TEXT_RAW));
index 5b3a034e77a18cd59ecccb2cb59f5a5dc899681f..3b0bf4729968e3fcaa31f9738a2f47569dd987b2 100644 (file)
@@ -43,7 +43,7 @@ void test_checkout_head__with_index_only_tree(void)
        cl_git_pass(git_index_add_bypath(index, "newdir/newfile.txt"));
        cl_git_pass(git_index_write(index));
 
-       cl_assert(git_path_isfile("testrepo/newdir/newfile.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/newdir/newfile.txt"));
        cl_assert(git_index_get_bypath(index, "newdir/newfile.txt", 0) != NULL);
 
        git_index_free(index);
@@ -55,7 +55,7 @@ void test_checkout_head__with_index_only_tree(void)
 
        cl_git_pass(git_repository_index(&index, g_repo));
 
-       cl_assert(!git_path_isfile("testrepo/newdir/newfile.txt"));
+       cl_assert(!git_fs_path_isfile("testrepo/newdir/newfile.txt"));
        cl_assert(git_index_get_bypath(index, "newdir/newfile.txt", 0) == NULL);
 
        git_index_free(index);
@@ -79,8 +79,8 @@ void test_checkout_head__do_not_remove_untracked_file(void)
        opts.checkout_strategy = GIT_CHECKOUT_FORCE;
        cl_git_pass(git_checkout_head(g_repo, &opts));
 
-       cl_assert(!git_path_isfile("testrepo/tracked/tracked"));
-       cl_assert(git_path_isfile("testrepo/tracked/untracked"));
+       cl_assert(!git_fs_path_isfile("testrepo/tracked/tracked"));
+       cl_assert(git_fs_path_isfile("testrepo/tracked/untracked"));
 }
 
 void test_checkout_head__do_not_remove_untracked_file_in_subdir(void)
@@ -104,9 +104,9 @@ void test_checkout_head__do_not_remove_untracked_file_in_subdir(void)
        opts.checkout_strategy = GIT_CHECKOUT_FORCE;
        cl_git_pass(git_checkout_head(g_repo, &opts));
 
-       cl_assert(!git_path_isfile("testrepo/tracked/tracked"));
-       cl_assert(!git_path_isfile("testrepo/tracked/subdir/tracked"));
-       cl_assert(git_path_isfile("testrepo/tracked/subdir/untracked"));
+       cl_assert(!git_fs_path_isfile("testrepo/tracked/tracked"));
+       cl_assert(!git_fs_path_isfile("testrepo/tracked/subdir/tracked"));
+       cl_assert(git_fs_path_isfile("testrepo/tracked/subdir/untracked"));
 }
 
 void test_checkout_head__do_remove_untracked_paths(void)
@@ -131,8 +131,8 @@ void test_checkout_head__do_remove_untracked_paths(void)
        opts.paths.count = 1;
        cl_git_pass(git_checkout_head(g_repo, &opts));
 
-       cl_assert(git_path_isfile("testrepo/tracked/tracked"));
-       cl_assert(!git_path_isfile("testrepo/tracked/untracked"));
+       cl_assert(git_fs_path_isfile("testrepo/tracked/tracked"));
+       cl_assert(!git_fs_path_isfile("testrepo/tracked/untracked"));
 }
 
 void test_checkout_head__do_remove_tracked_subdir(void)
@@ -158,9 +158,9 @@ void test_checkout_head__do_remove_tracked_subdir(void)
        opts.checkout_strategy = GIT_CHECKOUT_FORCE;
        cl_git_pass(git_checkout_head(g_repo, &opts));
 
-       cl_assert(!git_path_isdir("testrepo/subdir/tracked"));
-       cl_assert(!git_path_isfile("testrepo/subdir/tracked-file"));
-       cl_assert(git_path_isfile("testrepo/subdir/untracked-file"));
+       cl_assert(!git_fs_path_isdir("testrepo/subdir/tracked"));
+       cl_assert(!git_fs_path_isfile("testrepo/subdir/tracked-file"));
+       cl_assert(git_fs_path_isfile("testrepo/subdir/untracked-file"));
 }
 
 void test_checkout_head__typechange_workdir(void)
index 077d24cd3af1f8a59ec07a7f600909368b5d3782..d77c7abd514a2edb25b6623506d9e22208f94c83 100644 (file)
@@ -46,19 +46,19 @@ void test_checkout_icase__cleanup(void)
 static char *get_filename(const char *in)
 {
        char *search_dirname, *search_filename, *filename = NULL;
-       git_buf out = GIT_BUF_INIT;
+       git_str out = GIT_STR_INIT;
        DIR *dir;
        struct dirent *de;
 
-       cl_assert(search_dirname = git_path_dirname(in));
-       cl_assert(search_filename = git_path_basename(in));
+       cl_assert(search_dirname = git_fs_path_dirname(in));
+       cl_assert(search_filename = git_fs_path_basename(in));
 
        cl_assert(dir = opendir(search_dirname));
 
        while ((de = readdir(dir))) {
                if (strcasecmp(de->d_name, search_filename) == 0) {
-                       git_buf_join(&out, '/', search_dirname, de->d_name);
-                       filename = git_buf_detach(&out);
+                       git_str_join(&out, '/', search_dirname, de->d_name);
+                       filename = git_str_detach(&out);
                        break;
                }
        }
@@ -67,7 +67,7 @@ static char *get_filename(const char *in)
 
        git__free(search_dirname);
        git__free(search_filename);
-       git_buf_dispose(&out);
+       git_str_dispose(&out);
 
        return filename;
 }
@@ -134,7 +134,7 @@ void test_checkout_icase__refuses_to_overwrite_links_for_files(void)
 
        cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
 
-       cl_assert(!git_path_exists("tmp"));
+       cl_assert(!git_fs_path_exists("tmp"));
        assert_name_is("testrepo/BRANCH_FILE.txt");
 }
 
@@ -146,7 +146,7 @@ void test_checkout_icase__overwrites_links_for_files_when_forced(void)
 
        cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
 
-       cl_assert(!git_path_exists("tmp"));
+       cl_assert(!git_fs_path_exists("tmp"));
        assert_name_is("testrepo/new.txt");
 }
 
@@ -159,7 +159,7 @@ void test_checkout_icase__overwrites_empty_folders_for_files(void)
        cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
 
        assert_name_is("testrepo/new.txt");
-       cl_assert(!git_path_isdir("testrepo/new.txt"));
+       cl_assert(!git_fs_path_isdir("testrepo/new.txt"));
 }
 
 void test_checkout_icase__refuses_to_overwrite_populated_folders_for_files(void)
@@ -173,7 +173,7 @@ void test_checkout_icase__refuses_to_overwrite_populated_folders_for_files(void)
        cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
 
        assert_name_is("testrepo/BRANCH_FILE.txt");
-       cl_assert(git_path_isdir("testrepo/BRANCH_FILE.txt"));
+       cl_assert(git_fs_path_isdir("testrepo/BRANCH_FILE.txt"));
 }
 
 void test_checkout_icase__overwrites_folders_for_files_when_forced(void)
@@ -187,7 +187,7 @@ void test_checkout_icase__overwrites_folders_for_files_when_forced(void)
        cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
 
        assert_name_is("testrepo/new.txt");
-       cl_assert(!git_path_isdir("testrepo/new.txt"));
+       cl_assert(!git_fs_path_isdir("testrepo/new.txt"));
 }
 
 void test_checkout_icase__refuses_to_overwrite_files_for_folders(void)
@@ -199,7 +199,7 @@ void test_checkout_icase__refuses_to_overwrite_files_for_folders(void)
 
        cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
        assert_name_is("testrepo/A");
-       cl_assert(!git_path_isdir("testrepo/A"));
+       cl_assert(!git_fs_path_isdir("testrepo/A"));
 }
 
 void test_checkout_icase__overwrites_files_for_folders_when_forced(void)
@@ -211,7 +211,7 @@ void test_checkout_icase__overwrites_files_for_folders_when_forced(void)
 
        cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
        assert_name_is("testrepo/a");
-       cl_assert(git_path_isdir("testrepo/a"));
+       cl_assert(git_fs_path_isdir("testrepo/a"));
 }
 
 void test_checkout_icase__refuses_to_overwrite_links_for_folders(void)
@@ -222,7 +222,7 @@ void test_checkout_icase__refuses_to_overwrite_links_for_folders(void)
 
        cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
 
-       cl_assert(!git_path_exists("b.txt"));
+       cl_assert(!git_fs_path_exists("b.txt"));
        assert_name_is("testrepo/A");
 }
 
@@ -234,7 +234,7 @@ void test_checkout_icase__overwrites_links_for_folders_when_forced(void)
 
        cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
 
-       cl_assert(!git_path_exists("b.txt"));
+       cl_assert(!git_fs_path_exists("b.txt"));
        assert_name_is("testrepo/a");
 }
 
index 5089753656d7e7445af55d94a154ea380ee86219..6a80d22c58f9c5194c7bbaba73a01deb3b06f285 100644 (file)
@@ -8,7 +8,7 @@
 #include "repo/repo_helpers.h"
 
 static git_repository *g_repo;
-static git_buf g_global_path = GIT_BUF_INIT;
+static git_str g_global_path = GIT_STR_INIT;
 
 void test_checkout_index__initialize(void)
 {
@@ -33,7 +33,7 @@ void test_checkout_index__cleanup(void)
 {
        git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL,
                g_global_path.ptr);
-       git_buf_dispose(&g_global_path);
+       git_str_dispose(&g_global_path);
 
        cl_git_sandbox_cleanup();
 
@@ -56,9 +56,9 @@ void test_checkout_index__can_create_missing_files(void)
 {
        git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
 
-       cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
-       cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt"));
-       cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt"));
+       cl_assert_equal_i(false, git_fs_path_isfile("./testrepo/README"));
+       cl_assert_equal_i(false, git_fs_path_isfile("./testrepo/branch_file.txt"));
+       cl_assert_equal_i(false, git_fs_path_isfile("./testrepo/new.txt"));
 
        opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_RECREATE_MISSING;
 
@@ -77,7 +77,7 @@ void test_checkout_index__can_remove_untracked_files(void)
        cl_git_mkfile("./testrepo/dir/one", "one\n");
        cl_git_mkfile("./testrepo/dir/subdir/two", "two\n");
 
-       cl_assert_equal_i(true, git_path_isdir("./testrepo/dir/subdir/subsubdir"));
+       cl_assert_equal_i(true, git_fs_path_isdir("./testrepo/dir/subdir/subsubdir"));
 
        opts.checkout_strategy =
                GIT_CHECKOUT_SAFE |
@@ -86,7 +86,7 @@ void test_checkout_index__can_remove_untracked_files(void)
 
        cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
 
-       cl_assert_equal_i(false, git_path_isdir("./testrepo/dir"));
+       cl_assert_equal_i(false, git_fs_path_isdir("./testrepo/dir"));
 }
 
 void test_checkout_index__can_disable_pathspec_match(void)
@@ -152,15 +152,15 @@ void test_checkout_index__honor_the_specified_pathspecs(void)
        opts.paths.strings = entries;
        opts.paths.count = 1;
 
-       cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
-       cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt"));
-       cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt"));
+       cl_assert_equal_i(false, git_fs_path_isfile("./testrepo/README"));
+       cl_assert_equal_i(false, git_fs_path_isfile("./testrepo/branch_file.txt"));
+       cl_assert_equal_i(false, git_fs_path_isfile("./testrepo/new.txt"));
 
        opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_RECREATE_MISSING;
 
        cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
 
-       cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
+       cl_assert_equal_i(false, git_fs_path_isfile("./testrepo/README"));
        check_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n");
        check_file_contents("./testrepo/new.txt", "my new file\n");
 }
@@ -203,14 +203,14 @@ void test_checkout_index__honor_coreautocrlf_setting_set_to_true(void)
 
 static void populate_symlink_workdir(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_repository *repo;
        git_remote *origin;
        git_object *target;
 
        const char *url = git_repository_path(g_repo);
 
-       cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), "symlink.git"));
+       cl_git_pass(git_str_joinpath(&path, clar_sandbox_path(), "symlink.git"));
        cl_git_pass(git_repository_init(&repo, path.ptr, true));
        cl_git_pass(git_repository_set_workdir(repo, "symlink", 1));
 
@@ -226,7 +226,7 @@ static void populate_symlink_workdir(void)
 
        git_object_free(target);
        git_repository_free(repo);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_checkout_index__honor_coresymlinks_default_true(void)
@@ -236,7 +236,7 @@ void test_checkout_index__honor_coresymlinks_default_true(void)
 
        cl_must_pass(p_mkdir("symlink", 0777));
 
-       if (!git_path_supports_symlinks("symlink/test"))
+       if (!git_fs_path_supports_symlinks("symlink/test"))
                cl_skip();
 
 #ifdef GIT_WIN32
@@ -269,7 +269,7 @@ void test_checkout_index__honor_coresymlinks_default_false(void)
         * supports symlinks.  Bail entirely on POSIX platforms that
         * do support symlinks.
         */
-       if (git_path_supports_symlinks("symlink/test"))
+       if (git_fs_path_supports_symlinks("symlink/test"))
                cl_skip();
 #endif
 
@@ -281,7 +281,7 @@ void test_checkout_index__coresymlinks_set_to_true_fails_when_unsupported(void)
 {
        git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
 
-       if (git_path_supports_symlinks("testrepo/test")) {
+       if (git_fs_path_supports_symlinks("testrepo/test")) {
                cl_skip();
        }
 
@@ -297,7 +297,7 @@ void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
        char link_data[GIT_PATH_MAX];
        size_t link_size = GIT_PATH_MAX;
 
-       if (!git_path_supports_symlinks("testrepo/test")) {
+       if (!git_fs_path_supports_symlinks("testrepo/test")) {
                cl_skip();
        }
 
@@ -578,8 +578,8 @@ void test_checkout_index__can_overcome_name_clashes(void)
        cl_git_pass(p_mkdir("./testrepo/path0", 0777));
        cl_git_mkfile("./testrepo/path0/file0", "content\r\n");
 
-       cl_assert(git_path_isfile("./testrepo/path1"));
-       cl_assert(git_path_isfile("./testrepo/path0/file0"));
+       cl_assert(git_fs_path_isfile("./testrepo/path1"));
+       cl_assert(git_fs_path_isfile("./testrepo/path0/file0"));
 
        opts.checkout_strategy =
                GIT_CHECKOUT_SAFE |
@@ -587,14 +587,14 @@ void test_checkout_index__can_overcome_name_clashes(void)
                GIT_CHECKOUT_ALLOW_CONFLICTS;
        cl_git_pass(git_checkout_index(g_repo, index, &opts));
 
-       cl_assert(git_path_isfile("./testrepo/path1"));
-       cl_assert(git_path_isfile("./testrepo/path0/file0"));
+       cl_assert(git_fs_path_isfile("./testrepo/path1"));
+       cl_assert(git_fs_path_isfile("./testrepo/path0/file0"));
 
        opts.checkout_strategy = GIT_CHECKOUT_FORCE;
        cl_git_pass(git_checkout_index(g_repo, index, &opts));
 
-       cl_assert(git_path_isfile("./testrepo/path0"));
-       cl_assert(git_path_isfile("./testrepo/path1/file1"));
+       cl_assert(git_fs_path_isfile("./testrepo/path0"));
+       cl_assert(git_fs_path_isfile("./testrepo/path1/file1"));
 
        git_index_free(index);
 }
@@ -622,9 +622,9 @@ void test_checkout_index__can_update_prefixed_files(void)
 {
        git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
 
-       cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
-       cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt"));
-       cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt"));
+       cl_assert_equal_i(false, git_fs_path_isfile("./testrepo/README"));
+       cl_assert_equal_i(false, git_fs_path_isfile("./testrepo/branch_file.txt"));
+       cl_assert_equal_i(false, git_fs_path_isfile("./testrepo/new.txt"));
 
        cl_git_mkfile("./testrepo/READ", "content\n");
        cl_git_mkfile("./testrepo/README.after", "content\n");
@@ -647,10 +647,10 @@ void test_checkout_index__can_update_prefixed_files(void)
        check_file_contents_nocr("./testrepo/branch_file.txt", "hi\nbye!\n");
        check_file_contents_nocr("./testrepo/new.txt", "my new file\n");
 
-       cl_assert(!git_path_exists("testrepo/READ"));
-       cl_assert(!git_path_exists("testrepo/README.after"));
-       cl_assert(!git_path_exists("testrepo/branch_file"));
-       cl_assert(!git_path_exists("testrepo/branch_file.txt.after"));
+       cl_assert(!git_fs_path_exists("testrepo/READ"));
+       cl_assert(!git_fs_path_exists("testrepo/README.after"));
+       cl_assert(!git_fs_path_exists("testrepo/branch_file"));
+       cl_assert(!git_fs_path_exists("testrepo/branch_file.txt.after"));
 }
 
 void test_checkout_index__can_checkout_a_newly_initialized_repository(void)
@@ -688,7 +688,7 @@ void test_checkout_index__target_directory(void)
        opts.checkout_strategy = GIT_CHECKOUT_SAFE |
                GIT_CHECKOUT_RECREATE_MISSING;
        opts.target_directory = "alternative";
-       cl_assert(!git_path_isdir("alternative"));
+       cl_assert(!git_fs_path_isdir("alternative"));
 
        opts.notify_flags = GIT_CHECKOUT_NOTIFY_ALL;
        opts.notify_cb = checkout_count_callback;
@@ -741,7 +741,7 @@ void test_checkout_index__target_directory_from_bare(void)
        cl_git_fail(git_checkout_index(g_repo, NULL, &opts));
 
        opts.target_directory = "alternative";
-       cl_assert(!git_path_isdir("alternative"));
+       cl_assert(!git_fs_path_isdir("alternative"));
 
        cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
 
@@ -765,9 +765,9 @@ void test_checkout_index__can_get_repo_from_index(void)
        git_index *index;
        git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
 
-       cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
-       cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt"));
-       cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt"));
+       cl_assert_equal_i(false, git_fs_path_isfile("./testrepo/README"));
+       cl_assert_equal_i(false, git_fs_path_isfile("./testrepo/branch_file.txt"));
+       cl_assert_equal_i(false, git_fs_path_isfile("./testrepo/new.txt"));
 
        opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_RECREATE_MISSING;
 
@@ -808,7 +808,7 @@ void test_checkout_index__writes_conflict_file(void)
 {
        git_index *index;
        git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
-       git_buf conflicting_buf = GIT_BUF_INIT;
+       git_str conflicting_buf = GIT_STR_INIT;
 
        cl_git_pass(git_repository_index(&index, g_repo));
 
@@ -824,7 +824,7 @@ void test_checkout_index__writes_conflict_file(void)
                "=======\n"
                "this file is changed in branch and master\n"
                ">>>>>>> theirs\n") == 0);
-       git_buf_dispose(&conflicting_buf);
+       git_str_dispose(&conflicting_buf);
 
        git_index_free(index);
 }
@@ -855,7 +855,7 @@ void test_checkout_index__conflicts_honor_coreautocrlf(void)
 #ifdef GIT_WIN32
        git_index *index;
        git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
-       git_buf conflicting_buf = GIT_BUF_INIT;
+       git_str conflicting_buf = GIT_STR_INIT;
 
        cl_git_pass(p_unlink("./testrepo/.gitattributes"));
        cl_repo_set_bool(g_repo, "core.autocrlf", true);
@@ -874,7 +874,7 @@ void test_checkout_index__conflicts_honor_coreautocrlf(void)
                "=======\r\n"
                "this file is changed in branch and master\r\n"
                ">>>>>>> theirs\r\n") == 0);
-       git_buf_dispose(&conflicting_buf);
+       git_str_dispose(&conflicting_buf);
 
        git_index_free(index);
 #endif
index 611e850d39294f3a94ba28eb7566d797bc9d1d40..732f1d5e8bd9fcffad9e5a29f7c63756668e041c 100644 (file)
@@ -3,7 +3,6 @@
 
 #include "git2/checkout.h"
 #include "repository.h"
-#include "buffer.h"
 #include "futils.h"
 
 static const char *repo_name = "nasty";
@@ -28,9 +27,9 @@ static void test_checkout_passes(const char *refname, const char *filename)
        git_oid commit_id;
        git_commit *commit;
        git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&path, repo_name, filename));
+       cl_git_pass(git_str_joinpath(&path, repo_name, filename));
 
        cl_git_pass(git_reference_name_to_id(&commit_id, repo, refname));
        cl_git_pass(git_commit_lookup(&commit, repo, &commit_id));
@@ -39,10 +38,10 @@ static void test_checkout_passes(const char *refname, const char *filename)
                GIT_CHECKOUT_DONT_UPDATE_INDEX;
 
        cl_git_pass(git_checkout_tree(repo, (const git_object *)commit, &opts));
-       cl_assert(!git_path_exists(path.ptr));
+       cl_assert(!git_fs_path_exists(path.ptr));
 
        git_commit_free(commit);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 static void test_checkout_fails(const char *refname, const char *filename)
@@ -50,9 +49,9 @@ static void test_checkout_fails(const char *refname, const char *filename)
        git_oid commit_id;
        git_commit *commit;
        git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&path, repo_name, filename));
+       cl_git_pass(git_str_joinpath(&path, repo_name, filename));
 
        cl_git_pass(git_reference_name_to_id(&commit_id, repo, refname));
        cl_git_pass(git_commit_lookup(&commit, repo, &commit_id));
@@ -60,10 +59,10 @@ static void test_checkout_fails(const char *refname, const char *filename)
        opts.checkout_strategy = GIT_CHECKOUT_FORCE;
 
        cl_git_fail(git_checkout_tree(repo, (const git_object *)commit, &opts));
-       cl_assert(!git_path_exists(path.ptr));
+       cl_assert(!git_fs_path_exists(path.ptr));
 
        git_commit_free(commit);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 /* A tree that contains ".git" as a tree, with a blob inside
@@ -247,7 +246,7 @@ void test_checkout_nasty__only_looks_like_a_git_shortname(void)
        opts.checkout_strategy = GIT_CHECKOUT_FORCE;
 
        cl_git_pass(git_checkout_tree(repo, (const git_object *)commit, &opts));
-       cl_assert(git_path_exists("nasty/git~3/foobar"));
+       cl_assert(git_fs_path_exists("nasty/git~3/foobar"));
 
        git_commit_free(commit);
 #endif
index 3241a3eb7672dbfe294ca0fc870833a95b63d3db..d4b57f5d14f146ff7dac708ffd069522b851464c 100644 (file)
@@ -3,7 +3,6 @@
 
 #include "git2/checkout.h"
 #include "repository.h"
-#include "buffer.h"
 #include "futils.h"
 
 static git_repository *g_repo;
@@ -35,7 +34,7 @@ void test_checkout_tree__cleanup(void)
 
        cl_git_sandbox_cleanup();
 
-       if (git_path_isdir("alternative"))
+       if (git_fs_path_isdir("alternative"))
                git_futils_rmdir_r("alternative", NULL, GIT_RMDIR_REMOVE_FILES);
 }
 
@@ -55,19 +54,19 @@ void test_checkout_tree__can_checkout_a_subdirectory_from_a_commit(void)
 
        cl_git_pass(git_revparse_single(&g_object, g_repo, "subtrees"));
 
-       cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/"));
+       cl_assert_equal_i(false, git_fs_path_isdir("./testrepo/ab/"));
 
        cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
 
-       cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/2.txt"));
-       cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/fgh/1.txt"));
+       cl_assert_equal_i(true, git_fs_path_isfile("./testrepo/ab/de/2.txt"));
+       cl_assert_equal_i(true, git_fs_path_isfile("./testrepo/ab/de/fgh/1.txt"));
 }
 
 void test_checkout_tree__can_checkout_and_remove_directory(void)
 {
-       cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/"));
+       cl_assert_equal_i(false, git_fs_path_isdir("./testrepo/ab/"));
 
-       /* Checkout brach "subtrees" and update HEAD, so that HEAD matches the
+       /* Checkout branch "subtrees" and update HEAD, so that HEAD matches the
         * current working tree
         */
        cl_git_pass(git_revparse_single(&g_object, g_repo, "subtrees"));
@@ -75,14 +74,14 @@ void test_checkout_tree__can_checkout_and_remove_directory(void)
 
        cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
 
-       cl_assert_equal_i(true, git_path_isdir("./testrepo/ab/"));
-       cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/2.txt"));
-       cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/fgh/1.txt"));
+       cl_assert_equal_i(true, git_fs_path_isdir("./testrepo/ab/"));
+       cl_assert_equal_i(true, git_fs_path_isfile("./testrepo/ab/de/2.txt"));
+       cl_assert_equal_i(true, git_fs_path_isfile("./testrepo/ab/de/fgh/1.txt"));
 
        git_object_free(g_object);
        g_object = NULL;
 
-       /* Checkout brach "master" and update HEAD, so that HEAD matches the
+       /* Checkout branch "master" and update HEAD, so that HEAD matches the
         * current working tree
         */
        cl_git_pass(git_revparse_single(&g_object, g_repo, "master"));
@@ -91,7 +90,7 @@ void test_checkout_tree__can_checkout_and_remove_directory(void)
        cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master"));
 
        /* This directory should no longer exist */
-       cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/"));
+       cl_assert_equal_i(false, git_fs_path_isdir("./testrepo/ab/"));
 }
 
 void test_checkout_tree__can_checkout_a_subdirectory_from_a_subtree(void)
@@ -103,12 +102,12 @@ void test_checkout_tree__can_checkout_a_subdirectory_from_a_subtree(void)
 
        cl_git_pass(git_revparse_single(&g_object, g_repo, "subtrees:ab"));
 
-       cl_assert_equal_i(false, git_path_isdir("./testrepo/de/"));
+       cl_assert_equal_i(false, git_fs_path_isdir("./testrepo/de/"));
 
        cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
 
-       cl_assert_equal_i(true, git_path_isfile("./testrepo/de/2.txt"));
-       cl_assert_equal_i(true, git_path_isfile("./testrepo/de/fgh/1.txt"));
+       cl_assert_equal_i(true, git_fs_path_isfile("./testrepo/de/2.txt"));
+       cl_assert_equal_i(true, git_fs_path_isfile("./testrepo/de/fgh/1.txt"));
 }
 
 static void progress(const char *path, size_t cur, size_t tot, void *payload)
@@ -150,7 +149,7 @@ void test_checkout_tree__doesnt_write_unrequested_files_to_worktree(void)
         */
        opts.checkout_strategy = GIT_CHECKOUT_NONE;
        git_checkout_tree(g_repo, (git_object*)p_chomped_commit, &opts);
-       cl_assert_equal_i(false, git_path_isfile("testrepo/readme.txt"));
+       cl_assert_equal_i(false, git_fs_path_isfile("testrepo/readme.txt"));
 
        git_commit_free(p_master_commit);
        git_commit_free(p_chomped_commit);
@@ -175,12 +174,12 @@ void test_checkout_tree__can_switch_branches(void)
        cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
        cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir"));
 
-       cl_assert(git_path_isfile("testrepo/README"));
-       cl_assert(git_path_isfile("testrepo/branch_file.txt"));
-       cl_assert(git_path_isfile("testrepo/new.txt"));
-       cl_assert(git_path_isfile("testrepo/a/b.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/README"));
+       cl_assert(git_fs_path_isfile("testrepo/branch_file.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/new.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/a/b.txt"));
 
-       cl_assert(!git_path_isdir("testrepo/ab"));
+       cl_assert(!git_fs_path_isdir("testrepo/ab"));
 
        assert_on_branch(g_repo, "dir");
 
@@ -195,15 +194,15 @@ void test_checkout_tree__can_switch_branches(void)
        cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
        cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
 
-       cl_assert(git_path_isfile("testrepo/README"));
-       cl_assert(git_path_isfile("testrepo/branch_file.txt"));
-       cl_assert(git_path_isfile("testrepo/new.txt"));
-       cl_assert(git_path_isfile("testrepo/ab/4.txt"));
-       cl_assert(git_path_isfile("testrepo/ab/c/3.txt"));
-       cl_assert(git_path_isfile("testrepo/ab/de/2.txt"));
-       cl_assert(git_path_isfile("testrepo/ab/de/fgh/1.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/README"));
+       cl_assert(git_fs_path_isfile("testrepo/branch_file.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/new.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/ab/4.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/ab/c/3.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/ab/de/2.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/ab/de/fgh/1.txt"));
 
-       cl_assert(!git_path_isdir("testrepo/a"));
+       cl_assert(!git_fs_path_isdir("testrepo/a"));
 
        assert_on_branch(g_repo, "subtrees");
 
@@ -217,11 +216,11 @@ void test_checkout_tree__can_remove_untracked(void)
        opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_REMOVE_UNTRACKED;
 
        cl_git_mkfile("testrepo/untracked_file", "as you wish");
-       cl_assert(git_path_isfile("testrepo/untracked_file"));
+       cl_assert(git_fs_path_isfile("testrepo/untracked_file"));
 
        cl_git_pass(git_checkout_head(g_repo, &opts));
 
-       cl_assert(!git_path_isfile("testrepo/untracked_file"));
+       cl_assert(!git_fs_path_isfile("testrepo/untracked_file"));
 }
 
 void test_checkout_tree__can_remove_ignored(void)
@@ -238,11 +237,11 @@ void test_checkout_tree__can_remove_ignored(void)
        cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "ignored_file"));
        cl_assert_equal_i(1, ignored);
 
-       cl_assert(git_path_isfile("testrepo/ignored_file"));
+       cl_assert(git_fs_path_isfile("testrepo/ignored_file"));
 
        cl_git_pass(git_checkout_head(g_repo, &opts));
 
-       cl_assert(!git_path_isfile("testrepo/ignored_file"));
+       cl_assert(!git_fs_path_isfile("testrepo/ignored_file"));
 }
 
 static int checkout_tree_with_blob_ignored_in_workdir(int strategy, bool isdir)
@@ -265,12 +264,12 @@ static int checkout_tree_with_blob_ignored_in_workdir(int strategy, bool isdir)
        cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
        cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir"));
 
-       cl_assert(git_path_isfile("testrepo/README"));
-       cl_assert(git_path_isfile("testrepo/branch_file.txt"));
-       cl_assert(git_path_isfile("testrepo/new.txt"));
-       cl_assert(git_path_isfile("testrepo/a/b.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/README"));
+       cl_assert(git_fs_path_isfile("testrepo/branch_file.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/new.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/a/b.txt"));
 
-       cl_assert(!git_path_isdir("testrepo/ab"));
+       cl_assert(!git_fs_path_isdir("testrepo/ab"));
 
        assert_on_branch(g_repo, "dir");
 
@@ -286,12 +285,12 @@ static int checkout_tree_with_blob_ignored_in_workdir(int strategy, bool isdir)
                cl_git_mkfile("testrepo/ab/4.txt/file2.txt", "foo bar foo");
                cl_git_mkfile("testrepo/ab/4.txt/file3.txt", "inky blinky pinky clyde");
 
-               cl_assert(git_path_isdir("testrepo/ab/4.txt"));
+               cl_assert(git_fs_path_isdir("testrepo/ab/4.txt"));
        } else {
                cl_must_pass(p_mkdir("testrepo/ab", 0777));
                cl_git_mkfile("testrepo/ab/4.txt", "as you wish");
 
-               cl_assert(git_path_isfile("testrepo/ab/4.txt"));
+               cl_assert(git_fs_path_isfile("testrepo/ab/4.txt"));
        }
 
        cl_git_pass(git_ignore_add_rule(g_repo, "ab/4.txt\n"));
@@ -325,7 +324,7 @@ void test_checkout_tree__can_overwrite_ignored_by_default(void)
 
        cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
 
-       cl_assert(git_path_isfile("testrepo/ab/4.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/ab/4.txt"));
 
        assert_on_branch(g_repo, "subtrees");
 }
@@ -346,7 +345,7 @@ void test_checkout_tree__can_overwrite_ignored_folder_by_default(void)
 
        cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
 
-       cl_assert(git_path_isfile("testrepo/ab/4.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/ab/4.txt"));
 
        assert_on_branch(g_repo, "subtrees");
 
@@ -365,7 +364,7 @@ void test_checkout_tree__can_update_only(void)
        opts.checkout_strategy = GIT_CHECKOUT_FORCE;
        cl_git_pass(git_checkout_head(g_repo, &opts));
 
-       cl_assert(!git_path_isdir("testrepo/a"));
+       cl_assert(!git_fs_path_isdir("testrepo/a"));
 
        check_file_contents_nocr("testrepo/branch_file.txt", "hi\nbye!\n");
 
@@ -385,7 +384,7 @@ void test_checkout_tree__can_update_only(void)
         * the test_checkout_tree__can_switch_branches test), but with
         * UPDATE_ONLY it will not have been created.
         */
-       cl_assert(!git_path_isdir("testrepo/a"));
+       cl_assert(!git_fs_path_isdir("testrepo/a"));
 
        /* but this file still should have been updated */
        check_file_contents_nocr("testrepo/branch_file.txt", "hi\n");
@@ -411,10 +410,10 @@ void test_checkout_tree__can_checkout_with_pattern(void)
        git_object_free(g_object);
        g_object = NULL;
 
-       cl_assert(git_path_exists("testrepo/README"));
-       cl_assert(!git_path_exists("testrepo/branch_file.txt"));
-       cl_assert(!git_path_exists("testrepo/link_to_new.txt"));
-       cl_assert(!git_path_exists("testrepo/new.txt"));
+       cl_assert(git_fs_path_exists("testrepo/README"));
+       cl_assert(!git_fs_path_exists("testrepo/branch_file.txt"));
+       cl_assert(!git_fs_path_exists("testrepo/link_to_new.txt"));
+       cl_assert(!git_fs_path_exists("testrepo/new.txt"));
 
        /* now to a narrow patterned checkout */
 
@@ -426,10 +425,10 @@ void test_checkout_tree__can_checkout_with_pattern(void)
 
        cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
 
-       cl_assert(git_path_exists("testrepo/README"));
-       cl_assert(!git_path_exists("testrepo/branch_file.txt"));
-       cl_assert(git_path_exists("testrepo/link_to_new.txt"));
-       cl_assert(git_path_exists("testrepo/new.txt"));
+       cl_assert(git_fs_path_exists("testrepo/README"));
+       cl_assert(!git_fs_path_exists("testrepo/branch_file.txt"));
+       cl_assert(git_fs_path_exists("testrepo/link_to_new.txt"));
+       cl_assert(git_fs_path_exists("testrepo/new.txt"));
 }
 
 void test_checkout_tree__pathlist_checkout_ignores_non_matches(void)
@@ -446,10 +445,10 @@ void test_checkout_tree__pathlist_checkout_ignores_non_matches(void)
        cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
        cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master"));
 
-       cl_assert(git_path_exists("testrepo/README"));
-       cl_assert(git_path_exists("testrepo/branch_file.txt"));
-       cl_assert(git_path_exists("testrepo/link_to_new.txt"));
-       cl_assert(git_path_exists("testrepo/new.txt"));
+       cl_assert(git_fs_path_exists("testrepo/README"));
+       cl_assert(git_fs_path_exists("testrepo/branch_file.txt"));
+       cl_assert(git_fs_path_exists("testrepo/link_to_new.txt"));
+       cl_assert(git_fs_path_exists("testrepo/new.txt"));
 
        git_object_free(g_object);
        cl_git_pass(git_revparse_single(&g_object, g_repo, "8496071c1b46c854b31185ea97743be6a8774479"));
@@ -461,10 +460,10 @@ void test_checkout_tree__pathlist_checkout_ignores_non_matches(void)
 
        cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
 
-       cl_assert(git_path_exists("testrepo/README"));
-       cl_assert(!git_path_exists("testrepo/branch_file.txt"));
-       cl_assert(!git_path_exists("testrepo/link_to_new.txt"));
-       cl_assert(git_path_exists("testrepo/new.txt"));
+       cl_assert(git_fs_path_exists("testrepo/README"));
+       cl_assert(!git_fs_path_exists("testrepo/branch_file.txt"));
+       cl_assert(!git_fs_path_exists("testrepo/link_to_new.txt"));
+       cl_assert(git_fs_path_exists("testrepo/new.txt"));
 }
 
 void test_checkout_tree__can_disable_pattern_match(void)
@@ -485,7 +484,7 @@ void test_checkout_tree__can_disable_pattern_match(void)
        git_object_free(g_object);
        g_object = NULL;
 
-       cl_assert(!git_path_isfile("testrepo/branch_file.txt"));
+       cl_assert(!git_fs_path_isfile("testrepo/branch_file.txt"));
 
        /* now to a narrow patterned checkout, but disable pattern */
 
@@ -499,7 +498,7 @@ void test_checkout_tree__can_disable_pattern_match(void)
 
        cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
 
-       cl_assert(!git_path_isfile("testrepo/branch_file.txt"));
+       cl_assert(!git_fs_path_isfile("testrepo/branch_file.txt"));
 
        /* let's try that again, but allow the pattern match */
 
@@ -507,10 +506,10 @@ void test_checkout_tree__can_disable_pattern_match(void)
 
        cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
 
-       cl_assert(git_path_isfile("testrepo/branch_file.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/branch_file.txt"));
 }
 
-void assert_conflict(
+static void assert_conflict(
        const char *entry_path,
        const char *new_content,
        const char *parent_sha,
@@ -519,7 +518,7 @@ void assert_conflict(
        git_index *index;
        git_object *hack_tree;
        git_reference *branch, *head;
-       git_buf file_path = GIT_BUF_INIT;
+       git_str file_path = GIT_STR_INIT;
 
        cl_git_pass(git_repository_index(&index, g_repo));
 
@@ -538,7 +537,7 @@ void assert_conflict(
        g_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
        cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
 
-       /* Hack-ishy workaound to ensure *all* the index entries
+       /* Hack-ishy workaround to ensure *all* the index entries
         * match the content of the tree
         */
        cl_git_pass(git_object_peel(&hack_tree, g_object, GIT_OBJECT_TREE));
@@ -549,9 +548,9 @@ void assert_conflict(
        g_object = NULL;
 
        /* Create a conflicting file */
-       cl_git_pass(git_buf_joinpath(&file_path, "./testrepo", entry_path));
-       cl_git_mkfile(git_buf_cstr(&file_path), new_content);
-       git_buf_dispose(&file_path);
+       cl_git_pass(git_str_joinpath(&file_path, "./testrepo", entry_path));
+       cl_git_mkfile(git_str_cstr(&file_path), new_content);
+       git_str_dispose(&file_path);
 
        /* Trying to checkout the original commit */
        cl_git_pass(git_revparse_single(&g_object, g_repo, commit_sha));
@@ -624,7 +623,7 @@ void test_checkout_tree__donot_update_deleted_file_by_default(void)
        cl_git_pass(git_index_remove_bypath(index ,"branch_file.txt"));
        cl_git_pass(git_index_write(index));
 
-       cl_assert(!git_path_exists("testrepo/branch_file.txt"));
+       cl_assert(!git_fs_path_exists("testrepo/branch_file.txt"));
 
        cl_git_pass(git_oid_fromstr(&new_id, "099fabac3a9ea935598528c27f866e34089c2eff"));
        cl_git_pass(git_commit_lookup(&new_commit, g_repo, &new_id));
@@ -687,16 +686,16 @@ void test_checkout_tree__can_cancel_checkout_from_notify(void)
        opts.notify_payload = &ca;
        opts.checkout_strategy = GIT_CHECKOUT_FORCE;
 
-       cl_assert(!git_path_exists("testrepo/new.txt"));
+       cl_assert(!git_fs_path_exists("testrepo/new.txt"));
 
        cl_git_fail_with(git_checkout_tree(g_repo, obj, &opts), -5555);
 
-       cl_assert(!git_path_exists("testrepo/new.txt"));
+       cl_assert(!git_fs_path_exists("testrepo/new.txt"));
 
        /* on case-insensitive FS = a/b.txt, branch_file.txt, new.txt */
        /* on case-sensitive FS   = README, then above */
 
-       if (git_path_exists("testrepo/.git/CoNfIg")) /* case insensitive */
+       if (git_fs_path_exists("testrepo/.git/CoNfIg")) /* case insensitive */
                cl_assert_equal_i(3, ca.count);
        else
                cl_assert_equal_i(4, ca.count);
@@ -708,9 +707,9 @@ void test_checkout_tree__can_cancel_checkout_from_notify(void)
 
        cl_git_fail_with(git_checkout_tree(g_repo, obj, &opts), 123);
 
-       cl_assert(!git_path_exists("testrepo/new.txt"));
+       cl_assert(!git_fs_path_exists("testrepo/new.txt"));
 
-       if (git_path_exists("testrepo/.git/CoNfIg")) /* case insensitive */
+       if (git_fs_path_exists("testrepo/.git/CoNfIg")) /* case insensitive */
                cl_assert_equal_i(4, ca.count);
        else
                cl_assert_equal_i(1, ca.count);
@@ -800,7 +799,7 @@ void test_checkout_tree__can_write_to_empty_dirs(void)
 
        cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
 
-       cl_assert(git_path_isfile("testrepo/a/b.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/a/b.txt"));
 
        git_object_free(obj);
 }
@@ -819,7 +818,7 @@ void test_checkout_tree__fails_when_dir_in_use(void)
 
        cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
 
-       cl_assert(git_path_isfile("testrepo/a/b.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/a/b.txt"));
 
        git_object_free(obj);
 
@@ -832,7 +831,7 @@ void test_checkout_tree__fails_when_dir_in_use(void)
 
        cl_git_pass(p_chdir("../.."));
 
-       cl_assert(git_path_is_empty_dir("testrepo/a"));
+       cl_assert(git_fs_path_is_empty_dir("testrepo/a"));
 
        git_object_free(obj);
 #endif
@@ -853,7 +852,7 @@ void test_checkout_tree__can_continue_when_dir_in_use(void)
 
        cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
 
-       cl_assert(git_path_isfile("testrepo/a/b.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/a/b.txt"));
 
        git_object_free(obj);
 
@@ -866,7 +865,7 @@ void test_checkout_tree__can_continue_when_dir_in_use(void)
 
        cl_git_pass(p_chdir("../.."));
 
-       cl_assert(git_path_is_empty_dir("testrepo/a"));
+       cl_assert(git_fs_path_is_empty_dir("testrepo/a"));
 
        git_object_free(obj);
 #endif
@@ -897,7 +896,7 @@ void test_checkout_tree__target_directory_from_bare(void)
        cl_git_fail(git_checkout_tree(g_repo, g_object, &opts));
 
        opts.target_directory = "alternative";
-       cl_assert(!git_path_isdir("alternative"));
+       cl_assert(!git_fs_path_isdir("alternative"));
 
        cl_git_pass(git_checkout_tree(g_repo, g_object, &opts));
 
@@ -924,12 +923,12 @@ void test_checkout_tree__extremely_long_file_name(void)
        cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
 
        sprintf(path, "testrepo/%s.txt", longname);
-       cl_assert(git_path_exists(path));
+       cl_assert(git_fs_path_exists(path));
 
        git_object_free(g_object);
        cl_git_pass(git_revparse_single(&g_object, g_repo, "master"));
        cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
-       cl_assert(!git_path_exists(path));
+       cl_assert(!git_fs_path_exists(path));
 }
 
 static void create_conflict(const char *path)
@@ -1035,22 +1034,24 @@ void test_checkout_tree__filemode_preserved_in_index(void)
        git_index_free(index);
 }
 
-mode_t read_filemode(const char *path)
+#ifndef GIT_WIN32
+static mode_t read_filemode(const char *path)
 {
-       git_buf fullpath = GIT_BUF_INIT;
+       git_str fullpath = GIT_STR_INIT;
        struct stat st;
        mode_t result;
 
-       git_buf_joinpath(&fullpath, "testrepo", path);
+       git_str_joinpath(&fullpath, "testrepo", path);
        cl_must_pass(p_stat(fullpath.ptr, &st));
 
        result = GIT_PERMS_IS_EXEC(st.st_mode) ?
                GIT_FILEMODE_BLOB_EXECUTABLE : GIT_FILEMODE_BLOB;
 
-       git_buf_dispose(&fullpath);
+       git_str_dispose(&fullpath);
 
        return result;
 }
+#endif
 
 void test_checkout_tree__filemode_preserved_in_workdir(void)
 {
@@ -1139,7 +1140,7 @@ void test_checkout_tree__removes_conflicts(void)
        cl_assert_equal_p(NULL, git_index_get_bypath(index, "other.txt", 2));
        cl_assert_equal_p(NULL, git_index_get_bypath(index, "other.txt", 3));
 
-       cl_assert(!git_path_exists("testrepo/other.txt"));
+       cl_assert(!git_fs_path_exists("testrepo/other.txt"));
 
        git_commit_free(commit);
        git_index_free(index);
@@ -1184,7 +1185,7 @@ void test_checkout_tree__removes_conflicts_only_by_pathscope(void)
        cl_assert(git_index_get_bypath(index, "other.txt", 2) != NULL);
        cl_assert(git_index_get_bypath(index, "other.txt", 3) != NULL);
 
-       cl_assert(git_path_exists("testrepo/other.txt"));
+       cl_assert(git_fs_path_exists("testrepo/other.txt"));
 
        git_commit_free(commit);
        git_index_free(index);
@@ -1215,8 +1216,8 @@ void test_checkout_tree__case_changing_rename(void)
        cl_git_pass(git_checkout_tree(g_repo, (git_object *)dir_commit, &opts));
        cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir"));
 
-       cl_assert(git_path_isfile("testrepo/README"));
-       case_sensitive = !git_path_isfile("testrepo/readme");
+       cl_assert(git_fs_path_isfile("testrepo/README"));
+       case_sensitive = !git_fs_path_isfile("testrepo/readme");
 
        cl_assert(index_entry = git_index_get_bypath(index, "README", 0));
        cl_assert_equal_s("README", index_entry->path);
@@ -1236,9 +1237,9 @@ void test_checkout_tree__case_changing_rename(void)
 
        cl_git_pass(git_commit_create(&commit_id, g_repo, "refs/heads/dir", signature, signature, NULL, "case-changing rename", tree, 1, (const git_commit **)&dir_commit));
 
-       cl_assert(git_path_isfile("testrepo/readme"));
+       cl_assert(git_fs_path_isfile("testrepo/readme"));
        if (case_sensitive)
-               cl_assert(!git_path_isfile("testrepo/README"));
+               cl_assert(!git_fs_path_isfile("testrepo/README"));
 
        cl_assert(index_entry = git_index_get_bypath(index, "readme", 0));
        cl_assert_equal_s("readme", index_entry->path);
@@ -1254,9 +1255,9 @@ void test_checkout_tree__case_changing_rename(void)
 
        assert_on_branch(g_repo, "master");
 
-       cl_assert(git_path_isfile("testrepo/README"));
+       cl_assert(git_fs_path_isfile("testrepo/README"));
        if (case_sensitive)
-               cl_assert(!git_path_isfile("testrepo/readme"));
+               cl_assert(!git_fs_path_isfile("testrepo/readme"));
 
        cl_assert(index_entry = git_index_get_bypath(index, "README", 0));
        cl_assert_equal_s("README", index_entry->path);
@@ -1268,7 +1269,7 @@ void test_checkout_tree__case_changing_rename(void)
        git_commit_free(master_commit);
 }
 
-void perfdata_cb(const git_checkout_perfdata *in, void *payload)
+static void perfdata_cb(const git_checkout_perfdata *in, void *payload)
 {
        memcpy(payload, in, sizeof(git_checkout_perfdata));
 }
@@ -1297,7 +1298,7 @@ void test_checkout_tree__can_collect_perfdata(void)
        git_object_free(obj);
 }
 
-void update_attr_callback(
+static void update_attr_callback(
        const char *path,
        size_t completed_steps,
        size_t total_steps,
@@ -1317,7 +1318,7 @@ void test_checkout_tree__caches_attributes_during_checkout(void)
        git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
        git_oid oid;
        git_object *obj = NULL;
-       git_buf ident1 = GIT_BUF_INIT, ident2 = GIT_BUF_INIT;
+       git_str ident1 = GIT_STR_INIT, ident2 = GIT_STR_INIT;
        char *ident_paths[] = { "ident1.txt", "ident2.txt" };
 
        opts.progress_cb = update_attr_callback;
@@ -1346,8 +1347,8 @@ void test_checkout_tree__caches_attributes_during_checkout(void)
        cl_assert_equal_strn(ident1.ptr, "# $Id: ", 7);
        cl_assert_equal_strn(ident2.ptr, "# $Id: ", 7);
 
-       git_buf_dispose(&ident1);
-       git_buf_dispose(&ident2);
+       git_str_dispose(&ident1);
+       git_str_dispose(&ident2);
        git_object_free(obj);
 }
 
@@ -1367,13 +1368,13 @@ void test_checkout_tree__can_not_update_index(void)
 
        cl_git_pass(git_reset(g_repo, head, GIT_RESET_HARD, &g_opts));
 
-       cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/"));
+       cl_assert_equal_i(false, git_fs_path_isdir("./testrepo/ab/"));
 
        cl_git_pass(git_revparse_single(&g_object, g_repo, "subtrees"));
 
        cl_git_pass(git_checkout_tree(g_repo, g_object, &opts));
 
-       cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/2.txt"));
+       cl_assert_equal_i(true, git_fs_path_isfile("./testrepo/ab/de/2.txt"));
        cl_git_pass(git_status_file(&status, g_repo, "ab/de/2.txt"));
        cl_assert_equal_i(GIT_STATUS_WT_NEW, status);
 
@@ -1404,13 +1405,13 @@ void test_checkout_tree__can_update_but_not_write_index(void)
 
        cl_git_pass(git_reset(g_repo, head, GIT_RESET_HARD, &g_opts));
 
-       cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/"));
+       cl_assert_equal_i(false, git_fs_path_isdir("./testrepo/ab/"));
 
        cl_git_pass(git_revparse_single(&g_object, g_repo, "subtrees"));
 
        cl_git_pass(git_checkout_tree(g_repo, g_object, &opts));
 
-       cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/2.txt"));
+       cl_assert_equal_i(true, git_fs_path_isfile("./testrepo/ab/de/2.txt"));
        cl_git_pass(git_status_file(&status, g_repo, "ab/de/2.txt"));
        cl_assert_equal_i(GIT_STATUS_INDEX_NEW, status);
 
@@ -1451,15 +1452,15 @@ void test_checkout_tree__safe_proceeds_if_no_index(void)
        cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
        cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
 
-       cl_assert(git_path_isfile("testrepo/README"));
-       cl_assert(git_path_isfile("testrepo/branch_file.txt"));
-       cl_assert(git_path_isfile("testrepo/new.txt"));
-       cl_assert(git_path_isfile("testrepo/ab/4.txt"));
-       cl_assert(git_path_isfile("testrepo/ab/c/3.txt"));
-       cl_assert(git_path_isfile("testrepo/ab/de/2.txt"));
-       cl_assert(git_path_isfile("testrepo/ab/de/fgh/1.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/README"));
+       cl_assert(git_fs_path_isfile("testrepo/branch_file.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/new.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/ab/4.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/ab/c/3.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/ab/de/2.txt"));
+       cl_assert(git_fs_path_isfile("testrepo/ab/de/fgh/1.txt"));
 
-       cl_assert(!git_path_isdir("testrepo/a"));
+       cl_assert(!git_fs_path_isdir("testrepo/a"));
 
        assert_on_branch(g_repo, "subtrees");
 
@@ -1651,7 +1652,7 @@ void test_checkout_tree__dry_run(void)
        opts.checkout_strategy = GIT_CHECKOUT_FORCE;
        cl_git_pass(git_checkout_head(g_repo, &opts));
 
-       cl_assert(!git_path_isdir("testrepo/a"));
+       cl_assert(!git_fs_path_isdir("testrepo/a"));
 
        check_file_contents_nocr("testrepo/branch_file.txt", "hi\nbye!\n");
 
@@ -1674,11 +1675,11 @@ void test_checkout_tree__dry_run(void)
        /* these normally would have been created and updated, but with
         * DRY_RUN they will be unchanged.
         */
-       cl_assert(!git_path_isdir("testrepo/a"));
+       cl_assert(!git_fs_path_isdir("testrepo/a"));
        check_file_contents_nocr("testrepo/branch_file.txt", "hi\nbye!\n");
 
        /* check that notify callback was invoked */
        cl_assert_equal_i(ct.n_updates, 2);
-       
+
        git_object_free(obj);
 }
index db3f02a5c9c65b77442bd2bc95019e6ce2d04468..b888843f03fb3d56be66775ee735a0cc4a00415f 100644 (file)
@@ -76,12 +76,12 @@ void test_checkout_typechange__cleanup(void)
 
 static void assert_file_exists(const char *path)
 {
-       cl_assert_(git_path_isfile(path), path);
+       cl_assert_(git_fs_path_isfile(path), path);
 }
 
 static void assert_dir_exists(const char *path)
 {
-       cl_assert_(git_path_isdir(path), path);
+       cl_assert_(git_fs_path_isdir(path), path);
 }
 
 static void assert_workdir_matches_tree(
@@ -90,7 +90,7 @@ static void assert_workdir_matches_tree(
        git_object *obj;
        git_tree *tree;
        size_t i, max_i;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        if (!root)
                root = git_repository_workdir(repo);
@@ -106,7 +106,7 @@ static void assert_workdir_matches_tree(
                const git_tree_entry *te = git_tree_entry_byindex(tree, i);
                cl_assert(te);
 
-               cl_git_pass(git_buf_joinpath(&path, root, git_tree_entry_name(te)));
+               cl_git_pass(git_str_joinpath(&path, root, git_tree_entry_name(te)));
 
                switch (git_tree_entry_type(te)) {
                case GIT_OBJECT_COMMIT:
@@ -126,7 +126,7 @@ static void assert_workdir_matches_tree(
                                /* because of cross-platform, don't confirm exec bit yet */
                                break;
                        case GIT_FILEMODE_LINK:
-                               cl_assert_(git_path_exists(path.ptr), path.ptr);
+                               cl_assert_(git_fs_path_exists(path.ptr), path.ptr);
                                /* because of cross-platform, don't confirm link yet */
                                break;
                        default:
@@ -139,7 +139,7 @@ static void assert_workdir_matches_tree(
        }
 
        git_tree_free(tree);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_checkout_typechange__checkout_typechanges_safe(void)
@@ -163,19 +163,19 @@ void test_checkout_typechange__checkout_typechanges_safe(void)
                git_object_free(obj);
 
                if (!g_typechange_empty[i]) {
-                       cl_assert(git_path_isdir("typechanges"));
-                       cl_assert(git_path_exists("typechanges/a"));
-                       cl_assert(git_path_exists("typechanges/b"));
-                       cl_assert(git_path_exists("typechanges/c"));
-                       cl_assert(git_path_exists("typechanges/d"));
-                       cl_assert(git_path_exists("typechanges/e"));
+                       cl_assert(git_fs_path_isdir("typechanges"));
+                       cl_assert(git_fs_path_exists("typechanges/a"));
+                       cl_assert(git_fs_path_exists("typechanges/b"));
+                       cl_assert(git_fs_path_exists("typechanges/c"));
+                       cl_assert(git_fs_path_exists("typechanges/d"));
+                       cl_assert(git_fs_path_exists("typechanges/e"));
                } else {
-                       cl_assert(git_path_isdir("typechanges"));
-                       cl_assert(!git_path_exists("typechanges/a"));
-                       cl_assert(!git_path_exists("typechanges/b"));
-                       cl_assert(!git_path_exists("typechanges/c"));
-                       cl_assert(!git_path_exists("typechanges/d"));
-                       cl_assert(!git_path_exists("typechanges/e"));
+                       cl_assert(git_fs_path_isdir("typechanges"));
+                       cl_assert(!git_fs_path_exists("typechanges/a"));
+                       cl_assert(!git_fs_path_exists("typechanges/b"));
+                       cl_assert(!git_fs_path_exists("typechanges/c"));
+                       cl_assert(!git_fs_path_exists("typechanges/d"));
+                       cl_assert(!git_fs_path_exists("typechanges/e"));
                }
        }
 }
@@ -226,31 +226,31 @@ static void force_create_file(const char *file)
 
 static int make_submodule_dirty(git_submodule *sm, const char *name, void *payload)
 {
-       git_buf submodulepath = GIT_BUF_INIT;
-       git_buf dirtypath = GIT_BUF_INIT;
+       git_str submodulepath = GIT_STR_INIT;
+       git_str dirtypath = GIT_STR_INIT;
        git_repository *submodule_repo;
 
        GIT_UNUSED(name);
        GIT_UNUSED(payload);
 
        /* remove submodule directory in preparation for init and repo_init */
-       cl_git_pass(git_buf_joinpath(
+       cl_git_pass(git_str_joinpath(
                &submodulepath,
                git_repository_workdir(g_repo),
                git_submodule_path(sm)
        ));
-       git_futils_rmdir_r(git_buf_cstr(&submodulepath), NULL, GIT_RMDIR_REMOVE_FILES);
+       git_futils_rmdir_r(git_str_cstr(&submodulepath), NULL, GIT_RMDIR_REMOVE_FILES);
 
        /* initialize submodule's repository */
        cl_git_pass(git_submodule_repo_init(&submodule_repo, sm, 0));
 
        /* create a file in the submodule workdir to make it dirty */
        cl_git_pass(
-               git_buf_joinpath(&dirtypath, git_repository_workdir(submodule_repo), "dirty"));
-       force_create_file(git_buf_cstr(&dirtypath));
+               git_str_joinpath(&dirtypath, git_repository_workdir(submodule_repo), "dirty"));
+       force_create_file(git_str_cstr(&dirtypath));
 
-       git_buf_dispose(&dirtypath);
-       git_buf_dispose(&submodulepath);
+       git_str_dispose(&dirtypath);
+       git_str_dispose(&submodulepath);
        git_repository_free(submodule_repo);
 
        return 0;
@@ -293,12 +293,12 @@ void test_checkout_typechange__checkout_with_conflicts(void)
                        GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED;
                memset(&cts, 0, sizeof(cts));
 
-               cl_assert(git_path_exists("typechanges/untracked"));
+               cl_assert(git_fs_path_exists("typechanges/untracked"));
 
                cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
                cl_assert_equal_i(0, cts.conflicts);
 
-               cl_assert(!git_path_exists("typechanges/untracked"));
+               cl_assert(!git_fs_path_exists("typechanges/untracked"));
 
                cl_git_pass(
                        git_repository_set_head_detached(g_repo, git_object_id(obj)));
index 50e8d86006af40e8398911849fddd0b769c59985..f90ce022602069b2b61dcddbfc96460e50f35f4e 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar.h"
 #include "clar_libgit2.h"
 
-#include "buffer.h"
 #include "futils.h"
 #include "git2/cherrypick.h"
 
index 10e8c2d8b4f64fbc4fd52b04254120472ba6a91a..8fd1ecbdfa2d67c6c451363cdd242e670f604c27 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar.h"
 #include "clar_libgit2.h"
 
-#include "buffer.h"
 #include "futils.h"
 #include "git2/cherrypick.h"
 
@@ -72,8 +71,8 @@ void test_cherrypick_workdir__automerge(void)
                cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
                cl_git_pass(git_cherrypick(repo, commit, NULL));
 
-               cl_assert(git_path_exists(TEST_REPO_PATH "/.git/CHERRY_PICK_HEAD"));
-               cl_assert(git_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
+               cl_assert(git_fs_path_exists(TEST_REPO_PATH "/.git/CHERRY_PICK_HEAD"));
+               cl_assert(git_fs_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
 
                cl_git_pass(git_index_write_tree(&cherrypicked_tree_oid, repo_index));
                cl_git_pass(git_tree_lookup(&cherrypicked_tree, repo, &cherrypicked_tree_oid));
@@ -115,7 +114,7 @@ void test_cherrypick_workdir__empty_result(void)
 
        /* 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_assert(git_fs_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));
@@ -140,7 +139,7 @@ void test_cherrypick_workdir__conflicts(void)
 {
        git_commit *head = NULL, *commit = NULL;
        git_oid head_oid, cherry_oid;
-       git_buf conflicting_buf = GIT_BUF_INIT, mergemsg_buf = GIT_BUF_INIT;
+       git_str conflicting_buf = GIT_STR_INIT, mergemsg_buf = GIT_STR_INIT;
 
        struct merge_index_entry merge_index_entries[] = {
                { 0100644, "242e7977ba73637822ffb265b46004b9b0e5153b", 0, "file1.txt" },
@@ -161,24 +160,24 @@ void test_cherrypick_workdir__conflicts(void)
        cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
        cl_git_pass(git_cherrypick(repo, commit, NULL));
 
-       cl_assert(git_path_exists(TEST_REPO_PATH "/.git/CHERRY_PICK_HEAD"));
-       cl_assert(git_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
+       cl_assert(git_fs_path_exists(TEST_REPO_PATH "/.git/CHERRY_PICK_HEAD"));
+       cl_assert(git_fs_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
 
        cl_assert(merge_test_index(repo_index, merge_index_entries, 7));
 
        cl_git_pass(git_futils_readbuffer(&mergemsg_buf,
                TEST_REPO_PATH "/.git/MERGE_MSG"));
-       cl_assert(strcmp(git_buf_cstr(&mergemsg_buf),
+       cl_assert(strcmp(git_str_cstr(&mergemsg_buf),
                "Change all files\n" \
                "\n" \
-               "Conflicts:\n" \
-               "\tfile2.txt\n" \
-               "\tfile3.txt\n") == 0);
+               "#Conflicts:\n" \
+               "#\tfile2.txt\n" \
+               "#\tfile3.txt\n") == 0);
 
        cl_git_pass(git_futils_readbuffer(&conflicting_buf,
                TEST_REPO_PATH "/file2.txt"));
 
-       cl_assert(strcmp(git_buf_cstr(&conflicting_buf),
+       cl_assert(strcmp(git_str_cstr(&conflicting_buf),
                "!File 2\n" \
                "File 2\n" \
                "File 2\n" \
@@ -204,7 +203,7 @@ void test_cherrypick_workdir__conflicts(void)
        cl_git_pass(git_futils_readbuffer(&conflicting_buf,
                TEST_REPO_PATH "/file3.txt"));
 
-       cl_assert(strcmp(git_buf_cstr(&conflicting_buf),
+       cl_assert(strcmp(git_str_cstr(&conflicting_buf),
                "!File 3\n" \
                "File 3\n" \
                "File 3\n" \
@@ -228,8 +227,8 @@ void test_cherrypick_workdir__conflicts(void)
 
        git_commit_free(commit);
        git_commit_free(head);
-       git_buf_dispose(&mergemsg_buf);
-       git_buf_dispose(&conflicting_buf);
+       git_str_dispose(&mergemsg_buf);
+       git_str_dispose(&conflicting_buf);
 }
 
 /* git reset --hard bafbf6912c09505ac60575cd43d3f2aba3bd84d8
@@ -324,7 +323,7 @@ void test_cherrypick_workdir__both_renamed(void)
 {
        git_commit *head, *commit;
        git_oid head_oid, cherry_oid;
-       git_buf mergemsg_buf = GIT_BUF_INIT;
+       git_str mergemsg_buf = GIT_STR_INIT;
        git_cherrypick_options opts = GIT_CHERRYPICK_OPTIONS_INIT;
 
        struct merge_index_entry merge_index_entries[] = {
@@ -350,15 +349,15 @@ void test_cherrypick_workdir__both_renamed(void)
 
        cl_git_pass(git_futils_readbuffer(&mergemsg_buf,
                TEST_REPO_PATH "/.git/MERGE_MSG"));
-       cl_assert(strcmp(git_buf_cstr(&mergemsg_buf),
+       cl_assert(strcmp(git_str_cstr(&mergemsg_buf),
                "Renamed file3.txt -> file3.txt.renamed\n" \
                "\n" \
-               "Conflicts:\n" \
-               "\tfile3.txt\n" \
-               "\tfile3.txt.renamed\n" \
-               "\tfile3.txt.renamed_on_branch\n") == 0);
+               "#Conflicts:\n" \
+               "#\tfile3.txt\n" \
+               "#\tfile3.txt.renamed\n" \
+               "#\tfile3.txt.renamed_on_branch\n") == 0);
 
-       git_buf_dispose(&mergemsg_buf);
+       git_str_dispose(&mergemsg_buf);
        git_commit_free(commit);
        git_commit_free(head);
 }
@@ -374,8 +373,8 @@ void test_cherrypick_workdir__nonmerge_fails_mainline_specified(void)
 
        opts.mainline = 1;
        cl_must_fail(git_cherrypick(repo, commit, &opts));
-       cl_assert(!git_path_exists(TEST_REPO_PATH "/.git/CHERRY_PICK_HEAD"));
-       cl_assert(!git_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
+       cl_assert(!git_fs_path_exists(TEST_REPO_PATH "/.git/CHERRY_PICK_HEAD"));
+       cl_assert(!git_fs_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
 
        git_reference_free(head);
        git_commit_free(commit);
@@ -397,8 +396,8 @@ void test_cherrypick_workdir__merge_fails_without_mainline_specified(void)
        cl_git_pass(git_commit_lookup(&commit, repo, &cherry_oid));
 
        cl_must_fail(git_cherrypick(repo, commit, NULL));
-       cl_assert(!git_path_exists(TEST_REPO_PATH "/.git/CHERRY_PICK_HEAD"));
-       cl_assert(!git_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
+       cl_assert(!git_fs_path_exists(TEST_REPO_PATH "/.git/CHERRY_PICK_HEAD"));
+       cl_assert(!git_fs_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
 
        git_commit_free(commit);
        git_commit_free(head);
index 8c22382bd56e905fc539bb05f69860da469ebc6d..3f659c2f6c4672daf9623577b70c600751a3978f 100644 (file)
@@ -13,12 +13,12 @@ enum cl_test_status {
        CL_TEST_OK,
        CL_TEST_FAILURE,
        CL_TEST_SKIP,
-       CL_TEST_NOTRUN,
+       CL_TEST_NOTRUN
 };
 
 enum cl_output_format {
        CL_OUTPUT_CLAP,
-       CL_OUTPUT_TAP,
+       CL_OUTPUT_TAP
 };
 
 /** Setup clar environment */
@@ -60,7 +60,7 @@ typedef enum cl_trace_event {
        CL_TRACE__TEST__END,
        CL_TRACE__TEST__RUN_BEGIN,
        CL_TRACE__TEST__RUN_END,
-       CL_TRACE__TEST__LONGJMP,
+       CL_TRACE__TEST__LONGJMP
 } cl_trace_event;
 
 typedef void (cl_trace_cb)(
index 1af110efa2380ddc226fb49795acf70a64f50274..6279f5057d7e9f29736fdd5d9ad1971ee67fe65f 100644 (file)
@@ -2,7 +2,7 @@
 #include <stdio.h>
 #include <time.h>
 
-int clar_summary_close_tag(
+static int clar_summary_close_tag(
     struct clar_summary *summary, const char *tag, int indent)
 {
        const char *indt;
@@ -14,12 +14,12 @@ int clar_summary_close_tag(
        return fprintf(summary->fp, "%s</%s>\n", indt, tag);
 }
 
-int clar_summary_testsuites(struct clar_summary *summary)
+static int clar_summary_testsuites(struct clar_summary *summary)
 {
        return fprintf(summary->fp, "<testsuites>\n");
 }
 
-int clar_summary_testsuite(struct clar_summary *summary,
+static int clar_summary_testsuite(struct clar_summary *summary,
     int idn, const char *name, const char *pkg, time_t timestamp,
     double elapsed, int test_count, int fail_count, int error_count)
 {
@@ -42,7 +42,7 @@ int clar_summary_testsuite(struct clar_summary *summary,
                       idn, name, pkg, iso_dt, elapsed, test_count, fail_count, error_count);
 }
 
-int clar_summary_testcase(struct clar_summary *summary,
+static int clar_summary_testcase(struct clar_summary *summary,
     const char *name, const char *classname, double elapsed)
 {
        return fprintf(summary->fp,
@@ -50,7 +50,7 @@ int clar_summary_testcase(struct clar_summary *summary,
                name, classname, elapsed);
 }
 
-int clar_summary_failure(struct clar_summary *summary,
+static int clar_summary_failure(struct clar_summary *summary,
     const char *type, const char *message, const char *desc)
 {
        return fprintf(summary->fp,
index c4550c32a8bc581541dca5838937cbea1a064e41..783b457f958a18e5bf3e70f33fedcbfae4d23540 100644 (file)
@@ -1,6 +1,6 @@
 #include "clar_libgit2.h"
 #include "posix.h"
-#include "path.h"
+#include "fs_path.h"
 #include "git2/sys/repository.h"
 
 void cl_git_report_failure(
@@ -68,7 +68,7 @@ void cl_git_rmfile(const char *filename)
 
 char *cl_getenv(const char *name)
 {
-       git_buf out = GIT_BUF_INIT;
+       git_str out = GIT_STR_INIT;
        int error = git__getenv(&out, name);
 
        cl_assert(error >= 0 || error == GIT_ENOTFOUND);
@@ -83,7 +83,7 @@ char *cl_getenv(const char *name)
                return dup;
        }
 
-       return git_buf_detach(&out);
+       return git_str_detach(&out);
 }
 
 bool cl_is_env_set(const char *name)
@@ -278,11 +278,11 @@ const char* cl_git_path_url(const char *path)
        static char url[4096 + 1];
 
        const char *in_buf;
-       git_buf path_buf = GIT_BUF_INIT;
-       git_buf url_buf = GIT_BUF_INIT;
+       git_str path_buf = GIT_STR_INIT;
+       git_str url_buf = GIT_STR_INIT;
 
-       cl_git_pass(git_path_prettify_dir(&path_buf, path, NULL));
-       cl_git_pass(git_buf_puts(&url_buf, "file://"));
+       cl_git_pass(git_fs_path_prettify_dir(&path_buf, path, NULL));
+       cl_git_pass(git_str_puts(&url_buf, "file://"));
 
 #ifdef GIT_WIN32
        /*
@@ -294,29 +294,29 @@ const char* cl_git_path_url(const char *path)
         * *nix: file:///usr/home/...
         * Windows: file:///C:/Users/...
         */
-       cl_git_pass(git_buf_putc(&url_buf, '/'));
+       cl_git_pass(git_str_putc(&url_buf, '/'));
 #endif
 
-       in_buf = git_buf_cstr(&path_buf);
+       in_buf = git_str_cstr(&path_buf);
 
        /*
         * A very hacky Url encoding that only takes care of escaping the spaces
         */
        while (*in_buf) {
                if (*in_buf == ' ')
-                       cl_git_pass(git_buf_puts(&url_buf, "%20"));
+                       cl_git_pass(git_str_puts(&url_buf, "%20"));
                else
-                       cl_git_pass(git_buf_putc(&url_buf, *in_buf));
+                       cl_git_pass(git_str_putc(&url_buf, *in_buf));
 
                in_buf++;
        }
 
        cl_assert(url_buf.size < sizeof(url) - 1);
 
-       strncpy(url, git_buf_cstr(&url_buf), sizeof(url) - 1);
+       strncpy(url, git_str_cstr(&url_buf), sizeof(url) - 1);
        url[sizeof(url) - 1] = '\0';
-       git_buf_dispose(&url_buf);
-       git_buf_dispose(&path_buf);
+       git_str_dispose(&url_buf);
+       git_str_dispose(&path_buf);
        return url;
 }
 
@@ -324,27 +324,27 @@ const char *cl_git_sandbox_path(int is_dir, ...)
 {
        const char *path = NULL;
        static char _temp[GIT_PATH_MAX];
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        va_list arg;
 
-       cl_git_pass(git_buf_sets(&buf, clar_sandbox_path()));
+       cl_git_pass(git_str_sets(&buf, clar_sandbox_path()));
 
        va_start(arg, is_dir);
 
        while ((path = va_arg(arg, const char *)) != NULL) {
-               cl_git_pass(git_buf_joinpath(&buf, buf.ptr, path));
+               cl_git_pass(git_str_joinpath(&buf, buf.ptr, path));
        }
        va_end(arg);
 
-       cl_git_pass(git_path_prettify(&buf, buf.ptr, NULL));
+       cl_git_pass(git_fs_path_prettify(&buf, buf.ptr, NULL));
        if (is_dir)
-               git_path_to_dir(&buf);
+               git_fs_path_to_dir(&buf);
 
        /* make sure we won't truncate */
-       cl_assert(git_buf_len(&buf) < sizeof(_temp));
-       git_buf_copy_cstr(_temp, sizeof(_temp), &buf);
+       cl_assert(git_str_len(&buf) < sizeof(_temp));
+       git_str_copy_cstr(_temp, sizeof(_temp), &buf);
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        return _temp;
 }
@@ -354,13 +354,13 @@ typedef struct {
        size_t filename_len;
 } remove_data;
 
-static int remove_placeholders_recurs(void *_data, git_buf *path)
+static int remove_placeholders_recurs(void *_data, git_str *path)
 {
        remove_data *data = (remove_data *)_data;
        size_t pathlen;
 
-       if (git_path_isdir(path->ptr) == true)
-               return git_path_direach(path, 0, remove_placeholders_recurs, data);
+       if (git_fs_path_isdir(path->ptr) == true)
+               return git_fs_path_direach(path, 0, remove_placeholders_recurs, data);
 
        pathlen = path->size;
 
@@ -380,12 +380,12 @@ int cl_git_remove_placeholders(const char *directory_path, const char *filename)
 {
        int error;
        remove_data data;
-       git_buf buffer = GIT_BUF_INIT;
+       git_str buffer = GIT_STR_INIT;
 
-       if (git_path_isdir(directory_path) == false)
+       if (git_fs_path_isdir(directory_path) == false)
                return -1;
 
-       if (git_buf_sets(&buffer, directory_path) < 0)
+       if (git_str_sets(&buffer, directory_path) < 0)
                return -1;
 
        data.filename = filename;
@@ -393,7 +393,7 @@ int cl_git_remove_placeholders(const char *directory_path, const char *filename)
 
        error = remove_placeholders_recurs(&data, &buffer);
 
-       git_buf_dispose(&buffer);
+       git_str_dispose(&buffer);
 
        return error;
 }
@@ -548,47 +548,43 @@ void clar__assert_equal_file(
                (size_t)expected_bytes, (size_t)total_bytes);
 }
 
-static char *_cl_restore_home = NULL;
+static git_buf _cl_restore_home = GIT_BUF_INIT;
 
 void cl_fake_home_cleanup(void *payload)
 {
-       char *restore = _cl_restore_home;
-       _cl_restore_home = NULL;
-
        GIT_UNUSED(payload);
 
-       if (restore) {
+       if (_cl_restore_home.ptr) {
                cl_git_pass(git_libgit2_opts(
-                       GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, restore));
-               git__free(restore);
+                       GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, _cl_restore_home.ptr));
+               git_buf_dispose(&_cl_restore_home);
        }
 }
 
 void cl_fake_home(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        cl_git_pass(git_libgit2_opts(
-               GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &path));
+               GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &_cl_restore_home));
 
-       _cl_restore_home = git_buf_detach(&path);
        cl_set_cleanup(cl_fake_home_cleanup, NULL);
 
-       if (!git_path_exists("home"))
+       if (!git_fs_path_exists("home"))
                cl_must_pass(p_mkdir("home", 0777));
-       cl_git_pass(git_path_prettify(&path, "home", NULL));
+       cl_git_pass(git_fs_path_prettify(&path, "home", NULL));
        cl_git_pass(git_libgit2_opts(
                GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr));
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void cl_sandbox_set_search_path_defaults(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
-       git_buf_joinpath(&path, clar_sandbox_path(), "__config");
+       git_str_joinpath(&path, clar_sandbox_path(), "__config");
 
-       if (!git_path_exists(path.ptr))
+       if (!git_fs_path_exists(path.ptr))
                cl_must_pass(p_mkdir(path.ptr, 0777));
 
        git_libgit2_opts(
@@ -600,18 +596,23 @@ void cl_sandbox_set_search_path_defaults(void)
        git_libgit2_opts(
                GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_PROGRAMDATA, path.ptr);
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
+}
+
+void cl_sandbox_disable_ownership_validation(void)
+{
+       git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 0);
 }
 
 #ifdef GIT_WIN32
 bool cl_sandbox_supports_8dot3(void)
 {
-       git_buf longpath = GIT_BUF_INIT;
+       git_str longpath = GIT_STR_INIT;
        char *shortname;
        bool supported;
 
        cl_git_pass(
-               git_buf_joinpath(&longpath, clar_sandbox_path(), "longer_than_8dot3"));
+               git_str_joinpath(&longpath, clar_sandbox_path(), "longer_than_8dot3"));
 
        cl_git_write2file(longpath.ptr, "", 0, O_RDWR|O_CREAT, 0666);
        shortname = git_win32_path_8dot3_name(longpath.ptr);
@@ -619,7 +620,7 @@ bool cl_sandbox_supports_8dot3(void)
        supported = (shortname != NULL);
 
        git__free(shortname);
-       git_buf_dispose(&longpath);
+       git_str_dispose(&longpath);
 
        return supported;
 }
index e3b7bd9f83f8814b763e382550d31f30afc5311a..da3f415245812c3abfeb8a4679a2b748d94a1c79 100644 (file)
@@ -222,6 +222,7 @@ void cl_fake_home(void);
 void cl_fake_home_cleanup(void *);
 
 void cl_sandbox_set_search_path_defaults(void);
+void cl_sandbox_disable_ownership_validation(void);
 
 #ifdef GIT_WIN32
 # define cl_msleep(x) Sleep(x)
index 737506da2c325228b8616ee5cc26a799ae53715d..2330f9351d1b422ca99f33c2a133a67e015d602c 100644 (file)
@@ -1,6 +1,5 @@
 #include "clar_libgit2.h"
 #include "clar_libgit2_timer.h"
-#include "buffer.h"
 
 void cl_perf_timer__init(cl_perf_timer *t)
 {
index 0d150e0189f3a7c43b771aaf3ae7c5981169b371..7571a52e997c195c9edfa93f85053572bae59053 100644 (file)
@@ -3,7 +3,7 @@
 
 struct cl_perf_timer
 {
-       /* cummulative running time across all start..stop intervals */
+       /* cumulative running time across all start..stop intervals */
        double sum;
 
        /* value of last start..stop interval */
@@ -27,7 +27,7 @@ void cl_perf_timer__stop(cl_perf_timer *t);
 double cl_perf_timer__last(const cl_perf_timer *t);
 
 /**
- * return cummulative running time across all start..stop
+ * return cumulative running time across all start..stop
  * intervals in seconds.
  */
 double cl_perf_timer__sum(const cl_perf_timer *t);
index 8eb6d4e8dd96d41c9addf6f67bca3009c8df0a07..ebb0f41dda7cdaed0c1d6b5965f726c0b2ad55a5 100644 (file)
@@ -150,7 +150,7 @@ static cl_perf_timer s_timer_run = CL_PERF_TIMER_INIT;
  */
 static cl_perf_timer s_timer_test = CL_PERF_TIMER_INIT;
 
-void _cl_trace_cb__event_handler(
+static void _cl_trace_cb__event_handler(
        cl_trace_event ev,
        const char *suite_name,
        const char *test_name,
index b90ff310752158fa63cbf65367565aaf1ac7e09a..e0bd74df78a691f287b9a31ef202954e01b37196 100644 (file)
@@ -2,42 +2,41 @@
 
 #include "git2/clone.h"
 #include "clone.h"
-#include "buffer.h"
 #include "path.h"
 #include "posix.h"
 #include "futils.h"
 
-static int file_url(git_buf *buf, const char *host, const char *path)
+static int file_url(git_str *buf, const char *host, const char *path)
 {
        if (path[0] == '/')
                path++;
 
-       git_buf_clear(buf);
-       return git_buf_printf(buf, "file://%s/%s", host, path);
+       git_str_clear(buf);
+       return git_str_printf(buf, "file://%s/%s", host, path);
 }
 
 #ifdef GIT_WIN32
-static int git_style_unc_path(git_buf *buf, const char *host, const char *path)
+static int git_style_unc_path(git_str *buf, const char *host, const char *path)
 {
-       git_buf_clear(buf);
+       git_str_clear(buf);
 
        if (host)
-               git_buf_printf(buf, "//%s/", host);
+               git_str_printf(buf, "//%s/", host);
 
        if (path[0] == '/')
                path++;
 
        if (git__isalpha(path[0]) && path[1] == ':' && path[2] == '/') {
-               git_buf_printf(buf, "%c$/", path[0]);
+               git_str_printf(buf, "%c$/", path[0]);
                path += 3;
        }
 
-       git_buf_puts(buf, path);
+       git_str_puts(buf, path);
 
-       return git_buf_oom(buf) ? -1 : 0;
+       return git_str_oom(buf) ? -1 : 0;
 }
 
-static int unc_path(git_buf *buf, const char *host, const char *path)
+static int unc_path(git_str *buf, const char *host, const char *path)
 {
        char *c;
 
@@ -54,7 +53,7 @@ static int unc_path(git_buf *buf, const char *host, const char *path)
 
 void test_clone_local__should_clone_local(void)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        /* we use a fixture path because it needs to exist for us to want to clone */
        const char *path = cl_fixture("testrepo.git");
@@ -79,8 +78,8 @@ void test_clone_local__should_clone_local(void)
 
        /* Ensure that file:/// urls are percent decoded: .git == %2e%67%69%74 */
        cl_git_pass(file_url(&buf, "", path));
-       git_buf_shorten(&buf, 4);
-       cl_git_pass(git_buf_puts(&buf, "%2e%67%69%74"));
+       git_str_shorten(&buf, 4);
+       cl_git_pass(git_str_puts(&buf, "%2e%67%69%74"));
        cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_AUTO));
        cl_assert_equal_i(1,  git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL));
        cl_assert_equal_i(1,  git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_NO_LINKS));
@@ -91,14 +90,14 @@ void test_clone_local__should_clone_local(void)
        cl_assert_equal_i(1,  git_clone__should_clone_local(path, GIT_CLONE_LOCAL_NO_LINKS));
        cl_assert_equal_i(0, git_clone__should_clone_local(path, GIT_CLONE_NO_LOCAL));
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 }
 
 void test_clone_local__hardlinks(void)
 {
        git_repository *repo;
        git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        struct stat st;
 
        /*
@@ -117,21 +116,21 @@ void test_clone_local__hardlinks(void)
        cl_git_pass(git_clone(&repo, cl_git_path_url("clone.git"), "./clone2.git", &opts));
 
 #ifndef GIT_WIN32
-       git_buf_clear(&buf);
-       cl_git_pass(git_buf_join_n(&buf, '/', 4, git_repository_path(repo), "objects", "08", "b041783f40edfe12bb406c9c9a8a040177c125"));
+       git_str_clear(&buf);
+       cl_git_pass(git_str_join_n(&buf, '/', 4, git_repository_path(repo), "objects", "08", "b041783f40edfe12bb406c9c9a8a040177c125"));
 
        cl_git_pass(p_stat(buf.ptr, &st));
        cl_assert_equal_i(2, st.st_nlink);
 #endif
 
        git_repository_free(repo);
-       git_buf_clear(&buf);
+       git_str_clear(&buf);
 
        opts.local = GIT_CLONE_LOCAL_NO_LINKS;
        cl_git_pass(git_clone(&repo, cl_git_path_url("clone.git"), "./clone3.git", &opts));
 
-       git_buf_clear(&buf);
-       cl_git_pass(git_buf_join_n(&buf, '/', 4, git_repository_path(repo), "objects", "08", "b041783f40edfe12bb406c9c9a8a040177c125"));
+       git_str_clear(&buf);
+       cl_git_pass(git_str_join_n(&buf, '/', 4, git_repository_path(repo), "objects", "08", "b041783f40edfe12bb406c9c9a8a040177c125"));
 
        cl_git_pass(p_stat(buf.ptr, &st));
        cl_assert_equal_i(1, st.st_nlink);
@@ -142,14 +141,14 @@ void test_clone_local__hardlinks(void)
        cl_git_pass(git_clone(&repo, "./clone.git", "./clone4.git", NULL));
 
 #ifndef GIT_WIN32
-       git_buf_clear(&buf);
-       cl_git_pass(git_buf_join_n(&buf, '/', 4, git_repository_path(repo), "objects", "08", "b041783f40edfe12bb406c9c9a8a040177c125"));
+       git_str_clear(&buf);
+       cl_git_pass(git_str_join_n(&buf, '/', 4, git_repository_path(repo), "objects", "08", "b041783f40edfe12bb406c9c9a8a040177c125"));
 
        cl_git_pass(p_stat(buf.ptr, &st));
        cl_assert_equal_i(3, st.st_nlink);
 #endif
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        git_repository_free(repo);
 
        cl_git_pass(git_futils_rmdir_r("./clone.git", NULL, GIT_RMDIR_REMOVE_FILES));
@@ -164,7 +163,7 @@ void test_clone_local__standard_unc_paths_are_written_git_style(void)
        git_repository *repo;
        git_remote *remote;
        git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
-       git_buf unc = GIT_BUF_INIT, git_unc = GIT_BUF_INIT;
+       git_str unc = GIT_STR_INIT, git_unc = GIT_STR_INIT;
 
        /* we use a fixture path because it needs to exist for us to want to clone */
        const char *path = cl_fixture("testrepo.git");
@@ -179,8 +178,8 @@ void test_clone_local__standard_unc_paths_are_written_git_style(void)
 
        git_remote_free(remote);
        git_repository_free(repo);
-       git_buf_dispose(&unc);
-       git_buf_dispose(&git_unc);
+       git_str_dispose(&unc);
+       git_str_dispose(&git_unc);
 
        cl_git_pass(git_futils_rmdir_r("./clone.git", NULL, GIT_RMDIR_REMOVE_FILES));
 #endif
@@ -192,7 +191,7 @@ void test_clone_local__git_style_unc_paths(void)
        git_repository *repo;
        git_remote *remote;
        git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
-       git_buf git_unc = GIT_BUF_INIT;
+       git_str git_unc = GIT_STR_INIT;
 
        /* we use a fixture path because it needs to exist for us to want to clone */
        const char *path = cl_fixture("testrepo.git");
@@ -206,7 +205,7 @@ void test_clone_local__git_style_unc_paths(void)
 
        git_remote_free(remote);
        git_repository_free(repo);
-       git_buf_dispose(&git_unc);
+       git_str_dispose(&git_unc);
 
        cl_git_pass(git_futils_rmdir_r("./clone.git", NULL, GIT_RMDIR_REMOVE_FILES));
 #endif
index ec12fee18a13a7d963362c97d347f0388fa47fd7..eab633635164e088fc821682d560d8be7aae5828 100644 (file)
@@ -51,10 +51,10 @@ void test_clone_nonetwork__bad_urls(void)
 {
        /* Clone should clean up the mess if the URL isn't a git repository */
        cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options));
-       cl_assert(!git_path_exists("./foo"));
+       cl_assert(!git_fs_path_exists("./foo"));
        g_options.bare = true;
        cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options));
-       cl_assert(!git_path_exists("./foo"));
+       cl_assert(!git_fs_path_exists("./foo"));
 
        cl_git_fail(git_clone(&g_repo, "git://example.com:asdf", "./foo", &g_options));
        cl_git_fail(git_clone(&g_repo, "https://example.com:asdf/foo", "./foo", &g_options));
@@ -70,12 +70,12 @@ void test_clone_nonetwork__do_not_clean_existing_directory(void)
         * Should clean up entries it creates. */
        p_mkdir("./foo", GIT_DIR_MODE);
        cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options));
-       cl_assert(git_path_is_empty_dir("./foo"));
+       cl_assert(git_fs_path_is_empty_dir("./foo"));
 
        /* Try again with a bare repository. */
        g_options.bare = true;
        cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options));
-       cl_assert(git_path_is_empty_dir("./foo"));
+       cl_assert(git_fs_path_is_empty_dir("./foo"));
 }
 
 void test_clone_nonetwork__local(void)
@@ -109,7 +109,7 @@ void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(vo
        cl_git_fail(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
 }
 
-int custom_origin_name_remote_create(
+static int custom_origin_name_remote_create(
        git_remote **out,
        git_repository *repo,
        const char *name,
@@ -145,15 +145,15 @@ void test_clone_nonetwork__cope_with_already_existing_directory(void)
 
 void test_clone_nonetwork__can_prevent_the_checkout_of_a_standard_repo(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        g_options.checkout_opts.checkout_strategy = 0;
        cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
-       cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&path)));
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
+       cl_assert_equal_i(false, git_fs_path_isfile(git_str_cstr(&path)));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_clone_nonetwork__can_checkout_given_branch(void)
@@ -168,7 +168,7 @@ void test_clone_nonetwork__can_checkout_given_branch(void)
        cl_git_pass(git_repository_head(&g_ref, g_repo));
        cl_assert_equal_s(git_reference_name(g_ref), "refs/heads/test");
 
-       cl_assert(git_path_exists("foo/readme.txt"));
+       cl_assert(git_fs_path_exists("foo/readme.txt"));
 
        cl_git_pass(git_reference_lookup(&remote_head, g_repo, "refs/remotes/origin/HEAD"));
        cl_assert_equal_i(GIT_REFERENCE_SYMBOLIC, git_reference_type(remote_head));
@@ -196,7 +196,7 @@ void test_clone_nonetwork__can_cancel_clone_in_fetch(void)
                -54321);
 
        cl_assert(!g_repo);
-       cl_assert(!git_path_exists("foo/readme.txt"));
+       cl_assert(!git_fs_path_exists("foo/readme.txt"));
 }
 
 static int clone_cancel_checkout_cb(
@@ -227,7 +227,7 @@ void test_clone_nonetwork__can_cancel_clone_in_checkout(void)
                -12345);
 
        cl_assert(!g_repo);
-       cl_assert(!git_path_exists("foo/readme.txt"));
+       cl_assert(!git_fs_path_exists("foo/readme.txt"));
 }
 
 void test_clone_nonetwork__can_detached_head(void)
@@ -304,9 +304,9 @@ static void assert_correct_reflog(const char *name)
 {
        git_reflog *log;
        const git_reflog_entry *entry;
-       git_buf expected_message = GIT_BUF_INIT;
+       git_str expected_message = GIT_STR_INIT;
 
-       git_buf_printf(&expected_message,
+       git_str_printf(&expected_message,
                "clone: from %s", cl_git_fixture_url("testrepo.git"));
 
        cl_git_pass(git_reflog_read(&log, g_repo, name));
@@ -316,7 +316,7 @@ static void assert_correct_reflog(const char *name)
 
        git_reflog_free(log);
 
-       git_buf_dispose(&expected_message);
+       git_str_dispose(&expected_message);
 }
 
 void test_clone_nonetwork__clone_updates_reflog_properly(void)
index b03169bc8d4ecf1c55715a6e6c92577833d0f9ce..fd574f7f254c9ac5a03dd3b330f0c16d3b9facee 100644 (file)
@@ -111,7 +111,7 @@ void test_commit_commit__create_initial_commit_parent_not_current(void)
        git_signature_free(s);
 }
 
-void assert_commit_summary(const char *expected, const char *given)
+static void assert_commit_summary(const char *expected, const char *given)
 {
        git_commit *dummy;
 
@@ -123,7 +123,7 @@ void assert_commit_summary(const char *expected, const char *given)
        git_commit__free(dummy);
 }
 
-void assert_commit_body(const char *expected, const char *given)
+static void assert_commit_body(const char *expected, const char *given)
 {
        git_commit *dummy;
 
@@ -139,8 +139,11 @@ void test_commit_commit__summary(void)
 {
        assert_commit_summary("One-liner with no trailing newline", "One-liner with no trailing newline");
        assert_commit_summary("One-liner with trailing newline", "One-liner with trailing newline\n");
+       assert_commit_summary("One-liner with trailing newline and space", "One-liner with trailing newline and space\n ");
        assert_commit_summary("Trimmed leading&trailing newlines", "\n\nTrimmed leading&trailing newlines\n\n");
        assert_commit_summary("First paragraph only", "\nFirst paragraph only\n\n(There are more!)");
+       assert_commit_summary("First paragraph only with space in the next line", "\nFirst paragraph only with space in the next line\n \n(There are more!)");
+       assert_commit_summary("First paragraph only with spaces in the next line", "\nFirst paragraph only with spaces in the next line\n    \n(There are more!)");
        assert_commit_summary("First paragraph with  unwrapped trailing\tlines", "\nFirst paragraph\nwith  unwrapped\ntrailing\tlines\n\n(Yes, unwrapped!)");
        assert_commit_summary("\tLeading tabs", "\tLeading\n\ttabs\n\nare preserved"); /* tabs around newlines are collapsed down to a single space */
        assert_commit_summary(" Leading Spaces", " Leading\n Spaces\n\nare preserved"); /* spaces around newlines are collapsed down to a single space */
index f0a31de9a4376356e63b0c5a1e06e2e2b63c3d90..04366d7d277433860b0b21c653156ed2a5bb14ab 100644 (file)
@@ -445,15 +445,15 @@ cpxtDQQMGYFpXK/71stq\n\
 
        cl_git_pass(git_commit_header_field(&buf, commit, "tree"));
        cl_assert_equal_s("6b79e22d69bf46e289df0345a14ca059dfc9bdf6", buf.ptr);
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
 
        cl_git_pass(git_commit_header_field(&buf, commit, "parent"));
        cl_assert_equal_s("34734e478d6cf50c27c9d69026d93974d052c454", buf.ptr);
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
 
        cl_git_pass(git_commit_header_field(&buf, commit, "gpgsig"));
        cl_assert_equal_s(gpgsig, buf.ptr);
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
 
        cl_git_fail_with(GIT_ENOTFOUND, git_commit_header_field(&buf, commit, "awesomeness"));
        cl_git_fail_with(GIT_ENOTFOUND, git_commit_header_field(&buf, commit, "par"));
@@ -513,7 +513,6 @@ committer Some User <someuser@gmail.com> 1454537944 -0700\n\
 \n\
 corrupt signature\n";
 
-
        cl_git_pass(git_repository_odb__weakptr(&odb, g_repo));
        cl_git_pass(git_odb_write(&commit_id, odb, passing_commit_cases[4], strlen(passing_commit_cases[4]), GIT_OBJECT_COMMIT));
 
@@ -521,13 +520,16 @@ corrupt signature\n";
        cl_assert_equal_s(gpgsig, signature.ptr);
        cl_assert_equal_s(data, signed_data.ptr);
 
-       git_buf_clear(&signature);
-       git_buf_clear(&signed_data);
+       git_buf_dispose(&signature);
+       git_buf_dispose(&signed_data);
 
        cl_git_pass(git_commit_extract_signature(&signature, &signed_data, g_repo, &commit_id, "gpgsig"));
        cl_assert_equal_s(gpgsig, signature.ptr);
        cl_assert_equal_s(data, signed_data.ptr);
 
+       git_buf_dispose(&signature);
+       git_buf_dispose(&signed_data);
+
        /* Try to parse a tree */
        cl_git_pass(git_oid_fromstr(&commit_id, "45dd856fdd4d89b884c340ba0e047752d9b085d6"));
        cl_git_fail_with(GIT_ENOTFOUND, git_commit_extract_signature(&signature, &signed_data, g_repo, &commit_id, NULL));
@@ -539,15 +541,11 @@ corrupt signature\n";
        cl_assert_equal_i(GIT_ERROR_OBJECT, git_error_last()->klass);
 
        /* Parse the commit with a single-line signature */
-       git_buf_clear(&signature);
-       git_buf_clear(&signed_data);
        cl_git_pass(git_odb_write(&commit_id, odb, oneline_signature, strlen(oneline_signature), GIT_OBJECT_COMMIT));
        cl_git_pass(git_commit_extract_signature(&signature, &signed_data, g_repo, &commit_id, NULL));
        cl_assert_equal_s("bad", signature.ptr);
        cl_assert_equal_s(oneline_data, signed_data.ptr);
 
-
        git_buf_dispose(&signature);
        git_buf_dispose(&signed_data);
-
 }
index 2c2278546160bddde41b6e2bf7efc8622bf5f97e..5a9c9d5a5eb982358c345727514e087e927d31c8 100644 (file)
@@ -155,7 +155,7 @@ void test_commit_write__root(void)
        cl_git_pass(git_signature_new(&committer, committer_name, committer_email, 123456789, 60));
        cl_git_pass(git_signature_new(&author, committer_name, committer_email, 987654321, 90));
 
-       /* First we need to update HEAD so it points to our non-existant branch */
+       /* First we need to update HEAD so it points to our non-existent branch */
        cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
        cl_assert(git_reference_type(head) == GIT_REFERENCE_SYMBOLIC);
        head_old = git__strdup(git_reference_symbolic_target(head));
index 5858782c18ee8a26620cc20e44b531703cc3a6dd..564719dcbcf7e897e3bea278fad07f7eb629b500 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "futils.h"
 #include "repository.h"
 
@@ -23,43 +22,46 @@ void test_config_conditionals__cleanup(void)
 
 static void assert_condition_includes(const char *keyword, const char *path, bool expected)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_buf value = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_config *cfg;
 
-       cl_git_pass(git_buf_printf(&buf, "[includeIf \"%s:%s\"]\n", keyword, path));
-       cl_git_pass(git_buf_puts(&buf, "path = other\n"));
+       cl_git_pass(git_str_printf(&buf, "[includeIf \"%s:%s\"]\n", keyword, path));
+       cl_git_pass(git_str_puts(&buf, "path = other\n"));
 
        cl_git_mkfile("empty_standard_repo/.git/config", buf.ptr);
        cl_git_mkfile("empty_standard_repo/.git/other", "[foo]\nbar=baz\n");
        _repo = cl_git_sandbox_reopen();
 
+       git_str_dispose(&buf);
+
        cl_git_pass(git_repository_config(&cfg, _repo));
 
        if (expected) {
-               git_buf_clear(&buf);
-               cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
-               cl_assert_equal_s("baz", git_buf_cstr(&buf));
+               cl_git_pass(git_config_get_string_buf(&value, cfg, "foo.bar"));
+               cl_assert_equal_s("baz", value.ptr);
        } else {
                cl_git_fail_with(GIT_ENOTFOUND,
-                                git_config_get_string_buf(&buf, cfg, "foo.bar"));
+                                git_config_get_string_buf(&value, cfg, "foo.bar"));
        }
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
+       git_buf_dispose(&value);
        git_config_free(cfg);
 }
 
-static char *sandbox_path(git_buf *buf, const char *suffix)
+static char *sandbox_path(git_str *buf, const char *suffix)
 {
        char *path = p_realpath(clar_sandbox_path(), NULL);
        cl_assert(path);
-       cl_git_pass(git_buf_attach(buf, path, 0));
-       cl_git_pass(git_buf_joinpath(buf, buf->ptr, suffix));
+       cl_git_pass(git_str_attach(buf, path, 0));
+       cl_git_pass(git_str_joinpath(buf, buf->ptr, suffix));
        return buf->ptr;
 }
 
 void test_config_conditionals__gitdir(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        assert_condition_includes("gitdir", ROOT_PREFIX "/", true);
        assert_condition_includes("gitdir", "empty_stand", false);
@@ -90,17 +92,17 @@ void test_config_conditionals__gitdir(void)
        assert_condition_includes("gitdir", sandbox_path(&path, "Empty_Standard_Repo"), false);
        assert_condition_includes("gitdir", sandbox_path(&path, "Empty_Standard_Repo/"), false);
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_config_conditionals__gitdir_i(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        assert_condition_includes("gitdir/i", sandbox_path(&path, "empty_standard_repo/"), true);
        assert_condition_includes("gitdir/i", sandbox_path(&path, "EMPTY_STANDARD_REPO/"), true);
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_config_conditionals__invalid_conditional_fails(void)
@@ -146,3 +148,28 @@ void test_config_conditionals__onbranch(void)
        assert_condition_includes("onbranch", "dir*", false);
        assert_condition_includes("onbranch", "dir/*", false);
 }
+
+void test_config_conditionals__empty(void)
+{
+       git_buf value = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
+       git_config *cfg;
+
+       cl_git_pass(git_str_puts(&buf, "[includeIf]\n"));
+       cl_git_pass(git_str_puts(&buf, "path = other\n"));
+
+       cl_git_mkfile("empty_standard_repo/.git/config", buf.ptr);
+       cl_git_mkfile("empty_standard_repo/.git/other", "[foo]\nbar=baz\n");
+       _repo = cl_git_sandbox_reopen();
+
+       git_str_dispose(&buf);
+
+       cl_git_pass(git_repository_config(&cfg, _repo));
+
+       cl_git_fail_with(GIT_ENOTFOUND,
+               git_config_get_string_buf(&value, cfg, "foo.bar"));
+
+       git_str_dispose(&buf);
+       git_buf_dispose(&value);
+       git_config_free(cfg);
+}
index d92ff1a4ee81d660127f5d1a092b1f64a8147239..ecdab5bf616501a68e4559267acade37d1d8ad74 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "config_helpers.h"
 #include "repository.h"
-#include "buffer.h"
 
 void assert_config_entry_existence(
        git_repository *repo,
@@ -13,7 +12,7 @@ void assert_config_entry_existence(
        int result;
 
        cl_git_pass(git_repository_config__weakptr(&config, repo));
-       
+
        result = git_config_get_entry(&entry, config, name);
        git_config_entry_free(entry);
 
@@ -35,7 +34,7 @@ void assert_config_entry_value(
 
        cl_git_pass(git_config_get_string_buf(&buf, config, name));
 
-       cl_assert_equal_s(expected_value, git_buf_cstr(&buf));
+       cl_assert_equal_s(expected_value, buf.ptr);
        git_buf_dispose(&buf);
 }
 
index 15c469fcb83a4efeed9309e1074d5afdf01748b9..8422d32c94421a7d5b2aabb9099f704f551b80b6 100644 (file)
@@ -22,7 +22,7 @@ void test_config_configlevel__adding_the_same_level_twice_returns_EEXISTS(void)
 void test_config_configlevel__can_replace_a_config_file_at_an_existing_level(void)
 {
        git_config *cfg;
-       git_buf buf = {0};
+       git_buf buf = GIT_BUF_INIT;
 
        cl_git_pass(git_config_new(&cfg));
        cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"),
index ed47d02515a879d9f12b63e6f579c47dea07aee1..5aba4eec69e59e1efe1a7cf2225220780bb77830 100644 (file)
@@ -1,27 +1,26 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "futils.h"
 
 void test_config_global__initialize(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        cl_git_pass(git_futils_mkdir_r("home", 0777));
-       cl_git_pass(git_path_prettify(&path, "home", NULL));
+       cl_git_pass(git_fs_path_prettify(&path, "home", NULL));
        cl_git_pass(git_libgit2_opts(
                GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr));
 
        cl_git_pass(git_futils_mkdir_r("xdg/git", 0777));
-       cl_git_pass(git_path_prettify(&path, "xdg/git", NULL));
+       cl_git_pass(git_fs_path_prettify(&path, "xdg/git", NULL));
        cl_git_pass(git_libgit2_opts(
                GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr));
 
        cl_git_pass(git_futils_mkdir_r("etc", 0777));
-       cl_git_pass(git_path_prettify(&path, "etc", NULL));
+       cl_git_pass(git_fs_path_prettify(&path, "etc", NULL));
        cl_git_pass(git_libgit2_opts(
                GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_config_global__cleanup(void)
@@ -132,24 +131,25 @@ void test_config_global__open_programdata(void)
 {
        git_config *cfg;
        git_repository *repo;
-       git_buf config_path = GIT_BUF_INIT;
+       git_buf dir_path = GIT_BUF_INIT;
+       git_str config_path = GIT_STR_INIT;
        git_buf var_contents = GIT_BUF_INIT;
 
        if (cl_is_env_set("GITTEST_INVASIVE_FS_STRUCTURE"))
                cl_skip();
 
        cl_git_pass(git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH,
-               GIT_CONFIG_LEVEL_PROGRAMDATA, &config_path));
+               GIT_CONFIG_LEVEL_PROGRAMDATA, &dir_path));
 
-       if (!git_path_isdir(config_path.ptr))
-               cl_git_pass(p_mkdir(config_path.ptr, 0777));
+       if (!git_fs_path_isdir(dir_path.ptr))
+               cl_git_pass(p_mkdir(dir_path.ptr, 0777));
 
-       cl_git_pass(git_buf_puts(&config_path, "/config"));
+       cl_git_pass(git_str_joinpath(&config_path, dir_path.ptr, "config"));
 
        cl_git_pass(git_config_open_ondisk(&cfg, config_path.ptr));
        cl_git_pass(git_config_set_string(cfg, "programdata.var", "even higher level"));
 
-       git_buf_dispose(&config_path);
+       git_str_dispose(&config_path);
        git_config_free(cfg);
 
        git_config_open_default(&cfg);
@@ -165,6 +165,7 @@ void test_config_global__open_programdata(void)
        cl_assert_equal_s("even higher level", var_contents.ptr);
 
        git_config_free(cfg);
+       git_buf_dispose(&dir_path);
        git_buf_dispose(&var_contents);
        git_repository_free(repo);
        cl_fixture_cleanup("./foo.git");
index b702d62114057ac324b5d2c26ad424fc33e4a435..9328f3cf6491c98d8f22333d3deee72ad379f422 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "futils.h"
 
 static git_config *cfg;
@@ -7,14 +6,14 @@ static git_buf buf;
 
 void test_config_include__initialize(void)
 {
-    cfg = NULL;
-    git_buf_init(&buf, 0);
+       cfg = NULL;
+       memset(&buf, 0, sizeof(git_buf));
 }
 
 void test_config_include__cleanup(void)
 {
-    git_config_free(cfg);
-    git_buf_dispose(&buf);
+       git_config_free(cfg);
+       git_buf_dispose(&buf);
 }
 
 void test_config_include__relative(void)
@@ -22,19 +21,21 @@ void test_config_include__relative(void)
        cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config-include")));
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.baz"));
-       cl_assert_equal_s("huzzah", git_buf_cstr(&buf));
+       cl_assert_equal_s("huzzah", buf.ptr);
 }
 
 void test_config_include__absolute(void)
 {
-       cl_git_pass(git_buf_printf(&buf, "[include]\npath = %s/config-included", cl_fixture("config")));
+       git_str cfgdata = GIT_STR_INIT;
+       cl_git_pass(git_str_printf(&cfgdata, "[include]\npath = %s/config-included", cl_fixture("config")));
+
+       cl_git_mkfile("config-include-absolute", cfgdata.ptr);
+       git_str_dispose(&cfgdata);
 
-       cl_git_mkfile("config-include-absolute", git_buf_cstr(&buf));
-       git_buf_dispose(&buf);
        cl_git_pass(git_config_open_ondisk(&cfg, "config-include-absolute"));
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.baz"));
-       cl_assert_equal_s("huzzah", git_buf_cstr(&buf));
+       cl_assert_equal_s("huzzah", buf.ptr);
 
        cl_git_pass(p_unlink("config-include-absolute"));
 }
@@ -47,7 +48,7 @@ void test_config_include__homedir(void)
        cl_git_pass(git_config_open_ondisk(&cfg, "config-include-homedir"));
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.baz"));
-       cl_assert_equal_s("huzzah", git_buf_cstr(&buf));
+       cl_assert_equal_s("huzzah", buf.ptr);
 
        cl_sandbox_set_search_path_defaults();
 
@@ -66,10 +67,10 @@ void test_config_include__ordering(void)
        cl_git_pass(git_config_open_ondisk(&cfg, "including"));
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.frotz"));
-       cl_assert_equal_s("hiya", git_buf_cstr(&buf));
-       git_buf_clear(&buf);
+       cl_assert_equal_s("hiya", buf.ptr);
+       git_buf_dispose(&buf);
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.baz"));
-       cl_assert_equal_s("huzzah", git_buf_cstr(&buf));
+       cl_assert_equal_s("huzzah", buf.ptr);
 
        cl_git_pass(p_unlink("included"));
        cl_git_pass(p_unlink("including"));
@@ -92,7 +93,7 @@ void test_config_include__empty_path_sanely_handled(void)
        cl_git_mkfile("a", "[include]\npath");
        cl_git_pass(git_config_open_ondisk(&cfg, "a"));
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "include.path"));
-       cl_assert_equal_s("", git_buf_cstr(&buf));
+       cl_assert_equal_s("", buf.ptr);
 
        cl_git_pass(p_unlink("a"));
 }
@@ -105,7 +106,7 @@ void test_config_include__missing(void)
        cl_git_pass(git_config_open_ondisk(&cfg, "including"));
        cl_assert(git_error_last() == NULL);
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
-       cl_assert_equal_s("baz", git_buf_cstr(&buf));
+       cl_assert_equal_s("baz", buf.ptr);
 
        cl_git_pass(p_unlink("including"));
 }
@@ -119,7 +120,7 @@ void test_config_include__missing_homedir(void)
        cl_git_pass(git_config_open_ondisk(&cfg, "including"));
        cl_assert(git_error_last() == NULL);
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
-       cl_assert_equal_s("baz", git_buf_cstr(&buf));
+       cl_assert_equal_s("baz", buf.ptr);
 
        cl_sandbox_set_search_path_defaults();
        cl_git_pass(p_unlink("including"));
@@ -137,11 +138,11 @@ void test_config_include__depth2(void)
        cl_git_pass(git_config_open_ondisk(&cfg, "top-level"));
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
-       cl_assert_equal_s("baz", git_buf_cstr(&buf));
+       cl_assert_equal_s("baz", buf.ptr);
 
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar2"));
-       cl_assert_equal_s("baz2", git_buf_cstr(&buf));
+       cl_assert_equal_s("baz2", buf.ptr);
 
        cl_git_pass(p_unlink("top-level"));
        cl_git_pass(p_unlink("middle"));
@@ -186,13 +187,13 @@ void test_config_include__rewriting_include_twice_refreshes_values(void)
        cl_git_pass(git_config_open_ondisk(&cfg, "top-level"));
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
 
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        cl_git_mkfile("included", "[foo]\nother = value2");
        cl_git_fail(git_config_get_string_buf(&buf, cfg, "foo.bar"));
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.other"));
        cl_assert_equal_s(buf.ptr, "value2");
 
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        cl_git_mkfile("included", "[foo]\nanother = bar");
        cl_git_fail(git_config_get_string_buf(&buf, cfg, "foo.other"));
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.another"));
index 4f08a48172f355ed7f08907b73906319826b4430..244e3755965442b93a01f25272e769655f009720 100644 (file)
@@ -128,7 +128,7 @@ void test_config_multivar__add(void)
        int n;
 
        cl_git_pass(git_config_open_ondisk(&cfg, "config/config11"));
-       cl_git_pass(git_config_set_multivar(cfg, _name, "nonexistant", "git://git.otherplace.org/libgit2"));
+       cl_git_pass(git_config_set_multivar(cfg, _name, "non-existent", "git://git.otherplace.org/libgit2"));
 
        n = 0;
        cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n));
index 22c330f6f98abebbdea70019dcd3f5d432d547e6..baca05332239378d8e487de4f0a8bcf4dec7f6fc 100644 (file)
@@ -22,10 +22,10 @@ void test_config_new__write_new_config(void)
        cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG));
 
        cl_git_pass(git_config_get_string_buf(&buf, config, "color.ui"));
-       cl_assert_equal_s("auto", git_buf_cstr(&buf));
-       git_buf_clear(&buf);
+       cl_assert_equal_s("auto", buf.ptr);
+       git_buf_dispose(&buf);
        cl_git_pass(git_config_get_string_buf(&buf, config, "core.editor"));
-       cl_assert_equal_s("ed", git_buf_cstr(&buf));
+       cl_assert_equal_s("ed", buf.ptr);
 
        git_buf_dispose(&buf);
        git_config_free(config);
index 8d1bb8b0afa2c86b90b51e7ee99612c0c64cb317..a2e668c207b48c526cbb4190f3e0afd1d538521e 100644 (file)
@@ -1,6 +1,5 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
-#include "path.h"
+#include "fs_path.h"
 
 static git_buf buf = GIT_BUF_INIT;
 
@@ -36,11 +35,11 @@ void test_config_read__case_sensitive(void)
        cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config1")));
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "this.that.other"));
-       cl_assert_equal_s("true", git_buf_cstr(&buf));
-       git_buf_clear(&buf);
+       cl_assert_equal_s("true", buf.ptr);
+       git_buf_dispose(&buf);
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "this.That.other"));
-       cl_assert_equal_s("yes", git_buf_cstr(&buf));
+       cl_assert_equal_s("yes", buf.ptr);
 
        cl_git_pass(git_config_get_bool(&i, cfg, "this.that.other"));
        cl_assert(i == 1);
@@ -64,7 +63,7 @@ void test_config_read__multiline_value(void)
        cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config2")));
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "this.That.and"));
-       cl_assert_equal_s("one one one two two three three", git_buf_cstr(&buf));
+       cl_assert_equal_s("one one one two two three three", buf.ptr);
 
        git_config_free(cfg);
 }
@@ -84,7 +83,7 @@ void test_config_read__multiline_value_and_eof(void)
        cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "header.key1"));
-       cl_assert_equal_s("foo", git_buf_cstr(&buf));
+       cl_assert_equal_s("foo", buf.ptr);
 
        git_config_free(cfg);
 }
@@ -98,7 +97,7 @@ void test_config_read__multiline_eof(void)
        cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "header.key1"));
-       cl_assert_equal_s("", git_buf_cstr(&buf));
+       cl_assert_equal_s("", buf.ptr);
 
        git_config_free(cfg);
 }
@@ -113,7 +112,7 @@ void test_config_read__subsection_header(void)
        cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config3")));
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "section.subsection.var"));
-       cl_assert_equal_s("hello", git_buf_cstr(&buf));
+       cl_assert_equal_s("hello", buf.ptr);
 
        /* The subsection is transformed to lower-case */
        cl_must_fail(git_config_get_string_buf(&buf, cfg, "section.subSectIon.var"));
@@ -131,14 +130,14 @@ void test_config_read__lone_variable(void)
        cl_git_fail(git_config_get_int32(&i, cfg, "some.section.variable"));
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.section.variable"));
-       cl_assert_equal_s("", git_buf_cstr(&buf));
-       git_buf_clear(&buf);
+       cl_assert_equal_s("", buf.ptr);
+       git_buf_dispose(&buf);
 
        cl_git_pass(git_config_get_bool(&i, cfg, "some.section.variable"));
        cl_assert(i == 1);
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.section.variableeq"));
-       cl_assert_equal_s("", git_buf_cstr(&buf));
+       cl_assert_equal_s("", buf.ptr);
 
        cl_git_pass(git_config_get_bool(&i, cfg, "some.section.variableeq"));
        cl_assert(i == 0);
@@ -210,6 +209,21 @@ void test_config_read__symbol_headers(void)
 {
        git_config *cfg;
        cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config20")));
+       cl_git_pass(git_config_get_string_buf(&buf, cfg, "valid.[subsection].something"));
+       cl_assert_equal_s("a", buf.ptr);
+       git_buf_dispose(&buf);
+       cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec.[subsec]/child.parent"));
+       cl_assert_equal_s("grand", buf.ptr);
+       git_buf_dispose(&buf);
+       cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec2.[subsec2]/child2.type"));
+       cl_assert_equal_s("dvcs", buf.ptr);
+       git_buf_dispose(&buf);
+       cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec3.escape\"quote.vcs"));
+       cl_assert_equal_s("git", buf.ptr);
+       git_buf_dispose(&buf);
+       cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec4.escaping\\slash.lib"));
+       cl_assert_equal_s("git2", buf.ptr);
+       git_buf_dispose(&buf);
        git_config_free(cfg);
 }
 
@@ -220,6 +234,19 @@ void test_config_read__multiline_multiple_quoted_comment_chars(void)
        git_config_free(cfg);
 }
 
+void test_config_read__multiline_multiple_quoted_quote_at_beginning_of_line(void)
+{
+       git_config* cfg;
+       cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config22")));
+       cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m"));
+       cl_assert_equal_s("cmd ;; ;; bar", buf.ptr);
+       git_buf_dispose(&buf);
+       cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m2"));
+       cl_assert_equal_s("'; ; something '", buf.ptr);
+       git_buf_dispose(&buf);
+       git_config_free(cfg);
+}
+
 void test_config_read__header_in_last_line(void)
 {
        git_config *cfg;
@@ -234,11 +261,11 @@ void test_config_read__prefixes(void)
 
        cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9")));
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "remote.ab.url"));
-       cl_assert_equal_s("http://example.com/git/ab", git_buf_cstr(&buf));
-       git_buf_clear(&buf);
+       cl_assert_equal_s("http://example.com/git/ab", buf.ptr);
+       git_buf_dispose(&buf);
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "remote.abba.url"));
-       cl_assert_equal_s("http://example.com/git/abba", git_buf_cstr(&buf));
+       cl_assert_equal_s("http://example.com/git/abba", buf.ptr);
 
        git_config_free(cfg);
 }
@@ -249,7 +276,7 @@ void test_config_read__escaping_quotes(void)
 
        cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config13")));
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.editor"));
-       cl_assert_equal_s("\"C:/Program Files/Nonsense/bah.exe\" \"--some option\"", git_buf_cstr(&buf));
+       cl_assert_equal_s("\"C:/Program Files/Nonsense/bah.exe\" \"--some option\"", buf.ptr);
 
        git_config_free(cfg);
 }
@@ -446,11 +473,11 @@ void test_config_read__whitespace_not_required_around_assignment(void)
        cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config14")));
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "a.b"));
-       cl_assert_equal_s("c", git_buf_cstr(&buf));
-       git_buf_clear(&buf);
+       cl_assert_equal_s("c", buf.ptr);
+       git_buf_dispose(&buf);
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "d.e"));
-       cl_assert_equal_s("f", git_buf_cstr(&buf));
+       cl_assert_equal_s("f", buf.ptr);
 
        git_config_free(cfg);
 }
@@ -596,7 +623,7 @@ void test_config_read__simple_read_from_specific_level(void)
        cl_git_pass(git_config_get_bool(&i, cfg_specific, "core.boolglobal"));
        cl_assert_equal_b(true, i);
        cl_git_pass(git_config_get_string_buf(&buf, cfg_specific, "core.stringglobal"));
-       cl_assert_equal_s("I'm a global config value!", git_buf_cstr(&buf));
+       cl_assert_equal_s("I'm a global config value!", buf.ptr);
 
        git_config_free(cfg_specific);
        git_config_free(cfg);
@@ -692,7 +719,7 @@ void test_config_read__override_variable(void)
        cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
 
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.var"));
-       cl_assert_equal_s("two", git_buf_cstr(&buf));
+       cl_assert_equal_s("two", buf.ptr);
 
        git_config_free(cfg);
 }
@@ -702,15 +729,15 @@ void test_config_read__path(void)
        git_config *cfg;
        git_buf path = GIT_BUF_INIT;
        git_buf old_path = GIT_BUF_INIT;
-       git_buf home_path = GIT_BUF_INIT;
-       git_buf expected_path = GIT_BUF_INIT;
+       git_str home_path = GIT_STR_INIT;
+       git_str expected_path = GIT_STR_INIT;
 
        cl_git_pass(p_mkdir("fakehome", 0777));
-       cl_git_pass(git_path_prettify(&home_path, "fakehome", NULL));
+       cl_git_pass(git_fs_path_prettify(&home_path, "fakehome", NULL));
        cl_git_pass(git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &old_path));
        cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, home_path.ptr));
        cl_git_mkfile("./testconfig", "[some]\n path = ~/somefile");
-       cl_git_pass(git_path_join_unrooted(&expected_path, "somefile", home_path.ptr, NULL));
+       cl_git_pass(git_fs_path_join_unrooted(&expected_path, "somefile", home_path.ptr, NULL));
 
        cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
        cl_git_pass(git_config_get_path(&path, cfg, "some.path"));
@@ -718,14 +745,14 @@ void test_config_read__path(void)
        git_buf_dispose(&path);
 
        cl_git_mkfile("./testconfig", "[some]\n path = ~/");
-       cl_git_pass(git_path_join_unrooted(&expected_path, "", home_path.ptr, NULL));
+       cl_git_pass(git_fs_path_join_unrooted(&expected_path, "", home_path.ptr, NULL));
 
        cl_git_pass(git_config_get_path(&path, cfg, "some.path"));
        cl_assert_equal_s(expected_path.ptr, path.ptr);
        git_buf_dispose(&path);
 
        cl_git_mkfile("./testconfig", "[some]\n path = ~");
-       cl_git_pass(git_buf_sets(&expected_path, home_path.ptr));
+       cl_git_pass(git_str_sets(&expected_path, home_path.ptr));
 
        cl_git_pass(git_config_get_path(&path, cfg, "some.path"));
        cl_assert_equal_s(expected_path.ptr, path.ptr);
@@ -736,8 +763,8 @@ void test_config_read__path(void)
 
        cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, old_path.ptr));
        git_buf_dispose(&old_path);
-       git_buf_dispose(&home_path);
-       git_buf_dispose(&expected_path);
+       git_str_dispose(&home_path);
+       git_str_dispose(&expected_path);
        git_config_free(cfg);
 }
 
@@ -884,18 +911,18 @@ void test_config_read__single_line(void)
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.var"));
        cl_assert_equal_s(buf.ptr, "value");
 
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.OtheR.var"));
        cl_assert_equal_s(buf.ptr, "value");
 
        git_config_free(cfg);
        cl_git_mkfile("./testconfig", "[some] var = value\n[some \"OtheR\"]var = value");
        cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.var"));
        cl_assert_equal_s(buf.ptr, "value");
 
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.OtheR.var"));
        cl_assert_equal_s(buf.ptr, "value");
 
index 5d544b8cb4a08bb9bea67ce4ff1893d58f30c169..a8901e394c0b6cd215a29f3be54c5218553e4ee2 100644 (file)
@@ -25,7 +25,7 @@ void test_config_readonly__writing_to_readonly_fails(void)
        cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
 
        cl_git_fail_with(GIT_ENOTFOUND, git_config_set_string(cfg, "foo.bar", "baz"));
-       cl_assert(!git_path_exists("global"));
+       cl_assert(!git_fs_path_exists("global"));
 }
 
 void test_config_readonly__writing_to_cfg_with_rw_precedence_succeeds(void)
@@ -41,8 +41,8 @@ void test_config_readonly__writing_to_cfg_with_rw_precedence_succeeds(void)
 
        cl_git_pass(git_config_set_string(cfg, "foo.bar", "baz"));
 
-       cl_assert(git_path_exists("local"));
-       cl_assert(!git_path_exists("global"));
+       cl_assert(git_fs_path_exists("local"));
+       cl_assert(!git_fs_path_exists("global"));
        cl_git_pass(p_unlink("local"));
 }
 
@@ -59,7 +59,7 @@ void test_config_readonly__writing_to_cfg_with_ro_precedence_succeeds(void)
 
        cl_git_pass(git_config_set_string(cfg, "foo.bar", "baz"));
 
-       cl_assert(!git_path_exists("local"));
-       cl_assert(git_path_exists("global"));
+       cl_assert(!git_fs_path_exists("local"));
+       cl_assert(git_fs_path_exists("global"));
        cl_git_pass(p_unlink("global"));
 }
index 577452e8d143021c74c048fe95dd6743027b2e95..69e6810facf0bc9a215605db8ba3863d08c49f55 100644 (file)
@@ -30,7 +30,7 @@ void test_config_stress__dont_break_on_invalid_input(void)
 {
        git_config *config;
 
-       cl_assert(git_path_exists(TEST_CONFIG));
+       cl_assert(git_fs_path_exists(TEST_CONFIG));
        cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG));
 
        cl_git_pass(git_config_get_string_buf(&buf, config, "color.ui"));
@@ -39,11 +39,11 @@ void test_config_stress__dont_break_on_invalid_input(void)
        git_config_free(config);
 }
 
-void assert_config_value(git_config *config, const char *key, const char *value)
+static void assert_config_value(git_config *config, const char *key, const char *value)
 {
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        cl_git_pass(git_config_get_string_buf(&buf, config, key));
-       cl_assert_equal_s(value, git_buf_cstr(&buf));
+       cl_assert_equal_s(value, buf.ptr);
 }
 
 void test_config_stress__comments(void)
@@ -72,7 +72,7 @@ void test_config_stress__escape_subsection_names(void)
 {
        git_config *config;
 
-       cl_assert(git_path_exists("git-test-config"));
+       cl_assert(git_fs_path_exists("git-test-config"));
        cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG));
 
        cl_git_pass(git_config_set_string(config, "some.sec\\tion.other", "foo"));
@@ -90,7 +90,7 @@ void test_config_stress__trailing_backslash(void)
        git_config *config;
        const char *path =  "C:\\iam\\some\\windows\\path\\";
 
-       cl_assert(git_path_exists("git-test-config"));
+       cl_assert(git_fs_path_exists("git-test-config"));
        cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG));
        cl_git_pass(git_config_set_string(config, "windows.path", path));
        git_config_free(config);
index 78ed7f15b76cd5646f60786716077f702fe84acf..9d8c3fe94957bc7786996cd15c3e6a885fb3222c 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "futils.h"
 #include "git2/sys/config.h"
 #include "config.h"
@@ -9,6 +8,7 @@ void test_config_write__initialize(void)
        cl_fixture_sandbox("config/config9");
        cl_fixture_sandbox("config/config15");
        cl_fixture_sandbox("config/config17");
+       cl_fixture_sandbox("config/config22");
 }
 
 void test_config_write__cleanup(void)
@@ -16,6 +16,7 @@ void test_config_write__cleanup(void)
        cl_fixture_cleanup("config9");
        cl_fixture_cleanup("config15");
        cl_fixture_cleanup("config17");
+       cl_fixture_cleanup("config22");
 }
 
 void test_config_write__replace_value(void)
@@ -290,7 +291,7 @@ void test_config_write__write_subsection(void)
 
        cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "my.own.var"));
-       cl_assert_equal_s("works", git_buf_cstr(&buf));
+       cl_assert_equal_s("works", buf.ptr);
 
        git_buf_dispose(&buf);
        git_config_free(cfg);
@@ -313,27 +314,27 @@ void test_config_write__value_containing_quotes(void)
        cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
        cl_git_pass(git_config_set_string(cfg, "core.somevar", "this \"has\" quotes"));
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.somevar"));
-       cl_assert_equal_s("this \"has\" quotes", git_buf_cstr(&buf));
-       git_buf_clear(&buf);
+       cl_assert_equal_s("this \"has\" quotes", buf.ptr);
+       git_buf_dispose(&buf);
        git_config_free(cfg);
 
        cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.somevar"));
-       cl_assert_equal_s("this \"has\" quotes", git_buf_cstr(&buf));
-       git_buf_clear(&buf);
+       cl_assert_equal_s("this \"has\" quotes", buf.ptr);
+       git_buf_dispose(&buf);
        git_config_free(cfg);
 
        /* The code path for values that already exist is different, check that one as well */
        cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
        cl_git_pass(git_config_set_string(cfg, "core.somevar", "this also \"has\" quotes"));
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.somevar"));
-       cl_assert_equal_s("this also \"has\" quotes", git_buf_cstr(&buf));
-       git_buf_clear(&buf);
+       cl_assert_equal_s("this also \"has\" quotes", buf.ptr);
+       git_buf_dispose(&buf);
        git_config_free(cfg);
 
        cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.somevar"));
-       cl_assert_equal_s("this also \"has\" quotes", git_buf_cstr(&buf));
+       cl_assert_equal_s("this also \"has\" quotes", buf.ptr);
        git_buf_dispose(&buf);
        git_config_free(cfg);
 }
@@ -346,13 +347,13 @@ void test_config_write__escape_value(void)
        cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
        cl_git_pass(git_config_set_string(cfg, "core.somevar", "this \"has\" quotes and \t"));
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.somevar"));
-       cl_assert_equal_s("this \"has\" quotes and \t", git_buf_cstr(&buf));
-       git_buf_clear(&buf);
+       cl_assert_equal_s("this \"has\" quotes and \t", buf.ptr);
+       git_buf_dispose(&buf);
        git_config_free(cfg);
 
        cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.somevar"));
-       cl_assert_equal_s("this \"has\" quotes and \t", git_buf_cstr(&buf));
+       cl_assert_equal_s("this \"has\" quotes and \t", buf.ptr);
        git_buf_dispose(&buf);
        git_config_free(cfg);
 }
@@ -390,7 +391,7 @@ void test_config_write__add_value_at_specific_level(void)
        cl_git_pass(git_config_get_bool(&i, cfg, "core.boolglobal"));
        cl_assert_equal_b(true, i);
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.stringglobal"));
-       cl_assert_equal_s("I'm a global config value!", git_buf_cstr(&buf));
+       cl_assert_equal_s("I'm a global config value!", buf.ptr);
 
        git_buf_dispose(&buf);
        git_config_free(cfg);
@@ -553,7 +554,7 @@ void test_config_write__preserves_whitespace_and_comments(void)
        const char *file_name  = "config-duplicate-header";
        const char *n;
        git_config *cfg;
-       git_buf newfile = GIT_BUF_INIT;
+       git_str newfile = GIT_STR_INIT;
 
        /* This config can occur after removing and re-adding the origin remote */
        const char *file_content = SECTION_FOO_WITH_COMMENT SECTION_BAR;
@@ -580,7 +581,7 @@ void test_config_write__preserves_whitespace_and_comments(void)
 
        cl_assert_equal_s("[newsection]\n\tnewname = new_value\n", n);
 
-       git_buf_dispose(&newfile);
+       git_str_dispose(&newfile);
        git_config_free(cfg);
 }
 
@@ -588,7 +589,7 @@ void test_config_write__preserves_entry_with_name_only(void)
 {
        const char *file_name  = "config-empty-value";
        git_config *cfg;
-       git_buf newfile = GIT_BUF_INIT;
+       git_str newfile = GIT_STR_INIT;
 
        /* Write the test config and make sure the expected entry exists */
        cl_git_mkfile(file_name, "[section \"foo\"]\n\tname\n");
@@ -599,7 +600,7 @@ void test_config_write__preserves_entry_with_name_only(void)
        cl_git_pass(git_futils_readbuffer(&newfile, file_name));
        cl_assert_equal_s("[section \"foo\"]\n\tname\n\tother = otherval\n[newsection]\n\tnewname = new_value\n", newfile.ptr);
 
-       git_buf_dispose(&newfile);
+       git_str_dispose(&newfile);
        git_config_free(cfg);
 }
 
@@ -607,7 +608,7 @@ void test_config_write__to_empty_file(void)
 {
        git_config *cfg;
        const char *filename = "config-file";
-       git_buf result = GIT_BUF_INIT;
+       git_str result = GIT_STR_INIT;
 
        cl_git_mkfile(filename, "");
        cl_git_pass(git_config_open_ondisk(&cfg, filename));
@@ -617,14 +618,14 @@ void test_config_write__to_empty_file(void)
        cl_git_pass(git_futils_readbuffer(&result, "config-file"));
        cl_assert_equal_s("[section]\n\tname = value\n", result.ptr);
 
-       git_buf_dispose(&result);
+       git_str_dispose(&result);
 }
 
 void test_config_write__to_file_with_only_comment(void)
 {
        git_config *cfg;
        const char *filename = "config-file";
-       git_buf result = GIT_BUF_INIT;
+       git_str result = GIT_STR_INIT;
 
        cl_git_mkfile(filename, "\n\n");
        cl_git_pass(git_config_open_ondisk(&cfg, filename));
@@ -634,7 +635,7 @@ void test_config_write__to_file_with_only_comment(void)
        cl_git_pass(git_futils_readbuffer(&result, "config-file"));
        cl_assert_equal_s("\n\n[section]\n\tname = value\n", result.ptr);
 
-       git_buf_dispose(&result);
+       git_str_dispose(&result);
 }
 
 void test_config_write__locking(void)
@@ -699,7 +700,7 @@ void test_config_write__repeated(void)
 {
        const char *filename = "config-repeated";
        git_config *cfg;
-       git_buf result = GIT_BUF_INIT;
+       git_str result = GIT_STR_INIT;
        const char *expected = "[sample \"prefix\"]\n\
 \tsetting1 = someValue1\n\
 \tsetting2 = someValue2\n\
@@ -717,7 +718,7 @@ void test_config_write__repeated(void)
 
        cl_git_pass(git_futils_readbuffer(&result, filename));
        cl_assert_equal_s(expected, result.ptr);
-       git_buf_dispose(&result);
+       git_str_dispose(&result);
 
        git_config_free(cfg);
 }
@@ -726,7 +727,7 @@ void test_config_write__preserve_case(void)
 {
        const char *filename = "config-preserve-case";
        git_config *cfg;
-       git_buf result = GIT_BUF_INIT;
+       git_str result = GIT_STR_INIT;
        const char *expected = "[sOMe]\n" \
                "\tThInG = foo\n" \
                "\tOtheR = thing\n";
@@ -740,7 +741,24 @@ void test_config_write__preserve_case(void)
 
        cl_git_pass(git_futils_readbuffer(&result, filename));
        cl_assert_equal_s(expected, result.ptr);
-       git_buf_dispose(&result);
+       git_str_dispose(&result);
+
+       git_config_free(cfg);
+}
+
+void test_config_write__write_config_file_with_multi_line_value(void)
+{
+       git_config* cfg;
+       git_buf buf = GIT_BUF_INIT;
+
+       cl_git_pass(git_config_open_ondisk(&cfg, "config22"));
+       cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m"));
+       cl_assert_equal_s("cmd ;; ;; bar", buf.ptr);
+       cl_git_pass(git_config_set_string(cfg, "sOMe.ThInG", "foo"));
+       git_buf_dispose(&buf);
+       cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m"));
+       cl_assert_equal_s("cmd ;; ;; bar", buf.ptr);
+       git_buf_dispose(&buf);
 
        git_config_free(cfg);
 }
diff --git a/tests/core/buf.c b/tests/core/buf.c
new file mode 100644 (file)
index 0000000..3959fa8
--- /dev/null
@@ -0,0 +1,54 @@
+#include "clar_libgit2.h"
+#include "buf.h"
+
+void test_core_buf__sanitize(void)
+{
+       git_buf buf = { (char *)0x42, 0, 16 };
+
+       cl_git_pass(git_buf_sanitize(&buf));
+       cl_assert_equal_s(buf.ptr, "");
+       cl_assert_equal_i(buf.reserved, 0);
+       cl_assert_equal_i(buf.size, 0);
+
+       git_buf_dispose(&buf);
+}
+
+void test_core_buf__tostr(void)
+{
+       git_str str = GIT_STR_INIT;
+       git_buf buf = { (char *)0x42, 0, 16 };
+
+       cl_git_pass(git_buf_tostr(&str, &buf));
+
+       cl_assert_equal_s(buf.ptr, "");
+       cl_assert_equal_i(buf.reserved, 0);
+       cl_assert_equal_i(buf.size, 0);
+
+       cl_assert_equal_s(str.ptr, "");
+       cl_assert_equal_i(str.asize, 0);
+       cl_assert_equal_i(str.size, 0);
+
+       git_buf_dispose(&buf);
+       git_str_dispose(&str);
+}
+
+void test_core_buf__fromstr(void)
+{
+       git_str str = GIT_STR_INIT;
+       git_buf buf = { (char *)0x42, 0, 16 };
+
+       cl_git_pass(git_buf_tostr(&str, &buf));
+       cl_git_pass(git_str_puts(&str, "Hello, world."));
+       cl_git_pass(git_buf_fromstr(&buf, &str));
+
+       cl_assert(buf.reserved > 14);
+       cl_assert_equal_i(buf.size, 13);
+       cl_assert_equal_s(buf.ptr, "Hello, world.");
+
+       cl_assert_equal_s(str.ptr, "");
+       cl_assert_equal_i(str.asize, 0);
+       cl_assert_equal_i(str.size, 0);
+
+       git_buf_dispose(&buf);
+       git_str_dispose(&str);
+}
diff --git a/tests/core/buffer.c b/tests/core/buffer.c
deleted file mode 100644 (file)
index 2af4a87..0000000
+++ /dev/null
@@ -1,1226 +0,0 @@
-#include "clar_libgit2.h"
-#include "buffer.h"
-#include "git2/sys/hashsig.h"
-#include "futils.h"
-
-#define TESTSTR "Have you seen that? Have you seeeen that??"
-const char *test_string = TESTSTR;
-const char *test_string_x2 = TESTSTR TESTSTR;
-
-#define TESTSTR_4096 REP1024("1234")
-#define TESTSTR_8192 REP1024("12341234")
-const char *test_4096 = TESTSTR_4096;
-const char *test_8192 = TESTSTR_8192;
-
-/* test basic data concatenation */
-void test_core_buffer__0(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       cl_assert(buf.size == 0);
-
-       git_buf_puts(&buf, test_string);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(test_string, git_buf_cstr(&buf));
-
-       git_buf_puts(&buf, test_string);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(test_string_x2, git_buf_cstr(&buf));
-
-       git_buf_dispose(&buf);
-}
-
-/* test git_buf_printf */
-void test_core_buffer__1(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       git_buf_printf(&buf, "%s %s %d ", "shoop", "da", 23);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s("shoop da 23 ", git_buf_cstr(&buf));
-
-       git_buf_printf(&buf, "%s %d", "woop", 42);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s("shoop da 23 woop 42", git_buf_cstr(&buf));
-
-       git_buf_dispose(&buf);
-}
-
-/* more thorough test of concatenation options */
-void test_core_buffer__2(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-       int i;
-       char data[128];
-
-       cl_assert(buf.size == 0);
-
-       /* this must be safe to do */
-       git_buf_dispose(&buf);
-       cl_assert(buf.size == 0);
-       cl_assert(buf.asize == 0);
-
-       /* empty buffer should be empty string */
-       cl_assert_equal_s("", git_buf_cstr(&buf));
-       cl_assert(buf.size == 0);
-       /* cl_assert(buf.asize == 0); -- should not assume what git_buf does */
-
-       /* free should set us back to the beginning */
-       git_buf_dispose(&buf);
-       cl_assert(buf.size == 0);
-       cl_assert(buf.asize == 0);
-
-       /* add letter */
-       git_buf_putc(&buf, '+');
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s("+", git_buf_cstr(&buf));
-
-       /* add letter again */
-       git_buf_putc(&buf, '+');
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s("++", git_buf_cstr(&buf));
-
-       /* let's try that a few times */
-       for (i = 0; i < 16; ++i) {
-               git_buf_putc(&buf, '+');
-               cl_assert(git_buf_oom(&buf) == 0);
-       }
-       cl_assert_equal_s("++++++++++++++++++", git_buf_cstr(&buf));
-
-       git_buf_dispose(&buf);
-
-       /* add data */
-       git_buf_put(&buf, "xo", 2);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s("xo", git_buf_cstr(&buf));
-
-       /* add letter again */
-       git_buf_put(&buf, "xo", 2);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s("xoxo", git_buf_cstr(&buf));
-
-       /* let's try that a few times */
-       for (i = 0; i < 16; ++i) {
-               git_buf_put(&buf, "xo", 2);
-               cl_assert(git_buf_oom(&buf) == 0);
-       }
-       cl_assert_equal_s("xoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxo",
-                                          git_buf_cstr(&buf));
-
-       git_buf_dispose(&buf);
-
-       /* set to string */
-       git_buf_sets(&buf, test_string);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(test_string, git_buf_cstr(&buf));
-
-       /* append string */
-       git_buf_puts(&buf, test_string);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(test_string_x2, git_buf_cstr(&buf));
-
-       /* set to string again (should overwrite - not append) */
-       git_buf_sets(&buf, test_string);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(test_string, git_buf_cstr(&buf));
-
-       /* test clear */
-       git_buf_clear(&buf);
-       cl_assert_equal_s("", git_buf_cstr(&buf));
-
-       git_buf_dispose(&buf);
-
-       /* test extracting data into buffer */
-       git_buf_puts(&buf, REP4("0123456789"));
-       cl_assert(git_buf_oom(&buf) == 0);
-
-       git_buf_copy_cstr(data, sizeof(data), &buf);
-       cl_assert_equal_s(REP4("0123456789"), data);
-       git_buf_copy_cstr(data, 11, &buf);
-       cl_assert_equal_s("0123456789", data);
-       git_buf_copy_cstr(data, 3, &buf);
-       cl_assert_equal_s("01", data);
-       git_buf_copy_cstr(data, 1, &buf);
-       cl_assert_equal_s("", data);
-
-       git_buf_copy_cstr(data, sizeof(data), &buf);
-       cl_assert_equal_s(REP4("0123456789"), data);
-
-       git_buf_sets(&buf, REP256("x"));
-       git_buf_copy_cstr(data, sizeof(data), &buf);
-       /* since sizeof(data) == 128, only 127 bytes should be copied */
-       cl_assert_equal_s(REP4(REP16("x")) REP16("x") REP16("x")
-                                          REP16("x") "xxxxxxxxxxxxxxx", data);
-
-       git_buf_dispose(&buf);
-
-       git_buf_copy_cstr(data, sizeof(data), &buf);
-       cl_assert_equal_s("", data);
-}
-
-/* let's do some tests with larger buffers to push our limits */
-void test_core_buffer__3(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       /* set to string */
-       git_buf_set(&buf, test_4096, 4096);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(test_4096, git_buf_cstr(&buf));
-
-       /* append string */
-       git_buf_puts(&buf, test_4096);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(test_8192, git_buf_cstr(&buf));
-
-       /* set to string again (should overwrite - not append) */
-       git_buf_set(&buf, test_4096, 4096);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(test_4096, git_buf_cstr(&buf));
-
-       git_buf_dispose(&buf);
-}
-
-/* let's try some producer/consumer tests */
-void test_core_buffer__4(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-       int i;
-
-       for (i = 0; i < 10; ++i) {
-               git_buf_puts(&buf, "1234"); /* add 4 */
-               cl_assert(git_buf_oom(&buf) == 0);
-               git_buf_consume(&buf, buf.ptr + 2); /* eat the first two */
-               cl_assert(strlen(git_buf_cstr(&buf)) == (size_t)((i + 1) * 2));
-       }
-       /* we have appended 1234 10x and removed the first 20 letters */
-       cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf));
-
-       git_buf_consume(&buf, NULL);
-       cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf));
-
-       git_buf_consume(&buf, "invalid pointer");
-       cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf));
-
-       git_buf_consume(&buf, buf.ptr);
-       cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf));
-
-       git_buf_consume(&buf, buf.ptr + 1);
-       cl_assert_equal_s("2341234123412341234", git_buf_cstr(&buf));
-
-       git_buf_consume(&buf, buf.ptr + buf.size);
-       cl_assert_equal_s("", git_buf_cstr(&buf));
-
-       git_buf_dispose(&buf);
-}
-
-
-static void
-check_buf_append(
-       const char* data_a,
-       const char* data_b,
-       const char* expected_data,
-       size_t expected_size,
-       size_t expected_asize)
-{
-       git_buf tgt = GIT_BUF_INIT;
-
-       git_buf_sets(&tgt, data_a);
-       cl_assert(git_buf_oom(&tgt) == 0);
-       git_buf_puts(&tgt, data_b);
-       cl_assert(git_buf_oom(&tgt) == 0);
-       cl_assert_equal_s(expected_data, git_buf_cstr(&tgt));
-       cl_assert_equal_i(tgt.size, expected_size);
-       if (expected_asize > 0)
-               cl_assert_equal_i(tgt.asize, expected_asize);
-
-       git_buf_dispose(&tgt);
-}
-
-static void
-check_buf_append_abc(
-       const char* buf_a,
-       const char* buf_b,
-       const char* buf_c,
-       const char* expected_ab,
-       const char* expected_abc,
-       const char* expected_abca,
-       const char* expected_abcab,
-       const char* expected_abcabc)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       git_buf_sets(&buf, buf_a);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(buf_a, git_buf_cstr(&buf));
-
-       git_buf_puts(&buf, buf_b);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(expected_ab, git_buf_cstr(&buf));
-
-       git_buf_puts(&buf, buf_c);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(expected_abc, git_buf_cstr(&buf));
-
-       git_buf_puts(&buf, buf_a);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(expected_abca, git_buf_cstr(&buf));
-
-       git_buf_puts(&buf, buf_b);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(expected_abcab, git_buf_cstr(&buf));
-
-       git_buf_puts(&buf, buf_c);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(expected_abcabc, git_buf_cstr(&buf));
-
-       git_buf_dispose(&buf);
-}
-
-/* more variations on append tests */
-void test_core_buffer__5(void)
-{
-       check_buf_append("", "", "", 0, 0);
-       check_buf_append("a", "", "a", 1, 0);
-       check_buf_append("", "a", "a", 1, 8);
-       check_buf_append("", "a", "a", 1, 8);
-       check_buf_append("a", "b", "ab", 2, 8);
-       check_buf_append("", "abcdefgh", "abcdefgh", 8, 16);
-       check_buf_append("abcdefgh", "", "abcdefgh", 8, 16);
-
-       /* buffer with starting asize will grow to:
-        *  1 ->  2,  2 ->  3,  3 ->  5,  4 ->  6,  5 ->  8,  6 ->  9,
-        *  7 -> 11,  8 -> 12,  9 -> 14, 10 -> 15, 11 -> 17, 12 -> 18,
-        * 13 -> 20, 14 -> 21, 15 -> 23, 16 -> 24, 17 -> 26, 18 -> 27,
-        * 19 -> 29, 20 -> 30, 21 -> 32, 22 -> 33, 23 -> 35, 24 -> 36,
-        * ...
-        * follow sequence until value > target size,
-        * then round up to nearest multiple of 8.
-        */
-
-       check_buf_append("abcdefgh", "/", "abcdefgh/", 9, 16);
-       check_buf_append("abcdefgh", "ijklmno", "abcdefghijklmno", 15, 16);
-       check_buf_append("abcdefgh", "ijklmnop", "abcdefghijklmnop", 16, 24);
-       check_buf_append("0123456789", "0123456789",
-                                        "01234567890123456789", 20, 24);
-       check_buf_append(REP16("x"), REP16("o"),
-                                        REP16("x") REP16("o"), 32, 40);
-
-       check_buf_append(test_4096, "", test_4096, 4096, 4104);
-       check_buf_append(test_4096, test_4096, test_8192, 8192, 8200);
-
-       /* check sequences of appends */
-       check_buf_append_abc("a", "b", "c",
-                                                "ab", "abc", "abca", "abcab", "abcabc");
-       check_buf_append_abc("a1", "b2", "c3",
-                                                "a1b2", "a1b2c3", "a1b2c3a1",
-                                                "a1b2c3a1b2", "a1b2c3a1b2c3");
-       check_buf_append_abc("a1/", "b2/", "c3/",
-                                                "a1/b2/", "a1/b2/c3/", "a1/b2/c3/a1/",
-                                                "a1/b2/c3/a1/b2/", "a1/b2/c3/a1/b2/c3/");
-}
-
-/* test swap */
-void test_core_buffer__6(void)
-{
-       git_buf a = GIT_BUF_INIT;
-       git_buf b = GIT_BUF_INIT;
-
-       git_buf_sets(&a, "foo");
-       cl_assert(git_buf_oom(&a) == 0);
-       git_buf_sets(&b, "bar");
-       cl_assert(git_buf_oom(&b) == 0);
-
-       cl_assert_equal_s("foo", git_buf_cstr(&a));
-       cl_assert_equal_s("bar", git_buf_cstr(&b));
-
-       git_buf_swap(&a, &b);
-
-       cl_assert_equal_s("bar", git_buf_cstr(&a));
-       cl_assert_equal_s("foo", git_buf_cstr(&b));
-
-       git_buf_dispose(&a);
-       git_buf_dispose(&b);
-}
-
-
-/* test detach/attach data */
-void test_core_buffer__7(void)
-{
-       const char *fun = "This is fun";
-       git_buf a = GIT_BUF_INIT;
-       char *b = NULL;
-
-       git_buf_sets(&a, "foo");
-       cl_assert(git_buf_oom(&a) == 0);
-       cl_assert_equal_s("foo", git_buf_cstr(&a));
-
-       b = git_buf_detach(&a);
-
-       cl_assert_equal_s("foo", b);
-       cl_assert_equal_s("", a.ptr);
-       git__free(b);
-
-       b = git_buf_detach(&a);
-
-       cl_assert_equal_s(NULL, b);
-       cl_assert_equal_s("", a.ptr);
-
-       git_buf_dispose(&a);
-
-       b = git__strdup(fun);
-       git_buf_attach(&a, b, 0);
-
-       cl_assert_equal_s(fun, a.ptr);
-       cl_assert(a.size == strlen(fun));
-       cl_assert(a.asize == strlen(fun) + 1);
-
-       git_buf_dispose(&a);
-
-       b = git__strdup(fun);
-       git_buf_attach(&a, b, strlen(fun) + 1);
-
-       cl_assert_equal_s(fun, a.ptr);
-       cl_assert(a.size == strlen(fun));
-       cl_assert(a.asize == strlen(fun) + 1);
-
-       git_buf_dispose(&a);
-}
-
-
-static void
-check_joinbuf_2(
-       const char *a,
-       const char *b,
-       const char *expected)
-{
-       char sep = '/';
-       git_buf buf = GIT_BUF_INIT;
-
-       git_buf_join(&buf, sep, a, b);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(expected, git_buf_cstr(&buf));
-       git_buf_dispose(&buf);
-}
-
-static void
-check_joinbuf_overlapped(
-       const char *oldval,
-       int ofs_a,
-       const char *b,
-       const char *expected)
-{
-       char sep = '/';
-       git_buf buf = GIT_BUF_INIT;
-
-       git_buf_sets(&buf, oldval);
-       git_buf_join(&buf, sep, buf.ptr + ofs_a, b);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(expected, git_buf_cstr(&buf));
-       git_buf_dispose(&buf);
-}
-
-static void
-check_joinbuf_n_2(
-       const char *a,
-       const char *b,
-       const char *expected)
-{
-       char sep = '/';
-       git_buf buf = GIT_BUF_INIT;
-
-       git_buf_sets(&buf, a);
-       cl_assert(git_buf_oom(&buf) == 0);
-
-       git_buf_join_n(&buf, sep, 1, b);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(expected, git_buf_cstr(&buf));
-
-       git_buf_dispose(&buf);
-}
-
-static void
-check_joinbuf_n_4(
-       const char *a,
-       const char *b,
-       const char *c,
-       const char *d,
-       const char *expected)
-{
-       char sep = ';';
-       git_buf buf = GIT_BUF_INIT;
-       git_buf_join_n(&buf, sep, 4, a, b, c, d);
-       cl_assert(git_buf_oom(&buf) == 0);
-       cl_assert_equal_s(expected, git_buf_cstr(&buf));
-       git_buf_dispose(&buf);
-}
-
-/* test join */
-void test_core_buffer__8(void)
-{
-       git_buf a = GIT_BUF_INIT;
-
-       git_buf_join_n(&a, '/', 1, "foo");
-       cl_assert(git_buf_oom(&a) == 0);
-       cl_assert_equal_s("foo", git_buf_cstr(&a));
-
-       git_buf_join_n(&a, '/', 1, "bar");
-       cl_assert(git_buf_oom(&a) == 0);
-       cl_assert_equal_s("foo/bar", git_buf_cstr(&a));
-
-       git_buf_join_n(&a, '/', 1, "baz");
-       cl_assert(git_buf_oom(&a) == 0);
-       cl_assert_equal_s("foo/bar/baz", git_buf_cstr(&a));
-
-       git_buf_dispose(&a);
-
-       check_joinbuf_2(NULL, "", "");
-       check_joinbuf_2(NULL, "a", "a");
-       check_joinbuf_2(NULL, "/a", "/a");
-       check_joinbuf_2("", "", "");
-       check_joinbuf_2("", "a", "a");
-       check_joinbuf_2("", "/a", "/a");
-       check_joinbuf_2("a", "", "a/");
-       check_joinbuf_2("a", "/", "a/");
-       check_joinbuf_2("a", "b", "a/b");
-       check_joinbuf_2("/", "a", "/a");
-       check_joinbuf_2("/", "", "/");
-       check_joinbuf_2("/a", "/b", "/a/b");
-       check_joinbuf_2("/a", "/b/", "/a/b/");
-       check_joinbuf_2("/a/", "b/", "/a/b/");
-       check_joinbuf_2("/a/", "/b/", "/a/b/");
-       check_joinbuf_2("/a/", "//b/", "/a/b/");
-       check_joinbuf_2("/abcd", "/defg", "/abcd/defg");
-       check_joinbuf_2("/abcd", "/defg/", "/abcd/defg/");
-       check_joinbuf_2("/abcd/", "defg/", "/abcd/defg/");
-       check_joinbuf_2("/abcd/", "/defg/", "/abcd/defg/");
-
-       check_joinbuf_overlapped("abcd", 0, "efg", "abcd/efg");
-       check_joinbuf_overlapped("abcd", 1, "efg", "bcd/efg");
-       check_joinbuf_overlapped("abcd", 2, "efg", "cd/efg");
-       check_joinbuf_overlapped("abcd", 3, "efg", "d/efg");
-       check_joinbuf_overlapped("abcd", 4, "efg", "efg");
-       check_joinbuf_overlapped("abc/", 2, "efg", "c/efg");
-       check_joinbuf_overlapped("abc/", 3, "efg", "/efg");
-       check_joinbuf_overlapped("abc/", 4, "efg", "efg");
-       check_joinbuf_overlapped("abcd", 3, "", "d/");
-       check_joinbuf_overlapped("abcd", 4, "", "");
-       check_joinbuf_overlapped("abc/", 2, "", "c/");
-       check_joinbuf_overlapped("abc/", 3, "", "/");
-       check_joinbuf_overlapped("abc/", 4, "", "");
-
-       check_joinbuf_n_2("", "", "");
-       check_joinbuf_n_2("", "a", "a");
-       check_joinbuf_n_2("", "/a", "/a");
-       check_joinbuf_n_2("a", "", "a/");
-       check_joinbuf_n_2("a", "/", "a/");
-       check_joinbuf_n_2("a", "b", "a/b");
-       check_joinbuf_n_2("/", "a", "/a");
-       check_joinbuf_n_2("/", "", "/");
-       check_joinbuf_n_2("/a", "/b", "/a/b");
-       check_joinbuf_n_2("/a", "/b/", "/a/b/");
-       check_joinbuf_n_2("/a/", "b/", "/a/b/");
-       check_joinbuf_n_2("/a/", "/b/", "/a/b/");
-       check_joinbuf_n_2("/abcd", "/defg", "/abcd/defg");
-       check_joinbuf_n_2("/abcd", "/defg/", "/abcd/defg/");
-       check_joinbuf_n_2("/abcd/", "defg/", "/abcd/defg/");
-       check_joinbuf_n_2("/abcd/", "/defg/", "/abcd/defg/");
-
-       check_joinbuf_n_4("", "", "", "", "");
-       check_joinbuf_n_4("", "a", "", "", "a;");
-       check_joinbuf_n_4("a", "", "", "", "a;");
-       check_joinbuf_n_4("", "", "", "a", "a");
-       check_joinbuf_n_4("a", "b", "", ";c;d;", "a;b;c;d;");
-       check_joinbuf_n_4("a", "b", "", ";c;d", "a;b;c;d");
-       check_joinbuf_n_4("abcd", "efgh", "ijkl", "mnop", "abcd;efgh;ijkl;mnop");
-       check_joinbuf_n_4("abcd;", "efgh;", "ijkl;", "mnop;", "abcd;efgh;ijkl;mnop;");
-       check_joinbuf_n_4(";abcd;", ";efgh;", ";ijkl;", ";mnop;", ";abcd;efgh;ijkl;mnop;");
-}
-
-void test_core_buffer__9(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       /* just some exhaustive tests of various separator placement */
-       char *a[] = { "", "-", "a-", "-a", "-a-" };
-       char *b[] = { "", "-", "b-", "-b", "-b-" };
-       char sep[] = { 0, '-', '/' };
-       char *expect_null[] = { "",    "-",     "a-",     "-a",     "-a-",
-                                                       "-",   "--",    "a--",    "-a-",    "-a--",
-                                                       "b-",  "-b-",   "a-b-",   "-ab-",   "-a-b-",
-                                                       "-b",  "--b",   "a--b",   "-a-b",   "-a--b",
-                                                       "-b-", "--b-",  "a--b-",  "-a-b-",  "-a--b-" };
-       char *expect_dash[] = { "",    "-",     "a-",     "-a-",    "-a-",
-                                                       "-",   "-",     "a-",     "-a-",    "-a-",
-                                                       "b-",  "-b-",   "a-b-",   "-a-b-",  "-a-b-",
-                                                       "-b",  "-b",    "a-b",    "-a-b",   "-a-b",
-                                                       "-b-", "-b-",   "a-b-",   "-a-b-",  "-a-b-" };
-       char *expect_slas[] = { "",    "-/",    "a-/",    "-a/",    "-a-/",
-                                                       "-",   "-/-",   "a-/-",   "-a/-",   "-a-/-",
-                                                       "b-",  "-/b-",  "a-/b-",  "-a/b-",  "-a-/b-",
-                                                       "-b",  "-/-b",  "a-/-b",  "-a/-b",  "-a-/-b",
-                                                       "-b-", "-/-b-", "a-/-b-", "-a/-b-", "-a-/-b-" };
-       char **expect_values[] = { expect_null, expect_dash, expect_slas };
-       char separator, **expect;
-       unsigned int s, i, j;
-
-       for (s = 0; s < sizeof(sep) / sizeof(char); ++s) {
-               separator = sep[s];
-               expect = expect_values[s];
-
-               for (j = 0; j < sizeof(b) / sizeof(char*); ++j) {
-                       for (i = 0; i < sizeof(a) / sizeof(char*); ++i) {
-                               git_buf_join(&buf, separator, a[i], b[j]);
-                               cl_assert_equal_s(*expect, buf.ptr);
-                               expect++;
-                       }
-               }
-       }
-
-       git_buf_dispose(&buf);
-}
-
-void test_core_buffer__10(void)
-{
-       git_buf a = GIT_BUF_INIT;
-
-       cl_git_pass(git_buf_join_n(&a, '/', 1, "test"));
-       cl_assert_equal_s(a.ptr, "test");
-       cl_git_pass(git_buf_join_n(&a, '/', 1, "string"));
-       cl_assert_equal_s(a.ptr, "test/string");
-       git_buf_clear(&a);
-       cl_git_pass(git_buf_join_n(&a, '/', 3, "test", "string", "join"));
-       cl_assert_equal_s(a.ptr, "test/string/join");
-       cl_git_pass(git_buf_join_n(&a, '/', 2, a.ptr, "more"));
-       cl_assert_equal_s(a.ptr, "test/string/join/test/string/join/more");
-
-       git_buf_dispose(&a);
-}
-
-void test_core_buffer__join3(void)
-{
-       git_buf a = GIT_BUF_INIT;
-
-       cl_git_pass(git_buf_join3(&a, '/', "test", "string", "join"));
-       cl_assert_equal_s("test/string/join", a.ptr);
-       cl_git_pass(git_buf_join3(&a, '/', "test/", "string", "join"));
-       cl_assert_equal_s("test/string/join", a.ptr);
-       cl_git_pass(git_buf_join3(&a, '/', "test/", "/string", "join"));
-       cl_assert_equal_s("test/string/join", a.ptr);
-       cl_git_pass(git_buf_join3(&a, '/', "test/", "/string/", "join"));
-       cl_assert_equal_s("test/string/join", a.ptr);
-       cl_git_pass(git_buf_join3(&a, '/', "test/", "/string/", "/join"));
-       cl_assert_equal_s("test/string/join", a.ptr);
-
-       cl_git_pass(git_buf_join3(&a, '/', "", "string", "join"));
-       cl_assert_equal_s("string/join", a.ptr);
-       cl_git_pass(git_buf_join3(&a, '/', "", "string/", "join"));
-       cl_assert_equal_s("string/join", a.ptr);
-       cl_git_pass(git_buf_join3(&a, '/', "", "string/", "/join"));
-       cl_assert_equal_s("string/join", a.ptr);
-
-       cl_git_pass(git_buf_join3(&a, '/', "string", "", "join"));
-       cl_assert_equal_s("string/join", a.ptr);
-       cl_git_pass(git_buf_join3(&a, '/', "string/", "", "join"));
-       cl_assert_equal_s("string/join", a.ptr);
-       cl_git_pass(git_buf_join3(&a, '/', "string/", "", "/join"));
-       cl_assert_equal_s("string/join", a.ptr);
-
-       git_buf_dispose(&a);
-}
-
-void test_core_buffer__11(void)
-{
-       git_buf a = GIT_BUF_INIT;
-       char *t1[] = { "nothing", "in", "common" };
-       char *t2[] = { "something", "something else", "some other" };
-       char *t3[] = { "something", "some fun", "no fun" };
-       char *t4[] = { "happy", "happier", "happiest" };
-       char *t5[] = { "happiest", "happier", "happy" };
-       char *t6[] = { "no", "nope", "" };
-       char *t7[] = { "", "doesn't matter" };
-
-       cl_git_pass(git_buf_common_prefix(&a, t1, 3));
-       cl_assert_equal_s(a.ptr, "");
-
-       cl_git_pass(git_buf_common_prefix(&a, t2, 3));
-       cl_assert_equal_s(a.ptr, "some");
-
-       cl_git_pass(git_buf_common_prefix(&a, t3, 3));
-       cl_assert_equal_s(a.ptr, "");
-
-       cl_git_pass(git_buf_common_prefix(&a, t4, 3));
-       cl_assert_equal_s(a.ptr, "happ");
-
-       cl_git_pass(git_buf_common_prefix(&a, t5, 3));
-       cl_assert_equal_s(a.ptr, "happ");
-
-       cl_git_pass(git_buf_common_prefix(&a, t6, 3));
-       cl_assert_equal_s(a.ptr, "");
-
-       cl_git_pass(git_buf_common_prefix(&a, t7, 3));
-       cl_assert_equal_s(a.ptr, "");
-
-       git_buf_dispose(&a);
-}
-
-void test_core_buffer__rfind_variants(void)
-{
-       git_buf a = GIT_BUF_INIT;
-       ssize_t len;
-
-       cl_git_pass(git_buf_sets(&a, "/this/is/it/"));
-
-       len = (ssize_t)git_buf_len(&a);
-
-       cl_assert(git_buf_rfind(&a, '/') == len - 1);
-       cl_assert(git_buf_rfind_next(&a, '/') == len - 4);
-
-       cl_assert(git_buf_rfind(&a, 'i') == len - 3);
-       cl_assert(git_buf_rfind_next(&a, 'i') == len - 3);
-
-       cl_assert(git_buf_rfind(&a, 'h') == 2);
-       cl_assert(git_buf_rfind_next(&a, 'h') == 2);
-
-       cl_assert(git_buf_rfind(&a, 'q') == -1);
-       cl_assert(git_buf_rfind_next(&a, 'q') == -1);
-
-       git_buf_dispose(&a);
-}
-
-void test_core_buffer__puts_escaped(void)
-{
-       git_buf a = GIT_BUF_INIT;
-
-       git_buf_clear(&a);
-       cl_git_pass(git_buf_puts_escaped(&a, "this is a test", "", ""));
-       cl_assert_equal_s("this is a test", a.ptr);
-
-       git_buf_clear(&a);
-       cl_git_pass(git_buf_puts_escaped(&a, "this is a test", "t", "\\"));
-       cl_assert_equal_s("\\this is a \\tes\\t", a.ptr);
-
-       git_buf_clear(&a);
-       cl_git_pass(git_buf_puts_escaped(&a, "this is a test", "i ", "__"));
-       cl_assert_equal_s("th__is__ __is__ a__ test", a.ptr);
-
-       git_buf_clear(&a);
-       cl_git_pass(git_buf_puts_escape_regex(&a, "^match\\s*[A-Z]+.*"));
-       cl_assert_equal_s("\\^match\\\\s\\*\\[A-Z\\]\\+\\.\\*", a.ptr);
-
-       git_buf_dispose(&a);
-}
-
-static void assert_unescape(char *expected, char *to_unescape) {
-       git_buf buf = GIT_BUF_INIT;
-
-       cl_git_pass(git_buf_sets(&buf, to_unescape));
-       git_buf_unescape(&buf);
-       cl_assert_equal_s(expected, buf.ptr);
-       cl_assert_equal_sz(strlen(expected), buf.size);
-
-       git_buf_dispose(&buf);
-}
-
-void test_core_buffer__unescape(void)
-{
-       assert_unescape("Escaped\\", "Es\\ca\\ped\\");
-       assert_unescape("Es\\caped\\", "Es\\\\ca\\ped\\\\");
-       assert_unescape("\\", "\\");
-       assert_unescape("\\", "\\\\");
-       assert_unescape("", "");
-}
-
-void test_core_buffer__encode_base64(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       /*     t  h  i  s
-        * 0x 74 68 69 73
-     * 0b 01110100 01101000 01101001 01110011
-        * 0b 011101 000110 100001 101001 011100 110000
-        * 0x 1d 06 21 29 1c 30
-        *     d  G  h  p  c  w
-        */
-       cl_git_pass(git_buf_encode_base64(&buf, "this", 4));
-       cl_assert_equal_s("dGhpcw==", buf.ptr);
-
-       git_buf_clear(&buf);
-       cl_git_pass(git_buf_encode_base64(&buf, "this!", 5));
-       cl_assert_equal_s("dGhpcyE=", buf.ptr);
-
-       git_buf_clear(&buf);
-       cl_git_pass(git_buf_encode_base64(&buf, "this!\n", 6));
-       cl_assert_equal_s("dGhpcyEK", buf.ptr);
-
-       git_buf_dispose(&buf);
-}
-
-void test_core_buffer__decode_base64(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       cl_git_pass(git_buf_decode_base64(&buf, "dGhpcw==", 8));
-       cl_assert_equal_s("this", buf.ptr);
-
-       git_buf_clear(&buf);
-       cl_git_pass(git_buf_decode_base64(&buf, "dGhpcyE=", 8));
-       cl_assert_equal_s("this!", buf.ptr);
-
-       git_buf_clear(&buf);
-       cl_git_pass(git_buf_decode_base64(&buf, "dGhpcyEK", 8));
-       cl_assert_equal_s("this!\n", buf.ptr);
-
-       cl_git_fail(git_buf_decode_base64(&buf, "This is not a valid base64 string!!!", 36));
-       cl_assert_equal_s("this!\n", buf.ptr);
-
-       git_buf_dispose(&buf);
-}
-
-void test_core_buffer__encode_base85(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       cl_git_pass(git_buf_encode_base85(&buf, "this", 4));
-       cl_assert_equal_s("bZBXF", buf.ptr);
-       git_buf_clear(&buf);
-
-       cl_git_pass(git_buf_encode_base85(&buf, "two rnds", 8));
-       cl_assert_equal_s("ba!tca&BaE", buf.ptr);
-       git_buf_clear(&buf);
-
-       cl_git_pass(git_buf_encode_base85(&buf, "this is base 85 encoded",
-               strlen("this is base 85 encoded")));
-       cl_assert_equal_s("bZBXFAZc?TVqtS-AUHK3Wo~0{WMyOk", buf.ptr);
-       git_buf_clear(&buf);
-
-       git_buf_dispose(&buf);
-}
-
-void test_core_buffer__decode_base85(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       cl_git_pass(git_buf_decode_base85(&buf, "bZBXF", 5, 4));
-       cl_assert_equal_sz(4, buf.size);
-       cl_assert_equal_s("this", buf.ptr);
-       git_buf_clear(&buf);
-
-       cl_git_pass(git_buf_decode_base85(&buf, "ba!tca&BaE", 10, 8));
-       cl_assert_equal_sz(8, buf.size);
-       cl_assert_equal_s("two rnds", buf.ptr);
-       git_buf_clear(&buf);
-
-       cl_git_pass(git_buf_decode_base85(&buf, "bZBXFAZc?TVqtS-AUHK3Wo~0{WMyOk", 30, 23));
-       cl_assert_equal_sz(23, buf.size);
-       cl_assert_equal_s("this is base 85 encoded", buf.ptr);
-       git_buf_clear(&buf);
-
-       git_buf_dispose(&buf);
-}
-
-void test_core_buffer__decode_base85_fails_gracefully(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       git_buf_puts(&buf, "foobar");
-
-       cl_git_fail(git_buf_decode_base85(&buf, "invalid charsZZ", 15, 42));
-       cl_git_fail(git_buf_decode_base85(&buf, "invalidchars__ ", 15, 42));
-       cl_git_fail(git_buf_decode_base85(&buf, "overflowZZ~~~~~", 15, 42));
-       cl_git_fail(git_buf_decode_base85(&buf, "truncated", 9, 42));
-       cl_assert_equal_sz(6, buf.size);
-       cl_assert_equal_s("foobar", buf.ptr);
-
-       git_buf_dispose(&buf);
-}
-
-void test_core_buffer__classify_with_utf8(void)
-{
-       char *data0 = "Simple text\n";
-       size_t data0len = 12;
-       char *data1 = "Is that UTF-8 data I see…\nYep!\n";
-       size_t data1len = 31;
-       char *data2 = "Internal NUL!!!\000\n\nI see you!\n";
-       size_t data2len = 29;
-       char *data3 = "\xef\xbb\xbfThis is UTF-8 with a BOM.\n";
-       size_t data3len = 20;
-       git_buf b;
-
-       b.ptr = data0; b.size = b.asize = data0len;
-       cl_assert(!git_buf_is_binary(&b));
-       cl_assert(!git_buf_contains_nul(&b));
-
-       b.ptr = data1; b.size = b.asize = data1len;
-       cl_assert(!git_buf_is_binary(&b));
-       cl_assert(!git_buf_contains_nul(&b));
-
-       b.ptr = data2; b.size = b.asize = data2len;
-       cl_assert(git_buf_is_binary(&b));
-       cl_assert(git_buf_contains_nul(&b));
-
-       b.ptr = data3; b.size = b.asize = data3len;
-       cl_assert(!git_buf_is_binary(&b));
-       cl_assert(!git_buf_contains_nul(&b));
-}
-
-#define SIMILARITY_TEST_DATA_1 \
-       "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \
-       "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \
-       "020\n021\n022\n023\n024\n025\n026\n027\n028\n029\n" \
-       "030\n031\n032\n033\n034\n035\n036\n037\n038\n039\n" \
-       "040\n041\n042\n043\n044\n045\n046\n047\n048\n049\n"
-
-void test_core_buffer__similarity_metric(void)
-{
-       git_hashsig *a, *b;
-       git_buf buf = GIT_BUF_INIT;
-       int sim;
-
-       /* in the first case, we compare data to itself and expect 100% match */
-
-       cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1));
-       cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
-       cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
-
-       cl_assert_equal_i(100, git_hashsig_compare(a, b));
-
-       git_hashsig_free(a);
-       git_hashsig_free(b);
-
-       /* if we change just a single byte, how much does that change magnify? */
-
-       cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1));
-       cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
-       cl_git_pass(git_buf_sets(&buf,
-               "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \
-               "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \
-               "x020x\n021\n022\n023\n024\n025\n026\n027\n028\n029\n" \
-               "030\n031\n032\n033\n034\n035\n036\n037\n038\n039\n" \
-               "040\n041\n042\n043\n044\n045\n046\n047\n048\n049\n"
-               ));
-       cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
-
-       sim = git_hashsig_compare(a, b);
-
-       cl_assert_in_range(95, sim, 100); /* expect >95% similarity */
-
-       git_hashsig_free(a);
-       git_hashsig_free(b);
-
-       /* let's try comparing data to a superset of itself */
-
-       cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1));
-       cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
-       cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1
-               "050\n051\n052\n053\n054\n055\n056\n057\n058\n059\n"));
-       cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
-
-       sim = git_hashsig_compare(a, b);
-       /* 20% lines added ~= 10% lines changed */
-
-       cl_assert_in_range(85, sim, 95); /* expect similarity around 90% */
-
-       git_hashsig_free(a);
-       git_hashsig_free(b);
-
-       /* what if we keep about half the original data and add half new */
-
-       cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1));
-       cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
-       cl_git_pass(git_buf_sets(&buf,
-               "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \
-               "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \
-               "020x\n021\n022\n023\n024\n" \
-               "x25\nx26\nx27\nx28\nx29\n" \
-               "x30\nx31\nx32\nx33\nx34\nx35\nx36\nx37\nx38\nx39\n" \
-               "x40\nx41\nx42\nx43\nx44\nx45\nx46\nx47\nx48\nx49\n"
-               ));
-       cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
-
-       sim = git_hashsig_compare(a, b);
-       /* 50% lines changed */
-
-       cl_assert_in_range(40, sim, 60); /* expect in the 40-60% similarity range */
-
-       git_hashsig_free(a);
-       git_hashsig_free(b);
-
-       /* lastly, let's check that we can hash file content as well */
-
-       cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1));
-       cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
-
-       cl_git_pass(git_futils_mkdir("scratch", 0755, GIT_MKDIR_PATH));
-       cl_git_mkfile("scratch/testdata", SIMILARITY_TEST_DATA_1);
-       cl_git_pass(git_hashsig_create_fromfile(
-               &b, "scratch/testdata", GIT_HASHSIG_NORMAL));
-
-       cl_assert_equal_i(100, git_hashsig_compare(a, b));
-
-       git_hashsig_free(a);
-       git_hashsig_free(b);
-
-       git_buf_dispose(&buf);
-       git_futils_rmdir_r("scratch", NULL, GIT_RMDIR_REMOVE_FILES);
-}
-
-
-void test_core_buffer__similarity_metric_whitespace(void)
-{
-       git_hashsig *a, *b;
-       git_buf buf = GIT_BUF_INIT;
-       int sim, i, j;
-       git_hashsig_option_t opt;
-       const char *tabbed =
-               "       for (s = 0; s < sizeof(sep) / sizeof(char); ++s) {\n"
-               "               separator = sep[s];\n"
-               "               expect = expect_values[s];\n"
-               "\n"
-               "               for (j = 0; j < sizeof(b) / sizeof(char*); ++j) {\n"
-               "                       for (i = 0; i < sizeof(a) / sizeof(char*); ++i) {\n"
-               "                               git_buf_join(&buf, separator, a[i], b[j]);\n"
-               "                               cl_assert_equal_s(*expect, buf.ptr);\n"
-               "                               expect++;\n"
-               "                       }\n"
-               "               }\n"
-               "       }\n";
-       const char *spaced =
-               "   for (s = 0; s < sizeof(sep) / sizeof(char); ++s) {\n"
-               "       separator = sep[s];\n"
-               "       expect = expect_values[s];\n"
-               "\n"
-               "       for (j = 0; j < sizeof(b) / sizeof(char*); ++j) {\n"
-               "           for (i = 0; i < sizeof(a) / sizeof(char*); ++i) {\n"
-               "               git_buf_join(&buf, separator, a[i], b[j]);\n"
-               "               cl_assert_equal_s(*expect, buf.ptr);\n"
-               "               expect++;\n"
-               "           }\n"
-               "       }\n"
-               "   }\n";
-       const char *crlf_spaced2 =
-               "  for (s = 0; s < sizeof(sep) / sizeof(char); ++s) {\r\n"
-               "    separator = sep[s];\r\n"
-               "    expect = expect_values[s];\r\n"
-               "\r\n"
-               "    for (j = 0; j < sizeof(b) / sizeof(char*); ++j) {\r\n"
-               "      for (i = 0; i < sizeof(a) / sizeof(char*); ++i) {\r\n"
-               "        git_buf_join(&buf, separator, a[i], b[j]);\r\n"
-               "        cl_assert_equal_s(*expect, buf.ptr);\r\n"
-               "        expect++;\r\n"
-               "      }\r\n"
-               "    }\r\n"
-               "  }\r\n";
-       const char *text[3] = { tabbed, spaced, crlf_spaced2 };
-
-       /* let's try variations of our own code with whitespace changes */
-
-       for (opt = GIT_HASHSIG_NORMAL; opt <= GIT_HASHSIG_SMART_WHITESPACE; ++opt) {
-               for (i = 0; i < 3; ++i) {
-                       for (j = 0; j < 3; ++j) {
-                               cl_git_pass(git_buf_sets(&buf, text[i]));
-                               cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, opt));
-
-                               cl_git_pass(git_buf_sets(&buf, text[j]));
-                               cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, opt));
-
-                               sim = git_hashsig_compare(a, b);
-
-                               if (opt == GIT_HASHSIG_NORMAL) {
-                                       if (i == j)
-                                               cl_assert_equal_i(100, sim);
-                                       else
-                                               cl_assert_in_range(0, sim, 30); /* pretty different */
-                               } else {
-                                       cl_assert_equal_i(100, sim);
-                               }
-
-                               git_hashsig_free(a);
-                               git_hashsig_free(b);
-                       }
-               }
-       }
-
-       git_buf_dispose(&buf);
-}
-
-#include "../filter/crlf.h"
-
-#define check_buf(expected,buf) do { \
-       cl_assert_equal_s(expected, buf.ptr); \
-       cl_assert_equal_sz(strlen(expected), buf.size); } while (0)
-
-void test_core_buffer__lf_and_crlf_conversions(void)
-{
-       git_buf src = GIT_BUF_INIT, tgt = GIT_BUF_INIT;
-
-       /* LF source */
-
-       git_buf_sets(&src, "lf\nlf\nlf\nlf\n");
-
-       cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
-       check_buf("lf\r\nlf\r\nlf\r\nlf\r\n", tgt);
-
-       cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
-       check_buf(src.ptr, tgt);
-
-       git_buf_sets(&src, "\nlf\nlf\nlf\nlf\nlf");
-
-       cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
-       check_buf("\r\nlf\r\nlf\r\nlf\r\nlf\r\nlf", tgt);
-
-       cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
-       check_buf(src.ptr, tgt);
-
-       /* CRLF source */
-
-       git_buf_sets(&src, "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n");
-
-       cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
-       check_buf("crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n", tgt);
-
-       git_buf_sets(&src, "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n");
-
-       cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
-       check_buf("crlf\ncrlf\ncrlf\ncrlf\n", tgt);
-
-       git_buf_sets(&src, "\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf");
-
-       cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
-       check_buf("\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf", tgt);
-
-       git_buf_sets(&src, "\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf");
-
-       cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
-       check_buf("\ncrlf\ncrlf\ncrlf\ncrlf\ncrlf", tgt);
-
-       /* CRLF in LF text */
-
-       git_buf_sets(&src, "\nlf\nlf\ncrlf\r\nlf\nlf\ncrlf\r\n");
-
-       cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
-       check_buf("\r\nlf\r\nlf\r\ncrlf\r\nlf\r\nlf\r\ncrlf\r\n", tgt);
-
-       git_buf_sets(&src, "\nlf\nlf\ncrlf\r\nlf\nlf\ncrlf\r\n");
-
-       cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
-       check_buf("\nlf\nlf\ncrlf\nlf\nlf\ncrlf\n", tgt);
-
-       /* LF in CRLF text */
-
-       git_buf_sets(&src, "\ncrlf\r\ncrlf\r\nlf\ncrlf\r\ncrlf");
-
-       cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
-       check_buf("\r\ncrlf\r\ncrlf\r\nlf\r\ncrlf\r\ncrlf", tgt);
-
-       cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
-       check_buf("\ncrlf\ncrlf\nlf\ncrlf\ncrlf", tgt);
-
-       /* bare CR test */
-
-       git_buf_sets(&src, "\rcrlf\r\nlf\nlf\ncr\rcrlf\r\nlf\ncr\r");
-
-       cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
-       check_buf("\rcrlf\r\nlf\r\nlf\r\ncr\rcrlf\r\nlf\r\ncr\r", tgt);
-
-       git_buf_sets(&src, "\rcrlf\r\nlf\nlf\ncr\rcrlf\r\nlf\ncr\r");
-
-       cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
-       check_buf("\rcrlf\nlf\nlf\ncr\rcrlf\nlf\ncr\r", tgt);
-
-       git_buf_sets(&src, "\rcr\r");
-       cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
-       check_buf(src.ptr, tgt);
-       cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
-       check_buf("\rcr\r", tgt);
-
-       git_buf_dispose(&src);
-       git_buf_dispose(&tgt);
-
-       /* blob correspondence tests */
-
-       git_buf_sets(&src, ALL_CRLF_TEXT_RAW);
-       cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
-       check_buf(ALL_CRLF_TEXT_AS_CRLF, tgt);
-       git_buf_sets(&src, ALL_CRLF_TEXT_RAW);
-       cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
-       check_buf(ALL_CRLF_TEXT_AS_LF, tgt);
-       git_buf_dispose(&src);
-       git_buf_dispose(&tgt);
-
-       git_buf_sets(&src, ALL_LF_TEXT_RAW);
-       cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
-       check_buf(ALL_LF_TEXT_AS_CRLF, tgt);
-       git_buf_sets(&src, ALL_LF_TEXT_RAW);
-       cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
-       check_buf(ALL_LF_TEXT_AS_LF, tgt);
-       git_buf_dispose(&src);
-       git_buf_dispose(&tgt);
-
-       git_buf_sets(&src, MORE_CRLF_TEXT_RAW);
-       cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
-       check_buf(MORE_CRLF_TEXT_AS_CRLF, tgt);
-       git_buf_sets(&src, MORE_CRLF_TEXT_RAW);
-       cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
-       check_buf(MORE_CRLF_TEXT_AS_LF, tgt);
-       git_buf_dispose(&src);
-       git_buf_dispose(&tgt);
-
-       git_buf_sets(&src, MORE_LF_TEXT_RAW);
-       cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
-       check_buf(MORE_LF_TEXT_AS_CRLF, tgt);
-       git_buf_sets(&src, MORE_LF_TEXT_RAW);
-       cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
-       check_buf(MORE_LF_TEXT_AS_LF, tgt);
-       git_buf_dispose(&src);
-       git_buf_dispose(&tgt);
-}
-
-void test_core_buffer__dont_grow_borrowed(void)
-{
-       const char *somestring = "blah blah";
-       git_buf buf = GIT_BUF_INIT;
-
-       git_buf_attach_notowned(&buf, somestring, strlen(somestring) + 1);
-       cl_assert_equal_p(somestring, buf.ptr);
-       cl_assert_equal_i(0, buf.asize);
-       cl_assert_equal_i(strlen(somestring) + 1, buf.size);
-
-       cl_git_fail_with(GIT_EINVALID, git_buf_grow(&buf, 1024));
-}
-
-void test_core_buffer__dont_hit_infinite_loop_when_resizing(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       cl_git_pass(git_buf_puts(&buf, "foobar"));
-       /*
-        * We do not care whether this succeeds or fails, which
-        * would depend on platform-specific allocation
-        * semantics. We only want to know that the function
-        * actually returns.
-        */
-       (void)git_buf_try_grow(&buf, SIZE_MAX, true);
-
-       git_buf_dispose(&buf);
-}
-
-void test_core_buffer__avoid_printing_into_oom_buffer(void)
-{
-       git_buf buf = GIT_BUF_INIT;
-
-       /* Emulate OOM situation with a previous allocation */
-       buf.asize = 8;
-       buf.ptr = git_buf__oom;
-
-       /*
-        * Print the same string again. As the buffer still has
-        * an `asize` of 8 due to the previous print,
-        * `ENSURE_SIZE` would not try to reallocate the array at
-        * all. As it didn't explicitly check for `git_buf__oom`
-        * in earlier versions, this would've resulted in it
-        * returning successfully and thus `git_buf_puts` would
-        * just print into the `git_buf__oom` array.
-        */
-       cl_git_fail(git_buf_puts(&buf, "foobar"));
-}
index d31274808357857a57e760d1d63a4e4dc2eff56b..6d22b503d46bf485959c912e7448eb9939479351 100644 (file)
@@ -1,6 +1,5 @@
 #include "clar_libgit2.h"
 #include "futils.h"
-#include "path.h"
 #include "posix.h"
 
 void test_core_copy__file(void)
@@ -12,7 +11,7 @@ void test_core_copy__file(void)
 
        cl_git_pass(git_futils_cp("copy_me", "copy_me_two", 0664));
 
-       cl_git_pass(git_path_lstat("copy_me_two", &st));
+       cl_git_pass(git_fs_path_lstat("copy_me_two", &st));
        cl_assert(S_ISREG(st.st_mode));
        cl_assert(strlen(content) == (size_t)st.st_size);
 
@@ -27,7 +26,7 @@ void test_core_copy__file_in_dir(void)
 
        cl_git_pass(git_futils_mkdir("an_dir/in_a_dir", 0775, GIT_MKDIR_PATH));
        cl_git_mkfile("an_dir/in_a_dir/copy_me", content);
-       cl_assert(git_path_isdir("an_dir"));
+       cl_assert(git_fs_path_isdir("an_dir"));
 
        cl_git_pass(git_futils_mkpath2file
                ("an_dir/second_dir/and_more/copy_me_two", 0775));
@@ -37,23 +36,25 @@ void test_core_copy__file_in_dir(void)
                 "an_dir/second_dir/and_more/copy_me_two",
                 0664));
 
-       cl_git_pass(git_path_lstat("an_dir/second_dir/and_more/copy_me_two", &st));
+       cl_git_pass(git_fs_path_lstat("an_dir/second_dir/and_more/copy_me_two", &st));
        cl_assert(S_ISREG(st.st_mode));
        cl_assert(strlen(content) == (size_t)st.st_size);
 
        cl_git_pass(git_futils_rmdir_r("an_dir", NULL, GIT_RMDIR_REMOVE_FILES));
-       cl_assert(!git_path_isdir("an_dir"));
+       cl_assert(!git_fs_path_isdir("an_dir"));
 }
 
-void assert_hard_link(const char *path)
+#ifndef GIT_WIN32
+static void assert_hard_link(const char *path)
 {
        /* we assert this by checking that there's more than one link to the file */
        struct stat st;
 
-       cl_assert(git_path_isfile(path));
+       cl_assert(git_fs_path_isfile(path));
        cl_git_pass(p_stat(path, &st));
        cl_assert(st.st_nlink > 1);
 }
+#endif
 
 void test_core_copy__tree(void)
 {
@@ -74,73 +75,73 @@ void test_core_copy__tree(void)
        cl_assert(p_symlink("../../b/f2", "src/c/d/l1") == 0);
 #endif
 
-       cl_assert(git_path_isdir("src"));
-       cl_assert(git_path_isdir("src/b"));
-       cl_assert(git_path_isdir("src/c/d"));
-       cl_assert(git_path_isfile("src/c/d/f4"));
+       cl_assert(git_fs_path_isdir("src"));
+       cl_assert(git_fs_path_isdir("src/b"));
+       cl_assert(git_fs_path_isdir("src/c/d"));
+       cl_assert(git_fs_path_isfile("src/c/d/f4"));
 
        /* copy with no empty dirs, yes links, no dotfiles, no overwrite */
 
        cl_git_pass(
                git_futils_cp_r("src", "t1", GIT_CPDIR_COPY_SYMLINKS, 0) );
 
-       cl_assert(git_path_isdir("t1"));
-       cl_assert(git_path_isdir("t1/b"));
-       cl_assert(git_path_isdir("t1/c"));
-       cl_assert(git_path_isdir("t1/c/d"));
-       cl_assert(!git_path_isdir("t1/c/e"));
+       cl_assert(git_fs_path_isdir("t1"));
+       cl_assert(git_fs_path_isdir("t1/b"));
+       cl_assert(git_fs_path_isdir("t1/c"));
+       cl_assert(git_fs_path_isdir("t1/c/d"));
+       cl_assert(!git_fs_path_isdir("t1/c/e"));
 
-       cl_assert(git_path_isfile("t1/f1"));
-       cl_assert(git_path_isfile("t1/b/f2"));
-       cl_assert(git_path_isfile("t1/c/f3"));
-       cl_assert(git_path_isfile("t1/c/d/f4"));
-       cl_assert(!git_path_isfile("t1/c/d/.f5"));
+       cl_assert(git_fs_path_isfile("t1/f1"));
+       cl_assert(git_fs_path_isfile("t1/b/f2"));
+       cl_assert(git_fs_path_isfile("t1/c/f3"));
+       cl_assert(git_fs_path_isfile("t1/c/d/f4"));
+       cl_assert(!git_fs_path_isfile("t1/c/d/.f5"));
 
-       cl_git_pass(git_path_lstat("t1/c/f3", &st));
+       cl_git_pass(git_fs_path_lstat("t1/c/f3", &st));
        cl_assert(S_ISREG(st.st_mode));
        cl_assert(strlen(content) == (size_t)st.st_size);
 
 #ifndef GIT_WIN32
-       cl_git_pass(git_path_lstat("t1/c/d/l1", &st));
+       cl_git_pass(git_fs_path_lstat("t1/c/d/l1", &st));
        cl_assert(S_ISLNK(st.st_mode));
 #endif
 
        cl_git_pass(git_futils_rmdir_r("t1", NULL, GIT_RMDIR_REMOVE_FILES));
-       cl_assert(!git_path_isdir("t1"));
+       cl_assert(!git_fs_path_isdir("t1"));
 
        /* copy with empty dirs, no links, yes dotfiles, no overwrite */
 
        cl_git_pass(
                git_futils_cp_r("src", "t2", GIT_CPDIR_CREATE_EMPTY_DIRS | GIT_CPDIR_COPY_DOTFILES, 0) );
 
-       cl_assert(git_path_isdir("t2"));
-       cl_assert(git_path_isdir("t2/b"));
-       cl_assert(git_path_isdir("t2/c"));
-       cl_assert(git_path_isdir("t2/c/d"));
-       cl_assert(git_path_isdir("t2/c/e"));
+       cl_assert(git_fs_path_isdir("t2"));
+       cl_assert(git_fs_path_isdir("t2/b"));
+       cl_assert(git_fs_path_isdir("t2/c"));
+       cl_assert(git_fs_path_isdir("t2/c/d"));
+       cl_assert(git_fs_path_isdir("t2/c/e"));
 
-       cl_assert(git_path_isfile("t2/f1"));
-       cl_assert(git_path_isfile("t2/b/f2"));
-       cl_assert(git_path_isfile("t2/c/f3"));
-       cl_assert(git_path_isfile("t2/c/d/f4"));
-       cl_assert(git_path_isfile("t2/c/d/.f5"));
+       cl_assert(git_fs_path_isfile("t2/f1"));
+       cl_assert(git_fs_path_isfile("t2/b/f2"));
+       cl_assert(git_fs_path_isfile("t2/c/f3"));
+       cl_assert(git_fs_path_isfile("t2/c/d/f4"));
+       cl_assert(git_fs_path_isfile("t2/c/d/.f5"));
 
 #ifndef GIT_WIN32
-       cl_git_fail(git_path_lstat("t2/c/d/l1", &st));
+       cl_git_fail(git_fs_path_lstat("t2/c/d/l1", &st));
 #endif
 
        cl_git_pass(git_futils_rmdir_r("t2", NULL, GIT_RMDIR_REMOVE_FILES));
-       cl_assert(!git_path_isdir("t2"));
+       cl_assert(!git_fs_path_isdir("t2"));
 
 #ifndef GIT_WIN32
        cl_git_pass(git_futils_cp_r("src", "t3", GIT_CPDIR_CREATE_EMPTY_DIRS | GIT_CPDIR_LINK_FILES, 0));
-       cl_assert(git_path_isdir("t3"));
+       cl_assert(git_fs_path_isdir("t3"));
 
-       cl_assert(git_path_isdir("t3"));
-       cl_assert(git_path_isdir("t3/b"));
-       cl_assert(git_path_isdir("t3/c"));
-       cl_assert(git_path_isdir("t3/c/d"));
-       cl_assert(git_path_isdir("t3/c/e"));
+       cl_assert(git_fs_path_isdir("t3"));
+       cl_assert(git_fs_path_isdir("t3/b"));
+       cl_assert(git_fs_path_isdir("t3/c"));
+       cl_assert(git_fs_path_isdir("t3/c/d"));
+       cl_assert(git_fs_path_isdir("t3/c/e"));
 
        assert_hard_link("t3/f1");
        assert_hard_link("t3/b/f2");
index 08e0b11cf16368be6551a7a6f63ac3d4b706cfc4..2419ec7ab92c6c497c53f06373667360265fcfad 100644 (file)
@@ -9,7 +9,7 @@ typedef struct name_data {
 typedef struct walk_data {
        char *sub;              /* sub-directory name */
        name_data *names; /* name state data    */
-       git_buf path;
+       git_str path;
 } walk_data;
 
 
@@ -27,7 +27,7 @@ static void setup(walk_data *d)
        if (strcmp(d->sub, ".") != 0)
                cl_must_pass(p_mkdir(d->sub, 0777));
 
-       cl_git_pass(git_buf_sets(&d->path, d->sub));
+       cl_git_pass(git_str_sets(&d->path, d->sub));
 
        state_loc = d;
 
@@ -55,7 +55,7 @@ static void dirent_cleanup__cb(void *_d)
 
        cl_must_pass(p_rmdir(top_dir));
 
-       git_buf_dispose(&d->path);
+       git_str_dispose(&d->path);
 }
 
 static void check_counts(walk_data *d)
@@ -81,7 +81,7 @@ static int update_count(name_data *data, const char *name)
        return GIT_ERROR;
 }
 
-static int one_entry(void *state, git_buf *path)
+static int one_entry(void *state, git_str *path)
 {
        walk_data *d = (walk_data *) state;
 
@@ -104,7 +104,7 @@ static name_data dot_names[] = {
 static walk_data dot = {
        ".",
        dot_names,
-       GIT_BUF_INIT
+       GIT_STR_INIT
 };
 
 /* make sure that the '.' folder is not traversed */
@@ -113,7 +113,7 @@ void test_core_dirent__dont_traverse_dot(void)
        cl_set_cleanup(&dirent_cleanup__cb, &dot);
        setup(&dot);
 
-       cl_git_pass(git_path_direach(&dot.path, 0, one_entry, &dot));
+       cl_git_pass(git_fs_path_direach(&dot.path, 0, one_entry, &dot));
 
        check_counts(&dot);
 }
@@ -128,7 +128,7 @@ static name_data sub_names[] = {
 static walk_data sub = {
        "sub",
        sub_names,
-       GIT_BUF_INIT
+       GIT_STR_INIT
 };
 
 /* traverse a subfolder */
@@ -137,7 +137,7 @@ void test_core_dirent__traverse_subfolder(void)
        cl_set_cleanup(&dirent_cleanup__cb, &sub);
        setup(&sub);
 
-       cl_git_pass(git_path_direach(&sub.path, 0, one_entry, &sub));
+       cl_git_pass(git_fs_path_direach(&sub.path, 0, one_entry, &sub));
 
        check_counts(&sub);
 }
@@ -146,7 +146,7 @@ void test_core_dirent__traverse_subfolder(void)
 static walk_data sub_slash = {
        "sub/",
        sub_names,
-       GIT_BUF_INIT
+       GIT_STR_INIT
 };
 
 /* traverse a slash-terminated subfolder */
@@ -155,7 +155,7 @@ void test_core_dirent__traverse_slash_terminated_folder(void)
        cl_set_cleanup(&dirent_cleanup__cb, &sub_slash);
        setup(&sub_slash);
 
-       cl_git_pass(git_path_direach(&sub_slash.path, 0, one_entry, &sub_slash));
+       cl_git_pass(git_fs_path_direach(&sub_slash.path, 0, one_entry, &sub_slash));
 
        check_counts(&sub_slash);
 }
@@ -167,7 +167,7 @@ static name_data empty_names[] = {
 static walk_data empty = {
        "empty",
        empty_names,
-       GIT_BUF_INIT
+       GIT_STR_INIT
 };
 
 /* make sure that empty folders are not traversed */
@@ -176,12 +176,12 @@ void test_core_dirent__dont_traverse_empty_folders(void)
        cl_set_cleanup(&dirent_cleanup__cb, &empty);
        setup(&empty);
 
-       cl_git_pass(git_path_direach(&empty.path, 0, one_entry, &empty));
+       cl_git_pass(git_fs_path_direach(&empty.path, 0, one_entry, &empty));
 
        check_counts(&empty);
 
        /* make sure callback not called */
-       cl_assert(git_path_is_empty_dir(empty.path.ptr));
+       cl_assert(git_fs_path_is_empty_dir(empty.path.ptr));
 }
 
 static name_data odd_names[] = {
@@ -195,7 +195,7 @@ static name_data odd_names[] = {
 static walk_data odd = {
        "odd",
        odd_names,
-       GIT_BUF_INIT
+       GIT_STR_INIT
 };
 
 /* make sure that strange looking filenames ('..c') are traversed */
@@ -204,7 +204,7 @@ void test_core_dirent__traverse_weird_filenames(void)
        cl_set_cleanup(&dirent_cleanup__cb, &odd);
        setup(&odd);
 
-       cl_git_pass(git_path_direach(&odd.path, 0, one_entry, &odd));
+       cl_git_pass(git_fs_path_direach(&odd.path, 0, one_entry, &odd));
 
        check_counts(&odd);
 }
@@ -224,30 +224,30 @@ void test_core_dirent__length_limits(void)
 void test_core_dirent__empty_dir(void)
 {
        cl_must_pass(p_mkdir("empty_dir", 0777));
-       cl_assert(git_path_is_empty_dir("empty_dir"));
+       cl_assert(git_fs_path_is_empty_dir("empty_dir"));
 
        cl_git_mkfile("empty_dir/content", "whatever\n");
-       cl_assert(!git_path_is_empty_dir("empty_dir"));
-       cl_assert(!git_path_is_empty_dir("empty_dir/content"));
+       cl_assert(!git_fs_path_is_empty_dir("empty_dir"));
+       cl_assert(!git_fs_path_is_empty_dir("empty_dir/content"));
 
        cl_must_pass(p_unlink("empty_dir/content"));
 
        cl_must_pass(p_mkdir("empty_dir/content", 0777));
-       cl_assert(!git_path_is_empty_dir("empty_dir"));
-       cl_assert(git_path_is_empty_dir("empty_dir/content"));
+       cl_assert(!git_fs_path_is_empty_dir("empty_dir"));
+       cl_assert(git_fs_path_is_empty_dir("empty_dir/content"));
 
        cl_must_pass(p_rmdir("empty_dir/content"));
 
        cl_must_pass(p_rmdir("empty_dir"));
 }
 
-static void handle_next(git_path_diriter *diriter, walk_data *walk)
+static void handle_next(git_fs_path_diriter *diriter, walk_data *walk)
 {
        const char *fullpath, *filename;
        size_t fullpath_len, filename_len;
 
-       cl_git_pass(git_path_diriter_fullpath(&fullpath, &fullpath_len, diriter));
-       cl_git_pass(git_path_diriter_filename(&filename, &filename_len, diriter));
+       cl_git_pass(git_fs_path_diriter_fullpath(&fullpath, &fullpath_len, diriter));
+       cl_git_pass(git_fs_path_diriter_filename(&filename, &filename_len, diriter));
 
        cl_assert_equal_strn(fullpath, "sub/", 4);
        cl_assert_equal_s(fullpath+4, filename);
@@ -258,42 +258,42 @@ static void handle_next(git_path_diriter *diriter, walk_data *walk)
 /* test directory iterator */
 void test_core_dirent__diriter_with_fullname(void)
 {
-       git_path_diriter diriter = GIT_PATH_DIRITER_INIT;
+       git_fs_path_diriter diriter = GIT_FS_PATH_DIRITER_INIT;
        int error;
 
        cl_set_cleanup(&dirent_cleanup__cb, &sub);
        setup(&sub);
 
-       cl_git_pass(git_path_diriter_init(&diriter, sub.path.ptr, 0));
+       cl_git_pass(git_fs_path_diriter_init(&diriter, sub.path.ptr, 0));
 
-       while ((error = git_path_diriter_next(&diriter)) == 0)
+       while ((error = git_fs_path_diriter_next(&diriter)) == 0)
                handle_next(&diriter, &sub);
 
        cl_assert_equal_i(error, GIT_ITEROVER);
 
-       git_path_diriter_free(&diriter);
+       git_fs_path_diriter_free(&diriter);
 
        check_counts(&sub);
 }
 
 void test_core_dirent__diriter_at_directory_root(void)
 {
-       git_path_diriter diriter = GIT_PATH_DIRITER_INIT;
+       git_fs_path_diriter diriter = GIT_FS_PATH_DIRITER_INIT;
        const char *sandbox_path, *path;
        char *root_path;
        size_t path_len;
        int root_offset, error;
 
        sandbox_path = clar_sandbox_path();
-       cl_assert((root_offset = git_path_root(sandbox_path)) >= 0);
+       cl_assert((root_offset = git_fs_path_root(sandbox_path)) >= 0);
 
        cl_assert(root_path = git__calloc(1, root_offset + 2));
        strncpy(root_path, sandbox_path, root_offset + 1);
 
-       cl_git_pass(git_path_diriter_init(&diriter, root_path, 0));
+       cl_git_pass(git_fs_path_diriter_init(&diriter, root_path, 0));
 
-       while ((error = git_path_diriter_next(&diriter)) == 0) {
-               cl_git_pass(git_path_diriter_fullpath(&path, &path_len, &diriter));
+       while ((error = git_fs_path_diriter_next(&diriter)) == 0) {
+               cl_git_pass(git_fs_path_diriter_fullpath(&path, &path_len, &diriter));
 
                cl_assert(path_len > (size_t)(root_offset + 1));
                cl_assert(path[root_offset+1] != '/');
@@ -301,6 +301,6 @@ void test_core_dirent__diriter_at_directory_root(void)
 
        cl_assert_equal_i(error, GIT_ITEROVER);
 
-       git_path_diriter_free(&diriter);
+       git_fs_path_diriter_free(&diriter);
        git__free(root_path);
 }
index 3c34b2c4da495a60f49f7fb6c1ffb2926eac53b7..8ba9b91240a5d3bba0fbf03c425434f8d7f249b7 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "futils.h"
 #include "sysdir.h"
-#include "path.h"
 
 #ifdef GIT_WIN32
 #define NUM_VARS 5
@@ -83,7 +82,7 @@ static void setenv_and_check(const char *name, const char *value)
 
 void test_core_env__0(void)
 {
-       git_buf path = GIT_BUF_INIT, found = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT, found = GIT_STR_INIT;
        char testfile[16], tidx = '0';
        char **val;
        const char *testname = "testfile";
@@ -103,16 +102,16 @@ void test_core_env__0(void)
                        continue;
                }
 
-               cl_git_pass(git_path_prettify(&path, *val, NULL));
+               cl_git_pass(git_fs_path_prettify(&path, *val, NULL));
 
                /* vary testfile name in each directory so accidentally leaving
                 * an environment variable set from a previous iteration won't
                 * accidentally make this test pass...
                 */
                testfile[testlen] = tidx++;
-               cl_git_pass(git_buf_joinpath(&path, path.ptr, testfile));
+               cl_git_pass(git_str_joinpath(&path, path.ptr, testfile));
                cl_git_mkfile(path.ptr, "find me");
-               git_buf_rtruncate_at_char(&path, '/');
+               git_str_rtruncate_at_char(&path, '/');
 
                cl_assert_equal_i(
                        GIT_ENOTFOUND, git_sysdir_find_global_file(&found, testfile));
@@ -137,7 +136,7 @@ void test_core_env__0(void)
                cl_git_pass(git_sysdir_find_global_file(&found, testfile));
 
                {
-                       int root = git_path_root(path.ptr);
+                       int root = git_fs_path_root(path.ptr);
                        char old;
 
                        if (root >= 0) {
@@ -162,14 +161,14 @@ void test_core_env__0(void)
                (void)p_rmdir(*val);
        }
 
-       git_buf_dispose(&path);
-       git_buf_dispose(&found);
+       git_str_dispose(&path);
+       git_str_dispose(&found);
 }
 
 
 void test_core_env__1(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        cl_assert_equal_i(
                GIT_ENOTFOUND, git_sysdir_find_global_file(&path, "nonexistentfile"));
@@ -206,21 +205,21 @@ void test_core_env__1(void)
                GIT_ENOTFOUND, git_sysdir_find_system_file(&path, "nonexistentfile"));
 #endif
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 static void check_global_searchpath(
-       const char *path, int position, const char *file, git_buf *temp)
+       const char *path, int position, const char *file, git_str *temp)
 {
-       git_buf out = GIT_BUF_INIT;
+       git_str out = GIT_STR_INIT;
 
        /* build and set new path */
        if (position < 0)
-               cl_git_pass(git_buf_join(temp, GIT_PATH_LIST_SEPARATOR, path, "$PATH"));
+               cl_git_pass(git_str_join(temp, GIT_PATH_LIST_SEPARATOR, path, "$PATH"));
        else if (position > 0)
-               cl_git_pass(git_buf_join(temp, GIT_PATH_LIST_SEPARATOR, "$PATH", path));
+               cl_git_pass(git_str_join(temp, GIT_PATH_LIST_SEPARATOR, "$PATH", path));
        else
-               cl_git_pass(git_buf_sets(temp, path));
+               cl_git_pass(git_str_sets(temp, path));
 
        cl_git_pass(git_libgit2_opts(
                GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, temp->ptr));
@@ -245,12 +244,12 @@ static void check_global_searchpath(
        cl_assert_equal_i(
                GIT_ENOTFOUND, git_sysdir_find_global_file(temp, file));
 
-       git_buf_dispose(&out);
+       git_str_dispose(&out);
 }
 
 void test_core_env__2(void)
 {
-       git_buf path = GIT_BUF_INIT, found = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT, found = GIT_STR_INIT;
        char testfile[16], tidx = '0';
        char **val;
        const char *testname = "alternate";
@@ -270,15 +269,15 @@ void test_core_env__2(void)
                        continue;
                }
 
-               cl_git_pass(git_path_prettify(&path, *val, NULL));
+               cl_git_pass(git_fs_path_prettify(&path, *val, NULL));
 
                /* vary testfile name so any sloppiness is resetting variables or
                 * deleting files won't accidentally make a test pass.
                 */
                testfile[testlen] = tidx++;
-               cl_git_pass(git_buf_joinpath(&path, path.ptr, testfile));
+               cl_git_pass(git_str_joinpath(&path, path.ptr, testfile));
                cl_git_mkfile(path.ptr, "find me");
-               git_buf_rtruncate_at_char(&path, '/');
+               git_str_rtruncate_at_char(&path, '/');
 
                /* default should be NOTFOUND */
                cl_assert_equal_i(
@@ -290,32 +289,32 @@ void test_core_env__2(void)
                check_global_searchpath(path.ptr,  1, testfile, &found);
 
                /* cleanup */
-               cl_git_pass(git_buf_joinpath(&path, path.ptr, testfile));
+               cl_git_pass(git_str_joinpath(&path, path.ptr, testfile));
                (void)p_unlink(path.ptr);
                (void)p_rmdir(*val);
        }
 
-       git_buf_dispose(&path);
-       git_buf_dispose(&found);
+       git_str_dispose(&path);
+       git_str_dispose(&found);
 }
 
 void test_core_env__substitution(void)
 {
-  git_buf buf = GIT_BUF_INIT, expected = GIT_BUF_INIT;
+  git_str buf = GIT_STR_INIT, expected = GIT_STR_INIT;
 
   /* Set it to something non-default so we have controllable values */
   cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, "/tmp/a"));
   cl_git_pass(git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &buf));
   cl_assert_equal_s("/tmp/a", buf.ptr);
 
-  git_buf_clear(&buf);
-  cl_git_pass(git_buf_join(&buf, GIT_PATH_LIST_SEPARATOR, "$PATH", "/tmp/b"));
+  git_str_clear(&buf);
+  cl_git_pass(git_str_join(&buf, GIT_PATH_LIST_SEPARATOR, "$PATH", "/tmp/b"));
   cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, buf.ptr));
   cl_git_pass(git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &buf));
 
-  cl_git_pass(git_buf_join(&expected, GIT_PATH_LIST_SEPARATOR, "/tmp/a", "/tmp/b"));
+  cl_git_pass(git_str_join(&expected, GIT_PATH_LIST_SEPARATOR, "/tmp/a", "/tmp/b"));
   cl_assert_equal_s(expected.ptr, buf.ptr);
 
-  git_buf_dispose(&expected);
-  git_buf_dispose(&buf);
+  git_str_dispose(&expected);
+  git_str_dispose(&buf);
 }
index e527ce97cac1deb488714a26af0cedd42c4cb98f..6f40c24569fea1b1d98ed1d4148ebdfc423c9e29 100644 (file)
@@ -14,7 +14,7 @@ void test_core_filebuf__0(void)
        cl_must_pass(p_close(fd));
 
        cl_git_fail(git_filebuf_open(&file, test, 0, 0666));
-       cl_assert(git_path_exists(testlock));
+       cl_assert(git_fs_path_exists(testlock));
 
        cl_must_pass(p_unlink(testlock));
 }
@@ -142,14 +142,14 @@ void test_core_filebuf__rename_error(void)
 
        cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));
 
-       cl_assert_equal_i(true, git_path_exists(test_lock));
+       cl_assert_equal_i(true, git_fs_path_exists(test_lock));
 
        cl_git_fail(git_filebuf_commit(&file));
        p_close(fd);
 
        git_filebuf_cleanup(&file);
 
-       cl_assert_equal_i(false, git_path_exists(test_lock));
+       cl_assert_equal_i(false, git_fs_path_exists(test_lock));
 }
 
 void test_core_filebuf__symlink_follow(void)
@@ -157,7 +157,7 @@ void test_core_filebuf__symlink_follow(void)
        git_filebuf file = GIT_FILEBUF_INIT;
        const char *dir = "linkdir", *source = "linkdir/link";
 
-       if (!git_path_supports_symlinks(clar_sandbox_path()))
+       if (!git_fs_path_supports_symlinks(clar_sandbox_path()))
                cl_skip();
 
        cl_git_pass(p_mkdir(dir, 0777));
@@ -166,10 +166,10 @@ void test_core_filebuf__symlink_follow(void)
        cl_git_pass(git_filebuf_open(&file, source, 0, 0666));
        cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));
 
-       cl_assert_equal_i(true, git_path_exists("linkdir/target.lock"));
+       cl_assert_equal_i(true, git_fs_path_exists("linkdir/target.lock"));
 
        cl_git_pass(git_filebuf_commit(&file));
-       cl_assert_equal_i(true, git_path_exists("linkdir/target"));
+       cl_assert_equal_i(true, git_fs_path_exists("linkdir/target"));
 
        git_filebuf_cleanup(&file);
 
@@ -177,10 +177,10 @@ void test_core_filebuf__symlink_follow(void)
        cl_git_pass(git_filebuf_open(&file, source, 0, 0666));
        cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));
 
-       cl_assert_equal_i(true, git_path_exists("linkdir/target.lock"));
+       cl_assert_equal_i(true, git_fs_path_exists("linkdir/target.lock"));
 
        cl_git_pass(git_filebuf_commit(&file));
-       cl_assert_equal_i(true, git_path_exists("linkdir/target"));
+       cl_assert_equal_i(true, git_fs_path_exists("linkdir/target"));
 
        git_filebuf_cleanup(&file);
        cl_git_pass(git_futils_rmdir_r(dir, NULL, GIT_RMDIR_REMOVE_FILES));
@@ -189,27 +189,27 @@ void test_core_filebuf__symlink_follow(void)
 void test_core_filebuf__symlink_follow_absolute_paths(void)
 {
        git_filebuf file = GIT_FILEBUF_INIT;
-       git_buf source = GIT_BUF_INIT, target = GIT_BUF_INIT;
+       git_str source = GIT_STR_INIT, target = GIT_STR_INIT;
 
-       if (!git_path_supports_symlinks(clar_sandbox_path()))
+       if (!git_fs_path_supports_symlinks(clar_sandbox_path()))
                cl_skip();
 
-       cl_git_pass(git_buf_joinpath(&source, clar_sandbox_path(), "linkdir/link"));
-       cl_git_pass(git_buf_joinpath(&target, clar_sandbox_path(), "linkdir/target"));
+       cl_git_pass(git_str_joinpath(&source, clar_sandbox_path(), "linkdir/link"));
+       cl_git_pass(git_str_joinpath(&target, clar_sandbox_path(), "linkdir/target"));
        cl_git_pass(p_mkdir("linkdir", 0777));
        cl_git_pass(p_symlink(target.ptr, source.ptr));
 
        cl_git_pass(git_filebuf_open(&file, source.ptr, 0, 0666));
        cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));
 
-       cl_assert_equal_i(true, git_path_exists("linkdir/target.lock"));
+       cl_assert_equal_i(true, git_fs_path_exists("linkdir/target.lock"));
 
        cl_git_pass(git_filebuf_commit(&file));
-       cl_assert_equal_i(true, git_path_exists("linkdir/target"));
+       cl_assert_equal_i(true, git_fs_path_exists("linkdir/target"));
 
        git_filebuf_cleanup(&file);
-       git_buf_dispose(&source);
-       git_buf_dispose(&target);
+       git_str_dispose(&source);
+       git_str_dispose(&target);
 
        cl_git_pass(git_futils_rmdir_r("linkdir", NULL, GIT_RMDIR_REMOVE_FILES));
 }
@@ -219,7 +219,7 @@ void test_core_filebuf__symlink_depth(void)
        git_filebuf file = GIT_FILEBUF_INIT;
        const char *dir = "linkdir", *source = "linkdir/link";
 
-       if (!git_path_supports_symlinks(clar_sandbox_path()))
+       if (!git_fs_path_supports_symlinks(clar_sandbox_path()))
                cl_skip();
 
        cl_git_pass(p_mkdir(dir, 0777));
index 2c8294c876fc9b9741ed5cd3d1076e7fc9f31960..3501765f62113c352fe795439d591a254fdda3cd 100644 (file)
@@ -14,27 +14,27 @@ void test_core_futils__cleanup(void)
 
 void test_core_futils__writebuffer(void)
 {
-       git_buf out = GIT_BUF_INIT,
-               append = GIT_BUF_INIT;
+       git_str out = GIT_STR_INIT,
+               append = GIT_STR_INIT;
 
        /* create a new file */
-       git_buf_puts(&out, "hello!\n");
-       git_buf_printf(&out, "this is a %s\n", "test");
+       git_str_puts(&out, "hello!\n");
+       git_str_printf(&out, "this is a %s\n", "test");
 
        cl_git_pass(git_futils_writebuffer(&out, "futils/test-file", O_RDWR|O_CREAT, 0666));
 
        cl_assert_equal_file(out.ptr, out.size, "futils/test-file");
 
        /* append some more data */
-       git_buf_puts(&append, "And some more!\n");
-       git_buf_put(&out, append.ptr, append.size);
+       git_str_puts(&append, "And some more!\n");
+       git_str_put(&out, append.ptr, append.size);
 
        cl_git_pass(git_futils_writebuffer(&append, "futils/test-file", O_RDWR|O_APPEND, 0666));
 
        cl_assert_equal_file(out.ptr, out.size, "futils/test-file");
 
-       git_buf_dispose(&out);
-       git_buf_dispose(&append);
+       git_str_dispose(&out);
+       git_str_dispose(&append);
 }
 
 void test_core_futils__write_hidden_file(void)
@@ -42,17 +42,17 @@ void test_core_futils__write_hidden_file(void)
 #ifndef GIT_WIN32
        cl_skip();
 #else
-       git_buf out = GIT_BUF_INIT, append = GIT_BUF_INIT;
+       git_str out = GIT_STR_INIT, append = GIT_STR_INIT;
        bool hidden;
 
-       git_buf_puts(&out, "hidden file.\n");
+       git_str_puts(&out, "hidden file.\n");
        git_futils_writebuffer(&out, "futils/test-file", O_RDWR | O_CREAT, 0666);
 
        cl_git_pass(git_win32__set_hidden("futils/test-file", true));
 
        /* append some more data */
-       git_buf_puts(&append, "And some more!\n");
-       git_buf_put(&out, append.ptr, append.size);
+       git_str_puts(&append, "And some more!\n");
+       git_str_put(&out, append.ptr, append.size);
 
        cl_git_pass(git_futils_writebuffer(&append, "futils/test-file", O_RDWR | O_APPEND, 0666));
 
@@ -61,14 +61,14 @@ void test_core_futils__write_hidden_file(void)
        cl_git_pass(git_win32__hidden(&hidden, "futils/test-file"));
        cl_assert(hidden);
 
-       git_buf_dispose(&out);
-       git_buf_dispose(&append);
+       git_str_dispose(&out);
+       git_str_dispose(&append);
 #endif
 }
 
 void test_core_futils__recursive_rmdir_keeps_symlink_targets(void)
 {
-       if (!git_path_supports_symlinks(clar_sandbox_path()))
+       if (!git_fs_path_supports_symlinks(clar_sandbox_path()))
                cl_skip();
 
        cl_git_pass(git_futils_mkdir_r("a/b", 0777));
@@ -80,10 +80,36 @@ void test_core_futils__recursive_rmdir_keeps_symlink_targets(void)
 
        cl_git_pass(git_futils_rmdir_r("a", NULL, GIT_RMDIR_REMOVE_FILES));
 
-       cl_assert(git_path_exists("dir-target"));
-       cl_assert(git_path_exists("file-target"));
+       cl_assert(git_fs_path_exists("dir-target"));
+       cl_assert(git_fs_path_exists("file-target"));
 
        cl_must_pass(p_unlink("dir-target/file"));
        cl_must_pass(p_rmdir("dir-target"));
        cl_must_pass(p_unlink("file-target"));
 }
+
+void test_core_futils__mktmp_umask(void)
+{
+#ifdef GIT_WIN32
+       cl_skip();
+#else
+       git_str path = GIT_STR_INIT;
+       struct stat st;
+       int fd;
+
+       umask(0);
+       cl_assert((fd = git_futils_mktmp(&path, "foo", 0777)) >= 0);
+       cl_must_pass(p_fstat(fd, &st));
+       cl_assert_equal_i(st.st_mode & 0777, 0777);
+       cl_must_pass(p_unlink(path.ptr));
+       close(fd);
+
+       umask(077);
+       cl_assert((fd = git_futils_mktmp(&path, "foo", 0777)) >= 0);
+       cl_must_pass(p_fstat(fd, &st));
+       cl_assert_equal_i(st.st_mode & 0777, 0700);
+       cl_must_pass(p_unlink(path.ptr));
+       close(fd);
+       git_str_dispose(&path);
+#endif
+}
diff --git a/tests/core/gitstr.c b/tests/core/gitstr.c
new file mode 100644 (file)
index 0000000..0a624e2
--- /dev/null
@@ -0,0 +1,1225 @@
+#include "clar_libgit2.h"
+#include "git2/sys/hashsig.h"
+#include "futils.h"
+
+#define TESTSTR "Have you seen that? Have you seeeen that??"
+const char *test_string = TESTSTR;
+const char *test_string_x2 = TESTSTR TESTSTR;
+
+#define TESTSTR_4096 REP1024("1234")
+#define TESTSTR_8192 REP1024("12341234")
+const char *test_4096 = TESTSTR_4096;
+const char *test_8192 = TESTSTR_8192;
+
+/* test basic data concatenation */
+void test_core_gitstr__0(void)
+{
+       git_str buf = GIT_STR_INIT;
+
+       cl_assert(buf.size == 0);
+
+       git_str_puts(&buf, test_string);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(test_string, git_str_cstr(&buf));
+
+       git_str_puts(&buf, test_string);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(test_string_x2, git_str_cstr(&buf));
+
+       git_str_dispose(&buf);
+}
+
+/* test git_str_printf */
+void test_core_gitstr__1(void)
+{
+       git_str buf = GIT_STR_INIT;
+
+       git_str_printf(&buf, "%s %s %d ", "shoop", "da", 23);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s("shoop da 23 ", git_str_cstr(&buf));
+
+       git_str_printf(&buf, "%s %d", "woop", 42);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s("shoop da 23 woop 42", git_str_cstr(&buf));
+
+       git_str_dispose(&buf);
+}
+
+/* more thorough test of concatenation options */
+void test_core_gitstr__2(void)
+{
+       git_str buf = GIT_STR_INIT;
+       int i;
+       char data[128];
+
+       cl_assert(buf.size == 0);
+
+       /* this must be safe to do */
+       git_str_dispose(&buf);
+       cl_assert(buf.size == 0);
+       cl_assert(buf.asize == 0);
+
+       /* empty buffer should be empty string */
+       cl_assert_equal_s("", git_str_cstr(&buf));
+       cl_assert(buf.size == 0);
+       /* cl_assert(buf.asize == 0); -- should not assume what git_str does */
+
+       /* free should set us back to the beginning */
+       git_str_dispose(&buf);
+       cl_assert(buf.size == 0);
+       cl_assert(buf.asize == 0);
+
+       /* add letter */
+       git_str_putc(&buf, '+');
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s("+", git_str_cstr(&buf));
+
+       /* add letter again */
+       git_str_putc(&buf, '+');
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s("++", git_str_cstr(&buf));
+
+       /* let's try that a few times */
+       for (i = 0; i < 16; ++i) {
+               git_str_putc(&buf, '+');
+               cl_assert(git_str_oom(&buf) == 0);
+       }
+       cl_assert_equal_s("++++++++++++++++++", git_str_cstr(&buf));
+
+       git_str_dispose(&buf);
+
+       /* add data */
+       git_str_put(&buf, "xo", 2);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s("xo", git_str_cstr(&buf));
+
+       /* add letter again */
+       git_str_put(&buf, "xo", 2);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s("xoxo", git_str_cstr(&buf));
+
+       /* let's try that a few times */
+       for (i = 0; i < 16; ++i) {
+               git_str_put(&buf, "xo", 2);
+               cl_assert(git_str_oom(&buf) == 0);
+       }
+       cl_assert_equal_s("xoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxo",
+                                          git_str_cstr(&buf));
+
+       git_str_dispose(&buf);
+
+       /* set to string */
+       git_str_sets(&buf, test_string);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(test_string, git_str_cstr(&buf));
+
+       /* append string */
+       git_str_puts(&buf, test_string);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(test_string_x2, git_str_cstr(&buf));
+
+       /* set to string again (should overwrite - not append) */
+       git_str_sets(&buf, test_string);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(test_string, git_str_cstr(&buf));
+
+       /* test clear */
+       git_str_clear(&buf);
+       cl_assert_equal_s("", git_str_cstr(&buf));
+
+       git_str_dispose(&buf);
+
+       /* test extracting data into buffer */
+       git_str_puts(&buf, REP4("0123456789"));
+       cl_assert(git_str_oom(&buf) == 0);
+
+       git_str_copy_cstr(data, sizeof(data), &buf);
+       cl_assert_equal_s(REP4("0123456789"), data);
+       git_str_copy_cstr(data, 11, &buf);
+       cl_assert_equal_s("0123456789", data);
+       git_str_copy_cstr(data, 3, &buf);
+       cl_assert_equal_s("01", data);
+       git_str_copy_cstr(data, 1, &buf);
+       cl_assert_equal_s("", data);
+
+       git_str_copy_cstr(data, sizeof(data), &buf);
+       cl_assert_equal_s(REP4("0123456789"), data);
+
+       git_str_sets(&buf, REP256("x"));
+       git_str_copy_cstr(data, sizeof(data), &buf);
+       /* since sizeof(data) == 128, only 127 bytes should be copied */
+       cl_assert_equal_s(REP4(REP16("x")) REP16("x") REP16("x")
+                                          REP16("x") "xxxxxxxxxxxxxxx", data);
+
+       git_str_dispose(&buf);
+
+       git_str_copy_cstr(data, sizeof(data), &buf);
+       cl_assert_equal_s("", data);
+}
+
+/* let's do some tests with larger buffers to push our limits */
+void test_core_gitstr__3(void)
+{
+       git_str buf = GIT_STR_INIT;
+
+       /* set to string */
+       git_str_set(&buf, test_4096, 4096);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(test_4096, git_str_cstr(&buf));
+
+       /* append string */
+       git_str_puts(&buf, test_4096);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(test_8192, git_str_cstr(&buf));
+
+       /* set to string again (should overwrite - not append) */
+       git_str_set(&buf, test_4096, 4096);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(test_4096, git_str_cstr(&buf));
+
+       git_str_dispose(&buf);
+}
+
+/* let's try some producer/consumer tests */
+void test_core_gitstr__4(void)
+{
+       git_str buf = GIT_STR_INIT;
+       int i;
+
+       for (i = 0; i < 10; ++i) {
+               git_str_puts(&buf, "1234"); /* add 4 */
+               cl_assert(git_str_oom(&buf) == 0);
+               git_str_consume(&buf, buf.ptr + 2); /* eat the first two */
+               cl_assert(strlen(git_str_cstr(&buf)) == (size_t)((i + 1) * 2));
+       }
+       /* we have appended 1234 10x and removed the first 20 letters */
+       cl_assert_equal_s("12341234123412341234", git_str_cstr(&buf));
+
+       git_str_consume(&buf, NULL);
+       cl_assert_equal_s("12341234123412341234", git_str_cstr(&buf));
+
+       git_str_consume(&buf, "invalid pointer");
+       cl_assert_equal_s("12341234123412341234", git_str_cstr(&buf));
+
+       git_str_consume(&buf, buf.ptr);
+       cl_assert_equal_s("12341234123412341234", git_str_cstr(&buf));
+
+       git_str_consume(&buf, buf.ptr + 1);
+       cl_assert_equal_s("2341234123412341234", git_str_cstr(&buf));
+
+       git_str_consume(&buf, buf.ptr + buf.size);
+       cl_assert_equal_s("", git_str_cstr(&buf));
+
+       git_str_dispose(&buf);
+}
+
+
+static void
+check_buf_append(
+       const char* data_a,
+       const char* data_b,
+       const char* expected_data,
+       size_t expected_size,
+       size_t expected_asize)
+{
+       git_str tgt = GIT_STR_INIT;
+
+       git_str_sets(&tgt, data_a);
+       cl_assert(git_str_oom(&tgt) == 0);
+       git_str_puts(&tgt, data_b);
+       cl_assert(git_str_oom(&tgt) == 0);
+       cl_assert_equal_s(expected_data, git_str_cstr(&tgt));
+       cl_assert_equal_i(tgt.size, expected_size);
+       if (expected_asize > 0)
+               cl_assert_equal_i(tgt.asize, expected_asize);
+
+       git_str_dispose(&tgt);
+}
+
+static void
+check_buf_append_abc(
+       const char* buf_a,
+       const char* buf_b,
+       const char* buf_c,
+       const char* expected_ab,
+       const char* expected_abc,
+       const char* expected_abca,
+       const char* expected_abcab,
+       const char* expected_abcabc)
+{
+       git_str buf = GIT_STR_INIT;
+
+       git_str_sets(&buf, buf_a);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(buf_a, git_str_cstr(&buf));
+
+       git_str_puts(&buf, buf_b);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(expected_ab, git_str_cstr(&buf));
+
+       git_str_puts(&buf, buf_c);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(expected_abc, git_str_cstr(&buf));
+
+       git_str_puts(&buf, buf_a);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(expected_abca, git_str_cstr(&buf));
+
+       git_str_puts(&buf, buf_b);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(expected_abcab, git_str_cstr(&buf));
+
+       git_str_puts(&buf, buf_c);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(expected_abcabc, git_str_cstr(&buf));
+
+       git_str_dispose(&buf);
+}
+
+/* more variations on append tests */
+void test_core_gitstr__5(void)
+{
+       check_buf_append("", "", "", 0, 0);
+       check_buf_append("a", "", "a", 1, 0);
+       check_buf_append("", "a", "a", 1, 8);
+       check_buf_append("", "a", "a", 1, 8);
+       check_buf_append("a", "b", "ab", 2, 8);
+       check_buf_append("", "abcdefgh", "abcdefgh", 8, 16);
+       check_buf_append("abcdefgh", "", "abcdefgh", 8, 16);
+
+       /* buffer with starting asize will grow to:
+        *  1 ->  2,  2 ->  3,  3 ->  5,  4 ->  6,  5 ->  8,  6 ->  9,
+        *  7 -> 11,  8 -> 12,  9 -> 14, 10 -> 15, 11 -> 17, 12 -> 18,
+        * 13 -> 20, 14 -> 21, 15 -> 23, 16 -> 24, 17 -> 26, 18 -> 27,
+        * 19 -> 29, 20 -> 30, 21 -> 32, 22 -> 33, 23 -> 35, 24 -> 36,
+        * ...
+        * follow sequence until value > target size,
+        * then round up to nearest multiple of 8.
+        */
+
+       check_buf_append("abcdefgh", "/", "abcdefgh/", 9, 16);
+       check_buf_append("abcdefgh", "ijklmno", "abcdefghijklmno", 15, 16);
+       check_buf_append("abcdefgh", "ijklmnop", "abcdefghijklmnop", 16, 24);
+       check_buf_append("0123456789", "0123456789",
+                                        "01234567890123456789", 20, 24);
+       check_buf_append(REP16("x"), REP16("o"),
+                                        REP16("x") REP16("o"), 32, 40);
+
+       check_buf_append(test_4096, "", test_4096, 4096, 4104);
+       check_buf_append(test_4096, test_4096, test_8192, 8192, 8200);
+
+       /* check sequences of appends */
+       check_buf_append_abc("a", "b", "c",
+                                                "ab", "abc", "abca", "abcab", "abcabc");
+       check_buf_append_abc("a1", "b2", "c3",
+                                                "a1b2", "a1b2c3", "a1b2c3a1",
+                                                "a1b2c3a1b2", "a1b2c3a1b2c3");
+       check_buf_append_abc("a1/", "b2/", "c3/",
+                                                "a1/b2/", "a1/b2/c3/", "a1/b2/c3/a1/",
+                                                "a1/b2/c3/a1/b2/", "a1/b2/c3/a1/b2/c3/");
+}
+
+/* test swap */
+void test_core_gitstr__6(void)
+{
+       git_str a = GIT_STR_INIT;
+       git_str b = GIT_STR_INIT;
+
+       git_str_sets(&a, "foo");
+       cl_assert(git_str_oom(&a) == 0);
+       git_str_sets(&b, "bar");
+       cl_assert(git_str_oom(&b) == 0);
+
+       cl_assert_equal_s("foo", git_str_cstr(&a));
+       cl_assert_equal_s("bar", git_str_cstr(&b));
+
+       git_str_swap(&a, &b);
+
+       cl_assert_equal_s("bar", git_str_cstr(&a));
+       cl_assert_equal_s("foo", git_str_cstr(&b));
+
+       git_str_dispose(&a);
+       git_str_dispose(&b);
+}
+
+
+/* test detach/attach data */
+void test_core_gitstr__7(void)
+{
+       const char *fun = "This is fun";
+       git_str a = GIT_STR_INIT;
+       char *b = NULL;
+
+       git_str_sets(&a, "foo");
+       cl_assert(git_str_oom(&a) == 0);
+       cl_assert_equal_s("foo", git_str_cstr(&a));
+
+       b = git_str_detach(&a);
+
+       cl_assert_equal_s("foo", b);
+       cl_assert_equal_s("", a.ptr);
+       git__free(b);
+
+       b = git_str_detach(&a);
+
+       cl_assert_equal_s(NULL, b);
+       cl_assert_equal_s("", a.ptr);
+
+       git_str_dispose(&a);
+
+       b = git__strdup(fun);
+       git_str_attach(&a, b, 0);
+
+       cl_assert_equal_s(fun, a.ptr);
+       cl_assert(a.size == strlen(fun));
+       cl_assert(a.asize == strlen(fun) + 1);
+
+       git_str_dispose(&a);
+
+       b = git__strdup(fun);
+       git_str_attach(&a, b, strlen(fun) + 1);
+
+       cl_assert_equal_s(fun, a.ptr);
+       cl_assert(a.size == strlen(fun));
+       cl_assert(a.asize == strlen(fun) + 1);
+
+       git_str_dispose(&a);
+}
+
+
+static void
+check_joinbuf_2(
+       const char *a,
+       const char *b,
+       const char *expected)
+{
+       char sep = '/';
+       git_str buf = GIT_STR_INIT;
+
+       git_str_join(&buf, sep, a, b);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(expected, git_str_cstr(&buf));
+       git_str_dispose(&buf);
+}
+
+static void
+check_joinbuf_overlapped(
+       const char *oldval,
+       int ofs_a,
+       const char *b,
+       const char *expected)
+{
+       char sep = '/';
+       git_str buf = GIT_STR_INIT;
+
+       git_str_sets(&buf, oldval);
+       git_str_join(&buf, sep, buf.ptr + ofs_a, b);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(expected, git_str_cstr(&buf));
+       git_str_dispose(&buf);
+}
+
+static void
+check_joinbuf_n_2(
+       const char *a,
+       const char *b,
+       const char *expected)
+{
+       char sep = '/';
+       git_str buf = GIT_STR_INIT;
+
+       git_str_sets(&buf, a);
+       cl_assert(git_str_oom(&buf) == 0);
+
+       git_str_join_n(&buf, sep, 1, b);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(expected, git_str_cstr(&buf));
+
+       git_str_dispose(&buf);
+}
+
+static void
+check_joinbuf_n_4(
+       const char *a,
+       const char *b,
+       const char *c,
+       const char *d,
+       const char *expected)
+{
+       char sep = ';';
+       git_str buf = GIT_STR_INIT;
+       git_str_join_n(&buf, sep, 4, a, b, c, d);
+       cl_assert(git_str_oom(&buf) == 0);
+       cl_assert_equal_s(expected, git_str_cstr(&buf));
+       git_str_dispose(&buf);
+}
+
+/* test join */
+void test_core_gitstr__8(void)
+{
+       git_str a = GIT_STR_INIT;
+
+       git_str_join_n(&a, '/', 1, "foo");
+       cl_assert(git_str_oom(&a) == 0);
+       cl_assert_equal_s("foo", git_str_cstr(&a));
+
+       git_str_join_n(&a, '/', 1, "bar");
+       cl_assert(git_str_oom(&a) == 0);
+       cl_assert_equal_s("foo/bar", git_str_cstr(&a));
+
+       git_str_join_n(&a, '/', 1, "baz");
+       cl_assert(git_str_oom(&a) == 0);
+       cl_assert_equal_s("foo/bar/baz", git_str_cstr(&a));
+
+       git_str_dispose(&a);
+
+       check_joinbuf_2(NULL, "", "");
+       check_joinbuf_2(NULL, "a", "a");
+       check_joinbuf_2(NULL, "/a", "/a");
+       check_joinbuf_2("", "", "");
+       check_joinbuf_2("", "a", "a");
+       check_joinbuf_2("", "/a", "/a");
+       check_joinbuf_2("a", "", "a/");
+       check_joinbuf_2("a", "/", "a/");
+       check_joinbuf_2("a", "b", "a/b");
+       check_joinbuf_2("/", "a", "/a");
+       check_joinbuf_2("/", "", "/");
+       check_joinbuf_2("/a", "/b", "/a/b");
+       check_joinbuf_2("/a", "/b/", "/a/b/");
+       check_joinbuf_2("/a/", "b/", "/a/b/");
+       check_joinbuf_2("/a/", "/b/", "/a/b/");
+       check_joinbuf_2("/a/", "//b/", "/a/b/");
+       check_joinbuf_2("/abcd", "/defg", "/abcd/defg");
+       check_joinbuf_2("/abcd", "/defg/", "/abcd/defg/");
+       check_joinbuf_2("/abcd/", "defg/", "/abcd/defg/");
+       check_joinbuf_2("/abcd/", "/defg/", "/abcd/defg/");
+
+       check_joinbuf_overlapped("abcd", 0, "efg", "abcd/efg");
+       check_joinbuf_overlapped("abcd", 1, "efg", "bcd/efg");
+       check_joinbuf_overlapped("abcd", 2, "efg", "cd/efg");
+       check_joinbuf_overlapped("abcd", 3, "efg", "d/efg");
+       check_joinbuf_overlapped("abcd", 4, "efg", "efg");
+       check_joinbuf_overlapped("abc/", 2, "efg", "c/efg");
+       check_joinbuf_overlapped("abc/", 3, "efg", "/efg");
+       check_joinbuf_overlapped("abc/", 4, "efg", "efg");
+       check_joinbuf_overlapped("abcd", 3, "", "d/");
+       check_joinbuf_overlapped("abcd", 4, "", "");
+       check_joinbuf_overlapped("abc/", 2, "", "c/");
+       check_joinbuf_overlapped("abc/", 3, "", "/");
+       check_joinbuf_overlapped("abc/", 4, "", "");
+
+       check_joinbuf_n_2("", "", "");
+       check_joinbuf_n_2("", "a", "a");
+       check_joinbuf_n_2("", "/a", "/a");
+       check_joinbuf_n_2("a", "", "a/");
+       check_joinbuf_n_2("a", "/", "a/");
+       check_joinbuf_n_2("a", "b", "a/b");
+       check_joinbuf_n_2("/", "a", "/a");
+       check_joinbuf_n_2("/", "", "/");
+       check_joinbuf_n_2("/a", "/b", "/a/b");
+       check_joinbuf_n_2("/a", "/b/", "/a/b/");
+       check_joinbuf_n_2("/a/", "b/", "/a/b/");
+       check_joinbuf_n_2("/a/", "/b/", "/a/b/");
+       check_joinbuf_n_2("/abcd", "/defg", "/abcd/defg");
+       check_joinbuf_n_2("/abcd", "/defg/", "/abcd/defg/");
+       check_joinbuf_n_2("/abcd/", "defg/", "/abcd/defg/");
+       check_joinbuf_n_2("/abcd/", "/defg/", "/abcd/defg/");
+
+       check_joinbuf_n_4("", "", "", "", "");
+       check_joinbuf_n_4("", "a", "", "", "a;");
+       check_joinbuf_n_4("a", "", "", "", "a;");
+       check_joinbuf_n_4("", "", "", "a", "a");
+       check_joinbuf_n_4("a", "b", "", ";c;d;", "a;b;c;d;");
+       check_joinbuf_n_4("a", "b", "", ";c;d", "a;b;c;d");
+       check_joinbuf_n_4("abcd", "efgh", "ijkl", "mnop", "abcd;efgh;ijkl;mnop");
+       check_joinbuf_n_4("abcd;", "efgh;", "ijkl;", "mnop;", "abcd;efgh;ijkl;mnop;");
+       check_joinbuf_n_4(";abcd;", ";efgh;", ";ijkl;", ";mnop;", ";abcd;efgh;ijkl;mnop;");
+}
+
+void test_core_gitstr__9(void)
+{
+       git_str buf = GIT_STR_INIT;
+
+       /* just some exhaustive tests of various separator placement */
+       char *a[] = { "", "-", "a-", "-a", "-a-" };
+       char *b[] = { "", "-", "b-", "-b", "-b-" };
+       char sep[] = { 0, '-', '/' };
+       char *expect_null[] = { "",    "-",     "a-",     "-a",     "-a-",
+                                                       "-",   "--",    "a--",    "-a-",    "-a--",
+                                                       "b-",  "-b-",   "a-b-",   "-ab-",   "-a-b-",
+                                                       "-b",  "--b",   "a--b",   "-a-b",   "-a--b",
+                                                       "-b-", "--b-",  "a--b-",  "-a-b-",  "-a--b-" };
+       char *expect_dash[] = { "",    "-",     "a-",     "-a-",    "-a-",
+                                                       "-",   "-",     "a-",     "-a-",    "-a-",
+                                                       "b-",  "-b-",   "a-b-",   "-a-b-",  "-a-b-",
+                                                       "-b",  "-b",    "a-b",    "-a-b",   "-a-b",
+                                                       "-b-", "-b-",   "a-b-",   "-a-b-",  "-a-b-" };
+       char *expect_slas[] = { "",    "-/",    "a-/",    "-a/",    "-a-/",
+                                                       "-",   "-/-",   "a-/-",   "-a/-",   "-a-/-",
+                                                       "b-",  "-/b-",  "a-/b-",  "-a/b-",  "-a-/b-",
+                                                       "-b",  "-/-b",  "a-/-b",  "-a/-b",  "-a-/-b",
+                                                       "-b-", "-/-b-", "a-/-b-", "-a/-b-", "-a-/-b-" };
+       char **expect_values[] = { expect_null, expect_dash, expect_slas };
+       char separator, **expect;
+       unsigned int s, i, j;
+
+       for (s = 0; s < sizeof(sep) / sizeof(char); ++s) {
+               separator = sep[s];
+               expect = expect_values[s];
+
+               for (j = 0; j < sizeof(b) / sizeof(char*); ++j) {
+                       for (i = 0; i < sizeof(a) / sizeof(char*); ++i) {
+                               git_str_join(&buf, separator, a[i], b[j]);
+                               cl_assert_equal_s(*expect, buf.ptr);
+                               expect++;
+                       }
+               }
+       }
+
+       git_str_dispose(&buf);
+}
+
+void test_core_gitstr__10(void)
+{
+       git_str a = GIT_STR_INIT;
+
+       cl_git_pass(git_str_join_n(&a, '/', 1, "test"));
+       cl_assert_equal_s(a.ptr, "test");
+       cl_git_pass(git_str_join_n(&a, '/', 1, "string"));
+       cl_assert_equal_s(a.ptr, "test/string");
+       git_str_clear(&a);
+       cl_git_pass(git_str_join_n(&a, '/', 3, "test", "string", "join"));
+       cl_assert_equal_s(a.ptr, "test/string/join");
+       cl_git_pass(git_str_join_n(&a, '/', 2, a.ptr, "more"));
+       cl_assert_equal_s(a.ptr, "test/string/join/test/string/join/more");
+
+       git_str_dispose(&a);
+}
+
+void test_core_gitstr__join3(void)
+{
+       git_str a = GIT_STR_INIT;
+
+       cl_git_pass(git_str_join3(&a, '/', "test", "string", "join"));
+       cl_assert_equal_s("test/string/join", a.ptr);
+       cl_git_pass(git_str_join3(&a, '/', "test/", "string", "join"));
+       cl_assert_equal_s("test/string/join", a.ptr);
+       cl_git_pass(git_str_join3(&a, '/', "test/", "/string", "join"));
+       cl_assert_equal_s("test/string/join", a.ptr);
+       cl_git_pass(git_str_join3(&a, '/', "test/", "/string/", "join"));
+       cl_assert_equal_s("test/string/join", a.ptr);
+       cl_git_pass(git_str_join3(&a, '/', "test/", "/string/", "/join"));
+       cl_assert_equal_s("test/string/join", a.ptr);
+
+       cl_git_pass(git_str_join3(&a, '/', "", "string", "join"));
+       cl_assert_equal_s("string/join", a.ptr);
+       cl_git_pass(git_str_join3(&a, '/', "", "string/", "join"));
+       cl_assert_equal_s("string/join", a.ptr);
+       cl_git_pass(git_str_join3(&a, '/', "", "string/", "/join"));
+       cl_assert_equal_s("string/join", a.ptr);
+
+       cl_git_pass(git_str_join3(&a, '/', "string", "", "join"));
+       cl_assert_equal_s("string/join", a.ptr);
+       cl_git_pass(git_str_join3(&a, '/', "string/", "", "join"));
+       cl_assert_equal_s("string/join", a.ptr);
+       cl_git_pass(git_str_join3(&a, '/', "string/", "", "/join"));
+       cl_assert_equal_s("string/join", a.ptr);
+
+       git_str_dispose(&a);
+}
+
+void test_core_gitstr__11(void)
+{
+       git_str a = GIT_STR_INIT;
+       char *t1[] = { "nothing", "in", "common" };
+       char *t2[] = { "something", "something else", "some other" };
+       char *t3[] = { "something", "some fun", "no fun" };
+       char *t4[] = { "happy", "happier", "happiest" };
+       char *t5[] = { "happiest", "happier", "happy" };
+       char *t6[] = { "no", "nope", "" };
+       char *t7[] = { "", "doesn't matter" };
+
+       cl_git_pass(git_str_common_prefix(&a, t1, 3));
+       cl_assert_equal_s(a.ptr, "");
+
+       cl_git_pass(git_str_common_prefix(&a, t2, 3));
+       cl_assert_equal_s(a.ptr, "some");
+
+       cl_git_pass(git_str_common_prefix(&a, t3, 3));
+       cl_assert_equal_s(a.ptr, "");
+
+       cl_git_pass(git_str_common_prefix(&a, t4, 3));
+       cl_assert_equal_s(a.ptr, "happ");
+
+       cl_git_pass(git_str_common_prefix(&a, t5, 3));
+       cl_assert_equal_s(a.ptr, "happ");
+
+       cl_git_pass(git_str_common_prefix(&a, t6, 3));
+       cl_assert_equal_s(a.ptr, "");
+
+       cl_git_pass(git_str_common_prefix(&a, t7, 3));
+       cl_assert_equal_s(a.ptr, "");
+
+       git_str_dispose(&a);
+}
+
+void test_core_gitstr__rfind_variants(void)
+{
+       git_str a = GIT_STR_INIT;
+       ssize_t len;
+
+       cl_git_pass(git_str_sets(&a, "/this/is/it/"));
+
+       len = (ssize_t)git_str_len(&a);
+
+       cl_assert(git_str_rfind(&a, '/') == len - 1);
+       cl_assert(git_str_rfind_next(&a, '/') == len - 4);
+
+       cl_assert(git_str_rfind(&a, 'i') == len - 3);
+       cl_assert(git_str_rfind_next(&a, 'i') == len - 3);
+
+       cl_assert(git_str_rfind(&a, 'h') == 2);
+       cl_assert(git_str_rfind_next(&a, 'h') == 2);
+
+       cl_assert(git_str_rfind(&a, 'q') == -1);
+       cl_assert(git_str_rfind_next(&a, 'q') == -1);
+
+       git_str_dispose(&a);
+}
+
+void test_core_gitstr__puts_escaped(void)
+{
+       git_str a = GIT_STR_INIT;
+
+       git_str_clear(&a);
+       cl_git_pass(git_str_puts_escaped(&a, "this is a test", "", ""));
+       cl_assert_equal_s("this is a test", a.ptr);
+
+       git_str_clear(&a);
+       cl_git_pass(git_str_puts_escaped(&a, "this is a test", "t", "\\"));
+       cl_assert_equal_s("\\this is a \\tes\\t", a.ptr);
+
+       git_str_clear(&a);
+       cl_git_pass(git_str_puts_escaped(&a, "this is a test", "i ", "__"));
+       cl_assert_equal_s("th__is__ __is__ a__ test", a.ptr);
+
+       git_str_clear(&a);
+       cl_git_pass(git_str_puts_escape_regex(&a, "^match\\s*[A-Z]+.*"));
+       cl_assert_equal_s("\\^match\\\\s\\*\\[A-Z\\]\\+\\.\\*", a.ptr);
+
+       git_str_dispose(&a);
+}
+
+static void assert_unescape(char *expected, char *to_unescape) {
+       git_str buf = GIT_STR_INIT;
+
+       cl_git_pass(git_str_sets(&buf, to_unescape));
+       git_str_unescape(&buf);
+       cl_assert_equal_s(expected, buf.ptr);
+       cl_assert_equal_sz(strlen(expected), buf.size);
+
+       git_str_dispose(&buf);
+}
+
+void test_core_gitstr__unescape(void)
+{
+       assert_unescape("Escaped\\", "Es\\ca\\ped\\");
+       assert_unescape("Es\\caped\\", "Es\\\\ca\\ped\\\\");
+       assert_unescape("\\", "\\");
+       assert_unescape("\\", "\\\\");
+       assert_unescape("", "");
+}
+
+void test_core_gitstr__encode_base64(void)
+{
+       git_str buf = GIT_STR_INIT;
+
+       /*     t  h  i  s
+        * 0x 74 68 69 73
+     * 0b 01110100 01101000 01101001 01110011
+        * 0b 011101 000110 100001 101001 011100 110000
+        * 0x 1d 06 21 29 1c 30
+        *     d  G  h  p  c  w
+        */
+       cl_git_pass(git_str_encode_base64(&buf, "this", 4));
+       cl_assert_equal_s("dGhpcw==", buf.ptr);
+
+       git_str_clear(&buf);
+       cl_git_pass(git_str_encode_base64(&buf, "this!", 5));
+       cl_assert_equal_s("dGhpcyE=", buf.ptr);
+
+       git_str_clear(&buf);
+       cl_git_pass(git_str_encode_base64(&buf, "this!\n", 6));
+       cl_assert_equal_s("dGhpcyEK", buf.ptr);
+
+       git_str_dispose(&buf);
+}
+
+void test_core_gitstr__decode_base64(void)
+{
+       git_str buf = GIT_STR_INIT;
+
+       cl_git_pass(git_str_decode_base64(&buf, "dGhpcw==", 8));
+       cl_assert_equal_s("this", buf.ptr);
+
+       git_str_clear(&buf);
+       cl_git_pass(git_str_decode_base64(&buf, "dGhpcyE=", 8));
+       cl_assert_equal_s("this!", buf.ptr);
+
+       git_str_clear(&buf);
+       cl_git_pass(git_str_decode_base64(&buf, "dGhpcyEK", 8));
+       cl_assert_equal_s("this!\n", buf.ptr);
+
+       cl_git_fail(git_str_decode_base64(&buf, "This is not a valid base64 string!!!", 36));
+       cl_assert_equal_s("this!\n", buf.ptr);
+
+       git_str_dispose(&buf);
+}
+
+void test_core_gitstr__encode_base85(void)
+{
+       git_str buf = GIT_STR_INIT;
+
+       cl_git_pass(git_str_encode_base85(&buf, "this", 4));
+       cl_assert_equal_s("bZBXF", buf.ptr);
+       git_str_clear(&buf);
+
+       cl_git_pass(git_str_encode_base85(&buf, "two rnds", 8));
+       cl_assert_equal_s("ba!tca&BaE", buf.ptr);
+       git_str_clear(&buf);
+
+       cl_git_pass(git_str_encode_base85(&buf, "this is base 85 encoded",
+               strlen("this is base 85 encoded")));
+       cl_assert_equal_s("bZBXFAZc?TVqtS-AUHK3Wo~0{WMyOk", buf.ptr);
+       git_str_clear(&buf);
+
+       git_str_dispose(&buf);
+}
+
+void test_core_gitstr__decode_base85(void)
+{
+       git_str buf = GIT_STR_INIT;
+
+       cl_git_pass(git_str_decode_base85(&buf, "bZBXF", 5, 4));
+       cl_assert_equal_sz(4, buf.size);
+       cl_assert_equal_s("this", buf.ptr);
+       git_str_clear(&buf);
+
+       cl_git_pass(git_str_decode_base85(&buf, "ba!tca&BaE", 10, 8));
+       cl_assert_equal_sz(8, buf.size);
+       cl_assert_equal_s("two rnds", buf.ptr);
+       git_str_clear(&buf);
+
+       cl_git_pass(git_str_decode_base85(&buf, "bZBXFAZc?TVqtS-AUHK3Wo~0{WMyOk", 30, 23));
+       cl_assert_equal_sz(23, buf.size);
+       cl_assert_equal_s("this is base 85 encoded", buf.ptr);
+       git_str_clear(&buf);
+
+       git_str_dispose(&buf);
+}
+
+void test_core_gitstr__decode_base85_fails_gracefully(void)
+{
+       git_str buf = GIT_STR_INIT;
+
+       git_str_puts(&buf, "foobar");
+
+       cl_git_fail(git_str_decode_base85(&buf, "invalid charsZZ", 15, 42));
+       cl_git_fail(git_str_decode_base85(&buf, "invalidchars__ ", 15, 42));
+       cl_git_fail(git_str_decode_base85(&buf, "overflowZZ~~~~~", 15, 42));
+       cl_git_fail(git_str_decode_base85(&buf, "truncated", 9, 42));
+       cl_assert_equal_sz(6, buf.size);
+       cl_assert_equal_s("foobar", buf.ptr);
+
+       git_str_dispose(&buf);
+}
+
+void test_core_gitstr__classify_with_utf8(void)
+{
+       char *data0 = "Simple text\n";
+       size_t data0len = 12;
+       char *data1 = "Is that UTF-8 data I see…\nYep!\n";
+       size_t data1len = 31;
+       char *data2 = "Internal NUL!!!\000\n\nI see you!\n";
+       size_t data2len = 29;
+       char *data3 = "\xef\xbb\xbfThis is UTF-8 with a BOM.\n";
+       size_t data3len = 20;
+       git_str b;
+
+       b.ptr = data0; b.size = b.asize = data0len;
+       cl_assert(!git_str_is_binary(&b));
+       cl_assert(!git_str_contains_nul(&b));
+
+       b.ptr = data1; b.size = b.asize = data1len;
+       cl_assert(!git_str_is_binary(&b));
+       cl_assert(!git_str_contains_nul(&b));
+
+       b.ptr = data2; b.size = b.asize = data2len;
+       cl_assert(git_str_is_binary(&b));
+       cl_assert(git_str_contains_nul(&b));
+
+       b.ptr = data3; b.size = b.asize = data3len;
+       cl_assert(!git_str_is_binary(&b));
+       cl_assert(!git_str_contains_nul(&b));
+}
+
+#define SIMILARITY_TEST_DATA_1 \
+       "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \
+       "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \
+       "020\n021\n022\n023\n024\n025\n026\n027\n028\n029\n" \
+       "030\n031\n032\n033\n034\n035\n036\n037\n038\n039\n" \
+       "040\n041\n042\n043\n044\n045\n046\n047\n048\n049\n"
+
+void test_core_gitstr__similarity_metric(void)
+{
+       git_hashsig *a, *b;
+       git_str buf = GIT_STR_INIT;
+       int sim;
+
+       /* in the first case, we compare data to itself and expect 100% match */
+
+       cl_git_pass(git_str_sets(&buf, SIMILARITY_TEST_DATA_1));
+       cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
+       cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
+
+       cl_assert_equal_i(100, git_hashsig_compare(a, b));
+
+       git_hashsig_free(a);
+       git_hashsig_free(b);
+
+       /* if we change just a single byte, how much does that change magnify? */
+
+       cl_git_pass(git_str_sets(&buf, SIMILARITY_TEST_DATA_1));
+       cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
+       cl_git_pass(git_str_sets(&buf,
+               "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \
+               "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \
+               "x020x\n021\n022\n023\n024\n025\n026\n027\n028\n029\n" \
+               "030\n031\n032\n033\n034\n035\n036\n037\n038\n039\n" \
+               "040\n041\n042\n043\n044\n045\n046\n047\n048\n049\n"
+               ));
+       cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
+
+       sim = git_hashsig_compare(a, b);
+
+       cl_assert_in_range(95, sim, 100); /* expect >95% similarity */
+
+       git_hashsig_free(a);
+       git_hashsig_free(b);
+
+       /* let's try comparing data to a superset of itself */
+
+       cl_git_pass(git_str_sets(&buf, SIMILARITY_TEST_DATA_1));
+       cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
+       cl_git_pass(git_str_sets(&buf, SIMILARITY_TEST_DATA_1
+               "050\n051\n052\n053\n054\n055\n056\n057\n058\n059\n"));
+       cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
+
+       sim = git_hashsig_compare(a, b);
+       /* 20% lines added ~= 10% lines changed */
+
+       cl_assert_in_range(85, sim, 95); /* expect similarity around 90% */
+
+       git_hashsig_free(a);
+       git_hashsig_free(b);
+
+       /* what if we keep about half the original data and add half new */
+
+       cl_git_pass(git_str_sets(&buf, SIMILARITY_TEST_DATA_1));
+       cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
+       cl_git_pass(git_str_sets(&buf,
+               "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \
+               "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \
+               "020x\n021\n022\n023\n024\n" \
+               "x25\nx26\nx27\nx28\nx29\n" \
+               "x30\nx31\nx32\nx33\nx34\nx35\nx36\nx37\nx38\nx39\n" \
+               "x40\nx41\nx42\nx43\nx44\nx45\nx46\nx47\nx48\nx49\n"
+               ));
+       cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
+
+       sim = git_hashsig_compare(a, b);
+       /* 50% lines changed */
+
+       cl_assert_in_range(40, sim, 60); /* expect in the 40-60% similarity range */
+
+       git_hashsig_free(a);
+       git_hashsig_free(b);
+
+       /* lastly, let's check that we can hash file content as well */
+
+       cl_git_pass(git_str_sets(&buf, SIMILARITY_TEST_DATA_1));
+       cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL));
+
+       cl_git_pass(git_futils_mkdir("scratch", 0755, GIT_MKDIR_PATH));
+       cl_git_mkfile("scratch/testdata", SIMILARITY_TEST_DATA_1);
+       cl_git_pass(git_hashsig_create_fromfile(
+               &b, "scratch/testdata", GIT_HASHSIG_NORMAL));
+
+       cl_assert_equal_i(100, git_hashsig_compare(a, b));
+
+       git_hashsig_free(a);
+       git_hashsig_free(b);
+
+       git_str_dispose(&buf);
+       git_futils_rmdir_r("scratch", NULL, GIT_RMDIR_REMOVE_FILES);
+}
+
+
+void test_core_gitstr__similarity_metric_whitespace(void)
+{
+       git_hashsig *a, *b;
+       git_str buf = GIT_STR_INIT;
+       int sim, i, j;
+       git_hashsig_option_t opt;
+       const char *tabbed =
+               "       for (s = 0; s < sizeof(sep) / sizeof(char); ++s) {\n"
+               "               separator = sep[s];\n"
+               "               expect = expect_values[s];\n"
+               "\n"
+               "               for (j = 0; j < sizeof(b) / sizeof(char*); ++j) {\n"
+               "                       for (i = 0; i < sizeof(a) / sizeof(char*); ++i) {\n"
+               "                               git_str_join(&buf, separator, a[i], b[j]);\n"
+               "                               cl_assert_equal_s(*expect, buf.ptr);\n"
+               "                               expect++;\n"
+               "                       }\n"
+               "               }\n"
+               "       }\n";
+       const char *spaced =
+               "   for (s = 0; s < sizeof(sep) / sizeof(char); ++s) {\n"
+               "       separator = sep[s];\n"
+               "       expect = expect_values[s];\n"
+               "\n"
+               "       for (j = 0; j < sizeof(b) / sizeof(char*); ++j) {\n"
+               "           for (i = 0; i < sizeof(a) / sizeof(char*); ++i) {\n"
+               "               git_str_join(&buf, separator, a[i], b[j]);\n"
+               "               cl_assert_equal_s(*expect, buf.ptr);\n"
+               "               expect++;\n"
+               "           }\n"
+               "       }\n"
+               "   }\n";
+       const char *crlf_spaced2 =
+               "  for (s = 0; s < sizeof(sep) / sizeof(char); ++s) {\r\n"
+               "    separator = sep[s];\r\n"
+               "    expect = expect_values[s];\r\n"
+               "\r\n"
+               "    for (j = 0; j < sizeof(b) / sizeof(char*); ++j) {\r\n"
+               "      for (i = 0; i < sizeof(a) / sizeof(char*); ++i) {\r\n"
+               "        git_str_join(&buf, separator, a[i], b[j]);\r\n"
+               "        cl_assert_equal_s(*expect, buf.ptr);\r\n"
+               "        expect++;\r\n"
+               "      }\r\n"
+               "    }\r\n"
+               "  }\r\n";
+       const char *text[3] = { tabbed, spaced, crlf_spaced2 };
+
+       /* let's try variations of our own code with whitespace changes */
+
+       for (opt = GIT_HASHSIG_NORMAL; opt <= GIT_HASHSIG_SMART_WHITESPACE; ++opt) {
+               for (i = 0; i < 3; ++i) {
+                       for (j = 0; j < 3; ++j) {
+                               cl_git_pass(git_str_sets(&buf, text[i]));
+                               cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, opt));
+
+                               cl_git_pass(git_str_sets(&buf, text[j]));
+                               cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, opt));
+
+                               sim = git_hashsig_compare(a, b);
+
+                               if (opt == GIT_HASHSIG_NORMAL) {
+                                       if (i == j)
+                                               cl_assert_equal_i(100, sim);
+                                       else
+                                               cl_assert_in_range(0, sim, 30); /* pretty different */
+                               } else {
+                                       cl_assert_equal_i(100, sim);
+                               }
+
+                               git_hashsig_free(a);
+                               git_hashsig_free(b);
+                       }
+               }
+       }
+
+       git_str_dispose(&buf);
+}
+
+#include "../filter/crlf.h"
+
+#define check_buf(expected,buf) do { \
+       cl_assert_equal_s(expected, buf.ptr); \
+       cl_assert_equal_sz(strlen(expected), buf.size); } while (0)
+
+void test_core_gitstr__lf_and_crlf_conversions(void)
+{
+       git_str src = GIT_STR_INIT, tgt = GIT_STR_INIT;
+
+       /* LF source */
+
+       git_str_sets(&src, "lf\nlf\nlf\nlf\n");
+
+       cl_git_pass(git_str_lf_to_crlf(&tgt, &src));
+       check_buf("lf\r\nlf\r\nlf\r\nlf\r\n", tgt);
+
+       cl_git_pass(git_str_crlf_to_lf(&tgt, &src));
+       check_buf(src.ptr, tgt);
+
+       git_str_sets(&src, "\nlf\nlf\nlf\nlf\nlf");
+
+       cl_git_pass(git_str_lf_to_crlf(&tgt, &src));
+       check_buf("\r\nlf\r\nlf\r\nlf\r\nlf\r\nlf", tgt);
+
+       cl_git_pass(git_str_crlf_to_lf(&tgt, &src));
+       check_buf(src.ptr, tgt);
+
+       /* CRLF source */
+
+       git_str_sets(&src, "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n");
+
+       cl_git_pass(git_str_lf_to_crlf(&tgt, &src));
+       check_buf("crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n", tgt);
+
+       git_str_sets(&src, "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n");
+
+       cl_git_pass(git_str_crlf_to_lf(&tgt, &src));
+       check_buf("crlf\ncrlf\ncrlf\ncrlf\n", tgt);
+
+       git_str_sets(&src, "\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf");
+
+       cl_git_pass(git_str_lf_to_crlf(&tgt, &src));
+       check_buf("\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf", tgt);
+
+       git_str_sets(&src, "\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf");
+
+       cl_git_pass(git_str_crlf_to_lf(&tgt, &src));
+       check_buf("\ncrlf\ncrlf\ncrlf\ncrlf\ncrlf", tgt);
+
+       /* CRLF in LF text */
+
+       git_str_sets(&src, "\nlf\nlf\ncrlf\r\nlf\nlf\ncrlf\r\n");
+
+       cl_git_pass(git_str_lf_to_crlf(&tgt, &src));
+       check_buf("\r\nlf\r\nlf\r\ncrlf\r\nlf\r\nlf\r\ncrlf\r\n", tgt);
+
+       git_str_sets(&src, "\nlf\nlf\ncrlf\r\nlf\nlf\ncrlf\r\n");
+
+       cl_git_pass(git_str_crlf_to_lf(&tgt, &src));
+       check_buf("\nlf\nlf\ncrlf\nlf\nlf\ncrlf\n", tgt);
+
+       /* LF in CRLF text */
+
+       git_str_sets(&src, "\ncrlf\r\ncrlf\r\nlf\ncrlf\r\ncrlf");
+
+       cl_git_pass(git_str_lf_to_crlf(&tgt, &src));
+       check_buf("\r\ncrlf\r\ncrlf\r\nlf\r\ncrlf\r\ncrlf", tgt);
+
+       cl_git_pass(git_str_crlf_to_lf(&tgt, &src));
+       check_buf("\ncrlf\ncrlf\nlf\ncrlf\ncrlf", tgt);
+
+       /* bare CR test */
+
+       git_str_sets(&src, "\rcrlf\r\nlf\nlf\ncr\rcrlf\r\nlf\ncr\r");
+
+       cl_git_pass(git_str_lf_to_crlf(&tgt, &src));
+       check_buf("\rcrlf\r\nlf\r\nlf\r\ncr\rcrlf\r\nlf\r\ncr\r", tgt);
+
+       git_str_sets(&src, "\rcrlf\r\nlf\nlf\ncr\rcrlf\r\nlf\ncr\r");
+
+       cl_git_pass(git_str_crlf_to_lf(&tgt, &src));
+       check_buf("\rcrlf\nlf\nlf\ncr\rcrlf\nlf\ncr\r", tgt);
+
+       git_str_sets(&src, "\rcr\r");
+       cl_git_pass(git_str_lf_to_crlf(&tgt, &src));
+       check_buf(src.ptr, tgt);
+       cl_git_pass(git_str_crlf_to_lf(&tgt, &src));
+       check_buf("\rcr\r", tgt);
+
+       git_str_dispose(&src);
+       git_str_dispose(&tgt);
+
+       /* blob correspondence tests */
+
+       git_str_sets(&src, ALL_CRLF_TEXT_RAW);
+       cl_git_pass(git_str_lf_to_crlf(&tgt, &src));
+       check_buf(ALL_CRLF_TEXT_AS_CRLF, tgt);
+       git_str_sets(&src, ALL_CRLF_TEXT_RAW);
+       cl_git_pass(git_str_crlf_to_lf(&tgt, &src));
+       check_buf(ALL_CRLF_TEXT_AS_LF, tgt);
+       git_str_dispose(&src);
+       git_str_dispose(&tgt);
+
+       git_str_sets(&src, ALL_LF_TEXT_RAW);
+       cl_git_pass(git_str_lf_to_crlf(&tgt, &src));
+       check_buf(ALL_LF_TEXT_AS_CRLF, tgt);
+       git_str_sets(&src, ALL_LF_TEXT_RAW);
+       cl_git_pass(git_str_crlf_to_lf(&tgt, &src));
+       check_buf(ALL_LF_TEXT_AS_LF, tgt);
+       git_str_dispose(&src);
+       git_str_dispose(&tgt);
+
+       git_str_sets(&src, MORE_CRLF_TEXT_RAW);
+       cl_git_pass(git_str_lf_to_crlf(&tgt, &src));
+       check_buf(MORE_CRLF_TEXT_AS_CRLF, tgt);
+       git_str_sets(&src, MORE_CRLF_TEXT_RAW);
+       cl_git_pass(git_str_crlf_to_lf(&tgt, &src));
+       check_buf(MORE_CRLF_TEXT_AS_LF, tgt);
+       git_str_dispose(&src);
+       git_str_dispose(&tgt);
+
+       git_str_sets(&src, MORE_LF_TEXT_RAW);
+       cl_git_pass(git_str_lf_to_crlf(&tgt, &src));
+       check_buf(MORE_LF_TEXT_AS_CRLF, tgt);
+       git_str_sets(&src, MORE_LF_TEXT_RAW);
+       cl_git_pass(git_str_crlf_to_lf(&tgt, &src));
+       check_buf(MORE_LF_TEXT_AS_LF, tgt);
+       git_str_dispose(&src);
+       git_str_dispose(&tgt);
+}
+
+void test_core_gitstr__dont_grow_borrowed(void)
+{
+       const char *somestring = "blah blah";
+       git_str buf = GIT_STR_INIT;
+
+       git_str_attach_notowned(&buf, somestring, strlen(somestring) + 1);
+       cl_assert_equal_p(somestring, buf.ptr);
+       cl_assert_equal_i(0, buf.asize);
+       cl_assert_equal_i(strlen(somestring) + 1, buf.size);
+
+       cl_git_fail_with(GIT_EINVALID, git_str_grow(&buf, 1024));
+}
+
+void test_core_gitstr__dont_hit_infinite_loop_when_resizing(void)
+{
+       git_str buf = GIT_STR_INIT;
+
+       cl_git_pass(git_str_puts(&buf, "foobar"));
+       /*
+        * We do not care whether this succeeds or fails, which
+        * would depend on platform-specific allocation
+        * semantics. We only want to know that the function
+        * actually returns.
+        */
+       (void)git_str_try_grow(&buf, SIZE_MAX, true);
+
+       git_str_dispose(&buf);
+}
+
+void test_core_gitstr__avoid_printing_into_oom_buffer(void)
+{
+       git_str buf = GIT_STR_INIT;
+
+       /* Emulate OOM situation with a previous allocation */
+       buf.asize = 8;
+       buf.ptr = git_str__oom;
+
+       /*
+        * Print the same string again. As the buffer still has
+        * an `asize` of 8 due to the previous print,
+        * `ENSURE_SIZE` would not try to reallocate the array at
+        * all. As it didn't explicitly check for `git_str__oom`
+        * in earlier versions, this would've resulted in it
+        * returning successfully and thus `git_str_puts` would
+        * just print into the `git_str__oom` array.
+        */
+       cl_git_fail(git_str_puts(&buf, "foobar"));
+}
index 498094bdbb8dbaf4183a85650405c420809e23c6..af1b4eabf4828a4b47584ac2aa9dffb428d112cd 100644 (file)
@@ -1,8 +1,8 @@
 #include "clar_libgit2.h"
-#include "path.h"
+#include "fs_path.h"
 
 #ifdef GIT_USE_ICONV
-static git_path_iconv_t ic;
+static git_fs_path_iconv_t ic;
 static char *nfc = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D";
 static char *nfd = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D";
 #endif
@@ -10,14 +10,14 @@ static char *nfd = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D";
 void test_core_iconv__initialize(void)
 {
 #ifdef GIT_USE_ICONV
-       cl_git_pass(git_path_iconv_init_precompose(&ic));
+       cl_git_pass(git_fs_path_iconv_init_precompose(&ic));
 #endif
 }
 
 void test_core_iconv__cleanup(void)
 {
 #ifdef GIT_USE_ICONV
-       git_path_iconv_clear(&ic);
+       git_fs_path_iconv_clear(&ic);
 #endif
 }
 
@@ -27,7 +27,7 @@ void test_core_iconv__unchanged(void)
        const char *data = "Ascii data", *original = data;
        size_t datalen = strlen(data);
 
-       cl_git_pass(git_path_iconv(&ic, &data, &datalen));
+       cl_git_pass(git_fs_path_iconv(&ic, &data, &datalen));
        GIT_UNUSED(datalen);
 
        /* There are no high bits set, so this should leave data untouched */
@@ -42,7 +42,7 @@ void test_core_iconv__decomposed_to_precomposed(void)
        size_t datalen, nfdlen = strlen(nfd);
 
        datalen = nfdlen;
-       cl_git_pass(git_path_iconv(&ic, &data, &datalen));
+       cl_git_pass(git_fs_path_iconv(&ic, &data, &datalen));
        GIT_UNUSED(datalen);
 
        /* The decomposed nfd string should be transformed to the nfc form
@@ -50,13 +50,13 @@ void test_core_iconv__decomposed_to_precomposed(void)
         */
        cl_assert_equal_s(nfc, data);
 
-       /* should be able to do it multiple times with the same git_path_iconv_t */
+       /* should be able to do it multiple times with the same git_fs_path_iconv_t */
        data = nfd; datalen = nfdlen;
-       cl_git_pass(git_path_iconv(&ic, &data, &datalen));
+       cl_git_pass(git_fs_path_iconv(&ic, &data, &datalen));
        cl_assert_equal_s(nfc, data);
 
        data = nfd; datalen = nfdlen;
-       cl_git_pass(git_path_iconv(&ic, &data, &datalen));
+       cl_git_pass(git_fs_path_iconv(&ic, &data, &datalen));
        cl_assert_equal_s(nfc, data);
 #endif
 }
@@ -67,7 +67,7 @@ void test_core_iconv__precomposed_is_unmodified(void)
        const char *data = nfc;
        size_t datalen = strlen(nfc);
 
-       cl_git_pass(git_path_iconv(&ic, &data, &datalen));
+       cl_git_pass(git_fs_path_iconv(&ic, &data, &datalen));
        GIT_UNUSED(datalen);
 
        /* data is already in precomposed form, so even though some bytes have
index a8cbd930b6068b4d817a62d1dd78918e63f39c89..eba77ef522f7f38d84e0754380655f39c4e7115d 100644 (file)
@@ -2,7 +2,7 @@
 
 void test_core_init__returns_count(void)
 {
-       /* libgit2_clar initializes us first, so we have an existing
+       /* libgit2_tests initializes us first, so we have an existing
         * initialization.
         */
        cl_assert_equal_i(2, git_libgit2_init());
index 0493edf1dd7358375f4877f22aa9622c249fcc56..a1e2706b270f5207b7f313ec9445efb406049584 100644 (file)
@@ -1,7 +1,5 @@
 #include "clar_libgit2.h"
 #include "posix.h"
-#include "buffer.h"
-#include "path.h"
 
 #ifdef GIT_WIN32
 # include "win32/reparse.h"
@@ -82,7 +80,7 @@ static void do_junction(const char *old, const char *new)
 {
        GIT_REPARSE_DATA_BUFFER *reparse_buf;
        HANDLE handle;
-       git_buf unparsed_buf = GIT_BUF_INIT;
+       git_str unparsed_buf = GIT_STR_INIT;
        wchar_t *subst_utf16, *print_utf16;
        DWORD ioctl_ret;
        int subst_utf16_len, subst_byte_len, print_utf16_len, print_byte_len, ret;
@@ -93,14 +91,14 @@ static void do_junction(const char *old, const char *new)
         * backslashes instead of forward, and end in a trailing backslash.
         * eg: \??\C:\Foo\
         */
-       git_buf_puts(&unparsed_buf, "\\??\\");
+       git_str_puts(&unparsed_buf, "\\??\\");
 
        for (i = 0; i < strlen(old); i++)
-               git_buf_putc(&unparsed_buf, old[i] == '/' ? '\\' : old[i]);
+               git_str_putc(&unparsed_buf, old[i] == '/' ? '\\' : old[i]);
 
-       git_buf_putc(&unparsed_buf, '\\');
+       git_str_putc(&unparsed_buf, '\\');
 
-       subst_utf16_len = git__utf8_to_16(NULL, 0, git_buf_cstr(&unparsed_buf));
+       subst_utf16_len = git__utf8_to_16(NULL, 0, git_str_cstr(&unparsed_buf));
        subst_byte_len = subst_utf16_len * sizeof(WCHAR);
 
        print_utf16_len = subst_utf16_len - 4;
@@ -127,11 +125,11 @@ static void do_junction(const char *old, const char *new)
        print_utf16 = subst_utf16 + subst_utf16_len + 1;
 
        ret = git__utf8_to_16(subst_utf16, subst_utf16_len + 1,
-               git_buf_cstr(&unparsed_buf));
+               git_str_cstr(&unparsed_buf));
        cl_assert_equal_i(subst_utf16_len, ret);
 
        ret = git__utf8_to_16(print_utf16,
-               print_utf16_len + 1, git_buf_cstr(&unparsed_buf) + 4);
+               print_utf16_len + 1, git_str_cstr(&unparsed_buf) + 4);
        cl_assert_equal_i(print_utf16_len, ret);
 
        reparse_buf->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
@@ -147,7 +145,7 @@ static void do_junction(const char *old, const char *new)
        CloseHandle(handle);
        LocalFree(reparse_buf);
 
-       git_buf_dispose(&unparsed_buf);
+       git_str_dispose(&unparsed_buf);
 }
 
 static void do_custom_reparse(const char *path)
@@ -300,7 +298,7 @@ void test_core_link__stat_dangling_symlink_directory(void)
 
 void test_core_link__lstat_symlink(void)
 {
-       git_buf target_path = GIT_BUF_INIT;
+       git_str target_path = GIT_STR_INIT;
        struct stat st;
 
        if (!should_run())
@@ -309,10 +307,10 @@ void test_core_link__lstat_symlink(void)
        /* Windows always writes the canonical path as the link target, so
         * write the full path on all platforms.
         */
-       git_buf_join(&target_path, '/', clar_sandbox_path(), "lstat_target");
+       git_str_join(&target_path, '/', clar_sandbox_path(), "lstat_target");
 
        cl_git_rewritefile("lstat_target", "This is the target of a symbolic link.\n");
-       do_symlink(git_buf_cstr(&target_path), "lstat_symlink", 0);
+       do_symlink(git_str_cstr(&target_path), "lstat_symlink", 0);
 
        cl_must_pass(p_lstat("lstat_target", &st));
        cl_assert(S_ISREG(st.st_mode));
@@ -320,32 +318,32 @@ void test_core_link__lstat_symlink(void)
 
        cl_must_pass(p_lstat("lstat_symlink", &st));
        cl_assert(S_ISLNK(st.st_mode));
-       cl_assert_equal_i(git_buf_len(&target_path), st.st_size);
+       cl_assert_equal_i(git_str_len(&target_path), st.st_size);
 
-       git_buf_dispose(&target_path);
+       git_str_dispose(&target_path);
 }
 
 void test_core_link__lstat_symlink_directory(void)
 {
-       git_buf target_path = GIT_BUF_INIT;
+       git_str target_path = GIT_STR_INIT;
        struct stat st;
 
        if (!should_run())
                clar__skip();
 
-       git_buf_join(&target_path, '/', clar_sandbox_path(), "lstat_dirtarget");
+       git_str_join(&target_path, '/', clar_sandbox_path(), "lstat_dirtarget");
 
        p_mkdir("lstat_dirtarget", 0777);
-       do_symlink(git_buf_cstr(&target_path), "lstat_dirlink", 1);
+       do_symlink(git_str_cstr(&target_path), "lstat_dirlink", 1);
 
        cl_must_pass(p_lstat("lstat_dirtarget", &st));
        cl_assert(S_ISDIR(st.st_mode));
 
        cl_must_pass(p_lstat("lstat_dirlink", &st));
        cl_assert(S_ISLNK(st.st_mode));
-       cl_assert_equal_i(git_buf_len(&target_path), st.st_size);
+       cl_assert_equal_i(git_str_len(&target_path), st.st_size);
 
-       git_buf_dispose(&target_path);
+       git_str_dispose(&target_path);
 }
 
 void test_core_link__lstat_dangling_symlink(void)
@@ -383,13 +381,13 @@ void test_core_link__lstat_dangling_symlink_directory(void)
 void test_core_link__stat_junction(void)
 {
 #ifdef GIT_WIN32
-       git_buf target_path = GIT_BUF_INIT;
+       git_str target_path = GIT_STR_INIT;
        struct stat st;
 
-       git_buf_join(&target_path, '/', clar_sandbox_path(), "stat_junctarget");
+       git_str_join(&target_path, '/', clar_sandbox_path(), "stat_junctarget");
 
        p_mkdir("stat_junctarget", 0777);
-       do_junction(git_buf_cstr(&target_path), "stat_junction");
+       do_junction(git_str_cstr(&target_path), "stat_junction");
 
        cl_must_pass(p_stat("stat_junctarget", &st));
        cl_assert(S_ISDIR(st.st_mode));
@@ -397,40 +395,40 @@ void test_core_link__stat_junction(void)
        cl_must_pass(p_stat("stat_junction", &st));
        cl_assert(S_ISDIR(st.st_mode));
 
-       git_buf_dispose(&target_path);
+       git_str_dispose(&target_path);
 #endif
 }
 
 void test_core_link__stat_dangling_junction(void)
 {
 #ifdef GIT_WIN32
-       git_buf target_path = GIT_BUF_INIT;
+       git_str target_path = GIT_STR_INIT;
        struct stat st;
 
-       git_buf_join(&target_path, '/', clar_sandbox_path(), "stat_nonexistent_junctarget");
+       git_str_join(&target_path, '/', clar_sandbox_path(), "stat_nonexistent_junctarget");
 
        p_mkdir("stat_nonexistent_junctarget", 0777);
-       do_junction(git_buf_cstr(&target_path), "stat_dangling_junction");
+       do_junction(git_str_cstr(&target_path), "stat_dangling_junction");
 
        RemoveDirectory("stat_nonexistent_junctarget");
 
        cl_must_fail(p_stat("stat_nonexistent_junctarget", &st));
        cl_must_fail(p_stat("stat_dangling_junction", &st));
 
-       git_buf_dispose(&target_path);
+       git_str_dispose(&target_path);
 #endif
 }
 
 void test_core_link__lstat_junction(void)
 {
 #ifdef GIT_WIN32
-       git_buf target_path = GIT_BUF_INIT;
+       git_str target_path = GIT_STR_INIT;
        struct stat st;
 
-       git_buf_join(&target_path, '/', clar_sandbox_path(), "lstat_junctarget");
+       git_str_join(&target_path, '/', clar_sandbox_path(), "lstat_junctarget");
 
        p_mkdir("lstat_junctarget", 0777);
-       do_junction(git_buf_cstr(&target_path), "lstat_junction");
+       do_junction(git_str_cstr(&target_path), "lstat_junction");
 
        cl_must_pass(p_lstat("lstat_junctarget", &st));
        cl_assert(S_ISDIR(st.st_mode));
@@ -438,20 +436,20 @@ void test_core_link__lstat_junction(void)
        cl_must_pass(p_lstat("lstat_junction", &st));
        cl_assert(S_ISLNK(st.st_mode));
 
-       git_buf_dispose(&target_path);
+       git_str_dispose(&target_path);
 #endif
 }
 
 void test_core_link__lstat_dangling_junction(void)
 {
 #ifdef GIT_WIN32
-       git_buf target_path = GIT_BUF_INIT;
+       git_str target_path = GIT_STR_INIT;
        struct stat st;
 
-       git_buf_join(&target_path, '/', clar_sandbox_path(), "lstat_nonexistent_junctarget");
+       git_str_join(&target_path, '/', clar_sandbox_path(), "lstat_nonexistent_junctarget");
 
        p_mkdir("lstat_nonexistent_junctarget", 0777);
-       do_junction(git_buf_cstr(&target_path), "lstat_dangling_junction");
+       do_junction(git_str_cstr(&target_path), "lstat_dangling_junction");
 
        RemoveDirectory("lstat_nonexistent_junctarget");
 
@@ -459,9 +457,9 @@ void test_core_link__lstat_dangling_junction(void)
 
        cl_must_pass(p_lstat("lstat_dangling_junction", &st));
        cl_assert(S_ISLNK(st.st_mode));
-       cl_assert_equal_i(git_buf_len(&target_path), st.st_size);
+       cl_assert_equal_i(git_str_len(&target_path), st.st_size);
 
-       git_buf_dispose(&target_path);
+       git_str_dispose(&target_path);
 #endif
 }
 
@@ -554,79 +552,79 @@ void test_core_link__readlink_normal_file(void)
 
 void test_core_link__readlink_symlink(void)
 {
-       git_buf target_path = GIT_BUF_INIT;
+       git_str target_path = GIT_STR_INIT;
        int len;
        char buf[2048];
 
        if (!should_run())
                clar__skip();
 
-       git_buf_join(&target_path, '/', clar_sandbox_path(), "readlink_target");
+       git_str_join(&target_path, '/', clar_sandbox_path(), "readlink_target");
 
        cl_git_rewritefile("readlink_target", "This is the target of a symlink\n");
-       do_symlink(git_buf_cstr(&target_path), "readlink_link", 0);
+       do_symlink(git_str_cstr(&target_path), "readlink_link", 0);
 
        len = p_readlink("readlink_link", buf, 2048);
        cl_must_pass(len);
 
        buf[len] = 0;
 
-       cl_assert_equal_s(git_buf_cstr(&target_path), buf);
+       cl_assert_equal_s(git_str_cstr(&target_path), buf);
 
-       git_buf_dispose(&target_path);
+       git_str_dispose(&target_path);
 }
 
 void test_core_link__readlink_dangling(void)
 {
-       git_buf target_path = GIT_BUF_INIT;
+       git_str target_path = GIT_STR_INIT;
        int len;
        char buf[2048];
 
        if (!should_run())
                clar__skip();
 
-       git_buf_join(&target_path, '/', clar_sandbox_path(), "readlink_nonexistent");
+       git_str_join(&target_path, '/', clar_sandbox_path(), "readlink_nonexistent");
 
-       do_symlink(git_buf_cstr(&target_path), "readlink_dangling", 0);
+       do_symlink(git_str_cstr(&target_path), "readlink_dangling", 0);
 
        len = p_readlink("readlink_dangling", buf, 2048);
        cl_must_pass(len);
 
        buf[len] = 0;
 
-       cl_assert_equal_s(git_buf_cstr(&target_path), buf);
+       cl_assert_equal_s(git_str_cstr(&target_path), buf);
 
-       git_buf_dispose(&target_path);
+       git_str_dispose(&target_path);
 }
 
 void test_core_link__readlink_multiple(void)
 {
-       git_buf target_path = GIT_BUF_INIT,
-               path3 = GIT_BUF_INIT, path2 = GIT_BUF_INIT, path1 = GIT_BUF_INIT;
+       git_str target_path = GIT_STR_INIT,
+               path3 = GIT_STR_INIT, path2 = GIT_STR_INIT, path1 = GIT_STR_INIT;
        int len;
        char buf[2048];
 
        if (!should_run())
                clar__skip();
 
-       git_buf_join(&target_path, '/', clar_sandbox_path(), "readlink_final");
-       git_buf_join(&path3, '/', clar_sandbox_path(), "readlink_3");
-       git_buf_join(&path2, '/', clar_sandbox_path(), "readlink_2");
-       git_buf_join(&path1, '/', clar_sandbox_path(), "readlink_1");
+       git_str_join(&target_path, '/', clar_sandbox_path(), "readlink_final");
+       git_str_join(&path3, '/', clar_sandbox_path(), "readlink_3");
+       git_str_join(&path2, '/', clar_sandbox_path(), "readlink_2");
+       git_str_join(&path1, '/', clar_sandbox_path(), "readlink_1");
 
-       do_symlink(git_buf_cstr(&target_path), git_buf_cstr(&path3), 0);
-       do_symlink(git_buf_cstr(&path3), git_buf_cstr(&path2), 0);
-       do_symlink(git_buf_cstr(&path2), git_buf_cstr(&path1), 0);
+       do_symlink(git_str_cstr(&target_path), git_str_cstr(&path3), 0);
+       do_symlink(git_str_cstr(&path3), git_str_cstr(&path2), 0);
+       do_symlink(git_str_cstr(&path2), git_str_cstr(&path1), 0);
 
        len = p_readlink("readlink_1", buf, 2048);
        cl_must_pass(len);
 
        buf[len] = 0;
 
-       cl_assert_equal_s(git_buf_cstr(&path2), buf);
+       cl_assert_equal_s(git_str_cstr(&path2), buf);
 
-       git_buf_dispose(&path1);
-       git_buf_dispose(&path2);
-       git_buf_dispose(&path3);
-       git_buf_dispose(&target_path);
+       git_str_dispose(&path1);
+       git_str_dispose(&path2);
+       git_str_dispose(&path3);
+       git_str_dispose(&target_path);
 }
index 3f04c2ad37134ff13aad22da9f801a8db10f7ab5..58a4cfcdb8124820f4f520aa94c0b832f0b87ba1 100644 (file)
@@ -1,6 +1,5 @@
 #include "clar_libgit2.h"
 #include "futils.h"
-#include "path.h"
 #include "posix.h"
 
 static void cleanup_basic_dirs(void *ref)
@@ -15,41 +14,41 @@ static void cleanup_basic_dirs(void *ref)
 
 void test_core_mkdir__absolute(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        cl_set_cleanup(cleanup_basic_dirs, NULL);
 
-       git_buf_joinpath(&path, clar_sandbox_path(), "d0");
+       git_str_joinpath(&path, clar_sandbox_path(), "d0");
 
        /* make a directory */
-       cl_assert(!git_path_isdir(path.ptr));
+       cl_assert(!git_fs_path_isdir(path.ptr));
        cl_git_pass(git_futils_mkdir(path.ptr, 0755, 0));
-       cl_assert(git_path_isdir(path.ptr));
+       cl_assert(git_fs_path_isdir(path.ptr));
 
-       git_buf_joinpath(&path, path.ptr, "subdir");
-       cl_assert(!git_path_isdir(path.ptr));
+       git_str_joinpath(&path, path.ptr, "subdir");
+       cl_assert(!git_fs_path_isdir(path.ptr));
        cl_git_pass(git_futils_mkdir(path.ptr, 0755, 0));
-       cl_assert(git_path_isdir(path.ptr));
+       cl_assert(git_fs_path_isdir(path.ptr));
 
        /* ensure mkdir_r works for a single subdir */
-       git_buf_joinpath(&path, path.ptr, "another");
-       cl_assert(!git_path_isdir(path.ptr));
+       git_str_joinpath(&path, path.ptr, "another");
+       cl_assert(!git_fs_path_isdir(path.ptr));
        cl_git_pass(git_futils_mkdir_r(path.ptr, 0755));
-       cl_assert(git_path_isdir(path.ptr));
+       cl_assert(git_fs_path_isdir(path.ptr));
 
        /* ensure mkdir_r works */
-       git_buf_joinpath(&path, clar_sandbox_path(), "d1/foo/bar/asdf");
-       cl_assert(!git_path_isdir(path.ptr));
+       git_str_joinpath(&path, clar_sandbox_path(), "d1/foo/bar/asdf");
+       cl_assert(!git_fs_path_isdir(path.ptr));
        cl_git_pass(git_futils_mkdir_r(path.ptr, 0755));
-       cl_assert(git_path_isdir(path.ptr));
+       cl_assert(git_fs_path_isdir(path.ptr));
 
        /* ensure we don't imply recursive */
-       git_buf_joinpath(&path, clar_sandbox_path(), "d2/foo/bar/asdf");
-       cl_assert(!git_path_isdir(path.ptr));
+       git_str_joinpath(&path, clar_sandbox_path(), "d2/foo/bar/asdf");
+       cl_assert(!git_fs_path_isdir(path.ptr));
        cl_git_fail(git_futils_mkdir(path.ptr, 0755, 0));
-       cl_assert(!git_path_isdir(path.ptr));
+       cl_assert(!git_fs_path_isdir(path.ptr));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_core_mkdir__basic(void)
@@ -57,39 +56,39 @@ void test_core_mkdir__basic(void)
        cl_set_cleanup(cleanup_basic_dirs, NULL);
 
        /* make a directory */
-       cl_assert(!git_path_isdir("d0"));
+       cl_assert(!git_fs_path_isdir("d0"));
        cl_git_pass(git_futils_mkdir("d0", 0755, 0));
-       cl_assert(git_path_isdir("d0"));
+       cl_assert(git_fs_path_isdir("d0"));
 
        /* make a path */
-       cl_assert(!git_path_isdir("d1"));
+       cl_assert(!git_fs_path_isdir("d1"));
        cl_git_pass(git_futils_mkdir("d1/d1.1/d1.2", 0755, GIT_MKDIR_PATH));
-       cl_assert(git_path_isdir("d1"));
-       cl_assert(git_path_isdir("d1/d1.1"));
-       cl_assert(git_path_isdir("d1/d1.1/d1.2"));
+       cl_assert(git_fs_path_isdir("d1"));
+       cl_assert(git_fs_path_isdir("d1/d1.1"));
+       cl_assert(git_fs_path_isdir("d1/d1.1/d1.2"));
 
        /* make a dir exclusively */
-       cl_assert(!git_path_isdir("d2"));
+       cl_assert(!git_fs_path_isdir("d2"));
        cl_git_pass(git_futils_mkdir("d2", 0755, GIT_MKDIR_EXCL));
-       cl_assert(git_path_isdir("d2"));
+       cl_assert(git_fs_path_isdir("d2"));
 
        /* make exclusive failure */
        cl_git_fail(git_futils_mkdir("d2", 0755, GIT_MKDIR_EXCL));
 
        /* make a path exclusively */
-       cl_assert(!git_path_isdir("d3"));
+       cl_assert(!git_fs_path_isdir("d3"));
        cl_git_pass(git_futils_mkdir("d3/d3.1/d3.2", 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL));
-       cl_assert(git_path_isdir("d3"));
-       cl_assert(git_path_isdir("d3/d3.1/d3.2"));
+       cl_assert(git_fs_path_isdir("d3"));
+       cl_assert(git_fs_path_isdir("d3/d3.1/d3.2"));
 
        /* make exclusive path failure */
        cl_git_fail(git_futils_mkdir("d3/d3.1/d3.2", 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL));
        /* ??? Should EXCL only apply to the last item in the path? */
 
        /* path with trailing slash? */
-       cl_assert(!git_path_isdir("d4"));
+       cl_assert(!git_fs_path_isdir("d4"));
        cl_git_pass(git_futils_mkdir("d4/d4.1/", 0755, GIT_MKDIR_PATH));
-       cl_assert(git_path_isdir("d4/d4.1"));
+       cl_assert(git_fs_path_isdir("d4/d4.1"));
 }
 
 static void cleanup_basedir(void *ref)
@@ -107,10 +106,10 @@ void test_core_mkdir__with_base(void)
        cl_git_pass(git_futils_mkdir(BASEDIR, 0755, GIT_MKDIR_PATH));
 
        cl_git_pass(git_futils_mkdir_relative("a", BASEDIR, 0755, 0, NULL));
-       cl_assert(git_path_isdir(BASEDIR "/a"));
+       cl_assert(git_fs_path_isdir(BASEDIR "/a"));
 
        cl_git_pass(git_futils_mkdir_relative("b/b1/b2", BASEDIR, 0755, GIT_MKDIR_PATH, NULL));
-       cl_assert(git_path_isdir(BASEDIR "/b/b1/b2"));
+       cl_assert(git_fs_path_isdir(BASEDIR "/b/b1/b2"));
 
        /* exclusive with existing base */
        cl_git_pass(git_futils_mkdir_relative("c/c1/c2", BASEDIR, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL, NULL));
@@ -126,7 +125,7 @@ void test_core_mkdir__with_base(void)
 
        /* path with shorter base and existing dirs */
        cl_git_pass(git_futils_mkdir_relative("dir/here/d/", "base", 0755, GIT_MKDIR_PATH, NULL));
-       cl_assert(git_path_isdir("base/dir/here/d"));
+       cl_assert(git_fs_path_isdir("base/dir/here/d"));
 
        /* fail: path with shorter base and existing dirs */
        cl_git_fail(git_futils_mkdir_relative("dir/here/e/", "base", 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL, NULL));
@@ -179,85 +178,85 @@ void test_core_mkdir__chmods(void)
 
        cl_git_pass(git_futils_mkdir_relative("mode/is/important", "r", 0777, GIT_MKDIR_PATH, NULL));
 
-       cl_git_pass(git_path_lstat("r/mode", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode", &st));
        check_mode(0755, st.st_mode);
-       cl_git_pass(git_path_lstat("r/mode/is", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode/is", &st));
        check_mode(0755, st.st_mode);
-       cl_git_pass(git_path_lstat("r/mode/is/important", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode/is/important", &st));
        check_mode(0755, st.st_mode);
 
        cl_git_pass(git_futils_mkdir_relative("mode2/is2/important2", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD, NULL));
 
-       cl_git_pass(git_path_lstat("r/mode2", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode2", &st));
        check_mode(0755, st.st_mode);
-       cl_git_pass(git_path_lstat("r/mode2/is2", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode2/is2", &st));
        check_mode(0755, st.st_mode);
-       cl_git_pass(git_path_lstat("r/mode2/is2/important2", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode2/is2/important2", &st));
        check_mode(0777, st.st_mode);
 
        cl_git_pass(git_futils_mkdir_relative("mode3/is3/important3", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD_PATH, NULL));
 
-       cl_git_pass(git_path_lstat("r/mode3", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode3", &st));
        check_mode(0777, st.st_mode);
-       cl_git_pass(git_path_lstat("r/mode3/is3", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode3/is3", &st));
        check_mode(0777, st.st_mode);
-       cl_git_pass(git_path_lstat("r/mode3/is3/important3", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode3/is3/important3", &st));
        check_mode(0777, st.st_mode);
 
        /* test that we chmod existing dir */
 
        cl_git_pass(git_futils_mkdir_relative("mode/is/important", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD, NULL));
 
-       cl_git_pass(git_path_lstat("r/mode", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode", &st));
        check_mode(0755, st.st_mode);
-       cl_git_pass(git_path_lstat("r/mode/is", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode/is", &st));
        check_mode(0755, st.st_mode);
-       cl_git_pass(git_path_lstat("r/mode/is/important", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode/is/important", &st));
        check_mode(0777, st.st_mode);
 
        /* test that we chmod even existing dirs if CHMOD_PATH is set */
 
        cl_git_pass(git_futils_mkdir_relative("mode2/is2/important2.1", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD_PATH, NULL));
 
-       cl_git_pass(git_path_lstat("r/mode2", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode2", &st));
        check_mode(0777, st.st_mode);
-       cl_git_pass(git_path_lstat("r/mode2/is2", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode2/is2", &st));
        check_mode(0777, st.st_mode);
-       cl_git_pass(git_path_lstat("r/mode2/is2/important2.1", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode2/is2/important2.1", &st));
        check_mode(0777, st.st_mode);
 }
 
 void test_core_mkdir__keeps_parent_symlinks(void)
 {
 #ifndef GIT_WIN32
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        cl_set_cleanup(cleanup_basic_dirs, NULL);
 
        /* make a directory */
-       cl_assert(!git_path_isdir("d0"));
+       cl_assert(!git_fs_path_isdir("d0"));
        cl_git_pass(git_futils_mkdir("d0", 0755, 0));
-       cl_assert(git_path_isdir("d0"));
+       cl_assert(git_fs_path_isdir("d0"));
 
        cl_must_pass(symlink("d0", "d1"));
-       cl_assert(git_path_islink("d1"));
+       cl_assert(git_fs_path_islink("d1"));
 
        cl_git_pass(git_futils_mkdir("d1/foo/bar", 0755, GIT_MKDIR_PATH|GIT_MKDIR_REMOVE_SYMLINKS));
-       cl_assert(git_path_islink("d1"));
-       cl_assert(git_path_isdir("d1/foo/bar"));
-       cl_assert(git_path_isdir("d0/foo/bar"));
+       cl_assert(git_fs_path_islink("d1"));
+       cl_assert(git_fs_path_isdir("d1/foo/bar"));
+       cl_assert(git_fs_path_isdir("d0/foo/bar"));
 
        cl_must_pass(symlink("d0", "d2"));
-       cl_assert(git_path_islink("d2"));
+       cl_assert(git_fs_path_islink("d2"));
 
-       git_buf_joinpath(&path, clar_sandbox_path(), "d2/other/dir");
+       git_str_joinpath(&path, clar_sandbox_path(), "d2/other/dir");
 
        cl_git_pass(git_futils_mkdir(path.ptr, 0755, GIT_MKDIR_PATH|GIT_MKDIR_REMOVE_SYMLINKS));
-       cl_assert(git_path_islink("d2"));
-       cl_assert(git_path_isdir("d2/other/dir"));
-       cl_assert(git_path_isdir("d0/other/dir"));
+       cl_assert(git_fs_path_islink("d2"));
+       cl_assert(git_fs_path_isdir("d2/other/dir"));
+       cl_assert(git_fs_path_isdir("d0/other/dir"));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 #endif
 }
 
@@ -276,16 +275,16 @@ void test_core_mkdir__mkdir_path_inside_unwriteable_parent(void)
 
        cl_git_pass(git_futils_mkdir("r", 0777, 0));
        cl_git_pass(git_futils_mkdir_relative("mode/is/important", "r", 0777, GIT_MKDIR_PATH, NULL));
-       cl_git_pass(git_path_lstat("r/mode", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode", &st));
        check_mode(0755, st.st_mode);
 
        cl_must_pass(p_chmod("r/mode", 0111));
-       cl_git_pass(git_path_lstat("r/mode", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode", &st));
        check_mode(0111, st.st_mode);
 
        cl_git_pass(
                git_futils_mkdir_relative("mode/is/okay/inside", "r", 0777, GIT_MKDIR_PATH, NULL));
-       cl_git_pass(git_path_lstat("r/mode/is/okay/inside", &st));
+       cl_git_pass(git_fs_path_lstat("r/mode/is/okay/inside", &st));
        check_mode(0755, st.st_mode);
 
        cl_must_pass(p_chmod("r/mode", 0777));
index 7ee6fb67dab200b4a9584d0accea116d24b71833..894feadf61d904b4de9293f994757900148d35cf 100644 (file)
@@ -1,4 +1,5 @@
 #include "clar_libgit2.h"
+#include "oid.h"
 
 static git_oid id;
 static git_oid idp;
@@ -68,3 +69,11 @@ void test_core_oid__ncmp(void)
        cl_assert(!git_oid_ncmp(&id, &id, 40));
        cl_assert(!git_oid_ncmp(&id, &id, 41));
 }
+
+void test_core_oid__is_hexstr(void)
+{
+       cl_assert(git_oid__is_hexstr("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
+       cl_assert(!git_oid__is_hexstr("deadbeefdeadbeef"));
+       cl_assert(!git_oid__is_hexstr("zeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
+       cl_assert(!git_oid__is_hexstr("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef1"));
+}
index eac3573fea7edc4f453725e7791285a81e7619c0..1d8d0ef491b1daba4137d9515905a3cf6d099749 100644 (file)
@@ -1,17 +1,32 @@
 #include "clar_libgit2.h"
 #include "futils.h"
+#include "fs_path.h"
+
+static char *path_save;
+
+void test_core_path__initialize(void)
+{
+       path_save = cl_getenv("PATH");
+}
+
+void test_core_path__cleanup(void)
+{
+       cl_setenv("PATH", path_save);
+       git__free(path_save);
+       path_save = NULL;
+}
 
 static void
 check_dirname(const char *A, const char *B)
 {
-       git_buf dir = GIT_BUF_INIT;
+       git_str dir = GIT_STR_INIT;
        char *dir2;
 
-       cl_assert(git_path_dirname_r(&dir, A) >= 0);
+       cl_assert(git_fs_path_dirname_r(&dir, A) >= 0);
        cl_assert_equal_s(B, dir.ptr);
-       git_buf_dispose(&dir);
+       git_str_dispose(&dir);
 
-       cl_assert((dir2 = git_path_dirname(A)) != NULL);
+       cl_assert((dir2 = git_fs_path_dirname(A)) != NULL);
        cl_assert_equal_s(B, dir2);
        git__free(dir2);
 }
@@ -19,14 +34,14 @@ check_dirname(const char *A, const char *B)
 static void
 check_basename(const char *A, const char *B)
 {
-       git_buf base = GIT_BUF_INIT;
+       git_str base = GIT_STR_INIT;
        char *base2;
 
-       cl_assert(git_path_basename_r(&base, A) >= 0);
+       cl_assert(git_fs_path_basename_r(&base, A) >= 0);
        cl_assert_equal_s(B, base.ptr);
-       git_buf_dispose(&base);
+       git_str_dispose(&base);
 
-       cl_assert((base2 = git_path_basename(A)) != NULL);
+       cl_assert((base2 = git_fs_path_basename(A)) != NULL);
        cl_assert_equal_s(B, base2);
        git__free(base2);
 }
@@ -34,12 +49,12 @@ check_basename(const char *A, const char *B)
 static void
 check_joinpath(const char *path_a, const char *path_b, const char *expected_path)
 {
-       git_buf joined_path = GIT_BUF_INIT;
+       git_str joined_path = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&joined_path, path_a, path_b));
+       cl_git_pass(git_str_joinpath(&joined_path, path_a, path_b));
        cl_assert_equal_s(expected_path, joined_path.ptr);
 
-       git_buf_dispose(&joined_path);
+       git_str_dispose(&joined_path);
 }
 
 static void
@@ -50,15 +65,29 @@ check_joinpath_n(
        const char *path_d,
        const char *expected_path)
 {
-       git_buf joined_path = GIT_BUF_INIT;
+       git_str joined_path = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_join_n(&joined_path, '/', 4,
+       cl_git_pass(git_str_join_n(&joined_path, '/', 4,
                                                           path_a, path_b, path_c, path_d));
        cl_assert_equal_s(expected_path, joined_path.ptr);
 
-       git_buf_dispose(&joined_path);
+       git_str_dispose(&joined_path);
 }
 
+static void check_setenv(const char* name, const char* value)
+{
+    char* check;
+
+    cl_git_pass(cl_setenv(name, value));
+    check = cl_getenv(name);
+
+    if (value)
+       cl_assert_equal_s(value, check);
+    else
+       cl_assert(check == NULL);
+
+    git__free(check);
+}
 
 /* get the dirname of a path */
 void test_core_path__00_dirname(void)
@@ -172,13 +201,13 @@ check_path_to_dir(
        const char* path,
     const char* expected)
 {
-       git_buf tgt = GIT_BUF_INIT;
+       git_str tgt = GIT_STR_INIT;
 
-       git_buf_sets(&tgt, path);
-       cl_git_pass(git_path_to_dir(&tgt));
+       git_str_sets(&tgt, path);
+       cl_git_pass(git_fs_path_to_dir(&tgt));
        cl_assert_equal_s(expected, tgt.ptr);
 
-       git_buf_dispose(&tgt);
+       git_str_dispose(&tgt);
 }
 
 static void
@@ -193,7 +222,7 @@ check_string_to_dir(
 
        strncpy(buf, path, len + 2);
 
-       git_path_string_to_dir(buf, maxlen);
+       git_fs_path_string_to_dir(buf, maxlen);
 
        cl_assert_equal_s(expected, buf);
 
@@ -231,46 +260,46 @@ void test_core_path__07_path_to_dir(void)
 /* join path to itself */
 void test_core_path__08_self_join(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        size_t asize = 0;
 
        asize = path.asize;
-       cl_git_pass(git_buf_sets(&path, "/foo"));
+       cl_git_pass(git_str_sets(&path, "/foo"));
        cl_assert_equal_s(path.ptr, "/foo");
        cl_assert(asize < path.asize);
 
        asize = path.asize;
-       cl_git_pass(git_buf_joinpath(&path, path.ptr, "this is a new string"));
+       cl_git_pass(git_str_joinpath(&path, path.ptr, "this is a new string"));
        cl_assert_equal_s(path.ptr, "/foo/this is a new string");
        cl_assert(asize < path.asize);
 
        asize = path.asize;
-       cl_git_pass(git_buf_joinpath(&path, path.ptr, "/grow the buffer, grow the buffer, grow the buffer"));
+       cl_git_pass(git_str_joinpath(&path, path.ptr, "/grow the buffer, grow the buffer, grow the buffer"));
        cl_assert_equal_s(path.ptr, "/foo/this is a new string/grow the buffer, grow the buffer, grow the buffer");
        cl_assert(asize < path.asize);
 
-       git_buf_dispose(&path);
-       cl_git_pass(git_buf_sets(&path, "/foo/bar"));
+       git_str_dispose(&path);
+       cl_git_pass(git_str_sets(&path, "/foo/bar"));
 
-       cl_git_pass(git_buf_joinpath(&path, path.ptr + 4, "baz"));
+       cl_git_pass(git_str_joinpath(&path, path.ptr + 4, "baz"));
        cl_assert_equal_s(path.ptr, "/bar/baz");
 
        asize = path.asize;
-       cl_git_pass(git_buf_joinpath(&path, path.ptr + 4, "somethinglongenoughtorealloc"));
+       cl_git_pass(git_str_joinpath(&path, path.ptr + 4, "somethinglongenoughtorealloc"));
        cl_assert_equal_s(path.ptr, "/baz/somethinglongenoughtorealloc");
        cl_assert(asize < path.asize);
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 static void check_percent_decoding(const char *expected_result, const char *input)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        cl_git_pass(git__percent_decode(&buf, input));
-       cl_assert_equal_s(expected_result, git_buf_cstr(&buf));
+       cl_assert_equal_s(expected_result, git_str_cstr(&buf));
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 }
 
 void test_core_path__09_percent_decode(void)
@@ -289,17 +318,17 @@ void test_core_path__09_percent_decode(void)
 
 static void check_fromurl(const char *expected_result, const char *input, int should_fail)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        assert(should_fail || expected_result);
 
        if (!should_fail) {
-               cl_git_pass(git_path_fromurl(&buf, input));
-               cl_assert_equal_s(expected_result, git_buf_cstr(&buf));
+               cl_git_pass(git_fs_path_fromurl(&buf, input));
+               cl_assert_equal_s(expected_result, git_str_cstr(&buf));
        } else
-               cl_git_fail(git_path_fromurl(&buf, input));
+               cl_git_fail(git_fs_path_fromurl(&buf, input));
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 }
 
 #ifdef GIT_WIN32
@@ -353,7 +382,7 @@ static int check_one_walkup_step(void *ref, const char *path)
 
 void test_core_path__11_walkup(void)
 {
-       git_buf p = GIT_BUF_INIT;
+       git_str p = GIT_STR_INIT;
 
        char *expect[] = {
                /*  1 */ "/a/b/c/d/e/", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
@@ -398,11 +427,11 @@ void test_core_path__11_walkup(void)
 
        for (i = 0, j = 0; expect[i] != NULL; i++, j++) {
 
-               git_buf_sets(&p, expect[i]);
+               git_str_sets(&p, expect[i]);
 
                info.expect_idx = i;
                cl_git_pass(
-                       git_path_walk_up(&p, root[j], check_one_walkup_step, &info)
+                       git_fs_path_walk_up(&p, root[j], check_one_walkup_step, &info)
                );
 
                cl_assert_equal_s(p.ptr, expect[i]);
@@ -410,12 +439,12 @@ void test_core_path__11_walkup(void)
                i = info.expect_idx;
        }
 
-       git_buf_dispose(&p);
+       git_str_dispose(&p);
 }
 
 void test_core_path__11a_walkup_cancel(void)
 {
-       git_buf p = GIT_BUF_INIT;
+       git_str p = GIT_STR_INIT;
        int cancel[] = { 3, 2, 1, 0 };
        char *expect[] = {
                "/a/b/c/d/e/", "/a/b/c/d/", "/a/b/c/", "[CANCEL]", NULL,
@@ -432,35 +461,35 @@ void test_core_path__11a_walkup_cancel(void)
 
        for (i = 0, j = 0; expect[i] != NULL; i++, j++) {
 
-               git_buf_sets(&p, expect[i]);
+               git_str_sets(&p, expect[i]);
 
                info.cancel_after = cancel[j];
                info.expect_idx = i;
 
                cl_assert_equal_i(
                        CANCEL_VALUE,
-                       git_path_walk_up(&p, root[j], check_one_walkup_step, &info)
+                       git_fs_path_walk_up(&p, root[j], check_one_walkup_step, &info)
                );
 
                /* skip to next run of expectations */
                while (expect[i] != NULL) i++;
        }
 
-       git_buf_dispose(&p);
+       git_str_dispose(&p);
 }
 
 void test_core_path__12_offset_to_path_root(void)
 {
-       cl_assert(git_path_root("non/rooted/path") == -1);
-       cl_assert(git_path_root("/rooted/path") == 0);
+       cl_assert(git_fs_path_root("non/rooted/path") == -1);
+       cl_assert(git_fs_path_root("/rooted/path") == 0);
 
 #ifdef GIT_WIN32
        /* Windows specific tests */
-       cl_assert(git_path_root("C:non/rooted/path") == -1);
-       cl_assert(git_path_root("C:/rooted/path") == 2);
-       cl_assert(git_path_root("//computername/sharefolder/resource") == 14);
-       cl_assert(git_path_root("//computername/sharefolder") == 14);
-       cl_assert(git_path_root("//computername") == -1);
+       cl_assert(git_fs_path_root("C:non/rooted/path") == -1);
+       cl_assert(git_fs_path_root("C:/rooted/path") == 2);
+       cl_assert(git_fs_path_root("//computername/sharefolder/resource") == 14);
+       cl_assert(git_fs_path_root("//computername/sharefolder") == 14);
+       cl_assert(git_fs_path_root("//computername") == -1);
 #endif
 }
 
@@ -468,87 +497,87 @@ void test_core_path__12_offset_to_path_root(void)
 
 void test_core_path__13_cannot_prettify_a_non_existing_file(void)
 {
-       git_buf p = GIT_BUF_INIT;
+       git_str p = GIT_STR_INIT;
 
-       cl_assert_equal_b(git_path_exists(NON_EXISTING_FILEPATH), false);
-       cl_assert_equal_i(GIT_ENOTFOUND, git_path_prettify(&p, NON_EXISTING_FILEPATH, NULL));
-       cl_assert_equal_i(GIT_ENOTFOUND, git_path_prettify(&p, NON_EXISTING_FILEPATH "/so-do-i", NULL));
+       cl_assert_equal_b(git_fs_path_exists(NON_EXISTING_FILEPATH), false);
+       cl_assert_equal_i(GIT_ENOTFOUND, git_fs_path_prettify(&p, NON_EXISTING_FILEPATH, NULL));
+       cl_assert_equal_i(GIT_ENOTFOUND, git_fs_path_prettify(&p, NON_EXISTING_FILEPATH "/so-do-i", NULL));
 
-       git_buf_dispose(&p);
+       git_str_dispose(&p);
 }
 
 void test_core_path__14_apply_relative(void)
 {
-       git_buf p = GIT_BUF_INIT;
+       git_str p = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_sets(&p, "/this/is/a/base"));
+       cl_git_pass(git_str_sets(&p, "/this/is/a/base"));
 
-       cl_git_pass(git_path_apply_relative(&p, "../test"));
+       cl_git_pass(git_fs_path_apply_relative(&p, "../test"));
        cl_assert_equal_s("/this/is/a/test", p.ptr);
 
-       cl_git_pass(git_path_apply_relative(&p, "../../the/./end"));
+       cl_git_pass(git_fs_path_apply_relative(&p, "../../the/./end"));
        cl_assert_equal_s("/this/is/the/end", p.ptr);
 
-       cl_git_pass(git_path_apply_relative(&p, "./of/this/../the/string"));
+       cl_git_pass(git_fs_path_apply_relative(&p, "./of/this/../the/string"));
        cl_assert_equal_s("/this/is/the/end/of/the/string", p.ptr);
 
-       cl_git_pass(git_path_apply_relative(&p, "../../../../../.."));
+       cl_git_pass(git_fs_path_apply_relative(&p, "../../../../../.."));
        cl_assert_equal_s("/this/", p.ptr);
 
-       cl_git_pass(git_path_apply_relative(&p, "../"));
+       cl_git_pass(git_fs_path_apply_relative(&p, "../"));
        cl_assert_equal_s("/", p.ptr);
 
-       cl_git_fail(git_path_apply_relative(&p, "../../.."));
+       cl_git_fail(git_fs_path_apply_relative(&p, "../../.."));
 
 
-       cl_git_pass(git_buf_sets(&p, "d:/another/test"));
+       cl_git_pass(git_str_sets(&p, "d:/another/test"));
 
-       cl_git_pass(git_path_apply_relative(&p, "../.."));
+       cl_git_pass(git_fs_path_apply_relative(&p, "../.."));
        cl_assert_equal_s("d:/", p.ptr);
 
-       cl_git_pass(git_path_apply_relative(&p, "from/here/to/../and/./back/."));
+       cl_git_pass(git_fs_path_apply_relative(&p, "from/here/to/../and/./back/."));
        cl_assert_equal_s("d:/from/here/and/back/", p.ptr);
 
 
-       cl_git_pass(git_buf_sets(&p, "https://my.url.com/test.git"));
+       cl_git_pass(git_str_sets(&p, "https://my.url.com/test.git"));
 
-       cl_git_pass(git_path_apply_relative(&p, "../another.git"));
+       cl_git_pass(git_fs_path_apply_relative(&p, "../another.git"));
        cl_assert_equal_s("https://my.url.com/another.git", p.ptr);
 
-       cl_git_pass(git_path_apply_relative(&p, "../full/path/url.patch"));
+       cl_git_pass(git_fs_path_apply_relative(&p, "../full/path/url.patch"));
        cl_assert_equal_s("https://my.url.com/full/path/url.patch", p.ptr);
 
-       cl_git_pass(git_path_apply_relative(&p, ".."));
+       cl_git_pass(git_fs_path_apply_relative(&p, ".."));
        cl_assert_equal_s("https://my.url.com/full/path/", p.ptr);
 
-       cl_git_pass(git_path_apply_relative(&p, "../../../"));
+       cl_git_pass(git_fs_path_apply_relative(&p, "../../../"));
        cl_assert_equal_s("https://", p.ptr);
 
 
-       cl_git_pass(git_buf_sets(&p, "../../this/is/relative"));
+       cl_git_pass(git_str_sets(&p, "../../this/is/relative"));
 
-       cl_git_pass(git_path_apply_relative(&p, "../../preserves/the/prefix"));
+       cl_git_pass(git_fs_path_apply_relative(&p, "../../preserves/the/prefix"));
        cl_assert_equal_s("../../this/preserves/the/prefix", p.ptr);
 
-       cl_git_pass(git_path_apply_relative(&p, "../../../../that"));
+       cl_git_pass(git_fs_path_apply_relative(&p, "../../../../that"));
        cl_assert_equal_s("../../that", p.ptr);
 
-       cl_git_pass(git_path_apply_relative(&p, "../there"));
+       cl_git_pass(git_fs_path_apply_relative(&p, "../there"));
        cl_assert_equal_s("../../there", p.ptr);
-       git_buf_dispose(&p);
+       git_str_dispose(&p);
 }
 
 static void assert_resolve_relative(
-       git_buf *buf, const char *expected, const char *path)
+       git_str *buf, const char *expected, const char *path)
 {
-       cl_git_pass(git_buf_sets(buf, path));
-       cl_git_pass(git_path_resolve_relative(buf, 0));
+       cl_git_pass(git_str_sets(buf, path));
+       cl_git_pass(git_fs_path_resolve_relative(buf, 0));
        cl_assert_equal_s(expected, buf->ptr);
 }
 
 void test_core_path__15_resolve_relative(void)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        assert_resolve_relative(&buf, "", "");
        assert_resolve_relative(&buf, "", ".");
@@ -595,23 +624,23 @@ void test_core_path__15_resolve_relative(void)
        assert_resolve_relative(&buf, "../../path", "../../test//../././path");
        assert_resolve_relative(&buf, "../d", "a/b/../../../c/../d");
 
-       cl_git_pass(git_buf_sets(&buf, "/.."));
-       cl_git_fail(git_path_resolve_relative(&buf, 0));
+       cl_git_pass(git_str_sets(&buf, "/.."));
+       cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
 
-       cl_git_pass(git_buf_sets(&buf, "/./.."));
-       cl_git_fail(git_path_resolve_relative(&buf, 0));
+       cl_git_pass(git_str_sets(&buf, "/./.."));
+       cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
 
-       cl_git_pass(git_buf_sets(&buf, "/.//.."));
-       cl_git_fail(git_path_resolve_relative(&buf, 0));
+       cl_git_pass(git_str_sets(&buf, "/.//.."));
+       cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
 
-       cl_git_pass(git_buf_sets(&buf, "/../."));
-       cl_git_fail(git_path_resolve_relative(&buf, 0));
+       cl_git_pass(git_str_sets(&buf, "/../."));
+       cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
 
-       cl_git_pass(git_buf_sets(&buf, "/../.././../a"));
-       cl_git_fail(git_path_resolve_relative(&buf, 0));
+       cl_git_pass(git_str_sets(&buf, "/../.././../a"));
+       cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
 
-       cl_git_pass(git_buf_sets(&buf, "////.."));
-       cl_git_fail(git_path_resolve_relative(&buf, 0));
+       cl_git_pass(git_str_sets(&buf, "////.."));
+       cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
 
        /* things that start with Windows network paths */
 #ifdef GIT_WIN32
@@ -619,8 +648,8 @@ void test_core_path__15_resolve_relative(void)
        assert_resolve_relative(&buf, "//a/", "//a/b/..");
        assert_resolve_relative(&buf, "//a/b/c", "//a/Q/../b/x/y/../../c");
 
-       cl_git_pass(git_buf_sets(&buf, "//a/b/../.."));
-       cl_git_fail(git_path_resolve_relative(&buf, 0));
+       cl_git_pass(git_str_sets(&buf, "//a/b/../.."));
+       cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
 #else
        assert_resolve_relative(&buf, "/a/b/c", "//a/b/c");
        assert_resolve_relative(&buf, "/a/", "//a/b/..");
@@ -628,11 +657,11 @@ void test_core_path__15_resolve_relative(void)
        assert_resolve_relative(&buf, "/", "//a/b/../..");
 #endif
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 }
 
 #define assert_common_dirlen(i, p, q) \
-       cl_assert_equal_i((i), git_path_common_dirlen((p), (q)));
+       cl_assert_equal_i((i), git_fs_path_common_dirlen((p), (q)));
 
 void test_core_path__16_resolve_relative(void)
 {
@@ -651,11 +680,85 @@ void test_core_path__16_resolve_relative(void)
        assert_common_dirlen(7, "/a/b/c/foo.txt", "/a/b/c/d/e/bar.txt");
 }
 
-void test_core_path__git_path_is_file(void)
+static void fix_path(git_str *s)
+{
+#ifndef GIT_WIN32
+       GIT_UNUSED(s);
+#else
+       char* c;
+
+       for (c = s->ptr; *c; c++) {
+               if (*c == '/')
+                       *c = '\\';
+       }
+#endif
+}
+
+void test_core_path__find_exe_in_path(void)
+{
+       char *orig_path;
+       git_str sandbox_path = GIT_STR_INIT;
+       git_str new_path = GIT_STR_INIT, full_path = GIT_STR_INIT,
+               dummy_path = GIT_STR_INIT;
+
+#ifdef GIT_WIN32
+       static const char *bogus_path_1 = "c:\\does\\not\\exist\\";
+       static const char *bogus_path_2 = "e:\\non\\existent";
+#else
+       static const char *bogus_path_1 = "/this/path/does/not/exist/";
+       static const char *bogus_path_2 = "/non/existent";
+#endif
+
+       orig_path = cl_getenv("PATH");
+
+       git_str_puts(&sandbox_path, clar_sandbox_path());
+       git_str_joinpath(&dummy_path, sandbox_path.ptr, "dummmmmmmy_libgit2_file");
+       cl_git_rewritefile(dummy_path.ptr, "this is a dummy file");
+
+       fix_path(&sandbox_path);
+       fix_path(&dummy_path);
+
+       cl_git_pass(git_str_printf(&new_path, "%s%c%s%c%s%c%s",
+               bogus_path_1, GIT_PATH_LIST_SEPARATOR,
+               orig_path, GIT_PATH_LIST_SEPARATOR,
+               sandbox_path.ptr, GIT_PATH_LIST_SEPARATOR,
+               bogus_path_2));
+
+       check_setenv("PATH", new_path.ptr);
+
+       cl_git_fail_with(GIT_ENOTFOUND, git_fs_path_find_executable(&full_path, "this_file_does_not_exist"));
+       cl_git_pass(git_fs_path_find_executable(&full_path, "dummmmmmmy_libgit2_file"));
+
+       cl_assert_equal_s(full_path.ptr, dummy_path.ptr);
+
+       git_str_dispose(&full_path);
+       git_str_dispose(&new_path);
+       git_str_dispose(&dummy_path);
+       git_str_dispose(&sandbox_path);
+       git__free(orig_path);
+}
+
+void test_core_path__validate_current_user_ownership(void)
 {
-       cl_git_fail(git_path_is_gitfile("blob", 4, -1, GIT_PATH_FS_HFS));
-       cl_git_pass(git_path_is_gitfile("blob", 4, GIT_PATH_GITFILE_GITIGNORE, GIT_PATH_FS_HFS));
-       cl_git_pass(git_path_is_gitfile("blob", 4, GIT_PATH_GITFILE_GITMODULES, GIT_PATH_FS_HFS));
-       cl_git_pass(git_path_is_gitfile("blob", 4, GIT_PATH_GITFILE_GITATTRIBUTES, GIT_PATH_FS_HFS));
-       cl_git_fail(git_path_is_gitfile("blob", 4, 3, GIT_PATH_FS_HFS));
+       bool is_cur;
+
+       cl_must_pass(p_mkdir("testdir", 0777));
+       cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "testdir"));
+       cl_assert_equal_i(is_cur, 1);
+
+       cl_git_rewritefile("testfile", "This is a test file.");
+       cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "testfile"));
+       cl_assert_equal_i(is_cur, 1);
+
+#ifdef GIT_WIN32
+       cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "C:\\"));
+       cl_assert_equal_i(is_cur, 0);
+
+       cl_git_fail(git_fs_path_owner_is_current_user(&is_cur, "c:\\path\\does\\not\\exist"));
+#else
+       cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "/"));
+       cl_assert_equal_i(is_cur, 0);
+
+       cl_git_fail(git_fs_path_owner_is_current_user(&is_cur, "/path/does/not/exist"));
+#endif
 }
index 1bb1e9c6b1d539be47e2e881a75718e59a88836d..cba312913f4de39315650ce38b082b4bbc995fbf 100644 (file)
@@ -147,7 +147,7 @@ void test_core_posix__utimes(void)
 
 void test_core_posix__unlink_removes_symlink(void)
 {
-       if (!git_path_supports_symlinks(clar_sandbox_path()))
+       if (!git_fs_path_supports_symlinks(clar_sandbox_path()))
                clar__skip();
 
        cl_git_mkfile("file", "Dummy file.");
@@ -159,8 +159,8 @@ void test_core_posix__unlink_removes_symlink(void)
        cl_must_pass(p_unlink("file-symlink"));
        cl_must_pass(p_unlink("dir-symlink"));
 
-       cl_assert(git_path_exists("file"));
-       cl_assert(git_path_exists("dir"));
+       cl_assert(git_fs_path_exists("file"));
+       cl_assert(git_fs_path_exists("dir"));
 
        cl_must_pass(p_unlink("file"));
        cl_must_pass(p_rmdir("dir"));
@@ -168,9 +168,9 @@ void test_core_posix__unlink_removes_symlink(void)
 
 void test_core_posix__symlink_resolves_to_correct_type(void)
 {
-       git_buf contents = GIT_BUF_INIT;
+       git_str contents = GIT_STR_INIT;
 
-       if (!git_path_supports_symlinks(clar_sandbox_path()))
+       if (!git_fs_path_supports_symlinks(clar_sandbox_path()))
                clar__skip();
 
        cl_must_pass(git_futils_mkdir("dir", 0777, 0));
@@ -187,14 +187,14 @@ void test_core_posix__symlink_resolves_to_correct_type(void)
        cl_must_pass(p_rmdir("dir"));
        cl_must_pass(p_rmdir("file"));
 
-       git_buf_dispose(&contents);
+       git_str_dispose(&contents);
 }
 
 void test_core_posix__relative_symlink(void)
 {
-       git_buf contents = GIT_BUF_INIT;
+       git_str contents = GIT_STR_INIT;
 
-       if (!git_path_supports_symlinks(clar_sandbox_path()))
+       if (!git_fs_path_supports_symlinks(clar_sandbox_path()))
                clar__skip();
 
        cl_must_pass(git_futils_mkdir("dir", 0777, 0));
@@ -207,14 +207,14 @@ void test_core_posix__relative_symlink(void)
        cl_must_pass(p_unlink("dir/link"));
        cl_must_pass(p_rmdir("dir"));
 
-       git_buf_dispose(&contents);
+       git_str_dispose(&contents);
 }
 
 void test_core_posix__symlink_to_file_across_dirs(void)
 {
-       git_buf contents = GIT_BUF_INIT;
+       git_str contents = GIT_STR_INIT;
 
-       if (!git_path_supports_symlinks(clar_sandbox_path()))
+       if (!git_fs_path_supports_symlinks(clar_sandbox_path()))
                clar__skip();
 
        /*
@@ -234,5 +234,5 @@ void test_core_posix__symlink_to_file_across_dirs(void)
        cl_must_pass(p_unlink("link"));
        cl_must_pass(p_rmdir("dir"));
 
-       git_buf_dispose(&contents);
+       git_str_dispose(&contents);
 }
index b436b97e061832e921460e2f263738d4e369ab3a..f6c66b3a44aea5700d9266efc3299ce7daa24abc 100644 (file)
@@ -5,116 +5,116 @@ static const char *empty_tmp_dir = "test_gitfo_rmdir_recurs_test";
 
 void test_core_rmdir__initialize(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        cl_must_pass(p_mkdir(empty_tmp_dir, 0777));
 
-       cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/one"));
+       cl_git_pass(git_str_joinpath(&path, empty_tmp_dir, "/one"));
        cl_must_pass(p_mkdir(path.ptr, 0777));
 
-       cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/one/two_one"));
+       cl_git_pass(git_str_joinpath(&path, empty_tmp_dir, "/one/two_one"));
        cl_must_pass(p_mkdir(path.ptr, 0777));
 
-       cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/one/two_two"));
+       cl_git_pass(git_str_joinpath(&path, empty_tmp_dir, "/one/two_two"));
        cl_must_pass(p_mkdir(path.ptr, 0777));
 
-       cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/one/two_two/three"));
+       cl_git_pass(git_str_joinpath(&path, empty_tmp_dir, "/one/two_two/three"));
        cl_must_pass(p_mkdir(path.ptr, 0777));
 
-       cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/two"));
+       cl_git_pass(git_str_joinpath(&path, empty_tmp_dir, "/two"));
        cl_must_pass(p_mkdir(path.ptr, 0777));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_core_rmdir__cleanup(void)
 {
-       if (git_path_exists(empty_tmp_dir))
+       if (git_fs_path_exists(empty_tmp_dir))
                cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_REMOVE_FILES));
 }
 
-/* make sure empty dir can be deleted recusively */
+/* make sure empty dir can be deleted recursively */
 void test_core_rmdir__delete_recursive(void)
 {
-       git_buf path = GIT_BUF_INIT;
-       cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/one"));
-       cl_assert(git_path_exists(git_buf_cstr(&path)));
+       git_str path = GIT_STR_INIT;
+       cl_git_pass(git_str_joinpath(&path, empty_tmp_dir, "/one"));
+       cl_assert(git_fs_path_exists(git_str_cstr(&path)));
 
        cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_EMPTY_HIERARCHY));
 
-       cl_assert(!git_path_exists(git_buf_cstr(&path)));
+       cl_assert(!git_fs_path_exists(git_str_cstr(&path)));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
-/* make sure non-empty dir cannot be deleted recusively */
+/* make sure non-empty dir cannot be deleted recursively */
 void test_core_rmdir__fail_to_delete_non_empty_dir(void)
 {
-       git_buf file = GIT_BUF_INIT;
+       git_str file = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&file, empty_tmp_dir, "/two/file.txt"));
+       cl_git_pass(git_str_joinpath(&file, empty_tmp_dir, "/two/file.txt"));
 
-       cl_git_mkfile(git_buf_cstr(&file), "dummy");
+       cl_git_mkfile(git_str_cstr(&file), "dummy");
 
        cl_git_fail(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_EMPTY_HIERARCHY));
 
        cl_must_pass(p_unlink(file.ptr));
        cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_EMPTY_HIERARCHY));
 
-       cl_assert(!git_path_exists(empty_tmp_dir));
+       cl_assert(!git_fs_path_exists(empty_tmp_dir));
 
-       git_buf_dispose(&file);
+       git_str_dispose(&file);
 }
 
 void test_core_rmdir__keep_base(void)
 {
        cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_SKIP_ROOT));
-       cl_assert(git_path_exists(empty_tmp_dir));
+       cl_assert(git_fs_path_exists(empty_tmp_dir));
 }
 
 void test_core_rmdir__can_skip_non_empty_dir(void)
 {
-       git_buf file = GIT_BUF_INIT;
+       git_str file = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&file, empty_tmp_dir, "/two/file.txt"));
+       cl_git_pass(git_str_joinpath(&file, empty_tmp_dir, "/two/file.txt"));
 
-       cl_git_mkfile(git_buf_cstr(&file), "dummy");
+       cl_git_mkfile(git_str_cstr(&file), "dummy");
 
        cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_SKIP_NONEMPTY));
-       cl_assert(git_path_exists(git_buf_cstr(&file)) == true);
+       cl_assert(git_fs_path_exists(git_str_cstr(&file)) == true);
 
        cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_REMOVE_FILES));
-       cl_assert(git_path_exists(empty_tmp_dir) == false);
+       cl_assert(git_fs_path_exists(empty_tmp_dir) == false);
 
-       git_buf_dispose(&file);
+       git_str_dispose(&file);
 }
 
 void test_core_rmdir__can_remove_empty_parents(void)
 {
-       git_buf file = GIT_BUF_INIT;
+       git_str file = GIT_STR_INIT;
 
        cl_git_pass(
-               git_buf_joinpath(&file, empty_tmp_dir, "/one/two_two/three/file.txt"));
-       cl_git_mkfile(git_buf_cstr(&file), "dummy");
-       cl_assert(git_path_isfile(git_buf_cstr(&file)));
+               git_str_joinpath(&file, empty_tmp_dir, "/one/two_two/three/file.txt"));
+       cl_git_mkfile(git_str_cstr(&file), "dummy");
+       cl_assert(git_fs_path_isfile(git_str_cstr(&file)));
 
        cl_git_pass(git_futils_rmdir_r("one/two_two/three/file.txt", empty_tmp_dir,
                GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_EMPTY_PARENTS));
 
-       cl_assert(!git_path_exists(git_buf_cstr(&file)));
+       cl_assert(!git_fs_path_exists(git_str_cstr(&file)));
 
-       git_buf_rtruncate_at_char(&file, '/'); /* three (only contained file.txt) */
-       cl_assert(!git_path_exists(git_buf_cstr(&file)));
+       git_str_rtruncate_at_char(&file, '/'); /* three (only contained file.txt) */
+       cl_assert(!git_fs_path_exists(git_str_cstr(&file)));
 
-       git_buf_rtruncate_at_char(&file, '/'); /* two_two (only contained three) */
-       cl_assert(!git_path_exists(git_buf_cstr(&file)));
+       git_str_rtruncate_at_char(&file, '/'); /* two_two (only contained three) */
+       cl_assert(!git_fs_path_exists(git_str_cstr(&file)));
 
-       git_buf_rtruncate_at_char(&file, '/'); /* one (contained two_one also) */
-       cl_assert(git_path_exists(git_buf_cstr(&file)));
+       git_str_rtruncate_at_char(&file, '/'); /* one (contained two_one also) */
+       cl_assert(git_fs_path_exists(git_str_cstr(&file)));
 
-       cl_assert(git_path_exists(empty_tmp_dir) == true);
+       cl_assert(git_fs_path_exists(empty_tmp_dir) == true);
 
-       git_buf_dispose(&file);
+       git_str_dispose(&file);
 
        cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_EMPTY_HIERARCHY));
 }
index 196b003525fea9b6169f7ea1a56afb9710f5e581..9ccdaab3ce53f686843743986835d30160a47e93 100644 (file)
@@ -13,7 +13,7 @@ void test_core_sha1__cleanup(void)
        cl_fixture_cleanup(FIXTURE_DIR);
 }
 
-static int sha1_file(git_oid *oid, const char *filename)
+static int sha1_file(unsigned char *out, const char *filename)
 {
        git_hash_ctx ctx;
        char buf[2048];
@@ -23,7 +23,7 @@ static int sha1_file(git_oid *oid, const char *filename)
        fd = p_open(filename, O_RDONLY);
        cl_assert(fd >= 0);
 
-       cl_git_pass(git_hash_ctx_init(&ctx));
+       cl_git_pass(git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA1));
 
        while ((read_len = p_read(fd, buf, 2048)) > 0)
                cl_git_pass(git_hash_update(&ctx, buf, (size_t)read_len));
@@ -31,7 +31,7 @@ static int sha1_file(git_oid *oid, const char *filename)
        cl_assert_equal_i(0, read_len);
        p_close(fd);
 
-       ret = git_hash_final(oid, &ctx);
+       ret = git_hash_final(out, &ctx);
        git_hash_ctx_cleanup(&ctx);
 
        return ret;
@@ -39,26 +39,32 @@ static int sha1_file(git_oid *oid, const char *filename)
 
 void test_core_sha1__sum(void)
 {
-       git_oid oid, expected;
+       unsigned char expected[GIT_HASH_SHA1_SIZE] = {
+               0x4e, 0x72, 0x67, 0x9e, 0x3e, 0xa4, 0xd0, 0x4e, 0x0c, 0x64,
+               0x2f, 0x02, 0x9e, 0x61, 0xeb, 0x80, 0x56, 0xc7, 0xed, 0x94
+       };
+       unsigned char actual[GIT_HASH_SHA1_SIZE];
 
-       cl_git_pass(sha1_file(&oid, FIXTURE_DIR "/hello_c"));
-       git_oid_fromstr(&expected, "4e72679e3ea4d04e0c642f029e61eb8056c7ed94");
-       cl_assert_equal_oid(&expected, &oid);
+       cl_git_pass(sha1_file(actual, FIXTURE_DIR "/hello_c"));
+       cl_assert_equal_i(0, memcmp(expected, actual, GIT_HASH_SHA1_SIZE));
 }
 
 /* test that sha1 collision detection works when enabled */
 void test_core_sha1__detect_collision_attack(void)
 {
-       git_oid oid, expected;
+       unsigned char actual[GIT_HASH_SHA1_SIZE];
+       unsigned char expected[GIT_HASH_SHA1_SIZE] = {
+               0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17,
+               0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a
+       };
 
 #ifdef GIT_SHA1_COLLISIONDETECT
        GIT_UNUSED(&expected);
-       cl_git_fail(sha1_file(&oid, FIXTURE_DIR "/shattered-1.pdf"));
+       cl_git_fail(sha1_file(actual, FIXTURE_DIR "/shattered-1.pdf"));
        cl_assert_equal_s("SHA1 collision attack detected", git_error_last()->message);
 #else
-       cl_git_pass(sha1_file(&oid, FIXTURE_DIR "/shattered-1.pdf"));
-       git_oid_fromstr(&expected, "38762cf7f55934b34d179ae6a4c80cadccbb7f0a");
-       cl_assert_equal_oid(&expected, &oid);
+       cl_git_pass(sha1_file(actual, FIXTURE_DIR "/shattered-1.pdf"));
+       cl_assert_equal_i(0, memcmp(expected, actual, GIT_HASH_SHA1_SIZE));
 #endif
 }
 
index d5bbcea19f22568a798bb57ad73db6872327269c..cb4e34efaafea1396c45351c9d0e939dfcfe4a68 100644 (file)
@@ -241,7 +241,7 @@ void test_core_sortedcache__in_memory(void)
 static void sortedcache_test_reload(git_sortedcache *sc)
 {
        int count = 0;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        char *scan, *after;
        sortedcache_test_struct *item;
 
@@ -266,7 +266,7 @@ static void sortedcache_test_reload(git_sortedcache *sc)
 
        git_sortedcache_wunlock(sc);
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 }
 
 void test_core_sortedcache__on_disk(void)
index 7f5d6675340136f63333acba5d87ad221499901b..210072fe3a29fda5c6021cf63f1d0ec95731bbcf 100644 (file)
@@ -1,6 +1,5 @@
 #include "clar_libgit2.h"
 #include "futils.h"
-#include "path.h"
 #include "posix.h"
 
 void test_core_stat__initialize(void)
@@ -98,17 +97,17 @@ void test_core_stat__0(void)
 void test_core_stat__root(void)
 {
        const char *sandbox = clar_sandbox_path();
-       git_buf root = GIT_BUF_INIT;
+       git_str root = GIT_STR_INIT;
        int root_len;
        struct stat st;
 
-       root_len = git_path_root(sandbox);
+       root_len = git_fs_path_root(sandbox);
        cl_assert(root_len >= 0);
 
-       git_buf_set(&root, sandbox, root_len+1);
+       git_str_set(&root, sandbox, root_len+1);
 
        cl_must_pass(p_stat(root.ptr, &st));
        cl_assert(S_ISDIR(st.st_mode));
 
-       git_buf_dispose(&root);
+       git_str_dispose(&root);
 }
index d24da874da59f08d167e0dec38693dbe75dade19..160e2f61218d39b19ede982794149cbbe04571d0 100644 (file)
@@ -67,7 +67,7 @@ void test_core_structinit__compare(void)
         * which is not guaranteed to be initialized to anything sane at all.
         *
         * Assume most compilers, in a debug build, will clear that memory for
-        * us or set it to sentinal markers.  Etc.
+        * us or set it to sentinel markers.  Etc.
         */
 #if !defined(DEBUG) && !defined(_DEBUG)
        clar__skip();
index 2ce935bf5466e6c2b28edaa354f19975c551c42b..a4ece902fd9f85cb40e67f2324ee14b702d6d2f8 100644 (file)
@@ -4,7 +4,7 @@
 void test_core_useragent__get(void)
 {
        const char *custom_name = "super duper git";
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        cl_assert_equal_p(NULL, git_libgit2__user_agent());
        cl_git_pass(git_libgit2_opts(GIT_OPT_SET_USER_AGENT, custom_name));
@@ -13,5 +13,5 @@ void test_core_useragent__get(void)
        cl_git_pass(git_libgit2_opts(GIT_OPT_GET_USER_AGENT, &buf));
        cl_assert_equal_s(custom_name, buf.ptr);
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 }
index 021828e9e1cbd9299927df930e69a77b1c6ab207..e1987b8d631d2689388c6fb961fdaffa509ffec1 100644 (file)
@@ -1,4 +1,5 @@
 #include "clar_libgit2.h"
+#include "utf8.h"
 
 void test_core_utf8__char_length(void)
 {
index 3cbcea168d4ccd96250e37c92b43be04f455b49f..c22e81008b6ffa8a84dadc668e78f72a9f689ea4 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "zstream.h"
 
 static const char *data = "This is a test test test of This is a test";
@@ -60,7 +59,7 @@ void test_core_zstream__basic(void)
 
 void test_core_zstream__fails_on_trailing_garbage(void)
 {
-       git_buf deflated = GIT_BUF_INIT, inflated = GIT_BUF_INIT;
+       git_str deflated = GIT_STR_INIT, inflated = GIT_STR_INIT;
        char i = 0;
 
        /* compress a simple string */
@@ -68,29 +67,29 @@ void test_core_zstream__fails_on_trailing_garbage(void)
 
        /* append some garbage */
        for (i = 0; i < 10; i++) {
-               git_buf_putc(&deflated, i);
+               git_str_putc(&deflated, i);
        }
 
        cl_git_fail(git_zstream_inflatebuf(&inflated, deflated.ptr, deflated.size));
 
-       git_buf_dispose(&deflated);
-       git_buf_dispose(&inflated);
+       git_str_dispose(&deflated);
+       git_str_dispose(&inflated);
 }
 
 void test_core_zstream__buffer(void)
 {
-       git_buf out = GIT_BUF_INIT;
+       git_str out = GIT_STR_INIT;
        cl_git_pass(git_zstream_deflatebuf(&out, data, strlen(data) + 1));
        assert_zlib_equal(data, strlen(data) + 1, out.ptr, out.size);
-       git_buf_dispose(&out);
+       git_str_dispose(&out);
 }
 
 #define BIG_STRING_PART "Big Data IS Big - Long Data IS Long - We need a buffer larger than 1024 x 1024 to make sure we trigger chunked compression - Big Big Data IS Bigger than Big - Long Long Data IS Longer than Long"
 
-static void compress_and_decompress_input_various_ways(git_buf *input)
+static void compress_and_decompress_input_various_ways(git_str *input)
 {
-       git_buf out1 = GIT_BUF_INIT, out2 = GIT_BUF_INIT;
-       git_buf inflated = GIT_BUF_INIT;
+       git_str out1 = GIT_STR_INIT, out2 = GIT_STR_INIT;
+       git_str inflated = GIT_STR_INIT;
        size_t i, fixed_size = max(input->size / 2, 256);
        char *fixed = git__malloc(fixed_size);
        cl_assert(fixed);
@@ -119,7 +118,7 @@ static void compress_and_decompress_input_various_ways(git_buf *input)
                while (!git_zstream_done(&zs)) {
                        size_t written = use_fixed_size;
                        cl_git_pass(git_zstream_get_output(fixed, &written, &zs));
-                       cl_git_pass(git_buf_put(&out2, fixed, written));
+                       cl_git_pass(git_str_put(&out2, fixed, written));
                }
 
                git_zstream_free(&zs);
@@ -129,30 +128,30 @@ static void compress_and_decompress_input_various_ways(git_buf *input)
                cl_assert_equal_sz(out1.size, out2.size);
                cl_assert(!memcmp(out1.ptr, out2.ptr, out1.size));
 
-               git_buf_dispose(&out2);
+               git_str_dispose(&out2);
        }
 
        cl_git_pass(git_zstream_inflatebuf(&inflated, out1.ptr, out1.size));
        cl_assert_equal_i(input->size, inflated.size);
        cl_assert(memcmp(input->ptr, inflated.ptr, inflated.size) == 0);
 
-       git_buf_dispose(&out1);
-       git_buf_dispose(&inflated);
+       git_str_dispose(&out1);
+       git_str_dispose(&inflated);
        git__free(fixed);
 }
 
 void test_core_zstream__big_data(void)
 {
-       git_buf in = GIT_BUF_INIT;
+       git_str in = GIT_STR_INIT;
        size_t scan, target;
 
        for (target = 1024; target <= 1024 * 1024 * 4; target *= 8) {
 
                /* make a big string that's easy to compress */
-               git_buf_clear(&in);
+               git_str_clear(&in);
                while (in.size < target)
                        cl_git_pass(
-                               git_buf_put(&in, BIG_STRING_PART, strlen(BIG_STRING_PART)));
+                               git_str_put(&in, BIG_STRING_PART, strlen(BIG_STRING_PART)));
 
                compress_and_decompress_input_various_ways(&in);
 
@@ -164,5 +163,5 @@ void test_core_zstream__big_data(void)
                compress_and_decompress_input_various_ways(&in);
        }
 
-       git_buf_dispose(&in);
+       git_str_dispose(&in);
 }
index 88881d1e13720aab54d325f9f1fd052928b8e4e2..82b5c67282e250b811fe893bc41265b3c6f8d401 100644 (file)
@@ -1,6 +1,6 @@
 #include "clar_libgit2.h"
 
-#include "util.h"
+#include "date.h"
 
 void test_date_date__overflow(void)
 {
@@ -8,8 +8,15 @@ void test_date_date__overflow(void)
    git_time_t d2038, d2039;
 
    /* This is expected to fail on a 32-bit machine. */
-   cl_git_pass(git__date_parse(&d2038, "2038-1-1"));
-   cl_git_pass(git__date_parse(&d2039, "2039-1-1"));
+   cl_git_pass(git_date_parse(&d2038, "2038-1-1"));
+   cl_git_pass(git_date_parse(&d2039, "2039-1-1"));
    cl_assert(d2038 < d2039);
 #endif
 }
+
+void test_date_date__invalid_date(void)
+{
+   git_time_t d;
+   cl_git_fail(git_date_parse(&d, ""));
+   cl_git_fail(git_date_parse(&d, "NEITHER_INTEGER_NOR_DATETIME"));
+}
index d98c1f05efa2a82bd7bd9566029055fcdab094cf..b0bbcfce514169740ae8c34eb99821fe99ca41f6 100644 (file)
@@ -1,40 +1,37 @@
 #include "clar_libgit2.h"
 
-#include "util.h"
+#include "date.h"
 
 void test_date_rfc2822__format_rfc2822_no_offset(void)
 {
        git_time t = {1397031663, 0};
-       char buf[GIT_DATE_RFC2822_SZ];
+       git_str buf = GIT_STR_INIT;
 
-       cl_git_pass(git__date_rfc2822_fmt(buf, sizeof(buf), &t));
-       cl_assert(strcmp(buf, "Wed, 9 Apr 2014 08:21:03 +0000") == 0);
+       cl_git_pass(git_date_rfc2822_fmt(&buf, t.time, t.offset));
+       cl_assert_equal_s("Wed, 9 Apr 2014 08:21:03 +0000", buf.ptr);
+
+       git_str_dispose(&buf);
 }
 
 void test_date_rfc2822__format_rfc2822_positive_offset(void)
 {
        git_time t = {1397031663, 120};
-       char buf[GIT_DATE_RFC2822_SZ];
+       git_str buf = GIT_STR_INIT;
+
+       cl_git_pass(git_date_rfc2822_fmt(&buf, t.time, t.offset));
+       cl_assert_equal_s("Wed, 9 Apr 2014 10:21:03 +0200", buf.ptr);
 
-       cl_git_pass(git__date_rfc2822_fmt(buf, sizeof(buf), &t));
-       cl_assert(strcmp(buf, "Wed, 9 Apr 2014 10:21:03 +0200") == 0);
+       git_str_dispose(&buf);
 }
 
 void test_date_rfc2822__format_rfc2822_negative_offset(void)
 {
        git_time t = {1397031663, -120};
-       char buf[GIT_DATE_RFC2822_SZ];
+       git_str buf = GIT_STR_INIT;
 
-       cl_git_pass(git__date_rfc2822_fmt(buf, sizeof(buf), &t));
-       cl_assert(strcmp(buf, "Wed, 9 Apr 2014 06:21:03 -0200") == 0);
-}
-
-void test_date_rfc2822__format_rfc2822_buffer_too_small(void)
-{
-       /* "Wed, 10 Apr 2014 08:21:03 +0000" */
-       git_time t = {1397031663 + 86400, 0};
-       char buf[GIT_DATE_RFC2822_SZ-1];
+       cl_git_pass(git_date_rfc2822_fmt(&buf, t.time, t.offset));
+       cl_assert_equal_s("Wed, 9 Apr 2014 06:21:03 -0200", buf.ptr);
 
-       cl_git_fail(git__date_rfc2822_fmt(buf, sizeof(buf), &t));
+       git_str_dispose(&buf);
 }
 
index 26ca4efd82598ec78aef60454f70da52084f4cbe..ba67ca46b22c2446e9062ad19e7d2ad388f33e51 100644 (file)
@@ -32,7 +32,7 @@ void test_describe_describe__describe_a_repo_with_no_refs(void)
 {
        git_repository *repo;
        git_describe_options opts = GIT_DESCRIBE_OPTIONS_INIT;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_object *object;
        git_describe_result *result = NULL;
 
@@ -50,6 +50,6 @@ void test_describe_describe__describe_a_repo_with_no_refs(void)
 
        git_describe_result_free(result);
        git_object_free(object);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        cl_git_sandbox_cleanup();
 }
index 80217dcf0c654508eeb71d52e9ac5df5164f5d1c..3df3b7c596608fe0d5f60c842aa359473b63208c 100644 (file)
@@ -18,7 +18,7 @@ void assert_describe(
        cl_git_pass(git_describe_commit(&result, object, opts));
        cl_git_pass(git_describe_format(&label, result, fmt_opts));
 
-       cl_must_pass(wildmatch(expected_output, git_buf_cstr(&label), 0));
+       cl_must_pass(wildmatch(expected_output, label.ptr, 0));
 
        git_describe_result_free(result);
        git_object_free(object);
@@ -37,7 +37,7 @@ void assert_describe_workdir(
        cl_git_pass(git_describe_workdir(&result, repo, opts));
        cl_git_pass(git_describe_format(&label, result, fmt_opts));
 
-       cl_must_pass(wildmatch(expected_output, git_buf_cstr(&label), 0));
+       cl_must_pass(wildmatch(expected_output, label.ptr, 0));
 
        git_describe_result_free(result);
        git_buf_dispose(&label);
index 16a0638e39214bea0e5c0f8eb539212fa8235d83..43e8c5e1932b3b5542c6b327db8345b4ea2847c4 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 
 extern void assert_describe(
        const char *expected_output,
index 7edf37b5129c8c46ff57aecbaa7e80d831774dc4..4e71f39c640641c45ffc4bf25bd0ef9cba550dd9 100644 (file)
@@ -2,7 +2,6 @@
 
 #include "git2/sys/diff.h"
 
-#include "buffer.h"
 #include "delta.h"
 #include "filebuf.h"
 #include "repository.h"
@@ -18,7 +17,7 @@ void test_diff_binary__cleanup(void)
        cl_git_sandbox_cleanup();
 }
 
-void test_patch(
+static void test_patch(
        const char *one,
        const char *two,
        const git_diff_options *opts,
@@ -53,7 +52,7 @@ void test_patch(
 
        cl_assert_equal_s(expected, actual.ptr);
 
-       git_buf_clear(&actual);
+       git_buf_dispose(&actual);
        cl_git_pass(git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, git_diff_print_callback__to_buf, &actual));
 
        cl_assert_equal_s(expected, actual.ptr);
@@ -197,7 +196,7 @@ void test_diff_binary__delete(void)
 void test_diff_binary__delta(void)
 {
        git_index *index;
-       git_buf contents = GIT_BUF_INIT;
+       git_str contents = GIT_STR_INIT;
        size_t i;
        git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
        const char *expected =
@@ -239,7 +238,7 @@ void test_diff_binary__delta(void)
                expected);
 
        git_index_free(index);
-       git_buf_dispose(&contents);
+       git_str_dispose(&contents);
 }
 
 void test_diff_binary__delta_append(void)
@@ -283,7 +282,7 @@ void test_diff_binary__empty_for_no_diff(void)
        git_commit *commit;
        git_tree *tree;
        git_diff *diff;
-       git_buf actual = GIT_BUF_INIT;
+       git_str actual = GIT_STR_INIT;
 
        opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
        opts.id_abbrev = GIT_OID_HEXSZ;
@@ -299,7 +298,7 @@ void test_diff_binary__empty_for_no_diff(void)
 
        cl_assert_equal_s("", actual.ptr);
 
-       git_buf_dispose(&actual);
+       git_str_dispose(&actual);
        git_diff_free(diff);
        git_commit_free(commit);
        git_tree_free(tree);
@@ -359,24 +358,24 @@ static int print_cb(
        const git_diff_line *line,
        void *payload)
 {
-       git_buf *buf = (git_buf *)payload;
+       git_str *buf = (git_str *)payload;
 
        GIT_UNUSED(delta);
 
        if (hunk)
-               git_buf_put(buf, hunk->header, hunk->header_len);
+               git_str_put(buf, hunk->header, hunk->header_len);
 
        if (line)
-               git_buf_put(buf, line->content, line->content_len);
+               git_str_put(buf, line->content, line->content_len);
 
-       return git_buf_oom(buf) ? -1 : 0;
+       return git_str_oom(buf) ? -1 : 0;
 }
 
 void test_diff_binary__print_patch_from_diff(void)
 {
        git_index *index;
        git_diff *diff;
-       git_buf actual = GIT_BUF_INIT;
+       git_str actual = GIT_STR_INIT;
        git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
        const char *expected =
                "diff --git a/untimely.txt b/untimely.txt\n" \
@@ -403,7 +402,7 @@ void test_diff_binary__print_patch_from_diff(void)
 
        cl_assert_equal_s(expected, actual.ptr);
 
-       git_buf_dispose(&actual);
+       git_str_dispose(&actual);
        git_diff_free(diff);
        git_index_free(index);
 }
@@ -411,13 +410,13 @@ void test_diff_binary__print_patch_from_diff(void)
 struct diff_data {
        char *old_path;
        git_oid old_id;
-       git_buf old_binary_base85;
+       git_str old_binary_base85;
        size_t old_binary_inflatedlen;
        git_diff_binary_t old_binary_type;
 
        char *new_path;
        git_oid new_id;
-       git_buf new_binary_base85;
+       git_str new_binary_base85;
        size_t new_binary_inflatedlen;
        git_diff_binary_t new_binary_type;
 };
@@ -452,12 +451,12 @@ static int binary_cb(
 
        GIT_UNUSED(delta);
 
-       git_buf_encode_base85(&diff_data->old_binary_base85,
+       git_str_encode_base85(&diff_data->old_binary_base85,
                binary->old_file.data, binary->old_file.datalen);
        diff_data->old_binary_inflatedlen = binary->old_file.inflatedlen;
        diff_data->old_binary_type = binary->old_file.type;
 
-       git_buf_encode_base85(&diff_data->new_binary_base85,
+       git_str_encode_base85(&diff_data->new_binary_base85,
                binary->new_file.data, binary->new_file.datalen);
        diff_data->new_binary_inflatedlen = binary->new_file.inflatedlen;
        diff_data->new_binary_type = binary->new_file.type;
@@ -541,6 +540,6 @@ void test_diff_binary__blob_to_blob(void)
        git__free(diff_data.old_path);
        git__free(diff_data.new_path);
 
-       git_buf_dispose(&diff_data.old_binary_base85);
-       git_buf_dispose(&diff_data.new_binary_base85);
+       git_str_dispose(&diff_data.old_binary_base85);
+       git_str_dispose(&diff_data.new_binary_base85);
 }
index 50edf6bc061a8c5c71cf02c9d01897f5c4586d7d..d2f42207d7d00f5e7bf35fe4f987bdf557b18fa1 100644 (file)
@@ -604,12 +604,28 @@ void test_diff_blob__can_correctly_detect_a_binary_blob_as_binary(void)
        cl_assert_equal_i(true, git_blob_is_binary(alien));
 }
 
+void test_diff_blob__can_correctly_detect_binary_blob_data_as_binary(void)
+{
+       /* alien.png */
+       const char *content = git_blob_rawcontent(alien);
+       size_t len = (size_t)git_blob_rawsize(alien);
+       cl_assert_equal_i(true, git_blob_data_is_binary(content, len));
+}
+
 void test_diff_blob__can_correctly_detect_a_textual_blob_as_non_binary(void)
 {
        /* tests/resources/attr/root_test4.txt */
        cl_assert_equal_i(false, git_blob_is_binary(d));
 }
 
+void test_diff_blob__can_correctly_detect_textual_blob_data_as_non_binary(void)
+{
+       /* tests/resources/attr/root_test4.txt */
+       const char *content = git_blob_rawcontent(d);
+       size_t len = (size_t)git_blob_rawsize(d);
+       cl_assert_equal_i(false, git_blob_data_is_binary(content, len));
+}
+
 /*
  * git_diff_blob_to_buffer tests
  */
@@ -915,7 +931,7 @@ void test_diff_blob__using_path_and_attributes(void)
                "+More lines\n"
                "+And more\n"
                "+Go here\n", buf.ptr);
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        git_patch_free(p);
 
        cl_git_pass(git_patch_from_blob_and_buffer(
@@ -925,7 +941,7 @@ void test_diff_blob__using_path_and_attributes(void)
                "diff --git a/zzz.binary b/zzz.binary\n"
                "index 45141a7..75b0dbb 100644\n"
                "Binary files a/zzz.binary and b/zzz.binary differ\n", buf.ptr);
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        git_patch_free(p);
 
        cl_git_pass(git_patch_from_blob_and_buffer(
@@ -940,7 +956,7 @@ void test_diff_blob__using_path_and_attributes(void)
                "+More lines\n"
                "+And more\n"
                "+Go here\n", buf.ptr);
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        git_patch_free(p);
 
        cl_git_pass(git_patch_from_blob_and_buffer(
@@ -955,7 +971,7 @@ void test_diff_blob__using_path_and_attributes(void)
                "+More lines\n"
                "+And more\n"
                "+Go here\n", buf.ptr);
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        git_patch_free(p);
 
        /* "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\n0123456789\n"
@@ -971,7 +987,7 @@ void test_diff_blob__using_path_and_attributes(void)
                "diff --git a/zzz.normal b/zzz.normal\n"
                "index b435cd5..1604519 100644\n"
                "Binary files a/zzz.normal and b/zzz.normal differ\n", buf.ptr);
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        git_patch_free(p);
 
        cl_git_pass(git_patch_from_blob_and_buffer(
@@ -985,7 +1001,7 @@ void test_diff_blob__using_path_and_attributes(void)
                "@@ -3 +3 @@\n"
                "-0123456789\n"
                "+replace a line\n", buf.ptr);
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        git_patch_free(p);
 
        cl_git_pass(git_patch_from_blob_and_buffer(
@@ -999,7 +1015,7 @@ void test_diff_blob__using_path_and_attributes(void)
                "@@ -3 +3 @@\n"
                "-0123456789\n"
                "+replace a line\n", buf.ptr);
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        git_patch_free(p);
 
        cl_git_pass(git_patch_from_blob_and_buffer(
@@ -1013,7 +1029,7 @@ void test_diff_blob__using_path_and_attributes(void)
                "@@ -3 +3 @@ 0123456789\n"
                "-0123456789\n"
                "+replace a line\n", buf.ptr);
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        git_patch_free(p);
 
        git_buf_dispose(&buf);
index cace40967f8db337521c6fb89161801cef9a6ed2..304a54b56dccec34ddf1738a463cb90cb5d01e3e 100644 (file)
@@ -178,7 +178,8 @@ void test_diff_drivers__builtins(void)
 {
        git_diff *diff;
        git_patch *patch;
-       git_buf file = GIT_BUF_INIT, actual = GIT_BUF_INIT, expected = GIT_BUF_INIT;
+       git_str file = GIT_STR_INIT, expected = GIT_STR_INIT;
+       git_buf actual = GIT_BUF_INIT;
        git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
        git_vector files = GIT_VECTOR_INIT;
        size_t i;
@@ -186,7 +187,7 @@ void test_diff_drivers__builtins(void)
 
        g_repo = cl_git_sandbox_init("userdiff");
 
-       cl_git_pass(git_path_dirload(&files, "userdiff/files", 9, 0));
+       cl_git_pass(git_fs_path_dirload(&files, "userdiff/files", 9, 0));
 
        opts.interhunk_lines = 1;
        opts.context_lines = 1;
@@ -205,15 +206,15 @@ void test_diff_drivers__builtins(void)
                cl_git_pass(git_patch_from_diff(&patch, diff, 0));
                cl_git_pass(git_patch_to_buf(&actual, patch));
 
-               git_buf_sets(&expected, "userdiff/expected/nodriver/diff.");
-               git_buf_puts(&expected, extension);
+               git_str_sets(&expected, "userdiff/expected/nodriver/diff.");
+               git_str_puts(&expected, extension);
                cl_git_pass(git_futils_readbuffer(&expected, expected.ptr));
 
                overwrite_filemode(expected.ptr, &actual);
 
                cl_assert_equal_s(expected.ptr, actual.ptr);
 
-               git_buf_clear(&actual);
+               git_buf_dispose(&actual);
                git_patch_free(patch);
                git_diff_free(diff);
 
@@ -230,24 +231,24 @@ void test_diff_drivers__builtins(void)
                cl_git_pass(git_patch_from_diff(&patch, diff, 0));
                cl_git_pass(git_patch_to_buf(&actual, patch));
 
-               git_buf_sets(&expected, "userdiff/expected/driver/diff.");
-               git_buf_puts(&expected, extension);
+               git_str_sets(&expected, "userdiff/expected/driver/diff.");
+               git_str_puts(&expected, extension);
                cl_git_pass(git_futils_readbuffer(&expected, expected.ptr));
 
                overwrite_filemode(expected.ptr, &actual);
 
                cl_assert_equal_s(expected.ptr, actual.ptr);
 
-               git_buf_clear(&actual);
+               git_buf_dispose(&actual);
                git_patch_free(patch);
                git_diff_free(diff);
 
                git__free(path);
        }
 
-       git_buf_dispose(&file);
        git_buf_dispose(&actual);
-       git_buf_dispose(&expected);
+       git_str_dispose(&file);
+       git_str_dispose(&expected);
        git_vector_free(&files);
 }
 
diff --git a/tests/diff/externalmodifications.c b/tests/diff/externalmodifications.c
new file mode 100644 (file)
index 0000000..df62c33
--- /dev/null
@@ -0,0 +1,133 @@
+#include "clar_libgit2.h"
+#include "../checkout/checkout_helpers.h"
+
+#include "index.h"
+#include "repository.h"
+
+static git_repository *g_repo;
+
+void test_diff_externalmodifications__initialize(void)
+{
+       g_repo = cl_git_sandbox_init("testrepo2");
+}
+
+void test_diff_externalmodifications__cleanup(void)
+{
+       cl_git_sandbox_cleanup();
+       g_repo = NULL;
+}
+
+void test_diff_externalmodifications__file_becomes_smaller(void)
+{
+       git_index *index;
+       git_diff *diff;
+       git_patch* patch;
+       git_str path = GIT_STR_INIT;
+       char big_string[500001];
+
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(g_repo), "README"));
+
+       /* Modify the file with a large string */
+       memset(big_string, '\n', sizeof(big_string) - 1);
+       big_string[sizeof(big_string) - 1] = '\0';
+       cl_git_mkfile(path.ptr, big_string);
+
+       /* Get a diff */
+       cl_git_pass(git_repository_index(&index, g_repo));
+       cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, NULL));
+       cl_assert_equal_i(1, git_diff_num_deltas(diff));
+       cl_assert_equal_i(500000, git_diff_get_delta(diff, 0)->new_file.size);
+
+       /* Simulate file modification after we've gotten the diff.
+        * Write a shorter string to ensure that we don't mmap 500KB from
+        * the previous revision, which would most likely crash. */
+       cl_git_mkfile(path.ptr, "hello");
+
+       /* Attempt to get a patch */
+       cl_git_fail(git_patch_from_diff(&patch, diff, 0));
+
+       git_index_free(index);
+       git_diff_free(diff);
+       git_str_dispose(&path);
+}
+
+void test_diff_externalmodifications__file_becomes_empty(void)
+{
+       git_index *index;
+       git_diff *diff;
+       git_patch* patch;
+       git_str path = GIT_STR_INIT;
+
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(g_repo), "README"));
+
+       /* Modify the file */
+       cl_git_mkfile(path.ptr, "hello");
+
+       /* Get a diff */
+       cl_git_pass(git_repository_index(&index, g_repo));
+       cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, NULL));
+       cl_assert_equal_i(1, git_diff_num_deltas(diff));
+       cl_assert_equal_i(5, git_diff_get_delta(diff, 0)->new_file.size);
+
+       /* Empty out the file after we've gotten the diff */
+       cl_git_mkfile(path.ptr, "");
+
+       /* Attempt to get a patch */
+       cl_git_fail(git_patch_from_diff(&patch, diff, 0));
+
+       git_index_free(index);
+       git_diff_free(diff);
+       git_str_dispose(&path);
+}
+
+void test_diff_externalmodifications__file_deleted(void)
+{
+       git_index *index;
+       git_diff *diff;
+       git_patch* patch;
+       git_str path = GIT_STR_INIT;
+
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(g_repo), "README"));
+
+       /* Get a diff */
+       cl_git_pass(git_repository_index(&index, g_repo));
+       cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, NULL));
+       cl_assert_equal_i(0, git_diff_num_deltas(diff));
+
+       /* Delete the file */
+       cl_git_rmfile(path.ptr);
+
+       /* Attempt to get a patch */
+       cl_git_fail(git_patch_from_diff(&patch, diff, 0));
+
+       git_index_free(index);
+       git_diff_free(diff);
+       git_str_dispose(&path);
+}
+
+void test_diff_externalmodifications__empty_file_becomes_non_empty(void)
+{
+       git_index *index;
+       git_diff *diff;
+       git_patch* patch;
+       git_str path = GIT_STR_INIT;
+
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(g_repo), "README"));
+
+       /* Empty out the file */
+       cl_git_mkfile(path.ptr, "");
+
+       /* Get a diff */
+       cl_git_pass(git_repository_index(&index, g_repo));
+       cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, NULL));
+       cl_assert_equal_i(1, git_diff_num_deltas(diff));
+       cl_assert_equal_i(0, git_diff_get_delta(diff, 0)->new_file.size);
+
+       /* Simulate file modification after we've gotten the diff */
+       cl_git_mkfile(path.ptr, "hello");
+       cl_git_fail(git_patch_from_diff(&patch, diff, 0));
+
+       git_index_free(index);
+       git_diff_free(diff);
+       git_str_dispose(&path);
+}
index ea7aa070fa252f862e244c3d38a8bc149a32b52e..612804c4288bb2f84272934cd76b48f80c8c071b 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar.h"
 #include "clar_libgit2.h"
 
-#include "buffer.h"
 #include "commit.h"
 #include "diff.h"
 #include "diff_generate.h"
@@ -41,12 +40,12 @@ static void assert_email_match(
        cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
        cl_git_pass(git_diff_format_email(&buf, diff, opts));
 
-       cl_assert_equal_s(expected, git_buf_cstr(&buf));
-       git_buf_clear(&buf);
+       cl_assert_equal_s(expected, buf.ptr);
+       git_buf_dispose(&buf);
 
        cl_git_pass(git_diff_commit_as_email(
                &buf, repo, commit, 1, 1, opts->flags, NULL));
-       cl_assert_equal_s(expected, git_buf_cstr(&buf));
+       cl_assert_equal_s(expected, buf.ptr);
 
        git_diff_free(diff);
        git_commit_free(commit);
@@ -258,7 +257,7 @@ void test_diff_format_email__multiple(void)
        cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
        cl_git_pass(git_diff_format_email(&buf, diff, &opts));
 
-       cl_assert_equal_s(email, git_buf_cstr(&buf));
+       cl_assert_equal_s(email, buf.ptr);
 
        git_diff_free(diff);
        git_commit_free(commit);
index 6b6e6645e4534b28a8fa69bc2bafc7299bc1efc2..9c3f798e4aab143fd8744edfe95d47674c45e779 100644 (file)
@@ -39,21 +39,21 @@ void test_diff_parse__nonpatches_fail_with_notfound(void)
 static void test_parse_invalid_diff(const char *invalid_diff)
 {
        git_diff *diff;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        /* throw some random (legitimate) diffs in with the given invalid
         * one.
         */
-       git_buf_puts(&buf, PATCH_ORIGINAL_TO_CHANGE_FIRSTLINE);
-       git_buf_puts(&buf, PATCH_BINARY_DELTA);
-       git_buf_puts(&buf, invalid_diff);
-       git_buf_puts(&buf, PATCH_ORIGINAL_TO_CHANGE_MIDDLE);
-       git_buf_puts(&buf, PATCH_BINARY_LITERAL);
+       git_str_puts(&buf, PATCH_ORIGINAL_TO_CHANGE_FIRSTLINE);
+       git_str_puts(&buf, PATCH_BINARY_DELTA);
+       git_str_puts(&buf, invalid_diff);
+       git_str_puts(&buf, PATCH_ORIGINAL_TO_CHANGE_MIDDLE);
+       git_str_puts(&buf, PATCH_BINARY_LITERAL);
 
        cl_git_fail_with(GIT_ERROR,
                git_diff_from_buffer(&diff, buf.ptr, buf.size));
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 }
 
 void test_diff_parse__exact_rename(void)
@@ -431,6 +431,32 @@ void test_diff_parse__new_file_with_space(void)
        git_diff_free(diff);
 }
 
+void test_diff_parse__new_file_with_space_and_regenerate_patch(void)
+{
+       const char *content = PATCH_ORIGINAL_NEW_FILE_WITH_SPACE;
+       git_diff *diff = NULL;
+       git_buf buf = GIT_BUF_INIT;
+
+       cl_git_pass(git_diff_from_buffer(&diff, content, strlen(content)));
+       cl_git_pass(git_diff_to_buf(&buf, diff, GIT_DIFF_FORMAT_PATCH));
+
+       git_buf_dispose(&buf);
+       git_diff_free(diff);
+}
+
+void test_diff_parse__delete_file_with_space_and_regenerate_patch(void)
+{
+       const char *content = PATCH_DELETE_FILE_WITH_SPACE;
+       git_diff *diff = NULL;
+       git_buf buf = GIT_BUF_INIT;
+
+       cl_git_pass(git_diff_from_buffer(&diff, content, strlen(content)));
+       cl_git_pass(git_diff_to_buf(&buf, diff, GIT_DIFF_FORMAT_PATCH));
+
+       git_buf_dispose(&buf);
+       git_diff_free(diff);
+}
+
 void test_diff_parse__crlf(void)
 {
        const char *text = PATCH_CRLF;
index d288bba58aab090b913537ab68c2445f5235a9c5..8945afc26a8c55bbc7f4d2f1b6156225d03cddb1 100644 (file)
@@ -208,7 +208,7 @@ void test_diff_patch__config_options(void)
        cl_git_pass(git_patch_to_buf(&buf, patch));
        cl_assert_equal_s(expected1, buf.ptr);
 
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        git_patch_free(patch);
        git_diff_free(diff);
 
@@ -219,7 +219,7 @@ void test_diff_patch__config_options(void)
        cl_git_pass(git_patch_to_buf(&buf, patch));
        cl_assert_equal_s(expected2, buf.ptr);
 
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        git_patch_free(patch);
        git_diff_free(diff);
 
@@ -233,7 +233,7 @@ void test_diff_patch__config_options(void)
        cl_git_pass(git_patch_to_buf(&buf, patch));
        cl_assert_equal_s(expected3, buf.ptr);
 
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        git_patch_free(patch);
        git_diff_free(diff);
 
@@ -247,7 +247,7 @@ void test_diff_patch__config_options(void)
        cl_git_pass(git_patch_to_buf(&buf, patch));
        cl_assert_equal_s(expected4, buf.ptr);
 
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        git_patch_free(patch);
        git_diff_free(diff);
 
@@ -267,7 +267,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void)
        const git_diff_hunk *hunk;
        const git_diff_line *line;
        size_t hunklen;
-       git_buf old_content = GIT_BUF_INIT, actual = GIT_BUF_INIT;
+       git_str old_content = GIT_STR_INIT, actual = GIT_STR_INIT;
        const char *new_content = "The Song of Seven Cities\n------------------------\n\nI WAS Lord of Cities very sumptuously builded.\nSeven roaring Cities paid me tribute from afar.\nIvory their outposts were--the guardrooms of them gilded,\nAnd garrisoned with Amazons invincible in war.\n\nThis is some new text;\nNot as good as the old text;\nBut here it is.\n\nSo they warred and trafficked only yesterday, my Cities.\nTo-day there is no mark or mound of where my Cities stood.\nFor the River rose at midnight and it washed away my Cities.\nThey are evened with Atlantis and the towns before the Flood.\n\nRain on rain-gorged channels raised the water-levels round them,\nFreshet backed on freshet swelled and swept their world from sight,\nTill the emboldened floods linked arms and, flashing forward, drowned them--\nDrowned my Seven Cities and their peoples in one night!\n\nLow among the alders lie their derelict foundations,\nThe beams wherein they trusted and the plinths whereon they built--\nMy rulers and their treasure and their unborn populations,\nDead, destroyed, aborted, and defiled with mud and silt!\n\nAnother replacement;\nBreaking up the poem;\nGenerating some hunks.\n\nTo the sound of trumpets shall their seed restore my Cities\nWealthy and well-weaponed, that once more may I behold\nAll the world go softly when it walks before my Cities,\nAnd the horses and the chariots fleeing from them as of old!\n\n  -- Rudyard Kipling\n";
 
        g_repo = cl_git_sandbox_init("renames");
@@ -311,7 +311,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void)
 
        cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 0));
        cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin);
-       cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
+       cl_git_pass(git_str_set(&actual, line->content, line->content_len));
        cl_assert_equal_s("Ivory their outposts were--the guardrooms of them gilded,\n", actual.ptr);
        cl_assert_equal_i(6, line->old_lineno);
        cl_assert_equal_i(6, line->new_lineno);
@@ -319,7 +319,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void)
 
        cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 3));
        cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin);
-       cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
+       cl_git_pass(git_str_set(&actual, line->content, line->content_len));
        cl_assert_equal_s("All the world went softly when it walked before my Cities--\n", actual.ptr);
        cl_assert_equal_i(9, line->old_lineno);
        cl_assert_equal_i(-1, line->new_lineno);
@@ -327,7 +327,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void)
 
        cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 12));
        cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin);
-       cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
+       cl_git_pass(git_str_set(&actual, line->content, line->content_len));
        cl_assert_equal_s("This is some new text;\n", actual.ptr);
        cl_assert_equal_i(-1, line->old_lineno);
        cl_assert_equal_i(9, line->new_lineno);
@@ -348,7 +348,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void)
 
        cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 0));
        cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin);
-       cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
+       cl_git_pass(git_str_set(&actual, line->content, line->content_len));
        cl_assert_equal_s("My rulers and their treasure and their unborn populations,\n", actual.ptr);
        cl_assert_equal_i(31, line->old_lineno);
        cl_assert_equal_i(25, line->new_lineno);
@@ -356,7 +356,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void)
 
        cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 3));
        cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin);
-       cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
+       cl_git_pass(git_str_set(&actual, line->content, line->content_len));
        cl_assert_equal_s("The Daughters of the Palace whom they cherished in my Cities,\n", actual.ptr);
        cl_assert_equal_i(34, line->old_lineno);
        cl_assert_equal_i(-1, line->new_lineno);
@@ -364,7 +364,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void)
 
        cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 12));
        cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin);
-       cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
+       cl_git_pass(git_str_set(&actual, line->content, line->content_len));
        cl_assert_equal_s("Another replacement;\n", actual.ptr);
        cl_assert_equal_i(-1, line->old_lineno);
        cl_assert_equal_i(28, line->new_lineno);
@@ -375,7 +375,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void)
 
        /* Let's check line numbers when there is no newline */
 
-       git_buf_rtrim(&old_content);
+       git_str_rtrim(&old_content);
        cl_git_rewritefile("renames/songof7cities.txt", old_content.ptr);
 
        cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, head, &opt));
@@ -403,35 +403,35 @@ void test_diff_patch__hunks_have_correct_line_numbers(void)
 
        cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 1));
        cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin);
-       cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
+       cl_git_pass(git_str_set(&actual, line->content, line->content_len));
        cl_assert_equal_s("And the horses and the chariots fleeing from them as of old!\n", actual.ptr);
        cl_assert_equal_i(47, line->old_lineno);
        cl_assert_equal_i(47, line->new_lineno);
 
        cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 2));
        cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin);
-       cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
+       cl_git_pass(git_str_set(&actual, line->content, line->content_len));
        cl_assert_equal_s("\n", actual.ptr);
        cl_assert_equal_i(48, line->old_lineno);
        cl_assert_equal_i(48, line->new_lineno);
 
        cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 3));
        cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin);
-       cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
+       cl_git_pass(git_str_set(&actual, line->content, line->content_len));
        cl_assert_equal_s("  -- Rudyard Kipling\n", actual.ptr);
        cl_assert_equal_i(49, line->old_lineno);
        cl_assert_equal_i(-1, line->new_lineno);
 
        cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 4));
        cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin);
-       cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
+       cl_git_pass(git_str_set(&actual, line->content, line->content_len));
        cl_assert_equal_s("  -- Rudyard Kipling", actual.ptr);
        cl_assert_equal_i(-1, line->old_lineno);
        cl_assert_equal_i(49, line->new_lineno);
 
        cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 5));
        cl_assert_equal_i(GIT_DIFF_LINE_DEL_EOFNL, (int)line->origin);
-       cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
+       cl_git_pass(git_str_set(&actual, line->content, line->content_len));
        cl_assert_equal_s("\n\\ No newline at end of file\n", actual.ptr);
        cl_assert_equal_i(-1, line->old_lineno);
        cl_assert_equal_i(49, line->new_lineno);
@@ -439,8 +439,8 @@ void test_diff_patch__hunks_have_correct_line_numbers(void)
        git_patch_free(patch);
        git_diff_free(diff);
 
-       git_buf_dispose(&actual);
-       git_buf_dispose(&old_content);
+       git_str_dispose(&actual);
+       git_str_dispose(&old_content);
        git_tree_free(head);
 }
 
@@ -532,7 +532,7 @@ static void check_single_patch_stats(
 void test_diff_patch__line_counts_with_eofnl(void)
 {
        git_config *cfg;
-       git_buf content = GIT_BUF_INIT;
+       git_str content = GIT_STR_INIT;
        const char *end;
        git_index *index;
        const char *expected =
@@ -565,15 +565,15 @@ void test_diff_patch__line_counts_with_eofnl(void)
 
        /* remove first line */
 
-       end = git_buf_cstr(&content) + git_buf_find(&content, '\n') + 1;
-       git_buf_consume(&content, end);
+       end = git_str_cstr(&content) + git_str_find(&content, '\n') + 1;
+       git_str_consume(&content, end);
        cl_git_rewritefile("renames/songof7cities.txt", content.ptr);
 
        check_single_patch_stats(g_repo, 1, 0, 1, 3, NULL, NULL);
 
        /* remove trailing whitespace */
 
-       git_buf_rtrim(&content);
+       git_str_rtrim(&content);
        cl_git_rewritefile("renames/songof7cities.txt", content.ptr);
 
        check_single_patch_stats(g_repo, 2, 1, 2, 6, NULL, NULL);
@@ -585,7 +585,7 @@ void test_diff_patch__line_counts_with_eofnl(void)
        cl_git_pass(git_index_write(index));
        git_index_free(index);
 
-       cl_git_pass(git_buf_putc(&content, '\n'));
+       cl_git_pass(git_str_putc(&content, '\n'));
        cl_git_rewritefile("renames/songof7cities.txt", content.ptr);
 
        check_single_patch_stats(g_repo, 1, 1, 1, 3, NULL, NULL);
@@ -613,7 +613,7 @@ void test_diff_patch__line_counts_with_eofnl(void)
        check_single_patch_stats(
                g_repo, 1, 1, 1, 6, expected_sizes, expected);
 
-       git_buf_dispose(&content);
+       git_str_dispose(&content);
 }
 
 void test_diff_patch__can_strip_bad_utf8(void)
index bd25d29aaba782a35fe1e79a5ffa8e731e878f65..30e9ea43201701d4ed2b2fba84b38e902da7775a 100644 (file)
@@ -375,7 +375,7 @@ void test_diff_rename__not_exact_match(void)
        /* git diff -M -C --find-copies-harder --break-rewrites \
         *          1c068dee5790ef1580cfc4cd670915b48d790084 \
         *          19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13
-        * with ignore_space whitespace comparision
+        * with ignore_space whitespace comparison
         */
        cl_git_pass(git_diff_tree_to_tree(
                &diff, g_repo, old_tree, new_tree, &diffopts));
@@ -460,7 +460,7 @@ void test_diff_rename__working_directory_changes(void)
        git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
        git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT;
        diff_expects exp;
-       git_buf old_content = GIT_BUF_INIT, content = GIT_BUF_INIT;;
+       git_str old_content = GIT_STR_INIT, content = GIT_STR_INIT;;
 
        tree = resolve_commit_oid_to_tree(g_repo, sha0);
        diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED | GIT_DIFF_INCLUDE_UNTRACKED;
@@ -514,7 +514,7 @@ void test_diff_rename__working_directory_changes(void)
        cl_git_pass(
                git_futils_readbuffer(&old_content, "renames/songof7cities.txt"));
        cl_git_pass(
-               git_buf_lf_to_crlf(&content, &old_content));
+               git_str_lf_to_crlf(&content, &old_content));
        cl_git_pass(
                git_futils_writebuffer(&content, "renames/songof7cities.txt", 0, 0));
 
@@ -576,7 +576,7 @@ void test_diff_rename__working_directory_changes(void)
 
        cl_git_pass(git_oid_fromstr(&id, blobsha));
        cl_git_pass(git_blob_lookup(&blob, g_repo, &id));
-       cl_git_pass(git_buf_set(
+       cl_git_pass(git_str_set(
                &content, git_blob_rawcontent(blob), (size_t)git_blob_rawsize(blob)));
        cl_git_rewritefile("renames/songof7cities.txt", content.ptr);
        git_blob_free(blob);
@@ -604,8 +604,8 @@ void test_diff_rename__working_directory_changes(void)
        git_diff_free(diff);
 
        git_tree_free(tree);
-       git_buf_dispose(&content);
-       git_buf_dispose(&old_content);
+       git_str_dispose(&content);
+       git_str_dispose(&old_content);
 }
 
 void test_diff_rename__patch(void)
@@ -666,7 +666,7 @@ void test_diff_rename__patch(void)
 
 void test_diff_rename__file_exchange(void)
 {
-       git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT;
+       git_str c1 = GIT_STR_INIT, c2 = GIT_STR_INIT;
        git_index *index;
        git_tree *tree;
        git_diff *diff;
@@ -708,13 +708,13 @@ void test_diff_rename__file_exchange(void)
        git_tree_free(tree);
        git_index_free(index);
 
-       git_buf_dispose(&c1);
-       git_buf_dispose(&c2);
+       git_str_dispose(&c1);
+       git_str_dispose(&c2);
 }
 
 void test_diff_rename__file_exchange_three(void)
 {
-       git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT, c3 = GIT_BUF_INIT;
+       git_str c1 = GIT_STR_INIT, c2 = GIT_STR_INIT, c3 = GIT_STR_INIT;
        git_index *index;
        git_tree *tree;
        git_diff *diff;
@@ -760,14 +760,14 @@ void test_diff_rename__file_exchange_three(void)
        git_tree_free(tree);
        git_index_free(index);
 
-       git_buf_dispose(&c1);
-       git_buf_dispose(&c2);
-       git_buf_dispose(&c3);
+       git_str_dispose(&c1);
+       git_str_dispose(&c2);
+       git_str_dispose(&c3);
 }
 
 void test_diff_rename__file_partial_exchange(void)
 {
-       git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT;
+       git_str c1 = GIT_STR_INIT, c2 = GIT_STR_INIT;
        git_index *index;
        git_tree *tree;
        git_diff *diff;
@@ -779,7 +779,7 @@ void test_diff_rename__file_partial_exchange(void)
        cl_git_pass(git_futils_readbuffer(&c1, "renames/untimely.txt"));
        cl_git_pass(git_futils_writebuffer(&c1, "renames/songof7cities.txt", 0, 0));
        for (i = 0; i < 100; ++i)
-               cl_git_pass(git_buf_puts(&c2, "this is not the content you are looking for\n"));
+               cl_git_pass(git_str_puts(&c2, "this is not the content you are looking for\n"));
        cl_git_pass(git_futils_writebuffer(&c2, "renames/untimely.txt", 0, 0));
 
        cl_git_pass(
@@ -813,13 +813,13 @@ void test_diff_rename__file_partial_exchange(void)
        git_tree_free(tree);
        git_index_free(index);
 
-       git_buf_dispose(&c1);
-       git_buf_dispose(&c2);
+       git_str_dispose(&c1);
+       git_str_dispose(&c2);
 }
 
 void test_diff_rename__rename_and_copy_from_same_source(void)
 {
-       git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT;
+       git_str c1 = GIT_STR_INIT, c2 = GIT_STR_INIT;
        git_index *index;
        git_tree *tree;
        git_diff *diff;
@@ -831,9 +831,9 @@ void test_diff_rename__rename_and_copy_from_same_source(void)
         * and the second 2/3 of file into another new place
         */
        cl_git_pass(git_futils_readbuffer(&c1, "renames/songof7cities.txt"));
-       cl_git_pass(git_buf_set(&c2, c1.ptr, c1.size));
-       git_buf_truncate(&c1, c1.size * 2 / 3);
-       git_buf_consume(&c2, ((char *)c2.ptr) + (c2.size / 3));
+       cl_git_pass(git_str_set(&c2, c1.ptr, c1.size));
+       git_str_truncate(&c1, c1.size * 2 / 3);
+       git_str_consume(&c2, ((char *)c2.ptr) + (c2.size / 3));
        cl_git_pass(git_futils_writebuffer(&c1, "renames/song_a.txt", 0, 0));
        cl_git_pass(git_futils_writebuffer(&c2, "renames/song_b.txt", 0, 0));
 
@@ -870,13 +870,13 @@ void test_diff_rename__rename_and_copy_from_same_source(void)
        git_tree_free(tree);
        git_index_free(index);
 
-       git_buf_dispose(&c1);
-       git_buf_dispose(&c2);
+       git_str_dispose(&c1);
+       git_str_dispose(&c2);
 }
 
 void test_diff_rename__from_deleted_to_split(void)
 {
-       git_buf c1 = GIT_BUF_INIT;
+       git_str c1 = GIT_STR_INIT;
        git_index *index;
        git_tree *tree;
        git_diff *diff;
@@ -924,7 +924,7 @@ void test_diff_rename__from_deleted_to_split(void)
        git_tree_free(tree);
        git_index_free(index);
 
-       git_buf_dispose(&c1);
+       git_str_dispose(&c1);
 }
 
 struct rename_expected
@@ -938,7 +938,7 @@ struct rename_expected
        size_t idx;
 };
 
-int test_names_expected(const git_diff_delta *delta, float progress, void *p)
+static int test_names_expected(const git_diff_delta *delta, float progress, void *p)
 {
        struct rename_expected *expected = p;
 
@@ -967,7 +967,7 @@ void test_diff_rename__rejected_match_can_match_others(void)
        git_diff *diff;
        git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
        git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT;
-       git_buf one = GIT_BUF_INIT, two = GIT_BUF_INIT;
+       git_str one = GIT_STR_INIT, two = GIT_STR_INIT;
        unsigned int status[] = { GIT_DELTA_RENAMED, GIT_DELTA_RENAMED };
        const char *sources[] = { "Class1.cs", "Class2.cs" };
        const char *targets[] = { "ClassA.cs", "ClassB.cs" };
@@ -1024,25 +1024,25 @@ void test_diff_rename__rejected_match_can_match_others(void)
        git_index_free(index);
        git_reference_free(head);
        git_reference_free(selfsimilar);
-       git_buf_dispose(&one);
-       git_buf_dispose(&two);
+       git_str_dispose(&one);
+       git_str_dispose(&two);
 }
 
 static void write_similarity_file_two(const char *filename, size_t b_lines)
 {
-       git_buf contents = GIT_BUF_INIT;
+       git_str contents = GIT_STR_INIT;
        size_t i;
 
        for (i = 0; i < b_lines; i++)
-               git_buf_printf(&contents, "%02d - bbbbb\r\n", (int)(i+1));
+               git_str_printf(&contents, "%02d - bbbbb\r\n", (int)(i+1));
 
        for (i = b_lines; i < 50; i++)
-               git_buf_printf(&contents, "%02d - aaaaa%s", (int)(i+1), (i == 49 ? "" : "\r\n"));
+               git_str_printf(&contents, "%02d - aaaaa%s", (int)(i+1), (i == 49 ? "" : "\r\n"));
 
        cl_git_pass(
                git_futils_writebuffer(&contents, filename, O_RDWR|O_CREAT, 0777));
 
-       git_buf_dispose(&contents);
+       git_str_dispose(&contents);
 }
 
 void test_diff_rename__rejected_match_can_match_others_two(void)
@@ -1346,7 +1346,7 @@ void test_diff_rename__rewrite_on_single_file(void)
 
 void test_diff_rename__can_find_copy_to_split(void)
 {
-       git_buf c1 = GIT_BUF_INIT;
+       git_str c1 = GIT_STR_INIT;
        git_index *index;
        git_tree *tree;
        git_diff *diff;
@@ -1390,12 +1390,12 @@ void test_diff_rename__can_find_copy_to_split(void)
        git_tree_free(tree);
        git_index_free(index);
 
-       git_buf_dispose(&c1);
+       git_str_dispose(&c1);
 }
 
 void test_diff_rename__can_delete_unmodified_deltas(void)
 {
-       git_buf c1 = GIT_BUF_INIT;
+       git_str c1 = GIT_STR_INIT;
        git_index *index;
        git_tree *tree;
        git_diff *diff;
@@ -1438,7 +1438,7 @@ void test_diff_rename__can_delete_unmodified_deltas(void)
        git_tree_free(tree);
        git_index_free(index);
 
-       git_buf_dispose(&c1);
+       git_str_dispose(&c1);
 }
 
 void test_diff_rename__matches_config_behavior(void)
index 54572672ca4b4ec7fe65f5146fd95df7c9876b2e..f69dba9b30657695c1637fc883629c5703e53a2f 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar.h"
 #include "clar_libgit2.h"
 
-#include "buffer.h"
 #include "commit.h"
 #include "diff.h"
 #include "diff_generate.h"
@@ -53,11 +52,11 @@ void test_diff_stats__stat(void)
        cl_assert_equal_sz(3, git_diff_stats_deletions(_stats));
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0));
-       cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
+       cl_assert(strcmp(buf.ptr, stat) == 0);
        git_buf_dispose(&buf);
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 80));
-       cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
+       cl_assert(strcmp(buf.ptr, stat) == 0);
        git_buf_dispose(&buf);
 }
 
@@ -77,7 +76,7 @@ void test_diff_stats__multiple_hunks(void)
        cl_assert_equal_sz(4, git_diff_stats_deletions(_stats));
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -92,7 +91,7 @@ void test_diff_stats__numstat(void)
                &_stats, "cd471f0d8770371e1bc78bcbb38db4c7e4106bd2", false);
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_NUMBER, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -110,7 +109,7 @@ void test_diff_stats__shortstat(void)
        cl_assert_equal_sz(3, git_diff_stats_deletions(_stats));
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_SHORT, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -128,7 +127,7 @@ void test_diff_stats__shortstat_noinsertions(void)
        cl_assert_equal_sz(2, git_diff_stats_deletions(_stats));
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_SHORT, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -146,7 +145,7 @@ void test_diff_stats__shortstat_nodeletions(void)
        cl_assert_equal_sz(0, git_diff_stats_deletions(_stats));
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_SHORT, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -166,7 +165,7 @@ void test_diff_stats__rename(void)
        cl_assert_equal_sz(1, git_diff_stats_deletions(_stats));
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -186,7 +185,7 @@ void test_diff_stats__rename_nochanges(void)
        cl_assert_equal_sz(0, git_diff_stats_deletions(_stats));
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -206,7 +205,7 @@ void test_diff_stats__rename_and_modifiy(void)
        cl_assert_equal_sz(1, git_diff_stats_deletions(_stats));
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -225,7 +224,7 @@ void test_diff_stats__rename_in_subdirectory(void)
        cl_assert_equal_sz(0, git_diff_stats_deletions(_stats));
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -247,7 +246,7 @@ void test_diff_stats__rename_no_find(void)
        cl_assert_equal_sz(10, git_diff_stats_deletions(_stats));
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -269,7 +268,7 @@ void test_diff_stats__rename_nochanges_no_find(void)
        cl_assert_equal_sz(13, git_diff_stats_deletions(_stats));
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -290,7 +289,7 @@ void test_diff_stats__rename_and_modify_no_find(void)
        cl_assert_equal_sz(8, git_diff_stats_deletions(_stats));
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -309,7 +308,7 @@ void test_diff_stats__binary(void)
        cl_assert_equal_sz(0, git_diff_stats_deletions(_stats));
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -323,7 +322,7 @@ void test_diff_stats__binary_numstat(void)
                &_stats, "8d7523f6fcb2404257889abe0d96f093d9f524f9", false);
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_NUMBER, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -339,7 +338,7 @@ void test_diff_stats__mode_change(void)
                &_stats, "7ade76dd34bba4733cf9878079f9fd4a456a9189", false);
 
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL | GIT_DIFF_STATS_INCLUDE_SUMMARY, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
        git_buf_dispose(&buf);
 }
 
@@ -372,7 +371,7 @@ void test_diff_stats__new_file(void)
        cl_git_pass(git_diff_from_buffer(&diff, input, strlen(input)));
        cl_git_pass(git_diff_get_stats(&_stats, diff));
        cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL | GIT_DIFF_STATS_INCLUDE_SUMMARY, 0));
-       cl_assert_equal_s(stat, git_buf_cstr(&buf));
+       cl_assert_equal_s(stat, buf.ptr);
 
        git_buf_dispose(&buf);
        git_diff_free(diff);
index 93223ef7d4bb17bb670c9f2d8a082b9c3b59a3e0..0436ca5c8e86a6a773ae0ed1c27e15877477e2b2 100644 (file)
@@ -15,7 +15,7 @@ void test_diff_submodules__cleanup(void)
        cl_git_sandbox_cleanup();
 }
 
-#define get_buf_ptr(buf) ((buf)->asize ? (buf)->ptr : NULL)
+#define get_buf_ptr(buf) ((buf)->size ? (buf)->ptr : NULL)
 
 static void check_diff_patches_at_line(
        git_diff *diff, const char **expected,
index dfe4d254cca79f4f6fbd3a6bef23254a63b9c706..e03ee7b228f491379845526aaadbde693d307423 100644 (file)
@@ -320,7 +320,7 @@ void test_diff_tree__checks_options_version(void)
        err = git_error_last();
 }
 
-void process_tree_to_tree_diffing(
+static void process_tree_to_tree_diffing(
        const char *old_commit,
        const char *new_commit)
 {
index 00c52ff1b4c2c007fb313ce05755dcc6e245921b..cdf53faa1290075a44ad2edc382c98203896b6b1 100644 (file)
@@ -1,6 +1,7 @@
 #include "clar_libgit2.h"
 #include "diff_helpers.h"
 #include "repository.h"
+#include "index.h"
 #include "git2/sys/diff.h"
 #include "../checkout/checkout_helpers.h"
 
@@ -1252,7 +1253,7 @@ void test_diff_workdir__can_diff_empty_file(void)
        /* empty contents of file */
 
        cl_git_rewritefile("attr_index/README.txt", "");
-       cl_git_pass(git_path_lstat("attr_index/README.txt", &st));
+       cl_git_pass(git_fs_path_lstat("attr_index/README.txt", &st));
        cl_assert_equal_i(0, (int)st.st_size);
 
        cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
@@ -1265,7 +1266,7 @@ void test_diff_workdir__can_diff_empty_file(void)
        /* remove a file altogether */
 
        cl_git_pass(p_unlink("attr_index/README.txt"));
-       cl_assert(!git_path_exists("attr_index/README.txt"));
+       cl_assert(!git_fs_path_exists("attr_index/README.txt"));
 
        cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
        cl_assert_equal_i(3, (int)git_diff_num_deltas(diff));
@@ -1663,7 +1664,7 @@ void test_diff_workdir__patience_diff(void)
        cl_git_pass(git_patch_to_buf(&buf, patch));
 
        cl_assert_equal_s(expected_normal, buf.ptr);
-       git_buf_clear(&buf);
+       git_buf_dispose(&buf);
        git_patch_free(patch);
        git_diff_free(diff);
 
@@ -1675,9 +1676,8 @@ void test_diff_workdir__patience_diff(void)
        cl_git_pass(git_patch_to_buf(&buf, patch));
 
        cl_assert_equal_s(expected_patience, buf.ptr);
-       git_buf_clear(&buf);
-
        git_buf_dispose(&buf);
+
        git_patch_free(patch);
        git_diff_free(diff);
 }
@@ -1754,13 +1754,13 @@ void test_diff_workdir__with_stale_index(void)
        git_index_free(idx);
 }
 
-static int touch_file(void *payload, git_buf *path)
+static int touch_file(void *payload, git_str *path)
 {
        struct stat st;
        struct p_timeval times[2];
 
        GIT_UNUSED(payload);
-       if (git_path_isdir(path->ptr))
+       if (git_fs_path_isdir(path->ptr))
                return 0;
 
        cl_must_pass(p_stat(path->ptr, &st));
@@ -1804,10 +1804,10 @@ void test_diff_workdir__can_update_index(void)
 
        /* touch all the files so stat times are different */
        {
-               git_buf path = GIT_BUF_INIT;
-               cl_git_pass(git_buf_sets(&path, "status"));
-               cl_git_pass(git_path_direach(&path, 0, touch_file, NULL));
-               git_buf_dispose(&path);
+               git_str path = GIT_STR_INIT;
+               cl_git_pass(git_str_sets(&path, "status"));
+               cl_git_pass(git_fs_path_direach(&path, 0, touch_file, NULL));
+               git_str_dispose(&path);
        }
 
        opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
@@ -1873,9 +1873,9 @@ void test_diff_workdir__binary_detection(void)
 {
        git_index *idx;
        git_diff *diff = NULL;
-       git_buf b = GIT_BUF_INIT;
+       git_str b = GIT_STR_INIT;
        int i;
-       git_buf data[10] = {
+       git_str data[10] = {
                { "1234567890", 0, 10 },         /* 0 - all ascii text control */
                { "\xC3\x85\xC3\xBC\xE2\x80\xA0\x48\xC3\xB8\xCF\x80\xCE\xA9", 0, 14 },            /* 1 - UTF-8 multibyte text */
                { "\xEF\xBB\xBF\xC3\x9C\xE2\xA4\x92\xC6\x92\x38\xC2\xA3\xE2\x82\xAC", 0, 16 }, /* 2 - UTF-8 with BOM */
@@ -1899,7 +1899,7 @@ void test_diff_workdir__binary_detection(void)
         * then we will try with test data in index and ASCII in workdir.
         */
 
-       cl_git_pass(git_buf_sets(&b, "empty_standard_repo/0"));
+       cl_git_pass(git_str_sets(&b, "empty_standard_repo/0"));
        for (i = 0; i < 10; ++i) {
                b.ptr[b.size - 1] = '0' + i;
                cl_git_mkfile(b.ptr, "baseline");
@@ -1931,7 +1931,7 @@ void test_diff_workdir__binary_detection(void)
 
        git_diff_free(diff);
 
-       cl_git_pass(git_buf_sets(&b, "empty_standard_repo/0"));
+       cl_git_pass(git_str_sets(&b, "empty_standard_repo/0"));
        for (i = 0; i < 10; ++i) {
                b.ptr[b.size - 1] = '0' + i;
                cl_git_pass(git_index_add_bypath(idx, &b.ptr[b.size - 1]));
@@ -1959,7 +1959,7 @@ void test_diff_workdir__binary_detection(void)
        git_diff_free(diff);
 
        git_index_free(idx);
-       git_buf_dispose(&b);
+       git_str_dispose(&b);
 }
 
 void test_diff_workdir__to_index_conflicted(void) {
@@ -2005,8 +2005,10 @@ void test_diff_workdir__only_writes_index_when_necessary(void)
        git_diff *diff = NULL;
        git_reference *head;
        git_object *head_object;
-       git_oid initial, first, second;
-       git_buf path = GIT_BUF_INIT;
+       unsigned char initial[GIT_HASH_SHA1_SIZE],
+                     first[GIT_HASH_SHA1_SIZE],
+                     second[GIT_HASH_SHA1_SIZE];
+       git_str path = GIT_STR_INIT;
        struct stat st;
        struct p_timeval times[2];
 
@@ -2020,7 +2022,7 @@ void test_diff_workdir__only_writes_index_when_necessary(void)
 
        cl_git_pass(git_reset(g_repo, head_object, GIT_RESET_HARD, NULL));
 
-       git_oid_cpy(&initial, git_index_checksum(index));
+       memcpy(initial, git_index__checksum(index), GIT_HASH_SHA1_SIZE);
 
        /* update the index timestamp to avoid raciness */
        cl_must_pass(p_stat("status/.git/index", &st));
@@ -2036,21 +2038,21 @@ void test_diff_workdir__only_writes_index_when_necessary(void)
        cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
        git_diff_free(diff);
 
-       git_oid_cpy(&first, git_index_checksum(index));
-       cl_assert(!git_oid_equal(&initial, &first));
+       memcpy(first, git_index__checksum(index), GIT_HASH_SHA1_SIZE);
+       cl_assert(memcmp(initial, first, GIT_HASH_SHA1_SIZE) != 0);
 
        /* touch all the files so stat times are different */
-       cl_git_pass(git_buf_sets(&path, "status"));
-       cl_git_pass(git_path_direach(&path, 0, touch_file, NULL));
+       cl_git_pass(git_str_sets(&path, "status"));
+       cl_git_pass(git_fs_path_direach(&path, 0, touch_file, NULL));
 
        cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
        git_diff_free(diff);
 
        /* ensure the second diff did update the index */
-       git_oid_cpy(&second, git_index_checksum(index));
-       cl_assert(!git_oid_equal(&first, &second));
+       memcpy(second, git_index__checksum(index), GIT_HASH_SHA1_SIZE);
+       cl_assert(memcmp(first, second, GIT_HASH_SHA1_SIZE) != 0);
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_object_free(head_object);
        git_reference_free(head);
        git_index_free(index);
index ccf79c2aa717bdb170558e98532cc078c4c2e40a..27a665582569f490bc080d8395bdb166926df080 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar.h"
 #include "clar_libgit2.h"
 
-#include "buffer.h"
 #include "diff_generate.h"
 
 static git_repository *repo;
@@ -43,7 +42,7 @@ static void assert_email_match(
        git_buf buf = GIT_BUF_INIT;
 
        email_for_commit(&buf, commit_id, opts);
-       cl_assert_equal_s(expected, git_buf_cstr(&buf));
+       cl_assert_equal_s(expected, buf.ptr);
 
        git_buf_dispose(&buf);
 }
@@ -54,15 +53,17 @@ static void assert_subject_match(
        git_email_create_options *opts)
 {
        git_buf buf = GIT_BUF_INIT;
-       const char *loc;
+       char *subject, *nl;
 
        email_for_commit(&buf, commit_id, opts);
 
-       cl_assert((loc = strstr(buf.ptr, "\nSubject: ")) != NULL);
-       git_buf_consume(&buf, (loc + 10));
-       git_buf_truncate_at_char(&buf, '\n');
+       cl_assert((subject = strstr(buf.ptr, "\nSubject: ")) != NULL);
+       subject += 10;
 
-       cl_assert_equal_s(expected, git_buf_cstr(&buf));
+       if ((nl = strchr(subject, '\n')) != NULL)
+               *nl = '\0';
+
+       cl_assert_equal_s(expected, subject);
 
        git_buf_dispose(&buf);
 }
@@ -327,7 +328,7 @@ void test_email_create__custom_summary_and_body(void)
        cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
        cl_git_pass(git_email_create_from_diff(&buf, diff, 2, 4, &oid, summary, body, git_commit_author(commit), &opts));
 
-       cl_assert_equal_s(expected, git_buf_cstr(&buf));
+       cl_assert_equal_s(expected, buf.ptr);
 
        git_diff_free(diff);
        git_commit_free(commit);
diff --git a/tests/email/create.c.bak b/tests/email/create.c.bak
new file mode 100644 (file)
index 0000000..3bb95a6
--- /dev/null
@@ -0,0 +1,386 @@
+#include "clar.h"
+#include "clar_libgit2.h"
+
+#include "buffer.h"
+#include "diff_generate.h"
+
+static git_repository *repo;
+
+void test_email_create__initialize(void)
+{
+       repo = cl_git_sandbox_init("diff_format_email");
+}
+
+void test_email_create__cleanup(void)
+{
+       cl_git_sandbox_cleanup();
+}
+
+static void email_for_commit(
+       git_buf *out,
+       const char *commit_id,
+       git_email_create_options *opts)
+{
+       git_oid oid;
+       git_commit *commit = NULL;
+       git_diff *diff = NULL;
+
+       git_oid_fromstr(&oid, commit_id);
+
+       cl_git_pass(git_commit_lookup(&commit, repo, &oid));
+
+       cl_git_pass(git_email_create_from_commit(out, commit, opts));
+
+       git_diff_free(diff);
+       git_commit_free(commit);
+}
+
+static void assert_email_match(
+       const char *expected,
+       const char *commit_id,
+       git_email_create_options *opts)
+{
+       git_buf buf = GIT_BUF_INIT;
+
+       email_for_commit(&buf, commit_id, opts);
+       cl_assert_equal_s(expected, git_buf_cstr(&buf));
+
+       git_buf_dispose(&buf);
+}
+
+static void assert_subject_match(
+       const char *expected,
+       const char *commit_id,
+       git_email_create_options *opts)
+{
+       git_buf buf = GIT_BUF_INIT;
+       const char *loc;
+
+       email_for_commit(&buf, commit_id, opts);
+
+       cl_assert((loc = strstr(buf.ptr, "\nSubject: ")) != NULL);
+       git_buf_consume(&buf, (loc + 10));
+       git_buf_truncate_at_char(&buf, '\n');
+
+       cl_assert_equal_s(expected, git_buf_cstr(&buf));
+
+       git_buf_dispose(&buf);
+}
+
+void test_email_create__commit(void)
+{
+       const char *expected =
+       "From 9264b96c6d104d0e07ae33d3007b6a48246c6f92 Mon Sep 17 00:00:00 2001\n" \
+       "From: Jacques Germishuys <jacquesg@striata.com>\n" \
+       "Date: Wed, 9 Apr 2014 20:57:01 +0200\n" \
+       "Subject: [PATCH] Modify some content\n" \
+       "\n" \
+       "---\n" \
+       " file1.txt | 8 +++++---\n" \
+       " 1 file changed, 5 insertions(+), 3 deletions(-)\n" \
+       "\n" \
+       "diff --git a/file1.txt b/file1.txt\n" \
+       "index 94aaae8..af8f41d 100644\n" \
+       "--- a/file1.txt\n" \
+       "+++ b/file1.txt\n" \
+       "@@ -1,15 +1,17 @@\n" \
+       " file1.txt\n" \
+       " file1.txt\n" \
+       "+_file1.txt_\n" \
+       " file1.txt\n" \
+       " file1.txt\n" \
+       " file1.txt\n" \
+       " file1.txt\n" \
+       "+\n" \
+       "+\n" \
+       " file1.txt\n" \
+       " file1.txt\n" \
+       " file1.txt\n" \
+       " file1.txt\n" \
+       " file1.txt\n" \
+       "-file1.txt\n" \
+       "-file1.txt\n" \
+       "-file1.txt\n" \
+       "+_file1.txt_\n" \
+       "+_file1.txt_\n" \
+       " file1.txt\n" \
+       "--\n" \
+       "libgit2 " LIBGIT2_VERSION "\n" \
+       "\n";
+
+       assert_email_match(
+               expected, "9264b96c6d104d0e07ae33d3007b6a48246c6f92", NULL);
+}
+
+void test_email_create__custom_summary_and_body(void)
+{
+       const char *expected = "From 627e7e12d87e07a83fad5b6bfa25e86ead4a5270 Mon Sep 17 00:00:00 2001\n" \
+       "From: Patrick Steinhardt <ps@pks.im>\n" \
+       "Date: Tue, 24 Nov 2015 13:34:39 +0100\n" \
+       "Subject: [PPPPPATCH 2/4] This is a subject\n" \
+       "\n" \
+       "Modify content of file3.txt by appending a new line. Make this\n" \
+       "commit message somewhat longer to test behavior with newlines\n" \
+       "embedded in the message body.\n" \
+       "\n" \
+       "Also test if new paragraphs are included correctly.\n" \
+       "---\n" \
+       " file3.txt | 1 +\n" \
+       " 1 file changed, 1 insertion(+)\n" \
+       "\n" \
+       "diff --git a/file3.txt b/file3.txt\n" \
+       "index 9a2d780..7309653 100644\n" \
+       "--- a/file3.txt\n" \
+       "+++ b/file3.txt\n" \
+       "@@ -3,3 +3,4 @@ file3!\n" \
+       " file3\n" \
+       " file3\n" \
+       " file3\n" \
+       "+file3\n" \
+       "--\n" \
+       "libgit2 " LIBGIT2_VERSION "\n" \
+       "\n";
+
+       const char *summary = "This is a subject\nwith\nnewlines";
+       const char *body = "Modify content of file3.txt by appending a new line. Make this\n" \
+       "commit message somewhat longer to test behavior with newlines\n" \
+       "embedded in the message body.\n" \
+       "\n" \
+       "Also test if new paragraphs are included correctly.";
+
+       git_oid oid;
+       git_commit *commit = NULL;
+       git_diff *diff = NULL;
+       git_buf buf = GIT_BUF_INIT;
+       git_email_create_options opts = GIT_EMAIL_CREATE_OPTIONS_INIT;
+
+       opts.subject_prefix = "PPPPPATCH";
+
+       git_oid_fromstr(&oid, "627e7e12d87e07a83fad5b6bfa25e86ead4a5270");
+       cl_git_pass(git_commit_lookup(&commit, repo, &oid));
+       cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
+       cl_git_pass(git_email_create_from_diff(&buf, diff, 2, 4, &oid, summary, body, git_commit_author(commit), &opts));
+
+       cl_assert_equal_s(expected, git_buf_cstr(&buf));
+
+       git_diff_free(diff);
+       git_commit_free(commit);
+       git_buf_dispose(&buf);
+}
+
+void test_email_create__mode_change(void)
+{
+       const char *expected =
+       "From 7ade76dd34bba4733cf9878079f9fd4a456a9189 Mon Sep 17 00:00:00 2001\n" \
+       "From: Jacques Germishuys <jacquesg@striata.com>\n" \
+       "Date: Thu, 10 Apr 2014 10:05:03 +0200\n" \
+       "Subject: [PATCH] Update permissions\n" \
+       "\n" \
+       "---\n" \
+       " file1.txt.renamed | 0\n" \
+       " 1 file changed, 0 insertions(+), 0 deletions(-)\n" \
+       " mode change 100644 => 100755 file1.txt.renamed\n" \
+       "\n" \
+       "diff --git a/file1.txt.renamed b/file1.txt.renamed\n" \
+       "old mode 100644\n" \
+       "new mode 100755\n" \
+       "--\n" \
+       "libgit2 " LIBGIT2_VERSION "\n" \
+       "\n";
+
+       assert_email_match(expected, "7ade76dd34bba4733cf9878079f9fd4a456a9189", NULL);
+}
+
+void test_email_create__rename(void)
+{
+       const char *expected =
+       "From 6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d Mon Sep 17 00:00:00 2001\n" \
+       "From: Jacques Germishuys <jacquesg@striata.com>\n" \
+       "Date: Wed, 9 Apr 2014 21:15:56 +0200\n" \
+       "Subject: [PATCH] Renamed file1.txt -> file1.txt.renamed\n" \
+       "\n" \
+       "---\n" \
+       " file1.txt => file1.txt.renamed | 4 ++--\n" \
+       " 1 file changed, 2 insertions(+), 2 deletions(-)\n" \
+       "\n" \
+       "diff --git a/file1.txt b/file1.txt.renamed\n" \
+       "similarity index 86%\n" \
+       "rename from file1.txt\n" \
+       "rename to file1.txt.renamed\n" \
+       "index af8f41d..a97157a 100644\n" \
+       "--- a/file1.txt\n" \
+       "+++ b/file1.txt.renamed\n" \
+       "@@ -3,13 +3,13 @@ file1.txt\n" \
+       " _file1.txt_\n" \
+       " file1.txt\n" \
+       " file1.txt\n" \
+       "-file1.txt\n" \
+       "+file1.txt_renamed\n" \
+       " file1.txt\n" \
+       " \n" \
+       " \n" \
+       " file1.txt\n" \
+       " file1.txt\n" \
+       "-file1.txt\n" \
+       "+file1.txt_renamed\n" \
+       " file1.txt\n" \
+       " file1.txt\n" \
+       " _file1.txt_\n" \
+       "--\n" \
+       "libgit2 " LIBGIT2_VERSION "\n" \
+       "\n";
+
+       assert_email_match(expected, "6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d", NULL);
+}
+
+void test_email_create__rename_as_add_delete(void)
+{
+       const char *expected =
+       "From 6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d Mon Sep 17 00:00:00 2001\n" \
+       "From: Jacques Germishuys <jacquesg@striata.com>\n" \
+       "Date: Wed, 9 Apr 2014 21:15:56 +0200\n" \
+       "Subject: [PATCH] Renamed file1.txt -> file1.txt.renamed\n" \
+       "\n" \
+       "---\n" \
+       " file1.txt         | 17 -----------------\n" \
+       " file1.txt.renamed | 17 +++++++++++++++++\n" \
+       " 2 files changed, 17 insertions(+), 17 deletions(-)\n" \
+       " delete mode 100644 file1.txt\n" \
+       " create mode 100644 file1.txt.renamed\n" \
+       "\n" \
+       "diff --git a/file1.txt b/file1.txt\n" \
+       "deleted file mode 100644\n" \
+       "index af8f41d..0000000\n" \
+       "--- a/file1.txt\n" \
+       "+++ /dev/null\n" \
+       "@@ -1,17 +0,0 @@\n" \
+       "-file1.txt\n" \
+       "-file1.txt\n" \
+       "-_file1.txt_\n" \
+       "-file1.txt\n" \
+       "-file1.txt\n" \
+       "-file1.txt\n" \
+       "-file1.txt\n" \
+       "-\n" \
+       "-\n" \
+       "-file1.txt\n" \
+       "-file1.txt\n" \
+       "-file1.txt\n" \
+       "-file1.txt\n" \
+       "-file1.txt\n" \
+       "-_file1.txt_\n" \
+       "-_file1.txt_\n" \
+       "-file1.txt\n" \
+       "diff --git a/file1.txt.renamed b/file1.txt.renamed\n" \
+       "new file mode 100644\n" \
+       "index 0000000..a97157a\n" \
+       "--- /dev/null\n" \
+       "+++ b/file1.txt.renamed\n" \
+       "@@ -0,0 +1,17 @@\n" \
+       "+file1.txt\n" \
+       "+file1.txt\n" \
+       "+_file1.txt_\n" \
+       "+file1.txt\n" \
+       "+file1.txt\n" \
+       "+file1.txt_renamed\n" \
+       "+file1.txt\n" \
+       "+\n" \
+       "+\n" \
+       "+file1.txt\n" \
+       "+file1.txt\n" \
+       "+file1.txt_renamed\n" \
+       "+file1.txt\n" \
+       "+file1.txt\n" \
+       "+_file1.txt_\n" \
+       "+_file1.txt_\n" \
+       "+file1.txt\n" \
+       "--\n" \
+       "libgit2 " LIBGIT2_VERSION "\n" \
+       "\n";
+
+       git_email_create_options opts = GIT_EMAIL_CREATE_OPTIONS_INIT;
+       opts.flags |= GIT_EMAIL_CREATE_NO_RENAMES;
+
+       assert_email_match(expected, "6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d", &opts);
+}
+
+void test_email_create__binary(void)
+{
+       const char *expected =
+       "From 8d7523f6fcb2404257889abe0d96f093d9f524f9 Mon Sep 17 00:00:00 2001\n" \
+       "From: Jacques Germishuys <jacquesg@striata.com>\n" \
+       "Date: Sun, 13 Apr 2014 18:10:18 +0200\n" \
+       "Subject: [PATCH] Modified binary file\n" \
+       "\n" \
+       "---\n" \
+       " binary.bin | Bin 3 -> 5 bytes\n" \
+       " 1 file changed, 0 insertions(+), 0 deletions(-)\n" \
+       "\n" \
+       "diff --git a/binary.bin b/binary.bin\n" \
+       "index bd474b2519cc15eab801ff851cc7d50f0dee49a1..9ac35ff15cd8864aeafd889e4826a3150f0b06c4 100644\n" \
+       "GIT binary patch\n" \
+       "literal 5\n" \
+       "Mc${NkU}WL~000&M4gdfE\n" \
+       "\n" \
+       "literal 3\n" \
+       "Kc${Nk-~s>u4FC%O\n" \
+       "\n" \
+       "--\n" \
+       "libgit2 " LIBGIT2_VERSION "\n" \
+       "\n";
+
+       assert_email_match(expected, "8d7523f6fcb2404257889abe0d96f093d9f524f9", NULL);
+}
+
+void test_email_create__binary_not_included(void)
+{
+       const char *expected =
+       "From 8d7523f6fcb2404257889abe0d96f093d9f524f9 Mon Sep 17 00:00:00 2001\n" \
+       "From: Jacques Germishuys <jacquesg@striata.com>\n" \
+       "Date: Sun, 13 Apr 2014 18:10:18 +0200\n" \
+       "Subject: [PATCH] Modified binary file\n" \
+       "\n" \
+       "---\n" \
+       " binary.bin | Bin 3 -> 5 bytes\n" \
+       " 1 file changed, 0 insertions(+), 0 deletions(-)\n" \
+       "\n" \
+       "diff --git a/binary.bin b/binary.bin\n" \
+       "index bd474b2..9ac35ff 100644\n" \
+       "Binary files a/binary.bin and b/binary.bin differ\n" \
+       "--\n" \
+       "libgit2 " LIBGIT2_VERSION "\n" \
+       "\n";
+
+       git_email_create_options opts = GIT_EMAIL_CREATE_OPTIONS_INIT;
+       opts.diff_opts.flags &= ~GIT_DIFF_SHOW_BINARY;
+
+       assert_email_match(expected, "8d7523f6fcb2404257889abe0d96f093d9f524f9", &opts);
+}
+
+void test_email_create__commit_subjects(void)
+{
+       git_email_create_options opts = GIT_EMAIL_CREATE_OPTIONS_INIT;
+
+       assert_subject_match("[PATCH] Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+
+       opts.reroll_number = 42;
+       assert_subject_match("[PATCH v42] Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+
+       opts.flags |= GIT_EMAIL_CREATE_ALWAYS_NUMBER;
+       assert_subject_match("[PATCH v42 1/1] Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+
+       opts.start_number = 9;
+       assert_subject_match("[PATCH v42 9/9] Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+
+       opts.subject_prefix = "";
+       assert_subject_match("[v42 9/9] Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+
+       opts.reroll_number = 0;
+       assert_subject_match("[9/9] Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+
+       opts.start_number = 0;
+       assert_subject_match("[1/1] Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+
+       opts.flags = GIT_EMAIL_CREATE_OMIT_NUMBERS;
+       assert_subject_match("Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+}
diff --git a/tests/fetch/local.c b/tests/fetch/local.c
new file mode 100644 (file)
index 0000000..20bd7ad
--- /dev/null
@@ -0,0 +1,67 @@
+#include "clar_libgit2.h"
+#include "futils.h"
+
+static git_repository *repo;
+
+void test_fetch_local__initialize(void)
+{
+       cl_git_pass(git_repository_init(&repo, "./fetch", 0));
+}
+
+void test_fetch_local__cleanup(void)
+{
+       git_repository_free(repo);
+       repo = NULL;
+
+       cl_fixture_cleanup("./fetch");
+}
+
+void test_fetch_local__defaults(void)
+{
+       git_remote *remote;
+       git_object *obj;
+       git_oid expected_id;
+
+       cl_git_pass(git_remote_create(&remote, repo, "test",
+               cl_fixture("testrepo.git")));
+       cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL));
+
+       git_oid_fromstr(&expected_id, "258f0e2a959a364e40ed6603d5d44fbb24765b10");
+
+       cl_git_pass(git_revparse_single(&obj, repo, "refs/remotes/test/haacked"));
+       cl_assert_equal_oid(&expected_id, git_object_id(obj));
+
+       git_object_free(obj);
+       git_remote_free(remote);
+}
+
+void test_fetch_local__reachable_commit(void)
+{
+       git_remote *remote;
+       git_strarray refspecs;
+       git_object *obj;
+       git_oid expected_id;
+       git_str fetchhead = GIT_STR_INIT;
+       char *refspec = "+5b5b025afb0b4c913b4c338a42934a3863bf3644:refs/success";
+
+       refspecs.strings = &refspec;
+       refspecs.count = 1;
+
+       git_oid_fromstr(&expected_id, "5b5b025afb0b4c913b4c338a42934a3863bf3644");
+
+       cl_git_pass(git_remote_create(&remote, repo, "test",
+               cl_fixture("testrepo.git")));
+       cl_git_pass(git_remote_fetch(remote, &refspecs, NULL, NULL));
+
+       cl_git_pass(git_revparse_single(&obj, repo, "refs/success"));
+       cl_assert_equal_oid(&expected_id, git_object_id(obj));
+
+       cl_git_pass(git_futils_readbuffer(&fetchhead, "./fetch/.git/FETCH_HEAD"));
+       cl_assert_equal_strn(fetchhead.ptr,
+               "5b5b025afb0b4c913b4c338a42934a3863bf3644\t\t'5b5b025afb0b4c913b4c338a42934a3863bf3644' of ",
+               strlen("5b5b025afb0b4c913b4c338a42934a3863bf3644\t\t'5b5b025afb0b4c913b4c338a42934a3863bf3644' of "));
+
+       git_str_dispose(&fetchhead);
+       git_object_free(obj);
+       git_remote_free(remote);
+}
index c75b65b90f7f34dea5b9f352b9f007c70a8c7a3d..77c3220016bf2811f248a70fe9a96e26806197f8 100644 (file)
@@ -1,48 +1,48 @@
 
 #define FETCH_HEAD_WILDCARD_DATA_LOCAL \
-       "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" \
-       "d96c4e80345534eccee5ac7b07fc7603b56124cb\tnot-for-merge\ttag 'annotated_tag' of git://github.com/libgit2/TestGitRepository\n" \
-       "55a1a760df4b86a02094a904dfa511deb5655905\tnot-for-merge\ttag 'blob' of git://github.com/libgit2/TestGitRepository\n" \
-       "8f50ba15d49353813cc6e20298002c0d17b0a9ee\tnot-for-merge\ttag 'commit_tree' of git://github.com/libgit2/TestGitRepository\n"
+       "49322bb17d3acc9146f98c97d078513228bbf3c0\t\tbranch 'master' of https://github.com/libgit2/TestGitRepository\n" \
+       "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of https://github.com/libgit2/TestGitRepository\n" \
+       "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of https://github.com/libgit2/TestGitRepository\n" \
+       "d96c4e80345534eccee5ac7b07fc7603b56124cb\tnot-for-merge\ttag 'annotated_tag' of https://github.com/libgit2/TestGitRepository\n" \
+       "55a1a760df4b86a02094a904dfa511deb5655905\tnot-for-merge\ttag 'blob' of https://github.com/libgit2/TestGitRepository\n" \
+       "8f50ba15d49353813cc6e20298002c0d17b0a9ee\tnot-for-merge\ttag 'commit_tree' of https://github.com/libgit2/TestGitRepository\n"
 
 #define FETCH_HEAD_WILDCARD_DATA \
-       "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" \
-       "d96c4e80345534eccee5ac7b07fc7603b56124cb\tnot-for-merge\ttag 'annotated_tag' of git://github.com/libgit2/TestGitRepository\n" \
-       "55a1a760df4b86a02094a904dfa511deb5655905\tnot-for-merge\ttag 'blob' of git://github.com/libgit2/TestGitRepository\n" \
-       "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"
+       "49322bb17d3acc9146f98c97d078513228bbf3c0\t\tbranch 'master' of https://github.com/libgit2/TestGitRepository\n" \
+       "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of https://github.com/libgit2/TestGitRepository\n" \
+       "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of https://github.com/libgit2/TestGitRepository\n" \
+       "d96c4e80345534eccee5ac7b07fc7603b56124cb\tnot-for-merge\ttag 'annotated_tag' of https://github.com/libgit2/TestGitRepository\n" \
+       "55a1a760df4b86a02094a904dfa511deb5655905\tnot-for-merge\ttag 'blob' of https://github.com/libgit2/TestGitRepository\n" \
+       "8f50ba15d49353813cc6e20298002c0d17b0a9ee\tnot-for-merge\ttag 'commit_tree' of https://github.com/libgit2/TestGitRepository\n" \
+       "6e0c7bdb9b4ed93212491ee778ca1c65047cab4e\tnot-for-merge\ttag 'nearly-dangling' of https://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" \
+       "49322bb17d3acc9146f98c97d078513228bbf3c0\t\tbranch 'master' of https://github.com/libgit2/TestGitRepository\n" \
+       "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of https://github.com/libgit2/TestGitRepository\n" \
+       "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of https://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" \
-       "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of git://github.com/libgit2/TestGitRepository\n" \
-       "d96c4e80345534eccee5ac7b07fc7603b56124cb\tnot-for-merge\ttag 'annotated_tag' of git://github.com/libgit2/TestGitRepository\n" \
-       "55a1a760df4b86a02094a904dfa511deb5655905\tnot-for-merge\ttag 'blob' of git://github.com/libgit2/TestGitRepository\n" \
-       "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"
+       "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of https://github.com/libgit2/TestGitRepository\n" \
+       "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\tbranch 'master' of https://github.com/libgit2/TestGitRepository\n" \
+       "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of https://github.com/libgit2/TestGitRepository\n" \
+       "d96c4e80345534eccee5ac7b07fc7603b56124cb\tnot-for-merge\ttag 'annotated_tag' of https://github.com/libgit2/TestGitRepository\n" \
+       "55a1a760df4b86a02094a904dfa511deb5655905\tnot-for-merge\ttag 'blob' of https://github.com/libgit2/TestGitRepository\n" \
+       "8f50ba15d49353813cc6e20298002c0d17b0a9ee\tnot-for-merge\ttag 'commit_tree' of https://github.com/libgit2/TestGitRepository\n" \
+       "6e0c7bdb9b4ed93212491ee778ca1c65047cab4e\tnot-for-merge\ttag 'nearly-dangling' of https://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" \
+       "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of https://github.com/libgit2/TestGitRepository\n" \
+       "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\tbranch 'master' of https://github.com/libgit2/TestGitRepository\n" \
+       "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of https://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" \
+       "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of https://github.com/libgit2/TestGitRepository\n" \
+       "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\tbranch 'master' of https://github.com/libgit2/TestGitRepository\n" \
+       "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of https://github.com/libgit2/TestGitRepository\n" \
+       "8f50ba15d49353813cc6e20298002c0d17b0a9ee\tnot-for-merge\ttag 'commit_tree' of https://github.com/libgit2/TestGitRepository\n" \
 
 #define FETCH_HEAD_EXPLICIT_DATA \
-       "0966a434eb1a025db6b71485ab63a3bfbea520b6\t\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n"
+       "0966a434eb1a025db6b71485ab63a3bfbea520b6\t\tbranch 'first-merge' of https://github.com/libgit2/TestGitRepository\n"
 
 #define FETCH_HEAD_QUOTE_DATA \
-       "0966a434eb1a025db6b71485ab63a3bfbea520b6\t\tbranch 'first's-merge' of git://github.com/libgit2/TestGitRepository\n"
+       "0966a434eb1a025db6b71485ab63a3bfbea520b6\t\tbranch 'first's-merge' of https://github.com/libgit2/TestGitRepository\n"
index 6881af40a0099a574ba1cb705500030545d9a03b..aadcc788027495dd5ef88795220467a5ac670465 100644 (file)
@@ -33,42 +33,42 @@ static void populate_fetchhead(git_vector *out, git_repository *repo)
                "49322bb17d3acc9146f98c97d078513228bbf3c0"));
        cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 1,
                "refs/heads/master",
-               "git://github.com/libgit2/TestGitRepository"));
+               "https://github.com/libgit2/TestGitRepository"));
        cl_git_pass(git_vector_insert(out, fetchhead_ref));
 
        cl_git_pass(git_oid_fromstr(&oid,
                "0966a434eb1a025db6b71485ab63a3bfbea520b6"));
        cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0,
                "refs/heads/first-merge",
-               "git://github.com/libgit2/TestGitRepository"));
+               "https://github.com/libgit2/TestGitRepository"));
        cl_git_pass(git_vector_insert(out, fetchhead_ref));
 
        cl_git_pass(git_oid_fromstr(&oid,
                "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1"));
        cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0,
                "refs/heads/no-parent",
-               "git://github.com/libgit2/TestGitRepository"));
+               "https://github.com/libgit2/TestGitRepository"));
        cl_git_pass(git_vector_insert(out, fetchhead_ref));
 
        cl_git_pass(git_oid_fromstr(&oid,
                "d96c4e80345534eccee5ac7b07fc7603b56124cb"));
        cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0,
                "refs/tags/annotated_tag",
-               "git://github.com/libgit2/TestGitRepository"));
+               "https://github.com/libgit2/TestGitRepository"));
        cl_git_pass(git_vector_insert(out, fetchhead_ref));
 
        cl_git_pass(git_oid_fromstr(&oid,
                "55a1a760df4b86a02094a904dfa511deb5655905"));
        cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0,
                "refs/tags/blob",
-               "git://github.com/libgit2/TestGitRepository"));
+               "https://github.com/libgit2/TestGitRepository"));
        cl_git_pass(git_vector_insert(out, fetchhead_ref));
 
        cl_git_pass(git_oid_fromstr(&oid,
                "8f50ba15d49353813cc6e20298002c0d17b0a9ee"));
        cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0,
                "refs/tags/commit_tree",
-               "git://github.com/libgit2/TestGitRepository"));
+               "https://github.com/libgit2/TestGitRepository"));
        cl_git_pass(git_vector_insert(out, fetchhead_ref));
 
        cl_git_pass(git_fetchhead_write(repo, out));
@@ -78,7 +78,7 @@ void test_fetchhead_nonetwork__write(void)
 {
        git_vector fetchhead_vector = GIT_VECTOR_INIT;
        git_fetchhead_ref *fetchhead_ref;
-       git_buf fetchhead_buf = GIT_BUF_INIT;
+       git_str fetchhead_buf = GIT_STR_INIT;
        int equals = 0;
        size_t i;
 
@@ -94,7 +94,7 @@ void test_fetchhead_nonetwork__write(void)
 
        equals = (strcmp(fetchhead_buf.ptr, FETCH_HEAD_WILDCARD_DATA_LOCAL) == 0);
 
-       git_buf_dispose(&fetchhead_buf);
+       git_str_dispose(&fetchhead_buf);
 
        git_vector_foreach(&fetchhead_vector, i, fetchhead_ref) {
                git_fetchhead_ref_free(fetchhead_ref);
@@ -408,7 +408,7 @@ static bool found_master;
 static bool found_haacked;
 static bool find_master_haacked_called;
 
-int find_master_haacked(const char *ref_name, const char *remote_url, const git_oid *oid, unsigned int is_merge, void *payload)
+static int find_master_haacked(const char *ref_name, const char *remote_url, const git_oid *oid, unsigned int is_merge, void *payload)
 {
        GIT_UNUSED(remote_url);
        GIT_UNUSED(oid);
@@ -431,7 +431,7 @@ int find_master_haacked(const char *ref_name, const char *remote_url, const git_
 void test_fetchhead_nonetwork__create_when_refpecs_given(void)
 {
        git_remote *remote;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        char *refspec1 = "refs/heads/master";
        char *refspec2 = "refs/heads/haacked";
        char *refspecs[] = { refspec1, refspec2 };
@@ -443,12 +443,12 @@ void test_fetchhead_nonetwork__create_when_refpecs_given(void)
        cl_set_cleanup(&cleanup_repository, "./test1");
        cl_git_pass(git_repository_init(&g_repo, "./test1", 0));
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_path(g_repo), "FETCH_HEAD"));
+       cl_git_pass(git_str_joinpath(&path, git_repository_path(g_repo), "FETCH_HEAD"));
        cl_git_pass(git_remote_create(&remote, g_repo, "origin", cl_fixture("testrepo.git")));
 
-       cl_assert(!git_path_exists(path.ptr));
+       cl_assert(!git_fs_path_exists(path.ptr));
        cl_git_pass(git_remote_fetch(remote, &specs, NULL, NULL));
-       cl_assert(git_path_exists(path.ptr));
+       cl_assert(git_fs_path_exists(path.ptr));
 
        cl_git_pass(git_repository_fetchhead_foreach(g_repo, find_master_haacked, NULL));
        cl_assert(find_master_haacked_called);
@@ -456,7 +456,7 @@ void test_fetchhead_nonetwork__create_when_refpecs_given(void)
        cl_assert(found_haacked);
 
        git_remote_free(remote);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 static bool count_refs_called;
@@ -466,7 +466,7 @@ struct prefix_count {
        int expected;
 };
 
-int count_refs(const char *ref_name, const char *remote_url, const git_oid *oid, unsigned int is_merge, void *payload)
+static int count_refs(const char *ref_name, const char *remote_url, const git_oid *oid, unsigned int is_merge, void *payload)
 {
        int i;
        struct prefix_count *prefix_counts = (struct prefix_count *) payload;
@@ -488,7 +488,7 @@ int count_refs(const char *ref_name, const char *remote_url, const git_oid *oid,
 void test_fetchhead_nonetwork__create_with_multiple_refspecs(void)
 {
        git_remote *remote;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        cl_set_cleanup(&cleanup_repository, "./test1");
        cl_git_pass(git_repository_init(&g_repo, "./test1", 0));
@@ -499,16 +499,16 @@ void test_fetchhead_nonetwork__create_with_multiple_refspecs(void)
        /* Pick up the new refspec */
        cl_git_pass(git_remote_lookup(&remote, g_repo, "origin"));
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_path(g_repo), "FETCH_HEAD"));
-       cl_assert(!git_path_exists(path.ptr));
+       cl_git_pass(git_str_joinpath(&path, git_repository_path(g_repo), "FETCH_HEAD"));
+       cl_assert(!git_fs_path_exists(path.ptr));
        cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL));
-       cl_assert(git_path_exists(path.ptr));
+       cl_assert(git_fs_path_exists(path.ptr));
 
        {
                int i;
                struct prefix_count prefix_counts[] = {
                        {"refs/notes/", 0, 1},
-                       {"refs/heads/", 0, 12},
+                       {"refs/heads/", 0, 13},
                        {"refs/tags/", 0, 7},
                        {NULL, 0, 0},
                };
@@ -520,7 +520,7 @@ void test_fetchhead_nonetwork__create_with_multiple_refspecs(void)
        }
 
        git_remote_free(remote);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_fetchhead_nonetwork__credentials_are_stripped(void)
index bc9c7f289389d0e23258fcf7950b0432670632b5..925ea58d2ec9712e68e833b51c695a2d51c5071c 100644 (file)
@@ -1,6 +1,5 @@
 #include "clar_libgit2.h"
 #include "git2/sys/filter.h"
-#include "buffer.h"
 
 static git_repository *g_repo = NULL;
 
index ee3b6353b322c265a7a5cb5e5383e82c00370e34..95a9f978e2b3b2413d8a1864431179768030e270 100644 (file)
@@ -2,14 +2,15 @@
 #include "posix.h"
 #include "filter.h"
 #include "git2/sys/filter.h"
+#include "custom_helpers.h"
 
 #define VERY_SECURE_ENCRYPTION(b) ((b) ^ 0xff)
 
 int bitflip_filter_apply(
        git_filter     *self,
        void          **payload,
-       git_buf        *to,
-       const git_buf  *from,
+       git_str        *to,
+       const git_str  *from,
        const git_filter_source *source)
 {
        const unsigned char *src = (const unsigned char *)from->ptr;
@@ -25,7 +26,7 @@ int bitflip_filter_apply(
        if (!from->size)
                return 0;
 
-       cl_git_pass(git_buf_grow(to, from->size));
+       cl_git_pass(git_str_grow(to, from->size));
 
        dst = (unsigned char *)to->ptr;
 
@@ -70,8 +71,8 @@ git_filter *create_bitflip_filter(void)
 int reverse_filter_apply(
        git_filter     *self,
        void          **payload,
-       git_buf        *to,
-       const git_buf  *from,
+       git_str        *to,
+       const git_str  *from,
        const git_filter_source *source)
 {
        const unsigned char *src = (const unsigned char *)from->ptr;
@@ -87,7 +88,7 @@ int reverse_filter_apply(
        if (!from->size)
                return 0;
 
-       cl_git_pass(git_buf_grow(to, from->size));
+       cl_git_pass(git_str_grow(to, from->size));
 
        dst = (unsigned char *)to->ptr + from->size - 1;
 
@@ -128,7 +129,7 @@ git_filter *create_reverse_filter(const char *attrs)
        return filter;
 }
 
-int erroneous_filter_stream(
+static int erroneous_filter_stream(
        git_writestream **out,
        git_filter *self,
        void **payload,
index 537a51da226d1689d66adc10a2447f5377a4d392..0936c581b86db73dcc32d46e43dd207d9cbccedf 100644 (file)
@@ -7,13 +7,13 @@ extern git_filter *create_erroneous_filter(const char *attr);
 extern int bitflip_filter_apply(
        git_filter     *self,
        void          **payload,
-       git_buf        *to,
-       const git_buf  *from,
+       git_str        *to,
+       const git_str  *from,
        const git_filter_source *source);
 
 extern int reverse_filter_apply(
        git_filter     *self,
        void          **payload,
-       git_buf        *to,
-       const git_buf  *from,
+       git_str        *to,
+       const git_str  *from,
        const git_filter_source *source);
index 521c01c02e3ba86377a021474d4b9cd17944fffe..14b33bab9b574c42c3a0384b37efabdcf6a393e4 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "git2/sys/filter.h"
 #include "crlf.h"
-#include "buffer.h"
 
 static git_repository *g_repo = NULL;
 
@@ -53,25 +52,25 @@ void test_filter_file__apply(void)
 
 struct buf_writestream {
        git_writestream base;
-       git_buf buf;
+       git_str buf;
 };
 
-int buf_writestream_write(git_writestream *s, const char *buf, size_t len)
+static int buf_writestream_write(git_writestream *s, const char *buf, size_t len)
 {
        struct buf_writestream *stream = (struct buf_writestream *)s;
-       return git_buf_put(&stream->buf, buf, len);
+       return git_str_put(&stream->buf, buf, len);
 }
 
-int buf_writestream_close(git_writestream *s)
+static int buf_writestream_close(git_writestream *s)
 {
        GIT_UNUSED(s);
        return 0;
 }
 
-void buf_writestream_free(git_writestream *s)
+static void buf_writestream_free(git_writestream *s)
 {
        struct buf_writestream *stream = (struct buf_writestream *)s;
-       git_buf_dispose(&stream->buf);
+       git_str_dispose(&stream->buf);
 }
 
 void test_filter_file__apply_stream(void)
index 6889d715bb32690352ca0e861e1aad79286babb6..429c104432466c258a890f948f9dcd8680c8b218 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "git2/sys/filter.h"
 #include "crlf.h"
-#include "buffer.h"
 
 static git_repository *g_repo = NULL;
 
index b6a4c3ca1fae68f9b50c3a8b14ed0b9aaf29846f..0f85f9c473600c58d12c5b1d12f367926966d146 100644 (file)
@@ -137,12 +137,12 @@ git_filter *create_compress_filter(void)
 
 static void writefile(const char *filename, size_t numchunks)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        char buf[CHUNKSIZE];
        size_t i = 0, j = 0;
        int fd;
 
-       cl_git_pass(git_buf_joinpath(&path, "empty_standard_repo", filename));
+       cl_git_pass(git_str_joinpath(&path, "empty_standard_repo", filename));
 
        fd = p_open(path.ptr, O_RDWR|O_CREAT, 0666);
        cl_assert(fd >= 0);
@@ -156,7 +156,7 @@ static void writefile(const char *filename, size_t numchunks)
        }
        p_close(fd);
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 static void test_stream(size_t numchunks)
index 4996b3b1ea2a166142274c56c0ede851f35a10dc..b687b4b44cd812d41070032368eadf9fcf11670e 100644 (file)
@@ -3,29 +3,33 @@
 #include "path.h"
 
 static git_repository *g_repo = NULL;
-static git_buf system_attr_path = GIT_BUF_INIT;
+static git_str system_attr_path = GIT_STR_INIT;
 
 void test_filter_systemattrs__initialize(void)
 {
+       git_buf system_path = GIT_BUF_INIT;
+
        g_repo = cl_git_sandbox_init("crlf");
        cl_must_pass(p_unlink("crlf/.gitattributes"));
 
        cl_git_pass(git_libgit2_opts(
-               GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, &system_attr_path));
-       cl_git_pass(git_buf_joinpath(&system_attr_path,
-               system_attr_path.ptr, "gitattributes"));
+               GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, &system_path));
+       cl_git_pass(git_str_joinpath(&system_attr_path,
+               system_path.ptr, "gitattributes"));
 
        cl_git_mkfile(system_attr_path.ptr,
                "*.txt text\n"
                "*.bin binary\n"
                "*.crlf text eol=crlf\n"
                "*.lf text eol=lf\n");
+
+       git_buf_dispose(&system_path);
 }
 
 void test_filter_systemattrs__cleanup(void)
 {
        cl_must_pass(p_unlink(system_attr_path.ptr));
-       git_buf_dispose(&system_attr_path);
+       git_str_dispose(&system_attr_path);
 
        cl_git_sandbox_cleanup();
 }
index 0c9c13b1e4c6b338f95331c38a0f4e4d557f1433..ee61a8dba6613a6b20a59fa8cc5a57c90198c079 100644 (file)
@@ -78,8 +78,8 @@ static int wildcard_filter_check(
 static int wildcard_filter_apply(
        git_filter     *self,
        void          **payload,
-       git_buf        *to,
-       const git_buf  *from,
+       git_str        *to,
+       const git_str  *from,
        const git_filter_source *source)
 {
        const char *filtername = *payload;
index 9ed6edef302b5711eedc7d9b3f8d069c54e9dcec..d2cdb684ad0068aaa2211f2ad9214c60d50e5be8 100644 (file)
@@ -8,7 +8,7 @@
 
 from __future__ import with_statement
 from string import Template
-import re, fnmatch, os, sys, codecs, pickle
+import re, fnmatch, os, sys, codecs, pickle, io
 
 class Module(object):
     class Template(object):
@@ -147,7 +147,7 @@ class TestSuite(object):
         self.path = path
         self.output = output
 
-    def should_generate(self, path):
+    def maybe_generate(self, path):
         if not os.path.isfile(path):
             return True
 
@@ -216,33 +216,82 @@ class TestSuite(object):
         return sum(len(module.callbacks) for module in self.modules.values())
 
     def write(self):
-        output = os.path.join(self.output, 'clar.suite')
+        wrote_suite = self.write_suite()
+        wrote_header = self.write_header()
 
-        if not self.should_generate(output):
+        if wrote_suite or wrote_header:
+            self.save_cache()
+            return True
+
+        return False
+
+    def write_output(self, fn, data):
+        if not self.maybe_generate(fn):
             return False
 
-        with open(output, 'w') as data:
+        current = None
+
+        try:
+            with open(fn, 'r') as input:
+                current = input.read()
+        except OSError:
+            pass
+        except IOError:
+            pass
+
+        if current == data:
+            return False
+
+        with open(fn, 'w') as output:
+            output.write(data)
+
+        return True
+
+    def write_suite(self):
+        suite_fn = os.path.join(self.output, 'clar.suite')
+
+        with io.StringIO() as suite_file:
             modules = sorted(self.modules.values(), key=lambda module: module.name)
 
             for module in modules:
                 t = Module.DeclarationTemplate(module)
-                data.write(t.render())
+                suite_file.write(t.render())
 
             for module in modules:
                 t = Module.CallbacksTemplate(module)
-                data.write(t.render())
+                suite_file.write(t.render())
 
             suites = "static struct clar_suite _clar_suites[] = {" + ','.join(
                 Module.InfoTemplate(module).render() for module in modules
             ) + "\n};\n"
 
-            data.write(suites)
+            suite_file.write(suites)
 
-            data.write("static const size_t _clar_suite_count = %d;\n" % self.suite_count())
-            data.write("static const size_t _clar_callback_count = %d;\n" % self.callback_count())
+            suite_file.write(u"static const size_t _clar_suite_count = %d;\n" % self.suite_count())
+            suite_file.write(u"static const size_t _clar_callback_count = %d;\n" % self.callback_count())
 
-        self.save_cache()
-        return True
+            return self.write_output(suite_fn, suite_file.getvalue())
+
+        return False
+
+    def write_header(self):
+        header_fn = os.path.join(self.output, 'clar_suite.h')
+
+        with io.StringIO() as header_file:
+            header_file.write(u"#ifndef _____clar_suite_h_____\n")
+            header_file.write(u"#define _____clar_suite_h_____\n")
+
+            modules = sorted(self.modules.values(), key=lambda module: module.name)
+
+            for module in modules:
+                t = Module.DeclarationTemplate(module)
+                header_file.write(t.render())
+
+            header_file.write(u"#endif\n")
+
+            return self.write_output(header_fn, header_file.getvalue())
+
+        return False
 
 if __name__ == '__main__':
     from optparse import OptionParser
@@ -263,5 +312,5 @@ if __name__ == '__main__':
     suite.load(options.force)
     suite.disable(options.excluded)
     if suite.write():
-        print("Written `clar.suite` (%d tests in %d suites)" % (suite.callback_count(), suite.suite_count()))
+        print("Written `clar.suite`, `clar_suite.h` (%d tests in %d suites)" % (suite.callback_count(), suite.suite_count()))
 
diff --git a/tests/graph/commit_graph.c b/tests/graph/commit_graph.c
deleted file mode 100644 (file)
index 5926dca..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-#include "clar_libgit2.h"
-
-#include <git2.h>
-#include <git2/sys/commit_graph.h>
-
-#include "commit_graph.h"
-#include "futils.h"
-
-void test_graph_commit_graph__parse(void)
-{
-       git_repository *repo;
-       struct git_commit_graph_file *file;
-       struct git_commit_graph_entry e, parent;
-       git_oid id;
-       git_buf commit_graph_path = GIT_BUF_INIT;
-
-       cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
-       cl_git_pass(git_buf_joinpath(&commit_graph_path, git_repository_path(repo), "objects/info/commit-graph"));
-       cl_git_pass(git_commit_graph_file_open(&file, git_buf_cstr(&commit_graph_path)));
-       cl_assert_equal_i(git_commit_graph_file_needs_refresh(file, git_buf_cstr(&commit_graph_path)), 0);
-
-       cl_git_pass(git_oid_fromstr(&id, "5001298e0c09ad9c34e4249bc5801c75e9754fa5"));
-       cl_git_pass(git_commit_graph_entry_find(&e, file, &id, GIT_OID_HEXSZ));
-       cl_assert_equal_oid(&e.sha1, &id);
-       cl_git_pass(git_oid_fromstr(&id, "418382dff1ffb8bdfba833f4d8bbcde58b1e7f47"));
-       cl_assert_equal_oid(&e.tree_oid, &id);
-       cl_assert_equal_i(e.generation, 1);
-       cl_assert_equal_i(e.commit_time, UINT64_C(1273610423));
-       cl_assert_equal_i(e.parent_count, 0);
-
-       cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
-       cl_git_pass(git_commit_graph_entry_find(&e, file, &id, GIT_OID_HEXSZ));
-       cl_assert_equal_oid(&e.sha1, &id);
-       cl_assert_equal_i(e.generation, 5);
-       cl_assert_equal_i(e.commit_time, UINT64_C(1274813907));
-       cl_assert_equal_i(e.parent_count, 2);
-
-       cl_git_pass(git_oid_fromstr(&id, "9fd738e8f7967c078dceed8190330fc8648ee56a"));
-       cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 0));
-       cl_assert_equal_oid(&parent.sha1, &id);
-       cl_assert_equal_i(parent.generation, 4);
-
-       cl_git_pass(git_oid_fromstr(&id, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
-       cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 1));
-       cl_assert_equal_oid(&parent.sha1, &id);
-       cl_assert_equal_i(parent.generation, 3);
-
-       git_commit_graph_file_free(file);
-       git_repository_free(repo);
-       git_buf_dispose(&commit_graph_path);
-}
-
-void test_graph_commit_graph__parse_octopus_merge(void)
-{
-       git_repository *repo;
-       struct git_commit_graph_file *file;
-       struct git_commit_graph_entry e, parent;
-       git_oid id;
-       git_buf commit_graph_path = GIT_BUF_INIT;
-
-       cl_git_pass(git_repository_open(&repo, cl_fixture("merge-recursive/.gitted")));
-       cl_git_pass(git_buf_joinpath(&commit_graph_path, git_repository_path(repo), "objects/info/commit-graph"));
-       cl_git_pass(git_commit_graph_file_open(&file, git_buf_cstr(&commit_graph_path)));
-
-       cl_git_pass(git_oid_fromstr(&id, "d71c24b3b113fd1d1909998c5bfe33b86a65ee03"));
-       cl_git_pass(git_commit_graph_entry_find(&e, file, &id, GIT_OID_HEXSZ));
-       cl_assert_equal_oid(&e.sha1, &id);
-       cl_git_pass(git_oid_fromstr(&id, "348f16ffaeb73f319a75cec5b16a0a47d2d5e27c"));
-       cl_assert_equal_oid(&e.tree_oid, &id);
-       cl_assert_equal_i(e.generation, 7);
-       cl_assert_equal_i(e.commit_time, UINT64_C(1447083009));
-       cl_assert_equal_i(e.parent_count, 3);
-
-       cl_git_pass(git_oid_fromstr(&id, "ad2ace9e15f66b3d1138922e6ffdc3ea3f967fa6"));
-       cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 0));
-       cl_assert_equal_oid(&parent.sha1, &id);
-       cl_assert_equal_i(parent.generation, 6);
-
-       cl_git_pass(git_oid_fromstr(&id, "483065df53c0f4a02cdc6b2910b05d388fc17ffb"));
-       cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 1));
-       cl_assert_equal_oid(&parent.sha1, &id);
-       cl_assert_equal_i(parent.generation, 2);
-
-       cl_git_pass(git_oid_fromstr(&id, "815b5a1c80ca749d705c7aa0cb294a00cbedd340"));
-       cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 2));
-       cl_assert_equal_oid(&parent.sha1, &id);
-       cl_assert_equal_i(parent.generation, 6);
-
-       git_commit_graph_file_free(file);
-       git_repository_free(repo);
-       git_buf_dispose(&commit_graph_path);
-}
-
-void test_graph_commit_graph__writer(void)
-{
-       git_repository *repo;
-       git_commit_graph_writer *w = NULL;
-       git_revwalk *walk;
-       git_commit_graph_writer_options opts = GIT_COMMIT_GRAPH_WRITER_OPTIONS_INIT;
-       git_buf cgraph = GIT_BUF_INIT, expected_cgraph = GIT_BUF_INIT, path = GIT_BUF_INIT;
-
-       cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
-
-       cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "objects/info"));
-       cl_git_pass(git_commit_graph_writer_new(&w, git_buf_cstr(&path)));
-
-       /* This is equivalent to `git commit-graph write --reachable`. */
-       cl_git_pass(git_revwalk_new(&walk, repo));
-       cl_git_pass(git_revwalk_push_glob(walk, "refs/*"));
-       cl_git_pass(git_commit_graph_writer_add_revwalk(w, walk));
-       git_revwalk_free(walk);
-
-       cl_git_pass(git_commit_graph_writer_dump(&cgraph, w, &opts));
-       cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "objects/info/commit-graph"));
-       cl_git_pass(git_futils_readbuffer(&expected_cgraph, git_buf_cstr(&path)));
-
-       cl_assert_equal_i(git_buf_len(&cgraph), git_buf_len(&expected_cgraph));
-       cl_assert_equal_i(memcmp(git_buf_cstr(&cgraph), git_buf_cstr(&expected_cgraph), git_buf_len(&cgraph)), 0);
-
-       git_buf_dispose(&cgraph);
-       git_buf_dispose(&expected_cgraph);
-       git_buf_dispose(&path);
-       git_commit_graph_writer_free(w);
-       git_repository_free(repo);
-}
diff --git a/tests/graph/commitgraph.c b/tests/graph/commitgraph.c
new file mode 100644 (file)
index 0000000..7607c35
--- /dev/null
@@ -0,0 +1,126 @@
+#include "clar_libgit2.h"
+
+#include <git2.h>
+#include <git2/sys/commit_graph.h>
+
+#include "commit_graph.h"
+#include "futils.h"
+
+void test_graph_commitgraph__parse(void)
+{
+       git_repository *repo;
+       struct git_commit_graph_file *file;
+       struct git_commit_graph_entry e, parent;
+       git_oid id;
+       git_str commit_graph_path = GIT_STR_INIT;
+
+       cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+       cl_git_pass(git_str_joinpath(&commit_graph_path, git_repository_path(repo), "objects/info/commit-graph"));
+       cl_git_pass(git_commit_graph_file_open(&file, git_str_cstr(&commit_graph_path)));
+       cl_assert_equal_i(git_commit_graph_file_needs_refresh(file, git_str_cstr(&commit_graph_path)), 0);
+
+       cl_git_pass(git_oid_fromstr(&id, "5001298e0c09ad9c34e4249bc5801c75e9754fa5"));
+       cl_git_pass(git_commit_graph_entry_find(&e, file, &id, GIT_OID_HEXSZ));
+       cl_assert_equal_oid(&e.sha1, &id);
+       cl_git_pass(git_oid_fromstr(&id, "418382dff1ffb8bdfba833f4d8bbcde58b1e7f47"));
+       cl_assert_equal_oid(&e.tree_oid, &id);
+       cl_assert_equal_i(e.generation, 1);
+       cl_assert_equal_i(e.commit_time, UINT64_C(1273610423));
+       cl_assert_equal_i(e.parent_count, 0);
+
+       cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
+       cl_git_pass(git_commit_graph_entry_find(&e, file, &id, GIT_OID_HEXSZ));
+       cl_assert_equal_oid(&e.sha1, &id);
+       cl_assert_equal_i(e.generation, 5);
+       cl_assert_equal_i(e.commit_time, UINT64_C(1274813907));
+       cl_assert_equal_i(e.parent_count, 2);
+
+       cl_git_pass(git_oid_fromstr(&id, "9fd738e8f7967c078dceed8190330fc8648ee56a"));
+       cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 0));
+       cl_assert_equal_oid(&parent.sha1, &id);
+       cl_assert_equal_i(parent.generation, 4);
+
+       cl_git_pass(git_oid_fromstr(&id, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
+       cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 1));
+       cl_assert_equal_oid(&parent.sha1, &id);
+       cl_assert_equal_i(parent.generation, 3);
+
+       git_commit_graph_file_free(file);
+       git_repository_free(repo);
+       git_str_dispose(&commit_graph_path);
+}
+
+void test_graph_commitgraph__parse_octopus_merge(void)
+{
+       git_repository *repo;
+       struct git_commit_graph_file *file;
+       struct git_commit_graph_entry e, parent;
+       git_oid id;
+       git_str commit_graph_path = GIT_STR_INIT;
+
+       cl_git_pass(git_repository_open(&repo, cl_fixture("merge-recursive/.gitted")));
+       cl_git_pass(git_str_joinpath(&commit_graph_path, git_repository_path(repo), "objects/info/commit-graph"));
+       cl_git_pass(git_commit_graph_file_open(&file, git_str_cstr(&commit_graph_path)));
+
+       cl_git_pass(git_oid_fromstr(&id, "d71c24b3b113fd1d1909998c5bfe33b86a65ee03"));
+       cl_git_pass(git_commit_graph_entry_find(&e, file, &id, GIT_OID_HEXSZ));
+       cl_assert_equal_oid(&e.sha1, &id);
+       cl_git_pass(git_oid_fromstr(&id, "348f16ffaeb73f319a75cec5b16a0a47d2d5e27c"));
+       cl_assert_equal_oid(&e.tree_oid, &id);
+       cl_assert_equal_i(e.generation, 7);
+       cl_assert_equal_i(e.commit_time, UINT64_C(1447083009));
+       cl_assert_equal_i(e.parent_count, 3);
+
+       cl_git_pass(git_oid_fromstr(&id, "ad2ace9e15f66b3d1138922e6ffdc3ea3f967fa6"));
+       cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 0));
+       cl_assert_equal_oid(&parent.sha1, &id);
+       cl_assert_equal_i(parent.generation, 6);
+
+       cl_git_pass(git_oid_fromstr(&id, "483065df53c0f4a02cdc6b2910b05d388fc17ffb"));
+       cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 1));
+       cl_assert_equal_oid(&parent.sha1, &id);
+       cl_assert_equal_i(parent.generation, 2);
+
+       cl_git_pass(git_oid_fromstr(&id, "815b5a1c80ca749d705c7aa0cb294a00cbedd340"));
+       cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 2));
+       cl_assert_equal_oid(&parent.sha1, &id);
+       cl_assert_equal_i(parent.generation, 6);
+
+       git_commit_graph_file_free(file);
+       git_repository_free(repo);
+       git_str_dispose(&commit_graph_path);
+}
+
+void test_graph_commitgraph__writer(void)
+{
+       git_repository *repo;
+       git_commit_graph_writer *w = NULL;
+       git_revwalk *walk;
+       git_commit_graph_writer_options opts = GIT_COMMIT_GRAPH_WRITER_OPTIONS_INIT;
+       git_buf cgraph = GIT_BUF_INIT;
+       git_str expected_cgraph = GIT_STR_INIT, path = GIT_STR_INIT;
+
+       cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+
+       cl_git_pass(git_str_joinpath(&path, git_repository_path(repo), "objects/info"));
+       cl_git_pass(git_commit_graph_writer_new(&w, git_str_cstr(&path)));
+
+       /* This is equivalent to `git commit-graph write --reachable`. */
+       cl_git_pass(git_revwalk_new(&walk, repo));
+       cl_git_pass(git_revwalk_push_glob(walk, "refs/*"));
+       cl_git_pass(git_commit_graph_writer_add_revwalk(w, walk));
+       git_revwalk_free(walk);
+
+       cl_git_pass(git_commit_graph_writer_dump(&cgraph, w, &opts));
+       cl_git_pass(git_str_joinpath(&path, git_repository_path(repo), "objects/info/commit-graph"));
+       cl_git_pass(git_futils_readbuffer(&expected_cgraph, git_str_cstr(&path)));
+
+       cl_assert_equal_i(cgraph.size, git_str_len(&expected_cgraph));
+       cl_assert_equal_i(memcmp(cgraph.ptr, git_str_cstr(&expected_cgraph), cgraph.size), 0);
+
+       git_buf_dispose(&cgraph);
+       git_str_dispose(&expected_cgraph);
+       git_str_dispose(&path);
+       git_commit_graph_writer_free(w);
+       git_repository_free(repo);
+}
index 5c84164998f103b0029f3477eb8356732cdf52fc..9693d7d67fed37e167dc08e24e2669194b816e8d 100644 (file)
@@ -200,12 +200,12 @@ void test_graph_reachable_from_any__exhaustive(void)
                                        descendants,
                                        n_descendants);
                        if (actual_reachable != expected_reachable) {
-                               git_buf error_message_buf = GIT_BUF_INIT;
+                               git_str error_message_buf = GIT_STR_INIT;
                                char parent_oidbuf[9] = {0}, child_oidbuf[9] = {0};
 
                                cl_git_pass(git_oid_nfmt(
                                                parent_oidbuf, 8, git_commit_id(parent_commit)));
-                               git_buf_printf(&error_message_buf,
+                               git_str_printf(&error_message_buf,
                                               "git_graph_reachable_from_any(\"%s\", %zu, "
                                               "{",
                                               parent_oidbuf,
@@ -216,14 +216,14 @@ void test_graph_reachable_from_any__exhaustive(void)
                                                        git_oid_nfmt(child_oidbuf,
                                                                     8,
                                                                     &descendants[descendant_i]));
-                                       git_buf_printf(&error_message_buf, " \"%s\"", child_oidbuf);
+                                       git_str_printf(&error_message_buf, " \"%s\"", child_oidbuf);
                                }
-                               git_buf_printf(&error_message_buf,
+                               git_str_printf(&error_message_buf,
                                               " }) = %d, expected = %d",
                                               actual_reachable,
                                               expected_reachable);
                                cl_check_(actual_reachable == expected_reachable,
-                                         git_buf_cstr(&error_message_buf));
+                                         git_str_cstr(&error_message_buf));
                        }
                }
        }
diff --git a/tests/headertest.c b/tests/headertest.c
new file mode 100644 (file)
index 0000000..2af8a14
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Dummy project to validate header files
+ *
+ * This project is not intended to be executed, it should only include all
+ * header files to make sure that they can be used with stricter compiler
+ * settings than the libgit2 source files generally supports.
+ */
+#include "git2.h"
+
+int main(void)
+{
+    return 0;
+}
index d55bdc5dd23cefd0d78889711ab344ce87cfa69a..a574d1d799d4db5284e6dbcc8c73568a79b7f822 100644 (file)
@@ -257,7 +257,7 @@ void test_ignore_path__skip_gitignore_directory(void)
 {
        cl_git_rewritefile("attr/.git/info/exclude", "/NewFolder\n/NewFolder/NewFolder");
        cl_must_pass(p_unlink("attr/.gitignore"));
-       cl_assert(!git_path_exists("attr/.gitignore"));
+       cl_assert(!git_fs_path_exists("attr/.gitignore"));
        p_mkdir("attr/.gitignore", 0777);
        cl_git_mkfile("attr/.gitignore/garbage.txt", "new_file\n");
 
@@ -270,7 +270,7 @@ void test_ignore_path__skip_gitignore_directory(void)
 void test_ignore_path__subdirectory_gitignore(void)
 {
        cl_must_pass(p_unlink("attr/.gitignore"));
-       cl_assert(!git_path_exists("attr/.gitignore"));
+       cl_assert(!git_fs_path_exists("attr/.gitignore"));
        cl_git_mkfile(
                "attr/.gitignore",
                "file1\n");
index 83e821bdd8cfac40ec18139d098e5e3a43a80452..deb7175900ea6f0cde06c2745ac31c6b2327f4b2 100644 (file)
@@ -610,12 +610,12 @@ void test_ignore_status__filenames_with_special_prefixes_do_not_interfere_with_s
        int i;
 
        for (i = 0; *(test_cases + i) != NULL; i++) {
-               git_buf file = GIT_BUF_INIT;
+               git_str file = GIT_STR_INIT;
                char *file_name = *(test_cases + i);
                git_repository *repo = cl_git_sandbox_init("empty_standard_repo");
 
-               cl_git_pass(git_buf_joinpath(&file, "empty_standard_repo", file_name));
-               cl_git_mkfile(git_buf_cstr(&file), "Please don't ignore me!");
+               cl_git_pass(git_str_joinpath(&file, "empty_standard_repo", file_name));
+               cl_git_mkfile(git_str_cstr(&file), "Please don't ignore me!");
 
                memset(&st, 0, sizeof(st));
                cl_git_pass(git_status_foreach(repo, cb_status__single, &st));
@@ -626,7 +626,7 @@ void test_ignore_status__filenames_with_special_prefixes_do_not_interfere_with_s
                cl_assert(st.status == GIT_STATUS_WT_NEW);
 
                cl_git_sandbox_cleanup();
-               git_buf_dispose(&file);
+               git_str_dispose(&file);
        }
 }
 
index 26c19d76d420a11fea69c31e230f604cefa126fc..7520c23a33b582f57f96b2404a9b359fdbd52853 100644 (file)
@@ -14,7 +14,7 @@
 static git_repository *g_repo;
 static git_index *g_index;
 
-static git_buf expected_fixture = GIT_BUF_INIT;
+static git_str expected_fixture = GIT_STR_INIT;
 
 void test_index_crlf__initialize(void)
 {
@@ -29,7 +29,7 @@ void test_index_crlf__cleanup(void)
 
        if (expected_fixture.size) {
                cl_fixture_cleanup(expected_fixture.ptr);
-               git_buf_dispose(&expected_fixture);
+               git_str_dispose(&expected_fixture);
        }
 }
 
@@ -42,30 +42,30 @@ struct compare_data
        const char *attrs;
 };
 
-static int add_and_check_file(void *payload, git_buf *actual_path)
+static int add_and_check_file(void *payload, git_str *actual_path)
 {
-       git_buf expected_path = GIT_BUF_INIT;
-       git_buf expected_path_fail = GIT_BUF_INIT;
-       git_buf expected_contents = GIT_BUF_INIT;
+       git_str expected_path = GIT_STR_INIT;
+       git_str expected_path_fail = GIT_STR_INIT;
+       git_str expected_contents = GIT_STR_INIT;
        struct compare_data *cd = payload;
        char *basename;
        const git_index_entry *entry;
        git_blob *blob;
        bool failed = true;
 
-       basename = git_path_basename(actual_path->ptr);
+       basename = git_fs_path_basename(actual_path->ptr);
 
        if (!strcmp(basename, ".git") || !strcmp(basename, ".gitattributes")) {
                failed = false;
                goto done;
        }
 
-       cl_git_pass(git_buf_joinpath(&expected_path, cd->dirname, basename));
+       cl_git_pass(git_str_joinpath(&expected_path, cd->dirname, basename));
 
-       cl_git_pass(git_buf_puts(&expected_path_fail, expected_path.ptr));
-       cl_git_pass(git_buf_puts(&expected_path_fail, ".fail"));
+       cl_git_pass(git_str_puts(&expected_path_fail, expected_path.ptr));
+       cl_git_pass(git_str_puts(&expected_path_fail, ".fail"));
 
-       if (git_path_isfile(expected_path.ptr)) {
+       if (git_fs_path_isfile(expected_path.ptr)) {
                cl_git_pass(git_index_add_bypath(g_index, basename));
 
                cl_assert(entry = git_index_get_bypath(g_index, basename, 0));
@@ -77,9 +77,9 @@ static int add_and_check_file(void *payload, git_buf *actual_path)
                        goto done;
 
                git_blob_free(blob);
-       } else if (git_path_isfile(expected_path_fail.ptr)) {
+       } else if (git_fs_path_isfile(expected_path_fail.ptr)) {
                cl_git_pass(git_futils_readbuffer(&expected_contents, expected_path_fail.ptr));
-               git_buf_rtrim(&expected_contents);
+               git_str_rtrim(&expected_contents);
 
                if (git_index_add_bypath(g_index, basename) == 0 ||
                        git_error_last()->klass != GIT_ERROR_FILTER ||
@@ -93,18 +93,18 @@ static int add_and_check_file(void *payload, git_buf *actual_path)
 
 done:
        if (failed) {
-               git_buf details = GIT_BUF_INIT;
-               git_buf_printf(&details, "filename=%s, system=%s, autocrlf=%s, safecrlf=%s, attrs={%s}",
+               git_str details = GIT_STR_INIT;
+               git_str_printf(&details, "filename=%s, system=%s, autocrlf=%s, safecrlf=%s, attrs={%s}",
                        basename, cd->systype, cd->autocrlf, cd->safecrlf, cd->attrs);
                clar__fail(__FILE__, __func__, __LINE__,
                        "index contents did not match expected", details.ptr, 0);
-               git_buf_dispose(&details);
+               git_str_dispose(&details);
        }
 
        git__free(basename);
-       git_buf_dispose(&expected_contents);
-       git_buf_dispose(&expected_path);
-       git_buf_dispose(&expected_path_fail);
+       git_str_dispose(&expected_contents);
+       git_str_dispose(&expected_path);
+       git_str_dispose(&expected_path_fail);
        return 0;
 }
 
@@ -118,34 +118,34 @@ static const char *system_type(void)
 
 static void test_add_index(const char *safecrlf, const char *autocrlf, const char *attrs)
 {
-       git_buf attrbuf = GIT_BUF_INIT;
-       git_buf expected_dirname = GIT_BUF_INIT;
-       git_buf sandboxname = GIT_BUF_INIT;
-       git_buf reponame = GIT_BUF_INIT;
+       git_str attrbuf = GIT_STR_INIT;
+       git_str expected_dirname = GIT_STR_INIT;
+       git_str sandboxname = GIT_STR_INIT;
+       git_str reponame = GIT_STR_INIT;
        struct compare_data compare_data = { system_type(), NULL, safecrlf, autocrlf, attrs };
        const char *c;
 
-       git_buf_puts(&reponame, "crlf");
+       git_str_puts(&reponame, "crlf");
 
-       git_buf_puts(&sandboxname, "autocrlf_");
-       git_buf_puts(&sandboxname, autocrlf);
+       git_str_puts(&sandboxname, "autocrlf_");
+       git_str_puts(&sandboxname, autocrlf);
 
-       git_buf_puts(&sandboxname, ",safecrlf_");
-       git_buf_puts(&sandboxname, safecrlf);
+       git_str_puts(&sandboxname, ",safecrlf_");
+       git_str_puts(&sandboxname, safecrlf);
 
        if (*attrs) {
-               git_buf_puts(&sandboxname, ",");
+               git_str_puts(&sandboxname, ",");
 
                for (c = attrs; *c; c++) {
                        if (*c == ' ')
-                               git_buf_putc(&sandboxname, ',');
+                               git_str_putc(&sandboxname, ',');
                        else if (*c == '=')
-                               git_buf_putc(&sandboxname, '_');
+                               git_str_putc(&sandboxname, '_');
                        else
-                               git_buf_putc(&sandboxname, *c);
+                               git_str_putc(&sandboxname, *c);
                }
 
-               git_buf_printf(&attrbuf, "* %s\n", attrs);
+               git_str_printf(&attrbuf, "* %s\n", attrs);
                cl_git_mkfile("crlf/.gitattributes", attrbuf.ptr);
        }
 
@@ -154,23 +154,23 @@ static void test_add_index(const char *safecrlf, const char *autocrlf, const cha
 
        cl_git_pass(git_index_clear(g_index));
 
-       git_buf_joinpath(&expected_dirname, "crlf_data", system_type());
-       git_buf_puts(&expected_dirname, "_to_odb");
+       git_str_joinpath(&expected_dirname, "crlf_data", system_type());
+       git_str_puts(&expected_dirname, "_to_odb");
 
-       git_buf_joinpath(&expected_fixture, expected_dirname.ptr, sandboxname.ptr);
+       git_str_joinpath(&expected_fixture, expected_dirname.ptr, sandboxname.ptr);
        cl_fixture_sandbox(expected_fixture.ptr);
 
        compare_data.dirname = sandboxname.ptr;
-       cl_git_pass(git_path_direach(&reponame, 0, add_and_check_file, &compare_data));
+       cl_git_pass(git_fs_path_direach(&reponame, 0, add_and_check_file, &compare_data));
 
        cl_fixture_cleanup(expected_fixture.ptr);
-       git_buf_dispose(&expected_fixture);
+       git_str_dispose(&expected_fixture);
 
-       git_buf_dispose(&attrbuf);
-       git_buf_dispose(&expected_fixture);
-       git_buf_dispose(&expected_dirname);
-       git_buf_dispose(&sandboxname);
-       git_buf_dispose(&reponame);
+       git_str_dispose(&attrbuf);
+       git_str_dispose(&expected_fixture);
+       git_str_dispose(&expected_dirname);
+       git_str_dispose(&sandboxname);
+       git_str_dispose(&reponame);
 }
 
 static void set_up_workingdir(const char *name)
@@ -179,9 +179,9 @@ static void set_up_workingdir(const char *name)
        size_t i;
        const char *fn;
 
-       git_path_dirload(&contents, name, 0, 0);
+       git_fs_path_dirload(&contents, name, 0, 0);
        git_vector_foreach(&contents, i, fn) {
-               char *basename = git_path_basename(fn);
+               char *basename = git_fs_path_basename(fn);
                bool skip = strncasecmp(basename, ".git", 4) == 0 && strlen(basename) == 4;
 
                git__free(basename);
@@ -193,19 +193,19 @@ static void set_up_workingdir(const char *name)
        git_vector_free_deep(&contents);
 
        /* copy input files */
-       git_path_dirload(&contents, cl_fixture("crlf"), 0, 0);
+       git_fs_path_dirload(&contents, cl_fixture("crlf"), 0, 0);
        git_vector_foreach(&contents, i, fn) {
-               char *basename = git_path_basename(fn);
-               git_buf dest_filename = GIT_BUF_INIT;
+               char *basename = git_fs_path_basename(fn);
+               git_str dest_filename = GIT_STR_INIT;
 
                if (strcmp(basename, ".gitted") &&
                        strcmp(basename, ".gitattributes")) {
-                       git_buf_joinpath(&dest_filename, name, basename);
+                       git_str_joinpath(&dest_filename, name, basename);
                        cl_git_pass(git_futils_cp(fn, dest_filename.ptr, 0644));
                }
 
                git__free(basename);
-               git_buf_dispose(&dest_filename);
+               git_str_dispose(&dest_filename);
        }
        git_vector_free_deep(&contents);
 }
index 3d2bb4a0373adc20d7021c41e8cf3c10a4c74b21..1ab8a9a7ff74ba2c0e6358578e6bcb6b9a3efeaa 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "posix.h"
 #include "index.h"
 
@@ -36,10 +35,10 @@ void test_index_filemodes__read(void)
 static void replace_file_with_mode(
        const char *filename, const char *backup, unsigned int create_mode)
 {
-       git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT, content = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&path, "filemodes", filename));
-       cl_git_pass(git_buf_printf(&content, "%s as %08u (%d)",
+       cl_git_pass(git_str_joinpath(&path, "filemodes", filename));
+       cl_git_pass(git_str_printf(&content, "%s as %08u (%d)",
                filename, create_mode, rand()));
 
        cl_git_pass(p_rename(path.ptr, backup));
@@ -47,8 +46,8 @@ static void replace_file_with_mode(
                path.ptr, content.ptr, content.size,
                O_WRONLY|O_CREAT|O_TRUNC, create_mode);
 
-       git_buf_dispose(&path);
-       git_buf_dispose(&content);
+       git_str_dispose(&path);
+       git_str_dispose(&content);
 }
 
 #define add_and_check_mode(I,F,X) add_and_check_mode_(I,F,X,__FILE__,__func__,__LINE__)
index 6edcf030a75391173a8cda75fc733c3b2f1f14e9..3efd855a7e6d1772fc4c615cb457742f246235f0 100644 (file)
@@ -47,16 +47,16 @@ static bool try_create_file_with_nsec_timestamp(const char *path)
  */
 static bool should_expect_nsecs(void)
 {
-       git_buf nsec_path = GIT_BUF_INIT;
+       git_str nsec_path = GIT_STR_INIT;
        bool expect;
 
-       git_buf_joinpath(&nsec_path, clar_sandbox_path(), "nsec_test");
+       git_str_joinpath(&nsec_path, clar_sandbox_path(), "nsec_test");
 
        expect = try_create_file_with_nsec_timestamp(nsec_path.ptr);
 
        cl_must_pass(p_unlink(nsec_path.ptr));
 
-       git_buf_dispose(&nsec_path);
+       git_str_dispose(&nsec_path);
 
        return expect;
 }
index b06f55de4cc7ae4ea69961f71c970ca058531bb5..07b3b73d429f88d1032e612a66604bbf608befc7 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "../checkout/checkout_helpers.h"
 
-#include "buffer.h"
 #include "index.h"
 #include "repository.h"
 
@@ -24,9 +23,9 @@ void test_index_racy__diff(void)
 {
        git_index *index;
        git_diff *diff;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "A"));
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(g_repo), "A"));
        cl_git_mkfile(path.ptr, "A");
 
        /* Put 'A' into the index */
@@ -46,21 +45,21 @@ void test_index_racy__diff(void)
 
        git_index_free(index);
        git_diff_free(diff);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_index_racy__write_index_just_after_file(void)
 {
        git_index *index;
        git_diff *diff;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        struct p_timeval times[2];
 
        /* Make sure we do have a timestamp */
        cl_git_pass(git_repository_index(&index, g_repo));
        cl_git_pass(git_index_write(index));
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "A"));
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(g_repo), "A"));
        cl_git_mkfile(path.ptr, "A");
        /* Force the file's timestamp to be a second after we wrote the index */
        times[0].tv_sec = index->stamp.mtime.tv_sec + 1;
@@ -95,7 +94,7 @@ void test_index_racy__write_index_just_after_file(void)
        cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, NULL));
        cl_assert_equal_i(1, git_diff_num_deltas(diff));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_diff_free(diff);
        git_index_free(index);
 }
@@ -103,7 +102,7 @@ void test_index_racy__write_index_just_after_file(void)
 
 static void setup_race(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_index *index;
        git_index_entry *entry;
        struct stat st;
@@ -112,7 +111,7 @@ static void setup_race(void)
        cl_git_pass(git_repository_index__weakptr(&index, g_repo));
        cl_git_pass(git_index_write(index));
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "A"));
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(g_repo), "A"));
 
        cl_git_mkfile(path.ptr, "A");
        cl_git_pass(git_index_add_bypath(index, "A"));
@@ -129,7 +128,7 @@ static void setup_race(void)
        entry->mtime.seconds = (int32_t)st.st_mtime;
        entry->mtime.nanoseconds = (int32_t)st.st_mtime_nsec;
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_index_racy__smudges_index_entry_on_save(void)
@@ -169,14 +168,14 @@ void test_index_racy__detects_diff_of_change_in_identical_timestamp(void)
 
 static void setup_uptodate_files(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_index *index;
        const git_index_entry *a_entry;
        git_index_entry new_entry = {{0}};
 
        cl_git_pass(git_repository_index(&index, g_repo));
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "A"));
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(g_repo), "A"));
        cl_git_mkfile(path.ptr, "A");
 
        /* Put 'A' into the index */
@@ -196,7 +195,7 @@ static void setup_uptodate_files(void)
        cl_git_pass(git_index_add_from_buffer(index, &new_entry, "hello!\n", 7));
 
        git_index_free(index);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_index_racy__adding_to_index_is_uptodate(void)
index d9d8371dd50d98497b100c170f69b55af334892f..205d12e5b143137f51369bbb2fb1d35a256ca481 100644 (file)
@@ -28,7 +28,7 @@ static struct test_entry test_entries[] = {
 /* Helpers */
 static void copy_file(const char *src, const char *dst)
 {
-       git_buf source_buf = GIT_BUF_INIT;
+       git_str source_buf = GIT_STR_INIT;
        git_file dst_fd;
 
        cl_git_pass(git_futils_readbuffer(&source_buf, src));
@@ -40,28 +40,28 @@ static void copy_file(const char *src, const char *dst)
        cl_git_pass(p_write(dst_fd, source_buf.ptr, source_buf.size));
 
 cleanup:
-       git_buf_dispose(&source_buf);
+       git_str_dispose(&source_buf);
        p_close(dst_fd);
 }
 
 static void files_are_equal(const char *a, const char *b)
 {
-       git_buf buf_a = GIT_BUF_INIT;
-       git_buf buf_b = GIT_BUF_INIT;
+       git_str buf_a = GIT_STR_INIT;
+       git_str buf_b = GIT_STR_INIT;
        int pass;
 
        if (git_futils_readbuffer(&buf_a, a) < 0)
                cl_assert(0);
 
        if (git_futils_readbuffer(&buf_b, b) < 0) {
-               git_buf_dispose(&buf_a);
+               git_str_dispose(&buf_a);
                cl_assert(0);
        }
 
        pass = (buf_a.size == buf_b.size && !memcmp(buf_a.ptr, buf_b.ptr, buf_a.size));
 
-       git_buf_dispose(&buf_a);
-       git_buf_dispose(&buf_b);
+       git_str_dispose(&buf_a);
+       git_str_dispose(&buf_b);
 
        cl_assert(pass);
 }
@@ -200,14 +200,14 @@ void test_index_tests__write(void)
 
 void test_index_tests__sort0(void)
 {
-       /* sort the entires in an index */
+       /* sort the entries in an index */
 
    /*
    * TODO: This no longer applies:
    * index sorting in Git uses some specific changes to the way
    * directories are sorted.
    *
-   * We need to specificially check for this by creating a new
+   * We need to specifically check for this by creating a new
    * index, adding entries in random order and then
    * checking for consistency
    */
@@ -215,7 +215,7 @@ void test_index_tests__sort0(void)
 
 void test_index_tests__sort1(void)
 {
-   /* sort the entires in an empty index */
+   /* sort the entries in an empty index */
    git_index *index;
 
    cl_git_pass(git_index_open(&index, "fake-index"));
@@ -242,7 +242,7 @@ void test_index_tests__add(void)
 
        cl_set_cleanup(&cleanup_myrepo, NULL);
 
-       /* Intialize a new repository */
+       /* Initialize a new repository */
        cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
 
        /* Ensure we're the only guy in the room */
@@ -293,7 +293,7 @@ void test_index_tests__add_frombuffer(void)
 
        cl_set_cleanup(&cleanup_myrepo, NULL);
 
-       /* Intialize a new repository */
+       /* Initialize a new repository */
        cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
 
        /* Ensure we're the only guy in the room */
@@ -435,7 +435,7 @@ void test_index_tests__add_frombuffer_reset_entry(void)
 
        cl_set_cleanup(&cleanup_myrepo, NULL);
 
-       /* Intialize a new repository */
+       /* Initialize a new repository */
        cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
        cl_git_pass(git_repository_index(&index, repo));
        cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777));
@@ -544,12 +544,12 @@ void test_index_tests__add_bypath_to_a_bare_repository_returns_EBAREPO(void)
 static void assert_add_bypath_fails(git_repository *repo, const char *fn)
 {
        git_index *index;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        cl_git_pass(git_repository_index(&index, repo));
        cl_assert(git_index_entrycount(index) == 0);
 
-       git_buf_joinpath(&path, "./invalid", fn);
+       git_str_joinpath(&path, "./invalid", fn);
 
        cl_git_mkfile(path.ptr, NULL);
        cl_git_fail(git_index_add_bypath(index, fn));
@@ -557,7 +557,7 @@ static void assert_add_bypath_fails(git_repository *repo, const char *fn)
 
        cl_assert(git_index_entrycount(index) == 0);
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_index_free(index);
 }
 
@@ -571,9 +571,9 @@ void test_index_tests__cannot_add_invalid_filename(void)
        cl_must_pass(p_mkdir("./invalid/subdir", 0777));
 
        /* cl_git_mkfile() needs the dir to exist */
-       if (!git_path_exists("./invalid/.GIT"))
+       if (!git_fs_path_exists("./invalid/.GIT"))
                cl_must_pass(p_mkdir("./invalid/.GIT", 0777));
-       if (!git_path_exists("./invalid/.GiT"))
+       if (!git_fs_path_exists("./invalid/.GiT"))
                cl_must_pass(p_mkdir("./invalid/.GiT", 0777));
 
        assert_add_bypath_fails(repo, ".git/hello");
@@ -592,7 +592,7 @@ void test_index_tests__cannot_add_invalid_filename(void)
 static void assert_add_fails(git_repository *repo, const char *fn)
 {
        git_index *index;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_index_entry entry = {{0}};
 
        cl_git_pass(git_repository_index(&index, repo));
@@ -606,7 +606,7 @@ static void assert_add_fails(git_repository *repo, const char *fn)
 
        cl_assert(git_index_entrycount(index) == 0);
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_index_free(index);
 }
 
@@ -659,7 +659,7 @@ static void assert_write_fails(git_repository *repo, const char *fn_orig)
        git_index *index;
        git_oid expected;
        const git_index_entry *entry;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        char *fn;
 
        cl_git_pass(git_repository_index(&index, repo));
@@ -673,7 +673,7 @@ static void assert_write_fails(git_repository *repo, const char *fn_orig)
        replace_char(fn, '/', '_');
        replace_char(fn, ':', '!');
 
-       git_buf_joinpath(&path, "./invalid", fn);
+       git_str_joinpath(&path, "./invalid", fn);
 
        cl_git_mkfile(path.ptr, NULL);
 
@@ -691,7 +691,7 @@ static void assert_write_fails(git_repository *repo, const char *fn_orig)
        p_unlink(path.ptr);
 
        cl_git_pass(git_index_remove_all(index, NULL, NULL, NULL));
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_index_free(index);
        git__free(fn);
 }
index 25d8c29902e29288b4f4cdfac7c081a260215082..7218b4f758d5db1386da236e8c23d77eee49ad5b 100644 (file)
@@ -279,12 +279,12 @@ static const char *expected_index_ci[] = {
 
 void test_iterator_index__case_folding(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        int fs_is_ci = 0;
 
-       cl_git_pass(git_buf_joinpath(&path, cl_fixture("icase"), ".gitted/CoNfIg"));
-       fs_is_ci = git_path_exists(path.ptr);
-       git_buf_dispose(&path);
+       cl_git_pass(git_str_joinpath(&path, cl_fixture("icase"), ".gitted/CoNfIg"));
+       fs_is_ci = git_fs_path_exists(path.ptr);
+       git_str_dispose(&path);
 
        index_iterator_test(
                "icase", NULL, NULL, 0, ARRAY_SIZE(expected_index_cs),
@@ -978,22 +978,22 @@ void test_iterator_index__pathlist_with_directory(void)
 
 static void create_paths(git_index *index, const char *root, int depth)
 {
-       git_buf fullpath = GIT_BUF_INIT;
+       git_str fullpath = GIT_STR_INIT;
        git_index_entry entry;
        size_t root_len;
        int i;
 
        if (root) {
-               cl_git_pass(git_buf_puts(&fullpath, root));
-               cl_git_pass(git_buf_putc(&fullpath, '/'));
+               cl_git_pass(git_str_puts(&fullpath, root));
+               cl_git_pass(git_str_putc(&fullpath, '/'));
        }
 
        root_len = fullpath.size;
 
        for (i = 0; i < 8; i++) {
                bool file = (depth == 0 || (i % 2) == 0);
-               git_buf_truncate(&fullpath, root_len);
-               cl_git_pass(git_buf_printf(&fullpath, "item%d", i));
+               git_str_truncate(&fullpath, root_len);
+               cl_git_pass(git_str_printf(&fullpath, "item%d", i));
 
                if (file) {
                        memset(&entry, 0, sizeof(git_index_entry));
@@ -1007,7 +1007,7 @@ static void create_paths(git_index *index, const char *root, int depth)
                }
        }
 
-       git_buf_dispose(&fullpath);
+       git_str_dispose(&fullpath);
 }
 
 void test_iterator_index__pathlist_for_deeply_nested_item(void)
index f7fb9a7ee97f3b398a46aab44e1b691fcc0861cc..4145c8dea2942be4d1f26b88d801ceb5fca15e4a 100644 (file)
@@ -623,7 +623,7 @@ static void build_test_tree(
        const char *scan = fmt, *next;
        char type, delimiter;
        git_filemode_t mode = GIT_FILEMODE_BLOB;
-       git_buf name = GIT_BUF_INIT;
+       git_str name = GIT_STR_INIT;
        va_list arglist;
 
        cl_git_pass(git_treebuilder_new(&builder, repo, NULL)); /* start builder */
@@ -640,7 +640,7 @@ static void build_test_tree(
                delimiter = *scan++; /* read and skip delimiter */
                for (next = scan; *next && *next != delimiter; ++next)
                        /* seek end */;
-               cl_git_pass(git_buf_set(&name, scan, (size_t)(next - scan)));
+               cl_git_pass(git_str_set(&name, scan, (size_t)(next - scan)));
                for (scan = next; *scan && (*scan == delimiter || *scan == ','); ++scan)
                        /* skip delimiter and optional comma */;
 
@@ -653,7 +653,7 @@ static void build_test_tree(
        cl_git_pass(git_treebuilder_write(out, builder));
 
        git_treebuilder_free(builder);
-       git_buf_dispose(&name);
+       git_str_dispose(&name);
 }
 
 void test_iterator_tree__case_conflicts_0(void)
index 82ee363f9f7b98c19dd9fca6158200b306e8c870..86b847cab668dbd95f7a8687ef27c1f1796f0dab 100644 (file)
@@ -643,7 +643,7 @@ void test_iterator_workdir__filesystem2(void)
  */
 void test_iterator_workdir__filesystem_gunk(void)
 {
-       git_buf parent = GIT_BUF_INIT;
+       git_str parent = GIT_STR_INIT;
        git_iterator *i;
        int n;
 
@@ -653,8 +653,8 @@ void test_iterator_workdir__filesystem_gunk(void)
        g_repo = cl_git_sandbox_init("testrepo");
 
        for (n = 0; n < 100000; n++) {
-               git_buf_clear(&parent);
-               cl_git_pass(git_buf_printf(&parent, "%s/refs/heads/foo/%d/subdir", git_repository_path(g_repo), n));
+               git_str_clear(&parent);
+               cl_git_pass(git_str_printf(&parent, "%s/refs/heads/foo/%d/subdir", git_repository_path(g_repo), n));
                cl_git_pass(git_futils_mkdir(parent.ptr, 0775, GIT_MKDIR_PATH));
        }
 
@@ -667,7 +667,7 @@ void test_iterator_workdir__filesystem_gunk(void)
        expect_iterator_items(i, 17, NULL, 16, NULL);
 
        git_iterator_free(i);
-       git_buf_dispose(&parent);
+       git_str_dispose(&parent);
 }
 
 void test_iterator_workdir__skips_unreadable_dirs(void)
@@ -1019,19 +1019,19 @@ void test_iterator_workdir__pathlist_with_dirs(void)
 
 static void create_paths(const char *root, int depth)
 {
-       git_buf fullpath = GIT_BUF_INIT;
+       git_str fullpath = GIT_STR_INIT;
        size_t root_len;
        int i;
 
-       cl_git_pass(git_buf_puts(&fullpath, root));
-       cl_git_pass(git_path_to_dir(&fullpath));
+       cl_git_pass(git_str_puts(&fullpath, root));
+       cl_git_pass(git_fs_path_to_dir(&fullpath));
 
        root_len = fullpath.size;
 
        for (i = 0; i < 8; i++) {
                bool file = (depth == 0 || (i % 2) == 0);
-               git_buf_truncate(&fullpath, root_len);
-               cl_git_pass(git_buf_printf(&fullpath, "item%d", i));
+               git_str_truncate(&fullpath, root_len);
+               cl_git_pass(git_str_printf(&fullpath, "item%d", i));
 
                if (file) {
                        cl_git_rewritefile(fullpath.ptr, "This is a file!\n");
@@ -1043,7 +1043,7 @@ static void create_paths(const char *root, int depth)
                }
        }
 
-       git_buf_dispose(&fullpath);
+       git_str_dispose(&fullpath);
 }
 
 void test_iterator_workdir__pathlist_for_deeply_nested_item(void)
index ba3b3a2f6dbf9a645d5027c49136eb210e284ed5..5ea470f34ac322e05dc29e606857c44ef8f02644 100644 (file)
@@ -103,15 +103,15 @@ void test_mailmap_parsing__string(void)
 
 void test_mailmap_parsing__windows_string(void)
 {
-       git_buf unixbuf = GIT_BUF_INIT;
-       git_buf winbuf = GIT_BUF_INIT;
+       git_str unixbuf = GIT_STR_INIT;
+       git_str winbuf = GIT_STR_INIT;
 
        /* Parse with windows-style line endings */
-       git_buf_attach_notowned(&unixbuf, string_mailmap, strlen(string_mailmap));
-       cl_git_pass(git_buf_lf_to_crlf(&winbuf, &unixbuf));
+       git_str_attach_notowned(&unixbuf, string_mailmap, strlen(string_mailmap));
+       cl_git_pass(git_str_lf_to_crlf(&winbuf, &unixbuf));
 
        cl_git_pass(git_mailmap_from_buffer(&g_mailmap, winbuf.ptr, winbuf.size));
-       git_buf_dispose(&winbuf);
+       git_str_dispose(&winbuf);
 
        /* We should have parsed all of the entries */
        check_mailmap_entries(g_mailmap, entries, ARRAY_SIZE(entries));
index 56751c288691759c99553cd3b7c2e7021efb9a19..d879073a8257a551eadd4ce2bf68dd3744aebad2 100644 (file)
@@ -26,6 +26,7 @@ int main(int argc, char *argv[])
 
        cl_global_trace_register();
        cl_sandbox_set_search_path_defaults();
+       cl_sandbox_disable_ownership_validation();
 
        /* Run the test suite */
        res = clar_test_run();
index 1432a7d112f5086c33c798d9a11e94db6fda39aa..8c61303e342c9b2d28d2e2efe525e9fdbc1f8cf8 100644 (file)
@@ -53,28 +53,28 @@ static void analysis_from_branch(
        const char *our_branchname,
        const char *their_branchname)
 {
-       git_buf our_refname = GIT_BUF_INIT;
-       git_buf their_refname = GIT_BUF_INIT;
+       git_str our_refname = GIT_STR_INIT;
+       git_str their_refname = GIT_STR_INIT;
        git_reference *our_ref;
        git_reference *their_ref;
        git_annotated_commit *their_head;
 
        if (our_branchname != NULL) {
-               cl_git_pass(git_buf_printf(&our_refname, "%s%s", GIT_REFS_HEADS_DIR, our_branchname));
-               cl_git_pass(git_reference_lookup(&our_ref, repo, git_buf_cstr(&our_refname)));
+               cl_git_pass(git_str_printf(&our_refname, "%s%s", GIT_REFS_HEADS_DIR, our_branchname));
+               cl_git_pass(git_reference_lookup(&our_ref, repo, git_str_cstr(&our_refname)));
        } else {
                cl_git_pass(git_reference_lookup(&our_ref, repo, GIT_HEAD_FILE));
        }
 
-       cl_git_pass(git_buf_printf(&their_refname, "%s%s", GIT_REFS_HEADS_DIR, their_branchname));
+       cl_git_pass(git_str_printf(&their_refname, "%s%s", GIT_REFS_HEADS_DIR, their_branchname));
 
-       cl_git_pass(git_reference_lookup(&their_ref, repo, git_buf_cstr(&their_refname)));
+       cl_git_pass(git_reference_lookup(&their_ref, repo, git_str_cstr(&their_refname)));
        cl_git_pass(git_annotated_commit_from_ref(&their_head, repo, their_ref));
 
        cl_git_pass(git_merge_analysis_for_ref(merge_analysis, merge_pref, repo, our_ref, (const git_annotated_commit **)&their_head, 1));
 
-       git_buf_dispose(&our_refname);
-       git_buf_dispose(&their_refname);
+       git_str_dispose(&our_refname);
+       git_str_dispose(&their_refname);
        git_annotated_commit_free(their_head);
        git_reference_free(our_ref);
        git_reference_free(their_ref);
@@ -120,15 +120,15 @@ void test_merge_analysis__unborn(void)
 {
        git_merge_analysis_t merge_analysis;
        git_merge_preference_t merge_pref;
-       git_buf master = GIT_BUF_INIT;
+       git_str master = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&master, git_repository_path(repo), "refs/heads/master"));
-       cl_must_pass(p_unlink(git_buf_cstr(&master)));
+       cl_git_pass(git_str_joinpath(&master, git_repository_path(repo), "refs/heads/master"));
+       cl_must_pass(p_unlink(git_str_cstr(&master)));
 
        analysis_from_branch(&merge_analysis, &merge_pref, NULL, NOFASTFORWARD_BRANCH);
        cl_assert_equal_i(GIT_MERGE_ANALYSIS_FASTFORWARD|GIT_MERGE_ANALYSIS_UNBORN, merge_analysis);
 
-       git_buf_dispose(&master);
+       git_str_dispose(&master);
 }
 
 void test_merge_analysis__fastforward_with_config_noff(void)
index 27f19c1b01b1c281fee998e2b3048549b525dc7c..0b1e7ee032ee5b9315b97d89edb766d8e7696957 100644 (file)
        "this file is changed in branch and master\n" \
        ">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n"
 
+#define CONFLICTING_ZDIFF3_FILE \
+       "<<<<<<< HEAD\n" \
+       "this file is changed in master and branch\n" \
+       "||||||| initial\n" \
+       "this file is a conflict\n" \
+       "=======\n" \
+       "this file is changed in branch and master\n" \
+       ">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n"
+
 #define CONFLICTING_UNION_FILE \
        "this file is changed in master and branch\n" \
        "this file is changed in branch and master\n"
index a3fececb4628e4045a4e5ff508ef5c0d679d8eaf..b7d320cbbb88f2e1e774ebecb50570b60c81ef6e 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "git2/repository.h"
 #include "git2/merge.h"
-#include "buffer.h"
 #include "merge.h"
 
 #define TEST_REPO_PATH "merge-resolve"
@@ -71,14 +70,23 @@ static int test_driver_apply(
        const char *filter_name,
        const git_merge_driver_source *src)
 {
+       git_str str = GIT_STR_INIT;
+       int error;
+
        GIT_UNUSED(s);
        GIT_UNUSED(src);
 
        *path_out = "applied.txt";
        *mode_out = GIT_FILEMODE_BLOB;
 
-       return git_buf_printf(merged_out, "This is the `%s` driver.\n",
+       error = git_str_printf(&str, "This is the `%s` driver.\n",
                filter_name);
+
+       merged_out->ptr = str.ptr;
+       merged_out->size = str.size;
+       merged_out->reserved = 0;
+
+       return error;
 }
 
 static struct test_merge_driver test_driver_custom = {
@@ -117,19 +125,19 @@ static void test_drivers_unregister(void)
 
 static void set_gitattributes_to(const char *driver)
 {
-       git_buf line = GIT_BUF_INIT;
+       git_str line = GIT_STR_INIT;
 
        if (driver && strcmp(driver, ""))
-               git_buf_printf(&line, "automergeable.txt merge=%s\n", driver);
+               git_str_printf(&line, "automergeable.txt merge=%s\n", driver);
        else if (driver)
-               git_buf_printf(&line, "automergeable.txt merge\n");
+               git_str_printf(&line, "automergeable.txt merge\n");
        else
-               git_buf_printf(&line, "automergeable.txt -merge\n");
+               git_str_printf(&line, "automergeable.txt -merge\n");
 
-       cl_assert(!git_buf_oom(&line));
+       cl_assert(!git_str_oom(&line));
 
        cl_git_mkfile(TEST_REPO_PATH "/.gitattributes", line.ptr);
-       git_buf_dispose(&line);
+       git_str_dispose(&line);
 }
 
 static void merge_branch(void)
@@ -172,11 +180,11 @@ void test_merge_driver__shutdown_is_called(void)
     test_driver_custom.shutdown = 0;
     test_driver_wildcard.initialized = 0;
     test_driver_wildcard.shutdown = 0;
-    
+
     /* run the merge with the custom driver */
     set_gitattributes_to("custom");
     merge_branch();
-    
+
        /* unregister the drivers, ensure their shutdown function is called */
        test_drivers_unregister();
 
index 6877f984865049a987c380af65eb312b41ecefa6..6296f3b7b683e0820e6d33d7f43ac52aa99c6d67 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "git2/repository.h"
 #include "git2/merge.h"
-#include "buffer.h"
 #include "merge.h"
 #include "merge_helpers.h"
 #include "conflict_data.h"
@@ -425,3 +424,42 @@ void test_merge_files__crlf_conflict_markers_for_crlf_files(void)
        cl_assert(memcmp(expected_diff3, result.ptr, expected_len) == 0);
        git_merge_file_result_free(&result);
 }
+
+void test_merge_files__conflicts_in_zdiff3(void)
+{
+       git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT,
+               ours = GIT_MERGE_FILE_INPUT_INIT,
+               theirs = GIT_MERGE_FILE_INPUT_INIT;
+       git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT;
+       git_merge_file_result result = {0};
+
+       const char *expected_zdiff3 =
+               "1,\nfoo,\nbar,\n" \
+               "<<<<<<< file.txt\n" \
+               "||||||| file.txt\n# add more here\n" \
+               "=======\nquux,\nwoot,\n" \
+               ">>>>>>> file.txt\nbaz,\n3,\n";
+       size_t expected_zdiff3_len = strlen(expected_zdiff3);
+
+       ancestor.ptr = "1,\n# add more here\n3,\n";
+       ancestor.size = strlen(ancestor.ptr);
+       ancestor.path = "file.txt";
+       ancestor.mode = 0100644;
+
+       ours.ptr = "1,\nfoo,\nbar,\nbaz,\n3,\n";
+       ours.size = strlen(ours.ptr);
+       ours.path = "file.txt";
+       ours.mode = 0100644;
+
+       theirs.ptr = "1,\nfoo,\nbar,\nquux,\nwoot,\nbaz,\n3,\n";
+       theirs.size = strlen(theirs.ptr);
+       theirs.path = "file.txt";
+       theirs.mode = 0100644;
+
+       opts.flags |= GIT_MERGE_FILE_STYLE_ZDIFF3;
+       cl_git_pass(git_merge_file(&result, &ancestor, &ours, &theirs, &opts));
+       cl_assert_equal_i(0, result.automergeable);
+       cl_assert_equal_i(expected_zdiff3_len, result.len);
+       cl_assert(memcmp(expected_zdiff3, result.ptr, expected_zdiff3_len) == 0);
+       git_merge_file_result_free(&result);
+}
index 27f355f35300c55f26eb8541b3846c9abeb22526..ce3cd229bb015c07a8c7063e60892289ad4f6200 100644 (file)
@@ -17,15 +17,15 @@ int merge_trees_from_branches(
        git_commit *our_commit, *their_commit, *ancestor_commit = NULL;
        git_tree *our_tree, *their_tree, *ancestor_tree = NULL;
        git_oid our_oid, their_oid, ancestor_oid;
-       git_buf branch_buf = GIT_BUF_INIT;
+       git_str branch_buf = GIT_STR_INIT;
        int error;
 
-       git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours_name);
+       git_str_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours_name);
        cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr));
        cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid));
 
-       git_buf_clear(&branch_buf);
-       git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs_name);
+       git_str_clear(&branch_buf);
+       git_str_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs_name);
        cl_git_pass(git_reference_name_to_id(&their_oid, repo, branch_buf.ptr));
        cl_git_pass(git_commit_lookup(&their_commit, repo, &their_oid));
 
@@ -43,7 +43,7 @@ int merge_trees_from_branches(
 
        error = git_merge_trees(index, repo, ancestor_tree, our_tree, their_tree, opts);
 
-       git_buf_dispose(&branch_buf);
+       git_str_dispose(&branch_buf);
        git_tree_free(our_tree);
        git_tree_free(their_tree);
        git_tree_free(ancestor_tree);
@@ -61,21 +61,21 @@ int merge_commits_from_branches(
 {
        git_commit *our_commit, *their_commit;
        git_oid our_oid, their_oid;
-       git_buf branch_buf = GIT_BUF_INIT;
+       git_str branch_buf = GIT_STR_INIT;
        int error;
 
-       git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours_name);
+       git_str_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours_name);
        cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr));
        cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid));
 
-       git_buf_clear(&branch_buf);
-       git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs_name);
+       git_str_clear(&branch_buf);
+       git_str_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs_name);
        cl_git_pass(git_reference_name_to_id(&their_oid, repo, branch_buf.ptr));
        cl_git_pass(git_commit_lookup(&their_commit, repo, &their_oid));
 
        error = git_merge_commits(index, repo, our_commit, their_commit, opts);
 
-       git_buf_dispose(&branch_buf);
+       git_str_dispose(&branch_buf);
        git_commit_free(our_commit);
        git_commit_free(their_commit);
 
@@ -328,12 +328,12 @@ int merge_test_reuc(git_index *index, const struct merge_reuc_entry expected[],
        return 1;
 }
 
-int dircount(void *payload, git_buf *pathbuf)
+static int dircount(void *payload, git_str *pathbuf)
 {
        size_t *entries = payload;
-       size_t len = git_buf_len(pathbuf);
+       size_t len = git_str_len(pathbuf);
 
-       if (len < 5 || strcmp(pathbuf->ptr + (git_buf_len(pathbuf) - 5), "/.git") != 0)
+       if (len < 5 || strcmp(pathbuf->ptr + (git_str_len(pathbuf) - 5), "/.git") != 0)
                (*entries)++;
 
        return 0;
@@ -343,10 +343,10 @@ int merge_test_workdir(git_repository *repo, const struct merge_index_entry expe
 {
        size_t actual_len = 0, i;
        git_oid actual_oid, expected_oid;
-       git_buf wd = GIT_BUF_INIT;
+       git_str wd = GIT_STR_INIT;
 
-       git_buf_puts(&wd, repo->workdir);
-       git_path_direach(&wd, 0, dircount, &actual_len);
+       git_str_puts(&wd, repo->workdir);
+       git_fs_path_direach(&wd, 0, dircount, &actual_len);
 
        if (actual_len != expected_len)
                return 0;
@@ -359,7 +359,7 @@ int merge_test_workdir(git_repository *repo, const struct merge_index_entry expe
                        return 0;
        }
 
-       git_buf_dispose(&wd);
+       git_str_dispose(&wd);
 
        return 1;
 }
index 166b4eefddb68d66f277bb091b7cb4519a29ca18..339812ba590717a4c867168ab021dd8f6c41bd06 100644 (file)
@@ -65,4 +65,8 @@ int merge_test_reuc(git_index *index, const struct merge_reuc_entry expected[],
 
 int merge_test_workdir(git_repository *repo, const struct merge_index_entry expected[], size_t expected_len);
 
+void merge__dump_names(git_index *index);
+void merge__dump_index_entries(git_vector *index_entries);
+void merge__dump_reuc(git_index *index);
+
 #endif
index dd26464fbeeee4004391d6173ee82004a691b287..3bf6c5208442f002989fab4573ac57dfc1b652c2 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "git2/repository.h"
 #include "git2/merge.h"
-#include "buffer.h"
 #include "merge.h"
 #include "futils.h"
 #include "../merge_helpers.h"
index 32866ea6d3692847b620f8e3fcc0cf9f1df78319..a0521c4e855861da51c3ccc94a4e8cc8003ea145 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "git2/repository.h"
 #include "git2/merge.h"
-#include "buffer.h"
 #include "merge.h"
 #include "../merge_helpers.h"
 #include "futils.h"
index eef7bc96be065493010c04eaac2e2185039b403e..26f6d33062ac42212b1c1620ffe7931ac7c32a96 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "git2/repository.h"
 #include "git2/merge.h"
-#include "buffer.h"
 #include "merge.h"
 #include "../merge_helpers.h"
 #include "futils.h"
@@ -279,7 +278,7 @@ void test_merge_trees_renames__cache_recomputation(void)
 {
        git_oid blob, binary, ancestor_oid, theirs_oid, ours_oid;
        git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_treebuilder *builder;
        git_tree *ancestor_tree, *their_tree, *our_tree;
        git_index *index;
@@ -307,9 +306,9 @@ void test_merge_trees_renames__cache_recomputation(void)
         */
        cl_git_pass(git_treebuilder_new(&builder, repo, NULL));
        for (i = 0; i < 1000; i++) {
-               cl_git_pass(git_buf_printf(&path, "%"PRIuZ".txt", i));
+               cl_git_pass(git_str_printf(&path, "%"PRIuZ".txt", i));
                cl_git_pass(git_treebuilder_insert(NULL, builder, path.ptr, &blob, GIT_FILEMODE_BLOB));
-               git_buf_clear(&path);
+               git_str_clear(&path);
        }
        cl_git_pass(git_treebuilder_insert(NULL, builder, "original.bin", &binary, GIT_FILEMODE_BLOB));
        cl_git_pass(git_treebuilder_write(&ancestor_oid, builder));
@@ -344,7 +343,7 @@ void test_merge_trees_renames__cache_recomputation(void)
        cl_git_pass(git_merge_trees(&index, repo, ancestor_tree, our_tree, their_tree, &opts));
 
        git_treebuilder_free(builder);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_index_free(index);
        git_tree_free(ancestor_tree);
        git_tree_free(their_tree);
index ac4f09f80f8eca24923812e22bfaf21567a393b1..dce392c863e5419da4c669515356d766f80f3923 100644 (file)
@@ -30,15 +30,15 @@ static int merge_trivial(git_index **index, const char *ours, const char *theirs
        git_commit *our_commit, *their_commit, *ancestor_commit;
        git_tree *our_tree, *their_tree, *ancestor_tree;
        git_oid our_oid, their_oid, ancestor_oid;
-       git_buf branch_buf = GIT_BUF_INIT;
+       git_str branch_buf = GIT_STR_INIT;
        git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
 
-       git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours);
+       git_str_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours);
        cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr));
        cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid));
 
-       git_buf_clear(&branch_buf);
-       git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs);
+       git_str_clear(&branch_buf);
+       git_str_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs);
        cl_git_pass(git_reference_name_to_id(&their_oid, repo, branch_buf.ptr));
        cl_git_pass(git_commit_lookup(&their_commit, repo, &their_oid));
 
@@ -51,7 +51,7 @@ static int merge_trivial(git_index **index, const char *ours, const char *theirs
 
        cl_git_pass(git_merge_trees(index, repo, ancestor_tree, our_tree, their_tree, &opts));
 
-       git_buf_dispose(&branch_buf);
+       git_str_dispose(&branch_buf);
        git_tree_free(our_tree);
        git_tree_free(their_tree);
        git_tree_free(ancestor_tree);
index ce7703496452de302e552e591872cb92f3c003c2..9917df506daf413a1534efd5bb85fbad5a2b70e0 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "git2/repository.h"
 #include "git2/merge.h"
-#include "buffer.h"
 #include "merge.h"
 #include "../merge_helpers.h"
 #include "futils.h"
index 6044bca43b949160856a32402f821ee751658fdf..b9c2ad0330c98a0c10ca90a8af2dbbd4de8576cf 100644 (file)
@@ -1,6 +1,5 @@
 #include "clar_libgit2.h"
 #include "git2/merge.h"
-#include "buffer.h"
 #include "merge.h"
 #include "index.h"
 #include "../merge_helpers.h"
@@ -109,29 +108,29 @@ static int merge_branch(void)
 static void write_files(char *files[])
 {
        char *filename;
-       git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT, content = GIT_STR_INIT;
        size_t i;
 
        for (i = 0, filename = files[i]; filename; filename = files[++i]) {
-               git_buf_clear(&path);
-               git_buf_clear(&content);
+               git_str_clear(&path);
+               git_str_clear(&content);
 
-               git_buf_printf(&path, "%s/%s", TEST_REPO_PATH, filename);
-               git_buf_printf(&content, "This is a dirty file in the working directory!\n\n"
+               git_str_printf(&path, "%s/%s", TEST_REPO_PATH, filename);
+               git_str_printf(&content, "This is a dirty file in the working directory!\n\n"
                        "It will not be staged!  Its filename is %s.\n", filename);
 
                cl_git_mkfile(path.ptr, content.ptr);
        }
 
-       git_buf_dispose(&path);
-       git_buf_dispose(&content);
+       git_str_dispose(&path);
+       git_str_dispose(&content);
 }
 
 static void hack_index(char *files[])
 {
        char *filename;
        struct stat statbuf;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_index_entry *entry;
        struct p_timeval times[2];
        time_t now;
@@ -153,12 +152,12 @@ static void hack_index(char *files[])
        times[1].tv_usec = 0;
 
        for (i = 0, filename = files[i]; filename; filename = files[++i]) {
-               git_buf_clear(&path);
+               git_str_clear(&path);
 
                cl_assert(entry = (git_index_entry *)
                        git_index_get_bypath(repo_index, filename, 0));
 
-               cl_git_pass(git_buf_printf(&path, "%s/%s", TEST_REPO_PATH, filename));
+               cl_git_pass(git_str_printf(&path, "%s/%s", TEST_REPO_PATH, filename));
                cl_git_pass(p_utimes(path.ptr, times));
                cl_git_pass(p_stat(path.ptr, &statbuf));
 
@@ -178,7 +177,7 @@ static void hack_index(char *files[])
                entry->file_size = (uint32_t)statbuf.st_size;
        }
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 static void stage_random_files(char *files[])
@@ -196,7 +195,7 @@ static void stage_content(char *content[])
 {
        git_reference *head;
        git_object *head_object;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        char *filename, *text;
        size_t i;
 
@@ -208,9 +207,9 @@ static void stage_content(char *content[])
                filename && text;
                filename = content[++i], text = content[++i]) {
 
-               git_buf_clear(&path);
+               git_str_clear(&path);
 
-               cl_git_pass(git_buf_printf(&path, "%s/%s", TEST_REPO_PATH, filename));
+               cl_git_pass(git_str_printf(&path, "%s/%s", TEST_REPO_PATH, filename));
 
                cl_git_mkfile(path.ptr, text);
                cl_git_pass(git_index_add_bypath(repo_index, filename));
@@ -218,7 +217,7 @@ static void stage_content(char *content[])
 
        git_object_free(head_object);
        git_reference_free(head);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 static int merge_dirty_files(char *dirty_files[])
index e7dc267e49b7f34abd0dc47b79b436a751e2d07d..7669e1b1ac1de46bd0c5e3bdb4ffa0cb2288c9d4 100644 (file)
@@ -23,7 +23,7 @@ void test_merge_workdir_recursive__writes_conflict_with_virtual_base(void)
 {
        git_index *index;
        git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
-       git_buf conflicting_buf = GIT_BUF_INIT;
+       git_str conflicting_buf = GIT_STR_INIT;
 
        struct merge_index_entry merge_index_entries[] = {
                { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" },
@@ -46,7 +46,7 @@ void test_merge_workdir_recursive__writes_conflict_with_virtual_base(void)
        cl_assert_equal_s(CONFLICTING_RECURSIVE_F1_TO_F2, conflicting_buf.ptr);
 
        git_index_free(index);
-       git_buf_dispose(&conflicting_buf);
+       git_str_dispose(&conflicting_buf);
 }
 
 void test_merge_workdir_recursive__conflicting_merge_base_with_diff3(void)
@@ -54,7 +54,7 @@ void test_merge_workdir_recursive__conflicting_merge_base_with_diff3(void)
        git_index *index;
        git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
        git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
-       git_buf conflicting_buf = GIT_BUF_INIT;
+       git_str conflicting_buf = GIT_STR_INIT;
 
        struct merge_index_entry merge_index_entries[] = {
                { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" },
@@ -80,5 +80,5 @@ void test_merge_workdir_recursive__conflicting_merge_base_with_diff3(void)
        cl_assert_equal_s(CONFLICTING_RECURSIVE_H2_TO_H1_WITH_DIFF3, conflicting_buf.ptr);
 
        git_index_free(index);
-       git_buf_dispose(&conflicting_buf);
+       git_str_dispose(&conflicting_buf);
 }
index e8cd333af80cc00502edf913ea44ee62aed43f34..1b5128cf1b7185770134283c43438c9165a949d1 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "git2/repository.h"
 #include "git2/merge.h"
-#include "buffer.h"
 #include "merge.h"
 #include "../merge_helpers.h"
 #include "futils.h"
index 0b85f271244342dde0b6615f599cdafa530a3db9..3db2d074fb9ae4d27cf1b45b59ccc92a948e0c48 100644 (file)
@@ -46,29 +46,29 @@ void test_merge_workdir_setup__cleanup(void)
 
 static bool test_file_contents(const char *filename, const char *expected)
 {
-       git_buf file_path_buf = GIT_BUF_INIT, file_buf = GIT_BUF_INIT;
+       git_str file_path_buf = GIT_STR_INIT, file_buf = GIT_STR_INIT;
        bool equals;
-       
-       git_buf_joinpath(&file_path_buf, git_repository_path(repo), filename);
-       
+
+       git_str_joinpath(&file_path_buf, git_repository_path(repo), filename);
+
        cl_git_pass(git_futils_readbuffer(&file_buf, file_path_buf.ptr));
        equals = (strcmp(file_buf.ptr, expected) == 0);
 
-       git_buf_dispose(&file_path_buf);
-       git_buf_dispose(&file_buf);
-       
+       git_str_dispose(&file_path_buf);
+       git_str_dispose(&file_buf);
+
        return equals;
 }
 
 static void write_file_contents(const char *filename, const char *output)
 {
-       git_buf file_path_buf = GIT_BUF_INIT;
+       git_str file_path_buf = GIT_STR_INIT;
 
-       git_buf_joinpath(&file_path_buf, git_repository_path(repo),
+       git_str_joinpath(&file_path_buf, git_repository_path(repo),
                filename);
        cl_git_rewritefile(file_path_buf.ptr, output);
 
-       git_buf_dispose(&file_path_buf);
+       git_str_dispose(&file_path_buf);
 }
 
 /* git merge --no-ff octo1 */
@@ -77,13 +77,13 @@ void test_merge_workdir_setup__one_branch(void)
        git_oid our_oid;
        git_reference *octo1_ref;
        git_annotated_commit *our_head, *their_heads[1];
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
-       
+
        cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref));
-       
+
        cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 1));
 
        cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n"));
@@ -92,7 +92,7 @@ void test_merge_workdir_setup__one_branch(void)
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'\n"));
 
        git_reference_free(octo1_ref);
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
 }
@@ -103,10 +103,10 @@ void test_merge_workdir_setup__one_oid(void)
        git_oid our_oid;
        git_oid octo1_oid;
        git_annotated_commit *our_head, *their_heads[1];
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
-       
+
        cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
        cl_git_pass(git_annotated_commit_lookup(&their_heads[0], repo, &octo1_oid));
 
@@ -128,10 +128,10 @@ void test_merge_workdir_setup__two_branches(void)
        git_reference *octo1_ref;
        git_reference *octo2_ref;
        git_annotated_commit *our_head, *their_heads[2];
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
-       
+
        cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref));
 
@@ -139,15 +139,15 @@ void test_merge_workdir_setup__two_branches(void)
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[1], repo, octo2_ref));
 
        cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 2));
-       
+
        cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n"));
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO2_BRANCH "'\n"));
-       
+
        git_reference_free(octo1_ref);
        git_reference_free(octo2_ref);
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
        git_annotated_commit_free(their_heads[1]);
@@ -161,13 +161,13 @@ void test_merge_workdir_setup__three_branches(void)
        git_reference *octo2_ref;
        git_reference *octo3_ref;
        git_annotated_commit *our_head, *their_heads[3];
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
 
        cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref));
-       
+
        cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[1], repo, octo2_ref));
 
@@ -180,7 +180,7 @@ void test_merge_workdir_setup__three_branches(void)
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO2_BRANCH "' and '" OCTO3_BRANCH "'\n"));
-       
+
        git_reference_free(octo1_ref);
        git_reference_free(octo2_ref);
        git_reference_free(octo3_ref);
@@ -199,13 +199,13 @@ void test_merge_workdir_setup__three_oids(void)
        git_oid octo2_oid;
        git_oid octo3_oid;
        git_annotated_commit *our_head, *their_heads[3];
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
 
        cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
        cl_git_pass(git_annotated_commit_lookup(&their_heads[0], repo, &octo1_oid));
-       
+
        cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID));
        cl_git_pass(git_annotated_commit_lookup(&their_heads[1], repo, &octo2_oid));
 
@@ -218,7 +218,7 @@ void test_merge_workdir_setup__three_oids(void)
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; commit '" OCTO2_OID "'; commit '" OCTO3_OID "'\n"));
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
        git_annotated_commit_free(their_heads[1]);
@@ -232,7 +232,7 @@ void test_merge_workdir_setup__branches_and_oids_1(void)
        git_reference *octo1_ref;
        git_oid octo2_oid;
        git_annotated_commit *our_head, *their_heads[2];
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
 
@@ -248,7 +248,7 @@ void test_merge_workdir_setup__branches_and_oids_1(void)
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'; commit '" OCTO2_OID "'\n"));
-       
+
        git_reference_free(octo1_ref);
 
        git_annotated_commit_free(our_head);
@@ -271,23 +271,23 @@ void test_merge_workdir_setup__branches_and_oids_2(void)
 
        cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref));
-       
+
        cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID));
        cl_git_pass(git_annotated_commit_lookup(&their_heads[1], repo, &octo2_oid));
 
        cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[2], repo, octo3_ref));
-       
+
        cl_git_pass(git_oid_fromstr(&octo4_oid, OCTO4_OID));
        cl_git_pass(git_annotated_commit_lookup(&their_heads[3], repo, &octo4_oid));
-       
+
        cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 4));
 
        cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n"));
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO3_BRANCH "'; commit '" OCTO2_OID "'; commit '" OCTO4_OID "'\n"));
-       
+
        git_reference_free(octo1_ref);
        git_reference_free(octo3_ref);
 
@@ -307,7 +307,7 @@ void test_merge_workdir_setup__branches_and_oids_3(void)
        git_oid octo3_oid;
        git_reference *octo4_ref;
        git_annotated_commit *our_head, *their_heads[4];
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
 
@@ -319,17 +319,17 @@ void test_merge_workdir_setup__branches_and_oids_3(void)
 
        cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID));
        cl_git_pass(git_annotated_commit_lookup(&their_heads[2], repo, &octo3_oid));
-       
+
        cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[3], repo, octo4_ref));
-       
+
        cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 4));
 
        cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n"));
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; branches '" OCTO2_BRANCH "' and '" OCTO4_BRANCH "'; commit '" OCTO3_OID "'\n"));
-       
+
        git_reference_free(octo2_ref);
        git_reference_free(octo4_ref);
 
@@ -350,19 +350,19 @@ void test_merge_workdir_setup__branches_and_oids_4(void)
        git_reference *octo4_ref;
        git_reference *octo5_ref;
        git_annotated_commit *our_head, *their_heads[5];
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
-       
+
        cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
        cl_git_pass(git_annotated_commit_lookup(&their_heads[0], repo, &octo1_oid));
-       
+
        cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[1], repo, octo2_ref));
-       
+
        cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID));
        cl_git_pass(git_annotated_commit_lookup(&their_heads[2], repo, &octo3_oid));
-       
+
        cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[3], repo, octo4_ref));
 
@@ -375,7 +375,7 @@ void test_merge_workdir_setup__branches_and_oids_4(void)
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; branches '" OCTO2_BRANCH "', '" OCTO4_BRANCH "' and '" OCTO5_BRANCH "'; commit '" OCTO3_OID "'\n"));
-       
+
        git_reference_free(octo2_ref);
        git_reference_free(octo4_ref);
        git_reference_free(octo5_ref);
@@ -396,30 +396,30 @@ void test_merge_workdir_setup__three_same_branches(void)
        git_reference *octo1_2_ref;
        git_reference *octo1_3_ref;
        git_annotated_commit *our_head, *their_heads[3];
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
-       
+
        cl_git_pass(git_reference_lookup(&octo1_1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_1_ref));
-       
+
        cl_git_pass(git_reference_lookup(&octo1_2_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[1], repo, octo1_2_ref));
-       
+
        cl_git_pass(git_reference_lookup(&octo1_3_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[2], repo, octo1_3_ref));
-       
+
        cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 3));
 
        cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO1_OID "\n" OCTO1_OID "\n"));
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO1_BRANCH "' and '" OCTO1_BRANCH "'\n"));
-       
+
        git_reference_free(octo1_1_ref);
        git_reference_free(octo1_2_ref);
        git_reference_free(octo1_3_ref);
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
        git_annotated_commit_free(their_heads[1]);
@@ -434,26 +434,26 @@ void test_merge_workdir_setup__three_same_oids(void)
        git_oid octo1_2_oid;
        git_oid octo1_3_oid;
        git_annotated_commit *our_head, *their_heads[3];
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
-       
+
        cl_git_pass(git_oid_fromstr(&octo1_1_oid, OCTO1_OID));
        cl_git_pass(git_annotated_commit_lookup(&their_heads[0], repo, &octo1_1_oid));
-       
+
        cl_git_pass(git_oid_fromstr(&octo1_2_oid, OCTO1_OID));
        cl_git_pass(git_annotated_commit_lookup(&their_heads[1], repo, &octo1_2_oid));
-       
+
        cl_git_pass(git_oid_fromstr(&octo1_3_oid, OCTO1_OID));
        cl_git_pass(git_annotated_commit_lookup(&their_heads[2], repo, &octo1_3_oid));
-       
+
        cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 3));
-       
+
        cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO1_OID "\n" OCTO1_OID "\n"));
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; commit '" OCTO1_OID "'; commit '" OCTO1_OID "'\n"));
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
        git_annotated_commit_free(their_heads[1]);
@@ -464,41 +464,41 @@ static int create_remote_tracking_branch(const char *branch_name, const char *oi
 {
        int error = 0;
 
-       git_buf remotes_path = GIT_BUF_INIT,
-               origin_path = GIT_BUF_INIT,
-               filename = GIT_BUF_INIT,
-               data = GIT_BUF_INIT;
+       git_str remotes_path = GIT_STR_INIT,
+               origin_path = GIT_STR_INIT,
+               filename = GIT_STR_INIT,
+               data = GIT_STR_INIT;
 
-       if ((error = git_buf_puts(&remotes_path, git_repository_path(repo))) < 0 ||
-               (error = git_buf_puts(&remotes_path, GIT_REFS_REMOTES_DIR)) < 0)
+       if ((error = git_str_puts(&remotes_path, git_repository_path(repo))) < 0 ||
+               (error = git_str_puts(&remotes_path, GIT_REFS_REMOTES_DIR)) < 0)
                goto done;
 
-       if (!git_path_exists(git_buf_cstr(&remotes_path)) &&
-               (error = p_mkdir(git_buf_cstr(&remotes_path), 0777)) < 0)
+       if (!git_fs_path_exists(git_str_cstr(&remotes_path)) &&
+               (error = p_mkdir(git_str_cstr(&remotes_path), 0777)) < 0)
                goto done;
 
-       if ((error = git_buf_puts(&origin_path, git_buf_cstr(&remotes_path))) < 0 ||
-               (error = git_buf_puts(&origin_path, "origin")) < 0)
+       if ((error = git_str_puts(&origin_path, git_str_cstr(&remotes_path))) < 0 ||
+               (error = git_str_puts(&origin_path, "origin")) < 0)
                goto done;
 
-       if (!git_path_exists(git_buf_cstr(&origin_path)) &&
-               (error = p_mkdir(git_buf_cstr(&origin_path), 0777)) < 0)
+       if (!git_fs_path_exists(git_str_cstr(&origin_path)) &&
+               (error = p_mkdir(git_str_cstr(&origin_path), 0777)) < 0)
                goto done;
 
-       if ((error = git_buf_puts(&filename, git_buf_cstr(&origin_path))) < 0 ||
-               (error = git_buf_puts(&filename, "/")) < 0 ||
-               (error = git_buf_puts(&filename, branch_name)) < 0 ||
-               (error = git_buf_puts(&data, oid_str)) < 0 ||
-               (error = git_buf_puts(&data, "\n")) < 0)
+       if ((error = git_str_puts(&filename, git_str_cstr(&origin_path))) < 0 ||
+               (error = git_str_puts(&filename, "/")) < 0 ||
+               (error = git_str_puts(&filename, branch_name)) < 0 ||
+               (error = git_str_puts(&data, oid_str)) < 0 ||
+               (error = git_str_puts(&data, "\n")) < 0)
                goto done;
 
-       cl_git_rewritefile(git_buf_cstr(&filename), git_buf_cstr(&data));
+       cl_git_rewritefile(git_str_cstr(&filename), git_str_cstr(&data));
 
 done:
-       git_buf_dispose(&remotes_path);
-       git_buf_dispose(&origin_path);
-       git_buf_dispose(&filename);
-       git_buf_dispose(&data);
+       git_str_dispose(&remotes_path);
+       git_str_dispose(&origin_path);
+       git_str_dispose(&filename);
+       git_str_dispose(&data);
 
        return error;
 }
@@ -514,10 +514,10 @@ void test_merge_workdir_setup__remote_tracking_one_branch(void)
 
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
-       
+
        cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref));
-       
+
        cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 1));
 
        cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n"));
@@ -526,7 +526,7 @@ void test_merge_workdir_setup__remote_tracking_one_branch(void)
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge remote-tracking branch 'refs/remotes/origin/" OCTO1_BRANCH "'\n"));
 
        git_reference_free(octo1_ref);
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
 }
@@ -544,7 +544,7 @@ void test_merge_workdir_setup__remote_tracking_two_branches(void)
 
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
-       
+
        cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref));
 
@@ -552,15 +552,15 @@ void test_merge_workdir_setup__remote_tracking_two_branches(void)
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[1], repo, octo2_ref));
 
        cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 2));
-       
+
        cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n"));
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge remote-tracking branches 'refs/remotes/origin/" OCTO1_BRANCH "' and 'refs/remotes/origin/" OCTO2_BRANCH "'\n"));
-       
+
        git_reference_free(octo1_ref);
        git_reference_free(octo2_ref);
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
        git_annotated_commit_free(their_heads[1]);
@@ -578,13 +578,13 @@ void test_merge_workdir_setup__remote_tracking_three_branches(void)
        cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID));
        cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID));
        cl_git_pass(create_remote_tracking_branch(OCTO3_BRANCH, OCTO3_OID));
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
 
        cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref));
-       
+
        cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[1], repo, octo2_ref));
 
@@ -597,7 +597,7 @@ void test_merge_workdir_setup__remote_tracking_three_branches(void)
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge remote-tracking branches 'refs/remotes/origin/" OCTO1_BRANCH "', 'refs/remotes/origin/" OCTO2_BRANCH "' and 'refs/remotes/origin/" OCTO3_BRANCH "'\n"));
-       
+
        git_reference_free(octo1_ref);
        git_reference_free(octo2_ref);
        git_reference_free(octo3_ref);
@@ -628,15 +628,15 @@ void test_merge_workdir_setup__normal_branch_and_remote_tracking_branch(void)
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[1], repo, octo2_ref));
 
        cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 2));
-       
+
        cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n"));
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "', remote-tracking branch 'refs/remotes/origin/" OCTO2_BRANCH "'\n"));
-       
+
        git_reference_free(octo1_ref);
        git_reference_free(octo2_ref);
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
        git_annotated_commit_free(their_heads[1]);
@@ -654,7 +654,7 @@ void test_merge_workdir_setup__remote_tracking_branch_and_normal_branch(void)
 
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
-       
+
        cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref));
 
@@ -662,15 +662,15 @@ void test_merge_workdir_setup__remote_tracking_branch_and_normal_branch(void)
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[1], repo, octo2_ref));
 
        cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 2));
-       
+
        cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n"));
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO2_BRANCH "', remote-tracking branch 'refs/remotes/origin/" OCTO1_BRANCH "'\n"));
-       
+
        git_reference_free(octo1_ref);
        git_reference_free(octo2_ref);
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
        git_annotated_commit_free(their_heads[1]);
@@ -691,7 +691,7 @@ void test_merge_workdir_setup__two_remote_tracking_branch_and_two_normal_branche
 
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
-       
+
        cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref));
 
@@ -705,17 +705,17 @@ void test_merge_workdir_setup__two_remote_tracking_branch_and_two_normal_branche
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[3], repo, octo4_ref));
 
        cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 4));
-       
+
        cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n"));
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO3_BRANCH "', remote-tracking branches 'refs/remotes/origin/" OCTO2_BRANCH "' and 'refs/remotes/origin/" OCTO4_BRANCH "'\n"));
-       
+
        git_reference_free(octo1_ref);
        git_reference_free(octo2_ref);
        git_reference_free(octo3_ref);
        git_reference_free(octo4_ref);
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
        git_annotated_commit_free(their_heads[1]);
@@ -735,14 +735,14 @@ void test_merge_workdir_setup__pull_one(void)
 
        cl_git_pass(git_oid_fromstr(&octo1_1_oid, OCTO1_OID));
        cl_git_pass(git_annotated_commit_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_1_oid));
-       
+
        cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 1));
-       
+
        cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n"));
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch 'octo1' of http://remote.url/repo.git\n"));
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
 }
@@ -754,7 +754,7 @@ void test_merge_workdir_setup__pull_two(void)
        git_oid octo1_oid;
        git_oid octo2_oid;
        git_annotated_commit *our_head, *their_heads[2];
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
 
@@ -770,7 +770,7 @@ void test_merge_workdir_setup__pull_two(void)
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO2_BRANCH "' of http://remote.url/repo.git\n"));
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
        git_annotated_commit_free(their_heads[1]);
@@ -784,7 +784,7 @@ void test_merge_workdir_setup__pull_three(void)
        git_oid octo2_oid;
        git_oid octo3_oid;
        git_annotated_commit *our_head, *their_heads[3];
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
 
@@ -803,7 +803,7 @@ void test_merge_workdir_setup__pull_three(void)
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO2_BRANCH "' and '" OCTO3_BRANCH "' of http://remote.url/repo.git\n"));
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
        git_annotated_commit_free(their_heads[1]);
@@ -817,7 +817,7 @@ void test_merge_workdir_setup__three_remotes(void)
        git_oid octo2_oid;
        git_oid octo3_oid;
        git_annotated_commit *our_head, *their_heads[3];
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
 
@@ -836,7 +836,7 @@ void test_merge_workdir_setup__three_remotes(void)
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "' of http://remote.first/repo.git, branch '" OCTO2_BRANCH "' of http://remote.second/repo.git, branch '" OCTO3_BRANCH "' of http://remote.third/repo.git\n"));
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
        git_annotated_commit_free(their_heads[1]);
@@ -851,7 +851,7 @@ void test_merge_workdir_setup__two_remotes(void)
        git_oid octo3_oid;
        git_oid octo4_oid;
        git_annotated_commit *our_head, *their_heads[4];
-       
+
        cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
        cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid));
 
@@ -873,7 +873,7 @@ void test_merge_workdir_setup__two_remotes(void)
        cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
        cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
        cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO3_BRANCH "' of http://remote.first/repo.git, branches '" OCTO2_BRANCH "' and '" OCTO4_BRANCH "' of http://remote.second/repo.git\n"));
-       
+
        git_annotated_commit_free(our_head);
        git_annotated_commit_free(their_heads[0]);
        git_annotated_commit_free(their_heads[1]);
@@ -1036,9 +1036,9 @@ void test_merge_workdir_setup__removed_after_failure(void)
        cl_git_fail(git_merge(
                repo, (const git_annotated_commit **)&their_heads[0], 1, NULL, NULL));
 
-       cl_assert(!git_path_exists("merge-resolve/.git/" GIT_MERGE_HEAD_FILE));
-       cl_assert(!git_path_exists("merge-resolve/.git/" GIT_MERGE_MODE_FILE));
-       cl_assert(!git_path_exists("merge-resolve/.git/" GIT_MERGE_MSG_FILE));
+       cl_assert(!git_fs_path_exists("merge-resolve/.git/" GIT_MERGE_HEAD_FILE));
+       cl_assert(!git_fs_path_exists("merge-resolve/.git/" GIT_MERGE_MODE_FILE));
+       cl_assert(!git_fs_path_exists("merge-resolve/.git/" GIT_MERGE_MSG_FILE));
 
        git_reference_free(octo1_ref);
 
@@ -1061,7 +1061,7 @@ void test_merge_workdir_setup__unlocked_after_success(void)
        cl_git_pass(git_merge(
                repo, (const git_annotated_commit **)&their_heads[0], 1, NULL, NULL));
 
-       cl_assert(!git_path_exists("merge-resolve/.git/index.lock"));
+       cl_assert(!git_fs_path_exists("merge-resolve/.git/index.lock"));
 
        git_reference_free(octo1_ref);
 
@@ -1087,7 +1087,7 @@ void test_merge_workdir_setup__unlocked_after_conflict(void)
        cl_git_fail(git_merge(
                repo, (const git_annotated_commit **)&their_heads[0], 1, NULL, NULL));
 
-       cl_assert(!git_path_exists("merge-resolve/.git/index.lock"));
+       cl_assert(!git_fs_path_exists("merge-resolve/.git/index.lock"));
 
        git_reference_free(octo1_ref);
 
index 6b4e174921a138c7d8081a4b3563c1f531348902..b9d3fc24ca2fce775ff9f31b526399720683eab1 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "git2/repository.h"
 #include "git2/merge.h"
-#include "buffer.h"
 #include "merge.h"
 #include "../merge_helpers.h"
 #include "../conflict_data.h"
@@ -126,7 +125,7 @@ void test_merge_workdir_simple__automerge(void)
 {
        git_index *index;
        const git_index_entry *entry;
-       git_buf automergeable_buf = GIT_BUF_INIT;
+       git_str automergeable_buf = GIT_STR_INIT;
 
        struct merge_index_entry merge_index_entries[] = {
                ADDED_IN_MASTER_INDEX_ENTRY,
@@ -155,7 +154,7 @@ void test_merge_workdir_simple__automerge(void)
        cl_git_pass(git_futils_readbuffer(&automergeable_buf,
                TEST_REPO_PATH "/automergeable.txt"));
        cl_assert(strcmp(automergeable_buf.ptr, AUTOMERGEABLE_MERGED_FILE) == 0);
-       git_buf_dispose(&automergeable_buf);
+       git_str_dispose(&automergeable_buf);
 
        cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
        cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
@@ -202,7 +201,7 @@ void test_merge_workdir_simple__automerge_crlf(void)
 #ifdef GIT_WIN32
        git_index *index;
        const git_index_entry *entry;
-       git_buf automergeable_buf = GIT_BUF_INIT;
+       git_str automergeable_buf = GIT_STR_INIT;
 
        struct merge_index_entry merge_index_entries[] = {
                ADDED_IN_MASTER_INDEX_ENTRY,
@@ -230,7 +229,7 @@ void test_merge_workdir_simple__automerge_crlf(void)
        cl_git_pass(git_futils_readbuffer(&automergeable_buf,
                TEST_REPO_PATH "/automergeable.txt"));
        cl_assert(strcmp(automergeable_buf.ptr, AUTOMERGEABLE_MERGED_FILE_CRLF) == 0);
-       git_buf_dispose(&automergeable_buf);
+       git_str_dispose(&automergeable_buf);
 
        cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
        cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
@@ -246,7 +245,7 @@ void test_merge_workdir_simple__automerge_crlf(void)
 
 void test_merge_workdir_simple__mergefile(void)
 {
-       git_buf conflicting_buf = GIT_BUF_INIT, mergemsg_buf = GIT_BUF_INIT;
+       git_str conflicting_buf = GIT_STR_INIT, mergemsg_buf = GIT_STR_INIT;
 
        struct merge_index_entry merge_index_entries[] = {
                ADDED_IN_MASTER_INDEX_ENTRY,
@@ -276,13 +275,13 @@ void test_merge_workdir_simple__mergefile(void)
        cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_MERGE_FILE) == 0);
        cl_git_pass(git_futils_readbuffer(&mergemsg_buf,
                TEST_REPO_PATH "/.git/MERGE_MSG"));
-       cl_assert(strcmp(git_buf_cstr(&mergemsg_buf),
+       cl_assert(strcmp(git_str_cstr(&mergemsg_buf),
                "Merge commit '7cb63eed597130ba4abb87b3e544b85021905520'\n" \
                "\n" \
-               "Conflicts:\n" \
-               "\tconflicting.txt\n") == 0);
-       git_buf_dispose(&conflicting_buf);
-       git_buf_dispose(&mergemsg_buf);
+               "#Conflicts:\n" \
+               "#\tconflicting.txt\n") == 0);
+       git_str_dispose(&conflicting_buf);
+       git_str_dispose(&mergemsg_buf);
 
        cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
        cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
@@ -290,7 +289,7 @@ void test_merge_workdir_simple__mergefile(void)
 
 void test_merge_workdir_simple__diff3(void)
 {
-       git_buf conflicting_buf = GIT_BUF_INIT;
+       git_str conflicting_buf = GIT_STR_INIT;
 
        struct merge_index_entry merge_index_entries[] = {
                ADDED_IN_MASTER_INDEX_ENTRY,
@@ -318,7 +317,43 @@ void test_merge_workdir_simple__diff3(void)
        cl_git_pass(git_futils_readbuffer(&conflicting_buf,
                TEST_REPO_PATH "/conflicting.txt"));
        cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_DIFF3_FILE) == 0);
-       git_buf_dispose(&conflicting_buf);
+       git_str_dispose(&conflicting_buf);
+
+       cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
+       cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
+}
+
+void test_merge_workdir_simple__zdiff3(void)
+{
+       git_str conflicting_buf = GIT_STR_INIT;
+
+       struct merge_index_entry merge_index_entries[] = {
+               ADDED_IN_MASTER_INDEX_ENTRY,
+               AUTOMERGEABLE_INDEX_ENTRY,
+               CHANGED_IN_BRANCH_INDEX_ENTRY,
+               CHANGED_IN_MASTER_INDEX_ENTRY,
+
+               { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" },
+               { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" },
+               { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" },
+
+               UNCHANGED_INDEX_ENTRY,
+       };
+
+       struct merge_reuc_entry merge_reuc_entries[] = {
+               AUTOMERGEABLE_REUC_ENTRY,
+               REMOVED_IN_BRANCH_REUC_ENTRY,
+               REMOVED_IN_MASTER_REUC_ENTRY
+       };
+
+       set_core_autocrlf_to(repo, false);
+
+       merge_simple_branch(0, GIT_CHECKOUT_CONFLICT_STYLE_ZDIFF3);
+
+       cl_git_pass(git_futils_readbuffer(&conflicting_buf,
+               TEST_REPO_PATH "/conflicting.txt"));
+       cl_assert_equal_s(CONFLICTING_ZDIFF3_FILE, conflicting_buf.ptr);
+       git_str_dispose(&conflicting_buf);
 
        cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
        cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
@@ -326,7 +361,7 @@ void test_merge_workdir_simple__diff3(void)
 
 void test_merge_workdir_simple__union(void)
 {
-       git_buf conflicting_buf = GIT_BUF_INIT;
+       git_str conflicting_buf = GIT_STR_INIT;
 
        struct merge_index_entry merge_index_entries[] = {
                ADDED_IN_MASTER_INDEX_ENTRY,
@@ -353,7 +388,7 @@ void test_merge_workdir_simple__union(void)
        cl_git_pass(git_futils_readbuffer(&conflicting_buf,
                TEST_REPO_PATH "/conflicting.txt"));
        cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_UNION_FILE) == 0);
-       git_buf_dispose(&conflicting_buf);
+       git_str_dispose(&conflicting_buf);
 
        cl_assert(merge_test_index(repo_index, merge_index_entries, 6));
        cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4));
@@ -361,7 +396,7 @@ void test_merge_workdir_simple__union(void)
 
 void test_merge_workdir_simple__gitattributes_union(void)
 {
-       git_buf conflicting_buf = GIT_BUF_INIT;
+       git_str conflicting_buf = GIT_STR_INIT;
 
        struct merge_index_entry merge_index_entries[] = {
                ADDED_IN_MASTER_INDEX_ENTRY,
@@ -389,7 +424,7 @@ void test_merge_workdir_simple__gitattributes_union(void)
        cl_git_pass(git_futils_readbuffer(&conflicting_buf,
                TEST_REPO_PATH "/conflicting.txt"));
        cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_UNION_FILE) == 0);
-       git_buf_dispose(&conflicting_buf);
+       git_str_dispose(&conflicting_buf);
 
        cl_assert(merge_test_index(repo_index, merge_index_entries, 6));
        cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4));
@@ -398,7 +433,7 @@ void test_merge_workdir_simple__gitattributes_union(void)
 void test_merge_workdir_simple__diff3_from_config(void)
 {
        git_config *config;
-       git_buf conflicting_buf = GIT_BUF_INIT;
+       git_str conflicting_buf = GIT_STR_INIT;
 
        struct merge_index_entry merge_index_entries[] = {
                ADDED_IN_MASTER_INDEX_ENTRY,
@@ -429,7 +464,49 @@ void test_merge_workdir_simple__diff3_from_config(void)
        cl_git_pass(git_futils_readbuffer(&conflicting_buf,
                TEST_REPO_PATH "/conflicting.txt"));
        cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_DIFF3_FILE) == 0);
-       git_buf_dispose(&conflicting_buf);
+       git_str_dispose(&conflicting_buf);
+
+       cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
+       cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
+
+       git_config_free(config);
+}
+
+void test_merge_workdir_simple__zdiff3_from_config(void)
+{
+       git_config *config;
+       git_str conflicting_buf = GIT_STR_INIT;
+
+       struct merge_index_entry merge_index_entries[] = {
+               ADDED_IN_MASTER_INDEX_ENTRY,
+               AUTOMERGEABLE_INDEX_ENTRY,
+               CHANGED_IN_BRANCH_INDEX_ENTRY,
+               CHANGED_IN_MASTER_INDEX_ENTRY,
+
+               { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" },
+               { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" },
+               { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" },
+
+               UNCHANGED_INDEX_ENTRY,
+       };
+
+       struct merge_reuc_entry merge_reuc_entries[] = {
+               AUTOMERGEABLE_REUC_ENTRY,
+               REMOVED_IN_BRANCH_REUC_ENTRY,
+               REMOVED_IN_MASTER_REUC_ENTRY
+       };
+
+       cl_git_pass(git_repository_config(&config, repo));
+       cl_git_pass(git_config_set_string(config, "merge.conflictstyle", "zdiff3"));
+
+       set_core_autocrlf_to(repo, false);
+
+       merge_simple_branch(0, 0);
+
+       cl_git_pass(git_futils_readbuffer(&conflicting_buf,
+               TEST_REPO_PATH "/conflicting.txt"));
+       cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_ZDIFF3_FILE) == 0);
+       git_str_dispose(&conflicting_buf);
 
        cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
        cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
@@ -440,7 +517,7 @@ void test_merge_workdir_simple__diff3_from_config(void)
 void test_merge_workdir_simple__merge_overrides_config(void)
 {
        git_config *config;
-       git_buf conflicting_buf = GIT_BUF_INIT;
+       git_str conflicting_buf = GIT_STR_INIT;
 
        struct merge_index_entry merge_index_entries[] = {
                ADDED_IN_MASTER_INDEX_ENTRY,
@@ -471,7 +548,7 @@ void test_merge_workdir_simple__merge_overrides_config(void)
        cl_git_pass(git_futils_readbuffer(&conflicting_buf,
                TEST_REPO_PATH "/conflicting.txt"));
        cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_MERGE_FILE) == 0);
-       git_buf_dispose(&conflicting_buf);
+       git_str_dispose(&conflicting_buf);
 
        cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
        cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
@@ -505,7 +582,7 @@ void test_merge_workdir_simple__checkout_ours(void)
        cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
        cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
 
-       cl_assert(git_path_exists(TEST_REPO_PATH "/conflicting.txt"));
+       cl_assert(git_fs_path_exists(TEST_REPO_PATH "/conflicting.txt"));
 }
 
 void test_merge_workdir_simple__favor_ours(void)
index 35280e61e8dadf33dad1da35ea5b2a69815fb78b..5117be789584dc0744b1cc976a6b9de81153fe8c 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "git2/repository.h"
 #include "git2/merge.h"
-#include "buffer.h"
 #include "merge.h"
 #include "../merge_helpers.h"
 
index c5bb7030ef39dd6e6a4fa6074e8587e220963480..fe83748516f815e775ba0a57ea060788d1380c9d 100644 (file)
@@ -30,26 +30,26 @@ void test_merge_workdir_trivial__cleanup(void)
 
 static int merge_trivial(const char *ours, const char *theirs)
 {
-       git_buf branch_buf = GIT_BUF_INIT;
+       git_str branch_buf = GIT_STR_INIT;
        git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
        git_reference *our_ref, *their_ref;
        git_annotated_commit *their_heads[1];
 
        checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
 
-       git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours);
+       git_str_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours);
        cl_git_pass(git_reference_symbolic_create(&our_ref, repo, "HEAD", branch_buf.ptr, 1, NULL));
 
        cl_git_pass(git_checkout_head(repo, &checkout_opts));
 
-       git_buf_clear(&branch_buf);
-       git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs);
+       git_str_clear(&branch_buf);
+       git_str_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs);
        cl_git_pass(git_reference_lookup(&their_ref, repo, branch_buf.ptr));
        cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, their_ref));
 
        cl_git_pass(git_merge(repo, (const git_annotated_commit **)their_heads, 1, NULL, NULL));
 
-       git_buf_dispose(&branch_buf);
+       git_str_dispose(&branch_buf);
        git_reference_free(our_ref);
        git_reference_free(their_ref);
        git_annotated_commit_free(their_heads[0]);
index 9cc83de7256ab6640fc03b3a77975e8a4d3ae371..919e10a499cefce260a0267eb5841e538f5af943 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "message.h"
 
 static void assert_trailers(const char *message, git_message_trailer *trailers)
 {
index 13f03100b363d0415e662efc35fbe3e606b81235..dc37c38ab6bace6ef0c2f007b2e4faec6a9db9d3 100644 (file)
@@ -1,6 +1,5 @@
 #include "clar_libgit2.h"
 
-#include "buffer.h"
 #include "path.h"
 #include "remote.h"
 
@@ -46,7 +45,7 @@ void test_network_fetchlocal__complete(void)
        cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
 
        cl_git_pass(git_reference_list(&refnames, repo));
-       cl_assert_equal_i(19, (int)refnames.count);
+       cl_assert_equal_i(20, (int)refnames.count);
        cl_assert(callcount > 0);
 
        git_strarray_dispose(&refnames);
@@ -75,7 +74,7 @@ void test_network_fetchlocal__prune(void)
        cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
 
        cl_git_pass(git_reference_list(&refnames, repo));
-       cl_assert_equal_i(19, (int)refnames.count);
+       cl_assert_equal_i(20, (int)refnames.count);
        cl_assert(callcount > 0);
        git_strarray_dispose(&refnames);
        git_remote_free(origin);
@@ -89,7 +88,7 @@ void test_network_fetchlocal__prune(void)
        cl_git_pass(git_remote_prune(origin, &options.callbacks));
 
        cl_git_pass(git_reference_list(&refnames, repo));
-       cl_assert_equal_i(18, (int)refnames.count);
+       cl_assert_equal_i(19, (int)refnames.count);
        git_strarray_dispose(&refnames);
        git_remote_free(origin);
 
@@ -102,14 +101,14 @@ void test_network_fetchlocal__prune(void)
        cl_git_pass(git_remote_prune(origin, &options.callbacks));
 
        cl_git_pass(git_reference_list(&refnames, repo));
-       cl_assert_equal_i(17, (int)refnames.count);
+       cl_assert_equal_i(18, (int)refnames.count);
        git_strarray_dispose(&refnames);
        git_remote_free(origin);
 
        git_repository_free(repo);
 }
 
-int update_tips_fail_on_call(const char *ref, const git_oid *old, const git_oid *new, void *data)
+static int update_tips_fail_on_call(const char *ref, const git_oid *old, const git_oid *new, void *data)
 {
        GIT_UNUSED(ref);
        GIT_UNUSED(old);
@@ -120,7 +119,7 @@ int update_tips_fail_on_call(const char *ref, const git_oid *old, const git_oid
        return 0;
 }
 
-void assert_ref_exists(git_repository *repo, const char *name)
+static void assert_ref_exists(git_repository *repo, const char *name)
 {
        git_reference *ref;
 
@@ -167,7 +166,7 @@ void test_network_fetchlocal__prune_overlapping(void)
        assert_ref_exists(repo, "refs/remotes/origin/master");
        assert_ref_exists(repo, "refs/remotes/origin/pr/42");
        cl_git_pass(git_reference_list(&refnames, repo));
-       cl_assert_equal_i(20, (int)refnames.count);
+       cl_assert_equal_i(21, (int)refnames.count);
        git_strarray_dispose(&refnames);
 
        cl_git_pass(git_config_delete_multivar(config, "remote.origin.fetch", "refs"));
@@ -182,7 +181,7 @@ void test_network_fetchlocal__prune_overlapping(void)
        assert_ref_exists(repo, "refs/remotes/origin/master");
        assert_ref_exists(repo, "refs/remotes/origin/pr/42");
        cl_git_pass(git_reference_list(&refnames, repo));
-       cl_assert_equal_i(20, (int)refnames.count);
+       cl_assert_equal_i(21, (int)refnames.count);
        git_strarray_dispose(&refnames);
 
        cl_git_pass(git_config_delete_multivar(config, "remote.origin.fetch", "refs"));
@@ -222,7 +221,7 @@ void test_network_fetchlocal__fetchprune(void)
        cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
 
        cl_git_pass(git_reference_list(&refnames, repo));
-       cl_assert_equal_i(19, (int)refnames.count);
+       cl_assert_equal_i(20, (int)refnames.count);
        cl_assert(callcount > 0);
        git_strarray_dispose(&refnames);
        git_remote_free(origin);
@@ -236,7 +235,7 @@ void test_network_fetchlocal__fetchprune(void)
        cl_git_pass(git_remote_prune(origin, &options.callbacks));
 
        cl_git_pass(git_reference_list(&refnames, repo));
-       cl_assert_equal_i(18, (int)refnames.count);
+       cl_assert_equal_i(19, (int)refnames.count);
        git_strarray_dispose(&refnames);
        git_remote_free(origin);
 
@@ -252,7 +251,7 @@ void test_network_fetchlocal__fetchprune(void)
        cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
 
        cl_git_pass(git_reference_list(&refnames, repo));
-       cl_assert_equal_i(17, (int)refnames.count);
+       cl_assert_equal_i(18, (int)refnames.count);
        git_strarray_dispose(&refnames);
        git_remote_free(origin);
 
@@ -336,7 +335,7 @@ void test_network_fetchlocal__partial(void)
        git_strarray_dispose(&refnames);
 
        cl_git_pass(git_reference_list(&refnames, repo));
-       cl_assert_equal_i(20, (int)refnames.count); /* 18 remote + 1 local */
+       cl_assert_equal_i(21, (int)refnames.count); /* 18 remote + 1 local */
        cl_assert(callcount > 0);
 
        git_strarray_dispose(&refnames);
@@ -419,7 +418,7 @@ void test_network_fetchlocal__multi_remotes(void)
        cl_git_pass(git_remote_fetch(test, NULL, &options, NULL));
 
        cl_git_pass(git_reference_list(&refnames, repo));
-       cl_assert_equal_i(33, (int)refnames.count);
+       cl_assert_equal_i(35, (int)refnames.count);
        git_strarray_dispose(&refnames);
 
        cl_git_pass(git_remote_set_url(repo, "test_with_pushurl", cl_git_fixture_url("testrepo.git")));
@@ -427,7 +426,7 @@ void test_network_fetchlocal__multi_remotes(void)
        cl_git_pass(git_remote_fetch(test2, NULL, &options, NULL));
 
        cl_git_pass(git_reference_list(&refnames, repo));
-       cl_assert_equal_i(45, (int)refnames.count);
+       cl_assert_equal_i(48, (int)refnames.count);
 
        git_strarray_dispose(&refnames);
        git_remote_free(test);
@@ -510,3 +509,44 @@ void test_network_fetchlocal__prune_load_fetch_prune_config(void)
        git_remote_free(origin);
        git_repository_free(repo);
 }
+
+static int update_tips_error(const char *ref, const git_oid *old, const git_oid *new, void *data)
+{
+       int *callcount = (int *) data;
+
+       GIT_UNUSED(ref);
+       GIT_UNUSED(old);
+       GIT_UNUSED(new);
+
+       (*callcount)++;
+
+       return -1;
+}
+
+void test_network_fetchlocal__update_tips_error_is_propagated(void)
+{
+       git_repository *repo;
+       git_reference_iterator *iterator;
+       git_reference *ref;
+       git_remote *remote;
+       git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
+       int callcount = 0;
+
+       cl_git_pass(git_repository_init(&repo, "foo.git", true));
+       cl_set_cleanup(cleanup_local_repo, "foo.git");
+
+       cl_git_pass(git_remote_create_with_fetchspec(&remote, repo, "origin", cl_git_fixture_url("testrepo.git"), "+refs/heads/*:refs/remotes/update-tips/*"));
+
+       options.callbacks.update_tips = update_tips_error;
+       options.callbacks.payload = &callcount;
+
+       cl_git_fail(git_remote_fetch(remote, NULL, &options, NULL));
+       cl_assert_equal_i(1, callcount);
+
+       cl_git_pass(git_reference_iterator_glob_new(&iterator, repo, "refs/remotes/update-tips/**/"));
+       cl_assert_equal_i(GIT_ITEROVER, git_reference_next(&ref, iterator));
+
+       git_reference_iterator_free(iterator);
+       git_remote_free(remote);
+       git_repository_free(repo);
+}
index b0417f7648489337d3454a19bd39302274b01eac..a7c0d81f6caf756e43758f6ce7e97f35fc812e95 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "refspec.h"
 #include "remote.h"
 
index 16cce6777d710194b150541c5eb7e01b4f6d1a06..2007f3776a1b594ea80118c036de8efdb6c6252c 100644 (file)
@@ -1,11 +1,10 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "path.h"
 #include "posix.h"
 #include "git2/sys/repository.h"
 
 static git_repository *repo;
-static git_buf file_path_buf = GIT_BUF_INIT;
+static git_str file_path_buf = GIT_STR_INIT;
 static git_remote *remote;
 
 static char *push_refspec_strings[] = {
@@ -25,7 +24,7 @@ void test_network_remote_local__initialize(void)
 
 void test_network_remote_local__cleanup(void)
 {
-       git_buf_dispose(&file_path_buf);
+       git_str_dispose(&file_path_buf);
 
        git_remote_free(remote);
        remote = NULL;
@@ -38,9 +37,9 @@ void test_network_remote_local__cleanup(void)
 
 static void connect_to_local_repository(const char *local_repository)
 {
-       git_buf_sets(&file_path_buf, cl_git_path_url(local_repository));
+       git_str_sets(&file_path_buf, cl_git_path_url(local_repository));
 
-       cl_git_pass(git_remote_create_anonymous(&remote, repo, git_buf_cstr(&file_path_buf)));
+       cl_git_pass(git_remote_create_anonymous(&remote, repo, git_str_cstr(&file_path_buf)));
        cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL));
 }
 
@@ -62,7 +61,7 @@ void test_network_remote_local__retrieve_advertised_references(void)
 
        cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
 
-       cl_assert_equal_i(refs_len, 29);
+       cl_assert_equal_i(refs_len, 30);
 }
 
 void test_network_remote_local__retrieve_advertised_before_connect(void)
@@ -70,9 +69,9 @@ void test_network_remote_local__retrieve_advertised_before_connect(void)
        const git_remote_head **refs;
        size_t refs_len = 0;
 
-       git_buf_sets(&file_path_buf, cl_git_path_url(cl_fixture("testrepo.git")));
+       git_str_sets(&file_path_buf, cl_git_path_url(cl_fixture("testrepo.git")));
 
-       cl_git_pass(git_remote_create_anonymous(&remote, repo, git_buf_cstr(&file_path_buf)));
+       cl_git_pass(git_remote_create_anonymous(&remote, repo, git_str_cstr(&file_path_buf)));
        cl_git_fail(git_remote_ls(&refs, &refs_len, remote));
 }
 
@@ -86,7 +85,7 @@ void test_network_remote_local__retrieve_advertised_references_after_disconnect(
 
        cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
 
-       cl_assert_equal_i(refs_len, 29);
+       cl_assert_equal_i(refs_len, 30);
 }
 
 void test_network_remote_local__retrieve_advertised_references_from_spaced_repository(void)
@@ -101,7 +100,7 @@ void test_network_remote_local__retrieve_advertised_references_from_spaced_repos
 
        cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
 
-       cl_assert_equal_i(refs_len, 29);
+       cl_assert_equal_i(refs_len, 30);
 
        git_remote_free(remote);        /* Disconnect from the "spaced repo" before the cleanup */
        remote = NULL;
@@ -472,10 +471,10 @@ void test_network_remote_local__anonymous_remote_inmemory_repo(void)
        git_repository *inmemory;
        git_remote *remote;
 
-       git_buf_sets(&file_path_buf, cl_git_path_url(cl_fixture("testrepo.git")));
+       git_str_sets(&file_path_buf, cl_git_path_url(cl_fixture("testrepo.git")));
 
        cl_git_pass(git_repository_new(&inmemory));
-       cl_git_pass(git_remote_create_anonymous(&remote, inmemory, git_buf_cstr(&file_path_buf)));
+       cl_git_pass(git_remote_create_anonymous(&remote, inmemory, git_str_cstr(&file_path_buf)));
        cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL));
        cl_assert(git_remote_connected(remote));
        git_remote_disconnect(remote);
index 34860542e458a54d74f6918296d6f5d8530dc740..3905debdfee9875a50215f7b521c9b8a31e6ec54 100644 (file)
@@ -29,7 +29,7 @@ void test_network_remote_push__cleanup(void)
        cl_fixture_cleanup("dummy.git");
 }
 
-int negotiation_cb(const git_push_update **updates, size_t len, void *payload)
+static int negotiation_cb(const git_push_update **updates, size_t len, void *payload)
 {
        const git_push_update *expected = payload;
 
@@ -69,7 +69,7 @@ void test_network_remote_push__delete_notification(void)
 
 }
 
-void create_dummy_commit(git_reference **out, git_repository *repo)
+static void create_dummy_commit(git_reference **out, git_repository *repo)
 {
        git_index *index;
        git_oid tree_id, commit_id;
index ed6a890751fd1e0336f1a8f07858e7ef39677cc2..79c4f39fa21c9d15538a480f7bd3c3d433b09094 100644 (file)
@@ -1,6 +1,5 @@
 #include "clar_libgit2.h"
 #include "config/config_helpers.h"
-#include "buffer.h"
 #include "refspec.h"
 #include "remote.h"
 
@@ -28,7 +27,7 @@ void test_network_remote_remotes__cleanup(void)
 
 void test_network_remote_remotes__parsing(void)
 {
-       git_buf url = GIT_BUF_INIT;
+       git_str url = GIT_STR_INIT;
        git_remote *_remote2 = NULL;
 
        cl_assert_equal_s(git_remote_name(_remote), "test");
@@ -53,7 +52,7 @@ void test_network_remote_remotes__parsing(void)
        cl_assert_equal_s(url.ptr, "git://github.com/libgit2/pushlibgit2");
 
        git_remote_free(_remote2);
-       git_buf_dispose(&url);
+       git_str_dispose(&url);
 }
 
 static int remote_ready_callback(git_remote *remote, int direction, void *payload)
@@ -79,7 +78,7 @@ static int remote_ready_callback(git_remote *remote, int direction, void *payloa
 
 void test_network_remote_remotes__remote_ready(void)
 {
-       git_buf url = GIT_BUF_INIT;
+       git_str url = GIT_STR_INIT;
 
        git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
        callbacks.remote_ready = remote_ready_callback;
@@ -95,29 +94,31 @@ void test_network_remote_remotes__remote_ready(void)
        cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, &callbacks));
        cl_assert_equal_s(url.ptr, "push_url");
 
-       git_buf_dispose(&url);
+       git_str_dispose(&url);
 }
 
 #ifndef GIT_DEPRECATE_HARD
 static int urlresolve_callback(git_buf *url_resolved, const char *url, int direction, void *payload)
 {
+       int error = -1;
+
        cl_assert(strcmp(url, "git://github.com/libgit2/libgit2") == 0);
        cl_assert(strcmp(payload, "payload") == 0);
        cl_assert(url_resolved->size == 0);
 
        if (direction == GIT_DIRECTION_PUSH)
-               git_buf_sets(url_resolved, "pushresolve");
+               error = git_buf_set(url_resolved, "pushresolve", strlen("pushresolve") + 1);
        if (direction == GIT_DIRECTION_FETCH)
-               git_buf_sets(url_resolved, "fetchresolve");
+               error = git_buf_set(url_resolved, "fetchresolve", strlen("fetchresolve") + 1);
 
-       return GIT_OK;
+       return error;
 }
 #endif
 
 void test_network_remote_remotes__urlresolve(void)
 {
 #ifndef GIT_DEPRECATE_HARD
-       git_buf url = GIT_BUF_INIT;
+       git_str url = GIT_STR_INIT;
 
        git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
        callbacks.resolve_url = urlresolve_callback;
@@ -133,7 +134,7 @@ void test_network_remote_remotes__urlresolve(void)
        cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, &callbacks));
        cl_assert_equal_s(url.ptr, "pushresolve");
 
-       git_buf_dispose(&url);
+       git_str_dispose(&url);
 #endif
 }
 
@@ -151,7 +152,7 @@ static int urlresolve_passthrough_callback(git_buf *url_resolved, const char *ur
 void test_network_remote_remotes__urlresolve_passthrough(void)
 {
 #ifndef GIT_DEPRECATE_HARD
-       git_buf url = GIT_BUF_INIT;
+       git_str url = GIT_STR_INIT;
        const char *orig_url = "git://github.com/libgit2/libgit2";
 
        git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
@@ -167,13 +168,13 @@ void test_network_remote_remotes__urlresolve_passthrough(void)
        cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, &callbacks));
        cl_assert_equal_s(url.ptr, orig_url);
 
-       git_buf_dispose(&url);
+       git_str_dispose(&url);
 #endif
 }
 
 void test_network_remote_remotes__instance_url(void)
 {
-       git_buf url = GIT_BUF_INIT;
+       git_str url = GIT_STR_INIT;
        const char *orig_url = "git://github.com/libgit2/libgit2";
 
        cl_assert_equal_s(git_remote_name(_remote), "test");
@@ -181,11 +182,11 @@ void test_network_remote_remotes__instance_url(void)
 
        cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_FETCH, NULL));
        cl_assert_equal_s(url.ptr, orig_url);
-       git_buf_clear(&url);
+       git_str_clear(&url);
 
        cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, NULL));
        cl_assert_equal_s(url.ptr, orig_url);
-       git_buf_clear(&url);
+       git_str_clear(&url);
 
        /* Setting the instance url updates the fetch and push URLs */
        git_remote_set_instance_url(_remote, "https://github.com/new/remote/url");
@@ -194,11 +195,11 @@ void test_network_remote_remotes__instance_url(void)
 
        cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_FETCH, NULL));
        cl_assert_equal_s(url.ptr, "https://github.com/new/remote/url");
-       git_buf_clear(&url);
+       git_str_clear(&url);
 
        cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, NULL));
        cl_assert_equal_s(url.ptr, "https://github.com/new/remote/url");
-       git_buf_clear(&url);
+       git_str_clear(&url);
 
        /* Setting the instance push url updates only the push URL */
        git_remote_set_instance_pushurl(_remote, "https://github.com/new/push/url");
@@ -207,13 +208,13 @@ void test_network_remote_remotes__instance_url(void)
 
        cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_FETCH, NULL));
        cl_assert_equal_s(url.ptr, "https://github.com/new/remote/url");
-       git_buf_clear(&url);
+       git_str_clear(&url);
 
        cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, NULL));
        cl_assert_equal_s(url.ptr, "https://github.com/new/push/url");
-       git_buf_clear(&url);
+       git_str_clear(&url);
 
-       git_buf_dispose(&url);
+       git_str_dispose(&url);
 }
 
 void test_network_remote_remotes__pushurl(void)
index edfd6abecaa7eb1106fcc05e89669cee52a1ec65..8149ba52c2258257e1fd6a47de1fbde135dce249 100644 (file)
@@ -552,6 +552,6 @@ void test_network_url_parse__ipv6_invalid_addresses(void)
        cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
                "https://user:pass@fe80::dcad:beff:fe00:0001:9191/resource"));
 
-       /* Invalid chracter inside address */
+       /* Invalid character inside address */
        cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, "http://[fe8o::dcad:beff:fe00:0001]/resource"));
 }
index 2c0b614d995fb54a16dad3e543852ce5525f70bc..a94db7daf1ebe4ef88dd53e34e39783cea24257b 100644 (file)
@@ -17,9 +17,9 @@ void test_network_url_redirect__cleanup(void)
 void test_network_url_redirect__redirect_http(void)
 {
        cl_git_pass(git_net_url_parse(&conndata,
-                               "http://example.com/foo/bar/baz"));
+               "http://example.com/foo/bar/baz"));
        cl_git_pass(git_net_url_apply_redirect(&conndata,
-                               "http://example.com/foo/bar/baz", "bar/baz"));
+               "http://example.com/foo/bar/baz", false, "bar/baz"));
        cl_assert_equal_s(conndata.scheme, "http");
        cl_assert_equal_s(conndata.host, "example.com");
        cl_assert_equal_s(conndata.port, "80");
@@ -31,9 +31,9 @@ void test_network_url_redirect__redirect_http(void)
 void test_network_url_redirect__redirect_ssl(void)
 {
        cl_git_pass(git_net_url_parse(&conndata,
-                               "https://example.com/foo/bar/baz"));
+               "https://example.com/foo/bar/baz"));
        cl_git_pass(git_net_url_apply_redirect(&conndata,
-                               "https://example.com/foo/bar/baz", "bar/baz"));
+               "https://example.com/foo/bar/baz", false, "bar/baz"));
        cl_assert_equal_s(conndata.scheme, "https");
        cl_assert_equal_s(conndata.host, "example.com");
        cl_assert_equal_s(conndata.port, "443");
@@ -45,9 +45,9 @@ void test_network_url_redirect__redirect_ssl(void)
 void test_network_url_redirect__redirect_leaves_root_path(void)
 {
        cl_git_pass(git_net_url_parse(&conndata,
-                               "https://example.com/foo/bar/baz"));
+               "https://example.com/foo/bar/baz"));
        cl_git_pass(git_net_url_apply_redirect(&conndata,
-                               "https://example.com/foo/bar/baz", "/foo/bar/baz"));
+               "https://example.com/foo/bar/baz", false, "/foo/bar/baz"));
        cl_assert_equal_s(conndata.scheme, "https");
        cl_assert_equal_s(conndata.host, "example.com");
        cl_assert_equal_s(conndata.port, "443");
@@ -59,9 +59,9 @@ void test_network_url_redirect__redirect_leaves_root_path(void)
 void test_network_url_redirect__redirect_encoded_username_password(void)
 {
        cl_git_pass(git_net_url_parse(&conndata,
-                               "https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz"));
+               "https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz"));
        cl_git_pass(git_net_url_apply_redirect(&conndata,
-                               "https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz", "bar/baz"));
+               "https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz", false, "bar/baz"));
        cl_assert_equal_s(conndata.scheme, "https");
        cl_assert_equal_s(conndata.host, "example.com");
        cl_assert_equal_s(conndata.port, "443");
@@ -70,27 +70,42 @@ void test_network_url_redirect__redirect_encoded_username_password(void)
        cl_assert_equal_s(conndata.password, "pass@word%zyx%v");
 }
 
+void test_network_url_redirect__redirect_cross_host_allowed(void)
+{
+       cl_git_pass(git_net_url_parse(&conndata,
+               "https://bar.com/bar/baz"));
+       cl_git_pass(git_net_url_apply_redirect(&conndata,
+               "https://foo.com/bar/baz", true, NULL));
+       cl_assert_equal_s(conndata.scheme, "https");
+       cl_assert_equal_s(conndata.host, "foo.com");
+       cl_assert_equal_s(conndata.port, "443");
+       cl_assert_equal_s(conndata.path, "/bar/baz");
+       cl_assert_equal_p(conndata.username, NULL);
+       cl_assert_equal_p(conndata.password, NULL);
+}
+
 void test_network_url_redirect__redirect_cross_host_denied(void)
 {
-       cl_git_pass(git_net_url_parse(&conndata, "https://bar.com/bar/baz"));
+       cl_git_pass(git_net_url_parse(&conndata,
+               "https://bar.com/bar/baz"));
        cl_git_fail_with(git_net_url_apply_redirect(&conndata,
-                               "https://foo.com/bar/baz", NULL),
-                       -1);
+               "https://foo.com/bar/baz", false, NULL), -1);
 }
 
 void test_network_url_redirect__redirect_http_downgrade_denied(void)
 {
-       cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/baz"));
+       cl_git_pass(git_net_url_parse(&conndata,
+               "https://foo.com/bar/baz"));
        cl_git_fail_with(git_net_url_apply_redirect(&conndata,
-                               "http://foo.com/bar/baz", NULL),
-                       -1);
+               "http://foo.com/bar/baz", true, NULL), -1);
 }
 
 void test_network_url_redirect__redirect_relative(void)
 {
-       cl_git_pass(git_net_url_parse(&conndata, "http://foo.com/bar/baz/biff"));
+       cl_git_pass(git_net_url_parse(&conndata,
+               "http://foo.com/bar/baz/biff"));
        cl_git_pass(git_net_url_apply_redirect(&conndata,
-                               "/zap/baz/biff?bam", NULL));
+               "/zap/baz/biff?bam", true, NULL));
        cl_assert_equal_s(conndata.scheme, "http");
        cl_assert_equal_s(conndata.host, "foo.com");
        cl_assert_equal_s(conndata.port, "80");
@@ -101,9 +116,10 @@ void test_network_url_redirect__redirect_relative(void)
 
 void test_network_url_redirect__redirect_relative_ssl(void)
 {
-       cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/baz/biff"));
+       cl_git_pass(git_net_url_parse(&conndata,
+               "https://foo.com/bar/baz/biff"));
        cl_git_pass(git_net_url_apply_redirect(&conndata,
-                               "/zap/baz/biff?bam", NULL));
+               "/zap/baz/biff?bam", true, NULL));
        cl_assert_equal_s(conndata.scheme, "https");
        cl_assert_equal_s(conndata.host, "foo.com");
        cl_assert_equal_s(conndata.port, "443");
@@ -114,16 +130,18 @@ void test_network_url_redirect__redirect_relative_ssl(void)
 
 void test_network_url_redirect__service_query_no_query_params_in_location(void)
 {
-       cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/info/refs?service=git-upload-pack"));
+       cl_git_pass(git_net_url_parse(&conndata,
+               "https://foo.com/bar/info/refs?service=git-upload-pack"));
        cl_git_pass(git_net_url_apply_redirect(&conndata,
-                               "/baz/info/refs", "/info/refs?service=git-upload-pack"));
+               "/baz/info/refs", true, "/info/refs?service=git-upload-pack"));
        cl_assert_equal_s(conndata.path, "/baz");
 }
 
 void test_network_url_redirect__service_query_with_query_params_in_location(void)
 {
-       cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/info/refs?service=git-upload-pack"));
+       cl_git_pass(git_net_url_parse(&conndata,
+               "https://foo.com/bar/info/refs?service=git-upload-pack"));
        cl_git_pass(git_net_url_apply_redirect(&conndata,
-                               "/baz/info/refs?service=git-upload-pack", "/info/refs?service=git-upload-pack"));
+               "/baz/info/refs?service=git-upload-pack", true, "/info/refs?service=git-upload-pack"));
        cl_assert_equal_s(conndata.path, "/baz");
 }
diff --git a/tests/network/url/scp.c b/tests/network/url/scp.c
new file mode 100644 (file)
index 0000000..8cdc832
--- /dev/null
@@ -0,0 +1,321 @@
+#include "clar_libgit2.h"
+#include "net.h"
+
+static git_net_url conndata;
+
+void test_network_url_scp__initialize(void)
+{
+       memset(&conndata, 0, sizeof(conndata));
+}
+
+void test_network_url_scp__cleanup(void)
+{
+       git_net_url_dispose(&conndata);
+}
+
+/* Hostname */
+
+void test_network_url_scp__hostname_trivial(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "example.com:/resource"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "example.com");
+       cl_assert_equal_s(conndata.port, "22");
+       cl_assert_equal_s(conndata.path, "/resource");
+       cl_assert_equal_p(conndata.username, NULL);
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_scp__hostname_bracketed(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "[example.com]:/resource"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "example.com");
+       cl_assert_equal_s(conndata.port, "22");
+       cl_assert_equal_s(conndata.path, "/resource");
+       cl_assert_equal_p(conndata.username, NULL);
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_scp__hostname_root(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "example.com:/"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "example.com");
+       cl_assert_equal_s(conndata.port, "22");
+       cl_assert_equal_s(conndata.path, "/");
+       cl_assert_equal_p(conndata.username, NULL);
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_scp__hostname_user(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "git@example.com:/resource"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "example.com");
+       cl_assert_equal_s(conndata.port, "22");
+       cl_assert_equal_s(conndata.path, "/resource");
+       cl_assert_equal_s(conndata.username, "git");
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_scp__hostname_user_bracketed(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "[git@example.com]:/resource"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "example.com");
+       cl_assert_equal_s(conndata.port, "22");
+       cl_assert_equal_s(conndata.path, "/resource");
+       cl_assert_equal_s(conndata.username, "git");
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_scp__hostname_port(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "[example.com:42]:/resource"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "example.com");
+       cl_assert_equal_s(conndata.port, "42");
+       cl_assert_equal_s(conndata.path, "/resource");
+       cl_assert_equal_p(conndata.username, NULL);
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_scp__hostname_user_port(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "[git@example.com:42]:/resource"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "example.com");
+       cl_assert_equal_s(conndata.port, "42");
+       cl_assert_equal_s(conndata.path, "/resource");
+       cl_assert_equal_s(conndata.username, "git");
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_scp__ipv4_trivial(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "192.168.99.88:/resource/a/b/c"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "192.168.99.88");
+       cl_assert_equal_s(conndata.port, "22");
+       cl_assert_equal_s(conndata.path, "/resource/a/b/c");
+       cl_assert_equal_p(conndata.username, NULL);
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_scp__ipv4_bracketed(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "[192.168.99.88]:/resource/a/b/c"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "192.168.99.88");
+       cl_assert_equal_s(conndata.port, "22");
+       cl_assert_equal_s(conndata.path, "/resource/a/b/c");
+       cl_assert_equal_p(conndata.username, NULL);
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_scp__ipv4_user(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "git@192.168.99.88:/resource/a/b/c"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "192.168.99.88");
+       cl_assert_equal_s(conndata.port, "22");
+       cl_assert_equal_s(conndata.path, "/resource/a/b/c");
+       cl_assert_equal_s(conndata.username, "git");
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_scp__ipv4_port(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "[192.168.99.88:1111]:/resource/a/b/c"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "192.168.99.88");
+       cl_assert_equal_s(conndata.port, "1111");
+       cl_assert_equal_s(conndata.path, "/resource/a/b/c");
+       cl_assert_equal_p(conndata.username, NULL);
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_scp__ipv4_user_port(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "[git@192.168.99.88:1111]:/resource/a/b/c"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "192.168.99.88");
+       cl_assert_equal_s(conndata.port, "1111");
+       cl_assert_equal_s(conndata.path, "/resource/a/b/c");
+       cl_assert_equal_s(conndata.username, "git");
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_scp__ipv6_trivial(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "[fe80::dcad:beff:fe00:0001]:/resource/foo"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "[fe80::dcad:beff:fe00:0001]");
+       cl_assert_equal_s(conndata.port, "22");
+       cl_assert_equal_s(conndata.path, "/resource/foo");
+       cl_assert_equal_p(conndata.username, NULL);
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_scp__ipv6_user(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "git@[fe80::dcad:beff:fe00:0001]:/resource/foo"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "[fe80::dcad:beff:fe00:0001]");
+       cl_assert_equal_s(conndata.port, "22");
+       cl_assert_equal_s(conndata.path, "/resource/foo");
+       cl_assert_equal_s(conndata.username, "git");
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_scp__ipv6_port(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "[[fe80::dcad:beff:fe00:0001]:99]:/resource/foo"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "[fe80::dcad:beff:fe00:0001]");
+       cl_assert_equal_s(conndata.port, "99");
+       cl_assert_equal_s(conndata.path, "/resource/foo");
+       cl_assert_equal_p(conndata.username, NULL);
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_scp__ipv6_user_port(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "[git@[fe80::dcad:beff:fe00:0001]:99]:/resource/foo"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "[fe80::dcad:beff:fe00:0001]");
+       cl_assert_equal_s(conndata.port, "99");
+       cl_assert_equal_s(conndata.path, "/resource/foo");
+       cl_assert_equal_s(conndata.username, "git");
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_scp__hexhost_and_port(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "[fe:22]:/resource/foo"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "fe");
+       cl_assert_equal_s(conndata.port, "22");
+       cl_assert_equal_s(conndata.path, "/resource/foo");
+       cl_assert_equal_p(conndata.username, NULL);
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_scp__malformed_ipv6_one(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "fe80::dcad:beff:fe00:0001]:/resource"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "fe80");
+       cl_assert_equal_s(conndata.port, "22");
+       cl_assert_equal_s(conndata.path, ":dcad:beff:fe00:0001]:/resource");
+       cl_assert_equal_p(conndata.username, NULL);
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_scp__malformed_ipv6_two(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "[fe80::dcad:beff:fe00:0001]:42]:/resource"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "[fe80::dcad:beff:fe00:0001]");
+       cl_assert_equal_s(conndata.port, "22");
+       cl_assert_equal_s(conndata.path, "42]:/resource");
+       cl_assert_equal_p(conndata.username, NULL);
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_scp__malformed_ipv6_with_user(void)
+{
+       cl_git_pass(git_net_url_parse_scp(&conndata, "git@[fe80::dcad:beff:fe00:0001]:42]:/resource"));
+       cl_assert_equal_s(conndata.scheme, "ssh");
+       cl_assert_equal_s(conndata.host, "[fe80::dcad:beff:fe00:0001]");
+       cl_assert_equal_s(conndata.port, "22");
+       cl_assert_equal_s(conndata.path, "42]:/resource");
+       cl_assert_equal_s(conndata.username, "git");
+       cl_assert_equal_p(conndata.password, NULL);
+       cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_scp__invalid_addresses(void)
+{
+       /* Path is required */
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "example.com"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "example.com:"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[example.com:42]:"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[git@example.com:42]:"));
+
+       /* Host is required */
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               ":"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               ":foo"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "git@:foo"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[]:"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "git@[]:"));
+
+       /* User is required if specified */
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "@example.com:foo"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "@:foo"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[@localhost:22]:foo"));
+
+       /* Port is required in brackets */
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[example.com:]:foo"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[git@example.com:]:foo"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[fe:]:foo"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[@localhost]:foo"));
+
+       /* Extra brackets are disallowed */
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[git@[[fe80::dcad:beff:fe00:0001]]:42]:foo"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[[git@[fe80::dcad:beff:fe00:0001]]:42]:foo"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[[git@[fe80::dcad:beff:fe00:0001]:42]]:foo"));
+
+       /* Closing bracket missing */
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[fe80::dcad:beff:fe00:0001:/resource"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[[fe80::dcad:beff:fe00:0001]:42:/resource"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[git@[fe80::dcad:beff:fe00:0001]:42:/resource"));
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+               "[git@[fe80::dcad:beff:fe00:0001:42]:/resource"));
+
+       /* Invalid character inside address */
+       cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+               "[fe8o::dcad:beff:fe00:0001]:/resource"));
+}
diff --git a/tests/network/url/valid.c b/tests/network/url/valid.c
new file mode 100644 (file)
index 0000000..2b2cb7b
--- /dev/null
@@ -0,0 +1,17 @@
+#include "clar_libgit2.h"
+#include "net.h"
+
+void test_network_url_valid__test(void)
+{
+       cl_assert(git_net_str_is_url("http://example.com/"));
+       cl_assert(git_net_str_is_url("file://localhost/tmp/foo/"));
+       cl_assert(git_net_str_is_url("ssh://user@host:42/tmp"));
+       cl_assert(git_net_str_is_url("git+ssh://user@host:42/tmp"));
+       cl_assert(git_net_str_is_url("ssh+git://user@host:42/tmp"));
+       cl_assert(git_net_str_is_url("https://user:pass@example.com/foo/bar"));
+
+       cl_assert(!git_net_str_is_url("host:foo.git"));
+       cl_assert(!git_net_str_is_url("host:/foo.git"));
+       cl_assert(!git_net_str_is_url("[host:42]:/foo.git"));
+       cl_assert(!git_net_str_is_url("[user@host:42]:/foo.git"));
+}
index af9686790797db3cd963af23cbad8868a01b695b..a36cddb8ad401a8e77cbe5c0c350db25a6f63878 100644 (file)
@@ -1,7 +1,5 @@
 #include "clar_libgit2.h"
 
-#include "buffer.h"
-
 static git_repository *_repo;
 static git_signature *_sig;
 
@@ -105,7 +103,7 @@ static int note_list_create_cb(
        return 0;
 }
 
-void assert_notes_seen(struct note_create_payload payload[], size_t n)
+static void assert_notes_seen(struct note_create_payload payload[], size_t n)
 {
        size_t seen = 0, i;
 
@@ -282,7 +280,7 @@ void test_notes_notes__inserting_a_note_without_passing_a_namespace_uses_the_def
        create_note(&note_oid, NULL, "08b041783f40edfe12bb406c9c9a8a040177c125", "hello world\n");
 
        cl_git_pass(git_note_read(&note, _repo, NULL, &target_oid));
-       cl_git_pass(git_note_read(&default_namespace_note, _repo, git_buf_cstr(&default_ref), &target_oid));
+       cl_git_pass(git_note_read(&default_namespace_note, _repo, default_ref.ptr, &target_oid));
 
        assert_note_equal(note, "hello world\n", &note_oid);
        assert_note_equal(default_namespace_note, "hello world\n", &note_oid);
index 3bcb05f20f5c7ecea67437b7cb88439ab4b177fd..6ba324c76b10f5c0acf201fabc8c972bf13adba3 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 
 #include "notes.h"
-#include "buffer.h"
 
 static git_repository *_repo;
 static git_note *_note;
@@ -57,7 +56,7 @@ void test_notes_notesref__config_corenotesref(void)
 
        cl_git_pass(git_note_default_ref(&default_ref, _repo));
        cl_assert_equal_s("refs/notes/mydefaultnotesref", default_ref.ptr);
-       git_buf_clear(&default_ref);
+       git_buf_dispose(&default_ref);
 
        cl_git_pass(git_config_delete_entry(_cfg, "core.notesRef"));
 
index a8e3d3097b8caea93d4e18f35261b9980e72cee5..00b553e7123dc5a2b64044d3c431e4a09ed8e870 100644 (file)
@@ -24,7 +24,7 @@ static off64_t g_crlf_raw_len[CRLF_NUM_TEST_OBJECTS] = {
 
 static git_oid g_crlf_oids[CRLF_NUM_TEST_OBJECTS];
 
-static git_buf g_crlf_filtered[CRLF_NUM_TEST_OBJECTS] = {
+static git_str g_crlf_filtered[CRLF_NUM_TEST_OBJECTS] = {
        { "", 0, 0 },
        { "foo\nbar\n", 0, 8 },
        { "foo\rbar\r", 0, 8 },
@@ -36,16 +36,16 @@ static git_buf g_crlf_filtered[CRLF_NUM_TEST_OBJECTS] = {
        { "\xFE\xFF\x00T\x00h\x00i\x00s\x00!", 0, 12 }
 };
 
-static git_buf_text_stats g_crlf_filtered_stats[CRLF_NUM_TEST_OBJECTS] = {
+static git_str_text_stats g_crlf_filtered_stats[CRLF_NUM_TEST_OBJECTS] = {
        { 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 2, 0, 6, 0 },
        { 0, 0, 2, 0, 0, 6, 0 },
        { 0, 0, 2, 2, 2, 6, 0 },
        { 0, 0, 4, 4, 1, 31, 0 },
        { 0, 1, 1, 2, 1, 9, 5 },
-       { GIT_BUF_BOM_UTF8, 0, 0, 1, 0, 16, 0 },
-       { GIT_BUF_BOM_UTF8, 0, 2, 2, 2, 27, 0 },
-       { GIT_BUF_BOM_UTF16_BE, 5, 0, 0, 0, 7, 5 },
+       { GIT_STR_BOM_UTF8, 0, 0, 1, 0, 16, 0 },
+       { GIT_STR_BOM_UTF8, 0, 2, 2, 2, 27, 0 },
+       { GIT_STR_BOM_UTF16_BE, 5, 0, 0, 0, 7, 5 },
 };
 
 void test_object_blob_filter__initialize(void)
@@ -90,19 +90,19 @@ void test_object_blob_filter__stats(void)
 {
        int i;
        git_blob *blob;
-       git_buf buf = GIT_BUF_INIT;
-       git_buf_text_stats stats;
+       git_str buf = GIT_STR_INIT;
+       git_str_text_stats stats;
 
        for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) {
                cl_git_pass(git_blob_lookup(&blob, g_repo, &g_crlf_oids[i]));
                cl_git_pass(git_blob__getbuf(&buf, blob));
-               git_buf_gather_text_stats(&stats, &buf, false);
+               git_str_gather_text_stats(&stats, &buf, false);
                cl_assert_equal_i(
                        0, memcmp(&g_crlf_filtered_stats[i], &stats, sizeof(stats)));
                git_blob_free(blob);
        }
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 }
 
 void test_object_blob_filter__to_odb(void)
index df229f98f9da7c4452d21e3395fd7c4bb47b03d9..60ff3991b9ecfca19a3cb42407bfaabc4ab9d4ba 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "posix.h"
 #include "path.h"
 #include "futils.h"
@@ -48,15 +47,15 @@ void test_object_blob_fromstream__multiple_write(void)
 
 static void write_attributes(git_repository *repo)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&buf, git_repository_path(repo), "info"));
-       cl_git_pass(git_buf_joinpath(&buf, git_buf_cstr(&buf), "attributes"));
+       cl_git_pass(git_str_joinpath(&buf, git_repository_path(repo), "info"));
+       cl_git_pass(git_str_joinpath(&buf, git_str_cstr(&buf), "attributes"));
 
-       cl_git_pass(git_futils_mkpath2file(git_buf_cstr(&buf), 0777));
-       cl_git_rewritefile(git_buf_cstr(&buf), GITATTR);
+       cl_git_pass(git_futils_mkpath2file(git_str_cstr(&buf), 0777));
+       cl_git_rewritefile(git_str_cstr(&buf), GITATTR);
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 }
 
 static void assert_named_chunked_blob(const char *expected_sha, const char *fake_name)
index 9a18d7cd410553b980eeddb72ecff6db847ac910..422258d632c77c0ccc579383ac9c8a2846087eea 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "posix.h"
 #include "path.h"
 #include "futils.h"
@@ -38,32 +37,32 @@ void test_object_blob_write__can_create_a_blob_in_a_standard_repo_from_a_file_lo
 
 void test_object_blob_write__can_create_a_blob_in_a_standard_repo_from_a_absolute_filepath_pointing_outside_of_the_working_directory(void)
 {
-       git_buf full_path = GIT_BUF_INIT;
+       git_str full_path = GIT_STR_INIT;
 
        repo = cl_git_sandbox_init(WORKDIR);
 
        cl_must_pass(p_mkdir(ELSEWHERE, 0777));
-       cl_must_pass(git_path_prettify_dir(&full_path, ELSEWHERE, NULL));
-       cl_must_pass(git_buf_puts(&full_path, "test.txt"));
+       cl_must_pass(git_fs_path_prettify_dir(&full_path, ELSEWHERE, NULL));
+       cl_must_pass(git_str_puts(&full_path, "test.txt"));
 
-       assert_blob_creation(ELSEWHERE "/test.txt", git_buf_cstr(&full_path), &git_blob_create_from_disk);
+       assert_blob_creation(ELSEWHERE "/test.txt", git_str_cstr(&full_path), &git_blob_create_from_disk);
 
-       git_buf_dispose(&full_path);
+       git_str_dispose(&full_path);
        cl_must_pass(git_futils_rmdir_r(ELSEWHERE, NULL, GIT_RMDIR_REMOVE_FILES));
 }
 
 void test_object_blob_write__can_create_a_blob_in_a_bare_repo_from_a_absolute_filepath(void)
 {
-       git_buf full_path = GIT_BUF_INIT;
+       git_str full_path = GIT_STR_INIT;
 
        repo = cl_git_sandbox_init(BARE_REPO);
 
        cl_must_pass(p_mkdir(ELSEWHERE, 0777));
-       cl_must_pass(git_path_prettify_dir(&full_path, ELSEWHERE, NULL));
-       cl_must_pass(git_buf_puts(&full_path, "test.txt"));
+       cl_must_pass(git_fs_path_prettify_dir(&full_path, ELSEWHERE, NULL));
+       cl_must_pass(git_str_puts(&full_path, "test.txt"));
 
-       assert_blob_creation(ELSEWHERE "/test.txt", git_buf_cstr(&full_path), &git_blob_create_from_disk);
+       assert_blob_creation(ELSEWHERE "/test.txt", git_str_cstr(&full_path), &git_blob_create_from_disk);
 
-       git_buf_dispose(&full_path);
+       git_str_dispose(&full_path);
        cl_must_pass(git_futils_rmdir_r(ELSEWHERE, NULL, GIT_RMDIR_REMOVE_FILES));
 }
index f7ff05c01daa480fb02815ff389f2da80d2137a2..7322a4e860217d6411dbb2c9776671a76e32aa4a 100644 (file)
@@ -25,7 +25,7 @@ void test_object_commit_commitstagedfile__generate_predictable_object_ids(void)
        git_oid expected_blob_oid, tree_oid, expected_tree_oid, commit_oid, expected_commit_oid;
        git_signature *signature;
        git_tree *tree;
-       git_buf buffer;
+       git_buf buffer = GIT_BUF_INIT;
 
        /*
         * The test below replicates the following git scenario
@@ -111,7 +111,6 @@ void test_object_commit_commitstagedfile__generate_predictable_object_ids(void)
        cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60));
        cl_git_pass(git_tree_lookup(&tree, repo, &tree_oid));
 
-       memset(&buffer, 0, sizeof(git_buf));
        cl_git_pass(git_message_prettify(&buffer, "Initial commit", 0, '#'));
 
        cl_git_pass(git_commit_create_v(
index 2458537fc207665f6bd568418d8585666cdf43d4..a7b1ceeb4ed9d05d34bf0b2407c89d74d4cf07c8 100644 (file)
@@ -66,13 +66,13 @@ void test_object_lookup__lookup_corrupt_object_returns_error(void)
 {
        const char *commit = "8e73b769e97678d684b809b163bebdae2911720f",
              *file = "objects/8e/73b769e97678d684b809b163bebdae2911720f";
-       git_buf path = GIT_BUF_INIT, contents = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT, contents = GIT_STR_INIT;
        git_oid oid;
        git_object *object;
        size_t i;
 
        cl_git_pass(git_oid_fromstr(&oid, commit));
-       cl_git_pass(git_buf_joinpath(&path, git_repository_path(g_repo), file));
+       cl_git_pass(git_str_joinpath(&path, git_repository_path(g_repo), file));
        cl_git_pass(git_futils_readbuffer(&contents, path.ptr));
 
        /* Corrupt and try to read the object */
@@ -88,8 +88,8 @@ void test_object_lookup__lookup_corrupt_object_returns_error(void)
        cl_git_pass(git_object_lookup(&object, g_repo, &oid, GIT_OBJECT_COMMIT));
 
        git_object_free(object);
-       git_buf_dispose(&path);
-       git_buf_dispose(&contents);
+       git_str_dispose(&path);
+       git_str_dispose(&contents);
 }
 
 void test_object_lookup__lookup_object_with_wrong_hash_returns_error(void)
@@ -97,15 +97,15 @@ void test_object_lookup__lookup_object_with_wrong_hash_returns_error(void)
        const char *oldloose = "objects/8e/73b769e97678d684b809b163bebdae2911720f",
              *newloose = "objects/8e/73b769e97678d684b809b163bebdae2911720e",
              *commit = "8e73b769e97678d684b809b163bebdae2911720e";
-       git_buf oldpath = GIT_BUF_INIT, newpath = GIT_BUF_INIT;
+       git_str oldpath = GIT_STR_INIT, newpath = GIT_STR_INIT;
        git_object *object;
        git_oid oid;
 
        cl_git_pass(git_oid_fromstr(&oid, commit));
 
        /* Copy object to another location with wrong hash */
-       cl_git_pass(git_buf_joinpath(&oldpath, git_repository_path(g_repo), oldloose));
-       cl_git_pass(git_buf_joinpath(&newpath, git_repository_path(g_repo), newloose));
+       cl_git_pass(git_str_joinpath(&oldpath, git_repository_path(g_repo), oldloose));
+       cl_git_pass(git_str_joinpath(&newpath, git_repository_path(g_repo), newloose));
        cl_git_pass(git_futils_cp(oldpath.ptr, newpath.ptr, 0644));
 
        /* Verify that lookup fails due to a hashsum mismatch */
@@ -117,6 +117,6 @@ void test_object_lookup__lookup_object_with_wrong_hash_returns_error(void)
        cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, 1));
 
        git_object_free(object);
-       git_buf_dispose(&oldpath);
-       git_buf_dispose(&newpath);
+       git_str_dispose(&oldpath);
+       git_str_dispose(&newpath);
 }
index bc005340bbb2b65ba8b3cde99fc611384126238f..d87c8ef7060983b87323d9fd9a47098b30d11861 100644 (file)
@@ -1,13 +1,11 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
-#include "message.h"
 
 static void assert_message_prettifying(char *expected_output, char *input, int strip_comments)
 {
        git_buf prettified_message = GIT_BUF_INIT;
 
        git_message_prettify(&prettified_message, input, strip_comments, '#');
-       cl_assert_equal_s(expected_output, git_buf_cstr(&prettified_message));
+       cl_assert_equal_s(expected_output, prettified_message.ptr);
 
        git_buf_dispose(&prettified_message);
 }
index 88b1380a481383a95fc32a408841aacdd8cfef02..40a01ae09e543e0d22e7013874de3f678a65b3f3 100644 (file)
@@ -38,7 +38,7 @@ void test_object_raw_convert__succeed_on_oid_to_string_conversion(void)
                cl_assert(*(str+i) == '\0');
                /* must not touch bytes past end of string */
                cl_assert(*(str+(i+1)) == 'Z');
-               /* i == n-1 charaters of string */
+               /* i == n-1 characters of string */
                cl_git_pass(strncmp(exp, out, i));
        }
 
index 830f1caa1900dff93494f7af63b96853e3bd091c..5a3e818552abc9d95d47ab9b3cf83174acc219da 100644 (file)
@@ -26,18 +26,18 @@ void test_object_raw_hash__hash_by_blocks(void)
        git_hash_ctx ctx;
        git_oid id1, id2;
 
-       cl_git_pass(git_hash_ctx_init(&ctx));
+       cl_git_pass(git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA1));
 
        /* should already be init'd */
        cl_git_pass(git_hash_update(&ctx, hello_text, strlen(hello_text)));
-       cl_git_pass(git_hash_final(&id2, &ctx));
+       cl_git_pass(git_hash_final(id2.id, &ctx));
        cl_git_pass(git_oid_fromstr(&id1, hello_id));
        cl_assert(git_oid_cmp(&id1, &id2) == 0);
 
        /* reinit should permit reuse */
        cl_git_pass(git_hash_init(&ctx));
        cl_git_pass(git_hash_update(&ctx, bye_text, strlen(bye_text)));
-       cl_git_pass(git_hash_final(&id2, &ctx));
+       cl_git_pass(git_hash_final(id2.id, &ctx));
        cl_git_pass(git_oid_fromstr(&id1, bye_id));
        cl_assert(git_oid_cmp(&id1, &id2) == 0);
 
@@ -49,14 +49,14 @@ void test_object_raw_hash__hash_buffer_in_single_call(void)
        git_oid id1, id2;
 
        cl_git_pass(git_oid_fromstr(&id1, hello_id));
-       git_hash_buf(&id2, hello_text, strlen(hello_text));
+       git_hash_buf(id2.id, hello_text, strlen(hello_text), GIT_HASH_ALGORITHM_SHA1);
        cl_assert(git_oid_cmp(&id1, &id2) == 0);
 }
 
 void test_object_raw_hash__hash_vector(void)
 {
        git_oid id1, id2;
-       git_buf_vec vec[2];
+       git_str_vec vec[2];
 
        cl_git_pass(git_oid_fromstr(&id1, hello_id));
 
@@ -65,7 +65,7 @@ void test_object_raw_hash__hash_vector(void)
        vec[1].data = hello_text+4;
        vec[1].len  = strlen(hello_text)-4;
 
-       git_hash_vec(&id2, vec, 2);
+       git_hash_vec(id2.id, vec, 2, GIT_HASH_ALGORITHM_SHA1);
 
        cl_assert(git_oid_cmp(&id1, &id2) == 0);
 }
index 813cd86b6f2867cc52cce163e6b307d748d17481..e8d2cf5a5bfbb524cfd32276934eca88d1c3983f 100644 (file)
@@ -33,7 +33,7 @@ static int insert_sequential_oids(
 
        for (i = 0; i < n; ++i) {
                p_snprintf(numbuf, sizeof(numbuf), "%u", (unsigned int)i);
-               git_hash_buf(&oid, numbuf, strlen(numbuf));
+               git_hash_buf(oid.id, numbuf, strlen(numbuf), GIT_HASH_ALGORITHM_SHA1);
 
                oids[i] = git__malloc(GIT_OID_HEXSZ + 1);
                cl_assert(oids[i]);
index 9bc127680791530e88e4d957766aeb785d0b8917..40e05f3577d303be31f30abc4928eaf03f7a3ecc 100644 (file)
@@ -39,8 +39,8 @@ static void streaming_write(git_oid *oid, git_odb *odb, git_rawobj *raw)
 
 static void check_object_files(object_data *d)
 {
-   cl_assert(git_path_exists(d->dir));
-   cl_assert(git_path_exists(d->file));
+   cl_assert(git_fs_path_exists(d->dir));
+   cl_assert(git_fs_path_exists(d->file));
 }
 
 static void cmp_objects(git_rawobj *o1, git_rawobj *o2)
index 48c8bfd36aa5d45f32298e33d4d224fd075dd3c6..3c1a989564106227912bea203637168a208c5f7a 100644 (file)
@@ -221,7 +221,7 @@ void test_object_tag_write__deleting_with_an_invalid_name_returns_EINVALIDSPEC(v
        cl_assert_equal_i(GIT_EINVALIDSPEC, git_tag_delete(g_repo, "Inv@{id"));
 }
 
-void create_annotation(git_oid *tag_id, const char *name)
+static void create_annotation(git_oid *tag_id, const char *name)
 {
        git_object *target;
        git_oid target_id;
index de2e64c68f517eb60d52b360e1b95592bc81927f..95a2e70fb9daef5e82b7510900baa83454cd5d72 100644 (file)
@@ -21,7 +21,7 @@ void test_object_tree_read__cleanup(void)
 
 void test_object_tree_read__loaded(void)
 {
-       /* acces randomly the entries on a loaded tree */
+       /* access randomly the entries on a loaded tree */
        git_oid id;
        git_tree *tree;
 
index 1bc5a50a02bfe2c8ea05d8ecfe019ba13f4a6e0f..a4ceb35b684dd0c930c20926f881d770ba706fc6 100644 (file)
@@ -394,12 +394,12 @@ void test_object_tree_write__cruel_paths(void)
 
        for (i = 0; i < count; ++i) {
                for (j = 0; j < count; ++j) {
-                       git_buf b = GIT_BUF_INIT;
-                       cl_git_pass(git_buf_joinpath(&b, the_paths[i], the_paths[j]));
+                       git_str b = GIT_STR_INIT;
+                       cl_git_pass(git_str_joinpath(&b, the_paths[i], the_paths[j]));
                        cl_git_pass(git_tree_entry_bypath(&te, tree, b.ptr));
                        cl_assert_equal_s(the_paths[j], git_tree_entry_name(te));
                        git_tree_entry_free(te);
-                       git_buf_dispose(&b);
+                       git_str_dispose(&b);
                }
        }
 
diff --git a/tests/object/validate.c b/tests/object/validate.c
new file mode 100644 (file)
index 0000000..87193de
--- /dev/null
@@ -0,0 +1,50 @@
+#include "clar_libgit2.h"
+
+#define VALID_COMMIT "tree bdd24e358576f1baa275df98cdcaf3ac9a3f4233\n" \
+               "parent d6d956f1d66210bfcd0484166befab33b5987a39\n" \
+               "author Edward Thomson <ethomson@edwardthomson.com> 1638286404 -0500\n" \
+               "committer Edward Thomson <ethomson@edwardthomson.com> 1638324642 -0500\n" \
+               "\n" \
+               "commit go here.\n"
+#define VALID_TREE "100644 HEADER\0\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42"
+
+#define INVALID_COMMIT "tree bdd24e358576f1baa275df98cdcaf3ac9a3f4233\n" \
+               "parent d6d956f1d66210bfcd0484166befab33b5987a39\n" \
+               "committer Edward Thomson <ethomson@edwardthomson.com> 1638324642 -0500\n" \
+               "\n" \
+               "commit go here.\n"
+#define INVALID_TREE "100644 HEADER \x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42"
+
+void test_object_validate__valid(void)
+{
+       int valid;
+
+       cl_git_pass(git_object_rawcontent_is_valid(&valid, "", 0, GIT_OBJECT_BLOB));
+       cl_assert_equal_i(1, valid);
+
+       cl_git_pass(git_object_rawcontent_is_valid(&valid, "foobar", 0, GIT_OBJECT_BLOB));
+       cl_assert_equal_i(1, valid);
+
+       cl_git_pass(git_object_rawcontent_is_valid(&valid, VALID_COMMIT, CONST_STRLEN(VALID_COMMIT), GIT_OBJECT_COMMIT));
+       cl_assert_equal_i(1, valid);
+
+       cl_git_pass(git_object_rawcontent_is_valid(&valid, VALID_TREE, CONST_STRLEN(VALID_TREE), GIT_OBJECT_TREE));
+       cl_assert_equal_i(1, valid);
+}
+
+void test_object_validate__invalid(void)
+{
+       int valid;
+
+       cl_git_pass(git_object_rawcontent_is_valid(&valid, "", 0, GIT_OBJECT_COMMIT));
+       cl_assert_equal_i(0, valid);
+
+       cl_git_pass(git_object_rawcontent_is_valid(&valid, "foobar", 0, GIT_OBJECT_COMMIT));
+       cl_assert_equal_i(0, valid);
+
+       cl_git_pass(git_object_rawcontent_is_valid(&valid, INVALID_COMMIT, CONST_STRLEN(INVALID_COMMIT), GIT_OBJECT_COMMIT));
+       cl_assert_equal_i(0, valid);
+
+       cl_git_pass(git_object_rawcontent_is_valid(&valid, INVALID_TREE, CONST_STRLEN(INVALID_TREE), GIT_OBJECT_TREE));
+       cl_assert_equal_i(0, valid);
+}
index f65a44bb54265a1cc353815861ebd96759f0a70d..6c00fda2fa48adbb7563c489fd21e947bbfe8ec6 100644 (file)
@@ -2,7 +2,7 @@
 #include "odb.h"
 #include "filebuf.h"
 
-static git_buf destpath, filepath;
+static git_str destpath, filepath;
 static const char *paths[] = {
        "A.git", "B.git", "C.git", "D.git", "E.git", "F.git", "G.git"
 };
@@ -13,8 +13,8 @@ void test_odb_alternates__cleanup(void)
 {
        size_t i;
 
-       git_buf_dispose(&destpath);
-       git_buf_dispose(&filepath);
+       git_str_dispose(&destpath);
+       git_str_dispose(&filepath);
 
        for (i = 0; i < ARRAY_SIZE(paths); i++)
                cl_fixture_cleanup(paths[i]);
@@ -22,18 +22,18 @@ void test_odb_alternates__cleanup(void)
 
 static void init_linked_repo(const char *path, const char *alternate)
 {
-       git_buf_clear(&destpath);
-       git_buf_clear(&filepath);
+       git_str_clear(&destpath);
+       git_str_clear(&filepath);
 
        cl_git_pass(git_repository_init(&repo, path, 1));
-       cl_git_pass(git_path_prettify(&destpath, alternate, NULL));
-       cl_git_pass(git_buf_joinpath(&destpath, destpath.ptr, "objects"));
-       cl_git_pass(git_buf_joinpath(&filepath, git_repository_path(repo), "objects/info"));
+       cl_git_pass(git_fs_path_prettify(&destpath, alternate, NULL));
+       cl_git_pass(git_str_joinpath(&destpath, destpath.ptr, "objects"));
+       cl_git_pass(git_str_joinpath(&filepath, git_repository_path(repo), "objects/info"));
        cl_git_pass(git_futils_mkdir(filepath.ptr, 0755, GIT_MKDIR_PATH));
-       cl_git_pass(git_buf_joinpath(&filepath, filepath.ptr , "alternates"));
+       cl_git_pass(git_str_joinpath(&filepath, filepath.ptr , "alternates"));
 
-       cl_git_pass(git_filebuf_open(&file, git_buf_cstr(&filepath), 0, 0666));
-       git_filebuf_printf(&file, "%s\n", git_buf_cstr(&destpath));
+       cl_git_pass(git_filebuf_open(&file, git_str_cstr(&filepath), 0, 0666));
+       git_filebuf_printf(&file, "%s\n", git_str_cstr(&destpath));
        cl_git_pass(git_filebuf_commit(&file));
 
        git_repository_free(repo);
index 139d2fc72a07e99b11461ef4e9b237f35d248de3..5427992429931d0293ae68ba05324c0eb1ea9ffe 100644 (file)
@@ -123,6 +123,18 @@ static int fake_backend__read_prefix(
        return 0;
 }
 
+static int fake_backend__refresh(git_odb_backend *backend)
+{
+       fake_backend *fake;
+
+       fake = (fake_backend *)backend;
+
+       fake->refresh_calls++;
+
+       return 0;
+}
+
+
 static void fake_backend__free(git_odb_backend *_backend)
 {
        fake_backend *backend;
@@ -134,7 +146,8 @@ static void fake_backend__free(git_odb_backend *_backend)
 
 int build_fake_backend(
        git_odb_backend **out,
-       const fake_object *objects)
+       const fake_object *objects,
+       bool support_refresh)
 {
        fake_backend *backend;
 
@@ -143,12 +156,12 @@ int build_fake_backend(
 
        backend->parent.version = GIT_ODB_BACKEND_VERSION;
 
-       backend->parent.refresh = NULL;
        backend->objects = objects;
 
        backend->parent.read = fake_backend__read;
        backend->parent.read_prefix = fake_backend__read_prefix;
        backend->parent.read_header = fake_backend__read_header;
+       backend->parent.refresh = support_refresh ? fake_backend__refresh : NULL;
        backend->parent.exists = fake_backend__exists;
        backend->parent.exists_prefix = fake_backend__exists_prefix;
        backend->parent.free = &fake_backend__free;
index 5c393c0a53651ef29ff3fd53b2de2e57614ab09e..32d7a8bf03b986126fadc2764fbe2795be1f5280 100644 (file)
@@ -13,10 +13,12 @@ typedef struct {
        int read_calls;
        int read_header_calls;
        int read_prefix_calls;
+       int refresh_calls;
 
        const fake_object *objects;
 } fake_backend;
 
 int build_fake_backend(
        git_odb_backend **out,
-       const fake_object *objects);
+       const fake_object *objects,
+       bool support_refresh);
index 1c6068df350a77e6cbc5417adfe3b1df2259a566..5f1eacd52b362f7b32a938593d3c3f690d65eee1 100644 (file)
@@ -29,10 +29,10 @@ void test_odb_backend_multiple__initialize(void)
        _obj = NULL;
        _repo = cl_git_sandbox_init("testrepo.git");
 
-       cl_git_pass(build_fake_backend(&backend, _objects_filled));
+       cl_git_pass(build_fake_backend(&backend, _objects_filled, false));
        _fake_filled = (fake_backend *)backend;
 
-       cl_git_pass(build_fake_backend(&backend, _objects_empty));
+       cl_git_pass(build_fake_backend(&backend, _objects_empty, false));
        _fake_empty = (fake_backend *)backend;
 }
 
index ede48ade66e586cb19ba211f33c43e466068e2e1..2db10efbceabcbd2ad0f1184af8984d6b988c8f5 100644 (file)
@@ -23,7 +23,7 @@ static void setup_repository_and_backend(void)
 
        _repo = cl_git_sandbox_init("testrepo.git");
 
-       cl_git_pass(build_fake_backend(&backend, _objects));
+       cl_git_pass(build_fake_backend(&backend, _objects, false));
 
        cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
        cl_git_pass(git_odb_add_backend(odb, backend, 10));
diff --git a/tests/odb/backend/refreshing.c b/tests/odb/backend/refreshing.c
new file mode 100644 (file)
index 0000000..9e49298
--- /dev/null
@@ -0,0 +1,176 @@
+#include "clar_libgit2.h"
+#include "repository.h"
+#include "backend_helpers.h"
+
+static git_repository *_repo;
+static fake_backend *_fake;
+
+#define NONEXISTING_HASH "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
+#define EXISTING_HASH "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"
+
+static const fake_object _objects[] = {
+       { EXISTING_HASH, "" },
+       { NULL, NULL }
+};
+
+static git_oid _nonexisting_oid;
+static git_oid _existing_oid;
+
+static void setup_repository_and_backend(void)
+{
+       git_odb *odb = NULL;
+       git_odb_backend *backend = NULL;
+
+       _repo = cl_git_sandbox_init("testrepo.git");
+
+       cl_git_pass(build_fake_backend(&backend, _objects, true));
+
+       cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
+       cl_git_pass(git_odb_add_backend(odb, backend, 10));
+
+       _fake = (fake_backend *)backend;
+}
+
+void test_odb_backend_refreshing__initialize(void)
+{
+       git_oid_fromstr(&_nonexisting_oid, NONEXISTING_HASH);
+       git_oid_fromstr(&_existing_oid, EXISTING_HASH);
+       setup_repository_and_backend();
+}
+
+void test_odb_backend_refreshing__cleanup(void)
+{
+       cl_git_sandbox_cleanup();
+}
+
+void test_odb_backend_refreshing__exists_is_invoked_twice_on_failure(void)
+{
+       git_odb *odb;
+
+       cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
+       cl_assert_equal_b(false, git_odb_exists(odb, &_nonexisting_oid));
+
+       cl_assert_equal_i(2, _fake->exists_calls);
+       cl_assert_equal_i(1, _fake->refresh_calls);
+}
+
+void test_odb_backend_refreshing__read_is_invoked_twice_on_failure(void)
+{
+       git_object *obj;
+
+       cl_git_fail_with(
+               git_object_lookup(&obj, _repo, &_nonexisting_oid, GIT_OBJECT_ANY),
+               GIT_ENOTFOUND);
+
+       cl_assert_equal_i(2, _fake->read_calls);
+       cl_assert_equal_i(1, _fake->refresh_calls);
+}
+
+void test_odb_backend_refreshing__readprefix_is_invoked_twice_on_failure(void)
+{
+       git_object *obj;
+
+       cl_git_fail_with(
+               git_object_lookup_prefix(&obj, _repo, &_nonexisting_oid, 7, GIT_OBJECT_ANY),
+               GIT_ENOTFOUND);
+
+       cl_assert_equal_i(2, _fake->read_prefix_calls);
+       cl_assert_equal_i(1, _fake->refresh_calls);
+}
+
+void test_odb_backend_refreshing__readheader_is_invoked_twice_on_failure(void)
+{
+       git_odb *odb;
+       size_t len;
+       git_object_t type;
+
+       cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
+
+       cl_git_fail_with(
+               git_odb_read_header(&len, &type, odb, &_nonexisting_oid),
+               GIT_ENOTFOUND);
+
+       cl_assert_equal_i(2, _fake->read_header_calls);
+       cl_assert_equal_i(1, _fake->refresh_calls);
+}
+
+void test_odb_backend_refreshing__exists_is_invoked_once_on_success(void)
+{
+       git_odb *odb;
+
+       cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
+       cl_assert_equal_b(true, git_odb_exists(odb, &_existing_oid));
+
+       cl_assert_equal_i(1, _fake->exists_calls);
+       cl_assert_equal_i(0, _fake->refresh_calls);
+}
+
+void test_odb_backend_refreshing__read_is_invoked_once_on_success(void)
+{
+       git_object *obj;
+
+       cl_git_pass(git_object_lookup(&obj, _repo, &_existing_oid, GIT_OBJECT_ANY));
+
+       cl_assert_equal_i(1, _fake->read_calls);
+       cl_assert_equal_i(0, _fake->refresh_calls);
+
+       git_object_free(obj);
+}
+
+void test_odb_backend_refreshing__readprefix_is_invoked_once_on_success(void)
+{
+       git_object *obj;
+
+       cl_git_pass(git_object_lookup_prefix(&obj, _repo, &_existing_oid, 7, GIT_OBJECT_ANY));
+
+       cl_assert_equal_i(1, _fake->read_prefix_calls);
+       cl_assert_equal_i(0, _fake->refresh_calls);
+
+       git_object_free(obj);
+}
+
+void test_odb_backend_refreshing__readheader_is_invoked_once_on_success(void)
+{
+       git_odb *odb;
+       size_t len;
+       git_object_t type;
+
+       cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
+
+       cl_git_pass(git_odb_read_header(&len, &type, odb, &_existing_oid));
+
+       cl_assert_equal_i(1, _fake->read_header_calls);
+       cl_assert_equal_i(0, _fake->refresh_calls);
+}
+
+void test_odb_backend_refreshing__read_is_invoked_twice_when_revparsing_a_full_oid(void)
+{
+       git_object *obj;
+
+       cl_git_fail_with(
+               git_revparse_single(&obj, _repo, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
+               GIT_ENOTFOUND);
+
+       cl_assert_equal_i(2, _fake->read_calls);
+       cl_assert_equal_i(1, _fake->refresh_calls);
+}
+
+void test_odb_backend_refreshing__refresh_is_invoked(void)
+{
+       git_odb *odb;
+
+       cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
+       cl_assert_equal_i(0, git_odb_refresh(odb));
+
+       cl_assert_equal_i(1, _fake->refresh_calls);
+}
+
+void test_odb_backend_refreshing__refresh_suppressed_with_no_refresh(void)
+{
+       git_odb *odb;
+
+       cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
+       cl_assert_equal_b(false, git_odb_exists_ext(odb, &_nonexisting_oid, GIT_ODB_LOOKUP_NO_REFRESH));
+
+       cl_assert_equal_i(0, _fake->refresh_calls);
+}
index 484dcba5a5a37402f697eeab51c8f70eb4c169fa..6c9293ac0d8319708edef1fb10b9dd8f6bb96ba3 100644 (file)
@@ -13,7 +13,7 @@ static void setup_backend(const fake_object *objs)
 {
        git_odb_backend *backend;
 
-       cl_git_pass(build_fake_backend(&backend, objs));
+       cl_git_pass(build_fake_backend(&backend, objs, false));
 
        cl_git_pass(git_repository_odb__weakptr(&_odb, _repo));
        cl_git_pass(git_odb_add_backend(_odb, backend, 10));
index 89b22ad4aed939a8fb973b5e3418d94ced0e70ca..e3ec62d3ff8b34674f107b87f65d37e286a9ff1b 100644 (file)
@@ -28,7 +28,7 @@ void test_odb_emptyobjects__blob_notfound(void)
        cl_git_fail_with(GIT_ENOTFOUND, git_blob_lookup(&blob, g_repo, &id));
 
        cl_git_pass(git_odb_write(&written_id, g_odb, "", 0, GIT_OBJECT_BLOB));
-       cl_assert(git_path_exists(TEST_REPO_PATH "/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391"));
+       cl_assert(git_fs_path_exists(TEST_REPO_PATH "/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391"));
 }
 
 void test_odb_emptyobjects__read_tree(void)
index 02112380b80424efcf4bae4973e0af712b5b48f7..c2a44836338af5d0ece5dc6fcec0ec76e312e5bb 100644 (file)
@@ -2,7 +2,6 @@
 #include "odb.h"
 #include "git2/odb_backend.h"
 #include "pack.h"
-#include "buffer.h"
 
 static git_odb *_odb;
 static git_repository *_repo;
@@ -121,15 +120,15 @@ void test_odb_foreach__files_in_objects_dir(void)
 {
        git_repository *repo;
        git_odb *odb;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        int nobj = 0;
 
        cl_fixture_sandbox("testrepo.git");
        cl_git_pass(git_repository_open(&repo, "testrepo.git"));
 
-       cl_git_pass(git_buf_joinpath(&buf, git_repository_path(repo), "objects/somefile"));
+       cl_git_pass(git_str_joinpath(&buf, git_repository_path(repo), "objects/somefile"));
        cl_git_mkfile(buf.ptr, "");
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        cl_git_pass(git_repository_odb(&odb, repo));
        cl_git_pass(git_odb_foreach(odb, foreach_cb, &nobj));
index 1ecd92a8d27c1b70ac32db4be9782a9653366c2e..2396e37746c328d017739580d24040d9d8eb02ea 100644 (file)
@@ -19,7 +19,7 @@ void test_odb_freshen__cleanup(void)
 
 static void set_time_wayback(struct stat *out, const char *fn)
 {
-       git_buf fullpath = GIT_BUF_INIT;
+       git_str fullpath = GIT_STR_INIT;
        struct p_timeval old[2];
 
        old[0].tv_sec = 1234567890;
@@ -27,11 +27,11 @@ static void set_time_wayback(struct stat *out, const char *fn)
        old[1].tv_sec = 1234567890;
        old[1].tv_usec = 0;
 
-       git_buf_joinpath(&fullpath, "testrepo.git/objects", fn);
+       git_str_joinpath(&fullpath, "testrepo.git/objects", fn);
 
-       cl_must_pass(p_utimes(git_buf_cstr(&fullpath), old));
-       cl_must_pass(p_lstat(git_buf_cstr(&fullpath), out));
-       git_buf_dispose(&fullpath);
+       cl_must_pass(p_utimes(git_str_cstr(&fullpath), old));
+       cl_must_pass(p_lstat(git_str_cstr(&fullpath), out));
+       git_str_dispose(&fullpath);
 }
 
 #define LOOSE_STR     "my new file\n"
index 8be2cfd02d6650c20a29176759886d05625a5c76..acc786ee4ccc197b62364f0055f0523f8e132a31 100644 (file)
@@ -23,11 +23,11 @@ void test_odb_largefiles__cleanup(void)
 static void writefile(git_oid *oid)
 {
        static git_odb_stream *stream;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        size_t i;
 
        for (i = 0; i < 3041; i++)
-               cl_git_pass(git_buf_puts(&buf, "Hello, world.\n"));
+               cl_git_pass(git_str_puts(&buf, "Hello, world.\n"));
 
        cl_git_pass(git_odb_open_wstream(&stream, odb, LARGEFILE_SIZE, GIT_OBJECT_BLOB));
        for (i = 0; i < 126103; i++)
@@ -36,13 +36,13 @@ static void writefile(git_oid *oid)
        cl_git_pass(git_odb_stream_finalize_write(oid, stream));
 
        git_odb_stream_free(stream);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 }
 
 void test_odb_largefiles__write_from_memory(void)
 {
        git_oid expected, oid;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        size_t i;
 
 #ifndef GIT_ARCH_64
@@ -55,7 +55,7 @@ void test_odb_largefiles__write_from_memory(void)
                cl_skip();
 
        for (i = 0; i < (3041*126103); i++)
-               cl_git_pass(git_buf_puts(&buf, "Hello, world.\n"));
+               cl_git_pass(git_str_puts(&buf, "Hello, world.\n"));
 
        git_oid_fromstr(&expected, "3fb56989cca483b21ba7cb0a6edb229d10e1c26c");
        cl_git_pass(git_odb_write(&oid, odb, buf.ptr, buf.size, GIT_OBJECT_BLOB));
@@ -107,7 +107,7 @@ void test_odb_largefiles__streamread(void)
        cl_assert_equal_sz(LARGEFILE_SIZE, len);
        cl_assert_equal_i(GIT_OBJECT_BLOB, type);
 
-       cl_git_pass(git_hash_ctx_init(&hash));
+       cl_git_pass(git_hash_ctx_init(&hash, GIT_HASH_ALGORITHM_SHA1));
        cl_git_pass(git_odb__format_object_header(&hdr_len, hdr, sizeof(hdr), len, type));
 
        cl_git_pass(git_hash_update(&hash, hdr, hdr_len));
@@ -119,7 +119,7 @@ void test_odb_largefiles__streamread(void)
 
        cl_assert_equal_sz(LARGEFILE_SIZE, total);
 
-       git_hash_final(&read_oid, &hash);
+       git_hash_final(read_oid.id, &hash);
 
        cl_assert_equal_oid(&oid, &read_oid);
 
index 5cf567cc26a5eba0273e053693780ad8db934081..fe013a78c20cfee7f9227cc9ec9e4cf2aa55a657 100644 (file)
@@ -187,7 +187,7 @@ void test_odb_loose__read_header(void)
        test_read_header(&some);
 }
 
-void test_write_object_permission(
+static void test_write_object_permission(
        mode_t dir_mode, mode_t file_mode,
        mode_t expected_dir_mode, mode_t expected_file_mode)
 {
@@ -228,7 +228,7 @@ void test_odb_loose__permissions_standard(void)
        test_write_object_permission(0, 0, GIT_OBJECT_DIR_MODE, GIT_OBJECT_FILE_MODE);
 }
 
-void test_odb_loose_permissions_readonly(void)
+void test_odb_loose__permissions_readonly(void)
 {
        test_write_object_permission(0777, 0444, 0777, 0444);
 }
index 7d43c6a098f8132c986ec8aa41ca40e1bb1282af..dfaee0e855d5caa89b150acb5b7af34b78fd1287 100644 (file)
@@ -8,9 +8,9 @@
 
 #define LIVE_REPO_URL "http://github.com/libgit2/TestGitRepository"
 #define LIVE_EMPTYREPO_URL "http://github.com/libgit2/TestEmptyRepository"
-#define BB_REPO_URL "https://libgit3@bitbucket.org/libgit2/testgitrepository.git"
-#define BB_REPO_URL_WITH_PASS "https://libgit3:libgit3@bitbucket.org/libgit2/testgitrepository.git"
-#define BB_REPO_URL_WITH_WRONG_PASS "https://libgit3:wrong@bitbucket.org/libgit2/testgitrepository.git"
+#define BB_REPO_URL "https://libgit2-test@bitbucket.org/libgit2-test/testgitrepository.git"
+#define BB_REPO_URL_WITH_PASS "https://libgit2-test:YT77Ppm2nq8w4TYjGS8U@bitbucket.org/libgit2-test/testgitrepository.git"
+#define BB_REPO_URL_WITH_WRONG_PASS "https://libgit2-test:wrong@bitbucket.org/libgit2-test/testgitrepository.git"
 #define GOOGLESOURCE_REPO_URL "https://chromium.googlesource.com/external/github.com/sergi/go-diff"
 
 #define SSH_REPO_URL "ssh://github.com/libgit2/TestGitRepository"
@@ -32,6 +32,8 @@ static char *_remote_proxy_user = NULL;
 static char *_remote_proxy_pass = NULL;
 static char *_remote_proxy_selfsigned = NULL;
 static char *_remote_expectcontinue = NULL;
+static char *_remote_redirect_initial = NULL;
+static char *_remote_redirect_subsequent = NULL;
 
 static int _orig_proxies_need_reset = 0;
 static char *_orig_http_proxy = NULL;
@@ -78,6 +80,8 @@ void test_online_clone__initialize(void)
        _remote_proxy_pass = cl_getenv("GITTEST_REMOTE_PROXY_PASS");
        _remote_proxy_selfsigned = cl_getenv("GITTEST_REMOTE_PROXY_SELFSIGNED");
        _remote_expectcontinue = cl_getenv("GITTEST_REMOTE_EXPECTCONTINUE");
+       _remote_redirect_initial = cl_getenv("GITTEST_REMOTE_REDIRECT_INITIAL");
+       _remote_redirect_subsequent = cl_getenv("GITTEST_REMOTE_REDIRECT_SUBSEQUENT");
 
        if (_remote_expectcontinue)
                git_libgit2_opts(GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE, 1);
@@ -92,6 +96,8 @@ void test_online_clone__cleanup(void)
                g_repo = NULL;
        }
        cl_fixture_cleanup("./foo");
+       cl_fixture_cleanup("./initial");
+       cl_fixture_cleanup("./subsequent");
 
        git__free(_remote_url);
        git__free(_remote_user);
@@ -107,6 +113,8 @@ void test_online_clone__cleanup(void)
        git__free(_remote_proxy_pass);
        git__free(_remote_proxy_selfsigned);
        git__free(_remote_expectcontinue);
+       git__free(_remote_redirect_initial);
+       git__free(_remote_redirect_subsequent);
 
        if (_orig_proxies_need_reset) {
                cl_setenv("HTTP_PROXY", _orig_http_proxy);
@@ -180,7 +188,7 @@ static int fetch_progress(const git_indexer_progress *stats, void *payload)
 
 void test_online_clone__can_checkout_a_cloned_repo(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_reference *head, *remote_head;
        bool checkout_progress_cb_was_called = false,
                  fetch_progress_cb_was_called = false;
@@ -193,8 +201,8 @@ void test_online_clone__can_checkout_a_cloned_repo(void)
 
        cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
-       cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path)));
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
+       cl_assert_equal_i(true, git_fs_path_isfile(git_str_cstr(&path)));
 
        cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
        cl_assert_equal_i(GIT_REFERENCE_SYMBOLIC, git_reference_type(head));
@@ -209,7 +217,7 @@ void test_online_clone__can_checkout_a_cloned_repo(void)
 
        git_reference_free(remote_head);
        git_reference_free(head);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 static int remote_mirror_cb(git_remote **out, git_repository *repo,
@@ -361,7 +369,7 @@ void test_online_clone__cred_callback_called_again_on_auth_failure(void)
        cl_assert_equal_i(3, counter);
 }
 
-int cred_default(
+static int cred_default(
        git_credential **cred,
        const char *url,
        const char *user_from_url,
@@ -405,23 +413,23 @@ void test_online_clone__credentials(void)
 
 void test_online_clone__credentials_via_custom_headers(void)
 {
-       const char *creds = "libgit3:libgit3";
-       git_buf auth = GIT_BUF_INIT;
+       const char *creds = "libgit2-test:YT77Ppm2nq8w4TYjGS8U";
+       git_str auth = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_puts(&auth, "Authorization: Basic "));
-       cl_git_pass(git_buf_encode_base64(&auth, creds, strlen(creds)));
+       cl_git_pass(git_str_puts(&auth, "Authorization: Basic "));
+       cl_git_pass(git_str_encode_base64(&auth, creds, strlen(creds)));
        g_options.fetch_opts.custom_headers.count = 1;
        g_options.fetch_opts.custom_headers.strings = &auth.ptr;
 
-       cl_git_pass(git_clone(&g_repo, "https://bitbucket.org/libgit2/testgitrepository.git", "./foo", &g_options));
+       cl_git_pass(git_clone(&g_repo, "https://bitbucket.org/libgit2-test/testgitrepository.git", "./foo", &g_options));
 
-       git_buf_dispose(&auth);
+       git_str_dispose(&auth);
 }
 
 void test_online_clone__bitbucket_style(void)
 {
        git_credential_userpass_payload user_pass = {
-               "libgit3", "libgit3"
+               "libgit2-test", "YT77Ppm2nq8w4TYjGS8U"
        };
 
        g_options.fetch_opts.callbacks.credentials = git_credential_userpass;
@@ -435,7 +443,7 @@ void test_online_clone__bitbucket_style(void)
 void test_online_clone__bitbucket_uses_creds_in_url(void)
 {
        git_credential_userpass_payload user_pass = {
-               "libgit2", "wrong"
+               "libgit2-test", "wrong"
        };
 
        g_options.fetch_opts.callbacks.credentials = git_credential_userpass;
@@ -453,7 +461,7 @@ void test_online_clone__bitbucket_uses_creds_in_url(void)
 void test_online_clone__bitbucket_falls_back_to_specified_creds(void)
 {
        git_credential_userpass_payload user_pass = {
-               "libgit2", "libgit2"
+               "libgit2-test", "libgit2"
        };
 
        g_options.fetch_opts.callbacks.credentials = git_credential_userpass;
@@ -618,7 +626,7 @@ 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)
+static int ssh_certificate_check(git_cert *cert, int valid, const char *host, void *payload)
 {
        git_cert_hostkey *key;
        git_oid expected = {{0}}, actual = {{0}};
@@ -807,12 +815,12 @@ static int proxy_cert_cb(git_cert *cert, int valid, const char *host, void *payl
 
 void test_online_clone__proxy_credentials_request(void)
 {
-       git_buf url = GIT_BUF_INIT;
+       git_str url = GIT_STR_INIT;
 
        if (!_remote_proxy_host || !_remote_proxy_user || !_remote_proxy_pass)
                cl_skip();
 
-       cl_git_pass(git_buf_printf(&url, "%s://%s/",
+       cl_git_pass(git_str_printf(&url, "%s://%s/",
                _remote_proxy_scheme ? _remote_proxy_scheme : "http",
                _remote_proxy_host));
 
@@ -824,17 +832,17 @@ void test_online_clone__proxy_credentials_request(void)
        cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options));
        cl_assert(called_proxy_creds);
 
-       git_buf_dispose(&url);
+       git_str_dispose(&url);
 }
 
 void test_online_clone__proxy_credentials_in_url(void)
 {
-       git_buf url = GIT_BUF_INIT;
+       git_str url = GIT_STR_INIT;
 
        if (!_remote_proxy_host || !_remote_proxy_user || !_remote_proxy_pass)
                cl_skip();
 
-       cl_git_pass(git_buf_printf(&url, "%s://%s:%s@%s/",
+       cl_git_pass(git_str_printf(&url, "%s://%s:%s@%s/",
                _remote_proxy_scheme ? _remote_proxy_scheme : "http",
                _remote_proxy_user, _remote_proxy_pass, _remote_proxy_host));
 
@@ -845,12 +853,12 @@ void test_online_clone__proxy_credentials_in_url(void)
        cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options));
        cl_assert(called_proxy_creds == 0);
 
-       git_buf_dispose(&url);
+       git_str_dispose(&url);
 }
 
 void test_online_clone__proxy_credentials_in_environment(void)
 {
-       git_buf url = GIT_BUF_INIT;
+       git_str url = GIT_STR_INIT;
 
        if (!_remote_proxy_host || !_remote_proxy_user || !_remote_proxy_pass)
                cl_skip();
@@ -863,7 +871,7 @@ void test_online_clone__proxy_credentials_in_environment(void)
        g_options.fetch_opts.proxy_opts.type = GIT_PROXY_AUTO;
        g_options.fetch_opts.proxy_opts.certificate_check = proxy_cert_cb;
 
-       cl_git_pass(git_buf_printf(&url, "%s://%s:%s@%s/",
+       cl_git_pass(git_str_printf(&url, "%s://%s:%s@%s/",
                _remote_proxy_scheme ? _remote_proxy_scheme : "http",
                _remote_proxy_user, _remote_proxy_pass, _remote_proxy_host));
 
@@ -873,17 +881,17 @@ void test_online_clone__proxy_credentials_in_environment(void)
 
        cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options));
 
-       git_buf_dispose(&url);
+       git_str_dispose(&url);
 }
 
 void test_online_clone__proxy_credentials_in_url_https(void)
 {
-       git_buf url = GIT_BUF_INIT;
+       git_str url = GIT_STR_INIT;
 
        if (!_remote_proxy_host || !_remote_proxy_user || !_remote_proxy_pass)
                cl_skip();
 
-       cl_git_pass(git_buf_printf(&url, "%s://%s:%s@%s/",
+       cl_git_pass(git_str_printf(&url, "%s://%s:%s@%s/",
                _remote_proxy_scheme ? _remote_proxy_scheme : "http",
                _remote_proxy_user, _remote_proxy_pass, _remote_proxy_host));
 
@@ -895,7 +903,7 @@ void test_online_clone__proxy_credentials_in_url_https(void)
        cl_git_pass(git_clone(&g_repo, "https://github.com/libgit2/TestGitRepository", "./foo", &g_options));
        cl_assert(called_proxy_creds == 0);
 
-       git_buf_dispose(&url);
+       git_str_dispose(&url);
 }
 
 void test_online_clone__proxy_auto_not_detected(void)
@@ -907,12 +915,12 @@ void test_online_clone__proxy_auto_not_detected(void)
 
 void test_online_clone__proxy_cred_callback_after_failed_url_creds(void)
 {
-       git_buf url = GIT_BUF_INIT;
+       git_str url = GIT_STR_INIT;
 
        if (!_remote_proxy_host || !_remote_proxy_user || !_remote_proxy_pass)
                cl_skip();
 
-       cl_git_pass(git_buf_printf(&url, "%s://invalid_user_name:INVALID_pass_WORD@%s/",
+       cl_git_pass(git_str_printf(&url, "%s://invalid_user_name:INVALID_pass_WORD@%s/",
                _remote_proxy_scheme ? _remote_proxy_scheme : "http",
                _remote_proxy_host));
 
@@ -924,17 +932,73 @@ void test_online_clone__proxy_cred_callback_after_failed_url_creds(void)
        cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options));
        cl_assert(called_proxy_creds);
 
-       git_buf_dispose(&url);
+       git_str_dispose(&url);
 }
 
 void test_online_clone__azurerepos(void)
 {
        cl_git_pass(git_clone(&g_repo, "https://libgit2@dev.azure.com/libgit2/test/_git/test", "./foo", &g_options));
-       cl_assert(git_path_exists("./foo/master.txt"));
+       cl_assert(git_fs_path_exists("./foo/master.txt"));
 }
 
 void test_online_clone__path_whitespace(void)
 {
        cl_git_pass(git_clone(&g_repo, "https://libgit2@dev.azure.com/libgit2/test/_git/spaces%20in%20the%20name", "./foo", &g_options));
-       cl_assert(git_path_exists("./foo/master.txt"));
+       cl_assert(git_fs_path_exists("./foo/master.txt"));
+}
+
+void test_online_clone__redirect_default_succeeds_for_initial(void)
+{
+       git_clone_options options = GIT_CLONE_OPTIONS_INIT;
+
+       if (!_remote_redirect_initial || !_remote_redirect_subsequent)
+               cl_skip();
+
+       cl_git_pass(git_clone(&g_repo, _remote_redirect_initial, "./initial", &options));
+}
+
+void test_online_clone__redirect_default_fails_for_subsequent(void)
+{
+       git_clone_options options = GIT_CLONE_OPTIONS_INIT;
+
+       if (!_remote_redirect_initial || !_remote_redirect_subsequent)
+               cl_skip();
+
+       cl_git_fail(git_clone(&g_repo, _remote_redirect_subsequent, "./fail", &options));
+}
+
+void test_online_clone__redirect_none(void)
+{
+       git_clone_options options = GIT_CLONE_OPTIONS_INIT;
+
+       if (!_remote_redirect_initial)
+               cl_skip();
+
+       options.fetch_opts.follow_redirects = GIT_REMOTE_REDIRECT_NONE;
+
+       cl_git_fail(git_clone(&g_repo, _remote_redirect_initial, "./fail", &options));
+}
+
+void test_online_clone__redirect_initial_succeeds_for_initial(void)
+{
+       git_clone_options options = GIT_CLONE_OPTIONS_INIT;
+
+       if (!_remote_redirect_initial || !_remote_redirect_subsequent)
+               cl_skip();
+
+       options.fetch_opts.follow_redirects = GIT_REMOTE_REDIRECT_INITIAL;
+
+       cl_git_pass(git_clone(&g_repo, _remote_redirect_initial, "./initial", &options));
+}
+
+void test_online_clone__redirect_initial_fails_for_subsequent(void)
+{
+       git_clone_options options = GIT_CLONE_OPTIONS_INIT;
+
+       if (!_remote_redirect_initial || !_remote_redirect_subsequent)
+               cl_skip();
+
+       options.fetch_opts.follow_redirects = GIT_REMOTE_REDIRECT_INITIAL;
+
+       cl_git_fail(git_clone(&g_repo, _remote_redirect_subsequent, "./fail", &options));
 }
index c7a0de1a18e6a6c477f91dc4c02318c2f587650d..7932a9e68f35fc52385d2d14b313242f22b0f2cc 100644 (file)
@@ -28,22 +28,22 @@ void test_online_customcert__initialize(void)
        g_repo = NULL;
 
        if (!initialized) {
-               git_buf path = GIT_BUF_INIT, file = GIT_BUF_INIT;
+               git_str path = GIT_STR_INIT, file = GIT_STR_INIT;
                char cwd[GIT_PATH_MAX];
 
                cl_fixture_sandbox(CUSTOM_CERT_ONE_PATH);
                cl_fixture_sandbox(CUSTOM_CERT_TWO_FILE);
 
                cl_must_pass(p_getcwd(cwd, GIT_PATH_MAX));
-               cl_git_pass(git_buf_joinpath(&path, cwd, CUSTOM_CERT_ONE_PATH));
-               cl_git_pass(git_buf_joinpath(&file, cwd, CUSTOM_CERT_TWO_FILE));
+               cl_git_pass(git_str_joinpath(&path, cwd, CUSTOM_CERT_ONE_PATH));
+               cl_git_pass(git_str_joinpath(&file, cwd, CUSTOM_CERT_TWO_FILE));
 
                cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SSL_CERT_LOCATIONS,
                                             file.ptr, path.ptr));
                initialized = true;
 
-               git_buf_dispose(&file);
-               git_buf_dispose(&path);
+               git_str_dispose(&file);
+               git_str_dispose(&path);
        }
 #endif
 }
@@ -66,7 +66,7 @@ void test_online_customcert__file(void)
 {
 #if (GIT_OPENSSL || GIT_MBEDTLS)
        cl_git_pass(git_clone(&g_repo, CUSTOM_CERT_ONE_URL, "./cloned", NULL));
-       cl_assert(git_path_exists("./cloned/master.txt"));
+       cl_assert(git_fs_path_exists("./cloned/master.txt"));
 #endif
 }
 
@@ -74,6 +74,6 @@ void test_online_customcert__path(void)
 {
 #if (GIT_OPENSSL || GIT_MBEDTLS)
        cl_git_pass(git_clone(&g_repo, CUSTOM_CERT_TWO_URL, "./cloned", NULL));
-       cl_assert(git_path_exists("./cloned/master.txt"));
+       cl_assert(git_fs_path_exists("./cloned/master.txt"));
 #endif
 }
index 67dfd69ed62f6aaaaea64130eae4336abb2d06f3..5beb5b618adec4a72402a842ef43faab6c56466b 100644 (file)
@@ -1,4 +1,5 @@
 #include "clar_libgit2.h"
+#include "futils.h"
 
 static git_repository *_repo;
 static int counter;
@@ -7,15 +8,19 @@ static char *_remote_proxy_scheme = NULL;
 static char *_remote_proxy_host = NULL;
 static char *_remote_proxy_user = NULL;
 static char *_remote_proxy_pass = NULL;
+static char *_remote_redirect_initial = NULL;
+static char *_remote_redirect_subsequent = NULL;
 
 void test_online_fetch__initialize(void)
 {
        cl_git_pass(git_repository_init(&_repo, "./fetch", 0));
 
-    _remote_proxy_scheme = cl_getenv("GITTEST_REMOTE_PROXY_SCHEME");
-    _remote_proxy_host = cl_getenv("GITTEST_REMOTE_PROXY_HOST");
-    _remote_proxy_user = cl_getenv("GITTEST_REMOTE_PROXY_USER");
-    _remote_proxy_pass = cl_getenv("GITTEST_REMOTE_PROXY_PASS");
+       _remote_proxy_scheme = cl_getenv("GITTEST_REMOTE_PROXY_SCHEME");
+       _remote_proxy_host = cl_getenv("GITTEST_REMOTE_PROXY_HOST");
+       _remote_proxy_user = cl_getenv("GITTEST_REMOTE_PROXY_USER");
+       _remote_proxy_pass = cl_getenv("GITTEST_REMOTE_PROXY_PASS");
+       _remote_redirect_initial = cl_getenv("GITTEST_REMOTE_REDIRECT_INITIAL");
+       _remote_redirect_subsequent = cl_getenv("GITTEST_REMOTE_REDIRECT_SUBSEQUENT");
 }
 
 void test_online_fetch__cleanup(void)
@@ -24,11 +29,14 @@ void test_online_fetch__cleanup(void)
        _repo = NULL;
 
        cl_fixture_cleanup("./fetch");
-
-    git__free(_remote_proxy_scheme);
-    git__free(_remote_proxy_host);
-    git__free(_remote_proxy_user);
-    git__free(_remote_proxy_pass);
+       cl_fixture_cleanup("./redirected");
+
+       git__free(_remote_proxy_scheme);
+       git__free(_remote_proxy_host);
+       git__free(_remote_proxy_user);
+       git__free(_remote_proxy_pass);
+       git__free(_remote_redirect_initial);
+       git__free(_remote_redirect_subsequent);
 }
 
 static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void *data)
@@ -67,11 +75,6 @@ static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n)
        git_remote_free(remote);
 }
 
-void test_online_fetch__default_git(void)
-{
-       do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6);
-}
-
 void test_online_fetch__default_http(void)
 {
        do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6);
@@ -84,7 +87,7 @@ void test_online_fetch__default_https(void)
 
 void test_online_fetch__no_tags_git(void)
 {
-       do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_NONE, 3);
+       do_fetch("https://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_NONE, 3);
 }
 
 void test_online_fetch__no_tags_http(void)
@@ -95,7 +98,7 @@ void test_online_fetch__no_tags_http(void)
 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_create(&remote, _repo, "test", "https://github.com/libgit2/TestGitRepository.git"));
        cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL));
        cl_git_pass(git_remote_download(remote, NULL, NULL));
        git_remote_disconnect(remote);
@@ -226,13 +229,13 @@ void test_online_fetch__twice(void)
 void test_online_fetch__proxy(void)
 {
     git_remote *remote;
-    git_buf url = GIT_BUF_INIT;
+    git_str url = GIT_STR_INIT;
     git_fetch_options fetch_opts;
 
     if (!_remote_proxy_host || !_remote_proxy_user || !_remote_proxy_pass)
         cl_skip();
 
-    cl_git_pass(git_buf_printf(&url, "%s://%s:%s@%s/",
+    cl_git_pass(git_str_printf(&url, "%s://%s:%s@%s/",
         _remote_proxy_scheme ? _remote_proxy_scheme : "http",
         _remote_proxy_user, _remote_proxy_pass, _remote_proxy_host));
 
@@ -245,5 +248,105 @@ void test_online_fetch__proxy(void)
     cl_git_pass(git_remote_fetch(remote, NULL, &fetch_opts, NULL));
 
     git_remote_free(remote);
-    git_buf_dispose(&url);
+    git_str_dispose(&url);
+}
+
+static int do_redirected_fetch(const char *url, const char *name, const char *config)
+{
+       git_repository *repo;
+       git_remote *remote;
+       int error;
+
+       cl_git_pass(git_repository_init(&repo, "./redirected", 0));
+       cl_fixture_cleanup(name);
+
+       if (config)
+               cl_repo_set_string(repo, "http.followRedirects", config);
+
+       cl_git_pass(git_remote_create(&remote, repo, name, url));
+       error = git_remote_fetch(remote, NULL, NULL, NULL);
+
+       git_remote_free(remote);
+       git_repository_free(repo);
+
+       cl_fixture_cleanup("./redirected");
+
+       return error;
+}
+
+void test_online_fetch__redirect_config(void)
+{
+       if (!_remote_redirect_initial || !_remote_redirect_subsequent)
+               cl_skip();
+
+       /* config defaults */
+       cl_git_pass(do_redirected_fetch(_remote_redirect_initial, "initial", NULL));
+       cl_git_fail(do_redirected_fetch(_remote_redirect_subsequent, "subsequent", NULL));
+
+       /* redirect=initial */
+       cl_git_pass(do_redirected_fetch(_remote_redirect_initial, "initial", "initial"));
+       cl_git_fail(do_redirected_fetch(_remote_redirect_subsequent, "subsequent", "initial"));
+
+       /* redirect=false */
+       cl_git_fail(do_redirected_fetch(_remote_redirect_initial, "initial", "false"));
+       cl_git_fail(do_redirected_fetch(_remote_redirect_subsequent, "subsequent", "false"));
+}
+
+void test_online_fetch__reachable_commit(void)
+{
+       git_remote *remote;
+       git_strarray refspecs;
+       git_object *obj;
+       git_oid expected_id;
+       git_str fetchhead = GIT_STR_INIT;
+       char *refspec = "+2c349335b7f797072cf729c4f3bb0914ecb6dec9:refs/success";
+
+       refspecs.strings = &refspec;
+       refspecs.count = 1;
+
+       git_oid_fromstr(&expected_id, "2c349335b7f797072cf729c4f3bb0914ecb6dec9");
+
+       cl_git_pass(git_remote_create(&remote, _repo, "test",
+               "https://github.com/libgit2/TestGitRepository"));
+       cl_git_pass(git_remote_fetch(remote, &refspecs, NULL, NULL));
+
+       cl_git_pass(git_revparse_single(&obj, _repo, "refs/success"));
+       cl_assert_equal_oid(&expected_id, git_object_id(obj));
+
+       cl_git_pass(git_futils_readbuffer(&fetchhead, "./fetch/.git/FETCH_HEAD"));
+       cl_assert_equal_s(fetchhead.ptr,
+               "2c349335b7f797072cf729c4f3bb0914ecb6dec9\t\t'2c349335b7f797072cf729c4f3bb0914ecb6dec9' of https://github.com/libgit2/TestGitRepository\n");
+
+       git_str_dispose(&fetchhead);
+       git_object_free(obj);
+       git_remote_free(remote);
+}
+
+void test_online_fetch__reachable_commit_without_destination(void)
+{
+       git_remote *remote;
+       git_strarray refspecs;
+       git_object *obj;
+       git_oid expected_id;
+       git_str fetchhead = GIT_STR_INIT;
+       char *refspec = "2c349335b7f797072cf729c4f3bb0914ecb6dec9";
+
+       refspecs.strings = &refspec;
+       refspecs.count = 1;
+
+       git_oid_fromstr(&expected_id, "2c349335b7f797072cf729c4f3bb0914ecb6dec9");
+
+       cl_git_pass(git_remote_create(&remote, _repo, "test",
+               "https://github.com/libgit2/TestGitRepository"));
+       cl_git_pass(git_remote_fetch(remote, &refspecs, NULL, NULL));
+
+       cl_git_fail_with(GIT_ENOTFOUND, git_revparse_single(&obj, _repo, "refs/success"));
+
+       cl_git_pass(git_futils_readbuffer(&fetchhead, "./fetch/.git/FETCH_HEAD"));
+       cl_assert_equal_s(fetchhead.ptr,
+               "2c349335b7f797072cf729c4f3bb0914ecb6dec9\t\t'2c349335b7f797072cf729c4f3bb0914ecb6dec9' of https://github.com/libgit2/TestGitRepository\n");
+
+       git_str_dispose(&fetchhead);
+       git_object_free(obj);
+       git_remote_free(remote);
 }
index b6199313818ac864a976b590f033af870fd2276f..1b66c528e979dd647beee4c5fcc0e3e532095f7b 100644 (file)
@@ -5,7 +5,7 @@
 #include "../fetchhead/fetchhead_data.h"
 #include "git2/clone.h"
 
-#define LIVE_REPO_URL "git://github.com/libgit2/TestGitRepository"
+#define LIVE_REPO_URL "https://github.com/libgit2/TestGitRepository"
 
 static git_repository *g_repo;
 static git_clone_options g_options;
@@ -52,8 +52,7 @@ static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fet
 {
        git_remote *remote;
        git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
-       git_buf fetchhead_buf = GIT_BUF_INIT;
-       int equals = 0;
+       git_str fetchhead_buf = GIT_STR_INIT;
        git_strarray array, *active_refs = NULL;
 
        cl_git_pass(git_remote_lookup(&remote, g_repo, "origin"));
@@ -70,11 +69,8 @@ static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fet
 
        cl_git_pass(git_futils_readbuffer(&fetchhead_buf, "./foo/.git/FETCH_HEAD"));
 
-       equals = (strcmp(fetchhead_buf.ptr, expected_fetchhead) == 0);
-
-       git_buf_dispose(&fetchhead_buf);
-
-       cl_assert(equals);
+       cl_assert_equal_s(fetchhead_buf.ptr, expected_fetchhead);
+       git_str_dispose(&fetchhead_buf);
 }
 
 void test_online_fetchhead__wildcard_spec(void)
@@ -157,7 +153,7 @@ void test_online_fetchhead__colon_only_dst_refspec_creates_no_branch(void)
 
 void test_online_fetchhead__creds_get_stripped(void)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_remote *remote;
 
        cl_git_pass(git_repository_init(&g_repo, "./foo", 0));
@@ -169,5 +165,5 @@ void test_online_fetchhead__creds_get_stripped(void)
                "49322bb17d3acc9146f98c97d078513228bbf3c0\t\thttps://github.com/libgit2/TestGitRepository\n");
 
        git_remote_free(remote);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 }
index c82b606cb9afcb45bf0a7d59a2a368d579c94d1b..51adc3930caf98ca02efa4464242a006bc28ae5a 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "posix.h"
 #include "vector.h"
 #include "../submodule/submodule_helpers.h"
@@ -129,28 +128,28 @@ static void do_verify_push_status(record_callbacks_data *data, const push_status
                        }
 
        if (failed) {
-               git_buf msg = GIT_BUF_INIT;
+               git_str msg = GIT_STR_INIT;
 
-               git_buf_puts(&msg, "Expected and actual push statuses differ:\nEXPECTED:\n");
+               git_str_puts(&msg, "Expected and actual push statuses differ:\nEXPECTED:\n");
 
                for(i = 0; i < expected_len; i++) {
-                       git_buf_printf(&msg, "%s: %s\n",
+                       git_str_printf(&msg, "%s: %s\n",
                                expected[i].ref,
                                expected[i].success ? "success" : "failed");
                }
 
-               git_buf_puts(&msg, "\nACTUAL:\n");
+               git_str_puts(&msg, "\nACTUAL:\n");
 
                git_vector_foreach(actual, i, iter) {
                        if (iter->success)
-                               git_buf_printf(&msg, "%s: success\n", iter->ref);
+                               git_str_printf(&msg, "%s: success\n", iter->ref);
                        else
-                               git_buf_printf(&msg, "%s: failed with message: %s", iter->ref, iter->msg);
+                               git_str_printf(&msg, "%s: failed with message: %s", iter->ref, iter->msg);
                }
 
-               cl_fail(git_buf_cstr(&msg));
+               cl_fail(git_str_cstr(&msg));
 
-               git_buf_dispose(&msg);
+               git_str_dispose(&msg);
        }
 
        git_vector_foreach(actual, i, iter) {
@@ -192,7 +191,7 @@ static void verify_tracking_branches(git_remote *remote, expected_ref expected_r
 {
        git_refspec *fetch_spec;
        size_t i, j;
-       git_buf msg = GIT_BUF_INIT;
+       git_str msg = GIT_STR_INIT;
        git_buf ref_name = GIT_BUF_INIT;
        git_vector actual_refs = GIT_VECTOR_INIT;
        git_branch_iterator *iter;
@@ -230,12 +229,12 @@ static void verify_tracking_branches(git_remote *remote, expected_ref expected_r
 
                /* Find matching remote branch */
                git_vector_foreach(&actual_refs, j, actual_ref) {
-                       if (!strcmp(git_buf_cstr(&ref_name), actual_ref))
+                       if (!strcmp(ref_name.ptr, actual_ref))
                                break;
                }
 
                if (j == actual_refs.length) {
-                       git_buf_printf(&msg, "Did not find expected tracking branch '%s'.", git_buf_cstr(&ref_name));
+                       git_str_printf(&msg, "Did not find expected tracking branch '%s'.", ref_name.ptr);
                        failed = 1;
                        goto failed;
                }
@@ -244,7 +243,7 @@ static void verify_tracking_branches(git_remote *remote, expected_ref expected_r
                cl_git_pass(git_reference_name_to_id(&oid, remote->repo, actual_ref));
 
                if (git_oid_cmp(expected_refs[i].oid, &oid) != 0) {
-                       git_buf_puts(&msg, "Tracking branch commit does not match expected ID.");
+                       git_str_puts(&msg, "Tracking branch commit does not match expected ID.");
                        failed = 1;
                        goto failed;
                }
@@ -255,27 +254,27 @@ static void verify_tracking_branches(git_remote *remote, expected_ref expected_r
 
        /* Make sure there are no extra branches */
        if (actual_refs.length > 0) {
-               git_buf_puts(&msg, "Unexpected remote tracking branches exist.");
+               git_str_puts(&msg, "Unexpected remote tracking branches exist.");
                failed = 1;
                goto failed;
        }
 
 failed:
        if (failed)
-               cl_fail(git_buf_cstr(&msg));
+               cl_fail(git_str_cstr(&msg));
 
        git_vector_foreach(&actual_refs, i, actual_ref)
                git__free(actual_ref);
 
        git_vector_free(&actual_refs);
-       git_buf_dispose(&msg);
+       git_str_dispose(&msg);
        git_buf_dispose(&ref_name);
 }
 
 static void verify_update_tips_callback(git_remote *remote, expected_ref expected_refs[], size_t expected_refs_len)
 {
        git_refspec *fetch_spec;
-       git_buf msg = GIT_BUF_INIT;
+       git_str msg = GIT_STR_INIT;
        git_buf ref_name = GIT_BUF_INIT;
        updated_tip *tip = NULL;
        size_t i, j;
@@ -293,18 +292,18 @@ static void verify_update_tips_callback(git_remote *remote, expected_ref expecte
 
                /* Find matching update_tip entry */
                git_vector_foreach(&_record_cbs_data.updated_tips, j, tip) {
-                       if (!strcmp(git_buf_cstr(&ref_name), tip->name))
+                       if (!strcmp(ref_name.ptr, tip->name))
                                break;
                }
 
                if (j == _record_cbs_data.updated_tips.length) {
-                       git_buf_printf(&msg, "Did not find expected updated tip entry for branch '%s'.", git_buf_cstr(&ref_name));
+                       git_str_printf(&msg, "Did not find expected updated tip entry for branch '%s'.", ref_name.ptr);
                        failed = 1;
                        goto failed;
                }
 
                if (git_oid_cmp(expected_refs[i].oid, &tip->new_oid) != 0) {
-                       git_buf_printf(&msg, "Updated tip ID does not match expected ID");
+                       git_str_printf(&msg, "Updated tip ID does not match expected ID");
                        failed = 1;
                        goto failed;
                }
@@ -312,10 +311,10 @@ static void verify_update_tips_callback(git_remote *remote, expected_ref expecte
 
 failed:
        if (failed)
-               cl_fail(git_buf_cstr(&msg));
+               cl_fail(git_str_cstr(&msg));
 
        git_buf_dispose(&ref_name);
-       git_buf_dispose(&msg);
+       git_str_dispose(&msg);
 }
 
 void test_online_push__initialize(void)
index b39f7811421c994d8b111cfa2a06c51fe800ea0a..cd1831d4c71c5ec3abacec4e1adb71b618e93ec3 100644 (file)
@@ -1,6 +1,4 @@
-
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "vector.h"
 #include "push_util.h"
 
@@ -12,7 +10,7 @@ void updated_tip_free(updated_tip *t)
        git__free(t);
 }
 
-void push_status_free(push_status *s)
+static void push_status_free(push_status *s)
 {
        git__free(s->ref);
        git__free(s->msg);
@@ -57,7 +55,7 @@ int record_update_tips_cb(const char *refname, const git_oid *a, const git_oid *
 
 int create_deletion_refspecs(git_vector *out, const git_remote_head **heads, size_t heads_len)
 {
-       git_buf del_spec = GIT_BUF_INIT;
+       git_str del_spec = GIT_STR_INIT;
        int valid;
        size_t i;
 
@@ -70,9 +68,9 @@ int create_deletion_refspecs(git_vector *out, const git_remote_head **heads, siz
 
                /* Create a refspec that deletes a branch in the remote */
                if (strcmp(head->name, "refs/heads/master")) {
-                       cl_git_pass(git_buf_putc(&del_spec, ':'));
-                       cl_git_pass(git_buf_puts(&del_spec, head->name));
-                       cl_git_pass(git_vector_insert(out, git_buf_detach(&del_spec)));
+                       cl_git_pass(git_str_putc(&del_spec, ':'));
+                       cl_git_pass(git_str_puts(&del_spec, head->name));
+                       cl_git_pass(git_vector_insert(out, git_str_detach(&del_spec)));
                }
        }
 
@@ -88,7 +86,7 @@ int record_ref_cb(git_remote_head *head, void *payload)
 void verify_remote_refs(const git_remote_head *actual_refs[], size_t actual_refs_len, const expected_ref expected_refs[], size_t expected_refs_len)
 {
        size_t i, j = 0;
-       git_buf msg = GIT_BUF_INIT;
+       git_str msg = GIT_STR_INIT;
        const git_remote_head *actual;
        char *oid_str;
        bool master_present = false;
@@ -120,24 +118,24 @@ void verify_remote_refs(const git_remote_head *actual_refs[], size_t actual_refs
        return;
 
 failed:
-       git_buf_puts(&msg, "Expected and actual refs differ:\nEXPECTED:\n");
+       git_str_puts(&msg, "Expected and actual refs differ:\nEXPECTED:\n");
 
        for(i = 0; i < expected_refs_len; i++) {
                oid_str = git_oid_tostr_s(expected_refs[i].oid);
-               cl_git_pass(git_buf_printf(&msg, "%s = %s\n", expected_refs[i].name, oid_str));
+               cl_git_pass(git_str_printf(&msg, "%s = %s\n", expected_refs[i].name, oid_str));
        }
 
-       git_buf_puts(&msg, "\nACTUAL:\n");
+       git_str_puts(&msg, "\nACTUAL:\n");
        for (i = 0; i < actual_refs_len; i++) {
                actual = actual_refs[i];
                if (master_present && !strcmp(actual->name, "refs/heads/master"))
                        continue;
 
                oid_str = git_oid_tostr_s(&actual->oid);
-               cl_git_pass(git_buf_printf(&msg, "%s = %s\n", actual->name, oid_str));
+               cl_git_pass(git_str_printf(&msg, "%s = %s\n", actual->name, oid_str));
        }
 
-       cl_fail(git_buf_cstr(&msg));
+       cl_fail(git_str_cstr(&msg));
 
-       git_buf_dispose(&msg);
+       git_str_dispose(&msg);
 }
index f7fe4142ff4007567bd9633f2b2f1f7b062d1da2..887874d9285ffd367eedcbcc4be944c30db6285b 100644 (file)
@@ -1,6 +1,6 @@
 #include "clar_libgit2.h"
 
-#define URL "git://github.com/libgit2/TestGitRepository"
+#define URL "https://github.com/libgit2/TestGitRepository"
 #define REFSPEC "refs/heads/first-merge:refs/remotes/origin/first-merge"
 
 static int remote_single_branch(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload)
index 5e0b77e9bd2cfd4ad8b2775dcc17ed5374e53bd7..fa08485fb927388d68272131464add3b71c46bab 100644 (file)
@@ -34,12 +34,12 @@ void test_pack_filelimit__initialize_unlimited(void)
 
 void test_pack_filelimit__cleanup(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, original_mwindow_file_limit));
 
-       cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), "repo.git"));
+       cl_git_pass(git_str_joinpath(&path, clar_sandbox_path(), "repo.git"));
        cl_fixture_cleanup(path.ptr);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 /*
@@ -47,14 +47,14 @@ void test_pack_filelimit__cleanup(void)
  * (README.md) has the same content in all commits, but the second one
  * (file.txt) has a different content in each commit.
  */
-void create_packfile_commit(
+static void create_packfile_commit(
                git_repository *repo,
                git_oid *out_commit_id,
                git_oid *parent_id,
                size_t commit_index,
                size_t commit_count)
 {
-       git_buf file_contents = GIT_BUF_INIT;
+       git_str file_contents = GIT_STR_INIT;
        git_treebuilder *treebuilder;
        git_packbuilder *packbuilder;
        git_signature *s;
@@ -67,7 +67,7 @@ void create_packfile_commit(
        cl_git_pass(git_blob_create_from_buffer(&oid, repo, "", 0));
        cl_git_pass(git_treebuilder_insert(NULL, treebuilder, "README.md", &oid, 0100644));
 
-       cl_git_pass(git_buf_printf(&file_contents, "Commit %zd/%zd", commit_index, commit_count));
+       cl_git_pass(git_str_printf(&file_contents, "Commit %zd/%zd", commit_index, commit_count));
        cl_git_pass(git_blob_create_from_buffer(&oid, repo, file_contents.ptr, file_contents.size));
        cl_git_pass(git_treebuilder_insert(NULL, treebuilder, "file.txt", &oid, 0100644));
 
@@ -82,7 +82,7 @@ void create_packfile_commit(
 
        cl_git_pass(git_oid_cpy(out_commit_id, &commit_id));
 
-       git_buf_dispose(&file_contents);
+       git_str_dispose(&file_contents);
        git_treebuilder_free(treebuilder);
        git_packbuilder_free(packbuilder);
        git_signature_free(s);
@@ -90,7 +90,7 @@ void create_packfile_commit(
 
 void test_pack_filelimit__open_repo_with_multiple_packfiles(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_mwindow_ctl *ctl = &git_mwindow__mem_ctl;
        git_repository *repo;
        git_revwalk *walk;
@@ -103,7 +103,7 @@ void test_pack_filelimit__open_repo_with_multiple_packfiles(void)
         * Create a repository and populate it with 16 commits, each in its own
         * packfile.
         */
-       cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), "repo.git"));
+       cl_git_pass(git_str_joinpath(&path, clar_sandbox_path(), "repo.git"));
        cl_git_pass(git_repository_init(&repo, path.ptr, true));
        for (i = 0; i < commit_count; ++i) {
                create_packfile_commit(repo, &id, parent_id, i + 1, commit_count);
@@ -130,7 +130,7 @@ void test_pack_filelimit__open_repo_with_multiple_packfiles(void)
 
        cl_assert_equal_i(expected_open_mwindow_files, open_windows);
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_revwalk_free(walk);
        git_repository_free(repo);
 }
index 422c3def4e4024a213fef0f9e996c58bb415ee70..ec48ffd98191cf2aec77d3ea65127157b01760cc 100644 (file)
@@ -169,8 +169,7 @@ void test_pack_indexer__fix_thin(void)
        cl_assert_equal_i(stats.indexed_objects, 2);
        cl_assert_equal_i(stats.local_objects, 1);
 
-       git_oid_fromstr(&should_id, "fefdb2d740a3a6b6c03a0c7d6ce431c6d5810e13");
-       cl_assert_equal_oid(&should_id, git_indexer_hash(idx));
+       cl_assert_equal_s("fefdb2d740a3a6b6c03a0c7d6ce431c6d5810e13", git_indexer_name(idx));
 
        git_indexer_free(idx);
        git_odb_free(odb);
@@ -279,21 +278,21 @@ void test_pack_indexer__out_of_order_with_connectivity_checks(void)
        git_indexer_free(idx);
 }
 
-static int find_tmp_file_recurs(void *opaque, git_buf *path)
+static int find_tmp_file_recurs(void *opaque, git_str *path)
 {
        int error = 0;
-       git_buf *first_tmp_file = opaque;
+       git_str *first_tmp_file = opaque;
        struct stat st;
 
        if ((error = p_lstat_posixly(path->ptr, &st)) < 0)
                return error;
 
        if (S_ISDIR(st.st_mode))
-               return git_path_direach(path, 0, find_tmp_file_recurs, opaque);
+               return git_fs_path_direach(path, 0, find_tmp_file_recurs, opaque);
 
        /* This is the template that's used in git_futils_mktmp. */
-       if (strstr(git_buf_cstr(path), "_git2_") != NULL)
-               return git_buf_sets(first_tmp_file, git_buf_cstr(path));
+       if (strstr(git_str_cstr(path), "_git2_") != NULL)
+               return git_str_sets(first_tmp_file, git_str_cstr(path));
 
        return 0;
 }
@@ -301,21 +300,21 @@ static int find_tmp_file_recurs(void *opaque, git_buf *path)
 void test_pack_indexer__no_tmp_files(void)
 {
        git_indexer *idx = NULL;
-       git_buf path = GIT_BUF_INIT;
-       git_buf first_tmp_file = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
+       git_str first_tmp_file = GIT_STR_INIT;
 
        /* Precondition: there are no temporary files. */
-       cl_git_pass(git_buf_sets(&path, clar_sandbox_path()));
+       cl_git_pass(git_str_sets(&path, clar_sandbox_path()));
        cl_git_pass(find_tmp_file_recurs(&first_tmp_file, &path));
-       git_buf_dispose(&path);
-       cl_assert(git_buf_len(&first_tmp_file) == 0);
+       git_str_dispose(&path);
+       cl_assert(git_str_len(&first_tmp_file) == 0);
 
        cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL));
        git_indexer_free(idx);
 
-       cl_git_pass(git_buf_sets(&path, clar_sandbox_path()));
+       cl_git_pass(git_str_sets(&path, clar_sandbox_path()));
        cl_git_pass(find_tmp_file_recurs(&first_tmp_file, &path));
-       git_buf_dispose(&path);
-       cl_assert(git_buf_len(&first_tmp_file) == 0);
-       git_buf_dispose(&first_tmp_file);
+       git_str_dispose(&path);
+       cl_assert(git_str_len(&first_tmp_file) == 0);
+       git_str_dispose(&first_tmp_file);
 }
index d5b91d28ba3635e57d4aaaf522679be47032dd9a..9dd949363e6200a8d5c7b219b283773eec07191a 100644 (file)
@@ -12,12 +12,12 @@ void test_pack_midx__parse(void)
        struct git_midx_file *idx;
        struct git_midx_entry e;
        git_oid id;
-       git_buf midx_path = GIT_BUF_INIT;
+       git_str midx_path = GIT_STR_INIT;
 
        cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
-       cl_git_pass(git_buf_joinpath(&midx_path, git_repository_path(repo), "objects/pack/multi-pack-index"));
-       cl_git_pass(git_midx_open(&idx, git_buf_cstr(&midx_path)));
-       cl_assert_equal_i(git_midx_needs_refresh(idx, git_buf_cstr(&midx_path)), 0);
+       cl_git_pass(git_str_joinpath(&midx_path, git_repository_path(repo), "objects/pack/multi-pack-index"));
+       cl_git_pass(git_midx_open(&idx, git_str_cstr(&midx_path)));
+       cl_assert_equal_i(git_midx_needs_refresh(idx, git_str_cstr(&midx_path)), 0);
 
        cl_git_pass(git_oid_fromstr(&id, "5001298e0c09ad9c34e4249bc5801c75e9754fa5"));
        cl_git_pass(git_midx_entry_find(&e, idx, &id, GIT_OID_HEXSZ));
@@ -28,7 +28,7 @@ void test_pack_midx__parse(void)
 
        git_midx_free(idx);
        git_repository_free(repo);
-       git_buf_dispose(&midx_path);
+       git_str_dispose(&midx_path);
 }
 
 void test_pack_midx__lookup(void)
@@ -51,27 +51,28 @@ void test_pack_midx__writer(void)
 {
        git_repository *repo;
        git_midx_writer *w = NULL;
-       git_buf midx = GIT_BUF_INIT, expected_midx = GIT_BUF_INIT, path = GIT_BUF_INIT;
+       git_buf midx = GIT_BUF_INIT;
+       git_str expected_midx = GIT_STR_INIT, path = GIT_STR_INIT;
 
        cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "objects/pack"));
-       cl_git_pass(git_midx_writer_new(&w, git_buf_cstr(&path)));
+       cl_git_pass(git_str_joinpath(&path, git_repository_path(repo), "objects/pack"));
+       cl_git_pass(git_midx_writer_new(&w, git_str_cstr(&path)));
 
        cl_git_pass(git_midx_writer_add(w, "pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx"));
        cl_git_pass(git_midx_writer_add(w, "pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx"));
        cl_git_pass(git_midx_writer_add(w, "pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx"));
 
        cl_git_pass(git_midx_writer_dump(&midx, w));
-       cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "objects/pack/multi-pack-index"));
-       cl_git_pass(git_futils_readbuffer(&expected_midx, git_buf_cstr(&path)));
+       cl_git_pass(git_str_joinpath(&path, git_repository_path(repo), "objects/pack/multi-pack-index"));
+       cl_git_pass(git_futils_readbuffer(&expected_midx, git_str_cstr(&path)));
 
-       cl_assert_equal_i(git_buf_len(&midx), git_buf_len(&expected_midx));
-       cl_assert_equal_strn(git_buf_cstr(&midx), git_buf_cstr(&expected_midx), git_buf_len(&midx));
+       cl_assert_equal_i(midx.size, git_str_len(&expected_midx));
+       cl_assert_equal_strn(midx.ptr, git_str_cstr(&expected_midx), midx.size);
 
        git_buf_dispose(&midx);
-       git_buf_dispose(&expected_midx);
-       git_buf_dispose(&path);
+       git_str_dispose(&expected_midx);
+       git_str_dispose(&path);
        git_midx_writer_free(w);
        git_repository_free(repo);
 }
@@ -81,30 +82,30 @@ void test_pack_midx__odb_create(void)
        git_repository *repo;
        git_odb *odb;
        git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
-       git_buf midx = GIT_BUF_INIT, expected_midx = GIT_BUF_INIT, midx_path = GIT_BUF_INIT;
+       git_str midx = GIT_STR_INIT, expected_midx = GIT_STR_INIT, midx_path = GIT_STR_INIT;
        struct stat st;
 
        opts.bare = true;
        opts.local = GIT_CLONE_LOCAL;
        cl_git_pass(git_clone(&repo, cl_fixture("testrepo/.gitted"), "./clone.git", &opts));
-       cl_git_pass(git_buf_joinpath(&midx_path, git_repository_path(repo), "objects/pack/multi-pack-index"));
-       cl_git_fail(p_stat(git_buf_cstr(&midx_path), &st));
+       cl_git_pass(git_str_joinpath(&midx_path, git_repository_path(repo), "objects/pack/multi-pack-index"));
+       cl_git_fail(p_stat(git_str_cstr(&midx_path), &st));
 
        cl_git_pass(git_repository_odb(&odb, repo));
        cl_git_pass(git_odb_write_multi_pack_index(odb));
        git_odb_free(odb);
 
-       cl_git_pass(p_stat(git_buf_cstr(&midx_path), &st));
+       cl_git_pass(p_stat(git_str_cstr(&midx_path), &st));
 
        cl_git_pass(git_futils_readbuffer(&expected_midx, cl_fixture("testrepo.git/objects/pack/multi-pack-index")));
-       cl_git_pass(git_futils_readbuffer(&midx, git_buf_cstr(&midx_path)));
-       cl_assert_equal_i(git_buf_len(&midx), git_buf_len(&expected_midx));
-       cl_assert_equal_strn(git_buf_cstr(&midx), git_buf_cstr(&expected_midx), git_buf_len(&midx));
+       cl_git_pass(git_futils_readbuffer(&midx, git_str_cstr(&midx_path)));
+       cl_assert_equal_i(git_str_len(&midx), git_str_len(&expected_midx));
+       cl_assert_equal_strn(git_str_cstr(&midx), git_str_cstr(&expected_midx), git_str_len(&midx));
 
        git_repository_free(repo);
-       git_buf_dispose(&midx);
-       git_buf_dispose(&midx_path);
-       git_buf_dispose(&expected_midx);
+       git_str_dispose(&midx);
+       git_str_dispose(&midx_path);
+       git_str_dispose(&expected_midx);
 
        cl_git_pass(git_futils_rmdir_r("./clone.git", NULL, GIT_RMDIR_REMOVE_FILES));
-}
\ No newline at end of file
+}
index 5f5441a5ded25a8928c6daf7f34d0f85012c6e98..f23579817cf1526afe025906172fd076b4fd756b 100644 (file)
@@ -5,6 +5,7 @@
 #include "iterator.h"
 #include "vector.h"
 #include "posix.h"
+#include "hash.h"
 
 static git_repository *_repo;
 static git_revwalk *_revwalker;
@@ -96,10 +97,10 @@ static int feed_indexer(void *ptr, size_t len, void *payload)
 void test_pack_packbuilder__create_pack(void)
 {
        git_indexer_progress stats;
-       git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT, path = GIT_STR_INIT;
        git_hash_ctx ctx;
-       git_oid hash;
-       char hex[GIT_OID_HEXSZ+1]; hex[GIT_OID_HEXSZ] = '\0';
+       unsigned char hash[GIT_HASH_SHA1_SIZE];
+       char hex[(GIT_HASH_SHA1_SIZE * 2) + 1];
 
        seed_packbuilder();
 
@@ -107,8 +108,7 @@ void test_pack_packbuilder__create_pack(void)
        cl_git_pass(git_packbuilder_foreach(_packbuilder, feed_indexer, &stats));
        cl_git_pass(git_indexer_commit(_indexer, &stats));
 
-       git_oid_fmt(hex, git_indexer_hash(_indexer));
-       git_buf_printf(&path, "pack-%s.pack", hex);
+       git_str_printf(&path, "pack-%s.pack", git_indexer_name(_indexer));
 
        /*
         * By default, packfiles are created with only one thread.
@@ -124,31 +124,26 @@ void test_pack_packbuilder__create_pack(void)
         *
         */
 
-       cl_git_pass(git_futils_readbuffer(&buf, git_buf_cstr(&path)));
+       cl_git_pass(git_futils_readbuffer(&buf, git_str_cstr(&path)));
 
-       cl_git_pass(git_hash_ctx_init(&ctx));
+       cl_git_pass(git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA1));
        cl_git_pass(git_hash_update(&ctx, buf.ptr, buf.size));
-       cl_git_pass(git_hash_final(&hash, &ctx));
+       cl_git_pass(git_hash_final(hash, &ctx));
        git_hash_ctx_cleanup(&ctx);
 
-       git_buf_dispose(&path);
-       git_buf_dispose(&buf);
-
-       git_oid_fmt(hex, &hash);
+       git_str_dispose(&path);
+       git_str_dispose(&buf);
 
+       git_hash_fmt(hex, hash, GIT_HASH_SHA1_SIZE);
        cl_assert_equal_s(hex, "5d410bdf97cf896f9007681b92868471d636954b");
 }
 
-void test_pack_packbuilder__get_hash(void)
+void test_pack_packbuilder__get_name(void)
 {
-       char hex[GIT_OID_HEXSZ+1]; hex[GIT_OID_HEXSZ] = '\0';
-
        seed_packbuilder();
 
        cl_git_pass(git_packbuilder_write(_packbuilder, ".", 0, NULL, NULL));
-       git_oid_fmt(hex, git_packbuilder_hash(_packbuilder));
-
-       cl_assert_equal_s(hex, "7f5fa362c664d68ba7221259be1cbd187434b2f0");
+       cl_assert_equal_s("7f5fa362c664d68ba7221259be1cbd187434b2f0", git_packbuilder_name(_packbuilder));
 }
 
 void test_pack_packbuilder__write_default_path(void)
@@ -156,8 +151,8 @@ void test_pack_packbuilder__write_default_path(void)
        seed_packbuilder();
 
        cl_git_pass(git_packbuilder_write(_packbuilder, NULL, 0, NULL, NULL));
-       cl_assert(git_path_exists("objects/pack/pack-7f5fa362c664d68ba7221259be1cbd187434b2f0.idx"));
-       cl_assert(git_path_exists("objects/pack/pack-7f5fa362c664d68ba7221259be1cbd187434b2f0.pack"));
+       cl_assert(git_fs_path_exists("objects/pack/pack-7f5fa362c664d68ba7221259be1cbd187434b2f0.idx"));
+       cl_assert(git_fs_path_exists("objects/pack/pack-7f5fa362c664d68ba7221259be1cbd187434b2f0.pack"));
 }
 
 static void test_write_pack_permission(mode_t given, mode_t expected)
index 3f89eb51af965f5238f32a4307cef36ce5243e21..a3c4c6730b4dcea76a2f890e8cf3c6887bc1f1c0 100644 (file)
@@ -27,13 +27,14 @@ static void ensure_patch_validity(git_patch *patch)
        cl_assert_equal_i(0, delta->new_file.size);
 }
 
-static void ensure_identical_patch_inout(const char *content) {
+static void ensure_identical_patch_inout(const char *content)
+{
        git_buf buf = GIT_BUF_INIT;
        git_patch *patch;
 
        cl_git_pass(git_patch_from_buffer(&patch, content, strlen(content), NULL));
        cl_git_pass(git_patch_to_buf(&buf, patch));
-       cl_assert_equal_strn(git_buf_cstr(&buf), content, strlen(content));
+       cl_assert_equal_strn(buf.ptr, content, strlen(content));
 
        git_patch_free(patch);
        git_buf_dispose(&buf);
@@ -131,12 +132,13 @@ void test_patch_parse__files_with_whitespaces_succeeds(void)
 
 void test_patch_parse__lifetime_of_patch_does_not_depend_on_buffer(void)
 {
-       git_buf diff = GIT_BUF_INIT, rendered = GIT_BUF_INIT;
+       git_str diff = GIT_STR_INIT;
+       git_buf rendered = GIT_BUF_INIT;
        git_patch *patch;
 
-       cl_git_pass(git_buf_sets(&diff, PATCH_ORIGINAL_TO_CHANGE_MIDDLE));
+       cl_git_pass(git_str_sets(&diff, PATCH_ORIGINAL_TO_CHANGE_MIDDLE));
        cl_git_pass(git_patch_from_buffer(&patch, diff.ptr, diff.size, NULL));
-       git_buf_dispose(&diff);
+       git_str_dispose(&diff);
 
        cl_git_pass(git_patch_to_buf(&rendered, patch));
        cl_assert_equal_s(PATCH_ORIGINAL_TO_CHANGE_MIDDLE, rendered.ptr);
index 1e03889fcb776cb22a25ac310d542abe35656e0d..7e2cb6a589fa22f6f6f8bd99f0817433d3e8f4da 100644 (file)
        "@@ -0,0 +1 @@\n" \
        "+a\n"
 
+#define PATCH_DELETE_FILE_WITH_SPACE \
+       "diff --git a/sp ace.txt b/sp ace.txt\n" \
+       "deleted file mode 100644\n" \
+       "index 789819226..000000000\n" \
+       "--- a/sp ace.txt\n" \
+       "+++ /dev/null\n" \
+       "@@ -1 +0,0 @@\n" \
+       "-a\n"
+
 #define PATCH_CRLF \
        "diff --git a/test-file b/test-file\r\n" \
        "new file mode 100644\r\n" \
index b0a9339436de3608ba52951804ed5d0815a03e8f..33cf27ddb06b17e94a4ef4d4c5a62a1a83725280 100644 (file)
@@ -9,7 +9,7 @@
  * and then print a variety of patch files.
  */
 
-void patch_print_from_patchfile(const char *data, size_t len)
+static void patch_print_from_patchfile(const char *data, size_t len)
 {
        git_patch *patch;
        git_buf buf = GIT_BUF_INIT;
index c875a862ce7b059bfb3ac274687652862967e36c..db5359af8b541c6899b21ca6d5b5d2f384a139a7 100644 (file)
@@ -1,4 +1,5 @@
 #include "clar_libgit2.h"
+#include "fs_path.h"
 #include "path.h"
 
 void test_path_core__cleanup(void)
@@ -12,11 +13,11 @@ static void test_make_relative(
        const char *parent,
        int expected_status)
 {
-       git_buf buf = GIT_BUF_INIT;
-       git_buf_puts(&buf, path);
-       cl_assert_equal_i(expected_status, git_path_make_relative(&buf, parent));
+       git_str buf = GIT_STR_INIT;
+       git_str_puts(&buf, path);
+       cl_assert_equal_i(expected_status, git_fs_path_make_relative(&buf, parent));
        cl_assert_equal_s(expected_path, buf.ptr);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 }
 
 void test_path_core__make_relative(void)
@@ -59,284 +60,252 @@ void test_path_core__make_relative(void)
 
 void test_path_core__isvalid_standard(void)
 {
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar/file.txt", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar/.file", 0, 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar/file.txt", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar/.file", 0));
+}
+
+/* Ensure that `is_valid_str` only reads str->size bytes */
+void test_path_core__isvalid_standard_str(void)
+{
+       git_str str = GIT_STR_INIT_CONST("foo/bar//zap", 0);
+       unsigned int flags = GIT_FS_PATH_REJECT_EMPTY_COMPONENT;
+
+       str.size = 0;
+       cl_assert_equal_b(false, git_fs_path_str_is_valid(&str, flags));
+
+       str.size = 3;
+       cl_assert_equal_b(true, git_fs_path_str_is_valid(&str, flags));
+
+       str.size = 4;
+       cl_assert_equal_b(false, git_fs_path_str_is_valid(&str, flags));
+
+       str.size = 5;
+       cl_assert_equal_b(true, git_fs_path_str_is_valid(&str, flags));
+
+       str.size = 7;
+       cl_assert_equal_b(true, git_fs_path_str_is_valid(&str, flags));
+
+       str.size = 8;
+       cl_assert_equal_b(false, git_fs_path_str_is_valid(&str, flags));
+
+       str.size = strlen(str.ptr);
+       cl_assert_equal_b(false, git_fs_path_str_is_valid(&str, flags));
 }
 
 void test_path_core__isvalid_empty_dir_component(void)
 {
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo//bar", 0, 0));
+       unsigned int flags = GIT_FS_PATH_REJECT_EMPTY_COMPONENT;
+
+       /* empty component */
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo//bar", 0));
 
        /* leading slash */
-       cl_assert_equal_b(false, git_path_validate(NULL, "/", 0, 0));
-       cl_assert_equal_b(false, git_path_validate(NULL, "/foo", 0, 0));
-       cl_assert_equal_b(false, git_path_validate(NULL, "/foo/bar", 0, 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("/", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("/foo", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("/foo/bar", 0));
 
        /* trailing slash */
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo/", 0, 0));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo/bar/", 0, 0));
-}
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo/", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar/", 0));
 
-void test_path_core__isvalid_dot_and_dotdot(void)
-{
-       cl_assert_equal_b(true, git_path_validate(NULL, ".", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "./foo", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/.", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "./foo", 0, 0));
-
-       cl_assert_equal_b(true, git_path_validate(NULL, "..", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "../foo", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/..", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "../foo", 0, 0));
-
-       cl_assert_equal_b(false, git_path_validate(NULL, ".", 0, GIT_PATH_REJECT_TRAVERSAL));
-       cl_assert_equal_b(false, git_path_validate(NULL, "./foo", 0, GIT_PATH_REJECT_TRAVERSAL));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo/.", 0, GIT_PATH_REJECT_TRAVERSAL));
-       cl_assert_equal_b(false, git_path_validate(NULL, "./foo", 0, GIT_PATH_REJECT_TRAVERSAL));
-
-       cl_assert_equal_b(false, git_path_validate(NULL, "..", 0, GIT_PATH_REJECT_TRAVERSAL));
-       cl_assert_equal_b(false, git_path_validate(NULL, "../foo", 0, GIT_PATH_REJECT_TRAVERSAL));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo/..", 0, GIT_PATH_REJECT_TRAVERSAL));
-       cl_assert_equal_b(false, git_path_validate(NULL, "../foo", 0, GIT_PATH_REJECT_TRAVERSAL));
+
+       /* empty component */
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo//bar", flags));
+
+       /* leading slash */
+       cl_assert_equal_b(false, git_fs_path_is_valid("/", flags));
+       cl_assert_equal_b(false, git_fs_path_is_valid("/foo", flags));
+       cl_assert_equal_b(false, git_fs_path_is_valid("/foo/bar", flags));
+
+       /* trailing slash */
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo/", flags));
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo/bar/", flags));
 }
 
-void test_path_core__isvalid_dot_git(void)
+void test_path_core__isvalid_dot_and_dotdot(void)
 {
-       cl_assert_equal_b(true, git_path_validate(NULL, ".git", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".git/foo", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/.git", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/.git/bar", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/.GIT/bar", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar/.Git", 0, 0));
-
-       cl_assert_equal_b(false, git_path_validate(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
-       cl_assert_equal_b(false, git_path_validate(NULL, ".git/foo", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo/.git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo/.git/bar", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo/.GIT/bar", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo/bar/.Git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
-
-       cl_assert_equal_b(true, git_path_validate(NULL, "!git", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/!git", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "!git/bar", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".tig", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/.tig", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".tig/bar", 0, 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid(".", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("./foo", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo/.", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("./foo", 0));
+
+       cl_assert_equal_b(true, git_fs_path_is_valid("..", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("../foo", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo/..", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("../foo", 0));
+
+       cl_assert_equal_b(false, git_fs_path_is_valid(".", GIT_FS_PATH_REJECT_TRAVERSAL));
+       cl_assert_equal_b(false, git_fs_path_is_valid("./foo", GIT_FS_PATH_REJECT_TRAVERSAL));
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo/.", GIT_FS_PATH_REJECT_TRAVERSAL));
+       cl_assert_equal_b(false, git_fs_path_is_valid("./foo", GIT_FS_PATH_REJECT_TRAVERSAL));
+
+       cl_assert_equal_b(false, git_fs_path_is_valid("..", GIT_FS_PATH_REJECT_TRAVERSAL));
+       cl_assert_equal_b(false, git_fs_path_is_valid("../foo", GIT_FS_PATH_REJECT_TRAVERSAL));
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo/..", GIT_FS_PATH_REJECT_TRAVERSAL));
+       cl_assert_equal_b(false, git_fs_path_is_valid("../foo", GIT_FS_PATH_REJECT_TRAVERSAL));
 }
 
 void test_path_core__isvalid_backslash(void)
 {
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo\\file.txt", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar\\file.txt", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar\\", 0, 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo\\file.txt", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar\\file.txt", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar\\", 0));
 
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo\\file.txt", 0, GIT_PATH_REJECT_BACKSLASH));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo/bar\\file.txt", 0, GIT_PATH_REJECT_BACKSLASH));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo/bar\\", 0, GIT_PATH_REJECT_BACKSLASH));
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo\\file.txt", GIT_FS_PATH_REJECT_BACKSLASH));
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo/bar\\file.txt", GIT_FS_PATH_REJECT_BACKSLASH));
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo/bar\\", GIT_FS_PATH_REJECT_BACKSLASH));
 }
 
 void test_path_core__isvalid_trailing_dot(void)
 {
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo.", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo...", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar.", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo./bar", 0, 0));
-
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo.", 0, GIT_PATH_REJECT_TRAILING_DOT));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo...", 0, GIT_PATH_REJECT_TRAILING_DOT));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo/bar.", 0, GIT_PATH_REJECT_TRAILING_DOT));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo./bar", 0, GIT_PATH_REJECT_TRAILING_DOT));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo.", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo...", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar.", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo./bar", 0));
+
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo.", GIT_FS_PATH_REJECT_TRAILING_DOT));
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo...", GIT_FS_PATH_REJECT_TRAILING_DOT));
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo/bar.", GIT_FS_PATH_REJECT_TRAILING_DOT));
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo./bar", GIT_FS_PATH_REJECT_TRAILING_DOT));
 }
 
 void test_path_core__isvalid_trailing_space(void)
 {
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo ", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo   ", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar ", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, " ", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo /bar", 0, 0));
-
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo   ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo/bar ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
-       cl_assert_equal_b(false, git_path_validate(NULL, " ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo /bar", 0, GIT_PATH_REJECT_TRAILING_SPACE));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo ", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo   ", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar ", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid(" ", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo /bar", 0));
+
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo ", GIT_FS_PATH_REJECT_TRAILING_SPACE));
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo   ", GIT_FS_PATH_REJECT_TRAILING_SPACE));
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo/bar ", GIT_FS_PATH_REJECT_TRAILING_SPACE));
+       cl_assert_equal_b(false, git_fs_path_is_valid(" ", GIT_FS_PATH_REJECT_TRAILING_SPACE));
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo /bar", GIT_FS_PATH_REJECT_TRAILING_SPACE));
 }
 
 void test_path_core__isvalid_trailing_colon(void)
 {
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo:", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar:", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, ":", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "foo:/bar", 0, 0));
-
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo:", 0, GIT_PATH_REJECT_TRAILING_COLON));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo/bar:", 0, GIT_PATH_REJECT_TRAILING_COLON));
-       cl_assert_equal_b(false, git_path_validate(NULL, ":", 0, GIT_PATH_REJECT_TRAILING_COLON));
-       cl_assert_equal_b(false, git_path_validate(NULL, "foo:/bar", 0, GIT_PATH_REJECT_TRAILING_COLON));
-}
-
-void test_path_core__isvalid_dotgit_ntfs(void)
-{
-       cl_assert_equal_b(true, git_path_validate(NULL, ".git", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".git ", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".git.", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".git.. .", 0, 0));
-
-       cl_assert_equal_b(true, git_path_validate(NULL, "git~1", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "git~1 ", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "git~1.", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "git~1.. .", 0, 0));
-
-       cl_assert_equal_b(false, git_path_validate(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, ".git ", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, ".git.", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, ".git.. .", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
-
-       cl_assert_equal_b(false, git_path_validate(NULL, "git~1", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "git~1 ", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "git~1.", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "git~1.. .", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo:", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar:", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid(":", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("foo:/bar", 0));
+
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo:", GIT_FS_PATH_REJECT_TRAILING_COLON));
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo/bar:", GIT_FS_PATH_REJECT_TRAILING_COLON));
+       cl_assert_equal_b(false, git_fs_path_is_valid(":", GIT_FS_PATH_REJECT_TRAILING_COLON));
+       cl_assert_equal_b(false, git_fs_path_is_valid("foo:/bar", GIT_FS_PATH_REJECT_TRAILING_COLON));
 }
 
 void test_path_core__isvalid_dos_paths(void)
 {
-       cl_assert_equal_b(true, git_path_validate(NULL, "aux", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "aux.", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "aux:", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "aux.asdf", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "aux.asdf\\zippy", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "aux:asdf\\foobar", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "con", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "prn", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "nul", 0, 0));
-
-       cl_assert_equal_b(false, git_path_validate(NULL, "aux", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "aux.", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "aux:", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "aux.asdf", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "aux.asdf\\zippy", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "aux:asdf\\foobar", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "con", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "prn", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "nul", 0, GIT_PATH_REJECT_DOS_PATHS));
-
-       cl_assert_equal_b(true, git_path_validate(NULL, "aux1", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "aux1", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(true, git_path_validate(NULL, "auxn", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(true, git_path_validate(NULL, "aux\\foo", 0, GIT_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(true, git_fs_path_is_valid("aux", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("aux.", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("aux:", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("aux.asdf", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("aux.asdf\\zippy", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("aux:asdf\\foobar", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("con", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("prn", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("nul", 0));
+
+       cl_assert_equal_b(false, git_fs_path_is_valid("aux", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("aux.", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("aux:", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("aux.asdf", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("aux.asdf\\zippy", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("aux:asdf\\foobar", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("con", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("prn", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("nul", GIT_FS_PATH_REJECT_DOS_PATHS));
+
+       cl_assert_equal_b(true, git_fs_path_is_valid("aux1", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("aux1", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(true, git_fs_path_is_valid("auxn", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(true, git_fs_path_is_valid("aux\\foo", GIT_FS_PATH_REJECT_DOS_PATHS));
 }
 
 void test_path_core__isvalid_dos_paths_withnum(void)
 {
-       cl_assert_equal_b(true, git_path_validate(NULL, "com1", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "com1.", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "com1:", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "com1.asdf", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "com1.asdf\\zippy", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "com1:asdf\\foobar", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "com1\\foo", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "lpt1", 0, 0));
-
-       cl_assert_equal_b(false, git_path_validate(NULL, "com1", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "com1.", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "com1:", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "com1.asdf", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "com1.asdf\\zippy", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "com1:asdf\\foobar", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "com1/foo", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "lpt1", 0, GIT_PATH_REJECT_DOS_PATHS));
-
-       cl_assert_equal_b(true, git_path_validate(NULL, "com0", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "com0", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(true, git_path_validate(NULL, "com10", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "com10", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(true, git_path_validate(NULL, "comn", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(true, git_path_validate(NULL, "com1\\foo", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(true, git_path_validate(NULL, "lpt0", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(true, git_path_validate(NULL, "lpt10", 0, GIT_PATH_REJECT_DOS_PATHS));
-       cl_assert_equal_b(true, git_path_validate(NULL, "lptn", 0, GIT_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(true, git_fs_path_is_valid("com1", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("com1.", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("com1:", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("com1.asdf", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("com1.asdf\\zippy", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("com1:asdf\\foobar", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("com1\\foo", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("lpt1", 0));
+
+       cl_assert_equal_b(false, git_fs_path_is_valid("com1", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("com1.", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("com1:", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("com1.asdf", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("com1.asdf\\zippy", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("com1:asdf\\foobar", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("com1/foo", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("lpt1", GIT_FS_PATH_REJECT_DOS_PATHS));
+
+       cl_assert_equal_b(true, git_fs_path_is_valid("com0", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("com0", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(true, git_fs_path_is_valid("com10", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("com10", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(true, git_fs_path_is_valid("comn", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(true, git_fs_path_is_valid("com1\\foo", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(true, git_fs_path_is_valid("lpt0", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(true, git_fs_path_is_valid("lpt10", GIT_FS_PATH_REJECT_DOS_PATHS));
+       cl_assert_equal_b(true, git_fs_path_is_valid("lptn", GIT_FS_PATH_REJECT_DOS_PATHS));
 }
 
 void test_path_core__isvalid_nt_chars(void)
 {
-       cl_assert_equal_b(true, git_path_validate(NULL, "asdf\001foo", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "asdf\037bar", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "asdf<bar", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "asdf>foo", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "asdf:foo", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "asdf\"bar", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "asdf|foo", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "asdf?bar", 0, 0));
-       cl_assert_equal_b(true, git_path_validate(NULL, "asdf*bar", 0, 0));
-
-       cl_assert_equal_b(false, git_path_validate(NULL, "asdf\001foo", 0, GIT_PATH_REJECT_NT_CHARS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "asdf\037bar", 0, GIT_PATH_REJECT_NT_CHARS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "asdf<bar", 0, GIT_PATH_REJECT_NT_CHARS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "asdf>foo", 0, GIT_PATH_REJECT_NT_CHARS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "asdf:foo", 0, GIT_PATH_REJECT_NT_CHARS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "asdf\"bar", 0, GIT_PATH_REJECT_NT_CHARS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "asdf|foo", 0, GIT_PATH_REJECT_NT_CHARS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "asdf?bar", 0, GIT_PATH_REJECT_NT_CHARS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "asdf*bar", 0, GIT_PATH_REJECT_NT_CHARS));
-}
-
-void test_path_core__isvalid_dotgit_with_hfs_ignorables(void)
-{
-       cl_assert_equal_b(false, git_path_validate(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, ".git\xe2\x80\x8c", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, ".gi\xe2\x80\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, ".g\xe2\x80\x8eIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, ".\xe2\x80\x8fgIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "\xe2\x80\xaa.gIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-
-       cl_assert_equal_b(false, git_path_validate(NULL, "\xe2\x80\xab.\xe2\x80\xacG\xe2\x80\xadI\xe2\x80\xaet", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "\xe2\x81\xab.\xe2\x80\xaaG\xe2\x81\xabI\xe2\x80\xact", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, "\xe2\x81\xad.\xe2\x80\xaeG\xef\xbb\xbfIT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-
-       cl_assert_equal_b(true, git_path_validate(NULL, ".", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".g", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".gi", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(true, git_path_validate(NULL, " .git", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(true, git_path_validate(NULL, "..git\xe2\x80\x8c", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".gi\xe2\x80\x8dT.", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".g\xe2\x80It", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".\xe2gIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(true, git_path_validate(NULL, "\xe2\x80\xaa.gi", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".gi\x80\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".gi\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".g\xe2i\x80T\x8e", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".git\xe2\x80\xbf", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(true, git_path_validate(NULL, ".git\xe2\xab\x81", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(true, git_fs_path_is_valid("asdf\001foo", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("asdf\037bar", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("asdf<bar", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("asdf>foo", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("asdf:foo", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("asdf\"bar", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("asdf|foo", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("asdf?bar", 0));
+       cl_assert_equal_b(true, git_fs_path_is_valid("asdf*bar", 0));
+
+       cl_assert_equal_b(false, git_fs_path_is_valid("asdf\001foo", GIT_FS_PATH_REJECT_NT_CHARS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("asdf\037bar", GIT_FS_PATH_REJECT_NT_CHARS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("asdf<bar", GIT_FS_PATH_REJECT_NT_CHARS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("asdf>foo", GIT_FS_PATH_REJECT_NT_CHARS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("asdf:foo", GIT_FS_PATH_REJECT_NT_CHARS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("asdf\"bar", GIT_FS_PATH_REJECT_NT_CHARS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("asdf|foo", GIT_FS_PATH_REJECT_NT_CHARS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("asdf?bar", GIT_FS_PATH_REJECT_NT_CHARS));
+       cl_assert_equal_b(false, git_fs_path_is_valid("asdf*bar", GIT_FS_PATH_REJECT_NT_CHARS));
 }
 
 void test_path_core__validate_workdir(void)
 {
-       cl_must_pass(git_path_validate_workdir(NULL, "/foo/bar"));
-       cl_must_pass(git_path_validate_workdir(NULL, "C:\\Foo\\Bar"));
-       cl_must_pass(git_path_validate_workdir(NULL, "\\\\?\\C:\\Foo\\Bar"));
-       cl_must_pass(git_path_validate_workdir(NULL, "\\\\?\\C:\\Foo\\Bar"));
-       cl_must_pass(git_path_validate_workdir(NULL, "\\\\?\\UNC\\server\\C$\\folder"));
+       cl_must_pass(git_path_validate_length(NULL, "/foo/bar"));
+       cl_must_pass(git_path_validate_length(NULL, "C:\\Foo\\Bar"));
+       cl_must_pass(git_path_validate_length(NULL, "\\\\?\\C:\\Foo\\Bar"));
+       cl_must_pass(git_path_validate_length(NULL, "\\\\?\\C:\\Foo\\Bar"));
+       cl_must_pass(git_path_validate_length(NULL, "\\\\?\\UNC\\server\\C$\\folder"));
 
 #ifdef GIT_WIN32
        /*
-        * In the absense of a repo configuration, 259 character paths
+        * In the absence of a repo configuration, 259 character paths
         * succeed. >= 260 character paths fail.
         */
-       cl_must_pass(git_path_validate_workdir(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\ok.txt"));
-       cl_must_pass(git_path_validate_workdir(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\260.txt"));
-       cl_must_fail(git_path_validate_workdir(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\longer_than_260.txt"));
+       cl_must_pass(git_path_validate_length(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\ok.txt"));
+       cl_must_pass(git_path_validate_length(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\260.txt"));
+       cl_must_fail(git_path_validate_length(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\longer_than_260.txt"));
 
        /* count characters, not bytes */
-       cl_must_pass(git_path_validate_workdir(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\260.txt"));
-       cl_must_fail(git_path_validate_workdir(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\long.txt"));
+       cl_must_pass(git_path_validate_length(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\260.txt"));
+       cl_must_fail(git_path_validate_length(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\long.txt"));
 #else
-       cl_must_pass(git_path_validate_workdir(NULL, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/ok.txt"));
-       cl_must_pass(git_path_validate_workdir(NULL, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/260.txt"));
-       cl_must_pass(git_path_validate_workdir(NULL, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
-       cl_must_pass(git_path_validate_workdir(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\260.txt"));
-       cl_must_pass(git_path_validate_workdir(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\long.txt"));
+       cl_must_pass(git_path_validate_length(NULL, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/ok.txt"));
+       cl_must_pass(git_path_validate_length(NULL, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/260.txt"));
+       cl_must_pass(git_path_validate_length(NULL, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
+       cl_must_pass(git_path_validate_length(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\260.txt"));
+       cl_must_pass(git_path_validate_length(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\long.txt"));
 #endif
 }
 
@@ -352,15 +321,15 @@ void test_path_core__validate_workdir_with_core_longpath(void)
        cl_git_pass(git_repository_config(&config, repo));
 
        /* fail by default */
-       cl_must_fail(git_path_validate_workdir(repo, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
+       cl_must_fail(git_path_validate_length(repo, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
 
        /* set core.longpaths explicitly on */
        cl_git_pass(git_config_set_bool(config, "core.longpaths", 1));
-       cl_must_pass(git_path_validate_workdir(repo, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
+       cl_must_pass(git_path_validate_length(repo, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
 
        /* set core.longpaths explicitly off */
        cl_git_pass(git_config_set_bool(config, "core.longpaths", 0));
-       cl_must_fail(git_path_validate_workdir(repo, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
+       cl_must_fail(git_path_validate_length(repo, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
 
        git_config_free(config);
        git_repository_free(repo);
@@ -373,19 +342,19 @@ static void test_join_unrooted(
        const char *path,
        const char *base)
 {
-       git_buf result = GIT_BUF_INIT;
+       git_str result = GIT_STR_INIT;
        ssize_t root_at;
 
-       cl_git_pass(git_path_join_unrooted(&result, path, base, &root_at));
+       cl_git_pass(git_fs_path_join_unrooted(&result, path, base, &root_at));
        cl_assert_equal_s(expected_result, result.ptr);
        cl_assert_equal_i(expected_rootlen, root_at);
 
-       git_buf_dispose(&result);
+       git_str_dispose(&result);
 }
 
 void test_path_core__join_unrooted(void)
 {
-       git_buf out = GIT_BUF_INIT;
+       git_str out = GIT_STR_INIT;
 
        test_join_unrooted("foo", 0, "foo", NULL);
        test_join_unrooted("foo/bar", 0, "foo/bar", NULL);
@@ -421,7 +390,7 @@ void test_path_core__join_unrooted(void)
        /* Trailing slash in the base is ignored */
        test_join_unrooted("c:/foo/bar/foobar", 6, "c:/foo/bar/foobar", "c:/foo/");
 
-       git_buf_dispose(&out);
+       git_str_dispose(&out);
 }
 
 void test_path_core__join_unrooted_respects_funny_windows_roots(void)
index 2f9fcae4fc8e7a9786847ba81e9f3925c504b904..855145f420bdd4a29854b1a0ca6c828f9265ace1 100644 (file)
@@ -1,4 +1,5 @@
 #include "clar_libgit2.h"
+
 #include "path.h"
 
 static char *gitmodules_altnames[] = {
@@ -113,8 +114,93 @@ void test_path_dotgit__dotgit_modules(void)
 
 void test_path_dotgit__dotgit_modules_symlink(void)
 {
-       cl_assert_equal_b(true, git_path_validate(NULL, ".gitmodules", 0, GIT_PATH_REJECT_DOT_GIT_HFS|GIT_PATH_REJECT_DOT_GIT_NTFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, ".gitmodules", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_HFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, ".gitmodules", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_NTFS));
-       cl_assert_equal_b(false, git_path_validate(NULL, ".gitmodules . .::$DATA", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_NTFS));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".gitmodules", 0, GIT_PATH_REJECT_DOT_GIT_HFS|GIT_PATH_REJECT_DOT_GIT_NTFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, ".gitmodules", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, ".gitmodules", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_NTFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, ".gitmodules . .::$DATA", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_NTFS));
+}
+
+void test_path_dotgit__git_fs_path_is_file(void)
+{
+       cl_git_fail(git_path_is_gitfile("blob", 4, -1, GIT_PATH_FS_HFS));
+       cl_git_pass(git_path_is_gitfile("blob", 4, GIT_PATH_GITFILE_GITIGNORE, GIT_PATH_FS_HFS));
+       cl_git_pass(git_path_is_gitfile("blob", 4, GIT_PATH_GITFILE_GITMODULES, GIT_PATH_FS_HFS));
+       cl_git_pass(git_path_is_gitfile("blob", 4, GIT_PATH_GITFILE_GITATTRIBUTES, GIT_PATH_FS_HFS));
+       cl_git_fail(git_path_is_gitfile("blob", 4, 3, GIT_PATH_FS_HFS));
+}
+
+void test_path_dotgit__isvalid_dot_git(void)
+{
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".git", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".git/foo", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, "foo/.git", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, "foo/.git/bar", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, "foo/.GIT/bar", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, "foo/bar/.Git", 0, 0));
+
+       cl_assert_equal_b(false, git_path_is_valid(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, ".git/foo", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, "foo/.git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, "foo/.git/bar", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, "foo/.GIT/bar", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, "foo/bar/.Git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
+
+       cl_assert_equal_b(true, git_path_is_valid(NULL, "!git", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, "foo/!git", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, "!git/bar", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".tig", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, "foo/.tig", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".tig/bar", 0, 0));
+}
+
+void test_path_dotgit__isvalid_dotgit_ntfs(void)
+{
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".git", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".git ", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".git.", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".git.. .", 0, 0));
+
+       cl_assert_equal_b(true, git_path_is_valid(NULL, "git~1", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, "git~1 ", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, "git~1.", 0, 0));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, "git~1.. .", 0, 0));
+
+       cl_assert_equal_b(false, git_path_is_valid(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, ".git ", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, ".git.", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, ".git.. .", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+
+       cl_assert_equal_b(false, git_path_is_valid(NULL, "git~1", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, "git~1 ", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, "git~1.", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, "git~1.. .", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+}
+
+void test_path_dotgit__isvalid_dotgit_with_hfs_ignorables(void)
+{
+       cl_assert_equal_b(false, git_path_is_valid(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, ".git\xe2\x80\x8c", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, ".gi\xe2\x80\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, ".g\xe2\x80\x8eIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, ".\xe2\x80\x8fgIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, "\xe2\x80\xaa.gIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+
+       cl_assert_equal_b(false, git_path_is_valid(NULL, "\xe2\x80\xab.\xe2\x80\xacG\xe2\x80\xadI\xe2\x80\xaet", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, "\xe2\x81\xab.\xe2\x80\xaaG\xe2\x81\xabI\xe2\x80\xact", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(false, git_path_is_valid(NULL, "\xe2\x81\xad.\xe2\x80\xaeG\xef\xbb\xbfIT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".g", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".gi", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, " .git", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, "..git\xe2\x80\x8c", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".gi\xe2\x80\x8dT.", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".g\xe2\x80It", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".\xe2gIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, "\xe2\x80\xaa.gi", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".gi\x80\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".gi\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".g\xe2i\x80T\x8e", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".git\xe2\x80\xbf", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+       cl_assert_equal_b(true, git_path_is_valid(NULL, ".git\xe2\xab\x81", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
 }
index 46b5c9f7015326465ea64e894af5f5634b488f31..1aaf6867a26d4fd23dca44248d9ddeeeb89a8ebb 100644 (file)
@@ -1,40 +1,31 @@
 
 #include "clar_libgit2.h"
-#include "path.h"
 
 #ifdef GIT_WIN32
 #include "win32/path_w32.h"
 #endif
 
-void test_utf8_to_utf16(const char *utf8_in, const wchar_t *utf16_expected)
-{
 #ifdef GIT_WIN32
+static void test_utf8_to_utf16(const char *utf8_in, const wchar_t *utf16_expected)
+{
        git_win32_path path_utf16;
        int path_utf16len;
 
        cl_assert((path_utf16len = git_win32_path_from_utf8(path_utf16, utf8_in)) >= 0);
        cl_assert_equal_wcs(utf16_expected, path_utf16);
        cl_assert_equal_i(wcslen(utf16_expected), path_utf16len);
-#else
-       GIT_UNUSED(utf8_in);
-       GIT_UNUSED(utf16_expected);
-#endif
 }
 
-void test_utf8_to_utf16_relative(const char* utf8_in, const wchar_t* utf16_expected)
+static void test_utf8_to_utf16_relative(const char* utf8_in, const wchar_t* utf16_expected)
 {
-#ifdef GIT_WIN32
        git_win32_path path_utf16;
        int path_utf16len;
 
        cl_assert((path_utf16len = git_win32_path_relative_from_utf8(path_utf16, utf8_in)) >= 0);
        cl_assert_equal_wcs(utf16_expected, path_utf16);
        cl_assert_equal_i(wcslen(utf16_expected), path_utf16len);
-#else
-       GIT_UNUSED(utf8_in);
-       GIT_UNUSED(utf16_expected);
-#endif
 }
+#endif
 
 void test_path_win32__utf8_to_utf16(void)
 {
@@ -278,7 +269,7 @@ void test_path_win32__8dot3_name(void)
        cl_assert_equal_s("WINDOWS", (shortname = git_win32_path_8dot3_name("C:\\WINDOWS")));
        git__free(shortname);
 
-       /* Create some predictible short names */
+       /* Create some predictable short names */
        cl_must_pass(p_mkdir(".foo", 0777));
        cl_assert_equal_s("FOO~1", (shortname = git_win32_path_8dot3_name(".foo")));
        git__free(shortname);
index 49a601243fe468830923032e88040ed75a7dfc6d..a120f28aca84b93009af9423069e18b6cabcd10e 100644 (file)
@@ -47,7 +47,7 @@ static void test_operations(git_rebase *rebase, size_t expected_current)
        }
 }
 
-void test_iterator(bool inmemory)
+static void test_iterator(bool inmemory)
 {
        git_rebase *rebase;
        git_rebase_options opts = GIT_REBASE_OPTIONS_INIT;
index d24e4facffe648fc097e6744c4f7337f3c278ee0..5f730f750b3582c5e21212a11e2365185a3c14a4 100644 (file)
@@ -729,7 +729,7 @@ void test_rebase_merge__copy_notes_disabled_in_config(void)
        test_copy_note(NULL, 0);
 }
 
-void rebase_checkout_progress_cb(
+static void rebase_checkout_progress_cb(
        const char *path,
        size_t completed_steps,
        size_t total_steps,
index 06c18937aa19c25ebdfd944029412f002f2aeff0..4064cf79b5f15127b01ccb7aeefe22af4614afd2 100644 (file)
@@ -86,7 +86,7 @@ committer Rebaser <rebaser@rebaser.rb> 1405694510 +0000\n";
        git_rebase_free(rebase);
 }
 
-int create_cb_signed_gpg(
+static int create_cb_signed_gpg(
        git_oid *out,
        const git_signature *author,
        const git_signature *committer,
@@ -263,8 +263,8 @@ int signing_cb_passthrough(
        const char *commit_content,
        void *payload)
 {
-       cl_assert_equal_b(false, git_buf_is_allocated(signature));
-       cl_assert_equal_b(false, git_buf_is_allocated(signature_field));
+       cl_assert_equal_i(0, signature->size);
+       cl_assert_equal_i(0, signature_field->size);
        cl_assert_equal_s(expected_commit_content, commit_content);
        cl_assert_equal_p(NULL, payload);
        return GIT_PASSTHROUGH;
@@ -342,8 +342,8 @@ cttVRsdOoego+fiy08eFE+aJIeYiINRGhqOBTsuqG4jIdpdKxPE=\n\
 =KbsY\n\
 -----END PGP SIGNATURE-----";
 
-       cl_assert_equal_b(false, git_buf_is_allocated(signature));
-       cl_assert_equal_b(false, git_buf_is_allocated(signature_field));
+       cl_assert_equal_i(0, signature->size);
+       cl_assert_equal_i(0, signature_field->size);
        cl_assert_equal_s(expected_commit_content, commit_content);
        cl_assert_equal_p(NULL, payload);
 
@@ -426,8 +426,10 @@ int signing_cb_magic_field(
        const char *signature_content = "magic word: pretty please";
        const char *signature_field_content = "magicsig";
 
-       cl_assert_equal_b(false, git_buf_is_allocated(signature));
-       cl_assert_equal_b(false, git_buf_is_allocated(signature_field));
+       cl_assert_equal_p(NULL, signature->ptr);
+       cl_assert_equal_i(0, signature->size);
+       cl_assert_equal_p(NULL, signature_field->ptr);
+       cl_assert_equal_i(0, signature_field->size);
        cl_assert_equal_s(expected_commit_content, commit_content);
        cl_assert_equal_p(NULL, payload);
 
index a28b3f4b2a12d759cbf7bcef40f6f53fd9f08759..0b3c2d5b58c9484f0e45afe264a6aa0ad962e8e5 100644 (file)
@@ -65,7 +65,7 @@ void test_rebase_submodule__init_untracked(void)
        git_rebase *rebase;
        git_reference *branch_ref, *upstream_ref;
        git_annotated_commit *branch_head, *upstream_head;
-       git_buf untracked_path = GIT_BUF_INIT;
+       git_str untracked_path = GIT_STR_INIT;
        FILE *fp;
        git_submodule *submodule;
 
@@ -78,11 +78,11 @@ void test_rebase_submodule__init_untracked(void)
        cl_git_pass(git_submodule_lookup(&submodule, repo, "my-submodule"));
        cl_git_pass(git_submodule_update(submodule, 1, NULL));
 
-       git_buf_printf(&untracked_path, "%s/my-submodule/untracked", git_repository_workdir(repo));
-       fp = fopen(git_buf_cstr(&untracked_path), "w");
+       git_str_printf(&untracked_path, "%s/my-submodule/untracked", git_repository_workdir(repo));
+       fp = fopen(git_str_cstr(&untracked_path), "w");
        fprintf(fp, "An untracked file in a submodule should not block a rebase\n");
        fclose(fp);
-       git_buf_dispose(&untracked_path);
+       git_str_dispose(&untracked_path);
 
        cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
 
index 9e4c229648489974dd5128a94d8b04218c55bc51..32742f9ccd8f443ac6b6dcfdfd53c0e8a56a1f5b 100644 (file)
@@ -49,7 +49,7 @@ void test_refs_basic__longpaths(void)
        const char *base;
        size_t base_len, extra_len;
        ssize_t remain_len, i;
-       git_buf refname = GIT_BUF_INIT;
+       git_str refname = GIT_STR_INIT;
        git_reference *one = NULL, *two = NULL;
        git_oid id;
 
@@ -62,10 +62,10 @@ void test_refs_basic__longpaths(void)
        remain_len = (ssize_t)MAX_PATH - (base_len + extra_len);
        cl_assert(remain_len > 0);
 
-       cl_git_pass(git_buf_puts(&refname, "refs/heads/"));
+       cl_git_pass(git_str_puts(&refname, "refs/heads/"));
 
        for (i = 0; i < remain_len; i++) {
-               cl_git_pass(git_buf_putc(&refname, 'a'));
+               cl_git_pass(git_str_putc(&refname, 'a'));
        }
 
        /*
@@ -75,11 +75,11 @@ void test_refs_basic__longpaths(void)
        cl_git_pass(git_reference_create(&one, g_repo, refname.ptr, &id, 0, NULL));
 
        /* Adding one more character gives us a path that is too long. */
-       cl_git_pass(git_buf_putc(&refname, 'z'));
+       cl_git_pass(git_str_putc(&refname, 'z'));
        cl_git_fail(git_reference_create(&two, g_repo, refname.ptr, &id, 0, NULL));
 
        git_reference_free(one);
        git_reference_free(two);
-       git_buf_dispose(&refname);
+       git_str_dispose(&refname);
 #endif
 }
index 70ffad88d241ffa9fd7fbfd5f282112fa5edf973..2fb11668b507b5b492afddd0662fcd7ade8cfdaf 100644 (file)
@@ -120,19 +120,19 @@ static void assert_branch_matches_name(
        const char *expected, const char *lookup_as)
 {
        git_reference *ref;
-       git_buf b = GIT_BUF_INIT;
+       git_str b = GIT_STR_INIT;
 
        cl_git_pass(git_branch_lookup(&ref, repo, lookup_as, GIT_BRANCH_LOCAL));
 
-       cl_git_pass(git_buf_sets(&b, "refs/heads/"));
-       cl_git_pass(git_buf_puts(&b, expected));
+       cl_git_pass(git_str_sets(&b, "refs/heads/"));
+       cl_git_pass(git_str_puts(&b, expected));
        cl_assert_equal_s(b.ptr, git_reference_name(ref));
 
        cl_git_pass(
                git_oid_cmp(git_reference_target(ref), git_commit_id(target)));
 
        git_reference_free(ref);
-       git_buf_dispose(&b);
+       git_str_dispose(&b);
 }
 
 void test_refs_branches_create__can_create_branch_with_unicode(void)
@@ -145,7 +145,7 @@ void test_refs_branches_create__can_create_branch_with_unicode(void)
        const char *expected[] = { nfc, nfd, emoji };
        unsigned int i;
        bool fs_decompose_unicode =
-               git_path_does_fs_decompose_unicode(git_repository_path(repo));
+               git_fs_path_does_decompose_unicode(git_repository_path(repo));
 
        retrieve_known_commit(&target, repo);
 
index 6093c7886583cd744cb0f0ba211c5c48156bc88e..27995f9e2c8b66dd5c73bc9ca807f33284deb88c 100644 (file)
@@ -136,7 +136,7 @@ void test_refs_branches_delete__removes_reflog(void)
 
        cl_assert_equal_i(false, git_reference_has_log(repo, "refs/heads/track-local"));
 
-       /* Reading a nonexistant reflog creates it, but it should be empty */
+       /* Reading a non-existent reflog creates it, but it should be empty */
        cl_git_pass(git_reflog_read(&log, repo, "refs/heads/track-local"));
        cl_assert_equal_i(0, git_reflog_entrycount(log));
        git_reflog_free(log);
@@ -153,8 +153,8 @@ void test_refs_branches_delete__removes_empty_folders(void)
        git_oid oidzero = {{0}};
        git_signature *sig;
 
-       git_buf ref_folder = GIT_BUF_INIT;
-       git_buf reflog_folder = GIT_BUF_INIT;
+       git_str ref_folder = GIT_STR_INIT;
+       git_str reflog_folder = GIT_STR_INIT;
 
        /* Create a new branch with a nested name */
        cl_git_pass(git_oid_fromstr(&commit_id, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"));
@@ -170,19 +170,19 @@ void test_refs_branches_delete__removes_empty_folders(void)
        git_signature_free(sig);
        git_reflog_free(log);
 
-       cl_git_pass(git_buf_joinpath(&ref_folder, commondir, "refs/heads/some/deep"));
-       cl_git_pass(git_buf_join3(&reflog_folder, '/', commondir, GIT_REFLOG_DIR, "refs/heads/some/deep"));
+       cl_git_pass(git_str_joinpath(&ref_folder, commondir, "refs/heads/some/deep"));
+       cl_git_pass(git_str_join3(&reflog_folder, '/', commondir, GIT_REFLOG_DIR, "refs/heads/some/deep"));
 
-       cl_assert(git_path_exists(git_buf_cstr(&ref_folder)) == true);
-       cl_assert(git_path_exists(git_buf_cstr(&reflog_folder)) == true);
+       cl_assert(git_fs_path_exists(git_str_cstr(&ref_folder)) == true);
+       cl_assert(git_fs_path_exists(git_str_cstr(&reflog_folder)) == true);
 
        cl_git_pass(git_branch_delete(branch));
 
-       cl_assert(git_path_exists(git_buf_cstr(&ref_folder)) == false);
-       cl_assert(git_path_exists(git_buf_cstr(&reflog_folder)) == false);
+       cl_assert(git_fs_path_exists(git_str_cstr(&ref_folder)) == false);
+       cl_assert(git_fs_path_exists(git_str_cstr(&reflog_folder)) == false);
 
        git_reference_free(branch);
-       git_buf_dispose(&ref_folder);
-       git_buf_dispose(&reflog_folder);
+       git_str_dispose(&ref_folder);
+       git_str_dispose(&reflog_folder);
 }
 
index ca366c9f3c169f3663646709bf3db92f31308de9..e086681e554f9841216a9fe12b4959e5815f16f1 100644 (file)
@@ -48,7 +48,7 @@ static void assert_retrieval(unsigned int flags, unsigned int expected_count)
 
 void test_refs_branches_iterator__retrieve_all_branches(void)
 {
-       assert_retrieval(GIT_BRANCH_ALL, 14);
+       assert_retrieval(GIT_BRANCH_ALL, 15);
 }
 
 void test_refs_branches_iterator__retrieve_remote_branches(void)
@@ -58,7 +58,7 @@ void test_refs_branches_iterator__retrieve_remote_branches(void)
 
 void test_refs_branches_iterator__retrieve_local_branches(void)
 {
-       assert_retrieval(GIT_BRANCH_LOCAL, 12);
+       assert_retrieval(GIT_BRANCH_LOCAL, 13);
 }
 
 struct expectations {
index 2cba9dfd3a3dbf11fc83164a4c4941c8b821f7d1..46a5082d2fdb9424c1e96afa78f9d19eab6047df 100644 (file)
@@ -67,16 +67,14 @@ void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_coll
 {
        git_reference *original_ref, *new_ref;
        git_config *config;
-       git_buf buf = GIT_BUF_INIT;
-       char *original_remote, *original_merge;
+       git_buf original_remote = GIT_BUF_INIT,
+               original_merge = GIT_BUF_INIT;
        const char *str;
 
        cl_git_pass(git_repository_config_snapshot(&config, repo));
 
-       cl_git_pass(git_config_get_string_buf(&buf, config, "branch.master.remote"));
-       original_remote = git_buf_detach(&buf);
-       cl_git_pass(git_config_get_string_buf(&buf, config, "branch.master.merge"));
-       original_merge  = git_buf_detach(&buf);
+       cl_git_pass(git_config_get_string_buf(&original_remote, config, "branch.master.remote"));
+       cl_git_pass(git_config_get_string_buf(&original_merge, config, "branch.master.merge"));
        git_config_free(config);
 
        cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2"));
@@ -88,9 +86,9 @@ void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_coll
 
        cl_git_pass(git_repository_config_snapshot(&config, repo));
        cl_git_pass(git_config_get_string(&str, config, "branch.master.remote"));
-       cl_assert_equal_s(original_remote, str);
+       cl_assert_equal_s(original_remote.ptr, str);
        cl_git_pass(git_config_get_string(&str, config, "branch.master.merge"));
-       cl_assert_equal_s(original_merge str);
+       cl_assert_equal_s(original_merge.ptr, str);
        git_config_free(config);
 
        cl_assert_equal_i(GIT_EEXISTS,
@@ -100,9 +98,9 @@ void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_coll
 
        cl_git_pass(git_repository_config_snapshot(&config, repo));
        cl_git_pass(git_config_get_string(&str, config, "branch.master.remote"));
-       cl_assert_equal_s(original_remote, str);
+       cl_assert_equal_s(original_remote.ptr, str);
        cl_git_pass(git_config_get_string(&str, config, "branch.master.merge"));
-       cl_assert_equal_s(original_merge str);
+       cl_assert_equal_s(original_merge.ptr, str);
        git_config_free(config);
 
        git_reference_free(original_ref);
@@ -115,11 +113,12 @@ void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_coll
 
        cl_git_pass(git_repository_config_snapshot(&config, repo));
        cl_git_pass(git_config_get_string(&str, config, "branch.master.remote"));
-       cl_assert_equal_s(original_remote, str);
+       cl_assert_equal_s(original_remote.ptr, str);
        cl_git_pass(git_config_get_string(&str, config, "branch.master.merge"));
-       cl_assert_equal_s(original_merge str);
+       cl_assert_equal_s(original_merge.ptr, str);
 
-       git__free(original_remote); git__free(original_merge);
+       git_buf_dispose(&original_remote);
+       git_buf_dispose(&original_merge);
        git_reference_free(original_ref);
        git_config_free(config);
 }
index 290916eecd0d5fad3e3e9f0a50e17ff3ff2da508..efa68e32b11767abc6272e1b467fcd7882c29683 100644 (file)
@@ -51,7 +51,7 @@ static int name_is_valid(const char *name)
        return valid;
 }
 
-void test_refs_branches_is_name_valid(void)
+void test_refs_branches_name__is_name_valid(void)
 {
        cl_assert_equal_i(true, name_is_valid("master"));
        cl_assert_equal_i(true, name_is_valid("test/master"));
index 27a3b0c44975e3179cdfde40a2568d0373a49d11..e2bd3485a8026b7d5af6ac70c73c8a1cf2a2886e 100644 (file)
@@ -32,10 +32,9 @@ void test_refs_branches_remote__can_get_remote_for_branch(void)
 void test_refs_branches_remote__no_matching_remote_returns_error(void)
 {
        const char *unknown = "refs/remotes/nonexistent/master";
-       git_buf buf;
+       git_buf buf = GIT_BUF_INIT;
 
        git_error_clear();
-       memset(&buf, 0, sizeof(git_buf));
        cl_git_fail_with(git_branch_remote_name(&buf, g_repo, unknown), GIT_ENOTFOUND);
        cl_assert(git_error_last() != NULL);
 }
@@ -43,10 +42,9 @@ void test_refs_branches_remote__no_matching_remote_returns_error(void)
 void test_refs_branches_remote__local_remote_returns_error(void)
 {
        const char *local = "refs/heads/master";
-       git_buf buf;
+       git_buf buf = GIT_BUF_INIT;
 
        git_error_clear();
-       memset(&buf, 0, sizeof(git_buf));
        cl_git_fail_with(git_branch_remote_name(&buf, g_repo, local), GIT_ERROR);
        cl_assert(git_error_last() != NULL);
 }
@@ -54,7 +52,7 @@ void test_refs_branches_remote__local_remote_returns_error(void)
 void test_refs_branches_remote__ambiguous_remote_returns_error(void)
 {
        git_remote *remote;
-       git_buf buf;
+       git_buf buf = GIT_BUF_INIT;
 
        /* Create the remote */
        cl_git_pass(git_remote_create_with_fetchspec(&remote, g_repo, "addtest", "http://github.com/libgit2/libgit2", "refs/heads/*:refs/remotes/test/*"));
@@ -62,7 +60,6 @@ void test_refs_branches_remote__ambiguous_remote_returns_error(void)
        git_remote_free(remote);
 
        git_error_clear();
-       memset(&buf, 0, sizeof(git_buf));
        cl_git_fail_with(git_branch_remote_name(&buf, g_repo, remote_tracking_branch_name), GIT_EAMBIGUOUS);
        cl_assert(git_error_last() != NULL);
 }
index 2eb639738ae4d0beddf619fcd0274dcd27782042..5bae154d23c7beeb16f921a99050f38edd377459 100644 (file)
@@ -8,7 +8,6 @@ void test_refs_branches_upstreamname__initialize(void)
 {
        cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
 
-       git_buf_init(&upstream_name, 0);
 }
 
 void test_refs_branches_upstreamname__cleanup(void)
@@ -24,7 +23,7 @@ void test_refs_branches_upstreamname__can_retrieve_the_remote_tracking_reference
        cl_git_pass(git_branch_upstream_name(
                &upstream_name, repo, "refs/heads/master"));
 
-       cl_assert_equal_s("refs/remotes/test/master", git_buf_cstr(&upstream_name));
+       cl_assert_equal_s("refs/remotes/test/master", upstream_name.ptr);
 }
 
 void test_refs_branches_upstreamname__can_retrieve_the_local_upstream_reference_name_of_a_local_branch(void)
@@ -32,5 +31,5 @@ void test_refs_branches_upstreamname__can_retrieve_the_local_upstream_reference_
        cl_git_pass(git_branch_upstream_name(
                &upstream_name, repo, "refs/heads/track-local"));
 
-       cl_assert_equal_s("refs/heads/master", git_buf_cstr(&upstream_name));
+       cl_assert_equal_s("refs/heads/master", upstream_name.ptr);
 }
index 228f479a07a2ecafaf747bda4b72c16161aa45b4..4f508aed2f4a556ca25a7f82b92e17dee19f8155 100644 (file)
@@ -1,4 +1,5 @@
 #include "clar_libgit2.h"
+#include "refs.h"
 
 void test_refs_crashes__double_free(void)
 {
@@ -18,3 +19,26 @@ void test_refs_crashes__double_free(void)
 
        cl_git_sandbox_cleanup();
 }
+
+void test_refs_crashes__empty_packedrefs(void)
+{
+       git_repository *repo;
+       git_reference *ref;
+       const char *REFNAME = "refs/heads/xxx";
+       git_str temp_path = GIT_STR_INIT;
+       int fd = 0;
+
+       repo = cl_git_sandbox_init("empty_bare.git");
+
+       /* create zero-length packed-refs file */
+       cl_git_pass(git_str_joinpath(&temp_path, git_repository_path(repo), GIT_PACKEDREFS_FILE));
+       cl_git_pass(((fd = p_creat(temp_path.ptr, 0644)) < 0));
+       cl_git_pass(p_close(fd));
+
+       /* should fail gracefully */
+       cl_git_fail_with(
+               GIT_ENOTFOUND, git_reference_lookup(&ref, repo, REFNAME));
+
+       cl_git_sandbox_cleanup();
+       git_str_dispose(&temp_path);
+}
index 3e99a7959b744ef0a8d9dcb2d0e119088c3549a3..42cc534b561f7df97796bbc04a1b74aa9a4dffcd 100644 (file)
@@ -29,11 +29,11 @@ void test_refs_delete__packed_loose(void)
 {
        /* deleting a ref which is both packed and loose should remove both tracks in the filesystem */
        git_reference *looked_up_ref, *another_looked_up_ref;
-       git_buf temp_path = GIT_BUF_INIT;
+       git_str temp_path = GIT_STR_INIT;
 
        /* Ensure the loose reference exists on the file system */
-       cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), packed_test_head_name));
-       cl_assert(git_path_exists(temp_path.ptr));
+       cl_git_pass(git_str_joinpath(&temp_path, git_repository_path(g_repo), packed_test_head_name));
+       cl_assert(git_fs_path_exists(temp_path.ptr));
 
        /* Lookup the reference */
        cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name));
@@ -49,10 +49,10 @@ void test_refs_delete__packed_loose(void)
        cl_git_fail(git_reference_lookup(&another_looked_up_ref, g_repo, packed_test_head_name));
 
        /* Ensure the loose reference doesn't exist any longer on the file system */
-       cl_assert(!git_path_exists(temp_path.ptr));
+       cl_assert(!git_fs_path_exists(temp_path.ptr));
 
        git_reference_free(another_looked_up_ref);
-       git_buf_dispose(&temp_path);
+       git_str_dispose(&temp_path);
 }
 
 void test_refs_delete__packed_only(void)
index 3ff18a27a3b2f09638c62ab008a54fceb4a3ef48..b208a95a2b7cbd820ebf0c4f6a5a39fc19566387 100644 (file)
@@ -48,8 +48,8 @@ static void assert_retrieval(const char *glob, int expected_count)
 
 void test_refs_foreachglob__retrieve_all_refs(void)
 {
-       /* 12 heads (including one packed head) + 1 note + 2 remotes + 7 tags + 1 blob */
-       assert_retrieval("*", 23);
+       /* 13 heads (including one packed head) + 1 note + 2 remotes + 7 tags + 1 blob */
+       assert_retrieval("*", 24);
 }
 
 void test_refs_foreachglob__retrieve_remote_branches(void)
@@ -59,7 +59,7 @@ void test_refs_foreachglob__retrieve_remote_branches(void)
 
 void test_refs_foreachglob__retrieve_local_branches(void)
 {
-       assert_retrieval("refs/heads/*", 12);
+       assert_retrieval("refs/heads/*", 13);
 }
 
 void test_refs_foreachglob__retrieve_nonexistant(void)
index 8d52755c241f73cbfd14115db4546741b67524da..a4f9e62ec810ea1e502b12d4ef3658366554a251 100644 (file)
@@ -28,6 +28,7 @@ static const char *refnames[] = {
        "refs/heads/test",
        "refs/heads/track-local",
        "refs/heads/trailing",
+       "refs/heads/with-empty-log",
        "refs/notes/fanout",
        "refs/remotes/test/master",
        "refs/tags/annotated_tag_to_blob",
@@ -58,6 +59,7 @@ static const char *refnames_with_symlink[] = {
        "refs/heads/test",
        "refs/heads/track-local",
        "refs/heads/trailing",
+       "refs/heads/with-empty-log",
        "refs/notes/fanout",
        "refs/remotes/test/master",
        "refs/tags/annotated_tag_to_blob",
index 676fb175986525b98e0e3399d92e7a10664b67e3..1c1cd51cba54b3304b7773da2155f77e41fe8040 100644 (file)
@@ -33,11 +33,11 @@ static void packall(void)
 void test_refs_pack__empty(void)
 {
        /* create a packfile for an empty folder */
-       git_buf temp_path = GIT_BUF_INIT;
+       git_str temp_path = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_join_n(&temp_path, '/', 3, git_repository_path(g_repo), GIT_REFS_HEADS_DIR, "empty_dir"));
+       cl_git_pass(git_str_join_n(&temp_path, '/', 3, git_repository_path(g_repo), GIT_REFS_HEADS_DIR, "empty_dir"));
        cl_git_pass(git_futils_mkdir_r(temp_path.ptr, GIT_REFS_DIR_MODE));
-       git_buf_dispose(&temp_path);
+       git_str_dispose(&temp_path);
 
        packall();
 }
@@ -46,7 +46,7 @@ void test_refs_pack__loose(void)
 {
        /* create a packfile from all the loose refs in a repo */
        git_reference *reference;
-       git_buf temp_path = GIT_BUF_INIT;
+       git_str temp_path = GIT_STR_INIT;
 
        /* Ensure a known loose ref can be looked up */
        cl_git_pass(git_reference_lookup(&reference, g_repo, loose_tag_ref_name));
@@ -62,8 +62,8 @@ void test_refs_pack__loose(void)
        packall();
 
        /* Ensure the packed-refs file exists */
-       cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), GIT_PACKEDREFS_FILE));
-       cl_assert(git_path_exists(temp_path.ptr));
+       cl_git_pass(git_str_joinpath(&temp_path, git_repository_path(g_repo), GIT_PACKEDREFS_FILE));
+       cl_assert(git_fs_path_exists(temp_path.ptr));
 
        /* Ensure the known ref can still be looked up but is now packed */
        cl_git_pass(git_reference_lookup(&reference, g_repo, loose_tag_ref_name));
@@ -71,11 +71,11 @@ void test_refs_pack__loose(void)
        cl_assert_equal_s(reference->name, loose_tag_ref_name);
 
        /* Ensure the known ref has been removed from the loose folder structure */
-       cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), loose_tag_ref_name));
-       cl_assert(!git_path_exists(temp_path.ptr));
+       cl_git_pass(git_str_joinpath(&temp_path, git_repository_path(g_repo), loose_tag_ref_name));
+       cl_assert(!git_fs_path_exists(temp_path.ptr));
 
        git_reference_free(reference);
-       git_buf_dispose(&temp_path);
+       git_str_dispose(&temp_path);
 }
 
 void test_refs_pack__symbolic(void)
index 1bbc387664952c447168db4d32f6ae9d530373ee..a622c770b806dcf57d73addd1618772de71b4b4f 100644 (file)
@@ -31,7 +31,7 @@ void test_refs_read__loose_tag(void)
        /* lookup a loose tag reference */
        git_reference *reference;
        git_object *object;
-       git_buf ref_name_from_tag_name = GIT_BUF_INIT;
+       git_str ref_name_from_tag_name = GIT_STR_INIT;
 
        cl_git_pass(git_reference_lookup(&reference, g_repo, loose_tag_ref_name));
        cl_assert(git_reference_type(reference) & GIT_REFERENCE_DIRECT);
@@ -43,9 +43,9 @@ void test_refs_read__loose_tag(void)
        cl_assert(git_object_type(object) == GIT_OBJECT_TAG);
 
        /* Ensure the name of the tag matches the name of the reference */
-       cl_git_pass(git_buf_joinpath(&ref_name_from_tag_name, GIT_REFS_TAGS_DIR, git_tag_name((git_tag *)object)));
+       cl_git_pass(git_str_joinpath(&ref_name_from_tag_name, GIT_REFS_TAGS_DIR, git_tag_name((git_tag *)object)));
        cl_assert_equal_s(ref_name_from_tag_name.ptr, loose_tag_ref_name);
-       git_buf_dispose(&ref_name_from_tag_name);
+       git_str_dispose(&ref_name_from_tag_name);
 
        git_object_free(object);
 
index 42b49216cd91714d14d1c1a8587dc9762e61053c..70d5d36d540db8bd818e4a0e1b29fc8aae83d2b9 100644 (file)
@@ -2,24 +2,24 @@
 #include "git2/refs.h"
 #include "common.h"
 #include "util.h"
-#include "buffer.h"
 #include "path.h"
+#include "ref_helpers.h"
 
 int reference_is_packed(git_reference *ref)
 {
-       git_buf ref_path = GIT_BUF_INIT;
+       git_str ref_path = GIT_STR_INIT;
        int packed;
 
        assert(ref);
 
-       if (git_buf_joinpath(&ref_path,
+       if (git_str_joinpath(&ref_path,
                git_repository_path(git_reference_owner(ref)),
                git_reference_name(ref)) < 0)
                return -1;
 
-       packed = !git_path_isfile(ref_path.ptr);
+       packed = !git_fs_path_isfile(ref_path.ptr);
 
-       git_buf_dispose(&ref_path);
+       git_str_dispose(&ref_path);
 
        return packed;
 }
index 53b8c6f3ed18f88688c37074588a8c1df9012052..ed183d2f2ca570ce5249f4e7878c32653f441357 100644 (file)
@@ -338,7 +338,7 @@ void test_refs_reflog_messages__updating_a_direct_reference(void)
 
 void test_refs_reflog_messages__creating_branches_default_messages(void)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_annotated_commit *annotated;
        git_object *obj;
        git_commit *target;
@@ -350,11 +350,11 @@ void test_refs_reflog_messages__creating_branches_default_messages(void)
 
        cl_git_pass(git_branch_create(&branch1, g_repo, NEW_BRANCH_NAME, target, false));
 
-       cl_git_pass(git_buf_printf(&buf, "branch: Created from %s", git_oid_tostr_s(git_commit_id(target))));
+       cl_git_pass(git_str_printf(&buf, "branch: Created from %s", git_oid_tostr_s(git_commit_id(target))));
        cl_reflog_check_entry(g_repo, "refs/heads/" NEW_BRANCH_NAME, 0,
                GIT_OID_HEX_ZERO,
                git_oid_tostr_s(git_commit_id(target)),
-               g_email, git_buf_cstr(&buf));
+               g_email, git_str_cstr(&buf));
 
        cl_git_pass(git_reference_remove(g_repo, "refs/heads/" NEW_BRANCH_NAME));
 
@@ -367,7 +367,7 @@ void test_refs_reflog_messages__creating_branches_default_messages(void)
                g_email, "branch: Created from e90810b8df3");
 
        git_annotated_commit_free(annotated);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        git_commit_free(target);
        git_reference_free(branch1);
        git_reference_free(branch2);
index 5cefc3227ec8500809d8e72435a567aa56639473..32ce7ffb7adb583f14d17e39ba0ba53f4509fb78 100644 (file)
@@ -100,60 +100,60 @@ void test_refs_reflog_reflog__append_then_read(void)
 void test_refs_reflog_reflog__renaming_the_reference_moves_the_reflog(void)
 {
        git_reference *master, *new_master;
-       git_buf master_log_path = GIT_BUF_INIT, moved_log_path = GIT_BUF_INIT;
+       git_str master_log_path = GIT_STR_INIT, moved_log_path = GIT_STR_INIT;
 
-       git_buf_joinpath(&master_log_path, git_repository_path(g_repo), GIT_REFLOG_DIR);
-       git_buf_puts(&moved_log_path, git_buf_cstr(&master_log_path));
-       git_buf_joinpath(&master_log_path, git_buf_cstr(&master_log_path), "refs/heads/master");
-       git_buf_joinpath(&moved_log_path, git_buf_cstr(&moved_log_path), "refs/moved");
+       git_str_joinpath(&master_log_path, git_repository_path(g_repo), GIT_REFLOG_DIR);
+       git_str_puts(&moved_log_path, git_str_cstr(&master_log_path));
+       git_str_joinpath(&master_log_path, git_str_cstr(&master_log_path), "refs/heads/master");
+       git_str_joinpath(&moved_log_path, git_str_cstr(&moved_log_path), "refs/moved");
 
-       cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&master_log_path)));
-       cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&moved_log_path)));
+       cl_assert_equal_i(true, git_fs_path_isfile(git_str_cstr(&master_log_path)));
+       cl_assert_equal_i(false, git_fs_path_isfile(git_str_cstr(&moved_log_path)));
 
        cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master"));
        cl_git_pass(git_reference_rename(&new_master, master, "refs/moved", 0, NULL));
        git_reference_free(master);
 
-       cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&master_log_path)));
-       cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&moved_log_path)));
+       cl_assert_equal_i(false, git_fs_path_isfile(git_str_cstr(&master_log_path)));
+       cl_assert_equal_i(true, git_fs_path_isfile(git_str_cstr(&moved_log_path)));
 
        git_reference_free(new_master);
-       git_buf_dispose(&moved_log_path);
-       git_buf_dispose(&master_log_path);
+       git_str_dispose(&moved_log_path);
+       git_str_dispose(&master_log_path);
 }
 
 void test_refs_reflog_reflog__deleting_the_reference_deletes_the_reflog(void)
 {
        git_reference *master;
-       git_buf master_log_path = GIT_BUF_INIT;
+       git_str master_log_path = GIT_STR_INIT;
 
-       git_buf_joinpath(&master_log_path, git_repository_path(g_repo), GIT_REFLOG_DIR);
-       git_buf_joinpath(&master_log_path, git_buf_cstr(&master_log_path), "refs/heads/master");
+       git_str_joinpath(&master_log_path, git_repository_path(g_repo), GIT_REFLOG_DIR);
+       git_str_joinpath(&master_log_path, git_str_cstr(&master_log_path), "refs/heads/master");
 
-       cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&master_log_path)));
+       cl_assert_equal_i(true, git_fs_path_isfile(git_str_cstr(&master_log_path)));
 
        cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master"));
        cl_git_pass(git_reference_delete(master));
        git_reference_free(master);
 
-       cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&master_log_path)));
-       git_buf_dispose(&master_log_path);
+       cl_assert_equal_i(false, git_fs_path_isfile(git_str_cstr(&master_log_path)));
+       git_str_dispose(&master_log_path);
 }
 
 void test_refs_reflog_reflog__removes_empty_reflog_dir(void)
 {
        git_reference *ref;
-       git_buf log_path = GIT_BUF_INIT;
+       git_str log_path = GIT_STR_INIT;
        git_oid id;
 
        /* Create a new branch pointing at the HEAD */
        git_oid_fromstr(&id, current_master_tip);
        cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/new-dir/new-head", &id, 0, NULL));
 
-       git_buf_joinpath(&log_path, git_repository_path(g_repo), GIT_REFLOG_DIR);
-       git_buf_joinpath(&log_path, git_buf_cstr(&log_path), "refs/heads/new-dir/new-head");
+       git_str_joinpath(&log_path, git_repository_path(g_repo), GIT_REFLOG_DIR);
+       git_str_joinpath(&log_path, git_str_cstr(&log_path), "refs/heads/new-dir/new-head");
 
-       cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&log_path)));
+       cl_assert_equal_i(true, git_fs_path_isfile(git_str_cstr(&log_path)));
 
        cl_git_pass(git_reference_delete(ref));
        git_reference_free(ref);
@@ -163,13 +163,13 @@ void test_refs_reflog_reflog__removes_empty_reflog_dir(void)
        cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/new-dir", &id, 0, NULL));
        git_reference_free(ref);
 
-       git_buf_dispose(&log_path);
+       git_str_dispose(&log_path);
 }
 
 void test_refs_reflog_reflog__fails_gracefully_on_nonempty_reflog_dir(void)
 {
        git_reference *ref;
-       git_buf log_path = GIT_BUF_INIT;
+       git_str log_path = GIT_STR_INIT;
        git_oid id;
 
        /* Create a new branch pointing at the HEAD */
@@ -177,10 +177,10 @@ void test_refs_reflog_reflog__fails_gracefully_on_nonempty_reflog_dir(void)
        cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/new-dir/new-head", &id, 0, NULL));
        git_reference_free(ref);
 
-       git_buf_joinpath(&log_path, git_repository_path(g_repo), GIT_REFLOG_DIR);
-       git_buf_joinpath(&log_path, git_buf_cstr(&log_path), "refs/heads/new-dir/new-head");
+       git_str_joinpath(&log_path, git_repository_path(g_repo), GIT_REFLOG_DIR);
+       git_str_joinpath(&log_path, git_str_cstr(&log_path), "refs/heads/new-dir/new-head");
 
-       cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&log_path)));
+       cl_assert_equal_i(true, git_fs_path_isfile(git_str_cstr(&log_path)));
 
        /* delete the ref manually, leave the reflog */
        cl_must_pass(p_unlink("testrepo.git/refs/heads/new-dir/new-head"));
@@ -190,7 +190,7 @@ void test_refs_reflog_reflog__fails_gracefully_on_nonempty_reflog_dir(void)
        cl_git_fail_with(GIT_EDIRECTORY, git_reference_create(&ref, g_repo, "refs/heads/new-dir", &id, 0, NULL));
        git_reference_free(ref);
 
-       git_buf_dispose(&log_path);
+       git_str_dispose(&log_path);
 }
 
 static void assert_has_reflog(bool expected_result, const char *name)
@@ -209,17 +209,17 @@ void test_refs_reflog_reflog__reading_the_reflog_from_a_reference_with_no_log_re
 {
        git_reflog *reflog;
        const char *refname = "refs/heads/subtrees";
-       git_buf subtrees_log_path = GIT_BUF_INIT;
+       git_str subtrees_log_path = GIT_STR_INIT;
 
-       git_buf_join_n(&subtrees_log_path, '/', 3, git_repository_path(g_repo), GIT_REFLOG_DIR, refname);
-       cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&subtrees_log_path)));
+       git_str_join_n(&subtrees_log_path, '/', 3, git_repository_path(g_repo), GIT_REFLOG_DIR, refname);
+       cl_assert_equal_i(false, git_fs_path_isfile(git_str_cstr(&subtrees_log_path)));
 
        cl_git_pass(git_reflog_read(&reflog, g_repo, refname));
 
        cl_assert_equal_i(0, (int)git_reflog_entrycount(reflog));
 
        git_reflog_free(reflog);
-       git_buf_dispose(&subtrees_log_path);
+       git_str_dispose(&subtrees_log_path);
 }
 
 void test_refs_reflog_reflog__reading_a_reflog_with_invalid_format_succeeds(void)
@@ -231,7 +231,7 @@ void test_refs_reflog_reflog__reading_a_reflog_with_invalid_format_succeeds(void
        const git_reflog_entry *entry;
        git_reference *ref;
        git_oid id;
-       git_buf logpath = GIT_BUF_INIT, logcontents = GIT_BUF_INIT;
+       git_str logpath = GIT_STR_INIT, logcontents = GIT_STR_INIT;
        char *star;
 
        /* Create a new branch. */
@@ -242,18 +242,18 @@ void test_refs_reflog_reflog__reading_a_reflog_with_invalid_format_succeeds(void
         * Corrupt the branch reflog by introducing a newline inside the reflog message.
         * We do this by replacing '*' with '\n'
         */
-       cl_git_pass(git_buf_join_n(&logpath, '/', 3, git_repository_path(g_repo), GIT_REFLOG_DIR, refname));
-       cl_git_pass(git_futils_readbuffer(&logcontents, git_buf_cstr(&logpath)));
-       cl_assert((star = strchr(git_buf_cstr(&logcontents), '*')) != NULL);
+       cl_git_pass(git_str_join_n(&logpath, '/', 3, git_repository_path(g_repo), GIT_REFLOG_DIR, refname));
+       cl_git_pass(git_futils_readbuffer(&logcontents, git_str_cstr(&logpath)));
+       cl_assert((star = strchr(git_str_cstr(&logcontents), '*')) != NULL);
        *star = '\n';
-       cl_git_rewritefile(git_buf_cstr(&logpath), git_buf_cstr(&logcontents));
+       cl_git_rewritefile(git_str_cstr(&logpath), git_str_cstr(&logcontents));
 
        /*
         * Confirm that the file was rewritten successfully
         * and now contains a '\n' in the expected location
         */
-       cl_git_pass(git_futils_readbuffer(&logcontents, git_buf_cstr(&logpath)));
-       cl_assert(strstr(git_buf_cstr(&logcontents), "Reflog\nmessage") != NULL);
+       cl_git_pass(git_futils_readbuffer(&logcontents, git_str_cstr(&logpath)));
+       cl_assert(strstr(git_str_cstr(&logcontents), "Reflog\nmessage") != NULL);
 
        cl_git_pass(git_reflog_read(&reflog, g_repo, refname));
        cl_assert(entry = git_reflog_entry_byindex(reflog, 0));
@@ -261,14 +261,14 @@ void test_refs_reflog_reflog__reading_a_reflog_with_invalid_format_succeeds(void
 
        git_reference_free(ref);
        git_reflog_free(reflog);
-       git_buf_dispose(&logpath);
-       git_buf_dispose(&logcontents);
+       git_str_dispose(&logpath);
+       git_str_dispose(&logcontents);
 }
 
 void test_refs_reflog_reflog__cannot_write_a_moved_reflog(void)
 {
        git_reference *master, *new_master;
-       git_buf master_log_path = GIT_BUF_INIT, moved_log_path = GIT_BUF_INIT;
+       git_str master_log_path = GIT_STR_INIT, moved_log_path = GIT_STR_INIT;
        git_reflog *reflog;
 
        cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master"));
@@ -283,8 +283,8 @@ void test_refs_reflog_reflog__cannot_write_a_moved_reflog(void)
 
        git_reflog_free(reflog);
        git_reference_free(new_master);
-       git_buf_dispose(&moved_log_path);
-       git_buf_dispose(&master_log_path);
+       git_str_dispose(&moved_log_path);
+       git_str_dispose(&master_log_path);
 }
 
 void test_refs_reflog_reflog__renaming_with_an_invalid_name_returns_EINVALIDSPEC(void)
index aecb78b02bd217cd5e50bbbb170e951583c8a71c..2ea41ee061e487570be17293e729a9e535bbaa2b 100644 (file)
@@ -2,8 +2,9 @@
 
 #include "repository.h"
 #include "reflog.h"
+#include "reflog_helpers.h"
 
-static int reflog_entry_tostr(git_buf *out, const git_reflog_entry *entry)
+int reflog_entry_tostr(git_str *out, const git_reflog_entry *entry)
 {
        char old_oid[GIT_OID_HEXSZ], new_oid[GIT_OID_HEXSZ];
 
@@ -12,7 +13,7 @@ static int reflog_entry_tostr(git_buf *out, const git_reflog_entry *entry)
        git_oid_tostr((char *)&old_oid, GIT_OID_HEXSZ, git_reflog_entry_id_old(entry));
        git_oid_tostr((char *)&new_oid, GIT_OID_HEXSZ, git_reflog_entry_id_new(entry));
 
-       return git_buf_printf(out, "%s %s %s %s", old_oid, new_oid, "somesig", git_reflog_entry_message(entry));
+       return git_str_printf(out, "%s %s %s %s", old_oid, new_oid, "somesig", git_reflog_entry_message(entry));
 }
 
 size_t reflog_entrycount(git_repository *repo, const char *name)
@@ -34,7 +35,7 @@ void cl_reflog_check_entry_(git_repository *repo, const char *reflog, size_t idx
 {
        git_reflog *log;
        const git_reflog_entry *entry;
-       git_buf result = GIT_BUF_INIT;
+       git_str result = GIT_STR_INIT;
 
        cl_git_pass(git_reflog_read(&log, repo, reflog));
        entry = git_reflog_entry_byindex(log, idx);
@@ -47,7 +48,7 @@ void cl_reflog_check_entry_(git_repository *repo, const char *reflog, size_t idx
                        if (git_oid_cmp(git_object_id(obj), git_reflog_entry_id_old(entry)) != 0) {
                                git_oid__writebuf(&result, "\tOld OID: \"", git_object_id(obj));
                                git_oid__writebuf(&result, "\" != \"", git_reflog_entry_id_old(entry));
-                               git_buf_puts(&result, "\"\n");
+                               git_str_puts(&result, "\"\n");
                        }
                        git_object_free(obj);
                } else {
@@ -56,7 +57,7 @@ void cl_reflog_check_entry_(git_repository *repo, const char *reflog, size_t idx
                        if (git_oid_cmp(oid, git_reflog_entry_id_old(entry)) != 0) {
                                git_oid__writebuf(&result, "\tOld OID: \"", oid);
                                git_oid__writebuf(&result, "\" != \"", git_reflog_entry_id_old(entry));
-                               git_buf_puts(&result, "\"\n");
+                               git_str_puts(&result, "\"\n");
                        }
                        git__free(oid);
                }
@@ -67,7 +68,7 @@ void cl_reflog_check_entry_(git_repository *repo, const char *reflog, size_t idx
                        if (git_oid_cmp(git_object_id(obj), git_reflog_entry_id_new(entry)) != 0) {
                                git_oid__writebuf(&result, "\tNew OID: \"", git_object_id(obj));
                                git_oid__writebuf(&result, "\" != \"", git_reflog_entry_id_new(entry));
-                               git_buf_puts(&result, "\"\n");
+                               git_str_puts(&result, "\"\n");
                        }
                        git_object_free(obj);
                } else {
@@ -76,26 +77,26 @@ void cl_reflog_check_entry_(git_repository *repo, const char *reflog, size_t idx
                        if (git_oid_cmp(oid, git_reflog_entry_id_new(entry)) != 0) {
                                git_oid__writebuf(&result, "\tNew OID: \"", oid);
                                git_oid__writebuf(&result, "\" != \"", git_reflog_entry_id_new(entry));
-                               git_buf_puts(&result, "\"\n");
+                               git_str_puts(&result, "\"\n");
                        }
                        git__free(oid);
                }
        }
 
        if (email && strcmp(email, git_reflog_entry_committer(entry)->email) != 0)
-               git_buf_printf(&result, "\tEmail: \"%s\" != \"%s\"\n", email, git_reflog_entry_committer(entry)->email);
+               git_str_printf(&result, "\tEmail: \"%s\" != \"%s\"\n", email, git_reflog_entry_committer(entry)->email);
 
        if (message) {
                const char *entry_msg = git_reflog_entry_message(entry);
                if (entry_msg == NULL) entry_msg = "";
 
                if (entry_msg && strcmp(message, entry_msg) != 0)
-                       git_buf_printf(&result, "\tMessage: \"%s\" != \"%s\"\n", message, entry_msg);
+                       git_str_printf(&result, "\tMessage: \"%s\" != \"%s\"\n", message, entry_msg);
        }
-       if (git_buf_len(&result) != 0)
-               clar__fail(file, func, line, "Reflog entry mismatch", git_buf_cstr(&result), 1);
+       if (git_str_len(&result) != 0)
+               clar__fail(file, func, line, "Reflog entry mismatch", git_str_cstr(&result), 1);
 
-       git_buf_dispose(&result);
+       git_str_dispose(&result);
        git_reflog_free(log);
 }
 
@@ -103,17 +104,17 @@ void reflog_print(git_repository *repo, const char *reflog_name)
 {
        git_reflog *reflog;
        size_t idx;
-       git_buf out = GIT_BUF_INIT;
+       git_str out = GIT_STR_INIT;
 
        git_reflog_read(&reflog, repo, reflog_name);
 
        for (idx = 0; idx < git_reflog_entrycount(reflog); idx++) {
                const git_reflog_entry *entry = git_reflog_entry_byindex(reflog, idx);
                reflog_entry_tostr(&out, entry);
-               git_buf_putc(&out, '\n');
+               git_str_putc(&out, '\n');
        }
 
-       fprintf(stderr, "%s", git_buf_cstr(&out));
-       git_buf_dispose(&out);
+       fprintf(stderr, "%s", git_str_cstr(&out));
+       git_str_dispose(&out);
        git_reflog_free(reflog);
 }
index 80814ea28928bdabaa04006ca2fed7ea637bc014..4cd92cadc3106eb9382f76c087dd5401b6157cab 100644 (file)
@@ -1,10 +1,12 @@
 size_t reflog_entrycount(git_repository *repo, const char *name);
 
 #define cl_reflog_check_entry(repo, reflog, idx, old_spec, new_spec, email, message) \
-    cl_reflog_check_entry_(repo, reflog, idx, old_spec, new_spec, email, message, __FILE__, __LINE__)
+    cl_reflog_check_entry_(repo, reflog, idx, old_spec, new_spec, email, message, __FILE__, __FUNCTION__, __LINE__)
 
 void cl_reflog_check_entry_(git_repository *repo, const char *reflog, size_t idx,
-                                               const char *old_spec, const char *new_spec,
-                                               const char *email, const char *message, const char *file, int line);
+       const char *old_spec, const char *new_spec,
+       const char *email, const char *message,
+       const char *file, const char *func, int line);
 
 void reflog_print(git_repository *repo, const char *reflog_name);
+int reflog_entry_tostr(git_str *out, const git_reflog_entry *entry);
index b1b75cd647414737904e20b40dfe3038aa990983..f71e657820f934054d50c391b488d268a9e36101 100644 (file)
@@ -36,12 +36,12 @@ void test_refs_rename__loose(void)
 {
        /* rename a loose reference */
        git_reference *looked_up_ref, *new_ref, *another_looked_up_ref;
-       git_buf temp_path = GIT_BUF_INIT;
+       git_str temp_path = GIT_STR_INIT;
        const char *new_name = "refs/tags/Nemo/knows/refs.kung-fu";
 
        /* Ensure the ref doesn't exist on the file system */
-       cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), new_name));
-       cl_assert(!git_path_exists(temp_path.ptr));
+       cl_git_pass(git_str_joinpath(&temp_path, git_repository_path(g_repo), new_name));
+       cl_assert(!git_fs_path_exists(temp_path.ptr));
 
        /* Retrieval of the reference to rename */
        cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, loose_tag_ref_name));
@@ -66,24 +66,24 @@ void test_refs_rename__loose(void)
        cl_assert(reference_is_packed(new_ref) == 0);
 
        /* ...and the ref can be found in the file system */
-       cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), new_name));
-       cl_assert(git_path_exists(temp_path.ptr));
+       cl_git_pass(git_str_joinpath(&temp_path, git_repository_path(g_repo), new_name));
+       cl_assert(git_fs_path_exists(temp_path.ptr));
 
        git_reference_free(new_ref);
        git_reference_free(another_looked_up_ref);
-       git_buf_dispose(&temp_path);
+       git_str_dispose(&temp_path);
 }
 
 void test_refs_rename__packed(void)
 {
        /* rename a packed reference (should make it loose) */
        git_reference *looked_up_ref, *new_ref, *another_looked_up_ref;
-       git_buf temp_path = GIT_BUF_INIT;
+       git_str temp_path = GIT_STR_INIT;
        const char *brand_new_name = "refs/heads/brand_new_name";
 
        /* Ensure the ref doesn't exist on the file system */
-       cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), packed_head_name));
-       cl_assert(!git_path_exists(temp_path.ptr));
+       cl_git_pass(git_str_joinpath(&temp_path, git_repository_path(g_repo), packed_head_name));
+       cl_assert(!git_fs_path_exists(temp_path.ptr));
 
        /* The reference can however be looked-up... */
        cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
@@ -108,24 +108,24 @@ void test_refs_rename__packed(void)
        cl_assert(reference_is_packed(new_ref) == 0);
 
        /* ...and the ref now happily lives in the file system */
-       cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), brand_new_name));
-       cl_assert(git_path_exists(temp_path.ptr));
+       cl_git_pass(git_str_joinpath(&temp_path, git_repository_path(g_repo), brand_new_name));
+       cl_assert(git_fs_path_exists(temp_path.ptr));
 
        git_reference_free(new_ref);
        git_reference_free(another_looked_up_ref);
-       git_buf_dispose(&temp_path);
+       git_str_dispose(&temp_path);
 }
 
 void test_refs_rename__packed_doesnt_pack_others(void)
 {
        /* renaming a packed reference does not pack another reference which happens to be in both loose and pack state */
        git_reference *looked_up_ref, *another_looked_up_ref, *renamed_ref;
-       git_buf temp_path = GIT_BUF_INIT;
+       git_str temp_path = GIT_STR_INIT;
        const char *brand_new_name = "refs/heads/brand_new_name";
 
        /* Ensure the other reference exists on the file system */
-       cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), packed_test_head_name));
-       cl_assert(git_path_exists(temp_path.ptr));
+       cl_git_pass(git_str_joinpath(&temp_path, git_repository_path(g_repo), packed_test_head_name));
+       cl_assert(git_fs_path_exists(temp_path.ptr));
 
        /* Lookup the other reference */
        cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, packed_test_head_name));
@@ -151,11 +151,11 @@ void test_refs_rename__packed_doesnt_pack_others(void)
        cl_assert(reference_is_packed(another_looked_up_ref) == 0);
 
        /* Ensure the other ref still exists on the file system */
-       cl_assert(git_path_exists(temp_path.ptr));
+       cl_assert(git_fs_path_exists(temp_path.ptr));
 
        git_reference_free(renamed_ref);
        git_reference_free(another_looked_up_ref);
-       git_buf_dispose(&temp_path);
+       git_str_dispose(&temp_path);
 }
 
 void test_refs_rename__name_collision(void)
index bc6e0a4c4115114f93a759ee11f17bb231620e39..0bd2ae5bc2c7543645cf3d157daa18404bfbbe24 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 
 #include "git2/revparse.h"
-#include "buffer.h"
 #include "refs.h"
 #include "path.h"
 
@@ -292,7 +291,7 @@ void test_refs_revparse__upstream(void)
 void test_refs_revparse__ordinal(void)
 {
        assert_invalid_single_spec("master@{-2}");
-       
+
        /* TODO: make the test below actually fail
         * cl_git_fail(git_revparse_single(&g_obj, g_repo, "master@{1a}"));
         */
@@ -326,19 +325,19 @@ void test_refs_revparse__previous_head(void)
 static void create_fake_stash_reference_and_reflog(git_repository *repo)
 {
        git_reference *master, *new_master;
-       git_buf log_path = GIT_BUF_INIT;
+       git_str log_path = GIT_STR_INIT;
 
-       git_buf_joinpath(&log_path, git_repository_path(repo), "logs/refs/fakestash");
+       git_str_joinpath(&log_path, git_repository_path(repo), "logs/refs/fakestash");
 
-       cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&log_path)));
+       cl_assert_equal_i(false, git_fs_path_isfile(git_str_cstr(&log_path)));
 
        cl_git_pass(git_reference_lookup(&master, repo, "refs/heads/master"));
        cl_git_pass(git_reference_rename(&new_master, master, "refs/fakestash", 0, NULL));
        git_reference_free(master);
 
-       cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&log_path)));
+       cl_assert_equal_i(true, git_fs_path_isfile(git_str_cstr(&log_path)));
 
-       git_buf_dispose(&log_path);
+       git_str_dispose(&log_path);
        git_reference_free(new_master);
 }
 
@@ -400,7 +399,7 @@ void test_refs_revparse__date(void)
         * a65fedf HEAD@{1335806603 -0900}: commit:
         * be3563a HEAD@{1335806563 -0700}: clone: from /Users/ben/src/libgit2/tests/resour
         */
-       test_object("HEAD@{10 years ago}", NULL);
+       test_object("HEAD@{10 years ago}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
 
        test_object("HEAD@{1 second}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
        test_object("HEAD@{1 second ago}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
@@ -418,11 +417,12 @@ void test_refs_revparse__date(void)
 
 
        /*
-        * $ git reflog -1 "master@{2012-04-30 17:22:42 +0000}"
-        * warning: Log for 'master' only goes back to Mon, 30 Apr 2012 09:22:43 -0800.
+        * $ git rev-parse "master@{2012-04-30 17:22:42 +0000}"
+        * warning: log for 'master' only goes back to Mon, 30 Apr 2012 09:22:43 -0800
+        * be3563ae3f795b2b4353bcce3a527ad0a4f7f644
         */
-       test_object("master@{2012-04-30 17:22:42 +0000}", NULL);
-       test_object("master@{2012-04-30 09:22:42 -0800}", NULL);
+       test_object("master@{2012-04-30 17:22:42 +0000}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
+       test_object("master@{2012-04-30 09:22:42 -0800}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
 
        /*
         * $ git reflog -1 "master@{2012-04-30 17:22:43 +0000}"
@@ -452,6 +452,25 @@ void test_refs_revparse__date(void)
         */
        test_object("master@{1335806603}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
        test_object("master@{1335806602}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
+
+       /*
+        * $ git rev-parse "with-empty-log@{2 days ago}" --
+        * fatal: log for refs/heads/with-empty-log is empty
+        */
+       test_object("with-empty-log@{2 days ago}", NULL);
+}
+
+void test_refs_revparse__invalid_date(void)
+{
+       /*
+        * $ git rev-parse HEAD@{} --
+        * fatal: bad revision 'HEAD@{}'
+        *
+        * $ git rev-parse HEAD@{NEITHER_INTEGER_NOR_DATETIME} --
+        * fatal: bad revision 'HEAD@{NEITHER_INTEGER_NOR_DATETIME}'
+        */
+       test_object("HEAD@{}", NULL);
+       test_object("HEAD@{NEITHER_INTEGER_NOR_DATETIME}", NULL);
 }
 
 void test_refs_revparse__colon(void)
@@ -555,7 +574,7 @@ void test_refs_revparse__a_too_short_objectid_returns_EAMBIGUOUS(void)
 /*
  * $ echo "aabqhq" | git hash-object -t blob --stdin
  * dea509d0b3cb8ee0650f6ca210bc83f4678851ba
- * 
+ *
  * $ echo "aaazvc" | git hash-object -t blob --stdin
  * dea509d097ce692e167dfc6a48a7a280cc5e877e
  */
@@ -569,11 +588,11 @@ void test_refs_revparse__a_not_precise_enough_objectid_returns_EAMBIGUOUS(void)
 
        cl_git_mkfile("testrepo/one.txt", "aabqhq\n");
        cl_git_mkfile("testrepo/two.txt", "aaazvc\n");
-       
+
        cl_git_pass(git_repository_index(&index, repo));
        cl_git_pass(git_index_add_bypath(index, "one.txt"));
        cl_git_pass(git_index_add_bypath(index, "two.txt"));
-       
+
        cl_git_fail_with(git_revparse_single(&obj, repo, "dea509d0"), GIT_EAMBIGUOUS);
 
        cl_git_pass(git_revparse_single(&obj, repo, "dea509d09"));
@@ -588,7 +607,7 @@ void test_refs_revparse__issue_994(void)
        git_repository *repo;
        git_reference *head, *with_at;
        git_object *target;
-       
+
        repo = cl_git_sandbox_init("testrepo.git");
 
        cl_assert_equal_i(GIT_ENOTFOUND,
@@ -862,3 +881,10 @@ void test_refs_revparse__uneven_sizes(void)
        test_object("a65fedf39aefe402d3bb6e24df4d",
                                "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
 }
+
+void test_refs_revparse__parses_at_head(void)
+{
+       test_id("HEAD", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", NULL, GIT_REVSPEC_SINGLE);
+       test_id("@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", NULL, GIT_REVSPEC_SINGLE);
+       test_id("@", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", NULL, GIT_REVSPEC_SINGLE);
+}
index f995d26cac79d2f5171efbc9f71198cc4d55708d..e008adc744eb3087afe2c5f90c7641e6588cd5bd 100644 (file)
@@ -2,7 +2,7 @@
 
 #include "repository.h"
 
-void assert_shorthand(git_repository *repo, const char *refname, const char *shorthand)
+static void assert_shorthand(git_repository *repo, const char *refname, const char *shorthand)
 {
        git_reference *ref;
 
index 0ca5df7d641a91e46ecad7e4d1fa718c37e27117..1dd1760b9ed9a97e91c2431d24dc4a89ab80419b 100644 (file)
@@ -7,7 +7,7 @@ static int name_is_valid(const char *name)
        return valid;
 }
 
-void test_refs_tags_is_name_valid(void)
+void test_refs_tags_name__is_name_valid(void)
 {
        cl_assert_equal_i(true, name_is_valid("sometag"));
        cl_assert_equal_i(true, name_is_valid("test/sometag"));
index 7e825ca16ca2d35d0cbed7c90cff55a71e63cb04..3700462676faff2bbd4aa350a360bd08069dffec 100644 (file)
@@ -15,24 +15,24 @@ static char *NON_FORCE_FETCHSPEC = "refs/heads/main:refs/remotes/repo1/main";
 
 void test_remote_fetch__initialize(void) {
        git_config *c;
-       git_buf repo1_path_buf = GIT_BUF_INIT;
-       git_buf repo2_path_buf = GIT_BUF_INIT;
+       git_str repo1_path_buf = GIT_STR_INIT;
+       git_str repo2_path_buf = GIT_STR_INIT;
        const char *sandbox = clar_sandbox_path();
 
-       cl_git_pass(git_buf_joinpath(&repo1_path_buf, sandbox, "fetchtest_repo1"));
-       repo1_path = git_buf_detach(&repo1_path_buf);
+       cl_git_pass(git_str_joinpath(&repo1_path_buf, sandbox, "fetchtest_repo1"));
+       repo1_path = git_str_detach(&repo1_path_buf);
        cl_git_pass(git_repository_init(&repo1, repo1_path, true));
 
-       cl_git_pass(git_buf_joinpath(&repo2_path_buf, sandbox, "fetchtest_repo2"));
-       repo2_path = git_buf_detach(&repo2_path_buf);
+       cl_git_pass(git_str_joinpath(&repo2_path_buf, sandbox, "fetchtest_repo2"));
+       repo2_path = git_str_detach(&repo2_path_buf);
        cl_git_pass(git_repository_init(&repo2, repo2_path, true));
 
        cl_git_pass(git_repository_config(&c, repo1));
        cl_git_pass(git_config_set_string(c, "user.email", "some@email"));
        cl_git_pass(git_config_set_string(c, "user.name", "some@name"));
        git_config_free(c);
-       git_buf_dispose(&repo1_path_buf);
-       git_buf_dispose(&repo2_path_buf);
+       git_str_dispose(&repo1_path_buf);
+       git_str_dispose(&repo2_path_buf);
 }
 
 void test_remote_fetch__cleanup(void) {
@@ -62,7 +62,7 @@ void test_remote_fetch__cleanup(void) {
  * @param force     Whether to use a spec with '+' prefixed to force the refs
  *                  to update
  */
-void do_time_travelling_fetch(git_oid *commit1id, git_oid *commit2id,
+static void do_time_travelling_fetch(git_oid *commit1id, git_oid *commit2id,
                bool force) {
        char *refspec_strs = {
                force ? FORCE_FETCHSPEC : NON_FORCE_FETCHSPEC,
index 8cd4371f5557ad6358a487fb6cea62f5efdbb094..f62a2545bac5898ee0c81ece0a6c8080226b04cf 100644 (file)
@@ -40,7 +40,7 @@ void test_remote_httpproxy__cleanup(void)
        cl_git_sandbox_cleanup();
 }
 
-void assert_proxy_is(const char *expected)
+static void assert_proxy_is(const char *expected)
 {
        git_remote *remote;
        char *proxy;
@@ -57,7 +57,7 @@ void assert_proxy_is(const char *expected)
        git__free(proxy);
 }
 
-void assert_config_match(const char *config, const char *expected)
+static void assert_config_match(const char *config, const char *expected)
 {
        git_remote *remote;
        char *proxy;
@@ -106,7 +106,7 @@ void test_remote_httpproxy__config_empty_overrides(void)
        assert_config_match("remote.lg2.proxy", "");
 }
 
-void assert_global_config_match(const char *config, const char *expected)
+static void assert_global_config_match(const char *config, const char *expected)
 {
        git_remote *remote;
        char *proxy;
index 05d4757cf0c2c2d1ef2dd60503fac51001566af8..c39df4be7f2b2d825379eb8ac2751475eec51193 100644 (file)
@@ -4,7 +4,12 @@
 
 #define REPO_PATH "testrepo2/.gitted"
 #define REMOTE_ORIGIN "origin"
-#define REMOTE_INSTEADOF "insteadof-test"
+#define REMOTE_INSTEADOF_URL_FETCH "insteadof-url-fetch"
+#define REMOTE_INSTEADOF_URL_PUSH "insteadof-url-push"
+#define REMOTE_INSTEADOF_URL_BOTH "insteadof-url-both"
+#define REMOTE_INSTEADOF_PUSHURL_FETCH "insteadof-pushurl-fetch"
+#define REMOTE_INSTEADOF_PUSHURL_PUSH "insteadof-pushurl-push"
+#define REMOTE_INSTEADOF_PUSHURL_BOTH "insteadof-pushurl-both"
 
 static git_repository *g_repo;
 static git_remote *g_remote;
@@ -21,7 +26,7 @@ void test_remote_insteadof__cleanup(void)
        git_remote_free(g_remote);
 }
 
-void test_remote_insteadof__url_insteadof_not_applicable(void)
+void test_remote_insteadof__not_applicable(void)
 {
        cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH)));
        cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_ORIGIN));
@@ -29,44 +34,121 @@ void test_remote_insteadof__url_insteadof_not_applicable(void)
        cl_assert_equal_s(
                git_remote_url(g_remote),
                "https://github.com/libgit2/false.git");
+       cl_assert_equal_p(git_remote_pushurl(g_remote), NULL);
 }
 
-void test_remote_insteadof__url_insteadof_applicable(void)
+void test_remote_insteadof__url_insteadof_fetch(void)
 {
        cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH)));
-       cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF));
+       cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF_URL_FETCH));
 
        cl_assert_equal_s(
            git_remote_url(g_remote),
-           "http://github.com/libgit2/libgit2");
+           "http://github.com/url/fetch/libgit2");
+       cl_assert_equal_p(git_remote_pushurl(g_remote), NULL);
 }
 
-void test_remote_insteadof__pushurl_insteadof_not_applicable(void)
+void test_remote_insteadof__url_insteadof_push(void)
 {
        cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH)));
-       cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_ORIGIN));
+       cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF_URL_PUSH));
 
-       cl_assert_equal_p(git_remote_pushurl(g_remote), NULL);
+       cl_assert_equal_s(
+           git_remote_url(g_remote),
+           "http://example.com/url/push/libgit2");
+       cl_assert_equal_s(
+           git_remote_pushurl(g_remote),
+           "git@github.com:url/push/libgit2");
 }
 
-void test_remote_insteadof__pushurl_insteadof_applicable(void)
+void test_remote_insteadof__url_insteadof_both(void)
 {
        cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH)));
-       cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF));
+       cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF_URL_BOTH));
 
+       cl_assert_equal_s(
+           git_remote_url(g_remote),
+           "http://github.com/url/both/libgit2");
        cl_assert_equal_s(
            git_remote_pushurl(g_remote),
-           "git@github.com:libgit2/libgit2");
+           "git@github.com:url/both/libgit2");
 }
 
-void test_remote_insteadof__anonymous_remote(void)
+void test_remote_insteadof__pushurl_insteadof_fetch(void)
+{
+       cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH)));
+       cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF_PUSHURL_FETCH));
+
+       cl_assert_equal_s(
+           git_remote_url(g_remote),
+           "http://github.com/url/fetch/libgit2");
+       cl_assert_equal_s(
+           git_remote_pushurl(g_remote),
+           "http://github.com/url/fetch/libgit2-push");
+}
+
+void test_remote_insteadof__pushurl_insteadof_push(void)
+{
+       cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH)));
+       cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF_PUSHURL_PUSH));
+
+       cl_assert_equal_s(
+           git_remote_url(g_remote),
+           "http://example.com/url/push/libgit2");
+       cl_assert_equal_s(
+           git_remote_pushurl(g_remote),
+           "http://example.com/url/push/libgit2-push");
+}
+
+void test_remote_insteadof__pushurl_insteadof_both(void)
+{
+       cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH)));
+       cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF_PUSHURL_BOTH));
+
+       cl_assert_equal_s(
+           git_remote_url(g_remote),
+           "http://github.com/url/both/libgit2");
+       cl_assert_equal_s(
+           git_remote_pushurl(g_remote),
+           "http://github.com/url/both/libgit2-push");
+}
+
+void test_remote_insteadof__anonymous_remote_fetch(void)
 {
        cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH)));
        cl_git_pass(git_remote_create_anonymous(&g_remote, g_repo,
-           "http://example.com/libgit2/libgit2"));
+           "http://example.com/url/fetch/libgit2"));
 
        cl_assert_equal_s(
            git_remote_url(g_remote),
-           "http://github.com/libgit2/libgit2");
+           "http://github.com/url/fetch/libgit2");
        cl_assert_equal_p(git_remote_pushurl(g_remote), NULL);
 }
+
+void test_remote_insteadof__anonymous_remote_push(void)
+{
+       cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH)));
+       cl_git_pass(git_remote_create_anonymous(&g_remote, g_repo,
+           "http://example.com/url/push/libgit2"));
+
+       cl_assert_equal_s(
+           git_remote_url(g_remote),
+           "http://example.com/url/push/libgit2");
+       cl_assert_equal_s(
+           git_remote_pushurl(g_remote),
+           "git@github.com:url/push/libgit2");
+}
+
+void test_remote_insteadof__anonymous_remote_both(void)
+{
+       cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH)));
+       cl_git_pass(git_remote_create_anonymous(&g_remote, g_repo,
+           "http://example.com/url/both/libgit2"));
+
+       cl_assert_equal_s(
+           git_remote_url(g_remote),
+           "http://github.com/url/both/libgit2");
+       cl_assert_equal_s(
+           git_remote_pushurl(g_remote),
+           "git@github.com:url/both/libgit2");
+}
index 6ca31f550a72e2e2b91833c3b73b0150a2f784c6..37f6b521d820644f3cb548d299ddc2681b88a11d 100644 (file)
@@ -3,7 +3,7 @@
 #include "futils.h"
 #include <ctype.h>
 
-static git_buf path = GIT_BUF_INIT;
+static git_str path = GIT_STR_INIT;
 
 void test_repo_config__initialize(void)
 {
@@ -11,24 +11,23 @@ void test_repo_config__initialize(void)
        cl_git_pass(cl_rename(
                "empty_standard_repo/.gitted", "empty_standard_repo/.git"));
 
-       git_buf_clear(&path);
+       git_str_clear(&path);
 
        cl_must_pass(p_mkdir("alternate", 0777));
-       cl_git_pass(git_path_prettify(&path, "alternate", NULL));
+       cl_git_pass(git_fs_path_prettify(&path, "alternate", NULL));
 }
 
 void test_repo_config__cleanup(void)
 {
        cl_sandbox_set_search_path_defaults();
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        cl_git_pass(
                git_futils_rmdir_r("alternate", NULL, GIT_RMDIR_REMOVE_FILES));
-       cl_assert(!git_path_isdir("alternate"));
+       cl_assert(!git_fs_path_isdir("alternate"));
 
        cl_fixture_cleanup("empty_standard_repo");
-
 }
 
 void test_repo_config__can_open_global_when_there_is_no_file(void)
@@ -60,7 +59,7 @@ void test_repo_config__can_open_missing_global_with_separators(void)
        git_repository *repo;
        git_config *config, *global;
 
-       cl_git_pass(git_buf_printf(
+       cl_git_pass(git_str_printf(
                &path, "%c%s", GIT_PATH_LIST_SEPARATOR, "dummy"));
 
        cl_git_pass(git_libgit2_opts(
@@ -70,7 +69,7 @@ void test_repo_config__can_open_missing_global_with_separators(void)
        cl_git_pass(git_libgit2_opts(
                GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
        cl_git_pass(git_repository_config(&config, repo));
@@ -101,7 +100,7 @@ void test_repo_config__read_with_no_configs_at_all(void)
        /* with none */
 
        cl_must_pass(p_unlink("empty_standard_repo/.git/config"));
-       cl_assert(!git_path_isfile("empty_standard_repo/.git/config"));
+       cl_assert(!git_fs_path_isfile("empty_standard_repo/.git/config"));
 
        cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
        git_repository__configmap_lookup_cache_clear(repo);
@@ -115,7 +114,7 @@ void test_repo_config__read_with_no_configs_at_all(void)
        cl_sandbox_set_search_path_defaults();
 
        cl_must_pass(p_mkdir("alternate/1", 0777));
-       cl_git_pass(git_buf_joinpath(&path, path.ptr, "1"));
+       cl_git_pass(git_str_joinpath(&path, path.ptr, "1"));
        cl_git_rewritefile("alternate/1/gitconfig", "[core]\n\tabbrev = 10\n");
        cl_git_pass(git_libgit2_opts(
                GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr));
@@ -177,16 +176,16 @@ void test_repo_config__read_with_no_configs_at_all(void)
        cl_assert_equal_i(40, val);
 
        cl_must_pass(p_unlink("empty_standard_repo/.git/config"));
-       cl_assert(!git_path_isfile("empty_standard_repo/.git/config"));
+       cl_assert(!git_fs_path_isfile("empty_standard_repo/.git/config"));
 
        cl_must_pass(p_unlink("alternate/1/gitconfig"));
-       cl_assert(!git_path_isfile("alternate/1/gitconfig"));
+       cl_assert(!git_fs_path_isfile("alternate/1/gitconfig"));
 
        cl_must_pass(p_unlink("alternate/2/config"));
-       cl_assert(!git_path_isfile("alternate/2/config"));
+       cl_assert(!git_fs_path_isfile("alternate/2/config"));
 
        cl_must_pass(p_unlink("alternate/3/.gitconfig"));
-       cl_assert(!git_path_isfile("alternate/3/.gitconfig"));
+       cl_assert(!git_fs_path_isfile("alternate/3/.gitconfig"));
 
        git_repository__configmap_lookup_cache_clear(repo);
        val = -1;
@@ -196,8 +195,8 @@ void test_repo_config__read_with_no_configs_at_all(void)
 
        /* reopen */
 
-       cl_assert(!git_path_isfile("empty_standard_repo/.git/config"));
-       cl_assert(!git_path_isfile("alternate/3/.gitconfig"));
+       cl_assert(!git_fs_path_isfile("empty_standard_repo/.git/config"));
+       cl_assert(!git_fs_path_isfile("alternate/3/.gitconfig"));
 
        cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
        git_repository__configmap_lookup_cache_clear(repo);
@@ -206,6 +205,6 @@ void test_repo_config__read_with_no_configs_at_all(void)
        cl_assert_equal_i(7, val);
        git_repository_free(repo);
 
-       cl_assert(!git_path_exists("empty_standard_repo/.git/config"));
-       cl_assert(!git_path_exists("alternate/3/.gitconfig"));
+       cl_assert(!git_fs_path_exists("empty_standard_repo/.git/config"));
+       cl_assert(!git_fs_path_exists("alternate/3/.gitconfig"));
 }
index c026eefc3100366c34c6d2a190b3de6199eb3ef1..523fdf8e39500d82b6ef1b3ed6826da0299e82ee 100644 (file)
@@ -28,16 +28,17 @@ static void ensure_repository_discover(const char *start_path,
                                       const char *ceiling_dirs,
                                       const char *expected_path)
 {
-       git_buf found_path = GIT_BUF_INIT, resolved = GIT_BUF_INIT;
+       git_buf found_path = GIT_BUF_INIT;
+       git_str resolved = GIT_STR_INIT;
 
-       git_buf_attach(&resolved, p_realpath(expected_path, NULL), 0);
+       git_str_attach(&resolved, p_realpath(expected_path, NULL), 0);
        cl_assert(resolved.size > 0);
-       cl_git_pass(git_path_to_dir(&resolved));
+       cl_git_pass(git_fs_path_to_dir(&resolved));
        cl_git_pass(git_repository_discover(&found_path, start_path, 1, ceiling_dirs));
 
        cl_assert_equal_s(found_path.ptr, resolved.ptr);
 
-       git_buf_dispose(&resolved);
+       git_str_dispose(&resolved);
        git_buf_dispose(&found_path);
 }
 
@@ -46,7 +47,7 @@ static void write_file(const char *path, const char *content)
        git_file file;
        int error;
 
-       if (git_path_exists(path)) {
+       if (git_fs_path_exists(path)) {
                cl_git_pass(p_unlink(path));
        }
 
@@ -59,24 +60,24 @@ static void write_file(const char *path, const char *content)
 }
 
 /*no check is performed on ceiling_dirs length, so be sure it's long enough */
-static void append_ceiling_dir(git_buf *ceiling_dirs, const char *path)
+static void append_ceiling_dir(git_str *ceiling_dirs, const char *path)
 {
-       git_buf pretty_path = GIT_BUF_INIT;
+       git_str pretty_path = GIT_STR_INIT;
        char ceiling_separator[2] = { GIT_PATH_LIST_SEPARATOR, '\0' };
 
-       cl_git_pass(git_path_prettify_dir(&pretty_path, path, NULL));
+       cl_git_pass(git_fs_path_prettify_dir(&pretty_path, path, NULL));
 
        if (ceiling_dirs->size > 0)
-               git_buf_puts(ceiling_dirs, ceiling_separator);
+               git_str_puts(ceiling_dirs, ceiling_separator);
 
-       git_buf_puts(ceiling_dirs, pretty_path.ptr);
+       git_str_puts(ceiling_dirs, pretty_path.ptr);
 
-       git_buf_dispose(&pretty_path);
-       cl_assert(git_buf_oom(ceiling_dirs) == 0);
+       git_str_dispose(&pretty_path);
+       cl_assert(git_str_oom(ceiling_dirs) == 0);
 }
 
 static git_buf discovered;
-static git_buf ceiling_dirs;
+static git_str ceiling_dirs;
 
 void test_repo_discover__initialize(void)
 {
@@ -84,8 +85,7 @@ void test_repo_discover__initialize(void)
        const mode_t mode = 0777;
        git_futils_mkdir_r(DISCOVER_FOLDER, mode);
 
-       git_buf_init(&discovered, 0);
-       git_buf_init(&ceiling_dirs, 0);
+       git_str_init(&ceiling_dirs, 0);
        append_ceiling_dir(&ceiling_dirs, TEMP_REPO_FOLDER);
 
        cl_git_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1));
@@ -115,7 +115,7 @@ void test_repo_discover__initialize(void)
 void test_repo_discover__cleanup(void)
 {
        git_buf_dispose(&discovered);
-       git_buf_dispose(&ceiling_dirs);
+       git_str_dispose(&ceiling_dirs);
        cl_git_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, NULL, GIT_RMDIR_REMOVE_FILES));
 }
 
index 43defc168a30bf862e651a91ef2d48021e6d7e51..e3e522480f287adbbbc8ca9f8f10647404b4c491 100644 (file)
@@ -24,11 +24,11 @@ void test_repo_env__cleanup(void)
 {
        cl_git_sandbox_cleanup();
 
-       if (git_path_isdir("attr"))
+       if (git_fs_path_isdir("attr"))
                git_futils_rmdir_r("attr", NULL, GIT_RMDIR_REMOVE_FILES);
-       if (git_path_isdir("testrepo.git"))
+       if (git_fs_path_isdir("testrepo.git"))
                git_futils_rmdir_r("testrepo.git", NULL, GIT_RMDIR_REMOVE_FILES);
-       if (git_path_isdir("peeled.git"))
+       if (git_fs_path_isdir("peeled.git"))
                git_futils_rmdir_r("peeled.git", NULL, GIT_RMDIR_REMOVE_FILES);
 
        clear_git_env();
@@ -38,14 +38,14 @@ static int GIT_FORMAT_PRINTF(2, 3) cl_setenv_printf(const char *name, const char
 {
        int ret;
        va_list args;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        va_start(args, fmt);
-       cl_git_pass(git_buf_vprintf(&buf, fmt, args));
+       cl_git_pass(git_str_vprintf(&buf, fmt, args));
        va_end(args);
 
-       ret = cl_setenv(name, git_buf_cstr(&buf));
-       git_buf_dispose(&buf);
+       ret = cl_setenv(name, git_str_cstr(&buf));
+       git_str_dispose(&buf);
        return ret;
 }
 
@@ -80,12 +80,12 @@ static void env_cd_(
        void (*passfail_)(const char *, const char *, const char *, int),
        const char *file, const char *func, int line)
 {
-       git_buf cwd_buf = GIT_BUF_INIT;
-       cl_git_pass(git_path_prettify_dir(&cwd_buf, ".", NULL));
+       git_str cwd_buf = GIT_STR_INIT;
+       cl_git_pass(git_fs_path_prettify_dir(&cwd_buf, ".", NULL));
        cl_must_pass(p_chdir(path));
        passfail_(NULL, file, func, line);
-       cl_must_pass(p_chdir(git_buf_cstr(&cwd_buf)));
-       git_buf_dispose(&cwd_buf);
+       cl_must_pass(p_chdir(git_str_cstr(&cwd_buf)));
+       git_str_dispose(&cwd_buf);
 }
 #define env_cd_pass(path) env_cd_((path), env_pass_, __FILE__, __func__, __LINE__)
 #define env_cd_fail(path) env_cd_((path), env_fail_, __FILE__, __func__, __LINE__)
@@ -128,7 +128,7 @@ static void env_check_objects_(bool a, bool t, bool p, const char *file, const c
 void test_repo_env__open(void)
 {
        git_repository *repo = NULL;
-       git_buf repo_dir_buf = GIT_BUF_INIT;
+       git_str repo_dir_buf = GIT_STR_INIT;
        const char *repo_dir = NULL;
        git_index *index = NULL;
        const char *t_obj = "testrepo.git/objects";
@@ -141,8 +141,8 @@ void test_repo_env__open(void)
        cl_fixture_sandbox("peeled.git");
        cl_git_pass(p_rename("attr/.gitted", "attr/.git"));
 
-       cl_git_pass(git_path_prettify_dir(&repo_dir_buf, "attr", NULL));
-       repo_dir = git_buf_cstr(&repo_dir_buf);
+       cl_git_pass(git_fs_path_prettify_dir(&repo_dir_buf, "attr", NULL));
+       repo_dir = git_str_cstr(&repo_dir_buf);
 
        /* GIT_DIR that doesn't exist */
        cl_setenv("GIT_DIR", "does-not-exist");
@@ -271,7 +271,7 @@ void test_repo_env__open(void)
        cl_fixture_cleanup("testrepo.git");
        cl_fixture_cleanup("attr");
 
-       git_buf_dispose(&repo_dir_buf);
+       git_str_dispose(&repo_dir_buf);
 
        clear_git_env();
 }
index bffb51bb56b839776c34e9677b83f3298502af98..e23bb77f98a8892c1ee9d342f48c0dae4edb0c28 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 
 static git_repository *_repo;
 
@@ -18,14 +17,14 @@ void test_repo_hashfile__cleanup(void)
 void test_repo_hashfile__simple(void)
 {
        git_oid a, b;
-       git_buf full = GIT_BUF_INIT;
+       git_str full = GIT_STR_INIT;
 
        /* hash with repo relative path */
        cl_git_pass(git_odb_hashfile(&a, "status/current_file", GIT_OBJECT_BLOB));
        cl_git_pass(git_repository_hashfile(&b, _repo, "current_file", GIT_OBJECT_BLOB, NULL));
        cl_assert_equal_oid(&a, &b);
 
-       cl_git_pass(git_buf_joinpath(&full, git_repository_workdir(_repo), "current_file"));
+       cl_git_pass(git_str_joinpath(&full, git_repository_workdir(_repo), "current_file"));
 
        /* hash with full path */
        cl_git_pass(git_odb_hashfile(&a, full.ptr, GIT_OBJECT_BLOB));
@@ -36,20 +35,20 @@ void test_repo_hashfile__simple(void)
        cl_git_fail(git_odb_hashfile(&a, full.ptr, GIT_OBJECT_ANY));
        cl_git_fail(git_repository_hashfile(&b, _repo, full.ptr, GIT_OBJECT_OFS_DELTA, NULL));
 
-       git_buf_dispose(&full);
+       git_str_dispose(&full);
 }
 
 void test_repo_hashfile__filtered_in_workdir(void)
 {
-       git_buf root = GIT_BUF_INIT, txt = GIT_BUF_INIT, bin = GIT_BUF_INIT;
+       git_str root = GIT_STR_INIT, txt = GIT_STR_INIT, bin = GIT_STR_INIT;
        char cwd[GIT_PATH_MAX];
        git_oid a, b;
 
        cl_must_pass(p_getcwd(cwd, GIT_PATH_MAX));
        cl_must_pass(p_mkdir("absolute", 0777));
-       cl_git_pass(git_buf_joinpath(&root, cwd, "status"));
-       cl_git_pass(git_buf_joinpath(&txt, root.ptr, "testfile.txt"));
-       cl_git_pass(git_buf_joinpath(&bin, root.ptr, "testfile.bin"));
+       cl_git_pass(git_str_joinpath(&root, cwd, "status"));
+       cl_git_pass(git_str_joinpath(&txt, root.ptr, "testfile.txt"));
+       cl_git_pass(git_str_joinpath(&bin, root.ptr, "testfile.bin"));
 
        cl_repo_set_bool(_repo, "core.autocrlf", true);
 
@@ -120,22 +119,22 @@ void test_repo_hashfile__filtered_in_workdir(void)
        cl_git_fail(git_odb_hashfile(&a, "status/testfile.txt", 0));
        cl_git_fail(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJECT_ANY, NULL));
 
-       git_buf_dispose(&txt);
-       git_buf_dispose(&bin);
-       git_buf_dispose(&root);
+       git_str_dispose(&txt);
+       git_str_dispose(&bin);
+       git_str_dispose(&root);
 }
 
 void test_repo_hashfile__filtered_outside_workdir(void)
 {
-       git_buf root = GIT_BUF_INIT, txt = GIT_BUF_INIT, bin = GIT_BUF_INIT;
+       git_str root = GIT_STR_INIT, txt = GIT_STR_INIT, bin = GIT_STR_INIT;
        char cwd[GIT_PATH_MAX];
        git_oid a, b;
 
        cl_must_pass(p_getcwd(cwd, GIT_PATH_MAX));
        cl_must_pass(p_mkdir("absolute", 0777));
-       cl_git_pass(git_buf_joinpath(&root, cwd, "absolute"));
-       cl_git_pass(git_buf_joinpath(&txt, root.ptr, "testfile.txt"));
-       cl_git_pass(git_buf_joinpath(&bin, root.ptr, "testfile.bin"));
+       cl_git_pass(git_str_joinpath(&root, cwd, "absolute"));
+       cl_git_pass(git_str_joinpath(&txt, root.ptr, "testfile.txt"));
+       cl_git_pass(git_str_joinpath(&bin, root.ptr, "testfile.bin"));
 
        cl_repo_set_bool(_repo, "core.autocrlf", true);
        cl_git_append2file("status/.gitattributes", "*.txt text\n*.bin binary\n\n");
@@ -166,7 +165,7 @@ void test_repo_hashfile__filtered_outside_workdir(void)
        cl_git_pass(git_repository_hashfile(&b, _repo, bin.ptr, GIT_OBJECT_BLOB, NULL));
        cl_assert_equal_oid(&a, &b);
 
-       git_buf_dispose(&txt);
-       git_buf_dispose(&bin);
-       git_buf_dispose(&root);
+       git_str_dispose(&txt);
+       git_str_dispose(&bin);
+       git_str_dispose(&root);
 }
index 1aa326f7f0137c5e17bd86d0f8875cdab0d1bf9a..7cf6742cad8691b26f07aa7ab00beedf29a778a8 100644 (file)
@@ -12,7 +12,7 @@ enum repo_mode {
 };
 
 static git_repository *g_repo = NULL;
-static git_buf g_global_path = GIT_BUF_INIT;
+static git_str g_global_path = GIT_STR_INIT;
 
 void test_repo_init__initialize(void)
 {
@@ -26,7 +26,7 @@ void test_repo_init__cleanup(void)
 {
        git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL,
                g_global_path.ptr);
-       git_buf_dispose(&g_global_path);
+       git_str_dispose(&g_global_path);
 
        cl_fixture_cleanup("tmp_global_path");
 }
@@ -47,7 +47,7 @@ static void ensure_repository_init(
 {
        const char *workdir;
 
-       cl_assert(!git_path_isdir(working_directory));
+       cl_assert(!git_fs_path_isdir(working_directory));
 
        cl_git_pass(git_repository_init(&g_repo, working_directory, is_bare));
 
@@ -100,16 +100,16 @@ void test_repo_init__bare_repo_noslash(void)
 
 void test_repo_init__bare_repo_escaping_current_workdir(void)
 {
-       git_buf path_repository = GIT_BUF_INIT;
-       git_buf path_current_workdir = GIT_BUF_INIT;
+       git_str path_repository = GIT_STR_INIT;
+       git_str path_current_workdir = GIT_STR_INIT;
 
-       cl_git_pass(git_path_prettify_dir(&path_current_workdir, ".", NULL));
+       cl_git_pass(git_fs_path_prettify_dir(&path_current_workdir, ".", NULL));
 
-       cl_git_pass(git_buf_joinpath(&path_repository, git_buf_cstr(&path_current_workdir), "a/b/c"));
-       cl_git_pass(git_futils_mkdir_r(git_buf_cstr(&path_repository), GIT_DIR_MODE));
+       cl_git_pass(git_str_joinpath(&path_repository, git_str_cstr(&path_current_workdir), "a/b/c"));
+       cl_git_pass(git_futils_mkdir_r(git_str_cstr(&path_repository), GIT_DIR_MODE));
 
        /* Change the current working directory */
-       cl_git_pass(chdir(git_buf_cstr(&path_repository)));
+       cl_git_pass(chdir(git_str_cstr(&path_repository)));
 
        /* Initialize a bare repo with a relative path escaping out of the current working directory */
        cl_git_pass(git_repository_init(&g_repo, "../d/e.git", 1));
@@ -121,10 +121,10 @@ void test_repo_init__bare_repo_escaping_current_workdir(void)
        /* Open a bare repo with a relative path escaping out of the current working directory */
        cl_git_pass(git_repository_open(&g_repo, "../d/e.git"));
 
-       cl_git_pass(chdir(git_buf_cstr(&path_current_workdir)));
+       cl_git_pass(chdir(git_str_cstr(&path_current_workdir)));
 
-       git_buf_dispose(&path_current_workdir);
-       git_buf_dispose(&path_repository);
+       git_str_dispose(&path_current_workdir);
+       git_str_dispose(&path_repository);
 
        cleanup_repository("a");
 }
@@ -168,26 +168,26 @@ void test_repo_init__reinit_too_recent_bare_repo(void)
 
 void test_repo_init__additional_templates(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        cl_set_cleanup(&cleanup_repository, "tester");
 
        ensure_repository_init("tester", 0, "tester/.git/", "tester/");
 
        cl_git_pass(
-               git_buf_joinpath(&path, git_repository_path(g_repo), "description"));
-       cl_assert(git_path_isfile(git_buf_cstr(&path)));
+               git_str_joinpath(&path, git_repository_path(g_repo), "description"));
+       cl_assert(git_fs_path_isfile(git_str_cstr(&path)));
 
        cl_git_pass(
-               git_buf_joinpath(&path, git_repository_path(g_repo), "info/exclude"));
-       cl_assert(git_path_isfile(git_buf_cstr(&path)));
+               git_str_joinpath(&path, git_repository_path(g_repo), "info/exclude"));
+       cl_assert(git_fs_path_isfile(git_str_cstr(&path)));
 
        cl_git_pass(
-               git_buf_joinpath(&path, git_repository_path(g_repo), "hooks"));
-       cl_assert(git_path_isdir(git_buf_cstr(&path)));
+               git_str_joinpath(&path, git_repository_path(g_repo), "hooks"));
+       cl_assert(git_fs_path_isdir(git_str_cstr(&path)));
        /* won't confirm specific contents of hooks dir since it may vary */
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 static void assert_config_entry_on_init_bytype(
@@ -257,7 +257,7 @@ void test_repo_init__symlinks_win32_enabled_by_global_config(void)
        git_config *config, *repo_config;
        int val;
 
-       if (!git_path_supports_symlinks("link"))
+       if (!git_fs_path_supports_symlinks("link"))
                cl_skip();
 
        create_tmp_global_config("tmp_global_config", "core.symlinks", "true");
@@ -303,7 +303,7 @@ void test_repo_init__symlinks_posix_detected(void)
        cl_skip();
 #else
        assert_config_entry_on_init(
-           "core.symlinks", git_path_supports_symlinks("link") ? GIT_ENOTFOUND : false);
+           "core.symlinks", git_fs_path_supports_symlinks("link") ? GIT_ENOTFOUND : false);
 #endif
 }
 
@@ -418,12 +418,12 @@ void test_repo_init__extended_1(void)
 
        cl_assert(!git__suffixcmp(git_repository_workdir(g_repo), "/c_wd/"));
        cl_assert(!git__suffixcmp(git_repository_path(g_repo), "/c.git/"));
-       cl_assert(git_path_isfile("root/b/c_wd/.git"));
+       cl_assert(git_fs_path_isfile("root/b/c_wd/.git"));
        cl_assert(!git_repository_is_bare(g_repo));
        /* repo will not be counted as empty because we set head to "development" */
        cl_assert(!git_repository_is_empty(g_repo));
 
-       cl_git_pass(git_path_lstat(git_repository_path(g_repo), &st));
+       cl_git_pass(git_fs_path_lstat(git_repository_path(g_repo), &st));
        cl_assert(S_ISDIR(st.st_mode));
        if (cl_is_chmod_supported())
                cl_assert((S_ISGID & st.st_mode) == S_ISGID);
@@ -447,7 +447,7 @@ void test_repo_init__extended_1(void)
 void test_repo_init__relative_gitdir(void)
 {
        git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
-       git_buf dot_git_content = GIT_BUF_INIT;
+       git_str dot_git_content = GIT_STR_INIT;
 
        opts.workdir_path = "../c_wd";
        opts.flags =
@@ -472,18 +472,18 @@ void test_repo_init__relative_gitdir(void)
        cl_git_pass(git_futils_readbuffer(&dot_git_content, "root/b/c_wd/.git"));
        cl_assert_equal_s("gitdir: ../my_repository/", dot_git_content.ptr);
 
-       git_buf_dispose(&dot_git_content);
+       git_str_dispose(&dot_git_content);
        cleanup_repository("root");
 }
 
 void test_repo_init__relative_gitdir_2(void)
 {
        git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
-       git_buf dot_git_content = GIT_BUF_INIT;
-       git_buf full_path = GIT_BUF_INIT;
+       git_str dot_git_content = GIT_STR_INIT;
+       git_str full_path = GIT_STR_INIT;
 
-       cl_git_pass(git_path_prettify(&full_path, ".", NULL));
-       cl_git_pass(git_buf_joinpath(&full_path, full_path.ptr, "root/b/c_wd"));
+       cl_git_pass(git_fs_path_prettify(&full_path, ".", NULL));
+       cl_git_pass(git_str_joinpath(&full_path, full_path.ptr, "root/b/c_wd"));
 
        opts.workdir_path = full_path.ptr;
        opts.flags =
@@ -493,7 +493,7 @@ void test_repo_init__relative_gitdir_2(void)
 
        /* make the directory first, then it should succeed */
        cl_git_pass(git_repository_init_ext(&g_repo, "root/b/my_repository", &opts));
-       git_buf_dispose(&full_path);
+       git_str_dispose(&full_path);
 
        cl_assert(!git__suffixcmp(git_repository_workdir(g_repo), "root/b/c_wd/"));
        cl_assert(!git__suffixcmp(git_repository_path(g_repo), "root/b/my_repository/"));
@@ -509,7 +509,7 @@ void test_repo_init__relative_gitdir_2(void)
        cl_git_pass(git_futils_readbuffer(&dot_git_content, "root/b/c_wd/.git"));
        cl_assert_equal_s("gitdir: ../my_repository/", dot_git_content.ptr);
 
-       git_buf_dispose(&dot_git_content);
+       git_str_dispose(&dot_git_content);
        cleanup_repository("root");
 }
 
@@ -598,25 +598,25 @@ void test_repo_init__at_filesystem_root(void)
 {
        git_repository *repo;
        const char *sandbox = clar_sandbox_path();
-       git_buf root = GIT_BUF_INIT;
+       git_str root = GIT_STR_INIT;
        int root_len;
 
        if (!cl_is_env_set("GITTEST_INVASIVE_FS_STRUCTURE"))
                cl_skip();
 
-       root_len = git_path_root(sandbox);
+       root_len = git_fs_path_root(sandbox);
        cl_assert(root_len >= 0);
 
-       git_buf_put(&root, sandbox, root_len+1);
-       git_buf_joinpath(&root, root.ptr, "libgit2_test_dir");
+       git_str_put(&root, sandbox, root_len+1);
+       git_str_joinpath(&root, root.ptr, "libgit2_test_dir");
 
-       cl_assert(!git_path_exists(root.ptr));
+       cl_assert(!git_fs_path_exists(root.ptr));
 
        cl_git_pass(git_repository_init(&repo, root.ptr, 0));
-       cl_assert(git_path_isdir(root.ptr));
+       cl_assert(git_fs_path_isdir(root.ptr));
        cl_git_pass(git_futils_rmdir_r(root.ptr, NULL, GIT_RMDIR_REMOVE_FILES));
 
-       git_buf_dispose(&root);
+       git_str_dispose(&root);
        git_repository_free(repo);
 }
 
@@ -710,29 +710,29 @@ void test_repo_init__longpath(void)
 #ifdef GIT_WIN32
        size_t padding = CONST_STRLEN("objects/pack/pack-.pack.lock") + GIT_OID_HEXSZ;
        size_t max, i;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_repository *one = NULL, *two = NULL;
 
        /*
         * Files within repositories need to fit within MAX_PATH;
         * that means a repo path must be at most (MAX_PATH - 18).
         */
-       cl_git_pass(git_buf_puts(&path, clar_sandbox_path()));
-       cl_git_pass(git_buf_putc(&path, '/'));
+       cl_git_pass(git_str_puts(&path, clar_sandbox_path()));
+       cl_git_pass(git_str_putc(&path, '/'));
 
        max = ((MAX_PATH) - path.size) - padding;
 
        for (i = 0; i < max - 1; i++)
-               cl_git_pass(git_buf_putc(&path, 'a'));
+               cl_git_pass(git_str_putc(&path, 'a'));
 
        cl_git_pass(git_repository_init(&one, path.ptr, 1));
 
        /* Paths longer than this are rejected */
-       cl_git_pass(git_buf_putc(&path, 'z'));
+       cl_git_pass(git_str_putc(&path, 'z'));
        cl_git_fail(git_repository_init(&two, path.ptr, 1));
 
        git_repository_free(one);
        git_repository_free(two);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 #endif
 }
index 14577c8f0e82f3513fed8c038c7f7d0b4bae3068..6241f48f95f9a5aced3afc3906bd0e74483c78de 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "refs.h"
 #include "posix.h"
 
@@ -23,17 +22,18 @@ void test_repo_message__none(void)
 
 void test_repo_message__message(void)
 {
-       git_buf path = GIT_BUF_INIT, actual = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
+       git_buf actual = GIT_BUF_INIT;
        const char expected[] = "Test\n\nThis is a test of the emergency broadcast system\n";
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_path(_repo), "MERGE_MSG"));
-       cl_git_mkfile(git_buf_cstr(&path), expected);
+       cl_git_pass(git_str_joinpath(&path, git_repository_path(_repo), "MERGE_MSG"));
+       cl_git_mkfile(git_str_cstr(&path), expected);
 
        cl_git_pass(git_repository_message(&actual, _repo));
-       cl_assert_equal_s(expected, git_buf_cstr(&actual));
+       cl_assert_equal_s(expected, actual.ptr);
        git_buf_dispose(&actual);
 
-       cl_git_pass(p_unlink(git_buf_cstr(&path)));
+       cl_git_pass(p_unlink(git_str_cstr(&path)));
        cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(&actual, _repo));
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
index bd60c12c29b2834e3aff442433bf694485a2b5b2..4b6609a81e14c896c481d31ba3d627831673d8c2 100644 (file)
@@ -3,13 +3,30 @@
 #include "sysdir.h"
 #include <ctype.h>
 
+static int validate_ownership = 0;
+static git_buf config_path = GIT_BUF_INIT;
+
+void test_repo_open__initialize(void)
+{
+       cl_git_pass(git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &config_path));
+       cl_git_pass(git_libgit2_opts(GIT_OPT_GET_OWNER_VALIDATION, &validate_ownership));
+}
 
 void test_repo_open__cleanup(void)
 {
        cl_git_sandbox_cleanup();
+       cl_fixture_cleanup("empty_standard_repo");
+       cl_fixture_cleanup("__global_config");
 
-       if (git_path_isdir("alternate"))
+       if (git_fs_path_isdir("alternate"))
                git_futils_rmdir_r("alternate", NULL, GIT_RMDIR_REMOVE_FILES);
+
+       git_fs_path__set_owner(GIT_FS_PATH_MOCK_OWNER_NONE);
+
+       cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, config_path.ptr));
+       git_buf_dispose(&config_path);
+
+       cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, validate_ownership));
 }
 
 void test_repo_open__bare_empty_repo(void)
@@ -105,12 +122,12 @@ void test_repo_open__check_if_repository(void)
 
 static void make_gitlink_dir(const char *dir, const char *linktext)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        cl_git_pass(git_futils_mkdir(dir, 0777, GIT_MKDIR_VERIFY_DIR));
-       cl_git_pass(git_buf_joinpath(&path, dir, ".git"));
+       cl_git_pass(git_str_joinpath(&path, dir, ".git"));
        cl_git_rewritefile(path.ptr, linktext);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_repo_open__gitlinked(void)
@@ -136,7 +153,7 @@ void test_repo_open__gitlinked(void)
 void test_repo_open__with_symlinked_config(void)
 {
 #ifndef GIT_WIN32
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_repository *repo;
        git_config *cfg;
        int32_t value;
@@ -147,7 +164,7 @@ void test_repo_open__with_symlinked_config(void)
        cl_git_pass(git_futils_mkdir_r("home", 0777));
        cl_git_mkfile("home/.gitconfig.linked", "[global]\ntest = 4567\n");
        cl_must_pass(symlink(".gitconfig.linked", "home/.gitconfig"));
-       cl_git_pass(git_path_prettify(&path, "home", NULL));
+       cl_git_pass(git_fs_path_prettify(&path, "home", NULL));
        cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr));
 
        cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
@@ -157,9 +174,9 @@ void test_repo_open__with_symlinked_config(void)
 
        git_config_free(cfg);
        git_repository_free(repo);
-       cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES));
+       cl_git_pass(git_futils_rmdir_r(git_str_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES));
        cl_sandbox_set_search_path_defaults();
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 #endif
 }
 
@@ -173,7 +190,7 @@ void test_repo_open__from_git_new_workdir(void)
         */
 
        git_repository *repo2;
-       git_buf link_tgt = GIT_BUF_INIT, link = GIT_BUF_INIT, body = GIT_BUF_INIT;
+       git_str link_tgt = GIT_STR_INIT, link = GIT_STR_INIT, body = GIT_STR_INIT;
        const char **scan;
        int link_fd;
        static const char *links[] = {
@@ -190,19 +207,19 @@ void test_repo_open__from_git_new_workdir(void)
        cl_git_pass(p_mkdir("alternate/.git", 0777));
 
        for (scan = links; *scan != NULL; scan++) {
-               git_buf_joinpath(&link_tgt, "empty_standard_repo/.git", *scan);
-               if (git_path_exists(link_tgt.ptr)) {
-                       git_buf_joinpath(&link_tgt, "../../empty_standard_repo/.git", *scan);
-                       git_buf_joinpath(&link, "alternate/.git", *scan);
+               git_str_joinpath(&link_tgt, "empty_standard_repo/.git", *scan);
+               if (git_fs_path_exists(link_tgt.ptr)) {
+                       git_str_joinpath(&link_tgt, "../../empty_standard_repo/.git", *scan);
+                       git_str_joinpath(&link, "alternate/.git", *scan);
                        if (strchr(*scan, '/'))
                                git_futils_mkpath2file(link.ptr, 0777);
                        cl_assert_(symlink(link_tgt.ptr, link.ptr) == 0, strerror(errno));
                }
        }
        for (scan = copies; *scan != NULL; scan++) {
-               git_buf_joinpath(&link_tgt, "empty_standard_repo/.git", *scan);
-               if (git_path_exists(link_tgt.ptr)) {
-                       git_buf_joinpath(&link, "alternate/.git", *scan);
+               git_str_joinpath(&link_tgt, "empty_standard_repo/.git", *scan);
+               if (git_fs_path_exists(link_tgt.ptr)) {
+                       git_str_joinpath(&link, "alternate/.git", *scan);
                        cl_git_pass(git_futils_readbuffer(&body, link_tgt.ptr));
 
                        cl_assert((link_fd = git_futils_creat_withpath(link.ptr, 0777, 0666)) >= 0);
@@ -211,9 +228,9 @@ void test_repo_open__from_git_new_workdir(void)
                }
        }
 
-       git_buf_dispose(&link_tgt);
-       git_buf_dispose(&link);
-       git_buf_dispose(&body);
+       git_str_dispose(&link_tgt);
+       git_str_dispose(&link);
+       git_str_dispose(&body);
 
 
        cl_git_pass(git_repository_open(&repo2, "alternate"));
@@ -233,10 +250,10 @@ void test_repo_open__from_git_new_workdir(void)
 void test_repo_open__failures(void)
 {
        git_repository *base, *repo;
-       git_buf ceiling = GIT_BUF_INIT;
+       git_str ceiling = GIT_STR_INIT;
 
        base = cl_git_sandbox_init("attr");
-       cl_git_pass(git_buf_sets(&ceiling, git_repository_workdir(base)));
+       cl_git_pass(git_str_sets(&ceiling, git_repository_workdir(base)));
 
        /* fail with no searching */
        cl_git_fail(git_repository_open(&repo, "attr/sub"));
@@ -245,7 +262,7 @@ void test_repo_open__failures(void)
 
        /* fail with ceiling too low */
        cl_git_fail(git_repository_open_ext(&repo, "attr/sub", 0, ceiling.ptr));
-       cl_git_pass(git_buf_joinpath(&ceiling, ceiling.ptr, "sub"));
+       cl_git_pass(git_str_joinpath(&ceiling, ceiling.ptr, "sub"));
        cl_git_fail(git_repository_open_ext(&repo, "attr/sub/sub", 0, ceiling.ptr));
 
        /* fail with no repo */
@@ -260,7 +277,7 @@ void test_repo_open__failures(void)
                GIT_REPOSITORY_OPEN_NO_SEARCH | GIT_REPOSITORY_OPEN_NO_DOTGIT,
                NULL));
 
-       git_buf_dispose(&ceiling);
+       git_str_dispose(&ceiling);
 }
 
 void test_repo_open__bad_gitlinks(void)
@@ -291,7 +308,7 @@ void test_repo_open__bad_gitlinks(void)
 }
 
 #ifdef GIT_WIN32
-static void unposix_path(git_buf *path)
+static void unposix_path(git_str *path)
 {
        char *src, *tgt;
 
@@ -318,44 +335,44 @@ void test_repo_open__win32_path(void)
 {
 #ifdef GIT_WIN32
        git_repository *repo = cl_git_sandbox_init("empty_standard_repo"), *repo2;
-       git_buf winpath = GIT_BUF_INIT;
+       git_str winpath = GIT_STR_INIT;
        static const char *repo_path = "empty_standard_repo/.git/";
        static const char *repo_wd   = "empty_standard_repo/";
 
        cl_assert(git__suffixcmp(git_repository_path(repo), repo_path) == 0);
        cl_assert(git__suffixcmp(git_repository_workdir(repo), repo_wd) == 0);
 
-       cl_git_pass(git_buf_sets(&winpath, git_repository_path(repo)));
+       cl_git_pass(git_str_sets(&winpath, git_repository_path(repo)));
        unposix_path(&winpath);
        cl_git_pass(git_repository_open(&repo2, winpath.ptr));
        cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0);
        cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0);
        git_repository_free(repo2);
 
-       cl_git_pass(git_buf_sets(&winpath, git_repository_path(repo)));
-       git_buf_truncate(&winpath, winpath.size - 1); /* remove trailing '/' */
+       cl_git_pass(git_str_sets(&winpath, git_repository_path(repo)));
+       git_str_truncate(&winpath, winpath.size - 1); /* remove trailing '/' */
        unposix_path(&winpath);
        cl_git_pass(git_repository_open(&repo2, winpath.ptr));
        cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0);
        cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0);
        git_repository_free(repo2);
 
-       cl_git_pass(git_buf_sets(&winpath, git_repository_workdir(repo)));
+       cl_git_pass(git_str_sets(&winpath, git_repository_workdir(repo)));
        unposix_path(&winpath);
        cl_git_pass(git_repository_open(&repo2, winpath.ptr));
        cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0);
        cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0);
        git_repository_free(repo2);
 
-       cl_git_pass(git_buf_sets(&winpath, git_repository_workdir(repo)));
-       git_buf_truncate(&winpath, winpath.size - 1); /* remove trailing '/' */
+       cl_git_pass(git_str_sets(&winpath, git_repository_workdir(repo)));
+       git_str_truncate(&winpath, winpath.size - 1); /* remove trailing '/' */
        unposix_path(&winpath);
        cl_git_pass(git_repository_open(&repo2, winpath.ptr));
        cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0);
        cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0);
        git_repository_free(repo2);
 
-       git_buf_dispose(&winpath);
+       git_str_dispose(&winpath);
 #endif
 }
 
@@ -367,7 +384,7 @@ void test_repo_open__opening_a_non_existing_repository_returns_ENOTFOUND(void)
 
 void test_repo_open__no_config(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_repository *repo;
        git_config *config;
 
@@ -381,7 +398,7 @@ void test_repo_open__no_config(void)
 
        /* isolate from system level configs */
        cl_must_pass(p_mkdir("alternate", 0777));
-       cl_git_pass(git_path_prettify(&path, "alternate", NULL));
+       cl_git_pass(git_fs_path_prettify(&path, "alternate", NULL));
        cl_git_pass(git_libgit2_opts(
                GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr));
        cl_git_pass(git_libgit2_opts(
@@ -389,7 +406,7 @@ void test_repo_open__no_config(void)
        cl_git_pass(git_libgit2_opts(
                GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 
        cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
        cl_git_pass(git_repository_config(&config, repo));
@@ -453,3 +470,133 @@ void test_repo_open__force_bare(void)
        git_repository_free(barerepo);
 }
 
+void test_repo_open__validates_dir_ownership(void)
+{
+       git_repository *repo;
+
+       cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 1));
+
+       cl_fixture_sandbox("empty_standard_repo");
+       cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git"));
+
+       /* When the current user owns the repo config, that's acceptable */
+       git_fs_path__set_owner(GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
+       cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
+       git_repository_free(repo);
+
+       /* When the system user owns the repo config, fail */
+       git_fs_path__set_owner(GIT_FS_PATH_MOCK_OWNER_SYSTEM);
+       cl_git_fail(git_repository_open(&repo, "empty_standard_repo"));
+
+       /* When an unknown user owns the repo config, fail */
+       git_fs_path__set_owner(GIT_FS_PATH_MOCK_OWNER_OTHER);
+       cl_git_fail(git_repository_open(&repo, "empty_standard_repo"));
+}
+
+void test_repo_open__can_allowlist_dirs_with_problematic_ownership(void)
+{
+       git_repository *repo;
+       git_str config_path = GIT_STR_INIT,
+               config_filename = GIT_STR_INIT,
+               config_data = GIT_STR_INIT;
+
+       cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 1));
+
+       cl_fixture_sandbox("empty_standard_repo");
+       cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git"));
+
+       git_fs_path__set_owner(GIT_FS_PATH_MOCK_OWNER_OTHER);
+       cl_git_fail(git_repository_open(&repo, "empty_standard_repo"));
+
+       /* Add safe.directory options to the global configuration */
+       git_str_joinpath(&config_path, clar_sandbox_path(), "__global_config");
+       cl_must_pass(p_mkdir(config_path.ptr, 0777));
+       git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, config_path.ptr);
+
+       git_str_joinpath(&config_filename, config_path.ptr, ".gitconfig");
+
+       git_str_printf(&config_data,
+               "[foo]\n" \
+               "\tbar = Foobar\n" \
+               "\tbaz = Baz!\n" \
+               "[safe]\n" \
+               "\tdirectory = /non/existent/path\n" \
+               "\tdirectory = /\n" \
+               "\tdirectory = c:\\\\temp\n" \
+               "\tdirectory = %s/%s\n" \
+               "\tdirectory = /tmp\n" \
+               "[bar]\n" \
+               "\tfoo = barfoo\n",
+               clar_sandbox_path(), "empty_standard_repo");
+       cl_git_rewritefile(config_filename.ptr, config_data.ptr);
+
+       cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
+       git_repository_free(repo);
+
+       git_str_dispose(&config_path);
+       git_str_dispose(&config_filename);
+       git_str_dispose(&config_data);
+}
+
+void test_repo_open__can_reset_safe_directory_list(void)
+{
+       git_repository *repo;
+       git_str config_path = GIT_STR_INIT,
+               config_filename = GIT_STR_INIT,
+               config_data = GIT_STR_INIT;
+
+       cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 1));
+
+       cl_fixture_sandbox("empty_standard_repo");
+       cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git"));
+
+       git_fs_path__set_owner(GIT_FS_PATH_MOCK_OWNER_OTHER);
+       cl_git_fail(git_repository_open(&repo, "empty_standard_repo"));
+
+       /* Add safe.directory options to the global configuration */
+       git_str_joinpath(&config_path, clar_sandbox_path(), "__global_config");
+       cl_must_pass(p_mkdir(config_path.ptr, 0777));
+       git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, config_path.ptr);
+
+       git_str_joinpath(&config_filename, config_path.ptr, ".gitconfig");
+
+       /* The blank resets our sandbox directory and opening fails */
+
+       git_str_printf(&config_data,
+               "[foo]\n" \
+               "\tbar = Foobar\n" \
+               "\tbaz = Baz!\n" \
+               "[safe]\n" \
+               "\tdirectory = %s/%s\n" \
+               "\tdirectory = \n" \
+               "\tdirectory = /tmp\n" \
+               "[bar]\n" \
+               "\tfoo = barfoo\n",
+               clar_sandbox_path(), "empty_standard_repo");
+       cl_git_rewritefile(config_filename.ptr, config_data.ptr);
+
+       cl_git_fail(git_repository_open(&repo, "empty_standard_repo"));
+
+       /* The blank resets tmp and allows subsequent declarations to succeed */
+
+       git_str_clear(&config_data);
+       git_str_printf(&config_data,
+               "[foo]\n" \
+               "\tbar = Foobar\n" \
+               "\tbaz = Baz!\n" \
+               "[safe]\n" \
+               "\tdirectory = /tmp\n" \
+               "\tdirectory = \n" \
+               "\tdirectory = %s/%s\n" \
+               "[bar]\n" \
+               "\tfoo = barfoo\n",
+               clar_sandbox_path(), "empty_standard_repo");
+       cl_git_rewritefile(config_filename.ptr, config_data.ptr);
+
+       cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
+       git_repository_free(repo);
+
+       git_str_dispose(&config_path);
+       git_str_dispose(&config_filename);
+       git_str_dispose(&config_data);
+}
index b22f3f6bac4d0e16b29d147dcc4721686765e55a..1efde70a50d96fc73a3cb4eb8db719593e4998fb 100644 (file)
@@ -13,25 +13,25 @@ void make_head_unborn(git_repository* repo, const char *target)
 
 void delete_head(git_repository* repo)
 {
-       git_buf head_path = GIT_BUF_INIT;
+       git_str head_path = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&head_path, git_repository_path(repo), GIT_HEAD_FILE));
-       cl_git_pass(p_unlink(git_buf_cstr(&head_path)));
+       cl_git_pass(git_str_joinpath(&head_path, git_repository_path(repo), GIT_HEAD_FILE));
+       cl_git_pass(p_unlink(git_str_cstr(&head_path)));
 
-       git_buf_dispose(&head_path);
+       git_str_dispose(&head_path);
 }
 
 void create_tmp_global_config(const char *dirname, const char *key, const char *val)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_config *config;
 
        cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH,
                GIT_CONFIG_LEVEL_GLOBAL, dirname));
        cl_must_pass(p_mkdir(dirname, 0777));
-       cl_git_pass(git_buf_joinpath(&path, dirname, ".gitconfig"));
+       cl_git_pass(git_str_joinpath(&path, dirname, ".gitconfig"));
        cl_git_pass(git_config_open_ondisk(&config, path.ptr));
        cl_git_pass(git_config_set_string(config, key, val));
        git_config_free(config);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
index 8e024bcbb72defd1145ba8bbaaf16bd6c48164c0..245d8625ac74430de118ca0813f5af758a4bc32a 100644 (file)
@@ -10,7 +10,7 @@ void test_repo_reservedname__cleanup(void)
 void test_repo_reservedname__includes_shortname_on_win32(void)
 {
        git_repository *repo;
-       git_buf *reserved;
+       git_str *reserved;
        size_t reserved_len;
 
        repo = cl_git_sandbox_init("nasty");
@@ -29,7 +29,7 @@ void test_repo_reservedname__includes_shortname_on_win32(void)
 void test_repo_reservedname__includes_shortname_when_requested(void)
 {
        git_repository *repo;
-       git_buf *reserved;
+       git_str *reserved;
        size_t reserved_len;
 
        repo = cl_git_sandbox_init("nasty");
@@ -47,7 +47,7 @@ void test_repo_reservedname__custom_shortname_recognized(void)
 {
 #ifdef GIT_WIN32
        git_repository *repo;
-       git_buf *reserved;
+       git_str *reserved;
        size_t reserved_len;
 
        if (!cl_sandbox_supports_8dot3())
@@ -83,7 +83,7 @@ void test_repo_reservedname__submodule_pointer(void)
 #ifdef GIT_WIN32
        git_repository *super_repo, *sub_repo;
        git_submodule *sub;
-       git_buf *sub_reserved;
+       git_str *sub_reserved;
        size_t sub_reserved_len;
 
        if (!cl_sandbox_supports_8dot3())
@@ -117,16 +117,16 @@ void test_repo_reservedname__submodule_pointer_during_create(void)
        git_repository *repo;
        git_submodule *sm;
        git_submodule_update_options update_options = GIT_SUBMODULE_UPDATE_OPTIONS_INIT;
-       git_buf url = GIT_BUF_INIT;
+       git_str url = GIT_STR_INIT;
 
        repo = setup_fixture_super();
 
-       cl_git_pass(git_buf_joinpath(&url, clar_sandbox_path(), "sub.git"));
+       cl_git_pass(git_str_joinpath(&url, clar_sandbox_path(), "sub.git"));
        cl_repo_set_string(repo, "submodule.sub.url", url.ptr);
 
        cl_git_pass(git_submodule_lookup(&sm, repo, "sub"));
        cl_git_pass(git_submodule_update(sm, 1, &update_options));
 
        git_submodule_free(sm);
-       git_buf_dispose(&url);
+       git_str_dispose(&url);
 }
index 1fac627f66bd0b46d9e28e0fef11e782c6e0fcdb..9a965dec60bbdeb28c103a92af8253f4f41dccca 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 #include "git2/sys/repository.h"
 
-#include "buffer.h"
 #include "posix.h"
 #include "util.h"
 #include "path.h"
@@ -47,20 +46,20 @@ void test_repo_setters__setting_a_workdir_creates_a_gitlink(void)
 {
        git_config *cfg;
        git_buf buf = GIT_BUF_INIT;
-       git_buf content = GIT_BUF_INIT;
+       git_str content = GIT_STR_INIT;
 
        cl_git_pass(git_repository_set_workdir(repo, "./new_workdir", true));
 
-       cl_assert(git_path_isfile("./new_workdir/.git"));
+       cl_assert(git_fs_path_isfile("./new_workdir/.git"));
 
        cl_git_pass(git_futils_readbuffer(&content, "./new_workdir/.git"));
-       cl_assert(git__prefixcmp(git_buf_cstr(&content), "gitdir: ") == 0);
-       cl_assert(git__suffixcmp(git_buf_cstr(&content), "testrepo.git/") == 0);
-       git_buf_dispose(&content);
+       cl_assert(git__prefixcmp(git_str_cstr(&content), "gitdir: ") == 0);
+       cl_assert(git__suffixcmp(git_str_cstr(&content), "testrepo.git/") == 0);
+       git_str_dispose(&content);
 
        cl_git_pass(git_repository_config(&cfg, repo));
        cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.worktree"));
-       cl_assert(git__suffixcmp(git_buf_cstr(&buf), "new_workdir/") == 0);
+       cl_assert(git__suffixcmp(buf.ptr, "new_workdir/") == 0);
 
        git_buf_dispose(&buf);
        git_config_free(cfg);
@@ -81,7 +80,7 @@ void test_repo_setters__setting_a_new_index_on_a_repo_which_has_already_loaded_o
 
        git_index_free(new_index);
 
-       /* 
+       /*
         * Ensure the cleanup method won't try to free the repo as it's already been taken care of
         */
        repo = NULL;
@@ -102,7 +101,7 @@ void test_repo_setters__setting_a_new_odb_on_a_repo_which_already_loaded_one_pro
 
        git_odb_free(new_odb);
 
-       /* 
+       /*
         * Ensure the cleanup method won't try to free the repo as it's already been taken care of
         */
        repo = NULL;
index afb361787fb95c4fdc7532dc3f2cde3ab98e87b2..92b272dcee9511b43d1ae05931f53e63523519e2 100644 (file)
@@ -1,11 +1,10 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "refs.h"
 #include "posix.h"
 #include "futils.h"
 
 static git_repository *_repo;
-static git_buf _path;
+static git_str _path;
 
 void test_repo_state__initialize(void)
 {
@@ -15,14 +14,14 @@ void test_repo_state__initialize(void)
 void test_repo_state__cleanup(void)
 {
        cl_git_sandbox_cleanup();
-       git_buf_dispose(&_path);
+       git_str_dispose(&_path);
 }
 
 static void setup_simple_state(const char *filename)
 {
-       cl_git_pass(git_buf_joinpath(&_path, git_repository_path(_repo), filename));
-       git_futils_mkpath2file(git_buf_cstr(&_path), 0777);
-       cl_git_mkfile(git_buf_cstr(&_path), "dummy");
+       cl_git_pass(git_str_joinpath(&_path, git_repository_path(_repo), filename));
+       git_futils_mkpath2file(git_str_cstr(&_path), 0777);
+       cl_git_mkfile(git_str_cstr(&_path), "dummy");
 }
 
 static void assert_repo_state(git_repository_state_t state)
index 3513190ac20fbd479f49b4e976b7bc07158bf6ef..e8fe266cfc34d7469ae071163176b3ff07008e58 100644 (file)
@@ -7,7 +7,7 @@
 
 static git_repository *_repo = NULL;
 static mode_t g_umask = 0;
-static git_buf _global_path = GIT_BUF_INIT;
+static git_str _global_path = GIT_STR_INIT;
 
 static const char *fixture_repo;
 static const char *fixture_templates;
@@ -27,7 +27,7 @@ void test_repo_template__cleanup(void)
 {
        git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL,
                _global_path.ptr);
-       git_buf_dispose(&_global_path);
+       git_str_dispose(&_global_path);
 
        cl_fixture_cleanup("tmp_global_path");
 
@@ -51,15 +51,15 @@ static void assert_hooks_match(
        const char *hook_path,
        bool core_filemode)
 {
-       git_buf expected = GIT_BUF_INIT;
-       git_buf actual = GIT_BUF_INIT;
+       git_str expected = GIT_STR_INIT;
+       git_str actual = GIT_STR_INIT;
        struct stat expected_st, st;
 
-       cl_git_pass(git_buf_joinpath(&expected, template_dir, hook_path));
-       cl_git_pass(git_path_lstat(expected.ptr, &expected_st));
+       cl_git_pass(git_str_joinpath(&expected, template_dir, hook_path));
+       cl_git_pass(git_fs_path_lstat(expected.ptr, &expected_st));
 
-       cl_git_pass(git_buf_joinpath(&actual, repo_dir, hook_path));
-       cl_git_pass(git_path_lstat(actual.ptr, &st));
+       cl_git_pass(git_str_joinpath(&actual, repo_dir, hook_path));
+       cl_git_pass(git_fs_path_lstat(actual.ptr, &st));
 
        cl_assert(expected_st.st_size == st.st_size);
 
@@ -76,20 +76,20 @@ static void assert_hooks_match(
                cl_assert_equal_i_fmt(expected_mode, st.st_mode, "%07o");
        }
 
-       git_buf_dispose(&expected);
-       git_buf_dispose(&actual);
+       git_str_dispose(&expected);
+       git_str_dispose(&actual);
 }
 
 static void assert_mode_seems_okay(
        const char *base, const char *path,
        git_filemode_t expect_mode, bool expect_setgid, bool core_filemode)
 {
-       git_buf full = GIT_BUF_INIT;
+       git_str full = GIT_STR_INIT;
        struct stat st;
 
-       cl_git_pass(git_buf_joinpath(&full, base, path));
-       cl_git_pass(git_path_lstat(full.ptr, &st));
-       git_buf_dispose(&full);
+       cl_git_pass(git_str_joinpath(&full, base, path));
+       cl_git_pass(git_fs_path_lstat(full.ptr, &st));
+       git_str_dispose(&full);
 
        if (!core_filemode) {
                CLEAR_FOR_CORE_FILEMODE(expect_mode);
@@ -115,7 +115,7 @@ static void setup_repo(const char *name, git_repository_init_options *opts)
 
 static void setup_templates(const char *name, bool setup_globally)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        cl_fixture_sandbox("template");
        if (strcmp(name, "template"))
@@ -127,40 +127,40 @@ static void setup_templates(const char *name, bool setup_globally)
         * Create a symlink from link.sample to update.sample if the filesystem
         * supports it.
         */
-       cl_git_pass(git_buf_join3(&path, '/', name, "hooks", "link.sample"));
+       cl_git_pass(git_str_join3(&path, '/', name, "hooks", "link.sample"));
 #ifdef GIT_WIN32
        cl_git_mkfile(path.ptr, "#!/bin/sh\necho hello, world\n");
 #else
        cl_must_pass(p_symlink("update.sample", path.ptr));
 #endif
 
-       git_buf_clear(&path);
+       git_str_clear(&path);
 
        /* Create a file starting with a dot */
-       cl_git_pass(git_buf_join3(&path, '/', name, "hooks", ".dotfile"));
+       cl_git_pass(git_str_join3(&path, '/', name, "hooks", ".dotfile"));
        cl_git_mkfile(path.ptr, "something\n");
 
-       git_buf_clear(&path);
+       git_str_clear(&path);
 
        if (setup_globally) {
-               cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), name));
+               cl_git_pass(git_str_joinpath(&path, clar_sandbox_path(), name));
                create_tmp_global_config("tmp_global_path", "init.templatedir", path.ptr);
        }
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 static void validate_templates(git_repository *repo, const char *template_path)
 {
-       git_buf path = GIT_BUF_INIT, expected = GIT_BUF_INIT, actual = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT, expected = GIT_STR_INIT, actual = GIT_STR_INIT;
        int filemode;
 
-       cl_git_pass(git_buf_joinpath(&path, template_path, "description"));
+       cl_git_pass(git_str_joinpath(&path, template_path, "description"));
        cl_git_pass(git_futils_readbuffer(&expected, path.ptr));
 
-       git_buf_clear(&path);
+       git_str_clear(&path);
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "description"));
+       cl_git_pass(git_str_joinpath(&path, git_repository_path(repo), "description"));
        cl_git_pass(git_futils_readbuffer(&actual, path.ptr));
 
        cl_assert_equal_s(expected.ptr, actual.ptr);
@@ -177,9 +177,9 @@ static void validate_templates(git_repository *repo, const char *template_path)
                template_path, git_repository_path(repo),
                "hooks/.dotfile", filemode);
 
-       git_buf_dispose(&expected);
-       git_buf_dispose(&actual);
-       git_buf_dispose(&path);
+       git_str_dispose(&expected);
+       git_str_dispose(&actual);
+       git_str_dispose(&path);
 }
 
 void test_repo_template__external_templates_specified_in_options(void)
@@ -252,7 +252,7 @@ void test_repo_template__extended_with_template_and_shared_mode(void)
 void test_repo_template__templated_head_is_used(void)
 {
        git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
-       git_buf head = GIT_BUF_INIT;
+       git_str head = GIT_STR_INIT;
 
        opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
 
@@ -263,13 +263,13 @@ void test_repo_template__templated_head_is_used(void)
        cl_git_pass(git_futils_readbuffer(&head, "repo/.git/HEAD"));
        cl_assert_equal_s("foobar\n", head.ptr);
 
-       git_buf_dispose(&head);
+       git_str_dispose(&head);
 }
 
 void test_repo_template__initial_head_option_overrides_template_head(void)
 {
        git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
-       git_buf head = GIT_BUF_INIT;
+       git_str head = GIT_STR_INIT;
 
        opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
        opts.initial_head = "manual";
@@ -281,7 +281,7 @@ void test_repo_template__initial_head_option_overrides_template_head(void)
        cl_git_pass(git_futils_readbuffer(&head, "repo/.git/HEAD"));
        cl_assert_equal_s("ref: refs/heads/manual\n", head.ptr);
 
-       git_buf_dispose(&head);
+       git_str_dispose(&head);
 }
 
 void test_repo_template__empty_template_path(void)
@@ -293,3 +293,13 @@ void test_repo_template__empty_template_path(void)
 
        setup_repo("foo", &opts);
 }
+
+void test_repo_template__nonexistent_template_path(void)
+{
+       git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
+
+       opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
+       opts.template_path = "/tmp/path/that/does/not/exist/for/libgit2/test";
+
+       setup_repo("bar", &opts);
+}
index 1ea1d13fbbbc65d205822c2eb066c81218287e34..9d177c021712d82a081ed70bc69b4f50e4225ff3 100644 (file)
@@ -40,7 +40,7 @@ static int strequal_ignore_eol(const char *exp, const char *str)
 
 void test_reset_hard__resetting_reverts_modified_files(void)
 {
-       git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT, content = GIT_STR_INIT;
        int i;
        static const char *files[4] = {
                "current_file",
@@ -64,7 +64,7 @@ void test_reset_hard__resetting_reverts_modified_files(void)
        cl_assert(wd);
 
        for (i = 0; i < 4; ++i) {
-               cl_git_pass(git_buf_joinpath(&path, wd, files[i]));
+               cl_git_pass(git_str_joinpath(&path, wd, files[i]));
                cl_git_pass(git_futils_readbuffer(&content, path.ptr));
                cl_assert_equal_s(before[i], content.ptr);
        }
@@ -74,17 +74,17 @@ void test_reset_hard__resetting_reverts_modified_files(void)
        cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL));
 
        for (i = 0; i < 4; ++i) {
-               cl_git_pass(git_buf_joinpath(&path, wd, files[i]));
+               cl_git_pass(git_str_joinpath(&path, wd, files[i]));
                if (after[i]) {
                        cl_git_pass(git_futils_readbuffer(&content, path.ptr));
                        cl_assert(strequal_ignore_eol(after[i], content.ptr));
                } else {
-                       cl_assert(!git_path_exists(path.ptr));
+                       cl_assert(!git_fs_path_exists(path.ptr));
                }
        }
 
-       git_buf_dispose(&content);
-       git_buf_dispose(&path);
+       git_str_dispose(&content);
+       git_str_dispose(&path);
 }
 
 void test_reset_hard__cannot_reset_in_a_bare_repository(void)
@@ -154,7 +154,7 @@ void test_reset_hard__resetting_reverts_unmerged(void)
                cl_git_pass(git_revparse_single(&target, repo, "26a125e"));
                cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL));
 
-               cl_assert(git_path_exists("status/conflicting_file") == 0);
+               cl_assert(git_fs_path_exists("status/conflicting_file") == 0);
 
                git_object_free(target);
                target = NULL;
@@ -165,42 +165,42 @@ void test_reset_hard__resetting_reverts_unmerged(void)
 
 void test_reset_hard__cleans_up_merge(void)
 {
-       git_buf merge_head_path = GIT_BUF_INIT,
-               merge_msg_path = GIT_BUF_INIT,
-               merge_mode_path = GIT_BUF_INIT,
-               orig_head_path = GIT_BUF_INIT;
+       git_str merge_head_path = GIT_STR_INIT,
+               merge_msg_path = GIT_STR_INIT,
+               merge_mode_path = GIT_STR_INIT,
+               orig_head_path = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD"));
-       cl_git_mkfile(git_buf_cstr(&merge_head_path), "beefbeefbeefbeefbeefbeefbeefbeefbeefbeef\n");
+       cl_git_pass(git_str_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD"));
+       cl_git_mkfile(git_str_cstr(&merge_head_path), "beefbeefbeefbeefbeefbeefbeefbeefbeefbeef\n");
 
-       cl_git_pass(git_buf_joinpath(&merge_msg_path, git_repository_path(repo), "MERGE_MSG"));
-       cl_git_mkfile(git_buf_cstr(&merge_msg_path), "Merge commit 0017bd4ab1ec30440b17bae1680cff124ab5f1f6\n");
+       cl_git_pass(git_str_joinpath(&merge_msg_path, git_repository_path(repo), "MERGE_MSG"));
+       cl_git_mkfile(git_str_cstr(&merge_msg_path), "Merge commit 0017bd4ab1ec30440b17bae1680cff124ab5f1f6\n");
 
-       cl_git_pass(git_buf_joinpath(&merge_mode_path, git_repository_path(repo), "MERGE_MODE"));
-       cl_git_mkfile(git_buf_cstr(&merge_mode_path), "");
+       cl_git_pass(git_str_joinpath(&merge_mode_path, git_repository_path(repo), "MERGE_MODE"));
+       cl_git_mkfile(git_str_cstr(&merge_mode_path), "");
 
-       cl_git_pass(git_buf_joinpath(&orig_head_path, git_repository_path(repo), "ORIG_HEAD"));
-       cl_git_mkfile(git_buf_cstr(&orig_head_path), "0017bd4ab1ec30440b17bae1680cff124ab5f1f6");
+       cl_git_pass(git_str_joinpath(&orig_head_path, git_repository_path(repo), "ORIG_HEAD"));
+       cl_git_mkfile(git_str_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));
 
-       cl_assert(!git_path_exists(git_buf_cstr(&merge_head_path)));
-       cl_assert(!git_path_exists(git_buf_cstr(&merge_msg_path)));
-       cl_assert(!git_path_exists(git_buf_cstr(&merge_mode_path)));
+       cl_assert(!git_fs_path_exists(git_str_cstr(&merge_head_path)));
+       cl_assert(!git_fs_path_exists(git_str_cstr(&merge_msg_path)));
+       cl_assert(!git_fs_path_exists(git_str_cstr(&merge_mode_path)));
 
-       cl_assert(git_path_exists(git_buf_cstr(&orig_head_path)));
-       cl_git_pass(p_unlink(git_buf_cstr(&orig_head_path)));
+       cl_assert(git_fs_path_exists(git_str_cstr(&orig_head_path)));
+       cl_git_pass(p_unlink(git_str_cstr(&orig_head_path)));
 
-       git_buf_dispose(&merge_head_path);
-       git_buf_dispose(&merge_msg_path);
-       git_buf_dispose(&merge_mode_path);
-       git_buf_dispose(&orig_head_path);
+       git_str_dispose(&merge_head_path);
+       git_str_dispose(&merge_msg_path);
+       git_str_dispose(&merge_mode_path);
+       git_str_dispose(&orig_head_path);
 }
 
 void test_reset_hard__reflog_is_correct(void)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_annotated_commit *annotated;
        const char *exp_msg = "commit: Add a file which name should appear before the "
                "\"subdir/\" folder while being dealt with by the treewalker";
@@ -218,12 +218,12 @@ void test_reset_hard__reflog_is_correct(void)
 
        /* Moved branch, expect id in message */
        cl_git_pass(git_revparse_single(&target, repo, "HEAD~^{commit}"));
-       cl_git_pass(git_buf_printf(&buf, "reset: moving to %s", git_oid_tostr_s(git_object_id(target))));
+       cl_git_pass(git_str_printf(&buf, "reset: moving to %s", git_oid_tostr_s(git_object_id(target))));
        cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL));
-       reflog_check(repo, "HEAD", 4, NULL, git_buf_cstr(&buf));
-       reflog_check(repo, "refs/heads/master", 4, NULL, git_buf_cstr(&buf));
+       reflog_check(repo, "HEAD", 4, NULL, git_str_cstr(&buf));
+       reflog_check(repo, "refs/heads/master", 4, NULL, git_str_cstr(&buf));
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        /* Moved branch, expect revspec in message */
        exp_msg = "reset: moving to HEAD~^{commit}";
index 9928c687121ed0b37494d0edf793124284f49f3f..4a78d4c37676d9cc02f4b4e2f610a9fdd79736f1 100644 (file)
@@ -50,7 +50,7 @@ void test_reset_mixed__resetting_refreshes_the_index_to_the_commit_tree(void)
 
 void test_reset_mixed__reflog_is_correct(void)
 {
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        git_annotated_commit *annotated;
        const char *exp_msg = "commit: Updating test data so we can test inter-hunk-context";
 
@@ -68,12 +68,12 @@ void test_reset_mixed__reflog_is_correct(void)
 
        /* Moved branch, expect id in message */
        cl_git_pass(git_revparse_single(&target, repo, "HEAD~^{commit}"));
-       git_buf_clear(&buf);
-       cl_git_pass(git_buf_printf(&buf, "reset: moving to %s", git_oid_tostr_s(git_object_id(target))));
+       git_str_clear(&buf);
+       cl_git_pass(git_str_printf(&buf, "reset: moving to %s", git_oid_tostr_s(git_object_id(target))));
        cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL));
-       reflog_check(repo, "HEAD", 10, NULL, git_buf_cstr(&buf));
-       reflog_check(repo, "refs/heads/master", 10, NULL, git_buf_cstr(&buf));
-       git_buf_dispose(&buf);
+       reflog_check(repo, "HEAD", 10, NULL, git_str_cstr(&buf));
+       reflog_check(repo, "refs/heads/master", 10, NULL, git_str_cstr(&buf));
+       git_str_dispose(&buf);
 
        /* Moved branch, expect revspec in message */
        exp_msg = "reset: moving to HEAD~^{commit}";
index d9cfb0553e5187f1981948e7fcb60db78e250982..aca0834f25a700ffed296aab3426f7ac56bd645b 100644 (file)
@@ -116,33 +116,33 @@ void test_reset_soft__resetting_against_an_unborn_head_repo_makes_the_head_no_lo
 
 void test_reset_soft__fails_when_merging(void)
 {
-       git_buf merge_head_path = GIT_BUF_INIT;
+       git_str merge_head_path = GIT_STR_INIT;
 
        cl_git_pass(git_repository_detach_head(repo));
-       cl_git_pass(git_buf_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD"));
-       cl_git_mkfile(git_buf_cstr(&merge_head_path), "beefbeefbeefbeefbeefbeefbeefbeefbeefbeef\n");
+       cl_git_pass(git_str_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD"));
+       cl_git_mkfile(git_str_cstr(&merge_head_path), "beefbeefbeefbeefbeefbeefbeefbeefbeefbeef\n");
 
        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));
-       cl_git_pass(p_unlink(git_buf_cstr(&merge_head_path)));
+       cl_git_pass(p_unlink(git_str_cstr(&merge_head_path)));
 
-       git_buf_dispose(&merge_head_path);
+       git_str_dispose(&merge_head_path);
 }
 
 void test_reset_soft__fails_when_index_contains_conflicts_independently_of_MERGE_HEAD_file_existence(void)
 {
        git_index *index;
        git_reference *head;
-       git_buf merge_head_path = GIT_BUF_INIT;
+       git_str merge_head_path = GIT_STR_INIT;
 
        cl_git_sandbox_cleanup();
 
        repo = cl_git_sandbox_init("mergedrepo");
 
-       cl_git_pass(git_buf_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD"));
-       cl_git_pass(p_unlink(git_buf_cstr(&merge_head_path)));
-       git_buf_dispose(&merge_head_path);
+       cl_git_pass(git_str_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD"));
+       cl_git_pass(p_unlink(git_str_cstr(&merge_head_path)));
+       git_str_dispose(&merge_head_path);
 
        cl_git_pass(git_repository_index(&index, repo));
        cl_assert_equal_i(true, git_index_has_conflicts(index));
diff --git a/tests/resources/config/config22 b/tests/resources/config/config22
new file mode 100644 (file)
index 0000000..2a8e528
--- /dev/null
@@ -0,0 +1,10 @@
+[alias]
+       m = cmd \
+";;" \
+";;" \
+bar
+       m2 = '\
+";" \
+";" \
+something \
+'
index ad053d550bc207277ae2512f73000cc2d60dde64..078f237ed3a67df63dca21bf84949488226369bf 100644 (file)
@@ -1,4 +1,4 @@
-# pack-refs with: peeled fully-peeled 
+# pack-refs with: peeled fully-peeled sorted 
 c2596aa0151888587ec5c0187f261e63412d9e11 refs/foo/tag-outside-tags
 ^0df1a5865c8abfc09f1f2182e6a31be550e99f07
 0df1a5865c8abfc09f1f2182e6a31be550e99f07 refs/heads/master
diff --git a/tests/resources/renames/.gitted/objects/41/a766bb079e18ff6a24571831bd751168799a02 b/tests/resources/renames/.gitted/objects/41/a766bb079e18ff6a24571831bd751168799a02
new file mode 100644 (file)
index 0000000..4bd7592
--- /dev/null
@@ -0,0 +1 @@
+x\ 1­\8eKNÄ0\10DYû\14½GDþ\8f#!Ä\1c\80C¸ÓÝ\19K\89=ò8\12pz\82¸\ 2\8bZÔ[Ô«¥í{\19`g÷4:3`N¨µ\9f\8d?\83ÆÎè\85E\82Á \94Bp\988\99\10Õ=w®\ 3ÌLä,        \9a`u\8e\9e\ 3\9cháÈâ­#ÉV\8c\18·Öᣬ\aopí½}Ãë%è\98ÜsþmïÇ\83ûcª­ó}û\9aÖ2n\aNKÛßÀDoô%x\eáE'­ÕIÏ×\83ÿkO]\89J]AÊÆ0\1a \ 3ñÆ\83   Z\85Ê\9f\ 3þ\94ê\aÆ\86_[
\ No newline at end of file
diff --git a/tests/resources/renames/.gitted/objects/ba/8b004914491b129b4feff51b5fd8553b8e8156 b/tests/resources/renames/.gitted/objects/ba/8b004914491b129b4feff51b5fd8553b8e8156
new file mode 100644 (file)
index 0000000..c61d650
Binary files /dev/null and b/tests/resources/renames/.gitted/objects/ba/8b004914491b129b4feff51b5fd8553b8e8156 differ
diff --git a/tests/resources/renames/.gitted/objects/e5/6d39ca6d946331aa79c9c443d46c8a6ed4f550 b/tests/resources/renames/.gitted/objects/e5/6d39ca6d946331aa79c9c443d46c8a6ed4f550
new file mode 100644 (file)
index 0000000..d6deb18
Binary files /dev/null and b/tests/resources/renames/.gitted/objects/e5/6d39ca6d946331aa79c9c443d46c8a6ed4f550 differ
diff --git a/tests/resources/renames/.gitted/refs/heads/case-insensitive-status b/tests/resources/renames/.gitted/refs/heads/case-insensitive-status
new file mode 100644 (file)
index 0000000..5a92127
--- /dev/null
@@ -0,0 +1 @@
+41a766bb079e18ff6a24571831bd751168799a02
diff --git a/tests/resources/testrepo.git/logs/refs/heads/with-empty-log b/tests/resources/testrepo.git/logs/refs/heads/with-empty-log
new file mode 100644 (file)
index 0000000..e69de29
index 52f5e876fbc57f0f9de3f469603c777e1bce92ff..fadd7e88aba26a119d42868a43eb506bd57f2a18 100644 (file)
@@ -1,3 +1,3 @@
-# pack-refs with: peeled 
+# pack-refs with: peeled sorted 
 41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9 refs/heads/packed
 5b5b025afb0b4c913b4c338a42934a3863bf3644 refs/heads/packed-test
diff --git a/tests/resources/testrepo.git/refs/heads/with-empty-log b/tests/resources/testrepo.git/refs/heads/with-empty-log
new file mode 100644 (file)
index 0000000..dae4cb2
--- /dev/null
@@ -0,0 +1 @@
+8496071c1b46c854b31185ea97743be6a8774479
index 6018a19d2e978f6da3f430d40a5f0381dabd46eb..b57898695e3ed3955d5289afd46a2787046972d6 100644 (file)
@@ -1,4 +1,4 @@
-# pack-refs with: peeled 
+# pack-refs with: peeled sorted 
 41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9 refs/heads/packed
 5b5b025afb0b4c913b4c338a42934a3863bf3644 refs/heads/packed-test
 b25fa35b38051e4ae45d4222e795f9df2e43f1d1 refs/tags/packed-tag
index 4af067f04016f88731c257b0b31b0017ad580063..6966b8a5dd1983146438ecc71c6aef3fd364a498 100644 (file)
@@ -8,19 +8,42 @@
 [remote "origin"]
        url = https://github.com/libgit2/false.git
        fetch = +refs/heads/*:refs/remotes/origin/*
-[remote "insteadof-test"]
-       url = http://example.com/libgit2/libgit2
-       pushurl = http://github.com/libgit2/libgit2
+[remote "insteadof-url-fetch"]
+       url = http://example.com/url/fetch/libgit2
+       fetch = +refs/heads/*:refs/remotes/test/*
+[remote "insteadof-url-push"]
+       url = http://example.com/url/push/libgit2
+       fetch = +refs/heads/*:refs/remotes/test/*
+[remote "insteadof-url-both"]
+       url = http://example.com/url/both/libgit2
+       fetch = +refs/heads/*:refs/remotes/test/*
+[remote "insteadof-pushurl-fetch"]
+       url = http://example.com/url/fetch/libgit2
+       pushurl = http://example.com/url/fetch/libgit2-push
+       fetch = +refs/heads/*:refs/remotes/test/*
+[remote "insteadof-pushurl-push"]
+       url = http://example.com/url/push/libgit2
+       pushurl = http://example.com/url/push/libgit2-push
+       fetch = +refs/heads/*:refs/remotes/test/*
+[remote "insteadof-pushurl-both"]
+       url = http://example.com/url/both/libgit2
+       pushurl = http://example.com/url/both/libgit2-push
        fetch = +refs/heads/*:refs/remotes/test/*
 [branch "master"]
        remote = origin
        merge = refs/heads/master
        rebase = true
 [url "longer-non-prefix-match"]
-       insteadOf = ttp://example.com/li
+       # not applicable because it's not a prefix match
+       insteadOf = ttp://example.com/url/fetch/li
 [url "shorter-prefix"]
-       insteadOf = http://example.co
-[url "http://github.com"]
-       insteadOf = http://example.com
-[url "git@github.com:"]
-       pushInsteadOf = http://github.com/
+       # not applicable because the matched prefix is shorter
+       insteadOf = http://example.com/url/fe
+[url "http://github.com/url/fetch"]
+       insteadOf = http://example.com/url/fetch
+[url "http://github.com/url/both"]
+       insteadOf = http://example.com/url/both
+[url "git@github.com:url/push"]
+       pushInsteadOf = http://example.com/url/push
+[url "git@github.com:url/both"]
+       pushInsteadOf = http://example.com/url/both
index 97ea6a848d1df1366f754b3b1eb907409b6b555a..01de8717328d023ccf9db08128f715cce15499ff 100644 (file)
@@ -1,4 +1,4 @@
-# pack-refs with: peeled fully-peeled 
+# pack-refs with: peeled fully-peeled sorted 
 36060c58702ed4c2a40832c51758d5344201d89a refs/remotes/origin/master
 41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9 refs/remotes/origin/packed
 5b5b025afb0b4c913b4c338a42934a3863bf3644 refs/tags/v0.9
index 03cffbf3e9206cf43819ffdec80d497c2ffffe0c..9261cfe861fb04ea025a730039ae2d1b83c2cc80 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar.h"
 #include "clar_libgit2.h"
 
-#include "buffer.h"
 #include "futils.h"
 #include "git2/revert.h"
 
index 2ad059d99bbbf3d37f7e77feb55324b71ef8f0b9..3f54280caf6f2171fadc4128189024266c7b8daa 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar.h"
 #include "clar_libgit2.h"
 
-#include "buffer.h"
 #include "futils.h"
 #include "git2/revert.h"
 
@@ -66,7 +65,7 @@ void test_revert_workdir__conflicts(void)
        git_reference *head_ref;
        git_commit *head, *commit;
        git_oid revert_oid;
-       git_buf conflicting_buf = GIT_BUF_INIT, mergemsg_buf = GIT_BUF_INIT;
+       git_str conflicting_buf = GIT_STR_INIT, mergemsg_buf = GIT_STR_INIT;
 
        struct merge_index_entry merge_index_entries[] = {
                { 0100644, "7731926a337c4eaba1e2187d90ebfa0a93659382", 1, "file1.txt" },
@@ -112,7 +111,7 @@ void test_revert_workdir__conflicts(void)
                "File one\n" \
                ">>>>>>> parent of 72333f4... automergeable changes\n") == 0);
 
-       cl_assert(git_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
+       cl_assert(git_fs_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
        cl_git_pass(git_futils_readbuffer(&mergemsg_buf,
                TEST_REPO_PATH "/.git/MERGE_MSG"));
        cl_assert(strcmp(mergemsg_buf.ptr,
@@ -120,14 +119,14 @@ void test_revert_workdir__conflicts(void)
                "\n" \
                "This reverts commit 72333f47d4e83616630ff3b0ffe4c0faebcc3c45.\n"
                "\n" \
-               "Conflicts:\n" \
-               "\tfile1.txt\n") == 0);
+               "#Conflicts:\n" \
+               "#\tfile1.txt\n") == 0);
 
        git_commit_free(commit);
        git_commit_free(head);
        git_reference_free(head_ref);
-       git_buf_dispose(&mergemsg_buf);
-       git_buf_dispose(&conflicting_buf);
+       git_str_dispose(&mergemsg_buf);
+       git_str_dispose(&conflicting_buf);
 }
 
 /* git reset --hard 39467716290f6df775a91cdb9a4eb39295018145
@@ -308,7 +307,7 @@ void test_revert_workdir__again_after_edit(void)
  */
 void test_revert_workdir__again_after_edit_two(void)
 {
-       git_buf diff_buf = GIT_BUF_INIT;
+       git_str diff_buf = GIT_STR_INIT;
        git_config *config;
        git_oid head_commit_oid, revert_commit_oid;
        git_commit *head_commit, *revert_commit;
@@ -350,7 +349,7 @@ void test_revert_workdir__again_after_edit_two(void)
        git_commit_free(revert_commit);
        git_commit_free(head_commit);
        git_config_free(config);
-       git_buf_dispose(&diff_buf);
+       git_str_dispose(&diff_buf);
 }
 
 /* git reset --hard 72333f47d4e83616630ff3b0ffe4c0faebcc3c45
@@ -499,8 +498,8 @@ void test_revert_workdir__nonmerge_fails_mainline_specified(void)
 
        opts.mainline = 1;
        cl_must_fail(git_revert(repo, commit, &opts));
-       cl_assert(!git_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
-       cl_assert(!git_path_exists(TEST_REPO_PATH "/.git/REVERT_HEAD"));
+       cl_assert(!git_fs_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
+       cl_assert(!git_fs_path_exists(TEST_REPO_PATH "/.git/REVERT_HEAD"));
 
        git_reference_free(head);
        git_commit_free(commit);
@@ -518,8 +517,8 @@ void test_revert_workdir__merge_fails_without_mainline_specified(void)
        cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL));
 
        cl_must_fail(git_revert(repo, head, NULL));
-       cl_assert(!git_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
-       cl_assert(!git_path_exists(TEST_REPO_PATH "/.git/REVERT_HEAD"));
+       cl_assert(!git_fs_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
+       cl_assert(!git_fs_path_exists(TEST_REPO_PATH "/.git/REVERT_HEAD"));
 
        git_commit_free(head);
 }
index 5eb59545ea27ceca21237887c4fc386c9d43a52d..5125ae6399ba15f8a409d763d53d696ea2a1ba13 100644 (file)
@@ -70,7 +70,7 @@ void test_stash_apply__cleanup(void)
 
 void test_stash_apply__with_default(void)
 {
-       git_buf where = GIT_BUF_INIT;
+       git_str where = GIT_STR_INIT;
 
        cl_git_pass(git_stash_apply(repo, 0, NULL));
 
@@ -85,7 +85,7 @@ void test_stash_apply__with_default(void)
        cl_git_pass(git_futils_readbuffer(&where, "stash/where"));
        cl_assert_equal_s("....\n", where.ptr);
 
-       git_buf_dispose(&where);
+       git_str_dispose(&where);
 }
 
 void test_stash_apply__with_existing_file(void)
@@ -114,7 +114,7 @@ void test_stash_apply__merges_new_file(void)
 
 void test_stash_apply__with_reinstate_index(void)
 {
-       git_buf where = GIT_BUF_INIT;
+       git_str where = GIT_STR_INIT;
        git_stash_apply_options opts = GIT_STASH_APPLY_OPTIONS_INIT;
 
        opts.flags = GIT_STASH_APPLY_REINSTATE_INDEX;
@@ -132,7 +132,7 @@ void test_stash_apply__with_reinstate_index(void)
        cl_git_pass(git_futils_readbuffer(&where, "stash/where"));
        cl_assert_equal_s("....\n", where.ptr);
 
-       git_buf_dispose(&where);
+       git_str_dispose(&where);
 }
 
 void test_stash_apply__conflict_index_with_default(void)
@@ -316,7 +316,7 @@ struct seen_paths {
        bool when;
 };
 
-int checkout_notify(
+static int checkout_notify(
        git_checkout_notify_t why,
        const char *path,
        const git_diff_file *baseline,
@@ -368,7 +368,7 @@ void test_stash_apply__executes_notify_cb(void)
        cl_assert_equal_b(true, seen_paths.when);
 }
 
-int progress_cb(
+static int progress_cb(
        git_stash_apply_progress_t progress,
        void *payload)
 {
@@ -393,7 +393,7 @@ void test_stash_apply__calls_progress_cb(void)
        cl_assert_equal_i(progress, GIT_STASH_APPLY_PROGRESS_DONE);
 }
 
-int aborting_progress_cb(
+static int aborting_progress_cb(
        git_stash_apply_progress_t progress,
        void *payload)
 {
index 6b0895ba88c87311f626ce2772d6d169a807b5f2..a57147172745479b34e602cc4512df82c6ed1e16 100644 (file)
@@ -37,26 +37,26 @@ static void push_three_states(void)
        cl_git_pass(git_repository_index(&index, repo));
        cl_git_pass(git_index_add_bypath(index, "zero.txt"));
        cl_repo_commit_from_index(NULL, repo, signature, 0, "Initial commit");
-       cl_assert(git_path_exists("stash/zero.txt"));
+       cl_assert(git_fs_path_exists("stash/zero.txt"));
        git_index_free(index);
 
        cl_git_mkfile("stash/one.txt", "content\n");
        cl_git_pass(git_stash_save(
                &oid, repo, signature, "First", GIT_STASH_INCLUDE_UNTRACKED));
-       cl_assert(!git_path_exists("stash/one.txt"));
-       cl_assert(git_path_exists("stash/zero.txt"));
+       cl_assert(!git_fs_path_exists("stash/one.txt"));
+       cl_assert(git_fs_path_exists("stash/zero.txt"));
 
        cl_git_mkfile("stash/two.txt", "content\n");
        cl_git_pass(git_stash_save(
                &oid, repo, signature, "Second", GIT_STASH_INCLUDE_UNTRACKED));
-       cl_assert(!git_path_exists("stash/two.txt"));
-       cl_assert(git_path_exists("stash/zero.txt"));
+       cl_assert(!git_fs_path_exists("stash/two.txt"));
+       cl_assert(git_fs_path_exists("stash/zero.txt"));
 
        cl_git_mkfile("stash/three.txt", "content\n");
        cl_git_pass(git_stash_save(
                &oid, repo, signature, "Third", GIT_STASH_INCLUDE_UNTRACKED));
-       cl_assert(!git_path_exists("stash/three.txt"));
-       cl_assert(git_path_exists("stash/zero.txt"));
+       cl_assert(!git_fs_path_exists("stash/three.txt"));
+       cl_assert(git_fs_path_exists("stash/zero.txt"));
 }
 
 void test_stash_drop__cannot_drop_a_non_existing_stashed_state(void)
@@ -140,7 +140,7 @@ void test_stash_drop__dropping_the_last_entry_removes_the_stash(void)
                git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE), GIT_ENOTFOUND);
 }
 
-void retrieve_top_stash_id(git_oid *out)
+static void retrieve_top_stash_id(git_oid *out)
 {
        git_object *top_stash;
 
index d568567d5f92a7278f70160331daeee4e77ecbbf..f574211d794bed2b63d74b56fa56f8433020a396 100644 (file)
@@ -161,16 +161,16 @@ void test_stash_save__untracked_skips_ignored(void)
        cl_must_pass(p_mkdir("stash/bundle/vendor", 0777));
        cl_git_mkfile("stash/bundle/vendor/blah", "contents\n");
 
-       cl_assert(git_path_exists("stash/when")); /* untracked */
-       cl_assert(git_path_exists("stash/just.ignore")); /* ignored */
-       cl_assert(git_path_exists("stash/bundle/vendor/blah")); /* ignored */
+       cl_assert(git_fs_path_exists("stash/when")); /* untracked */
+       cl_assert(git_fs_path_exists("stash/just.ignore")); /* ignored */
+       cl_assert(git_fs_path_exists("stash/bundle/vendor/blah")); /* ignored */
 
        cl_git_pass(git_stash_save(
                &stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED));
 
-       cl_assert(!git_path_exists("stash/when"));
-       cl_assert(git_path_exists("stash/bundle/vendor/blah"));
-       cl_assert(git_path_exists("stash/just.ignore"));
+       cl_assert(!git_fs_path_exists("stash/when"));
+       cl_assert(git_fs_path_exists("stash/bundle/vendor/blah"));
+       cl_assert(git_fs_path_exists("stash/just.ignore"));
 }
 
 void test_stash_save__can_include_untracked_and_ignored_files(void)
@@ -185,7 +185,7 @@ void test_stash_save__can_include_untracked_and_ignored_files(void)
        assert_blob_oid("refs/stash^3:when", "b6ed15e81e2593d7bb6265eb4a991d29dc3e628b");
        assert_blob_oid("refs/stash^3:just.ignore", "78925fb1236b98b37a35e9723033e627f97aa88b");
 
-       cl_assert(!git_path_exists("stash/just.ignore"));
+       cl_assert(!git_fs_path_exists("stash/just.ignore"));
 }
 
 /*
@@ -201,12 +201,12 @@ void test_stash_save__untracked_regression(void)
        const char *paths[] = {"what", "where", "how", "why"};
        git_reference *head;
        git_commit *head_commit;
-       git_buf untracked_dir;
+       git_str untracked_dir;
 
        const char* workdir = git_repository_workdir(repo);
 
-       git_buf_init(&untracked_dir, 0);
-       git_buf_printf(&untracked_dir, "%sz", workdir);
+       git_str_init(&untracked_dir, 0);
+       git_str_printf(&untracked_dir, "%sz", workdir);
 
        cl_assert(!p_mkdir(untracked_dir.ptr, 0777));
 
@@ -227,7 +227,7 @@ void test_stash_save__untracked_regression(void)
 
        git_reference_free(head);
        git_commit_free(head_commit);
-       git_buf_dispose(&untracked_dir);
+       git_str_dispose(&untracked_dir);
 }
 
 #define MESSAGE "Look Ma! I'm on TV!"
@@ -450,9 +450,9 @@ void test_stash_save__ignored_directory(void)
 
        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"));
+       cl_assert(!git_fs_path_exists("stash/ignored_directory/sub/some_file"));
+       cl_assert(!git_fs_path_exists("stash/ignored_directory/sub"));
+       cl_assert(!git_fs_path_exists("stash/ignored_directory"));
 }
 
 void test_stash_save__skip_submodules(void)
index 7deec980f6fddc89b6f1370b5d669c288706e805..d5cf87d07e916f60f7f23588caf202cbe4232a73 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "path.h"
 #include "posix.h"
 #include "status_helpers.h"
@@ -23,11 +22,11 @@ void test_status_renames__cleanup(void)
 static void _rename_helper(
        git_repository *repo, const char *from, const char *to, const char *extra)
 {
-       git_buf oldpath = GIT_BUF_INIT, newpath = GIT_BUF_INIT;
+       git_str oldpath = GIT_STR_INIT, newpath = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(
+       cl_git_pass(git_str_joinpath(
                &oldpath, git_repository_workdir(repo), from));
-       cl_git_pass(git_buf_joinpath(
+       cl_git_pass(git_str_joinpath(
                &newpath, git_repository_workdir(repo), to));
 
        cl_git_pass(p_rename(oldpath.ptr, newpath.ptr));
@@ -35,8 +34,8 @@ static void _rename_helper(
        if (extra)
                cl_git_append2file(newpath.ptr, extra);
 
-       git_buf_dispose(&oldpath);
-       git_buf_dispose(&newpath);
+       git_str_dispose(&oldpath);
+       git_str_dispose(&newpath);
 }
 
 #define rename_file(R,O,N) _rename_helper((R), (O), (N), NULL)
@@ -719,3 +718,127 @@ void test_status_renames__precomposed_unicode_toggle_is_rename(void)
 #endif
 }
 
+void test_status_renames__rename_threshold(void)
+{
+       git_index *index;
+       git_status_list *statuslist;
+       git_status_options opts = GIT_STATUS_OPTIONS_INIT;
+
+       _rename_helper(g_repo, "ikeepsix.txt", "newname.txt",
+               "Line 1\n" \
+               "Line 2\n" \
+               "Line 3\n" \
+               "Line 4\n" \
+               "Line 5\n" \
+               "Line 6\n" \
+               "Line 7\n" \
+               "Line 8\n" \
+               "Line 9\n"
+       );
+
+       opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR;
+       opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED;
+
+       cl_git_pass(git_repository_index(&index, g_repo));
+
+       /* Default threshold */
+       {
+               struct status_entry expected[] = {
+                       { GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, "ikeepsix.txt", "newname.txt" },
+               };
+
+               cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts));
+               check_status(statuslist, expected, 1);
+               git_status_list_free(statuslist);
+       }
+
+       /* Threshold set to 90 */
+       {
+               struct status_entry expected[] = {
+                       { GIT_STATUS_WT_DELETED, "ikeepsix.txt", NULL },
+                       { GIT_STATUS_WT_NEW, "newname.txt", NULL }
+               };
+
+               opts.rename_threshold = 90;
+
+               cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts));
+               check_status(statuslist, expected, 2);
+               git_status_list_free(statuslist);
+       }
+
+       /* Threshold set to 25 */
+       {
+               struct status_entry expected[] = {
+                       { GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, "ikeepsix.txt", "newname.txt" },
+               };
+
+               opts.rename_threshold = 25;
+
+               cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts));
+               check_status(statuslist, expected, 1);
+               git_status_list_free(statuslist);
+       }
+
+       git_index_free(index);
+}
+
+void test_status_renames__case_insensitive_h2i_and_i2wc(void)
+{
+       git_status_list *statuslist;
+       git_status_options opts = GIT_STATUS_OPTIONS_INIT;
+       git_reference *head, *test_branch;
+       git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
+       git_str path_to_delete = GIT_STR_INIT;
+       git_str path_to_edit = GIT_STR_INIT;
+       git_index *index;
+       git_strarray paths = { NULL, 0 };
+
+       struct status_entry expected[] = {
+               { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_MODIFIED, "sixserving.txt", "sixserving-renamed.txt" },
+               { GIT_STATUS_INDEX_DELETED, "Wow.txt", "Wow.txt" }
+       };
+
+
+       /* Checkout the correct branch */
+       checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+       cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
+       cl_git_pass(git_reference_symbolic_set_target(
+               &test_branch, head, "refs/heads/case-insensitive-status", NULL));
+       cl_git_pass(git_checkout_head(g_repo, &checkout_opts));
+
+       cl_git_pass(git_repository_index(&index, g_repo));
+
+
+       /* Rename sixserving.txt, delete Wow.txt, and stage those changes */
+       rename_file(g_repo, "sixserving.txt", "sixserving-renamed.txt");
+       cl_git_pass(git_str_joinpath(
+               &path_to_delete, git_repository_workdir(g_repo), "Wow.txt"));
+       cl_git_rmfile(path_to_delete.ptr);
+
+       cl_git_pass(git_index_add_all(index, &paths, GIT_INDEX_ADD_FORCE, NULL, NULL));
+       cl_git_pass(git_index_write(index));
+
+
+       /* Change content of sixserving-renamed.txt */
+       cl_git_pass(git_str_joinpath(
+               &path_to_edit, git_repository_workdir(g_repo), "sixserving-renamed.txt"));
+       cl_git_append2file(path_to_edit.ptr, "New content\n");
+
+       /* Run status */
+       opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED;
+       opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR;
+       opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX;
+       opts.flags |= GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY;
+
+       cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts));
+       check_status(statuslist, expected, 2);
+       git_status_list_free(statuslist);
+
+       git_index_free(index);
+
+       git_str_dispose(&path_to_delete);
+       git_str_dispose(&path_to_edit);
+
+       git_reference_free(head);
+       git_reference_free(test_branch);
+}
index 38a39471ac24e3a3649c71d36ab82b26011bace5..d223657b4ead9877756f8f741c4e4931f0f53ee3 100644 (file)
@@ -36,9 +36,9 @@ void test_status_submodules__0(void)
 
        g_repo = setup_fixture_submodules();
 
-       cl_assert(git_path_isdir("submodules/.git"));
-       cl_assert(git_path_isdir("submodules/testrepo/.git"));
-       cl_assert(git_path_isfile("submodules/.gitmodules"));
+       cl_assert(git_fs_path_isdir("submodules/.git"));
+       cl_assert(git_fs_path_isdir("submodules/testrepo/.git"));
+       cl_assert(git_fs_path_isfile("submodules/.gitmodules"));
 
        cl_git_pass(
                git_status_foreach(g_repo, cb_status__count, &counts)
@@ -89,9 +89,9 @@ void test_status_submodules__1(void)
 
        g_repo = setup_fixture_submodules();
 
-       cl_assert(git_path_isdir("submodules/.git"));
-       cl_assert(git_path_isdir("submodules/testrepo/.git"));
-       cl_assert(git_path_isfile("submodules/.gitmodules"));
+       cl_assert(git_fs_path_isdir("submodules/.git"));
+       cl_assert(git_fs_path_isdir("submodules/testrepo/.git"));
+       cl_assert(git_fs_path_isfile("submodules/.gitmodules"));
 
        status_counts_init(counts, expected_files, expected_status);
 
index d9fce44046a7bd247351b18ebceb310a50f7ab50..00c6ec2d5cf53602659c2ca6b2f81221809ae165 100644 (file)
@@ -43,7 +43,7 @@ void test_status_worktree__whole_repository(void)
        cl_assert_equal_i(0, counts.wrong_sorted_path);
 }
 
-void assert_show(
+static void assert_show(
        const int entry_counts,
        const char *entry_paths[],
        const unsigned int entry_statuses[],
@@ -100,19 +100,19 @@ void test_status_worktree__empty_repository(void)
        cl_assert_equal_i(0, count);
 }
 
-static int remove_file_cb(void *data, git_buf *file)
+static int remove_file_cb(void *data, git_str *file)
 {
-       const char *filename = git_buf_cstr(file);
+       const char *filename = git_str_cstr(file);
 
        GIT_UNUSED(data);
 
        if (git__suffixcmp(filename, ".git") == 0)
                return 0;
 
-       if (git_path_isdir(filename))
+       if (git_fs_path_isdir(filename))
                cl_git_pass(git_futils_rmdir_r(filename, NULL, GIT_RMDIR_REMOVE_FILES));
        else
-               cl_git_pass(p_unlink(git_buf_cstr(file)));
+               cl_git_pass(p_unlink(git_str_cstr(file)));
 
        return 0;
 }
@@ -122,12 +122,12 @@ void test_status_worktree__purged_worktree(void)
 {
        status_entry_counts counts;
        git_repository *repo = cl_git_sandbox_init("status");
-       git_buf workdir = GIT_BUF_INIT;
+       git_str workdir = GIT_STR_INIT;
 
        /* first purge the contents of the worktree */
-       cl_git_pass(git_buf_sets(&workdir, git_repository_workdir(repo)));
-       cl_git_pass(git_path_direach(&workdir, 0, remove_file_cb, NULL));
-       git_buf_dispose(&workdir);
+       cl_git_pass(git_str_sets(&workdir, git_repository_workdir(repo)));
+       cl_git_pass(git_fs_path_direach(&workdir, 0, remove_file_cb, NULL));
+       git_str_dispose(&workdir);
 
        /* now get status */
        memset(&counts, 0x0, sizeof(status_entry_counts));
@@ -369,78 +369,78 @@ static int cb_status__check_592(const char *p, unsigned int s, void *payload)
 void test_status_worktree__issue_592(void)
 {
        git_repository *repo;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        repo = cl_git_sandbox_init("issue_592");
-       cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "l.txt"));
-       cl_git_pass(p_unlink(git_buf_cstr(&path)));
-       cl_assert(!git_path_exists("issue_592/l.txt"));
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(repo), "l.txt"));
+       cl_git_pass(p_unlink(git_str_cstr(&path)));
+       cl_assert(!git_fs_path_exists("issue_592/l.txt"));
 
        cl_git_pass(git_status_foreach(repo, cb_status__check_592, "l.txt"));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_status_worktree__issue_592_2(void)
 {
        git_repository *repo;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        repo = cl_git_sandbox_init("issue_592");
-       cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "c/a.txt"));
-       cl_git_pass(p_unlink(git_buf_cstr(&path)));
-       cl_assert(!git_path_exists("issue_592/c/a.txt"));
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(repo), "c/a.txt"));
+       cl_git_pass(p_unlink(git_str_cstr(&path)));
+       cl_assert(!git_fs_path_exists("issue_592/c/a.txt"));
 
        cl_git_pass(git_status_foreach(repo, cb_status__check_592, "c/a.txt"));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_status_worktree__issue_592_3(void)
 {
        git_repository *repo;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        repo = cl_git_sandbox_init("issue_592");
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "c"));
-       cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES));
-       cl_assert(!git_path_exists("issue_592/c/a.txt"));
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(repo), "c"));
+       cl_git_pass(git_futils_rmdir_r(git_str_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES));
+       cl_assert(!git_fs_path_exists("issue_592/c/a.txt"));
 
        cl_git_pass(git_status_foreach(repo, cb_status__check_592, "c/a.txt"));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_status_worktree__issue_592_4(void)
 {
        git_repository *repo;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        repo = cl_git_sandbox_init("issue_592");
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "t/b.txt"));
-       cl_git_pass(p_unlink(git_buf_cstr(&path)));
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(repo), "t/b.txt"));
+       cl_git_pass(p_unlink(git_str_cstr(&path)));
 
        cl_git_pass(git_status_foreach(repo, cb_status__check_592, "t/b.txt"));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_status_worktree__issue_592_5(void)
 {
        git_repository *repo;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        repo = cl_git_sandbox_init("issue_592");
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "t"));
-       cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES));
-       cl_git_pass(p_mkdir(git_buf_cstr(&path), 0777));
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(repo), "t"));
+       cl_git_pass(git_futils_rmdir_r(git_str_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES));
+       cl_git_pass(p_mkdir(git_str_cstr(&path), 0777));
 
        cl_git_pass(git_status_foreach(repo, cb_status__check_592, NULL));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_status_worktree__issue_592_ignores_0(void)
@@ -610,8 +610,8 @@ void test_status_worktree__filemode_non755(void)
        git_repository *repo = cl_git_sandbox_init("filemodes");
        status_entry_counts counts;
        git_status_options opts = GIT_STATUS_OPTIONS_INIT;
-       git_buf executable_path = GIT_BUF_INIT;
-       git_buf nonexecutable_path = GIT_BUF_INIT;
+       git_str executable_path = GIT_STR_INIT;
+       git_str nonexecutable_path = GIT_STR_INIT;
 
        if (!cl_is_chmod_supported())
                return;
@@ -620,14 +620,14 @@ void test_status_worktree__filemode_non755(void)
                GIT_STATUS_OPT_INCLUDE_IGNORED |
                GIT_STATUS_OPT_INCLUDE_UNMODIFIED;
 
-       git_buf_joinpath(&executable_path, git_repository_workdir(repo), "exec_on");
-       cl_must_pass(p_chmod(git_buf_cstr(&executable_path), 0744));
-       git_buf_dispose(&executable_path);
+       git_str_joinpath(&executable_path, git_repository_workdir(repo), "exec_on");
+       cl_must_pass(p_chmod(git_str_cstr(&executable_path), 0744));
+       git_str_dispose(&executable_path);
 
-       git_buf_joinpath(&nonexecutable_path, git_repository_workdir(repo), "exec_off");
+       git_str_joinpath(&nonexecutable_path, git_repository_workdir(repo), "exec_off");
 
-       cl_must_pass(p_chmod(git_buf_cstr(&nonexecutable_path), 0655));
-       git_buf_dispose(&nonexecutable_path);
+       cl_must_pass(p_chmod(git_str_cstr(&nonexecutable_path), 0655));
+       git_str_dispose(&nonexecutable_path);
 
        memset(&counts, 0, sizeof(counts));
        counts.expected_entry_count = filemode_count;
@@ -789,7 +789,7 @@ static void assert_ignore_case(
        int expected_camel_cased_file_status)
 {
        unsigned int status;
-       git_buf lower_case_path = GIT_BUF_INIT, camel_case_path = GIT_BUF_INIT;
+       git_str lower_case_path = GIT_STR_INIT, camel_case_path = GIT_STR_INIT;
        git_repository *repo, *repo2;
 
        repo = cl_git_sandbox_init("empty_standard_repo");
@@ -797,10 +797,10 @@ static void assert_ignore_case(
 
        cl_repo_set_bool(repo, "core.ignorecase", should_ignore_case);
 
-       cl_git_pass(git_buf_joinpath(&lower_case_path,
+       cl_git_pass(git_str_joinpath(&lower_case_path,
                git_repository_workdir(repo), "plop"));
 
-       cl_git_mkfile(git_buf_cstr(&lower_case_path), "");
+       cl_git_mkfile(git_str_cstr(&lower_case_path), "");
 
        stage_and_commit(repo, "plop");
 
@@ -809,10 +809,10 @@ static void assert_ignore_case(
        cl_git_pass(git_status_file(&status, repo2, "plop"));
        cl_assert_equal_i(GIT_STATUS_CURRENT, status);
 
-       cl_git_pass(git_buf_joinpath(&camel_case_path,
+       cl_git_pass(git_str_joinpath(&camel_case_path,
                git_repository_workdir(repo), "Plop"));
 
-       cl_git_pass(p_rename(git_buf_cstr(&lower_case_path), git_buf_cstr(&camel_case_path)));
+       cl_git_pass(p_rename(git_str_cstr(&lower_case_path), git_str_cstr(&camel_case_path)));
 
        cl_git_pass(git_status_file(&status, repo2, "plop"));
        cl_assert_equal_i(expected_lower_cased_file_status, status);
@@ -821,8 +821,8 @@ static void assert_ignore_case(
        cl_assert_equal_i(expected_camel_cased_file_status, status);
 
        git_repository_free(repo2);
-       git_buf_dispose(&lower_case_path);
-       git_buf_dispose(&camel_case_path);
+       git_str_dispose(&lower_case_path);
+       git_str_dispose(&camel_case_path);
 }
 
 void test_status_worktree__file_status_honors_core_ignorecase_true(void)
diff --git a/tests/str/basic.c b/tests/str/basic.c
new file mode 100644 (file)
index 0000000..5d25568
--- /dev/null
@@ -0,0 +1,50 @@
+#include "clar_libgit2.h"
+
+static const char *test_string = "Have you seen that? Have you seeeen that??";
+
+void test_str_basic__resize(void)
+{
+       git_str buf1 = GIT_STR_INIT;
+       git_str_puts(&buf1, test_string);
+       cl_assert(git_str_oom(&buf1) == 0);
+       cl_assert_equal_s(git_str_cstr(&buf1), test_string);
+
+       git_str_puts(&buf1, test_string);
+       cl_assert(strlen(git_str_cstr(&buf1)) == strlen(test_string) * 2);
+       git_str_dispose(&buf1);
+}
+
+void test_str_basic__resize_incremental(void)
+{
+       git_str buf1 = GIT_STR_INIT;
+
+       /* Presently, asking for 6 bytes will round up to 8. */
+       cl_git_pass(git_str_puts(&buf1, "Hello"));
+       cl_assert_equal_i(5, buf1.size);
+       cl_assert_equal_i(8, buf1.asize);
+
+       /* Ensure an additional byte does not realloc. */
+       cl_git_pass(git_str_grow_by(&buf1, 1));
+       cl_assert_equal_i(5, buf1.size);
+       cl_assert_equal_i(8, buf1.asize);
+
+       /* But requesting many does. */
+       cl_git_pass(git_str_grow_by(&buf1, 16));
+       cl_assert_equal_i(5, buf1.size);
+       cl_assert(buf1.asize > 8);
+
+       git_str_dispose(&buf1);
+}
+
+void test_str_basic__printf(void)
+{
+       git_str buf2 = GIT_STR_INIT;
+       git_str_printf(&buf2, "%s %s %d ", "shoop", "da", 23);
+       cl_assert(git_str_oom(&buf2) == 0);
+       cl_assert_equal_s(git_str_cstr(&buf2), "shoop da 23 ");
+
+       git_str_printf(&buf2, "%s %d", "woop", 42);
+       cl_assert(git_str_oom(&buf2) == 0);
+       cl_assert_equal_s(git_str_cstr(&buf2), "shoop da 23 woop 42");
+       git_str_dispose(&buf2);
+}
diff --git a/tests/str/oom.c b/tests/str/oom.c
new file mode 100644 (file)
index 0000000..3d59ead
--- /dev/null
@@ -0,0 +1,58 @@
+#include "clar_libgit2.h"
+
+/* Override default allocators with ones that will fail predictably. */
+
+static git_allocator std_alloc;
+static git_allocator oom_alloc;
+
+static void *oom_malloc(size_t n, const char *file, int line)
+{
+       /* Reject any allocation of more than 100 bytes */
+       return (n > 100) ? NULL : std_alloc.gmalloc(n, file, line);
+}
+
+static void *oom_realloc(void *p, size_t n, const char *file, int line)
+{
+       /* Reject any allocation of more than 100 bytes */
+       return (n > 100) ? NULL : std_alloc.grealloc(p, n, file, line);
+}
+
+void test_str_oom__initialize(void)
+{
+       git_stdalloc_init_allocator(&std_alloc);
+       git_stdalloc_init_allocator(&oom_alloc);
+
+       oom_alloc.gmalloc = oom_malloc;
+       oom_alloc.grealloc = oom_realloc;
+
+       cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ALLOCATOR, &oom_alloc));
+}
+
+void test_str_oom__cleanup(void)
+{
+       cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ALLOCATOR, NULL));
+}
+
+void test_str_oom__grow(void)
+{
+       git_str buf = GIT_STR_INIT;
+
+       cl_git_pass(git_str_grow(&buf, 42));
+       cl_assert(!git_str_oom(&buf));
+
+       cl_assert(git_str_grow(&buf, 101) == -1);
+       cl_assert(git_str_oom(&buf));
+
+       git_str_dispose(&buf);
+}
+
+void test_str_oom__grow_by(void)
+{
+       git_str buf = GIT_STR_INIT;
+
+       cl_git_pass(git_str_grow_by(&buf, 42));
+       cl_assert(!git_str_oom(&buf));
+
+       cl_assert(git_str_grow_by(&buf, 101) == -1);
+       cl_assert(git_str_oom(&buf));
+}
diff --git a/tests/str/percent.c b/tests/str/percent.c
new file mode 100644 (file)
index 0000000..3393890
--- /dev/null
@@ -0,0 +1,48 @@
+#include "clar_libgit2.h"
+
+static void expect_decode_pass(const char *expected, const char *encoded)
+{
+       git_str in = GIT_STR_INIT, out = GIT_STR_INIT;
+
+       /*
+        * ensure that we only read the given length of the input buffer
+        * by putting garbage at the end.  this will ensure that we do
+        * not, eg, rely on nul-termination or walk off the end of the buf.
+        */
+       cl_git_pass(git_str_puts(&in, encoded));
+       cl_git_pass(git_str_PUTS(&in, "TRAILER"));
+
+       cl_git_pass(git_str_decode_percent(&out, in.ptr, strlen(encoded)));
+
+       cl_assert_equal_s(expected, git_str_cstr(&out));
+       cl_assert_equal_i(strlen(expected), git_str_len(&out));
+
+       git_str_dispose(&in);
+       git_str_dispose(&out);
+}
+
+void test_str_percent__decode_succeeds(void)
+{
+       expect_decode_pass("", "");
+       expect_decode_pass(" ", "%20");
+       expect_decode_pass("a", "a");
+       expect_decode_pass(" a", "%20a");
+       expect_decode_pass("a ", "a%20");
+       expect_decode_pass("github.com", "github.com");
+       expect_decode_pass("github.com", "githu%62.com");
+       expect_decode_pass("github.com", "github%2ecom");
+       expect_decode_pass("foo bar baz", "foo%20bar%20baz");
+       expect_decode_pass("foo bar baz", "foo%20bar%20baz");
+       expect_decode_pass("foo bar ", "foo%20bar%20");
+}
+
+void test_str_percent__ignores_invalid(void)
+{
+       expect_decode_pass("githu%%.com", "githu%%.com");
+       expect_decode_pass("github.co%2", "github.co%2");
+       expect_decode_pass("github%2.com", "github%2.com");
+       expect_decode_pass("githu%2z.com", "githu%2z.com");
+       expect_decode_pass("github.co%9z", "github.co%9z");
+       expect_decode_pass("github.co%2", "github.co%2");
+       expect_decode_pass("github.co%", "github.co%");
+}
diff --git a/tests/str/quote.c b/tests/str/quote.c
new file mode 100644 (file)
index 0000000..2c65462
--- /dev/null
@@ -0,0 +1,87 @@
+#include "clar_libgit2.h"
+
+static void expect_quote_pass(const char *expected, const char *str)
+{
+       git_str buf = GIT_STR_INIT;
+
+       cl_git_pass(git_str_puts(&buf, str));
+       cl_git_pass(git_str_quote(&buf));
+
+       cl_assert_equal_s(expected, git_str_cstr(&buf));
+       cl_assert_equal_i(strlen(expected), git_str_len(&buf));
+
+       git_str_dispose(&buf);
+}
+
+void test_str_quote__quote_succeeds(void)
+{
+       expect_quote_pass("", "");
+       expect_quote_pass("foo", "foo");
+       expect_quote_pass("foo/bar/baz.c", "foo/bar/baz.c");
+       expect_quote_pass("foo bar", "foo bar");
+       expect_quote_pass("\"\\\"leading quote\"", "\"leading quote");
+       expect_quote_pass("\"slash\\\\y\"", "slash\\y");
+       expect_quote_pass("\"foo\\r\\nbar\"", "foo\r\nbar");
+       expect_quote_pass("\"foo\\177bar\"", "foo\177bar");
+       expect_quote_pass("\"foo\\001bar\"", "foo\001bar");
+       expect_quote_pass("\"foo\\377bar\"", "foo\377bar");
+}
+
+static void expect_unquote_pass(const char *expected, const char *quoted)
+{
+       git_str buf = GIT_STR_INIT;
+
+       cl_git_pass(git_str_puts(&buf, quoted));
+       cl_git_pass(git_str_unquote(&buf));
+
+       cl_assert_equal_s(expected, git_str_cstr(&buf));
+       cl_assert_equal_i(strlen(expected), git_str_len(&buf));
+
+       git_str_dispose(&buf);
+}
+
+static void expect_unquote_fail(const char *quoted)
+{
+       git_str buf = GIT_STR_INIT;
+
+       cl_git_pass(git_str_puts(&buf, quoted));
+       cl_git_fail(git_str_unquote(&buf));
+
+       git_str_dispose(&buf);
+}
+
+void test_str_quote__unquote_succeeds(void)
+{
+       expect_unquote_pass("", "\"\"");
+       expect_unquote_pass(" ", "\" \"");
+       expect_unquote_pass("foo", "\"foo\"");
+       expect_unquote_pass("foo bar", "\"foo bar\"");
+       expect_unquote_pass("foo\"bar", "\"foo\\\"bar\"");
+       expect_unquote_pass("foo\\bar", "\"foo\\\\bar\"");
+       expect_unquote_pass("foo\tbar", "\"foo\\tbar\"");
+       expect_unquote_pass("\vfoo\tbar\n", "\"\\vfoo\\tbar\\n\"");
+       expect_unquote_pass("foo\nbar", "\"foo\\012bar\"");
+       expect_unquote_pass("foo\r\nbar", "\"foo\\015\\012bar\"");
+       expect_unquote_pass("foo\r\nbar", "\"\\146\\157\\157\\015\\012\\142\\141\\162\"");
+       expect_unquote_pass("newline: \n", "\"newline: \\012\"");
+       expect_unquote_pass("0xff: \377", "\"0xff: \\377\"");
+}
+
+void test_str_quote__unquote_fails(void)
+{
+       expect_unquote_fail("no quotes at all");
+       expect_unquote_fail("\"no trailing quote");
+       expect_unquote_fail("no leading quote\"");
+       expect_unquote_fail("\"invalid \\z escape char\"");
+       expect_unquote_fail("\"\\q invalid escape char\"");
+       expect_unquote_fail("\"invalid escape char \\p\"");
+       expect_unquote_fail("\"invalid \\1 escape char \"");
+       expect_unquote_fail("\"invalid \\14 escape char \"");
+       expect_unquote_fail("\"invalid \\280 escape char\"");
+       expect_unquote_fail("\"invalid \\378 escape char\"");
+       expect_unquote_fail("\"invalid \\380 escape char\"");
+       expect_unquote_fail("\"invalid \\411 escape char\"");
+       expect_unquote_fail("\"truncated escape char \\\"");
+       expect_unquote_fail("\"truncated escape char \\0\"");
+       expect_unquote_fail("\"truncated escape char \\01\"");
+}
diff --git a/tests/str/splice.c b/tests/str/splice.c
new file mode 100644 (file)
index 0000000..14e844e
--- /dev/null
@@ -0,0 +1,92 @@
+#include "clar_libgit2.h"
+
+static git_str _buf;
+
+void test_str_splice__initialize(void) {
+   git_str_init(&_buf, 16);
+}
+
+void test_str_splice__cleanup(void) {
+   git_str_dispose(&_buf);
+}
+
+void test_str_splice__preprend(void)
+{
+       git_str_sets(&_buf, "world!");
+
+       cl_git_pass(git_str_splice(&_buf, 0, 0, "Hello Dolly", strlen("Hello ")));
+
+       cl_assert_equal_s("Hello world!", git_str_cstr(&_buf));
+}
+
+void test_str_splice__append(void)
+{
+       git_str_sets(&_buf, "Hello");
+
+       cl_git_pass(git_str_splice(&_buf, git_str_len(&_buf), 0, " world!", strlen(" world!")));
+
+       cl_assert_equal_s("Hello world!", git_str_cstr(&_buf));
+}
+
+void test_str_splice__insert_at(void)
+{
+       git_str_sets(&_buf, "Hell world!");
+
+       cl_git_pass(git_str_splice(&_buf, strlen("Hell"), 0, "o", strlen("o")));
+
+       cl_assert_equal_s("Hello world!", git_str_cstr(&_buf));
+}
+
+void test_str_splice__remove_at(void)
+{
+       git_str_sets(&_buf, "Hello world of warcraft!");
+
+       cl_git_pass(git_str_splice(&_buf, strlen("Hello world"), strlen(" of warcraft"), "", 0));
+
+       cl_assert_equal_s("Hello world!", git_str_cstr(&_buf));
+}
+
+void test_str_splice__replace(void)
+{
+       git_str_sets(&_buf, "Hell0 w0rld!");
+
+       cl_git_pass(git_str_splice(&_buf, strlen("Hell"), strlen("0 w0"), "o wo", strlen("o wo")));
+
+       cl_assert_equal_s("Hello world!", git_str_cstr(&_buf));
+}
+
+void test_str_splice__replace_with_longer(void)
+{
+       git_str_sets(&_buf, "Hello you!");
+
+       cl_git_pass(git_str_splice(&_buf, strlen("Hello "), strlen("you"), "world", strlen("world")));
+
+       cl_assert_equal_s("Hello world!", git_str_cstr(&_buf));
+}
+
+void test_str_splice__replace_with_shorter(void)
+{
+       git_str_sets(&_buf, "Brave new world!");
+
+       cl_git_pass(git_str_splice(&_buf, 0, strlen("Brave new"), "Hello", strlen("Hello")));
+
+       cl_assert_equal_s("Hello world!", git_str_cstr(&_buf));
+}
+
+void test_str_splice__truncate(void)
+{
+       git_str_sets(&_buf, "Hello world!!");
+
+       cl_git_pass(git_str_splice(&_buf, strlen("Hello world!"), strlen("!"), "", 0));
+
+       cl_assert_equal_s("Hello world!", git_str_cstr(&_buf));
+}
+
+void test_str_splice__dont_do_anything(void)
+{
+       git_str_sets(&_buf, "Hello world!");
+
+       cl_git_pass(git_str_splice(&_buf, 3, 0, "Hello", 0));
+
+       cl_assert_equal_s("Hello world!", git_str_cstr(&_buf));
+}
index 2ea0d4076113f400cd42550ef03fa5cd1089a1d6..aecf08bbe332355b4e312de2a3d218546cef9528 100644 (file)
@@ -90,7 +90,7 @@ void test_stress_diff__rename_big_files(void)
        git_index *index;
        char tmp[64];
        int i, j;
-       git_buf b = GIT_BUF_INIT;
+       git_str b = GIT_STR_INIT;
 
        g_repo = cl_git_sandbox_init("renames");
 
@@ -99,7 +99,7 @@ void test_stress_diff__rename_big_files(void)
        for (i = 0; i < 100; i += 1) {
                p_snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i);
                for (j = i * 256; j > 0; --j)
-                       git_buf_printf(&b, "more content %d\n", i);
+                       git_str_printf(&b, "more content %d\n", i);
                cl_git_mkfile(tmp, b.ptr);
        }
 
@@ -108,7 +108,7 @@ void test_stress_diff__rename_big_files(void)
                cl_git_pass(git_index_add_bypath(index, tmp + strlen("renames/")));
        }
 
-       git_buf_dispose(&b);
+       git_str_dispose(&b);
        git_index_free(index);
 
        test_with_many(100);
@@ -119,13 +119,13 @@ void test_stress_diff__rename_many_files(void)
        git_index *index;
        char tmp[64];
        int i;
-       git_buf b = GIT_BUF_INIT;
+       git_str b = GIT_STR_INIT;
 
        g_repo = cl_git_sandbox_init("renames");
 
        cl_git_pass(git_repository_index(&index, g_repo));
 
-       git_buf_printf(&b, "%08d\n" ANOTHER_POEM "%08d\n" ANOTHER_POEM ANOTHER_POEM, 0, 0);
+       git_str_printf(&b, "%08d\n" ANOTHER_POEM "%08d\n" ANOTHER_POEM ANOTHER_POEM, 0, 0);
 
        for (i = 0; i < 2500; i += 1) {
                p_snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i);
@@ -133,7 +133,7 @@ void test_stress_diff__rename_many_files(void)
                b.ptr[8] = '\n';
                cl_git_mkfile(tmp, b.ptr);
        }
-       git_buf_dispose(&b);
+       git_str_dispose(&b);
 
        for (i = 0; i < 2500; i += 1) {
                p_snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i);
index fc458f82621aa0c58da3b2e8adf2ceaa71c8e0b4..ae5507d7f521bc743b794fd2dee4eaeb2d029f57 100644 (file)
@@ -17,20 +17,20 @@ void test_submodule_add__cleanup(void)
 
 static void assert_submodule_url(const char* name, const char *url)
 {
-       git_buf key = GIT_BUF_INIT;
+       git_str key = GIT_STR_INIT;
 
 
-       cl_git_pass(git_buf_printf(&key, "submodule.%s.url", name));
-       assert_config_entry_value(g_repo, git_buf_cstr(&key), url);
+       cl_git_pass(git_str_printf(&key, "submodule.%s.url", name));
+       assert_config_entry_value(g_repo, git_str_cstr(&key), url);
 
-       git_buf_dispose(&key);
+       git_str_dispose(&key);
 }
 
 void test_submodule_add__url_absolute(void)
 {
        git_submodule *sm;
        git_repository *repo;
-       git_buf dot_git_content = GIT_BUF_INIT;
+       git_str dot_git_content = GIT_STR_INIT;
 
        g_repo = setup_fixture_submod2();
 
@@ -46,11 +46,11 @@ void test_submodule_add__url_absolute(void)
                );
        git_submodule_free(sm);
 
-       cl_assert(git_path_isfile("submod2/" "sm_libgit2" "/.git"));
+       cl_assert(git_fs_path_isfile("submod2/" "sm_libgit2" "/.git"));
 
-       cl_assert(git_path_isdir("submod2/.git/modules"));
-       cl_assert(git_path_isdir("submod2/.git/modules/" "sm_libgit2"));
-       cl_assert(git_path_isfile("submod2/.git/modules/" "sm_libgit2" "/HEAD"));
+       cl_assert(git_fs_path_isdir("submod2/.git/modules"));
+       cl_assert(git_fs_path_isdir("submod2/.git/modules/" "sm_libgit2"));
+       cl_assert(git_fs_path_isfile("submod2/.git/modules/" "sm_libgit2" "/HEAD"));
        assert_submodule_url("sm_libgit2", "https://github.com/libgit2/libgit2.git");
 
        cl_git_pass(git_repository_open(&repo, "submod2/" "sm_libgit2"));
@@ -63,7 +63,7 @@ void test_submodule_add__url_absolute(void)
        cl_assert_equal_s("gitdir: ../.git/modules/sm_libgit2/", dot_git_content.ptr);
 
        git_repository_free(repo);
-       git_buf_dispose(&dot_git_content);
+       git_str_dispose(&dot_git_content);
 
        /* add a submodule not using a gitlink */
 
@@ -72,9 +72,9 @@ void test_submodule_add__url_absolute(void)
                );
        git_submodule_free(sm);
 
-       cl_assert(git_path_isdir("submod2/" "sm_libgit2b" "/.git"));
-       cl_assert(git_path_isfile("submod2/" "sm_libgit2b" "/.git/HEAD"));
-       cl_assert(!git_path_exists("submod2/.git/modules/" "sm_libgit2b"));
+       cl_assert(git_fs_path_isdir("submod2/" "sm_libgit2b" "/.git"));
+       cl_assert(git_fs_path_isfile("submod2/" "sm_libgit2b" "/.git/HEAD"));
+       cl_assert(!git_fs_path_exists("submod2/.git/modules/" "sm_libgit2b"));
        assert_submodule_url("sm_libgit2b", "https://github.com/libgit2/libgit2.git");
 }
 
@@ -151,11 +151,11 @@ void test_submodule_add__path_exists_in_index(void)
 {
        git_index *index;
        git_submodule *sm;
-       git_buf filename = GIT_BUF_INIT;
+       git_str filename = GIT_STR_INIT;
 
        g_repo = cl_git_sandbox_init("testrepo");
 
-       cl_git_pass(git_buf_joinpath(&filename, "subdirectory", "test.txt"));
+       cl_git_pass(git_str_joinpath(&filename, "subdirectory", "test.txt"));
 
        cl_git_pass(git_repository_index__weakptr(&index, g_repo));
 
@@ -164,14 +164,14 @@ void test_submodule_add__path_exists_in_index(void)
        cl_git_fail_with(git_submodule_add_setup(&sm, g_repo, "./", "subdirectory", 1), GIT_EEXISTS);
 
        git_submodule_free(sm);
-       git_buf_dispose(&filename);
+       git_str_dispose(&filename);
 }
 
 void test_submodule_add__file_exists_in_index(void)
 {
        git_index *index;
        git_submodule *sm;
-       git_buf name = GIT_BUF_INIT;
+       git_str name = GIT_STR_INIT;
 
        g_repo = cl_git_sandbox_init("testrepo");
 
@@ -182,7 +182,7 @@ void test_submodule_add__file_exists_in_index(void)
        cl_git_fail_with(git_submodule_add_setup(&sm, g_repo, "./", "subdirectory", 1), GIT_EEXISTS);
 
        git_submodule_free(sm);
-       git_buf_dispose(&name);
+       git_str_dispose(&name);
 }
 
 void test_submodule_add__submodule_clone(void)
@@ -227,7 +227,7 @@ void test_submodule_add__submodule_clone_into_nonempty_dir_succeeds(void)
        cl_git_pass(git_submodule_clone(NULL, sm, NULL));
        cl_git_pass(git_submodule_add_finalize(sm));
 
-       cl_assert(git_path_exists("empty_standard_repo/sm/foobar"));
+       cl_assert(git_fs_path_exists("empty_standard_repo/sm/foobar"));
 
        assert_submodule_exists(g_repo, "sm");
 
index 08eb7680972d34296561c4c9e24324f662107343..bcd52b510b03d913ac51b8f45d3e783bf6cde3e4 100644 (file)
@@ -33,17 +33,17 @@ void test_submodule_escape__from_gitdir(void)
 {
        int foundit;
        git_submodule *sm;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        unsigned int sm_location;
 
        g_repo = setup_fixture_submodule_simple();
 
-       cl_git_pass(git_buf_joinpath(&buf, git_repository_workdir(g_repo), ".gitmodules"));
+       cl_git_pass(git_str_joinpath(&buf, git_repository_workdir(g_repo), ".gitmodules"));
        cl_git_rewritefile(buf.ptr,
                           "[submodule \"" EVIL_SM_NAME "\"]\n"
                           "    path = testrepo\n"
                           "    url = ../testrepo.git\n");
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        /* Find it all the different ways we know about it */
        foundit = 0;
@@ -67,17 +67,17 @@ void test_submodule_escape__from_gitdir_windows(void)
 {
        int foundit;
        git_submodule *sm;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
        unsigned int sm_location;
 
        g_repo = setup_fixture_submodule_simple();
 
-       cl_git_pass(git_buf_joinpath(&buf, git_repository_workdir(g_repo), ".gitmodules"));
+       cl_git_pass(git_str_joinpath(&buf, git_repository_workdir(g_repo), ".gitmodules"));
        cl_git_rewritefile(buf.ptr,
                           "[submodule \"" EVIL_SM_NAME_WINDOWS "\"]\n"
                           "    path = testrepo\n"
                           "    url = ../testrepo.git\n");
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        /* Find it all the different ways we know about it */
        foundit = 0;
index a1d870b9e744629ddb27a610ed5268a88c7a528a..a8e1291c4e0ea7edda74f66aa52887f93fc422e8 100644 (file)
@@ -15,13 +15,13 @@ void test_submodule_init__absolute_url(void)
 {
        git_submodule *sm;
        git_config *cfg;
-       git_buf absolute_url = GIT_BUF_INIT;
+       git_str absolute_url = GIT_STR_INIT;
        const char *config_url;
 
        g_repo = setup_fixture_submodule_simple();
 
-       cl_assert(git_path_dirname_r(&absolute_url, git_repository_workdir(g_repo)) > 0);
-       cl_git_pass(git_buf_joinpath(&absolute_url, absolute_url.ptr, "testrepo.git"));
+       cl_assert(git_fs_path_dirname_r(&absolute_url, git_repository_workdir(g_repo)) > 0);
+       cl_git_pass(git_str_joinpath(&absolute_url, absolute_url.ptr, "testrepo.git"));
 
        /* write the absolute url to the .gitmodules file*/
        cl_git_pass(git_submodule_set_url(g_repo, "testrepo", absolute_url.ptr));
@@ -39,7 +39,7 @@ void test_submodule_init__absolute_url(void)
        cl_git_pass(git_config_get_string(&config_url, cfg, "submodule.testrepo.url"));
        cl_assert_equal_s(absolute_url.ptr, config_url);
 
-       git_buf_dispose(&absolute_url);
+       git_str_dispose(&absolute_url);
        git_config_free(cfg);
        git_submodule_free(sm);
 }
@@ -48,13 +48,13 @@ void test_submodule_init__relative_url(void)
 {
        git_submodule *sm;
        git_config *cfg;
-       git_buf absolute_url = GIT_BUF_INIT;
+       git_str absolute_url = GIT_STR_INIT;
        const char *config_url;
 
        g_repo = setup_fixture_submodule_simple();
 
-       cl_assert(git_path_dirname_r(&absolute_url, git_repository_workdir(g_repo)) > 0);
-       cl_git_pass(git_buf_joinpath(&absolute_url, absolute_url.ptr, "testrepo.git"));
+       cl_assert(git_fs_path_dirname_r(&absolute_url, git_repository_workdir(g_repo)) > 0);
+       cl_git_pass(git_str_joinpath(&absolute_url, absolute_url.ptr, "testrepo.git"));
 
        cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo"));
 
@@ -69,7 +69,7 @@ void test_submodule_init__relative_url(void)
        cl_git_pass(git_config_get_string(&config_url, cfg, "submodule.testrepo.url"));
        cl_assert_equal_s(absolute_url.ptr, config_url);
 
-       git_buf_dispose(&absolute_url);
+       git_str_dispose(&absolute_url);
        git_config_free(cfg);
        git_submodule_free(sm);
 }
@@ -78,7 +78,7 @@ void test_submodule_init__relative_url_detached_head(void)
 {
        git_submodule *sm;
        git_config *cfg;
-       git_buf absolute_url = GIT_BUF_INIT;
+       git_str absolute_url = GIT_STR_INIT;
        const char *config_url;
        git_reference *head_ref = NULL;
        git_object *head_commit = NULL;
@@ -91,8 +91,8 @@ void test_submodule_init__relative_url_detached_head(void)
 
        cl_git_pass(git_repository_set_head_detached(g_repo, git_commit_id((git_commit *)head_commit)));
 
-       cl_assert(git_path_dirname_r(&absolute_url, git_repository_workdir(g_repo)) > 0);
-       cl_git_pass(git_buf_joinpath(&absolute_url, absolute_url.ptr, "testrepo.git"));
+       cl_assert(git_fs_path_dirname_r(&absolute_url, git_repository_workdir(g_repo)) > 0);
+       cl_git_pass(git_str_joinpath(&absolute_url, absolute_url.ptr, "testrepo.git"));
 
        cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo"));
 
@@ -107,7 +107,7 @@ void test_submodule_init__relative_url_detached_head(void)
        cl_git_pass(git_config_get_string(&config_url, cfg, "submodule.testrepo.url"));
        cl_assert_equal_s(absolute_url.ptr, config_url);
 
-       git_buf_dispose(&absolute_url);
+       git_str_dispose(&absolute_url);
        git_config_free(cfg);
        git_object_free(head_commit);
        git_reference_free(head_ref);
index cfc02acff53c3274926096a68b88275002d4ea62..e28ff8489012074a21a36bdfbbe285c66fcf77e3 100644 (file)
@@ -33,14 +33,14 @@ void test_submodule_inject_option__url(void)
 {
        int foundit;
        git_submodule *sm;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&buf, git_repository_workdir(g_repo), ".gitmodules"));
+       cl_git_pass(git_str_joinpath(&buf, git_repository_workdir(g_repo), ".gitmodules"));
        cl_git_rewritefile(buf.ptr,
                           "[submodule \"naughty\"]\n"
                           "    path = testrepo\n"
                           "    url = -u./payload\n");
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        /* We do want to find it, but with the appropriate field empty */
        foundit = 0;
@@ -58,14 +58,14 @@ void test_submodule_inject_option__path(void)
 {
        int foundit;
        git_submodule *sm;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&buf, git_repository_workdir(g_repo), ".gitmodules"));
+       cl_git_pass(git_str_joinpath(&buf, git_repository_workdir(g_repo), ".gitmodules"));
        cl_git_rewritefile(buf.ptr,
                           "[submodule \"naughty\"]\n"
                           "    path = --something\n"
                           "    url = blah.git\n");
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        /* We do want to find it, but with the appropriate field empty */
        foundit = 0;
index f49ebb4bdc60b4eec16844c4516120329125a1a4..acfdc838c2693dec0acc8dfbad304bc341f0e762 100644 (file)
@@ -255,7 +255,7 @@ static void add_submodule_with_commit(const char *name)
        git_submodule *sm;
        git_repository *smrepo;
        git_index *idx;
-       git_buf p = GIT_BUF_INIT;
+       git_str p = GIT_STR_INIT;
 
        cl_git_pass(git_submodule_add_setup(&sm, g_repo,
                "https://github.com/libgit2/libgit2.git", name, 1));
@@ -265,9 +265,9 @@ static void add_submodule_with_commit(const char *name)
        cl_git_pass(git_submodule_open(&smrepo, sm));
        cl_git_pass(git_repository_index(&idx, smrepo));
 
-       cl_git_pass(git_buf_joinpath(&p, git_repository_workdir(smrepo), "file"));
+       cl_git_pass(git_str_joinpath(&p, git_repository_workdir(smrepo), "file"));
        cl_git_mkfile(p.ptr, "new file");
-       git_buf_dispose(&p);
+       git_str_dispose(&p);
 
        cl_git_pass(git_index_add_bypath(idx, "file"));
        cl_git_pass(git_index_write(idx));
@@ -284,7 +284,7 @@ static void add_submodule_with_commit(const char *name)
 void test_submodule_lookup__just_added(void)
 {
        git_submodule *sm;
-       git_buf snap1 = GIT_BUF_INIT, snap2 = GIT_BUF_INIT;
+       git_str snap1 = GIT_STR_INIT, snap2 = GIT_STR_INIT;
        git_reference *original_head = NULL;
 
        refute_submodule_exists(g_repo, "sm_just_added", GIT_ENOTFOUND);
@@ -333,7 +333,7 @@ void test_submodule_lookup__just_added(void)
        baseline_tests();
 
        cl_git_rewritefile("submod2/.gitmodules", snap2.ptr);
-       git_buf_dispose(&snap2);
+       git_str_dispose(&snap2);
 
        refute_submodule_exists(g_repo, "mismatch_name", GIT_ENOTFOUND);
        refute_submodule_exists(g_repo, "mismatch_path", GIT_ENOTFOUND);
@@ -344,7 +344,7 @@ void test_submodule_lookup__just_added(void)
        baseline_tests();
 
        cl_git_rewritefile("submod2/.gitmodules", snap1.ptr);
-       git_buf_dispose(&snap1);
+       git_str_dispose(&snap1);
 
        refute_submodule_exists(g_repo, "mismatch_name", GIT_ENOTFOUND);
        refute_submodule_exists(g_repo, "mismatch_path", GIT_ENOTFOUND);
index 654f677e606e7a0872fd8eceb1f4e005cea5961b..7e7f0ca15923fdf27c23d3c6b3a3ee801deb18b7 100644 (file)
@@ -128,7 +128,7 @@ void test_submodule_modify__sync(void)
        git_submodule_free(sm3);
 }
 
-void assert_ignore_change(git_submodule_ignore_t ignore)
+static void assert_ignore_change(git_submodule_ignore_t ignore)
 {
        git_submodule *sm;
 
@@ -146,7 +146,7 @@ void test_submodule_modify__set_ignore(void)
        assert_ignore_change(GIT_SUBMODULE_IGNORE_ALL);
 }
 
-void assert_update_change(git_submodule_update_t update)
+static void assert_update_change(git_submodule_update_t update)
 {
        git_submodule *sm;
 
@@ -164,7 +164,7 @@ void test_submodule_modify__set_update(void)
        assert_update_change(GIT_SUBMODULE_UPDATE_CHECKOUT);
 }
 
-void assert_recurse_change(git_submodule_recurse_t recurse)
+static void assert_recurse_change(git_submodule_recurse_t recurse)
 {
        git_submodule *sm;
 
@@ -213,7 +213,7 @@ void test_submodule_modify__set_url(void)
 
 void test_submodule_modify__set_relative_url(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_repository *repo;
        git_submodule *sm;
 
@@ -222,12 +222,12 @@ void test_submodule_modify__set_relative_url(void)
        cl_git_pass(git_submodule_sync(sm));
        cl_git_pass(git_submodule_open(&repo, sm));
 
-       cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), "relative-url"));
+       cl_git_pass(git_str_joinpath(&path, clar_sandbox_path(), "relative-url"));
 
        assert_config_entry_value(g_repo, "submodule."SM1".url", path.ptr);
        assert_config_entry_value(repo, "remote.origin.url", path.ptr);
 
        git_repository_free(repo);
        git_submodule_free(sm);
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
index e47ee39836e73072a01eda1ffe2fb508f66be787..e82230e87c2d678b7850e89b99c54c9328b32d53 100644 (file)
@@ -69,7 +69,7 @@ void test_submodule_nosubs__add_and_delete(void)
 {
        git_repository *repo = cl_git_sandbox_init("status");
        git_submodule *sm;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
        cl_git_fail(git_submodule_lookup(NULL, repo, "libgit2"));
        cl_git_fail(git_submodule_lookup(NULL, repo, "submodules/libgit2"));
@@ -85,7 +85,7 @@ void test_submodule_nosubs__add_and_delete(void)
        cl_git_pass(git_futils_readbuffer(&buf, "status/.gitmodules"));
        cl_assert(strstr(buf.ptr, "[submodule \"submodules/libgit2\"]") != NULL);
        cl_assert(strstr(buf.ptr, "path = submodules/libgit2") != NULL);
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
 
        /* lookup */
 
index a8a5dccc34e99d54eae85944e042ea57f77e98e9..e6883d208816892c57cc7db74c274f169a214c7a 100644 (file)
@@ -23,33 +23,33 @@ void test_submodule_open__cleanup(void)
 
 static void assert_sm_valid(git_repository *parent, git_repository *child, const char *sm_name)
 {
-       git_buf expected = GIT_BUF_INIT, actual = GIT_BUF_INIT;
+       git_str expected = GIT_STR_INIT, actual = GIT_STR_INIT;
 
        /* assert working directory */
-       cl_git_pass(git_buf_joinpath(&expected, git_repository_workdir(parent), sm_name));
-       cl_git_pass(git_path_prettify_dir(&expected, expected.ptr, NULL));
-       cl_git_pass(git_buf_sets(&actual, git_repository_workdir(child)));
-       cl_git_pass(git_path_prettify_dir(&actual, actual.ptr, NULL));
+       cl_git_pass(git_str_joinpath(&expected, git_repository_workdir(parent), sm_name));
+       cl_git_pass(git_fs_path_prettify_dir(&expected, expected.ptr, NULL));
+       cl_git_pass(git_str_sets(&actual, git_repository_workdir(child)));
+       cl_git_pass(git_fs_path_prettify_dir(&actual, actual.ptr, NULL));
        cl_assert_equal_s(expected.ptr, actual.ptr);
 
-       git_buf_clear(&expected);
-       git_buf_clear(&actual);
+       git_str_clear(&expected);
+       git_str_clear(&actual);
 
        /* assert common directory */
-       cl_git_pass(git_buf_joinpath(&expected, git_repository_commondir(parent), "modules"));
-       cl_git_pass(git_buf_joinpath(&expected, expected.ptr, sm_name));
-       cl_git_pass(git_path_prettify_dir(&expected, expected.ptr, NULL));
-       cl_git_pass(git_buf_sets(&actual, git_repository_commondir(child)));
-       cl_git_pass(git_path_prettify_dir(&actual, actual.ptr, NULL));
+       cl_git_pass(git_str_joinpath(&expected, git_repository_commondir(parent), "modules"));
+       cl_git_pass(git_str_joinpath(&expected, expected.ptr, sm_name));
+       cl_git_pass(git_fs_path_prettify_dir(&expected, expected.ptr, NULL));
+       cl_git_pass(git_str_sets(&actual, git_repository_commondir(child)));
+       cl_git_pass(git_fs_path_prettify_dir(&actual, actual.ptr, NULL));
        cl_assert_equal_s(expected.ptr, actual.ptr);
 
        /* assert git directory */
-       cl_git_pass(git_buf_sets(&actual, git_repository_path(child)));
-       cl_git_pass(git_path_prettify_dir(&actual, actual.ptr, NULL));
+       cl_git_pass(git_str_sets(&actual, git_repository_path(child)));
+       cl_git_pass(git_fs_path_prettify_dir(&actual, actual.ptr, NULL));
        cl_assert_equal_s(expected.ptr, actual.ptr);
 
-       git_buf_dispose(&expected);
-       git_buf_dispose(&actual);
+       git_str_dispose(&expected);
+       git_str_dispose(&actual);
 }
 
 void test_submodule_open__opening_via_lookup_succeeds(void)
@@ -61,18 +61,18 @@ void test_submodule_open__opening_via_lookup_succeeds(void)
 
 void test_submodule_open__direct_open_succeeds(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_parent), "sm_unchanged"));
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(g_parent), "sm_unchanged"));
        cl_git_pass(git_repository_open(&g_child, path.ptr));
        assert_sm_valid(g_parent, g_child, "sm_unchanged");
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_submodule_open__direct_open_succeeds_for_broken_sm_with_gitdir(void)
 {
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        /*
         * This is actually not a valid submodule, but we
@@ -82,9 +82,9 @@ void test_submodule_open__direct_open_succeeds_for_broken_sm_with_gitdir(void)
         * add a test for this.
         */
        cl_git_mkfile("submod2/.git/modules/sm_unchanged/gitdir", ".git");
-       cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_parent), "sm_unchanged"));
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(g_parent), "sm_unchanged"));
        cl_git_pass(git_repository_open(&g_child, path.ptr));
        assert_sm_valid(g_parent, g_child, "sm_unchanged");
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
index 9962af311ef58f12d9332a1b1f3d7be8673360f3..39b55c403df83c0771aa14aed50bff32eddf6d8b 100644 (file)
@@ -11,7 +11,7 @@ void test_submodule_repository_init__basic(void)
 {
        git_submodule *sm;
        git_repository *repo;
-       git_buf dot_git_content = GIT_BUF_INIT;
+       git_str dot_git_content = GIT_STR_INIT;
 
        g_repo = setup_fixture_submod2();
 
@@ -26,13 +26,13 @@ void test_submodule_repository_init__basic(void)
        cl_git_pass(git_futils_readbuffer(&dot_git_content, "submod2/" "sm_gitmodules_only" "/.git"));
        cl_assert_equal_s("gitdir: ../.git/modules/sm_gitmodules_only/", dot_git_content.ptr);
 
-       cl_assert(git_path_isfile("submod2/" "sm_gitmodules_only" "/.git"));
+       cl_assert(git_fs_path_isfile("submod2/" "sm_gitmodules_only" "/.git"));
 
-       cl_assert(git_path_isdir("submod2/.git/modules"));
-       cl_assert(git_path_isdir("submod2/.git/modules/" "sm_gitmodules_only"));
-       cl_assert(git_path_isfile("submod2/.git/modules/" "sm_gitmodules_only" "/HEAD"));
+       cl_assert(git_fs_path_isdir("submod2/.git/modules"));
+       cl_assert(git_fs_path_isdir("submod2/.git/modules/" "sm_gitmodules_only"));
+       cl_assert(git_fs_path_isfile("submod2/.git/modules/" "sm_gitmodules_only" "/HEAD"));
 
        git_submodule_free(sm);
        git_repository_free(repo);
-       git_buf_dispose(&dot_git_content);
+       git_str_dispose(&dot_git_content);
 }
index 06595cc9aa2d86e227314a86b375974e72b54ce4..1d41337b7c3f11e531342e899ace8f2ca8d886e7 100644 (file)
@@ -31,10 +31,10 @@ void test_submodule_status__unchanged(void)
 
 static void rm_submodule(const char *name)
 {
-       git_buf path = GIT_BUF_INIT;
-       cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), name));
+       git_str path = GIT_STR_INIT;
+       cl_git_pass(git_str_joinpath(&path, git_repository_workdir(g_repo), name));
        cl_git_pass(git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES));
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 static void add_submodule_to_index(const char *name)
index 1d4759616d02b4594dcd26438803d95bcf698e4d..b8fc9f60deb8d8ddfe7e2c334e1ef61d4c1810cf 100644 (file)
@@ -1,5 +1,4 @@
 #include "clar_libgit2.h"
-#include "buffer.h"
 #include "path.h"
 #include "util.h"
 #include "posix.h"
  */
 void rewrite_gitmodules(const char *workdir)
 {
-       git_buf in_f = GIT_BUF_INIT, out_f = GIT_BUF_INIT, path = GIT_BUF_INIT;
+       git_str in_f = GIT_STR_INIT, out_f = GIT_STR_INIT, path = GIT_STR_INIT;
        FILE *in, *out;
        char line[256];
 
-       cl_git_pass(git_buf_joinpath(&in_f, workdir, "gitmodules"));
-       cl_git_pass(git_buf_joinpath(&out_f, workdir, ".gitmodules"));
+       cl_git_pass(git_str_joinpath(&in_f, workdir, "gitmodules"));
+       cl_git_pass(git_str_joinpath(&out_f, workdir, ".gitmodules"));
 
        cl_assert((in  = fopen(in_f.ptr, "rb")) != NULL);
        cl_assert((out = fopen(out_f.ptr, "wb")) != NULL);
@@ -32,16 +31,16 @@ void rewrite_gitmodules(const char *workdir)
                        scan += strlen("path =");
                        while (*scan == ' ') scan++;
 
-                       git_buf_joinpath(&path, workdir, scan);
-                       git_buf_rtrim(&path);
-                       git_buf_joinpath(&path, path.ptr, ".gitted");
+                       git_str_joinpath(&path, workdir, scan);
+                       git_str_rtrim(&path);
+                       git_str_joinpath(&path, path.ptr, ".gitted");
 
-                       if (!git_buf_oom(&path) && p_access(path.ptr, F_OK) == 0) {
-                               git_buf_joinpath(&out_f, workdir, scan);
-                               git_buf_rtrim(&out_f);
-                               git_buf_joinpath(&out_f, out_f.ptr, ".git");
+                       if (!git_str_oom(&path) && p_access(path.ptr, F_OK) == 0) {
+                               git_str_joinpath(&out_f, workdir, scan);
+                               git_str_rtrim(&out_f);
+                               git_str_joinpath(&out_f, out_f.ptr, ".git");
 
-                               if (!git_buf_oom(&out_f))
+                               if (!git_str_oom(&out_f))
                                        p_rename(path.ptr, out_f.ptr);
                        }
                }
@@ -57,18 +56,18 @@ void rewrite_gitmodules(const char *workdir)
                while (*scan == ' ') scan++;
 
                if (*scan == '.') {
-                       git_buf_joinpath(&path, workdir, scan);
-                       git_buf_rtrim(&path);
+                       git_str_joinpath(&path, workdir, scan);
+                       git_str_rtrim(&path);
                } else if (!*scan || *scan == '\n') {
-                       git_buf_joinpath(&path, workdir, "../testrepo.git");
+                       git_str_joinpath(&path, workdir, "../testrepo.git");
                } else {
                        fputs(line, out);
                        continue;
                }
 
-               git_path_prettify(&path, path.ptr, NULL);
-               git_buf_putc(&path, '\n');
-               cl_assert(!git_buf_oom(&path));
+               git_fs_path_prettify(&path, path.ptr, NULL);
+               git_str_putc(&path, '\n');
+               cl_assert(!git_str_oom(&path));
 
                fwrite(line, scan - line, sizeof(char), out);
                fputs(path.ptr, out);
@@ -79,9 +78,9 @@ void rewrite_gitmodules(const char *workdir)
 
        cl_must_pass(p_unlink(in_f.ptr));
 
-       git_buf_dispose(&in_f);
-       git_buf_dispose(&out_f);
-       git_buf_dispose(&path);
+       git_str_dispose(&in_f);
+       git_str_dispose(&out_f);
+       git_str_dispose(&path);
 }
 
 static void cleanup_fixture_submodules(void *payload)
index 79353e5751cce4eb6fac3222930d65c83f867d7f..4aa95985227517c9bc35843cb289369bd1266bab 100644 (file)
@@ -11,7 +11,7 @@ void test_submodule_update__cleanup(void)
        cl_git_sandbox_cleanup();
 }
 
-void test_submodule_update__unitialized_submodule_no_init(void)
+void test_submodule_update__uninitialized_submodule_no_init(void)
 {
        git_submodule *sm;
        git_submodule_update_options update_options = GIT_SUBMODULE_UPDATE_OPTIONS_INIT;
@@ -21,7 +21,7 @@ void test_submodule_update__unitialized_submodule_no_init(void)
        /* get the submodule */
        cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo"));
 
-       /* updating an unitialized repository throws */
+       /* updating an uninitialized repository throws */
        cl_git_fail_with(
                GIT_ERROR,
                git_submodule_update(sm, 0, &update_options));
index a104199e27a361795bb570517e72121c24b8d9e2..3298abee659e9f2121e1fd74b984eea4e090e9d4 100644 (file)
@@ -3,9 +3,9 @@
    Memcheck:Leak
    ...
    fun:git__realloc
-   fun:git_buf_try_grow
-   fun:git_buf_grow
-   fun:git_buf_vprintf
+   fun:git_str_try_grow
+   fun:git_str_grow
+   fun:git_str_vprintf
    fun:git_error_set
 }
 {
index e02f411792b591176b601900849ca44db2e3ea01..5c007987b163376f07672a377e0c092348f2eb61 100644 (file)
@@ -1,7 +1,6 @@
 #include "clar_libgit2.h"
 
 #include "repository.h"
-#include "buffer.h"
 #include "submodule.h"
 
 static const char *repo_name = "win32-forbidden";
index f8b8c4b0ae89e2e16ef5646ae617e6f0ad49b1aa..4be86db5a610ed8d97e729242dc072fab2d74f46 100644 (file)
@@ -2,11 +2,10 @@
 
 #include "git2/clone.h"
 #include "clone.h"
-#include "buffer.h"
 #include "futils.h"
 #include "repository.h"
 
-static git_buf path = GIT_BUF_INIT;
+static git_str path = GIT_STR_INIT;
 
 #define LONG_FILENAME "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt"
 
@@ -18,20 +17,20 @@ void test_win32_longpath__initialize(void)
        size_t remain = MAX_PATH - base_len;
        size_t i;
 
-       git_buf_clear(&path);
-       git_buf_puts(&path, base);
-       git_buf_putc(&path, '/');
+       git_str_clear(&path);
+       git_str_puts(&path, base);
+       git_str_putc(&path, '/');
 
        cl_assert(remain < (MAX_PATH - 5));
 
        for (i = 0; i < (remain - 5); i++)
-               git_buf_putc(&path, 'a');
+               git_str_putc(&path, 'a');
 #endif
 }
 
 void test_win32_longpath__cleanup(void)
 {
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        cl_git_sandbox_cleanup();
 }
 
@@ -49,7 +48,7 @@ void test_win32_longpath__workdir_path_validated(void)
 {
 #ifdef GIT_WIN32
        git_repository *repo = cl_git_sandbox_init("testrepo");
-       git_buf out = GIT_BUF_INIT;
+       git_str out = GIT_STR_INIT;
 
        cl_git_pass(git_repository_workdir_path(&out, repo, "a.txt"));
 
@@ -60,7 +59,7 @@ void test_win32_longpath__workdir_path_validated(void)
        cl_repo_set_bool(repo, "core.longpaths", true);
        cl_git_pass(git_repository_workdir_path(&out, repo, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt"));
        cl_git_pass(git_repository_workdir_path(&out, repo, LONG_FILENAME));
-       git_buf_dispose(&out);
+       git_str_dispose(&out);
 #endif
 }
 
@@ -68,7 +67,7 @@ void test_win32_longpath__workdir_path_validated(void)
 static void assert_longpath_status_and_add(git_repository *repo, const char *wddata, const char *repodata) {
        git_index *index;
        git_blob *blob;
-       git_buf out = GIT_BUF_INIT;
+       git_str out = GIT_STR_INIT;
        const git_index_entry *entry;
        unsigned int status_flags;
 
@@ -91,7 +90,7 @@ static void assert_longpath_status_and_add(git_repository *repo, const char *wdd
 
        git_blob_free(blob);
        git_index_free(index);
-       git_buf_dispose(&out);
+       git_str_dispose(&out);
 }
 #endif
 
diff --git a/tests/win32/systemdir.c b/tests/win32/systemdir.c
new file mode 100644 (file)
index 0000000..52c1784
--- /dev/null
@@ -0,0 +1,338 @@
+#include "clar_libgit2.h"
+#include "futils.h"
+#include "sysdir.h"
+#include "win32/findfile.h"
+
+#ifdef GIT_WIN32
+static char *path_save;
+static git_str gfw_path_root = GIT_STR_INIT;
+static git_str gfw_registry_root = GIT_STR_INIT;
+#endif
+
+void test_win32_systemdir__initialize(void)
+{
+#ifdef GIT_WIN32
+       git_str path_env = GIT_STR_INIT;
+
+       path_save = cl_getenv("PATH");
+       git_win32__set_registry_system_dir(L"");
+
+       cl_git_pass(git_str_puts(&path_env, "C:\\GitTempTest\\Foo;\"c:\\program files\\doesnotexisttesttemp\";C:\\fakefakedoesnotexist"));
+       cl_setenv("PATH", path_env.ptr);
+
+       cl_git_pass(git_str_puts(&gfw_path_root, clar_sandbox_path()));
+       cl_git_pass(git_str_puts(&gfw_path_root, "/fake_gfw_path_install"));
+
+       cl_git_pass(git_str_puts(&gfw_registry_root, clar_sandbox_path()));
+       cl_git_pass(git_str_puts(&gfw_registry_root, "/fake_gfw_registry_install"));
+
+       git_str_dispose(&path_env);
+#endif
+}
+
+void test_win32_systemdir__cleanup(void)
+{
+#ifdef GIT_WIN32
+       cl_fixture_cleanup("fake_gfw_path_install");
+       cl_fixture_cleanup("fake_gfw_registry_install");
+       git_str_dispose(&gfw_path_root);
+       git_str_dispose(&gfw_registry_root);
+
+       cl_setenv("PATH", path_save);
+       git__free(path_save);
+       path_save = NULL;
+
+       git_win32__set_registry_system_dir(NULL);
+       cl_sandbox_set_search_path_defaults();
+#endif
+}
+
+#ifdef GIT_WIN32
+static void fix_path(git_str *s)
+{
+       char *c;
+
+       for (c = s->ptr; *c; c++) {
+               if (*c == '/')
+                       *c = '\\';
+       }
+}
+
+static void populate_fake_gfw(
+       git_str *expected_etc_dir,
+       const char *root,
+       const char *token,
+       bool create_gitconfig,
+       bool create_mingw64_gitconfig,
+       bool add_to_path,
+       bool add_to_registry)
+{
+       git_str bin_path = GIT_STR_INIT, exe_path = GIT_STR_INIT,
+       etc_path = GIT_STR_INIT, mingw64_path = GIT_STR_INIT,
+       config_path = GIT_STR_INIT, path_env = GIT_STR_INIT,
+       config_data = GIT_STR_INIT;
+
+       cl_git_pass(git_str_puts(&bin_path, root));
+       cl_git_pass(git_str_puts(&bin_path, "/cmd"));
+       cl_git_pass(git_futils_mkdir_r(bin_path.ptr, 0755));
+
+       cl_git_pass(git_str_puts(&exe_path, bin_path.ptr));
+       cl_git_pass(git_str_puts(&exe_path, "/git.cmd"));
+       cl_git_mkfile(exe_path.ptr, "This is a fake executable.");
+
+       cl_git_pass(git_str_puts(&etc_path, root));
+       cl_git_pass(git_str_puts(&etc_path, "/etc"));
+       cl_git_pass(git_futils_mkdir_r(etc_path.ptr, 0755));
+
+       cl_git_pass(git_str_puts(&mingw64_path, root));
+       cl_git_pass(git_str_puts(&mingw64_path, "/mingw64/etc"));
+       cl_git_pass(git_futils_mkdir_r(mingw64_path.ptr, 0755));
+
+       if (create_gitconfig) {
+               git_str_clear(&config_data);
+               git_str_printf(&config_data, "[gfw]\n\ttest = etc %s\n", token);
+
+               cl_git_pass(git_str_puts(&config_path, etc_path.ptr));
+               cl_git_pass(git_str_puts(&config_path, "/gitconfig"));
+               cl_git_mkfile(config_path.ptr, config_data.ptr);
+       }
+
+       if (create_mingw64_gitconfig) {
+               git_str_clear(&config_data);
+               git_str_printf(&config_data, "[gfw]\n\ttest = mingw64 %s\n", token);
+
+               git_str_clear(&config_path);
+               cl_git_pass(git_str_puts(&config_path, mingw64_path.ptr));
+               cl_git_pass(git_str_puts(&config_path, "/gitconfig"));
+               cl_git_mkfile(config_path.ptr, config_data.ptr);
+       }
+
+       if (add_to_path) {
+               fix_path(&bin_path);
+               cl_git_pass(git_str_puts(&path_env, "C:\\GitTempTest\\Foo;\"c:\\program files\\doesnotexisttesttemp\";"));
+               cl_git_pass(git_str_puts(&path_env, bin_path.ptr));
+               cl_git_pass(git_str_puts(&path_env, ";C:\\fakefakedoesnotexist"));
+               cl_setenv("PATH", path_env.ptr);
+       }
+
+       if (add_to_registry) {
+               git_win32_path registry_path;
+               size_t offset = 0;
+
+               cl_assert(git_win32_path_from_utf8(registry_path, root) >= 0);
+               if (wcsncmp(registry_path, L"\\\\?\\", CONST_STRLEN("\\\\?\\")) == 0)
+                   offset = CONST_STRLEN("\\\\?\\");
+               git_win32__set_registry_system_dir(registry_path + offset);
+       }
+
+       cl_git_pass(git_str_join(expected_etc_dir, GIT_PATH_LIST_SEPARATOR, expected_etc_dir->ptr, etc_path.ptr));
+       cl_git_pass(git_str_join(expected_etc_dir, GIT_PATH_LIST_SEPARATOR, expected_etc_dir->ptr, mingw64_path.ptr));
+
+       git_str_dispose(&bin_path);
+       git_str_dispose(&exe_path);
+       git_str_dispose(&etc_path);
+       git_str_dispose(&mingw64_path);
+       git_str_dispose(&config_path);
+       git_str_dispose(&path_env);
+       git_str_dispose(&config_data);
+}
+
+static void populate_fake_ecosystem(
+       git_str *expected_etc_dir,
+       bool create_gitconfig,
+       bool create_mingw64_gitconfig,
+       bool path,
+       bool registry)
+{
+       if (path)
+               populate_fake_gfw(expected_etc_dir, gfw_path_root.ptr, "path", create_gitconfig, create_mingw64_gitconfig, true, false);
+
+       if (registry)
+               populate_fake_gfw(expected_etc_dir, gfw_registry_root.ptr, "registry", create_gitconfig, create_mingw64_gitconfig, false, true);
+}
+#endif
+
+void test_win32_systemdir__finds_etc_in_path(void)
+{
+#ifdef GIT_WIN32
+       git_str expected = GIT_STR_INIT, out = GIT_STR_INIT;
+       git_config *cfg;
+       git_buf value = GIT_BUF_INIT;
+
+       populate_fake_ecosystem(&expected, true, false, true, false);
+
+       cl_git_pass(git_win32__find_system_dirs(&out, "etc"));
+       cl_assert_equal_s(out.ptr, expected.ptr);
+
+       git_sysdir_reset();
+
+       cl_git_pass(git_config_open_default(&cfg));
+       cl_git_pass(git_config_get_string_buf(&value, cfg, "gfw.test"));
+       cl_assert_equal_s("etc path", value.ptr);
+
+       git_buf_dispose(&value);
+       git_str_dispose(&expected);
+       git_str_dispose(&out);
+       git_config_free(cfg);
+#endif
+}
+
+void test_win32_systemdir__finds_mingw64_etc_in_path(void)
+{
+#ifdef GIT_WIN32
+       git_str expected = GIT_STR_INIT, out = GIT_STR_INIT;
+       git_config* cfg;
+       git_buf value = GIT_BUF_INIT;
+
+       populate_fake_ecosystem(&expected, false, true, true, false);
+
+       cl_git_pass(git_win32__find_system_dirs(&out, "etc"));
+       cl_assert_equal_s(out.ptr, expected.ptr);
+
+       git_sysdir_reset();
+
+       cl_git_pass(git_config_open_default(&cfg));
+       cl_git_pass(git_config_get_string_buf(&value, cfg, "gfw.test"));
+       cl_assert_equal_s("mingw64 path", value.ptr);
+
+       git_buf_dispose(&value);
+       git_str_dispose(&expected);
+       git_str_dispose(&out);
+       git_config_free(cfg);
+#endif
+}
+
+void test_win32_systemdir__prefers_etc_to_mingw64_in_path(void)
+{
+#ifdef GIT_WIN32
+       git_str expected = GIT_STR_INIT, out = GIT_STR_INIT;
+       git_config* cfg;
+       git_buf value = GIT_BUF_INIT;
+
+       populate_fake_ecosystem(&expected, true, true, true, false);
+
+       cl_git_pass(git_win32__find_system_dirs(&out, "etc"));
+       cl_assert_equal_s(out.ptr, expected.ptr);
+
+       git_sysdir_reset();
+
+       cl_git_pass(git_config_open_default(&cfg));
+       cl_git_pass(git_config_get_string_buf(&value, cfg, "gfw.test"));
+       cl_assert_equal_s("etc path", value.ptr);
+
+       git_buf_dispose(&value);
+       git_str_dispose(&expected);
+       git_str_dispose(&out);
+       git_config_free(cfg);
+#endif
+}
+
+void test_win32_systemdir__finds_etc_in_registry(void)
+{
+#ifdef GIT_WIN32
+       git_str expected = GIT_STR_INIT, out = GIT_STR_INIT;
+       git_config* cfg;
+       git_buf value = GIT_BUF_INIT;
+
+       populate_fake_ecosystem(&expected, true, false, false, true);
+
+       cl_git_pass(git_win32__find_system_dirs(&out, "etc"));
+       cl_assert_equal_s(out.ptr, expected.ptr);
+
+       git_sysdir_reset();
+
+       cl_git_pass(git_config_open_default(&cfg));
+       cl_git_pass(git_config_get_string_buf(&value, cfg, "gfw.test"));
+       cl_assert_equal_s("etc registry", value.ptr);
+
+       git_buf_dispose(&value);
+       git_str_dispose(&expected);
+       git_str_dispose(&out);
+       git_config_free(cfg);
+#endif
+}
+
+void test_win32_systemdir__finds_mingw64_etc_in_registry(void)
+{
+#ifdef GIT_WIN32
+       git_str expected = GIT_STR_INIT, out = GIT_STR_INIT;
+       git_config* cfg;
+       git_buf value = GIT_BUF_INIT;
+
+       populate_fake_ecosystem(&expected, false, true, false, true);
+
+       cl_git_pass(git_win32__find_system_dirs(&out, "etc"));
+       cl_assert_equal_s(out.ptr, expected.ptr);
+
+       git_sysdir_reset();
+
+       cl_git_pass(git_config_open_default(&cfg));
+       cl_git_pass(git_config_get_string_buf(&value, cfg, "gfw.test"));
+       cl_assert_equal_s("mingw64 registry", value.ptr);
+
+       git_buf_dispose(&value);
+       git_str_dispose(&expected);
+       git_str_dispose(&out);
+       git_config_free(cfg);
+#endif
+}
+
+void test_win32_systemdir__prefers_etc_to_mingw64_in_registry(void)
+{
+#ifdef GIT_WIN32
+       git_str expected = GIT_STR_INIT, out = GIT_STR_INIT;
+       git_config* cfg;
+       git_buf value = GIT_BUF_INIT;
+
+       populate_fake_ecosystem(&expected, true, true, false, true);
+
+       cl_git_pass(git_win32__find_system_dirs(&out, "etc"));
+       cl_assert_equal_s(out.ptr, expected.ptr);
+
+       git_sysdir_reset();
+
+       cl_git_pass(git_config_open_default(&cfg));
+       cl_git_pass(git_config_get_string_buf(&value, cfg, "gfw.test"));
+       cl_assert_equal_s("etc registry", value.ptr);
+
+       git_buf_dispose(&value);
+       git_str_dispose(&expected);
+       git_str_dispose(&out);
+       git_config_free(cfg);
+#endif
+}
+
+void test_win32_systemdir__prefers_path_to_registry(void)
+{
+#ifdef GIT_WIN32
+       git_str expected = GIT_STR_INIT, out = GIT_STR_INIT;
+       git_config* cfg;
+       git_buf value = GIT_BUF_INIT;
+
+       populate_fake_ecosystem(&expected, true, true, true, true);
+
+       cl_git_pass(git_win32__find_system_dirs(&out, "etc"));
+       cl_assert_equal_s(out.ptr, expected.ptr);
+
+       git_sysdir_reset();
+
+       cl_git_pass(git_config_open_default(&cfg));
+       cl_git_pass(git_config_get_string_buf(&value, cfg, "gfw.test"));
+       cl_assert_equal_s("etc path", value.ptr);
+
+       git_buf_dispose(&value);
+       git_str_dispose(&expected);
+       git_str_dispose(&out);
+       git_config_free(cfg);
+#endif
+}
+
+void test_win32_systemdir__no_git_installed(void)
+{
+#ifdef GIT_WIN32
+       git_str out = GIT_STR_INIT;
+
+       cl_git_pass(git_win32__find_system_dirs(&out, "etc"));
+       cl_assert_equal_s(out.ptr, "");
+#endif
+}
index 2a1206032c880b3e6f4b0e58ebb643ba200858ee..5b7e2a837c2d69391ad5bb21425e528ce4ca4502 100644 (file)
@@ -57,7 +57,7 @@ void test_worktree_merge__merge_setup(void)
 {
        git_reference *ours_ref, *theirs_ref;
        git_annotated_commit *ours, *theirs;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        unsigned i;
 
        cl_git_pass(git_reference_lookup(&ours_ref, fixture.worktree, MASTER_BRANCH));
@@ -70,13 +70,13 @@ void test_worktree_merge__merge_setup(void)
                    ours, (const git_annotated_commit **)&theirs, 1));
 
        for (i = 0; i < ARRAY_SIZE(merge_files); i++) {
-               cl_git_pass(git_buf_joinpath(&path,
+               cl_git_pass(git_str_joinpath(&path,
                            fixture.worktree->gitdir,
                            merge_files[i]));
-               cl_assert(git_path_exists(path.ptr));
+               cl_assert(git_fs_path_exists(path.ptr));
        }
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_reference_free(ours_ref);
        git_reference_free(theirs_ref);
        git_annotated_commit_free(ours);
@@ -85,7 +85,7 @@ void test_worktree_merge__merge_setup(void)
 
 void test_worktree_merge__merge_conflict(void)
 {
-       git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT, buf = GIT_STR_INIT;
        git_reference *theirs_ref;
        git_annotated_commit *theirs;
        git_index *index;
@@ -111,11 +111,11 @@ void test_worktree_merge__merge_conflict(void)
        git_annotated_commit_free(theirs);
        git_index_free(index);
 
-       cl_git_pass(git_buf_joinpath(&path, fixture.worktree->workdir, "branch_file.txt"));
+       cl_git_pass(git_str_joinpath(&path, fixture.worktree->workdir, "branch_file.txt"));
        cl_git_pass(git_futils_readbuffer(&buf, path.ptr));
        cl_assert_equal_s(buf.ptr, CONFLICT_BRANCH_FILE_TXT);
 
-       git_buf_dispose(&path);
-       git_buf_dispose(&buf);
+       git_str_dispose(&path);
+       git_str_dispose(&buf);
 }
 
index 52d47334c118870837d41c4dff818180cf5e4b8c..0c3fdc173f2531eeed926098669fdc9ff16f4e61 100644 (file)
@@ -55,17 +55,17 @@ void test_worktree_open__repository_through_gitlink(void)
 
 void test_worktree_open__repository_through_gitdir(void)
 {
-       git_buf gitdir_path = GIT_BUF_INIT;
+       git_str gitdir_path = GIT_STR_INIT;
        git_repository *wt;
 
-       cl_git_pass(git_buf_joinpath(&gitdir_path, COMMON_REPO, ".git"));
-       cl_git_pass(git_buf_joinpath(&gitdir_path, gitdir_path.ptr, "worktrees"));
-       cl_git_pass(git_buf_joinpath(&gitdir_path, gitdir_path.ptr, "testrepo-worktree"));
+       cl_git_pass(git_str_joinpath(&gitdir_path, COMMON_REPO, ".git"));
+       cl_git_pass(git_str_joinpath(&gitdir_path, gitdir_path.ptr, "worktrees"));
+       cl_git_pass(git_str_joinpath(&gitdir_path, gitdir_path.ptr, "testrepo-worktree"));
 
        cl_git_pass(git_repository_open(&wt, gitdir_path.ptr));
        assert_worktree_valid(wt, COMMON_REPO, WORKTREE_REPO);
 
-       git_buf_dispose(&gitdir_path);
+       git_str_dispose(&gitdir_path);
        git_repository_free(wt);
 }
 
index 27dc667eaa869ae254390bc03a6451636d5e3af0..557726aafb61d76d10c8fb16d1c20be710896e6b 100644 (file)
@@ -177,22 +177,22 @@ void test_worktree_refs__creating_refs_uses_commondir(void)
 {
           git_reference *head, *branch, *lookup;
           git_commit *commit;
-          git_buf refpath = GIT_BUF_INIT;
+          git_str refpath = GIT_STR_INIT;
 
-          cl_git_pass(git_buf_joinpath(&refpath,
+          cl_git_pass(git_str_joinpath(&refpath,
                       git_repository_commondir(fixture.worktree), "refs/heads/testbranch"));
-          cl_assert(!git_path_exists(refpath.ptr));
+          cl_assert(!git_fs_path_exists(refpath.ptr));
 
           cl_git_pass(git_repository_head(&head, fixture.worktree));
           cl_git_pass(git_commit_lookup(&commit, fixture.worktree, git_reference_target(head)));
           cl_git_pass(git_branch_create(&branch, fixture.worktree, "testbranch", commit, 0));
           cl_git_pass(git_branch_lookup(&lookup, fixture.worktree, "testbranch", GIT_BRANCH_LOCAL));
           cl_assert(git_reference_cmp(branch, lookup) == 0);
-          cl_assert(git_path_exists(refpath.ptr));
+          cl_assert(git_fs_path_exists(refpath.ptr));
 
           git_reference_free(lookup);
           git_reference_free(branch);
           git_reference_free(head);
           git_commit_free(commit);
-          git_buf_dispose(&refpath);
+          git_str_dispose(&refpath);
 }
index 2e62c039c41aa3291b0369daa7b9209b4117c0cc..6b0c074526c54969dc1125804c1960501f00708f 100644 (file)
@@ -61,14 +61,14 @@ void test_worktree_submodule__open_discovered_submodule_worktree(void)
 
 void test_worktree_submodule__resolve_relative_url(void)
 {
-       git_buf wt_path = GIT_BUF_INIT;
+       git_str wt_path = GIT_STR_INIT;
        git_buf sm_relative_path = GIT_BUF_INIT, wt_relative_path = GIT_BUF_INIT;
        git_repository *repo;
        git_worktree *wt;
 
        cl_git_pass(git_futils_mkdir("subdir", 0755, GIT_MKDIR_PATH));
-       cl_git_pass(git_path_prettify_dir(&wt_path, "subdir", NULL));
-       cl_git_pass(git_buf_joinpath(&wt_path, wt_path.ptr, "wt"));
+       cl_git_pass(git_fs_path_prettify_dir(&wt_path, "subdir", NULL));
+       cl_git_pass(git_str_joinpath(&wt_path, wt_path.ptr, "wt"));
 
        /* Open child repository, which is a submodule */
        cl_git_pass(git_repository_open(&child.repo, WORKTREE_CHILD));
@@ -86,7 +86,7 @@ void test_worktree_submodule__resolve_relative_url(void)
 
        git_worktree_free(wt);
        git_repository_free(repo);
-       git_buf_dispose(&wt_path);
+       git_str_dispose(&wt_path);
        git_buf_dispose(&sm_relative_path);
        git_buf_dispose(&wt_relative_path);
 }
index 9b87bfae64f717fc7f6418728d4012383a0952eb..66273d1cb2439b44f0902889fd65e21444c4c088 100644 (file)
@@ -40,11 +40,11 @@ void test_worktree_worktree__list_with_invalid_worktree_dirs(void)
                { "gitdir", "HEAD" },
                { "HEAD", "commondir" },
        };
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_strarray wts;
        size_t i, j, len;
 
-       cl_git_pass(git_buf_joinpath(&path,
+       cl_git_pass(git_str_joinpath(&path,
                    fixture.repo->commondir,
                    "worktrees/invalid"));
        cl_git_pass(p_mkdir(path.ptr, 0755));
@@ -54,8 +54,8 @@ void test_worktree_worktree__list_with_invalid_worktree_dirs(void)
        for (i = 0; i < ARRAY_SIZE(filesets); i++) {
 
                for (j = 0; j < ARRAY_SIZE(filesets[i]); j++) {
-                       git_buf_truncate(&path, len);
-                       cl_git_pass(git_buf_joinpath(&path, path.ptr, filesets[i][j]));
+                       git_str_truncate(&path, len);
+                       cl_git_pass(git_str_joinpath(&path, path.ptr, filesets[i][j]));
                        cl_git_pass(p_close(p_creat(path.ptr, 0644)));
                }
 
@@ -65,13 +65,13 @@ void test_worktree_worktree__list_with_invalid_worktree_dirs(void)
                git_strarray_dispose(&wts);
 
                for (j = 0; j < ARRAY_SIZE(filesets[i]); j++) {
-                       git_buf_truncate(&path, len);
-                       cl_git_pass(git_buf_joinpath(&path, path.ptr, filesets[i][j]));
+                       git_str_truncate(&path, len);
+                       cl_git_pass(git_str_joinpath(&path, path.ptr, filesets[i][j]));
                        p_unlink(path.ptr);
                }
        }
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_worktree_worktree__list_in_worktree_repo(void)
@@ -100,11 +100,11 @@ void test_worktree_worktree__list_without_worktrees(void)
 void test_worktree_worktree__lookup(void)
 {
        git_worktree *wt;
-       git_buf gitdir_path = GIT_BUF_INIT;
+       git_str gitdir_path = GIT_STR_INIT;
 
        cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
 
-       cl_git_pass(git_buf_joinpath(&gitdir_path, fixture.repo->commondir, "worktrees/testrepo-worktree/"));
+       cl_git_pass(git_str_joinpath(&gitdir_path, fixture.repo->commondir, "worktrees/testrepo-worktree/"));
 
        cl_assert_equal_s(wt->gitdir_path, gitdir_path.ptr);
        cl_assert_equal_s(wt->parent_path, fixture.repo->workdir);
@@ -112,7 +112,7 @@ void test_worktree_worktree__lookup(void)
        cl_assert_equal_s(wt->commondir_path, fixture.repo->gitdir);
        cl_assert_equal_s(wt->commondir_path, fixture.repo->commondir);
 
-       git_buf_dispose(&gitdir_path);
+       git_str_dispose(&gitdir_path);
        git_worktree_free(wt);
 }
 
@@ -143,10 +143,10 @@ void test_worktree_worktree__open_invalid_commondir(void)
 {
        git_worktree *wt;
        git_repository *repo;
-       git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT, path = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_sets(&buf, "/path/to/nonexistent/commondir"));
-       cl_git_pass(git_buf_joinpath(&path,
+       cl_git_pass(git_str_sets(&buf, "/path/to/nonexistent/commondir"));
+       cl_git_pass(git_str_joinpath(&path,
                    fixture.repo->commondir,
                    "worktrees/testrepo-worktree/commondir"));
        cl_git_pass(git_futils_writebuffer(&buf, path.ptr, O_RDWR, 0644));
@@ -154,8 +154,8 @@ void test_worktree_worktree__open_invalid_commondir(void)
        cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
        cl_git_fail(git_repository_open_from_worktree(&repo, wt));
 
-       git_buf_dispose(&buf);
-       git_buf_dispose(&path);
+       git_str_dispose(&buf);
+       git_str_dispose(&path);
        git_worktree_free(wt);
 }
 
@@ -163,10 +163,10 @@ void test_worktree_worktree__open_invalid_gitdir(void)
 {
        git_worktree *wt;
        git_repository *repo;
-       git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT, path = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_sets(&buf, "/path/to/nonexistent/gitdir"));
-       cl_git_pass(git_buf_joinpath(&path,
+       cl_git_pass(git_str_sets(&buf, "/path/to/nonexistent/gitdir"));
+       cl_git_pass(git_str_joinpath(&path,
                    fixture.repo->commondir,
                    "worktrees/testrepo-worktree/gitdir"));
        cl_git_pass(git_futils_writebuffer(&buf, path.ptr, O_RDWR, 0644));
@@ -174,8 +174,8 @@ void test_worktree_worktree__open_invalid_gitdir(void)
        cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
        cl_git_fail(git_repository_open_from_worktree(&repo, wt));
 
-       git_buf_dispose(&buf);
-       git_buf_dispose(&path);
+       git_str_dispose(&buf);
+       git_str_dispose(&path);
        git_worktree_free(wt);
 }
 
@@ -183,16 +183,16 @@ void test_worktree_worktree__open_invalid_parent(void)
 {
        git_worktree *wt;
        git_repository *repo;
-       git_buf buf = GIT_BUF_INIT;
+       git_str buf = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_sets(&buf, "/path/to/nonexistent/gitdir"));
+       cl_git_pass(git_str_sets(&buf, "/path/to/nonexistent/gitdir"));
        cl_git_pass(git_futils_writebuffer(&buf,
                    fixture.worktree->gitlink, O_RDWR, 0644));
 
        cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
        cl_git_fail(git_repository_open_from_worktree(&repo, wt));
 
-       git_buf_dispose(&buf);
+       git_str_dispose(&buf);
        git_worktree_free(wt);
 }
 
@@ -201,9 +201,9 @@ void test_worktree_worktree__init(void)
        git_worktree *wt;
        git_repository *repo;
        git_reference *branch;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../worktree-new"));
+       cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-new"));
        cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-new", path.ptr, NULL));
 
        /* Open and verify created repo */
@@ -211,7 +211,7 @@ void test_worktree_worktree__init(void)
        cl_assert(git__suffixcmp(git_repository_workdir(repo), "worktree-new/") == 0);
        cl_git_pass(git_branch_lookup(&branch, repo, "worktree-new", GIT_BRANCH_LOCAL));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_worktree_free(wt);
        git_reference_free(branch);
        git_repository_free(repo);
@@ -222,12 +222,12 @@ void test_worktree_worktree__add_locked(void)
        git_worktree *wt;
        git_repository *repo;
        git_reference *branch;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_worktree_add_options opts = GIT_WORKTREE_ADD_OPTIONS_INIT;
 
        opts.lock = 1;
 
-       cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../worktree-locked"));
+       cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-locked"));
        cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-locked", path.ptr, &opts));
 
        /* Open and verify created repo */
@@ -236,7 +236,7 @@ void test_worktree_worktree__add_locked(void)
        cl_assert(git__suffixcmp(git_repository_workdir(repo), "worktree-locked/") == 0);
        cl_git_pass(git_branch_lookup(&branch, repo, "worktree-locked", GIT_BRANCH_LOCAL));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_worktree_free(wt);
        git_reference_free(branch);
        git_repository_free(repo);
@@ -247,16 +247,16 @@ void test_worktree_worktree__init_existing_branch(void)
        git_reference *head, *branch;
        git_commit *commit;
        git_worktree *wt;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        cl_git_pass(git_repository_head(&head, fixture.repo));
        cl_git_pass(git_commit_lookup(&commit, fixture.repo, &head->target.oid));
        cl_git_pass(git_branch_create(&branch, fixture.repo, "worktree-new", commit, false));
 
-       cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../worktree-new"));
+       cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-new"));
        cl_git_fail(git_worktree_add(&wt, fixture.repo, "worktree-new", path.ptr, NULL));
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_commit_free(commit);
        git_reference_free(head);
        git_reference_free(branch);
@@ -268,7 +268,7 @@ void test_worktree_worktree__add_with_explicit_branch(void)
        git_commit *commit;
        git_worktree *wt;
        git_repository *wtrepo;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        git_worktree_add_options opts = GIT_WORKTREE_ADD_OPTIONS_INIT;
 
        cl_git_pass(git_repository_head(&head, fixture.repo));
@@ -277,13 +277,13 @@ void test_worktree_worktree__add_with_explicit_branch(void)
 
        opts.ref = branch;
 
-       cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../worktree-with-different-name"));
+       cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-with-different-name"));
        cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-with-different-name", path.ptr, &opts));
        cl_git_pass(git_repository_open_from_worktree(&wtrepo, wt));
        cl_git_pass(git_repository_head(&wthead, wtrepo));
        cl_assert_equal_s(git_reference_name(wthead), "refs/heads/worktree-with-ref");
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_commit_free(commit);
        git_reference_free(head);
        git_reference_free(branch);
@@ -292,19 +292,41 @@ void test_worktree_worktree__add_with_explicit_branch(void)
        git_worktree_free(wt);
 }
 
+void test_worktree_worktree__add_no_checkout(void)
+{
+       git_worktree *wt;
+       git_repository *wtrepo;
+       git_index *index;
+       git_str path = GIT_STR_INIT;
+       git_worktree_add_options opts = GIT_WORKTREE_ADD_OPTIONS_INIT;
+
+       opts.checkout_options.checkout_strategy = GIT_CHECKOUT_NONE;
+
+       cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-no-checkout"));
+       cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-no-checkout", path.ptr, &opts));
+
+       cl_git_pass(git_repository_open(&wtrepo, path.ptr));
+       cl_git_pass(git_repository_index(&index, wtrepo));
+       cl_assert_equal_i(git_index_entrycount(index), 0);
+
+       git_str_dispose(&path);
+       git_worktree_free(wt);
+       git_index_free(index);
+       git_repository_free(wtrepo);
+}
 
 void test_worktree_worktree__init_existing_worktree(void)
 {
        git_worktree *wt;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../worktree-new"));
+       cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-new"));
        cl_git_fail(git_worktree_add(&wt, fixture.repo, "testrepo-worktree", path.ptr, NULL));
 
        cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
        cl_assert_equal_s(wt->gitlink_path, fixture.worktree->gitlink);
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_worktree_free(wt);
 }
 
@@ -312,54 +334,54 @@ void test_worktree_worktree__init_existing_path(void)
 {
        const char *wtfiles[] = { "HEAD", "commondir", "gitdir", "index" };
        git_worktree *wt;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
        unsigned i;
 
        /* Delete files to verify they have not been created by
         * the init call */
        for (i = 0; i < ARRAY_SIZE(wtfiles); i++) {
-               cl_git_pass(git_buf_joinpath(&path,
+               cl_git_pass(git_str_joinpath(&path,
                            fixture.worktree->gitdir, wtfiles[i]));
                cl_git_pass(p_unlink(path.ptr));
        }
 
-       cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../testrepo-worktree"));
+       cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../testrepo-worktree"));
        cl_git_fail(git_worktree_add(&wt, fixture.repo, "worktree-new", path.ptr, NULL));
 
        /* Verify files have not been re-created */
        for (i = 0; i < ARRAY_SIZE(wtfiles); i++) {
-               cl_git_pass(git_buf_joinpath(&path,
+               cl_git_pass(git_str_joinpath(&path,
                            fixture.worktree->gitdir, wtfiles[i]));
-               cl_assert(!git_path_exists(path.ptr));
+               cl_assert(!git_fs_path_exists(path.ptr));
        }
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
 }
 
 void test_worktree_worktree__init_submodule(void)
 {
        git_repository *repo, *sm, *wt;
        git_worktree *worktree;
-       git_buf path = GIT_BUF_INIT;
+       git_str path = GIT_STR_INIT;
 
        cleanup_fixture_worktree(&fixture);
        repo = setup_fixture_submod2();
 
-       cl_git_pass(git_buf_joinpath(&path, repo->workdir, "sm_unchanged"));
+       cl_git_pass(git_str_joinpath(&path, repo->workdir, "sm_unchanged"));
        cl_git_pass(git_repository_open(&sm, path.ptr));
-       cl_git_pass(git_buf_joinpath(&path, repo->workdir, "../worktree/"));
+       cl_git_pass(git_str_joinpath(&path, repo->workdir, "../worktree/"));
        cl_git_pass(git_worktree_add(&worktree, sm, "repo-worktree", path.ptr, NULL));
        cl_git_pass(git_repository_open_from_worktree(&wt, worktree));
 
-       cl_git_pass(git_path_prettify_dir(&path, path.ptr, NULL));
+       cl_git_pass(git_fs_path_prettify_dir(&path, path.ptr, NULL));
        cl_assert_equal_s(path.ptr, wt->workdir);
-       cl_git_pass(git_path_prettify_dir(&path, sm->commondir, NULL));
+       cl_git_pass(git_fs_path_prettify_dir(&path, sm->commondir, NULL));
        cl_assert_equal_s(sm->commondir, wt->commondir);
 
-       cl_git_pass(git_buf_joinpath(&path, sm->gitdir, "worktrees/repo-worktree/"));
+       cl_git_pass(git_str_joinpath(&path, sm->gitdir, "worktrees/repo-worktree/"));
        cl_assert_equal_s(path.ptr, wt->gitdir);
 
-       git_buf_dispose(&path);
+       git_str_dispose(&path);
        git_worktree_free(worktree);
        git_repository_free(sm);
        git_repository_free(wt);
@@ -388,13 +410,13 @@ void test_worktree_worktree__name(void)
 void test_worktree_worktree__path(void)
 {
        git_worktree *wt;
-       git_buf expected_path = GIT_BUF_INIT;
+       git_str expected_path = GIT_STR_INIT;
 
-       cl_git_pass(git_buf_joinpath(&expected_path, clar_sandbox_path(), "testrepo-worktree"));
+       cl_git_pass(git_str_joinpath(&expected_path, clar_sandbox_path(), "testrepo-worktree"));
        cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
        cl_assert_equal_s(git_worktree_path(wt), expected_path.ptr);
 
-       git_buf_dispose(&expected_path);
+       git_str_dispose(&expected_path);
        git_worktree_free(wt);
 }
 
@@ -560,8 +582,8 @@ void test_worktree_worktree__prune_gitdir_only(void)
        cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
        cl_git_pass(git_worktree_prune(wt, &opts));
 
-       cl_assert(!git_path_exists(wt->gitdir_path));
-       cl_assert(git_path_exists(wt->gitlink_path));
+       cl_assert(!git_fs_path_exists(wt->gitdir_path));
+       cl_assert(git_fs_path_exists(wt->gitlink_path));
 
        git_worktree_free(wt);
 }
@@ -576,8 +598,8 @@ void test_worktree_worktree__prune_worktree(void)
        cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
        cl_git_pass(git_worktree_prune(wt, &opts));
 
-       cl_assert(!git_path_exists(wt->gitdir_path));
-       cl_assert(!git_path_exists(wt->gitlink_path));
+       cl_assert(!git_fs_path_exists(wt->gitdir_path));
+       cl_assert(!git_fs_path_exists(wt->gitlink_path));
 
        git_worktree_free(wt);
 }