Merge remote-tracking branch 'carlosmn/empty-name' into empty-name
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5a228e3..402ff22 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -131,7 +131,9 @@
 IF (ZLIB_FOUND)
 	INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS})
 	LINK_LIBRARIES(${ZLIB_LIBRARIES})
-ELSE()
+	# Fake the message CMake would have shown
+	MESSAGE("-- Found zlib: ${ZLIB_LIBRARY}")
+ELSEIF (NOT ZLIB_LIBRARY)
 	MESSAGE( "zlib was not found; using bundled 3rd-party sources." )
 	INCLUDE_DIRECTORIES(deps/zlib)
 	ADD_DEFINITIONS(-DNO_VIZ -DSTDC -DNO_GZIP)
diff --git a/examples/general.c b/examples/general.c
index adc7ed8..d7a5847 100644
--- a/examples/general.c
+++ b/examples/general.c
@@ -453,7 +453,7 @@
   // Here we will implement something like `git for-each-ref` simply listing
   // out all available references and the object SHA they resolve to.
   git_strarray ref_list;
-  git_reference_list(&ref_list, repo, GIT_REF_LISTALL);
+  git_reference_list(&ref_list, repo);
 
   const char *refname;
   git_reference *ref;
diff --git a/include/git2/refs.h b/include/git2/refs.h
index e1d4253..754bda7 100644
--- a/include/git2/refs.h
+++ b/include/git2/refs.h
@@ -55,6 +55,19 @@
 	git_oid *out, git_repository *repo, const char *name);
 
 /**
+ * Lookup a reference by DWIMing its short name
+ *
+ * Apply the git precendence rules to the given shorthand to determine
+ * which reference the user is refering to.
+ *
+ * @param out pointer in which to store the reference
+ * @param repo the repository in which to look
+ * @param shrothand the short name for the reference
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_reference_dwim(git_reference **out, git_repository *repo, const char *shorthand);
+
+/**
  * Create a new symbolic reference.
  *
  * A symbolic reference is a reference name that refers to another
@@ -284,12 +297,6 @@
 /**
  * Fill a list with all the references that can be found in a repository.
  *
- * Using the `list_flags` parameter, the listed references may be filtered
- * by type (`GIT_REF_OID` or `GIT_REF_SYMBOLIC`) or using a bitwise OR of
- * `git_ref_t` values.  To include packed refs, include `GIT_REF_PACKED`.
- * For convenience, use the value `GIT_REF_LISTALL` to obtain all
- * references, including packed ones.
- *
  * The string array will be filled with the names of all references; these
  * values are owned by the user and should be free'd manually when no
  * longer needed, using `git_strarray_free()`.
@@ -297,36 +304,27 @@
  * @param array Pointer to a git_strarray structure where
  *		the reference names will be stored
  * @param repo Repository where to find the refs
- * @param list_flags Filtering flags for the reference listing
  * @return 0 or an error code
  */
-GIT_EXTERN(int) git_reference_list(git_strarray *array, git_repository *repo, unsigned int list_flags);
+GIT_EXTERN(int) git_reference_list(git_strarray *array, git_repository *repo);
 
 typedef int (*git_reference_foreach_cb)(const char *refname, void *payload);
 
 /**
  * Perform a callback on each reference in the repository.
  *
- * Using the `list_flags` parameter, the references may be filtered by
- * type (`GIT_REF_OID` or `GIT_REF_SYMBOLIC`) or using a bitwise OR of
- * `git_ref_t` values.  To include packed refs, include `GIT_REF_PACKED`.
- * For convenience, use the value `GIT_REF_LISTALL` to obtain all
- * references, including packed ones.
- *
  * The `callback` function will be called for each reference in the
  * repository, receiving the name of the reference and the `payload` value
  * passed to this method.  Returning a non-zero value from the callback
  * will terminate the iteration.
  *
  * @param repo Repository where to find the refs
- * @param list_flags Filtering flags for the reference listing.
  * @param callback Function which will be called for every listed ref
  * @param payload Additional data to pass to the callback
  * @return 0 on success, GIT_EUSER on non-zero callback, or error code
  */
 GIT_EXTERN(int) git_reference_foreach(
 	git_repository *repo,
-	unsigned int list_flags,
 	git_reference_foreach_cb callback,
 	void *payload);
 
@@ -347,6 +345,31 @@
 GIT_EXTERN(int) git_reference_cmp(git_reference *ref1, git_reference *ref2);
 
 /**
+ * Create an iterator for the repo's references
+ *
+ * @param out pointer in which to store the iterator
+ * @param repo the repository
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_reference_iterator_new(git_reference_iterator **out, git_repository *repo);
+
+/**
+ * Get the next reference name
+ *
+ * @param out pointer in which to store the string
+ * @param iter the iterator
+ * @param 0, GIT_ITEROVER if there are no more; or an error code
+ */
+GIT_EXTERN(int) git_reference_next(const char **out, git_reference_iterator *iter);
+
+/**
+ * Free the iterator and its associated resources
+ *
+ * @param iter the iterator to free
+ */
+GIT_EXTERN(void) git_reference_iterator_free(git_reference_iterator *iter);
+
+/**
  * Perform a callback on each reference in the repository whose name
  * matches the given pattern.
  *
@@ -360,7 +383,6 @@
  *
  * @param repo Repository where to find the refs
  * @param glob Pattern to match (fnmatch-style) against reference name.
- * @param list_flags Filtering flags for the reference listing.
  * @param callback Function which will be called for every listed ref
  * @param payload Additional data to pass to the callback
  * @return 0 on success, GIT_EUSER on non-zero callback, or error code
@@ -368,7 +390,6 @@
 GIT_EXTERN(int) git_reference_foreach_glob(
 	git_repository *repo,
 	const char *glob,
-	unsigned int list_flags,
 	git_reference_foreach_cb callback,
 	void *payload);
 
diff --git a/include/git2/repository.h b/include/git2/repository.h
index cd238e1..e0464c6 100644
--- a/include/git2/repository.h
+++ b/include/git2/repository.h
@@ -460,10 +460,19 @@
  * Use this function to get the contents of this file. Don't forget to
  * remove the file after you create the commit.
  *
+ * If the repository message exists and there are no errors reading it, this
+ * returns the bytes needed to store the message in memory (i.e. message
+ * file size plus one terminating NUL byte).  That value is returned even if
+ * `out` is NULL or `len` is shorter than the necessary size.
+ *
+ * The `out` buffer will *always* be NUL terminated, even if truncation
+ * occurs.
+ *
  * @param out Buffer to write data into or NULL to just read required size
- * @param len Length of buffer in bytes
+ * @param len Length of `out` buffer in bytes
  * @param repo Repository to read prepared message from
- * @return Bytes written to buffer, GIT_ENOTFOUND if no message, or -1 on error
+ * @return GIT_ENOUTFOUND if no message exists, other value < 0 for other
+ *         errors, or total bytes in message (may be > `len`) on success
  */
 GIT_EXTERN(int) git_repository_message(char *out, size_t len, git_repository *repo);
 
diff --git a/include/git2/sys/refdb_backend.h b/include/git2/sys/refdb_backend.h
index d5f599f..8dbf38c 100644
--- a/include/git2/sys/refdb_backend.h
+++ b/include/git2/sys/refdb_backend.h
@@ -20,6 +20,23 @@
  */
 GIT_BEGIN_DECL
 
+
+/**
+ * Every backend's iterator must have a pointer to itself as the first
+ * element, so the API can talk to it. You'd define your iterator as
+ *
+ *     struct my_iterator {
+ *             git_reference_iterator parent;
+ *             ...
+ *     }
+ *
+ * and assign `iter->parent.backend` to your `git_refdb_backend`.
+ */
+struct git_reference_iterator {
+	git_refdb_backend *backend;
+	char *glob;
+};
+
 /** An instance for a custom backend */
 struct git_refdb_backend {
     unsigned int version;
@@ -43,29 +60,42 @@
 		const char *ref_name);
 
 	/**
-	 * Enumerates each reference in the refdb.  A refdb implementation must
-	 * provide this function.
+	 * Allocate an iterator object for the backend.
+	 *
+	 * A refdb implementation must provide this function.
 	 */
-	int (*foreach)(
-		git_refdb_backend *backend,
-		unsigned int list_flags,
-		git_reference_foreach_cb callback,
-		void *payload);
+	int (*iterator)(
+		git_reference_iterator **iter,
+		struct git_refdb_backend *backend);
 
 	/**
-	 * Enumerates each reference in the refdb that matches the given
-	 * glob string.  A refdb implementation may provide this function;
-	 * if it is not provided, foreach will be used and the results filtered
-	 * against the glob.
+	 * Allocate a glob-filtering iterator object for the backend.
+	 *
+	 * A refdb implementation may provide this function. If it's
+	 * not available, the glob matching will be done by the frontend.
 	 */
-	int (*foreach_glob)(
-		git_refdb_backend *backend,
-		const char *glob,
-		unsigned int list_flags,
-		git_reference_foreach_cb callback,
-		void *payload);
+	int (*iterator_glob)(
+		git_reference_iterator **iter,
+		struct git_refdb_backend *backend,
+		const char *glob);
 
 	/**
+	 * Return the current value and advance the iterator.
+	 *
+	 * A refdb implementation must provide this function.
+	 */
+	int (*next)(
+		const char **name,
+		git_reference_iterator *iter);
+
+	/**
+	 * Free the iterator
+	 *
+	 * A refdb implementation must provide this function.
+	 */
+	void (*iterator_free)(
+		git_reference_iterator *iter);
+	/*
 	 * Writes the given reference to the refdb.  A refdb implementation
 	 * must provide this function.
 	 */
diff --git a/include/git2/types.h b/include/git2/types.h
index aca9ed9..43751d3 100644
--- a/include/git2/types.h
+++ b/include/git2/types.h
@@ -165,6 +165,10 @@
 /** In-memory representation of a reference. */
 typedef struct git_reference git_reference;
 
+/** Iterator for references */
+typedef struct git_reference_iterator  git_reference_iterator;
+
+
 /** Basic type of any Git reference. */
 typedef enum {
 	GIT_REF_INVALID = 0, /** Invalid reference */
diff --git a/src/branch.c b/src/branch.c
index 8302949..dd6dc68 100644
--- a/src/branch.c
+++ b/src/branch.c
@@ -124,40 +124,43 @@
 	return error;
 }
 
-typedef struct {
-	git_branch_foreach_cb branch_cb;
-	void *callback_payload;
-	unsigned int branch_type;
-} branch_foreach_filter;
-
-static int branch_foreach_cb(const char *branch_name, void *payload)
-{
-	branch_foreach_filter *filter = (branch_foreach_filter *)payload;
-
-	if (filter->branch_type & GIT_BRANCH_LOCAL &&
-		git__prefixcmp(branch_name, GIT_REFS_HEADS_DIR) == 0)
-		return filter->branch_cb(branch_name + strlen(GIT_REFS_HEADS_DIR), GIT_BRANCH_LOCAL, filter->callback_payload);
-
-	if (filter->branch_type & GIT_BRANCH_REMOTE &&
-		git__prefixcmp(branch_name, GIT_REFS_REMOTES_DIR) == 0)
-		return filter->branch_cb(branch_name + strlen(GIT_REFS_REMOTES_DIR), GIT_BRANCH_REMOTE, filter->callback_payload);
-
-	return 0;
-}
-
 int git_branch_foreach(
 	git_repository *repo,
 	unsigned int list_flags,
-	git_branch_foreach_cb branch_cb,
+	git_branch_foreach_cb callback,
 	void *payload)
 {
-	branch_foreach_filter filter;
+	git_reference_iterator *iter;
+	const char *name;
+	int error;
 
-	filter.branch_cb = branch_cb;
-	filter.branch_type = list_flags;
-	filter.callback_payload = payload;
+	if (git_reference_iterator_new(&iter, repo) < 0)
+		return -1;
 
-	return git_reference_foreach(repo, GIT_REF_LISTALL, &branch_foreach_cb, (void *)&filter);
+	while ((error = git_reference_next(&name, iter)) == 0) {
+		if (list_flags & GIT_BRANCH_LOCAL &&
+		    git__prefixcmp(name, GIT_REFS_HEADS_DIR) == 0) {
+			if (callback(name + strlen(GIT_REFS_HEADS_DIR), GIT_BRANCH_LOCAL, payload)) {
+				error = GIT_EUSER;
+				break;
+			}
+		}
+
+		if (list_flags & GIT_BRANCH_REMOTE &&
+		    git__prefixcmp(name, GIT_REFS_REMOTES_DIR) == 0) {
+			if (callback(name + strlen(GIT_REFS_REMOTES_DIR), GIT_BRANCH_REMOTE, payload)) {
+				error = GIT_EUSER;
+				break;
+			}
+		}
+	}
+
+	if (error == GIT_ITEROVER)
+		error = 0;
+
+	git_reference_iterator_free(iter);
+	return error;
+
 }
 
 int git_branch_move(
diff --git a/src/clone.c b/src/clone.c
index 38c0d40..499195d 100644
--- a/src/clone.c
+++ b/src/clone.c
@@ -243,7 +243,6 @@
 	/* Not master. Check all the other refs. */
 	if (git_reference_foreach(
 		repo,
-		GIT_REF_LISTALL,
 		reference_matches_remote_head,
 		&head_info) < 0)
 			goto cleanup;
@@ -355,7 +354,7 @@
 		const git_clone_options *options)
 {
 	int retcode = GIT_ERROR;
-	git_remote *origin;
+	git_remote *origin = NULL;
 
 	/* Construct an origin remote */
 	if ((retcode = create_and_configure_origin(&origin, repo, url, options)) < 0)
diff --git a/src/commit.c b/src/commit.c
index 3dc647c..be6e32c 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -292,7 +292,7 @@
 	const git_commit *commit,
 	unsigned int n)
 {
-	git_commit *current, *parent;
+	git_commit *current, *parent = NULL;
 	int error;
 
 	assert(ancestor && commit);
diff --git a/src/config_file.c b/src/config_file.c
index a9a40c3..e57cd1e 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -296,7 +296,7 @@
 
 static int config_set(git_config_backend *cfg, const char *name, const char *value)
 {
-	cvar_t *var = NULL, *old_var;
+	cvar_t *var = NULL, *old_var = NULL;
 	diskfile_backend *b = (diskfile_backend *)cfg;
 	char *key, *esc_value = NULL;
 	khiter_t pos;
diff --git a/src/diff.c b/src/diff.c
index e0dff9c..f466546 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -535,7 +535,7 @@
 static bool diff_time_eq(
 	const git_index_time *a, const git_index_time *b, bool use_nanos)
 {
-	return a->seconds == a->seconds &&
+	return a->seconds == b->seconds &&
 		(!use_nanos || a->nanoseconds == b->nanoseconds);
 }
 
diff --git a/src/diff_output.c b/src/diff_output.c
index 2214ae1..07fcf47 100644
--- a/src/diff_output.c
+++ b/src/diff_output.c
@@ -593,6 +593,8 @@
 		delta->new_file.flags |= GIT_DIFF_FLAG__NO_DATA;
 		break;
 	case GIT_DELTA_MODIFIED:
+	case GIT_DELTA_COPIED:
+	case GIT_DELTA_RENAMED:
 		break;
 	case GIT_DELTA_UNTRACKED:
 		delta->old_file.flags |= GIT_DIFF_FLAG__NO_DATA;
diff --git a/src/object.c b/src/object.c
index a6807f2..9b8ccdd 100644
--- a/src/object.c
+++ b/src/object.c
@@ -117,7 +117,7 @@
 {
 	git_object *object = NULL;
 	git_odb *odb = NULL;
-	git_odb_object *odb_obj;
+	git_odb_object *odb_obj = NULL;
 	int error = 0;
 
 	assert(repo && object_out && id);
diff --git a/src/push.c b/src/push.c
index 0499d86..452d717 100644
--- a/src/push.c
+++ b/src/push.c
@@ -180,7 +180,7 @@
 	git_buf remote_ref_name = GIT_BUF_INIT;
 	size_t i, j;
 	git_refspec *fetch_spec;
-	push_spec *push_spec;
+	push_spec *push_spec = NULL;
 	git_reference *remote_ref;
 	push_status *status;
 	int error = 0;
diff --git a/src/refdb.c b/src/refdb.c
index 33a1934..9f9037c 100644
--- a/src/refdb.c
+++ b/src/refdb.c
@@ -124,15 +124,62 @@
 	return error;
 }
 
-int git_refdb_foreach(
-	git_refdb *db,
-	unsigned int list_flags,
-	git_reference_foreach_cb callback,
-	void *payload)
+int git_refdb_iterator(git_reference_iterator **out, git_refdb *db)
 {
-	assert(db && db->backend);
+	if (!db->backend || !db->backend->iterator) {
+		giterr_set(GITERR_REFERENCE, "This backend doesn't support iterators");
+		return -1;
+	}
 
-	return db->backend->foreach(db->backend, list_flags, callback, payload);
+	if (db->backend->iterator(out, db->backend) < 0)
+		return -1;
+
+	return 0;
+}
+
+int git_refdb_iterator_glob(git_reference_iterator **out, git_refdb *db, const char *glob)
+{
+	if (!db->backend) {
+		giterr_set(GITERR_REFERENCE, "There are no backends loaded");
+		return -1;
+	}
+
+	if (db->backend->iterator_glob)
+		return db->backend->iterator_glob(out, db->backend, glob);
+
+	/* If the backend doesn't support glob-filtering themselves, we have to do it */
+	if (db->backend->iterator(out, db->backend) < 0)
+		return -1;
+
+	(*out)->glob = git__strdup(glob);
+	if (!(*out)->glob) {
+		db->backend->iterator_free(*out);
+		return -1;
+	}
+
+	return 0;
+}
+
+int git_refdb_next(const char **out, git_reference_iterator *iter)
+{
+	int error;
+
+	if (!iter->glob)
+		return iter->backend->next(out, iter);
+
+	/* If the iterator has a glob, we need to filter */
+	while ((error = iter->backend->next(out, iter)) == 0) {
+		if (!p_fnmatch(iter->glob, *out, 0))
+			break;
+	}
+
+	return error;
+}
+
+void git_refdb_iterator_free(git_reference_iterator *iter)
+{
+	git__free(iter->glob);
+	iter->backend->iterator_free(iter);
 }
 
 struct glob_cb_data {
@@ -141,43 +188,6 @@
 	void *payload;
 };
 
-static int fromglob_cb(const char *reference_name, void *payload)
-{
-	struct glob_cb_data *data = (struct glob_cb_data *)payload;
-
-	if (!p_fnmatch(data->glob, reference_name, 0))
-		return data->callback(reference_name, data->payload);
-
-	return 0;
-}
-
-int git_refdb_foreach_glob(
-	git_refdb *db,
-	const char *glob,
-	unsigned int list_flags,
-	git_reference_foreach_cb callback,
-	void *payload)
-{
-	int error;
-	struct glob_cb_data data;
-
-	assert(db && db->backend && glob && callback);
-
-	if(db->backend->foreach_glob != NULL)
-		error = db->backend->foreach_glob(db->backend,
-			glob, list_flags, callback, payload);
-	else {
-		data.glob = glob;
-		data.callback = callback;
-		data.payload = payload;
-
-		error = db->backend->foreach(db->backend,
-			list_flags, fromglob_cb, &data);
-	}
-
-	return error;
-}
-
 int git_refdb_write(git_refdb *db, const git_reference *ref)
 {
 	assert(db && db->backend);
diff --git a/src/refdb.h b/src/refdb.h
index 047113a..2edd05d 100644
--- a/src/refdb.h
+++ b/src/refdb.h
@@ -26,18 +26,10 @@
 	git_refdb *refdb,
 	const char *ref_name);
 
-int git_refdb_foreach(
-	git_refdb *refdb,
-	unsigned int list_flags,
-	git_reference_foreach_cb callback,
-	void *payload);
-
-int git_refdb_foreach_glob(
-	git_refdb *refdb,
-	const char *glob,
-	unsigned int list_flags,
-	git_reference_foreach_cb callback,
-	void *payload);
+int git_refdb_iterator(git_reference_iterator **out, git_refdb *db);
+int git_refdb_iterator_glob(git_reference_iterator **out, git_refdb *db, const char *glob);
+int git_refdb_next(const char **out, git_reference_iterator *iter);
+void git_refdb_iterator_free(git_reference_iterator *iter);
 
 int git_refdb_write(git_refdb *refdb, const git_reference *ref);
 
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index c0a32ba..c462a42 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -13,6 +13,7 @@
 #include "reflog.h"
 #include "refdb.h"
 #include "refdb_fs.h"
+#include "iterator.h"
 
 #include <git2/tag.h>
 #include <git2/object.h>
@@ -106,7 +107,7 @@
 
 	refname_len = refname_end - refname_begin;
 
-	ref = git__malloc(sizeof(struct packref) + refname_len + 1);
+	ref = git__calloc(1, sizeof(struct packref) + refname_len + 1);
 	GITERR_CHECK_ALLOC(ref);
 
 	memcpy(ref->name, refname_begin, refname_len);
@@ -180,6 +181,9 @@
 		GITERR_CHECK_ALLOC(ref_cache->packfile);
 	}
 
+	if (backend->path == NULL)
+		return 0;
+
 	result = reference_read(&packfile, &ref_cache->packfile_time,
 		backend->path, GIT_PACKEDREFS_FILE, &updated);
 
@@ -316,7 +320,7 @@
 	git_buf_rtrim(&ref_file);
 
 	name_len = strlen(name);
-	ref = git__malloc(sizeof(struct packref) + name_len + 1);
+	ref = git__calloc(1, sizeof(struct packref) + name_len + 1);
 	GITERR_CHECK_ALLOC(ref);
 
 	memcpy(ref->name, name, name_len);
@@ -558,65 +562,21 @@
 	int callback_error;
 };
 
-static git_ref_t loose_guess_rtype(const git_buf *full_path)
+typedef struct {
+	git_reference_iterator parent;
+	unsigned int loose;
+	/* packed */
+	git_strmap *h;
+	khiter_t k;
+	/* loose */
+	git_iterator *fsiter;
+	git_buf buf;
+} refdb_fs_iter;
+
+static int refdb_fs_backend__iterator(git_reference_iterator **out, git_refdb_backend *_backend)
 {
-	git_buf ref_file = GIT_BUF_INIT;
-	git_ref_t type;
-
-	type = GIT_REF_INVALID;
-
-	if (git_futils_readbuffer(&ref_file, full_path->ptr) == 0) {
-		if (git__prefixcmp((const char *)(ref_file.ptr), GIT_SYMREF) == 0)
-			type = GIT_REF_SYMBOLIC;
-		else
-			type = GIT_REF_OID;
-	}
-
-	git_buf_free(&ref_file);
-	return type;
-}
-
-static int _dirent_loose_listall(void *_data, git_buf *full_path)
-{
-	struct dirent_list_data *data = (struct dirent_list_data *)_data;
-	const char *file_path = full_path->ptr + data->repo_path_len;
-
-	if (git_path_isdir(full_path->ptr) == true)
-		return git_path_direach(full_path, _dirent_loose_listall, _data);
-
-	/* do not add twice a reference that exists already in the packfile */
-	if (git_strmap_exists(data->backend->refcache.packfile, file_path))
-		return 0;
-
-	if (data->list_type != GIT_REF_LISTALL) {
-		if ((data->list_type & loose_guess_rtype(full_path)) == 0)
-			return 0; /* we are filtering out this reference */
-	}
-
-	/* Locked references aren't returned */
-	if (!git__suffixcmp(file_path, GIT_FILELOCK_EXTENSION))
-		return 0;
-
-	if (data->callback(file_path, data->callback_payload))
-		data->callback_error = GIT_EUSER;
-
-	return data->callback_error;
-}
-
-static int refdb_fs_backend__foreach(
-	git_refdb_backend *_backend,
-	unsigned int list_type,
-	git_reference_foreach_cb callback,
-	void *payload)
-{
+	refdb_fs_iter *iter;
 	refdb_fs_backend *backend;
-	int result;
-	struct dirent_list_data data;
-	git_buf refs_path = GIT_BUF_INIT;
-	const char *ref_name;
-	void *ref = NULL;
-
-	GIT_UNUSED(ref);
 
 	assert(_backend);
 	backend = (refdb_fs_backend *)_backend;
@@ -624,32 +584,107 @@
 	if (packed_load(backend) < 0)
 		return -1;
 
-	/* list all the packed references first */
-	if (list_type & GIT_REF_OID) {
-		git_strmap_foreach(backend->refcache.packfile, ref_name, ref, {
-			if (callback(ref_name, payload))
-				return GIT_EUSER;
-		});
+	iter = git__calloc(1, sizeof(refdb_fs_iter));
+	GITERR_CHECK_ALLOC(iter);
+
+	iter->parent.backend = _backend;
+	iter->h = backend->refcache.packfile;
+	iter->k = kh_begin(backend->refcache.packfile);
+
+	*out = (git_reference_iterator *)iter;
+
+	return 0;
+}
+
+static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter)
+{
+	refdb_fs_iter *iter = (refdb_fs_iter *) _iter;
+
+	git_buf_free(&iter->buf);
+	git_iterator_free(iter->fsiter);
+	git__free(iter);
+}
+
+static int iter_packed(const char **out, refdb_fs_iter *iter)
+{
+	/* Move forward to the next entry */
+	while (!kh_exist(iter->h, iter->k)) {
+		iter->k++;
+		if (iter->k == kh_end(iter->h))
+			return GIT_ITEROVER;
 	}
 
-	/* now list the loose references, trying not to
-	 * duplicate the ref names already in the packed-refs file */
+	*out = kh_key(iter->h, iter->k);
+	iter->k++;
 
-	data.repo_path_len = strlen(backend->path);
-	data.list_type = list_type;
-	data.backend = backend;
-	data.callback = callback;
-	data.callback_payload = payload;
-	data.callback_error = 0;
+	return 0;
+}
 
-	if (git_buf_joinpath(&refs_path, backend->path, GIT_REFS_DIR) < 0)
+static int iter_loose(const char **out, refdb_fs_iter *iter)
+{
+	const git_index_entry *entry;
+	int retry;
+	git_strmap *packfile_refs;
+	refdb_fs_backend *backend = (refdb_fs_backend *) iter->parent.backend;
+
+	packfile_refs = backend->refcache.packfile;
+
+	do {
+		khiter_t pos;
+		if (git_iterator_current(&entry, iter->fsiter) < 0)
+			return -1;
+
+		git_buf_clear(&iter->buf);
+		if (!entry)
+			return GIT_ITEROVER;
+
+		if (git_buf_printf(&iter->buf, "refs/%s", entry->path) < 0)
+			return -1;
+
+		git_iterator_advance(NULL, iter->fsiter);
+
+		/* Skip this one if we already listed it in packed */
+		pos = git_strmap_lookup_index(packfile_refs, git_buf_cstr(&iter->buf));
+		retry = 0;
+		if (git_strmap_valid_index(packfile_refs, pos) ||
+		    !git_reference_is_valid_name(git_buf_cstr(&iter->buf)))
+			retry = 1;
+
+		*out = git_buf_cstr(&iter->buf);
+	} while (retry);
+
+	return 0;
+}
+
+static int iter_loose_setup(refdb_fs_iter *iter)
+{
+	refdb_fs_backend *backend = (refdb_fs_backend *) iter->parent.backend;
+
+	git_buf_clear(&iter->buf);
+	if (git_buf_printf(&iter->buf, "%s/refs", backend->path) < 0)
 		return -1;
 
-	result = git_path_direach(&refs_path, _dirent_loose_listall, &data);
+	return git_iterator_for_filesystem(&iter->fsiter, git_buf_cstr(&iter->buf), 0, NULL, NULL);
+}
 
-	git_buf_free(&refs_path);
+static int refdb_fs_backend__next(const char **out, git_reference_iterator *_iter)
+{
+	refdb_fs_iter *iter = (refdb_fs_iter *)_iter;
 
-	return data.callback_error ? GIT_EUSER : result;
+	if (iter->loose)
+		return iter_loose(out, iter);
+
+	if (iter->k != kh_end(iter->h)) {
+		int error = iter_packed(out, iter);
+		if (error != GIT_ITEROVER)
+			return error;
+	}
+
+	if (iter_loose_setup(iter) < 0)
+		return -1;
+	iter->loose = 1;
+
+	return iter_loose(out, iter);
 }
 
 static int loose_write(refdb_fs_backend *backend, const git_reference *ref)
@@ -1027,6 +1062,10 @@
 {
 	char *parts, *start, *end; 
 
+	/* Not all repositories have a path */
+	if (repo->path_repository == NULL)
+		return 0;
+
 	/* Load the path to the repo first */
 	git_buf_puts(path, repo->path_repository);
 
@@ -1081,7 +1120,9 @@
 
 	backend->parent.exists = &refdb_fs_backend__exists;
 	backend->parent.lookup = &refdb_fs_backend__lookup;
-	backend->parent.foreach = &refdb_fs_backend__foreach;
+	backend->parent.iterator = &refdb_fs_backend__iterator;
+	backend->parent.next = &refdb_fs_backend__next;
+	backend->parent.iterator_free = &refdb_fs_backend__iterator_free;
 	backend->parent.write = &refdb_fs_backend__write;
 	backend->parent.delete = &refdb_fs_backend__delete;
 	backend->parent.compress = &refdb_fs_backend__compress;
diff --git a/src/refs.c b/src/refs.c
index 8bba394..9c6c5c6 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -139,7 +139,7 @@
 	data.available = 1;
 
 	error = git_reference_foreach(
-		repo, GIT_REF_LISTALL, _reference_available_cb, (void *)&data);
+		repo, _reference_available_cb, (void *)&data);
 	if (error < 0)
 		return error;
 
@@ -290,6 +290,67 @@
 	return 0;
 }
 
+int git_reference_dwim(git_reference **out, git_repository *repo, const char *refname)
+{
+	int error = 0, i;
+	bool fallbackmode = true, foundvalid = false;
+	git_reference *ref;
+	git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT;
+
+	static const char* formatters[] = {
+		"%s",
+		GIT_REFS_DIR "%s",
+		GIT_REFS_TAGS_DIR "%s",
+		GIT_REFS_HEADS_DIR "%s",
+		GIT_REFS_REMOTES_DIR "%s",
+		GIT_REFS_REMOTES_DIR "%s/" GIT_HEAD_FILE,
+		NULL
+	};
+
+	if (*refname)
+		git_buf_puts(&name, refname);
+	else {
+		git_buf_puts(&name, GIT_HEAD_FILE);
+		fallbackmode = false;
+	}
+
+	for (i = 0; formatters[i] && (fallbackmode || i == 0); i++) {
+
+		git_buf_clear(&refnamebuf);
+
+		if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0)
+			goto cleanup;
+
+		if (!git_reference_is_valid_name(git_buf_cstr(&refnamebuf))) {
+			error = GIT_EINVALIDSPEC;
+			continue;
+		}
+		foundvalid = true;
+
+		error = git_reference_lookup_resolved(&ref, repo, git_buf_cstr(&refnamebuf), -1);
+
+		if (!error) {
+			*out = ref;
+			error = 0;
+			goto cleanup;
+		}
+
+		if (error != GIT_ENOTFOUND)
+			goto cleanup;
+	}
+
+cleanup:
+	if (error && !foundvalid) {
+		/* never found a valid reference name */
+		giterr_set(GITERR_REFERENCE,
+			"Could not use '%s' as valid reference name", git_buf_cstr(&name));
+	}
+
+	git_buf_free(&name);
+	git_buf_free(&refnamebuf);
+	return error;
+}
+
 /**
  * Getters
  */
@@ -558,14 +619,59 @@
 
 int git_reference_foreach(
 	git_repository *repo,
-	unsigned int list_flags,
 	git_reference_foreach_cb callback,
 	void *payload)
 {
-	git_refdb *refdb;
-	git_repository_refdb__weakptr(&refdb, repo);
+	git_reference_iterator *iter;
+	const char *name;
+	int error;
 
-	return git_refdb_foreach(refdb, list_flags, callback, payload);
+	if (git_reference_iterator_new(&iter, repo) < 0)
+		return -1;
+
+	while ((error = git_reference_next(&name, iter)) == 0) {
+		if (callback(name, payload)) {
+			error = GIT_EUSER;
+			goto out;
+		}
+	}
+
+	if (error == GIT_ITEROVER)
+		error = 0;
+
+out:
+	git_reference_iterator_free(iter);
+	return error;
+}
+
+int git_reference_iterator_new(git_reference_iterator **out, git_repository *repo)
+{
+	git_refdb *refdb;
+
+	if (git_repository_refdb__weakptr(&refdb, repo) < 0)
+		return -1;
+
+	return git_refdb_iterator(out, refdb);
+}
+
+int git_reference_iterator_glob_new(git_reference_iterator **out, git_repository *repo, const char *glob)
+{
+	git_refdb *refdb;
+
+	if (git_repository_refdb__weakptr(&refdb, repo) < 0)
+		return -1;
+
+	return git_refdb_iterator_glob(out, refdb, glob);
+}
+
+int git_reference_next(const char **out, git_reference_iterator *iter)
+{
+	return git_refdb_next(out, iter);
+}
+
+void git_reference_iterator_free(git_reference_iterator *iter)
+{
+	git_refdb_iterator_free(iter);
 }
 
 static int cb__reflist_add(const char *ref, void *data)
@@ -575,8 +681,7 @@
 
 int git_reference_list(
 	git_strarray *array,
-	git_repository *repo,
-	unsigned int list_flags)
+	git_repository *repo)
 {
 	git_vector ref_list;
 
@@ -589,7 +694,7 @@
 		return -1;
 
 	if (git_reference_foreach(
-			repo, list_flags, &cb__reflist_add, (void *)&ref_list) < 0) {
+			repo, &cb__reflist_add, (void *)&ref_list) < 0) {
 		git_vector_free(&ref_list);
 		return -1;
 	}
@@ -889,19 +994,29 @@
 int git_reference_foreach_glob(
 	git_repository *repo,
 	const char *glob,
-	unsigned int list_flags,
-	int (*callback)(
-		const char *reference_name,
-		void *payload),
+	git_reference_foreach_cb callback,
 	void *payload)
 {
-	git_refdb *refdb;
+	git_reference_iterator *iter;
+	const char *name;
+	int error;
 
-	assert(repo && glob && callback);
+	if (git_reference_iterator_glob_new(&iter, repo, glob) < 0)
+		return -1;
 
-	git_repository_refdb__weakptr(&refdb, repo);
+	while ((error = git_reference_next(&name, iter)) == 0) {
+		if (callback(name, payload)) {
+			error = GIT_EUSER;
+			goto out;
+		}
+	}
 
-	return git_refdb_foreach_glob(refdb, glob, list_flags, callback, payload);
+	if (error == GIT_ITEROVER)
+		error = 0;
+
+out:
+	git_reference_iterator_free(iter);
+	return error;
 }
 
 int git_reference_has_log(
diff --git a/src/remote.c b/src/remote.c
index 6925376..e5a7df7 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -292,7 +292,7 @@
 	git_buf_clear(&buf);
 	git_buf_printf(&buf, "remote.%s.pushurl", name);
 
-	if ((error = get_optional_config(config, &buf, NULL, &val)) < 0)
+	if ((error = get_optional_config(config, &buf, NULL, (void *)&val)) < 0)
 		goto cleanup;
 
 	if (val) {
@@ -1251,14 +1251,6 @@
 		update_config_entries_cb, &data);
 }
 
-static int rename_cb(const char *ref, void *data)
-{
-	if (git__prefixcmp(ref, GIT_REFS_REMOTES_DIR))
-		return 0;
-	
-	return git_vector_insert((git_vector *)data, git__strdup(ref));
-}
-
 static int rename_one_remote_reference(
 	git_repository *repo,
 	const char *reference_name,
@@ -1298,16 +1290,29 @@
 	int error = -1;
 	unsigned int i;
 	char *name;
+	const char *refname;
+	git_reference_iterator *iter;
 
 	if (git_vector_init(&refnames, 8, NULL) < 0)
+		return -1;
+
+	if (git_reference_iterator_new(&iter, repo) < 0)
 		goto cleanup;
 
-	if (git_reference_foreach(
-		repo,
-		GIT_REF_LISTALL,
-		rename_cb,
-		&refnames) < 0)
-			goto cleanup;
+	while ((error = git_reference_next(&refname, iter)) == 0) {
+		if (git__prefixcmp(refname, GIT_REFS_REMOTES_DIR))
+			continue;
+
+		if ((error = git_vector_insert(&refnames, git__strdup(refname))) < 0)
+			break;
+
+	}
+
+	git_reference_iterator_free(iter);
+	if (error == GIT_ITEROVER)
+		error = 0;
+	else
+		goto cleanup;
 
 	git_vector_foreach(&refnames, i, name) {
 		if ((error = rename_one_remote_reference(repo, name, old_name, new_name)) < 0)
diff --git a/src/repository.c b/src/repository.c
index e2cedc0..4ab3921 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -1473,7 +1473,7 @@
 
 static int repo_contains_no_reference(git_repository *repo)
 {
-	int error = git_reference_foreach(repo, GIT_REF_LISTALL, at_least_one_cb, NULL);
+	int error = git_reference_foreach(repo, at_least_one_cb, NULL);
 
 	if (error == GIT_EUSER)
 		return 0;
@@ -1596,6 +1596,9 @@
 	struct stat st;
 	int error;
 
+	if (buffer != NULL)
+		*buffer = '\0';
+
 	if (git_buf_joinpath(&path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0)
 		return -1;
 
diff --git a/src/revparse.c b/src/revparse.c
index e8cc32a..05231e3 100644
--- a/src/revparse.c
+++ b/src/revparse.c
@@ -14,67 +14,6 @@
 
 #include "git2.h"
 
-static int disambiguate_refname(git_reference **out, git_repository *repo, const char *refname)
-{
-	int error = 0, i;
-	bool fallbackmode = true, foundvalid = false;
-	git_reference *ref;
-	git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT;
-
-	static const char* formatters[] = {
-		"%s",
-		GIT_REFS_DIR "%s",
-		GIT_REFS_TAGS_DIR "%s",
-		GIT_REFS_HEADS_DIR "%s",
-		GIT_REFS_REMOTES_DIR "%s",
-		GIT_REFS_REMOTES_DIR "%s/" GIT_HEAD_FILE,
-		NULL
-	};
-
-	if (*refname)
-		git_buf_puts(&name, refname);
-	else {
-		git_buf_puts(&name, GIT_HEAD_FILE);
-		fallbackmode = false;
-	}
-
-	for (i = 0; formatters[i] && (fallbackmode || i == 0); i++) {
-
-		git_buf_clear(&refnamebuf);
-
-		if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0)
-			goto cleanup;
-
-		if (!git_reference_is_valid_name(git_buf_cstr(&refnamebuf))) {
-			error = GIT_EINVALIDSPEC;
-			continue;
-		}
-		foundvalid = true;
-
-		error = git_reference_lookup_resolved(&ref, repo, git_buf_cstr(&refnamebuf), -1);
-
-		if (!error) {
-			*out = ref;
-			error = 0;
-			goto cleanup;
-		}
-
-		if (error != GIT_ENOTFOUND)
-			goto cleanup;
-	}
-
-cleanup:
-	if (error && !foundvalid) {
-		/* never found a valid reference name */
-		giterr_set(GITERR_REFERENCE,
-			"Could not use '%s' as valid reference name", git_buf_cstr(&name));
-	}
-
-	git_buf_free(&name);
-	git_buf_free(&refnamebuf);
-	return error;
-}
-
 static int maybe_sha_or_abbrev(git_object** out, git_repository *repo, const char *spec, size_t speclen)
 {
 	git_oid oid;
@@ -157,7 +96,7 @@
 	if (error < 0 && error != GIT_ENOTFOUND)
 		return error;
 
-	error = disambiguate_refname(&ref, repo, spec);
+	error = git_reference_dwim(&ref, repo, spec);
 	if (!error) {
 		error = git_object_lookup(out, repo, git_reference_target(ref), GIT_OBJ_ANY);
 		git_reference_free(ref);
@@ -242,7 +181,7 @@
 
 		git_buf_put(&buf, msg+regexmatches[1].rm_so, regexmatches[1].rm_eo - regexmatches[1].rm_so);
 
-		if ((error = disambiguate_refname(base_ref, repo, git_buf_cstr(&buf))) == 0)
+		if ((error = git_reference_dwim(base_ref, repo, git_buf_cstr(&buf))) == 0)
 			goto cleanup;
 
 		if (error < 0 && error != GIT_ENOTFOUND)
@@ -323,7 +262,7 @@
 	int error = -1;
 
 	if (*base_ref == NULL) {
-		if ((error = disambiguate_refname(&ref, repo, identifier)) < 0)
+		if ((error = git_reference_dwim(&ref, repo, identifier)) < 0)
 			return error;
 	} else {
 		ref = *base_ref;
@@ -351,7 +290,7 @@
 	int error = -1;
 
 	if (*base_ref == NULL) {
-		if ((error = disambiguate_refname(&ref, repo, identifier)) < 0)
+		if ((error = git_reference_dwim(&ref, repo, identifier)) < 0)
 			return error;
 	} else {
 		ref = *base_ref;
diff --git a/src/revwalk.c b/src/revwalk.c
index 16f0662..528d02b 100644
--- a/src/revwalk.c
+++ b/src/revwalk.c
@@ -186,7 +186,7 @@
 	data.hide = hide;
 
 	if (git_reference_foreach_glob(
-		walk->repo, git_buf_cstr(&buf), GIT_REF_LISTALL, push_glob_cb, &data) < 0)
+		walk->repo, git_buf_cstr(&buf), push_glob_cb, &data) < 0)
 		goto on_error;
 
 	regfree(&preg);
diff --git a/src/status.c b/src/status.c
index 73472ab..89f3eed 100644
--- a/src/status.c
+++ b/src/status.c
@@ -266,6 +266,7 @@
 
 	opts.show  = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
 	opts.flags = GIT_STATUS_OPT_INCLUDE_IGNORED |
+		GIT_STATUS_OPT_RECURSE_IGNORED_DIRS |
 		GIT_STATUS_OPT_INCLUDE_UNTRACKED |
 		GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS |
 		GIT_STATUS_OPT_INCLUDE_UNMODIFIED;
@@ -281,22 +282,9 @@
 	}
 
 	if (!error && !sfi.count) {
-		git_buf full = GIT_BUF_INIT;
-
-		/* if the file actually exists and we still did not get a callback
-		 * for it, then it must be contained inside an ignored directory, so
-		 * mark it as such instead of generating an error.
-		 */
-		if (!git_buf_joinpath(&full, git_repository_workdir(repo), path) &&
-			git_path_exists(full.ptr))
-			sfi.status = GIT_STATUS_IGNORED;
-		else {
-			giterr_set(GITERR_INVALID,
-				"Attempt to get status of nonexistent file '%s'", path);
-			error = GIT_ENOTFOUND;
-		}
-
-		git_buf_free(&full);
+		giterr_set(GITERR_INVALID,
+			"Attempt to get status of nonexistent file '%s'", path);
+		error = GIT_ENOTFOUND;
 	}
 
 	*status_flags = sfi.status;
diff --git a/src/tag.c b/src/tag.c
index a4f2e25..f81956d 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -427,7 +427,7 @@
 	data.cb_data = cb_data;
 	data.repo = repo;
 
-	return git_reference_foreach(repo, GIT_REF_OID, &tags_cb, &data);
+	return git_reference_foreach(repo, &tags_cb, &data);
 }
 
 typedef struct {
diff --git a/src/transports/local.c b/src/transports/local.c
index 8b4d50c..bd3bf93 100644
--- a/src/transports/local.c
+++ b/src/transports/local.c
@@ -124,7 +124,7 @@
 
 	assert(t);
 
-	if (git_reference_list(&ref_names, t->repo, GIT_REF_LISTALL) < 0 ||
+	if (git_reference_list(&ref_names, t->repo) < 0 ||
 		git_vector_init(&t->refs, ref_names.count, NULL) < 0)
 		goto on_error;
 
diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c
index 765b914..67d3095 100644
--- a/src/transports/smart_protocol.c
+++ b/src/transports/smart_protocol.c
@@ -21,8 +21,8 @@
 	gitno_buffer *buf = &t->buffer;
 	git_vector *refs = &t->refs;
 	int error, flush = 0, recvd;
-	const char *line_end;
-	git_pkt *pkt;
+	const char *line_end = NULL;
+	git_pkt *pkt = NULL;
 	git_pkt_ref *ref;
 	size_t i;
 
@@ -135,7 +135,7 @@
 static int recv_pkt(git_pkt **out, gitno_buffer *buf)
 {
 	const char *ptr = buf->data, *line_end = ptr;
-	git_pkt *pkt;
+	git_pkt *pkt = NULL;
 	int pkt_type, error = 0, ret;
 
 	do {
@@ -193,7 +193,7 @@
 	unsigned int i;
 	git_reference *ref;
 
-	if (git_reference_list(&refs, repo, GIT_REF_LISTALL) < 0)
+	if (git_reference_list(&refs, repo) < 0)
 		return -1;
 
 	if (git_revwalk_new(&walk, repo) < 0)
@@ -640,8 +640,8 @@
 
 static int parse_report(gitno_buffer *buf, git_push *push)
 {
-	git_pkt *pkt;
-	const char *line_end;
+	git_pkt *pkt = NULL;
+	const char *line_end = NULL;
 	int error, recvd;
 
 	for (;;) {
diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c
index e502001..d803c81 100644
--- a/src/transports/winhttp.c
+++ b/src/transports/winhttp.c
@@ -893,7 +893,7 @@
 	wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")";
 	wchar_t host[GIT_WIN_PATH];
 	int32_t port;
-	const char *default_port;
+	const char *default_port = "80";
 	int ret;
 
 	if (!git__prefixcmp(url, prefix_http)) {
diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c
index 68d1716..de0e41b 100644
--- a/tests-clar/clar_libgit2.c
+++ b/tests-clar/clar_libgit2.c
@@ -190,6 +190,18 @@
 	return _cl_repo;
 }
 
+git_repository *cl_git_sandbox_reopen(void)
+{
+	if (_cl_repo) {
+		git_repository_free(_cl_repo);
+		_cl_repo = NULL;
+
+		cl_git_pass(git_repository_open(&_cl_repo, _cl_sandbox));
+	}
+
+	return _cl_repo;
+}
+
 void cl_git_sandbox_cleanup(void)
 {
 	if (_cl_repo) {
diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h
index 93909d8..3fcf45a 100644
--- a/tests-clar/clar_libgit2.h
+++ b/tests-clar/clar_libgit2.h
@@ -60,6 +60,7 @@
 
 git_repository *cl_git_sandbox_init(const char *sandbox);
 void cl_git_sandbox_cleanup(void);
+git_repository *cl_git_sandbox_reopen(void);
 
 /* Local-repo url helpers */
 const char* cl_git_fixture_url(const char *fixturename);
diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c
index 8b17fd9..8aae1fb 100644
--- a/tests-clar/clone/nonetwork.c
+++ b/tests-clar/clone/nonetwork.c
@@ -185,6 +185,7 @@
 	cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_NONE, origin->download_tags);
 
 	git_strarray_free(&tags);
+	git_remote_free(origin);
 }
 
 void test_clone_nonetwork__custom_autotag_tags_all(void)
@@ -199,6 +200,7 @@
 	cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_ALL, origin->download_tags);
 
 	git_strarray_free(&tags);
+	git_remote_free(origin);
 }
 
 void test_clone_nonetwork__cope_with_already_existing_directory(void)
diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c
index 5a8af93..8134cb6 100644
--- a/tests-clar/diff/rename.c
+++ b/tests-clar/diff/rename.c
@@ -364,7 +364,7 @@
 	cl_git_pass(git_repository_index(&index, g_repo));
 
 	tree = resolve_commit_oid_to_tree(g_repo, tree_sha);
-		
+
 	cl_git_rewritefile("renames/songof7cities.txt", "single line\n");
 	cl_git_pass(git_index_add_bypath(index, "songof7cities.txt"));
 
@@ -391,3 +391,56 @@
 
 	/* and with / without CRLF changes */
 }
+
+void test_diff_rename__patch(void)
+{
+	const char *sha0 = "2bc7f351d20b53f1c72c16c4b036e491c478c49a";
+	const char *sha1 = "1c068dee5790ef1580cfc4cd670915b48d790084";
+	git_tree *old_tree, *new_tree;
+	git_diff_list *diff;
+	git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
+	git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT;
+	git_diff_patch *patch;
+	const git_diff_delta *delta;
+	char *text;
+	const char *expected = "diff --git a/sixserving.txt b/ikeepsix.txt\nindex ad0a8e5..36020db 100644\n--- a/sixserving.txt\n+++ b/ikeepsix.txt\n@@ -1,3 +1,6 @@\n+I Keep Six Honest Serving-Men\n+=============================\n+\n I KEEP six honest serving-men\n  (They taught me all I knew);\n Their names are What and Why and When\n@@ -21,4 +24,4 @@\n One million Hows, two million Wheres,\n And seven million Whys!\n \n-                -- Rudyard Kipling\n+  -- Rudyard Kipling\n";
+
+	old_tree = resolve_commit_oid_to_tree(g_repo, sha0);
+	new_tree = resolve_commit_oid_to_tree(g_repo, sha1);
+
+	diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED;
+	cl_git_pass(git_diff_tree_to_tree(
+		&diff, g_repo, old_tree, new_tree, &diffopts));
+
+	opts.flags = GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES;
+	cl_git_pass(git_diff_find_similar(diff, &opts));
+
+	/* == Changes =====================================================
+	 * sixserving.txt  -> ikeepsix.txt    (copy, add title, >80% match)
+	 * sevencities.txt                    (no change)
+	 * sixserving.txt  -> sixserving.txt  (indentation change)
+	 * songofseven.txt -> songofseven.txt (major rewrite, <20% match - split)
+	 */
+
+	cl_assert_equal_i(4, (int)git_diff_num_deltas(diff));
+
+	cl_git_pass(git_diff_get_patch(&patch, &delta, diff, 0));
+	cl_assert_equal_i(GIT_DELTA_COPIED, (int)delta->status);
+
+	cl_git_pass(git_diff_patch_to_str(&text, patch));
+	cl_assert_equal_s(expected, text);
+	git__free(text);
+
+	git_diff_patch_free(patch);
+
+	cl_git_pass(git_diff_get_patch(NULL, &delta, diff, 1));
+	cl_assert_equal_i(GIT_DELTA_UNMODIFIED, (int)delta->status);
+
+	cl_git_pass(git_diff_get_patch(NULL, &delta, diff, 2));
+	cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status);
+
+	cl_git_pass(git_diff_get_patch(NULL, &delta, diff, 3));
+	cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status);
+
+	git_diff_list_free(diff);
+}
diff --git a/tests-clar/merge/trees/trivial.c b/tests-clar/merge/trees/trivial.c
index 7d8d2cb..e6096e2 100644
--- a/tests-clar/merge/trees/trivial.c
+++ b/tests-clar/merge/trees/trivial.c
@@ -67,7 +67,7 @@
 static int merge_trivial_conflict_entrycount(git_index *index)
 {
 	const git_index_entry *entry;
-	size_t count = 0;
+	int count = 0;
 	size_t i;
 
 	for (i = 0; i < git_index_entrycount(index); i++) {
diff --git a/tests-clar/network/fetchlocal.c b/tests-clar/network/fetchlocal.c
index bcf298c..09335b3 100644
--- a/tests-clar/network/fetchlocal.c
+++ b/tests-clar/network/fetchlocal.c
@@ -34,7 +34,7 @@
 	cl_git_pass(git_remote_download(origin, transfer_cb, &callcount));
 	cl_git_pass(git_remote_update_tips(origin));
 
-	cl_git_pass(git_reference_list(&refnames, repo, GIT_REF_LISTALL));
+	cl_git_pass(git_reference_list(&refnames, repo));
 	cl_assert_equal_i(19, (int)refnames.count);
 	cl_assert(callcount > 0);
 
@@ -58,7 +58,7 @@
 	const char *url;
 
 	cl_set_cleanup(&cleanup_sandbox, NULL);
-	cl_git_pass(git_reference_list(&refnames, repo, GIT_REF_LISTALL));
+	cl_git_pass(git_reference_list(&refnames, repo));
 	cl_assert_equal_i(1, (int)refnames.count);
 
 	url = cl_git_fixture_url("testrepo.git");
@@ -69,7 +69,7 @@
 
 	git_strarray_free(&refnames);
 
-	cl_git_pass(git_reference_list(&refnames, repo, GIT_REF_LISTALL));
+	cl_git_pass(git_reference_list(&refnames, repo));
 	cl_assert_equal_i(20, (int)refnames.count); /* 18 remote + 1 local */
 	cl_assert(callcount > 0);
 
diff --git a/tests-clar/network/remote/remotes.c b/tests-clar/network/remote/remotes.c
index 4c24db8..21f27bc 100644
--- a/tests-clar/network/remote/remotes.c
+++ b/tests-clar/network/remote/remotes.c
@@ -118,13 +118,13 @@
 	cl_git_pass(git_remote_add_fetch(_remote, "refs/*:refs/*"));
 
 	size++;
-	cl_assert_equal_i(size, git_remote_refspec_count(_remote));
+	cl_assert_equal_i((int)size, (int)git_remote_refspec_count(_remote));
 
 	_refspec = git_remote_get_refspec(_remote, size - 1);
 	cl_assert_equal_s(git_refspec_src(_refspec), "refs/*");
 	cl_assert_equal_s(git_refspec_dst(_refspec), "refs/*");
 	cl_assert_equal_s(git_refspec_string(_refspec), "refs/*:refs/*");
-	cl_assert_equal_i(_refspec->push, false);
+	cl_assert_equal_b(_refspec->push, false);
 }
 
 void test_network_remote_remotes__add_pushspec(void)
@@ -135,14 +135,14 @@
 
 	cl_git_pass(git_remote_add_push(_remote, "refs/*:refs/*"));
 	size++;
-	cl_assert_equal_i(size, git_remote_refspec_count(_remote));
+	cl_assert_equal_i((int)size, (int)git_remote_refspec_count(_remote));
 
 	_refspec = git_remote_get_refspec(_remote, size - 1);
 	cl_assert_equal_s(git_refspec_src(_refspec), "refs/*");
 	cl_assert_equal_s(git_refspec_dst(_refspec), "refs/*");
 	cl_assert_equal_s(git_refspec_string(_refspec), "refs/*:refs/*");
 
-	cl_assert_equal_i(_refspec->push, true);
+	cl_assert_equal_b(_refspec->push, true);
 }
 
 void test_network_remote_remotes__save(void)
@@ -169,12 +169,12 @@
 	cl_git_pass(git_remote_load(&_remote, _repo, "upstream"));
 
 	cl_git_pass(git_remote_get_fetch_refspecs(&array, _remote));
-	cl_assert_equal_i(1, array.count);
+	cl_assert_equal_i(1, (int)array.count);
 	cl_assert_equal_s(fetch_refspec, array.strings[0]);
 	git_strarray_free(&array);
 
 	cl_git_pass(git_remote_get_push_refspecs(&array, _remote));
-	cl_assert_equal_i(1, array.count);
+	cl_assert_equal_i(1, (int)array.count);
 	cl_assert_equal_s(push_refspec, array.strings[0]);
 	cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2");
 	cl_assert_equal_s(git_remote_pushurl(_remote), "git://github.com/libgit2/libgit2_push");
diff --git a/tests-clar/object/cache.c b/tests-clar/object/cache.c
index e06760e..b927b25 100644
--- a/tests-clar/object/cache.c
+++ b/tests-clar/object/cache.c
@@ -80,7 +80,7 @@
 		cl_assert_equal_i(count + 1, (int)git_cache_size(&g_repo->objects));
 	}
 
-	cl_assert_equal_i(i, git_cache_size(&g_repo->objects) - start);
+	cl_assert_equal_i(i, (int)git_cache_size(&g_repo->objects) - start);
 
 	git_odb_free(odb);
 
@@ -135,7 +135,7 @@
 		}
 	}
 
-	cl_assert_equal_i(nonblobs, git_cache_size(&g_repo->objects) - start);
+	cl_assert_equal_i(nonblobs, (int)git_cache_size(&g_repo->objects) - start);
 
 	git_odb_free(odb);
 }
