mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-10 18:28:16 +00:00
Imported Upstream 0.24.2
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJYEbeBAAoJECKxCSrd3EfdhE0QAK0vY+jfoj7jj9IUShIkEvH/ DcG/DXAkZAHDJvzugm31QWZtCES1s8cN4vKjdNiTEGOvzOlnlxR+GKwxmoEmYpxO R3KzvHTjLAXEQBMMvYikT9QT8/JV/WUQSdCfc82ZyPltq/lKcx0vXyLzpQ+MbZFu fAdQeZrvKBd0oEQqjw87+xAn95t7/XGzOT/j78AkSm4K6O531d3MXn96XRf8aWQ7 vB8kc1JclsUn+EyYvIazhwrieoHbhOhJoAUoPb4OAyznoSZzwmnUwCuWws2OhstI QHwhz9HYtnDmBi0i19rHCmHG7M8hF/X3SIaaP94meAI3sGukNJvdqcxOITSLD0Hj fh6J/ddkorSjeuzQPTvJ/vTfo0mZTBiqvgUIR/Lk4BV4/aaWyylrU3Fv2DK1LAXH XLYVgJmQMCejIu24N/nOgTnYaipjpLDegTrnXtbcl3l/Y+ZG3lwDrgYUmwokMdPW 8DsSsBfUw03td/6OSuDAjQuRrkam470bVPY1NlNA1iJq40N3AeQmNvRYvobCLrWn NdDGZGIworE/N+frcHIgolS0b6CYa3cOVsyk0R9CrPFJeAcTFrBShexcX9XnxKjH fP2LWQO4pkGmTtmbom31UWRe59lDM9PX/PAYL86OwL53al4lWVpxgu+pHwprU4E6 P69DPEqJLjPLVhjHbkhp =pKRh -----END PGP SIGNATURE----- Merge tag 'upstream/0.24.2'
This commit is contained in:
commit
7c7a1dbfab
@ -40,7 +40,7 @@ OPTION( USE_ICONV "Link with and use iconv library" OFF )
|
||||
OPTION( USE_SSH "Link with libssh to enable SSH support" ON )
|
||||
OPTION( USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF )
|
||||
OPTION( VALGRIND "Configure build for valgrind" OFF )
|
||||
OPTION( CURL "User curl for HTTP if available" ON)
|
||||
OPTION( CURL "Use curl for HTTP if available" ON)
|
||||
OPTION( DEBUG_POOL "Enable debug pool allocator" OFF )
|
||||
|
||||
IF(DEBUG_POOL)
|
||||
@ -151,6 +151,10 @@ FUNCTION(TARGET_OS_LIBRARIES target)
|
||||
TARGET_LINK_LIBRARIES(${target} socket nsl)
|
||||
LIST(APPEND LIBGIT2_PC_LIBS "-lsocket" "-lnsl")
|
||||
SET(LIBGIT2_PC_LIBS ${LIBGIT2_PC_LIBS} PARENT_SCOPE)
|
||||
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Haiku")
|
||||
TARGET_LINK_LIBRARIES(${target} network)
|
||||
LIST(APPEND LIBGIT2_PC_LIBS "-lnetwork")
|
||||
SET(LIBGIT2_PC_LIBS ${LIBGIT2_PC_LIBS} PARENT_SCOPE)
|
||||
ENDIF()
|
||||
CHECK_LIBRARY_EXISTS(rt clock_gettime "time.h" NEED_LIBRT)
|
||||
IF(NEED_LIBRT)
|
||||
@ -161,6 +165,8 @@ FUNCTION(TARGET_OS_LIBRARIES target)
|
||||
|
||||
IF(THREADSAFE)
|
||||
TARGET_LINK_LIBRARIES(${target} ${CMAKE_THREAD_LIBS_INIT})
|
||||
LIST(APPEND LIBGIT2_PC_LIBS ${CMAKE_THREAD_LIBS_INIT})
|
||||
SET(LIBGIT2_PC_LIBS ${LIBGIT2_PC_LIBS} PARENT_SCOPE)
|
||||
ENDIF()
|
||||
ENDFUNCTION()
|
||||
|
||||
@ -280,6 +286,7 @@ ELSE ()
|
||||
IF (CURL_FOUND)
|
||||
ADD_DEFINITIONS(-DGIT_CURL)
|
||||
INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIRS})
|
||||
LINK_DIRECTORIES(${CURL_LIBRARY_DIRS})
|
||||
LINK_LIBRARIES(${CURL_LIBRARIES})
|
||||
LIST(APPEND LIBGIT2_PC_LIBS ${CURL_LDFLAGS})
|
||||
ENDIF()
|
||||
@ -467,19 +474,21 @@ ELSE ()
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
|
||||
ENDIF ()
|
||||
|
||||
IF (MINGW) # MinGW always does PIC and complains if we tell it to
|
||||
IF (MINGW OR MSYS) # MinGW and MSYS always do PIC and complain if we tell them to
|
||||
STRING(REGEX REPLACE "-fPIC" "" CMAKE_SHARED_LIBRARY_C_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}")
|
||||
# MinGW >= 3.14 uses the C99-style stdio functions
|
||||
# automatically, but forks like mingw-w64 still want
|
||||
# us to define this in order to use them
|
||||
ADD_DEFINITIONS(-D__USE_MINGW_ANSI_STDIO=1)
|
||||
|
||||
ELSEIF (BUILD_SHARED_LIBS)
|
||||
ADD_C_FLAG_IF_SUPPORTED(-fvisibility=hidden)
|
||||
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
|
||||
ENDIF ()
|
||||
|
||||
IF (MINGW)
|
||||
# MinGW >= 3.14 uses the C99-style stdio functions
|
||||
# automatically, but forks like mingw-w64 still want
|
||||
# us to define this in order to use them
|
||||
ADD_DEFINITIONS(-D__USE_MINGW_ANSI_STDIO=1)
|
||||
ENDIF ()
|
||||
|
||||
ADD_C_FLAG_IF_SUPPORTED(-Wdocumentation)
|
||||
ADD_C_FLAG_IF_SUPPORTED(-Wno-missing-field-initializers)
|
||||
ADD_C_FLAG_IF_SUPPORTED(-Wstrict-aliasing=2)
|
||||
|
50
README.md
50
README.md
@ -15,18 +15,30 @@ with any kind of software without having to release its source code.
|
||||
Additionally, the example code has been released to the public domain (see the
|
||||
[separate license](examples/COPYING) for more information).
|
||||
|
||||
* Website: [libgit2.github.com](http://libgit2.github.com)
|
||||
* StackOverflow Tag: [libgit2](http://stackoverflow.com/questions/tagged/libgit2)
|
||||
* Issues: [GitHub Issues](https://github.com/libgit2/libgit2/issues) (Right here!)
|
||||
* API documentation: <http://libgit2.github.com/libgit2/>
|
||||
* IRC: [#libgit2](irc://irc.freenode.net/libgit2) on irc.freenode.net.
|
||||
* Mailing list: The libgit2 mailing list was
|
||||
traditionally hosted in Librelist but has been deprecated. We encourage you to
|
||||
[use StackOverflow](http://stackoverflow.com/questions/tagged/libgit2) instead for any questions regarding
|
||||
the library, or [open an issue](https://github.com/libgit2/libgit2/issues)
|
||||
on GitHub for bug reports. The mailing list archives are still available at
|
||||
<http://librelist.com/browser/libgit2/>.
|
||||
Getting Help
|
||||
============
|
||||
|
||||
**Join us on Slack**
|
||||
|
||||
Visit [slack.libgit2.org](http://slack.libgit2.org/) to sign up, then join
|
||||
us in `#libgit2`. If you prefer IRC, you can also point your client to our
|
||||
slack channel once you've registered.
|
||||
|
||||
**Getting Help**
|
||||
|
||||
If you have questions about the library, please be sure to check out the
|
||||
[API documentation](http://libgit2.github.com/libgit2/). If you still have
|
||||
questions, reach out to us on Slack or post a question on
|
||||
[StackOverflow](http://stackoverflow.com/questions/tagged/libgit2) (with the `libgit2` tag).
|
||||
|
||||
**Reporting Bugs**
|
||||
|
||||
Please open a [GitHub Issue](https://github.com/libgit2/libgit2/issues) and
|
||||
include as much information as possible. If possible, provide sample code
|
||||
that illustrates the problem you're seeing. If you're seeing a bug only
|
||||
on a specific repository, please provide a link to it if possible.
|
||||
|
||||
We ask that you not open a GitHub Issue for help, only for bug reports.
|
||||
|
||||
What It Can Do
|
||||
==============
|
||||
@ -235,16 +247,22 @@ we can add it to the list.
|
||||
How Can I Contribute?
|
||||
==================================
|
||||
|
||||
Check the [contribution guidelines](CONTRIBUTING.md) to understand our
|
||||
workflow, the libgit2 [coding conventions](CONVENTIONS.md), and our list of
|
||||
[good starting projects](PROJECTS.md).
|
||||
We welcome new contributors! We have a number of issues marked as
|
||||
["up for grabs"](https://github.com/libgit2/libgit2/issues?q=is%3Aissue+is%3Aopen+label%3A%22up+for+grabs%22)
|
||||
and
|
||||
["easy fix"](https://github.com/libgit2/libgit2/issues?utf8=✓&q=is%3Aissue+is%3Aopen+label%3A%22easy+fix%22)
|
||||
that are good places to jump in and get started. There's much more detailed
|
||||
information in our list of [outstanding projects](PROJECTS.md).
|
||||
|
||||
Please be sure to check the [contribution guidelines](CONTRIBUTING.md) to
|
||||
understand our workflow, and the libgit2 [coding conventions](CONVENTIONS.md).
|
||||
|
||||
License
|
||||
==================================
|
||||
|
||||
`libgit2` is under GPL2 **with linking exception**. This means you can link to
|
||||
and use the library from any program, proprietary or open source; paid or
|
||||
gratis. However, you cannot modify libgit2 and distribute it without
|
||||
supplying the source.
|
||||
gratis. However, if you modify libgit2 itself, you must distribute the
|
||||
source to your modified version of libgit2.
|
||||
|
||||
See the [COPYING file](COPYING) for the full license text.
|
||||
|
@ -66,6 +66,8 @@ Key
|
||||
- Bi - ignored blob (WD only)
|
||||
- T1,T2,T3 - trees with different SHAs,
|
||||
- Ti - ignored tree (WD only)
|
||||
- S1,S2 - submodules with different SHAs
|
||||
- Sd - dirty submodule (WD only)
|
||||
- x - nothing
|
||||
|
||||
Diff with 2 non-workdir iterators
|
||||
@ -162,6 +164,27 @@ Checkout From 3 Iterators (2 not workdir, 1 workdir)
|
||||
| 35+ | T1 | T2 | x | update locally deleted tree (SAFE+MISSING) |
|
||||
| 36* | T1 | T2 | B1/Bi | update to tree with typechanged tree->blob conflict (F-1) |
|
||||
| 37 | T1 | T2 | T1/T2/T3 | update to existing tree (MAYBE SAFE) |
|
||||
| 38+ | x | S1 | x | add submodule (SAFE) |
|
||||
| 39 | x | S1 | S1/Sd | independently added submodule (SUBMODULE) |
|
||||
| 40* | x | S1 | B1 | add submodule with blob confilct (FORCEABLE) |
|
||||
| 41* | x | S1 | T1 | add submodule with tree conflict (FORCEABLE) |
|
||||
| 42 | S1 | x | S1/Sd | deleted submodule (SUBMODULE) |
|
||||
| 43 | S1 | x | x | independently deleted submodule (SUBMODULE) |
|
||||
| 44 | S1 | x | B1 | independently deleted submodule with added blob (SAFE+MISSING) |
|
||||
| 45 | S1 | x | T1 | independently deleted submodule with added tree (SAFE+MISSING) |
|
||||
| 46 | S1 | S1 | x | locally deleted submodule (SUBMODULE) |
|
||||
| 47+ | S1 | S2 | x | update locally deleted submodule (SAFE) |
|
||||
| 48 | S1 | S1 | S2 | locally updated submodule commit (SUBMODULE) |
|
||||
| 49 | S1 | S2 | S1 | updated submodule commit (SUBMODULE) |
|
||||
| 50+ | S1 | B1 | x | add blob with locally deleted submodule (SAFE+MISSING) |
|
||||
| 51* | S1 | B1 | S1 | typechange submodule->blob (SAFE) |
|
||||
| 52* | S1 | B1 | Sd | typechange dirty submodule->blob (SAFE!?!?) |
|
||||
| 53+ | S1 | T1 | x | add tree with locally deleted submodule (SAFE+MISSING) |
|
||||
| 54* | S1 | T1 | S1/Sd | typechange submodule->tree (MAYBE SAFE) |
|
||||
| 55+ | B1 | S1 | x | add submodule with locally deleted blob (SAFE+MISSING) |
|
||||
| 56* | B1 | S1 | B1 | typechange blob->submodule (SAFE) |
|
||||
| 57+ | T1 | S1 | x | add submodule with locally deleted tree (SAFE+MISSING) |
|
||||
| 58* | T1 | S1 | T1 | typechange tree->submodule (SAFE) |
|
||||
|
||||
|
||||
The number is followed by ' ' if no change is needed or '+' if the case
|
||||
@ -176,6 +199,8 @@ There are four tiers of safe cases:
|
||||
content, which is unknown at this point
|
||||
* FORCEABLE == conflict unless FORCE is given
|
||||
* DIRTY == no conflict but change is not applied unless FORCE
|
||||
* SUBMODULE == no conflict and no change is applied unless a deleted
|
||||
submodule dir is empty
|
||||
|
||||
Some slightly unusual circumstances:
|
||||
|
||||
@ -198,7 +223,9 @@ Some slightly unusual circumstances:
|
||||
cases, if baseline == target, we don't touch the workdir (it is
|
||||
either already right or is "dirty"). However, since this case also
|
||||
implies that a ?/B1/x case will exist as well, it can be skipped.
|
||||
* 41 - It's not clear how core git distinguishes this case from 39 (mode?).
|
||||
* 52 - Core git makes destructive changes without any warning when the
|
||||
submodule is dirty and the type changes to a blob.
|
||||
|
||||
Cases 3, 17, 24, 26, and 29 are all considered conflicts even though
|
||||
none of them will require making any updates to the working directory.
|
||||
|
||||
|
@ -313,6 +313,13 @@ GIT_EXTERN(int) git_checkout_init_options(
|
||||
* Updates files in the index and the working tree to match the content of
|
||||
* the commit pointed at by HEAD.
|
||||
*
|
||||
* Note that this is _not_ the correct mechanism used to switch branches;
|
||||
* do not change your `HEAD` and then call this method, that would leave
|
||||
* you with checkout conflicts since your working directory would then
|
||||
* appear to be dirty. Instead, checkout the target of the branch and
|
||||
* then update `HEAD` using `git_repository_set_head` to point to the
|
||||
* branch you checked out.
|
||||
*
|
||||
* @param repo repository to check out (must be non-bare)
|
||||
* @param opts specifies checkout options (may be NULL)
|
||||
* @return 0 on success, GIT_EUNBORNBRANCH if HEAD points to a non
|
||||
|
@ -7,10 +7,10 @@
|
||||
#ifndef INCLUDE_git_version_h__
|
||||
#define INCLUDE_git_version_h__
|
||||
|
||||
#define LIBGIT2_VERSION "0.24.0"
|
||||
#define LIBGIT2_VERSION "0.24.2"
|
||||
#define LIBGIT2_VER_MAJOR 0
|
||||
#define LIBGIT2_VER_MINOR 24
|
||||
#define LIBGIT2_VER_REVISION 0
|
||||
#define LIBGIT2_VER_REVISION 2
|
||||
#define LIBGIT2_VER_PATCH 0
|
||||
|
||||
#define LIBGIT2_SOVERSION 24
|
||||
|
@ -6,6 +6,10 @@ then
|
||||
exit $?;
|
||||
fi
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
export PKG_CONFIG_PATH=$(ls -d /usr/local/Cellar/{curl,zlib}/*/lib/pkgconfig | paste -s -d':' -)
|
||||
fi
|
||||
|
||||
mkdir _build
|
||||
cd _build
|
||||
# shellcheck disable=SC2086
|
||||
|
@ -3,4 +3,6 @@
|
||||
set -x
|
||||
|
||||
brew update
|
||||
brew install homebrew/dupes/zlib
|
||||
brew install curl
|
||||
brew install libssh2
|
||||
|
@ -96,7 +96,7 @@ GIT_INLINE(int) git_array__search(
|
||||
{
|
||||
size_t lim;
|
||||
unsigned char *part, *array = array_ptr, *base = array_ptr;
|
||||
int cmp;
|
||||
int cmp = -1;
|
||||
|
||||
for (lim = array_len; lim != 0; lim >>= 1) {
|
||||
part = base + (lim >> 1) * item_size;
|
||||
|
@ -37,25 +37,27 @@ static void origin_decref(git_blame__origin *o)
|
||||
static int make_origin(git_blame__origin **out, git_commit *commit, const char *path)
|
||||
{
|
||||
git_blame__origin *o;
|
||||
git_object *blob;
|
||||
size_t path_len = strlen(path), alloc_len;
|
||||
int error = 0;
|
||||
|
||||
if ((error = git_object_lookup_bypath(&blob, (git_object*)commit,
|
||||
path, GIT_OBJ_BLOB)) < 0)
|
||||
return error;
|
||||
|
||||
GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(*o), path_len);
|
||||
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 1);
|
||||
o = git__calloc(1, alloc_len);
|
||||
GITERR_CHECK_ALLOC(o);
|
||||
|
||||
o->commit = commit;
|
||||
o->blob = (git_blob *) blob;
|
||||
o->refcnt = 1;
|
||||
strcpy(o->path, path);
|
||||
|
||||
if (!(error = git_object_lookup_bypath((git_object**)&o->blob, (git_object*)commit,
|
||||
path, GIT_OBJ_BLOB))) {
|
||||
*out = o;
|
||||
} else {
|
||||
origin_decref(o);
|
||||
}
|
||||
return error;
|
||||
*out = o;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Locate an existing origin or create a new one. */
|
||||
@ -529,8 +531,16 @@ static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
|
||||
goto finish;
|
||||
porigin = find_origin(blame, p, origin);
|
||||
|
||||
if (!porigin)
|
||||
if (!porigin) {
|
||||
/*
|
||||
* We only have to decrement the parent's
|
||||
* reference count when no porigin has
|
||||
* been created, as otherwise the commit
|
||||
* is assigned to the created object.
|
||||
*/
|
||||
git_commit_free(p);
|
||||
continue;
|
||||
}
|
||||
if (porigin->blob && origin->blob &&
|
||||
!git_oid_cmp(git_blob_id(porigin->blob), git_blob_id(origin->blob))) {
|
||||
pass_whole_blame(blame, origin, porigin);
|
||||
|
@ -464,7 +464,8 @@ static int checkout_action_with_wd(
|
||||
*action = CHECKOUT_ACTION_IF(SAFE, REMOVE, NONE);
|
||||
break;
|
||||
case GIT_DELTA_MODIFIED: /* case 16, 17, 18 (or 36 but not really) */
|
||||
if (checkout_is_workdir_modified(data, &delta->old_file, &delta->new_file, wd))
|
||||
if (wd->mode != GIT_FILEMODE_COMMIT &&
|
||||
checkout_is_workdir_modified(data, &delta->old_file, &delta->new_file, wd))
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT);
|
||||
else
|
||||
*action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
@ -1342,9 +1343,11 @@ fail:
|
||||
|
||||
static bool should_remove_existing(checkout_data *data)
|
||||
{
|
||||
int ignorecase = 0;
|
||||
int ignorecase;
|
||||
|
||||
git_repository__cvar(&ignorecase, data->repo, GIT_CVAR_IGNORECASE);
|
||||
if (git_repository__cvar(&ignorecase, data->repo, GIT_CVAR_IGNORECASE) < 0) {
|
||||
ignorecase = 0;
|
||||
}
|
||||
|
||||
return (ignorecase &&
|
||||
(data->strategy & GIT_CHECKOUT_DONT_REMOVE_EXISTING) == 0);
|
||||
@ -2405,8 +2408,13 @@ static int checkout_data_init(
|
||||
|
||||
if (!data->opts.baseline && !data->opts.baseline_index) {
|
||||
data->opts_free_baseline = true;
|
||||
error = 0;
|
||||
|
||||
error = checkout_lookup_head_tree(&data->opts.baseline, repo);
|
||||
/* if we don't have an index, this is an initial checkout and
|
||||
* should be against an empty baseline
|
||||
*/
|
||||
if (data->index->on_disk)
|
||||
error = checkout_lookup_head_tree(&data->opts.baseline, repo);
|
||||
|
||||
if (error == GIT_EUNBORNBRANCH) {
|
||||
error = 0;
|
||||
@ -2691,7 +2699,7 @@ int git_checkout_tree(
|
||||
if ((error = git_repository_index(&index, repo)) < 0)
|
||||
return error;
|
||||
|
||||
if ((opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) {
|
||||
if (opts && (opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) {
|
||||
iter_opts.pathlist.count = opts->paths.count;
|
||||
iter_opts.pathlist.strings = opts->paths.strings;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@
|
||||
# include "win32/error.h"
|
||||
# include "win32/version.h"
|
||||
# ifdef GIT_THREADS
|
||||
# include "win32/pthread.h"
|
||||
# include "win32/thread.h"
|
||||
# endif
|
||||
# if defined(GIT_MSVC_CRTDBG)
|
||||
# include "win32/w32_stack.h"
|
||||
|
@ -49,6 +49,37 @@ int git__delta_read_header(
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DELTA_HEADER_BUFFER_LEN 16
|
||||
int git__delta_read_header_fromstream(size_t *base_sz, size_t *res_sz, git_packfile_stream *stream)
|
||||
{
|
||||
static const size_t buffer_len = DELTA_HEADER_BUFFER_LEN;
|
||||
unsigned char buffer[DELTA_HEADER_BUFFER_LEN];
|
||||
const unsigned char *delta, *delta_end;
|
||||
size_t len;
|
||||
ssize_t read;
|
||||
|
||||
len = read = 0;
|
||||
while (len < buffer_len) {
|
||||
read = git_packfile_stream_read(stream, &buffer[len], buffer_len - len);
|
||||
|
||||
if (read == 0)
|
||||
break;
|
||||
|
||||
if (read == GIT_EBUFS)
|
||||
continue;
|
||||
|
||||
len += read;
|
||||
}
|
||||
|
||||
delta = buffer;
|
||||
delta_end = delta + len;
|
||||
if ((hdr_sz(base_sz, &delta, delta_end) < 0) ||
|
||||
(hdr_sz(res_sz, &delta, delta_end) < 0))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git__delta_apply(
|
||||
git_rawobj *out,
|
||||
const unsigned char *base,
|
||||
@ -90,13 +121,13 @@ int git__delta_apply(
|
||||
size_t off = 0, len = 0;
|
||||
|
||||
if (cmd & 0x01) off = *delta++;
|
||||
if (cmd & 0x02) off |= *delta++ << 8;
|
||||
if (cmd & 0x04) off |= *delta++ << 16;
|
||||
if (cmd & 0x08) off |= *delta++ << 24;
|
||||
if (cmd & 0x02) off |= *delta++ << 8UL;
|
||||
if (cmd & 0x04) off |= *delta++ << 16UL;
|
||||
if (cmd & 0x08) off |= *delta++ << 24UL;
|
||||
|
||||
if (cmd & 0x10) len = *delta++;
|
||||
if (cmd & 0x20) len |= *delta++ << 8;
|
||||
if (cmd & 0x40) len |= *delta++ << 16;
|
||||
if (cmd & 0x20) len |= *delta++ << 8UL;
|
||||
if (cmd & 0x40) len |= *delta++ << 16UL;
|
||||
if (!len) len = 0x10000;
|
||||
|
||||
if (base_len < off + len || res_sz < len)
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define INCLUDE_delta_apply_h__
|
||||
|
||||
#include "odb.h"
|
||||
#include "pack.h"
|
||||
|
||||
/**
|
||||
* Apply a git binary delta to recover the original content.
|
||||
@ -47,4 +48,15 @@ extern int git__delta_read_header(
|
||||
size_t *base_sz,
|
||||
size_t *res_sz);
|
||||
|
||||
/**
|
||||
* Read the header of a git binary delta
|
||||
*
|
||||
* This variant reads just enough from the packfile stream to read the
|
||||
* delta header.
|
||||
*/
|
||||
extern int git__delta_read_header_fromstream(
|
||||
size_t *base_sz,
|
||||
size_t *res_sz,
|
||||
git_packfile_stream *stream);
|
||||
|
||||
#endif
|
||||
|
@ -70,7 +70,7 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
|
||||
git_file source;
|
||||
char buffer[FILEIO_BUFSIZE];
|
||||
ssize_t read_bytes;
|
||||
int error;
|
||||
int error = 0;
|
||||
|
||||
source = p_open(file->path_original, O_RDONLY);
|
||||
if (source < 0) {
|
||||
|
20
src/global.c
20
src/global.c
@ -59,8 +59,9 @@ static int init_common(void)
|
||||
if ((ret = git_hash_global_init()) == 0 &&
|
||||
(ret = git_sysdir_global_init()) == 0 &&
|
||||
(ret = git_filter_global_init()) == 0 &&
|
||||
(ret = git_transport_ssh_global_init()) == 0)
|
||||
ret = git_openssl_stream_global_init();
|
||||
(ret = git_transport_ssh_global_init()) == 0 &&
|
||||
(ret = git_openssl_stream_global_init()) == 0)
|
||||
ret = git_mwindow_global_init();
|
||||
|
||||
GIT_MEMORY_BARRIER;
|
||||
|
||||
@ -85,11 +86,6 @@ static void shutdown_common(void)
|
||||
|
||||
git__free(git__user_agent);
|
||||
git__free(git__ssl_ciphers);
|
||||
|
||||
#if defined(GIT_MSVC_CRTDBG)
|
||||
git_win32__crtdbg_stacktrace_cleanup();
|
||||
git_win32__stack_cleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,7 +133,7 @@ static int synchronized_threads_init(void)
|
||||
|
||||
_tls_index = TlsAlloc();
|
||||
|
||||
win32_pthread_initialize();
|
||||
git_threads_init();
|
||||
|
||||
if (git_mutex_init(&git__mwindow_mutex))
|
||||
return -1;
|
||||
@ -181,6 +177,11 @@ int git_libgit2_shutdown(void)
|
||||
|
||||
TlsFree(_tls_index);
|
||||
git_mutex_free(&git__mwindow_mutex);
|
||||
|
||||
#if defined(GIT_MSVC_CRTDBG)
|
||||
git_win32__crtdbg_stacktrace_cleanup();
|
||||
git_win32__stack_cleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Exit the lock */
|
||||
@ -226,6 +227,9 @@ void git__free_tls_data(void)
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
GIT_UNUSED(hInstDll);
|
||||
GIT_UNUSED(lpvReserved);
|
||||
|
||||
/* This is how Windows lets us know our thread is being shut down */
|
||||
if (fdwReason == DLL_THREAD_DETACH) {
|
||||
git__free_tls_data();
|
||||
|
61
src/ignore.c
61
src/ignore.c
@ -11,35 +11,64 @@
|
||||
#define GIT_IGNORE_DEFAULT_RULES ".\n..\n.git\n"
|
||||
|
||||
/**
|
||||
* A negative ignore pattern can match a positive one without
|
||||
* wildcards if its pattern equals the tail of the positive
|
||||
* pattern. Thus
|
||||
* A negative ignore pattern can negate a positive one without
|
||||
* wildcards if it is a basename only and equals the basename of
|
||||
* the positive pattern. Thus
|
||||
*
|
||||
* foo/bar
|
||||
* !bar
|
||||
*
|
||||
* would result in foo/bar being unignored again.
|
||||
* would result in foo/bar being unignored again while
|
||||
*
|
||||
* moo/foo/bar
|
||||
* !foo/bar
|
||||
*
|
||||
* would do nothing. The reverse also holds true: a positive
|
||||
* basename pattern can be negated by unignoring the basename in
|
||||
* subdirectories. Thus
|
||||
*
|
||||
* bar
|
||||
* !foo/bar
|
||||
*
|
||||
* would result in foo/bar being unignored again. As with the
|
||||
* first case,
|
||||
*
|
||||
* foo/bar
|
||||
* !moo/foo/bar
|
||||
*
|
||||
* would do nothing, again.
|
||||
*/
|
||||
static int does_negate_pattern(git_attr_fnmatch *rule, git_attr_fnmatch *neg)
|
||||
{
|
||||
git_attr_fnmatch *longer, *shorter;
|
||||
char *p;
|
||||
|
||||
if ((rule->flags & GIT_ATTR_FNMATCH_NEGATIVE) == 0
|
||||
&& (neg->flags & GIT_ATTR_FNMATCH_NEGATIVE) != 0) {
|
||||
/*
|
||||
* no chance of matching if rule is shorter than
|
||||
* the negated one
|
||||
*/
|
||||
if (rule->length < neg->length)
|
||||
|
||||
/* If lengths match we need to have an exact match */
|
||||
if (rule->length == neg->length) {
|
||||
return strcmp(rule->pattern, neg->pattern) == 0;
|
||||
} else if (rule->length < neg->length) {
|
||||
shorter = rule;
|
||||
longer = neg;
|
||||
} else {
|
||||
shorter = neg;
|
||||
longer = rule;
|
||||
}
|
||||
|
||||
/* Otherwise, we need to check if the shorter
|
||||
* rule is a basename only (that is, it contains
|
||||
* no path separator) and, if so, if it
|
||||
* matches the tail of the longer rule */
|
||||
p = longer->pattern + longer->length - shorter->length;
|
||||
|
||||
if (p[-1] != '/')
|
||||
return false;
|
||||
if (memchr(shorter->pattern, '/', shorter->length) != NULL)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* shift pattern so its tail aligns with the
|
||||
* negated pattern
|
||||
*/
|
||||
p = rule->pattern + rule->length - neg->length;
|
||||
if (strcmp(p, neg->pattern) == 0)
|
||||
return true;
|
||||
return memcmp(p, shorter->pattern, shorter->length) == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
21
src/index.c
21
src/index.c
@ -505,10 +505,11 @@ static int index_remove_entry(git_index *index, size_t pos)
|
||||
int error = 0;
|
||||
git_index_entry *entry = git_vector_get(&index->entries, pos);
|
||||
|
||||
if (entry != NULL)
|
||||
if (entry != NULL) {
|
||||
git_tree_cache_invalidate_path(index->tree, entry->path);
|
||||
DELETE_IN_MAP(index, entry);
|
||||
}
|
||||
|
||||
DELETE_IN_MAP(index, entry);
|
||||
error = git_vector_remove(&index->entries, pos);
|
||||
|
||||
if (!error) {
|
||||
@ -2968,6 +2969,8 @@ int git_index_read_index(
|
||||
*remove_entry = NULL;
|
||||
int diff;
|
||||
|
||||
error = 0;
|
||||
|
||||
if (old_entry && new_entry)
|
||||
diff = git_index_entry_cmp(old_entry, new_entry);
|
||||
else if (!old_entry && new_entry)
|
||||
@ -2985,7 +2988,8 @@ int git_index_read_index(
|
||||
/* Path and stage are equal, if the OID is equal, keep it to
|
||||
* keep the stat cache data.
|
||||
*/
|
||||
if (git_oid_equal(&old_entry->id, &new_entry->id)) {
|
||||
if (git_oid_equal(&old_entry->id, &new_entry->id) &&
|
||||
old_entry->mode == new_entry->mode) {
|
||||
add_entry = (git_index_entry *)old_entry;
|
||||
} else {
|
||||
dup_entry = (git_index_entry *)new_entry;
|
||||
@ -2996,8 +3000,17 @@ int git_index_read_index(
|
||||
if (dup_entry) {
|
||||
if ((error = index_entry_dup_nocache(&add_entry, index, dup_entry)) < 0)
|
||||
goto done;
|
||||
|
||||
index_entry_adjust_namemask(add_entry,
|
||||
((struct entry_internal *)add_entry)->pathlen);
|
||||
}
|
||||
|
||||
/* invalidate this path in the tree cache if this is new (to
|
||||
* invalidate the parent trees)
|
||||
*/
|
||||
if (dup_entry && !remove_entry && index->tree)
|
||||
git_tree_cache_invalidate_path(index->tree, dup_entry->path);
|
||||
|
||||
if (add_entry) {
|
||||
if ((error = git_vector_insert(&new_entries, add_entry)) == 0)
|
||||
INSERT_IN_MAP_EX(index, new_entries_map, add_entry, error);
|
||||
@ -3008,7 +3021,7 @@ int git_index_read_index(
|
||||
|
||||
if (error < 0) {
|
||||
giterr_set(GITERR_INDEX, "failed to insert entry");
|
||||
return error;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (diff <= 0) {
|
||||
|
@ -2730,6 +2730,7 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde
|
||||
opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
|
||||
opts.pathspec.count = merged_paths->length;
|
||||
opts.pathspec.strings = (char **)merged_paths->contents;
|
||||
opts.ignore_submodules = GIT_SUBMODULE_IGNORE_ALL;
|
||||
|
||||
if ((error = git_diff_index_to_workdir(&wd_diff_list, repo, NULL, &opts)) < 0)
|
||||
goto done;
|
||||
|
@ -33,20 +33,7 @@ static git_mwindow_ctl mem_ctl;
|
||||
/* Global list of mwindow files, to open packs once across repos */
|
||||
git_strmap *git__pack_cache = NULL;
|
||||
|
||||
/**
|
||||
* Run under mwindow lock
|
||||
*/
|
||||
int git_mwindow_files_init(void)
|
||||
{
|
||||
if (git__pack_cache)
|
||||
return 0;
|
||||
|
||||
git__on_shutdown(git_mwindow_files_free);
|
||||
|
||||
return git_strmap_alloc(&git__pack_cache);
|
||||
}
|
||||
|
||||
void git_mwindow_files_free(void)
|
||||
static void git_mwindow_files_free(void)
|
||||
{
|
||||
git_strmap *tmp = git__pack_cache;
|
||||
|
||||
@ -54,6 +41,14 @@ void git_mwindow_files_free(void)
|
||||
git_strmap_free(tmp);
|
||||
}
|
||||
|
||||
int git_mwindow_global_init(void)
|
||||
{
|
||||
assert(!git__pack_cache);
|
||||
|
||||
git__on_shutdown(git_mwindow_files_free);
|
||||
return git_strmap_alloc(&git__pack_cache);
|
||||
}
|
||||
|
||||
int git_mwindow_get_pack(struct git_pack_file **out, const char *path)
|
||||
{
|
||||
int error;
|
||||
@ -69,12 +64,6 @@ int git_mwindow_get_pack(struct git_pack_file **out, const char *path)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (git_mwindow_files_init() < 0) {
|
||||
git_mutex_unlock(&git__mwindow_mutex);
|
||||
git__free(packname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pos = git_strmap_lookup_index(git__pack_cache, packname);
|
||||
git__free(packname);
|
||||
|
||||
|
@ -43,8 +43,7 @@ int git_mwindow_file_register(git_mwindow_file *mwf);
|
||||
void git_mwindow_file_deregister(git_mwindow_file *mwf);
|
||||
void git_mwindow_close(git_mwindow **w_cursor);
|
||||
|
||||
int git_mwindow_files_init(void);
|
||||
void git_mwindow_files_free(void);
|
||||
extern int git_mwindow_global_init(void);
|
||||
|
||||
struct git_pack_file; /* just declaration to avoid cyclical includes */
|
||||
int git_mwindow_get_pack(struct git_pack_file **out, const char *path);
|
||||
|
11
src/odb.c
11
src/odb.c
@ -803,19 +803,12 @@ int git_odb__read_header_or_object(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static git_oid empty_blob = {{ 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,
|
||||
0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91 }};
|
||||
static git_oid empty_tree = {{ 0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
|
||||
0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04 }};
|
||||
|
||||
static int hardcoded_objects(git_rawobj *raw, const git_oid *id)
|
||||
{
|
||||
if (!git_oid_cmp(id, &empty_blob)) {
|
||||
raw->type = GIT_OBJ_BLOB;
|
||||
raw->len = 0;
|
||||
raw->data = git__calloc(1, sizeof(uint8_t));
|
||||
return 0;
|
||||
} else if (!git_oid_cmp(id, &empty_tree)) {
|
||||
if (!git_oid_cmp(id, &empty_tree)) {
|
||||
raw->type = GIT_OBJ_TREE;
|
||||
raw->len = 0;
|
||||
raw->data = git__calloc(1, sizeof(uint8_t));
|
||||
@ -1229,7 +1222,7 @@ int git_odb__error_notfound(
|
||||
{
|
||||
if (oid != NULL) {
|
||||
char oid_str[GIT_OID_HEXSZ + 1];
|
||||
git_oid_tostr(oid_str, oid_len, oid);
|
||||
git_oid_tostr(oid_str, oid_len+1, oid);
|
||||
giterr_set(GITERR_ODB, "Object not found - %s (%.*s)",
|
||||
message, oid_len, oid_str);
|
||||
} else
|
||||
|
@ -91,7 +91,7 @@ static int object_mkdir(const git_buf *name, const loose_backend *be)
|
||||
|
||||
static size_t get_binary_object_header(obj_hdr *hdr, git_buf *obj)
|
||||
{
|
||||
unsigned char c;
|
||||
unsigned long c;
|
||||
unsigned char *data = (unsigned char *)obj->ptr;
|
||||
size_t shift, size, used = 0;
|
||||
|
||||
|
@ -591,9 +591,6 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
|
||||
struct pack_backend *backend = NULL;
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
|
||||
if (git_mwindow_files_init() < 0)
|
||||
return -1;
|
||||
|
||||
if (pack_backend__alloc(&backend, 8) < 0)
|
||||
return -1;
|
||||
|
||||
|
@ -522,8 +522,9 @@ ssize_t openssl_read(git_stream *stream, void *data, size_t len)
|
||||
openssl_stream *st = (openssl_stream *) stream;
|
||||
int ret;
|
||||
|
||||
if ((ret = SSL_read(st->ssl, data, len)) <= 0)
|
||||
ssl_set_error(st->ssl, ret);
|
||||
if ((ret = SSL_read(st->ssl, data, len)) <= 0) {
|
||||
return ssl_set_error(st->ssl, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1186,7 +1186,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
|
||||
git_mutex_init(&p[i].mutex);
|
||||
git_cond_init(&p[i].cond);
|
||||
|
||||
ret = git_thread_create(&p[i].thread, NULL,
|
||||
ret = git_thread_create(&p[i].thread,
|
||||
threaded_find_deltas, &p[i]);
|
||||
if (ret) {
|
||||
giterr_set(GITERR_THREAD, "unable to create thread");
|
||||
|
11
src/pack.c
11
src/pack.c
@ -499,15 +499,14 @@ int git_packfile_resolve_header(
|
||||
|
||||
if (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) {
|
||||
size_t base_size;
|
||||
git_rawobj delta;
|
||||
git_packfile_stream stream;
|
||||
|
||||
base_offset = get_delta_base(p, &w_curs, &curpos, type, offset);
|
||||
git_mwindow_close(&w_curs);
|
||||
error = packfile_unpack_compressed(&delta, p, &w_curs, &curpos, size, type);
|
||||
git_mwindow_close(&w_curs);
|
||||
if (error < 0)
|
||||
if ((error = git_packfile_stream_open(&stream, p, curpos)) < 0)
|
||||
return error;
|
||||
error = git__delta_read_header(delta.data, delta.len, &base_size, size_p);
|
||||
git__free(delta.data);
|
||||
error = git__delta_read_header_fromstream(&base_size, size_p, &stream);
|
||||
git_packfile_stream_free(&stream);
|
||||
if (error < 0)
|
||||
return error;
|
||||
} else
|
||||
|
@ -53,8 +53,10 @@ int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch)
|
||||
|
||||
if (rhs) {
|
||||
size_t rlen = strlen(++rhs);
|
||||
is_glob = (1 <= rlen && strchr(rhs, '*'));
|
||||
refspec->dst = git__strndup(rhs, rlen);
|
||||
if (rlen || !is_fetch) {
|
||||
is_glob = (1 <= rlen && strchr(rhs, '*'));
|
||||
refspec->dst = git__strndup(rhs, rlen);
|
||||
}
|
||||
}
|
||||
|
||||
llen = (rhs ? (size_t)(rhs - lhs - 1) : strlen(lhs));
|
||||
|
20
src/remote.c
20
src/remote.c
@ -1414,7 +1414,11 @@ static int update_tips_for_spec(
|
||||
/* In autotag mode, don't overwrite any locally-existing tags */
|
||||
error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
|
||||
log_message);
|
||||
if (error < 0 && error != GIT_EEXISTS)
|
||||
|
||||
if (error == GIT_EEXISTS)
|
||||
continue;
|
||||
|
||||
if (error < 0)
|
||||
goto on_error;
|
||||
|
||||
git_reference_free(ref);
|
||||
@ -2224,15 +2228,21 @@ static int remove_branch_config_related_entries(
|
||||
if (git_buf_printf(&buf, "branch.%.*s.merge", (int)branch_len, branch) < 0)
|
||||
break;
|
||||
|
||||
if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0)
|
||||
break;
|
||||
if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) {
|
||||
if (error != GIT_ENOTFOUND)
|
||||
break;
|
||||
giterr_clear();
|
||||
}
|
||||
|
||||
git_buf_clear(&buf);
|
||||
if (git_buf_printf(&buf, "branch.%.*s.remote", (int)branch_len, branch) < 0)
|
||||
break;
|
||||
|
||||
if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0)
|
||||
break;
|
||||
if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) {
|
||||
if (error != GIT_ENOTFOUND)
|
||||
break;
|
||||
giterr_clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (error == GIT_ITEROVER)
|
||||
|
@ -264,7 +264,7 @@ cleanup:
|
||||
* the stack could remove directories name limits, but at the cost of doing
|
||||
* repeated malloc/frees inside the loop below, so let's not do it now.
|
||||
*/
|
||||
static int find_ceiling_dir_offset(
|
||||
static size_t find_ceiling_dir_offset(
|
||||
const char *path,
|
||||
const char *ceiling_directories)
|
||||
{
|
||||
@ -278,7 +278,7 @@ static int find_ceiling_dir_offset(
|
||||
min_len = (size_t)(git_path_root(path) + 1);
|
||||
|
||||
if (ceiling_directories == NULL || min_len == 0)
|
||||
return (int)min_len;
|
||||
return min_len;
|
||||
|
||||
for (sep = ceil = ceiling_directories; *sep; ceil = sep + 1) {
|
||||
for (sep = ceil; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++);
|
||||
@ -305,7 +305,7 @@ static int find_ceiling_dir_offset(
|
||||
}
|
||||
}
|
||||
|
||||
return (int)(max_len <= min_len ? min_len : max_len);
|
||||
return (max_len <= min_len ? min_len : max_len);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -359,21 +359,36 @@ static int find_repo(
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
struct stat st;
|
||||
dev_t initial_device = 0;
|
||||
bool try_with_dot_git = ((flags & GIT_REPOSITORY_OPEN_BARE) != 0);
|
||||
int ceiling_offset;
|
||||
int min_iterations;
|
||||
bool in_dot_git;
|
||||
size_t ceiling_offset = 0;
|
||||
|
||||
git_buf_free(repo_path);
|
||||
|
||||
if ((error = git_path_prettify(&path, start_path, NULL)) < 0)
|
||||
return error;
|
||||
|
||||
ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
|
||||
/* in_dot_git toggles each loop:
|
||||
* /a/b/c/.git, /a/b/c, /a/b/.git, /a/b, /a/.git, /a
|
||||
* With GIT_REPOSITORY_OPEN_BARE, we assume we started with /a/b/c.git
|
||||
* and don't append .git the first time through.
|
||||
* min_iterations indicates the number of iterations left before going
|
||||
* further counts as a search. */
|
||||
if (flags & GIT_REPOSITORY_OPEN_BARE) {
|
||||
in_dot_git = true;
|
||||
min_iterations = 1;
|
||||
} else {
|
||||
in_dot_git = false;
|
||||
min_iterations = 2;
|
||||
}
|
||||
|
||||
if (!try_with_dot_git &&
|
||||
(error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
|
||||
return error;
|
||||
while (!error && (min_iterations || !(path.ptr[ceiling_offset] == 0 ||
|
||||
(flags & GIT_REPOSITORY_OPEN_NO_SEARCH)))) {
|
||||
if (!in_dot_git)
|
||||
if ((error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
|
||||
break;
|
||||
in_dot_git = !in_dot_git;
|
||||
|
||||
while (!error && !git_buf_len(repo_path)) {
|
||||
if (p_stat(path.ptr, &st) == 0) {
|
||||
/* check that we have not crossed device boundaries */
|
||||
if (initial_device == 0)
|
||||
@ -414,17 +429,10 @@ static int find_repo(
|
||||
break;
|
||||
}
|
||||
|
||||
if (try_with_dot_git) {
|
||||
/* if we tried original dir with and without .git AND either hit
|
||||
* directory ceiling or NO_SEARCH was requested, then be done.
|
||||
*/
|
||||
if (path.ptr[ceiling_offset] == '\0' ||
|
||||
(flags & GIT_REPOSITORY_OPEN_NO_SEARCH) != 0)
|
||||
break;
|
||||
/* otherwise look first for .git item */
|
||||
error = git_buf_joinpath(&path, path.ptr, DOT_GIT);
|
||||
}
|
||||
try_with_dot_git = !try_with_dot_git;
|
||||
/* Once we've checked the directory (and .git if applicable),
|
||||
* find the ceiling for a search. */
|
||||
if (min_iterations && (--min_iterations == 0))
|
||||
ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
|
||||
}
|
||||
|
||||
if (!error && parent_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "socket_stream.h"
|
||||
#include "curl_stream.h"
|
||||
|
||||
int stransport_error(OSStatus ret)
|
||||
static int stransport_error(OSStatus ret)
|
||||
{
|
||||
CFStringRef message;
|
||||
|
||||
@ -33,6 +33,7 @@ int stransport_error(OSStatus ret)
|
||||
CFRelease(message);
|
||||
#else
|
||||
giterr_set(GITERR_NET, "SecureTransport error: OSStatus %d", (unsigned int)ret);
|
||||
GIT_UNUSED(message);
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
@ -46,7 +47,7 @@ typedef struct {
|
||||
git_cert_x509 cert_info;
|
||||
} stransport_stream;
|
||||
|
||||
int stransport_connect(git_stream *stream)
|
||||
static int stransport_connect(git_stream *stream)
|
||||
{
|
||||
stransport_stream *st = (stransport_stream *) stream;
|
||||
int error;
|
||||
@ -66,6 +67,9 @@ int stransport_connect(git_stream *stream)
|
||||
if ((ret = SSLCopyPeerTrust(st->ctx, &trust)) != noErr)
|
||||
goto on_error;
|
||||
|
||||
if (!trust)
|
||||
return GIT_ECERTIFICATE;
|
||||
|
||||
if ((ret = SecTrustEvaluate(trust, &sec_res)) != noErr)
|
||||
goto on_error;
|
||||
|
||||
@ -89,7 +93,7 @@ on_error:
|
||||
return stransport_error(ret);
|
||||
}
|
||||
|
||||
int stransport_certificate(git_cert **out, git_stream *stream)
|
||||
static int stransport_certificate(git_cert **out, git_stream *stream)
|
||||
{
|
||||
stransport_stream *st = (stransport_stream *) stream;
|
||||
SecTrustRef trust = NULL;
|
||||
@ -116,7 +120,7 @@ int stransport_certificate(git_cert **out, git_stream *stream)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stransport_set_proxy(git_stream *stream, const char *proxy)
|
||||
static int stransport_set_proxy(git_stream *stream, const char *proxy)
|
||||
{
|
||||
stransport_stream *st = (stransport_stream *) stream;
|
||||
|
||||
@ -146,7 +150,7 @@ static OSStatus write_cb(SSLConnectionRef conn, const void *data, size_t *len)
|
||||
return noErr;
|
||||
}
|
||||
|
||||
ssize_t stransport_write(git_stream *stream, const char *data, size_t len, int flags)
|
||||
static ssize_t stransport_write(git_stream *stream, const char *data, size_t len, int flags)
|
||||
{
|
||||
stransport_stream *st = (stransport_stream *) stream;
|
||||
size_t data_len, processed;
|
||||
@ -195,7 +199,7 @@ static OSStatus read_cb(SSLConnectionRef conn, void *data, size_t *len)
|
||||
return error;
|
||||
}
|
||||
|
||||
ssize_t stransport_read(git_stream *stream, void *data, size_t len)
|
||||
static ssize_t stransport_read(git_stream *stream, void *data, size_t len)
|
||||
{
|
||||
stransport_stream *st = (stransport_stream *) stream;
|
||||
size_t processed;
|
||||
@ -207,7 +211,7 @@ ssize_t stransport_read(git_stream *stream, void *data, size_t len)
|
||||
return processed;
|
||||
}
|
||||
|
||||
int stransport_close(git_stream *stream)
|
||||
static int stransport_close(git_stream *stream)
|
||||
{
|
||||
stransport_stream *st = (stransport_stream *) stream;
|
||||
OSStatus ret;
|
||||
@ -219,7 +223,7 @@ int stransport_close(git_stream *stream)
|
||||
return git_stream_close(st->io);
|
||||
}
|
||||
|
||||
void stransport_free(git_stream *stream)
|
||||
static void stransport_free(git_stream *stream)
|
||||
{
|
||||
stransport_stream *st = (stransport_stream *) stream;
|
||||
|
||||
@ -255,6 +259,7 @@ int git_stransport_stream_new(git_stream **out, const char *host, const char *po
|
||||
st->ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
|
||||
if (!st->ctx) {
|
||||
giterr_set(GITERR_NET, "failed to create SSL context");
|
||||
git__free(st);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -264,7 +269,8 @@ int git_stransport_stream_new(git_stream **out, const char *host, const char *po
|
||||
(ret = SSLSetProtocolVersionMin(st->ctx, kTLSProtocol1)) != noErr ||
|
||||
(ret = SSLSetProtocolVersionMax(st->ctx, kTLSProtocol12)) != noErr ||
|
||||
(ret = SSLSetPeerDomainName(st->ctx, host, strlen(host))) != noErr) {
|
||||
git_stream_free((git_stream *)st);
|
||||
CFRelease(st->ctx);
|
||||
git__free(st);
|
||||
return stransport_error(ret);
|
||||
}
|
||||
|
||||
|
90
src/sysdir.c
90
src/sysdir.c
@ -83,45 +83,43 @@ static int git_sysdir_guess_template_dirs(git_buf *out)
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef int (*git_sysdir_guess_cb)(git_buf *out);
|
||||
|
||||
static git_buf git_sysdir__dirs[GIT_SYSDIR__MAX] =
|
||||
{ GIT_BUF_INIT, GIT_BUF_INIT, GIT_BUF_INIT, GIT_BUF_INIT, GIT_BUF_INIT };
|
||||
|
||||
static git_sysdir_guess_cb git_sysdir__dir_guess[GIT_SYSDIR__MAX] = {
|
||||
git_sysdir_guess_system_dirs,
|
||||
git_sysdir_guess_global_dirs,
|
||||
git_sysdir_guess_xdg_dirs,
|
||||
git_sysdir_guess_programdata_dirs,
|
||||
git_sysdir_guess_template_dirs,
|
||||
struct git_sysdir__dir {
|
||||
git_buf buf;
|
||||
int (*guess)(git_buf *out);
|
||||
};
|
||||
|
||||
static int git_sysdir__dirs_shutdown_set = 0;
|
||||
static struct git_sysdir__dir git_sysdir__dirs[] = {
|
||||
{ GIT_BUF_INIT, git_sysdir_guess_system_dirs },
|
||||
{ GIT_BUF_INIT, git_sysdir_guess_global_dirs },
|
||||
{ GIT_BUF_INIT, git_sysdir_guess_xdg_dirs },
|
||||
{ GIT_BUF_INIT, git_sysdir_guess_programdata_dirs },
|
||||
{ GIT_BUF_INIT, git_sysdir_guess_template_dirs },
|
||||
};
|
||||
|
||||
static void git_sysdir_global_shutdown(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(git_sysdir__dirs); ++i)
|
||||
git_buf_free(&git_sysdir__dirs[i].buf);
|
||||
}
|
||||
|
||||
int git_sysdir_global_init(void)
|
||||
{
|
||||
git_sysdir_t i;
|
||||
const git_buf *path;
|
||||
size_t i;
|
||||
int error = 0;
|
||||
|
||||
for (i = 0; !error && i < GIT_SYSDIR__MAX; i++)
|
||||
error = git_sysdir_get(&path, i);
|
||||
for (i = 0; !error && i < ARRAY_SIZE(git_sysdir__dirs); i++)
|
||||
error = git_sysdir__dirs[i].guess(&git_sysdir__dirs[i].buf);
|
||||
|
||||
git__on_shutdown(git_sysdir_global_shutdown);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void git_sysdir_global_shutdown(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < GIT_SYSDIR__MAX; ++i)
|
||||
git_buf_free(&git_sysdir__dirs[i]);
|
||||
|
||||
git_sysdir__dirs_shutdown_set = 0;
|
||||
}
|
||||
|
||||
static int git_sysdir_check_selector(git_sysdir_t which)
|
||||
{
|
||||
if (which < GIT_SYSDIR__MAX)
|
||||
if (which < ARRAY_SIZE(git_sysdir__dirs))
|
||||
return 0;
|
||||
|
||||
giterr_set(GITERR_INVALID, "config directory selector out of range");
|
||||
@ -137,18 +135,7 @@ int git_sysdir_get(const git_buf **out, git_sysdir_t which)
|
||||
|
||||
GITERR_CHECK_ERROR(git_sysdir_check_selector(which));
|
||||
|
||||
if (!git_buf_len(&git_sysdir__dirs[which])) {
|
||||
/* prepare shutdown if we're going to need it */
|
||||
if (!git_sysdir__dirs_shutdown_set) {
|
||||
git__on_shutdown(git_sysdir_global_shutdown);
|
||||
git_sysdir__dirs_shutdown_set = 1;
|
||||
}
|
||||
|
||||
GITERR_CHECK_ERROR(
|
||||
git_sysdir__dir_guess[which](&git_sysdir__dirs[which]));
|
||||
}
|
||||
|
||||
*out = &git_sysdir__dirs[which];
|
||||
*out = &git_sysdir__dirs[which].buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -183,31 +170,38 @@ int git_sysdir_set(git_sysdir_t which, const char *search_path)
|
||||
if (search_path != NULL)
|
||||
expand_path = strstr(search_path, PATH_MAGIC);
|
||||
|
||||
/* init with default if not yet done and needed (ignoring error) */
|
||||
if ((!search_path || expand_path) &&
|
||||
!git_buf_len(&git_sysdir__dirs[which]))
|
||||
git_sysdir__dir_guess[which](&git_sysdir__dirs[which]);
|
||||
/* reset the default if this path has been cleared */
|
||||
if (!search_path || expand_path)
|
||||
git_sysdir__dirs[which].guess(&git_sysdir__dirs[which].buf);
|
||||
|
||||
/* if $PATH is not referenced, then just set the path */
|
||||
if (!expand_path)
|
||||
return git_buf_sets(&git_sysdir__dirs[which], search_path);
|
||||
if (!expand_path) {
|
||||
if (search_path)
|
||||
git_buf_sets(&git_sysdir__dirs[which].buf, search_path);
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* otherwise set to join(before $PATH, old value, after $PATH) */
|
||||
if (expand_path > search_path)
|
||||
git_buf_set(&merge, search_path, expand_path - search_path);
|
||||
|
||||
if (git_buf_len(&git_sysdir__dirs[which]))
|
||||
if (git_buf_len(&git_sysdir__dirs[which].buf))
|
||||
git_buf_join(&merge, GIT_PATH_LIST_SEPARATOR,
|
||||
merge.ptr, git_sysdir__dirs[which].ptr);
|
||||
merge.ptr, git_sysdir__dirs[which].buf.ptr);
|
||||
|
||||
expand_path += strlen(PATH_MAGIC);
|
||||
if (*expand_path)
|
||||
git_buf_join(&merge, GIT_PATH_LIST_SEPARATOR, merge.ptr, expand_path);
|
||||
|
||||
git_buf_swap(&git_sysdir__dirs[which], &merge);
|
||||
git_buf_swap(&git_sysdir__dirs[which].buf, &merge);
|
||||
git_buf_free(&merge);
|
||||
|
||||
return git_buf_oom(&git_sysdir__dirs[which]) ? -1 : 0;
|
||||
done:
|
||||
if (git_buf_oom(&git_sysdir__dirs[which].buf))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int git_sysdir_find_in_dirlist(
|
||||
|
@ -103,9 +103,4 @@ extern int git_sysdir_get_str(char *out, size_t outlen, git_sysdir_t which);
|
||||
*/
|
||||
extern int git_sysdir_set(git_sysdir_t which, const char *paths);
|
||||
|
||||
/**
|
||||
* Free the configuration file search paths.
|
||||
*/
|
||||
extern void git_sysdir_global_shutdown(void);
|
||||
|
||||
#endif /* INCLUDE_sysdir_h__ */
|
||||
|
10
src/tag.c
10
src/tag.c
@ -137,8 +137,14 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
|
||||
|
||||
tag->message = NULL;
|
||||
if (buffer < buffer_end) {
|
||||
if( *buffer != '\n' )
|
||||
return tag_error("No new line before message");
|
||||
/* If we're not at the end of the header, search for it */
|
||||
if( *buffer != '\n' ) {
|
||||
search = strstr(buffer, "\n\n");
|
||||
if (search)
|
||||
buffer = search + 1;
|
||||
else
|
||||
return tag_error("tag contains no message");
|
||||
}
|
||||
|
||||
text_len = buffer_end - ++buffer;
|
||||
|
||||
|
@ -40,58 +40,12 @@ typedef git_atomic git_atomic_ssize;
|
||||
|
||||
#ifdef GIT_THREADS
|
||||
|
||||
#if !defined(GIT_WIN32)
|
||||
|
||||
typedef struct {
|
||||
pthread_t thread;
|
||||
} git_thread;
|
||||
|
||||
#define git_thread_create(git_thread_ptr, attr, start_routine, arg) \
|
||||
pthread_create(&(git_thread_ptr)->thread, attr, start_routine, arg)
|
||||
#define git_thread_join(git_thread_ptr, status) \
|
||||
pthread_join((git_thread_ptr)->thread, status)
|
||||
|
||||
#ifdef GIT_WIN32
|
||||
# include "win32/thread.h"
|
||||
#else
|
||||
# include "unix/pthread.h"
|
||||
#endif
|
||||
|
||||
/* Pthreads Mutex */
|
||||
#define git_mutex pthread_mutex_t
|
||||
#define git_mutex_init(a) pthread_mutex_init(a, NULL)
|
||||
#define git_mutex_lock(a) pthread_mutex_lock(a)
|
||||
#define git_mutex_unlock(a) pthread_mutex_unlock(a)
|
||||
#define git_mutex_free(a) pthread_mutex_destroy(a)
|
||||
|
||||
/* Pthreads condition vars */
|
||||
#define git_cond pthread_cond_t
|
||||
#define git_cond_init(c) pthread_cond_init(c, NULL)
|
||||
#define git_cond_free(c) pthread_cond_destroy(c)
|
||||
#define git_cond_wait(c, l) pthread_cond_wait(c, l)
|
||||
#define git_cond_signal(c) pthread_cond_signal(c)
|
||||
#define git_cond_broadcast(c) pthread_cond_broadcast(c)
|
||||
|
||||
/* Pthread (-ish) rwlock
|
||||
*
|
||||
* This differs from normal pthreads rwlocks in two ways:
|
||||
* 1. Separate APIs for releasing read locks and write locks (as
|
||||
* opposed to the pure POSIX API which only has one unlock fn)
|
||||
* 2. You should not use recursive read locks (i.e. grabbing a read
|
||||
* lock in a thread that already holds a read lock) because the
|
||||
* Windows implementation doesn't support it
|
||||
*/
|
||||
#define git_rwlock pthread_rwlock_t
|
||||
#define git_rwlock_init(a) pthread_rwlock_init(a, NULL)
|
||||
#define git_rwlock_rdlock(a) pthread_rwlock_rdlock(a)
|
||||
#define git_rwlock_rdunlock(a) pthread_rwlock_rdunlock(a)
|
||||
#define git_rwlock_wrlock(a) pthread_rwlock_wrlock(a)
|
||||
#define git_rwlock_wrunlock(a) pthread_rwlock_wrunlock(a)
|
||||
#define git_rwlock_free(a) pthread_rwlock_destroy(a)
|
||||
#define GIT_RWLOCK_STATIC_INIT PTHREAD_RWLOCK_INITIALIZER
|
||||
|
||||
#ifndef GIT_WIN32
|
||||
#define pthread_rwlock_rdunlock pthread_rwlock_unlock
|
||||
#define pthread_rwlock_wrunlock pthread_rwlock_unlock
|
||||
#endif
|
||||
|
||||
|
||||
GIT_INLINE(void) git_atomic_set(git_atomic *a, int val)
|
||||
{
|
||||
#if defined(GIT_WIN32)
|
||||
@ -178,7 +132,7 @@ GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
|
||||
#else
|
||||
|
||||
#define git_thread unsigned int
|
||||
#define git_thread_create(thread, attr, start_routine, arg) 0
|
||||
#define git_thread_create(thread, start_routine, arg) 0
|
||||
#define git_thread_join(id, status) (void)0
|
||||
|
||||
/* Pthreads Mutex */
|
||||
|
@ -114,7 +114,7 @@ static bool challenge_match(git_http_auth_scheme *scheme, void *data)
|
||||
size_t scheme_len;
|
||||
|
||||
scheme_len = strlen(scheme_name);
|
||||
return (strncmp(challenge, scheme_name, scheme_len) == 0 &&
|
||||
return (strncasecmp(challenge, scheme_name, scheme_len) == 0 &&
|
||||
(challenge[scheme_len] == '\0' || challenge[scheme_len] == ' '));
|
||||
}
|
||||
|
||||
@ -569,6 +569,7 @@ static int http_connect(http_subtransport *t)
|
||||
git_stream_close(t->io);
|
||||
git_stream_free(t->io);
|
||||
t->io = NULL;
|
||||
t->connected = 0;
|
||||
}
|
||||
|
||||
if (t->connection_data.use_ssl) {
|
||||
|
@ -433,6 +433,7 @@ int git_pkt_parse_line(
|
||||
* line?
|
||||
*/
|
||||
if (len == PKT_LEN_SIZE) {
|
||||
*head = NULL;
|
||||
*out = line;
|
||||
return 0;
|
||||
}
|
||||
|
@ -759,6 +759,14 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt,
|
||||
line_len -= (line_end - line);
|
||||
line = line_end;
|
||||
|
||||
/* When a valid packet with no content has been
|
||||
* read, git_pkt_parse_line does not report an
|
||||
* error, but the pkt pointer has not been set.
|
||||
* Handle this by skipping over empty packets.
|
||||
*/
|
||||
if (pkt == NULL)
|
||||
continue;
|
||||
|
||||
error = add_push_report_pkt(push, pkt);
|
||||
|
||||
git_pkt_free(pkt);
|
||||
@ -813,6 +821,9 @@ static int parse_report(transport_smart *transport, git_push *push)
|
||||
|
||||
error = 0;
|
||||
|
||||
if (pkt == NULL)
|
||||
continue;
|
||||
|
||||
switch (pkt->type) {
|
||||
case GIT_PKT_DATA:
|
||||
/* This is a sideband packet which contains other packets */
|
||||
|
@ -45,7 +45,7 @@ GIT_INLINE(git_filemode_t) normalize_filemode(git_filemode_t filemode)
|
||||
if (GIT_MODE_TYPE(filemode) == GIT_FILEMODE_COMMIT)
|
||||
return GIT_FILEMODE_COMMIT;
|
||||
|
||||
/* 12XXXX means commit */
|
||||
/* 12XXXX means symlink */
|
||||
if (GIT_MODE_TYPE(filemode) == GIT_FILEMODE_LINK)
|
||||
return GIT_FILEMODE_LINK;
|
||||
|
||||
|
54
src/unix/pthread.h
Normal file
54
src/unix/pthread.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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_unix_pthread_h__
|
||||
#define INCLUDE_unix_pthread_h__
|
||||
|
||||
typedef struct {
|
||||
pthread_t thread;
|
||||
} git_thread;
|
||||
|
||||
#define git_threads_init() (void)0
|
||||
#define git_thread_create(git_thread_ptr, start_routine, arg) \
|
||||
pthread_create(&(git_thread_ptr)->thread, NULL, start_routine, arg)
|
||||
#define git_thread_join(git_thread_ptr, status) \
|
||||
pthread_join((git_thread_ptr)->thread, status)
|
||||
|
||||
/* Git Mutex */
|
||||
#define git_mutex pthread_mutex_t
|
||||
#define git_mutex_init(a) pthread_mutex_init(a, NULL)
|
||||
#define git_mutex_lock(a) pthread_mutex_lock(a)
|
||||
#define git_mutex_unlock(a) pthread_mutex_unlock(a)
|
||||
#define git_mutex_free(a) pthread_mutex_destroy(a)
|
||||
|
||||
/* Git condition vars */
|
||||
#define git_cond pthread_cond_t
|
||||
#define git_cond_init(c) pthread_cond_init(c, NULL)
|
||||
#define git_cond_free(c) pthread_cond_destroy(c)
|
||||
#define git_cond_wait(c, l) pthread_cond_wait(c, l)
|
||||
#define git_cond_signal(c) pthread_cond_signal(c)
|
||||
#define git_cond_broadcast(c) pthread_cond_broadcast(c)
|
||||
|
||||
/* Pthread (-ish) rwlock
|
||||
*
|
||||
* This differs from normal pthreads rwlocks in two ways:
|
||||
* 1. Separate APIs for releasing read locks and write locks (as
|
||||
* opposed to the pure POSIX API which only has one unlock fn)
|
||||
* 2. You should not use recursive read locks (i.e. grabbing a read
|
||||
* lock in a thread that already holds a read lock) because the
|
||||
* Windows implementation doesn't support it
|
||||
*/
|
||||
#define git_rwlock pthread_rwlock_t
|
||||
#define git_rwlock_init(a) pthread_rwlock_init(a, NULL)
|
||||
#define git_rwlock_rdlock(a) pthread_rwlock_rdlock(a)
|
||||
#define git_rwlock_rdunlock(a) pthread_rwlock_unlock(a)
|
||||
#define git_rwlock_wrlock(a) pthread_rwlock_wrlock(a)
|
||||
#define git_rwlock_wrunlock(a) pthread_rwlock_unlock(a)
|
||||
#define git_rwlock_free(a) pthread_rwlock_destroy(a)
|
||||
#define GIT_RWLOCK_STATIC_INIT PTHREAD_RWLOCK_INITIALIZER
|
||||
|
||||
#endif /* INCLUDE_unix_pthread_h__ */
|
@ -122,8 +122,8 @@ int git__strtol64(int64_t *result, const char *nptr, const char **endptr, int ba
|
||||
v = c - 'A' + 10;
|
||||
if (v >= base)
|
||||
break;
|
||||
nn = n*base + v;
|
||||
if (nn < n)
|
||||
nn = n * base + (neg ? -v : v);
|
||||
if ((!neg && nn < n) || (neg && nn > n))
|
||||
ovfl = 1;
|
||||
n = nn;
|
||||
}
|
||||
@ -142,7 +142,7 @@ Return:
|
||||
return -1;
|
||||
}
|
||||
|
||||
*result = neg ? -n : n;
|
||||
*result = n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#ifdef GIT_THREADS
|
||||
#include "win32/pthread.h"
|
||||
#include "win32/thread.h"
|
||||
#endif
|
||||
|
||||
#include "git2.h"
|
||||
|
@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
|
||||
#ifndef GIT_PTHREAD_H
|
||||
#define GIT_PTHREAD_H
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# define GIT_RESTRICT __restrict
|
||||
#else
|
||||
# define GIT_RESTRICT __restrict__
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
HANDLE thread;
|
||||
void *(*proc)(void *);
|
||||
void *param;
|
||||
void *result;
|
||||
} git_win32_thread;
|
||||
|
||||
typedef int pthread_mutexattr_t;
|
||||
typedef int pthread_condattr_t;
|
||||
typedef int pthread_attr_t;
|
||||
typedef int pthread_rwlockattr_t;
|
||||
|
||||
typedef CRITICAL_SECTION pthread_mutex_t;
|
||||
typedef HANDLE pthread_cond_t;
|
||||
|
||||
typedef struct { void *Ptr; } GIT_SRWLOCK;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
GIT_SRWLOCK srwl;
|
||||
CRITICAL_SECTION csec;
|
||||
} native;
|
||||
} pthread_rwlock_t;
|
||||
|
||||
#define PTHREAD_MUTEX_INITIALIZER {(void*)-1}
|
||||
|
||||
int git_win32__thread_create(
|
||||
git_win32_thread *GIT_RESTRICT,
|
||||
const pthread_attr_t *GIT_RESTRICT,
|
||||
void *(*) (void *),
|
||||
void *GIT_RESTRICT);
|
||||
|
||||
int git_win32__thread_join(
|
||||
git_win32_thread *,
|
||||
void **);
|
||||
|
||||
#ifdef GIT_THREADS
|
||||
|
||||
typedef git_win32_thread git_thread;
|
||||
|
||||
#define git_thread_create(git_thread_ptr, attr, start_routine, arg) \
|
||||
git_win32__thread_create(git_thread_ptr, attr, start_routine, arg)
|
||||
#define git_thread_join(git_thread_ptr, status) \
|
||||
git_win32__thread_join(git_thread_ptr, status)
|
||||
|
||||
#endif
|
||||
|
||||
int pthread_mutex_init(
|
||||
pthread_mutex_t *GIT_RESTRICT mutex,
|
||||
const pthread_mutexattr_t *GIT_RESTRICT mutexattr);
|
||||
int pthread_mutex_destroy(pthread_mutex_t *);
|
||||
int pthread_mutex_lock(pthread_mutex_t *);
|
||||
int pthread_mutex_unlock(pthread_mutex_t *);
|
||||
|
||||
int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
|
||||
int pthread_cond_destroy(pthread_cond_t *);
|
||||
int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
|
||||
int pthread_cond_signal(pthread_cond_t *);
|
||||
/* pthread_cond_broadcast is not supported on Win32 yet. */
|
||||
|
||||
int pthread_num_processors_np(void);
|
||||
|
||||
int pthread_rwlock_init(
|
||||
pthread_rwlock_t *GIT_RESTRICT lock,
|
||||
const pthread_rwlockattr_t *GIT_RESTRICT attr);
|
||||
int pthread_rwlock_rdlock(pthread_rwlock_t *);
|
||||
int pthread_rwlock_rdunlock(pthread_rwlock_t *);
|
||||
int pthread_rwlock_wrlock(pthread_rwlock_t *);
|
||||
int pthread_rwlock_wrunlock(pthread_rwlock_t *);
|
||||
int pthread_rwlock_destroy(pthread_rwlock_t *);
|
||||
|
||||
extern int win32_pthread_initialize(void);
|
||||
|
||||
#endif
|
@ -5,18 +5,26 @@
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
|
||||
#include "pthread.h"
|
||||
#include "thread.h"
|
||||
#include "../global.h"
|
||||
|
||||
#define CLEAN_THREAD_EXIT 0x6F012842
|
||||
|
||||
typedef void (WINAPI *win32_srwlock_fn)(GIT_SRWLOCK *);
|
||||
|
||||
static win32_srwlock_fn win32_srwlock_initialize;
|
||||
static win32_srwlock_fn win32_srwlock_acquire_shared;
|
||||
static win32_srwlock_fn win32_srwlock_release_shared;
|
||||
static win32_srwlock_fn win32_srwlock_acquire_exclusive;
|
||||
static win32_srwlock_fn win32_srwlock_release_exclusive;
|
||||
|
||||
/* The thread procedure stub used to invoke the caller's procedure
|
||||
* and capture the return value for later collection. Windows will
|
||||
* only hold a DWORD, but we need to be able to store an entire
|
||||
* void pointer. This requires the indirection. */
|
||||
static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter)
|
||||
{
|
||||
git_win32_thread *thread = lpParameter;
|
||||
git_thread *thread = lpParameter;
|
||||
|
||||
thread->result = thread->proc(thread->param);
|
||||
|
||||
@ -25,14 +33,31 @@ static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter)
|
||||
return CLEAN_THREAD_EXIT;
|
||||
}
|
||||
|
||||
int git_win32__thread_create(
|
||||
git_win32_thread *GIT_RESTRICT thread,
|
||||
const pthread_attr_t *GIT_RESTRICT attr,
|
||||
int git_threads_init(void)
|
||||
{
|
||||
HMODULE hModule = GetModuleHandleW(L"kernel32");
|
||||
|
||||
if (hModule) {
|
||||
win32_srwlock_initialize = (win32_srwlock_fn)
|
||||
GetProcAddress(hModule, "InitializeSRWLock");
|
||||
win32_srwlock_acquire_shared = (win32_srwlock_fn)
|
||||
GetProcAddress(hModule, "AcquireSRWLockShared");
|
||||
win32_srwlock_release_shared = (win32_srwlock_fn)
|
||||
GetProcAddress(hModule, "ReleaseSRWLockShared");
|
||||
win32_srwlock_acquire_exclusive = (win32_srwlock_fn)
|
||||
GetProcAddress(hModule, "AcquireSRWLockExclusive");
|
||||
win32_srwlock_release_exclusive = (win32_srwlock_fn)
|
||||
GetProcAddress(hModule, "ReleaseSRWLockExclusive");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_thread_create(
|
||||
git_thread *GIT_RESTRICT thread,
|
||||
void *(*start_routine)(void*),
|
||||
void *GIT_RESTRICT arg)
|
||||
{
|
||||
GIT_UNUSED(attr);
|
||||
|
||||
thread->result = NULL;
|
||||
thread->param = arg;
|
||||
thread->proc = start_routine;
|
||||
@ -42,8 +67,8 @@ int git_win32__thread_create(
|
||||
return thread->thread ? 0 : -1;
|
||||
}
|
||||
|
||||
int git_win32__thread_join(
|
||||
git_win32_thread *thread,
|
||||
int git_thread_join(
|
||||
git_thread *thread,
|
||||
void **value_ptr)
|
||||
{
|
||||
DWORD exit;
|
||||
@ -70,39 +95,32 @@ int git_win32__thread_join(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_mutex_init(
|
||||
pthread_mutex_t *GIT_RESTRICT mutex,
|
||||
const pthread_mutexattr_t *GIT_RESTRICT mutexattr)
|
||||
int git_mutex_init(git_mutex *GIT_RESTRICT mutex)
|
||||
{
|
||||
GIT_UNUSED(mutexattr);
|
||||
InitializeCriticalSection(mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_mutex_destroy(pthread_mutex_t *mutex)
|
||||
int git_mutex_free(git_mutex *mutex)
|
||||
{
|
||||
DeleteCriticalSection(mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_mutex_lock(pthread_mutex_t *mutex)
|
||||
int git_mutex_lock(git_mutex *mutex)
|
||||
{
|
||||
EnterCriticalSection(mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_mutex_unlock(pthread_mutex_t *mutex)
|
||||
int git_mutex_unlock(git_mutex *mutex)
|
||||
{
|
||||
LeaveCriticalSection(mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
|
||||
int git_cond_init(git_cond *cond)
|
||||
{
|
||||
/* We don't support non-default attributes. */
|
||||
if (attr)
|
||||
return EINVAL;
|
||||
|
||||
/* This is an auto-reset event. */
|
||||
*cond = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
assert(*cond);
|
||||
@ -112,7 +130,7 @@ int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
|
||||
return *cond ? 0 : ENOMEM;
|
||||
}
|
||||
|
||||
int pthread_cond_destroy(pthread_cond_t *cond)
|
||||
int git_cond_free(git_cond *cond)
|
||||
{
|
||||
BOOL closed;
|
||||
|
||||
@ -127,7 +145,7 @@ int pthread_cond_destroy(pthread_cond_t *cond)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
int git_cond_wait(git_cond *cond, git_mutex *mutex)
|
||||
{
|
||||
int error;
|
||||
DWORD wait_result;
|
||||
@ -136,7 +154,7 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
return EINVAL;
|
||||
|
||||
/* The caller must be holding the mutex. */
|
||||
error = pthread_mutex_unlock(mutex);
|
||||
error = git_mutex_unlock(mutex);
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
@ -145,10 +163,10 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
assert(WAIT_OBJECT_0 == wait_result);
|
||||
GIT_UNUSED(wait_result);
|
||||
|
||||
return pthread_mutex_lock(mutex);
|
||||
return git_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
int pthread_cond_signal(pthread_cond_t *cond)
|
||||
int git_cond_signal(git_cond *cond)
|
||||
{
|
||||
BOOL signaled;
|
||||
|
||||
@ -162,36 +180,8 @@ int pthread_cond_signal(pthread_cond_t *cond)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pthread_cond_broadcast is not implemented because doing so with just
|
||||
* Win32 events is quite complicated, and no caller in libgit2 uses it
|
||||
* yet.
|
||||
*/
|
||||
int pthread_num_processors_np(void)
|
||||
int git_rwlock_init(git_rwlock *GIT_RESTRICT lock)
|
||||
{
|
||||
DWORD_PTR p, s;
|
||||
int n = 0;
|
||||
|
||||
if (GetProcessAffinityMask(GetCurrentProcess(), &p, &s))
|
||||
for (; p; p >>= 1)
|
||||
n += p&1;
|
||||
|
||||
return n ? n : 1;
|
||||
}
|
||||
|
||||
typedef void (WINAPI *win32_srwlock_fn)(GIT_SRWLOCK *);
|
||||
|
||||
static win32_srwlock_fn win32_srwlock_initialize;
|
||||
static win32_srwlock_fn win32_srwlock_acquire_shared;
|
||||
static win32_srwlock_fn win32_srwlock_release_shared;
|
||||
static win32_srwlock_fn win32_srwlock_acquire_exclusive;
|
||||
static win32_srwlock_fn win32_srwlock_release_exclusive;
|
||||
|
||||
int pthread_rwlock_init(
|
||||
pthread_rwlock_t *GIT_RESTRICT lock,
|
||||
const pthread_rwlockattr_t *GIT_RESTRICT attr)
|
||||
{
|
||||
GIT_UNUSED(attr);
|
||||
|
||||
if (win32_srwlock_initialize)
|
||||
win32_srwlock_initialize(&lock->native.srwl);
|
||||
else
|
||||
@ -200,7 +190,7 @@ int pthread_rwlock_init(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_rwlock_rdlock(pthread_rwlock_t *lock)
|
||||
int git_rwlock_rdlock(git_rwlock *lock)
|
||||
{
|
||||
if (win32_srwlock_acquire_shared)
|
||||
win32_srwlock_acquire_shared(&lock->native.srwl);
|
||||
@ -210,7 +200,7 @@ int pthread_rwlock_rdlock(pthread_rwlock_t *lock)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_rwlock_rdunlock(pthread_rwlock_t *lock)
|
||||
int git_rwlock_rdunlock(git_rwlock *lock)
|
||||
{
|
||||
if (win32_srwlock_release_shared)
|
||||
win32_srwlock_release_shared(&lock->native.srwl);
|
||||
@ -220,7 +210,7 @@ int pthread_rwlock_rdunlock(pthread_rwlock_t *lock)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_rwlock_wrlock(pthread_rwlock_t *lock)
|
||||
int git_rwlock_wrlock(git_rwlock *lock)
|
||||
{
|
||||
if (win32_srwlock_acquire_exclusive)
|
||||
win32_srwlock_acquire_exclusive(&lock->native.srwl);
|
||||
@ -230,7 +220,7 @@ int pthread_rwlock_wrlock(pthread_rwlock_t *lock)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_rwlock_wrunlock(pthread_rwlock_t *lock)
|
||||
int git_rwlock_wrunlock(git_rwlock *lock)
|
||||
{
|
||||
if (win32_srwlock_release_exclusive)
|
||||
win32_srwlock_release_exclusive(&lock->native.srwl);
|
||||
@ -240,30 +230,10 @@ int pthread_rwlock_wrunlock(pthread_rwlock_t *lock)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_rwlock_destroy(pthread_rwlock_t *lock)
|
||||
int git_rwlock_free(git_rwlock *lock)
|
||||
{
|
||||
if (!win32_srwlock_initialize)
|
||||
DeleteCriticalSection(&lock->native.csec);
|
||||
git__memzero(lock, sizeof(*lock));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int win32_pthread_initialize(void)
|
||||
{
|
||||
HMODULE hModule = GetModuleHandleW(L"kernel32");
|
||||
|
||||
if (hModule) {
|
||||
win32_srwlock_initialize = (win32_srwlock_fn)
|
||||
GetProcAddress(hModule, "InitializeSRWLock");
|
||||
win32_srwlock_acquire_shared = (win32_srwlock_fn)
|
||||
GetProcAddress(hModule, "AcquireSRWLockShared");
|
||||
win32_srwlock_release_shared = (win32_srwlock_fn)
|
||||
GetProcAddress(hModule, "ReleaseSRWLockShared");
|
||||
win32_srwlock_acquire_exclusive = (win32_srwlock_fn)
|
||||
GetProcAddress(hModule, "AcquireSRWLockExclusive");
|
||||
win32_srwlock_release_exclusive = (win32_srwlock_fn)
|
||||
GetProcAddress(hModule, "ReleaseSRWLockExclusive");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
62
src/win32/thread.h
Normal file
62
src/win32/thread.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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_win32_thread_h__
|
||||
#define INCLUDE_win32_thread_h__
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# define GIT_RESTRICT __restrict
|
||||
#else
|
||||
# define GIT_RESTRICT __restrict__
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
HANDLE thread;
|
||||
void *(*proc)(void *);
|
||||
void *param;
|
||||
void *result;
|
||||
} git_thread;
|
||||
|
||||
typedef CRITICAL_SECTION git_mutex;
|
||||
typedef HANDLE git_cond;
|
||||
|
||||
typedef struct { void *Ptr; } GIT_SRWLOCK;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
GIT_SRWLOCK srwl;
|
||||
CRITICAL_SECTION csec;
|
||||
} native;
|
||||
} git_rwlock;
|
||||
|
||||
int git_threads_init(void);
|
||||
|
||||
int git_thread_create(git_thread *GIT_RESTRICT,
|
||||
void *(*) (void *),
|
||||
void *GIT_RESTRICT);
|
||||
int git_thread_join(git_thread *, void **);
|
||||
|
||||
int git_mutex_init(git_mutex *GIT_RESTRICT mutex);
|
||||
int git_mutex_free(git_mutex *);
|
||||
int git_mutex_lock(git_mutex *);
|
||||
int git_mutex_unlock(git_mutex *);
|
||||
|
||||
int git_cond_init(git_cond *);
|
||||
int git_cond_free(git_cond *);
|
||||
int git_cond_wait(git_cond *, git_mutex *);
|
||||
int git_cond_signal(git_cond *);
|
||||
|
||||
int git_rwlock_init(git_rwlock *GIT_RESTRICT lock);
|
||||
int git_rwlock_rdlock(git_rwlock *);
|
||||
int git_rwlock_rdunlock(git_rwlock *);
|
||||
int git_rwlock_wrlock(git_rwlock *);
|
||||
int git_rwlock_wrunlock(git_rwlock *);
|
||||
int git_rwlock_free(git_rwlock *);
|
||||
|
||||
#endif /* INCLUDE_win32_thread_h__ */
|
@ -294,11 +294,12 @@ void test_checkout_index__options_dir_modes(void)
|
||||
(void)p_umask(um = p_umask(022));
|
||||
|
||||
cl_git_pass(p_stat("./testrepo/a", &st));
|
||||
cl_assert_equal_i_fmt(st.st_mode, (GIT_FILEMODE_TREE | 0701) & ~um, "%07o");
|
||||
/* Haiku & Hurd use other mode bits, so we must mask them out */
|
||||
cl_assert_equal_i_fmt(st.st_mode & (S_IFMT | 07777), (GIT_FILEMODE_TREE | 0701) & ~um, "%07o");
|
||||
|
||||
/* File-mode test, since we're on the 'dir' branch */
|
||||
cl_git_pass(p_stat("./testrepo/a/b.txt", &st));
|
||||
cl_assert_equal_i_fmt(st.st_mode, GIT_FILEMODE_BLOB_EXECUTABLE & ~um, "%07o");
|
||||
cl_assert_equal_i_fmt(st.st_mode & (S_IFMT | 07777), GIT_FILEMODE_BLOB_EXECUTABLE & ~um, "%07o");
|
||||
|
||||
git_commit_free(commit);
|
||||
}
|
||||
|
@ -1416,3 +1416,70 @@ void test_checkout_tree__safe_proceeds_if_no_index(void)
|
||||
git_object_free(obj);
|
||||
}
|
||||
|
||||
static int checkout_conflict_count_cb(
|
||||
git_checkout_notify_t why,
|
||||
const char *path,
|
||||
const git_diff_file *b,
|
||||
const git_diff_file *t,
|
||||
const git_diff_file *w,
|
||||
void *payload)
|
||||
{
|
||||
size_t *n = payload;
|
||||
|
||||
GIT_UNUSED(why);
|
||||
GIT_UNUSED(path);
|
||||
GIT_UNUSED(b);
|
||||
GIT_UNUSED(t);
|
||||
GIT_UNUSED(w);
|
||||
|
||||
(*n)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* A repo that has a HEAD (even a properly born HEAD that peels to
|
||||
* a commit) but no index should be treated as if it's an empty baseline
|
||||
*/
|
||||
void test_checkout_tree__baseline_is_empty_when_no_index(void)
|
||||
{
|
||||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||||
git_reference *head;
|
||||
git_object *obj;
|
||||
git_status_list *status;
|
||||
size_t conflicts = 0;
|
||||
|
||||
assert_on_branch(g_repo, "master");
|
||||
cl_git_pass(git_repository_head(&head, g_repo));
|
||||
cl_git_pass(git_reference_peel(&obj, head, GIT_OBJ_COMMIT));
|
||||
|
||||
cl_git_pass(git_reset(g_repo, obj, GIT_RESET_HARD, NULL));
|
||||
|
||||
cl_must_pass(p_unlink("testrepo/.git/index"));
|
||||
|
||||
/* for a safe checkout, we should have checkout conflicts with
|
||||
* the existing untracked files.
|
||||
*/
|
||||
opts.checkout_strategy &= ~GIT_CHECKOUT_FORCE;
|
||||
opts.notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICT;
|
||||
opts.notify_cb = checkout_conflict_count_cb;
|
||||
opts.notify_payload = &conflicts;
|
||||
|
||||
cl_git_fail_with(GIT_ECONFLICT, git_checkout_tree(g_repo, obj, &opts));
|
||||
cl_assert_equal_i(4, conflicts);
|
||||
|
||||
/* but force should succeed and update the index */
|
||||
opts.checkout_strategy |= GIT_CHECKOUT_FORCE;
|
||||
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
|
||||
|
||||
cl_git_pass(git_status_list_new(&status, g_repo, NULL));
|
||||
cl_assert_equal_i(0, git_status_list_entrycount(status));
|
||||
git_status_list_free(status);
|
||||
|
||||
git_object_free(obj);
|
||||
git_reference_free(head);
|
||||
}
|
||||
|
||||
void test_checkout_tree__nullopts(void)
|
||||
{
|
||||
cl_git_pass(git_checkout_tree(g_repo, NULL, NULL));
|
||||
}
|
||||
|
@ -6,6 +6,36 @@
|
||||
|
||||
static git_repository *g_repo = NULL;
|
||||
|
||||
/*
|
||||
From the test repo used for this test:
|
||||
--------------------------------------
|
||||
|
||||
This is a test repo for libgit2 where tree entries have type changes
|
||||
|
||||
The key types that could be found in tree entries are:
|
||||
|
||||
1 - GIT_FILEMODE_NEW = 0000000
|
||||
2 - GIT_FILEMODE_TREE = 0040000
|
||||
3 - GIT_FILEMODE_BLOB = 0100644
|
||||
4 - GIT_FILEMODE_BLOB_EXECUTABLE = 0100755
|
||||
5 - GIT_FILEMODE_LINK = 0120000
|
||||
6 - GIT_FILEMODE_COMMIT = 0160000
|
||||
|
||||
I will try to have every type of transition somewhere in the history
|
||||
of this repo.
|
||||
|
||||
Commits
|
||||
-------
|
||||
Initial commit - a(1) b(1) c(1) d(1) e(1)
|
||||
Create content - a(1->2) b(1->3) c(1->4) d(1->5) e(1->6)
|
||||
Changes #1 - a(2->3) b(3->4) c(4->5) d(5->6) e(6->2)
|
||||
Changes #2 - a(3->5) b(4->6) c(5->2) d(6->3) e(2->4)
|
||||
Changes #3 - a(5->3) b(6->4) c(2->5) d(3->6) e(4->2)
|
||||
Changes #4 - a(3->2) b(4->3) c(5->4) d(6->5) e(2->6)
|
||||
Changes #5 - a(2->1) b(3->1) c(4->1) d(5->1) e(6->1)
|
||||
|
||||
*/
|
||||
|
||||
static const char *g_typechange_oids[] = {
|
||||
"79b9f23e85f55ea36a472a902e875bc1121a94cb",
|
||||
"9bdb75b73836a99e3dbeea640a81de81031fdc29",
|
||||
@ -21,6 +51,14 @@ static bool g_typechange_empty[] = {
|
||||
true, false, false, false, false, false, true, true
|
||||
};
|
||||
|
||||
static const int g_typechange_expected_conflicts[] = {
|
||||
1, 2, 3, 3, 2, 3, 2
|
||||
};
|
||||
|
||||
static const int g_typechange_expected_untracked[] = {
|
||||
6, 4, 3, 2, 3, 2, 5
|
||||
};
|
||||
|
||||
void test_checkout_typechange__initialize(void)
|
||||
{
|
||||
g_repo = cl_git_sandbox_init("typechanges");
|
||||
@ -112,12 +150,7 @@ void test_checkout_typechange__checkout_typechanges_safe(void)
|
||||
for (i = 0; g_typechange_oids[i] != NULL; ++i) {
|
||||
cl_git_pass(git_revparse_single(&obj, g_repo, g_typechange_oids[i]));
|
||||
|
||||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||||
|
||||
/* There are bugs in some submodule->tree changes that prevent
|
||||
* SAFE from passing here, even though the following should work:
|
||||
*/
|
||||
/* !i ? GIT_CHECKOUT_FORCE : GIT_CHECKOUT_SAFE; */
|
||||
opts.checkout_strategy = !i ? GIT_CHECKOUT_FORCE : GIT_CHECKOUT_SAFE;
|
||||
|
||||
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
|
||||
|
||||
@ -190,6 +223,38 @@ static void force_create_file(const char *file)
|
||||
cl_git_rewritefile(file, "yowza!!");
|
||||
}
|
||||
|
||||
static int make_submodule_dirty(git_submodule *sm, const char *name, void *payload)
|
||||
{
|
||||
git_buf submodulepath = GIT_BUF_INIT;
|
||||
git_buf dirtypath = GIT_BUF_INIT;
|
||||
git_repository *submodule_repo;
|
||||
|
||||
GIT_UNUSED(name);
|
||||
GIT_UNUSED(payload);
|
||||
|
||||
/* remove submodule directory in preparation for init and repo_init */
|
||||
cl_git_pass(git_buf_joinpath(
|
||||
&submodulepath,
|
||||
git_repository_workdir(g_repo),
|
||||
git_submodule_path(sm)
|
||||
));
|
||||
git_futils_rmdir_r(git_buf_cstr(&submodulepath), NULL, GIT_RMDIR_REMOVE_FILES);
|
||||
|
||||
/* initialize submodule's repository */
|
||||
cl_git_pass(git_submodule_repo_init(&submodule_repo, sm, 0));
|
||||
|
||||
/* create a file in the submodule workdir to make it dirty */
|
||||
cl_git_pass(
|
||||
git_buf_joinpath(&dirtypath, git_repository_workdir(submodule_repo), "dirty"));
|
||||
force_create_file(git_buf_cstr(&dirtypath));
|
||||
|
||||
git_buf_free(&dirtypath);
|
||||
git_buf_free(&submodulepath);
|
||||
git_repository_free(submodule_repo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_checkout_typechange__checkout_with_conflicts(void)
|
||||
{
|
||||
int i;
|
||||
@ -211,13 +276,17 @@ void test_checkout_typechange__checkout_with_conflicts(void)
|
||||
git_futils_rmdir_r("typechanges/d", NULL, GIT_RMDIR_REMOVE_FILES);
|
||||
p_mkdir("typechanges/d", 0777); /* intentionally empty dir */
|
||||
force_create_file("typechanges/untracked");
|
||||
cl_git_pass(git_submodule_foreach(g_repo, make_submodule_dirty, NULL));
|
||||
|
||||
opts.checkout_strategy = GIT_CHECKOUT_SAFE;
|
||||
memset(&cts, 0, sizeof(cts));
|
||||
|
||||
cl_git_fail(git_checkout_tree(g_repo, obj, &opts));
|
||||
cl_assert(cts.conflicts > 0);
|
||||
cl_assert(cts.untracked > 0);
|
||||
cl_assert_equal_i(cts.conflicts, g_typechange_expected_conflicts[i]);
|
||||
cl_assert_equal_i(cts.untracked, g_typechange_expected_untracked[i]);
|
||||
cl_assert_equal_i(cts.dirty, 0);
|
||||
cl_assert_equal_i(cts.updates, 0);
|
||||
cl_assert_equal_i(cts.ignored, 0);
|
||||
|
||||
opts.checkout_strategy =
|
||||
GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED;
|
||||
|
@ -33,5 +33,13 @@ void test_core_strtol__int64(void)
|
||||
cl_assert(i == 2147483657LL);
|
||||
cl_git_pass(git__strtol64(&i, " -2147483657 ", NULL, 10));
|
||||
cl_assert(i == -2147483657LL);
|
||||
cl_git_pass(git__strtol64(&i, " 9223372036854775807 ", NULL, 10));
|
||||
cl_assert(i == INT64_MAX);
|
||||
cl_git_pass(git__strtol64(&i, " -9223372036854775808 ", NULL, 10));
|
||||
cl_assert(i == INT64_MIN);
|
||||
cl_git_pass(git__strtol64(&i, " 0x7fffffffffffffff ", NULL, 16));
|
||||
cl_assert(i == INT64_MAX);
|
||||
cl_git_pass(git__strtol64(&i, " -0x8000000000000000 ", NULL, 16));
|
||||
cl_assert(i == INT64_MIN);
|
||||
}
|
||||
|
||||
|
@ -2,105 +2,103 @@
|
||||
#include "git2/repository.h"
|
||||
#include "git2/index.h"
|
||||
|
||||
git_repository *repo = NULL;
|
||||
static git_repository *g_repo;
|
||||
static git_odb *g_odb;
|
||||
static git_index *g_index;
|
||||
static git_oid g_empty_id;
|
||||
|
||||
void test_index_collision__initialize(void)
|
||||
{
|
||||
g_repo = cl_git_sandbox_init("empty_standard_repo");
|
||||
cl_git_pass(git_repository_odb(&g_odb, g_repo));
|
||||
cl_git_pass(git_repository_index(&g_index, g_repo));
|
||||
|
||||
cl_git_pass(git_odb_write(&g_empty_id, g_odb, "", 0, GIT_OBJ_BLOB));
|
||||
}
|
||||
|
||||
void test_index_collision__cleanup(void)
|
||||
{
|
||||
git_index_free(g_index);
|
||||
git_odb_free(g_odb);
|
||||
cl_git_sandbox_cleanup();
|
||||
repo = NULL;
|
||||
}
|
||||
|
||||
void test_index_collision__add(void)
|
||||
{
|
||||
git_index *index;
|
||||
git_index_entry entry;
|
||||
git_oid tree_id;
|
||||
git_tree *tree;
|
||||
|
||||
repo = cl_git_sandbox_init("empty_standard_repo");
|
||||
cl_git_pass(git_repository_index(&index, repo));
|
||||
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
entry.ctime.seconds = 12346789;
|
||||
entry.mtime.seconds = 12346789;
|
||||
entry.mode = 0100644;
|
||||
entry.file_size = 0;
|
||||
git_oid_fromstr(&entry.id, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391");
|
||||
git_oid_cpy(&entry.id, &g_empty_id);
|
||||
|
||||
entry.path = "a/b";
|
||||
cl_git_pass(git_index_add(index, &entry));
|
||||
cl_git_pass(git_index_add(g_index, &entry));
|
||||
|
||||
/* create a tree/blob collision */
|
||||
entry.path = "a/b/c";
|
||||
cl_git_fail(git_index_add(index, &entry));
|
||||
cl_git_fail(git_index_add(g_index, &entry));
|
||||
|
||||
cl_git_pass(git_index_write_tree(&tree_id, index));
|
||||
cl_git_pass(git_tree_lookup(&tree, repo, &tree_id));
|
||||
cl_git_pass(git_index_write_tree(&tree_id, g_index));
|
||||
cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id));
|
||||
|
||||
git_tree_free(tree);
|
||||
git_index_free(index);
|
||||
}
|
||||
|
||||
void test_index_collision__add_with_highstage_1(void)
|
||||
{
|
||||
git_index *index;
|
||||
git_index_entry entry;
|
||||
|
||||
repo = cl_git_sandbox_init("empty_standard_repo");
|
||||
cl_git_pass(git_repository_index(&index, repo));
|
||||
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
entry.ctime.seconds = 12346789;
|
||||
entry.mtime.seconds = 12346789;
|
||||
entry.mode = 0100644;
|
||||
entry.file_size = 0;
|
||||
git_oid_fromstr(&entry.id, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391");
|
||||
git_oid_cpy(&entry.id, &g_empty_id);
|
||||
|
||||
entry.path = "a/b";
|
||||
GIT_IDXENTRY_STAGE_SET(&entry, 2);
|
||||
cl_git_pass(git_index_add(index, &entry));
|
||||
cl_git_pass(git_index_add(g_index, &entry));
|
||||
|
||||
/* create a blob beneath the previous tree entry */
|
||||
entry.path = "a/b/c";
|
||||
entry.flags = 0;
|
||||
cl_git_pass(git_index_add(index, &entry));
|
||||
cl_git_pass(git_index_add(g_index, &entry));
|
||||
|
||||
/* create another tree entry above the blob */
|
||||
entry.path = "a/b";
|
||||
GIT_IDXENTRY_STAGE_SET(&entry, 1);
|
||||
cl_git_pass(git_index_add(index, &entry));
|
||||
|
||||
git_index_free(index);
|
||||
cl_git_pass(git_index_add(g_index, &entry));
|
||||
}
|
||||
|
||||
void test_index_collision__add_with_highstage_2(void)
|
||||
{
|
||||
git_index *index;
|
||||
git_index_entry entry;
|
||||
|
||||
repo = cl_git_sandbox_init("empty_standard_repo");
|
||||
cl_git_pass(git_repository_index(&index, repo));
|
||||
cl_git_pass(git_repository_index(&g_index, g_repo));
|
||||
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
entry.ctime.seconds = 12346789;
|
||||
entry.mtime.seconds = 12346789;
|
||||
entry.mode = 0100644;
|
||||
entry.file_size = 0;
|
||||
git_oid_fromstr(&entry.id, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391");
|
||||
git_oid_cpy(&entry.id, &g_empty_id);
|
||||
|
||||
entry.path = "a/b/c";
|
||||
GIT_IDXENTRY_STAGE_SET(&entry, 1);
|
||||
cl_git_pass(git_index_add(index, &entry));
|
||||
cl_git_pass(git_index_add(g_index, &entry));
|
||||
|
||||
/* create a blob beneath the previous tree entry */
|
||||
entry.path = "a/b/c";
|
||||
GIT_IDXENTRY_STAGE_SET(&entry, 2);
|
||||
cl_git_pass(git_index_add(index, &entry));
|
||||
cl_git_pass(git_index_add(g_index, &entry));
|
||||
|
||||
/* create another tree entry above the blob */
|
||||
entry.path = "a/b";
|
||||
GIT_IDXENTRY_STAGE_SET(&entry, 3);
|
||||
cl_git_pass(git_index_add(index, &entry));
|
||||
|
||||
git_index_free(index);
|
||||
cl_git_pass(git_index_add(g_index, &entry));
|
||||
}
|
||||
|
@ -71,3 +71,58 @@ void test_index_read_index__maintains_stat_cache(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool roundtrip_with_read_index(const char *tree_idstr)
|
||||
{
|
||||
git_oid tree_id, new_tree_id;
|
||||
git_tree *tree;
|
||||
git_index *tree_index;
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&tree_id, tree_idstr));
|
||||
cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id));
|
||||
cl_git_pass(git_index_new(&tree_index));
|
||||
cl_git_pass(git_index_read_tree(tree_index, tree));
|
||||
cl_git_pass(git_index_read_index(_index, tree_index));
|
||||
cl_git_pass(git_index_write_tree(&new_tree_id, _index));
|
||||
|
||||
git_tree_free(tree);
|
||||
git_index_free(tree_index);
|
||||
|
||||
return git_oid_equal(&tree_id, &new_tree_id);
|
||||
}
|
||||
|
||||
void test_index_read_index__produces_treesame_indexes(void)
|
||||
{
|
||||
roundtrip_with_read_index("53fc32d17276939fc79ed05badaef2db09990016");
|
||||
roundtrip_with_read_index("944c0f6e4dfa41595e6eb3ceecdb14f50fe18162");
|
||||
roundtrip_with_read_index("1810dff58d8a660512d4832e740f692884338ccd");
|
||||
roundtrip_with_read_index("d52a8fe84ceedf260afe4f0287bbfca04a117e83");
|
||||
roundtrip_with_read_index("c36d8ea75da8cb510fcb0c408c1d7e53f9a99dbe");
|
||||
roundtrip_with_read_index("7b2417a23b63e1fdde88c80e14b33247c6e5785a");
|
||||
roundtrip_with_read_index("f82a8eb4cb20e88d1030fd10d89286215a715396");
|
||||
roundtrip_with_read_index("fd093bff70906175335656e6ce6ae05783708765");
|
||||
roundtrip_with_read_index("ae90f12eea699729ed24555e40b9fd669da12a12");
|
||||
}
|
||||
|
||||
void test_index_read_index__read_and_writes(void)
|
||||
{
|
||||
git_oid tree_id, new_tree_id;
|
||||
git_tree *tree;
|
||||
git_index *tree_index, *new_index;
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&tree_id, "ae90f12eea699729ed24555e40b9fd669da12a12"));
|
||||
cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id));
|
||||
cl_git_pass(git_index_new(&tree_index));
|
||||
cl_git_pass(git_index_read_tree(tree_index, tree));
|
||||
cl_git_pass(git_index_read_index(_index, tree_index));
|
||||
cl_git_pass(git_index_write(_index));
|
||||
|
||||
cl_git_pass(git_index_open(&new_index, git_index_path(_index)));
|
||||
cl_git_pass(git_index_write_tree_to(&new_tree_id, new_index, _repo));
|
||||
|
||||
cl_assert_equal_oid(&tree_id, &new_tree_id);
|
||||
|
||||
git_tree_free(tree);
|
||||
git_index_free(tree_index);
|
||||
git_index_free(new_index);
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ void test_object_cache__threadmania(void)
|
||||
fn = (th & 1) ? cache_parsed : cache_raw;
|
||||
|
||||
#ifdef GIT_THREADS
|
||||
cl_git_pass(git_thread_create(&t[th], NULL, fn, data));
|
||||
cl_git_pass(git_thread_create(&t[th], fn, data));
|
||||
#else
|
||||
cl_assert(fn(data) == data);
|
||||
git__free(data);
|
||||
@ -267,7 +267,7 @@ void test_object_cache__fast_thread_rush(void)
|
||||
data[th] = th;
|
||||
#ifdef GIT_THREADS
|
||||
cl_git_pass(
|
||||
git_thread_create(&t[th], NULL, cache_quick, &data[th]));
|
||||
git_thread_create(&t[th], cache_quick, &data[th]));
|
||||
#else
|
||||
cl_assert(cache_quick(&data[th]) == &data[th]);
|
||||
#endif
|
||||
|
@ -140,3 +140,40 @@ void test_object_tag_read__without_tagger_nor_message(void)
|
||||
git_tag_free(tag);
|
||||
git_repository_free(repo);
|
||||
}
|
||||
|
||||
static const char *silly_tag = "object c054ccaefbf2da31c3b19178f9e3ef20a3867924\n\
|
||||
type commit\n\
|
||||
tag v1_0_1\n\
|
||||
tagger Jamis Buck <jamis@37signals.com> 1107717917\n\
|
||||
diff --git a/lib/sqlite3/version.rb b/lib/sqlite3/version.rb\n\
|
||||
index 0b3bf69..4ee8fc2 100644\n\
|
||||
--- a/lib/sqlite3/version.rb\n\
|
||||
+++ b/lib/sqlite3/version.rb\n\
|
||||
@@ -36,7 +36,7 @@ module SQLite3\n\
|
||||
\n\
|
||||
MAJOR = 1\n\
|
||||
MINOR = 0\n\
|
||||
- TINY = 0\n\
|
||||
+ TINY = 1\n\
|
||||
\n\
|
||||
STRING = [ MAJOR, MINOR, TINY ].join( \".\" )\n\
|
||||
\n\
|
||||
-0600\n\
|
||||
\n\
|
||||
v1_0_1 release\n";
|
||||
|
||||
void test_object_tag_read__extra_header_fields(void)
|
||||
{
|
||||
git_tag *tag;
|
||||
git_odb *odb;
|
||||
git_oid id;
|
||||
|
||||
cl_git_pass(git_repository_odb__weakptr(&odb, g_repo));
|
||||
|
||||
cl_git_pass(git_odb_write(&id, odb, silly_tag, strlen(silly_tag), GIT_OBJ_TAG));
|
||||
cl_git_pass(git_tag_lookup(&tag, g_repo, &id));
|
||||
|
||||
cl_assert_equal_s("v1_0_1 release\n", git_tag_message(tag));
|
||||
|
||||
git_tag_free(tag);
|
||||
}
|
||||
|
@ -2,29 +2,33 @@
|
||||
#include "odb.h"
|
||||
#include "filebuf.h"
|
||||
|
||||
#define TEST_REPO_PATH "redundant.git"
|
||||
|
||||
git_repository *g_repo;
|
||||
git_odb *g_odb;
|
||||
|
||||
void test_odb_emptyobjects__initialize(void)
|
||||
{
|
||||
cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git")));
|
||||
}
|
||||
void test_odb_emptyobjects__cleanup(void)
|
||||
{
|
||||
git_repository_free(g_repo);
|
||||
g_repo = cl_git_sandbox_init(TEST_REPO_PATH);
|
||||
cl_git_pass(git_repository_odb(&g_odb, g_repo));
|
||||
}
|
||||
|
||||
void test_odb_emptyobjects__read(void)
|
||||
void test_odb_emptyobjects__cleanup(void)
|
||||
{
|
||||
git_oid id;
|
||||
git_odb_free(g_odb);
|
||||
cl_git_sandbox_cleanup();
|
||||
}
|
||||
|
||||
void test_odb_emptyobjects__blob_notfound(void)
|
||||
{
|
||||
git_oid id, written_id;
|
||||
git_blob *blob;
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&id, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"));
|
||||
cl_git_pass(git_blob_lookup(&blob, g_repo, &id));
|
||||
cl_assert_equal_i(GIT_OBJ_BLOB, git_object_type((git_object *) blob));
|
||||
cl_assert(git_blob_rawcontent(blob));
|
||||
cl_assert_equal_s("", git_blob_rawcontent(blob));
|
||||
cl_assert_equal_i(0, git_blob_rawsize(blob));
|
||||
git_blob_free(blob);
|
||||
cl_git_fail_with(GIT_ENOTFOUND, git_blob_lookup(&blob, g_repo, &id));
|
||||
|
||||
cl_git_pass(git_odb_write(&written_id, g_odb, "", 0, GIT_OBJ_BLOB));
|
||||
cl_assert(git_path_exists(TEST_REPO_PATH "/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391"));
|
||||
}
|
||||
|
||||
void test_odb_emptyobjects__read_tree(void)
|
||||
@ -43,15 +47,12 @@ void test_odb_emptyobjects__read_tree(void)
|
||||
void test_odb_emptyobjects__read_tree_odb(void)
|
||||
{
|
||||
git_oid id;
|
||||
git_odb *odb;
|
||||
git_odb_object *tree_odb;
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&id, "4b825dc642cb6eb9a060e54bf8d69288fbee4904"));
|
||||
cl_git_pass(git_repository_odb(&odb, g_repo));
|
||||
cl_git_pass(git_odb_read(&tree_odb, odb, &id));
|
||||
cl_git_pass(git_odb_read(&tree_odb, g_odb, &id));
|
||||
cl_assert(git_odb_object_data(tree_odb));
|
||||
cl_assert_equal_s("", git_odb_object_data(tree_odb));
|
||||
cl_assert_equal_i(0, git_odb_object_size(tree_odb));
|
||||
git_odb_object_free(tree_odb);
|
||||
git_odb_free(odb);
|
||||
}
|
||||
|
@ -35,6 +35,19 @@ static void fetchhead_test_clone(void)
|
||||
cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
|
||||
}
|
||||
|
||||
static int count_references(void)
|
||||
{
|
||||
git_strarray array;
|
||||
int refs;
|
||||
|
||||
cl_git_pass(git_reference_list(&array, g_repo));
|
||||
refs = array.count;
|
||||
|
||||
git_strarray_free(&array);
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
||||
static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fetchhead)
|
||||
{
|
||||
git_remote *remote;
|
||||
@ -101,3 +114,41 @@ void test_online_fetchhead__no_merges(void)
|
||||
cl_git_pass(git_tag_delete(g_repo, "commit_tree"));
|
||||
fetchhead_test_fetch(NULL, FETCH_HEAD_NO_MERGE_DATA3);
|
||||
}
|
||||
|
||||
void test_online_fetchhead__explicit_dst_refspec_creates_branch(void)
|
||||
{
|
||||
git_reference *ref;
|
||||
int refs;
|
||||
|
||||
fetchhead_test_clone();
|
||||
refs = count_references();
|
||||
fetchhead_test_fetch("refs/heads/first-merge:refs/heads/explicit-refspec", FETCH_HEAD_EXPLICIT_DATA);
|
||||
|
||||
cl_git_pass(git_branch_lookup(&ref, g_repo, "explicit-refspec", GIT_BRANCH_ALL));
|
||||
cl_assert_equal_i(refs + 1, count_references());
|
||||
}
|
||||
|
||||
void test_online_fetchhead__empty_dst_refspec_creates_no_branch(void)
|
||||
{
|
||||
git_reference *ref;
|
||||
int refs;
|
||||
|
||||
fetchhead_test_clone();
|
||||
refs = count_references();
|
||||
|
||||
fetchhead_test_fetch("refs/heads/first-merge", FETCH_HEAD_EXPLICIT_DATA);
|
||||
cl_git_fail(git_branch_lookup(&ref, g_repo, "first-merge", GIT_BRANCH_ALL));
|
||||
|
||||
cl_assert_equal_i(refs, count_references());
|
||||
}
|
||||
|
||||
void test_online_fetchhead__colon_only_dst_refspec_creates_no_branch(void)
|
||||
{
|
||||
int refs;
|
||||
|
||||
fetchhead_test_clone();
|
||||
refs = count_references();
|
||||
fetchhead_test_fetch("refs/heads/first-merge:", FETCH_HEAD_EXPLICIT_DATA);
|
||||
|
||||
cl_assert_equal_i(refs, count_references());
|
||||
}
|
||||
|
@ -118,12 +118,22 @@ void test_repo_discover__0(void)
|
||||
cl_git_fail(git_repository_discover(&found_path, ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs));
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs));
|
||||
|
||||
append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER_SUB);
|
||||
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
|
||||
|
||||
/* this must pass as ceiling_directories cannot prevent the current
|
||||
* working directory to be checked */
|
||||
ensure_repository_discover(SUB_REPOSITORY_FOLDER, ceiling_dirs, &sub_repository_path);
|
||||
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, &sub_repository_path);
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));
|
||||
|
||||
append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER);
|
||||
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
|
||||
|
||||
//this must pass as ceiling_directories cannot predent the current
|
||||
//working directory to be checked
|
||||
cl_git_pass(git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
|
||||
ensure_repository_discover(SUB_REPOSITORY_FOLDER, ceiling_dirs, &sub_repository_path);
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs));
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));
|
||||
|
@ -196,8 +196,9 @@ void test_repo_open__failures(void)
|
||||
&repo, "attr/sub", GIT_REPOSITORY_OPEN_NO_SEARCH, NULL));
|
||||
|
||||
/* fail with ceiling too low */
|
||||
cl_git_pass(git_buf_joinpath(&ceiling, ceiling.ptr, "sub"));
|
||||
cl_git_fail(git_repository_open_ext(&repo, "attr/sub", 0, ceiling.ptr));
|
||||
cl_git_pass(git_buf_joinpath(&ceiling, ceiling.ptr, "sub"));
|
||||
cl_git_fail(git_repository_open_ext(&repo, "attr/sub/sub", 0, ceiling.ptr));
|
||||
|
||||
/* fail with no repo */
|
||||
cl_git_pass(p_mkdir("alternate", 0777));
|
||||
|
@ -240,14 +240,18 @@ void test_reset_hard__switch_file_to_dir(void)
|
||||
{
|
||||
git_index_entry entry = {{ 0 }};
|
||||
git_index *idx;
|
||||
git_odb *odb;
|
||||
git_object *commit;
|
||||
git_tree *tree;
|
||||
git_signature *sig;
|
||||
git_oid src_tree_id, tgt_tree_id;
|
||||
git_oid src_id, tgt_id;
|
||||
|
||||
cl_git_pass(git_repository_odb(&odb, repo));
|
||||
cl_git_pass(git_odb_write(&entry.id, odb, "", 0, GIT_OBJ_BLOB));
|
||||
git_odb_free(odb);
|
||||
|
||||
entry.mode = GIT_FILEMODE_BLOB;
|
||||
cl_git_pass(git_oid_fromstr(&entry.id, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"));
|
||||
cl_git_pass(git_index_new(&idx));
|
||||
cl_git_pass(git_signature_now(&sig, "foo", "bar"));
|
||||
|
||||
|
@ -945,6 +945,44 @@ void test_status_ignore__negative_directory_ignores(void)
|
||||
assert_is_ignored("padded_parent/child8/bar.txt");
|
||||
}
|
||||
|
||||
void test_status_ignore__unignore_entry_in_ignored_dir(void)
|
||||
{
|
||||
static const char *test_files[] = {
|
||||
"empty_standard_repo/bar.txt",
|
||||
"empty_standard_repo/parent/bar.txt",
|
||||
"empty_standard_repo/parent/child/bar.txt",
|
||||
"empty_standard_repo/nested/parent/child/bar.txt",
|
||||
NULL
|
||||
};
|
||||
|
||||
make_test_data("empty_standard_repo", test_files);
|
||||
cl_git_mkfile(
|
||||
"empty_standard_repo/.gitignore",
|
||||
"bar.txt\n"
|
||||
"!parent/child/bar.txt\n");
|
||||
|
||||
assert_is_ignored("bar.txt");
|
||||
assert_is_ignored("parent/bar.txt");
|
||||
refute_is_ignored("parent/child/bar.txt");
|
||||
assert_is_ignored("nested/parent/child/bar.txt");
|
||||
}
|
||||
|
||||
void test_status_ignore__do_not_unignore_basename_prefix(void)
|
||||
{
|
||||
static const char *test_files[] = {
|
||||
"empty_standard_repo/foo_bar.txt",
|
||||
NULL
|
||||
};
|
||||
|
||||
make_test_data("empty_standard_repo", test_files);
|
||||
cl_git_mkfile(
|
||||
"empty_standard_repo/.gitignore",
|
||||
"foo_bar.txt\n"
|
||||
"!bar.txt\n");
|
||||
|
||||
assert_is_ignored("foo_bar.txt");
|
||||
}
|
||||
|
||||
void test_status_ignore__filename_with_cr(void)
|
||||
{
|
||||
int ignored;
|
||||
|
@ -75,7 +75,7 @@ void test_threads_refdb__iterator(void)
|
||||
for (t = 0; t < THREADS; ++t) {
|
||||
id[t] = t;
|
||||
#ifdef GIT_THREADS
|
||||
cl_git_pass(git_thread_create(&th[t], NULL, iterate_refs, &id[t]));
|
||||
cl_git_pass(git_thread_create(&th[t], iterate_refs, &id[t]));
|
||||
#else
|
||||
th[t] = t;
|
||||
iterate_refs(&id[t]);
|
||||
@ -196,7 +196,7 @@ void test_threads_refdb__edit_while_iterate(void)
|
||||
* for now by just running on a single thread...
|
||||
*/
|
||||
/* #ifdef GIT_THREADS */
|
||||
/* cl_git_pass(git_thread_create(&th[t], NULL, fn, &id[t])); */
|
||||
/* cl_git_pass(git_thread_create(&th[t], fn, &id[t])); */
|
||||
/* #else */
|
||||
fn(&id[t]);
|
||||
/* #endif */
|
||||
@ -211,7 +211,7 @@ void test_threads_refdb__edit_while_iterate(void)
|
||||
|
||||
for (t = 0; t < THREADS; ++t) {
|
||||
id[t] = t;
|
||||
cl_git_pass(git_thread_create(&th[t], NULL, iterate_refs, &id[t]));
|
||||
cl_git_pass(git_thread_create(&th[t], iterate_refs, &id[t]));
|
||||
}
|
||||
|
||||
for (t = 0; t < THREADS; ++t) {
|
||||
|
@ -24,7 +24,7 @@ void run_in_parallel(
|
||||
for (t = 0; t < threads; ++t) {
|
||||
id[t] = t;
|
||||
#ifdef GIT_THREADS
|
||||
cl_git_pass(git_thread_create(&th[t], NULL, func, &id[t]));
|
||||
cl_git_pass(git_thread_create(&th[t], func, &id[t]));
|
||||
#else
|
||||
cl_assert(func(&id[t]) == &id[t]);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user