Commit 1b9cc2ec by Carlos Martín Nieto

Merge remote-tracking branch 'upstream/master' into diff-indent-heuristic

parents 5efe9d12 524c1d3c
You are opening a _bug report_ against the libgit2 project. If you have a
question about an API or usage, please ask on StackOverflow:
http://stackoverflow.com/questions/tagged/libgit2. Please fill out the
reproduction steps (below) and delete this introductory paragraph. Thanks!
### Reproduction steps
### Expected behavior
### Actual behavior
### Version of libgit2 (release number or SHA1)
### Operating system(s) tested
......@@ -2,6 +2,7 @@
# see travis-ci.org for details
language: c
dist: trusty
os:
- linux
......@@ -17,19 +18,11 @@ env:
- secure: "YnhS+8n6B+uoyaYfaJ3Lei7cSJqHDPiKJCKFIF2c87YDfmCvAJke8QtE7IzjYDs7UFkTCM4ox+ph2bERUrxZbSCyEkHdjIZpKuMJfYWja/jgMqTMxdyOH9y8JLFbZsSXDIXDwqBlC6vVyl1fP90M35wuWcNTs6tctfVWVofEFbs="
- GITTEST_INVASIVE_FS_SIZE=1
matrix:
- OPTIONS="-DTHREADSAFE=ON -DCMAKE_BUILD_TYPE=Release"
- OPTIONS="-DTHREADSAFE=OFF -DBUILD_EXAMPLES=ON"
- OPTIONS="-DTHREADSAFE=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_WERROR=ON"
- OPTIONS="-DTHREADSAFE=OFF -DBUILD_EXAMPLES=ON -DENABLE_WERROR=ON"
addons:
apt:
packages:
- cmake
- libssh2-1-dev
- openssh-client
- openssh-server
- valgrind
sudo: false
dist: trusty
sudo: true
matrix:
fast_finish: true
......@@ -38,21 +31,24 @@ matrix:
compiler: gcc
include:
- compiler: gcc
env: PRECISE=1
os: linux
dist: precise
- compiler: gcc
env: COVERITY=1
os: linux
dist: trusty
- compiler: gcc
env:
- VALGRIND=1
OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=OFF -DDEBUG_POOL=ON -DCMAKE_BUILD_TYPE=Debug"
os: linux
dist: trusty
allow_failures:
- env: COVERITY=1
- env:
- VALGRIND=1
OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=OFF -DDEBUG_POOL=ON -DCMAKE_BUILD_TYPE=Debug"
install:
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then ./script/install-deps-${TRAVIS_OS_NAME}.sh; fi
- ./script/install-deps-${TRAVIS_OS_NAME}.sh
# Run the Build script and tests
script:
......
......@@ -22,6 +22,7 @@ Dmitry Kakurin
Dmitry Kovega
Emeric Fermas
Emmanuel Rodriguez
Eric Myhre
Florian Forster
Holger Weiss
Ingmar Vanhassel
......
v0.24 + 1
v0.26 + 1
---------
### Changes or improvements
* Improved `p_unlink` in `posix_w32.c` to try and make a file writable
before sleeping in the retry loop to prevent unnecessary calls to sleep.
### API additions
* `git_remote_create_detached()` creates a remote that is not associated
to any repository (and does not apply configuration like 'insteadof' rules).
This is mostly useful for e.g. emulating `git ls-remote` behavior.
### API removals
### Breaking API changes
v0.26
-----
### Changes or improvements
* Support for opening, creating and modifying worktrees.
* We can now detect SHA1 collisions resulting from the SHAttered attack. These
checks can be enabled at build time via `-DUSE_SHA1DC`.
* Fix for missing implementation of `git_merge_driver_source` getters.
* Fix for installed pkg-config file being broken when the prefix contains
spaces.
* We now detect when the hashsum of on-disk objects does not match their
expected hashsum.
* We now support open-ended ranges (e.g. "master..", "...master") in our
revision range parsing code.
* We now correctly compute ignores with leading "/" in subdirectories.
* We now optionally call `fsync` on loose objects, packfiles and their indexes,
loose references and packed reference files.
* We can now build against OpenSSL v1.1 and against LibreSSL.
* `GIT_MERGE_OPTIONS_INIT` now includes a setting to perform rename detection.
This aligns this structure with the default by `git_merge` and
`git_merge_trees` when `NULL` was provided for the options.
* Improvements for reading index v4 files.
* Perform additional retries for filesystem operations on Windows when files
are temporarily locked by other processes.
### API additions
* New family of functions to handle worktrees:
* `git_worktree_list()` lets you look up worktrees for a repository.
* `git_worktree_lookup()` lets you get a specific worktree.
* `git_worktree_open_from_repository()` lets you get the associated worktree
of a repository.
a worktree.
* `git_worktree_add` lets you create new worktrees.
* `git_worktree_prune` lets you remove worktrees from disk.
* `git_worktree_lock()` and `git_worktree_unlock()` let you lock
respectively unlock a worktree.
* `git_repository_open_from_worktree()` lets you open a repository via
* `git_repository_head_for_worktree()` lets you get the current `HEAD` for a
linked worktree.
* `git_repository_head_detached_for_worktree()` lets you check whether a
linked worktree is in detached HEAD mode.
* `git_repository_item_path()` lets you retrieve paths for various repository
files.
* `git_repository_commondir()` lets you retrieve the common directory of a
repository.
* `git_branch_is_checked_out()` allows you to check whether a branch is checked
out in a repository or any of its worktrees.
* `git_repository_submodule_cache_all()` and
`git_repository_submodule_cache_clear()` functions allow you to prime or clear
the submodule cache of a repository.
* You can disable strict hash verifications via the
`GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION` option with `git_libgit2_opts()`.
* You can enable us calling `fsync` for various files inside the ".git"
directory by setting the `GIT_OPT_ENABLE_FSYNC_GITDIR` option with
`git_libgit2_opts()`.
* You can now enable "offset deltas" when creating packfiles and negotiating
packfiles with a remote server by setting `GIT_OPT_ENABLE_OFS_DELTA` option
with `GIT_libgit2_opts()`.
* You can now set the default share mode on Windows for opening files using
`GIT_OPT_SET_WINDOWS_SHAREMODE` option with `git_libgit2_opts()`.
You can query the current share mode with `GIT_OPT_GET_WINDOWS_SHAREMODE`.
* `git_transport_smart_proxy_options()' enables you to get the proxy options for
smart transports.
* The `GIT_FILTER_INIT` macro and the `git_filter_init` function are provided
to initialize a `git_filter` structure.
### Breaking API changes
* `clone_checkout_strategy` has been removed from
`git_submodule_update_option`. The checkout strategy used to clone will
be the same strategy specified in `checkout_opts`.
v0.25
-------
### Changes or improvements
......@@ -15,14 +129,39 @@ v0.24 + 1
* Support for reading and writing git index v4 files
* Improve the performance of the revwalk and bring us closer to git's code.
* The reference db has improved support for concurrency and returns `GIT_ELOCKED`
when an operation could not be performed due to locking.
* Nanosecond resolution is now activated by default, following git's change to
do this.
* We now restrict the set of ciphers we let OpenSSL use by default.
* Users can now register their own merge drivers for use with `.gitattributes`.
The library also gained built-in support for the union merge driver.
* The default for creating references is now to validate that the object does
exist.
* Add `git_proxy_options` which is used by the different networking
implementations to let the caller specify the proxy settings instead of
relying on the environment variables.
### API additions
* You can now get the user-agent used by libgit2 using the
`GIT_OPT_GET_USER_AGENT` option with `git_libgit2_opts()`.
It is the counterpart to `GIT_OPT_SET_USER_AGENT`.
* The `GIT_OPT_SET_SSL_CIPHERS` option for `git_libgit2_opts()` lets you specify
a custom list of ciphers to use for OpenSSL.
* `git_commit_create_buffer()` creates a commit and writes it into a
user-provided buffer instead of writing it into the object db.
user-provided buffer instead of writing it into the object db. Combine it with
`git_commit_create_with_signature()` in order to create a commit with a
cryptographic signature.
* `git_blob_create_fromstream()` and
`git_blob_create_fromstream_commit()` allow you to create a blob by
......@@ -48,12 +187,48 @@ v0.24 + 1
`git_repository_open_ext` with this flag will error out if either
`$GIT_WORK_TREE` or `$GIT_COMMON_DIR` is set.
* `git_diff_from_buffer` can create a `git_diff` object from the contents
* `git_diff_from_buffer()` can create a `git_diff` object from the contents
of a git-style patch file.
* `git_index_version()` and `git_index_set_version()` to get and set
the index version
* `git_odb_expand_ids()` lets you check for the existence of multiple
objects at once.
* The new `git_blob_dup()`, `git_commit_dup()`, `git_tag_dup()` and
`git_tree_dup()` functions provide type-specific wrappers for
`git_object_dup()` to reduce noise and increase type safety for callers.
* `git_reference_dup()` lets you duplicate a reference to aid in ownership
management and cleanup.
* `git_signature_from_buffer()` lets you create a signature from a string in the
format that appear in objects.
* `git_tree_create_updated()` lets you create a tree based on another one
together with a list of updates. For the covered update cases, it's more
efficient than the `git_index` route.
* `git_apply_patch()` applies hunks from a `git_patch` to a buffer.
* `git_diff_to_buf()` lets you print an entire diff directory to a buffer,
similar to how `git_patch_to_buf()` works.
* `git_proxy_init_options()` is added to initialize a `git_proxy_options`
structure at run-time.
* `git_merge_driver_register()`, `git_merge_driver_unregister()` let you
register and unregister a custom merge driver to be used when `.gitattributes`
specifies it.
* `git_merge_driver_lookup()` can be used to look up a merge driver by name.
* `git_merge_driver_source_repo()`, `git_merge_driver_source_ancestor()`,
`git_merge_driver_source_ours()`, `git_merge_driver_source_theirs()`,
`git_merge_driver_source_file_options()` added as accessors to
`git_merge_driver_source`.
### API removals
* `git_blob_create_fromchunks()` has been removed in favour of
......@@ -78,6 +253,13 @@ v0.24 + 1
If this is `NULL`, then it will not be called and the `exists` function
will be used instead.
* `git_remote_connect()` now accepts `git_proxy_options` argument, and
`git_fetch_options` and `git_push_options` each have a `proxy_opts` field.
* `git_merge_options` now provides a `default_driver` that can be used
to provide the name of a merge driver to be used to handle files changed
during a merge.
v0.24
-------
......@@ -153,10 +335,6 @@ v0.24
### Breaking API changes
* `git_merge_options` now provides a `default_driver` that can be used
to provide the name of a merge driver to be used to handle files changed
during a merge.
* The `git_merge_tree_flag_t` is now `git_merge_flag_t`. Subsequently,
its members are no longer prefixed with `GIT_MERGE_TREE_FLAG` but are
now prefixed with `GIT_MERGE_FLAG`, and the `tree_flags` field of the
......
......@@ -18,11 +18,11 @@ other's toes.
- If a function returns an object as a return value, that function is
a getter and the object's lifetime is tied to the parent
object. Objects which are returned as the first argument as a
pointer-to-pointer are owned by the caller and it is repsponsible
pointer-to-pointer are owned by the caller and it is responsible
for freeing it. Strings are returned via `git_buf` in order to
allow for re-use and safe freeing.
- Most of what libgit2 does relates to I/O so you as a general rule
- Most of what libgit2 does relates to I/O so as a general rule
you should assume that any function can fail due to errors as even
getting data from the filesystem can result in all sorts of errors
and complex failure cases.
......
......@@ -958,3 +958,36 @@ necessary. Here is a sample; alter the names:
That's all there is to it!
----------------------------------------------------------------------
The bundled SHA1 collision detection code is licensed under the MIT license:
MIT License
Copyright (c) 2017:
Marc Stevens
Cryptology Group
Centrum Wiskunde & Informatica
P.O. Box 94079, 1090 GB Amsterdam, Netherlands
marc@marc-stevens.nl
Dan Shumow
Microsoft Research
danshu@microsoft.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
......@@ -5,7 +5,7 @@ So, you want to start helping out with `libgit2`? That's fantastic! We
welcome contributions and we promise we'll try to be nice.
This is a list of libgit2 related projects that new contributors can take
on. It includes a number of good starter projects and well as some larger
on. It includes a number of good starter projects as well as some larger
ideas that no one is actively working on.
## Before You Start
......@@ -70,11 +70,11 @@ some incremental steps listed towards the larger goal. Those steps
might make good smaller projects by themselves.
* Port part of the Git test suite to run against the command line emulation
in examples/
* Pick a Git command that is emulated in our examples/ area
in `examples/`
* Pick a Git command that is emulated in our `examples/` area
* Extract the Git tests that exercise that command
* Convert the tests to call our emulation
* These tests could go in examples/tests/...
* These tests could go in `examples/tests/`...
* Add hooks API to enumerate and manage hooks (not run them at this point)
* Enumeration of available hooks
* Lookup API to see which hooks have a script and get the script
......
......@@ -43,9 +43,16 @@ We ask that you not open a GitHub Issue for help, only for bug reports.
What It Can Do
==============
`libgit2` is already very usable and is being used in production for many
applications including the GitHub.com site, in Plastic SCM and also powering
Microsoft's Visual Studio tools for Git. The library provides:
libgit2 provides you with the ability to manage Git repositories in the
programming language of your choice. It's used in production to power many
applications including GitHub.com, Plastic SCM and Visual Studio Team Services.
It does not aim to replace the git tool or its user-facing commands. Some APIs
resemble the plumbing commands as those align closely with the concepts of the
Git system, but most commands a user would type are out of scope for this
library to implement directly.
The library provides:
* SHA conversions, formatting and shortening
* abstracted ODB backend system
......@@ -60,6 +67,16 @@ Microsoft's Visual Studio tools for Git. The library provides:
* descriptive and detailed error messages
* ...and more (over 175 different API calls)
As libgit2 is purely a consumer of the Git system, we have to
adjust to changes made upstream. This has two major consequences:
* Some changes may require us to change provided interfaces. While we try to
implement functions in a generic way so that no future changes are required,
we cannot promise a completely stable API.
* As we have to keep up with changes in behavior made upstream, we may lag
behind in some areas. We usually to document these incompatibilities in our
issue tracker with the label "git change".
Optional dependencies
=====================
......@@ -116,6 +133,14 @@ On most systems you can build the library using the following commands
Alternatively you can point the CMake GUI tool to the CMakeLists.txt file and generate platform specific build project or IDE workspace.
Once built, you can run the tests from the `build` directory with the command
$ make test
Alternatively you can run the test suite directly using,
$ ./libgit2_clar
To install the library you can specify the install prefix by setting:
$ cmake .. -DCMAKE_INSTALL_PREFIX=/install/prefix
......@@ -203,6 +228,8 @@ Here are the bindings to libgit2 that are currently available:
* git2go <https://github.com/libgit2/git2go>
* GObject
* libgit2-glib <https://wiki.gnome.org/Projects/Libgit2-glib>
* Guile
* Guile-Git <https://gitlab.com/guile-git/guile-git>
* Haskell
* hgit2 <https://github.com/jwiegley/gitlib>
* Java
......@@ -236,7 +263,7 @@ Here are the bindings to libgit2 that are currently available:
* Rust
* git2-rs <https://github.com/alexcrichton/git2-rs>
* Swift
* Gift <https://github.com/modocache/Gift>
* SwiftGit2 <https://github.com/SwiftGit2/SwiftGit2>
* Vala
* libgit2.vapi <https://github.com/apmasell/vapis/blob/master/libgit2.vapi>
......
......@@ -62,33 +62,38 @@ general case still affects you if you use ssh.
General Case
------------
By default we use libcurl, which has its own ![recommendations for
thread safety](http://curl.haxx.se/libcurl/c/libcurl-tutorial.html#Multi-threading).
If libcurl was not found or was disabled, libgit2 uses OpenSSL to be
able to use HTTPS as a transport. This library is made to be
thread-implementation agnostic, and the users of the library must set
which locking function it should use. This means that libgit2 cannot
know what to set as the user of libgit2 may use OpenSSL independently
and the locking settings must survive libgit2 shutting down.
Even if libgit2 doesn't use OpenSSL directly, OpenSSL can still be used
by libssh2 depending on the configuration. If OpenSSL is used both by
libgit2 and libssh2, you only need to set up threading for OpenSSL once.
libgit2 does provide a last-resort convenience function
If it's available, by default we use libcurl to provide HTTP tunneling support,
which may be linked against a number of cryptographic libraries and has its
own
[recommendations for thread safety](https://curl.haxx.se/libcurl/c/threadsafe.html).
If there are no alternative TLS implementations (currently only
SecureTransport), libgit2 uses OpenSSL in order to use HTTPS as a transport.
OpenSSL is thread-safe starting at version 1.1.0. If your copy of libgit2 is
linked against that version, you do not need to take any further steps.
Older versions of OpenSSL are made to be thread-implementation agnostic, and the
users of the library must set which locking function it should use. libgit2
cannot know what to set as the user of libgit2 may also be using OpenSSL independently and
the locking settings must then live outside the lifetime of libgit2.
Even if libgit2 doesn't use OpenSSL directly, OpenSSL can still be used by
libssh2 or libcurl depending on the configuration. If OpenSSL is used by
more than one library, you only need to set up threading for OpenSSL once.
If libgit2 is linked against OpenSSL, it provides a last-resort convenience function
`git_openssl_set_locking()` (available in `sys/openssl.h`) to use the
platform-native mutex mechanisms to perform the locking, which you may
rely on if you do not want to use OpenSSL outside of libgit2, or you
know that libgit2 will outlive the rest of the operations. It is not
platform-native mutex mechanisms to perform the locking, which you can use
if you do not want to use OpenSSL outside of libgit2, or you
know that libgit2 will outlive the rest of the operations. It is then not
safe to use OpenSSL multi-threaded after libgit2's shutdown function
has been called. Note `git_openssl_set_locking()` only works if
libgit2 uses OpenSSL directly - if OpenSSL is only used as a dependency
of libssh2 as described above, `git_openssl_set_locking()` is a no-op.
of libssh2 or libcurl as described above, `git_openssl_set_locking()` is a no-op.
If your programming language offers a package/bindings for OpenSSL,
you should very strongly prefer to use that in order to set up
locking, as they provide a level of coördination which is impossible
locking, as they provide a level of coordination which is impossible
when using this function.
See the
......@@ -96,13 +101,10 @@ See the
on threading for more details, and http://trac.libssh2.org/wiki/MultiThreading
for a specific example of providing the threading callbacks.
Be also aware that libgit2 does not always link against OpenSSL
if there are alternatives provided by the system.
libssh2 may be linked against OpenSSL or libgcrypt. If it uses OpenSSL,
see the above paragraphs. If it uses libgcrypt, then you need to
set up its locking before using it multi-threaded. libgit2 has no
direct connection to libgcrypt and thus has not convenience functions for
direct connection to libgcrypt and thus has no convenience functions for
it (but libgcrypt has macros). Read libgcrypt's
[threading documentation for more information](http://www.gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html)
......
......@@ -2,19 +2,30 @@ version: '{build}'
branches:
only:
- master
- appveyor
- /^maint.*/
environment:
GITTEST_INVASIVE_FS_STRUCTURE: 1
GITTEST_INVASIVE_FS_SIZE: 1
matrix:
- GENERATOR: "Visual Studio 11"
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
GENERATOR: "Visual Studio 10 2010"
ARCH: 32
- GENERATOR: "Visual Studio 11 Win64"
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
GENERATOR: "Visual Studio 10 2010 Win64"
ARCH: 64
- GENERATOR: "MSYS Makefiles"
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GENERATOR: "Visual Studio 14 2015"
ARCH: 32
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GENERATOR: "Visual Studio 14 2015 Win64"
ARCH: 64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GENERATOR: "MSYS Makefiles"
ARCH: i686 # this is for 32-bit MinGW-w64
- GENERATOR: "MSYS Makefiles"
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GENERATOR: "MSYS Makefiles"
ARCH: 64
cache:
- i686-4.9.2-release-win32-sjlj-rt_v3-rev1.7z
......
FILE(GLOB SRC_HTTP "*.c" "*.h")
ADD_LIBRARY(http-parser STATIC ${SRC_HTTP})
INCLUDE_DIRECTORIES(".")
ADD_LIBRARY(regex STATIC "regex.c" "regex.h")
FIND_PROGRAM(DLLTOOL dlltool CMAKE_FIND_ROOT_PATH_BOTH)
IF (NOT DLLTOOL)
MESSAGE(FATAL_ERROR "Could not find dlltool command")
ENDIF ()
SET(LIBWINHTTP_PATH "${CMAKE_BINARY_DIR}/deps/winhttp")
SET(LIBWINHTTP_PATH ${LIBWINHTTP_PATH} PARENT_SCOPE)
FILE(MAKE_DIRECTORY ${LIBWINHTTP_PATH})
IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
set(WINHTTP_DEF "winhttp64.def")
ELSE()
set(WINHTTP_DEF "winhttp.def")
ENDIF()
ADD_CUSTOM_COMMAND(
OUTPUT ${LIBWINHTTP_PATH}/libwinhttp.a
COMMAND ${DLLTOOL} -d ${WINHTTP_DEF} -k -D winhttp.dll -l libwinhttp.a
DEPENDS ${WINHTTP_DEF}
WORKING_DIRECTORY ${LIBWINHTTP_PATH}
)
SET_SOURCE_FILES_PROPERTIES(
${CMAKE_CURRENT_SOURCE_DIR}/src/transports/winhttp.c
PROPERTIES OBJECT_DEPENDS ${LIBWINHTTP_PATH}/libwinhttp.a
)
ADD_DEFINITIONS(-DNO_VIZ -DSTDC -DNO_GZIP)
FILE(GLOB SRC_ZLIB "*.c" "*.h")
INCLUDE_DIRECTORIES(".")
ADD_LIBRARY(zlib STATIC ${SRC_ZLIB})
......@@ -8,7 +8,8 @@
#ifndef ZCONF_H
#define ZCONF_H
#include "../../src/common.h"
#include "../../include/git2/types.h"
#include <stdarg.h>
/* Jeez, don't complain about non-prototype
* forms, we didn't write zlib */
......
LINK_DIRECTORIES(${LIBGIT2_LIBDIRS})
INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDES})
FILE(GLOB_RECURSE SRC_EXAMPLE_GIT2 network/*.c network/*.h)
ADD_EXECUTABLE(cgit2 ${SRC_EXAMPLE_GIT2})
IF(WIN32 OR ANDROID)
......
......@@ -75,15 +75,14 @@ int print_matched_cb(const char *path, const char *matched_pathspec, void *paylo
{
struct print_payload p = *(struct print_payload*)(payload);
int ret;
git_status_t status;
unsigned status;
(void)matched_pathspec;
if (git_status_file((unsigned int*)(&status), p.repo, path)) {
return -1; //abort
if (git_status_file(&status, p.repo, path)) {
return -1;
}
if (status & GIT_STATUS_WT_MODIFIED ||
status & GIT_STATUS_WT_NEW) {
if (status & GIT_STATUS_WT_MODIFIED || status & GIT_STATUS_WT_NEW) {
printf("add '%s'\n", path);
ret = 0;
} else {
......
......@@ -146,6 +146,25 @@ int match_uint16_arg(
return 1;
}
int match_uint32_arg(
uint32_t *out, struct args_info *args, const char *opt)
{
const char *found = match_numeric_arg(args, opt);
uint16_t val;
char *endptr = NULL;
if (!found)
return 0;
val = (uint32_t)strtoul(found, &endptr, 0);
if (!endptr || *endptr != '\0')
fatal("expected number after argument", opt);
if (out)
*out = val;
return 1;
}
static int match_int_internal(
int *out, const char *str, int allow_negative, const char *opt)
{
......
......@@ -73,6 +73,15 @@ extern int match_uint16_arg(
uint16_t *out, struct args_info *args, const char *opt);
/**
* Check current `args` entry against `opt` string parsing as uint32. If
* `opt` matches exactly, take the next arg as a uint16_t value; if `opt`
* is a prefix (equal sign optional), take the remainder of the arg as a
* uint32_t value; otherwise return 0.
*/
extern int match_uint32_arg(
uint32_t *out, struct args_info *args, const char *opt);
/**
* Check current `args` entry against `opt` string parsing as int. If
* `opt` matches exactly, take the next arg as an int value; if it matches
* as a prefix (equal sign optional), take the remainder of the arg as a
......
......@@ -293,11 +293,11 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
else if (is_prefixed(a, "-B") || is_prefixed(a, "--break-rewrites"))
/* TODO: parse thresholds */
o->findopts.flags |= GIT_DIFF_FIND_REWRITES;
else if (!match_uint16_arg(
else if (!match_uint32_arg(
&o->diffopts.context_lines, &args, "-U") &&
!match_uint16_arg(
!match_uint32_arg(
&o->diffopts.context_lines, &args, "--unified") &&
!match_uint16_arg(
!match_uint32_arg(
&o->diffopts.interhunk_lines, &args, "--inter-hunk-context") &&
!match_uint16_arg(
&o->diffopts.id_abbrev, &args, "--abbrev") &&
......
......@@ -50,7 +50,7 @@ static int sideband_progress(const char *str, int len, void *payload)
{
(void)payload; // unused
printf("remote: %*s", len, str);
printf("remote: %.*s", len, str);
fflush(stdout);
return 0;
}
......
#include "common.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
/* Shamelessly borrowed from http://stackoverflow.com/questions/3417837/
* with permission of the original author, Martin Pool.
......@@ -20,15 +22,27 @@ int cred_acquire_cb(git_cred **out,
unsigned int UNUSED(allowed_types),
void * UNUSED(payload))
{
char username[128] = {0};
char password[128] = {0};
char *username = NULL, *password = NULL;
int error;
printf("Username: ");
scanf("%s", username);
if (getline(&username, NULL, stdin) < 0) {
fprintf(stderr, "Unable to read username: %s", strerror(errno));
return -1;
}
/* Yup. Right there on your terminal. Careful where you copy/paste output. */
printf("Password: ");
scanf("%s", password);
if (getline(&password, NULL, stdin) < 0) {
fprintf(stderr, "Unable to read password: %s", strerror(errno));
free(username);
return -1;
}
return git_cred_userpass_plaintext_new(out, username, password);
error = git_cred_userpass_plaintext_new(out, username, password);
free(username);
free(password);
return error;
}
......@@ -55,6 +55,8 @@ static int update_cb(const char *refname, const git_oid *a, const git_oid *b, vo
*/
static int transfer_progress_cb(const git_transfer_progress *stats, void *payload)
{
(void)payload;
if (stats->received_objects == stats->total_objects) {
printf("Resolving deltas %d/%d\r",
stats->indexed_deltas, stats->total_deltas);
......@@ -71,7 +73,6 @@ int fetch(git_repository *repo, int argc, char **argv)
{
git_remote *remote = NULL;
const git_transfer_progress *stats;
struct dl_data data;
git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
if (argc < 2) {
......@@ -79,14 +80,13 @@ int fetch(git_repository *repo, int argc, char **argv)
return EXIT_FAILURE;
}
// Figure out whether it's a named remote or a URL
/* Figure out whether it's a named remote or a URL */
printf("Fetching %s for repo %p\n", argv[1], repo);
if (git_remote_lookup(&remote, repo, argv[1]) < 0) {
if (git_remote_lookup(&remote, repo, argv[1]) < 0)
if (git_remote_create_anonymous(&remote, repo, argv[1]) < 0)
return -1;
}
goto on_error;
// Set up the callbacks (only update_tips for now)
/* Set up the callbacks (only update_tips for now) */
fetch_opts.callbacks.update_tips = &update_cb;
fetch_opts.callbacks.sideband_progress = &progress_cb;
fetch_opts.callbacks.transfer_progress = transfer_progress_cb;
......@@ -98,7 +98,7 @@ int fetch(git_repository *repo, int argc, char **argv)
* "fetch".
*/
if (git_remote_fetch(remote, NULL, &fetch_opts, "fetch") < 0)
return -1;
goto on_error;
/**
* If there are local objects (we got a thin pack), then tell
......
......@@ -246,6 +246,18 @@ GIT_EXTERN(int) git_branch_is_head(
const git_reference *branch);
/**
* Determine if the current branch is checked out in any linked
* repository.
*
* @param branch Reference to the branch.
*
* @return 1 if branch is checked out, 0 if it isn't,
* error code otherwise.
*/
GIT_EXTERN(int) git_branch_is_checked_out(
const git_reference *branch);
/**
* Return the name of remote that the remote tracking branch belongs to.
*
* @param out Pointer to the user-allocated git_buf which will be filled with the name of the remote.
......
......@@ -255,7 +255,8 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor(
/**
* Get an arbitrary header field
*
* @param out the buffer to fill
* @param out the buffer to fill; existing content will be
* overwritten
* @param commit the commit to look in
* @param field the header field to return
* @return 0 on succeess, GIT_ENOTFOUND if the field does not exist,
......@@ -270,8 +271,10 @@ GIT_EXTERN(int) git_commit_header_field(git_buf *out, const git_commit *commit,
* `GITERR_INVALID`. If the commit does not have a signature, the
* error class will be `GITERR_OBJECT`.
*
* @param signature the signature block
* @param signed_data signed data; this is the commit contents minus the signature block
* @param signature the signature block; existing content will be
* overwritten
* @param signed_data signed data; this is the commit contents minus the signature block;
* existing content will be overwritten
* @param repo the repository in which the commit exists
* @param commit_id the commit from which to extract the data
* @param field the name of the header field containing the signature
......
......@@ -109,9 +109,27 @@ GIT_EXTERN(void) git_libgit2_version(int *major, int *minor, int *rev);
* was compiled
*/
typedef enum {
/**
* If set, libgit2 was built thread-aware and can be safely used from multiple
* threads.
*/
GIT_FEATURE_THREADS = (1 << 0),
/**
* If set, libgit2 was built with and linked against a TLS implementation.
* Custom TLS streams may still be added by the user to support HTTPS
* regardless of this.
*/
GIT_FEATURE_HTTPS = (1 << 1),
/**
* If set, libgit2 was built with and linked against libssh2. A custom
* transport may still be added by the user to support libssh2 regardless of
* this.
*/
GIT_FEATURE_SSH = (1 << 2),
/**
* If set, libgit2 was built with support for sub-second resolution in file
* modification times.
*/
GIT_FEATURE_NSEC = (1 << 3),
} git_feature_t;
......@@ -157,8 +175,14 @@ typedef enum {
GIT_OPT_SET_SSL_CERT_LOCATIONS,
GIT_OPT_SET_USER_AGENT,
GIT_OPT_ENABLE_STRICT_OBJECT_CREATION,
GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION,
GIT_OPT_SET_SSL_CIPHERS,
GIT_OPT_GET_USER_AGENT,
GIT_OPT_ENABLE_OFS_DELTA,
GIT_OPT_ENABLE_FSYNC_GITDIR,
GIT_OPT_GET_WINDOWS_SHAREMODE,
GIT_OPT_SET_WINDOWS_SHAREMODE,
GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION,
} git_libgit2_opt_t;
/**
......@@ -263,19 +287,64 @@ typedef enum {
* > - `user_agent` is the value that will be delivered as the
* > User-Agent header on HTTP requests.
*
* * opts(GIT_OPT_SET_WINDOWS_SHAREMODE, unsigned long value)
*
* > Set the share mode used when opening files on Windows.
* > For more information, see the documentation for CreateFile.
* > The default is: FILE_SHARE_READ | FILE_SHARE_WRITE. This is
* > ignored and unused on non-Windows platforms.
*
* * opts(GIT_OPT_GET_WINDOWS_SHAREMODE, unsigned long *value)
*
* > Get the share mode used when opening files on Windows.
*
* * opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, int enabled)
*
* > Enable strict input validation when creating new objects
* > to ensure that all inputs to the new objects are valid. For
* > example, when this is enabled, the parent(s) and tree inputs
* > will be validated when creating a new commit. This defaults
* > to disabled.
* > to enabled.
*
* * opts(GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, int enabled)
*
* > Validate the target of a symbolic ref when creating it. For
* > example, `foobar` is not a valid ref, therefore `foobar` is
* > not a valid target for a symbolic ref by default, whereas
* > `refs/heads/foobar` is. Disabling this bypasses validation
* > so that an arbitrary strings such as `foobar` can be used
* > for a symbolic ref target. This defaults to enabled.
*
* * opts(GIT_OPT_SET_SSL_CIPHERS, const char *ciphers)
*
* > Set the SSL ciphers use for HTTPS connections.
* >
* > - `ciphers` is the list of ciphers that are eanbled.
*
* * opts(GIT_OPT_ENABLE_OFS_DELTA, int enabled)
*
* > Enable or disable the use of "offset deltas" when creating packfiles,
* > and the negotiation of them when talking to a remote server.
* > Offset deltas store a delta base location as an offset into the
* > packfile from the current location, which provides a shorter encoding
* > and thus smaller resultant packfiles.
* > Packfiles containing offset deltas can still be read.
* > This defaults to enabled.
*
* * opts(GIT_OPT_ENABLE_FSYNC_GITDIR, int enabled)
*
* > Enable synchronized writes of files in the gitdir using `fsync`
* > (or the platform equivalent) to ensure that new object data
* > is written to permanent storage, not simply cached. This
* > defaults to disabled.
*
* opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, int enabled)
*
* > Enable strict verification of object hashsums when reading
* > objects from disk. This may impact performance due to an
* > additional checksum calculation on each object. This defaults
* > to enabled.
*
* @param option Option key
* @param ... value to set the option
* @return 0 on success, <0 on failure
......
......@@ -44,8 +44,8 @@ typedef enum {
typedef struct git_describe_options {
unsigned int version;
unsigned int max_candidates_tags; /** default: 10 */
unsigned int describe_strategy; /** default: GIT_DESCRIBE_DEFAULT */
unsigned int max_candidates_tags; /**< default: 10 */
unsigned int describe_strategy; /**< default: GIT_DESCRIBE_DEFAULT */
const char *pattern;
/**
* When calculating the distance from the matching tag or
......@@ -105,6 +105,9 @@ typedef struct {
GIT_EXTERN(int) git_describe_init_format_options(git_describe_format_options *opts, unsigned int version);
/**
* A struct that stores the result of a describe operation.
*/
typedef struct git_describe_result git_describe_result;
/**
......
......@@ -515,12 +515,12 @@ typedef int(*git_diff_binary_cb)(
* Structure describing a hunk of a diff.
*/
typedef struct {
int old_start; /** Starting line number in old_file */
int old_lines; /** Number of lines in old_file */
int new_start; /** Starting line number in new_file */
int new_lines; /** Number of lines in new_file */
size_t header_len; /** Number of bytes in header text */
char header[GIT_DIFF_HUNK_HEADER_SIZE]; /** Header text, NUL-byte terminated */
int old_start; /**< Starting line number in old_file */
int old_lines; /**< Number of lines in old_file */
int new_start; /**< Starting line number in new_file */
int new_lines; /**< Number of lines in new_file */
size_t header_len; /**< Number of bytes in header text */
char header[GIT_DIFF_HUNK_HEADER_SIZE]; /**< Header text, NUL-byte terminated */
} git_diff_hunk;
/**
......@@ -1400,6 +1400,51 @@ GIT_EXTERN(int) git_diff_format_email_init_options(
git_diff_format_email_options *opts,
unsigned int version);
/**
* Patch ID options structure
*
* Initialize with `GIT_DIFF_PATCHID_OPTIONS_INIT` macro to
* correctly set the default values and version.
*/
typedef struct git_diff_patchid_options {
unsigned int version;
} git_diff_patchid_options;
#define GIT_DIFF_PATCHID_OPTIONS_VERSION 1
#define GIT_DIFF_PATCHID_OPTIONS_INIT { GIT_DIFF_PATCHID_OPTIONS_VERSION }
/**
* Initialize `git_diff_patchid_options` structure.
*
* Initializes the structure with default values. Equivalent to
* creating an instance with `GIT_DIFF_PATCHID_OPTIONS_INIT`.
*/
GIT_EXTERN(int) git_diff_patchid_init_options(
git_diff_patchid_options *opts,
unsigned int version);
/**
* Calculate the patch ID for the given patch.
*
* Calculate a stable patch ID for the given patch by summing the
* hash of the file diffs, ignoring whitespace and line numbers.
* This can be used to derive whether two diffs are the same with
* a high probability.
*
* Currently, this function only calculates stable patch IDs, as
* defined in git-patch-id(1), and should in fact generate the
* same IDs as the upstream git project does.
*
* @param out Pointer where the calculated patch ID shoul be
* stored
* @param diff The diff to calculate the ID for
* @param opts Options for how to calculate the patch ID. This is
* intended for future changes, as currently no options are
* available.
* @return 0 on success, an error code otherwise.
*/
GIT_EXTERN(int) git_diff_patchid(git_oid *out, git_diff *diff, git_diff_patchid_options *opts);
GIT_END_DECL
/** @} */
......
......@@ -53,6 +53,8 @@ typedef enum {
GIT_PASSTHROUGH = -30, /**< Internal only */
GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */
GIT_RETRY = -32, /**< Internal only */
GIT_EMISMATCH = -33, /**< Hashsum mismatch in object */
} git_error_code;
/**
......@@ -100,6 +102,8 @@ typedef enum {
GITERR_REBASE,
GITERR_FILESYSTEM,
GITERR_PATCH,
GITERR_WORKTREE,
GITERR_SHA1
} git_error_t;
/**
......
......@@ -14,7 +14,7 @@ GIT_BEGIN_DECL
/**
* Init the global state
*
* This function must the called before any other libgit2 function in
* This function must be called before any other libgit2 function in
* order to set up global state and threading.
*
* This function may be called multiple times - it will return the number
......
......@@ -575,15 +575,16 @@ GIT_EXTERN(int) git_index_remove_bypath(git_index *index, const char *path);
* This method will fail in bare index instances.
*
* The `pathspec` is a list of file names or shell glob patterns that will
* matched against files in the repository's working directory. Each file
* that matches will be added to the index (either updating an existing
* entry or adding a new entry). You can disable glob expansion and force
* exact matching with the `GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH` flag.
* be matched against files in the repository's working directory. Each
* file that matches will be added to the index (either updating an
* existing entry or adding a new entry). You can disable glob expansion
* and force exact matching with the `GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH`
* flag.
*
* Files that are ignored will be skipped (unlike `git_index_add_bypath`).
* If a file is already tracked in the index, then it *will* be updated
* even if it is ignored. Pass the `GIT_INDEX_ADD_FORCE` flag to
* skip the checking of ignore rules.
* even if it is ignored. Pass the `GIT_INDEX_ADD_FORCE` flag to skip
* the checking of ignore rules.
*
* To emulate `git add -A` and generate an error if the pathspec contains
* the exact path of an ignored file (when not using FORCE), add the
......
......@@ -290,7 +290,8 @@ typedef struct {
} git_merge_options;
#define GIT_MERGE_OPTIONS_VERSION 1
#define GIT_MERGE_OPTIONS_INIT {GIT_MERGE_OPTIONS_VERSION}
#define GIT_MERGE_OPTIONS_INIT { \
GIT_MERGE_OPTIONS_VERSION, GIT_MERGE_FIND_RENAMES }
/**
* Initializes a `git_merge_options` with default values. Equivalent to
......
......@@ -488,7 +488,7 @@ GIT_EXTERN(git_otype) git_odb_object_type(git_odb_object *object);
* The backends are checked in relative ordering, based on the
* value of the `priority` parameter.
*
* Read <odb_backends.h> for more information.
* Read <sys/odb_backend.h> for more information.
*
* @param odb database to add the backend to
* @param backend pointer to a git_odb_backend instance
......@@ -509,7 +509,7 @@ GIT_EXTERN(int) git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int
*
* Writing is disabled on alternate backends.
*
* Read <odb_backends.h> for more information.
* Read <sys/odb_backend.h> for more information.
*
* @param odb database to add the backend to
* @param backend pointer to a git_odb_backend instance
......
......@@ -39,7 +39,7 @@ GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **out, const char *objects_
* @param out location to store the odb backend pointer
* @param objects_dir the Git repository's objects directory
* @param compression_level zlib compression level to use
* @param do_fsync whether to do an fsync() after writing (currently ignored)
* @param do_fsync whether to do an fsync() after writing
* @param dir_mode permissions to use creating a directory or 0 for defaults
* @param file_mode permissions to use creating a file or 0 for defaults
*
......
......@@ -50,17 +50,16 @@ GIT_EXTERN(int) git_oid_fromstr(git_oid *out, const char *str);
* Parse a hex formatted null-terminated string into a git_oid.
*
* @param out oid structure the result is written into.
* @param str input hex string; must be at least 4 characters
* long and null-terminated.
* @param str input hex string; must be null-terminated.
* @return 0 or an error code
*/
GIT_EXTERN(int) git_oid_fromstrp(git_oid *out, const char *str);
/**
* Parse N characters of a hex formatted object id into a git_oid
* Parse N characters of a hex formatted object id into a git_oid.
*
* If N is odd, N-1 characters will be parsed instead.
* The remaining space in the git_oid will be set to zero.
* If N is odd, the last byte's high nibble will be read in and the
* low nibble set to zero.
*
* @param out oid structure the result is written into.
* @param str input hex string of at least size `length`
......
......@@ -96,7 +96,7 @@ GIT_EXTERN(int) git_patch_from_blob_and_buffer(
git_patch **out,
const git_blob *old_blob,
const char *old_as_path,
const char *buffer,
const void *buffer,
size_t buffer_len,
const char *buffer_as_path,
const git_diff_options *opts);
......@@ -124,7 +124,7 @@ GIT_EXTERN(int) git_patch_from_buffers(
const void *old_buffer,
size_t old_len,
const char *old_as_path,
const char *new_buffer,
const void *new_buffer,
size_t new_len,
const char *new_as_path,
const git_diff_options *opts);
......@@ -191,7 +191,7 @@ GIT_EXTERN(int) git_patch_get_hunk(
*
* @param patch The git_patch object
* @param hunk_idx Index of the hunk
* @return Number of lines in hunk or -1 if invalid hunk index
* @return Number of lines in hunk or GIT_ENOTFOUND if invalid hunk index
*/
GIT_EXTERN(int) git_patch_num_lines_in_hunk(
const git_patch *patch,
......
......@@ -19,7 +19,7 @@ typedef enum {
/**
* Do not attempt to connect through a proxy
*
* If built against lbicurl, it itself may attempt to connect
* If built against libcurl, it itself may attempt to connect
* to a proxy if the environment variables specify it.
*/
GIT_PROXY_NONE,
......
......@@ -26,8 +26,6 @@
*/
GIT_BEGIN_DECL
typedef int (*git_remote_rename_problem_cb)(const char *problematic_refspec, void *payload);
/**
* Add a remote with the default fetch refspec to the repository's configuration.
*
......@@ -78,6 +76,24 @@ GIT_EXTERN(int) git_remote_create_anonymous(
const char *url);
/**
* Create a remote without a connected local repo
*
* Create a remote with the given url in-memory. You can use this when
* you have a URL instead of a remote's name.
*
* Contrasted with git_remote_create_anonymous, a detached remote
* will not consider any repo configuration values (such as insteadof url
* substitutions).
*
* @param out pointer to the new remote objects
* @param url the remote repository's URL
* @return 0 or an error code
*/
GIT_EXTERN(int) git_remote_create_detached(
git_remote **out,
const char *url);
/**
* Get the information for a particular remote
*
* The name will be checked for validity.
......@@ -360,6 +376,8 @@ typedef struct {
} git_push_update;
/**
* Callback used to inform of upcoming updates.
*
* @param updates an array containing the updates which will be sent
* as commands to the destination.
* @param len number of elements in `updates`
......@@ -569,7 +587,7 @@ typedef struct {
* Initializes a `git_fetch_options` with default values. Equivalent to
* creating an instance with GIT_FETCH_OPTIONS_INIT.
*
* @param opts the `git_push_options` instance to initialize.
* @param opts the `git_fetch_options` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_FETCH_OPTIONS_VERSION` here.
* @return Zero on success; -1 on failure.
......@@ -715,8 +733,8 @@ GIT_EXTERN(int) git_remote_prune(git_remote *remote, const git_remote_callbacks
* Peform all the steps from a push.
*
* @param remote the remote to push to
* @param refspecs the refspecs to use for pushing. If none are
* passed, the configured refspecs will be used
* @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
*/
GIT_EXTERN(int) git_remote_push(git_remote *remote,
......@@ -796,7 +814,7 @@ GIT_EXTERN(int) git_remote_is_valid_name(const char *remote_name);
* for the remote will be removed.
*
* @param repo the repository in which to act
* @param name the name of the remove to delete
* @param name the name of the remote to delete
* @return 0 on success, or an error code.
*/
GIT_EXTERN(int) git_remote_delete(git_repository *repo, const char *name);
......
......@@ -35,6 +35,17 @@ GIT_BEGIN_DECL
* @return 0 or an error code
*/
GIT_EXTERN(int) git_repository_open(git_repository **out, const char *path);
/**
* Open working tree as a repository
*
* Open the working directory of the working tree as a normal
* repository that can then be worked on.
*
* @param out Output pointer containing opened repository
* @param wt Working tree to open
* @return 0 or an error code
*/
GIT_EXTERN(int) git_repository_open_from_worktree(git_repository **out, git_worktree *wt);
/**
* Create a "fake" repository to wrap an object database
......@@ -335,6 +346,17 @@ GIT_EXTERN(int) git_repository_init_ext(
GIT_EXTERN(int) git_repository_head(git_reference **out, git_repository *repo);
/**
* Retrieve the referenced HEAD for the worktree
*
* @param out pointer to the reference which will be retrieved
* @param repo a repository object
* @param name name of the worktree to retrieve HEAD for
* @return 0 when successful, error-code otherwise
*/
GIT_EXTERN(int) git_repository_head_for_worktree(git_reference **out, git_repository *repo,
const char *name);
/**
* Check if a repository's HEAD is detached
*
* A repository's HEAD is detached when it points directly to a commit
......@@ -346,6 +368,20 @@ GIT_EXTERN(int) git_repository_head(git_reference **out, git_repository *repo);
*/
GIT_EXTERN(int) git_repository_head_detached(git_repository *repo);
/*
* Check if a worktree's HEAD is detached
*
* A worktree's HEAD is detached when it points directly to a
* commit instead of a branch.
*
* @param repo a repository object
* @param name name of the worktree to retrieve HEAD for
* @return 1 if HEAD is detached, 0 if its not; error code if
* there was an error
*/
GIT_EXTERN(int) git_repository_head_detached_for_worktree(git_repository *repo,
const char *name);
/**
* Check if the current branch is unborn
*
......@@ -371,6 +407,42 @@ GIT_EXTERN(int) git_repository_head_unborn(git_repository *repo);
GIT_EXTERN(int) git_repository_is_empty(git_repository *repo);
/**
* List of items which belong to the git repository layout
*/
typedef enum {
GIT_REPOSITORY_ITEM_GITDIR,
GIT_REPOSITORY_ITEM_WORKDIR,
GIT_REPOSITORY_ITEM_COMMONDIR,
GIT_REPOSITORY_ITEM_INDEX,
GIT_REPOSITORY_ITEM_OBJECTS,
GIT_REPOSITORY_ITEM_REFS,
GIT_REPOSITORY_ITEM_PACKED_REFS,
GIT_REPOSITORY_ITEM_REMOTES,
GIT_REPOSITORY_ITEM_CONFIG,
GIT_REPOSITORY_ITEM_INFO,
GIT_REPOSITORY_ITEM_HOOKS,
GIT_REPOSITORY_ITEM_LOGS,
GIT_REPOSITORY_ITEM_MODULES,
GIT_REPOSITORY_ITEM_WORKTREES
} git_repository_item_t;
/**
* Get the location of a specific repository file or directory
*
* This function will retrieve the path of a specific repository
* item. It will thereby honor things like the repository's
* common directory, gitdir, etc. In case a file path cannot
* exist for a given item (e.g. the working directory of a bare
* repository), GIT_ENOTFOUND is returned.
*
* @param out Buffer to store the path at
* @param repo Repository to get path for
* @param item The repository item for which to retrieve the path
* @return 0, GIT_ENOTFOUND if the path cannot exist or an error code
*/
GIT_EXTERN(int) git_repository_item_path(git_buf *out, git_repository *repo, git_repository_item_t item);
/**
* Get the path of this repository
*
* This is the path of the `.git` folder for normal repositories,
......@@ -393,6 +465,17 @@ GIT_EXTERN(const char *) git_repository_path(git_repository *repo);
GIT_EXTERN(const char *) git_repository_workdir(git_repository *repo);
/**
* Get the path of the shared common directory for this repository
*
* If the repository is bare is not a worktree, the git directory
* path is returned.
*
* @param repo A repository object
* @return the path to the common dir
*/
GIT_EXTERN(const char *) git_repository_commondir(git_repository *repo);
/**
* Set the path to the working directory for this repository
*
* The working directory doesn't need to be the same one
......@@ -421,6 +504,14 @@ GIT_EXTERN(int) git_repository_set_workdir(
GIT_EXTERN(int) git_repository_is_bare(git_repository *repo);
/**
* Check if a repository is a linked work tree
*
* @param repo Repo to test
* @return 1 if the repository is a linked work tree, 0 otherwise.
*/
GIT_EXTERN(int) git_repository_is_worktree(git_repository *repo);
/**
* Get the configuration file for this repository.
*
* If a configuration file has not been set, the default
......
......@@ -53,7 +53,7 @@ typedef enum {
*
* @param reset_type Kind of reset operation to perform.
*
* @param checkout_opts Checkout options to be used for a HARD reset.
* @param checkout_opts Optional checkout options to be used for a HARD reset.
* The checkout_strategy field will be overridden (based on reset_type).
* This parameter can be used to propagate notify and progress callbacks.
*
......@@ -61,7 +61,7 @@ typedef enum {
*/
GIT_EXTERN(int) git_reset(
git_repository *repo,
git_object *target,
const git_object *target,
git_reset_t reset_type,
const git_checkout_options *checkout_opts);
......@@ -79,7 +79,7 @@ GIT_EXTERN(int) git_reset(
*/
GIT_EXTERN(int) git_reset_from_annotated(
git_repository *repo,
git_annotated_commit *commit,
const git_annotated_commit *commit,
git_reset_t reset_type,
const git_checkout_options *checkout_opts);
......@@ -103,8 +103,8 @@ GIT_EXTERN(int) git_reset_from_annotated(
*/
GIT_EXTERN(int) git_reset_default(
git_repository *repo,
git_object *target,
git_strarray* pathspecs);
const git_object *target,
const git_strarray* pathspecs);
/** @} */
GIT_END_DECL
......
......@@ -75,7 +75,7 @@ GIT_EXTERN(int) git_revert_commit(
*
* @param repo the repository to revert
* @param commit the commit to revert
* @param given_opts merge flags
* @param given_opts the revert options (or null for defaults)
* @return zero on success, -1 on failure.
*/
GIT_EXTERN(int) git_revert(
......
......@@ -25,17 +25,15 @@ GIT_BEGIN_DECL
*/
typedef enum {
/**
* Sort the repository contents in no particular ordering;
* this sorting is arbitrary, implementation-specific
* and subject to change at any time.
* Sort the output with the same default time-order method from git.
* This is the default sorting for new walkers.
*/
GIT_SORT_NONE = 0,
/**
* Sort the repository contents in topological order
* (parents before children); this sorting mode
* can be combined with time sorting.
* Sort the repository contents in topological order (parents before
* children); this sorting mode can be combined with time sorting to
* produce git's "time-order".
*/
GIT_SORT_TOPOLOGICAL = 1 << 0,
......
......@@ -173,7 +173,7 @@ GIT_EXTERN(int) git_stash_apply_init_options(
* @param repo The owning repository.
* @param index The position within the stash list. 0 points to the
* most recent stashed state.
* @param options Options to control how stashes are applied.
* @param options Optional options to control how stashes are applied.
*
* @return 0 on success, GIT_ENOTFOUND if there's no stashed state for the
* given index, GIT_EMERGECONFLICT if changes exist in the working
......@@ -242,7 +242,7 @@ GIT_EXTERN(int) git_stash_drop(
* @param repo The owning repository.
* @param index The position within the stash list. 0 points to the
* most recent stashed state.
* @param options Options to control how stashes are applied.
* @param options Optional options to control how stashes are applied.
*
* @return 0 on success, GIT_ENOTFOUND if there's no stashed state for the given
* index, or error code. (see git_stash_apply() above for details)
......
......@@ -134,9 +134,7 @@ typedef struct git_submodule_update_options {
* checkout, set the `checkout_strategy` to
* `GIT_CHECKOUT_NONE`. Generally you will want the use
* GIT_CHECKOUT_SAFE to update files in the working
* directory. Use the `clone_checkout_strategy` field
* to set the checkout strategy that will be used in
* the case where update needs to clone the repository.
* directory.
*/
git_checkout_options checkout_opts;
......@@ -149,13 +147,6 @@ typedef struct git_submodule_update_options {
git_fetch_options fetch_opts;
/**
* The checkout strategy to use when the sub repository needs to
* be cloned. Use GIT_CHECKOUT_SAFE to create all files
* in the working directory for the newly cloned repository.
*/
unsigned int clone_checkout_strategy;
/**
* Allow fetching from the submodule's default remote if the target
* commit isn't found. Enabled by default.
*/
......@@ -166,7 +157,7 @@ typedef struct git_submodule_update_options {
#define GIT_SUBMODULE_UPDATE_OPTIONS_INIT \
{ GIT_SUBMODULE_UPDATE_OPTIONS_VERSION, \
{ GIT_CHECKOUT_OPTIONS_VERSION, GIT_CHECKOUT_SAFE }, \
GIT_FETCH_OPTIONS_INIT, GIT_CHECKOUT_SAFE, 1 }
GIT_FETCH_OPTIONS_INIT, 1 }
/**
* Initializes a `git_submodule_update_options` with default values.
......
......@@ -271,6 +271,17 @@ struct git_filter {
};
#define GIT_FILTER_VERSION 1
#define GIT_FILTER_INIT {GIT_FILTER_VERSION}
/**
* Initializes a `git_filter` with default values. Equivalent to
* creating an instance with GIT_FILTER_INIT.
*
* @param filter the `git_filter` struct to initialize.
* @param version Version the struct; pass `GIT_FILTER_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_filter_init(git_filter *filter, unsigned int version);
/**
* Register a filter under a given name with a given priority.
......
......@@ -36,23 +36,23 @@ GIT_EXTERN(git_merge_driver *) git_merge_driver_lookup(const char *name);
typedef struct git_merge_driver_source git_merge_driver_source;
/** Get the repository that the source data is coming from. */
GIT_EXTERN(git_repository *) git_merge_driver_source_repo(
GIT_EXTERN(const git_repository *) git_merge_driver_source_repo(
const git_merge_driver_source *src);
/** Gets the ancestor of the file to merge. */
GIT_EXTERN(git_index_entry *) git_merge_driver_source_ancestor(
GIT_EXTERN(const git_index_entry *) git_merge_driver_source_ancestor(
const git_merge_driver_source *src);
/** Gets the ours side of the file to merge. */
GIT_EXTERN(git_index_entry *) git_merge_driver_source_ours(
GIT_EXTERN(const git_index_entry *) git_merge_driver_source_ours(
const git_merge_driver_source *src);
/** Gets the theirs side of the file to merge. */
GIT_EXTERN(git_index_entry *) git_merge_driver_source_theirs(
GIT_EXTERN(const git_index_entry *) git_merge_driver_source_theirs(
const git_merge_driver_source *src);
/** Gets the merge file options that the merge was invoked with */
GIT_EXTERN(git_merge_file_options *) git_merge_driver_source_file_options(
GIT_EXTERN(const git_merge_file_options *) git_merge_driver_source_file_options(
const git_merge_driver_source *src);
......
......@@ -135,6 +135,35 @@ GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index
*/
GIT_EXTERN(int) git_repository_set_bare(git_repository *repo);
/**
* Load and cache all submodules.
*
* Because the `.gitmodules` file is unstructured, loading submodules is an
* O(N) operation. Any operation (such as `git_rebase_init`) that requires
* accessing all submodules is O(N^2) in the number of submodules, if it
* has to look each one up individually. This function loads all submodules
* and caches them so that subsequent calls to `git_submodule_lookup` are O(1).
*
* @param repo the repository whose submodules will be cached.
*/
GIT_EXTERN(int) git_repository_submodule_cache_all(
git_repository *repo);
/**
* Clear the submodule cache.
*
* Clear the submodule cache populated by `git_repository_submodule_cache_all`.
* If there is no cache, do nothing.
*
* The cache incorporates data from the repository's configuration, as well
* as the state of the working tree, the index, and HEAD. So any time any
* of these has changed, the cache might become invalid.
*
* @param repo the repository whose submodule cache will be cleared
*/
GIT_EXTERN(int) git_repository_submodule_cache_clear(
git_repository *repo);
/** @} */
GIT_END_DECL
#endif
......@@ -241,6 +241,16 @@ GIT_EXTERN(int) git_transport_smart_certificate_check(git_transport *transport,
*/
GIT_EXTERN(int) git_transport_smart_credentials(git_cred **out, git_transport *transport, const char *user, int methods);
/**
* Get a copy of the proxy options
*
* The url is copied and must be freed by the caller.
*
* @param out options struct to fill
* @param transport the transport to extract the data from.
*/
GIT_EXTERN(int) git_transport_smart_proxy_options(git_proxy_options *out, git_transport *transport);
/*
*** End of base transport interface ***
*** Begin interface for subtransports for the smart transport ***
......
......@@ -8,6 +8,14 @@
#define INCLUDE_git_transaction_h__
#include "common.h"
/**
* @file git2/transaction.h
* @brief Git transactional reference routines
* @defgroup git_transaction Git transactional reference routines
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
......@@ -107,5 +115,6 @@ GIT_EXTERN(int) git_transaction_commit(git_transaction *tx);
*/
GIT_EXTERN(void) git_transaction_free(git_transaction *tx);
/** @} */
GIT_END_DECL
#endif
......@@ -321,13 +321,13 @@ GIT_EXTERN(void) git_cred_free(git_cred *cred);
/**
* Signature of a function which acquires a credential object.
*
* - cred: The newly created credential object.
* - url: The resource for which we are demanding a credential.
* - username_from_url: The username that was embedded in a "user\@host"
* @param cred The newly created credential object.
* @param url The resource for which we are demanding a credential.
* @param username_from_url The username that was embedded in a "user\@host"
* remote url, or NULL if not included.
* - allowed_types: A bitmask stating which cred types are OK to return.
* - payload: The payload provided when specifying this callback.
* - returns 0 for success, < 0 to indicate an error, > 0 to indicate
* @param allowed_types A bitmask stating which cred types are OK to return.
* @param payload The payload provided when specifying this callback.
* @return 0 for success, < 0 to indicate an error, > 0 to indicate
* no credential was acquired
*/
typedef int (*git_cred_acquire_cb)(
......
......@@ -375,6 +375,19 @@ GIT_EXTERN(void) git_treebuilder_filter(
GIT_EXTERN(int) git_treebuilder_write(
git_oid *id, git_treebuilder *bld);
/**
* Write the contents of the tree builder as a tree object
* using a shared git_buf.
*
* @see git_treebuilder_write
*
* @param oid Pointer to store the OID of the newly written tree
* @param bld Tree builder to write
* @param tree Shared buffer for writing the tree. Will be grown as necessary.
* @return 0 or an error code
*/
GIT_EXTERN(int) git_treebuilder_write_with_buffer(
git_oid *oid, git_treebuilder *bld, git_buf *tree);
/** Callback for the tree traversal method */
typedef int (*git_treewalk_cb)(
......
......@@ -104,6 +104,9 @@ typedef struct git_refdb_backend git_refdb_backend;
*/
typedef struct git_repository git_repository;
/** Representation of a working tree */
typedef struct git_worktree git_worktree;
/** Representation of a generic object in a repository */
typedef struct git_object git_object;
......
......@@ -7,12 +7,12 @@
#ifndef INCLUDE_git_version_h__
#define INCLUDE_git_version_h__
#define LIBGIT2_VERSION "0.24.0"
#define LIBGIT2_VERSION "0.26.0"
#define LIBGIT2_VER_MAJOR 0
#define LIBGIT2_VER_MINOR 24
#define LIBGIT2_VER_MINOR 26
#define LIBGIT2_VER_REVISION 0
#define LIBGIT2_VER_PATCH 0
#define LIBGIT2_SOVERSION 24
#define LIBGIT2_SOVERSION 26
#endif
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_git_worktree_h__
#define INCLUDE_git_worktree_h__
#include "common.h"
#include "buffer.h"
#include "types.h"
#include "strarray.h"
/**
* @file git2/worktrees.h
* @brief Git worktree related functions
* @defgroup git_commit Git worktree related functions
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* List names of linked working trees
*
* The returned list should be released with `git_strarray_free`
* when no longer needed.
*
* @param out pointer to the array of working tree names
* @param repo the repo to use when listing working trees
* @return 0 or an error code
*/
GIT_EXTERN(int) git_worktree_list(git_strarray *out, git_repository *repo);
/**
* Lookup a working tree by its name for a given repository
*
* @param out Output pointer to looked up worktree or `NULL`
* @param repo The repository containing worktrees
* @param name Name of the working tree to look up
* @return 0 or an error code
*/
GIT_EXTERN(int) git_worktree_lookup(git_worktree **out, git_repository *repo, const char *name);
/**
* Open a worktree of a given repository
*
* If a repository is not the main tree but a worktree, this
* function will look up the worktree inside the parent
* repository and create a new `git_worktree` structure.
*
* @param out Out-pointer for the newly allocated worktree
* @param repo Repository to look up worktree for
*/
GIT_EXTERN(int) git_worktree_open_from_repository(git_worktree **out, git_repository *repo);
/**
* Free a previously allocated worktree
*
* @param wt worktree handle to close. If NULL nothing occurs.
*/
GIT_EXTERN(void) git_worktree_free(git_worktree *wt);
/**
* Check if worktree is valid
*
* A valid worktree requires both the git data structures inside
* the linked parent repository and the linked working copy to be
* present.
*
* @param wt Worktree to check
* @return 0 when worktree is valid, error-code otherwise
*/
GIT_EXTERN(int) git_worktree_validate(const git_worktree *wt);
typedef struct git_worktree_add_options {
unsigned int version;
int lock; /**< lock newly created worktree */
} git_worktree_add_options;
#define GIT_WORKTREE_ADD_OPTIONS_VERSION 1
#define GIT_WORKTREE_ADD_OPTIONS_INIT {GIT_WORKTREE_ADD_OPTIONS_VERSION,0}
/**
* Initializes a `git_worktree_add_options` with default vaules.
* Equivalent to creating an instance with
* GIT_WORKTREE_ADD_OPTIONS_INIT.
*
* @param opts the struct to initialize
* @param version Verison of struct; pass `GIT_WORKTREE_ADD_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
int git_worktree_add_init_options(git_worktree_add_options *opts,
unsigned int version);
/**
* Add a new working tree
*
* Add a new working tree for the repository, that is create the
* required data structures inside the repository and check out
* the current HEAD at `path`
*
* @param out Output pointer containing new working tree
* @param repo Repository to create working tree for
* @param name Name of the working tree
* @param path Path to create working tree at
* @param opts Options to modify default behavior. May be NULL
* @return 0 or an error code
*/
GIT_EXTERN(int) git_worktree_add(git_worktree **out, git_repository *repo,
const char *name, const char *path,
const git_worktree_add_options *opts);
/**
* Lock worktree if not already locked
*
* Lock a worktree, optionally specifying a reason why the linked
* working tree is being locked.
*
* @param wt Worktree to lock
* @param reason Reason why the working tree is being locked
* @return 0 on success, non-zero otherwise
*/
GIT_EXTERN(int) git_worktree_lock(git_worktree *wt, char *reason);
/**
* Unlock a locked worktree
*
* @param wt Worktree to unlock
* @return 0 on success, 1 if worktree was not locked, error-code
* otherwise
*/
GIT_EXTERN(int) git_worktree_unlock(git_worktree *wt);
/**
* Check if worktree is locked
*
* A worktree may be locked if the linked working tree is stored
* on a portable device which is not available.
*
* @param reason Buffer to store reason in. If NULL no reason is stored.
* @param wt Worktree to check
* @return 0 when the working tree not locked, a value greater
* than zero if it is locked, less than zero if there was an
* error
*/
GIT_EXTERN(int) git_worktree_is_locked(git_buf *reason, const git_worktree *wt);
/**
* Flags which can be passed to git_worktree_prune to alter its
* behavior.
*/
typedef enum {
/* Prune working tree even if working tree is valid */
GIT_WORKTREE_PRUNE_VALID = 1u << 0,
/* 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_t;
typedef struct git_worktree_prune_options {
unsigned int version;
uint32_t flags;
} git_worktree_prune_options;
#define GIT_WORKTREE_PRUNE_OPTIONS_VERSION 1
#define GIT_WORKTREE_PRUNE_OPTIONS_INIT {GIT_WORKTREE_PRUNE_OPTIONS_VERSION,0}
/**
* Initializes a `git_worktree_prune_options` with default vaules.
* Equivalent to creating an instance with
* GIT_WORKTREE_PRUNE_OPTIONS_INIT.
*
* @param opts the struct to initialize
* @param version Verison of struct; pass `GIT_WORKTREE_PRUNE_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_worktree_prune_init_options(
git_worktree_prune_options *opts,
unsigned int version);
/**
* Is the worktree prunable with the given options?
*
* A worktree is not prunable in the following scenarios:
*
* - the worktree is linking to a valid on-disk worktree. The
* `valid` member will cause this check to be ignored.
* - the worktree is locked. The `locked` flag will cause this
* check to be ignored.
*
* 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.
*/
GIT_EXTERN(int) git_worktree_is_prunable(git_worktree *wt,
git_worktree_prune_options *opts);
/**
* Prune working tree
*
* Prune the working tree, that is remove the git data
* structures on disk. The repository will only be pruned of
* `git_worktree_is_prunable` succeeds.
*
* @param wt Worktree to prune
* @param opts Specifies which checks to override. See
* `git_worktree_is_prunable`. May be NULL
* @return 0 or an error code
*/
GIT_EXTERN(int) git_worktree_prune(git_worktree *wt,
git_worktree_prune_options *opts);
/** @} */
GIT_END_DECL
#endif
prefix=@PKGCONFIG_PREFIX@
prefix="@PKGCONFIG_PREFIX@"
libdir=@PKGCONFIG_LIBDIR@
includedir=@PKGCONFIG_INCLUDEDIR@
......@@ -6,7 +6,7 @@ Name: libgit2
Description: The git library, take 2
Version: @LIBGIT2_VERSION_STRING@
Libs: -L"${libdir}" -lgit2
Libs: -L${libdir} -lgit2
Libs.private: @LIBGIT2_PC_LIBS@
Requires.private: @LIBGIT2_PC_REQUIRES@
......
......@@ -7,15 +7,17 @@ if [ "$ARCH" = "i686" ]; then
curl -LsSO http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.9.2/threads-win32/sjlj/$f
fi
7z x $f > /dev/null
mv mingw32 /MinGW
export PATH=`pwd`/mingw32/bin:$PATH
else
f=x86_64-4.9.2-release-win32-seh-rt_v3-rev1.7z
if ! [ -e $f ]; then
curl -LsSO http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/4.9.2/threads-win32/seh/$f
fi
7z x $f > /dev/null
mv mingw64 /MinGW
export PATH=`pwd`/mingw64/bin:$PATH
fi
cd build
gcc --version
cmake --version
cmake -D ENABLE_TRACE=ON -D BUILD_CLAR=ON .. -G"$GENERATOR"
cmake --build . --config RelWithDebInfo
#!/bin/sh
set -x
if [ -n "$COVERITY" ];
then
./script/coverity.sh;
......@@ -18,7 +20,7 @@ java -jar poxyproxy.jar -d --port 8080 --credentials foo:bar &
mkdir _build
cd _build
# shellcheck disable=SC2086
cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS || exit $?
cmake .. -DBUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS || exit $?
make -j2 install || exit $?
# If this platform doesn't support test execution, bail out now
......@@ -41,18 +43,40 @@ ctest -V -R libgit2_clar || exit $?
killall git-daemon
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
echo 'PasswordAuthentication yes' | sudo tee -a /etc/sshd_config
fi
# Set up sshd
mkdir ~/sshd/
cat >~/sshd/sshd_config<<-EOF
Port 2222
ListenAddress 0.0.0.0
Protocol 2
HostKey ${HOME}/sshd/id_rsa
PidFile ${HOME}/sshd/pid
RSAAuthentication yes
PasswordAuthentication yes
PubkeyAuthentication yes
ChallengeResponseAuthentication no
# Required here as sshd will simply close connection otherwise
UsePAM no
EOF
ssh-keygen -t rsa -f ~/sshd/id_rsa -N "" -q
/usr/sbin/sshd -f ~/sshd/sshd_config
# Set up keys
ssh-keygen -t rsa -f ~/.ssh/id_rsa -N "" -q
cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys
ssh-keyscan -t rsa localhost >>~/.ssh/known_hosts
while read algorithm key comment; do
echo "[localhost]:2222 $algorithm $key" >>~/.ssh/known_hosts
done <~/sshd/id_rsa.pub
# Get the fingerprint for localhost and remove the colons so we can parse it as a hex number
export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -F localhost -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':')
# Get the fingerprint for localhost and remove the colons so we can parse it as
# a hex number. The Mac version is newer so it has a different output format.
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -E md5 -F '[localhost]:2222' -l | tail -n 1 | cut -d ' ' -f 3 | cut -d : -f2- | tr -d :)
else
export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -F '[localhost]:2222' -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':')
fi
export GITTEST_REMOTE_URL="ssh://localhost/$HOME/_temp/test.git"
export GITTEST_REMOTE_URL="ssh://localhost:2222/$HOME/_temp/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"
......@@ -76,6 +100,8 @@ if [ -e ./libgit2_clar ]; then
fi
kill $(cat "$HOME/sshd/pid")
export GITTEST_REMOTE_URL="https://github.com/libgit2/non-existent"
export GITTEST_REMOTE_USER="libgit2test"
ctest -V -R libgit2_clar-cred_callback
#!/bin/bash
set -e
# Environment check
[ -z "$COVERITY_TOKEN" ] && echo "Need to set a coverity token" && exit 1
# Only run this on our branches
echo "Pull request: $TRAVIS_PULL_REQUEST | Slug: $TRAVIS_REPO_SLUG"
if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_REPO_SLUG" != "libgit2/libgit2" ];
echo "Branch: $TRAVIS_BRANCH | Pull request: $TRAVIS_PULL_REQUEST | Slug: $TRAVIS_REPO_SLUG"
if [ "$TRAVIS_BRANCH" != "master" -o "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_REPO_SLUG" != "libgit2/libgit2" ];
then
echo "Only analyzing 'development' on the main repo."
echo "Only analyzing the 'master' brach of the main repository."
exit 0
fi
COV_VERSION=6.6.1
# Environment check
[ -z "$COVERITY_TOKEN" ] && echo "Need to set a coverity token" && exit 1
case $(uname -m) in
i?86) BITS=32 ;;
amd64|x86_64) BITS=64 ;;
esac
SCAN_TOOL=https://scan.coverity.com/download/linux-${BITS}
SCAN_TOOL=https://scan.coverity.com/download/cxx/linux${BITS}
TOOL_BASE=$(pwd)/_coverity-scan
# Install coverity tools
......
#!/bin/sh
set -x
if [ -z "$PRECISE" ]; then
echo "deb http://libgit2deps.edwardthomson.com trusty libgit2deps" | sudo tee -a /etc/apt/sources.list
sudo apt-key adv --keyserver pgp.mit.edu --recv 99131CD5
sudo apt-get update -qq
sudo apt-get install -y curl libcurl3 libcurl3-gnutls libcurl4-gnutls-dev
fi
sudo apt-get install -y cmake libssh2-1-dev openssh-client openssh-server valgrind
......@@ -3,6 +3,7 @@
set -x
brew update
brew install homebrew/dupes/zlib
brew install zlib
brew install curl
brew install openssl
brew install libssh2
......@@ -5,8 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "common.h"
#include "annotated_commit.h"
#include "refs.h"
#include "cache.h"
......
......@@ -7,6 +7,8 @@
#ifndef INCLUDE_annotated_commit_h__
#define INCLUDE_annotated_commit_h__
#include "common.h"
#include "oidarray.h"
#include "git2/oid.h"
......
......@@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "apply.h"
#include <assert.h>
#include "git2/patch.h"
......@@ -12,7 +14,6 @@
#include "array.h"
#include "patch.h"
#include "fileops.h"
#include "apply.h"
#include "delta.h"
#include "zstream.h"
......@@ -173,7 +174,7 @@ static int apply_hunk(
git_diff_line *line = git_array_get(patch->lines, linenum);
if (!line) {
error = apply_err("Preimage does not contain line %d", linenum);
error = apply_err("preimage does not contain line %"PRIuZ, linenum);
goto done;
}
......@@ -193,7 +194,7 @@ static int apply_hunk(
line_num = hunk->hunk.new_start ? hunk->hunk.new_start - 1 : 0;
if (!find_hunk_linenum(&line_num, image, &preimage, line_num)) {
error = apply_err("Hunk at line %d did not apply",
error = apply_err("hunk at line %d did not apply",
hunk->hunk.new_start);
goto done;
}
......
......@@ -7,6 +7,8 @@
#ifndef INCLUDE_apply_h__
#define INCLUDE_apply_h__
#include "common.h"
#include "git2/patch.h"
#include "buffer.h"
......
#include "common.h"
/*
* 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 "attr.h"
#include "repository.h"
#include "sysdir.h"
#include "config.h"
......@@ -7,8 +15,6 @@
#include "git2/oid.h"
#include <ctype.h>
GIT__USE_STRMAP
const char *git_attr__true = "[internal]__TRUE__";
const char *git_attr__false = "[internal]__FALSE__";
const char *git_attr__unset = "[internal]__UNSET__";
......@@ -209,7 +215,7 @@ int git_attr_foreach(
if (git_strmap_exists(seen, assign->name))
continue;
git_strmap_insert(seen, assign->name, assign, error);
git_strmap_insert(seen, assign->name, assign, &error);
if (error < 0)
goto cleanup;
......@@ -292,7 +298,7 @@ static int attr_setup(git_repository *repo, git_attr_session *attr_session)
int error = 0;
const char *workdir = git_repository_workdir(repo);
git_index *idx = NULL;
git_buf sys = GIT_BUF_INIT;
git_buf path = GIT_BUF_INIT;
if (attr_session && attr_session->init_setup)
return 0;
......@@ -304,40 +310,45 @@ static int attr_setup(git_repository *repo, git_attr_session *attr_session)
* definitions will be available for later file parsing
*/
error = system_attr_file(&sys, attr_session);
error = system_attr_file(&path, attr_session);
if (error == 0)
error = preload_attr_file(
repo, attr_session, GIT_ATTR_FILE__FROM_FILE, NULL, sys.ptr);
repo, attr_session, GIT_ATTR_FILE__FROM_FILE, NULL, path.ptr);
if (error != GIT_ENOTFOUND)
return error;
git_buf_free(&sys);
goto out;
if ((error = preload_attr_file(
repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
NULL, git_repository_attr_cache(repo)->cfg_attr_file)) < 0)
return error;
goto out;
if ((error = git_repository_item_path(&path,
repo, GIT_REPOSITORY_ITEM_INFO)) < 0)
goto out;
if ((error = preload_attr_file(
repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
git_repository_path(repo), GIT_ATTR_FILE_INREPO)) < 0)
return error;
path.ptr, GIT_ATTR_FILE_INREPO)) < 0)
goto out;
if (workdir != NULL &&
(error = preload_attr_file(
repo, attr_session, GIT_ATTR_FILE__FROM_FILE, workdir, GIT_ATTR_FILE)) < 0)
return error;
goto out;
if ((error = git_repository_index__weakptr(&idx, repo)) < 0 ||
(error = preload_attr_file(
repo, attr_session, GIT_ATTR_FILE__FROM_INDEX, NULL, GIT_ATTR_FILE)) < 0)
return error;
goto out;
if (attr_session)
attr_session->init_setup = 1;
out:
git_buf_free(&path);
return error;
}
......@@ -472,7 +483,7 @@ static int collect_attr_files(
git_vector *files)
{
int error = 0;
git_buf dir = GIT_BUF_INIT;
git_buf dir = GIT_BUF_INIT, attrfile = GIT_BUF_INIT;
const char *workdir = git_repository_workdir(repo);
attr_walk_up_info info = { NULL };
......@@ -494,9 +505,13 @@ static int collect_attr_files(
* - $GIT_PREFIX/etc/gitattributes
*/
error = git_repository_item_path(&attrfile, repo, GIT_REPOSITORY_ITEM_INFO);
if (error < 0)
goto cleanup;
error = push_attr_file(
repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE,
git_repository_path(repo), GIT_ATTR_FILE_INREPO);
attrfile.ptr, GIT_ATTR_FILE_INREPO);
if (error < 0)
goto cleanup;
......@@ -538,6 +553,7 @@ static int collect_attr_files(
cleanup:
if (error < 0)
release_attr_files(files);
git_buf_free(&attrfile);
git_buf_free(&dir);
return error;
......
......@@ -7,6 +7,8 @@
#ifndef INCLUDE_attr_h__
#define INCLUDE_attr_h__
#include "common.h"
#include "attr_file.h"
#include "attrcache.h"
......
#include "common.h"
/*
* 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 "attr_file.h"
#include "repository.h"
#include "filebuf.h"
#include "attr_file.h"
#include "attrcache.h"
#include "git2/blob.h"
#include "git2/tree.h"
......@@ -30,7 +37,7 @@ int git_attr_file__new(
GITERR_CHECK_ALLOC(attrs);
if (git_mutex_init(&attrs->lock) < 0) {
giterr_set(GITERR_OS, "Failed to initialize lock");
giterr_set(GITERR_OS, "failed to initialize lock");
git__free(attrs);
return -1;
}
......@@ -49,7 +56,7 @@ int git_attr_file__clear_rules(git_attr_file *file, bool need_lock)
git_attr_rule *rule;
if (need_lock && git_mutex_lock(&file->lock) < 0) {
giterr_set(GITERR_OS, "Failed to lock attribute file");
giterr_set(GITERR_OS, "failed to lock attribute file");
return -1;
}
......@@ -140,7 +147,7 @@ int git_attr_file__load(
break;
}
default:
giterr_set(GITERR_INVALID, "Unknown file source %d", source);
giterr_set(GITERR_INVALID, "unknown file source %d", source);
return -1;
}
......@@ -212,7 +219,7 @@ int git_attr_file__out_of_date(
}
default:
giterr_set(GITERR_INVALID, "Invalid file type %d", file->source);
giterr_set(GITERR_INVALID, "invalid file type %d", file->source);
return -1;
}
}
......@@ -238,7 +245,7 @@ int git_attr_file__parse_buffer(
context = attrs->entry->path;
if (git_mutex_lock(&attrs->lock) < 0) {
giterr_set(GITERR_OS, "Failed to lock attribute file");
giterr_set(GITERR_OS, "failed to lock attribute file");
return -1;
}
......@@ -395,9 +402,13 @@ bool git_attr_fnmatch__match(
if ((match->flags & GIT_ATTR_FNMATCH_DIRECTORY) && !path->is_dir) {
bool samename;
/* for attribute checks or root ignore checks, fail match */
/*
* for attribute checks or checks at the root of this match's
* containing_dir (or root of the repository if no containing_dir),
* do not match.
*/
if (!(match->flags & GIT_ATTR_FNMATCH_IGNORE) ||
path->basename == path->path)
path->basename == relpath)
return false;
flags |= FNM_LEADING_DIR;
......
......@@ -7,6 +7,8 @@
#ifndef INCLUDE_attr_file_h__
#define INCLUDE_attr_file_h__
#include "common.h"
#include "git2/oid.h"
#include "git2/attr.h"
#include "vector.h"
......@@ -15,7 +17,7 @@
#include "fileops.h"
#define GIT_ATTR_FILE ".gitattributes"
#define GIT_ATTR_FILE_INREPO "info/attributes"
#define GIT_ATTR_FILE_INREPO "attributes"
#define GIT_ATTR_FILE_SYSTEM "gitattributes"
#define GIT_ATTR_FILE_XDG "attributes"
......
#include "common.h"
/*
* 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 "attrcache.h"
#include "repository.h"
#include "attr_file.h"
#include "config.h"
#include "sysdir.h"
#include "ignore.h"
GIT__USE_STRMAP
GIT_INLINE(int) attr_cache_lock(git_attr_cache *cache)
{
GIT_UNUSED(cache); /* avoid warning if threading is off */
if (git_mutex_lock(&cache->lock) < 0) {
giterr_set(GITERR_OS, "Unable to get attr cache lock");
giterr_set(GITERR_OS, "unable to get attr cache lock");
return -1;
}
return 0;
......@@ -82,7 +88,7 @@ static int attr_cache_make_entry(
&entry, git_repository_workdir(repo), path, &cache->pool);
if (!error) {
git_strmap_insert(cache->files, entry->path, entry, error);
git_strmap_insert(cache->files, entry->path, entry, &error);
if (error > 0)
error = 0;
}
......@@ -105,8 +111,11 @@ static int attr_cache_upsert(git_attr_cache *cache, git_attr_file *file)
GIT_REFCOUNT_OWN(file, entry);
GIT_REFCOUNT_INC(file);
old = git__compare_and_swap(
&entry->file[file->source], entry->file[file->source], file);
/*
* Replace the existing value if another thread has
* created it in the meantime.
*/
old = git__swap(entry->file[file->source], file);
if (old) {
GIT_REFCOUNT_OWN(old, NULL);
......@@ -121,20 +130,22 @@ static int attr_cache_remove(git_attr_cache *cache, git_attr_file *file)
{
int error = 0;
git_attr_file_entry *entry;
git_attr_file *old = NULL;
if (!file)
return 0;
if ((error = attr_cache_lock(cache)) < 0)
return error;
if ((entry = attr_cache_lookup_entry(cache, file->entry->path)) != NULL)
file = git__compare_and_swap(&entry->file[file->source], file, NULL);
old = git__compare_and_swap(&entry->file[file->source], file, NULL);
attr_cache_unlock(cache);
if (file) {
GIT_REFCOUNT_OWN(file, NULL);
git_attr_file__free(file);
if (old) {
GIT_REFCOUNT_OWN(old, NULL);
git_attr_file__free(old);
}
return error;
......@@ -287,14 +298,16 @@ static int attr_cache__lookup_path(
const char *cfgval = entry->value;
/* expand leading ~/ as needed */
if (cfgval && cfgval[0] == '~' && cfgval[1] == '/' &&
!git_sysdir_find_global_file(&buf, &cfgval[2]))
if (cfgval && cfgval[0] == '~' && cfgval[1] == '/') {
if (! (error = git_sysdir_expand_global_file(&buf, &cfgval[2])))
*out = git_buf_detach(&buf);
else if (cfgval)
} else if (cfgval) {
*out = git__strdup(cfgval);
}
else if (!git_sysdir_find_xdg_file(&buf, fallback))
}
else if (!git_sysdir_find_xdg_file(&buf, fallback)) {
*out = git_buf_detach(&buf);
}
git_config_entry_free(entry);
git_buf_free(&buf);
......@@ -309,7 +322,7 @@ static void attr_cache__free(git_attr_cache *cache)
if (!cache)
return;
unlock = (git_mutex_lock(&cache->lock) == 0);
unlock = (attr_cache_lock(cache) == 0);
if (cache->files != NULL) {
git_attr_file_entry *entry;
......@@ -345,13 +358,13 @@ static void attr_cache__free(git_attr_cache *cache)
cache->cfg_excl_file = NULL;
if (unlock)
git_mutex_unlock(&cache->lock);
attr_cache_unlock(cache);
git_mutex_free(&cache->lock);
git__free(cache);
}
int git_attr_cache__do_init(git_repository *repo)
int git_attr_cache__init(git_repository *repo)
{
int ret = 0;
git_attr_cache *cache = git_repository_attr_cache(repo);
......@@ -365,7 +378,7 @@ int git_attr_cache__do_init(git_repository *repo)
/* set up lock */
if (git_mutex_init(&cache->lock) < 0) {
giterr_set(GITERR_OS, "Unable to initialize lock for attr cache");
giterr_set(GITERR_OS, "unable to initialize lock for attr cache");
git__free(cache);
return -1;
}
......@@ -429,11 +442,11 @@ int git_attr_cache__insert_macro(git_repository *repo, git_attr_rule *macro)
if (macro->assigns.length == 0)
return 0;
if (git_mutex_lock(&cache->lock) < 0) {
giterr_set(GITERR_OS, "Unable to get attr cache lock");
if (attr_cache_lock(cache) < 0) {
giterr_set(GITERR_OS, "unable to get attr cache lock");
error = -1;
} else {
git_strmap_insert(macros, macro->match.pattern, macro, error);
git_strmap_insert(macros, macro->match.pattern, macro, &error);
git_mutex_unlock(&cache->lock);
}
......
......@@ -7,6 +7,8 @@
#ifndef INCLUDE_attrcache_h__
#define INCLUDE_attrcache_h__
#include "common.h"
#include "attr_file.h"
#include "strmap.h"
......@@ -22,10 +24,7 @@ typedef struct {
git_pool pool;
} git_attr_cache;
extern int git_attr_cache__do_init(git_repository *repo);
#define git_attr_cache__init(REPO) \
(git_repository_attr_cache(REPO) ? 0 : git_attr_cache__do_init(REPO))
extern int git_attr_cache__init(git_repository *repo);
/* get file - loading and reload as needed */
extern int git_attr_cache__get(
......
......@@ -6,6 +6,7 @@
*/
#include "blame.h"
#include "git2/commit.h"
#include "git2/revparse.h"
#include "git2/revwalk.h"
......
#ifndef INCLUDE_blame_h__
#define INCLUDE_blame_h__
#include "git2/blame.h"
#include "common.h"
#include "git2/blame.h"
#include "vector.h"
#include "diff.h"
#include "array.h"
......
......@@ -6,6 +6,7 @@
*/
#include "blame_git.h"
#include "commit.h"
#include "blob.h"
#include "xdiff/xinclude.h"
......@@ -478,14 +479,15 @@ cleanup:
* The blobs of origin and porigin exactly match, so everything origin is
* suspected for can be blamed on the parent.
*/
static void pass_whole_blame(git_blame *blame,
static int pass_whole_blame(git_blame *blame,
git_blame__origin *origin, git_blame__origin *porigin)
{
git_blame__entry *e;
if (!porigin->blob)
if (!porigin->blob &&
git_object_lookup((git_object**)&porigin->blob, blame->repository,
git_blob_id(origin->blob), GIT_OBJ_BLOB);
git_blob_id(origin->blob), GIT_OBJ_BLOB) < 0)
return -1;
for (e=blame->ent; e; e=e->next) {
if (!same_suspect(e->suspect, origin))
continue;
......@@ -493,6 +495,8 @@ static void pass_whole_blame(git_blame *blame,
origin_decref(e->suspect);
e->suspect = porigin;
}
return 0;
}
static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
......@@ -514,11 +518,12 @@ static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
if (!num_parents) {
git_oid_cpy(&blame->options.oldest_commit, git_commit_id(commit));
goto finish;
}
else if (num_parents < (int)ARRAY_SIZE(sg_buf))
} else if (num_parents < (int)ARRAY_SIZE(sg_buf))
memset(sg_buf, 0, sizeof(sg_buf));
else
else {
sg_origin = git__calloc(num_parents, sizeof(*sg_origin));
GITERR_CHECK_ALLOC(sg_origin);
}
for (i=0; i<num_parents; i++) {
git_commit *p;
......@@ -543,7 +548,7 @@ static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
}
if (porigin->blob && origin->blob &&
!git_oid_cmp(git_blob_id(porigin->blob), git_blob_id(origin->blob))) {
pass_whole_blame(blame, origin, porigin);
error = pass_whole_blame(blame, origin, porigin);
origin_decref(porigin);
goto finish;
}
......
......@@ -7,6 +7,8 @@
#ifndef INCLUDE_blame_git__
#define INCLUDE_blame_git__
#include "common.h"
#include "blame.h"
int git_blame__get_origin(
......
......@@ -5,14 +5,14 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "blob.h"
#include "git2/common.h"
#include "git2/object.h"
#include "git2/repository.h"
#include "git2/odb_backend.h"
#include "common.h"
#include "filebuf.h"
#include "blob.h"
#include "filter.h"
#include "buf_text.h"
......@@ -96,7 +96,7 @@ static int write_file_stream(
p_close(fd);
if (written != file_size || read_len < 0) {
giterr_set(GITERR_OS, "Failed to read file into stream");
giterr_set(GITERR_OS, "failed to read file into stream");
error = -1;
}
......@@ -142,7 +142,7 @@ static int write_symlink(
read_len = p_readlink(path, link_data, link_size);
if (read_len != (ssize_t)link_size) {
giterr_set(GITERR_OS, "Failed to create blob. Can't read symlink '%s'", path);
giterr_set(GITERR_OS, "failed to create blob: cannot read symlink '%s'", path);
git__free(link_data);
return -1;
}
......@@ -186,7 +186,7 @@ int git_blob__create_from_paths(
goto done;
if (S_ISDIR(st.st_mode)) {
giterr_set(GITERR_ODB, "cannot create blob from '%s'; it is a directory", content_path);
giterr_set(GITERR_ODB, "cannot create blob from '%s': it is a directory", content_path);
error = GIT_EDIRECTORY;
goto done;
}
......@@ -326,8 +326,8 @@ int git_blob_create_fromstream(git_writestream **out, git_repository *repo, cons
stream->parent.close = blob_writestream_close;
stream->parent.free = blob_writestream_free;
if ((error = git_buf_joinpath(&path,
git_repository_path(repo), GIT_OBJECTS_DIR "streamed")) < 0)
if ((error = git_repository_item_path(&path, repo, GIT_REPOSITORY_ITEM_OBJECTS)) < 0
|| (error = git_buf_joinpath(&path, path.ptr, "streamed")) < 0)
goto cleanup;
if ((error = git_filebuf_open_withsize(&stream->fbuf, git_buf_cstr(&path), GIT_FILEBUF_TEMPORARY,
......
......@@ -7,6 +7,8 @@
#ifndef INCLUDE_blob_h__
#define INCLUDE_blob_h__
#include "common.h"
#include "git2/blob.h"
#include "repository.h"
#include "odb.h"
......
......@@ -5,7 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "common.h"
#include "branch.h"
#include "commit.h"
#include "tag.h"
#include "config.h"
......@@ -13,6 +14,7 @@
#include "refs.h"
#include "remote.h"
#include "annotated_commit.h"
#include "worktree.h"
#include "git2/branch.h"
......@@ -33,7 +35,7 @@ static int retrieve_branch_reference(
/* OOM */;
else if ((error = git_reference_lookup(&branch, repo, ref_name.ptr)) < 0)
giterr_set(
GITERR_REFERENCE, "Cannot locate %s branch '%s'",
GITERR_REFERENCE, "cannot locate %s branch '%s'",
is_remote ? "remote-tracking" : "local", branch_name);
*branch_reference_out = branch; /* will be NULL on error */
......@@ -46,7 +48,7 @@ static int not_a_local_branch(const char *reference_name)
{
giterr_set(
GITERR_INVALID,
"Reference '%s' is not a local branch.", reference_name);
"reference '%s' is not a local branch.", reference_name);
return -1;
}
......@@ -58,16 +60,17 @@ static int create_branch(
const char *from,
int force)
{
int is_head = 0;
int is_unmovable_head = 0;
git_reference *branch = NULL;
git_buf canonical_branch_name = GIT_BUF_INIT,
log_message = GIT_BUF_INIT;
int error = -1;
int bare = git_repository_is_bare(repository);
assert(branch_name && commit && ref_out);
assert(git_object_owner((const git_object *)commit) == repository);
if (force && git_branch_lookup(&branch, repository, branch_name, GIT_BRANCH_LOCAL) == 0) {
if (force && !bare && git_branch_lookup(&branch, repository, branch_name, GIT_BRANCH_LOCAL) == 0) {
error = git_branch_is_head(branch);
git_reference_free(branch);
branch = NULL;
......@@ -75,11 +78,11 @@ static int create_branch(
if (error < 0)
goto cleanup;
is_head = error;
is_unmovable_head = error;
}
if (is_head && force) {
giterr_set(GITERR_REFERENCE, "Cannot force update branch '%s' as it is "
if (is_unmovable_head && force) {
giterr_set(GITERR_REFERENCE, "cannot force update branch '%s' as it is "
"the current HEAD of the repository.", branch_name);
error = -1;
goto cleanup;
......@@ -125,6 +128,31 @@ int git_branch_create_from_annotated(
repository, branch_name, commit->commit, commit->description, force);
}
static int branch_equals(git_repository *repo, const char *path, void *payload)
{
git_reference *branch = (git_reference *) payload;
git_reference *head = NULL;
int equal = 0;
if (git_reference__read_head(&head, repo, path) < 0 ||
git_reference_type(head) != GIT_REF_SYMBOLIC)
goto done;
equal = !git__strcmp(head->target.symbolic, branch->name);
done:
git_reference_free(head);
return equal;
}
int git_branch_is_checked_out(const git_reference *branch)
{
assert(branch && git_reference_is_branch(branch));
return git_repository_foreach_head(git_reference_owner(branch),
branch_equals, (void *) branch) == 1;
}
int git_branch_delete(git_reference *branch)
{
int is_head;
......@@ -134,7 +162,7 @@ int git_branch_delete(git_reference *branch)
assert(branch);
if (!git_reference_is_branch(branch) && !git_reference_is_remote(branch)) {
giterr_set(GITERR_INVALID, "Reference '%s' is not a valid branch.",
giterr_set(GITERR_INVALID, "reference '%s' is not a valid branch.",
git_reference_name(branch));
return GIT_ENOTFOUND;
}
......@@ -143,11 +171,17 @@ int git_branch_delete(git_reference *branch)
return is_head;
if (is_head) {
giterr_set(GITERR_REFERENCE, "Cannot delete branch '%s' as it is "
giterr_set(GITERR_REFERENCE, "cannot delete branch '%s' as it is "
"the current HEAD of the repository.", git_reference_name(branch));
return -1;
}
if (git_reference_is_branch(branch) && git_branch_is_checked_out(branch)) {
giterr_set(GITERR_REFERENCE, "Cannot delete branch '%s' as it is "
"the current HEAD of a linked repository.", git_reference_name(branch));
return -1;
}
if (git_buf_join(&config_section, '.', "branch",
git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR)) < 0)
goto on_error;
......@@ -305,7 +339,7 @@ int git_branch_name(
branch_name += strlen(GIT_REFS_REMOTES_DIR);
} else {
giterr_set(GITERR_INVALID,
"Reference '%s' is neither a local nor a remote branch.", ref->name);
"reference '%s' is neither a local nor a remote branch.", ref->name);
return -1;
}
*out = branch_name;
......@@ -435,7 +469,7 @@ int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refna
/* Verify that this is a remote branch */
if (!git_reference__is_remote(refname)) {
giterr_set(GITERR_INVALID, "Reference '%s' is not a remote branch.",
giterr_set(GITERR_INVALID, "reference '%s' is not a remote branch.",
refname);
error = GIT_ERROR;
goto cleanup;
......@@ -462,7 +496,7 @@ int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refna
git_remote_free(remote);
giterr_set(GITERR_REFERENCE,
"Reference '%s' is ambiguous", refname);
"reference '%s' is ambiguous", refname);
error = GIT_EAMBIGUOUS;
goto cleanup;
}
......@@ -476,7 +510,7 @@ int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refna
error = git_buf_puts(buf, remote_name);
} else {
giterr_set(GITERR_REFERENCE,
"Could not determine remote for '%s'", refname);
"could not determine remote for '%s'", refname);
error = GIT_ENOTFOUND;
}
......@@ -565,7 +599,7 @@ int git_branch_set_upstream(git_reference *branch, const char *upstream_name)
local = 0;
else {
giterr_set(GITERR_REFERENCE,
"Cannot set upstream for branch '%s'", shortname);
"cannot set upstream for branch '%s'", shortname);
return GIT_ENOTFOUND;
}
......
......@@ -7,6 +7,8 @@
#ifndef INCLUDE_branch_h__
#define INCLUDE_branch_h__
#include "common.h"
#include "buffer.h"
int git_branch_upstream__name(
......
......@@ -7,6 +7,8 @@
#ifndef INCLUDE_buf_text_h__
#define INCLUDE_buf_text_h__
#include "common.h"
#include "buffer.h"
typedef enum {
......
......@@ -18,18 +18,19 @@ char git_buf__initbuf[1];
char git_buf__oom[1];
#define ENSURE_SIZE(b, d) \
if ((d) > buf->asize && git_buf_grow(b, (d)) < 0)\
if ((d) > (b)->asize && git_buf_grow((b), (d)) < 0)\
return -1;
void git_buf_init(git_buf *buf, size_t initial_size)
int git_buf_init(git_buf *buf, size_t initial_size)
{
buf->asize = 0;
buf->size = 0;
buf->ptr = git_buf__initbuf;
if (initial_size)
git_buf_grow(buf, initial_size);
ENSURE_SIZE(buf, initial_size);
return 0;
}
int git_buf_try_grow(
......@@ -577,7 +578,7 @@ char *git_buf_detach(git_buf *buf)
return data;
}
void git_buf_attach(git_buf *buf, char *ptr, size_t asize)
int git_buf_attach(git_buf *buf, char *ptr, size_t asize)
{
git_buf_free(buf);
......@@ -588,9 +589,10 @@ void git_buf_attach(git_buf *buf, char *ptr, size_t asize)
buf->asize = (asize < buf->size) ? buf->size + 1 : asize;
else /* pass 0 to fall back on strlen + 1 */
buf->asize = buf->size + 1;
} else {
git_buf_grow(buf, asize);
}
ENSURE_SIZE(buf, asize);
return 0;
}
void git_buf_attach_notowned(git_buf *buf, const char *ptr, size_t size)
......@@ -724,9 +726,7 @@ int git_buf_join(
GITERR_CHECK_ALLOC_ADD(&alloc_len, strlen_a, strlen_b);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, need_sep);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 1);
if (git_buf_grow(buf, alloc_len) < 0)
return -1;
assert(buf->ptr);
ENSURE_SIZE(buf, alloc_len);
/* fix up internal pointers */
if (offset_a >= 0)
......@@ -780,8 +780,7 @@ int git_buf_join3(
GITERR_CHECK_ALLOC_ADD(&len_total, len_total, sep_b);
GITERR_CHECK_ALLOC_ADD(&len_total, len_total, len_c);
GITERR_CHECK_ALLOC_ADD(&len_total, len_total, 1);
if (git_buf_grow(buf, len_total) < 0)
return -1;
ENSURE_SIZE(buf, len_total);
tgt = buf->ptr;
......@@ -962,14 +961,14 @@ int git_buf_unquote(git_buf *buf)
case '0': case '1': case '2': case '3':
if (j == buf->size-3) {
giterr_set(GITERR_INVALID,
"Truncated quoted character \\%c", ch);
"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') {
giterr_set(GITERR_INVALID,
"Truncated quoted character \\%c%c%c",
"truncated quoted character \\%c%c%c",
buf->ptr[j], buf->ptr[j+1], buf->ptr[j+2]);
return -1;
}
......@@ -981,7 +980,7 @@ int git_buf_unquote(git_buf *buf)
break;
default:
giterr_set(GITERR_INVALID, "Invalid quoted character \\%c", ch);
giterr_set(GITERR_INVALID, "invalid quoted character \\%c", ch);
return -1;
}
}
......@@ -995,6 +994,6 @@ int git_buf_unquote(git_buf *buf)
return 0;
invalid:
giterr_set(GITERR_INVALID, "Invalid quoted line");
giterr_set(GITERR_INVALID, "invalid quoted line");
return -1;
}
......@@ -34,7 +34,7 @@ GIT_INLINE(bool) git_buf_is_allocated(const git_buf *buf)
* For the cases where GIT_BUF_INIT cannot be used to do static
* initialization.
*/
extern void git_buf_init(git_buf *buf, size_t initial_size);
extern int git_buf_init(git_buf *buf, size_t initial_size);
/**
* Resize the buffer allocation to make more space.
......@@ -66,13 +66,14 @@ extern int git_buf_try_grow(
* 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.
* git_buf__initbuf. If a buffer with a non-NULL ptr is passed in, this method
* assures that the buffer is '\0'-terminated.
*/
extern void 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 void git_buf_attach(git_buf *buf, char *ptr, size_t asize);
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_free` will not free the given buf.
......
......@@ -5,18 +5,16 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "common.h"
#include "cache.h"
#include "repository.h"
#include "commit.h"
#include "thread-utils.h"
#include "util.h"
#include "cache.h"
#include "odb.h"
#include "object.h"
#include "git2/oid.h"
GIT__USE_OIDMAP
bool git_cache__enabled = true;
ssize_t git_cache__max_storage = (256 * 1024 * 1024);
git_atomic_ssize git_cache__current_storage = {0};
......@@ -47,13 +45,13 @@ void git_cache_dump_stats(git_cache *cache)
{
git_cached_obj *object;
if (kh_size(cache->map) == 0)
if (git_cache_size(cache) == 0)
return;
printf("Cache %p: %d items cached, %"PRIdZ" bytes\n",
cache, kh_size(cache->map), cache->used_memory);
printf("Cache %p: %"PRIuZ" items cached, %"PRIdZ" bytes\n",
cache, git_cache_size(cache), cache->used_memory);
kh_foreach_value(cache->map, object, {
git_oidmap_foreach_value(cache->map, object, {
char oid_str[9];
printf(" %s%c %s (%"PRIuZ")\n",
git_object_type2string(object->type),
......@@ -70,7 +68,7 @@ int git_cache_init(git_cache *cache)
cache->map = git_oidmap_alloc();
GITERR_CHECK_ALLOC(cache->map);
if (git_rwlock_init(&cache->lock)) {
giterr_set(GITERR_OS, "Failed to initialize cache rwlock");
giterr_set(GITERR_OS, "failed to initialize cache rwlock");
return -1;
}
return 0;
......@@ -81,14 +79,14 @@ static void clear_cache(git_cache *cache)
{
git_cached_obj *evict = NULL;
if (kh_size(cache->map) == 0)
if (git_cache_size(cache) == 0)
return;
kh_foreach_value(cache->map, evict, {
git_oidmap_foreach_value(cache->map, evict, {
git_cached_obj_decref(evict);
});
kh_clear(oid, cache->map);
git_oidmap_clear(cache->map);
git_atomic_ssize_add(&git_cache__current_storage, -cache->used_memory);
cache->used_memory = 0;
}
......@@ -119,22 +117,22 @@ static void cache_evict_entries(git_cache *cache)
ssize_t evicted_memory = 0;
/* do not infinite loop if there's not enough entries to evict */
if (evict_count > kh_size(cache->map)) {
if (evict_count > git_cache_size(cache)) {
clear_cache(cache);
return;
}
while (evict_count > 0) {
khiter_t pos = seed++ % kh_end(cache->map);
khiter_t pos = seed++ % git_oidmap_end(cache->map);
if (kh_exist(cache->map, pos)) {
git_cached_obj *evict = kh_val(cache->map, pos);
if (git_oidmap_has_data(cache->map, pos)) {
git_cached_obj *evict = git_oidmap_value_at(cache->map, pos);
evict_count--;
evicted_memory += evict->size;
git_cached_obj_decref(evict);
kh_del(oid, cache->map, pos);
git_oidmap_delete_at(cache->map, pos);
}
}
......@@ -156,9 +154,9 @@ static void *cache_get(git_cache *cache, const git_oid *oid, unsigned int flags)
if (!git_cache__enabled || git_rwlock_rdlock(&cache->lock) < 0)
return NULL;
pos = kh_get(oid, cache->map, oid);
if (pos != kh_end(cache->map)) {
entry = kh_val(cache->map, pos);
pos = git_oidmap_lookup_index(cache->map, oid);
if (git_oidmap_valid_index(cache->map, pos)) {
entry = git_oidmap_value_at(cache->map, pos);
if (flags && entry->flags != flags) {
entry = NULL;
......@@ -193,16 +191,14 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
if (git_cache__current_storage.val > git_cache__max_storage)
cache_evict_entries(cache);
pos = kh_get(oid, cache->map, &entry->oid);
pos = git_oidmap_lookup_index(cache->map, &entry->oid);
/* not found */
if (pos == kh_end(cache->map)) {
if (!git_oidmap_valid_index(cache->map, pos)) {
int rval;
pos = kh_put(oid, cache->map, &entry->oid, &rval);
git_oidmap_insert(cache->map, &entry->oid, entry, &rval);
if (rval >= 0) {
kh_key(cache->map, pos) = &entry->oid;
kh_val(cache->map, pos) = entry;
git_cached_obj_incref(entry);
cache->used_memory += entry->size;
git_atomic_ssize_add(&git_cache__current_storage, (ssize_t)entry->size);
......@@ -210,7 +206,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
}
/* found */
else {
git_cached_obj *stored_entry = kh_val(cache->map, pos);
git_cached_obj *stored_entry = git_oidmap_value_at(cache->map, pos);
if (stored_entry->flags == entry->flags) {
git_cached_obj_decref(entry);
......@@ -221,8 +217,8 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
git_cached_obj_decref(stored_entry);
git_cached_obj_incref(entry);
kh_key(cache->map, pos) = &entry->oid;
kh_val(cache->map, pos) = entry;
git_oidmap_set_key_at(cache->map, pos, &entry->oid);
git_oidmap_set_value_at(cache->map, pos, entry);
} else {
/* NO OP */
}
......
......@@ -7,6 +7,8 @@
#ifndef INCLUDE_cache_h__
#define INCLUDE_cache_h__
#include "common.h"
#include "git2/common.h"
#include "git2/oid.h"
#include "git2/odb.h"
......@@ -53,7 +55,7 @@ void *git_cache_get_any(git_cache *cache, const git_oid *oid);
GIT_INLINE(size_t) git_cache_size(git_cache *cache)
{
return (size_t)kh_size(cache->map);
return (size_t)git_oidmap_size(cache->map);
}
GIT_INLINE(void) git_cached_obj_incref(void *_obj)
......
......@@ -7,6 +7,8 @@
#ifndef INCLUDE_checkout_h__
#define INCLUDE_checkout_h__
#include "common.h"
#include "git2/checkout.h"
#include "iterator.h"
......
......@@ -6,6 +6,7 @@
*/
#include "common.h"
#include "repository.h"
#include "filebuf.h"
#include "merge.h"
......@@ -28,7 +29,7 @@ static int write_cherrypick_head(
git_buf file_path = GIT_BUF_INIT;
int error = 0;
if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_CHERRYPICK_HEAD_FILE)) >= 0 &&
if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_CHERRYPICK_HEAD_FILE)) >= 0 &&
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_CHERRYPICK_FILE_MODE)) >= 0 &&
(error = git_filebuf_printf(&file, "%s\n", commit_oidstr)) >= 0)
error = git_filebuf_commit(&file);
......@@ -49,7 +50,7 @@ static int write_merge_msg(
git_buf file_path = GIT_BUF_INIT;
int error = 0;
if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 ||
if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_CHERRYPICK_FILE_MODE)) < 0 ||
(error = git_filebuf_printf(&file, "%s", commit_msg)) < 0)
goto cleanup;
......@@ -130,13 +131,13 @@ int git_cherrypick_commit(
if (git_commit_parentcount(cherrypick_commit) > 1) {
if (!mainline)
return cherrypick_seterr(cherrypick_commit,
"Mainline branch is not specified but %s is a merge commit");
"mainline branch is not specified but %s is a merge commit");
parent = mainline;
} else {
if (mainline)
return cherrypick_seterr(cherrypick_commit,
"Mainline branch specified but %s is not a merge commit");
"mainline branch specified but %s is not a merge commit");
parent = git_commit_parentcount(cherrypick_commit);
}
......
......@@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "clone.h"
#include <assert.h>
#include "git2/clone.h"
......@@ -16,7 +18,6 @@
#include "git2/commit.h"
#include "git2/tree.h"
#include "common.h"
#include "remote.h"
#include "fileops.h"
#include "refs.h"
......@@ -513,9 +514,8 @@ static int clone_local_into(git_repository *repo, git_remote *remote, const git_
return error;
}
git_buf_joinpath(&src_odb, git_repository_path(src), GIT_OBJECTS_DIR);
git_buf_joinpath(&dst_odb, git_repository_path(repo), GIT_OBJECTS_DIR);
if (git_buf_oom(&src_odb) || git_buf_oom(&dst_odb)) {
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;
}
......
......@@ -7,6 +7,10 @@
#ifndef INCLUDE_clone_h__
#define INCLUDE_clone_h__
#include "common.h"
#include "git2/clone.h"
extern int git_clone__should_clone_local(const char *url, git_clone_local_t local);
#endif
......@@ -5,13 +5,14 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "commit.h"
#include "git2/common.h"
#include "git2/object.h"
#include "git2/repository.h"
#include "git2/signature.h"
#include "git2/sys/commit.h"
#include "common.h"
#include "odb.h"
#include "commit.h"
#include "signature.h"
......@@ -159,6 +160,9 @@ static int git_commit__create_internal(
if (git_repository_odb__weakptr(&odb, repo) < 0)
goto cleanup;
if (git_odb__freshen(odb, tree) < 0)
goto cleanup;
if (git_odb_write(id, odb, buf.ptr, buf.size, GIT_OBJ_COMMIT) < 0)
goto cleanup;
......@@ -459,15 +463,16 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
buffer = buffer_start + header_len + 1;
/* extract commit message */
if (buffer <= buffer_end) {
if (buffer <= buffer_end)
commit->raw_message = git__strndup(buffer, buffer_end - buffer);
else
commit->raw_message = git__strdup("");
GITERR_CHECK_ALLOC(commit->raw_message);
}
return 0;
bad_buffer:
giterr_set(GITERR_OBJECT, "Failed to parse bad commit object");
giterr_set(GITERR_OBJECT, "failed to parse bad commit object");
return -1;
}
......@@ -597,7 +602,7 @@ int git_commit_parent(
parent_id = git_commit_parent_id(commit, n);
if (parent_id == NULL) {
giterr_set(GITERR_INVALID, "Parent %u does not exist", n);
giterr_set(GITERR_INVALID, "parent %u does not exist", n);
return GIT_ENOTFOUND;
}
......@@ -641,7 +646,7 @@ int git_commit_header_field(git_buf *out, const git_commit *commit, const char *
{
const char *eol, *buf = commit->raw_header;
git_buf_sanitize(out);
git_buf_clear(out);
while ((eol = strchr(buf, '\n'))) {
/* We can skip continuations here */
......@@ -705,8 +710,8 @@ int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_r
const char *h, *eol;
int error;
git_buf_sanitize(signature);
git_buf_sanitize(signed_data);
git_buf_clear(signature);
git_buf_clear(signed_data);
if (!field)
field = "gpgsig";
......@@ -765,8 +770,9 @@ int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_r
if (git_buf_oom(signature))
goto oom;
error = git_buf_puts(signed_data, eol+1);
git_odb_object_free(obj);
return git_buf_puts(signed_data, eol+1);
return error;
}
giterr_set(GITERR_OBJECT, "this commit is not signed");
......
......@@ -7,6 +7,8 @@
#ifndef INCLUDE_commit_h__
#define INCLUDE_commit_h__
#include "common.h"
#include "git2/commit.h"
#include "tree.h"
#include "repository.h"
......
......@@ -6,17 +6,22 @@
*/
#include "commit_list.h"
#include "common.h"
#include "revwalk.h"
#include "pool.h"
#include "odb.h"
int git_commit_list_time_cmp(const void *a, const void *b)
{
const git_commit_list_node *commit_a = a;
const git_commit_list_node *commit_b = b;
int64_t time_a = ((git_commit_list_node *) a)->time;
int64_t time_b = ((git_commit_list_node *) b)->time;
if (time_a < time_b)
return 1;
if (time_a > time_b)
return -1;
return (commit_a->time < commit_b->time);
return 0;
}
git_commit_list *git_commit_list_insert(git_commit_list_node *item, git_commit_list **list_p)
......@@ -56,7 +61,7 @@ static int commit_error(git_commit_list_node *commit, const char *msg)
git_oid_fmt(commit_oid, &commit->oid);
commit_oid[GIT_OID_HEXSZ] = '\0';
giterr_set(GITERR_ODB, "Failed to parse commit %s - %s", commit_oid, msg);
giterr_set(GITERR_ODB, "failed to parse commit %s - %s", commit_oid, msg);
return -1;
}
......@@ -186,7 +191,7 @@ int git_commit_list_parse(git_revwalk *walk, git_commit_list_node *commit)
return error;
if (obj->cached.type != GIT_OBJ_COMMIT) {
giterr_set(GITERR_INVALID, "Object is no commit object");
giterr_set(GITERR_INVALID, "object is no commit object");
error = -1;
} else
error = commit_quick_parse(
......
......@@ -7,6 +7,8 @@
#ifndef INCLUDE_commit_list_h__
#define INCLUDE_commit_list_h__
#include "common.h"
#include "git2/oid.h"
#define PARENT1 (1 << 0)
......@@ -28,6 +30,7 @@ typedef struct git_commit_list_node {
uninteresting:1,
topo_delay:1,
parsed:1,
added:1,
flags : FLAG_BITS;
unsigned short in_degree;
......
......@@ -7,6 +7,10 @@
#ifndef INCLUDE_common_h__
#define INCLUDE_common_h__
#ifndef LIBGIT2_NO_FEATURES_H
# include "git2/sys/features.h"
#endif
#include "git2/common.h"
#include "cc-compat.h"
......@@ -47,10 +51,6 @@
# ifdef GIT_THREADS
# include "win32/thread.h"
# endif
# if defined(GIT_MSVC_CRTDBG)
# include "win32/w32_stack.h"
# include "win32/w32_crtdbg_stacktrace.h"
# endif
#else
......@@ -103,7 +103,8 @@
/**
* Set the error message for this thread, formatting as needed.
*/
void giterr_set(int error_class, const char *string, ...);
void giterr_set(int error_class, const char *string, ...) GIT_FORMAT_PRINTF(2, 3);
/**
* Set the error message for a regex failure, using the internal regex
......@@ -187,7 +188,7 @@ GIT_INLINE(int) giterr__check_version(const void *structure, unsigned int expect
if (actual > 0 && actual <= expected_max)
return 0;
giterr_set(GITERR_INVALID, "Invalid version %d on %s", actual, name);
giterr_set(GITERR_INVALID, "invalid version %d on %s", actual, name);
return -1;
}
#define GITERR_CHECK_VERSION(S,V,N) if (giterr__check_version(S,V,N) < 0) return -1
......
......@@ -5,9 +5,9 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "common.h"
#include "sysdir.h"
#include "config.h"
#include "sysdir.h"
#include "git2/config.h"
#include "git2/sys/config.h"
#include "vector.h"
......@@ -109,7 +109,7 @@ int git_config_add_file_ondisk(
res = p_stat(path, &st);
if (res < 0 && errno != ENOENT) {
giterr_set(GITERR_CONFIG, "Error stat'ing config file '%s'", path);
giterr_set(GITERR_CONFIG, "failed to stat '%s'", path);
return -1;
}
......@@ -203,7 +203,7 @@ static int find_internal_file_by_level(
if (pos == -1) {
giterr_set(GITERR_CONFIG,
"No config file exists for the given level '%i'", (int)level);
"no config file exists for the given level '%i'", (int)level);
return GIT_ENOTFOUND;
}
......@@ -218,7 +218,7 @@ static int duplicate_level(void **old_raw, void *new_raw)
GIT_UNUSED(new_raw);
giterr_set(GITERR_CONFIG, "A file with the same level (%i) has already been added to the config", (int)(*old)->level);
giterr_set(GITERR_CONFIG, "a file with the same level (%i) has already been added to the config", (int)(*old)->level);
return GIT_EEXISTS;
}
......@@ -478,7 +478,7 @@ int git_config_iterator_glob_new(git_config_iterator **out, const git_config *cf
iter = git__calloc(1, sizeof(all_iter));
GITERR_CHECK_ALLOC(iter);
if ((result = regcomp(&iter->regex, regexp, REG_EXTENDED)) != 0) {
if ((result = p_regcomp(&iter->regex, regexp, REG_EXTENDED)) != 0) {
giterr_set_regex(&iter->regex, result);
git__free(iter);
return -1;
......@@ -512,7 +512,7 @@ int git_config_backend_foreach_match(
int error = 0;
if (regexp != NULL) {
if ((error = regcomp(&regex, regexp, REG_EXTENDED)) != 0) {
if ((error = p_regcomp(&regex, regexp, REG_EXTENDED)) != 0) {
giterr_set_regex(&regex, error);
regfree(&regex);
return -1;
......@@ -576,22 +576,50 @@ int git_config_foreach_match(
* Setters
**************/
static int config_error_nofiles(const char *name)
typedef enum {
BACKEND_USE_SET,
BACKEND_USE_DELETE
} backend_use;
static const char *uses[] = {
"set",
"delete"
};
static int get_backend_for_use(git_config_backend **out,
git_config *cfg, const char *name, backend_use use)
{
size_t i;
file_internal *f;
*out = NULL;
if (git_vector_length(&cfg->files) == 0) {
giterr_set(GITERR_CONFIG,
"Cannot set value for '%s' when no config files exist", name);
"cannot %s value for '%s' when no config files exist",
uses[use], name);
return GIT_ENOTFOUND;
}
git_vector_foreach(&cfg->files, i, f) {
if (!f->file->readonly) {
*out = f->file;
return 0;
}
}
giterr_set(GITERR_CONFIG,
"cannot %s value for '%s' when all config files are readonly",
uses[use], name);
return GIT_ENOTFOUND;
}
int git_config_delete_entry(git_config *cfg, const char *name)
{
git_config_backend *file;
file_internal *internal;
internal = git_vector_get(&cfg->files, 0);
if (!internal || !internal->file)
return config_error_nofiles(name);
file = internal->file;
if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
return GIT_ENOTFOUND;
return file->del(file, name);
}
......@@ -617,17 +645,14 @@ int git_config_set_string(git_config *cfg, const char *name, const char *value)
{
int error;
git_config_backend *file;
file_internal *internal;
if (!value) {
giterr_set(GITERR_CONFIG, "The value to set cannot be NULL");
giterr_set(GITERR_CONFIG, "the value to set cannot be NULL");
return -1;
}
internal = git_vector_get(&cfg->files, 0);
if (!internal || !internal->file)
return config_error_nofiles(name);
file = internal->file;
if (get_backend_for_use(&file, cfg, name, BACKEND_USE_SET) < 0)
return GIT_ENOTFOUND;
error = file->set(file, name, value);
......@@ -674,7 +699,7 @@ int git_config__update_entry(
static int config_error_notfound(const char *name)
{
giterr_set(GITERR_CONFIG, "Config value '%s' was not found", name);
giterr_set(GITERR_CONFIG, "config value '%s' was not found", name);
return GIT_ENOTFOUND;
}
......@@ -1003,7 +1028,7 @@ int git_config_multivar_iterator_new(git_config_iterator **out, const git_config
goto on_error;
if (regexp != NULL) {
error = regcomp(&iter->regex, regexp, REG_EXTENDED);
error = p_regcomp(&iter->regex, regexp, REG_EXTENDED);
if (error != 0) {
giterr_set_regex(&iter->regex, error);
error = -1;
......@@ -1032,12 +1057,9 @@ on_error:
int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value)
{
git_config_backend *file;
file_internal *internal;
internal = git_vector_get(&cfg->files, 0);
if (!internal || !internal->file)
return config_error_nofiles(name);
file = internal->file;
if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
return GIT_ENOTFOUND;
return file->set_multivar(file, name, regexp, value);
}
......@@ -1045,12 +1067,9 @@ int git_config_set_multivar(git_config *cfg, const char *name, const char *regex
int git_config_delete_multivar(git_config *cfg, const char *name, const char *regexp)
{
git_config_backend *file;
file_internal *internal;
internal = git_vector_get(&cfg->files, 0);
if (!internal || !internal->file)
return config_error_nofiles(name);
file = internal->file;
if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
return GIT_ENOTFOUND;
return file->del_multivar(file, name, regexp);
}
......@@ -1236,7 +1255,7 @@ int git_config_lookup_map_value(
}
fail_parse:
giterr_set(GITERR_CONFIG, "Failed to map '%s'", value);
giterr_set(GITERR_CONFIG, "failed to map '%s'", value);
return -1;
}
......@@ -1270,7 +1289,7 @@ int git_config_parse_bool(int *out, const char *value)
return 0;
}
giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a boolean value", value);
giterr_set(GITERR_CONFIG, "failed to parse '%s' as a boolean value", value);
return -1;
}
......@@ -1313,7 +1332,7 @@ int git_config_parse_int64(int64_t *out, const char *value)
}
fail_parse:
giterr_set(GITERR_CONFIG, "Failed to parse '%s' as an integer", value ? value : "(null)");
giterr_set(GITERR_CONFIG, "failed to parse '%s' as an integer", value ? value : "(null)");
return -1;
}
......@@ -1333,15 +1352,12 @@ int git_config_parse_int32(int32_t *out, const char *value)
return 0;
fail_parse:
giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a 32-bit integer", value ? value : "(null)");
giterr_set(GITERR_CONFIG, "failed to parse '%s' as a 32-bit integer", value ? value : "(null)");
return -1;
}
int git_config_parse_path(git_buf *out, const char *value)
{
int error = 0;
const git_buf *home;
assert(out && value);
git_buf_sanitize(out);
......@@ -1352,16 +1368,7 @@ int git_config_parse_path(git_buf *out, const char *value)
return -1;
}
if ((error = git_sysdir_get(&home, GIT_SYSDIR_GLOBAL)) < 0)
return error;
git_buf_sets(out, home->ptr);
git_buf_puts(out, value + 1);
if (git_buf_oom(out))
return -1;
return 0;
return git_sysdir_expand_global_file(out, value[1] ? &value[2] : NULL);
}
return git_buf_sets(out, value);
......@@ -1398,7 +1405,7 @@ int git_config__normalize_name(const char *in, char **out)
invalid:
git__free(name);
giterr_set(GITERR_CONFIG, "Invalid config item name '%s'", in);
giterr_set(GITERR_CONFIG, "invalid config item name '%s'", in);
return GIT_EINVALIDSPEC;
}
......@@ -1461,7 +1468,7 @@ int git_config_rename_section(
replace.ptr, strchr(replace.ptr, '.'))) < 0)
{
giterr_set(
GITERR_CONFIG, "Invalid config section '%s'", new_section_name);
GITERR_CONFIG, "invalid config section '%s'", new_section_name);
goto cleanup;
}
......
......@@ -7,6 +7,8 @@
#ifndef INCLUDE_config_h__
#define INCLUDE_config_h__
#include "common.h"
#include "git2.h"
#include "git2/config.h"
#include "vector.h"
......
......@@ -6,6 +6,7 @@
*/
#include "common.h"
#include "fileops.h"
#include "repository.h"
#include "config.h"
......@@ -78,6 +79,7 @@ static struct map_data _cvar_maps[] = {
{"core.logallrefupdates", NULL, 0, GIT_LOGALLREFUPDATES_DEFAULT },
{"core.protecthfs", NULL, 0, GIT_PROTECTHFS_DEFAULT },
{"core.protectntfs", NULL, 0, GIT_PROTECTNTFS_DEFAULT },
{"core.fsyncobjectfiles", NULL, 0, GIT_FSYNCOBJECTFILES_DEFAULT },
};
int git_config__cvar(int *out, git_config *config, git_cvar_cached cvar)
......
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment