diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2019-01-28 13:23:50 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-28 13:23:50 +0300 |
commit | 8d1b36a6d6cd0d0d1657a04634ea5b3301455715 (patch) | |
tree | 0701902d616a5457dcd3877c940a5fb3319a70a2 | |
parent | 313440c394589af4387daa71b31821ed9b7f4462 (diff) | |
parent | 703885a813c7e2a6266437814ae88290a39b8f05 (diff) |
Merge pull request #4942 from libgit2/ethomson/v0.27.8
Release v0.27.8
-rw-r--r-- | CHANGELOG.md | 33 | ||||
-rw-r--r-- | include/git2/refs.h | 2 | ||||
-rw-r--r-- | include/git2/version.h | 4 | ||||
-rw-r--r-- | src/annotated_commit.c | 8 | ||||
-rw-r--r-- | src/apply.c | 3 | ||||
-rw-r--r-- | src/attr_file.c | 5 | ||||
-rw-r--r-- | src/commit.c | 2 | ||||
-rw-r--r-- | src/config.c | 4 | ||||
-rw-r--r-- | src/diff_tform.c | 2 | ||||
-rw-r--r-- | src/filter.c | 6 | ||||
-rw-r--r-- | src/ignore.c | 25 | ||||
-rw-r--r-- | src/odb_loose.c | 14 | ||||
-rw-r--r-- | src/patch_parse.c | 20 | ||||
-rw-r--r-- | src/refs.c | 17 | ||||
-rw-r--r-- | src/signature.c | 2 | ||||
-rw-r--r-- | src/submodule.c | 2 | ||||
-rw-r--r-- | src/tree.c | 29 | ||||
-rw-r--r-- | src/util.c | 50 | ||||
-rw-r--r-- | tests/apply/fromfile.c | 3 | ||||
-rw-r--r-- | tests/commit/signature.c | 20 | ||||
-rw-r--r-- | tests/config/read.c | 20 | ||||
-rw-r--r-- | tests/core/strtol.c | 42 | ||||
-rw-r--r-- | tests/merge/annotated_commit.c | 26 | ||||
-rw-r--r-- | tests/status/ignore.c | 67 |
24 files changed, 298 insertions, 108 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index f7e72d343..e935b77ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,36 @@ +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 ------- diff --git a/include/git2/refs.h b/include/git2/refs.h index 0dd453e55..75afea5c8 100644 --- a/include/git2/refs.h +++ b/include/git2/refs.h @@ -710,7 +710,7 @@ GIT_EXTERN(int) git_reference_normalize_name( */ GIT_EXTERN(int) git_reference_peel( git_object **out, - git_reference *ref, + const git_reference *ref, git_otype type); /** diff --git a/include/git2/version.h b/include/git2/version.h index 964e4a58b..d59738084 100644 --- a/include/git2/version.h +++ b/include/git2/version.h @@ -7,10 +7,10 @@ #ifndef 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_MINOR 27 -#define LIBGIT2_VER_REVISION 7 +#define LIBGIT2_VER_REVISION 8 #define LIBGIT2_VER_PATCH 0 #define LIBGIT2_SOVERSION 27 diff --git a/src/annotated_commit.c b/src/annotated_commit.c index 72ba80a22..59891b6ab 100644 --- a/src/annotated_commit.c +++ b/src/annotated_commit.c @@ -123,19 +123,19 @@ int git_annotated_commit_from_ref( git_repository *repo, const git_reference *ref) { - git_reference *resolved; + git_object *peeled; int error = 0; assert(out && repo && ref); *out = NULL; - if ((error = git_reference_resolve(&resolved, ref)) < 0) + if ((error = git_reference_peel(&peeled, ref, GIT_OBJ_COMMIT)) < 0) return error; error = annotated_commit_init_from_id(out, repo, - git_reference_target(resolved), + git_object_id(peeled), git_reference_name(ref)); if (!error) { @@ -143,7 +143,7 @@ int git_annotated_commit_from_ref( GITERR_CHECK_ALLOC((*out)->ref_name); } - git_reference_free(resolved); + git_object_free(peeled); return error; } diff --git a/src/apply.c b/src/apply.c index 7801a0a54..2b3f0793f 100644 --- a/src/apply.c +++ b/src/apply.c @@ -312,8 +312,9 @@ static int apply_binary( &patch->binary.old_file)) < 0) goto done; + /* Verify that the resulting file with the reverse patch applied matches the source file */ 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"); goto done; } diff --git a/src/attr_file.c b/src/attr_file.c index f46cce3de..6821587bc 100644 --- a/src/attr_file.c +++ b/src/attr_file.c @@ -594,8 +594,9 @@ int git_attr_fnmatch__parse( } if (*pattern == '!' && (spec->flags & GIT_ATTR_FNMATCH_ALLOWNEG) != 0) { - spec->flags = spec->flags | - GIT_ATTR_FNMATCH_NEGATIVE | GIT_ATTR_FNMATCH_LEADINGDIR; + spec->flags = spec->flags | GIT_ATTR_FNMATCH_NEGATIVE; + if ((spec->flags & GIT_ATTR_FNMATCH_NOLEADINGDIR) == 0) + spec->flags |= GIT_ATTR_FNMATCH_LEADINGDIR; pattern++; } diff --git a/src/commit.c b/src/commit.c index 8972c077d..4fee8c8da 100644 --- a/src/commit.c +++ b/src/commit.c @@ -419,7 +419,7 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj) return -1; /* 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) return -1; diff --git a/src/config.c b/src/config.c index 5d95c2458..ba225297c 100644 --- a/src/config.c +++ b/src/config.c @@ -109,7 +109,7 @@ int git_config_add_file_ondisk( assert(cfg && path); 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); return -1; } @@ -513,6 +513,8 @@ int git_config_backend_foreach_match( regex_t regex; int error = 0; + assert(backend && cb); + if (regexp != NULL) { if ((error = p_regcomp(®ex, regexp, REG_EXTENDED)) != 0) { giterr_set_regex(®ex, error); diff --git a/src/diff_tform.c b/src/diff_tform.c index a9706e002..686addff4 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -816,6 +816,8 @@ int git_diff_find_similar( diff_find_match *best_match; git_diff_file swap; + assert(diff); + if ((error = normalize_find_opts(diff, &opts, given_opts)) < 0) return error; diff --git a/src/filter.c b/src/filter.c index 6ab09790b..ad741d6af 100644 --- a/src/filter.c +++ b/src/filter.c @@ -809,6 +809,7 @@ static int proxy_stream_close(git_writestream *s) { struct proxy_stream *proxy_stream = (struct proxy_stream *)s; git_buf *writebuf; + git_error_state error_state = {0}; int error; assert(proxy_stream); @@ -826,6 +827,11 @@ static int proxy_stream_close(git_writestream *s) git_buf_sanitize(proxy_stream->output); writebuf = proxy_stream->output; } 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; } diff --git a/src/ignore.c b/src/ignore.c index 76b997245..3b68e14a8 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -133,23 +133,12 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match 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); - if (rule->containing_dir) { + if (rule->containing_dir) git_buf_puts(&buf, rule->containing_dir); - } - - error = git_buf_puts(&buf, rule->pattern); + git_buf_puts(&buf, rule->pattern); - if ((rule->flags & (GIT_ATTR_FNMATCH_LEADINGDIR | GIT_ATTR_FNMATCH_NEGATIVE)) == GIT_ATTR_FNMATCH_LEADINGDIR) - error = git_buf_PUTS(&buf, "/*"); - - if (error < 0) + if (git_buf_oom(&buf)) goto out; if ((error = p_fnmatch(git_buf_cstr(&buf), path, fnflags)) < 0) { @@ -203,7 +192,10 @@ static int parse_ignore_file( 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( match, &attrs->pool, context, &scan))) @@ -445,6 +437,9 @@ static bool ignore_lookup_in_rules( git_attr_fnmatch *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)) { *ignored = ((match->flags & GIT_ATTR_FNMATCH_NEGATIVE) == 0) ? GIT_IGNORE_TRUE : GIT_IGNORE_FALSE; diff --git a/src/odb_loose.c b/src/odb_loose.c index 470421e15..840efbe90 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -1028,11 +1028,15 @@ static int loose_backend__readstream( done: if (error < 0) { - git_futils_mmap_free(&stream->map); - git_zstream_free(&stream->zstream); - git_hash_ctx_cleanup(hash_ctx); - git__free(hash_ctx); - git__free(stream); + if (stream) { + git_futils_mmap_free(&stream->map); + git_zstream_free(&stream->zstream); + git__free(stream); + } + if (hash_ctx) { + git_hash_ctx_cleanup(hash_ctx); + git__free(hash_ctx); + } } git_buf_free(&object_path); diff --git a/src/patch_parse.c b/src/patch_parse.c index e02c87cf3..7f6c013b1 100644 --- a/src/patch_parse.c +++ b/src/patch_parse.c @@ -458,26 +458,6 @@ done: 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) { git_off_t num; diff --git a/src/refs.c b/src/refs.c index c42968359..96ad6d8ad 100644 --- a/src/refs.c +++ b/src/refs.c @@ -709,6 +709,8 @@ int git_reference_rename( git_signature *who; int error; + assert(out && ref); + if ((error = git_reference__log_signature(&who, ref->db->repo)) < 0) return error; @@ -1337,7 +1339,7 @@ int git_reference_is_note(const git_reference *ref) 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_INVALID, @@ -1347,10 +1349,11 @@ static int peel_error(int error, git_reference *ref, const char* msg) int git_reference_peel( git_object **peeled, - git_reference *ref, + const git_reference *ref, git_otype target_type) { - git_reference *resolved = NULL; + const git_reference *resolved = NULL; + git_reference *allocated = NULL; git_object *target = NULL; int error; @@ -1359,8 +1362,10 @@ int git_reference_peel( if (ref->type == GIT_REF_OID) { resolved = ref; } 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"); + + resolved = allocated; } /* @@ -1389,9 +1394,7 @@ int git_reference_peel( cleanup: git_object_free(target); - - if (resolved != ref) - git_reference_free(resolved); + git_reference_free(allocated); return error; } diff --git a/src/signature.c b/src/signature.c index 91864bb88..11416d786 100644 --- a/src/signature.c +++ b/src/signature.c @@ -248,7 +248,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out, if ((tz_start[0] != '-' && tz_start[0] != '+') || 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 */ offset = 0; } diff --git a/src/submodule.c b/src/submodule.c index 06b7de585..2bfc46880 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -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) return error; - while (git_config_next(&entry, iter) == 0) { + while ((error = git_config_next(&entry, iter)) == 0) { const char *fdot, *ldot; fdot = strchr(entry->name, '.'); ldot = strrchr(entry->name, '.'); diff --git a/src/tree.c b/src/tree.c index a014ce807..d1c1d7769 100644 --- a/src/tree.c +++ b/src/tree.c @@ -399,21 +399,21 @@ static int tree_error(const char *str, const char *path) 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; - unsigned int mode = 0; + int32_t mode; + int error; - if (*buffer == ' ') + if (!buffer_len || git__isspace(*buffer)) return -1; - while ((c = *buffer++) != ' ') { - if (c < '0' || c > '7') - return -1; - mode = (mode << 3) + (c - '0'); - } - *modep = mode; - *buffer_out = buffer; + if ((error = git__strntol32(&mode, buffer, buffer_len, buffer_out, 8)) < 0) + return error; + + if (mode < 0 || mode > UINT16_MAX) + return -1; + + *mode_out = mode; return 0; } @@ -437,11 +437,14 @@ int git_tree__parse(void *_tree, git_odb_object *odb_obj) git_tree_entry *entry; size_t filename_len; 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); + 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) return tree_error("failed to parse tree: object is corrupted", NULL); diff --git a/src/util.c b/src/util.c index 911921857..a81557bac 100644 --- a/src/util.c +++ b/src/util.c @@ -83,36 +83,56 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha /* * White space */ - while (git__isspace(*p)) - p++; + while (nptr_len && git__isspace(*p)) + p++, nptr_len--; + + if (!nptr_len) + goto Return; /* * Sign */ - if (*p == '-' || *p == '+') - if (*p++ == '-') + if (*p == '-' || *p == '+') { + if (*p == '-') 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 (*p != '0') base = 10; - else { + else if (nptr_len > 2 && (p[1] == 'x' || p[1] == 'X')) + base = 16; + else base = 8; - if (p[1] == 'x' || p[1] == 'X') { - p += 2; - base = 16; - } - } - } else if (base == 16 && *p == '0') { - if (p[1] == 'x' || p[1] == 'X') - p += 2; - } else if (base < 0 || 36 < base) + } + + if (base < 0 || 36 < base) 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 */ for (; nptr_len > 0; p++,ndig++,nptr_len--) { diff --git a/tests/apply/fromfile.c b/tests/apply/fromfile.c index 31fffa1a2..211f6dcbb 100644 --- a/tests/apply/fromfile.c +++ b/tests/apply/fromfile.c @@ -43,7 +43,8 @@ static int apply_patchfile( if (error == 0) { 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_i(mode_expected, mode); diff --git a/tests/commit/signature.c b/tests/commit/signature.c index 286079fa2..d8edbaaa9 100644 --- a/tests/commit/signature.c +++ b/tests/commit/signature.c @@ -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"); } +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) { cl_git_fail(try_build_signature("<Phil Haack", "phil@haack", 1234567890, 60)); diff --git a/tests/config/read.c b/tests/config/read.c index 646567134..df745a567 100644 --- a/tests/config/read.c +++ b/tests/config/read.c @@ -524,6 +524,26 @@ void test_config_read__fallback_from_local_to_global_and_from_global_to_system(v 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: * int32global = 28 diff --git a/tests/core/strtol.c b/tests/core/strtol.c index ba79fba51..6f4e63af3 100644 --- a/tests/core/strtol.c +++ b/tests/core/strtol.c @@ -64,6 +64,28 @@ void test_core_strtol__int64(void) 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) { int32_t i32; @@ -76,6 +98,26 @@ void test_core_strtol__buffer_length_truncates(void) 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) { assert_l32_fails("2147483657foobar", 10); diff --git a/tests/merge/annotated_commit.c b/tests/merge/annotated_commit.c new file mode 100644 index 000000000..cfdf849e5 --- /dev/null +++ b/tests/merge/annotated_commit.c @@ -0,0 +1,26 @@ +#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); +} diff --git a/tests/status/ignore.c b/tests/status/ignore.c index dc58e8b45..824475e8c 100644 --- a/tests/status/ignore.c +++ b/tests/status/ignore.c @@ -1158,27 +1158,58 @@ void test_status_ignore__subdir_ignore_everything_except_certain_files(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", - "*.data\n" - "!dont_ignore/*.data\n"); + assert_is_ignored("foo.data"); + assert_is_ignored("bar.data"); - cl_git_pass(p_mkdir("empty_standard_repo/dont_ignore", 0777)); - cl_git_mkfile("empty_standard_repo/foo.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", ""); + refute_is_ignored("dont_ignore/foo.data"); + refute_is_ignored("dont_ignore/bar.data"); +} - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "foo.data")); - cl_assert_equal_i(1, ignored); - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "bar.data")); - cl_assert_equal_i(1, ignored); +void test_status_ignore__unignored_dir_with_ignored_contents(void) +{ + static const char *test_files[] = { + "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")); - cl_assert_equal_i(0, ignored); - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "dont_ignore/bar.data")); - cl_assert_equal_i(0, ignored); + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/.gitignore", + "*.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"); } |