diff --git a/tests-clar/refdb/inmemory.c b/tests-clar/refdb/inmemory.c
index 243b5bb..d2594cd 100644
--- a/tests-clar/refdb/inmemory.c
+++ b/tests-clar/refdb/inmemory.c
@@ -163,7 +163,7 @@
 	cl_git_pass(git_oid_fromstr(&oid3, "763d71aadf09a7951596c9746c024e7eece7c7af"));
 	cl_git_pass(git_reference_create(&write3, repo, GIT_REFS_HEADS_DIR "test3", &oid3, 0));
 
-	cl_git_pass(git_reference_foreach(repo, GIT_REF_LISTALL, foreach_test, &i));
+	cl_git_pass(git_reference_foreach(repo,foreach_test, &i));
 	cl_assert_equal_i(3, (int)i);
 
 	git_reference_free(write1);
@@ -210,7 +210,7 @@
 	git_reference_delete(write3);
 	git_reference_free(write3);
 
-	cl_git_pass(git_reference_foreach(repo, GIT_REF_LISTALL, delete_test, &i));
+	cl_git_pass(git_reference_foreach(repo, delete_test, &i));
 	cl_assert_equal_i(1, (int)i);
 
 	git_reference_free(write2);
diff --git a/tests-clar/refdb/testdb.c b/tests-clar/refdb/testdb.c
index 627254e..961e18d 100644
--- a/tests-clar/refdb/testdb.c
+++ b/tests-clar/refdb/testdb.c
@@ -112,33 +112,49 @@
 	return GIT_ENOTFOUND;
 }
 
-static int refdb_test_backend__foreach(
-	git_refdb_backend *_backend,
-	unsigned int list_flags,
-	git_reference_foreach_cb callback,
-	void *payload)
-{
-	refdb_test_backend *backend;
-	refdb_test_entry *entry;
+typedef struct {
+	git_reference_iterator parent;
 	size_t i;
+} refdb_test_iter;
 
-	assert(_backend);
-	backend = (refdb_test_backend *)_backend;
+static int refdb_test_backend__iterator(git_reference_iterator **out, git_refdb_backend *_backend)
+{
+	refdb_test_iter *iter;
 
-	git_vector_foreach(&backend->refs, i, entry) {
-		if (entry->type == GIT_REF_OID && (list_flags & GIT_REF_OID) == 0)
-			continue;
+	GIT_UNUSED(_backend);
 
-		if (entry->type == GIT_REF_SYMBOLIC && (list_flags & GIT_REF_SYMBOLIC) == 0)
-			continue;
+	iter = git__calloc(1, sizeof(refdb_test_iter));
+	GITERR_CHECK_ALLOC(iter);
 
-		if (callback(entry->name, payload) != 0)
-			return GIT_EUSER;
-	}
+	iter->parent.backend = _backend;
+	iter->i = 0;
+
+	*out = (git_reference_iterator *) iter;
 
 	return 0;
 }
 
+static int refdb_test_backend__next(const char **name, git_reference_iterator *_iter)
+{
+	refdb_test_entry *entry;
+	refdb_test_backend *backend = (refdb_test_backend *) _iter->backend;
+	refdb_test_iter *iter = (refdb_test_iter *) _iter;
+
+	entry = git_vector_get(&backend->refs, iter->i);
+	if (!entry)
+		return GIT_ITEROVER;
+
+	*name = entry->name;
+	iter->i++;
+
+	return 0;
+}
+
+static void refdb_test_backend__iterator_free(git_reference_iterator *iter)
+{
+	git__free(iter);
+}
+
 static void refdb_test_entry_free(refdb_test_entry *entry)
 {
 	if (entry->type == GIT_REF_SYMBOLIC)
@@ -200,7 +216,9 @@
 
 	backend->parent.exists = &refdb_test_backend__exists;
 	backend->parent.lookup = &refdb_test_backend__lookup;
-	backend->parent.foreach = &refdb_test_backend__foreach;
+	backend->parent.iterator = &refdb_test_backend__iterator;
+	backend->parent.next = &refdb_test_backend__next;
+	backend->parent.iterator_free = &refdb_test_backend__iterator_free;
 	backend->parent.write = &refdb_test_backend__write;
 	backend->parent.delete = &refdb_test_backend__delete;
 	backend->parent.free = &refdb_test_backend__free;
diff --git a/tests-clar/refs/branches/foreach.c b/tests-clar/refs/branches/foreach.c
index 96a5bc2..57f9c0e 100644
--- a/tests-clar/refs/branches/foreach.c
+++ b/tests-clar/refs/branches/foreach.c
@@ -24,6 +24,8 @@
 	repo = NULL;
 
 	cl_fixture_cleanup("testrepo.git");
+
+	cl_git_sandbox_cleanup();
 }
 
 static int count_branch_list_cb(const char *branch_name, git_branch_t branch_type, void *payload)
@@ -72,14 +74,11 @@
 {
 	int pos = 0;
 
-	while (findings[pos].branch_name)
-	{
+	for (pos = 0; findings[pos].branch_name; ++pos) {
 		if (strcmp(expected_branch_name, findings[pos].branch_name) == 0) {
 			cl_assert_equal_i(1, findings[pos].encounters);
 			return;
 		}
-
-		pos++;
 	}
 
 	cl_fail("expected branch not found in list.");
@@ -94,12 +93,9 @@
 
 	exp = (struct expectations *)payload;
 
-	while (exp[pos].branch_name)
-	{
+	for (pos = 0; exp[pos].branch_name; ++pos) {
 		if (strcmp(branch_name, exp[pos].branch_name) == 0)
 			exp[pos].encounters++;
-		
-		pos++;
 	}
 
 	return 0;
@@ -153,3 +149,25 @@
 
 	cl_assert_equal_i(5, count);
 }
+
+void test_refs_branches_foreach__mix_of_packed_and_loose(void)
+{
+	struct expectations exp[] = {
+		{ "master", 0 },
+		{ "origin/HEAD", 0 },
+		{ "origin/master", 0 },
+		{ "origin/packed", 0 },
+		{ NULL, 0 }
+	};
+	git_repository *r2;
+
+	r2 = cl_git_sandbox_init("testrepo2");
+
+	cl_git_pass(git_branch_foreach(r2, GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE,
+		contains_branch_list_cb, &exp));
+
+	assert_branch_has_been_found(exp, "master");
+	assert_branch_has_been_found(exp, "origin/HEAD");
+	assert_branch_has_been_found(exp, "origin/master");
+	assert_branch_has_been_found(exp, "origin/packed");
+}
diff --git a/tests-clar/refs/branches/upstream.c b/tests-clar/refs/branches/upstream.c
index 648acb4..69e55a0 100644
--- a/tests-clar/refs/branches/upstream.c
+++ b/tests-clar/refs/branches/upstream.c
@@ -113,11 +113,12 @@
 	cl_git_pass(git_config_get_string(&value, config, "branch.test.merge"));
 	cl_assert_equal_s(value, "refs/heads/master");
 
+	git_reference_free(branch);
+
 	/* local */
 	cl_git_pass(git_reference_lookup(&branch, repository, "refs/heads/test"));
 	cl_git_pass(git_branch_set_upstream(branch, "master"));
 
-	cl_git_pass(git_repository_config(&config, repository));
 	cl_git_pass(git_config_get_string(&value, config, "branch.test.remote"));
 	cl_assert_equal_s(value, ".");
 	cl_git_pass(git_config_get_string(&value, config, "branch.test.merge"));
diff --git a/tests-clar/refs/foreachglob.c b/tests-clar/refs/foreachglob.c
index 4da1a15..2c45808 100644
--- a/tests-clar/refs/foreachglob.c
+++ b/tests-clar/refs/foreachglob.c
@@ -37,11 +37,11 @@
 	return 0;
 }
 
-static void assert_retrieval(const char *glob, unsigned int flags, int expected_count)
+static void assert_retrieval(const char *glob, int expected_count)
 {
 	int count = 0;
 
-	cl_git_pass(git_reference_foreach_glob(repo, glob, flags, count_cb, &count));
+	cl_git_pass(git_reference_foreach_glob(repo, glob, count_cb, &count));
 
 	cl_assert_equal_i(expected_count, count);
 }
@@ -49,17 +49,17 @@
 void test_refs_foreachglob__retrieve_all_refs(void)
 {
 	/* 12 heads (including one packed head) + 1 note + 2 remotes + 7 tags */
-	assert_retrieval("*", GIT_REF_LISTALL, 22);
+	assert_retrieval("*", 22);
 }
 
 void test_refs_foreachglob__retrieve_remote_branches(void)
 {
-	assert_retrieval("refs/remotes/*", GIT_REF_LISTALL, 2);
+	assert_retrieval("refs/remotes/*", 2);
 }
 
 void test_refs_foreachglob__retrieve_local_branches(void)
 {
-	assert_retrieval("refs/heads/*", GIT_REF_LISTALL, 12);
+	assert_retrieval("refs/heads/*", 12);
 }
 
 void test_refs_foreachglob__retrieve_partially_named_references(void)
@@ -69,7 +69,7 @@
 	 * refs/remotes/test/master, refs/tags/test
 	 */
 
-	assert_retrieval("*test*", GIT_REF_LISTALL, 4);
+	assert_retrieval("*test*", 4);
 }
 
 
@@ -89,7 +89,7 @@
 	int count = 0;
 
 	cl_assert_equal_i(GIT_EUSER, git_reference_foreach_glob(
-		repo, "*", GIT_REF_LISTALL, interrupt_cb, &count) );
+		repo, "*", interrupt_cb, &count) );
 
 	cl_assert_equal_i(11, count);
 }
