Unverified Commit 8d1b36a6 by Edward Thomson Committed by GitHub

Merge pull request #4942 from libgit2/ethomson/v0.27.8

Release v0.27.8
parents 313440c3 703885a8
v0.27.8
-------
This is a bugfix release with the following change:
- Negative gitignore rules should match git's behavior. For example,
given a gitignore rule of `*.test` and a second gitignore rule of
`!dir/*`, we would incorrect apply the negation rules. With this
fix, we behave like git.
- Always provide custom transport implementations with the URL in the
action function. v0.27.7 included a change that would erroneously
provide NULL to subsequent calls to the action function. This is
fixed.
- Fix several bugs parsing malformed commits and malformed trees.
- Allow configuration file directory locations to be specified as
`/dev/null`.
- Ensure that when an error occurs reading from the loose ODB backend
that we do not segfault.
- Ensure that when a filter stream application fails that we do not
segfault.
- Ensure that any configuration reading failures are propagated while
loading submodule information.
- Peel annotated tags fully when creating an annotated commit.
- Ensure that numbers are parsed correctly in a variety of places.
v0.27.7 v0.27.7
------- -------
......
...@@ -710,7 +710,7 @@ GIT_EXTERN(int) git_reference_normalize_name( ...@@ -710,7 +710,7 @@ GIT_EXTERN(int) git_reference_normalize_name(
*/ */
GIT_EXTERN(int) git_reference_peel( GIT_EXTERN(int) git_reference_peel(
git_object **out, git_object **out,
git_reference *ref, const git_reference *ref,
git_otype type); git_otype type);
/** /**
......
...@@ -7,10 +7,10 @@ ...@@ -7,10 +7,10 @@
#ifndef INCLUDE_git_version_h__ #ifndef INCLUDE_git_version_h__
#define INCLUDE_git_version_h__ #define INCLUDE_git_version_h__
#define LIBGIT2_VERSION "0.27.7" #define LIBGIT2_VERSION "0.27.8"
#define LIBGIT2_VER_MAJOR 0 #define LIBGIT2_VER_MAJOR 0
#define LIBGIT2_VER_MINOR 27 #define LIBGIT2_VER_MINOR 27
#define LIBGIT2_VER_REVISION 7 #define LIBGIT2_VER_REVISION 8
#define LIBGIT2_VER_PATCH 0 #define LIBGIT2_VER_PATCH 0
#define LIBGIT2_SOVERSION 27 #define LIBGIT2_SOVERSION 27
......
...@@ -123,19 +123,19 @@ int git_annotated_commit_from_ref( ...@@ -123,19 +123,19 @@ int git_annotated_commit_from_ref(
git_repository *repo, git_repository *repo,
const git_reference *ref) const git_reference *ref)
{ {
git_reference *resolved; git_object *peeled;
int error = 0; int error = 0;
assert(out && repo && ref); assert(out && repo && ref);
*out = NULL; *out = NULL;
if ((error = git_reference_resolve(&resolved, ref)) < 0) if ((error = git_reference_peel(&peeled, ref, GIT_OBJ_COMMIT)) < 0)
return error; return error;
error = annotated_commit_init_from_id(out, error = annotated_commit_init_from_id(out,
repo, repo,
git_reference_target(resolved), git_object_id(peeled),
git_reference_name(ref)); git_reference_name(ref));
if (!error) { if (!error) {
...@@ -143,7 +143,7 @@ int git_annotated_commit_from_ref( ...@@ -143,7 +143,7 @@ int git_annotated_commit_from_ref(
GITERR_CHECK_ALLOC((*out)->ref_name); GITERR_CHECK_ALLOC((*out)->ref_name);
} }
git_reference_free(resolved); git_object_free(peeled);
return error; return error;
} }
......
...@@ -312,8 +312,9 @@ static int apply_binary( ...@@ -312,8 +312,9 @@ static int apply_binary(
&patch->binary.old_file)) < 0) &patch->binary.old_file)) < 0)
goto done; goto done;
/* Verify that the resulting file with the reverse patch applied matches the source file */
if (source_len != reverse.size || if (source_len != reverse.size ||
memcmp(source, reverse.ptr, source_len) != 0) { (source_len && memcmp(source, reverse.ptr, source_len) != 0)) {
error = apply_err("binary patch did not apply cleanly"); error = apply_err("binary patch did not apply cleanly");
goto done; goto done;
} }
......
...@@ -594,8 +594,9 @@ int git_attr_fnmatch__parse( ...@@ -594,8 +594,9 @@ int git_attr_fnmatch__parse(
} }
if (*pattern == '!' && (spec->flags & GIT_ATTR_FNMATCH_ALLOWNEG) != 0) { if (*pattern == '!' && (spec->flags & GIT_ATTR_FNMATCH_ALLOWNEG) != 0) {
spec->flags = spec->flags | spec->flags = spec->flags | GIT_ATTR_FNMATCH_NEGATIVE;
GIT_ATTR_FNMATCH_NEGATIVE | GIT_ATTR_FNMATCH_LEADINGDIR; if ((spec->flags & GIT_ATTR_FNMATCH_NOLEADINGDIR) == 0)
spec->flags |= GIT_ATTR_FNMATCH_LEADINGDIR;
pattern++; pattern++;
} }
......
...@@ -419,7 +419,7 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj) ...@@ -419,7 +419,7 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
return -1; return -1;
/* Some tools create multiple author fields, ignore the extra ones */ /* Some tools create multiple author fields, ignore the extra ones */
while ((size_t)(buffer_end - buffer) >= strlen("author ") && !git__prefixcmp(buffer, "author ")) { while (!git__prefixncmp(buffer, buffer_end - buffer, "author ")) {
if (git_signature__parse(&dummy_sig, &buffer, buffer_end, "author ", '\n') < 0) if (git_signature__parse(&dummy_sig, &buffer, buffer_end, "author ", '\n') < 0)
return -1; return -1;
......
...@@ -109,7 +109,7 @@ int git_config_add_file_ondisk( ...@@ -109,7 +109,7 @@ int git_config_add_file_ondisk(
assert(cfg && path); assert(cfg && path);
res = p_stat(path, &st); res = p_stat(path, &st);
if (res < 0 && errno != ENOENT) { if (res < 0 && errno != ENOENT && errno != ENOTDIR) {
giterr_set(GITERR_CONFIG, "failed to stat '%s'", path); giterr_set(GITERR_CONFIG, "failed to stat '%s'", path);
return -1; return -1;
} }
...@@ -513,6 +513,8 @@ int git_config_backend_foreach_match( ...@@ -513,6 +513,8 @@ int git_config_backend_foreach_match(
regex_t regex; regex_t regex;
int error = 0; int error = 0;
assert(backend && cb);
if (regexp != NULL) { if (regexp != NULL) {
if ((error = p_regcomp(&regex, regexp, REG_EXTENDED)) != 0) { if ((error = p_regcomp(&regex, regexp, REG_EXTENDED)) != 0) {
giterr_set_regex(&regex, error); giterr_set_regex(&regex, error);
......
...@@ -816,6 +816,8 @@ int git_diff_find_similar( ...@@ -816,6 +816,8 @@ int git_diff_find_similar(
diff_find_match *best_match; diff_find_match *best_match;
git_diff_file swap; git_diff_file swap;
assert(diff);
if ((error = normalize_find_opts(diff, &opts, given_opts)) < 0) if ((error = normalize_find_opts(diff, &opts, given_opts)) < 0)
return error; return error;
......
...@@ -809,6 +809,7 @@ static int proxy_stream_close(git_writestream *s) ...@@ -809,6 +809,7 @@ static int proxy_stream_close(git_writestream *s)
{ {
struct proxy_stream *proxy_stream = (struct proxy_stream *)s; struct proxy_stream *proxy_stream = (struct proxy_stream *)s;
git_buf *writebuf; git_buf *writebuf;
git_error_state error_state = {0};
int error; int error;
assert(proxy_stream); assert(proxy_stream);
...@@ -826,6 +827,11 @@ static int proxy_stream_close(git_writestream *s) ...@@ -826,6 +827,11 @@ static int proxy_stream_close(git_writestream *s)
git_buf_sanitize(proxy_stream->output); git_buf_sanitize(proxy_stream->output);
writebuf = proxy_stream->output; writebuf = proxy_stream->output;
} else { } else {
/* close stream before erroring out taking care
* to preserve the original error */
giterr_state_capture(&error_state, error);
proxy_stream->target->close(proxy_stream->target);
giterr_state_restore(&error_state);
return error; return error;
} }
......
...@@ -133,23 +133,12 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match ...@@ -133,23 +133,12 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
continue; continue;
} }
/*
* When dealing with a directory, we add '/<star>' so
* p_fnmatch() honours FNM_PATHNAME. Checking for LEADINGDIR
* alone isn't enough as that's also set for nagations, so we
* need to check that NEGATIVE is off.
*/
git_buf_clear(&buf); git_buf_clear(&buf);
if (rule->containing_dir) { if (rule->containing_dir)
git_buf_puts(&buf, rule->containing_dir); git_buf_puts(&buf, rule->containing_dir);
} git_buf_puts(&buf, rule->pattern);
error = git_buf_puts(&buf, rule->pattern);
if ((rule->flags & (GIT_ATTR_FNMATCH_LEADINGDIR | GIT_ATTR_FNMATCH_NEGATIVE)) == GIT_ATTR_FNMATCH_LEADINGDIR) if (git_buf_oom(&buf))
error = git_buf_PUTS(&buf, "/*");
if (error < 0)
goto out; goto out;
if ((error = p_fnmatch(git_buf_cstr(&buf), path, fnflags)) < 0) { if ((error = p_fnmatch(git_buf_cstr(&buf), path, fnflags)) < 0) {
...@@ -203,7 +192,10 @@ static int parse_ignore_file( ...@@ -203,7 +192,10 @@ static int parse_ignore_file(
break; break;
} }
match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE | GIT_ATTR_FNMATCH_ALLOWNEG; match->flags =
GIT_ATTR_FNMATCH_ALLOWSPACE |
GIT_ATTR_FNMATCH_ALLOWNEG |
GIT_ATTR_FNMATCH_NOLEADINGDIR;
if (!(error = git_attr_fnmatch__parse( if (!(error = git_attr_fnmatch__parse(
match, &attrs->pool, context, &scan))) match, &attrs->pool, context, &scan)))
...@@ -445,6 +437,9 @@ static bool ignore_lookup_in_rules( ...@@ -445,6 +437,9 @@ static bool ignore_lookup_in_rules(
git_attr_fnmatch *match; git_attr_fnmatch *match;
git_vector_rforeach(&file->rules, j, match) { git_vector_rforeach(&file->rules, j, match) {
if (match->flags & GIT_ATTR_FNMATCH_DIRECTORY &&
path->is_dir == GIT_DIR_FLAG_FALSE)
continue;
if (git_attr_fnmatch__match(match, path)) { if (git_attr_fnmatch__match(match, path)) {
*ignored = ((match->flags & GIT_ATTR_FNMATCH_NEGATIVE) == 0) ? *ignored = ((match->flags & GIT_ATTR_FNMATCH_NEGATIVE) == 0) ?
GIT_IGNORE_TRUE : GIT_IGNORE_FALSE; GIT_IGNORE_TRUE : GIT_IGNORE_FALSE;
......
...@@ -1028,11 +1028,15 @@ static int loose_backend__readstream( ...@@ -1028,11 +1028,15 @@ static int loose_backend__readstream(
done: done:
if (error < 0) { if (error < 0) {
git_futils_mmap_free(&stream->map); if (stream) {
git_zstream_free(&stream->zstream); git_futils_mmap_free(&stream->map);
git_hash_ctx_cleanup(hash_ctx); git_zstream_free(&stream->zstream);
git__free(hash_ctx); git__free(stream);
git__free(stream); }
if (hash_ctx) {
git_hash_ctx_cleanup(hash_ctx);
git__free(hash_ctx);
}
} }
git_buf_free(&object_path); git_buf_free(&object_path);
......
...@@ -458,26 +458,6 @@ done: ...@@ -458,26 +458,6 @@ done:
return error; return error;
} }
static int parse_number(git_off_t *out, git_patch_parse_ctx *ctx)
{
const char *end;
int64_t num;
if (!git__isdigit(ctx->parse_ctx.line[0]))
return -1;
if (git__strntol64(&num, ctx->parse_ctx.line, ctx->parse_ctx.line_len, &end, 10) < 0)
return -1;
if (num < 0)
return -1;
*out = num;
git_parse_advance_chars(&ctx->parse_ctx, (end - ctx->parse_ctx.line));
return 0;
}
static int parse_int(int *out, git_patch_parse_ctx *ctx) static int parse_int(int *out, git_patch_parse_ctx *ctx)
{ {
git_off_t num; git_off_t num;
......
...@@ -709,6 +709,8 @@ int git_reference_rename( ...@@ -709,6 +709,8 @@ int git_reference_rename(
git_signature *who; git_signature *who;
int error; int error;
assert(out && ref);
if ((error = git_reference__log_signature(&who, ref->db->repo)) < 0) if ((error = git_reference__log_signature(&who, ref->db->repo)) < 0)
return error; return error;
...@@ -1337,7 +1339,7 @@ int git_reference_is_note(const git_reference *ref) ...@@ -1337,7 +1339,7 @@ int git_reference_is_note(const git_reference *ref)
return git_reference__is_note(ref->name); return git_reference__is_note(ref->name);
} }
static int peel_error(int error, git_reference *ref, const char* msg) static int peel_error(int error, const git_reference *ref, const char* msg)
{ {
giterr_set( giterr_set(
GITERR_INVALID, GITERR_INVALID,
...@@ -1347,10 +1349,11 @@ static int peel_error(int error, git_reference *ref, const char* msg) ...@@ -1347,10 +1349,11 @@ static int peel_error(int error, git_reference *ref, const char* msg)
int git_reference_peel( int git_reference_peel(
git_object **peeled, git_object **peeled,
git_reference *ref, const git_reference *ref,
git_otype target_type) git_otype target_type)
{ {
git_reference *resolved = NULL; const git_reference *resolved = NULL;
git_reference *allocated = NULL;
git_object *target = NULL; git_object *target = NULL;
int error; int error;
...@@ -1359,8 +1362,10 @@ int git_reference_peel( ...@@ -1359,8 +1362,10 @@ int git_reference_peel(
if (ref->type == GIT_REF_OID) { if (ref->type == GIT_REF_OID) {
resolved = ref; resolved = ref;
} else { } else {
if ((error = git_reference_resolve(&resolved, ref)) < 0) if ((error = git_reference_resolve(&allocated, ref)) < 0)
return peel_error(error, ref, "Cannot resolve reference"); return peel_error(error, ref, "Cannot resolve reference");
resolved = allocated;
} }
/* /*
...@@ -1389,9 +1394,7 @@ int git_reference_peel( ...@@ -1389,9 +1394,7 @@ int git_reference_peel(
cleanup: cleanup:
git_object_free(target); git_object_free(target);
git_reference_free(allocated);
if (resolved != ref)
git_reference_free(resolved);
return error; return error;
} }
......
...@@ -248,7 +248,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out, ...@@ -248,7 +248,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
if ((tz_start[0] != '-' && tz_start[0] != '+') || if ((tz_start[0] != '-' && tz_start[0] != '+') ||
git__strntol32(&offset, tz_start + 1, git__strntol32(&offset, tz_start + 1,
buffer_end - tz_start + 1, &tz_end, 10) < 0) { buffer_end - tz_start - 1, &tz_end, 10) < 0) {
/* malformed timezone, just assume it's zero */ /* malformed timezone, just assume it's zero */
offset = 0; offset = 0;
} }
......
...@@ -181,7 +181,7 @@ static int load_submodule_names(git_strmap *out, git_repository *repo, git_confi ...@@ -181,7 +181,7 @@ static int load_submodule_names(git_strmap *out, git_repository *repo, git_confi
if ((error = git_config_iterator_glob_new(&iter, cfg, key)) < 0) if ((error = git_config_iterator_glob_new(&iter, cfg, key)) < 0)
return error; return error;
while (git_config_next(&entry, iter) == 0) { while ((error = git_config_next(&entry, iter)) == 0) {
const char *fdot, *ldot; const char *fdot, *ldot;
fdot = strchr(entry->name, '.'); fdot = strchr(entry->name, '.');
ldot = strrchr(entry->name, '.'); ldot = strrchr(entry->name, '.');
......
...@@ -399,21 +399,21 @@ static int tree_error(const char *str, const char *path) ...@@ -399,21 +399,21 @@ static int tree_error(const char *str, const char *path)
return -1; return -1;
} }
static int parse_mode(unsigned int *modep, const char *buffer, const char **buffer_out) static int parse_mode(uint16_t *mode_out, const char *buffer, size_t buffer_len, const char **buffer_out)
{ {
unsigned char c; int32_t mode;
unsigned int mode = 0; int error;
if (*buffer == ' ') if (!buffer_len || git__isspace(*buffer))
return -1; return -1;
while ((c = *buffer++) != ' ') { if ((error = git__strntol32(&mode, buffer, buffer_len, buffer_out, 8)) < 0)
if (c < '0' || c > '7') return error;
return -1;
mode = (mode << 3) + (c - '0'); if (mode < 0 || mode > UINT16_MAX)
} return -1;
*modep = mode;
*buffer_out = buffer; *mode_out = mode;
return 0; return 0;
} }
...@@ -437,11 +437,14 @@ int git_tree__parse(void *_tree, git_odb_object *odb_obj) ...@@ -437,11 +437,14 @@ int git_tree__parse(void *_tree, git_odb_object *odb_obj)
git_tree_entry *entry; git_tree_entry *entry;
size_t filename_len; size_t filename_len;
const char *nul; const char *nul;
unsigned int attr; uint16_t attr;
if (parse_mode(&attr, buffer, &buffer) < 0 || !buffer) if (parse_mode(&attr, buffer, buffer_end - buffer, &buffer) < 0 || !buffer)
return tree_error("failed to parse tree: can't parse filemode", NULL); return tree_error("failed to parse tree: can't parse filemode", NULL);
if (buffer >= buffer_end || (*buffer++) != ' ')
return tree_error("failed to parse tree: missing space after filemode", NULL);
if ((nul = memchr(buffer, 0, buffer_end - buffer)) == NULL) if ((nul = memchr(buffer, 0, buffer_end - buffer)) == NULL)
return tree_error("failed to parse tree: object is corrupted", NULL); return tree_error("failed to parse tree: object is corrupted", NULL);
......
...@@ -83,36 +83,56 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha ...@@ -83,36 +83,56 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha
/* /*
* White space * White space
*/ */
while (git__isspace(*p)) while (nptr_len && git__isspace(*p))
p++; p++, nptr_len--;
if (!nptr_len)
goto Return;
/* /*
* Sign * Sign
*/ */
if (*p == '-' || *p == '+') if (*p == '-' || *p == '+') {
if (*p++ == '-') if (*p == '-')
neg = 1; neg = 1;
p++;
nptr_len--;
}
if (!nptr_len)
goto Return;
/* /*
* Base * Automatically detect the base if none was given to us.
* Right now, we assume that a number starting with '0x'
* is hexadecimal and a number starting with '0' is
* octal.
*/ */
if (base == 0) { if (base == 0) {
if (*p != '0') if (*p != '0')
base = 10; base = 10;
else { else if (nptr_len > 2 && (p[1] == 'x' || p[1] == 'X'))
base = 16;
else
base = 8; base = 8;
if (p[1] == 'x' || p[1] == 'X') { }
p += 2;
base = 16; if (base < 0 || 36 < base)
}
}
} else if (base == 16 && *p == '0') {
if (p[1] == 'x' || p[1] == 'X')
p += 2;
} else if (base < 0 || 36 < base)
goto Return; goto Return;
/* /*
* Skip prefix of '0x'-prefixed hexadecimal numbers. There is no
* need to do the same for '0'-prefixed octal numbers as a
* leading '0' does not have any impact. Also, if we skip a
* leading '0' in such a string, then we may end up with no
* digits left and produce an error later on which isn't one.
*/
if (base == 16 && nptr_len > 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
p += 2;
nptr_len -= 2;
}
/*
* Non-empty sequence of digits * Non-empty sequence of digits
*/ */
for (; nptr_len > 0; p++,ndig++,nptr_len--) { for (; nptr_len > 0; p++,ndig++,nptr_len--) {
......
...@@ -43,7 +43,8 @@ static int apply_patchfile( ...@@ -43,7 +43,8 @@ static int apply_patchfile(
if (error == 0) { if (error == 0) {
cl_assert_equal_i(new_len, result.size); cl_assert_equal_i(new_len, result.size);
cl_assert(memcmp(new, result.ptr, new_len) == 0); if (new_len)
cl_assert(memcmp(new, result.ptr, new_len) == 0);
cl_assert_equal_s(filename_expected, filename); cl_assert_equal_s(filename_expected, filename);
cl_assert_equal_i(mode_expected, mode); cl_assert_equal_i(mode_expected, mode);
......
...@@ -43,6 +43,26 @@ void test_commit_signature__leading_and_trailing_crud_is_trimmed(void) ...@@ -43,6 +43,26 @@ void test_commit_signature__leading_and_trailing_crud_is_trimmed(void)
assert_name_and_email("nulltoken \xe2\x98\xba", "emeric.fermas@gmail.com", "nulltoken \xe2\x98\xba", "emeric.fermas@gmail.com"); assert_name_and_email("nulltoken \xe2\x98\xba", "emeric.fermas@gmail.com", "nulltoken \xe2\x98\xba", "emeric.fermas@gmail.com");
} }
void test_commit_signature__timezone_does_not_read_oob(void)
{
const char *header = "A <a@example.com> 1461698487 +1234", *header_end;
git_signature *sig;
/* Let the buffer end midway between the timezone offeset's "+12" and "34" */
header_end = header + strlen(header) - 2;
sig = git__calloc(1, sizeof(git_signature));
cl_assert(sig);
cl_git_pass(git_signature__parse(sig, &header, header_end, NULL, '\0'));
cl_assert_equal_s(sig->name, "A");
cl_assert_equal_s(sig->email, "a@example.com");
cl_assert_equal_i(sig->when.time, 1461698487);
cl_assert_equal_i(sig->when.offset, 12);
git_signature_free(sig);
}
void test_commit_signature__angle_brackets_in_names_are_not_supported(void) void test_commit_signature__angle_brackets_in_names_are_not_supported(void)
{ {
cl_git_fail(try_build_signature("<Phil Haack", "phil@haack", 1234567890, 60)); cl_git_fail(try_build_signature("<Phil Haack", "phil@haack", 1234567890, 60));
......
...@@ -524,6 +524,26 @@ void test_config_read__fallback_from_local_to_global_and_from_global_to_system(v ...@@ -524,6 +524,26 @@ void test_config_read__fallback_from_local_to_global_and_from_global_to_system(v
git_config_free(cfg); git_config_free(cfg);
} }
void test_config_read__parent_dir_is_file(void)
{
git_config *cfg;
int count;
cl_git_pass(git_config_new(&cfg));
/*
* Verify we can add non-existing files when the parent directory is not
* a directory.
*/
cl_git_pass(git_config_add_file_ondisk(cfg, "/dev/null/.gitconfig",
GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
count = 0;
cl_git_pass(git_config_foreach(cfg, count_cfg_entries_and_compare_levels, &count));
cl_assert_equal_i(0, count);
git_config_free(cfg);
}
/* /*
* At the beginning of the test, config18 has: * At the beginning of the test, config18 has:
* int32global = 28 * int32global = 28
......
...@@ -64,6 +64,28 @@ void test_core_strtol__int64(void) ...@@ -64,6 +64,28 @@ void test_core_strtol__int64(void)
assert_l64_fails("-0x8000000000000001", 16); assert_l64_fails("-0x8000000000000001", 16);
} }
void test_core_strtol__base_autodetection(void)
{
assert_l64_parses("0", 0, 0);
assert_l64_parses("00", 0, 0);
assert_l64_parses("0x", 0, 0);
assert_l64_parses("0foobar", 0, 0);
assert_l64_parses("07", 7, 0);
assert_l64_parses("017", 15, 0);
assert_l64_parses("0x8", 8, 0);
assert_l64_parses("0x18", 24, 0);
}
void test_core_strtol__buffer_length_with_autodetection_truncates(void)
{
int64_t i64;
cl_git_pass(git__strntol64(&i64, "011", 2, NULL, 0));
cl_assert_equal_i(i64, 1);
cl_git_pass(git__strntol64(&i64, "0x11", 3, NULL, 0));
cl_assert_equal_i(i64, 1);
}
void test_core_strtol__buffer_length_truncates(void) void test_core_strtol__buffer_length_truncates(void)
{ {
int32_t i32; int32_t i32;
...@@ -76,6 +98,26 @@ void test_core_strtol__buffer_length_truncates(void) ...@@ -76,6 +98,26 @@ void test_core_strtol__buffer_length_truncates(void)
cl_assert_equal_i(i64, 1); cl_assert_equal_i(i64, 1);
} }
void test_core_strtol__buffer_length_with_leading_ws_truncates(void)
{
int64_t i64;
cl_git_fail(git__strntol64(&i64, " 1", 1, NULL, 10));
cl_git_pass(git__strntol64(&i64, " 11", 2, NULL, 10));
cl_assert_equal_i(i64, 1);
}
void test_core_strtol__buffer_length_with_leading_sign_truncates(void)
{
int64_t i64;
cl_git_fail(git__strntol64(&i64, "-1", 1, NULL, 10));
cl_git_pass(git__strntol64(&i64, "-11", 2, NULL, 10));
cl_assert_equal_i(i64, -1);
}
void test_core_strtol__error_message_cuts_off(void) void test_core_strtol__error_message_cuts_off(void)
{ {
assert_l32_fails("2147483657foobar", 10); assert_l32_fails("2147483657foobar", 10);
......
#include "clar_libgit2.h"
static git_repository *g_repo;
void test_merge_annotated_commit__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
}
void test_merge_annotated_commit__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_merge_annotated_commit__lookup_annotated_tag(void)
{
git_annotated_commit *commit;
git_reference *ref;
cl_git_pass(git_reference_lookup(&ref, g_repo, "refs/tags/test"));
cl_git_pass(git_annotated_commit_from_ref(&commit, g_repo, ref));
git_annotated_commit_free(commit);
git_reference_free(ref);
}
...@@ -1158,27 +1158,58 @@ void test_status_ignore__subdir_ignore_everything_except_certain_files(void) ...@@ -1158,27 +1158,58 @@ void test_status_ignore__subdir_ignore_everything_except_certain_files(void)
void test_status_ignore__deeper(void) void test_status_ignore__deeper(void)
{ {
int ignored; const char *test_files[] = {
"empty_standard_repo/foo.data",
"empty_standard_repo/bar.data",
"empty_standard_repo/dont_ignore/foo.data",
"empty_standard_repo/dont_ignore/bar.data",
NULL
};
g_repo = cl_git_sandbox_init("empty_standard_repo"); make_test_data("empty_standard_repo", test_files);
cl_git_mkfile("empty_standard_repo/.gitignore",
"*.data\n"
"!dont_ignore/*.data\n");
cl_git_mkfile("empty_standard_repo/.gitignore", assert_is_ignored("foo.data");
"*.data\n" assert_is_ignored("bar.data");
"!dont_ignore/*.data\n");
cl_git_pass(p_mkdir("empty_standard_repo/dont_ignore", 0777)); refute_is_ignored("dont_ignore/foo.data");
cl_git_mkfile("empty_standard_repo/foo.data", ""); refute_is_ignored("dont_ignore/bar.data");
cl_git_mkfile("empty_standard_repo/bar.data", ""); }
cl_git_mkfile("empty_standard_repo/dont_ignore/foo.data", "");
cl_git_mkfile("empty_standard_repo/dont_ignore/bar.data", "");
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "foo.data")); void test_status_ignore__unignored_dir_with_ignored_contents(void)
cl_assert_equal_i(1, ignored); {
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "bar.data")); static const char *test_files[] = {
cl_assert_equal_i(1, ignored); "empty_standard_repo/dir/a.test",
"empty_standard_repo/dir/subdir/a.test",
NULL
};
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "dont_ignore/foo.data")); make_test_data("empty_standard_repo", test_files);
cl_assert_equal_i(0, ignored); cl_git_mkfile(
cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "dont_ignore/bar.data")); "empty_standard_repo/.gitignore",
cl_assert_equal_i(0, ignored); "*.test\n"
"!dir/*\n");
refute_is_ignored("dir/a.test");
assert_is_ignored("dir/subdir/a.test");
}
void test_status_ignore__unignored_subdirs(void)
{
static const char *test_files[] = {
"empty_standard_repo/dir/a.test",
"empty_standard_repo/dir/subdir/a.test",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
"dir/*\n"
"!dir/*/\n");
assert_is_ignored("dir/a.test");
refute_is_ignored("dir/subdir/a.test");
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment