summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.embed30
-rw-r--r--examples/log.c7
-rw-r--r--include/git2/odb.h2
-rw-r--r--include/git2/submodule.h51
-rw-r--r--include/git2/types.h51
-rw-r--r--src/config_file.c11
-rw-r--r--src/fileops.c1
-rw-r--r--src/odb_pack.c41
-rw-r--r--src/pack.c5
-rw-r--r--src/submodule.c5
-rw-r--r--tests-clar/config/read.c21
-rw-r--r--tests-clar/odb/mixed.c67
-rw-r--r--tests-clar/resources/duplicate.git/config2
-rw-r--r--tests-clar/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5eabin0 -> 22 bytes
-rw-r--r--tests-clar/resources/duplicate.git/objects/info/packs1
-rw-r--r--tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idxbin0 -> 1184 bytes
-rw-r--r--tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.packbin0 -> 249 bytes
-rw-r--r--tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idxbin0 -> 1268 bytes
-rw-r--r--tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.packbin0 -> 369 bytes
-rw-r--r--tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idxbin0 -> 1100 bytes
-rw-r--r--tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.packbin0 -> 47 bytes
-rw-r--r--tests-clar/resources/duplicate.git/refs/heads/dummy-marker.txt1
-rw-r--r--tests-clar/resources/submodules/gitmodules3
23 files changed, 234 insertions, 65 deletions
diff --git a/Makefile.embed b/Makefile.embed
index 76b4d3cda..2f3b057c7 100644
--- a/Makefile.embed
+++ b/Makefile.embed
@@ -1,15 +1,33 @@
-PLATFORM=$(shell uname -o)
+PLATFORM=$(shell uname -s)
+
+ifneq (,$(CROSS_COMPILE))
+ PREFIX=$(CROSS_COMPILE)-
+else
+ PREFIX=
+endif
+
+MINGW=0
+ifneq (,$(findstring MINGW32,$(PLATFORM)))
+ MINGW=1
+endif
+ifneq (,$(findstring mingw,$(CROSS_COMPILE)))
+ MINGW=1
+endif
rm=rm -f
-AR=ar cq
-RANLIB=ranlib
+AR=$(PREFIX)ar cq
+RANLIB=$(PREFIX)ranlib
+
LIBNAME=libgit2.a
-ifeq ($(PLATFORM),Msys)
+
+ifeq ($(MINGW),1)
CC=gcc
else
CC=cc
endif
+CC:=$(PREFIX)$(CC)
+
INCLUDES= -I. -Isrc -Iinclude -Ideps/http-parser -Ideps/zlib
DEFINES= $(INCLUDES) -DNO_VIZ -DSTDC -DNO_GZIP -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE $(EXTRA_DEFINES)
@@ -17,10 +35,10 @@ CFLAGS= -g $(DEFINES) -Wall -Wextra -O2 $(EXTRA_CFLAGS)
SRCS = $(wildcard src/*.c) $(wildcard src/transports/*.c) $(wildcard src/xdiff/*.c) $(wildcard deps/http-parser/*.c) $(wildcard deps/zlib/*.c) src/hash/hash_generic.c
-ifeq ($(PLATFORM),Msys)
+ifeq ($(MINGW),1)
SRCS += $(wildcard src/win32/*.c) $(wildcard src/compat/*.c) deps/regex/regex.c
INCLUDES += -Ideps/regex
- DEFINES += -DWIN32 -D_WIN32_WINNT=0x0501
+ DEFINES += -DWIN32 -D_WIN32_WINNT=0x0501 -D__USE_MINGW_ANSI_STDIO=1
else
SRCS += $(wildcard src/unix/*.c)
CFLAGS += -fPIC
diff --git a/examples/log.c b/examples/log.c
index dbbc42914..413c211e4 100644
--- a/examples/log.c
+++ b/examples/log.c
@@ -265,6 +265,7 @@ int main(int argc, char *argv[])
memset(&opt, 0, sizeof(opt));
opt.max_parents = -1;
+ opt.limit = -1;
for (i = 1; i < argc; ++i) {
a = argv[i];
@@ -294,8 +295,8 @@ int main(int argc, char *argv[])
if (!match_int(&opt.limit, a + 1, 0))
usage("Invalid limit on number of commits", a);
} else if (!strcmp(a, "-n")) {
- if (i + 1 == argc || !match_int(&opt.limit, argv[i], 0))
- usage("Argument -n not followed by valid count", argv[i]);
+ if (i + 1 == argc || !match_int(&opt.limit, argv[i + 1], 0))
+ usage("Argument -n not followed by valid count", argv[i + 1]);
else
++i;
}
@@ -363,7 +364,7 @@ int main(int argc, char *argv[])
if (count++ < opt.skip)
continue;
- if (printed++ >= opt.limit) {
+ if (opt.limit != -1 && printed++ >= opt.limit) {
git_commit_free(commit);
break;
}
diff --git a/include/git2/odb.h b/include/git2/odb.h
index b64436c4d..b3e9a57a6 100644
--- a/include/git2/odb.h
+++ b/include/git2/odb.h
@@ -120,7 +120,7 @@ GIT_EXTERN(int) git_odb_read(git_odb_object **out, git_odb *db, const git_oid *i
* @param db database to search for the object in.
* @param short_id a prefix of the id of the object to read.
* @param len the length of the prefix
- * @return
+ * @return
* - 0 if the object was read;
* - GIT_ENOTFOUND if the object is not in the database.
* - GIT_EAMBIGUOUS if the prefix is ambiguous (several objects match the prefix)
diff --git a/include/git2/submodule.h b/include/git2/submodule.h
index ba7a558d0..186f263f5 100644
--- a/include/git2/submodule.h
+++ b/include/git2/submodule.h
@@ -316,9 +316,10 @@ GIT_EXTERN(const git_oid *) git_submodule_head_id(git_submodule *submodule);
GIT_EXTERN(const git_oid *) git_submodule_wd_id(git_submodule *submodule);
/**
- * Get the ignore rule for the submodule.
+ * Get the ignore rule that will be used for the submodule.
*
- * There are four ignore values:
+ * These values control the behavior of `git_submodule_status()` for this
+ * submodule. There are four ignore values:
*
* - **GIT_SUBMODULE_IGNORE_NONE** will consider any change to the contents
* of the submodule from a clean checkout to be dirty, including the
@@ -332,6 +333,13 @@ GIT_EXTERN(const git_oid *) git_submodule_wd_id(git_submodule *submodule);
* - **GIT_SUBMODULE_IGNORE_ALL** means not to open the submodule repo.
* The working directory will be consider clean so long as there is a
* checked out version present.
+ *
+ * plus the special **GIT_SUBMODULE_IGNORE_RESET** which can be used with
+ * `git_submodule_set_ignore()` to revert to the on-disk setting.
+ *
+ * @param submodule The submodule to check
+ * @return The current git_submodule_ignore_t valyue what will be used for
+ * this submodule.
*/
GIT_EXTERN(git_submodule_ignore_t) git_submodule_ignore(
git_submodule *submodule);
@@ -339,15 +347,17 @@ GIT_EXTERN(git_submodule_ignore_t) git_submodule_ignore(
/**
* Set the ignore rule for the submodule.
*
- * This sets the ignore rule in memory for the submodule. This will be used
- * for any following actions (such as `git_submodule_status()`) while the
- * submodule is in memory. You should call `git_submodule_save()` if you
- * want to persist the new ignore role.
+ * This sets the in-memory ignore rule for the submodule which will
+ * control the behavior of `git_submodule_status()`.
+ *
+ * To make changes persistent, call `git_submodule_save()` to write the
+ * value to disk (in the ".gitmodules" and ".git/config" files).
*
- * Calling this again with GIT_SUBMODULE_IGNORE_RESET or calling
- * `git_submodule_reload()` will revert the rule to the value that was in
- * the original config.
+ * Call with `GIT_SUBMODULE_IGNORE_RESET` or call `git_submodule_reload()`
+ * to revert the in-memory rule to the value that is on disk.
*
+ * @param submodule The submodule to update
+ * @param ignore The new value for the ignore rule
* @return old value for ignore
*/
GIT_EXTERN(git_submodule_ignore_t) git_submodule_set_ignore(
@@ -355,7 +365,16 @@ GIT_EXTERN(git_submodule_ignore_t) git_submodule_set_ignore(
git_submodule_ignore_t ignore);
/**
- * Get the update rule for the submodule.
+ * Get the update rule that will be used for the submodule.
+ *
+ * This value controls the behavior of the `git submodule update` command.
+ * There are four useful values documented with `git_submodule_update_t`
+ * plus the `GIT_SUBMODULE_UPDATE_RESET` which can be used to revert to
+ * the on-disk setting.
+ *
+ * @param submodule The submodule to check
+ * @return The current git_submodule_update_t value that will be used
+ * for this submodule.
*/
GIT_EXTERN(git_submodule_update_t) git_submodule_update(
git_submodule *submodule);
@@ -363,13 +382,17 @@ GIT_EXTERN(git_submodule_update_t) git_submodule_update(
/**
* Set the update rule for the submodule.
*
- * This sets the update rule in memory for the submodule. You should call
- * `git_submodule_save()` if you want to persist the new update rule.
+ * The initial value comes from the ".git/config" setting of
+ * `submodule.$name.update` for this submodule (which is initialized from
+ * the ".gitmodules" file). Using this function sets the update rule in
+ * memory for the submodule. Call `git_submodule_save()` to write out the
+ * new update rule.
*
* Calling this again with GIT_SUBMODULE_UPDATE_RESET or calling
- * `git_submodule_reload()` will revert the rule to the value that was in
- * the original config.
+ * `git_submodule_reload()` will revert the rule to the on disk value.
*
+ * @param submodule The submodule to update
+ * @param update The new value to use
* @return old value for update
*/
GIT_EXTERN(git_submodule_update_t) git_submodule_set_update(
diff --git a/include/git2/types.h b/include/git2/types.h
index 1da0d3ed2..b500c986d 100644
--- a/include/git2/types.h
+++ b/include/git2/types.h
@@ -235,10 +235,29 @@ typedef int (*git_transfer_progress_callback)(const git_transfer_progress *stats
typedef struct git_submodule git_submodule;
/**
- * Values that could be specified for the update rule of a submodule.
+ * Submodule update values
*
- * Use the RESET value if you have altered the in-memory update value via
- * `git_submodule_set_update()` and wish to reset to the original default.
+ * These values represent settings for the `submodule.$name.update`
+ * configuration value which says how to handle `git submodule update` for
+ * this submodule. The value is usually set in the ".gitmodules" file and
+ * copied to ".git/config" when the submodule is initialized.
+ *
+ * You can override this setting on a per-submodule basis with
+ * `git_submodule_set_update()` and write the changed value to disk using
+ * `git_submodule_save()`. If you have overwritten the value, you can
+ * revert it by passing `GIT_SUBMODULE_UPDATE_RESET` to the set function.
+ *
+ * The values are:
+ *
+ * - GIT_SUBMODULE_UPDATE_RESET: reset to the on-disk value.
+ * - GIT_SUBMODULE_UPDATE_CHECKOUT: the default; when a submodule is
+ * updated, checkout the new detached HEAD to the submodule directory.
+ * - GIT_SUBMODULE_UPDATE_REBASE: update by rebasing the current checked
+ * out branch onto the commit from the superproject.
+ * - GIT_SUBMODULE_UPDATE_MERGE: update by merging the commit in the
+ * superproject into the current checkout out branch of the submodule.
+ * - GIT_SUBMODULE_UPDATE_NONE: do not update this submodule even when
+ * the commit in the superproject is updated.
*/
typedef enum {
GIT_SUBMODULE_UPDATE_RESET = -1,
@@ -249,11 +268,29 @@ typedef enum {
} git_submodule_update_t;
/**
- * Values that could be specified for how closely to examine the
- * working directory when getting submodule status.
+ * Submodule ignore values
+ *
+ * These values represent settings for the `submodule.$name.ignore`
+ * configuration value which says how deeply to look at the working
+ * directory when getting submodule status.
+ *
+ * You can override this value in memory on a per-submodule basis with
+ * `git_submodule_set_ignore()` and can write the changed value to disk
+ * with `git_submodule_save()`. If you have overwritten the value, you
+ * can revert to the on disk value by using `GIT_SUBMODULE_IGNORE_RESET`.
+ *
+ * The values are:
*
- * Use the RESET value if you have altered the in-memory ignore value via
- * `git_submodule_set_ignore()` and wish to reset to the original value.
+ * - GIT_SUBMODULE_IGNORE_RESET: reset to the on-disk value.
+ * - GIT_SUBMODULE_IGNORE_NONE: don't ignore any change - i.e. even an
+ * untracked file, will mark the submodule as dirty. Ignored files are
+ * still ignored, of course.
+ * - GIT_SUBMODULE_IGNORE_UNTRACKED: ignore untracked files; only changes
+ * to tracked files, or the index or the HEAD commit will matter.
+ * - GIT_SUBMODULE_IGNORE_DIRTY: ignore changes in the working directory,
+ * only considering changes if the HEAD of submodule has moved from the
+ * value in the superproject.
+ * - GIT_SUBMODULE_IGNORE_ALL: never check if the submodule is dirty
*/
typedef enum {
GIT_SUBMODULE_IGNORE_RESET = -1, /* reset to on-disk value */
diff --git a/src/config_file.c b/src/config_file.c
index 2b0732a13..570f286c8 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -792,6 +792,11 @@ static int parse_section_header_ext(diskfile_backend *cfg, const char *line, con
}
switch (c) {
+ case 0:
+ set_parse_error(cfg, 0, "Unexpected end-of-line in section header");
+ git_buf_free(&buf);
+ return -1;
+
case '"':
++quote_marks;
continue;
@@ -801,6 +806,12 @@ static int parse_section_header_ext(diskfile_backend *cfg, const char *line, con
switch (c) {
case '"':
+ if (&line[rpos-1] == last_quote) {
+ set_parse_error(cfg, 0, "Missing closing quotation mark in section header");
+ git_buf_free(&buf);
+ return -1;
+ }
+
case '\\':
break;
diff --git a/src/fileops.c b/src/fileops.c
index c01ff64db..7f8418d7a 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -222,6 +222,7 @@ int git_futils_writebuffer(
if ((error = p_write(fd, git_buf_cstr(buf), git_buf_len(buf))) < 0) {
giterr_set(GITERR_OS, "Could not write to '%s'", path);
(void)p_close(fd);
+ return error;
}
if ((error = p_close(fd)) < 0)
diff --git a/src/odb_pack.c b/src/odb_pack.c
index eec79259b..43880612a 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -259,23 +259,26 @@ static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backen
return git_odb__error_notfound("failed to find pack entry", oid);
}
-static unsigned pack_entry_find_prefix_inner(
- struct git_pack_entry *e,
- struct pack_backend *backend,
- const git_oid *short_oid,
- size_t len,
- struct git_pack_file *last_found)
+static int pack_entry_find_prefix(
+ struct git_pack_entry *e,
+ struct pack_backend *backend,
+ const git_oid *short_oid,
+ size_t len)
{
int error;
size_t i;
- unsigned found = 0;
+ git_oid found_full_oid = {{0}};
+ bool found = false;
+ struct git_pack_file *last_found = backend->last_found;
if (last_found) {
error = git_pack_entry_find(e, last_found, short_oid, len);
if (error == GIT_EAMBIGUOUS)
return error;
- if (!error)
- found = 1;
+ if (!error) {
+ git_oid_cpy(&found_full_oid, &e->sha1);
+ found = true;
+ }
}
for (i = 0; i < backend->packs.length; ++i) {
@@ -289,28 +292,16 @@ static unsigned pack_entry_find_prefix_inner(
if (error == GIT_EAMBIGUOUS)
return error;
if (!error) {
- if (++found > 1)
- break;
+ if (found && git_oid_cmp(&e->sha1, &found_full_oid))
+ return git_odb__error_ambiguous("found multiple pack entries");
+ git_oid_cpy(&found_full_oid, &e->sha1);
+ found = true;
backend->last_found = p;
}
}
- return found;
-}
-
-static int pack_entry_find_prefix(
- struct git_pack_entry *e,
- struct pack_backend *backend,
- const git_oid *short_oid,
- size_t len)
-{
- struct git_pack_file *last_found = backend->last_found;
- unsigned int found = pack_entry_find_prefix_inner(e, backend, short_oid, len, last_found);
-
if (!found)
return git_odb__error_notfound("no matching pack entry for prefix", short_oid);
- else if (found > 1)
- return git_odb__error_ambiguous("found multiple pack entries");
else
return 0;
}
diff --git a/src/pack.c b/src/pack.c
index 497db38e8..d7e6a1e94 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -822,7 +822,7 @@ void git_packfile_free(struct git_pack_file *p)
git_mwindow_free_all(&p->mwf);
- if (p->mwf.fd != -1)
+ if (p->mwf.fd >= 0)
p_close(p->mwf.fd);
pack_index_free(p);
@@ -905,7 +905,8 @@ static int packfile_open(struct git_pack_file *p)
cleanup:
giterr_set(GITERR_OS, "Invalid packfile '%s'", p->pack_name);
- p_close(p->mwf.fd);
+ if (p->mwf.fd >= 0)
+ p_close(p->mwf.fd);
p->mwf.fd = -1;
git_mutex_unlock(&p->lock);
diff --git a/src/submodule.c b/src/submodule.c
index b4e917561..40bda9a41 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -1025,6 +1025,7 @@ static int submodule_get(
if (!git_strmap_valid_index(smcfg, pos)) {
sm = submodule_alloc(repo, name);
+ GITERR_CHECK_ALLOC(sm);
/* insert value at name - if another thread beats us to it, then use
* their record and release our own.
@@ -1101,8 +1102,10 @@ static int submodule_load_from_config(
namestart = key + strlen("submodule.");
property = strrchr(namestart, '.');
- if (property == NULL)
+
+ if (!property || (property == namestart))
return 0;
+
property++;
is_path = (strcasecmp(property, "path") == 0);
diff --git a/tests-clar/config/read.c b/tests-clar/config/read.c
index 9f943d0f6..a18dca89b 100644
--- a/tests-clar/config/read.c
+++ b/tests-clar/config/read.c
@@ -431,10 +431,10 @@ void test_config_read__simple_read_from_specific_level(void)
git_config_free(cfg);
}
-static void clean_empty_config(void *unused)
+static void clean_test_config(void *unused)
{
GIT_UNUSED(unused);
- cl_fixture_cleanup("./empty");
+ cl_fixture_cleanup("./testconfig");
}
void test_config_read__can_load_and_parse_an_empty_config_file(void)
@@ -442,10 +442,21 @@ void test_config_read__can_load_and_parse_an_empty_config_file(void)
git_config *cfg;
int i;
- cl_set_cleanup(&clean_empty_config, NULL);
- cl_git_mkfile("./empty", "");
- cl_git_pass(git_config_open_ondisk(&cfg, "./empty"));
+ cl_set_cleanup(&clean_test_config, NULL);
+ cl_git_mkfile("./testconfig", "");
+ cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
cl_assert_equal_i(GIT_ENOTFOUND, git_config_get_int32(&i, cfg, "nope.neither"));
git_config_free(cfg);
}
+
+void test_config_read__corrupt_header(void)
+{
+ git_config *cfg;
+
+ cl_set_cleanup(&clean_test_config, NULL);
+ cl_git_mkfile("./testconfig", "[sneaky ] \"quoted closing quote mark\\\"");
+ cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig"));
+
+ git_config_free(cfg);
+}
diff --git a/tests-clar/odb/mixed.c b/tests-clar/odb/mixed.c
index da0ed97d7..dd4587831 100644
--- a/tests-clar/odb/mixed.c
+++ b/tests-clar/odb/mixed.c
@@ -16,10 +16,77 @@ void test_odb_mixed__cleanup(void)
void test_odb_mixed__dup_oid(void) {
const char hex[] = "ce013625030ba8dba906f756967f9e9ca394464a";
+ const char short_hex[] = "ce01362";
git_oid oid;
git_odb_object *obj;
+
cl_git_pass(git_oid_fromstr(&oid, hex));
cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, GIT_OID_HEXSZ));
+ cl_git_pass(git_oid_fromstrn(&oid, short_hex, sizeof(short_hex) - 1));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, sizeof(short_hex) - 1));
git_odb_object_free(obj);
}
+/* some known sha collisions of file content:
+ * 'aabqhq' and 'aaazvc' with prefix 'dea509d0' (+ '9' and + 'b')
+ * 'aaeufo' and 'aaaohs' with prefix '81b5bff5' (+ 'f' and + 'b')
+ * 'aafewy' and 'aaepta' with prefix '739e3c4c'
+ * 'aahsyn' and 'aadrjg' with prefix '0ddeaded' (+ '9' and + 'e')
+ */
+
+void test_odb_mixed__dup_oid_prefix_0(void) {
+ char hex[10];
+ git_oid oid;
+ git_odb_object *obj;
+
+ /* ambiguous in the same pack file */
+
+ strncpy(hex, "dea509d0", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_assert_equal_i(
+ GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+
+ strncpy(hex, "dea509d09", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+ git_odb_object_free(obj);
+
+ strncpy(hex, "dea509d0b", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+ git_odb_object_free(obj);
+
+ /* ambiguous in different pack files */
+
+ strncpy(hex, "81b5bff5", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_assert_equal_i(
+ GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+
+ strncpy(hex, "81b5bff5b", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+ git_odb_object_free(obj);
+
+ strncpy(hex, "81b5bff5f", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+ git_odb_object_free(obj);
+
+ /* ambiguous in pack file and loose */
+
+ strncpy(hex, "0ddeaded", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_assert_equal_i(
+ GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+
+ strncpy(hex, "0ddeaded9", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+ git_odb_object_free(obj);
+
+ strncpy(hex, "0ddeadede", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+ git_odb_object_free(obj);
+}
diff --git a/tests-clar/resources/duplicate.git/config b/tests-clar/resources/duplicate.git/config
index 515f48362..a4ef456cb 100644
--- a/tests-clar/resources/duplicate.git/config
+++ b/tests-clar/resources/duplicate.git/config
@@ -1,5 +1,5 @@
[core]
repositoryformatversion = 0
filemode = true
- bare = false
+ bare = true
logallrefupdates = true
diff --git a/tests-clar/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea b/tests-clar/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea
new file mode 100644
index 000000000..47c2a631a
--- /dev/null
+++ b/tests-clar/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea
Binary files differ
diff --git a/tests-clar/resources/duplicate.git/objects/info/packs b/tests-clar/resources/duplicate.git/objects/info/packs
index 3696a7d36..d0fdf905e 100644
--- a/tests-clar/resources/duplicate.git/objects/info/packs
+++ b/tests-clar/resources/duplicate.git/objects/info/packs
@@ -1,2 +1,3 @@
P pack-e87994ad581c9af946de0eb890175c08cd005f38.pack
+P pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack
diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx b/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx
new file mode 100644
index 000000000..acbed82b6
--- /dev/null
+++ b/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx
Binary files differ
diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack b/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack
new file mode 100644
index 000000000..652b0c91f
--- /dev/null
+++ b/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack
Binary files differ
diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx b/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx
new file mode 100644
index 000000000..fff685554
--- /dev/null
+++ b/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx
Binary files differ
diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack b/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack
new file mode 100644
index 000000000..e3e5f0e09
--- /dev/null
+++ b/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack
Binary files differ
diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx b/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx
new file mode 100644
index 000000000..9f78f6e0f
--- /dev/null
+++ b/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx
Binary files differ
diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack b/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack
new file mode 100644
index 000000000..d1dd3b61a
--- /dev/null
+++ b/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack
Binary files differ
diff --git a/tests-clar/resources/duplicate.git/refs/heads/dummy-marker.txt b/tests-clar/resources/duplicate.git/refs/heads/dummy-marker.txt
new file mode 100644
index 000000000..421376db9
--- /dev/null
+++ b/tests-clar/resources/duplicate.git/refs/heads/dummy-marker.txt
@@ -0,0 +1 @@
+dummy
diff --git a/tests-clar/resources/submodules/gitmodules b/tests-clar/resources/submodules/gitmodules
index 1262f8bb0..2798b696c 100644
--- a/tests-clar/resources/submodules/gitmodules
+++ b/tests-clar/resources/submodules/gitmodules
@@ -1,3 +1,6 @@
[submodule "testrepo"]
path = testrepo
+ url =
+[submodule ""]
+ path = testrepo
url = \ No newline at end of file