diff --git a/tests-clar/refs/iterator.c b/tests-clar/refs/iterator.c
new file mode 100644
index 0000000..d5555c6
--- /dev/null
+++ b/tests-clar/refs/iterator.c
@@ -0,0 +1,94 @@
+#include "clar_libgit2.h"
+#include "refs.h"
+#include "vector.h"
+
+static git_repository *repo;
+
+void test_refs_iterator__initialize(void)
+{
+	cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+}
+
+void test_refs_iterator__cleanup(void)
+{
+	git_repository_free(repo);
+}
+
+static const char *refnames[] = {
+	"refs/heads/br2",
+	"refs/heads/cannot-fetch",
+	"refs/heads/chomped",
+	"refs/heads/haacked",
+	"refs/heads/master",
+	"refs/heads/not-good",
+	"refs/heads/packed",
+	"refs/heads/packed-test",
+	"refs/heads/subtrees",
+	"refs/heads/test",
+	"refs/heads/track-local",
+	"refs/heads/trailing",
+	"refs/notes/fanout",
+	"refs/remotes/test/master",
+	"refs/tags/annotated_tag_to_blob",
+	"refs/tags/e90810b",
+	"refs/tags/hard_tag",
+	"refs/tags/point_to_blob",
+	"refs/tags/taggerless",
+	"refs/tags/test",
+	"refs/tags/wrapped_tag",
+};
+
+void test_refs_iterator__list(void)
+{
+	git_reference_iterator *iter;
+	git_vector output;
+	char *refname;
+	int error;
+	size_t i;
+
+	cl_git_pass(git_vector_init(&output, 32, git__strcmp_cb));
+	cl_git_pass(git_reference_iterator_new(&iter, repo));
+
+	do {
+		const char *name;
+		error = git_reference_next(&name, iter);
+		cl_assert(error == 0 || error == GIT_ITEROVER);
+		if (error != GIT_ITEROVER) {
+			char *dup = git__strdup(name);
+			cl_assert(dup != NULL);
+			cl_git_pass(git_vector_insert(&output, dup));
+		}
+	} while (!error);
+
+	cl_assert_equal_i(output.length, ARRAY_SIZE(refnames));
+
+	git_vector_sort(&output);
+	git_vector_foreach(&output, i, refname) {
+		cl_assert_equal_s(refname, refnames[i]);
+	}
+
+	git_reference_iterator_free(iter);
+
+	git_vector_foreach(&output, i, refname) {
+		git__free(refname);
+	}
+	git_vector_free(&output);
+}
+
+void test_refs_iterator__empty(void)
+{
+	git_reference_iterator *iter;
+	git_odb *odb;
+	const char *name;
+	git_repository *empty;
+
+	cl_git_pass(git_odb_new(&odb));
+	cl_git_pass(git_repository_wrap_odb(&empty, odb));
+
+	cl_git_pass(git_reference_iterator_new(&iter, empty));
+	cl_assert_equal_i(GIT_ITEROVER, git_reference_next(&name, iter));
+
+	git_reference_iterator_free(iter);
+	git_odb_free(odb);
+	git_repository_free(empty);
+}
diff --git a/tests-clar/refs/list.c b/tests-clar/refs/list.c
index 3948b2b..c9c2af4 100644
--- a/tests-clar/refs/list.c
+++ b/tests-clar/refs/list.c
@@ -25,7 +25,7 @@
    // try to list all the references in our test repo
 	git_strarray ref_list;
 
-	cl_git_pass(git_reference_list(&ref_list, g_repo, GIT_REF_LISTALL));
+	cl_git_pass(git_reference_list(&ref_list, g_repo));
 
 	/*{
 		unsigned short i;
@@ -41,17 +41,6 @@
 	git_strarray_free(&ref_list);
 }
 
-void test_refs_list__symbolic_only(void)
-{
-   // try to list only the symbolic references
-	git_strarray ref_list;
-
-	cl_git_pass(git_reference_list(&ref_list, g_repo, GIT_REF_SYMBOLIC));
-	cl_assert(ref_list.count == 0); /* no symrefs in the test repo */
-
-	git_strarray_free(&ref_list);
-}
-
 void test_refs_list__do_not_retrieve_references_which_name_end_with_a_lock_extension(void)
 {
 	git_strarray ref_list;
@@ -61,7 +50,7 @@
 		"./testrepo/.git/refs/heads/hanwen.lock",
 		"144344043ba4d4a405da03de3844aa829ae8be0e\n");
 
-	cl_git_pass(git_reference_list(&ref_list, g_repo, GIT_REF_LISTALL));
+	cl_git_pass(git_reference_list(&ref_list, g_repo));
 	cl_assert_equal_i((int)ref_list.count, 13);
 
 	git_strarray_free(&ref_list);
diff --git a/tests-clar/refs/listall.c b/tests-clar/refs/listall.c
index 8f4c374..c696fbb 100644
--- a/tests-clar/refs/listall.c
+++ b/tests-clar/refs/listall.c
@@ -9,7 +9,7 @@
 	size_t i;
 
 	cl_git_pass(git_repository_open(&repo, path));
-	cl_git_pass(git_reference_list(&ref_list, repo, GIT_REF_LISTALL));
+	cl_git_pass(git_reference_list(&ref_list, repo));
 
 	cl_assert(ref_list.count > 0);
 
@@ -38,7 +38,7 @@
 void test_refs_listall__from_repository_with_no_trailing_newline(void)
 {
 	cl_git_pass(git_repository_open(&repo, cl_fixture("bad_tag.git")));
-	cl_git_pass(git_reference_list(&ref_list, repo, GIT_REF_LISTALL));
+	cl_git_pass(git_reference_list(&ref_list, repo));
 
 	cl_assert(ref_list.count > 0);
 
diff --git a/tests-clar/repo/message.c b/tests-clar/repo/message.c
index 59487d5..629d40c 100644
--- a/tests-clar/repo/message.c
+++ b/tests-clar/repo/message.c
@@ -35,13 +35,18 @@
 
 	len = git_repository_message(NULL, 0, _repo);
 	cl_assert(len > 0);
+
 	_actual = git__malloc(len + 1);
 	cl_assert(_actual != NULL);
 
+	/* Test non truncation */
 	cl_assert(git_repository_message(_actual, len, _repo) > 0);
-	_actual[len] = '\0';
 	cl_assert_equal_s(expected, _actual);
 
+	/* Test truncation and that trailing NUL is inserted */
+	cl_assert(git_repository_message(_actual, 6, _repo) > 0);
+	cl_assert_equal_s("Test\n", _actual);
+
 	cl_git_pass(p_unlink(git_buf_cstr(&_path)));
 	cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(NULL, 0, _repo));
 }
diff --git a/tests-clar/resources/testrepo2/.gitted/HEAD b/tests-clar/resources/testrepo2/.gitted/HEAD
new file mode 100644
index 0000000..cb089cd
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests-clar/resources/testrepo2/.gitted/config b/tests-clar/resources/testrepo2/.gitted/config
new file mode 100644
index 0000000..fc2433c
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/config
@@ -0,0 +1,14 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+	ignorecase = true
+	precomposeunicode = false
+[remote "origin"]
+	url = https://github.com/libgit2/false.git
+	fetch = +refs/heads/*:refs/remotes/origin/*
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
+	rebase = true
diff --git a/tests-clar/resources/testrepo2/.gitted/description b/tests-clar/resources/testrepo2/.gitted/description
new file mode 100644
index 0000000..498b267
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/description
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff --git a/tests-clar/resources/testrepo2/.gitted/index b/tests-clar/resources/testrepo2/.gitted/index
new file mode 100644
index 0000000..b614d07
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/index
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/info/exclude b/tests-clar/resources/testrepo2/.gitted/info/exclude
new file mode 100644
index 0000000..a5196d1
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/info/exclude
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff --git a/tests-clar/resources/testrepo2/.gitted/logs/HEAD b/tests-clar/resources/testrepo2/.gitted/logs/HEAD
new file mode 100644
index 0000000..4e80c69
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/logs/HEAD
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 36060c58702ed4c2a40832c51758d5344201d89a Russell Belfer <rb@github.com> 1368278260 -0700	clone: from /Users/rb/src/libgit2/tests-clar/resources/../../../rugged/test/fixtures/testrepo.git
diff --git a/tests-clar/resources/testrepo2/.gitted/logs/refs/heads/master b/tests-clar/resources/testrepo2/.gitted/logs/refs/heads/master
new file mode 100644
index 0000000..4e80c69
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/logs/refs/heads/master
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 36060c58702ed4c2a40832c51758d5344201d89a Russell Belfer <rb@github.com> 1368278260 -0700	clone: from /Users/rb/src/libgit2/tests-clar/resources/../../../rugged/test/fixtures/testrepo.git
diff --git a/tests-clar/resources/testrepo2/.gitted/logs/refs/remotes/origin/HEAD b/tests-clar/resources/testrepo2/.gitted/logs/refs/remotes/origin/HEAD
new file mode 100644
index 0000000..4e80c69
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/logs/refs/remotes/origin/HEAD
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 36060c58702ed4c2a40832c51758d5344201d89a Russell Belfer <rb@github.com> 1368278260 -0700	clone: from /Users/rb/src/libgit2/tests-clar/resources/../../../rugged/test/fixtures/testrepo.git
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d b/tests-clar/resources/testrepo2/.gitted/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d
new file mode 100644
index 0000000..bfe146a
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 b/tests-clar/resources/testrepo2/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08
new file mode 100644
index 0000000..cedb2a2
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 b/tests-clar/resources/testrepo2/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7
new file mode 100644
index 0000000..93a16f1
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd b/tests-clar/resources/testrepo2/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd
new file mode 100644
index 0000000..ba0bfb3
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 b/tests-clar/resources/testrepo2/.gitted/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2
new file mode 100644
index 0000000..3cd240d
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/36/060c58702ed4c2a40832c51758d5344201d89a b/tests-clar/resources/testrepo2/.gitted/objects/36/060c58702ed4c2a40832c51758d5344201d89a
new file mode 100644
index 0000000..0c62460
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/36/060c58702ed4c2a40832c51758d5344201d89a
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 b/tests-clar/resources/testrepo2/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057
new file mode 100644
index 0000000..7ca4cee
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 b/tests-clar/resources/testrepo2/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045
new file mode 100644
index 0000000..8953b6c
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045
@@ -0,0 +1,2 @@
+xŽQ
+Â0DýÎ)öÊ6›Í¦ "xO°‰‰-ØFb¼¿EoàÏ0¼Ç¤º,ske×[ÎPn8R,EpD?±gŸ}Ê^3²âÙ<µåµGŽhYKÄèÒ8ЖDAÉ)¿ÉÈ;gôݧÚàšjïp™4ÕŽ¯ô-çû¢óãêr‚ÁŠ;°s°GA4Ûº=ìùÖ(ôin7øIÌKÍFE
\ No newline at end of file
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 b/tests-clar/resources/testrepo2/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644
new file mode 100644
index 0000000..c1f22c5
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644
@@ -0,0 +1,2 @@
+xŽÛ	1EýNi@™Ék2 "X‚$ÙYW0YcÿíÀ¿Ã…s¸¥ÕzïÚÚõMDÏ€0æœ8!¶†ÉÌÞs‰XŠªgÚdí::@X0»P¢wÙ"F/‰‰œÍRàˆUz÷¥múZZïú²¤ÒV}|•/œo5݇ÒêI£!¬1z Æ:vùÇUim}ê/¢>
+öF-
\ No newline at end of file
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96 b/tests-clar/resources/testrepo2/.gitted/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96
new file mode 100644
index 0000000..1fd79b4
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a b/tests-clar/resources/testrepo2/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a
new file mode 100644
index 0000000..2ef4faa
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 b/tests-clar/resources/testrepo2/.gitted/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0
new file mode 100644
index 0000000..3d1016d
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/tests-clar/resources/testrepo2/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d
new file mode 100644
index 0000000..2f9b6b6
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/tests-clar/resources/testrepo2/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479
new file mode 100644
index 0000000..5df58dd
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a b/tests-clar/resources/testrepo2/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a
new file mode 100644
index 0000000..a796124
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f b/tests-clar/resources/testrepo2/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f
new file mode 100644
index 0000000..f858869
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd b/tests-clar/resources/testrepo2/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd
new file mode 100644
index 0000000..d0d7e73
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 b/tests-clar/resources/testrepo2/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6
new file mode 100644
index 0000000..18a7f61
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 b/tests-clar/resources/testrepo2/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644
new file mode 100644
index 0000000..0817229
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644
@@ -0,0 +1,3 @@
+xKj1D³Ö)zçUBëÛ-0ÁuV9¦Õò<#£È÷ÏȲ+ŠW<Jú¶Ý&8Ê/s¨‚e‹µµÈ•KJ­«½S
+ØRvÌÁ{©æQ†îr«äY¹QN$H\Eµ²Íè=6áX5¦òÇK Fr)·(‰dC‡Î†”­–œ—jÊs®}À—ô9ác-Òw8Ëo¸\·r»¿IßÞÁ:
+l}F‚W$Ds´Ç£©ÿٚOW…e”]V8-ÝÌÈ"U
\ No newline at end of file
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd b/tests-clar/resources/testrepo2/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd
new file mode 100644
index 0000000..75f541f
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd
@@ -0,0 +1,3 @@
+xŽQ
+Â0DýÎ)öʦ»I<‚'ØlR+˜Fj¼¿EoàÏ0<xÃh«õÞa Üõµ]ș­åXUlÞPF)Åz‘4yó”µ,\r	'SÂÄ-mI4
+‘Xhô”&òÌFÞ}n+\µõ—Y´-p|鷜oU¶z;-‘aÑlt{ØË?®I«,:ÃoÚR̳cHK
\ No newline at end of file
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/c4/dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b b/tests-clar/resources/testrepo2/.gitted/objects/c4/dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b
new file mode 100644
index 0000000..599e160
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/c4/dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/tests-clar/resources/testrepo2/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
new file mode 100644
index 0000000..7112238
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 b/tests-clar/resources/testrepo2/.gitted/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1
new file mode 100644
index 0000000..0377096
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/fa/49b077972391ad58037050f2a75f74e3671e92 b/tests-clar/resources/testrepo2/.gitted/objects/fa/49b077972391ad58037050f2a75f74e3671e92
new file mode 100644
index 0000000..112998d
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/fa/49b077972391ad58037050f2a75f74e3671e92
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/fd/093bff70906175335656e6ce6ae05783708765 b/tests-clar/resources/testrepo2/.gitted/objects/fd/093bff70906175335656e6ce6ae05783708765
new file mode 100644
index 0000000..12bf5f3
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/fd/093bff70906175335656e6ce6ae05783708765
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx b/tests-clar/resources/testrepo2/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx
new file mode 100644
index 0000000..94c3c71
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack b/tests-clar/resources/testrepo2/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack
new file mode 100644
index 0000000..74c7fe4
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack
Binary files differ
diff --git a/tests-clar/resources/testrepo2/.gitted/packed-refs b/tests-clar/resources/testrepo2/.gitted/packed-refs
new file mode 100644
index 0000000..97ea6a8
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/packed-refs
@@ -0,0 +1,6 @@
+# pack-refs with: peeled fully-peeled 
+36060c58702ed4c2a40832c51758d5344201d89a refs/remotes/origin/master
+41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9 refs/remotes/origin/packed
+5b5b025afb0b4c913b4c338a42934a3863bf3644 refs/tags/v0.9
+0c37a5391bbff43c37f0d0371823a5509eed5b1d refs/tags/v1.0
+^5b5b025afb0b4c913b4c338a42934a3863bf3644
diff --git a/tests-clar/resources/testrepo2/.gitted/refs/heads/master b/tests-clar/resources/testrepo2/.gitted/refs/heads/master
new file mode 100644
index 0000000..a7eafce
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/refs/heads/master
@@ -0,0 +1 @@
+36060c58702ed4c2a40832c51758d5344201d89a
diff --git a/tests-clar/resources/testrepo2/.gitted/refs/remotes/origin/HEAD b/tests-clar/resources/testrepo2/.gitted/refs/remotes/origin/HEAD
new file mode 100644
index 0000000..6efe28f
--- /dev/null
+++ b/tests-clar/resources/testrepo2/.gitted/refs/remotes/origin/HEAD
@@ -0,0 +1 @@
+ref: refs/remotes/origin/master
diff --git a/tests-clar/resources/testrepo2/README b/tests-clar/resources/testrepo2/README
new file mode 100644
index 0000000..1385f26
--- /dev/null
+++ b/tests-clar/resources/testrepo2/README
@@ -0,0 +1 @@
+hey
diff --git a/tests-clar/resources/testrepo2/new.txt b/tests-clar/resources/testrepo2/new.txt
new file mode 100644
index 0000000..fa49b07
--- /dev/null
+++ b/tests-clar/resources/testrepo2/new.txt
@@ -0,0 +1 @@
+new file
diff --git a/tests-clar/resources/testrepo2/subdir/README b/tests-clar/resources/testrepo2/subdir/README
new file mode 100644
index 0000000..1385f26
--- /dev/null
+++ b/tests-clar/resources/testrepo2/subdir/README
@@ -0,0 +1 @@
+hey
diff --git a/tests-clar/resources/testrepo2/subdir/new.txt b/tests-clar/resources/testrepo2/subdir/new.txt
new file mode 100644
index 0000000..fa49b07
--- /dev/null
+++ b/tests-clar/resources/testrepo2/subdir/new.txt
@@ -0,0 +1 @@
+new file
diff --git a/tests-clar/resources/testrepo2/subdir/subdir2/README b/tests-clar/resources/testrepo2/subdir/subdir2/README
new file mode 100644
index 0000000..1385f26
--- /dev/null
+++ b/tests-clar/resources/testrepo2/subdir/subdir2/README
@@ -0,0 +1 @@
+hey
diff --git a/tests-clar/resources/testrepo2/subdir/subdir2/new.txt b/tests-clar/resources/testrepo2/subdir/subdir2/new.txt
new file mode 100644
index 0000000..fa49b07
--- /dev/null
+++ b/tests-clar/resources/testrepo2/subdir/subdir2/new.txt
@@ -0,0 +1 @@
+new file
diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c
index 0138b17..062a09a 100644
--- a/tests-clar/status/worktree.c
+++ b/tests-clar/status/worktree.c
@@ -672,3 +672,26 @@
 {
 	assert_ignore_case(false, GIT_STATUS_WT_DELETED, GIT_STATUS_WT_NEW);
 }
+
+void test_status_worktree__file_status_honors_case_ignorecase_regarding_untracked_files(void)
+{
+    git_repository *repo = cl_git_sandbox_init("status");
+    unsigned int status;
+    git_index *index;
+
+    cl_repo_set_bool(repo, "core.ignorecase", false);
+
+	repo = cl_git_sandbox_reopen();
+
+    /* Actually returns GIT_STATUS_IGNORED on Windows */
+    cl_git_fail_with(git_status_file(&status, repo, "NEW_FILE"), GIT_ENOTFOUND);
+
+    cl_git_pass(git_repository_index(&index, repo));
+
+    cl_git_pass(git_index_add_bypath(index, "new_file"));
+    cl_git_pass(git_index_write(index));
+    git_index_free(index);
+
+    /* Actually returns GIT_STATUS_IGNORED on Windows */
+    cl_git_fail_with(git_status_file(&status, repo, "NEW_FILE"), GIT_ENOTFOUND);
+}