summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <carlos@cmartin.tk>2011-11-18 22:45:56 +0100
committerCarlos Martín Nieto <carlos@cmartin.tk>2011-11-18 22:45:56 +0100
commitbdd31dd5e832126b2f22fccbe244a1106c241ab0 (patch)
treeb08a2ad0fad57131563aa8c071221bea241128c1
parent277b7efe493887081ce1dafd91199d0ee9f676c9 (diff)
parente4c93a392763a006d11e1c1dd01c12f85498dad5 (diff)
downloadlibgit2-error-handling.tar.gz
Merge branch 'development' into error-handlingerror-handling
The code in this branch has been modified so it works with the global state introduced in development.
-rw-r--r--README.md2
-rw-r--r--examples/general.c4
-rw-r--r--examples/network/.gitignore1
-rw-r--r--examples/network/git2.c5
-rw-r--r--include/git2.h1
-rw-r--r--include/git2/common.h13
-rw-r--r--include/git2/indexer.h4
-rw-r--r--include/git2/oid.h2
-rw-r--r--include/git2/refs.h68
-rw-r--r--include/git2/refspec.h2
-rw-r--r--include/git2/remote.h6
-rw-r--r--include/git2/thread-utils.h60
-rw-r--r--include/git2/threads.h48
-rw-r--r--include/git2/tree.h44
-rw-r--r--include/git2/windows.h59
-rw-r--r--src/blob.c2
-rw-r--r--src/buffer.c2
-rw-r--r--src/cache.c2
-rw-r--r--src/commit.c30
-rw-r--r--src/common.h1
-rw-r--r--src/config.c18
-rw-r--r--src/config.h1
-rw-r--r--src/config_file.c76
-rw-r--r--src/delta-apply.c2
-rw-r--r--src/errors.c18
-rw-r--r--src/fetch.c3
-rw-r--r--src/filebuf.c34
-rw-r--r--src/filebuf.h4
-rw-r--r--src/fileops.c50
-rw-r--r--src/fileops.h12
-rw-r--r--src/global.c134
-rw-r--r--src/global.h22
-rw-r--r--src/hash.c2
-rw-r--r--src/hashtable.c10
-rw-r--r--src/index.c26
-rw-r--r--src/index.h3
-rw-r--r--src/indexer.c12
-rw-r--r--src/mwindow.c102
-rw-r--r--src/mwindow.h3
-rw-r--r--src/netops.c2
-rw-r--r--src/object.c2
-rw-r--r--src/odb.c22
-rw-r--r--src/odb.h4
-rw-r--r--src/odb_loose.c35
-rw-r--r--src/odb_pack.c10
-rw-r--r--src/oid.c8
-rw-r--r--src/pack.c24
-rw-r--r--src/pack.h2
-rw-r--r--src/path.c4
-rw-r--r--src/pkt.c6
-rw-r--r--src/posix.c16
-rw-r--r--src/posix.h4
-rw-r--r--src/pqueue.c6
-rw-r--r--src/reflog.c60
-rw-r--r--src/reflog.h2
-rw-r--r--src/refs.c1293
-rw-r--r--src/refs.h13
-rw-r--r--src/refspec.c2
-rw-r--r--src/remote.c20
-rw-r--r--src/repository.c72
-rw-r--r--src/repository.h5
-rw-r--r--src/revwalk.c14
-rw-r--r--src/signature.c6
-rw-r--r--src/status.c139
-rw-r--r--src/tag.c34
-rw-r--r--src/thread-utils.h2
-rw-r--r--src/transports/git.c18
-rw-r--r--src/transports/http.c23
-rw-r--r--src/transports/local.c21
-rw-r--r--src/tree-cache.c4
-rw-r--r--src/tree.c126
-rw-r--r--src/tsort.c4
-rw-r--r--src/util.c4
-rw-r--r--src/util.h2
-rw-r--r--src/vector.c4
-rw-r--r--src/win32/dir.c23
-rw-r--r--src/win32/posix.h15
-rw-r--r--src/win32/posix_w32.c90
-rw-r--r--src/win32/utf-conv.c (renamed from src/win32/utf8-conv.c)34
-rw-r--r--src/win32/utf-conv.h (renamed from src/win32/utf8-conv.h)8
-rw-r--r--tests-clay/README.md2
-rwxr-xr-xtests-clay/clay217
-rw-r--r--tests-clay/clay.h66
-rw-r--r--tests-clay/clay_libgit2.h2
-rw-r--r--tests-clay/clay_main.c533
-rw-r--r--tests-clay/config/stress.c41
-rw-r--r--tests-clay/core/dirent.c6
-rw-r--r--tests-clay/core/filebuf.c6
-rw-r--r--tests-clay/core/path.c4
-rw-r--r--tests-clay/core/rmdir.c14
-rw-r--r--tests-clay/core/vector.c4
-rw-r--r--tests-clay/index/rename.c60
-rw-r--r--tests-clay/object/raw/chars.c52
-rw-r--r--tests-clay/object/raw/compare.c124
-rw-r--r--tests-clay/object/raw/convert.c75
-rw-r--r--tests-clay/object/raw/data.h323
-rw-r--r--tests-clay/object/raw/fromstr.c30
-rw-r--r--tests-clay/object/raw/hash.c162
-rw-r--r--tests-clay/object/raw/short.c94
-rw-r--r--tests-clay/object/raw/size.c13
-rw-r--r--tests-clay/object/raw/type2string.c54
-rw-r--r--tests-clay/object/tree/frompath.c2
-rw-r--r--tests-clay/status/single.c2
-rw-r--r--tests-clay/status/worktree.c2
-rw-r--r--tests/resources/status/.gitted/COMMIT_EDITMSG2
-rw-r--r--tests/resources/status/.gitted/ORIG_HEAD2
-rw-r--r--tests/resources/status/.gitted/indexbin1080 -> 1160 bytes
-rw-r--r--tests/resources/status/.gitted/logs/HEAD1
-rw-r--r--tests/resources/status/.gitted/logs/refs/heads/master1
-rw-r--r--tests/resources/status/.gitted/objects/26/a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f2
-rw-r--r--tests/resources/status/.gitted/objects/37/fcb02ccc1a85d1941e7f106d52dc3702dcf0d0bin0 -> 331 bytes
-rw-r--r--tests/resources/status/.gitted/objects/e8/ee89e15bbe9b20137715232387b3de5b28972ebin0 -> 38 bytes
-rw-r--r--tests/resources/status/.gitted/refs/heads/master2
-rw-r--r--tests/resources/status/subdir.txt2
-rw-r--r--tests/t00-core.c34
-rw-r--r--tests/t01-rawobj.c4
-rw-r--r--tests/t03-objwrite.c2
-rw-r--r--tests/t04-commit.c12
-rw-r--r--tests/t06-index.c4
-rw-r--r--tests/t07-hashtable.c6
-rw-r--r--tests/t08-tag.c9
-rw-r--r--tests/t09-tree.c4
-rw-r--r--tests/t10-refs.c192
-rw-r--r--tests/t12-repo.c12
-rw-r--r--tests/t15-config.c2
-rw-r--r--tests/t18-status.c22
-rw-r--r--tests/test_helpers.c58
-rw-r--r--tests/test_helpers.h5
-rwxr-xr-xtests/test_lib.c4
-rwxr-xr-xtests/test_lib.h1
-rw-r--r--tests/test_main.c4
131 files changed, 3641 insertions, 1705 deletions
diff --git a/README.md b/README.md
index 82517bc48..6ba9e6407 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@ Building libgit2 - Using CMake
==============================
libgit2 builds cleanly on most platforms without any external dependencies.
-Under Unix-like systems, like Linux, * BSD and Mac OS X, libgit2 expects `pthreads` to be available;
+Under Unix-like systems, like Linux, \*BSD and Mac OS X, libgit2 expects `pthreads` to be available;
they should be installed by default on all systems. Under Windows, libgit2 uses the native Windows API
for threading.
diff --git a/examples/general.c b/examples/general.c
index 9bfbc4083..8b58fa6ff 100644
--- a/examples/general.c
+++ b/examples/general.c
@@ -430,14 +430,14 @@ int main (int argc, char** argv)
printf("\n*Config Listing*\n");
const char *email;
- int j;
+ int32_t j;
git_config *cfg;
// Open a config object so we can read global values from it.
git_config_open_ondisk(&cfg, "~/.gitconfig");
- git_config_get_int(cfg, "help.autocorrect", &j);
+ git_config_get_int32(cfg, "help.autocorrect", &j);
printf("Autocorrect: %d\n", j);
git_config_get_string(cfg, "user.email", &email);
diff --git a/examples/network/.gitignore b/examples/network/.gitignore
new file mode 100644
index 000000000..1b48e66ed
--- /dev/null
+++ b/examples/network/.gitignore
@@ -0,0 +1 @@
+/git2
diff --git a/examples/network/git2.c b/examples/network/git2.c
index 0468c8ace..def56e83b 100644
--- a/examples/network/git2.c
+++ b/examples/network/git2.c
@@ -44,7 +44,8 @@ int main(int argc, char **argv)
int i, error;
if (argc < 2) {
- fprintf(stderr, "usage: %s <cmd> [repo]", argv[0]);
+ fprintf(stderr, "usage: %s <cmd> [repo]\n", argv[0]);
+ exit(EXIT_FAILURE);
}
for (i = 0; commands[i].name != NULL; ++i) {
@@ -53,5 +54,5 @@ int main(int argc, char **argv)
}
fprintf(stderr, "Command not found: %s\n", argv[1]);
-
+ return 1;
}
diff --git a/include/git2.h b/include/git2.h
index ad92809bb..14c090e39 100644
--- a/include/git2.h
+++ b/include/git2.h
@@ -11,6 +11,7 @@
#include "git2/version.h"
#include "git2/common.h"
+#include "git2/threads.h"
#include "git2/errors.h"
#include "git2/zlib.h"
diff --git a/include/git2/common.h b/include/git2/common.h
index ef279eac1..eee918a23 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -7,7 +7,6 @@
#ifndef INCLUDE_git_common_h__
#define INCLUDE_git_common_h__
-#include "thread-utils.h"
#include <time.h>
#include <stdlib.h>
@@ -38,18 +37,6 @@
# define GIT_EXTERN(type) extern type
#endif
-/** Declare a public TLS symbol exported for application use. */
-#if __GNUC__ >= 4
-# define GIT_EXTERN_TLS(type) extern \
- __attribute__((visibility("default"))) \
- GIT_TLS \
- type
-#elif defined(_MSC_VER)
-# define GIT_EXTERN_TLS(type) __declspec(dllexport) GIT_TLS type
-#else
-# define GIT_EXTERN_TLS(type) extern GIT_TLS type
-#endif
-
/** Declare a function as always inlined. */
#if defined(_MSC_VER)
# define GIT_INLINE(type) static __inline type
diff --git a/include/git2/indexer.h b/include/git2/indexer.h
index bd9b9b6ab..1e5eb380c 100644
--- a/include/git2/indexer.h
+++ b/include/git2/indexer.h
@@ -7,8 +7,8 @@
#ifndef _INCLUDE_git_indexer_h__
#define _INCLUDE_git_indexer_h__
-#include "git2/common.h"
-#include "git2/oid.h"
+#include "common.h"
+#include "oid.h"
GIT_BEGIN_DECL
diff --git a/include/git2/oid.h b/include/git2/oid.h
index b9824b887..9cebda931 100644
--- a/include/git2/oid.h
+++ b/include/git2/oid.h
@@ -100,7 +100,7 @@ GIT_EXTERN(void) git_oid_pathfmt(char *str, const git_oid *oid);
*
* @param oid the oid structure to format
* @return the c-string; NULL if memory is exhausted. Caller must
- * deallocate the string with free().
+ * deallocate the string with git__free().
*/
GIT_EXTERN(char *) git_oid_allocfmt(const git_oid *oid);
diff --git a/include/git2/refs.h b/include/git2/refs.h
index c319bfb3d..82c5d8881 100644
--- a/include/git2/refs.h
+++ b/include/git2/refs.h
@@ -23,8 +23,7 @@ GIT_BEGIN_DECL
/**
* Lookup a reference by its name in a repository.
*
- * The generated reference is owned by the repository and
- * should not be freed by the user.
+ * The generated reference must be freed by the user.
*
* @param reference_out pointer to the looked-up reference
* @param repo the repository to look up the reference
@@ -39,8 +38,7 @@ GIT_EXTERN(int) git_reference_lookup(git_reference **reference_out, git_reposito
* The reference will be created in the repository and written
* to the disk.
*
- * This reference is owned by the repository and shall not
- * be free'd by the user.
+ * The generated reference must be freed by the user.
*
* If `force` is true and there already exists a reference
* with the same name, it will be overwritten.
@@ -60,8 +58,7 @@ GIT_EXTERN(int) git_reference_create_symbolic(git_reference **ref_out, git_repos
* The reference will be created in the repository and written
* to the disk.
*
- * This reference is owned by the repository and shall not
- * be free'd by the user.
+ * The generated reference must be freed by the user.
*
* If `force` is true and there already exists a reference
* with the same name, it will be overwritten.
@@ -119,8 +116,13 @@ GIT_EXTERN(const char *) git_reference_name(git_reference *ref);
* Thie method iteratively peels a symbolic reference
* until it resolves to a direct reference to an OID.
*
+ * The peeled reference is returned in the `resolved_ref`
+ * argument, and must be freed manually once it's no longer
+ * needed.
+ *
* If a direct reference is passed as an argument,
- * that reference is returned immediately
+ * a copy of that reference is returned. This copy must
+ * be manually freed too.
*
* @param resolved_ref Pointer to the peeled reference
* @param ref The reference
@@ -173,9 +175,19 @@ GIT_EXTERN(int) git_reference_set_oid(git_reference *ref, const git_oid *id);
* The new name will be checked for validity and may be
* modified into a normalized form.
*
- * The refernece will be immediately renamed in-memory
+ * The given git_reference will be updated in place.
+ *
+ * The reference will be immediately renamed in-memory
* and on disk.
*
+ * If the `force` flag is not enabled, and there's already
+ * a reference with the given name, the renaming will fail.
+ *
+ * @param ref The reference to rename
+ * @param new_name The new name for the reference
+ * @param force Overwrite an existing reference
+ * @return GIT_SUCCESS or an error code
+ *
*/
GIT_EXTERN(int) git_reference_rename(git_reference *ref, const char *new_name, int force);
@@ -187,6 +199,8 @@ GIT_EXTERN(int) git_reference_rename(git_reference *ref, const char *new_name, i
* The reference will be immediately removed on disk and from
* memory. The given reference pointer will no longer be valid.
*
+ * @param ref The reference to remove
+ * @return GIT_SUCCESS or an error code
*/
GIT_EXTERN(int) git_reference_delete(git_reference *ref);
@@ -200,9 +214,6 @@ GIT_EXTERN(int) git_reference_delete(git_reference *ref);
* Once the `packed-refs` file has been written properly,
* the loose references will be removed from disk.
*
- * WARNING: calling this method may invalidate any existing
- * references previously loaded on the cache.
- *
* @param repo Repository where the loose refs will be packed
* @return GIT_SUCCESS or an error code
*/
@@ -253,6 +264,41 @@ GIT_EXTERN(int) git_reference_listall(git_strarray *array, git_repository *repo,
*/
GIT_EXTERN(int) git_reference_foreach(git_repository *repo, unsigned int list_flags, int (*callback)(const char *, void *), void *payload);
+/**
+ * Check if a reference has been loaded from a packfile
+ *
+ * @param ref A git reference
+ * @return 0 in case it's not packed; 1 otherwise
+ */
+GIT_EXTERN(int) git_reference_is_packed(git_reference *ref);
+
+/**
+ * Reload a reference from disk
+ *
+ * Reference pointers may become outdated if the Git
+ * repository is accessed simultaneously by other clients
+ * whilt the library is open.
+ *
+ * This method forces a reload of the reference from disk,
+ * to ensure that the provided information is still
+ * reliable.
+ *
+ * If the reload fails (e.g. the reference no longer exists
+ * on disk, or has become corrupted), an error code will be
+ * returned and the reference pointer will be invalidated.
+ *
+ * @param ref The reference to reload
+ * @return GIT_SUCCESS on success, or an error code
+ */
+GIT_EXTERN(int) git_reference_reload(git_reference *ref);
+
+/**
+ * Free the given reference
+ *
+ * @param ref git_reference
+ */
+GIT_EXTERN(void) git_reference_free(git_reference *ref);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/refspec.h b/include/git2/refspec.h
index eccbeaa7c..0f8b13cec 100644
--- a/include/git2/refspec.h
+++ b/include/git2/refspec.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_git_refspec_h__
#define INCLUDE_git_refspec_h__
-#include "git2/types.h"
+#include "types.h"
/**
* @file git2/refspec.h
diff --git a/include/git2/remote.h b/include/git2/remote.h
index e0be93757..54116c22e 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -7,9 +7,9 @@
#ifndef INCLUDE_git_remote_h__
#define INCLUDE_git_remote_h__
-#include "git2/common.h"
-#include "git2/repository.h"
-#include "git2/refspec.h"
+#include "common.h"
+#include "repository.h"
+#include "refspec.h"
/**
* @file git2/remote.h
* @brief Git remote management functions
diff --git a/include/git2/thread-utils.h b/include/git2/thread-utils.h
deleted file mode 100644
index 81c62d135..000000000
--- a/include/git2/thread-utils.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2009-2011 the libgit2 contributors
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-#ifndef INCLUDE_git_thread_utils_h__
-#define INCLUDE_git_thread_utils_h__
-
-/*
- * How TLS works is compiler+platform dependant
- * Sources: http://en.wikipedia.org/wiki/Thread-Specific_Storage
- * http://predef.sourceforge.net/precomp.html
- */
-
-#ifdef GIT_THREADS
-# define GIT_HAS_TLS 1
-
-/* No TLS in Cygwin */
-# if defined(__CHECKER__) || defined(__CYGWIN__)
-# undef GIT_HAS_TLS
-# define GIT_TLS
-
-/* No TLS in Mach binaries for Mac OS X */
-# elif defined(__APPLE__) && defined(__MACH__)
-# undef GIT_TLS
-# define GIT_TLS
-
-/* Normal TLS for GCC */
-# elif defined(__GNUC__) || \
- defined(__SUNPRO_C) || \
- defined(__SUNPRO_CC) || \
- defined(__xlc__) || \
- defined(__xlC__)
-# define GIT_TLS __thread
-
-/* ICC may run on Windows or Linux */
-# elif defined(__INTEL_COMPILER)
-# if defined(_WIN32) || defined(_WIN32_CE)
-# define GIT_TLS __declspec(thread)
-# else
-# define GIT_TLS __thread
-# endif
-
-/* Declspec for MSVC in Win32 */
-# elif defined(_WIN32) || \
- defined(_WIN32_CE) || \
- defined(__BORLANDC__)
-# define GIT_TLS __declspec(thread)
-
-/* Other platform; no TLS */
-# else
-# undef GIT_HAS_TLS
-# define GIT_TLS /* nothing: tls vars are thread-global */
-# endif
-#else /* Disable TLS if libgit2 is not threadsafe */
-# define GIT_TLS
-#endif /* GIT_THREADS */
-
-#endif /* INCLUDE_git_thread_utils_h__ */
diff --git a/include/git2/threads.h b/include/git2/threads.h
new file mode 100644
index 000000000..85472a441
--- /dev/null
+++ b/include/git2/threads.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009-2011 the libgit2 contributors
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_git_threads_h__
+#define INCLUDE_git_threads_h__
+
+#include "common.h"
+
+/**
+ * @file git2/threads.h
+ * @brief Library level thread functions
+ * @defgroup git_thread Threading functions
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Init the threading system.
+ *
+ * If libgit2 has been built with GIT_THREADS
+ * on, this function must be called once before
+ * any other library functions.
+ *
+ * If libgit2 has been built without GIT_THREADS
+ * support, this function is a no-op.
+ */
+GIT_EXTERN(void) git_threads_init(void);
+
+/**
+ * Shutdown the threading system.
+ *
+ * If libgit2 has been built with GIT_THREADS
+ * on, this function must be called before shutting
+ * down the library.
+ *
+ * If libgit2 has been built without GIT_THREADS
+ * support, this function is a no-op.
+ */
+GIT_EXTERN(void) git_threads_shutdown(void);
+
+/** @} */
+GIT_END_DECL
+#endif
+
diff --git a/include/git2/tree.h b/include/git2/tree.h
index 8d638f723..bd89de34f 100644
--- a/include/git2/tree.h
+++ b/include/git2/tree.h
@@ -269,19 +269,49 @@ GIT_EXTERN(void) git_treebuilder_filter(git_treebuilder *bld, int (*filter)(cons
GIT_EXTERN(int) git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *bld);
/**
- * Retrieve the tree object containing a tree entry, given
- * a relative path to this tree entry
+ * Retrieve a subtree contained in a tree, given its
+ * relative path.
*
* The returned tree is owned by the repository and
* should be closed with the `git_object_close` method.
*
- * @param parent_out Pointer where to store the parent tree
+ * @param subtree Pointer where to store the subtree
* @param root A previously loaded tree which will be the root of the relative path
- * @param treeentry_path Path to the tree entry from which to extract the last tree object
- * @return GIT_SUCCESS on success; GIT_ENOTFOUND if the path does not lead to an
- * entry, GIT_EINVALIDPATH or an error code
+ * @param subtree_path Path to the contained subtree
+ * @return GIT_SUCCESS on success; GIT_ENOTFOUND if the path does not lead to a
+ * subtree, GIT_EINVALIDPATH or an error code
*/
-GIT_EXTERN(int) git_tree_frompath(git_tree **parent_out, git_tree *root, const char *treeentry_path);
+GIT_EXTERN(int) git_tree_get_subtree(git_tree **subtree, git_tree *root, const char *subtree_path);
+
+/** Callback for the tree traversal method */
+typedef int (*git_treewalk_cb)(const char *root, git_tree_entry *entry, void *payload);
+
+/** Tree traversal modes */
+enum git_treewalk_mode {
+ GIT_TREEWALK_PRE = 0, /* Pre-order */
+ GIT_TREEWALK_POST = 1, /* Post-order */
+};
+
+/**
+ * Traverse the entries in a tree and its subtrees in
+ * post or pre order
+ *
+ * The entries will be traversed in the specified order,
+ * children subtrees will be automatically loaded as required,
+ * and the `callback` will be called once per entry with
+ * the current (relative) root for the entry and the entry
+ * data itself.
+ *
+ * If the callback returns a negative value, the passed entry
+ * will be skiped on the traversal.
+ *
+ * @param tree The tree to walk
+ * @param callback Function to call on each tree entry
+ * @param mode Traversal mode (pre or post-order)
+ * @return GIT_SUCCESS or an error code
+ */
+GIT_EXTERN(int) git_tree_walk(git_tree *walk, git_treewalk_cb callback, int mode, void *payload);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/windows.h b/include/git2/windows.h
new file mode 100644
index 000000000..6a2e9e2cd
--- /dev/null
+++ b/include/git2/windows.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2009-2011 the libgit2 contributors
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_git_windows_h__
+#define INCLUDE_git_windows_h__
+
+#include "common.h"
+
+/**
+ * @file git2/windows.h
+ * @brief Windows-specific functions
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Set the active codepage for Windows syscalls
+ *
+ * All syscalls performed by the library will assume
+ * this codepage when converting paths and strings
+ * to use by the Windows kernel.
+ *
+ * The default value of UTF-8 will work automatically
+ * with most Git repositories created on Unix systems.
+ *
+ * This settings needs only be changed when working
+ * with repositories that contain paths in specific,
+ * non-UTF codepages.
+ *
+ * A full list of all available codepage identifiers may
+ * be found at:
+ *
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx
+ *
+ * @param codepage numeric codepage identifier
+ */
+GIT_EXTERN(void) gitwin_set_codepage(unsigned int codepage);
+
+/**
+ * Return the active codepage for Windows syscalls
+ *
+ * @return numeric codepage identifier
+ */
+GIT_EXTERN(unsigned int) gitwin_get_codepage(void);
+
+/**
+ * Set the active Windows codepage to UTF-8 (this is
+ * the default value)
+ */
+GIT_EXTERN(void) gitwin_set_utf8(void);
+
+/** @} */
+GIT_END_DECL
+#endif
+
diff --git a/src/blob.c b/src/blob.c
index 42564ab50..f13a5be15 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -27,7 +27,7 @@ size_t git_blob_rawsize(git_blob *blob)
void git_blob__free(git_blob *blob)
{
git_odb_object_close(blob->odb_object);
- free(blob);
+ git__free(blob);
}
int git_blob__parse(git_blob *blob, git_odb_object *odb_obj)
diff --git a/src/buffer.c b/src/buffer.c
index 0eeeecf2f..1fb848e46 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -97,7 +97,7 @@ const char *git_buf_cstr(git_buf *buf)
void git_buf_free(git_buf *buf)
{
- free(buf->ptr);
+ git__free(buf->ptr);
}
void git_buf_clear(git_buf *buf)
diff --git a/src/cache.c b/src/cache.c
index 79f3eaea2..6ba4d212c 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -53,7 +53,7 @@ void git_cache_free(git_cache *cache)
git_mutex_free(&cache->nodes[i].lock);
}
- free(cache->nodes);
+ git__free(cache->nodes);
}
void *git_cache_get(git_cache *cache, const git_oid *oid)
diff --git a/src/commit.c b/src/commit.c
index ced457ecc..83bc9fc4c 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -32,7 +32,7 @@ static void clear_parents(git_commit *commit)
for (i = 0; i < commit->parent_oids.length; ++i) {
git_oid *parent = git_vector_get(&commit->parent_oids, i);
- free(parent);
+ git__free(parent);
}
git_vector_clear(&commit->parent_oids);
@@ -46,9 +46,9 @@ void git_commit__free(git_commit *commit)
git_signature_free(commit->author);
git_signature_free(commit->committer);
- free(commit->message);
- free(commit->message_encoding);
- free(commit);
+ git__free(commit->message);
+ git__free(commit->message_encoding);
+ git__free(commit);
}
const git_oid *git_commit_id(git_commit *c)
@@ -84,7 +84,7 @@ int git_commit_create_v(
message_encoding, message,
tree, parent_count, parents);
- free((void *)parents);
+ git__free((void *)parents);
return error;
}
@@ -137,15 +137,18 @@ int git_commit_create(
if (error == GIT_SUCCESS && update_ref != NULL) {
git_reference *head;
+ git_reference *target;
error = git_reference_lookup(&head, repo, update_ref);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to create commit");
- error = git_reference_resolve(&head, head);
+ error = git_reference_resolve(&target, head);
if (error < GIT_SUCCESS) {
- if (error != GIT_ENOTFOUND)
+ if (error != GIT_ENOTFOUND) {
+ git_reference_free(head);
return git__rethrow(error, "Failed to create commit");
+ }
/*
* The target of the reference was not found. This can happen
* just after a repository has been initialized (the master
@@ -153,10 +156,19 @@ int git_commit_create(
* point to) or after an orphan checkout, so if the target
* branch doesn't exist yet, create it and return.
*/
- return git_reference_create_oid(&head, repo, git_reference_target(head), oid, 1);
+ error = git_reference_create_oid(&target, repo, git_reference_target(head), oid, 1);
+
+ git_reference_free(head);
+ if (error == GIT_SUCCESS)
+ git_reference_free(target);
+
+ return error;
}
- error = git_reference_set_oid(head, oid);
+ error = git_reference_set_oid(target, oid);
+
+ git_reference_free(head);
+ git_reference_free(target);
}
if (error < GIT_SUCCESS)
diff --git a/src/common.h b/src/common.h
index 475edc518..f4dcc1ccd 100644
--- a/src/common.h
+++ b/src/common.h
@@ -8,7 +8,6 @@
#define INCLUDE_common_h__
#include "git2/common.h"
-#include "git2/thread-utils.h"
#include "cc-compat.h"
#include <assert.h>
diff --git a/src/config.c b/src/config.c
index f53afa145..4e48ff7f4 100644
--- a/src/config.c
+++ b/src/config.c
@@ -35,11 +35,11 @@ void git_config_free(git_config *cfg)
internal = git_vector_get(&cfg->files, i);
file = internal->file;
file->free(file);
- free(internal);
+ git__free(internal);
}
git_vector_free(&cfg->files);
- free(cfg);
+ git__free(cfg);
}
static int config_backend_cmp(const void *a, const void *b)
@@ -61,7 +61,7 @@ int git_config_new(git_config **out)
memset(cfg, 0x0, sizeof(git_config));
if (git_vector_init(&cfg->files, 3, config_backend_cmp) < 0) {
- free(cfg);
+ git__free(cfg);
return GIT_ENOMEM;
}
@@ -125,7 +125,7 @@ int git_config_add_file(git_config *cfg, git_config_file *file, int priority)
internal->priority = priority;
if (git_vector_insert(&cfg->files, internal) < 0) {
- free(internal);
+ git__free(internal);
return GIT_ENOMEM;
}
@@ -366,20 +366,20 @@ static int win32_find_system(char *system_config_path)
return git__throw(GIT_ERROR, "Failed to expand environment strings");
if (_waccess(apphome_utf16, F_OK) < 0) {
- free(apphome_utf16);
+ git__free(apphome_utf16);
return GIT_ENOTFOUND;
}
- apphome_utf8 = conv_utf16_to_utf8(apphome_utf16);
- free(apphome_utf16);
+ apphome_utf8 = gitwin_from_utf16(apphome_utf16);
+ git__free(apphome_utf16);
if (strlen(apphome_utf8) >= GIT_PATH_MAX) {
- free(apphome_utf8);
+ git__free(apphome_utf8);
return git__throw(GIT_ESHORTBUFFER, "Path is too long");
}
strcpy(system_config_path, apphome_utf8);
- free(apphome_utf8);
+ git__free(apphome_utf8);
return GIT_SUCCESS;
}
#endif
diff --git a/src/config.h b/src/config.h
index 7749a9c1a..43574a586 100644
--- a/src/config.h
+++ b/src/config.h
@@ -14,6 +14,7 @@
#define GIT_CONFIG_FILENAME ".gitconfig"
#define GIT_CONFIG_FILENAME_INREPO "config"
+#define GIT_CONFIG_FILE_MODE 0666
struct git_config {
git_vector files;
diff --git a/src/config_file.c b/src/config_file.c
index a85ae1578..aec29d4e2 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -90,10 +90,10 @@ static void cvar_free(cvar_t *var)
if (var == NULL)
return;
- free(var->section);
- free(var->name);
- free(var->value);
- free(var);
+ git__free(var->section);
+ git__free(var->name);
+ git__free(var->value);
+ git__free(var);
}
static void cvar_list_free(cvar_t_list *list)
@@ -188,7 +188,7 @@ static int cvar_normalize_name(cvar_t *var, char **output)
if (section_sp == NULL) {
ret = p_snprintf(name, len + 1, "%s.%s", var->section, var->name);
if (ret < 0) {
- free(name);
+ git__free(name);
return git__throw(GIT_EOSERR, "Failed to normalize name. OS err: %s", strerror(errno));
}
@@ -281,10 +281,10 @@ static void backend_free(git_config_file *_backend)
if (backend == NULL)
return;
- free(backend->file_path);
+ git__free(backend->file_path);
cvar_list_free(&backend->var_list);
- free(backend);
+ git__free(backend);
}
static int file_foreach(git_config_file *backend, int (*fn)(const char *, const char *, void *), void *data)
@@ -301,7 +301,7 @@ static int file_foreach(git_config_file *backend, int (*fn)(const char *, const
return ret;
ret = fn(normalized, var->value, data);
- free(normalized);
+ git__free(normalized);
if (ret)
break;
}
@@ -326,7 +326,7 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
if (tmp == NULL && value != NULL)
return GIT_ENOMEM;
- free(existing->value);
+ git__free(existing->value);
existing->value = tmp;
return config_write(b, existing);
@@ -411,7 +411,7 @@ int git_config_file__ondisk(git_config_file **out, const char *path)
backend->file_path = git__strdup(path);
if (backend->file_path == NULL) {
- free(backend);
+ git__free(backend);
return GIT_ENOMEM;
}
@@ -653,13 +653,13 @@ static int parse_section_header(diskfile_backend *cfg, char **section_out)
/* find the end of the variable's name */
name_end = strchr(line, ']');
if (name_end == NULL) {
- free(line);
+ git__free(line);
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse header. Can't find header name end");
}
name = (char *)git__malloc((size_t)(name_end - line) + 1);
if (name == NULL) {
- free(line);
+ git__free(line);
return GIT_ENOMEM;
}
@@ -679,8 +679,8 @@ static int parse_section_header(diskfile_backend *cfg, char **section_out)
if (isspace(c)){
name[name_length] = '\0';
error = parse_section_header_ext(line, name, section_out);
- free(line);
- free(name);
+ git__free(line);
+ git__free(name);
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to parse header");
}
@@ -699,14 +699,14 @@ static int parse_section_header(diskfile_backend *cfg, char **section_out)
}
name[name_length] = 0;
- free(line);
+ git__free(line);
git__strtolower(name);
*section_out = name;
return GIT_SUCCESS;
error:
- free(line);
- free(name);
+ git__free(line);
+ git__free(name);
return error;
}
@@ -810,7 +810,7 @@ static int config_parse(diskfile_backend *cfg_file)
break;
case '[': /* section header, new section begins */
- free(current_section);
+ git__free(current_section);
current_section = NULL;
error = parse_section_header(cfg_file, &current_section);
break;
@@ -826,7 +826,7 @@ static int config_parse(diskfile_backend *cfg_file)
if (error < GIT_SUCCESS)
break;
- var = malloc(sizeof(cvar_t));
+ var = git__malloc(sizeof(cvar_t));
if (var == NULL) {
error = GIT_ENOMEM;
break;
@@ -837,7 +837,7 @@ static int config_parse(diskfile_backend *cfg_file)
var->section = git__strdup(current_section);
if (var->section == NULL) {
error = GIT_ENOMEM;
- free(var);
+ git__free(var);
break;
}
@@ -851,7 +851,7 @@ static int config_parse(diskfile_backend *cfg_file)
}
}
- free(current_section);
+ git__free(current_section);
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to parse config");
}
@@ -915,7 +915,7 @@ static int config_write(diskfile_backend *cfg, cvar_t *var)
*/
pre_end = post_start = cfg->reader.read_ptr;
if (current_section)
- free(current_section);
+ git__free(current_section);
error = parse_section_header(cfg, &current_section);
if (error < GIT_SUCCESS)
break;
@@ -953,8 +953,8 @@ static int config_write(diskfile_backend *cfg, cvar_t *var)
if ((error = parse_variable(cfg, &var_name, &var_value)) == GIT_SUCCESS)
cmp = strcasecmp(var->name, var_name);
- free(var_name);
- free(var_value);
+ git__free(var_name);
+ git__free(var_value);
if (cmp != 0)
break;
@@ -1029,12 +1029,12 @@ static int config_write(diskfile_backend *cfg, cvar_t *var)
git__rethrow(error, "Failed to write new section");
cleanup:
- free(current_section);
+ git__free(current_section);
if (error < GIT_SUCCESS)
git_filebuf_cleanup(&file);
else
- error = git_filebuf_commit(&file);
+ error = git_filebuf_commit(&file, GIT_CONFIG_FILE_MODE);
git_futils_freebuffer(&cfg->reader.buffer);
return error;
@@ -1093,7 +1093,7 @@ static int parse_multiline_variable(diskfile_backend *cfg, const char *first, ch
ret = p_snprintf(buf, len, "%s %s", first, line);
if (ret < 0) {
error = git__throw(GIT_EOSERR, "Failed to parse multiline var. Failed to put together two lines. OS err: %s", strerror(errno));
- free(buf);
+ git__free(buf);
goto out;
}
@@ -1105,14 +1105,14 @@ static int parse_multiline_variable(diskfile_backend *cfg, const char *first, ch
if (is_multiline_var(buf)) {
char *final_val;
error = parse_multiline_variable(cfg, buf, &final_val);
- free(buf);
+ git__free(buf);
buf = final_val;
}
*out = buf;
out:
- free(line);
+ git__free(line);
return error;
}
@@ -1158,19 +1158,25 @@ static int parse_variable(diskfile_backend *cfg, char **var_name, char **var_val
while (isspace(value_start[0]))
value_start++;
- if (value_start[0] == '\0')
+ if (value_start[0] == '\0') {
+ *var_value = NULL;
goto out;
+ }
if (is_multiline_var(value_start)) {
error = parse_multiline_variable(cfg, value_start, var_value);
- if (error < GIT_SUCCESS)
- free(*var_name);
+ if (error != GIT_SUCCESS)
+ {
+ *var_value = NULL;
+ git__free(*var_name);
+ }
goto out;
}
- tmp = strdup(value_start);
+ tmp = git__strdup(value_start);
if (tmp == NULL) {
- free(*var_name);
+ git__free(*var_name);
+ *var_value = NULL;
error = GIT_ENOMEM;
goto out;
}
@@ -1182,6 +1188,6 @@ static int parse_variable(diskfile_backend *cfg, char **var_name, char **var_val
}
out:
- free(line);
+ git__free(line);
return error;
}
diff --git a/src/delta-apply.c b/src/delta-apply.c
index e1fb15b9b..3e40bf8cf 100644
--- a/src/delta-apply.c
+++ b/src/delta-apply.c
@@ -109,7 +109,7 @@ int git__delta_apply(
return GIT_SUCCESS;
fail:
- free(out->data);
+ git__free(out->data);
out->data = NULL;
return git__throw(GIT_ERROR, "Failed to apply delta");
}
diff --git a/src/errors.c b/src/errors.c
index 923cb3507..22b8ae7bf 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -7,14 +7,10 @@
#include "common.h"
#include "errors.h"
-#include "git2/thread-utils.h" /* for GIT_TLS */
-#include "thread-utils.h" /* for GIT_TLS */
#include "posix.h"
-
+#include "global.h"
#include <stdarg.h>
-GIT_TLS git_error *git_errno;
-
static struct {
int num;
const char *str;
@@ -115,11 +111,11 @@ git_error * git_error_createf(const char *file, unsigned int line, int code,
va_end(ap);
err->code = code;
- err->child = git_errno;
+ err->child = GIT_GLOBAL->git_errno;
err->file = file;
err->line = line;
- git_errno = err;
+ GIT_GLOBAL->git_errno = err;
return err;
}
@@ -149,13 +145,13 @@ void git_error_free(git_error *err)
void git_clearerror(void)
{
- git_error_free(git_errno);
- git_errno = NULL;
+ git_error_free(GIT_GLOBAL->git_errno);
+ GIT_GLOBAL->git_errno = NULL;
}
const char *git_lasterror(void)
{
- return git_errno == NULL ? NULL : git_errno->msg;
+ return GIT_GLOBAL->git_errno == NULL ? NULL : GIT_GLOBAL->git_errno->msg;
}
void git_error_print_stack(git_error *error_in)
@@ -163,7 +159,7 @@ void git_error_print_stack(git_error *error_in)
git_error *error;
if (error_in == NULL)
- error_in = git_errno;
+ error_in = GIT_GLOBAL->git_errno;
for (error = error_in; error; error = error->child)
fprintf(stderr, "%s:%u %s\n", error->file, error->line, error->msg);
diff --git a/src/fetch.c b/src/fetch.c
index ac7282819..af7dbaffd 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -14,6 +14,7 @@
#include "transport.h"
#include "remote.h"
#include "refspec.h"
+#include "pack.h"
#include "fetch.h"
#include "netops.h"
@@ -181,7 +182,7 @@ int git_fetch__download_pack(char **out, const char *buffered, size_t buffered_s
}
/* A bit dodgy, but we need to keep the pack at the temporary path */
- error = git_filebuf_commit_at(&file, file.path_lock);
+ error = git_filebuf_commit_at(&file, file.path_lock, GIT_PACK_FILE_MODE);
cleanup:
if (error < GIT_SUCCESS)
git_filebuf_cleanup(&file);
diff --git a/src/filebuf.c b/src/filebuf.c
index 1a98e3f43..199418032 100644
--- a/src/filebuf.c
+++ b/src/filebuf.c
@@ -10,6 +10,8 @@
#include "filebuf.h"
#include "fileops.h"
+#define GIT_LOCK_FILE_MODE 0644
+
static const size_t WRITE_BUFFER_SIZE = (4096 * 2);
static int lock_file(git_filebuf *file, int flags)
@@ -23,9 +25,10 @@ static int lock_file(git_filebuf *file, int flags)
/* create path to the file buffer is required */
if (flags & GIT_FILEBUF_FORCE) {
- file->fd = git_futils_creat_locked_withpath(file->path_lock, 0644);
+ /* XXX: Should dirmode here be configurable? Or is 0777 always fine? */
+ file->fd = git_futils_creat_locked_withpath(file->path_lock, 0777, GIT_LOCK_FILE_MODE);
} else {
- file->fd = git_futils_creat_locked(file->path_lock, 0644);
+ file->fd = git_futils_creat_locked(file->path_lock, GIT_LOCK_FILE_MODE);
}
if (file->fd < 0)
@@ -63,13 +66,13 @@ void git_filebuf_cleanup(git_filebuf *file)
if (file->digest)
git_hash_free_ctx(file->digest);
- free(file->buffer);
- free(file->z_buf);
+ git__free(file->buffer);
+ git__free(file->z_buf);
deflateEnd(&file->zs);
- free(file->path_original);
- free(file->path_lock);
+ git__free(file->path_original);
+ git__free(file->path_lock);
}
GIT_INLINE(int) flush_buffer(git_filebuf *file)
@@ -246,17 +249,17 @@ int git_filebuf_hash(git_oid *oid, git_filebuf *file)
return GIT_SUCCESS;
}
-int git_filebuf_commit_at(git_filebuf *file, const char *path)
+int git_filebuf_commit_at(git_filebuf *file, const char *path, mode_t mode)
{
- free(file->path_original);
+ git__free(file->path_original);
file->path_original = git__strdup(path);
if (file->path_original == NULL)
return GIT_ENOMEM;
- return git_filebuf_commit(file);
+ return git_filebuf_commit(file, mode);
}
-int git_filebuf_commit(git_filebuf *file)
+int git_filebuf_commit(git_filebuf *file, mode_t mode)
{
int error;
@@ -270,7 +273,12 @@ int git_filebuf_commit(git_filebuf *file)
p_close(file->fd);
file->fd = -1;
- error = git_futils_mv_atomic(file->path_lock, file->path_original);
+ if (p_chmod(file->path_lock, mode)) {
+ error = git__throw(GIT_EOSERR, "Failed to chmod locked file before committing");
+ goto cleanup;
+ }
+
+ error = p_rename(file->path_lock, file->path_original);
cleanup:
git_filebuf_cleanup(file);
@@ -368,12 +376,12 @@ int git_filebuf_printf(git_filebuf *file, const char *format, ...)
va_end(arglist);
if (len < 0) {
- free(tmp_buffer);
+ git__free(tmp_buffer);
return git__throw(GIT_EOSERR, "Failed to format string");
}
error = git_filebuf_write(file, tmp_buffer, len);
- free(tmp_buffer);
+ git__free(tmp_buffer);
return error;
}
diff --git a/src/filebuf.h b/src/filebuf.h
index 525ca3c81..d08505e8d 100644
--- a/src/filebuf.h
+++ b/src/filebuf.h
@@ -49,8 +49,8 @@ int git_filebuf_reserve(git_filebuf *file, void **buff, size_t len);
int git_filebuf_printf(git_filebuf *file, const char *format, ...) GIT_FORMAT_PRINTF(2, 3);
int git_filebuf_open(git_filebuf *lock, const char *path, int flags);
-int git_filebuf_commit(git_filebuf *lock);
-int git_filebuf_commit_at(git_filebuf *lock, const char *path);
+int git_filebuf_commit(git_filebuf *lock, mode_t mode);
+int git_filebuf_commit_at(git_filebuf *lock, const char *path, mode_t mode);
void git_filebuf_cleanup(git_filebuf *lock);
int git_filebuf_hash(git_oid *oid, git_filebuf *file);
diff --git a/src/fileops.c b/src/fileops.c
index 203cce0a4..955bb1bf6 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -8,32 +8,8 @@
#include "fileops.h"
#include <ctype.h>
-int git_futils_mv_atomic(const char *from, const char *to)
+int git_futils_mkpath2file(const char *file_path, const mode_t mode)
{
-#ifdef GIT_WIN32
- /*
- * Win32 POSIX compilance my ass. If the destination
- * file exists, the `rename` call fails. This is as
- * close as it gets with the Win32 API.
- */
- return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR;
-#else
- /* Don't even try this on Win32 */
- if (!link(from, to)) {
- p_unlink(from);
- return GIT_SUCCESS;
- }
-
- if (!rename(from, to))
- return GIT_SUCCESS;
-
- return GIT_ERROR;
-#endif
-}
-
-int git_futils_mkpath2file(const char *file_path)
-{
- const int mode = 0755; /* or 0777 ? */
int error = GIT_SUCCESS;
char target_folder_path[GIT_PATH_MAX];
@@ -67,23 +43,23 @@ int git_futils_mktmp(char *path_out, const char *filename)
return fd;
}
-int git_futils_creat_withpath(const char *path, int mode)
+int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode_t mode)
{
- if (git_futils_mkpath2file(path) < GIT_SUCCESS)
+ if (git_futils_mkpath2file(path, dirmode) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to create file %s", path);
return p_creat(path, mode);
}
-int git_futils_creat_locked(const char *path, int mode)
+int git_futils_creat_locked(const char *path, const mode_t mode)
{
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_EXCL, mode);
return fd >= 0 ? fd : git__throw(GIT_EOSERR, "Failed to create locked file. Could not open %s", path);
}
-int git_futils_creat_locked_withpath(const char *path, int mode)
+int git_futils_creat_locked_withpath(const char *path, const mode_t dirmode, const mode_t mode)
{
- if (git_futils_mkpath2file(path) < GIT_SUCCESS)
+ if (git_futils_mkpath2file(path, dirmode) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to create locked file %s", path);
return git_futils_creat_locked(path, mode);
@@ -181,7 +157,7 @@ int git_futils_readbuffer_updated(git_fbuffer *obj, const char *path, time_t *mt
if (p_read(fd, buff, len) < 0) {
p_close(fd);
- free(buff);
+ git__free(buff);
return git__throw(GIT_ERROR, "Failed to read file `%s`", path);
}
buff[len] = '\0';
@@ -207,17 +183,17 @@ int git_futils_readbuffer(git_fbuffer *obj, const char *path)
void git_futils_freebuffer(git_fbuffer *obj)
{
assert(obj);
- free(obj->data);
+ git__free(obj->data);
obj->data = NULL;
}
-int git_futils_mv_withpath(const char *from, const char *to)
+int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmode)
{
- if (git_futils_mkpath2file(to) < GIT_SUCCESS)
+ if (git_futils_mkpath2file(to, dirmode) < GIT_SUCCESS)
return GIT_EOSERR; /* The callee already takes care of setting the correct error message. */
- return git_futils_mv_atomic(from, to); /* The callee already takes care of setting the correct error message. */
+ return p_rename(from, to); /* The callee already takes care of setting the correct error message. */
}
int git_futils_mmap_ro(git_map *out, git_file fd, git_off_t begin, size_t len)
@@ -289,7 +265,7 @@ int git_futils_direach(
return GIT_SUCCESS;
}
-int git_futils_mkdir_r(const char *path, int mode)
+int git_futils_mkdir_r(const char *path, const mode_t mode)
{
int error, root_path_offset;
char *pp, *sp;
@@ -326,7 +302,7 @@ int git_futils_mkdir_r(const char *path, int mode)
error = GIT_SUCCESS;
}
- free(path_copy);
+ git__free(path_copy);
if (error < GIT_SUCCESS)
return git__throw(error, "Failed to recursively create `%s` tree structure", path);
diff --git a/src/fileops.h b/src/fileops.h
index 5b69199d2..56c4770cb 100644
--- a/src/fileops.h
+++ b/src/fileops.h
@@ -48,18 +48,18 @@ extern int git_futils_exists(const char *path);
* Create and open a file, while also
* creating all the folders in its path
*/
-extern int git_futils_creat_withpath(const char *path, int mode);
+extern int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode_t mode);
/**
* Create an open a process-locked file
*/
-extern int git_futils_creat_locked(const char *path, int mode);
+extern int git_futils_creat_locked(const char *path, const mode_t mode);
/**
* Create an open a process-locked file, while
* also creating all the folders in its path
*/
-extern int git_futils_creat_locked_withpath(const char *path, int mode);
+extern int git_futils_creat_locked_withpath(const char *path, const mode_t dirmode, const mode_t mode);
/**
* Check if the given path points to a directory
@@ -74,13 +74,13 @@ extern int git_futils_isfile(const char *path);
/**
* Create a path recursively
*/
-extern int git_futils_mkdir_r(const char *path, int mode);
+extern int git_futils_mkdir_r(const char *path, const mode_t mode);
/**
* Create all the folders required to contain
* the full path of a file
*/
-extern int git_futils_mkpath2file(const char *path);
+extern int git_futils_mkpath2file(const char *path, const mode_t mode);
extern int git_futils_rmdir_r(const char *path, int force);
@@ -98,7 +98,7 @@ extern int git_futils_mv_atomic(const char *from, const char *to);
* Move a file on the filesystem, create the
* destination path if it doesn't exist
*/
-extern int git_futils_mv_withpath(const char *from, const char *to);
+extern int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmode);
/**
diff --git a/src/global.c b/src/global.c
new file mode 100644
index 000000000..8ef286ef0
--- /dev/null
+++ b/src/global.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2009-2011 the libgit2 contributors
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#include "common.h"
+#include "global.h"
+#include "git2/threads.h"
+#include "thread-utils.h"
+
+/**
+ * Handle the global state with TLS
+ *
+ * If libgit2 is built with GIT_THREADS enabled,
+ * the `git_threads_init()` function must be called
+ * before calling any other function of the library.
+ *
+ * This function allocates a TLS index (using pthreads
+ * or the native Win32 API) to store the global state
+ * on a per-thread basis.
+ *
+ * Any internal method that requires global state will
+ * then call `git__global_state()` which returns a pointer
+ * to the global state structure; this pointer is lazily
+ * allocated on each thread.
+ *
+ * Before shutting down the library, the
+ * `git_threads_shutdown` method must be called to free
+ * the previously reserved TLS index.
+ *
+ * If libgit2 is built without threading support, the
+ * `git__global_statestate()` call returns a pointer to a single,
+ * statically allocated global state. The `git_thread_`
+ * functions are not available in that case.
+ */
+
+#if defined(GIT_THREADS) && defined(GIT_WIN32)
+
+static DWORD _tls_index;
+static int _tls_init = 0;
+
+void git_threads_init(void)
+{
+ if (_tls_init)
+ return;
+
+ _tls_index = TlsAlloc();
+ _tls_init = 1;
+}
+
+void git_threads_shutdown(void)
+{
+ TlsFree(_tls_index);
+ _tls_init = 0;
+}
+
+git_global_st *git__global_state(void)
+{
+ void *ptr;
+
+ if ((ptr = TlsGetValue(_tls_index)) != NULL)
+ return ptr;
+
+ ptr = malloc(sizeof(git_global_st));
+ if (!ptr)
+ return NULL;
+
+ memset(ptr, 0x0, sizeof(git_global_st));
+ TlsSetValue(_tls_index, ptr);
+ return ptr;
+}
+
+#elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
+
+static pthread_key_t _tls_key;
+static int _tls_init = 0;
+
+static void cb__free_status(void *st)
+{
+ free(st);
+}
+
+void git_threads_init(void)
+{
+ if (_tls_init)
+ return;
+
+ pthread_key_create(&_tls_key, &cb__free_status);
+ _tls_init = 1;
+}
+
+void git_threads_shutdown(void)
+{
+ pthread_key_delete(_tls_key);
+ _tls_init = 0;
+}
+
+git_global_st *git__global_state(void)
+{
+ void *ptr;
+
+ if ((ptr = pthread_getspecific(_tls_key)) != NULL)
+ return ptr;
+
+ ptr = malloc(sizeof(git_global_st));
+ if (!ptr)
+ return NULL;
+
+ memset(ptr, 0x0, sizeof(git_global_st));
+ pthread_setspecific(_tls_key, ptr);
+ return ptr;
+}
+
+#else
+
+static git_global_st __state;
+
+void git_threads_init(void)
+{
+ /* noop */
+}
+
+void git_threads_shutdown(void)
+{
+ /* noop */
+}
+
+git_global_st *git__global_state(void)
+{
+ return &__state;
+}
+
+#endif /* GIT_THREADS */
diff --git a/src/global.h b/src/global.h
new file mode 100644
index 000000000..6a15a8d02
--- /dev/null
+++ b/src/global.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2009-2011 the libgit2 contributors
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_global_h__
+#define INCLUDE_global_h__
+
+#include "mwindow.h"
+#include "git2/types.h"
+
+typedef struct {
+ git_error *git_errno;
+ git_mwindow_ctl mem_ctl;
+} git_global_st;
+
+git_global_st *git__global_state(void);
+
+#define GIT_GLOBAL (git__global_state())
+
+#endif
diff --git a/src/hash.c b/src/hash.c
index ff85ca957..56063cc0b 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -32,7 +32,7 @@ git_hash_ctx *git_hash_new_ctx(void)
void git_hash_free_ctx(git_hash_ctx *ctx)
{
- free(ctx);
+ git__free(ctx);
}
void git_hash_init(git_hash_ctx *ctx)
diff --git a/src/hashtable.c b/src/hashtable.c
index 1382eabaa..15d173992 100644
--- a/src/hashtable.c
+++ b/src/hashtable.c
@@ -39,17 +39,17 @@ static int resize_to(git_hashtable *self, size_t new_size)
self->is_resizing = 0;
else {
new_size *= 2;
- free(self->nodes);
+ git__free(self->nodes);
}
} while(self->is_resizing);
- free(old_nodes);
+ git__free(old_nodes);
return GIT_SUCCESS;
}
static int set_size(git_hashtable *self, size_t new_size)
{
- self->nodes = realloc(self->nodes, new_size * sizeof(git_hashtable_node));
+ self->nodes = git__realloc(self->nodes, new_size * sizeof(git_hashtable_node));
if (self->nodes == NULL)
return GIT_ENOMEM;
@@ -156,8 +156,8 @@ void git_hashtable_free(git_hashtable *self)
{
assert(self);
- free(self->nodes);
- free(self);
+ git__free(self->nodes);
+ git__free(self);
}
diff --git a/src/index.c b/src/index.c
index 7bf5daf2c..1a9745a2c 100644
--- a/src/index.c
+++ b/src/index.c
@@ -138,7 +138,7 @@ static int index_initialize(git_index **index_out, git_repository *owner, const
index->index_file_path = git__strdup(index_path);
if (index->index_file_path == NULL) {
- free(index);
+ git__free(index);
return GIT_ENOMEM;
}
@@ -179,8 +179,8 @@ void git_index_free(git_index *index)
git_vector_free(&index->entries);
git_vector_free(&index->unmerged);
- free(index->index_file_path);
- free(index);
+ git__free(index->index_file_path);
+ git__free(index);
}
void git_index_clear(git_index *index)
@@ -192,15 +192,15 @@ void git_index_clear(git_index *index)
for (i = 0; i < index->entries.length; ++i) {
git_index_entry *e;
e = git_vector_get(&index->entries, i);
- free(e->path);
- free(e);
+ git__free(e->path);
+ git__free(e);
}
for (i = 0; i < index->unmerged.length; ++i) {
git_index_entry_unmerged *e;
e = git_vector_get(&index->unmerged, i);
- free(e->path);
- free(e);
+ git__free(e->path);
+ git__free(e);
}
git_vector_clear(&index->entries);
@@ -262,7 +262,7 @@ int git_index_write(git_index *index)
return git__rethrow(error, "Failed to write index");
}
- if ((error = git_filebuf_commit(&file)) < GIT_SUCCESS)
+ if ((error = git_filebuf_commit(&file, GIT_INDEX_FILE_MODE)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to write index");
if (p_stat(index->index_file_path, &indexst) == 0) {
@@ -334,7 +334,7 @@ static int index_entry_init(git_index_entry **entry_out, git_index *index, const
entry->flags |= (stage << GIT_IDXENTRY_STAGESHIFT);
entry->path = git__strdup(rel_path);
if (entry->path == NULL) {
- free(entry);
+ git__free(entry);
return GIT_ENOMEM;
}
@@ -364,8 +364,8 @@ static void index_entry_free(git_index_entry *entry)
{
if (!entry)
return;
- free(entry->path);
- free(entry);
+ git__free(entry->path);
+ git__free(entry);
}
static int index_insert(git_index *index, git_index_entry *entry, int replace)
@@ -416,8 +416,8 @@ static int index_insert(git_index *index, git_index_entry *entry, int replace)
/* exists, replace it */
entry_array = (git_index_entry **) index->entries.contents;
- free(entry_array[position]->path);
- free(entry_array[position]);
+ git__free(entry_array[position]->path);
+ git__free(entry_array[position]);
entry_array[position] = entry;
return GIT_SUCCESS;
diff --git a/src/index.h b/src/index.h
index e912770b7..a1cd3403e 100644
--- a/src/index.h
+++ b/src/index.h
@@ -14,6 +14,9 @@
#include "git2/odb.h"
#include "git2/index.h"
+#define GIT_INDEX_FILE "index"
+#define GIT_INDEX_FILE_MODE 0666
+
struct git_index {
git_repository *repository;
char *index_file_path;
diff --git a/src/indexer.c b/src/indexer.c
index d5f605fdb..a69ab850c 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -272,7 +272,7 @@ int git_indexer_write(git_indexer *idx)
/* Figure out what the final name should be */
index_path(filename, idx);
/* Commit file */
- error = git_filebuf_commit_at(&idx->file, filename);
+ error = git_filebuf_commit_at(&idx->file, filename, GIT_PACK_FILE_MODE);
cleanup:
git_mwindow_free_all(&idx->pack->mwf);
@@ -367,7 +367,7 @@ int git_indexer_run(git_indexer *idx, git_indexer_stats *stats)
idx->fanout[i]++;
}
- free(obj.data);
+ git__free(obj.data);
stats->processed = ++processed;
}
@@ -390,12 +390,12 @@ void git_indexer_free(git_indexer *idx)
p_close(idx->pack->mwf.fd);
git_vector_foreach(&idx->objects, i, e)
- free(e);
+ git__free(e);
git_vector_free(&idx->objects);
git_vector_foreach(&idx->pack->cache, i, pe)
- free(pe);
+ git__free(pe);
git_vector_free(&idx->pack->cache);
- free(idx->pack);
- free(idx);
+ git__free(idx->pack);
+ git__free(idx);
}
diff --git a/src/mwindow.c b/src/mwindow.c
index e53477e98..8dc4573b4 100644
--- a/src/mwindow.c
+++ b/src/mwindow.c
@@ -10,6 +10,7 @@
#include "vector.h"
#include "fileops.h"
#include "map.h"
+#include "global.h"
#define DEFAULT_WINDOW_SIZE \
(sizeof(void*) >= 8 \
@@ -20,21 +21,15 @@
((1024 * 1024) * (sizeof(void*) >= 8 ? 8192ULL : 256UL))
/*
- * We need this because each process is only allowed a specific amount
- * of memory. Making it writable should generate one instance per
- * process, but we still need to set a couple of variables.
+ * These are the global options for mmmap limits.
+ * TODO: allow the user to change these
*/
-
-static git_mwindow_ctl ctl = {
- 0,
- 0,
+static struct {
+ size_t window_size;
+ size_t mapped_limit;
+} _mw_options = {
DEFAULT_WINDOW_SIZE,
DEFAULT_MAPPED_LIMIT,
- 0,
- 0,
- 0,
- 0,
- {0, 0, 0, 0, 0}
};
/*
@@ -43,33 +38,34 @@ static git_mwindow_ctl ctl = {
*/
void git_mwindow_free_all(git_mwindow_file *mwf)
{
+ git_mwindow_ctl *ctl = &GIT_GLOBAL->mem_ctl;
unsigned int i;
/*
* Remove these windows from the global list
*/
- for (i = 0; i < ctl.windowfiles.length; ++i){
- if (git_vector_get(&ctl.windowfiles, i) == mwf) {
- git_vector_remove(&ctl.windowfiles, i);
+ for (i = 0; i < ctl->windowfiles.length; ++i){
+ if (git_vector_get(&ctl->windowfiles, i) == mwf) {
+ git_vector_remove(&ctl->windowfiles, i);
break;
}
}
- if (ctl.windowfiles.length == 0) {
- git_vector_free(&ctl.windowfiles);
- ctl.windowfiles.contents = NULL;
+ if (ctl->windowfiles.length == 0) {
+ git_vector_free(&ctl->windowfiles);
+ ctl->windowfiles.contents = NULL;
}
while (mwf->windows) {
git_mwindow *w = mwf->windows;
assert(w->inuse_cnt == 0);
- ctl.mapped -= w->window_map.len;
- ctl.open_windows--;
+ ctl->mapped -= w->window_map.len;
+ ctl->open_windows--;
git_futils_mmap_free(&w->window_map);
mwf->windows = w->next;
- free(w);
+ git__free(w);
}
}
@@ -115,6 +111,7 @@ void git_mwindow_scan_lru(
*/
static int git_mwindow_close_lru(git_mwindow_file *mwf)
{
+ git_mwindow_ctl *ctl = &GIT_GLOBAL->mem_ctl;
unsigned int i;
git_mwindow *lru_w = NULL, *lru_l = NULL, **list = &mwf->windows;
@@ -122,16 +119,16 @@ static int git_mwindow_close_lru(git_mwindow_file *mwf)
if(mwf->windows)
git_mwindow_scan_lru(mwf, &lru_w, &lru_l);
- for (i = 0; i < ctl.windowfiles.length; ++i) {
+ for (i = 0; i < ctl->windowfiles.length; ++i) {
git_mwindow *last = lru_w;
- git_mwindow_file *cur = git_vector_get(&ctl.windowfiles, i);
+ git_mwindow_file *cur = git_vector_get(&ctl->windowfiles, i);
git_mwindow_scan_lru(cur, &lru_w, &lru_l);
if (lru_w != last)
list = &cur->windows;
}
if (lru_w) {
- ctl.mapped -= lru_w->window_map.len;
+ ctl->mapped -= lru_w->window_map.len;
git_futils_mmap_free(&lru_w->window_map);
if (lru_l)
@@ -139,8 +136,8 @@ static int git_mwindow_close_lru(git_mwindow_file *mwf)
else
*list = lru_w->next;
- free(lru_w);
- ctl.open_windows--;
+ git__free(lru_w);
+ ctl->open_windows--;
return GIT_SUCCESS;
}
@@ -148,9 +145,14 @@ static int git_mwindow_close_lru(git_mwindow_file *mwf)
return git__throw(GIT_ERROR, "Failed to close memory window. Couln't find LRU");
}
-static git_mwindow *new_window(git_mwindow_file *mwf, git_file fd, git_off_t size, git_off_t offset)
+static git_mwindow *new_window(
+ git_mwindow_file *mwf,
+ git_file fd,
+ git_off_t size,
+ git_off_t offset)
{
- size_t walign = ctl.window_size / 2;
+ git_mwindow_ctl *ctl = &GIT_GLOBAL->mem_ctl;
+ size_t walign = _mw_options.window_size / 2;
git_off_t len;
git_mwindow *w;
@@ -162,16 +164,16 @@ static git_mwindow *new_window(git_mwindow_file *mwf, git_file fd, git_off_t siz
w->offset = (offset / walign) * walign;
len = size - w->offset;
- if (len > (git_off_t)ctl.window_size)
- len = (git_off_t)ctl.window_size;
+ if (len > (git_off_t)_mw_options.window_size)
+ len = (git_off_t)_mw_options.window_size;
- ctl.mapped += (size_t)len;
+ ctl->mapped += (size_t)len;
- while(ctl.mapped_limit < ctl.mapped &&
- git_mwindow_close_lru(mwf) == GIT_SUCCESS) {}
+ while (_mw_options.mapped_limit < ctl->mapped &&
+ git_mwindow_close_lru(mwf) == GIT_SUCCESS) /* nop */;
/*
- * We treat ctl.mapped_limit as a soft limit. If we can't find a
+ * We treat _mw_options.mapped_limit as a soft limit. If we can't find a
* window to close and are above the limit, we still mmap the new
* window.
*/
@@ -179,19 +181,19 @@ static git_mwindow *new_window(git_mwindow_file *mwf, git_file fd, git_off_t siz
if (git_futils_mmap_ro(&w->window_map, fd, w->offset, (size_t)len) < GIT_SUCCESS)
goto cleanup;
- ctl.mmap_calls++;
- ctl.open_windows++;
+ ctl->mmap_calls++;
+ ctl->open_windows++;
- if (ctl.mapped > ctl.peak_mapped)
- ctl.peak_mapped = ctl.mapped;
+ if (ctl->mapped > ctl->peak_mapped)
+ ctl->peak_mapped = ctl->mapped;
- if (ctl.open_windows > ctl.peak_open_windows)
- ctl.peak_open_windows = ctl.open_windows;
+ if (ctl->open_windows > ctl->peak_open_windows)
+ ctl->peak_open_windows = ctl->open_windows;
return w;
cleanup:
- free(w);
+ git__free(w);
return NULL;
}
@@ -199,9 +201,14 @@ cleanup:
* Open a new window, closing the least recenty used until we have
* enough space. Don't forget to add it to your list
*/
-unsigned char *git_mwindow_open(git_mwindow_file *mwf, git_mwindow **cursor,
- git_off_t offset, int extra, unsigned int *left)
+unsigned char *git_mwindow_open(
+ git_mwindow_file *mwf,
+ git_mwindow **cursor,
+ git_off_t offset,
+ int extra,
+ unsigned int *left)
{
+ git_mwindow_ctl *ctl = &GIT_GLOBAL->mem_ctl;
git_mwindow *w = *cursor;
if (!w || !git_mwindow_contains(w, offset + extra)) {
@@ -229,7 +236,7 @@ unsigned char *git_mwindow_open(git_mwindow_file *mwf, git_mwindow **cursor,
/* If we changed w, store it in the cursor */
if (w != *cursor) {
- w->last_used = ctl.used_ctr++;
+ w->last_used = ctl->used_ctr++;
w->inuse_cnt++;
*cursor = w;
}
@@ -245,13 +252,14 @@ unsigned char *git_mwindow_open(git_mwindow_file *mwf, git_mwindow **cursor,
int git_mwindow_file_register(git_mwindow_file *mwf)
{
+ git_mwindow_ctl *ctl = &GIT_GLOBAL->mem_ctl;
int error;
- if (ctl.windowfiles.length == 0 &&
- (error = git_vector_init(&ctl.windowfiles, 8, NULL)) < GIT_SUCCESS)
+ if (ctl->windowfiles.length == 0 &&
+ (error = git_vector_init(&ctl->windowfiles, 8, NULL)) < GIT_SUCCESS)
return error;
- return git_vector_insert(&ctl.windowfiles, mwf);
+ return git_vector_insert(&ctl->windowfiles, mwf);
}
void git_mwindow_close(git_mwindow **window)
diff --git a/src/mwindow.h b/src/mwindow.h
index ec75f901f..11c3aa840 100644
--- a/src/mwindow.h
+++ b/src/mwindow.h
@@ -10,7 +10,6 @@
#include "map.h"
#include "vector.h"
-#include "fileops.h"
typedef struct git_mwindow {
struct git_mwindow *next;
@@ -29,8 +28,6 @@ typedef struct git_mwindow_file {
typedef struct git_mwindow_ctl {
size_t mapped;
unsigned int open_windows;
- size_t window_size; /* needs default value */
- size_t mapped_limit; /* needs default value */
unsigned int mmap_calls;
unsigned int peak_open_windows;
size_t peak_mapped;
diff --git a/src/netops.c b/src/netops.c
index dad296a94..73375d725 100644
--- a/src/netops.c
+++ b/src/netops.c
@@ -190,7 +190,7 @@ int gitno_extract_host_and_port(char **host, char **port, const char *url, const
delim = colon == NULL ? slash : colon;
*host = git__strndup(url, delim - url);
if (*host == NULL) {
- free(*port);
+ git__free(*port);
error = GIT_ENOMEM;
}
diff --git a/src/object.c b/src/object.c
index edc2d80fa..c84e94b05 100644
--- a/src/object.c
+++ b/src/object.c
@@ -213,7 +213,7 @@ void git_object__free(void *_obj)
break;
default:
- free(object);
+ git__free(object);
break;
}
}
diff --git a/src/odb.c b/src/odb.c
index 60789cf70..69fdba009 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -83,8 +83,8 @@ static void free_odb_object(void *o)
git_odb_object *object = (git_odb_object *)o;
if (object != NULL) {
- free(object->raw.data);
- free(object);
+ git__free(object->raw.data);
+ git__free(object);
}
}
@@ -205,8 +205,8 @@ static void fake_wstream__free(git_odb_stream *_stream)
{
fake_wstream *stream = (fake_wstream *)_stream;
- free(stream->buffer);
- free(stream);
+ git__free(stream->buffer);
+ git__free(stream);
}
static int init_fake_wstream(git_odb_stream **stream_p, git_odb_backend *backend, size_t size, git_otype type)
@@ -221,7 +221,7 @@ static int init_fake_wstream(git_odb_stream **stream_p, git_odb_backend *backend
stream->type = type;
stream->buffer = git__malloc(size);
if (stream->buffer == NULL) {
- free(stream);
+ git__free(stream);
return GIT_ENOMEM;
}
@@ -265,12 +265,12 @@ int git_odb_new(git_odb **out)
error = git_cache_init(&db->cache, GIT_DEFAULT_CACHE_SIZE, &free_odb_object);
if (error < GIT_SUCCESS) {
- free(db);
+ git__free(db);
return git__rethrow(error, "Failed to create object database");
}
if ((error = git_vector_init(&db->backends, 4, backend_sort_cmp)) < GIT_SUCCESS) {
- free(db);
+ git__free(db);
return git__rethrow(error, "Failed to create object database");
}
@@ -296,7 +296,7 @@ static int add_backend_internal(git_odb *odb, git_odb_backend *backend, int prio
internal->is_alternate = is_alternate;
if (git_vector_insert(&odb->backends, internal) < 0) {
- free(internal);
+ git__free(internal);
return GIT_ENOMEM;
}
@@ -421,14 +421,14 @@ void git_odb_close(git_odb *db)
git_odb_backend *backend = internal->backend;
if (backend->free) backend->free(backend);
- else free(backend);
+ else git__free(backend);
- free(internal);
+ git__free(internal);
}
git_vector_free(&db->backends);
git_cache_free(&db->cache);
- free(db);
+ git__free(db);
}
int git_odb_exists(git_odb *db, const git_oid *id)
diff --git a/src/odb.h b/src/odb.h
index 4e850916b..833739e99 100644
--- a/src/odb.h
+++ b/src/odb.h
@@ -14,6 +14,10 @@
#include "vector.h"
#include "cache.h"
+#define GIT_OBJECTS_DIR "objects/"
+#define GIT_OBJECT_DIR_MODE 0777
+#define GIT_OBJECT_FILE_MODE 0444
+
/* DO NOT EXPORT */
typedef struct {
void *data; /**< Raw, decompressed object data. */
diff --git a/src/odb_loose.c b/src/odb_loose.c
index dbfe18b43..57a0b0a8e 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -277,7 +277,7 @@ static void *inflate_tail(z_stream *s, void *hb, size_t used, obj_hdr *hdr)
else {
set_stream_output(s, buf + used, hdr->size - used);
if (finish_inflate(s)) {
- free(buf);
+ git__free(buf);
return NULL;
}
}
@@ -317,7 +317,7 @@ static int inflate_packlike_loose_disk_obj(git_rawobj *out, git_fbuffer *obj)
in = ((unsigned char *)obj->data) + used;
len = obj->len - used;
if (inflate_buffer(in, len, buf, hdr.size)) {
- free(buf);
+ git__free(buf);
return git__throw(GIT_ERROR, "Failed to inflate loose object. Could not inflate buffer");
}
buf[hdr.size] = '\0';
@@ -666,11 +666,22 @@ static int loose_backend__stream_fwrite(git_oid *oid, git_odb_stream *_stream)
if (object_file_name(final_path, sizeof(final_path), backend->objects_dir, oid))
return GIT_ENOMEM;
- if ((error = git_futils_mkpath2file(final_path)) < GIT_SUCCESS)
+ if ((error = git_futils_mkpath2file(final_path, GIT_OBJECT_DIR_MODE)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to write loose backend");
stream->finished = 1;
- return git_filebuf_commit_at(&stream->fbuf, final_path);
+
+ /*
+ * Don't try to add an existing object to the repository. This
+ * is what git does and allows us to sidestep the fact that
+ * we're not allowed to overwrite a read-only file on Windows.
+ */
+ if (git_futils_exists(final_path) == GIT_SUCCESS) {
+ git_filebuf_cleanup(&stream->fbuf);
+ return GIT_SUCCESS;
+ }
+
+ return git_filebuf_commit_at(&stream->fbuf, final_path, GIT_OBJECT_FILE_MODE);
}
static int loose_backend__stream_write(git_odb_stream *_stream, const char *data, size_t len)
@@ -686,7 +697,7 @@ static void loose_backend__stream_free(git_odb_stream *_stream)
if (!stream->finished)
git_filebuf_cleanup(&stream->fbuf);
- free(stream);
+ git__free(stream);
}
static int format_object_header(char *hdr, size_t n, size_t obj_len, git_otype obj_type)
@@ -739,14 +750,14 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_
(backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT));
if (error < GIT_SUCCESS) {
- free(stream);
+ git__free(stream);
return git__rethrow(error, "Failed to create loose backend stream");
}
error = stream->stream.write((git_odb_stream *)stream, hdr, hdrlen);
if (error < GIT_SUCCESS) {
git_filebuf_cleanup(&stream->fbuf);
- free(stream);
+ git__free(stream);
return git__rethrow(error, "Failed to create loose backend stream");
}
@@ -787,10 +798,10 @@ static int loose_backend__write(git_oid *oid, git_odb_backend *_backend, const v
if ((error = object_file_name(final_path, sizeof(final_path), backend->objects_dir, oid)) < GIT_SUCCESS)
goto cleanup;
- if ((error = git_futils_mkpath2file(final_path)) < GIT_SUCCESS)
+ if ((error = git_futils_mkpath2file(final_path, GIT_OBJECT_DIR_MODE)) < GIT_SUCCESS)
goto cleanup;
- return git_filebuf_commit_at(&fbuf, final_path);
+ return git_filebuf_commit_at(&fbuf, final_path, GIT_OBJECT_FILE_MODE);
cleanup:
git_filebuf_cleanup(&fbuf);
@@ -803,8 +814,8 @@ static void loose_backend__free(git_odb_backend *_backend)
assert(_backend);
backend = (loose_backend *)_backend;
- free(backend->objects_dir);
- free(backend);
+ git__free(backend->objects_dir);
+ git__free(backend);
}
int git_odb_backend_loose(
@@ -821,7 +832,7 @@ int git_odb_backend_loose(
backend->objects_dir = git__strdup(objects_dir);
if (backend->objects_dir == NULL) {
- free(backend);
+ git__free(backend);
return GIT_ENOMEM;
}
diff --git a/src/odb_pack.c b/src/odb_pack.c
index a8f854236..800e7b0da 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -231,7 +231,7 @@ static int packfile_load__cb(void *_data, char *path)
return git__rethrow(error, "Failed to load packfile");
if (git_vector_insert(&backend->packs, pack) < GIT_SUCCESS) {
- free(pack);
+ git__free(pack);
return GIT_ENOMEM;
}
@@ -445,8 +445,8 @@ static void pack_backend__free(git_odb_backend *_backend)
}
git_vector_free(&backend->packs);
- free(backend->pack_folder);
- free(backend);
+ git__free(backend->pack_folder);
+ git__free(backend);
}
int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
@@ -459,7 +459,7 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
return GIT_ENOMEM;
if (git_vector_init(&backend->packs, 8, packfile_sort__cb) < GIT_SUCCESS) {
- free(backend);
+ git__free(backend);
return GIT_ENOMEM;
}
@@ -469,7 +469,7 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
backend->pack_folder_mtime = 0;
if (backend->pack_folder == NULL) {
- free(backend);
+ git__free(backend);
return GIT_ENOMEM;
}
}
diff --git a/src/oid.c b/src/oid.c
index bbf19ea20..4b3080430 100644
--- a/src/oid.c
+++ b/src/oid.c
@@ -223,7 +223,7 @@ struct git_oid_shorten {
static int resize_trie(git_oid_shorten *self, size_t new_size)
{
- self->nodes = realloc(self->nodes, new_size * sizeof(trie_node));
+ self->nodes = git__realloc(self->nodes, new_size * sizeof(trie_node));
if (self->nodes == NULL)
return GIT_ENOMEM;
@@ -270,7 +270,7 @@ git_oid_shorten *git_oid_shorten_new(size_t min_length)
memset(os, 0x0, sizeof(git_oid_shorten));
if (resize_trie(os, 16) < GIT_SUCCESS) {
- free(os);
+ git__free(os);
return NULL;
}
@@ -282,8 +282,8 @@ git_oid_shorten *git_oid_shorten_new(size_t min_length)
void git_oid_shorten_free(git_oid_shorten *os)
{
- free(os->nodes);
- free(os);
+ git__free(os->nodes);
+ git__free(os);
}
diff --git a/src/pack.c b/src/pack.c
index 2516bea93..ae954b988 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -5,11 +5,13 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "mwindow.h"
+#include "common.h"
#include "odb.h"
#include "pack.h"
#include "delta-apply.h"
#include "sha1_lookup.h"
+#include "mwindow.h"
+#include "fileops.h"
#include "git2/oid.h"
#include "git2/zlib.h"
@@ -181,7 +183,7 @@ static int pack_index_open(struct git_pack_file *p)
strcpy(idx_name + strlen(idx_name) - strlen(".pack"), ".idx");
error = pack_index_check(idx_name, p);
- free(idx_name);
+ git__free(idx_name);
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to open index");
}
@@ -297,7 +299,7 @@ static int packfile_unpack_delta(
error = packfile_unpack_compressed(&delta, p, w_curs, curpos, delta_size, delta_type);
if (error < GIT_SUCCESS) {
- free(base.data);
+ git__free(base.data);
return git__rethrow(error, "Corrupted delta");
}
@@ -306,8 +308,8 @@ static int packfile_unpack_delta(
base.data, base.len,
delta.data, delta.len);
- free(base.data);
- free(delta.data);
+ git__free(base.data);
+ git__free(delta.data);
/* TODO: we might want to cache this shit. eventually */
//add_delta_base_cache(p, base_offset, base, base_size, *type);
@@ -390,7 +392,7 @@ int packfile_unpack_compressed(
st = inflateInit(&stream);
if (st != Z_OK) {
- free(buffer);
+ git__free(buffer);
return git__throw(GIT_EZLIB, "Error in zlib");
}
@@ -408,7 +410,7 @@ int packfile_unpack_compressed(
inflateEnd(&stream);
if ((st != Z_STREAM_END) || stream.total_out != size) {
- free(buffer);
+ git__free(buffer);
return git__throw(GIT_EZLIB, "Error in zlib");
}
@@ -504,8 +506,8 @@ void packfile_free(struct git_pack_file *p)
pack_index_free(p);
- free(p->bad_object_sha1);
- free(p);
+ git__free(p->bad_object_sha1);
+ git__free(p);
}
static int packfile_open(struct git_pack_file *p)
@@ -598,7 +600,7 @@ int git_packfile_check(struct git_pack_file **pack_out, const char *path)
*/
path_len -= strlen(".idx");
if (path_len < 1) {
- free(p);
+ git__free(p);
return git__throw(GIT_ENOTFOUND, "Failed to check packfile. Wrong path name");
}
@@ -610,7 +612,7 @@ int git_packfile_check(struct git_pack_file **pack_out, const char *path)
strcpy(p->pack_name + path_len, ".pack");
if (p_stat(p->pack_name, &st) < GIT_SUCCESS || !S_ISREG(st.st_mode)) {
- free(p);
+ git__free(p);
return git__throw(GIT_ENOTFOUND, "Failed to check packfile. File not found");
}
diff --git a/src/pack.h b/src/pack.h
index 0fddd9dc8..aecf580e9 100644
--- a/src/pack.h
+++ b/src/pack.h
@@ -15,6 +15,8 @@
#include "mwindow.h"
#include "odb.h"
+#define GIT_PACK_FILE_MODE 0444
+
#define PACK_SIGNATURE 0x5041434b /* "PACK" */
#define PACK_VERSION 2
#define pack_version_ok(v) ((v) == htonl(2) || (v) == htonl(3))
diff --git a/src/path.c b/src/path.c
index 2c6b76dd0..a8851dfdc 100644
--- a/src/path.c
+++ b/src/path.c
@@ -144,7 +144,7 @@ char *git_path_dirname(const char *path)
return NULL;
if (git_path_dirname_r(dname, len, path) < GIT_SUCCESS) {
- free(dname);
+ git__free(dname);
return NULL;
}
@@ -162,7 +162,7 @@ char *git_path_basename(const char *path)
return NULL;
if (git_path_basename_r(bname, len, path) < GIT_SUCCESS) {
- free(bname);
+ git__free(bname);
return NULL;
}
diff --git a/src/pkt.c b/src/pkt.c
index 9471df2d5..ff8c56eb2 100644
--- a/src/pkt.c
+++ b/src/pkt.c
@@ -149,7 +149,7 @@ static int ref_pkt(git_pkt **out, const char *line, size_t len)
out:
if (error < GIT_SUCCESS)
- free(pkt);
+ git__free(pkt);
else
*out = (git_pkt *)pkt;
@@ -260,10 +260,10 @@ void git_pkt_free(git_pkt *pkt)
{
if(pkt->type == GIT_PKT_REF) {
git_pkt_ref *p = (git_pkt_ref *) pkt;
- free(p->head.name);
+ git__free(p->head.name);
}
- free(pkt);
+ git__free(pkt);
}
int git_pkt_buffer_flush(git_buf *buf)
diff --git a/src/posix.c b/src/posix.c
index 1b85b053d..8c19588ee 100644
--- a/src/posix.c
+++ b/src/posix.c
@@ -17,7 +17,7 @@ int p_open(const char *path, int flags)
return open(path, flags | O_BINARY);
}
-int p_creat(const char *path, int mode)
+int p_creat(const char *path, mode_t mode)
{
return open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
}
@@ -39,6 +39,20 @@ int p_getcwd(char *buffer_out, size_t size)
return GIT_SUCCESS;
}
+int p_rename(const char *from, const char *to)
+{
+ if (!link(from, to)) {
+ p_unlink(from);
+ return GIT_SUCCESS;
+ }
+
+ if (!rename(from, to))
+ return GIT_SUCCESS;
+
+ return GIT_ERROR;
+
+}
+
#endif
int p_read(git_file fd, void *buf, size_t cnt)
diff --git a/src/posix.h b/src/posix.h
index 59bec2794..c12b41364 100644
--- a/src/posix.h
+++ b/src/posix.h
@@ -40,10 +40,12 @@ extern int p_write(git_file fd, const void *buf, size_t cnt);
#define p_fstat(f,b) fstat(f, b)
#define p_lseek(f,n,w) lseek(f, n, w)
#define p_close(fd) close(fd)
+#define p_umask(m) umask(m)
extern int p_open(const char *path, int flags);
-extern int p_creat(const char *path, int mode);
+extern int p_creat(const char *path, mode_t mode);
extern int p_getcwd(char *buffer_out, size_t size);
+extern int p_rename(const char *from, const char *to);
#ifndef GIT_WIN32
diff --git a/src/pqueue.c b/src/pqueue.c
index b5ddab835..80713fbba 100644
--- a/src/pqueue.c
+++ b/src/pqueue.c
@@ -17,7 +17,7 @@ int git_pqueue_init(git_pqueue *q, size_t n, git_pqueue_cmp cmppri)
assert(q);
/* Need to allocate n+1 elements since element 0 isn't used. */
- if ((q->d = malloc((n + 1) * sizeof(void *))) == NULL)
+ if ((q->d = git__malloc((n + 1) * sizeof(void *))) == NULL)
return GIT_ENOMEM;
q->size = 1;
@@ -30,7 +30,7 @@ int git_pqueue_init(git_pqueue *q, size_t n, git_pqueue_cmp cmppri)
void git_pqueue_free(git_pqueue *q)
{
- free(q->d);
+ git__free(q->d);
q->d = NULL;
}
@@ -102,7 +102,7 @@ int git_pqueue_insert(git_pqueue *q, void *d)
/* allocate more memory if necessary */
if (q->size >= q->avail) {
newsize = q->size + q->step;
- if ((tmp = realloc(q->d, sizeof(void *) * newsize)) == NULL)
+ if ((tmp = git__realloc(q->d, sizeof(void *) * newsize)) == NULL)
return GIT_ENOMEM;
q->d = tmp;
diff --git a/src/reflog.c b/src/reflog.c
index 594963c03..e0fa7a060 100644
--- a/src/reflog.c
+++ b/src/reflog.c
@@ -25,8 +25,8 @@ static int reflog_init(git_reflog **reflog, git_reference *ref)
log->ref_name = git__strdup(ref->name);
if (git_vector_init(&log->entries, 0, NULL) < 0) {
- free(log->ref_name);
- free(log);
+ git__free(log->ref_name);
+ git__free(log);
return GIT_ENOMEM;
}
@@ -71,7 +71,7 @@ static int reflog_write(const char *log_path, const char *oid_old,
}
git_filebuf_write(&fbuf, log.ptr, log.size);
- error = git_filebuf_commit(&fbuf);
+ error = git_filebuf_commit(&fbuf, GIT_REFLOG_FILE_MODE);
git_buf_free(&log);
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write reflog");
@@ -86,8 +86,8 @@ static int reflog_parse(git_reflog *log, const char *buf, size_t buf_size)
#define seek_forward(_increase) { \
if (_increase >= buf_size) { \
if (entry->committer) \
- free(entry->committer); \
- free(entry); \
+ git__free(entry->committer); \
+ git__free(entry); \
return git__throw(GIT_ERROR, "Failed to seek forward. Buffer size exceeded"); \
} \
buf += _increase; \
@@ -101,13 +101,13 @@ static int reflog_parse(git_reflog *log, const char *buf, size_t buf_size)
entry->committer = NULL;
if (git_oid_fromstrn(&entry->oid_old, buf, GIT_OID_HEXSZ) < GIT_SUCCESS) {
- free(entry);
+ git__free(entry);
return GIT_ERROR;
}
seek_forward(GIT_OID_HEXSZ + 1);
if (git_oid_fromstrn(&entry->oid_cur, buf, GIT_OID_HEXSZ) < GIT_SUCCESS) {
- free(entry);
+ git__free(entry);
return GIT_ERROR;
}
seek_forward(GIT_OID_HEXSZ + 1);
@@ -120,13 +120,13 @@ static int reflog_parse(git_reflog *log, const char *buf, size_t buf_size)
entry->committer = git__malloc(sizeof(git_signature));
if (entry->committer == NULL) {
- free(entry);
+ git__free(entry);
return GIT_ENOMEM;
}
if ((error = git_signature__parse(entry->committer, &ptr, buf + 1, NULL, *buf)) < GIT_SUCCESS) {
- free(entry->committer);
- free(entry);
+ git__free(entry->committer);
+ git__free(entry);
return git__rethrow(error, "Failed to parse reflog. Could not parse signature");
}
@@ -164,13 +164,13 @@ void git_reflog_free(git_reflog *reflog)
git_signature_free(entry->committer);
- free(entry->msg);
- free(entry);
+ git__free(entry->msg);
+ git__free(entry);
}
git_vector_free(&reflog->entries);
- free(reflog->ref_name);
- free(reflog);
+ git__free(reflog->ref_name);
+ git__free(reflog);
}
int git_reflog_read(git_reflog **reflog, git_reference *ref)
@@ -215,23 +215,37 @@ int git_reflog_write(git_reference *ref, const git_oid *oid_old,
const git_oid *oid;
if ((error = git_reference_resolve(&r, ref)) < GIT_SUCCESS)
- return git__rethrow(error, "Failed to write reflog. Cannot resolve reference `%s`", ref->name);
+ return git__rethrow(error,
+ "Failed to write reflog. Cannot resolve reference `%s`", ref->name);
oid = git_reference_oid(r);
- if (oid == NULL)
- return git__throw(GIT_ERROR, "Failed to write reflog. Cannot resolve reference `%s`", r->name);
+ if (oid == NULL) {
+ git_reference_free(r);
+ return git__throw(GIT_ERROR,
+ "Failed to write reflog. Cannot resolve reference `%s`", r->name);
+ }
git_oid_to_string(new, GIT_OID_HEXSZ+1, oid);
- git_path_join_n(log_path, 3, ref->owner->path_repository, GIT_REFLOG_DIR, ref->name);
+ git_path_join_n(log_path, 3,
+ ref->owner->path_repository, GIT_REFLOG_DIR, ref->name);
+
+ git_reference_free(r);
if (git_futils_exists(log_path)) {
- if ((error = git_futils_mkpath2file(log_path)) < GIT_SUCCESS)
- return git__rethrow(error, "Failed to write reflog. Cannot create reflog directory");
+ error = git_futils_mkpath2file(log_path, GIT_REFLOG_DIR_MODE);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error,
+ "Failed to write reflog. Cannot create reflog directory");
+
} else if (git_futils_isfile(log_path)) {
- return git__throw(GIT_ERROR, "Failed to write reflog. `%s` is directory", log_path);
- } else if (oid_old == NULL)
- return git__throw(GIT_ERROR, "Failed to write reflog. Old OID cannot be NULL for existing reference");
+ return git__throw(GIT_ERROR,
+ "Failed to write reflog. `%s` is directory", log_path);
+
+ } else if (oid_old == NULL) {
+ return git__throw(GIT_ERROR,
+ "Failed to write reflog. Old OID cannot be NULL for existing reference");
+ }
if (oid_old)
git_oid_to_string(old, GIT_OID_HEXSZ+1, oid_old);
diff --git a/src/reflog.h b/src/reflog.h
index 093874e51..44b063700 100644
--- a/src/reflog.h
+++ b/src/reflog.h
@@ -12,6 +12,8 @@
#include "vector.h"
#define GIT_REFLOG_DIR "logs/"
+#define GIT_REFLOG_DIR_MODE 0777
+#define GIT_REFLOG_FILE_MODE 0666
#define GIT_REFLOG_SIZE_MIN (2*GIT_OID_HEXSZ+2+17)
diff --git a/src/refs.c b/src/refs.c
index fcf771b5e..569efbf78 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -9,22 +9,24 @@
#include "hash.h"
#include "repository.h"
#include "fileops.h"
+#include "pack.h"
#include <git2/tag.h>
#include <git2/object.h>
#define MAX_NESTING_LEVEL 5
-typedef struct {
- git_reference ref;
- git_oid oid;
- git_oid peel_target;
-} reference_oid;
+enum {
+ GIT_PACKREF_HAS_PEEL = 1,
+ GIT_PACKREF_WAS_LOOSE = 2
+};
-typedef struct {
- git_reference ref;
- char *target;
-} reference_symbolic;
+struct packref {
+ git_oid oid;
+ git_oid peel;
+ char flags;
+ char name[GIT_FLEX_ARRAY];
+};
static const int default_table_size = 32;
@@ -39,97 +41,83 @@ static uint32_t reftable_hash(const void *key, int hash_id)
return git__hash(key, strlen((const char *)key), hash_seeds[hash_id]);
}
-static void reference_free(git_reference *reference);
-static int reference_create(git_reference **ref_out, git_repository *repo, const char *name, git_rtype type);
-static int reference_read(git_fbuffer *file_content, time_t *mtime, const char *repo_path, const char *ref_name, int *updated);
+static int reference_read(
+ git_fbuffer *file_content,
+ time_t *mtime,
+ const char *repo_path,
+ const char *ref_name,
+ int *updated);
/* loose refs */
static int loose_parse_symbolic(git_reference *ref, git_fbuffer *file_content);
-static int loose_parse_oid(git_reference *ref, git_fbuffer *file_content);
-static int loose_lookup(git_reference **ref_out, git_repository *repo, const char *name, int skip_symbolic);
+static int loose_parse_oid(git_oid *ref, git_fbuffer *file_content);
+static int loose_lookup(git_reference *ref);
+static int loose_lookup_to_packfile(struct packref **ref_out,
+ git_repository *repo, const char *name);
static int loose_write(git_reference *ref);
-static int loose_update(git_reference *ref);
/* packed refs */
-static int packed_parse_peel(reference_oid *tag_ref, const char **buffer_out, const char *buffer_end);
-static int packed_parse_oid(reference_oid **ref_out, git_repository *repo, const char **buffer_out, const char *buffer_end);
+static int packed_parse_peel(struct packref *tag_ref,
+ const char **buffer_out, const char *buffer_end);
+static int packed_parse_oid(struct packref **ref_out,
+ const char **buffer_out, const char *buffer_end);
static int packed_load(git_repository *repo);
static int packed_loadloose(git_repository *repository);
-static int packed_write_ref(reference_oid *ref, git_filebuf *file);
-static int packed_find_peel(reference_oid *ref);
+static int packed_write_ref(struct packref *ref, git_filebuf *file);
+static int packed_find_peel(git_repository *repo, struct packref *ref);
static int packed_remove_loose(git_repository *repo, git_vector *packing_list);
static int packed_sort(const void *a, const void *b);
+static int packed_lookup(git_reference *ref);
static int packed_write(git_repository *repo);
/* internal helpers */
-static int reference_available(git_repository *repo, const char *ref, const char *old_ref);
+static int reference_available(git_repository *repo,
+ const char *ref, const char *old_ref);
+static int reference_delete(git_reference *ref);
+static int reference_lookup(git_reference *ref);
/* name normalization */
-static int check_valid_ref_char(char ch);
-static int normalize_name(char *buffer_out, size_t out_size, const char *name, int is_oid_ref);
+static int normalize_name(char *buffer_out, size_t out_size,
+ const char *name, int is_oid_ref);
-/*****************************************
- * Internal methods - Constructor/destructor
- *****************************************/
-static void reference_free(git_reference *reference)
+
+void git_reference_free(git_reference *reference)
{
if (reference == NULL)
return;
- if (reference->name)
- free(reference->name);
+ git__free(reference->name);
- if (reference->type == GIT_REF_SYMBOLIC)
- free(((reference_symbolic *)reference)->target);
+ if (reference->flags & GIT_REF_SYMBOLIC)
+ git__free(reference->target.symbolic);
- free(reference);
+ git__free(reference);
}
static int reference_create(
git_reference **ref_out,
git_repository *repo,
- const char *name,
- git_rtype type)
+ const char *name)
{
- char normalized[GIT_REFNAME_MAX];
- int error = GIT_SUCCESS, size;
git_reference *reference = NULL;
assert(ref_out && repo && name);
- if (type == GIT_REF_SYMBOLIC)
- size = sizeof(reference_symbolic);
- else if (type == GIT_REF_OID)
- size = sizeof(reference_oid);
- else
- return git__throw(GIT_EINVALIDARGS,
- "Invalid reference type. Use either GIT_REF_OID or GIT_REF_SYMBOLIC as type specifier");
-
- reference = git__malloc(size);
+ reference = git__malloc(sizeof(git_reference));
if (reference == NULL)
return GIT_ENOMEM;
- memset(reference, 0x0, size);
+ memset(reference, 0x0, sizeof(git_reference));
reference->owner = repo;
- reference->type = type;
-
- error = normalize_name(normalized, sizeof(normalized), name, (type & GIT_REF_OID));
- if (error < GIT_SUCCESS)
- goto cleanup;
- reference->name = git__strdup(normalized);
+ reference->name = git__strdup(name);
if (reference->name == NULL) {
- error = GIT_ENOMEM;
- goto cleanup;
+ free(reference);
+ return GIT_ENOMEM;
}
*ref_out = reference;
-
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create reference");
-
-cleanup:
- reference_free(reference);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create reference");
+ return GIT_SUCCESS;
}
static int reference_read(git_fbuffer *file_content, time_t *mtime, const char *repo_path, const char *ref_name, int *updated)
@@ -144,62 +132,13 @@ static int reference_read(git_fbuffer *file_content, time_t *mtime, const char *
return git_futils_readbuffer_updated(file_content, path, mtime, updated);
}
-
-
-
-/*****************************************
- * Internal methods - Loose references
- *****************************************/
-static int loose_update(git_reference *ref)
-{
- int error, updated;
- git_fbuffer ref_file = GIT_FBUFFER_INIT;
-
- if (ref->type & GIT_REF_PACKED)
- return packed_load(ref->owner);
-
-/* error = reference_read(NULL, &ref_time, ref->owner->path_repository, ref->name);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- if (ref_time == ref->mtime)
- return GIT_SUCCESS;
-*/
- error = reference_read(&ref_file, &ref->mtime, ref->owner->path_repository, ref->name, &updated);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- if (!updated)
- goto cleanup;
-
- if (ref->type == GIT_REF_SYMBOLIC)
- error = loose_parse_symbolic(ref, &ref_file);
- else if (ref->type == GIT_REF_OID)
- error = loose_parse_oid(ref, &ref_file);
- else
- error = git__throw(GIT_EOBJCORRUPTED,
- "Invalid reference type (%d) for loose reference", ref->type);
-
-
-cleanup:
- git_futils_freebuffer(&ref_file);
- if (error != GIT_SUCCESS) {
- reference_free(ref);
- git_hashtable_remove(ref->owner->references.loose_cache, ref->name);
- }
-
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to update loose reference");
-}
-
static int loose_parse_symbolic(git_reference *ref, git_fbuffer *file_content)
{
const unsigned int header_len = strlen(GIT_SYMREF);
const char *refname_start;
char *eol;
- reference_symbolic *ref_sym;
refname_start = (const char *)file_content->data;
- ref_sym = (reference_symbolic *)ref;
if (file_content->len < (header_len + 1))
return git__throw(GIT_EOBJCORRUPTED,
@@ -212,13 +151,12 @@ static int loose_parse_symbolic(git_reference *ref, git_fbuffer *file_content)
refname_start += header_len;
- free(ref_sym->target);
- ref_sym->target = git__strdup(refname_start);
- if (ref_sym->target == NULL)
+ ref->target.symbolic = git__strdup(refname_start);
+ if (ref->target.symbolic == NULL)
return GIT_ENOMEM;
/* remove newline at the end of file */
- eol = strchr(ref_sym->target, '\n');
+ eol = strchr(ref->target.symbolic, '\n');
if (eol == NULL)
return git__throw(GIT_EOBJCORRUPTED,
"Failed to parse loose reference. Missing EOL");
@@ -230,21 +168,19 @@ static int loose_parse_symbolic(git_reference *ref, git_fbuffer *file_content)
return GIT_SUCCESS;
}
-static int loose_parse_oid(git_reference *ref, git_fbuffer *file_content)
+static int loose_parse_oid(git_oid *oid, git_fbuffer *file_content)
{
int error;
- reference_oid *ref_oid;
char *buffer;
buffer = (char *)file_content->data;
- ref_oid = (reference_oid *)ref;
/* File format: 40 chars (OID) + newline */
if (file_content->len < GIT_OID_HEXSZ + 1)
return git__throw(GIT_EOBJCORRUPTED,
"Failed to parse loose reference. Reference too short");
- if ((error = git_oid_fromstr(&ref_oid->oid, buffer)) < GIT_SUCCESS)
+ if ((error = git_oid_fromstr(oid, buffer)) < GIT_SUCCESS)
return git__rethrow(GIT_EOBJCORRUPTED, "Failed to parse loose reference.");
buffer = buffer + GIT_OID_HEXSZ;
@@ -258,7 +194,6 @@ static int loose_parse_oid(git_reference *ref, git_fbuffer *file_content)
return GIT_SUCCESS;
}
-
static git_rtype loose_guess_rtype(const char *full_path)
{
git_fbuffer ref_file = GIT_FBUFFER_INIT;
@@ -277,52 +212,75 @@ static git_rtype loose_guess_rtype(const char *full_path)
return type;
}
-static int loose_lookup(
- git_reference **ref_out,
+static int loose_lookup(git_reference *ref)
+{
+ int error = GIT_SUCCESS, updated;
+ git_fbuffer ref_file = GIT_FBUFFER_INIT;
+
+ if (reference_read(&ref_file, &ref->mtime,
+ ref->owner->path_repository, ref->name, &updated) < GIT_SUCCESS)
+ return git__throw(GIT_ENOTFOUND, "Failed to lookup loose reference");
+
+ if (!updated)
+ return GIT_SUCCESS;
+
+ if (ref->flags & GIT_REF_SYMBOLIC)
+ free(ref->target.symbolic);
+
+ ref->flags = 0;
+
+ if (git__prefixcmp((const char *)(ref_file.data), GIT_SYMREF) == 0) {
+ ref->flags |= GIT_REF_SYMBOLIC;
+ error = loose_parse_symbolic(ref, &ref_file);
+ } else {
+ ref->flags |= GIT_REF_OID;
+ error = loose_parse_oid(&ref->target.oid, &ref_file);
+ }
+
+ git_futils_freebuffer(&ref_file);
+
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to lookup loose reference");
+
+ return GIT_SUCCESS;
+}
+
+static int loose_lookup_to_packfile(
+ struct packref **ref_out,
git_repository *repo,
- const char *name,
- int skip_symbolic)
+ const char *name)
{
int error = GIT_SUCCESS;
git_fbuffer ref_file = GIT_FBUFFER_INIT;
- git_reference *ref = NULL;
- time_t ref_time = 0;
+ struct packref *ref = NULL;
+ size_t name_len;
*ref_out = NULL;
- error = reference_read(&ref_file, &ref_time, repo->path_repository, name, NULL);
+ error = reference_read(&ref_file, NULL, repo->path_repository, name, NULL);
if (error < GIT_SUCCESS)
goto cleanup;
- if (git__prefixcmp((const char *)(ref_file.data), GIT_SYMREF) == 0) {
- if (skip_symbolic)
- return GIT_SUCCESS;
-
- error = reference_create(&ref, repo, name, GIT_REF_SYMBOLIC);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- error = loose_parse_symbolic(ref, &ref_file);
- } else {
- error = reference_create(&ref, repo, name, GIT_REF_OID);
- if (error < GIT_SUCCESS)
- goto cleanup;
+ name_len = strlen(name);
+ ref = git__malloc(sizeof(struct packref) + name_len + 1);
- error = loose_parse_oid(ref, &ref_file);
- }
+ memcpy(ref->name, name, name_len);
+ ref->name[name_len] = 0;
+ error = loose_parse_oid(&ref->oid, &ref_file);
if (error < GIT_SUCCESS)
goto cleanup;
- ref->mtime = ref_time;
+ ref->flags = GIT_PACKREF_WAS_LOOSE;
+
*ref_out = ref;
git_futils_freebuffer(&ref_file);
return GIT_SUCCESS;
cleanup:
git_futils_freebuffer(&ref_file);
- reference_free(ref);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to lookup loose reference");
+ free(ref);
+ return git__rethrow(error, "Failed to lookup loose reference");
}
static int loose_write(git_reference *ref)
@@ -337,49 +295,36 @@ static int loose_write(git_reference *ref)
if ((error = git_filebuf_open(&file, ref_path, GIT_FILEBUF_FORCE)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to write loose reference");
- if (ref->type & GIT_REF_OID) {
- reference_oid *ref_oid = (reference_oid *)ref;
+ if (ref->flags & GIT_REF_OID) {
char oid[GIT_OID_HEXSZ + 1];
- memset(oid, 0x0, sizeof(oid));
+ git_oid_fmt(oid, &ref->target.oid);
+ oid[GIT_OID_HEXSZ] = '\0';
- git_oid_fmt(oid, &ref_oid->oid);
error = git_filebuf_printf(&file, "%s\n", oid);
if (error < GIT_SUCCESS)
goto unlock;
- } else if (ref->type & GIT_REF_SYMBOLIC) { /* GIT_REF_SYMBOLIC */
- reference_symbolic *ref_sym = (reference_symbolic *)ref;
-
- error = git_filebuf_printf(&file, GIT_SYMREF "%s\n", ref_sym->target);
+ } else if (ref->flags & GIT_REF_SYMBOLIC) { /* GIT_REF_SYMBOLIC */
+ error = git_filebuf_printf(&file, GIT_SYMREF "%s\n", ref->target.symbolic);
} else {
- error = git__throw(GIT_EOBJCORRUPTED, "Failed to write reference. Invalid reference type");
+ error = git__throw(GIT_EOBJCORRUPTED,
+ "Failed to write reference. Invalid reference type");
goto unlock;
}
- error = git_filebuf_commit(&file);
-
if (p_stat(ref_path, &st) == GIT_SUCCESS)
ref->mtime = st.st_mtime;
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write loose reference");
+ return git_filebuf_commit(&file, GIT_REFS_FILE_MODE);
unlock:
git_filebuf_cleanup(&file);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write loose reference");
+ return git__rethrow(error, "Failed to write loose reference");
}
-
-
-
-
-
-/*****************************************
- * Internal methods - Packed references
- *****************************************/
-
static int packed_parse_peel(
- reference_oid *tag_ref,
+ struct packref *tag_ref,
const char **buffer_out,
const char *buffer_end)
{
@@ -389,47 +334,48 @@ static int packed_parse_peel(
/* Ensure it's not the first entry of the file */
if (tag_ref == NULL)
- return git__throw(GIT_EPACKEDREFSCORRUPTED, "Failed to parse packed reference. Reference is the first entry of the file");
+ return git__throw(GIT_EPACKEDREFSCORRUPTED,
+ "Failed to parse packed reference. "
+ "Reference is the first entry of the file");
/* Ensure reference is a tag */
- if (git__prefixcmp(tag_ref->ref.name, GIT_REFS_TAGS_DIR) != 0)
- return git__throw(GIT_EPACKEDREFSCORRUPTED, "Failed to parse packed reference. Reference is not a tag");
+ if (git__prefixcmp(tag_ref->name, GIT_REFS_TAGS_DIR) != 0)
+ return git__throw(GIT_EPACKEDREFSCORRUPTED,
+ "Failed to parse packed reference. Reference is not a tag");
if (buffer + GIT_OID_HEXSZ >= buffer_end)
- return git__throw(GIT_EPACKEDREFSCORRUPTED, "Failed to parse packed reference. Buffer too small");
+ return git__throw(GIT_EPACKEDREFSCORRUPTED,
+ "Failed to parse packed reference. Buffer too small");
/* Is this a valid object id? */
- if (git_oid_fromstr(&tag_ref->peel_target, buffer) < GIT_SUCCESS)
- return git__throw(GIT_EPACKEDREFSCORRUPTED, "Failed to parse packed reference. Not a valid object ID");
+ if (git_oid_fromstr(&tag_ref->peel, buffer) < GIT_SUCCESS)
+ return git__throw(GIT_EPACKEDREFSCORRUPTED,
+ "Failed to parse packed reference. Not a valid object ID");
buffer = buffer + GIT_OID_HEXSZ;
if (*buffer == '\r')
buffer++;
if (*buffer != '\n')
- return git__throw(GIT_EPACKEDREFSCORRUPTED, "Failed to parse packed reference. Buffer not terminated correctly");
+ return git__throw(GIT_EPACKEDREFSCORRUPTED,
+ "Failed to parse packed reference. Buffer not terminated correctly");
*buffer_out = buffer + 1;
- tag_ref->ref.type |= GIT_REF_HAS_PEEL;
-
return GIT_SUCCESS;
}
static int packed_parse_oid(
- reference_oid **ref_out,
- git_repository *repo,
+ struct packref **ref_out,
const char **buffer_out,
const char *buffer_end)
{
- git_reference *_ref = NULL;
- reference_oid *ref = NULL;
+ struct packref *ref = NULL;
const char *buffer = *buffer_out;
const char *refname_begin, *refname_end;
int error = GIT_SUCCESS;
- int refname_len;
- char refname[GIT_REFNAME_MAX];
+ size_t refname_len;
git_oid id;
refname_begin = (buffer + GIT_OID_HEXSZ + 1);
@@ -449,22 +395,19 @@ static int packed_parse_oid(
goto cleanup;
}
- refname_len = refname_end - refname_begin;
-
- memcpy(refname, refname_begin, refname_len);
- refname[refname_len] = 0;
+ if (refname_end[-1] == '\r')
+ refname_end--;
- if (refname[refname_len - 1] == '\r')
- refname[refname_len - 1] = 0;
+ refname_len = refname_end - refname_begin;
- error = reference_create(&_ref, repo, refname, GIT_REF_OID);
- if (error < GIT_SUCCESS)
- goto cleanup;
+ ref = git__malloc(sizeof(struct packref) + refname_len + 1);
- ref = (reference_oid *)_ref;
+ memcpy(ref->name, refname_begin, refname_len);
+ ref->name[refname_len] = 0;
git_oid_cpy(&ref->oid, &id);
- ref->ref.type |= GIT_REF_PACKED;
+
+ ref->flags = 0;
*ref_out = ref;
*buffer_out = refname_end + 1;
@@ -472,8 +415,8 @@ static int packed_parse_oid(
return GIT_SUCCESS;
cleanup:
- reference_free((git_reference *)ref);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to parse OID of packed reference");
+ free(ref);
+ return git__rethrow(error, "Failed to parse OID of packed reference");
}
static int packed_load(git_repository *repo)
@@ -488,7 +431,7 @@ static int packed_load(git_repository *repo)
ref_cache->packfile = git_hashtable_alloc(
default_table_size,
reftable_hash,
- (git_hash_keyeq_ptr)(&git__strcmp_cb));
+ (git_hash_keyeq_ptr)&git__strcmp_cb);
if (ref_cache->packfile == NULL) {
error = GIT_ENOMEM;
@@ -497,7 +440,7 @@ static int packed_load(git_repository *repo)
}
error = reference_read(&packfile, &ref_cache->packfile_time,
- repo->path_repository, GIT_PACKEDREFS_FILE, &updated);
+ repo->path_repository, GIT_PACKEDREFS_FILE, &updated);
/*
* If we couldn't find the file, we need to clear the table and
@@ -535,9 +478,9 @@ static int packed_load(git_repository *repo)
}
while (buffer_start < buffer_end) {
- reference_oid *ref = NULL;
+ struct packref *ref = NULL;
- error = packed_parse_oid(&ref, repo, &buffer_start, buffer_end);
+ error = packed_parse_oid(&ref, &buffer_start, buffer_end);
if (error < GIT_SUCCESS)
goto cleanup;
@@ -547,9 +490,9 @@ static int packed_load(git_repository *repo)
goto cleanup;
}
- error = git_hashtable_insert(ref_cache->packfile, ref->ref.name, ref);
+ error = git_hashtable_insert(ref_cache->packfile, ref->name, ref);
if (error < GIT_SUCCESS) {
- reference_free((git_reference *)ref);
+ free(ref);
goto cleanup;
}
}
@@ -561,12 +504,10 @@ cleanup:
git_hashtable_free(ref_cache->packfile);
ref_cache->packfile = NULL;
git_futils_freebuffer(&packfile);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to load packed references");
+ return git__rethrow(error, "Failed to load packed references");
}
-
-
struct dirent_list_data {
git_repository *repo;
size_t repo_path_len;
@@ -582,7 +523,8 @@ static int _dirent_loose_listall(void *_data, char *full_path)
char *file_path = full_path + data->repo_path_len;
if (git_futils_isdir(full_path) == GIT_SUCCESS)
- return git_futils_direach(full_path, GIT_PATH_MAX, _dirent_loose_listall, _data);
+ return git_futils_direach(full_path, GIT_PATH_MAX,
+ _dirent_loose_listall, _data);
/* do not add twice a reference that exists already in the packfile */
if ((data->list_flags & GIT_REF_PACKED) != 0 &&
@@ -600,29 +542,35 @@ static int _dirent_loose_listall(void *_data, char *full_path)
static int _dirent_loose_load(void *data, char *full_path)
{
git_repository *repository = (git_repository *)data;
- git_reference *reference;
void *old_ref = NULL;
+ struct packref *ref;
char *file_path;
int error;
if (git_futils_isdir(full_path) == GIT_SUCCESS)
- return git_futils_direach(full_path, GIT_PATH_MAX, _dirent_loose_load, repository);
+ return git_futils_direach(
+ full_path, GIT_PATH_MAX,
+ _dirent_loose_load, repository);
file_path = full_path + strlen(repository->path_repository);
- error = loose_lookup(&reference, repository, file_path, 1);
- if (error == GIT_SUCCESS && reference != NULL) {
- reference->type |= GIT_REF_PACKED;
+ error = loose_lookup_to_packfile(&ref, repository, file_path);
- if (git_hashtable_insert2(repository->references.packfile, reference->name, reference, &old_ref) < GIT_SUCCESS) {
- reference_free(reference);
+ if (error == GIT_SUCCESS) {
+
+ if (git_hashtable_insert2(
+ repository->references.packfile,
+ ref->name, ref, &old_ref) < GIT_SUCCESS) {
+ free(ref);
return GIT_ENOMEM;
}
if (old_ref != NULL)
- reference_free((git_reference *)old_ref);
+ free(old_ref);
}
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to load loose dirent");
+ return error == GIT_SUCCESS ?
+ GIT_SUCCESS :
+ git__rethrow(error, "Failed to load loose references into packfile");
}
/*
@@ -640,30 +588,20 @@ static int packed_loadloose(git_repository *repository)
git_path_join(refs_path, repository->path_repository, GIT_REFS_DIR);
- /* Remove any loose references from the cache */
- {
- const void *GIT_UNUSED(_unused);
- git_reference *reference;
-
- GIT_HASHTABLE_FOREACH(repository->references.loose_cache, _unused, reference,
- reference_free(reference);
- );
- }
-
- git_hashtable_clear(repository->references.loose_cache);
-
/*
* Load all the loose files from disk into the Packfile table.
* This will overwrite any old packed entries with their
* updated loose versions
*/
- return git_futils_direach(refs_path, GIT_PATH_MAX, _dirent_loose_load, repository);
+ return git_futils_direach(
+ refs_path, GIT_PATH_MAX,
+ _dirent_loose_load, repository);
}
/*
* Write a single reference into a packfile
*/
-static int packed_write_ref(reference_oid *ref, git_filebuf *file)
+static int packed_write_ref(struct packref *ref, git_filebuf *file)
{
int error;
char oid[GIT_OID_HEXSZ + 1];
@@ -681,17 +619,19 @@ static int packed_write_ref(reference_oid *ref, git_filebuf *file)
* This obviously only applies to tags.
* The required peels have already been loaded into `ref->peel_target`.
*/
- if (ref->ref.type & GIT_REF_HAS_PEEL) {
+ if (ref->flags & GIT_PACKREF_HAS_PEEL) {
char peel[GIT_OID_HEXSZ + 1];
- git_oid_fmt(peel, &ref->peel_target);
+ git_oid_fmt(peel, &ref->peel);
peel[GIT_OID_HEXSZ] = 0;
- error = git_filebuf_printf(file, "%s %s\n^%s\n", oid, ref->ref.name, peel);
+ error = git_filebuf_printf(file, "%s %s\n^%s\n", oid, ref->name, peel);
} else {
- error = git_filebuf_printf(file, "%s %s\n", oid, ref->ref.name);
+ error = git_filebuf_printf(file, "%s %s\n", oid, ref->name);
}
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write packed reference");
+ return error == GIT_SUCCESS ?
+ GIT_SUCCESS :
+ git__rethrow(error, "Failed to write packed reference");
}
/*
@@ -702,25 +642,25 @@ static int packed_write_ref(reference_oid *ref, git_filebuf *file)
* cache on the packfile the OID of the object to
* which that 'big tag' is pointing to.
*/
-static int packed_find_peel(reference_oid *ref)
+static int packed_find_peel(git_repository *repo, struct packref *ref)
{
git_object *object;
int error;
- if (ref->ref.type & GIT_REF_HAS_PEEL)
+ if (ref->flags & GIT_PACKREF_HAS_PEEL)
return GIT_SUCCESS;
/*
* Only applies to tags, i.e. references
* in the /refs/tags folder
*/
- if (git__prefixcmp(ref->ref.name, GIT_REFS_TAGS_DIR) != 0)
+ if (git__prefixcmp(ref->name, GIT_REFS_TAGS_DIR) != 0)
return GIT_SUCCESS;
/*
* Find the tagged object in the repository
*/
- error = git_object_lookup(&object, ref->ref.owner, &ref->oid, GIT_OBJ_ANY);
+ error = git_object_lookup(&object, repo, &ref->oid, GIT_OBJ_ANY);
if (error < GIT_SUCCESS)
return git__throw(GIT_EOBJCORRUPTED, "Failed to find packed reference");
@@ -735,8 +675,8 @@ static int packed_find_peel(reference_oid *ref)
/*
* Find the object pointed at by this tag
*/
- git_oid_cpy(&ref->peel_target, git_tag_target_oid(tag));
- ref->ref.type |= GIT_REF_HAS_PEEL;
+ git_oid_cpy(&ref->peel, git_tag_target_oid(tag));
+ ref->flags |= GIT_PACKREF_HAS_PEEL;
/*
* The reference has now cached the resolved OID, and is
@@ -746,7 +686,6 @@ static int packed_find_peel(reference_oid *ref)
}
git_object_close(object);
-
return GIT_SUCCESS;
}
@@ -766,16 +705,11 @@ static int packed_remove_loose(git_repository *repo, git_vector *packing_list)
unsigned int i;
char full_path[GIT_PATH_MAX];
int error = GIT_SUCCESS;
- git_reference *reference;
for (i = 0; i < packing_list->length; ++i) {
- git_reference *ref = git_vector_get(packing_list, i);
+ struct packref *ref = git_vector_get(packing_list, i);
- /* Ensure the packed reference doesn't exist
- * in a (more up-to-date?) state as a loose reference
- */
- reference = git_hashtable_lookup(ref->owner->references.loose_cache, ref->name);
- if (reference != NULL)
+ if ((ref->flags & GIT_PACKREF_WAS_LOOSE) == 0)
continue;
git_path_join(full_path, repo->path_repository, ref->name);
@@ -789,19 +723,18 @@ static int packed_remove_loose(git_repository *repo, git_vector *packing_list)
* but we should keep going and remove as many as possible.
* After we've removed as many files as possible, we return
* the error code anyway.
- *
- * TODO: mark this with a very special error code?
- * GIT_EFAILTORMLOOSE
*/
}
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to remove loose packed reference");
+ return error == GIT_SUCCESS ?
+ GIT_SUCCESS :
+ git__rethrow(error, "Failed to remove loose packed reference");
}
static int packed_sort(const void *a, const void *b)
{
- const git_reference *ref_a = (const git_reference *)a;
- const git_reference *ref_b = (const git_reference *)b;
+ const struct packref *ref_a = (const struct packref *)a;
+ const struct packref *ref_b = (const struct packref *)b;
return strcmp(ref_a->name, ref_b->name);
}
@@ -822,16 +755,18 @@ static int packed_write(git_repository *repo)
assert(repo && repo->references.packfile);
total_refs = repo->references.packfile->key_count;
- if ((error = git_vector_init(&packing_list, total_refs, packed_sort)) < GIT_SUCCESS)
- return git__rethrow(error, "Failed to write packed reference");
+ if ((error =
+ git_vector_init(&packing_list, total_refs, packed_sort)) < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to init packed refernces list");
/* Load all the packfile into a vector */
{
- git_reference *reference;
+ struct packref *reference;
const void *GIT_UNUSED(_unused);
GIT_HASHTABLE_FOREACH(repo->references.packfile, _unused, reference,
- git_vector_insert(&packing_list, reference); /* cannot fail: vector already has the right size */
+ /* cannot fail: vector already has the right size */
+ git_vector_insert(&packing_list, reference);
);
}
@@ -841,27 +776,24 @@ static int packed_write(git_repository *repo)
/* Now we can open the file! */
git_path_join(pack_file_path, repo->path_repository, GIT_PACKEDREFS_FILE);
if ((error = git_filebuf_open(&pack_file, pack_file_path, 0)) < GIT_SUCCESS)
- return git__rethrow(error, "Failed to write packed reference");
+ return git__rethrow(error, "Failed to write open packed references file");
/* Packfiles have a header... apparently
* This is in fact not required, but we might as well print it
* just for kicks */
- if ((error = git_filebuf_printf(&pack_file, "%s\n", GIT_PACKEDREFS_HEADER)) < GIT_SUCCESS)
- return git__rethrow(error, "Failed to write packed reference");
+ if ((error =
+ git_filebuf_printf(&pack_file, "%s\n", GIT_PACKEDREFS_HEADER)) < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to write packed references file header");
for (i = 0; i < packing_list.length; ++i) {
- reference_oid *ref = (reference_oid *)git_vector_get(&packing_list, i);
-
- /* only direct references go to the packfile; otherwise
- * this is a disaster */
- assert(ref->ref.type & GIT_REF_OID);
+ struct packref *ref = (struct packref *)git_vector_get(&packing_list, i);
- if ((error = packed_find_peel(ref)) < GIT_SUCCESS) {
- error = git__throw(GIT_EOBJCORRUPTED, "A reference cannot be peeled");
+ if ((error = packed_find_peel(repo, ref)) < GIT_SUCCESS) {
+ error = git__throw(GIT_EOBJCORRUPTED,
+ "A reference cannot be peeled");
goto cleanup;
}
-
if ((error = packed_write_ref(ref, &pack_file)) < GIT_SUCCESS)
goto cleanup;
}
@@ -870,7 +802,7 @@ cleanup:
/* if we've written all the references properly, we can commit
* the packfile to make the changes effective */
if (error == GIT_SUCCESS) {
- error = git_filebuf_commit(&pack_file);
+ error = git_filebuf_commit(&pack_file, GIT_PACKEDREFS_FILE_MODE);
/* when and only when the packfile has been properly written,
* we can go ahead and remove the loose refs */
@@ -887,20 +819,22 @@ cleanup:
git_vector_free(&packing_list);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write packed reference");
+ return error == GIT_SUCCESS ?
+ GIT_SUCCESS :
+ git__rethrow(error, "Failed to write packed references file");
}
static int _reference_available_cb(const char *ref, void *data)
{
const char *new, *old;
- git_vector *refs;
+ const char **refs;
assert(ref && data);
- refs = (git_vector *)data;
+ refs = (const char **)data;
- new = (const char *)git_vector_get(refs, 0);
- old = (const char *)git_vector_get(refs, 1);
+ new = (const char *)refs[0];
+ old = (const char *)refs[1];
if (!old || strcmp(old, ref)) {
int reflen = strlen(ref);
@@ -916,35 +850,168 @@ static int _reference_available_cb(const char *ref, void *data)
return GIT_SUCCESS;
}
-static int reference_available(git_repository *repo, const char *ref, const char* old_ref)
+static int reference_available(
+ git_repository *repo,
+ const char *ref,
+ const char* old_ref)
+{
+ const char *refs[2];
+
+ refs[0] = ref;
+ refs[1] = old_ref;
+
+ if (git_reference_foreach(repo, GIT_REF_LISTALL,
+ _reference_available_cb, (void *)refs) < 0) {
+ return git__throw(GIT_EEXISTS,
+ "Reference name `%s` conflicts with existing reference", ref);
+ }
+
+ return GIT_SUCCESS;
+}
+
+static int reference_exists(int *exists, git_repository *repo, const char *ref_name)
{
int error;
- git_vector refs;
+ char ref_path[GIT_PATH_MAX];
- if (git_vector_init(&refs, 2, NULL) < GIT_SUCCESS)
- return GIT_ENOMEM;
+ error = packed_load(repo);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Cannot resolve if a reference exists");
+
+ git_path_join(ref_path, repo->path_repository, ref_name);
- git_vector_insert(&refs, (void *)ref);
- git_vector_insert(&refs, (void *)old_ref);
+ if (git_futils_isfile(ref_path) == GIT_SUCCESS ||
+ git_hashtable_lookup(repo->references.packfile, ref_path) != NULL) {
+ *exists = 1;
+ } else {
+ *exists = 0;
+ }
+
+ return GIT_SUCCESS;
+}
- error = git_reference_foreach(repo, GIT_REF_LISTALL, _reference_available_cb, (void *)&refs);
+static int packed_lookup(git_reference *ref)
+{
+ int error;
+ struct packref *pack_ref = NULL;
+
+ error = packed_load(ref->owner);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error,
+ "Failed to lookup reference from packfile");
+
+ if (ref->flags & GIT_REF_PACKED &&
+ ref->mtime == ref->owner->references.packfile_time)
+ return GIT_SUCCESS;
- git_vector_free(&refs);
+ if (ref->flags & GIT_REF_SYMBOLIC)
+ free(ref->target.symbolic);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__throw(GIT_EEXISTS, "Reference name `%s` conflicts with existing reference", ref);
+ /* Look up on the packfile */
+ pack_ref = git_hashtable_lookup(ref->owner->references.packfile, ref->name);
+ if (pack_ref == NULL)
+ return git__throw(GIT_ENOTFOUND,
+ "Failed to lookup reference from packfile");
+
+ ref->flags = GIT_REF_OID | GIT_REF_PACKED;
+ ref->mtime = ref->owner->references.packfile_time;
+ git_oid_cpy(&ref->target.oid, &pack_ref->oid);
+
+ return GIT_SUCCESS;
}
-/*****************************************
- * External Library API
- *****************************************/
+static int reference_lookup(git_reference *ref)
+{
+ int error_loose, error_packed;
-/**
- * Constructors
+ error_loose = loose_lookup(ref);
+ if (error_loose == GIT_SUCCESS)
+ return GIT_SUCCESS;
+
+ error_packed = packed_lookup(ref);
+ if (error_packed == GIT_SUCCESS)
+ return GIT_SUCCESS;
+
+ git_reference_free(ref);
+
+ if (error_loose != GIT_ENOTFOUND)
+ return git__rethrow(error_loose, "Failed to lookup reference");
+
+ if (error_packed != GIT_ENOTFOUND)
+ return git__rethrow(error_packed, "Failed to lookup reference");
+
+ return git__throw(GIT_ENOTFOUND, "Reference not found");
+}
+
+/*
+ * Delete a reference.
+ * This is an internal method; the reference is removed
+ * from disk or the packfile, but the pointer is not freed
*/
-int git_reference_lookup(git_reference **ref_out, git_repository *repo, const char *name)
+static int reference_delete(git_reference *ref)
+{
+ int error;
+
+ assert(ref);
+
+ /* If the reference is packed, this is an expensive operation.
+ * We need to reload the packfile, remove the reference from the
+ * packing list, and repack */
+ if (ref->flags & GIT_REF_PACKED) {
+ /* load the existing packfile */
+ if ((error = packed_load(ref->owner)) < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to delete reference");
+
+ if (git_hashtable_remove(ref->owner->references.packfile,
+ ref->name) < GIT_SUCCESS)
+ return git__throw(GIT_ENOTFOUND, "Reference not found");
+
+ error = packed_write(ref->owner);
+
+ /* If the reference is loose, we can just remove the reference
+ * from the filesystem */
+ } else {
+ char full_path[GIT_PATH_MAX];
+ git_reference *ref_in_pack;
+
+ git_path_join(full_path, ref->owner->path_repository, ref->name);
+
+ error = p_unlink(full_path);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ /* When deleting a loose reference, we have to ensure that an older
+ * packed version of it doesn't exist */
+ if (git_reference_lookup(&ref_in_pack, ref->owner,
+ ref->name) == GIT_SUCCESS) {
+ assert((ref_in_pack->flags & GIT_REF_PACKED) != 0);
+ error = git_reference_delete(ref_in_pack);
+ }
+ }
+
+cleanup:
+ return error == GIT_SUCCESS ?
+ GIT_SUCCESS :
+ git__rethrow(error, "Failed to delete reference");
+}
+
+int git_reference_delete(git_reference *ref)
+{
+ int error = reference_delete(ref);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ git_reference_free(ref);
+ return GIT_SUCCESS;
+}
+
+
+int git_reference_lookup(git_reference **ref_out,
+ git_repository *repo, const char *name)
{
int error;
char normalized_name[GIT_REFNAME_MAX];
+ git_reference *ref = NULL;
assert(ref_out && repo && name);
@@ -954,39 +1021,16 @@ int git_reference_lookup(git_reference **ref_out, git_repository *repo, const ch
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to lookup reference");
- /* First, check has been previously loaded and cached */
- *ref_out = git_hashtable_lookup(repo->references.loose_cache, normalized_name);
- if (*ref_out != NULL)
- return loose_update(*ref_out);
-
- /* Then check if there is a loose file for that reference.*/
- error = loose_lookup(ref_out, repo, normalized_name, 0);
-
- /* If the file exists, we store it on the cache */
- if (error == GIT_SUCCESS)
- return git_hashtable_insert(repo->references.loose_cache, (*ref_out)->name, (*ref_out));
-
- /* The loose lookup has failed, but not because the reference wasn't found;
- * probably the loose reference is corrupted. this is bad. */
- if (error != GIT_ENOTFOUND)
+ error = reference_create(&ref, repo, normalized_name);
+ if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to lookup reference");
- /*
- * If we cannot find a loose reference, we look into the packfile
- * Load the packfile first if it hasn't been loaded
- */
- /* load all the packed references */
- error = packed_load(repo);
+ error = reference_lookup(ref);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to lookup reference");
- /* Look up on the packfile */
- *ref_out = git_hashtable_lookup(repo->references.packfile, normalized_name);
- if (*ref_out != NULL)
- return GIT_SUCCESS;
-
- /* The reference doesn't exist anywhere */
- return git__throw(GIT_ENOTFOUND, "Failed to lookup reference. Reference doesn't exist");
+ *ref_out = ref;
+ return GIT_SUCCESS;
}
/**
@@ -996,15 +1040,21 @@ git_rtype git_reference_type(git_reference *ref)
{
assert(ref);
- if (ref->type & GIT_REF_OID)
+ if (ref->flags & GIT_REF_OID)
return GIT_REF_OID;
- if (ref->type & GIT_REF_SYMBOLIC)
+ if (ref->flags & GIT_REF_SYMBOLIC)
return GIT_REF_SYMBOLIC;
return GIT_REF_INVALID;
}
+int git_reference_is_packed(git_reference *ref)
+{
+ assert(ref);
+ return !!(ref->flags & GIT_REF_PACKED);
+}
+
const char *git_reference_name(git_reference *ref)
{
assert(ref);
@@ -1021,219 +1071,154 @@ const git_oid *git_reference_oid(git_reference *ref)
{
assert(ref);
- if ((ref->type & GIT_REF_OID) == 0)
+ if ((ref->flags & GIT_REF_OID) == 0)
return NULL;
- if (loose_update(ref) < GIT_SUCCESS)
- return NULL;
-
- return &((reference_oid *)ref)->oid;
+ return &ref->target.oid;
}
const char *git_reference_target(git_reference *ref)
{
assert(ref);
- if ((ref->type & GIT_REF_SYMBOLIC) == 0)
- return NULL;
-
- if (loose_update(ref) < GIT_SUCCESS)
+ if ((ref->flags & GIT_REF_SYMBOLIC) == 0)
return NULL;
- return ((reference_symbolic *)ref)->target;
+ return ref->target.symbolic;
}
-int git_reference_create_symbolic(git_reference **ref_out, git_repository *repo, const char *name, const char *target, int force)
+int git_reference_create_symbolic(
+ git_reference **ref_out,
+ git_repository *repo,
+ const char *name,
+ const char *target,
+ int force)
{
char normalized[GIT_REFNAME_MAX];
- int error = GIT_SUCCESS, updated = 0;
+ int ref_exists, error = GIT_SUCCESS;
git_reference *ref = NULL;
- void *old_ref = NULL;
- if (git_reference_lookup(&ref, repo, name) == GIT_SUCCESS && !force)
- return git__throw(GIT_EEXISTS, "Failed to create symbolic reference. Reference already exists");
+ error = normalize_name(normalized, sizeof(normalized), name, 0);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
- /*
- * If they old ref was of the same type, then we can just update
- * it (once we've checked that the target is valid). Otherwise we
- * need a new reference because we can't make a symbolic ref out
- * of an oid one.
- * If if didn't exist, then we need to create a new one anyway.
- */
- if (ref && ref->type & GIT_REF_SYMBOLIC){
- updated = 1;
- } else {
- ref = NULL;
- error = reference_create(&ref, repo, name, GIT_REF_SYMBOLIC);
- if (error < GIT_SUCCESS)
- goto cleanup;
- }
+ if ((error = reference_exists(&ref_exists, repo, normalized) < GIT_SUCCESS))
+ return git__rethrow(error, "Failed to create symbolic reference");
- /* The target can aither be the name of an object id reference or the name of another symbolic reference */
- error = normalize_name(normalized, sizeof(normalized), target, 0);
+ if (ref_exists && !force)
+ return git__throw(GIT_EEXISTS,
+ "Failed to create symbolic reference. Reference already exists");
+
+ error = reference_create(&ref, repo, normalized);
if (error < GIT_SUCCESS)
goto cleanup;
- /* set the target; this will write the reference on disk */
- error = git_reference_set_target(ref, normalized);
+ ref->flags |= GIT_REF_SYMBOLIC;
+
+ /* set the target; this will normalize the name automatically
+ * and write the reference on disk */
+ error = git_reference_set_target(ref, target);
if (error < GIT_SUCCESS)
goto cleanup;
- /*
- * If we didn't update the ref, then we need to insert or replace
- * it in the loose cache. If we replaced a ref, free it.
- */
- if (!updated){
- error = git_hashtable_insert2(repo->references.loose_cache, ref->name, ref, &old_ref);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- if (old_ref != NULL)
- reference_free((git_reference *)old_ref);
+ if (ref_out == NULL) {
+ git_reference_free(ref);
+ } else {
+ *ref_out = ref;
}
- *ref_out = ref;
-
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create symbolic reference");
+ return GIT_SUCCESS;
cleanup:
- reference_free(ref);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create symbolic reference");
+ git_reference_free(ref);
+ return git__rethrow(error, "Failed to create symbolic reference");
}
-int git_reference_create_oid(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id, int force)
+int git_reference_create_oid(
+ git_reference **ref_out,
+ git_repository *repo,
+ const char *name,
+ const git_oid *id,
+ int force)
{
- int error = GIT_SUCCESS, updated = 0;
+ int error = GIT_SUCCESS, ref_exists;
git_reference *ref = NULL;
- void *old_ref = NULL;
+ char normalized[GIT_REFNAME_MAX];
+
+ error = normalize_name(normalized, sizeof(normalized), name, 1);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ if ((error = reference_exists(&ref_exists, repo, normalized) < GIT_SUCCESS))
+ return git__rethrow(error, "Failed to create OID reference");
- if(git_reference_lookup(&ref, repo, name) == GIT_SUCCESS && !force)
- return git__throw(GIT_EEXISTS, "Failed to create reference OID. Reference already exists");
+ if (ref_exists && !force)
+ return git__throw(GIT_EEXISTS,
+ "Failed to create OID reference. Reference already exists");
if ((error = reference_available(repo, name, NULL)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to create reference");
- /*
- * If they old ref was of the same type, then we can just update
- * it (once we've checked that the target is valid). Otherwise we
- * need a new reference because we can't make a symbolic ref out
- * of an oid one.
- * If if didn't exist, then we need to create a new one anyway.
- */
- if (ref && ref-> type & GIT_REF_OID){
- updated = 1;
- } else {
- ref = NULL;
- error = reference_create(&ref, repo, name, GIT_REF_OID);
- if (error < GIT_SUCCESS)
- goto cleanup;
- }
+ error = reference_create(&ref, repo, name);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ ref->flags |= GIT_REF_OID;
/* set the oid; this will write the reference on disk */
error = git_reference_set_oid(ref, id);
if (error < GIT_SUCCESS)
goto cleanup;
- if(!updated){
- error = git_hashtable_insert2(repo->references.loose_cache, ref->name, ref, &old_ref);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- if (old_ref != NULL)
- reference_free((git_reference *)old_ref);
+ if (ref_out == NULL) {
+ git_reference_free(ref);
+ } else {
+ *ref_out = ref;
}
- *ref_out = ref;
-
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create reference OID");
+ return GIT_SUCCESS;
cleanup:
- reference_free(ref);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create reference OID");
+ git_reference_free(ref);
+ return git__rethrow(error, "Failed to create reference OID");
}
-/**
- * Setters
- */
-
/*
* Change the OID target of a reference.
*
- * For loose references, just change the oid in memory
- * and overwrite the file in disk.
- *
- * For packed files, this is not pretty:
- * For performance reasons, we write the new reference
- * loose on disk (it replaces the old on the packfile),
- * but we cannot invalidate the pointer to the reference,
- * and most importantly, the `packfile` object must stay
- * consistent with the representation of the packfile
- * on disk. This is what we need to:
+ * For both loose and packed references, just change
+ * the oid in memory and (over)write the file in disk.
*
- * 1. Copy the reference
- * 2. Change the oid on the original
- * 3. Write the original to disk
- * 4. Write the original to the loose cache
- * 5. Replace the original with the copy (old reference) in the packfile cache
+ * We do not repack packed references because of performance
+ * reasons.
*/
int git_reference_set_oid(git_reference *ref, const git_oid *id)
{
- reference_oid *ref_oid;
- reference_oid *ref_old = NULL;
int error = GIT_SUCCESS;
- if ((ref->type & GIT_REF_OID) == 0)
- return git__throw(GIT_EINVALIDREFSTATE, "Failed to set OID target of reference. Not an OID reference");
-
- ref_oid = (reference_oid *)ref;
+ if ((ref->flags & GIT_REF_OID) == 0)
+ return git__throw(GIT_EINVALIDREFSTATE,
+ "Failed to set OID target of reference. Not an OID reference");
assert(ref->owner);
/* Don't let the user create references to OIDs that
* don't exist in the ODB */
if (!git_odb_exists(git_repository_database(ref->owner), id))
- return git__throw(GIT_ENOTFOUND, "Failed to set OID target of reference. OID doesn't exist in ODB");
-
- /* duplicate the reference;
- * this copy will stay on the packfile cache */
- if (ref->type & GIT_REF_PACKED) {
- ref_old = git__malloc(sizeof(reference_oid));
- if (ref_old == NULL)
- return GIT_ENOMEM;
+ return git__throw(GIT_ENOTFOUND,
+ "Failed to set OID target of reference. OID doesn't exist in ODB");
- ref_old->ref.name = git__strdup(ref->name);
- if (ref_old->ref.name == NULL) {
- free(ref_old);
- return GIT_ENOMEM;
- }
- }
-
- git_oid_cpy(&ref_oid->oid, id);
- ref->type &= ~GIT_REF_HAS_PEEL;
+ /* Update the OID value on `ref` */
+ git_oid_cpy(&ref->target.oid, id);
error = loose_write(ref);
if (error < GIT_SUCCESS)
goto cleanup;
- if (ref->type & GIT_REF_PACKED) {
- /* insert the original on the loose cache */
- error = git_hashtable_insert(ref->owner->references.loose_cache, ref->name, ref);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- ref->type &= ~GIT_REF_PACKED;
-
- /* replace the original in the packfile with the copy */
- error = git_hashtable_insert(ref->owner->references.packfile, ref_old->ref.name, ref_old);
- if (error < GIT_SUCCESS)
- goto cleanup;
- }
-
return GIT_SUCCESS;
cleanup:
- reference_free((git_reference *)ref_old);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to set OID target of reference");
+ return git__rethrow(error, "Failed to set OID target of reference");
}
/*
@@ -1245,99 +1230,85 @@ cleanup:
*/
int git_reference_set_target(git_reference *ref, const char *target)
{
- reference_symbolic *ref_sym;
+ int error;
+ char normalized[GIT_REFNAME_MAX];
- if ((ref->type & GIT_REF_SYMBOLIC) == 0)
- return git__throw(GIT_EINVALIDREFSTATE, "Failed to set reference target. Not a symbolic reference");
+ if ((ref->flags & GIT_REF_SYMBOLIC) == 0)
+ return git__throw(GIT_EINVALIDREFSTATE,
+ "Failed to set reference target. Not a symbolic reference");
- ref_sym = (reference_symbolic *)ref;
+ error = normalize_name(normalized, sizeof(normalized), target, 0);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error,
+ "Failed to set reference target. Invalid target name");
- free(ref_sym->target);
- ref_sym->target = git__strdup(target);
- if (ref_sym->target == NULL)
+ git__free(ref->target.symbolic);
+ ref->target.symbolic = git__strdup(normalized);
+ if (ref->target.symbolic == NULL)
return GIT_ENOMEM;
return loose_write(ref);
}
-/**
- * Other
- */
-
int git_reference_rename(git_reference *ref, const char *new_name, int force)
{
int error;
- char *old_name = NULL;
char aux_path[GIT_PATH_MAX];
char normalized[GIT_REFNAME_MAX];
- const char *target_ref = NULL;
const char *head_target = NULL;
- const git_oid *target_oid = NULL;
- git_reference *new_ref = NULL, *head = NULL;
+ git_reference *existing_ref = NULL, *head = NULL;
- assert(ref);
+ error = normalize_name(normalized, sizeof(normalized),
+ new_name, ref->flags & GIT_REF_OID);
- error = normalize_name(normalized, sizeof(normalized), new_name, ref->type & GIT_REF_OID);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to rename reference. Invalid name");
new_name = normalized;
- error = git_reference_lookup(&new_ref, ref->owner, new_name);
- if (error == GIT_SUCCESS) {
- if (!force)
- return git__throw(GIT_EEXISTS, "Failed to rename reference. Reference already exists");
-
- error = git_reference_delete(new_ref);
- }
+ /* If we are forcing the rename, try to lookup a reference with the
+ * new one. If the lookup succeeds, we need to delete that ref
+ * before the renaming can proceed */
+ if (force) {
+ error = git_reference_lookup(&existing_ref, ref->owner, new_name);
- if (error < GIT_SUCCESS) {
- git_path_join(aux_path, ref->owner->path_repository, new_name);
- /* If we couldn't read the reference because it doesn't
- * exist it's ok - otherwise return */
- if (git_futils_isfile(aux_path) == GIT_SUCCESS)
+ if (error == GIT_SUCCESS) {
+ error = git_reference_delete(existing_ref);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error,
+ "Failed to rename reference. "
+ "The existing reference cannot be deleted");
+ } else if (error != GIT_ENOTFOUND)
goto cleanup;
- }
-
- if ((error = reference_available(ref->owner, new_name, ref->name)) < GIT_SUCCESS)
- return git__rethrow(error, "Failed to rename reference. Reference already exists");
- /*
- * First, we backup the reference targets. Just keeping the old
- * reference won't work, since we may have to remove it to create
- * the new reference, e.g. when renaming foo/bar -> foo.
- */
-
- old_name = git__strdup(ref->name);
-
- if (ref->type & GIT_REF_SYMBOLIC) {
- if ((target_ref = git_reference_target(ref)) == NULL)
- goto cleanup;
+ /* If we're not forcing the rename, check if the reference exists.
+ * If it does, renaming cannot continue */
} else {
- if ((target_oid = git_reference_oid(ref)) == NULL)
+ int exists;
+
+ error = reference_exists(&exists, ref->owner, normalized);
+ if (error < GIT_SUCCESS)
goto cleanup;
+
+ if (exists)
+ return git__throw(GIT_EEXISTS,
+ "Failed to rename reference. Reference already exists");
}
+ if ((error = reference_available(ref->owner, new_name, ref->name)) < GIT_SUCCESS)
+ return git__rethrow(error,
+ "Failed to rename reference. Reference already exists");
+
/*
* Now delete the old ref and remove an possibly existing directory
- * named `new_name`.
+ * named `new_name`. Note that using the internal `reference_delete`
+ * method deletes the ref from disk but doesn't free the pointer, so
+ * we can still access the ref's attributes for creating the new one
*/
-
- if (ref->type & GIT_REF_PACKED) {
- ref->type &= ~GIT_REF_PACKED;
-
- git_hashtable_remove(ref->owner->references.packfile, old_name);
- if ((error = packed_write(ref->owner)) < GIT_SUCCESS)
- goto rollback;
- } else {
- git_path_join(aux_path, ref->owner->path_repository, old_name);
- if ((error = p_unlink(aux_path)) < GIT_SUCCESS)
- goto cleanup;
-
- git_hashtable_remove(ref->owner->references.loose_cache, old_name);
- }
+ if ((error = reference_delete(ref)) < GIT_SUCCESS)
+ goto cleanup;
git_path_join(aux_path, ref->owner->path_repository, new_name);
if (git_futils_exists(aux_path) == GIT_SUCCESS) {
@@ -1363,8 +1334,7 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
* TODO
*
*/
-
- git_path_join_n(aux_path, 3, ref->owner->path_repository, "logs", old_name);
+ git_path_join_n(aux_path, 3, ref->owner->path_repository, "logs", ref->name);
if (git_futils_isfile(aux_path) == GIT_SUCCESS) {
if ((error = p_unlink(aux_path)) < GIT_SUCCESS)
goto rollback;
@@ -1373,138 +1343,107 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
/*
* Finally we can create the new reference.
*/
- if (ref->type & GIT_REF_SYMBOLIC) {
- if ((error = git_reference_create_symbolic(&new_ref, ref->owner, new_name, target_ref, 0)) < GIT_SUCCESS)
- goto rollback;
+ if (ref->flags & GIT_REF_SYMBOLIC) {
+ error = git_reference_create_symbolic(
+ NULL, ref->owner, new_name, ref->target.symbolic, 0);
} else {
- if ((error = git_reference_create_oid(&new_ref, ref->owner, new_name, target_oid, 0)) < GIT_SUCCESS)
- goto rollback;
+ error = git_reference_create_oid(
+ NULL, ref->owner, new_name, &ref->target.oid, 0);
}
- free(ref->name);
- ref->name = new_ref->name;
-
- /*
- * No need in new_ref anymore. We created it to fix the change on disk.
- * TODO: Refactoring required.
- */
- new_ref->name = NULL;
- reference_free(new_ref);
-
- if ((error = git_hashtable_insert(ref->owner->references.loose_cache, ref->name, ref)) < GIT_SUCCESS)
- goto rollback;
+ if (error < GIT_SUCCESS)
+ goto cleanup;
/*
* Check if we have to update HEAD.
*/
-
- if ((error = git_reference_lookup(&head, ref->owner, GIT_HEAD_FILE)) < GIT_SUCCESS)
+ error = git_reference_lookup(&head, ref->owner, GIT_HEAD_FILE);
+ if (error < GIT_SUCCESS)
goto cleanup;
head_target = git_reference_target(head);
- if (head_target && !strcmp(head_target, old_name))
- if ((error = git_reference_create_symbolic(&head, ref->owner, "HEAD", ref->name, 1)) < GIT_SUCCESS)
- goto rollback;
+ if (head_target && !strcmp(head_target, ref->name)) {
+ error = git_reference_create_symbolic(
+ &head, ref->owner, "HEAD", new_name, 1);
+
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+ }
+
+ /*
+ * Change the name of the reference given by the user.
+ */
+ git__free(ref->name);
+ ref->name = git__strdup(new_name);
+
+ /* The reference is no longer packed */
+ ref->flags &= ~GIT_REF_PACKED;
cleanup:
- free(old_name);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference");
+ /* We no longer need the newly created reference nor the head */
+ git_reference_free(head);
+ return error == GIT_SUCCESS ?
+ GIT_SUCCESS :
+ git__rethrow(error, "Failed to rename reference");
rollback:
/*
* Try to create the old reference again.
*/
- if (ref->type & GIT_REF_SYMBOLIC)
- error = git_reference_create_symbolic(&new_ref, ref->owner, old_name, target_ref, 0);
+ if (ref->flags & GIT_REF_SYMBOLIC)
+ error = git_reference_create_symbolic(
+ NULL, ref->owner, ref->name, ref->target.symbolic, 0);
else
- error = git_reference_create_oid(&new_ref, ref->owner, old_name, target_oid, 0);
-
- ref->name = old_name;
+ error = git_reference_create_oid(
+ NULL, ref->owner, ref->name, &ref->target.oid, 0);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference. Failed to rollback");
+ return error == GIT_SUCCESS ?
+ git__rethrow(GIT_ERROR, "Failed to rename reference. Did rollback") :
+ git__rethrow(error, "Failed to rename reference. Failed to rollback");
}
-/*
- * Delete a reference.
- *
- * If the reference is packed, this is an expensive
- * operation. We need to remove the reference from
- * the memory cache and then rewrite the whole pack
- *
- * If the reference is loose, we remove it on
- * the filesystem and update the in-memory cache
- * accordingly. We also make sure that an older version
- * of it doesn't exist as a packed reference. If this
- * is the case, this packed reference is removed as well.
- *
- * This obviously invalidates the `ref` pointer.
- */
-int git_reference_delete(git_reference *ref)
+int git_reference_resolve(git_reference **ref_out, git_reference *ref)
{
- int error;
- git_reference *reference;
+ int error, i = 0;
+ git_repository *repo;
assert(ref);
- if (ref->type & GIT_REF_PACKED) {
- /* load the existing packfile */
- if ((error = packed_load(ref->owner)) < GIT_SUCCESS)
- return git__rethrow(error, "Failed to delete reference");
-
- if (git_hashtable_remove(ref->owner->references.packfile, ref->name) < GIT_SUCCESS)
- return git__throw(GIT_ENOTFOUND, "Reference not found");
-
- error = packed_write(ref->owner);
- } else {
- char full_path[GIT_PATH_MAX];
- git_path_join(full_path, ref->owner->path_repository, ref->name);
- git_hashtable_remove(ref->owner->references.loose_cache, ref->name);
- error = p_unlink(full_path);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- /* When deleting a loose reference, we have to ensure that an older
- * packed version of it doesn't exist
- */
- if (!git_reference_lookup(&reference, ref->owner, ref->name)) {
- assert((reference->type & GIT_REF_PACKED) != 0);
- error = git_reference_delete(reference);
- }
- }
-
-cleanup:
- reference_free(ref);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to delete reference");
-}
-
-int git_reference_resolve(git_reference **resolved_ref, git_reference *ref)
-{
- git_repository *repo;
- int error, i;
+ *ref_out = NULL;
+ repo = ref->owner;
- assert(resolved_ref && ref);
- *resolved_ref = NULL;
+ /* If the reference is already resolved, we need to return a
+ * copy. Instead of duplicating `ref`, we look it up again to
+ * ensure the copy is out to date */
+ if (ref->flags & GIT_REF_OID)
+ return git_reference_lookup(ref_out, ref->owner, ref->name);
- if ((error = loose_update(ref)) < GIT_SUCCESS)
- return git__rethrow(error, "Failed to resolve reference");
+ /* Otherwise, keep iterating until the reference is resolved */
+ for (i = 0; i < MAX_NESTING_LEVEL; ++i) {
+ git_reference *new_ref;
- repo = ref->owner;
+ error = git_reference_lookup(&new_ref, repo, ref->target.symbolic);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to resolve reference");
- for (i = 0; i < MAX_NESTING_LEVEL; ++i) {
- reference_symbolic *ref_sym;
+ /* Free intermediate references, except for the original one
+ * we've received */
+ if (i > 0)
+ git_reference_free(ref);
- *resolved_ref = ref;
+ ref = new_ref;
- if (ref->type & GIT_REF_OID)
+ /* When the reference we've just looked up is an OID, we've
+ * successfully resolved the symbolic ref */
+ if (ref->flags & GIT_REF_OID) {
+ *ref_out = ref;
return GIT_SUCCESS;
-
- ref_sym = (reference_symbolic *)ref;
- if ((error = git_reference_lookup(&ref, repo, ref_sym->target)) < GIT_SUCCESS)
- return error;
+ }
}
- return git__throw(GIT_ENOMEM, "Failed to resolve reference. Reference is too nested");
+ return git__throw(GIT_ENOMEM,
+ "Failed to resolve reference. Reference is too nested");
}
int git_reference_packall(git_repository *repo)
@@ -1523,7 +1462,11 @@ int git_reference_packall(git_repository *repo)
return packed_write(repo);
}
-int git_reference_foreach(git_repository *repo, unsigned int list_flags, int (*callback)(const char *, void *), void *payload)
+int git_reference_foreach(
+ git_repository *repo,
+ unsigned int list_flags,
+ int (*callback)(const char *, void *),
+ void *payload)
{
int error;
struct dirent_list_data data;
@@ -1539,7 +1482,8 @@ int git_reference_foreach(git_repository *repo, unsigned int list_flags, int (*c
GIT_HASHTABLE_FOREACH(repo->references.packfile, ref_name, _unused,
if ((error = callback(ref_name, payload)) < GIT_SUCCESS)
- return git__throw(error, "Failed to list references. User callback failed");
+ return git__throw(error,
+ "Failed to list references. User callback failed");
);
}
@@ -1552,7 +1496,6 @@ int git_reference_foreach(git_repository *repo, unsigned int list_flags, int (*c
data.callback = callback;
data.callback_payload = payload;
-
git_path_join(refs_path, repo->path_repository, GIT_REFS_DIR);
return git_futils_direach(refs_path, GIT_PATH_MAX, _dirent_loose_listall, &data);
}
@@ -1562,7 +1505,10 @@ static int cb__reflist_add(const char *ref, void *data)
return git_vector_insert((git_vector *)data, git__strdup(ref));
}
-int git_reference_listall(git_strarray *array, git_repository *repo, unsigned int list_flags)
+int git_reference_listall(
+ git_strarray *array,
+ git_repository *repo,
+ unsigned int list_flags)
{
int error;
git_vector ref_list;
@@ -1575,7 +1521,8 @@ int git_reference_listall(git_strarray *array, git_repository *repo, unsigned in
if (git_vector_init(&ref_list, 8, NULL) < GIT_SUCCESS)
return GIT_ENOMEM;
- error = git_reference_foreach(repo, list_flags, &cb__reflist_add, (void *)&ref_list);
+ error = git_reference_foreach(
+ repo, list_flags, &cb__reflist_add, (void *)&ref_list);
if (error < GIT_SUCCESS) {
git_vector_free(&ref_list);
@@ -1587,59 +1534,39 @@ int git_reference_listall(git_strarray *array, git_repository *repo, unsigned in
return GIT_SUCCESS;
}
-
-
-
-/*****************************************
- * Init/free (repository API)
- *****************************************/
-int git_repository__refcache_init(git_refcache *refs)
+int git_reference_reload(git_reference *ref)
{
- assert(refs);
-
- refs->loose_cache = git_hashtable_alloc(
- default_table_size,
- reftable_hash,
- (git_hash_keyeq_ptr)(&git__strcmp_cb));
+ int error = reference_lookup(ref);
- /* packfile loaded lazily */
- refs->packfile = NULL;
- refs->packfile_time = 0;
+ if (error < GIT_SUCCESS) {
+ git_reference_free(ref);
+ return git__rethrow(error, "Failed to reload reference");
+ }
- return (refs->loose_cache) ? GIT_SUCCESS : GIT_ENOMEM;
+ return GIT_SUCCESS;
}
+
void git_repository__refcache_free(git_refcache *refs)
{
- git_reference *reference;
- const void *GIT_UNUSED(_unused);
-
assert(refs);
- GIT_HASHTABLE_FOREACH(refs->loose_cache, _unused, reference,
- reference_free(reference);
- );
-
- git_hashtable_free(refs->loose_cache);
-
if (refs->packfile) {
+ const void *GIT_UNUSED(_unused);
+ struct packref *reference;
+
GIT_HASHTABLE_FOREACH(refs->packfile, _unused, reference,
- reference_free(reference);
+ free(reference);
);
git_hashtable_free(refs->packfile);
}
}
-
-
-/*****************************************
- * Name normalization
- *****************************************/
-static int check_valid_ref_char(char ch)
+static int is_valid_ref_char(char ch)
{
if ((unsigned) ch <= ' ')
- return GIT_ERROR;
+ return 0;
switch (ch) {
case '~':
@@ -1649,13 +1576,17 @@ static int check_valid_ref_char(char ch)
case '?':
case '[':
case '*':
- return GIT_ERROR;
+ return 0;
default:
- return GIT_SUCCESS;
+ return 1;
}
}
-static int normalize_name(char *buffer_out, size_t out_size, const char *name, int is_oid_ref)
+static int normalize_name(
+ char *buffer_out,
+ size_t out_size,
+ const char *name,
+ int is_oid_ref)
{
const char *name_end, *buffer_out_start;
const char *current;
@@ -1672,26 +1603,33 @@ static int normalize_name(char *buffer_out, size_t out_size, const char *name, i
/* A refname can not be empty */
if (name_end == name)
- return git__throw(GIT_EINVALIDREFNAME, "Failed to normalize name. Reference name is empty");
+ return git__throw(GIT_EINVALIDREFNAME,
+ "Failed to normalize name. Reference name is empty");
/* A refname can not end with a dot or a slash */
if (*(name_end - 1) == '.' || *(name_end - 1) == '/')
- return git__throw(GIT_EINVALIDREFNAME, "Failed to normalize name. Reference name ends with dot or slash");
+ return git__throw(GIT_EINVALIDREFNAME,
+ "Failed to normalize name. Reference name ends with dot or slash");
while (current < name_end && out_size) {
- if (check_valid_ref_char(*current))
- return git__throw(GIT_EINVALIDREFNAME, "Failed to normalize name. Reference name contains invalid characters");
+ if (!is_valid_ref_char(*current))
+ return git__throw(GIT_EINVALIDREFNAME,
+ "Failed to normalize name. "
+ "Reference name contains invalid characters");
if (buffer_out > buffer_out_start) {
char prev = *(buffer_out - 1);
/* A refname can not start with a dot nor contain a double dot */
if (*current == '.' && ((prev == '.') || (prev == '/')))
- return git__throw(GIT_EINVALIDREFNAME, "Failed to normalize name. Reference name starts with a dot or contains a double dot");
+ return git__throw(GIT_EINVALIDREFNAME,
+ "Failed to normalize name. "
+ "Reference name starts with a dot or contains a double dot");
/* '@{' is forbidden within a refname */
if (*current == '{' && prev == '@')
- return git__throw(GIT_EINVALIDREFNAME, "Failed to normalize name. Reference name contains '@{'");
+ return git__throw(GIT_EINVALIDREFNAME,
+ "Failed to normalize name. Reference name contains '@{'");
/* Prevent multiple slashes from being added to the output */
if (*current == '/' && prev == '/') {
@@ -1713,13 +1651,18 @@ static int normalize_name(char *buffer_out, size_t out_size, const char *name, i
/* Object id refname have to contain at least one slash, except
* for HEAD in a detached state or MERGE_HEAD if we're in the
* middle of a merge */
- if (is_oid_ref && !contains_a_slash && (strcmp(name, GIT_HEAD_FILE) && strcmp(name, GIT_MERGE_HEAD_FILE)
- && strcmp(name, GIT_FETCH_HEAD_FILE)))
- return git__throw(GIT_EINVALIDREFNAME, "Failed to normalize name. Reference name contains no slashes");
+ if (is_oid_ref &&
+ !contains_a_slash &&
+ strcmp(name, GIT_HEAD_FILE) != 0 &&
+ strcmp(name, GIT_MERGE_HEAD_FILE) != 0 &&
+ strcmp(name, GIT_FETCH_HEAD_FILE) != 0)
+ return git__throw(GIT_EINVALIDREFNAME,
+ "Failed to normalize name. Reference name contains no slashes");
/* A refname can not end with ".lock" */
if (!git__suffixcmp(name, GIT_FILELOCK_EXTENSION))
- return git__throw(GIT_EINVALIDREFNAME, "Failed to normalize name. Reference name ends with '.lock'");
+ return git__throw(GIT_EINVALIDREFNAME,
+ "Failed to normalize name. Reference name ends with '.lock'");
*buffer_out = '\0';
@@ -1729,17 +1672,25 @@ static int normalize_name(char *buffer_out, size_t out_size, const char *name, i
*/
if (is_oid_ref && !(git__prefixcmp(buffer_out_start, GIT_REFS_DIR) ||
strcmp(buffer_out_start, GIT_HEAD_FILE)))
- return git__throw(GIT_EINVALIDREFNAME, "Failed to normalize name. Reference name does not start with 'refs/'");
+ return git__throw(GIT_EINVALIDREFNAME,
+ "Failed to normalize name. "
+ "Reference name does not start with 'refs/'");
return GIT_SUCCESS;
}
-int git_reference__normalize_name(char *buffer_out, size_t out_size, const char *name)
+int git_reference__normalize_name(
+ char *buffer_out,
+ size_t out_size,
+ const char *name)
{
return normalize_name(buffer_out, out_size, name, 0);
}
-int git_reference__normalize_name_oid(char *buffer_out, size_t out_size, const char *name)
+int git_reference__normalize_name_oid(
+ char *buffer_out,
+ size_t out_size,
+ const char *name)
{
return normalize_name(buffer_out, out_size, name, 1);
}
diff --git a/src/refs.h b/src/refs.h
index c4b0b0e39..c90f5bcc4 100644
--- a/src/refs.h
+++ b/src/refs.h
@@ -16,12 +16,15 @@
#define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/"
#define GIT_REFS_TAGS_DIR GIT_REFS_DIR "tags/"
#define GIT_REFS_REMOTES_DIR GIT_REFS_DIR "remotes/"
+#define GIT_REFS_DIR_MODE 0777
+#define GIT_REFS_FILE_MODE 0666
#define GIT_RENAMED_REF_FILE GIT_REFS_DIR "RENAMED-REF"
#define GIT_SYMREF "ref: "
#define GIT_PACKEDREFS_FILE "packed-refs"
#define GIT_PACKEDREFS_HEADER "# pack-refs with: peeled "
+#define GIT_PACKEDREFS_FILE_MODE 0666
#define GIT_HEAD_FILE "HEAD"
#define GIT_FETCH_HEAD_FILE "FETCH_HEAD"
@@ -31,21 +34,23 @@
#define GIT_REFNAME_MAX 1024
struct git_reference {
+ unsigned int flags;
git_repository *owner;
char *name;
- unsigned int type;
time_t mtime;
+
+ union {
+ git_oid oid;
+ char *symbolic;
+ } target;
};
typedef struct {
git_hashtable *packfile;
- git_hashtable *loose_cache;
time_t packfile_time;
} git_refcache;
-
void git_repository__refcache_free(git_refcache *refs);
-int git_repository__refcache_init(git_refcache *refs);
int git_reference__normalize_name(char *buffer_out, size_t out_size, const char *name);
int git_reference__normalize_name_oid(char *buffer_out, size_t out_size, const char *name);
diff --git a/src/refspec.c b/src/refspec.c
index ed4b5e6b8..e60e8f5b5 100644
--- a/src/refspec.c
+++ b/src/refspec.c
@@ -32,7 +32,7 @@ int git_refspec_parse(git_refspec *refspec, const char *str)
refspec->dst = git__strdup(delim + 1);
if (refspec->dst == NULL) {
- free(refspec->src);
+ git__free(refspec->src);
refspec->src = NULL;
return GIT_ENOMEM;
}
diff --git a/src/remote.c b/src/remote.c
index 10303b467..51e77e584 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -37,7 +37,7 @@ static int refspec_parse(git_refspec *refspec, const char *str)
refspec->dst = git__strdup(delim + 1);
if (refspec->dst == NULL) {
- free(refspec->src);
+ git__free(refspec->src);
refspec->src = NULL;
return GIT_ENOMEM;
}
@@ -69,7 +69,7 @@ int git_remote_new(git_remote **out, git_repository *repo, const char *url)
remote->repo = repo;
remote->url = git__strdup(url);
if (remote->url == NULL) {
- free(remote);
+ git__free(remote);
return GIT_ENOMEM;
}
@@ -151,7 +151,7 @@ int git_remote_get(git_remote **out, git_config *cfg, const char *name)
*out = remote;
cleanup:
- free(buf);
+ git__free(buf);
if (error < GIT_SUCCESS)
git_remote_free(remote);
@@ -261,17 +261,17 @@ void git_remote_free(git_remote *remote)
if (remote == NULL)
return;
- free(remote->fetch.src);
- free(remote->fetch.dst);
- free(remote->push.src);
- free(remote->push.dst);
- free(remote->url);
- free(remote->name);
+ git__free(remote->fetch.src);
+ git__free(remote->fetch.dst);
+ git__free(remote->push.src);
+ git__free(remote->push.dst);
+ git__free(remote->url);
+ git__free(remote->name);
if (remote->transport != NULL) {
if (remote->transport->connected)
remote->transport->close(remote->transport);
remote->transport->free(remote->transport);
}
- free(remote);
+ git__free(remote);
}
diff --git a/src/repository.c b/src/repository.c
index 328bc0d57..f8195e2d9 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -168,12 +168,7 @@ static git_repository *repository_alloc(void)
error = git_cache_init(&repo->objects, GIT_DEFAULT_CACHE_SIZE, &git_object__free);
if (error < GIT_SUCCESS) {
- free(repo);
- return NULL;
- }
-
- if (git_repository__refcache_init(&repo->references) < GIT_SUCCESS) {
- free(repo);
+ git__free(repo);
return NULL;
}
@@ -467,13 +462,13 @@ static int read_gitfile(char *path_out, const char *file_path, const char *base_
static void git_repository__free_dirs(git_repository *repo)
{
- free(repo->path_workdir);
+ git__free(repo->path_workdir);
repo->path_workdir = NULL;
- free(repo->path_index);
+ git__free(repo->path_index);
repo->path_index = NULL;
- free(repo->path_repository);
+ git__free(repo->path_repository);
repo->path_repository = NULL;
- free(repo->path_odb);
+ git__free(repo->path_odb);
repo->path_odb = NULL;
}
@@ -489,7 +484,7 @@ void git_repository_free(git_repository *repo)
if (repo->db != NULL)
git_odb_close(repo->db);
- free(repo);
+ git__free(repo);
}
int git_repository_discover(char *repository_path, size_t size, const char *start_path, int across_fs, const char *ceiling_dirs)
@@ -603,18 +598,23 @@ static int repo_init_reinit(const char *repository_path, int is_bare)
static int repo_init_createhead(git_repository *repo)
{
+ int error;
git_reference *head_reference;
- return git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE, 0);
+
+ error = git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE, 0);
+
+ git_reference_free(head_reference);
+
+ return error;
}
static int repo_init_structure(const char *git_dir, int is_bare)
{
- const int mode = 0755; /* or 0777 ? */
int error;
char temp_path[GIT_PATH_MAX];
- if (git_futils_mkdir_r(git_dir, mode))
+ if (git_futils_mkdir_r(git_dir, is_bare ? GIT_BARE_DIR_MODE : GIT_DIR_MODE))
return git__throw(GIT_ERROR, "Failed to initialize repository structure. Could not mkdir");
/* Hides the ".git" directory */
@@ -628,25 +628,25 @@ static int repo_init_structure(const char *git_dir, int is_bare)
/* Creates the '/objects/info/' directory */
git_path_join(temp_path, git_dir, GIT_OBJECTS_INFO_DIR);
- error = git_futils_mkdir_r(temp_path, mode);
+ error = git_futils_mkdir_r(temp_path, GIT_OBJECT_DIR_MODE);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to initialize repository structure");
/* Creates the '/objects/pack/' directory */
git_path_join(temp_path, git_dir, GIT_OBJECTS_PACK_DIR);
- error = p_mkdir(temp_path, mode);
+ error = p_mkdir(temp_path, GIT_OBJECT_DIR_MODE);
if (error < GIT_SUCCESS)
return git__throw(error, "Unable to create `%s` folder", temp_path);
/* Creates the '/refs/heads/' directory */
git_path_join(temp_path, git_dir, GIT_REFS_HEADS_DIR);
- error = git_futils_mkdir_r(temp_path, mode);
+ error = git_futils_mkdir_r(temp_path, GIT_REFS_DIR_MODE);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to initialize repository structure");
/* Creates the '/refs/tags/' directory */
git_path_join(temp_path, git_dir, GIT_REFS_TAGS_DIR);
- error = p_mkdir(temp_path, mode);
+ error = p_mkdir(temp_path, GIT_REFS_DIR_MODE);
if (error < GIT_SUCCESS)
return git__throw(error, "Unable to create `%s` folder", temp_path);
@@ -716,10 +716,15 @@ int git_repository_head_detached(git_repository *repo)
if (error < GIT_SUCCESS)
return error;
- if (git_reference_type(ref) == GIT_REF_SYMBOLIC)
+ if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
+ git_reference_free(ref);
return 0;
+ }
error = git_odb_read_header(&_size, &type, repo->db, git_reference_oid(ref));
+
+ git_reference_free(ref);
+
if (error < GIT_SUCCESS)
return error;
@@ -731,7 +736,7 @@ int git_repository_head_detached(git_repository *repo)
int git_repository_head(git_reference **head_out, git_repository *repo)
{
- git_reference *ref;
+ git_reference *ref, *resolved_ref;
int error;
*head_out = NULL;
@@ -740,11 +745,15 @@ int git_repository_head(git_reference **head_out, git_repository *repo)
if (error < GIT_SUCCESS)
return git__rethrow(GIT_ENOTAREPO, "Failed to locate the HEAD");
- error = git_reference_resolve(&ref, ref);
- if (error < GIT_SUCCESS)
+ error = git_reference_resolve(&resolved_ref, ref);
+ if (error < GIT_SUCCESS) {
+ git_reference_free(ref);
return git__rethrow(error, "Failed to resolve the HEAD");
+ }
+
+ git_reference_free(ref);
- *head_out = ref;
+ *head_out = resolved_ref;
return GIT_SUCCESS;
}
@@ -755,25 +764,36 @@ int git_repository_head_orphan(git_repository *repo)
error = git_repository_head(&ref, repo);
+ if (error == GIT_SUCCESS)
+ git_reference_free(ref);
+
return error == GIT_ENOTFOUND ? 1 : error;
}
int git_repository_is_empty(git_repository *repo)
{
- git_reference *head, *branch;
+ git_reference *head = NULL, *branch = NULL;
int error;
error = git_reference_lookup(&head, repo, "HEAD");
if (error < GIT_SUCCESS)
return git__throw(error, "Corrupted repository. HEAD does not exist");
- if (git_reference_type(head) != GIT_REF_SYMBOLIC)
+ if (git_reference_type(head) != GIT_REF_SYMBOLIC) {
+ git_reference_free(head);
return 0;
+ }
- if (strcmp(git_reference_target(head), "refs/heads/master") != 0)
+ if (strcmp(git_reference_target(head), "refs/heads/master") != 0) {
+ git_reference_free(head);
return 0;
+ }
error = git_reference_resolve(&branch, head);
+
+ git_reference_free(head);
+ git_reference_free(branch);
+
return error == GIT_ENOTFOUND ? 1 : error;
}
diff --git a/src/repository.h b/src/repository.h
index 99217e5a4..0c17958fd 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -18,11 +18,12 @@
#include "cache.h"
#include "refs.h"
#include "buffer.h"
+#include "odb.h"
#define DOT_GIT ".git"
#define GIT_DIR DOT_GIT "/"
-#define GIT_OBJECTS_DIR "objects/"
-#define GIT_INDEX_FILE "index"
+#define GIT_DIR_MODE 0755
+#define GIT_BARE_DIR_MODE 0777
struct git_object {
git_cached_obj cached;
diff --git a/src/revwalk.c b/src/revwalk.c
index 2d70d40e9..7e31650ff 100644
--- a/src/revwalk.c
+++ b/src/revwalk.c
@@ -68,7 +68,7 @@ static void commit_list_free(commit_list **list_p)
while (list) {
commit_list *temp = list;
list = temp->next;
- free(temp);
+ git__free(temp);
}
*list_p = NULL;
@@ -81,7 +81,7 @@ static commit_object *commit_list_pop(commit_list **stack)
if (top) {
*stack = top->next;
- free(top);
+ git__free(top);
}
return item;
}
@@ -156,7 +156,7 @@ static commit_object *commit_lookup(git_revwalk *walk, const git_oid *oid)
git_oid_cpy(&commit->oid, oid);
if (git_hashtable_insert(walk->commits, &commit->oid, commit) < GIT_SUCCESS) {
- free(commit);
+ git__free(commit);
return NULL;
}
@@ -442,7 +442,7 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
(git_hash_keyeq_ptr)git_oid_cmp);
if (walk->commits == NULL) {
- free(walk);
+ git__free(walk);
return GIT_ENOMEM;
}
@@ -475,17 +475,17 @@ void git_revwalk_free(git_revwalk *walk)
* make sure it's being free'd */
GIT_HASHTABLE_FOREACH(walk->commits, _unused, commit, {
if (commit->out_degree > PARENTS_PER_COMMIT)
- free(commit->parents);
+ git__free(commit->parents);
});
git_hashtable_free(walk->commits);
git_pqueue_free(&walk->iterator_time);
for (i = 0; i < walk->memory_alloc.length; ++i)
- free(git_vector_get(&walk->memory_alloc, i));
+ git__free(git_vector_get(&walk->memory_alloc, i));
git_vector_free(&walk->memory_alloc);
- free(walk);
+ git__free(walk);
}
git_repository *git_revwalk_repository(git_revwalk *walk)
diff --git a/src/signature.c b/src/signature.c
index 388e8d9c9..832d6439c 100644
--- a/src/signature.c
+++ b/src/signature.c
@@ -15,9 +15,9 @@ void git_signature_free(git_signature *sig)
if (sig == NULL)
return;
- free(sig->name);
- free(sig->email);
- free(sig);
+ git__free(sig->name);
+ git__free(sig->email);
+ git__free(sig);
}
static const char *skip_leading_spaces(const char *buffer, const char *buffer_end)
diff --git a/src/status.c b/src/status.c
index 1deade9a5..d50199d9a 100644
--- a/src/status.c
+++ b/src/status.c
@@ -142,16 +142,14 @@ static int retrieve_head_tree(git_tree **tree_out, git_repository *repo)
*tree_out = NULL;
error = git_repository_head(&resolved_head_ref, repo);
- if (error != GIT_SUCCESS && error != GIT_ENOTFOUND)
- return git__rethrow(error, "HEAD can't be resolved");
-
/*
* We assume that a situation where HEAD exists but can not be resolved is valid.
* A new repository fits this description for instance.
*/
-
if (error == GIT_ENOTFOUND)
return GIT_SUCCESS;
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "HEAD can't be resolved");
if ((error = git_commit_lookup(&head_commit, repo, git_reference_oid(resolved_head_ref))) < GIT_SUCCESS)
return git__rethrow(error, "The tip of HEAD can't be retrieved");
@@ -168,41 +166,45 @@ exit:
return error;
}
-#define GIT_STATUS_PATH_NULL -2
-#define GIT_STATUS_PATH_IGNORE -1
-#define GIT_STATUS_PATH_FILE 0
-#define GIT_STATUS_PATH_FOLDER 1
+enum path_type {
+ GIT_STATUS_PATH_NULL,
+ GIT_STATUS_PATH_IGNORE,
+ GIT_STATUS_PATH_FILE,
+ GIT_STATUS_PATH_FOLDER,
+};
static int dirent_cb(void *state, char *full_path);
static int alphasorted_futils_direach(
char *path, size_t path_sz,
int (*fn)(void *, char *), void *arg);
-static int process_folder(struct status_st *st, const git_tree_entry *tree_entry, char *full_path, int path_type)
+static int process_folder(struct status_st *st, const git_tree_entry *tree_entry, char *full_path, enum path_type path_type)
{
git_object *subtree = NULL;
git_tree *pushed_tree = NULL;
int error, pushed_tree_position = 0;
- git_otype tree_entry_type;
-
- tree_entry_type = git_tree_entry_type(tree_entry);
-
- switch (tree_entry_type) {
- case GIT_OBJ_TREE:
- error = git_tree_entry_2object(&subtree, ((git_object *)(st->tree))->repo, tree_entry);
- pushed_tree = st->tree;
- pushed_tree_position = st->tree_position;
- st->tree = (git_tree *)subtree;
- st->tree_position = 0;
- st->head_tree_relative_path_len += 1 + tree_entry->filename_len; /* path + '/' + name */
- break;
-
- case GIT_OBJ_BLOB:
- /* No op */
- break;
-
- default:
- error = git__throw(GIT_EINVALIDTYPE, "Unexpected tree entry type"); /* TODO: How should we deal with submodules? */
+ git_otype tree_entry_type = GIT_OBJ_BAD;
+
+ if (tree_entry != NULL) {
+ tree_entry_type = git_tree_entry_type(tree_entry);
+
+ switch (tree_entry_type) {
+ case GIT_OBJ_TREE:
+ error = git_tree_entry_2object(&subtree, ((git_object *)(st->tree))->repo, tree_entry);
+ pushed_tree = st->tree;
+ pushed_tree_position = st->tree_position;
+ st->tree = (git_tree *)subtree;
+ st->tree_position = 0;
+ st->head_tree_relative_path_len += 1 + tree_entry->filename_len; /* path + '/' + name */
+ break;
+
+ case GIT_OBJ_BLOB:
+ /* No op */
+ break;
+
+ default:
+ error = git__throw(GIT_EINVALIDTYPE, "Unexpected tree entry type"); /* TODO: How should we deal with submodules? */
+ }
}
if (full_path != NULL && path_type == GIT_STATUS_PATH_FOLDER)
@@ -229,7 +231,7 @@ static int store_if_changed(struct status_st *st, struct status_entry *e)
return git__throw(error, "Failed to process the file '%s'. It doesn't exist in the workdir, in the HEAD nor in the index", e->path);
if (e->status_flags == GIT_STATUS_CURRENT) {
- free(e);
+ git__free(e);
return GIT_SUCCESS;
}
@@ -242,7 +244,7 @@ static int determine_status(struct status_st *st,
const git_index_entry *index_entry,
char *full_path,
const char *status_path,
- int path_type)
+ enum path_type path_type)
{
struct status_entry *e;
int error = GIT_SUCCESS;
@@ -289,7 +291,7 @@ static int path_type_from(char *full_path, int is_dir)
if (!is_dir)
return GIT_STATUS_PATH_FILE;
- if (!git__suffixcmp(full_path, "/" DOT_GIT))
+ if (!git__suffixcmp(full_path, "/" DOT_GIT "/"))
return GIT_STATUS_PATH_IGNORE;
return GIT_STATUS_PATH_FOLDER;
@@ -324,30 +326,6 @@ static int compare(const char *left, const char *right)
return strcmp(left, right);
}
-/*
- * Convenience method to enumerate a tree. Contrarily to the git_tree_entry_byindex()
- * method, it allows the tree to be enumerated to be NULL. In this case, every returned
- * tree entry will be NULL as well.
- */
-static const git_tree_entry *git_tree_entry_bypos(git_tree *tree, unsigned int idx)
-{
- if (tree == NULL)
- return NULL;
-
- return git_vector_get(&tree->entries, idx);
-}
-
-/*
- * Convenience method to enumerate the index. This method is not supposed to be exposed
- * as part of the index API because it precludes that the index will not be altered
- * while the enumeration is being processed. Which wouldn't be very API friendly :)
- */
-static const git_index_entry *git_index_entry_bypos(git_index *index, unsigned int idx)
-{
- assert(index);
- return git_vector_get(&index->entries, idx);
-}
-
/* Greatly inspired from JGit IndexTreeWalker */
/* https://github.com/spearce/jgit/blob/ed47e29c777accfa78c6f50685a5df2b8f5b8ff5/org.spearce.jgit/src/org/spearce/jgit/lib/IndexTreeWalker.java#L88 */
@@ -355,7 +333,7 @@ static int dirent_cb(void *state, char *a)
{
const git_tree_entry *m;
const git_index_entry *entry;
- int path_type;
+ enum path_type path_type;
int cmpma, cmpmi, cmpai, error;
const char *pm, *pa, *pi;
const char *m_name, *i_name, *a_name;
@@ -370,15 +348,25 @@ static int dirent_cb(void *state, char *a)
a_name = (path_type != GIT_STATUS_PATH_NULL) ? a + st->workdir_path_len : NULL;
while (1) {
- m = git_tree_entry_bypos(st->tree, st->tree_position);
- entry = git_index_entry_bypos(st->index, st->index_position);
+ if (st->tree == NULL)
+ m = NULL;
+ else
+ m = git_tree_entry_byindex(st->tree, st->tree_position);
+
+ entry = git_index_get(st->index, st->index_position);
if ((m == NULL) && (a == NULL) && (entry == NULL))
return GIT_SUCCESS;
if (m != NULL) {
st->head_tree_relative_path[st->head_tree_relative_path_len] = '\0';
- git_path_join(st->head_tree_relative_path, st->head_tree_relative_path, m->filename);
+
+ /* When the tree entry is a folder, append a forward slash to its name */
+ if (git_tree_entry_type(m) == GIT_OBJ_TREE)
+ git_path_join_n(st->head_tree_relative_path, 3, st->head_tree_relative_path, m->filename, "");
+ else
+ git_path_join(st->head_tree_relative_path, st->head_tree_relative_path, m->filename);
+
m_name = st->head_tree_relative_path;
} else
m_name = NULL;
@@ -396,7 +384,7 @@ static int dirent_cb(void *state, char *a)
if((error = determine_status(st, pm != NULL, pi != NULL, pa != NULL, m, entry, a, status_path(pm, pi, pa), path_type)) < GIT_SUCCESS)
return git__rethrow(error, "An error occured while determining the status of '%s'", a);
- if (pa != NULL)
+ if ((pa != NULL) || (path_type == GIT_STATUS_PATH_FOLDER))
return GIT_SUCCESS;
}
}
@@ -466,7 +454,7 @@ int git_status_foreach(git_repository *repo, int (*callback)(const char *, unsig
error = git__rethrow(error, "Failed to determine statuses. User callback failed");
}
- free(e);
+ git__free(e);
}
exit:
@@ -570,7 +558,7 @@ int git_status_file(unsigned int *status_flags, git_repository *repo, const char
exit:
git_tree_close(tree);
- free(e);
+ git__free(e);
return error;
}
@@ -589,19 +577,32 @@ struct alphasorted_dirent_info {
static struct alphasorted_dirent_info *alphasorted_dirent_info_new(const char *path)
{
- int is_dir;
+ int is_dir, size;
struct alphasorted_dirent_info *di;
is_dir = git_futils_isdir(path) == GIT_SUCCESS ? 1 : 0;
+ size = sizeof(*di) + (is_dir ? GIT_PATH_MAX : strlen(path)) + 2;
- di = git__malloc(sizeof(*di) + (is_dir ? GIT_PATH_MAX : strlen(path)) + 1);
+ di = git__malloc(size);
if (di == NULL)
return NULL;
- memset(di, 0x0, sizeof(*di));
+ memset(di, 0x0, size);
strcpy(di->path, path);
- di->is_dir = is_dir;
+
+ if (is_dir) {
+ di->is_dir = 1;
+
+ /*
+ * Append a forward slash to the name to force folders
+ * to be ordered in a similar way than in a tree
+ *
+ * The file "subdir" should appear before the file "subdir.txt"
+ * The folder "subdir" should appear after the file "subdir.txt"
+ */
+ di->path[strlen(path)] = '/';
+ }
return di;
}
@@ -626,7 +627,7 @@ static int alphasorted_dirent_cb(void *state, char *full_path)
return GIT_ENOMEM;
if (git_vector_insert(entry_names, entry) < GIT_SUCCESS) {
- free(entry);
+ git__free(entry);
return GIT_ENOMEM;
}
@@ -659,7 +660,7 @@ static int alphasorted_futils_direach(
error = fn(arg, entry->path);
}
- free(entry);
+ git__free(entry);
}
git_vector_free(&entry_names);
diff --git a/src/tag.c b/src/tag.c
index ba75104ef..7372e68c7 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -16,9 +16,9 @@
void git_tag__free(git_tag *tag)
{
git_signature_free(tag->tagger);
- free(tag->message);
- free(tag->tag_name);
- free(tag);
+ git__free(tag->message);
+ git__free(tag->tag_name);
+ git__free(tag);
}
const git_oid *git_tag_id(git_tag *c)
@@ -153,6 +153,8 @@ static int retrieve_tag_reference(git_reference **tag_reference_out, char *ref_n
git_reference *tag_ref;
int error;
+ *tag_reference_out = NULL;
+
git_path_join(ref_name_out, GIT_REFS_TAGS_DIR, tag_name);
error = git_reference_lookup(&tag_ref, repo, ref_name_out);
if (error < GIT_SUCCESS)
@@ -224,6 +226,7 @@ static int git_tag_create__internal(
break;
default:
+ git_reference_free(new_ref);
return git__rethrow(error, "Failed to create tag");
}
@@ -232,6 +235,7 @@ static int git_tag_create__internal(
if (new_ref != NULL) {
if (!allow_ref_overwrite) {
git_oid_cpy(oid, git_reference_oid(new_ref));
+ git_reference_free(new_ref);
return git__throw(GIT_EEXISTS, "Tag already exists");
} else {
should_update_ref = 1;
@@ -239,8 +243,10 @@ static int git_tag_create__internal(
}
if (create_tag_annotation) {
- if ((error = write_tag_annotation(oid, repo, tag_name, target, tagger, message)) < GIT_SUCCESS)
+ if ((error = write_tag_annotation(oid, repo, tag_name, target, tagger, message)) < GIT_SUCCESS) {
+ git_reference_free(new_ref);
return error;
+ }
} else
git_oid_cpy(oid, git_object_id(target));
@@ -249,6 +255,8 @@ static int git_tag_create__internal(
else
error = git_reference_set_oid(new_ref, oid);
+ git_reference_free(new_ref);
+
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create tag");
}
@@ -281,7 +289,7 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
git_odb_stream *stream;
git_odb_object *target_obj;
- git_reference *new_ref;
+ git_reference *new_ref = NULL;
char ref_name[GIT_REFNAME_MAX];
assert(oid && buffer);
@@ -309,6 +317,7 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
break;
default:
+ git_reference_free(new_ref);
return git__rethrow(error, "Failed to create tag");
}
@@ -317,6 +326,7 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
if (new_ref != NULL) {
if (!allow_ref_overwrite) {
git_oid_cpy(oid, git_reference_oid(new_ref));
+ git_reference_free(new_ref);
return git__throw(GIT_EEXISTS, "Tag already exists");
} else {
should_update_ref = 1;
@@ -324,25 +334,31 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
}
/* write the buffer */
- if ((error = git_odb_open_wstream(&stream, repo->db, strlen(buffer), GIT_OBJ_TAG)) < GIT_SUCCESS)
+ if ((error = git_odb_open_wstream(&stream, repo->db, strlen(buffer), GIT_OBJ_TAG)) < GIT_SUCCESS) {
+ git_reference_free(new_ref);
return git__rethrow(error, "Failed to create tag");
+ }
stream->write(stream, buffer, strlen(buffer));
error = stream->finalize_write(oid, stream);
stream->free(stream);
- if (error < GIT_SUCCESS)
+ if (error < GIT_SUCCESS) {
+ git_reference_free(new_ref);
return git__rethrow(error, "Failed to create tag");
+ }
if (!should_update_ref)
error = git_reference_create_oid(&new_ref, repo, ref_name, oid, 0);
else
error = git_reference_set_oid(new_ref, oid);
+ git_reference_free(new_ref);
+
git_signature_free(tag.tagger);
- free(tag.tag_name);
- free(tag.message);
+ git__free(tag.tag_name);
+ git__free(tag.message);
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create tag");
}
diff --git a/src/thread-utils.h b/src/thread-utils.h
index 3361ed8bc..c5554799c 100644
--- a/src/thread-utils.h
+++ b/src/thread-utils.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_thread_utils_h__
#define INCLUDE_thread_utils_h__
-
+#include "common.h"
/* Common operations even if threading has been disabled */
typedef struct {
diff --git a/src/transports/git.c b/src/transports/git.c
index 489807851..c2014529b 100644
--- a/src/transports/git.c
+++ b/src/transports/git.c
@@ -109,8 +109,8 @@ static int do_connect(transport_git *t, const char *url)
error = send_request(s, NULL, url);
t->socket = s;
- free(host);
- free(port);
+ git__free(host);
+ git__free(port);
if (error < GIT_SUCCESS && s > 0)
close(s);
@@ -357,11 +357,11 @@ static int git_negotiate_fetch(git_transport *transport, git_repository *repo, g
gitno_consume(buf, line_end);
if (pkt->type == GIT_PKT_ACK) {
- free(pkt);
+ git__free(pkt);
error = GIT_SUCCESS;
goto done;
} else if (pkt->type == GIT_PKT_NAK) {
- free(pkt);
+ git__free(pkt);
break;
} else {
error = git__throw(GIT_ERROR, "Got unexpected pkt type");
@@ -424,12 +424,12 @@ static int git_download_pack(char **out, git_transport *transport, git_repositor
return error;
if (pkt->type == GIT_PKT_PACK) {
- free(pkt);
+ git__free(pkt);
return git_fetch__download_pack(out, buf->data, buf->offset, t->socket, repo);
}
/* For now we don't care about anything */
- free(pkt);
+ git__free(pkt);
gitno_consume(buf, line_end);
}
@@ -475,9 +475,9 @@ static void git_free(git_transport *transport)
}
git_vector_free(refs);
- free(t->heads);
- free(t->parent.url);
- free(t);
+ git__free(t->heads);
+ git__free(t->parent.url);
+ git__free(t);
}
int git_transport_git(git_transport **out)
diff --git a/src/transports/http.c b/src/transports/http.c
index 680354bae..66b6f252c 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -15,6 +15,7 @@
#include "buffer.h"
#include "pkt.h"
#include "refs.h"
+#include "pack.h"
#include "fetch.h"
#include "filebuf.h"
#include "repository.h"
@@ -389,18 +390,18 @@ static int on_body_parse_response(http_parser *parser, const char *str, size_t l
git_buf_consume(buf, line_end);
if (pkt->type == GIT_PKT_PACK) {
- free(pkt);
+ git__free(pkt);
t->pack_ready = 1;
return 0;
}
if (pkt->type == GIT_PKT_NAK) {
- free(pkt);
+ git__free(pkt);
return 0;
}
if (pkt->type != GIT_PKT_ACK) {
- free(pkt);
+ git__free(pkt);
continue;
}
@@ -702,7 +703,7 @@ static int http_download_pack(char **out, git_transport *transport, git_reposito
}
/* A bit dodgy, but we need to keep the pack at the temporary path */
- error = git_filebuf_commit_at(&file, file.path_lock);
+ error = git_filebuf_commit_at(&file, file.path_lock, GIT_PACK_FILE_MODE);
cleanup:
if (error < GIT_SUCCESS)
@@ -749,13 +750,13 @@ static void http_free(git_transport *transport)
}
git_vector_free(common);
git_buf_free(&t->buf);
- free(t->heads);
- free(t->content_type);
- free(t->host);
- free(t->port);
- free(t->service);
- free(t->parent.url);
- free(t);
+ git__free(t->heads);
+ git__free(t->content_type);
+ git__free(t->host);
+ git__free(t->port);
+ git__free(t->service);
+ git__free(t->parent.url);
+ git__free(t);
}
int git_transport_http(git_transport **out)
diff --git a/src/transports/local.c b/src/transports/local.c
index 3f47e9b89..058ed7e79 100644
--- a/src/transports/local.c
+++ b/src/transports/local.c
@@ -54,7 +54,7 @@ static int add_ref(const char *name, git_repository *repo, git_vector *vec)
{
const char peeled[] = "^{}";
git_remote_head *head;
- git_reference *ref;
+ git_reference *ref, *resolved_ref;
git_object *obj = NULL;
int error = GIT_SUCCESS, peel_len, ret;
@@ -72,7 +72,7 @@ static int add_ref(const char *name, git_repository *repo, git_vector *vec)
if (error < GIT_SUCCESS)
goto out;
- error = git_reference_resolve(&ref, ref);
+ error = git_reference_resolve(&resolved_ref, ref);
if (error < GIT_SUCCESS)
goto out;
@@ -111,10 +111,13 @@ static int add_ref(const char *name, git_repository *repo, git_vector *vec)
goto out;
out:
+ git_reference_free(ref);
+ git_reference_free(resolved_ref);
+
git_object_close(obj);
if (error < GIT_SUCCESS) {
- free(head->name);
- free(head);
+ git__free(head->name);
+ git__free(head);
}
return error;
}
@@ -190,16 +193,16 @@ static void local_free(git_transport *transport)
if (t->refs != NULL) {
git_vector_foreach (vec, i, h) {
- free(h->name);
- free(h);
+ git__free(h->name);
+ git__free(h);
}
git_vector_free(vec);
- free(vec);
+ git__free(vec);
}
git_repository_free(t->repo);
- free(t->parent.url);
- free(t);
+ git__free(t->parent.url);
+ git__free(t);
}
/**************
diff --git a/src/tree-cache.c b/src/tree-cache.c
index 5a3257520..ea8b7bfb7 100644
--- a/src/tree-cache.c
+++ b/src/tree-cache.c
@@ -196,6 +196,6 @@ void git_tree_cache_free(git_tree_cache *tree)
for (i = 0; i < tree->children_count; ++i)
git_tree_cache_free(tree->children[i]);
- free(tree->children);
- free(tree);
+ git__free(tree->children);
+ git__free(tree);
}
diff --git a/src/tree.c b/src/tree.c
index 00aefc295..92ca5ab77 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -15,6 +15,8 @@
#define MAX_FILEMODE 0777777
#define MAX_FILEMODE_BYTES 6
+#define ENTRY_IS_TREE(e) ((e)->attr & 040000)
+
static int valid_attributes(const int attributes)
{
return attributes >= 0 && attributes <= MAX_FILEMODE;
@@ -31,8 +33,8 @@ static int entry_sort_cmp(const void *a, const void *b)
const git_tree_entry *entry_b = (const git_tree_entry *)(b);
return git_futils_cmp_path(
- entry_a->filename, entry_a->filename_len, entry_a->attr & 040000,
- entry_b->filename, entry_b->filename_len, entry_b->attr & 040000);
+ entry_a->filename, entry_a->filename_len, ENTRY_IS_TREE(entry_a),
+ entry_b->filename, entry_b->filename_len, ENTRY_IS_TREE(entry_b));
}
@@ -128,12 +130,12 @@ void git_tree__free(git_tree *tree)
git_tree_entry *e;
e = git_vector_get(&tree->entries, i);
- free(e->filename);
- free(e);
+ git__free(e->filename);
+ git__free(e);
}
git_vector_free(&tree->entries);
- free(tree);
+ git__free(tree);
}
const git_oid *git_tree_id(git_tree *c)
@@ -376,7 +378,7 @@ static int write_tree(git_oid *oid, git_index *index, const char *dirname, unsig
last_comp = subdir;
}
error = append_entry(bld, last_comp, &sub_oid, S_IFDIR);
- free(subdir);
+ git__free(subdir);
if (error < GIT_SUCCESS) {
error = git__rethrow(error, "Failed to insert dir");
goto cleanup;
@@ -439,7 +441,7 @@ int git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source)
source_entries = source->entries.length;
if (git_vector_init(&bld->entries, source_entries, entry_sort_cmp) < GIT_SUCCESS) {
- free(bld);
+ git__free(bld);
return GIT_ENOMEM;
}
@@ -594,8 +596,8 @@ void git_treebuilder_clear(git_treebuilder *bld)
for (i = 0; i < bld->entries.length; ++i) {
git_tree_entry *e = bld->entries.contents[i];
- free(e->filename);
- free(e);
+ git__free(e->filename);
+ git__free(e);
}
git_vector_clear(&bld->entries);
@@ -605,10 +607,14 @@ void git_treebuilder_free(git_treebuilder *bld)
{
git_treebuilder_clear(bld);
git_vector_free(&bld->entries);
- free(bld);
+ git__free(bld);
}
-static int tree_frompath(git_tree **parent_out, git_tree *root, const char *treeentry_path, int offset)
+static int tree_frompath(
+ git_tree **parent_out,
+ git_tree *root,
+ const char *treeentry_path,
+ int offset)
{
char *slash_pos = NULL;
const git_tree_entry* entry;
@@ -616,15 +622,21 @@ static int tree_frompath(git_tree **parent_out, git_tree *root, const char *tree
git_tree *subtree;
if (!*(treeentry_path + offset))
- return git__rethrow(GIT_EINVALIDPATH, "Invalid relative path to a tree entry '%s'.", treeentry_path);
+ return git__rethrow(GIT_EINVALIDPATH,
+ "Invalid relative path to a tree entry '%s'.", treeentry_path);
slash_pos = (char *)strchr(treeentry_path + offset, '/');
if (slash_pos == NULL)
- return git_tree_lookup(parent_out, root->object.repo, git_object_id((const git_object *)root));
+ return git_tree_lookup(
+ parent_out,
+ root->object.repo,
+ git_object_id((const git_object *)root)
+ );
if (slash_pos == treeentry_path + offset)
- return git__rethrow(GIT_EINVALIDPATH, "Invalid relative path to a tree entry '%s'.", treeentry_path);
+ return git__rethrow(GIT_EINVALIDPATH,
+ "Invalid relative path to a tree entry '%s'.", treeentry_path);
*slash_pos = '\0';
@@ -634,23 +646,95 @@ static int tree_frompath(git_tree **parent_out, git_tree *root, const char *tree
*slash_pos = '/';
if (entry == NULL)
- return git__rethrow(GIT_ENOTFOUND, "No tree entry can be found from the given tree and relative path '%s'.", treeentry_path);
+ return git__rethrow(GIT_ENOTFOUND,
+ "No tree entry can be found from "
+ "the given tree and relative path '%s'.", treeentry_path);
+
- if ((error = git_tree_lookup(&subtree, root->object.repo, &entry->oid)) < GIT_SUCCESS)
+ error = git_tree_lookup(&subtree, root->object.repo, &entry->oid);
+ if (error < GIT_SUCCESS)
return error;
- error = tree_frompath(parent_out, subtree, treeentry_path, slash_pos - treeentry_path + 1);
+ error = tree_frompath(
+ parent_out,
+ subtree,
+ treeentry_path,
+ slash_pos - treeentry_path + 1
+ );
git_tree_close(subtree);
return error;
}
-int git_tree_frompath(git_tree **parent_out, git_tree *root, const char *treeentry_path)
+int git_tree_get_subtree(
+ git_tree **subtree,
+ git_tree *root,
+ const char *subtree_path)
{
char buffer[GIT_PATH_MAX];
- assert(root && treeentry_path);
+ assert(subtree && root && subtree_path);
+
+ strncpy(buffer, subtree_path, GIT_PATH_MAX);
+ return tree_frompath(subtree, root, buffer, 0);
+}
+
+static int tree_walk_post(
+ git_tree *tree,
+ git_treewalk_cb callback,
+ char *root,
+ size_t root_len,
+ void *payload)
+{
+ int error;
+ unsigned int i;
+
+ for (i = 0; i < tree->entries.length; ++i) {
+ git_tree_entry *entry = tree->entries.contents[i];
+
+ root[root_len] = '\0';
+
+ if (callback(root, entry, payload) < 0)
+ continue;
+
+ if (ENTRY_IS_TREE(entry)) {
+ git_tree *subtree;
+
+ if ((error = git_tree_lookup(
+ &subtree, tree->object.repo, &entry->oid)) < 0)
+ return error;
+
+ strcpy(root + root_len, entry->filename);
+ root[root_len + entry->filename_len] = '/';
+
+ tree_walk_post(subtree,
+ callback, root,
+ root_len + entry->filename_len + 1,
+ payload
+ );
- strcpy(buffer, treeentry_path);
- return tree_frompath(parent_out, root, buffer, 0);
+ git_tree_close(subtree);
+ }
+ }
+
+ return GIT_SUCCESS;
+}
+
+int git_tree_walk(git_tree *tree, git_treewalk_cb callback, int mode, void *payload)
+{
+ char root_path[GIT_PATH_MAX];
+
+ root_path[0] = '\0';
+ switch (mode) {
+ case GIT_TREEWALK_POST:
+ return tree_walk_post(tree, callback, root_path, 0, payload);
+
+ case GIT_TREEWALK_PRE:
+ return git__throw(GIT_ENOTIMPLEMENTED,
+ "Preorder tree walking is still not implemented");
+
+ default:
+ return git__throw(GIT_EINVALIDARGS,
+ "Invalid walking mode for tree walk");
+ }
}
diff --git a/src/tsort.c b/src/tsort.c
index 5dd99cc6e..df230b59d 100644
--- a/src/tsort.c
+++ b/src/tsort.c
@@ -178,7 +178,7 @@ static int check_invariant(struct tsort_run *stack, int stack_curr)
static int resize(struct tsort_store *store, size_t new_size)
{
if (store->alloc < new_size) {
- void **tempstore = realloc(store->storage, new_size * sizeof(void *));
+ void **tempstore = git__realloc(store->storage, new_size * sizeof(void *));
/**
* Do not propagate on OOM; this will abort the sort and
@@ -319,7 +319,7 @@ static ssize_t collapse(void **dst, struct tsort_run *stack, ssize_t stack_curr,
stack_curr--; \
} \
if (store->storage != NULL) {\
- free(store->storage);\
+ git__free(store->storage);\
store->storage = NULL;\
}\
return;\
diff --git a/src/util.c b/src/util.c
index c81ed2d3a..b3af7ffd8 100644
--- a/src/util.c
+++ b/src/util.c
@@ -26,9 +26,9 @@ void git_strarray_free(git_strarray *array)
{
size_t i;
for (i = 0; i < array->count; ++i)
- free(array->strings[i]);
+ git__free(array->strings[i]);
- free(array->strings);
+ git__free(array->strings);
}
int git__fnmatch(const char *pattern, const char *name, int flags)
diff --git a/src/util.h b/src/util.h
index 4de91b494..fbf9012a3 100644
--- a/src/util.h
+++ b/src/util.h
@@ -72,6 +72,8 @@ GIT_INLINE(void *) git__realloc(void *ptr, size_t size)
return new_ptr;
}
+#define git__free(ptr) free(ptr)
+
extern int git__prefixcmp(const char *str, const char *prefix);
extern int git__suffixcmp(const char *str, const char *suffix);
diff --git a/src/vector.c b/src/vector.c
index 8b20bb8ef..123aae8e6 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -18,7 +18,7 @@ static int resize_vector(git_vector *v)
if (v->_alloc_size < minimum_size)
v->_alloc_size = minimum_size;
- v->contents = realloc(v->contents, v->_alloc_size * sizeof(void *));
+ v->contents = git__realloc(v->contents, v->_alloc_size * sizeof(void *));
if (v->contents == NULL)
return GIT_ENOMEM;
@@ -29,7 +29,7 @@ static int resize_vector(git_vector *v)
void git_vector_free(git_vector *v)
{
assert(v);
- free(v->contents);
+ git__free(v->contents);
}
int git_vector_init(git_vector *v, unsigned int initial_size, git_vector_cmp cmp)
diff --git a/src/win32/dir.c b/src/win32/dir.c
index ab50318e3..01aaaaad3 100644
--- a/src/win32/dir.c
+++ b/src/win32/dir.c
@@ -6,7 +6,8 @@
*/
#define GIT__WIN32_NO_WRAP_DIR
#include "dir.h"
-#include "utf8-conv.h"
+#include "utf-conv.h"
+#include "git2/windows.h"
static int init_filter(char *filter, size_t n, const char *dir)
{
@@ -38,18 +39,18 @@ git__DIR *git__opendir(const char *dir)
new->dir = git__malloc(strlen(dir)+1);
if (!new->dir) {
- free(new);
+ git__free(new);
return NULL;
}
strcpy(new->dir, dir);
- filter_w = conv_utf8_to_utf16(filter);
+ filter_w = gitwin_to_utf16(filter);
new->h = FindFirstFileW(filter_w, &new->f);
- free(filter_w);
+ git__free(filter_w);
if (new->h == INVALID_HANDLE_VALUE) {
- free(new->dir);
- free(new);
+ git__free(new->dir);
+ git__free(new);
return NULL;
}
new->first = 1;
@@ -73,7 +74,7 @@ struct git__dirent *git__readdir(git__DIR *d)
return NULL;
d->entry.d_ino = 0;
- WideCharToMultiByte(CP_UTF8, 0, d->f.cFileName, -1, d->entry.d_name, GIT_PATH_MAX, NULL, NULL);
+ WideCharToMultiByte(gitwin_get_codepage(), 0, d->f.cFileName, -1, d->entry.d_name, GIT_PATH_MAX, NULL, NULL);
return &d->entry;
}
@@ -90,9 +91,9 @@ void git__rewinddir(git__DIR *d)
d->first = 0;
if (init_filter(filter, sizeof(filter), d->dir)) {
- filter_w = conv_utf8_to_utf16(filter);
+ filter_w = gitwin_to_utf16(filter);
d->h = FindFirstFileW(filter_w, &d->f);
- free(filter_w);
+ git__free(filter_w);
if (d->h != INVALID_HANDLE_VALUE)
d->first = 1;
@@ -106,8 +107,8 @@ int git__closedir(git__DIR *d)
if (d->h != INVALID_HANDLE_VALUE)
FindClose(d->h);
if (d->dir)
- free(d->dir);
- free(d);
+ git__free(d->dir);
+ git__free(d);
}
return 0;
}
diff --git a/src/win32/posix.h b/src/win32/posix.h
index 442717e42..ae6323679 100644
--- a/src/win32/posix.h
+++ b/src/win32/posix.h
@@ -9,7 +9,7 @@
#include "common.h"
#include "fnmatch.h"
-#include "utf8-conv.h"
+#include "utf-conv.h"
GIT_INLINE(int) p_link(const char *GIT_UNUSED(old), const char *GIT_UNUSED(new))
{
@@ -19,14 +19,14 @@ GIT_INLINE(int) p_link(const char *GIT_UNUSED(old), const char *GIT_UNUSED(new))
return -1;
}
-GIT_INLINE(int) p_mkdir(const char *path, int GIT_UNUSED(mode))
+GIT_INLINE(int) p_mkdir(const char *path, mode_t GIT_UNUSED(mode))
{
- wchar_t* buf = conv_utf8_to_utf16(path);
+ wchar_t* buf = gitwin_to_utf16(path);
int ret = _wmkdir(buf);
GIT_UNUSED_ARG(mode)
- free(buf);
+ git__free(buf);
return ret;
}
@@ -41,12 +41,13 @@ extern int p_mkstemp(char *tmp_path);
extern int p_setenv(const char* name, const char* value, int overwrite);
extern int p_stat(const char* path, struct stat* buf);
extern int p_chdir(const char* path);
-extern int p_chmod(const char* path, int mode);
+extern int p_chmod(const char* path, mode_t mode);
extern int p_rmdir(const char* path);
-extern int p_access(const char* path, int mode);
+extern int p_access(const char* path, mode_t mode);
extern int p_fsync(int fd);
extern int p_open(const char *path, int flags);
-extern int p_creat(const char *path, int mode);
+extern int p_creat(const char *path, mode_t mode);
extern int p_getcwd(char *buffer_out, size_t size);
+extern int p_rename(const char *from, const char *to);
#endif
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index cc17cc71f..6f722581e 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -6,7 +6,7 @@
*/
#include "posix.h"
#include "path.h"
-#include "utf8-conv.h"
+#include "utf-conv.h"
#include <errno.h>
#include <io.h>
#include <fcntl.h>
@@ -17,10 +17,10 @@ int p_unlink(const char *path)
int ret = 0;
wchar_t* buf;
- buf = conv_utf8_to_utf16(path);
+ buf = gitwin_to_utf16(path);
_wchmod(buf, 0666);
ret = _wunlink(buf);
- free(buf);
+ git__free(buf);
return ret;
}
@@ -59,7 +59,7 @@ GIT_INLINE(time_t) filetime_to_time_t(const FILETIME *ft)
static int do_lstat(const char *file_name, struct stat *buf)
{
WIN32_FILE_ATTRIBUTE_DATA fdata;
- wchar_t* fbuf = conv_utf8_to_utf16(file_name);
+ wchar_t* fbuf = gitwin_to_utf16(file_name);
if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) {
int fMode = S_IREAD;
@@ -86,11 +86,11 @@ static int do_lstat(const char *file_name, struct stat *buf)
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
- free(fbuf);
+ git__free(fbuf);
return GIT_SUCCESS;
}
- free(fbuf);
+ git__free(fbuf);
switch (GetLastError()) {
case ERROR_ACCESS_DENIED:
@@ -161,7 +161,7 @@ int p_readlink(const char *link, char *target, size_t target_len)
"'GetFinalPathNameByHandleW' is not available in this platform");
}
- link_w = conv_utf8_to_utf16(link);
+ link_w = gitwin_to_utf16(link);
hFile = CreateFileW(link_w, // file to open
GENERIC_READ, // open for reading
@@ -171,7 +171,7 @@ int p_readlink(const char *link, char *target, size_t target_len)
FILE_FLAG_BACKUP_SEMANTICS, // normal file
NULL); // no attr. template
- free(link_w);
+ git__free(link_w);
if (hFile == INVALID_HANDLE_VALUE)
return GIT_EOSERR;
@@ -184,17 +184,17 @@ int p_readlink(const char *link, char *target, size_t target_len)
dwRet = pGetFinalPath(hFile, target_w, target_len, 0x0);
if (dwRet >= target_len) {
- free(target_w);
+ git__free(target_w);
CloseHandle(hFile);
return GIT_ENOMEM;
}
if (!WideCharToMultiByte(CP_UTF8, 0, target_w, -1, target, target_len * sizeof(char), NULL, NULL)) {
- free(target_w);
+ git__free(target_w);
return GIT_EOSERR;
}
- free(target_w);
+ git__free(target_w);
CloseHandle(hFile);
if (dwRet > 4) {
@@ -223,20 +223,20 @@ int p_readlink(const char *link, char *target, size_t target_len)
int p_open(const char *path, int flags)
{
int fd;
- wchar_t* buf = conv_utf8_to_utf16(path);
+ wchar_t* buf = gitwin_to_utf16(path);
fd = _wopen(buf, flags | _O_BINARY);
- free(buf);
+ git__free(buf);
return fd;
}
-int p_creat(const char *path, int mode)
+int p_creat(const char *path, mode_t mode)
{
int fd;
- wchar_t* buf = conv_utf8_to_utf16(path);
+ wchar_t* buf = gitwin_to_utf16(path);
fd = _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode);
- free(buf);
+ git__free(buf);
return fd;
}
@@ -246,11 +246,11 @@ int p_getcwd(char *buffer_out, size_t size)
_wgetcwd(buf, (int)size);
if (!WideCharToMultiByte(CP_UTF8, 0, buf, -1, buffer_out, size, NULL, NULL)) {
- free(buf);
+ git__free(buf);
return GIT_EOSERR;
}
- free(buf);
+ git__free(buf);
return GIT_SUCCESS;
}
@@ -261,40 +261,40 @@ int p_stat(const char* path, struct stat* buf)
int p_chdir(const char* path)
{
- wchar_t* buf = conv_utf8_to_utf16(path);
+ wchar_t* buf = gitwin_to_utf16(path);
int ret = _wchdir(buf);
- free(buf);
+ git__free(buf);
return ret;
}
-int p_chmod(const char* path, int mode)
+int p_chmod(const char* path, mode_t mode)
{
- wchar_t* buf = conv_utf8_to_utf16(path);
+ wchar_t* buf = gitwin_to_utf16(path);
int ret = _wchmod(buf, mode);
- free(buf);
+ git__free(buf);
return ret;
}
int p_rmdir(const char* path)
{
- wchar_t* buf = conv_utf8_to_utf16(path);
+ wchar_t* buf = gitwin_to_utf16(path);
int ret = _wrmdir(buf);
- free(buf);
+ git__free(buf);
return ret;
}
int p_hide_directory__w32(const char *path)
{
int error;
- wchar_t* buf = conv_utf8_to_utf16(path);
+ wchar_t* buf = gitwin_to_utf16(path);
error = SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN) != 0 ?
GIT_SUCCESS : GIT_ERROR; /* MSDN states a "non zero" value indicates a success */
- free(buf);
+ git__free(buf);
if (error < GIT_SUCCESS)
error = git__throw(GIT_EOSERR, "Failed to hide directory '%s'", path);
@@ -305,7 +305,7 @@ int p_hide_directory__w32(const char *path)
char *p_realpath(const char *orig_path, char *buffer)
{
int ret, alloc = 0;
- wchar_t* orig_path_w = conv_utf8_to_utf16(orig_path);
+ wchar_t* orig_path_w = gitwin_to_utf16(orig_path);
wchar_t* buffer_w = (wchar_t*)git__malloc(GIT_PATH_MAX * sizeof(wchar_t));
if (buffer == NULL) {
@@ -314,21 +314,21 @@ char *p_realpath(const char *orig_path, char *buffer)
}
ret = GetFullPathNameW(orig_path_w, GIT_PATH_MAX, buffer_w, NULL);
- free(orig_path_w);
+ git__free(orig_path_w);
if (!ret || ret > GIT_PATH_MAX) {
- free(buffer_w);
- if (alloc) free(buffer);
+ git__free(buffer_w);
+ if (alloc) git__free(buffer);
return NULL;
}
if (!WideCharToMultiByte(CP_UTF8, 0, buffer_w, -1, buffer, GIT_PATH_MAX, NULL, NULL)) {
- free(buffer_w);
- if (alloc) free(buffer);
+ git__free(buffer_w);
+ if (alloc) git__free(buffer);
}
- free(buffer_w);
+ git__free(buffer_w);
git_path_mkposix(buffer);
return buffer;
}
@@ -355,7 +355,7 @@ int p_snprintf(char *buffer, size_t count, const char *format, ...)
return r;
}
-extern int p_creat(const char *path, int mode);
+extern int p_creat(const char *path, mode_t mode);
int p_mkstemp(char *tmp_path)
{
@@ -378,13 +378,27 @@ int p_setenv(const char* name, const char* value, int overwrite)
return (SetEnvironmentVariableA(name, value) == 0 ? GIT_EOSERR : GIT_SUCCESS);
}
-int p_access(const char* path, int mode)
+int p_access(const char* path, mode_t mode)
{
- wchar_t *buf = conv_utf8_to_utf16(path);
+ wchar_t *buf = gitwin_to_utf16(path);
int ret;
ret = _waccess(buf, mode);
- free(buf);
+ git__free(buf);
+
+ return ret;
+}
+
+extern int p_rename(const char *from, const char *to)
+{
+ wchar_t *wfrom = gitwin_to_utf16(from);
+ wchar_t *wto = gitwin_to_utf16(to);
+ int ret;
+
+ ret = MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR;
+
+ git__free(wfrom);
+ git__free(wto);
return ret;
}
diff --git a/src/win32/utf8-conv.c b/src/win32/utf-conv.c
index dec6f8e79..b41c78f92 100644
--- a/src/win32/utf8-conv.c
+++ b/src/win32/utf-conv.c
@@ -6,9 +6,29 @@
*/
#include "common.h"
-#include "utf8-conv.h"
+#include "utf-conv.h"
-wchar_t* conv_utf8_to_utf16(const char* str)
+/*
+ * Default codepage value
+ */
+static int _active_codepage = CP_UTF8;
+
+void gitwin_set_codepage(unsigned int codepage)
+{
+ _active_codepage = codepage;
+}
+
+unsigned int gitwin_get_codepage(void)
+{
+ return _active_codepage;
+}
+
+void gitwin_set_utf8(void)
+{
+ _active_codepage = CP_UTF8;
+}
+
+wchar_t* gitwin_to_utf16(const char* str)
{
wchar_t* ret;
int cb;
@@ -29,15 +49,15 @@ wchar_t* conv_utf8_to_utf16(const char* str)
ret = (wchar_t*)git__malloc(cb);
- if (MultiByteToWideChar(CP_UTF8, 0, str, -1, ret, cb) == 0) {
- free(ret);
+ if (MultiByteToWideChar(_active_codepage, 0, str, -1, ret, cb) == 0) {
+ git__free(ret);
ret = NULL;
}
return ret;
}
-char* conv_utf16_to_utf8(const wchar_t* str)
+char* gitwin_from_utf16(const wchar_t* str)
{
char* ret;
int cb;
@@ -58,8 +78,8 @@ char* conv_utf16_to_utf8(const wchar_t* str)
ret = (char*)git__malloc(cb);
- if (WideCharToMultiByte(CP_UTF8, 0, str, -1, ret, cb, NULL, NULL) == 0) {
- free(ret);
+ if (WideCharToMultiByte(_active_codepage, 0, str, -1, ret, cb, NULL, NULL) == 0) {
+ git__free(ret);
ret = NULL;
}
diff --git a/src/win32/utf8-conv.h b/src/win32/utf-conv.h
index 1967ac3a1..da03e3385 100644
--- a/src/win32/utf8-conv.h
+++ b/src/win32/utf-conv.h
@@ -7,11 +7,11 @@
#include <wchar.h>
-#ifndef INCLUDE_git_utf8conv_h__
-#define INCLUDE_git_utf8conv_h__
+#ifndef INCLUDE_git_utfconv_h__
+#define INCLUDE_git_utfconv_h__
-wchar_t* conv_utf8_to_utf16(const char* str);
-char* conv_utf16_to_utf8(const wchar_t* str);
+wchar_t* gitwin_to_utf16(const char* str);
+char* gitwin_from_utf16(const wchar_t* str);
#endif
diff --git a/tests-clay/README.md b/tests-clay/README.md
index 4939f5717..6b5a659f8 100644
--- a/tests-clay/README.md
+++ b/tests-clay/README.md
@@ -11,7 +11,7 @@ https://github.com/tanoku/clay
* Mix the tests:
- ./clay
+ ./clay -vtap .
* Make sure you actually build the tests by setting:
diff --git a/tests-clay/clay b/tests-clay/clay
index d042a2a1c..a40f6601a 100755
--- a/tests-clay/clay
+++ b/tests-clay/clay
@@ -4,13 +4,13 @@ from __future__ import with_statement
from string import Template
import re, fnmatch, os
-VERSION = "0.8.0"
+VERSION = "0.9.0"
-TEST_FUNC_REGEX = r"^(void\s+(test_%s__(\w+))\(\s*(void)?\s*\))\s*\{"
+TEST_FUNC_REGEX = r"^(void\s+(test_%s__(\w+))\(\s*void\s*\))\s*\{"
CLAY_HEADER = """
/*
- * Clay v0.7.0
+ * Clay v0.9.0
*
* This is an autogenerated file. Do not modify.
* To add new unit tests or suites, regenerate the whole
@@ -18,27 +18,17 @@ CLAY_HEADER = """
*/
"""
-TEMPLATE_SUITE = Template(
-r"""
- {
- "${clean_name}",
- ${initialize},
- ${cleanup},
- ${cb_ptr}, ${cb_count}
- }
-""")
-
def main():
from optparse import OptionParser
parser = OptionParser()
parser.add_option('-c', '--clay-path', dest='clay_path')
- parser.add_option('-v', '--report-to', dest='print_mode', default='stdout')
+ parser.add_option('-v', '--report-to', dest='print_mode', default='default')
options, args = parser.parse_args()
- for folder in args:
+ for folder in args or ['.']:
builder = ClayTestBuilder(folder,
clay_path = options.clay_path,
print_mode = options.print_mode)
@@ -47,17 +37,22 @@ def main():
class ClayTestBuilder:
- def __init__(self, path, clay_path = None, print_mode = 'stdout'):
+ def __init__(self, path, clay_path = None, print_mode = 'default'):
self.declarations = []
- self.callbacks = []
- self.suites = []
- self.suite_list = []
+ self.suite_names = []
+ self.callback_data = {}
+ self.suite_data = {}
self.clay_path = os.path.abspath(clay_path) if clay_path else None
- self.print_mode = print_mode
self.path = os.path.abspath(path)
- self.modules = ["clay_sandbox.c", "clay_fixtures.c", "clay_fs.c"]
+ self.modules = [
+ "clay_sandbox.c",
+ "clay_fixtures.c",
+ "clay_fs.c"
+ ]
+
+ self.modules.append("clay_print_%s.c" % print_mode)
print("Loading test suites...")
@@ -66,7 +61,6 @@ class ClayTestBuilder:
module_root = [c for c in module_root.split(os.sep) if c]
tests_in_module = fnmatch.filter(files, "*.c")
- tests_in_module.sort()
for test_file in tests_in_module:
full_path = os.path.join(root, test_file)
@@ -75,51 +69,107 @@ class ClayTestBuilder:
with open(full_path) as f:
self._process_test_file(test_name, f.read())
- if not self.suites:
+ if not self.suite_data:
raise RuntimeError(
'No tests found under "%s"' % folder_name)
def render(self):
main_file = os.path.join(self.path, 'clay_main.c')
with open(main_file, "w") as out:
- template = Template(self._load_file('clay.c'))
+ out.write(self._render_main())
+
+ header_file = os.path.join(self.path, 'clay.h')
+ with open(header_file, "w") as out:
+ out.write(self._render_header())
+
+ print ('Written Clay suite to "%s"' % self.path)
+
+ #####################################################
+ # Internal methods
+ #####################################################
+
+ def _render_cb(self, cb):
+ return '{"%s", &%s}' % (cb['short_name'], cb['symbol'])
+
+ def _render_suite(self, suite):
+ template = Template(
+r"""
+ {
+ "${clean_name}",
+ ${initialize},
+ ${cleanup},
+ ${cb_ptr}, ${cb_count}
+ }
+""")
- output = template.substitute(
- clay_print = self._get_print_method(),
- clay_modules = self._get_modules(),
+ callbacks = {}
+ for cb in ['initialize', 'cleanup']:
+ callbacks[cb] = (self._render_cb(suite[cb])
+ if suite[cb] else "{NULL, NULL}")
+
+ return template.substitute(
+ clean_name = suite['name'].replace("_", "::"),
+ initialize = callbacks['initialize'],
+ cleanup = callbacks['cleanup'],
+ cb_ptr = "_clay_cb_%s" % suite['name'],
+ cb_count = suite['cb_count']
+ ).strip()
- suites_str = ", ".join(self.suite_list),
+ def _render_callbacks(self, suite_name, callbacks):
+ template = Template(
+r"""
+static const struct clay_func _clay_cb_${suite_name}[] = {
+ ${callbacks}
+};
+""")
+ callbacks = [
+ self._render_cb(cb)
+ for cb in callbacks
+ if cb['short_name'] not in ('initialize', 'cleanup')
+ ]
+
+ return template.substitute(
+ suite_name = suite_name,
+ callbacks = ",\n\t".join(callbacks)
+ ).strip()
- test_callbacks = ",\n\t".join(self.callbacks),
- cb_count = len(self.callbacks),
+ def _render_header(self):
+ template = Template(self._load_file('clay.h'))
- test_suites = ",\n\t".join(self.suites),
- suite_count = len(self.suites),
- )
+ declarations = "\n".join(
+ "extern %s;" % decl
+ for decl in sorted(self.declarations)
+ )
- out.write(output)
+ return template.substitute(
+ extern_declarations = declarations,
+ )
- header_file = os.path.join(self.path, 'clay.h')
- with open(header_file, "w") as out:
- template = Template(self._load_file('clay.h'))
+ def _render_main(self):
+ template = Template(self._load_file('clay.c'))
+ suite_names = sorted(self.suite_names)
- output = template.substitute(
- extern_declarations = "\n".join(self.declarations),
- )
+ suite_data = [
+ self._render_suite(self.suite_data[s])
+ for s in suite_names
+ ]
- out.write(output)
+ callbacks = [
+ self._render_callbacks(s, self.callback_data[s])
+ for s in suite_names
+ ]
- print ('Written Clay suite to "%s"' % self.path)
+ callback_count = sum(
+ len(cbs) for cbs in self.callback_data.values()
+ )
- #####################################################
- # Internal methods
- #####################################################
- def _get_print_method(self):
- return {
- 'stdout' : 'printf(__VA_ARGS__)',
- 'stderr' : 'fprintf(stderr, __VA_ARGS__)',
- 'silent' : ''
- }[self.print_mode]
+ return template.substitute(
+ clay_modules = self._get_modules(),
+ clay_callbacks = "\n".join(callbacks),
+ clay_suites = ",\n\t".join(suite_data),
+ clay_suite_count = len(suite_data),
+ clay_callback_count = callback_count,
+ )
def _load_file(self, filename):
if self.clay_path:
@@ -151,52 +201,67 @@ class ClayTestBuilder:
return comment
- def _process_test_file(self, test_name, contents):
- regex_string = TEST_FUNC_REGEX % test_name
+ def _process_test_file(self, suite_name, contents):
+ regex_string = TEST_FUNC_REGEX % suite_name
regex = re.compile(regex_string, re.MULTILINE)
callbacks = []
- initialize = cleanup = "{NULL, NULL, 0}"
+ initialize = cleanup = None
- for (declaration, symbol, short_name, _) in regex.findall(contents):
- self.declarations.append("extern %s;" % declaration)
- func_ptr = '{"%s", &%s, %d}' % (
- short_name, symbol, len(self.suites)
- )
+ for (declaration, symbol, short_name) in regex.findall(contents):
+ data = {
+ "short_name" : short_name,
+ "declaration" : declaration,
+ "symbol" : symbol
+ }
if short_name == 'initialize':
- initialize = func_ptr
+ initialize = data
elif short_name == 'cleanup':
- cleanup = func_ptr
+ cleanup = data
else:
- callbacks.append(func_ptr)
+ callbacks.append(data)
if not callbacks:
return
- clean_name = test_name.replace("_", "::")
+ tests_in_suite = len(callbacks)
- suite = TEMPLATE_SUITE.substitute(
- clean_name = clean_name,
- initialize = initialize,
- cleanup = cleanup,
- cb_ptr = "&_all_callbacks[%d]" % len(self.callbacks),
- cb_count = len(callbacks)
- ).strip()
+ suite = {
+ "name" : suite_name,
+ "initialize" : initialize,
+ "cleanup" : cleanup,
+ "cb_count" : tests_in_suite
+ }
+
+ if initialize:
+ self.declarations.append(initialize['declaration'])
+
+ if cleanup:
+ self.declarations.append(cleanup['declaration'])
+
+ self.declarations += [
+ callback['declaration']
+ for callback in callbacks
+ ]
+
+ callbacks.sort(key=lambda x: x['short_name'])
+ self.callback_data[suite_name] = callbacks
+ self.suite_data[suite_name] = suite
+ self.suite_names.append(suite_name)
- self.callbacks += callbacks
- self.suites.append(suite)
- self.suite_list.append(clean_name)
+ print(" %s (%d tests)" % (suite_name, tests_in_suite))
- print(" %s (%d tests)" % (clean_name, len(callbacks)))
CLAY_FILES = {
-"clay.c" : r"""eJy9GWtT20jys/wrZk3AEggHyDd74SqVu1xRl2WrAqlsFaFUsjTGc9HDqxkFONb//brnpdHLux+uji+gnu6efndPc8CKJKtTSn6OOaeVmG+uJgcWxqn4d77twESasVUPxsouqGLFYxuWx2KDkMnbY1LR32tW0ZSsy4rwuEhX5TMQkOO3LpMX/la8bCnv8AYwF7EUdnKQ0jUrKEmy+CXawqXCn8/nAXnz2kB2gMbWgEiir9c37y4mB55l9sSKtHxSNzRQrU4D4BuaZfGWdcAp6JBoQTwtSfTL++ub6MMHEkVJSpPMOUKp/S2YIYQ/AxK1vxu8/Dsw1gd5mVJAbUAOXrKxQBI5Hw1GnCSU8zarPsyVsErrrQ+/pHj2A5Vg60LaMPrl+uafX99dRBEAvW0VP+YxSco8p2B8CI6QTKW53l1MkbPDuki2L74oQ7Kuyjwkoow4+w+IpI8iLg812GBFd5+/3Hx4f/cPl9nX6Nd/kbMLB3IbXd/+/fqz/xwQ338mRyQCyEeABOSnS3LmEuffBc23kTFBRgtp4B4QSGiRsvXEwyhE3UHQOhHKceT27v1ddLecHNCM01awQIA+xQzjgkCs459blvoXgQzvBq8uGKSOCqlO8PSu7NwoxWpyYorBPt9MJxPEYwn5UTLILR5VuZ+UBRcQKnFFjiNe1lVCg2UXLynBMwOYIXGBKYUwXdpL3KPJmj2LuqIRmq/FaRXzDhuDWsQ5VeykijJhaVVBRXideC6BgHuXEzCcIPhnVNT5ilbLNhKvmaAd2JplVBNmYN5hQnlllPNHhBs9k4ptBSsLEM/ry3dc0GeQaNfYQuN0BI8TwX7QSMs/cKKFViLKD3UDN+qWIs4syDFBUtaFGBHOchg4y2Igln8jsXS/f5yVCdySZDQu6m3gS+gxeEadt4/BwS9ZGadIDt0hWtVrIqo435ZoYSO2BUS0iFcZBfQdlCgQpOPvdV0kXathXCytcFsoP1IkFAgLQ2QsVRgPNOzkwQi/3rWsYILFGbAcOtX6Wr/1EGRY8kYo1y8oF6T+R6hgWjDV4+YJ1gA3+eRpXehzo6jGQFu65ObY5TCRCFVdyDDz94sbjh831tiDZGJk8qocrXIHUC+Vd+ftGJ54CtqPByA4lwG9Jr6aM/wuakAusXCjNyVaI+DpFQQFlvWbL58+BXDsdc58tJHnocb229vtF+fMiKNwWkHv3jVwPERi8iQwbDW8J7sLV3JrIW04nZwgVE5NefkDmnrxQuRdp2A5E6ckp2JTphzja0hGom5cDh4aYS0SREAzUE0Pk2lo7OI6mFzZAAjI38js44wsyGw+Ay12AzEquSlSH4MHqrFpDGNVTAaaKwohh2lAPsYsgw6y+FaAYMAm6EnMF4tDTvxDHpB7+DhMH8j9qYBfSAJWl9xPr6Q2zrfOEW9alMTpAi4J9hTn0+krHT4a2pMNVOBScI1r+48NFX3gCNAOmHFeDknvXsAbcUxFt2WlPcNVjTEJzlSijraZ0PTCiVLdFgLbhJ42YDCtk1VDJjUSAr4WXbFx1TOhcnKi9cMs9tYVpQMW6pzJTyORZr0bVh4qpwwDvx+Kqp2o0UKF4p7aChdJROV9pzGwJqndtt/g6wY1kGC6LOEryWfyCzzys3uP7jjk5IQpq7Yu0nLhr3v2MNcXee2WcaSPQ3KkGTu9wMJM6d9vSHjEZUOW/JMW1DP0mC3+uh37FjAIk47+Uqq/qPuQ4jWPH2lr5o2rR6mFDOO1P/2CGAvIVXJfymjlUIdk3iLmskH8VZ0uVK5aMCGn4rffvolv4nNdkLLIXojYUKkUUVWGwHGPhg/QKJN1iegzE/7p+VjhjitOIxCV+6oqwJ9JqHVFZX/sGxniLFvFyXce2oRIVipq/zQUHBoVCpKsKU6t3DhXuYGyOelgHVLj+xTQUFwI9qU5wzjBOd/zdE+SowOWYUN0f/aAhWt2OpOzhuNzyevsQU0bipG6QdGdy1uAJYaoqESZWZ7khFxAfJnPkJyfBfbiRly89tvZjPzxB0oG2p3tFYE/MZFsQHIpijYAvL/ITMwWck4C7r6yaIAMry6tMxQ21FAdQPA0hcSDx/ydE2WHKUlLyklRwuz3DM/XudOCkboJJPjAiavdr25FXAkYt3zVoAPdjUFy6e57Gyz3wPJB53+hCpdC7GCYN6TnFDVdhI7aqCabRy9RMq8qGn+XDJXh+Kjh3Igcs92tm23/U+MdS9sRrZJri5YpZGM7crC6WqZ0HdeZWIyGFUrSqvggiyoL+r2xvyA4j3OOG6X/f6VwTfgJhlywIHhCUS3M/IQDaeBQGsuiyM4I7zzFApmN0vEdt6Mppziiwk2iNOvNpmKDYwpaofMlJuYX7j6fWJaRbVUmFOggkTdlLZzd6FyX6p0WBk0OA/i5zvJOnVYO0Z5wsiZsTKo1DFsGQ1V3BDdakm0zwQyGohIJLTA0oPRGkz0+BFITpao2d2OYN6HYHWu1YQZG2WYGbl7YiFpRUVeFnlTbOxZg3zS+SK3FdZCD9CnDwhr2t0xhs2UKR9ZLHbgzu2piDh7P0ihegQYycseGbhuPRiBsCkondxBHp5eJfw4eBjeWGJ8dfkHQfvSaSav72rUTWOt6/ZC0G6WBV7I9U/O9y6FH7Zw5ryj7oGjv0vrvLIvo7mFa77wuK7MxdB52gKJ3hv3nHZzpFVf34WZEV0tEZZyRx9vA0+7SbN27j7f+DIybAK8ftWpBIFcpbgjZzclPY2sPnZYD9QsLGFyg9FqQuLNmIFXMOJSpuIBOllAp83yqeovbxWQTy8ricWjBExKFtTNJB5dEnAq7VtEbwO5iMlSbs+NyG/9eu8+F7sKjWeHt33koRjL39f+N8jKtM8p3nV13r2dFkGJRM088ALPXCYGfN68qDM3Rzl0Wj5VByU1XwR4rBR/gI8tJ1LQrSTp989pAdlOgwQpj/zeVx6zwu41b9vwHtCdeq2uk0+mJ/nF6i3tvaBHaVgnxn3G66ew6SKYFaWk1ksSRb5H/AuhDZ38=""",
+"clay.c" : r"""eJydWVtv3DYWftb8CnayjTW2PL7kzdMYCLKbwtjWBRIHKRAbAkfieLiRSFWkYnvT+e89PCQl6jJO0bx4dG48PJePh8wLLrKiyRn5iSrFar3cXs5etDTF9P/KakDTecHXIxqXQ1LNxX2fVlK9HSnSGqVmJ4ekZn80vGY52ciaKCrytXwEI+TwJFR5Uif6qWJqYAnISlPcAJA3OduQ9NPV9avz2YuolXrgIpcPVrWjOt87gtqyoqAVH5BzcC5zK0SwABeMpL++ubpO374laZrlLCsClnEnrmDPCfxckLT/3cmVX8CwY5QyZyDakQK5bNsSSRp8dBI0y5hSfVNjWuhhnTdVDH/QvfbDbIJvBMYw/fXq+udPr87TFIhRVdP7kpJMliUTOoZKSMgcw/XqfG4sB6ZFVj3FWiZkU8syIVqmiv8fXHKsVCHTkb1UevP+4/XbNzf/CY19Sn/7Lzk9Dygf0qsP/756Hz8uSBw/kpckBco7oCzID6/JaahcftGsrFIfgoIJDPCICCpM5Hwzi0x5mb2Do02mbeLIh5s3N+nNavaCFYr1igUq74FyUxcEitj8rHgeny+wbju5RnAod1tSg+IZLTlYEd3qin2eFfRpuZ3PZkaOZ+Sr5NA0Kq3LOJNCaSgVWpPDVMmmzthiNZTLJGRmQjIhITFnUKardpGQNdvwR93ULDXh61laUzUw40UFLZk1h1s0e0hZXUOrf5tFoYKGdVczCJwm5mcqmnLN6lVfSDVcswFtwwvmFAsI77QiLpmW6t7Q/T6zmleaSwHuRWP/DgV7BI92XSyczMBxmmn+laXO/wmOc9q6iB92BeW3KzUtWlIQgkw2Qu9xrrUwwSsoKONvo4zpjw8LmcEqWcGoaKpFjNRDyIzl99mQ4KdC0tyow1GQrpsN0TUtK2ki7N1uCSkTdF0wEN8BRIEjg3xvGpENo2bqYtU6VwH8oEsLH/BOGyO2R320Chdcc1oAtExx3fbaNI0EsAoxqmAh7afB+AWd/g4Ay2pUcNbp9HCZmZYPey3gGn/ifkIT0tWBI4xKHNtGDVo4MKu2jYYjTXzftCHY4kfCfpMohPaggbxL+wpvvxkpjDvxsLNxQ9aboLstYUOhg/PnTOKO4ukoPadH17Lu+wIIkJDlcrkYJtMNHnuS2QjH90XqJIz7obpnG9tvGi3vmWA11TDcmF2TnGpK1k+oYtb51zdUhs4r1jT7onYD2B23Qdr9Vp/vyGvoCwL/nCFL3/UwyxZyoGcLAVRDJUvcrSbVvH9DzT7d9cdbWTO7W9NRBl7VIKQzVK4bgZgZP9+MyX521+vPCHnAm32zqGV7QZld4OaWfUCeRZY6BjdQOEN03pDYTsjxUHRBXpspxGAVinUOHl8CwpkZ5frjL78sgB0NeLEpmigyO26/o93z7px6d6xMD8HDtSbYUyoe9BferKOPfA/p1m/nZItDR0eGirN9Kb/ChCqeCK51DJHzKExKprcyx+qY8pHYFVeTTO9sKwQVMAKhNqAIPm0kArwEWjwuA3LZlgns1xxJs4n6ZRWAi9Owfe9rjNta2XtsJ362mEWW7GuxPdQftgCJJLZcH3qsK6MI8siBjaGZKNy7w/Gjo4R4qI6iTc1Y7HSCwWfAw0/vkTPd1aCLjfe1GzLaHEyGCdo8hO8xpFksx+A9BwSwCgoeXw7OaD5Kvl3PSfsB1O0inMk6k26cmCgF12bmbhpz/IL0/hS64uYDcnTEbYp6CznXzZ/P/G7pFor6EPjSsRPy0hkOsK2leSjDrOzwvktOzeXDXGpkTWtePJGcK4sP+zBXwd26mMrGdzB3lKx9wfr7gR6HyAvMBgFCr/5mcHbt1Wm0/0bR+/4cQet73AyWziaefzQSF+RHRT5LbBF1dytuxTwhRnLVCf5muRfAA/LJScsg5Fj//vutvtXvG0GkgJzorTsR7dRDgI1aoY6a0LGxGyqxRxgpj8/2wFJFa8VScFbhLAc/ssTt1Wz2awdSvbI+s2VtxINKbmPUmHs/iBkLUKcrz6OZvT9FkRsc8RQzh4dX+nx6ZwDs4PgAj70gDWjr9M4efNaQXcHqneEqYNIUj661LFqb5IicQ+b9Z0LOThftwp27Ztnb0wPy55/GM9jd6bMuqAeusy14jq64AMC9lhyogws8ssF6bEFnYQxevh6PVVYt6uORHUPnH8J0/piTXDJFhISZ5JErvcQqAy6icBSkGT4MCgegYQHuZW8YBM07K7yuGf2CW8rZhjaFvti7bWPZgkk30No6wrbbX0HDK445SOFjMTUwJn1meD0BznyOR6wfOYJZeoEpw4BuXKconQPUGLVo/g6vDXB79o+GXZ9BjGDuNhFFyRugmRfFB14UpKplxkAPsr2VjQ5eHJeuwXbOGbNzGAXOXCkMusvGBQNidIh5IELB7liKRsfGKAK22b6bXH7nHZu6BP7z4LuBKHiAcMkY3HrM6jXTTS3IWAWBqEOg1L4pxxZmAGxzbhoqGb/aJN2rTbLnuWZAD2YXp6wgiUWeYothZe4butoS8w6ZqNs9hYOYiZ7M4rMEr0DSlNzA3mLRn7v92TccuNszsbf8aHgaD+otz853oYWJ0avlORV3mo5O2FVPwl3AW8HwocPL+aN7fJ53MiaNIOLe4BwxeIYDnnsycrw2s951+yhngxOkN4zLeHC1Z4J5uO5Ps1NTibmMTBS6vaPgbS4sofby9sO+m5eD+AmER9wGXIJF7N4uCB3cdkhNuQL0oQJQP2Po93JucTtEfAT8Qor7qXtmQqzUzjceLJLCzaq93blXteFjX2JfNA5lRf9owiFueO/q3smev3pZQ9j/7kmglHlTmCeImWnO9r9JSsrF6DTBY+jOuGGeMBy8dIdPD2B3s78AAFrlyw==""",
+"clay_print_default.c" : r"""eJyFU01P4zAQPSe/YqgU1a5Cuafa3RunistqT4AiEztgKbUje9LVCvHfsccpOGhbTs48z3t+85HSo0DdwdFqCd0g/rWj0wZbbTSy8AGoPLadnQzWEGM/aVQnoLPGI3QvwsEmXRhxUJ6Xr2XBoiT/pO/KgqR7ttpbIZWESiY130DlH8yqhvgiX7yQq2YKv1E4VDKQAvpWlmeq8C8TSvvXfF9JBJRz1iXgXAUJypgfWEbelZ9GH0zyWJArp0brsKVczy5apxzybabDqdMe3dRhSqME2NBBdk9PQmgsh1uhh8mphvoaJHjuqvJNU3lgledwH4JKPsL9NYYjppdFQarXP6nQLI69iOHKWJDKd06PqO2C0ushZwzahPFNhyflvujM6MIXnBZhzktNPfhnytI9sPkiexyufsDdn/2eB/lzOlk6X07n8v5YE52yfM2T9bCPaWeyShLQh74r+XV/ImG3RIiTrXTVBb+JDb9gfbuGBtbb9Tf+aELs//8hmbjZgLF2hM3NcnuTo0vS4ins6kI6DKKG7XZLwkfRDjpcCfc87ij08adkMa4hzaw49nN5HmWYBeE1UXjiKCPZHL6V7yZUhjs=""",
+"clay_print_tap.c" : r"""eJyFU8Fu2zAMPUdfwXoIYBuxgWK3Btuwnotih/U2wFBtORXmSIEkZyiG/ntJylnkNFlOMh+fyMdnSvggg25hb3UH7SBfm53TJjTa6JDjBwTlQ9Pa0YQVUOxHHdQBaK3xAdoX6aCMCSO3yhfir1jkVLJI0PUc4xKIcb8+z35+/wF75by2Bm4//zJZkSRv63rZIbZK9GD+TYgL+v3LGDr7x1yfgQDlnHVT1aP247UL0iOWXF6Lo+Q4wWWFfI3lmXF7sNIHN7Yh0pgAJR+JKmSnbQCqqjpxCwDt9nKj4A6Wnm3jKtXXqHXrN3O6V+i8Dq930Es9fKjGUwN8qMb4nEqewRkq4XNmrwd1jkn4nDloc2B2KZPwBu14Vq4gS3QP+ZTqlG+d3gVappsv8Pj08FCIRVIzIZwKSFLF3Om6rq/9VWto0jx9GLxG9ALirsWQVUeALFcd/+FDq6XHUaGahKHwyIFvkBkbwP7O0IwMD8qlBf+F2E4sWD6Lc2pn3bRzPr8yAf/W/Pzbnsn8BGVZokg62MGE9/8W8hnlzFrgTq7IYG6wl82gMSXdZrfmECvhBYpXMK1vP8nw+NBHfMjZPZoE+HkDvL/7UwK3oBJFrKlMl0/hm3gHeFWmnA==""",
"clay_sandbox.c" : r"""eJyNVV1P20AQfLZ/xRIkYpNATItaVSkPlaBVVEoiEgQSRJaxz+SEfY7uLmkD4r931+fEHwRahBST3Zudmb0xSgeahxDOAgl+mAQrfx7o2e2x9+XTtG/bypS50DZX/jJIeOTrdJ43OWEmlDZH9+kL1362rfHk28SfgNJ42uIxOAThULkLe0q7sHMCnmtblmR6IQV4676dsT8Ynw4u8cCh0n6aRcxt9hXPThCGTKkC9dof/nThhGD79kuNc8xFlW/O9H4Rx0x2QfEn5mtImHgw1Hd5LCIWg389uPj4wbYKHKOy6F4G0g+zhdBwAsf9Ro/BZ2KJRkl1O8UeNMRqTX6NUFerC/SUf5yZz6vx2eXocvh9cH7WssF6QYlgFZM46Y0zCQ5HHK8PHL6W4/vQ6XA3h2/MxuYHpvHB2RDhUzTGMibjl2QqndJcLBhNySuv10utZgTKlCKcr5y1d1jqrp0j6MqSLOvFxl/b6u3DIAY9Y9TNZSZShrZFGVOijX4GKwjESs+4eOiClivQGSwUgx7Oh/2e/QapFtVbBa8mLVOsMasQQ1K7LFHMQP9gesLS+YhAndPr4eWpa451wcA1Lt8uExGPja7JjCtQK6VZuhGU8EeGAmpaSHy4kDIXziULdYbFd8Qdvqns8D1Z6z8PjqoBWGY8gjzSC6ECEd1nfxz6Lo8pEajk3ZtSgNp3XrtUjVcDI1FNRDhDFcgSaVYMiZUv0wpYM4XoJ08iv6BglG54VG4vFXwd8CRPTivHI2tu8p8WpW0T2fVLox7wkoOJdxZXabkYoOqbh9yyLQTDaeg3PtRFNNU/A65eZDLFpT2xnC4tejQcD24Ak/o7kBGoJFAzpvIlV6JsvYoyiShD3NwHL/Zxl+/DsholaPfam6htFtHAIGUHcDSlNy72m0H1eqdTgtE9Wl+7sgs6xLRbLmebszgGm7ZYRozSR4zJ3Ff/3E7jH4NZj0Gga1c97n32vK0HKgHHUzS4xhM9vbg6P391qDCwTFX9AucI/x8h2Nvbdue33z9CMbmqEt3qRY3eX120XBI=""",
"clay_fixtures.c" : r"""eJyFUV1LwzAUfW5+xZU9rLUVJ4ggZQ9DFAUfRCZMRglZmrBAl5Qkk03xv9v0a82U+Zabc+45595rLLGCAlXSWKBrouEccbGzW81wSew6HCIrYljicTuqJBsWoS8UmFbPobXA8npye5OlFSI+GbaglbK4YDJFKOjeMAVjdfUInUPkyFZLWu7DWiKBxtgpKN78RZETEByactlLXcBVBmdTGF+OIxQEPhrHGdRQ1zzMv5xUYN84ROLY8b1MEPeTJEdsV3tRq0wdt06tWcWVzXpS9I3QSPCccbh7nr3jh6fF/O31Hr/M5o9ouGpa4NYlPHmBVt074i/lBLy+OsWHEjkcXLAhMl+p3Wk3bjBV1VIG6TxOApgWZN8s4k8bWjAit+W/NnoTejMddI+GqW1GTOaCox8pOffr""",
"clay_fs.c" : r"""eJylVdtu20YQfSa/YkAD8TKWY8dJX6L0wXDEVqgsBhINN7UFhiGX1qIkl9hd+dLG/57ZCynJUWEkfZE0s7NnZufMGe2xsqAlpJfj6ZsT399DgzUUojhKo8npb3Mg+ud8PBlNE/hq/NP4LJ5G49n5aTKOp71zNJvFs4vx06DzPz6MZ6HvS5UplkO+zAS89EtWUd7KtM3UkuS8kcqdGE/o/+t71tYm/ArTi8lk6HuS/UNTBRVtbtRyAGzo+x4rgaQ2zMaFvucJqlaicdd8z15AHKkE/rbxIQI6+DqrKp4TF3YAJ2GH/AxwTeu8fTBRA0jtl0Xp0K+sucAsx9suzPPauX2v5AIIMxYweO9AhnBwwELAbvTFXLGFrmf/aF+X4/Uu2L++3scEjwjmitRnQ/+x7/0tZ0XXecIaBTUv6AC22i/5SuRPnQWVynAy/z3CSYg/zpPZxVkCJQLp4m2YvYqVbJHrEHU7bJgG+y7IZNBQf1HBz2nNxQN5oeEHoDnnJdlOHYa2aa18dRetmlxziI8ZOl8bCV5ruk3u3ptw9OlUnaeMquxGorOfd/OcKs2kpEKlBFuMibHUuKUCm8gbW1aoOTge4HFwyZqC30l4EgdlhmYR+J4tVVBK1q0wpnv0U4JkKmqygxTDQEdfFKcfRpNRMsKx6zgzM7oLL+c4oz9A80aSs/jjp40U6bpmA46t0vgVzZpVS7TLApg3lOwe55A6ivMqe3AKCV4GoQXZo5WkXbk4kr5c0qpK+UoRW5SrMBM3t1cLg60HV19YSS0nVuA+wE/dY/zSg8XF32StX/S9h2OrobIVeLskUhVUCM2eF8wfpKI1oM3FO/hsb3+GHDeCo/DVdRNozjx6zxQ5fB06lXXwehIsPr2n+S0xtR4vBqboLvguYwqD9YUBvLD1D/DesFfr5ejPcTJPTpOLObHn/4PLnkprmpJ+WQy3pbpeqNZOcenovvVCxm1ZIK0bEl4Hrpdpf2pbYs2rjchDs+f6nfVfAXYRuu6hGRx9Yc1R3gZD5zVBweGsd5wsNjVuXG+0y81O6KRuDt4u+r8Ro/B6JRWOo5RG5OuxM6QZYUeGfVAcdM9B6b3lRlpqr8ya4gu/363wZ0W9oekNjt4udvVA1N/1oNxuQvfiHc342TdbTYNa0u2XPiN9I/NV464Qs/e1a8PxiLJvClb63wD3Q6FA""",
-"clay.h" : r"""eJy9Vctu2zAQPEdfsbV6sAQhTq9pGsAIbMSAERStg7YngqZWEVGZVEmqcVH030NSfkm2qqYHn0wtOTuzu0M65JlIMQNC7ubjb2Qx+bwg94QEoQ1ygUfxIOSCFVWKcKNNWvDlZX4bBD8lT4EV9BchVGtUZhhccGGASZFyw6VIggu71jaSUwVxxgtM6iOFZWntolJStWIpaqZ4ucnlgDqXVZESupTKRO93GohGQ1iBVFTl0MeG8eYzqr/jKIF6IUv6o0IL3mIz3YC6tCHPXH98F6azr4vHTxPycby4Dw7VOShfm0rhsFmmjxFBVw2WTVhTkS7l+jWQrbq/QEK0Pc+CYBTHAcQw9vOwbYMVZUpqeOYmB1yXBWfcgO81rFBr+oT2/Gg3ecu6qrQhpZ0oGVqASsBNIWoO2u9EcPsBrhLrlulsPiHEreazB78aTCvBvABGiwIyamefXsMAwn3OBN5FR8TuZD/xTSfvZF0iM5hC1hBgpNfQo6Am6ad/01235Ve2r46YaxDSgFEVnuLdzuouR/b9P+bEHO5Mg7qKjpnPPKlTEs4wqKuo51IJ+Y/XaSOpecPqYAIPj/P56cvQgtVd74Rtyt9hto5uArqt11fN3nR7jkMjdgrbe6YN7KnIH2pjOuqZSsWcoWxG+zaOnqkSXDy1a/AiTnimyykLtK9ufTEuB6cfjg3Ta7J+qSGQVsr9GEeCa2SVc9j14IT/vI4VmlymdtOSKOrOal/f29+4NqgEOdz5E2z/GF4ABeagMA=="""
+"clay.h" : r"""eJy9Vctu2zAQPEdfwVo9WIIQp9c0DWAENmLACIrWQdsTQZOriKhMqiTVqCj67yUp+aGH46YHn0wtdzizu0M65KlgkCKM75bTb3g1+7zC9xgHoQ1yAb14EHJB85IButGG5Xx9md0GwU/JGaI5+YUx0RqUGQcXXBhEpWDccCmS4MKutY1kRKE45TkkdUpuWTq7oJRUnRgDTRUvmrMcUGeyzBkma6lM9H6nAWswmOZARFmMfWwcN59R/R1HCaoXsiA/SrDgLTbVLag7NuSp64/vwnzxdfX4aYY/Tlf3waE6B+WVKRWM22X6GBZk02JpwpoItpbVayBbdS9AQrA9T4NgEscBitHUz8O2DW0IVVKjZ24yBFWRc8oN8r1GG9CaPIHNn+wmb1k3pTa4sBPFYwtQCXJTiNqD9jsRuv2ArhLrlvliOcPYrZaLB78azUtBvQBK8hylxM6eXaMRCvdnJuhd1CN2maeJb47yzqoCqAGG0pYAI72GEwpqktP0b47XbfmV7asj5hoJaZBRJQzxbmd1lwH9/h9zog53pkFdRX3mM09qSMIZBnUVnbhUQv7jdWokDd2wh8flcvgqdECHPe+BmtJ3iLab6/TjpjtVx95ue4a+BXui9l7pwl6sxad0EYOVzKWizkT2NPseTp6JElw8ddV7AQM+OeaOFdiXtr4Ml6Phx6Jhes2pX2oIYqVyP8aRQAW0dK66Hg14zuvYgMkks5uWRBGXq319b39DZUAJfLjzJ9j+GfwFGCyeSg=="""
}
if __name__ == '__main__':
main()
diff --git a/tests-clay/clay.h b/tests-clay/clay.h
index bc4267b66..db3a475b2 100644
--- a/tests-clay/clay.h
+++ b/tests-clay/clay.h
@@ -37,16 +37,16 @@ void cl_fixture_cleanup(const char *fixture_name);
/**
* Assertion macros with no error message
*/
-#define cl_must_pass(expr) cl_must_pass_((expr), NULL)
-#define cl_must_fail(expr) cl_must_fail_((expr), NULL)
-#define cl_assert(expr) cl_assert_((expr), NULL)
+#define cl_must_pass(expr) cl_must_pass_(expr, NULL)
+#define cl_must_fail(expr) cl_must_fail_(expr, NULL)
+#define cl_assert(expr) cl_assert_(expr, NULL)
/**
* Check macros with no error message
*/
-#define cl_check_pass(expr) cl_check_pass_((expr), NULL)
-#define cl_check_fail(expr) cl_check_fail_((expr), NULL)
-#define cl_check(expr) cl_check_((expr), NULL)
+#define cl_check_pass(expr) cl_check_pass_(expr, NULL)
+#define cl_check_fail(expr) cl_check_fail_(expr, NULL)
+#define cl_check(expr) cl_check_(expr, NULL)
/**
* Forced failure/warning
@@ -57,10 +57,13 @@ void cl_fixture_cleanup(const char *fixture_name);
/**
* Test method declarations
*/
+extern void test_config_stress__cleanup(void);
+extern void test_config_stress__dont_break_on_invalid_input(void);
+extern void test_config_stress__initialize(void);
extern void test_core_dirent__dont_traverse_dot(void);
-extern void test_core_dirent__traverse_subfolder(void);
-extern void test_core_dirent__traverse_slash_terminated_folder(void);
extern void test_core_dirent__dont_traverse_empty_folders(void);
+extern void test_core_dirent__traverse_slash_terminated_folder(void);
+extern void test_core_dirent__traverse_subfolder(void);
extern void test_core_dirent__traverse_weird_filenames(void);
extern void test_core_filebuf__0(void);
extern void test_core_filebuf__1(void);
@@ -72,9 +75,9 @@ extern void test_core_path__1(void);
extern void test_core_path__2(void);
extern void test_core_path__5(void);
extern void test_core_path__6(void);
-extern void test_core_rmdir__initialize(void);
extern void test_core_rmdir__delete_recursive(void);
extern void test_core_rmdir__fail_to_delete_non_empty_dir(void);
+extern void test_core_rmdir__initialize(void);
extern void test_core_string__0(void);
extern void test_core_string__1(void);
extern void test_core_strtol__int32(void);
@@ -82,21 +85,52 @@ extern void test_core_strtol__int64(void);
extern void test_core_vector__0(void);
extern void test_core_vector__1(void);
extern void test_core_vector__2(void);
-extern void test_network_remotes__initialize(void);
+extern void test_index_rename__single_file(void);
extern void test_network_remotes__cleanup(void);
+extern void test_network_remotes__fnmatch(void);
+extern void test_network_remotes__initialize(void);
extern void test_network_remotes__parsing(void);
extern void test_network_remotes__refspec_parsing(void);
-extern void test_network_remotes__fnmatch(void);
extern void test_network_remotes__transform(void);
-extern void test_object_tree_frompath__initialize(void);
+extern void test_object_raw_chars__build_valid_oid_from_raw_bytes(void);
+extern void test_object_raw_chars__find_invalid_chars_in_oid(void);
+extern void test_object_raw_compare__compare_allocfmt_oids(void);
+extern void test_object_raw_compare__compare_fmt_oids(void);
+extern void test_object_raw_compare__compare_pathfmt_oids(void);
+extern void test_object_raw_compare__succeed_on_copy_oid(void);
+extern void test_object_raw_compare__succeed_on_oid_comparison_equal(void);
+extern void test_object_raw_compare__succeed_on_oid_comparison_greater(void);
+extern void test_object_raw_compare__succeed_on_oid_comparison_lesser(void);
+extern void test_object_raw_convert__succeed_on_oid_to_string_conversion(void);
+extern void test_object_raw_convert__succeed_on_oid_to_string_conversion_big(void);
+extern void test_object_raw_fromstr__fail_on_invalid_oid_string(void);
+extern void test_object_raw_fromstr__succeed_on_valid_oid_string(void);
+extern void test_object_raw_hash__hash_buffer_in_single_call(void);
+extern void test_object_raw_hash__hash_by_blocks(void);
+extern void test_object_raw_hash__hash_commit_object(void);
+extern void test_object_raw_hash__hash_junk_data(void);
+extern void test_object_raw_hash__hash_multi_byte_object(void);
+extern void test_object_raw_hash__hash_one_byte_object(void);
+extern void test_object_raw_hash__hash_tag_object(void);
+extern void test_object_raw_hash__hash_tree_object(void);
+extern void test_object_raw_hash__hash_two_byte_object(void);
+extern void test_object_raw_hash__hash_vector(void);
+extern void test_object_raw_hash__hash_zero_length_object(void);
+extern void test_object_raw_short__oid_shortener_no_duplicates(void);
+extern void test_object_raw_short__oid_shortener_stresstest_git_oid_shorten(void);
+extern void test_object_raw_size__validate_oid_size(void);
+extern void test_object_raw_type2string__check_type_is_loose(void);
+extern void test_object_raw_type2string__convert_string_to_type(void);
+extern void test_object_raw_type2string__convert_type_to_string(void);
extern void test_object_tree_frompath__cleanup(void);
-extern void test_object_tree_frompath__retrieve_tree_from_path_to_treeentry(void);
-extern void test_object_tree_frompath__fail_when_processing_an_unknown_tree_segment(void);
extern void test_object_tree_frompath__fail_when_processing_an_invalid_path(void);
+extern void test_object_tree_frompath__fail_when_processing_an_unknown_tree_segment(void);
+extern void test_object_tree_frompath__initialize(void);
+extern void test_object_tree_frompath__retrieve_tree_from_path_to_treeentry(void);
extern void test_status_single__hash_single_file(void);
-extern void test_status_worktree__initialize(void);
extern void test_status_worktree__cleanup(void);
-extern void test_status_worktree__whole_repository(void);
extern void test_status_worktree__empty_repository(void);
+extern void test_status_worktree__initialize(void);
+extern void test_status_worktree__whole_repository(void);
#endif
diff --git a/tests-clay/clay_libgit2.h b/tests-clay/clay_libgit2.h
index ab3cf67ec..a5208962e 100644
--- a/tests-clay/clay_libgit2.h
+++ b/tests-clay/clay_libgit2.h
@@ -23,6 +23,6 @@
* just for consistency. Use with `git_` library
* calls that are supposed to fail!
*/
-#define cl_git_fail(expr) cl_must_fail((expr))
+#define cl_git_fail(expr) cl_must_fail(expr)
#endif
diff --git a/tests-clay/clay_main.c b/tests-clay/clay_main.c
index da90872ce..4ad6fc467 100644
--- a/tests-clay/clay_main.c
+++ b/tests-clay/clay_main.c
@@ -4,13 +4,12 @@
#include <stdio.h>
#include <string.h>
#include <math.h>
+#include <stdarg.h>
/* required for sandboxing */
#include <sys/types.h>
#include <sys/stat.h>
-#define clay_print(...) printf(__VA_ARGS__)
-
#ifdef _WIN32
# include <windows.h>
# include <io.h>
@@ -82,7 +81,6 @@ static struct {
struct clay_func {
const char *name;
void (*ptr)(void);
- size_t suite_n;
};
struct clay_suite {
@@ -93,10 +91,268 @@ struct clay_suite {
size_t test_count;
};
+/* From clay_print_*.c */
+static void clay_print_init(int test_count, int suite_count, const char *suite_names);
+static void clay_print_shutdown(int test_count, int suite_count, int error_count);
+static void clay_print_error(int num, const struct clay_error *error);
+static void clay_print_ontest(const char *test_name, int test_number, int failed);
+static void clay_print_onsuite(const char *suite_name);
+static void clay_print_onabort(const char *msg, ...);
+
/* From clay_sandbox.c */
static void clay_unsandbox(void);
static int clay_sandbox(void);
+/* Autogenerated test data by clay */
+static const struct clay_func _clay_cb_config_stress[] = {
+ {"dont_break_on_invalid_input", &test_config_stress__dont_break_on_invalid_input}
+};
+static const struct clay_func _clay_cb_core_dirent[] = {
+ {"dont_traverse_dot", &test_core_dirent__dont_traverse_dot},
+ {"dont_traverse_empty_folders", &test_core_dirent__dont_traverse_empty_folders},
+ {"traverse_slash_terminated_folder", &test_core_dirent__traverse_slash_terminated_folder},
+ {"traverse_subfolder", &test_core_dirent__traverse_subfolder},
+ {"traverse_weird_filenames", &test_core_dirent__traverse_weird_filenames}
+};
+static const struct clay_func _clay_cb_core_filebuf[] = {
+ {"0", &test_core_filebuf__0},
+ {"1", &test_core_filebuf__1},
+ {"2", &test_core_filebuf__2}
+};
+static const struct clay_func _clay_cb_core_oid[] = {
+ {"streq", &test_core_oid__streq}
+};
+static const struct clay_func _clay_cb_core_path[] = {
+ {"0", &test_core_path__0},
+ {"1", &test_core_path__1},
+ {"2", &test_core_path__2},
+ {"5", &test_core_path__5},
+ {"6", &test_core_path__6}
+};
+static const struct clay_func _clay_cb_core_rmdir[] = {
+ {"delete_recursive", &test_core_rmdir__delete_recursive},
+ {"fail_to_delete_non_empty_dir", &test_core_rmdir__fail_to_delete_non_empty_dir}
+};
+static const struct clay_func _clay_cb_core_string[] = {
+ {"0", &test_core_string__0},
+ {"1", &test_core_string__1}
+};
+static const struct clay_func _clay_cb_core_strtol[] = {
+ {"int32", &test_core_strtol__int32},
+ {"int64", &test_core_strtol__int64}
+};
+static const struct clay_func _clay_cb_core_vector[] = {
+ {"0", &test_core_vector__0},
+ {"1", &test_core_vector__1},
+ {"2", &test_core_vector__2}
+};
+static const struct clay_func _clay_cb_index_rename[] = {
+ {"single_file", &test_index_rename__single_file}
+};
+static const struct clay_func _clay_cb_network_remotes[] = {
+ {"fnmatch", &test_network_remotes__fnmatch},
+ {"parsing", &test_network_remotes__parsing},
+ {"refspec_parsing", &test_network_remotes__refspec_parsing},
+ {"transform", &test_network_remotes__transform}
+};
+static const struct clay_func _clay_cb_object_raw_chars[] = {
+ {"build_valid_oid_from_raw_bytes", &test_object_raw_chars__build_valid_oid_from_raw_bytes},
+ {"find_invalid_chars_in_oid", &test_object_raw_chars__find_invalid_chars_in_oid}
+};
+static const struct clay_func _clay_cb_object_raw_compare[] = {
+ {"compare_allocfmt_oids", &test_object_raw_compare__compare_allocfmt_oids},
+ {"compare_fmt_oids", &test_object_raw_compare__compare_fmt_oids},
+ {"compare_pathfmt_oids", &test_object_raw_compare__compare_pathfmt_oids},
+ {"succeed_on_copy_oid", &test_object_raw_compare__succeed_on_copy_oid},
+ {"succeed_on_oid_comparison_equal", &test_object_raw_compare__succeed_on_oid_comparison_equal},
+ {"succeed_on_oid_comparison_greater", &test_object_raw_compare__succeed_on_oid_comparison_greater},
+ {"succeed_on_oid_comparison_lesser", &test_object_raw_compare__succeed_on_oid_comparison_lesser}
+};
+static const struct clay_func _clay_cb_object_raw_convert[] = {
+ {"succeed_on_oid_to_string_conversion", &test_object_raw_convert__succeed_on_oid_to_string_conversion},
+ {"succeed_on_oid_to_string_conversion_big", &test_object_raw_convert__succeed_on_oid_to_string_conversion_big}
+};
+static const struct clay_func _clay_cb_object_raw_fromstr[] = {
+ {"fail_on_invalid_oid_string", &test_object_raw_fromstr__fail_on_invalid_oid_string},
+ {"succeed_on_valid_oid_string", &test_object_raw_fromstr__succeed_on_valid_oid_string}
+};
+static const struct clay_func _clay_cb_object_raw_hash[] = {
+ {"hash_buffer_in_single_call", &test_object_raw_hash__hash_buffer_in_single_call},
+ {"hash_by_blocks", &test_object_raw_hash__hash_by_blocks},
+ {"hash_commit_object", &test_object_raw_hash__hash_commit_object},
+ {"hash_junk_data", &test_object_raw_hash__hash_junk_data},
+ {"hash_multi_byte_object", &test_object_raw_hash__hash_multi_byte_object},
+ {"hash_one_byte_object", &test_object_raw_hash__hash_one_byte_object},
+ {"hash_tag_object", &test_object_raw_hash__hash_tag_object},
+ {"hash_tree_object", &test_object_raw_hash__hash_tree_object},
+ {"hash_two_byte_object", &test_object_raw_hash__hash_two_byte_object},
+ {"hash_vector", &test_object_raw_hash__hash_vector},
+ {"hash_zero_length_object", &test_object_raw_hash__hash_zero_length_object}
+};
+static const struct clay_func _clay_cb_object_raw_short[] = {
+ {"oid_shortener_no_duplicates", &test_object_raw_short__oid_shortener_no_duplicates},
+ {"oid_shortener_stresstest_git_oid_shorten", &test_object_raw_short__oid_shortener_stresstest_git_oid_shorten}
+};
+static const struct clay_func _clay_cb_object_raw_size[] = {
+ {"validate_oid_size", &test_object_raw_size__validate_oid_size}
+};
+static const struct clay_func _clay_cb_object_raw_type2string[] = {
+ {"check_type_is_loose", &test_object_raw_type2string__check_type_is_loose},
+ {"convert_string_to_type", &test_object_raw_type2string__convert_string_to_type},
+ {"convert_type_to_string", &test_object_raw_type2string__convert_type_to_string}
+};
+static const struct clay_func _clay_cb_object_tree_frompath[] = {
+ {"fail_when_processing_an_invalid_path", &test_object_tree_frompath__fail_when_processing_an_invalid_path},
+ {"fail_when_processing_an_unknown_tree_segment", &test_object_tree_frompath__fail_when_processing_an_unknown_tree_segment},
+ {"retrieve_tree_from_path_to_treeentry", &test_object_tree_frompath__retrieve_tree_from_path_to_treeentry}
+};
+static const struct clay_func _clay_cb_status_single[] = {
+ {"hash_single_file", &test_status_single__hash_single_file}
+};
+static const struct clay_func _clay_cb_status_worktree[] = {
+ {"empty_repository", &test_status_worktree__empty_repository},
+ {"whole_repository", &test_status_worktree__whole_repository}
+};
+
+static const struct clay_suite _clay_suites[] = {
+ {
+ "config::stress",
+ {"initialize", &test_config_stress__initialize},
+ {"cleanup", &test_config_stress__cleanup},
+ _clay_cb_config_stress, 1
+ },
+ {
+ "core::dirent",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_core_dirent, 5
+ },
+ {
+ "core::filebuf",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_core_filebuf, 3
+ },
+ {
+ "core::oid",
+ {"initialize", &test_core_oid__initialize},
+ {NULL, NULL},
+ _clay_cb_core_oid, 1
+ },
+ {
+ "core::path",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_core_path, 5
+ },
+ {
+ "core::rmdir",
+ {"initialize", &test_core_rmdir__initialize},
+ {NULL, NULL},
+ _clay_cb_core_rmdir, 2
+ },
+ {
+ "core::string",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_core_string, 2
+ },
+ {
+ "core::strtol",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_core_strtol, 2
+ },
+ {
+ "core::vector",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_core_vector, 3
+ },
+ {
+ "index::rename",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_index_rename, 1
+ },
+ {
+ "network::remotes",
+ {"initialize", &test_network_remotes__initialize},
+ {"cleanup", &test_network_remotes__cleanup},
+ _clay_cb_network_remotes, 4
+ },
+ {
+ "object::raw::chars",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_object_raw_chars, 2
+ },
+ {
+ "object::raw::compare",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_object_raw_compare, 7
+ },
+ {
+ "object::raw::convert",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_object_raw_convert, 2
+ },
+ {
+ "object::raw::fromstr",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_object_raw_fromstr, 2
+ },
+ {
+ "object::raw::hash",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_object_raw_hash, 11
+ },
+ {
+ "object::raw::short",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_object_raw_short, 2
+ },
+ {
+ "object::raw::size",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_object_raw_size, 1
+ },
+ {
+ "object::raw::type2string",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_object_raw_type2string, 3
+ },
+ {
+ "object::tree::frompath",
+ {"initialize", &test_object_tree_frompath__initialize},
+ {"cleanup", &test_object_tree_frompath__cleanup},
+ _clay_cb_object_tree_frompath, 3
+ },
+ {
+ "status::single",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_status_single, 1
+ },
+ {
+ "status::worktree",
+ {"initialize", &test_status_worktree__initialize},
+ {"cleanup", &test_status_worktree__cleanup},
+ _clay_cb_status_worktree, 2
+ }
+};
+
+static size_t _clay_suite_count = 22;
+static size_t _clay_callback_count = 65;
+
+/* Core test functions */
static void
clay_run_test(
const struct clay_func *test,
@@ -128,28 +384,11 @@ clay_run_test(
_clay.local_cleanup = NULL;
_clay.local_cleanup_payload = NULL;
- clay_print("%c", (_clay.suite_errors > error_st) ? 'F' : '.');
-}
-
-static void
-clay_print_error(int num, const struct clay_error *error)
-{
- clay_print(" %d) Failure:\n", num);
-
- clay_print("%s::%s (%s) [%s:%d] [-t%d]\n",
- error->suite,
- error->test,
- "no description",
- error->file,
- error->line_number,
- error->test_number);
-
- clay_print(" %s\n", error->error_msg);
-
- if (error->description != NULL)
- clay_print(" %s\n", error->description);
-
- clay_print("\n");
+ clay_print_ontest(
+ test->name,
+ _clay.test_count,
+ (_clay.suite_errors > error_st)
+ );
}
static void
@@ -166,6 +405,8 @@ clay_report_errors(void)
free(error);
error = next;
}
+
+ _clay.errors = _clay.last_error = NULL;
}
static void
@@ -174,6 +415,8 @@ clay_run_suite(const struct clay_suite *suite)
const struct clay_func *test = suite->tests;
size_t i;
+ clay_print_onsuite(suite->name);
+
_clay.active_suite = suite->name;
_clay.suite_errors = 0;
@@ -183,6 +426,7 @@ clay_run_suite(const struct clay_suite *suite)
}
}
+#if 0 /* temporarily disabled */
static void
clay_run_single(const struct clay_func *test,
const struct clay_suite *suite)
@@ -193,24 +437,20 @@ clay_run_single(const struct clay_func *test,
clay_run_test(test, &suite->initialize, &suite->cleanup);
}
+#endif
static void
clay_usage(const char *arg)
{
printf("Usage: %s [options]\n\n", arg);
printf("Options:\n");
- printf(" -tXX\t\tRun only the test number XX\n");
+// printf(" -tXX\t\tRun only the test number XX\n");
printf(" -sXX\t\tRun only the suite number XX\n");
exit(-1);
}
static void
-clay_parse_args(
- int argc, char **argv,
- const struct clay_func *callbacks,
- size_t cb_count,
- const struct clay_suite *suites,
- size_t suite_count)
+clay_parse_args(int argc, char **argv)
{
int i;
@@ -229,27 +469,13 @@ clay_parse_args(
clay_usage(argv[0]);
switch (action) {
- case 't':
- if ((size_t)num >= cb_count) {
- fprintf(stderr, "Test number %d does not exist.\n", num);
- exit(-1);
- }
-
- clay_print("Started (%s::%s)\n",
- suites[callbacks[num].suite_n].name,
- callbacks[num].name);
-
- clay_run_single(&callbacks[num], &suites[callbacks[num].suite_n]);
- break;
-
case 's':
- if ((size_t)num >= suite_count) {
- fprintf(stderr, "Suite number %d does not exist.\n", num);
+ if ((size_t)num >= _clay_suite_count) {
+ clay_print_onabort("Suite number %d does not exist.\n", num);
exit(-1);
}
- clay_print("Started (%s::*)\n", suites[num].name);
- clay_run_suite(&suites[num]);
+ clay_run_suite(&_clay_suites[num]);
break;
default:
@@ -259,15 +485,13 @@ clay_parse_args(
}
static int
-clay_test(
- int argc, char **argv,
- const char *suites_str,
- const struct clay_func *callbacks,
- size_t cb_count,
- const struct clay_suite *suites,
- size_t suite_count)
+clay_test(int argc, char **argv)
{
- clay_print("Loaded %d suites: %s\n", (int)suite_count, suites_str);
+ clay_print_init(
+ (int)_clay_callback_count,
+ (int)_clay_suite_count,
+ ""
+ );
if (clay_sandbox() < 0) {
fprintf(stderr,
@@ -276,21 +500,18 @@ clay_test(
}
if (argc > 1) {
- clay_parse_args(argc, argv,
- callbacks, cb_count, suites, suite_count);
-
+ clay_parse_args(argc, argv);
} else {
size_t i;
- clay_print("Started\n");
-
- for (i = 0; i < suite_count; ++i) {
- const struct clay_suite *s = &suites[i];
- clay_run_suite(s);
- }
+ for (i = 0; i < _clay_suite_count; ++i)
+ clay_run_suite(&_clay_suites[i]);
}
- clay_print("\n\n");
- clay_report_errors();
+ clay_print_shutdown(
+ (int)_clay_callback_count,
+ (int)_clay_suite_count,
+ _clay.total_errors
+ );
clay_unsandbox();
return _clay.total_errors;
@@ -335,7 +556,7 @@ clay__assert(
if (should_abort) {
if (!_clay.trampoline_enabled) {
- fprintf(stderr,
+ clay_print_onabort(
"Fatal error: a cleanup method raised an exception.");
exit(-1);
}
@@ -659,124 +880,68 @@ cl_fs_cleanup(void)
#endif
-static const struct clay_func _all_callbacks[] = {
- {"dont_traverse_dot", &test_core_dirent__dont_traverse_dot, 0},
- {"traverse_subfolder", &test_core_dirent__traverse_subfolder, 0},
- {"traverse_slash_terminated_folder", &test_core_dirent__traverse_slash_terminated_folder, 0},
- {"dont_traverse_empty_folders", &test_core_dirent__dont_traverse_empty_folders, 0},
- {"traverse_weird_filenames", &test_core_dirent__traverse_weird_filenames, 0},
- {"0", &test_core_filebuf__0, 1},
- {"1", &test_core_filebuf__1, 1},
- {"2", &test_core_filebuf__2, 1},
- {"streq", &test_core_oid__streq, 2},
- {"0", &test_core_path__0, 3},
- {"1", &test_core_path__1, 3},
- {"2", &test_core_path__2, 3},
- {"5", &test_core_path__5, 3},
- {"6", &test_core_path__6, 3},
- {"delete_recursive", &test_core_rmdir__delete_recursive, 4},
- {"fail_to_delete_non_empty_dir", &test_core_rmdir__fail_to_delete_non_empty_dir, 4},
- {"0", &test_core_string__0, 5},
- {"1", &test_core_string__1, 5},
- {"int32", &test_core_strtol__int32, 6},
- {"int64", &test_core_strtol__int64, 6},
- {"0", &test_core_vector__0, 7},
- {"1", &test_core_vector__1, 7},
- {"2", &test_core_vector__2, 7},
- {"parsing", &test_network_remotes__parsing, 8},
- {"refspec_parsing", &test_network_remotes__refspec_parsing, 8},
- {"fnmatch", &test_network_remotes__fnmatch, 8},
- {"transform", &test_network_remotes__transform, 8},
- {"retrieve_tree_from_path_to_treeentry", &test_object_tree_frompath__retrieve_tree_from_path_to_treeentry, 9},
- {"fail_when_processing_an_unknown_tree_segment", &test_object_tree_frompath__fail_when_processing_an_unknown_tree_segment, 9},
- {"fail_when_processing_an_invalid_path", &test_object_tree_frompath__fail_when_processing_an_invalid_path, 9},
- {"hash_single_file", &test_status_single__hash_single_file, 10},
- {"whole_repository", &test_status_worktree__whole_repository, 11},
- {"empty_repository", &test_status_worktree__empty_repository, 11}
-};
+static void clay_print_init(int test_count, int suite_count, const char *suite_names)
+{
+ (void)suite_names;
+ (void)suite_count;
+ printf("TAP version 13\n");
+ printf("1..%d\n", test_count);
+}
-static const struct clay_suite _all_suites[] = {
- {
- "core::dirent",
- {NULL, NULL, 0},
- {NULL, NULL, 0},
- &_all_callbacks[0], 5
- },
- {
- "core::filebuf",
- {NULL, NULL, 0},
- {NULL, NULL, 0},
- &_all_callbacks[5], 3
- },
- {
- "core::oid",
- {"initialize", &test_core_oid__initialize, 2},
- {NULL, NULL, 0},
- &_all_callbacks[8], 1
- },
- {
- "core::path",
- {NULL, NULL, 0},
- {NULL, NULL, 0},
- &_all_callbacks[9], 5
- },
- {
- "core::rmdir",
- {"initialize", &test_core_rmdir__initialize, 4},
- {NULL, NULL, 0},
- &_all_callbacks[14], 2
- },
- {
- "core::string",
- {NULL, NULL, 0},
- {NULL, NULL, 0},
- &_all_callbacks[16], 2
- },
- {
- "core::strtol",
- {NULL, NULL, 0},
- {NULL, NULL, 0},
- &_all_callbacks[18], 2
- },
- {
- "core::vector",
- {NULL, NULL, 0},
- {NULL, NULL, 0},
- &_all_callbacks[20], 3
- },
- {
- "network::remotes",
- {"initialize", &test_network_remotes__initialize, 8},
- {"cleanup", &test_network_remotes__cleanup, 8},
- &_all_callbacks[23], 4
- },
- {
- "object::tree::frompath",
- {"initialize", &test_object_tree_frompath__initialize, 9},
- {"cleanup", &test_object_tree_frompath__cleanup, 9},
- &_all_callbacks[27], 3
- },
- {
- "status::single",
- {NULL, NULL, 0},
- {NULL, NULL, 0},
- &_all_callbacks[30], 1
- },
- {
- "status::worktree",
- {"initialize", &test_status_worktree__initialize, 11},
- {"cleanup", &test_status_worktree__cleanup, 11},
- &_all_callbacks[31], 2
- }
-};
+static void clay_print_shutdown(int test_count, int suite_count, int error_count)
+{
+ (void)test_count;
+ (void)suite_count;
+ (void)error_count;
+
+ printf("\n");
+}
+
+static void clay_print_error(int num, const struct clay_error *error)
+{
+ (void)num;
+
+ printf(" ---\n");
+ printf(" message : %s\n", error->error_msg);
+ printf(" severity: fail\n");
+ printf(" suite : %s\n", error->suite);
+ printf(" test : %s\n", error->test);
+ printf(" file : %s\n", error->file);
+ printf(" line : %d\n", error->line_number);
+
+ if (error->description != NULL)
+ printf(" description: %s\n", error->description);
+
+ printf(" ...\n");
+}
+
+static void clay_print_ontest(const char *test_name, int test_number, int failed)
+{
+ printf("%s %d - %s\n",
+ failed ? "not ok" : "ok",
+ test_number,
+ test_name
+ );
+
+ clay_report_errors();
+}
+
+static void clay_print_onsuite(const char *suite_name)
+{
+ printf("# *** %s ***\n", suite_name);
+}
+
+static void clay_print_onabort(const char *msg, ...)
+{
+ va_list argp;
+ va_start(argp, msg);
+ fprintf(stdout, "Bail out! ");
+ vfprintf(stdout, msg, argp);
+ va_end(argp);
+}
-static const char _suites_str[] = "core::dirent, core::filebuf, core::oid, core::path, core::rmdir, core::string, core::strtol, core::vector, network::remotes, object::tree::frompath, status::single, status::worktree";
int _MAIN_CC main(int argc, char *argv[])
{
- return clay_test(
- argc, argv, _suites_str,
- _all_callbacks, 33,
- _all_suites, 12
- );
+ return clay_test(argc, argv);
}
diff --git a/tests-clay/config/stress.c b/tests-clay/config/stress.c
new file mode 100644
index 000000000..7b81400c1
--- /dev/null
+++ b/tests-clay/config/stress.c
@@ -0,0 +1,41 @@
+#include "clay_libgit2.h"
+
+#include "filebuf.h"
+#include "fileops.h"
+#include "posix.h"
+
+#define TEST_CONFIG "git-test-config"
+
+void test_config_stress__initialize(void)
+{
+ git_filebuf file;
+
+ git_filebuf_open(&file, TEST_CONFIG, 0);
+
+ git_filebuf_printf(&file, "[color]\n\tui = auto\n");
+ git_filebuf_printf(&file, "[core]\n\teditor = \n");
+
+ git_filebuf_commit(&file, 0666);
+}
+
+void test_config_stress__cleanup(void)
+{
+ p_unlink(TEST_CONFIG);
+}
+
+void test_config_stress__dont_break_on_invalid_input(void)
+{
+ const char *editor, *color;
+ struct git_config_file *file;
+ git_config *config;
+
+ cl_git_pass(git_futils_exists(TEST_CONFIG));
+ cl_git_pass(git_config_file__ondisk(&file, TEST_CONFIG));
+ cl_git_pass(git_config_new(&config));
+ cl_git_pass(git_config_add_file(config, file, 0));
+
+ cl_git_pass(git_config_get_string(config, "color.ui", &color));
+ cl_git_pass(git_config_get_string(config, "core.editor", &editor));
+
+ git_config_free(config);
+}
diff --git a/tests-clay/core/dirent.c b/tests-clay/core/dirent.c
index 73f571595..105e8d8f0 100644
--- a/tests-clay/core/dirent.c
+++ b/tests-clay/core/dirent.c
@@ -20,18 +20,18 @@ static void setup(walk_data *d)
{
name_data *n;
- cl_must_pass(p_mkdir(top_dir, 0755));
+ cl_must_pass(p_mkdir(top_dir, 0777));
cl_must_pass(p_chdir(top_dir));
if (strcmp(d->sub, ".") != 0)
- cl_must_pass(p_mkdir(d->sub, 0755));
+ cl_must_pass(p_mkdir(d->sub, 0777));
strcpy(path_buffer, d->sub);
state_loc = d;
for (n = d->names; n->name; n++) {
- git_file fd = p_creat(n->name, 0600);
+ git_file fd = p_creat(n->name, 0666);
cl_assert(fd >= 0);
p_close(fd);
n->count = 0;
diff --git a/tests-clay/core/filebuf.c b/tests-clay/core/filebuf.c
index e00e20497..e1ecb2798 100644
--- a/tests-clay/core/filebuf.c
+++ b/tests-clay/core/filebuf.c
@@ -27,14 +27,14 @@ void test_core_filebuf__1(void)
int fd;
char test[] = "test";
- fd = p_creat(test, 0644);
+ fd = p_creat(test, 0666);
cl_must_pass(fd);
cl_must_pass(p_write(fd, "libgit2 rocks\n", 14));
cl_must_pass(p_close(fd));
cl_git_pass(git_filebuf_open(&file, test, GIT_FILEBUF_APPEND));
cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));
- cl_git_pass(git_filebuf_commit(&file));
+ cl_git_pass(git_filebuf_commit(&file, 0666));
cl_must_pass(p_unlink(test));
}
@@ -51,7 +51,7 @@ void test_core_filebuf__2(void)
cl_git_pass(git_filebuf_open(&file, test, 0));
cl_git_pass(git_filebuf_write(&file, buf, sizeof(buf)));
- cl_git_pass(git_filebuf_commit(&file));
+ cl_git_pass(git_filebuf_commit(&file, 0666));
cl_must_pass(p_unlink(test));
}
diff --git a/tests-clay/core/path.c b/tests-clay/core/path.c
index db8f33d21..c394c7285 100644
--- a/tests-clay/core/path.c
+++ b/tests-clay/core/path.c
@@ -11,7 +11,7 @@ check_dirname(const char *A, const char *B)
cl_assert((dir2 = git_path_dirname(A)) != NULL);
cl_assert(strcmp(dir2, B) == 0);
- free(dir2);
+ git__free(dir2);
}
static void
@@ -24,7 +24,7 @@ check_basename(const char *A, const char *B)
cl_assert((base2 = git_path_basename(A)) != NULL);
cl_assert(strcmp(base2, B) == 0);
- free(base2);
+ git__free(base2);
}
static void
diff --git a/tests-clay/core/rmdir.c b/tests-clay/core/rmdir.c
index aa21c6a3d..20cc8f5f0 100644
--- a/tests-clay/core/rmdir.c
+++ b/tests-clay/core/rmdir.c
@@ -7,22 +7,22 @@ void test_core_rmdir__initialize(void)
{
char path[GIT_PATH_MAX];
- cl_must_pass(p_mkdir(empty_tmp_dir, 0755));
+ cl_must_pass(p_mkdir(empty_tmp_dir, 0777));
git_path_join(path, empty_tmp_dir, "/one");
- cl_must_pass(p_mkdir(path, 0755));
+ cl_must_pass(p_mkdir(path, 0777));
git_path_join(path, empty_tmp_dir, "/one/two_one");
- cl_must_pass(p_mkdir(path, 0755));
+ cl_must_pass(p_mkdir(path, 0777));
git_path_join(path, empty_tmp_dir, "/one/two_two");
- cl_must_pass(p_mkdir(path, 0755));
+ cl_must_pass(p_mkdir(path, 0777));
git_path_join(path, empty_tmp_dir, "/one/two_two/three");
- cl_must_pass(p_mkdir(path, 0755));
+ cl_must_pass(p_mkdir(path, 0777));
git_path_join(path, empty_tmp_dir, "/two");
- cl_must_pass(p_mkdir(path, 0755));
+ cl_must_pass(p_mkdir(path, 0777));
}
/* make sure empty dir can be deleted recusively */
@@ -39,7 +39,7 @@ void test_core_rmdir__fail_to_delete_non_empty_dir(void)
git_path_join(file, empty_tmp_dir, "/two/file.txt");
- fd = p_creat(file, 0755);
+ fd = p_creat(file, 0666);
cl_assert(fd >= 0);
cl_must_pass(p_close(fd));
diff --git a/tests-clay/core/vector.c b/tests-clay/core/vector.c
index 44e6d873d..b8a853c60 100644
--- a/tests-clay/core/vector.c
+++ b/tests-clay/core/vector.c
@@ -59,8 +59,8 @@ void test_core_vector__2(void)
git_vector_free(&x);
- free(ptrs[0]);
- free(ptrs[1]);
+ git__free(ptrs[0]);
+ git__free(ptrs[1]);
}
diff --git a/tests-clay/index/rename.c b/tests-clay/index/rename.c
new file mode 100644
index 000000000..ba72b62f7
--- /dev/null
+++ b/tests-clay/index/rename.c
@@ -0,0 +1,60 @@
+#include "clay_libgit2.h"
+#include "posix.h"
+
+static void file_create(const char *filename, const char *content)
+{
+ int fd;
+
+ fd = p_creat(filename, 0666);
+ cl_assert(fd != 0);
+ cl_git_pass(p_write(fd, content, strlen(content)));
+ cl_git_pass(p_close(fd))
+}
+
+void test_index_rename__single_file(void)
+{
+ git_repository *repo;
+ git_index *index;
+ int position;
+ git_oid expected;
+ git_index_entry *entry;
+
+ p_mkdir("rename", 0700);
+
+ cl_git_pass(git_repository_init(&repo, "./rename", 0));
+ cl_git_pass(git_repository_index(&index, repo));
+
+ cl_assert(git_index_entrycount(index) == 0);
+
+ file_create("./rename/lame.name.txt", "new_file\n");
+
+ /* This should add a new blob to the object database in 'd4/fa8600b4f37d7516bef4816ae2c64dbf029e3a' */
+ cl_git_pass(git_index_add(index, "lame.name.txt", 0));
+ cl_assert(git_index_entrycount(index) == 1);
+
+ cl_git_pass(git_oid_fromstr(&expected, "d4fa8600b4f37d7516bef4816ae2c64dbf029e3a"));
+
+ position = git_index_find(index, "lame.name.txt");
+
+ entry = git_index_get(index, position);
+ cl_assert(git_oid_cmp(&expected, &entry->oid) == 0);
+
+ /* This removes the entry from the index, but not from the object database */
+ cl_git_pass(git_index_remove(index, position));
+ cl_assert(git_index_entrycount(index) == 0);
+
+ p_rename("./rename/lame.name.txt", "./rename/fancy.name.txt");
+
+ cl_git_pass(git_index_add(index, "fancy.name.txt", 0));
+ cl_assert(git_index_entrycount(index) == 1);
+
+ position = git_index_find(index, "fancy.name.txt");
+
+ entry = git_index_get(index, position);
+ cl_assert(git_oid_cmp(&expected, &entry->oid) == 0);
+
+ git_index_free(index);
+ git_repository_free(repo);
+
+ cl_fixture_cleanup("rename");
+}
diff --git a/tests-clay/object/raw/chars.c b/tests-clay/object/raw/chars.c
new file mode 100644
index 000000000..eba352b40
--- /dev/null
+++ b/tests-clay/object/raw/chars.c
@@ -0,0 +1,52 @@
+
+#include "clay_libgit2.h"
+
+#include "odb.h"
+
+static int from_hex(unsigned int i)
+{
+ if (i >= '0' && i <= '9')
+ return i - '0';
+ if (i >= 'a' && i <= 'f')
+ return 10 + (i - 'a');
+ if (i >= 'A' && i <= 'F')
+ return 10 + (i - 'A');
+ return -1;
+}
+
+void test_object_raw_chars__find_invalid_chars_in_oid(void)
+{
+ git_oid out;
+ unsigned char exp[] = {
+ 0x16, 0xa6, 0x77, 0x70, 0xb7,
+ 0xd8, 0xd7, 0x23, 0x17, 0xc4,
+ 0xb7, 0x75, 0x21, 0x3c, 0x23,
+ 0xa8, 0xbd, 0x74, 0xf5, 0xe0,
+ };
+ char in[41] = "16a67770b7d8d72317c4b775213c23a8bd74f5e0";
+ unsigned int i;
+
+ for (i = 0; i < 256; i++) {
+ in[38] = (char)i;
+ if (from_hex(i) >= 0) {
+ exp[19] = (unsigned char)(from_hex(i) << 4);
+ cl_git_pass(git_oid_fromstr(&out, in));
+ cl_assert(memcmp(out.id, exp, sizeof(out.id)) == 0);
+ } else {
+ cl_git_fail(git_oid_fromstr(&out, in));
+ }
+ }
+}
+
+void test_object_raw_chars__build_valid_oid_from_raw_bytes(void)
+{
+ git_oid out;
+ unsigned char exp[] = {
+ 0x16, 0xa6, 0x77, 0x70, 0xb7,
+ 0xd8, 0xd7, 0x23, 0x17, 0xc4,
+ 0xb7, 0x75, 0x21, 0x3c, 0x23,
+ 0xa8, 0xbd, 0x74, 0xf5, 0xe0,
+ };
+ git_oid_fromraw(&out, exp);
+ cl_git_pass(memcmp(out.id, exp, sizeof(out.id)));
+}
diff --git a/tests-clay/object/raw/compare.c b/tests-clay/object/raw/compare.c
new file mode 100644
index 000000000..94b196945
--- /dev/null
+++ b/tests-clay/object/raw/compare.c
@@ -0,0 +1,124 @@
+
+#include "clay_libgit2.h"
+
+#include "odb.h"
+
+void test_object_raw_compare__succeed_on_copy_oid(void)
+{
+ git_oid a, b;
+ unsigned char exp[] = {
+ 0x16, 0xa6, 0x77, 0x70, 0xb7,
+ 0xd8, 0xd7, 0x23, 0x17, 0xc4,
+ 0xb7, 0x75, 0x21, 0x3c, 0x23,
+ 0xa8, 0xbd, 0x74, 0xf5, 0xe0,
+ };
+ memset(&b, 0, sizeof(b));
+ git_oid_fromraw(&a, exp);
+ git_oid_cpy(&b, &a);
+ cl_git_pass(memcmp(a.id, exp, sizeof(a.id)));
+}
+
+void test_object_raw_compare__succeed_on_oid_comparison_lesser(void)
+{
+ git_oid a, b;
+ unsigned char a_in[] = {
+ 0x16, 0xa6, 0x77, 0x70, 0xb7,
+ 0xd8, 0xd7, 0x23, 0x17, 0xc4,
+ 0xb7, 0x75, 0x21, 0x3c, 0x23,
+ 0xa8, 0xbd, 0x74, 0xf5, 0xe0,
+ };
+ unsigned char b_in[] = {
+ 0x16, 0xa6, 0x77, 0x70, 0xb7,
+ 0xd8, 0xd7, 0x23, 0x17, 0xc4,
+ 0xb7, 0x75, 0x21, 0x3c, 0x23,
+ 0xa8, 0xbd, 0x74, 0xf5, 0xf0,
+ };
+ git_oid_fromraw(&a, a_in);
+ git_oid_fromraw(&b, b_in);
+ cl_assert(git_oid_cmp(&a, &b) < 0);
+}
+
+void test_object_raw_compare__succeed_on_oid_comparison_equal(void)
+{
+ git_oid a, b;
+ unsigned char a_in[] = {
+ 0x16, 0xa6, 0x77, 0x70, 0xb7,
+ 0xd8, 0xd7, 0x23, 0x17, 0xc4,
+ 0xb7, 0x75, 0x21, 0x3c, 0x23,
+ 0xa8, 0xbd, 0x74, 0xf5, 0xe0,
+ };
+ git_oid_fromraw(&a, a_in);
+ git_oid_fromraw(&b, a_in);
+ cl_assert(git_oid_cmp(&a, &b) == 0);
+}
+
+void test_object_raw_compare__succeed_on_oid_comparison_greater(void)
+{
+ git_oid a, b;
+ unsigned char a_in[] = {
+ 0x16, 0xa6, 0x77, 0x70, 0xb7,
+ 0xd8, 0xd7, 0x23, 0x17, 0xc4,
+ 0xb7, 0x75, 0x21, 0x3c, 0x23,
+ 0xa8, 0xbd, 0x74, 0xf5, 0xe0,
+ };
+ unsigned char b_in[] = {
+ 0x16, 0xa6, 0x77, 0x70, 0xb7,
+ 0xd8, 0xd7, 0x23, 0x17, 0xc4,
+ 0xb7, 0x75, 0x21, 0x3c, 0x23,
+ 0xa8, 0xbd, 0x74, 0xf5, 0xd0,
+ };
+ git_oid_fromraw(&a, a_in);
+ git_oid_fromraw(&b, b_in);
+ cl_assert(git_oid_cmp(&a, &b) > 0);
+}
+
+void test_object_raw_compare__compare_fmt_oids(void)
+{
+ const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0";
+ git_oid in;
+ char out[GIT_OID_HEXSZ + 1];
+
+ cl_git_pass(git_oid_fromstr(&in, exp));
+
+ /* Format doesn't touch the last byte */
+ out[GIT_OID_HEXSZ] = 'Z';
+ git_oid_fmt(out, &in);
+ cl_assert(out[GIT_OID_HEXSZ] == 'Z');
+
+ /* Format produced the right result */
+ out[GIT_OID_HEXSZ] = '\0';
+ cl_assert(strcmp(exp, out) == 0);
+}
+
+void test_object_raw_compare__compare_allocfmt_oids(void)
+{
+ const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0";
+ git_oid in;
+ char *out;
+
+ cl_git_pass(git_oid_fromstr(&in, exp));
+
+ out = git_oid_allocfmt(&in);
+ cl_assert(out);
+ cl_assert(strcmp(exp, out) == 0);
+ git__free(out);
+}
+
+void test_object_raw_compare__compare_pathfmt_oids(void)
+{
+ const char *exp1 = "16a0123456789abcdef4b775213c23a8bd74f5e0";
+ const char *exp2 = "16/a0123456789abcdef4b775213c23a8bd74f5e0";
+ git_oid in;
+ char out[GIT_OID_HEXSZ + 2];
+
+ cl_git_pass(git_oid_fromstr(&in, exp1));
+
+ /* Format doesn't touch the last byte */
+ out[GIT_OID_HEXSZ + 1] = 'Z';
+ git_oid_pathfmt(out, &in);
+ cl_assert(out[GIT_OID_HEXSZ + 1] == 'Z');
+
+ /* Format produced the right result */
+ out[GIT_OID_HEXSZ + 1] = '\0';
+ cl_assert(strcmp(exp2, out) == 0);
+}
diff --git a/tests-clay/object/raw/convert.c b/tests-clay/object/raw/convert.c
new file mode 100644
index 000000000..f69f5f924
--- /dev/null
+++ b/tests-clay/object/raw/convert.c
@@ -0,0 +1,75 @@
+
+#include "clay_libgit2.h"
+
+#include "odb.h"
+
+void test_object_raw_convert__succeed_on_oid_to_string_conversion(void)
+{
+ const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0";
+ git_oid in;
+ char out[GIT_OID_HEXSZ + 1];
+ char *str;
+ int i;
+
+ cl_git_pass(git_oid_fromstr(&in, exp));
+
+ /* NULL buffer pointer, returns static empty string */
+ str = git_oid_to_string(NULL, sizeof(out), &in);
+ cl_assert(str && *str == '\0' && str != out);
+
+ /* zero buffer size, returns static empty string */
+ str = git_oid_to_string(out, 0, &in);
+ cl_assert(str && *str == '\0' && str != out);
+
+ /* NULL oid pointer, returns static empty string */
+ str = git_oid_to_string(out, sizeof(out), NULL);
+ cl_assert(str && *str == '\0' && str != out);
+
+ /* n == 1, returns out as an empty string */
+ str = git_oid_to_string(out, 1, &in);
+ cl_assert(str && *str == '\0' && str == out);
+
+ for (i = 1; i < GIT_OID_HEXSZ; i++) {
+ out[i+1] = 'Z';
+ str = git_oid_to_string(out, i+1, &in);
+ /* returns out containing c-string */
+ cl_assert(str && str == out);
+ /* must be '\0' terminated */
+ cl_assert(*(str+i) == '\0');
+ /* must not touch bytes past end of string */
+ cl_assert(*(str+(i+1)) == 'Z');
+ /* i == n-1 charaters of string */
+ cl_git_pass(strncmp(exp, out, i));
+ }
+
+ /* returns out as hex formatted c-string */
+ str = git_oid_to_string(out, sizeof(out), &in);
+ cl_assert(str && str == out && *(str+GIT_OID_HEXSZ) == '\0');
+ cl_assert(strcmp(exp, out) == 0);
+}
+
+void test_object_raw_convert__succeed_on_oid_to_string_conversion_big(void)
+{
+ const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0";
+ git_oid in;
+ char big[GIT_OID_HEXSZ + 1 + 3]; /* note + 4 => big buffer */
+ char *str;
+
+ cl_git_pass(git_oid_fromstr(&in, exp));
+
+ /* place some tail material */
+ big[GIT_OID_HEXSZ+0] = 'W'; /* should be '\0' afterwards */
+ big[GIT_OID_HEXSZ+1] = 'X'; /* should remain untouched */
+ big[GIT_OID_HEXSZ+2] = 'Y'; /* ditto */
+ big[GIT_OID_HEXSZ+3] = 'Z'; /* ditto */
+
+ /* returns big as hex formatted c-string */
+ str = git_oid_to_string(big, sizeof(big), &in);
+ cl_assert(str && str == big && *(str+GIT_OID_HEXSZ) == '\0');
+ cl_assert(strcmp(exp, big) == 0);
+
+ /* check tail material is untouched */
+ cl_assert(str && str == big && *(str+GIT_OID_HEXSZ+1) == 'X');
+ cl_assert(str && str == big && *(str+GIT_OID_HEXSZ+2) == 'Y');
+ cl_assert(str && str == big && *(str+GIT_OID_HEXSZ+3) == 'Z');
+}
diff --git a/tests-clay/object/raw/data.h b/tests-clay/object/raw/data.h
new file mode 100644
index 000000000..cf23819f1
--- /dev/null
+++ b/tests-clay/object/raw/data.h
@@ -0,0 +1,323 @@
+
+/*
+ * Raw data
+ */
+static unsigned char commit_data[] = {
+ 0x74, 0x72, 0x65, 0x65, 0x20, 0x64, 0x66, 0x66,
+ 0x32, 0x64, 0x61, 0x39, 0x30, 0x62, 0x32, 0x35,
+ 0x34, 0x65, 0x31, 0x62, 0x65, 0x62, 0x38, 0x38,
+ 0x39, 0x64, 0x31, 0x66, 0x31, 0x66, 0x31, 0x32,
+ 0x38, 0x38, 0x62, 0x65, 0x31, 0x38, 0x30, 0x33,
+ 0x37, 0x38, 0x32, 0x64, 0x66, 0x0a, 0x61, 0x75,
+ 0x74, 0x68, 0x6f, 0x72, 0x20, 0x41, 0x20, 0x55,
+ 0x20, 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61,
+ 0x75, 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x3e, 0x20, 0x31, 0x32, 0x32, 0x37, 0x38,
+ 0x31, 0x34, 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30,
+ 0x30, 0x30, 0x30, 0x0a, 0x63, 0x6f, 0x6d, 0x6d,
+ 0x69, 0x74, 0x74, 0x65, 0x72, 0x20, 0x43, 0x20,
+ 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72,
+ 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
+ 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d,
+ 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e,
+ 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34,
+ 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30,
+ 0x30, 0x0a, 0x0a, 0x41, 0x20, 0x6f, 0x6e, 0x65,
+ 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f,
+ 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x73, 0x75, 0x6d,
+ 0x6d, 0x61, 0x72, 0x79, 0x0a, 0x0a, 0x54, 0x68,
+ 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
+ 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x63, 0x6f,
+ 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67,
+ 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70,
+ 0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67,
+ 0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f,
+ 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d,
+ 0x6d, 0x69, 0x74, 0x2e, 0x0a, 0x0a, 0x53, 0x69,
+ 0x67, 0x6e, 0x65, 0x64, 0x2d, 0x6f, 0x66, 0x2d,
+ 0x62, 0x79, 0x3a, 0x20, 0x41, 0x20, 0x55, 0x20,
+ 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, 0x75,
+ 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, 0x61,
+ 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
+ 0x3e, 0x0a,
+};
+
+
+static unsigned char tree_data[] = {
+ 0x31, 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x6f,
+ 0x6e, 0x65, 0x00, 0x8b, 0x13, 0x78, 0x91, 0x79,
+ 0x1f, 0xe9, 0x69, 0x27, 0xad, 0x78, 0xe6, 0x4b,
+ 0x0a, 0xad, 0x7b, 0xde, 0xd0, 0x8b, 0xdc, 0x31,
+ 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x73, 0x6f,
+ 0x6d, 0x65, 0x00, 0xfd, 0x84, 0x30, 0xbc, 0x86,
+ 0x4c, 0xfc, 0xd5, 0xf1, 0x0e, 0x55, 0x90, 0xf8,
+ 0xa4, 0x47, 0xe0, 0x1b, 0x94, 0x2b, 0xfe, 0x31,
+ 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x74, 0x77,
+ 0x6f, 0x00, 0x78, 0x98, 0x19, 0x22, 0x61, 0x3b,
+ 0x2a, 0xfb, 0x60, 0x25, 0x04, 0x2f, 0xf6, 0xbd,
+ 0x87, 0x8a, 0xc1, 0x99, 0x4e, 0x85, 0x31, 0x30,
+ 0x30, 0x36, 0x34, 0x34, 0x20, 0x7a, 0x65, 0x72,
+ 0x6f, 0x00, 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1,
+ 0xd6, 0x43, 0x4b, 0x8b, 0x29, 0xae, 0x77, 0x5a,
+ 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91,
+};
+
+static unsigned char tag_data[] = {
+ 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x33,
+ 0x64, 0x37, 0x66, 0x38, 0x61, 0x36, 0x61, 0x66,
+ 0x30, 0x37, 0x36, 0x63, 0x38, 0x63, 0x33, 0x66,
+ 0x32, 0x30, 0x30, 0x37, 0x31, 0x61, 0x38, 0x39,
+ 0x33, 0x35, 0x63, 0x64, 0x62, 0x65, 0x38, 0x32,
+ 0x32, 0x38, 0x35, 0x39, 0x34, 0x64, 0x31, 0x0a,
+ 0x74, 0x79, 0x70, 0x65, 0x20, 0x63, 0x6f, 0x6d,
+ 0x6d, 0x69, 0x74, 0x0a, 0x74, 0x61, 0x67, 0x20,
+ 0x76, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0a, 0x74,
+ 0x61, 0x67, 0x67, 0x65, 0x72, 0x20, 0x43, 0x20,
+ 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72,
+ 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
+ 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d,
+ 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e,
+ 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34,
+ 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30,
+ 0x30, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x61, 0x67, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65,
+ 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x76, 0x30,
+ 0x2e, 0x30, 0x2e, 0x31, 0x0a,
+};
+
+/*
+ * Dummy data
+ */
+static unsigned char zero_data[] = {
+ 0x00,
+};
+
+static unsigned char one_data[] = {
+ 0x0a,
+};
+
+static unsigned char two_data[] = {
+ 0x61, 0x0a,
+};
+
+static unsigned char some_data[] = {
+ 0x2f, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x54, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20,
+ 0x69, 0x73, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20,
+ 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
+ 0x3b, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61,
+ 0x6e, 0x20, 0x72, 0x65, 0x64, 0x69, 0x73, 0x74,
+ 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69,
+ 0x74, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72,
+ 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0a,
+ 0x20, 0x2a, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e,
+ 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55,
+ 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
+ 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
+ 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c,
+ 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+ 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x2a, 0x20, 0x61,
+ 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73,
+ 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20,
+ 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
+ 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x2a, 0x0a,
+ 0x20, 0x2a, 0x20, 0x49, 0x6e, 0x20, 0x61, 0x64,
+ 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65,
+ 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e,
+ 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62,
+ 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65,
+ 0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x20, 0x2a, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68,
+ 0x6f, 0x72, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65,
+ 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x6c,
+ 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x70,
+ 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f,
+ 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e,
+ 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
+ 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x20,
+ 0x2a, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x69,
+ 0x6e, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x62,
+ 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x67,
+ 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0a, 0x20, 0x2a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20,
+ 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75,
+ 0x74, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65,
+ 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e,
+ 0x79, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69,
+ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x2a,
+ 0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20,
+ 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c,
+ 0x65, 0x2e, 0x20, 0x20, 0x28, 0x54, 0x68, 0x65,
+ 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
+ 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
+ 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a,
+ 0x20, 0x2a, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72,
+ 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20,
+ 0x64, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79,
+ 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63,
+ 0x74, 0x73, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x6f,
+ 0x76, 0x65, 0x72, 0x0a, 0x20, 0x2a, 0x20, 0x6d,
+ 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73,
+ 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65,
+ 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x0a, 0x20,
+ 0x2a, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62,
+ 0x69, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x78, 0x65,
+ 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e,
+ 0x29, 0x0a, 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c,
+ 0x65, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73,
+ 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x6f, 0x70, 0x65, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65,
+ 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x62, 0x75, 0x74,
+ 0x0a, 0x20, 0x2a, 0x20, 0x57, 0x49, 0x54, 0x48,
+ 0x4f, 0x55, 0x54, 0x20, 0x41, 0x4e, 0x59, 0x20,
+ 0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x59,
+ 0x3b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75,
+ 0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x69,
+ 0x65, 0x64, 0x20, 0x77, 0x61, 0x72, 0x72, 0x61,
+ 0x6e, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x0a, 0x20,
+ 0x2a, 0x20, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41,
+ 0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54,
+ 0x59, 0x20, 0x6f, 0x72, 0x20, 0x46, 0x49, 0x54,
+ 0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f, 0x52,
+ 0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49,
+ 0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55,
+ 0x52, 0x50, 0x4f, 0x53, 0x45, 0x2e, 0x20, 0x20,
+ 0x53, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x47, 0x4e, 0x55, 0x0a, 0x20, 0x2a, 0x20, 0x47,
+ 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50,
+ 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69,
+ 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x64,
+ 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x0a,
+ 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x59, 0x6f,
+ 0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64,
+ 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x72, 0x65,
+ 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61,
+ 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55,
+ 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
+ 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
+ 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a,
+ 0x20, 0x2a, 0x20, 0x61, 0x6c, 0x6f, 0x6e, 0x67,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
+ 0x61, 0x6d, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65,
+ 0x20, 0x43, 0x4f, 0x50, 0x59, 0x49, 0x4e, 0x47,
+ 0x2e, 0x20, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f,
+ 0x74, 0x2c, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65,
+ 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x2a, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20,
+ 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
+ 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x35, 0x31, 0x20,
+ 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x6c, 0x69, 0x6e,
+ 0x20, 0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2c,
+ 0x20, 0x46, 0x69, 0x66, 0x74, 0x68, 0x20, 0x46,
+ 0x6c, 0x6f, 0x6f, 0x72, 0x2c, 0x0a, 0x20, 0x2a,
+ 0x20, 0x42, 0x6f, 0x73, 0x74, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x4d, 0x41, 0x20, 0x30, 0x32, 0x31, 0x31,
+ 0x30, 0x2d, 0x31, 0x33, 0x30, 0x31, 0x2c, 0x20,
+ 0x55, 0x53, 0x41, 0x2e, 0x0a, 0x20, 0x2a, 0x2f,
+ 0x0a,
+};
+
+/*
+ * SHA1 Hashes
+ */
+static char *commit_id = "3d7f8a6af076c8c3f20071a8935cdbe8228594d1";
+static char *tree_id = "dff2da90b254e1beb889d1f1f1288be1803782df";
+static char *tag_id = "09d373e1dfdc16b129ceec6dd649739911541e05";
+static char *zero_id = "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391";
+static char *one_id = "8b137891791fe96927ad78e64b0aad7bded08bdc";
+static char *two_id = "78981922613b2afb6025042ff6bd878ac1994e85";
+static char *some_id = "fd8430bc864cfcd5f10e5590f8a447e01b942bfe";
+
+/*
+ * In-memory objects
+ */
+static git_rawobj tree_obj = {
+ tree_data,
+ sizeof(tree_data),
+ GIT_OBJ_TREE
+};
+
+static git_rawobj tag_obj = {
+ tag_data,
+ sizeof(tag_data),
+ GIT_OBJ_TAG
+};
+
+static git_rawobj zero_obj = {
+ zero_data,
+ 0,
+ GIT_OBJ_BLOB
+};
+
+static git_rawobj one_obj = {
+ one_data,
+ sizeof(one_data),
+ GIT_OBJ_BLOB
+};
+
+static git_rawobj two_obj = {
+ two_data,
+ sizeof(two_data),
+ GIT_OBJ_BLOB
+};
+
+static git_rawobj commit_obj = {
+ commit_data,
+ sizeof(commit_data),
+ GIT_OBJ_COMMIT
+};
+
+static git_rawobj some_obj = {
+ some_data,
+ sizeof(some_data),
+ GIT_OBJ_BLOB
+};
+
+static git_rawobj junk_obj = {
+ NULL,
+ 0,
+ GIT_OBJ_BAD
+};
diff --git a/tests-clay/object/raw/fromstr.c b/tests-clay/object/raw/fromstr.c
new file mode 100644
index 000000000..6d732d4eb
--- /dev/null
+++ b/tests-clay/object/raw/fromstr.c
@@ -0,0 +1,30 @@
+
+#include "clay_libgit2.h"
+
+#include "odb.h"
+
+void test_object_raw_fromstr__fail_on_invalid_oid_string(void)
+{
+ git_oid out;
+ cl_git_fail(git_oid_fromstr(&out, ""));
+ cl_git_fail(git_oid_fromstr(&out, "moo"));
+ cl_git_fail(git_oid_fromstr(&out, "16a67770b7d8d72317c4b775213c23a8bd74f5ez"));
+}
+
+void test_object_raw_fromstr__succeed_on_valid_oid_string(void)
+{
+ git_oid out;
+ unsigned char exp[] = {
+ 0x16, 0xa6, 0x77, 0x70, 0xb7,
+ 0xd8, 0xd7, 0x23, 0x17, 0xc4,
+ 0xb7, 0x75, 0x21, 0x3c, 0x23,
+ 0xa8, 0xbd, 0x74, 0xf5, 0xe0,
+ };
+
+ cl_git_pass(git_oid_fromstr(&out, "16a67770b7d8d72317c4b775213c23a8bd74f5e0"));
+ cl_git_pass(memcmp(out.id, exp, sizeof(out.id)));
+
+ cl_git_pass(git_oid_fromstr(&out, "16A67770B7D8D72317C4b775213C23A8BD74F5E0"));
+ cl_git_pass(memcmp(out.id, exp, sizeof(out.id)));
+
+}
diff --git a/tests-clay/object/raw/hash.c b/tests-clay/object/raw/hash.c
new file mode 100644
index 000000000..9974ed6ef
--- /dev/null
+++ b/tests-clay/object/raw/hash.c
@@ -0,0 +1,162 @@
+
+#include "clay_libgit2.h"
+
+#include "odb.h"
+#include "hash.h"
+
+#include "data.h"
+
+static int hash_object(git_oid *oid, git_rawobj *obj)
+{
+ return git_odb_hash(oid, obj->data, obj->len, obj->type);
+}
+
+static char *hello_id = "22596363b3de40b06f981fb85d82312e8c0ed511";
+static char *hello_text = "hello world\n";
+
+static char *bye_id = "ce08fe4884650f067bd5703b6a59a8b3b3c99a09";
+static char *bye_text = "bye world\n";
+
+void test_object_raw_hash__hash_by_blocks(void)
+{
+ git_hash_ctx *ctx;
+ git_oid id1, id2;
+
+ cl_assert((ctx = git_hash_new_ctx()) != NULL);
+
+ /* should already be init'd */
+ git_hash_update(ctx, hello_text, strlen(hello_text));
+ git_hash_final(&id2, ctx);
+ cl_git_pass(git_oid_fromstr(&id1, hello_id));
+ cl_assert(git_oid_cmp(&id1, &id2) == 0);
+
+ /* reinit should permit reuse */
+ git_hash_init(ctx);
+ git_hash_update(ctx, bye_text, strlen(bye_text));
+ git_hash_final(&id2, ctx);
+ cl_git_pass(git_oid_fromstr(&id1, bye_id));
+ cl_assert(git_oid_cmp(&id1, &id2) == 0);
+
+ git_hash_free_ctx(ctx);
+}
+
+void test_object_raw_hash__hash_buffer_in_single_call(void)
+{
+ git_oid id1, id2;
+
+ cl_git_pass(git_oid_fromstr(&id1, hello_id));
+ git_hash_buf(&id2, hello_text, strlen(hello_text));
+ cl_assert(git_oid_cmp(&id1, &id2) == 0);
+}
+
+void test_object_raw_hash__hash_vector(void)
+{
+ git_oid id1, id2;
+ git_buf_vec vec[2];
+
+ cl_git_pass(git_oid_fromstr(&id1, hello_id));
+
+ vec[0].data = hello_text;
+ vec[0].len = 4;
+ vec[1].data = hello_text+4;
+ vec[1].len = strlen(hello_text)-4;
+
+ git_hash_vec(&id2, vec, 2);
+
+ cl_assert(git_oid_cmp(&id1, &id2) == 0);
+}
+
+void test_object_raw_hash__hash_junk_data(void)
+{
+ git_oid id, id_zero;
+
+ cl_git_pass(git_oid_fromstr(&id_zero, zero_id));
+
+ /* invalid types: */
+ junk_obj.data = some_data;
+ cl_git_fail(hash_object(&id, &junk_obj));
+
+ junk_obj.type = GIT_OBJ__EXT1;
+ cl_git_fail(hash_object(&id, &junk_obj));
+
+ junk_obj.type = GIT_OBJ__EXT2;
+ cl_git_fail(hash_object(&id, &junk_obj));
+
+ junk_obj.type = GIT_OBJ_OFS_DELTA;
+ cl_git_fail(hash_object(&id, &junk_obj));
+
+ junk_obj.type = GIT_OBJ_REF_DELTA;
+ cl_git_fail(hash_object(&id, &junk_obj));
+
+ /* data can be NULL only if len is zero: */
+ junk_obj.type = GIT_OBJ_BLOB;
+ junk_obj.data = NULL;
+ cl_git_pass(hash_object(&id, &junk_obj));
+ cl_assert(git_oid_cmp(&id, &id_zero) == 0);
+
+ junk_obj.len = 1;
+ cl_git_fail(hash_object(&id, &junk_obj));
+}
+
+void test_object_raw_hash__hash_commit_object(void)
+{
+ git_oid id1, id2;
+
+ cl_git_pass(git_oid_fromstr(&id1, commit_id));
+ cl_git_pass(hash_object(&id2, &commit_obj));
+ cl_assert(git_oid_cmp(&id1, &id2) == 0);
+}
+
+void test_object_raw_hash__hash_tree_object(void)
+{
+ git_oid id1, id2;
+
+ cl_git_pass(git_oid_fromstr(&id1, tree_id));
+ cl_git_pass(hash_object(&id2, &tree_obj));
+ cl_assert(git_oid_cmp(&id1, &id2) == 0);
+}
+
+void test_object_raw_hash__hash_tag_object(void)
+{
+ git_oid id1, id2;
+
+ cl_git_pass(git_oid_fromstr(&id1, tag_id));
+ cl_git_pass(hash_object(&id2, &tag_obj));
+ cl_assert(git_oid_cmp(&id1, &id2) == 0);
+}
+
+void test_object_raw_hash__hash_zero_length_object(void)
+{
+ git_oid id1, id2;
+
+ cl_git_pass(git_oid_fromstr(&id1, zero_id));
+ cl_git_pass(hash_object(&id2, &zero_obj));
+ cl_assert(git_oid_cmp(&id1, &id2) == 0);
+}
+
+void test_object_raw_hash__hash_one_byte_object(void)
+{
+ git_oid id1, id2;
+
+ cl_git_pass(git_oid_fromstr(&id1, one_id));
+ cl_git_pass(hash_object(&id2, &one_obj));
+ cl_assert(git_oid_cmp(&id1, &id2) == 0);
+}
+
+void test_object_raw_hash__hash_two_byte_object(void)
+{
+ git_oid id1, id2;
+
+ cl_git_pass(git_oid_fromstr(&id1, two_id));
+ cl_git_pass(hash_object(&id2, &two_obj));
+ cl_assert(git_oid_cmp(&id1, &id2) == 0);
+}
+
+void test_object_raw_hash__hash_multi_byte_object(void)
+{
+ git_oid id1, id2;
+
+ cl_git_pass(git_oid_fromstr(&id1, some_id));
+ cl_git_pass(hash_object(&id2, &some_obj));
+ cl_assert(git_oid_cmp(&id1, &id2) == 0);
+}
diff --git a/tests-clay/object/raw/short.c b/tests-clay/object/raw/short.c
new file mode 100644
index 000000000..996f3f7b4
--- /dev/null
+++ b/tests-clay/object/raw/short.c
@@ -0,0 +1,94 @@
+
+#include "clay_libgit2.h"
+
+#include "odb.h"
+#include "hash.h"
+
+void test_object_raw_short__oid_shortener_no_duplicates(void)
+{
+ git_oid_shorten *os;
+ int min_len;
+
+ os = git_oid_shorten_new(0);
+ cl_assert(os != NULL);
+
+ git_oid_shorten_add(os, "22596363b3de40b06f981fb85d82312e8c0ed511");
+ git_oid_shorten_add(os, "ce08fe4884650f067bd5703b6a59a8b3b3c99a09");
+ git_oid_shorten_add(os, "16a0123456789abcdef4b775213c23a8bd74f5e0");
+ min_len = git_oid_shorten_add(os, "ce08fe4884650f067bd5703b6a59a8b3b3c99a09");
+
+ cl_assert(min_len == GIT_OID_HEXSZ + 1);
+
+ git_oid_shorten_free(os);
+}
+
+void test_object_raw_short__oid_shortener_stresstest_git_oid_shorten(void)
+{
+#define MAX_OIDS 1000
+
+ git_oid_shorten *os;
+ char *oids[MAX_OIDS];
+ char number_buffer[16];
+ git_oid oid;
+ size_t i, j;
+
+ int min_len = 0, found_collision;
+
+ os = git_oid_shorten_new(0);
+ cl_assert(os != NULL);
+
+ /*
+ * Insert in the shortener 1000 unique SHA1 ids
+ */
+ for (i = 0; i < MAX_OIDS; ++i) {
+ char *oid_text;
+
+ sprintf(number_buffer, "%u", (unsigned int)i);
+ git_hash_buf(&oid, number_buffer, strlen(number_buffer));
+
+ oid_text = git__malloc(GIT_OID_HEXSZ + 1);
+ git_oid_fmt(oid_text, &oid);
+ oid_text[GIT_OID_HEXSZ] = 0;
+
+ min_len = git_oid_shorten_add(os, oid_text);
+ cl_assert(min_len >= 0);
+
+ oids[i] = oid_text;
+ }
+
+ /*
+ * Compare the first `min_char - 1` characters of each
+ * SHA1 OID. If the minimizer worked, we should find at
+ * least one collision
+ */
+ found_collision = 0;
+ for (i = 0; i < MAX_OIDS; ++i) {
+ for (j = 0; j < MAX_OIDS; ++j) {
+ if (i != j && memcmp(oids[i], oids[j], min_len - 1) == 0)
+ found_collision = 1;
+ }
+ }
+ cl_assert(found_collision == 1);
+
+ /*
+ * Compare the first `min_char` characters of each
+ * SHA1 OID. If the minimizer worked, every single preffix
+ * should be unique.
+ */
+ found_collision = 0;
+ for (i = 0; i < MAX_OIDS; ++i) {
+ for (j = 0; j < MAX_OIDS; ++j) {
+ if (i != j && memcmp(oids[i], oids[j], min_len) == 0)
+ found_collision = 1;
+ }
+ }
+ cl_assert(found_collision == 0);
+
+ /* cleanup */
+ for (i = 0; i < MAX_OIDS; ++i)
+ git__free(oids[i]);
+
+ git_oid_shorten_free(os);
+
+#undef MAX_OIDS
+}
diff --git a/tests-clay/object/raw/size.c b/tests-clay/object/raw/size.c
new file mode 100644
index 000000000..44c5b6cd1
--- /dev/null
+++ b/tests-clay/object/raw/size.c
@@ -0,0 +1,13 @@
+
+#include "clay_libgit2.h"
+
+#include "odb.h"
+
+void test_object_raw_size__validate_oid_size(void)
+{
+ git_oid out;
+ cl_assert(20 == GIT_OID_RAWSZ);
+ cl_assert(40 == GIT_OID_HEXSZ);
+ cl_assert(sizeof(out) == GIT_OID_RAWSZ);
+ cl_assert(sizeof(out.id) == GIT_OID_RAWSZ);
+}
diff --git a/tests-clay/object/raw/type2string.c b/tests-clay/object/raw/type2string.c
new file mode 100644
index 000000000..109bc1112
--- /dev/null
+++ b/tests-clay/object/raw/type2string.c
@@ -0,0 +1,54 @@
+
+#include "clay_libgit2.h"
+
+#include "odb.h"
+#include "hash.h"
+
+void test_object_raw_type2string__convert_type_to_string(void)
+{
+ cl_assert(!strcmp(git_object_type2string(GIT_OBJ_BAD), ""));
+ cl_assert(!strcmp(git_object_type2string(GIT_OBJ__EXT1), ""));
+ cl_assert(!strcmp(git_object_type2string(GIT_OBJ_COMMIT), "commit"));
+ cl_assert(!strcmp(git_object_type2string(GIT_OBJ_TREE), "tree"));
+ cl_assert(!strcmp(git_object_type2string(GIT_OBJ_BLOB), "blob"));
+ cl_assert(!strcmp(git_object_type2string(GIT_OBJ_TAG), "tag"));
+ cl_assert(!strcmp(git_object_type2string(GIT_OBJ__EXT2), ""));
+ cl_assert(!strcmp(git_object_type2string(GIT_OBJ_OFS_DELTA), "OFS_DELTA"));
+ cl_assert(!strcmp(git_object_type2string(GIT_OBJ_REF_DELTA), "REF_DELTA"));
+
+ cl_assert(!strcmp(git_object_type2string(-2), ""));
+ cl_assert(!strcmp(git_object_type2string(8), ""));
+ cl_assert(!strcmp(git_object_type2string(1234), ""));
+}
+
+void test_object_raw_type2string__convert_string_to_type(void)
+{
+ cl_assert(git_object_string2type(NULL) == GIT_OBJ_BAD);
+ cl_assert(git_object_string2type("") == GIT_OBJ_BAD);
+ cl_assert(git_object_string2type("commit") == GIT_OBJ_COMMIT);
+ cl_assert(git_object_string2type("tree") == GIT_OBJ_TREE);
+ cl_assert(git_object_string2type("blob") == GIT_OBJ_BLOB);
+ cl_assert(git_object_string2type("tag") == GIT_OBJ_TAG);
+ cl_assert(git_object_string2type("OFS_DELTA") == GIT_OBJ_OFS_DELTA);
+ cl_assert(git_object_string2type("REF_DELTA") == GIT_OBJ_REF_DELTA);
+
+ cl_assert(git_object_string2type("CoMmIt") == GIT_OBJ_BAD);
+ cl_assert(git_object_string2type("hohoho") == GIT_OBJ_BAD);
+}
+
+void test_object_raw_type2string__check_type_is_loose(void)
+{
+ cl_assert(git_object_typeisloose(GIT_OBJ_BAD) == 0);
+ cl_assert(git_object_typeisloose(GIT_OBJ__EXT1) == 0);
+ cl_assert(git_object_typeisloose(GIT_OBJ_COMMIT) == 1);
+ cl_assert(git_object_typeisloose(GIT_OBJ_TREE) == 1);
+ cl_assert(git_object_typeisloose(GIT_OBJ_BLOB) == 1);
+ cl_assert(git_object_typeisloose(GIT_OBJ_TAG) == 1);
+ cl_assert(git_object_typeisloose(GIT_OBJ__EXT2) == 0);
+ cl_assert(git_object_typeisloose(GIT_OBJ_OFS_DELTA) == 0);
+ cl_assert(git_object_typeisloose(GIT_OBJ_REF_DELTA) == 0);
+
+ cl_assert(git_object_typeisloose(-2) == 0);
+ cl_assert(git_object_typeisloose(8) == 0);
+ cl_assert(git_object_typeisloose(1234) == 0);
+}
diff --git a/tests-clay/object/tree/frompath.c b/tests-clay/object/tree/frompath.c
index 23cb416fe..651a86d86 100644
--- a/tests-clay/object/tree/frompath.c
+++ b/tests-clay/object/tree/frompath.c
@@ -30,7 +30,7 @@ static void assert_tree_from_path(git_tree *root, const char *path, int expected
{
git_tree *containing_tree = NULL;
- cl_assert(git_tree_frompath(&containing_tree, root, path) == expected_result);
+ cl_assert(git_tree_get_subtree(&containing_tree, root, path) == expected_result);
if (containing_tree == NULL && expected_result != GIT_SUCCESS)
return;
diff --git a/tests-clay/status/single.c b/tests-clay/status/single.c
index ea1c77fa0..4fd6e6ff4 100644
--- a/tests-clay/status/single.c
+++ b/tests-clay/status/single.c
@@ -10,7 +10,7 @@ cleanup__remove_file(void *_file)
static void
file_create(const char *filename, const char *content)
{
- int fd = p_creat(filename, 0644);
+ int fd = p_creat(filename, 0666);
cl_assert(fd >= 0);
cl_must_pass(p_write(fd, content, strlen(content)));
cl_must_pass(p_close(fd));
diff --git a/tests-clay/status/worktree.c b/tests-clay/status/worktree.c
index 74dfd4898..7d120ecb5 100644
--- a/tests-clay/status/worktree.c
+++ b/tests-clay/status/worktree.c
@@ -71,7 +71,7 @@ void test_status_worktree__initialize(void)
* inside the fixtures folder in our libgit2 repo.
*/
cl_git_pass(
- git_futils_mv_atomic("status/.gitted", "status/.git")
+ p_rename("status/.gitted", "status/.git")
);
/*
diff --git a/tests/resources/status/.gitted/COMMIT_EDITMSG b/tests/resources/status/.gitted/COMMIT_EDITMSG
index ff887ba13..1a25cd4a6 100644
--- a/tests/resources/status/.gitted/COMMIT_EDITMSG
+++ b/tests/resources/status/.gitted/COMMIT_EDITMSG
@@ -1 +1 @@
-add subdir
+Add a file which name should appear before the "subdir/" folder while being dealt with by the treewalker
diff --git a/tests/resources/status/.gitted/ORIG_HEAD b/tests/resources/status/.gitted/ORIG_HEAD
index c2805f422..b46871fd6 100644
--- a/tests/resources/status/.gitted/ORIG_HEAD
+++ b/tests/resources/status/.gitted/ORIG_HEAD
@@ -1 +1 @@
-0017bd4ab1ec30440b17bae1680cff124ab5f1f6
+735b6a258cd196a8f7c9428419b02c1dca93fd75
diff --git a/tests/resources/status/.gitted/index b/tests/resources/status/.gitted/index
index 5c4b18841..d793791c9 100644
--- a/tests/resources/status/.gitted/index
+++ b/tests/resources/status/.gitted/index
Binary files differ
diff --git a/tests/resources/status/.gitted/logs/HEAD b/tests/resources/status/.gitted/logs/HEAD
index e876bd80b..7b95b3cf1 100644
--- a/tests/resources/status/.gitted/logs/HEAD
+++ b/tests/resources/status/.gitted/logs/HEAD
@@ -1,2 +1,3 @@
0000000000000000000000000000000000000000 0017bd4ab1ec30440b17bae1680cff124ab5f1f6 Jason Penny <jasonpenny4@gmail.com> 1308050070 -0400 commit (initial): initial
0017bd4ab1ec30440b17bae1680cff124ab5f1f6 735b6a258cd196a8f7c9428419b02c1dca93fd75 Jason Penny <jasonpenny4@gmail.com> 1308954538 -0400 commit: add subdir
+735b6a258cd196a8f7c9428419b02c1dca93fd75 26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f nulltoken <emeric.fermas@gmail.com> 1319911544 +0200 commit: Add a file which name should appear before the "subdir/" folder while being dealt with by the treewalker
diff --git a/tests/resources/status/.gitted/logs/refs/heads/master b/tests/resources/status/.gitted/logs/refs/heads/master
index e876bd80b..7b95b3cf1 100644
--- a/tests/resources/status/.gitted/logs/refs/heads/master
+++ b/tests/resources/status/.gitted/logs/refs/heads/master
@@ -1,2 +1,3 @@
0000000000000000000000000000000000000000 0017bd4ab1ec30440b17bae1680cff124ab5f1f6 Jason Penny <jasonpenny4@gmail.com> 1308050070 -0400 commit (initial): initial
0017bd4ab1ec30440b17bae1680cff124ab5f1f6 735b6a258cd196a8f7c9428419b02c1dca93fd75 Jason Penny <jasonpenny4@gmail.com> 1308954538 -0400 commit: add subdir
+735b6a258cd196a8f7c9428419b02c1dca93fd75 26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f nulltoken <emeric.fermas@gmail.com> 1319911544 +0200 commit: Add a file which name should appear before the "subdir/" folder while being dealt with by the treewalker
diff --git a/tests/resources/status/.gitted/objects/26/a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f b/tests/resources/status/.gitted/objects/26/a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f
new file mode 100644
index 000000000..f7dddc4ff
--- /dev/null
+++ b/tests/resources/status/.gitted/objects/26/a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f
@@ -0,0 +1,2 @@
+xMn )V (̀BD޾LЍRȷވ@,9̜tNj6f`M6Z;h Zp ڙY,37/;42x&<z #^
+䮁ZQ0嫫pޙ`l?{@)1+=#ö6j#֧qP>gϟۉIm|j \ No newline at end of file
diff --git a/tests/resources/status/.gitted/objects/37/fcb02ccc1a85d1941e7f106d52dc3702dcf0d0 b/tests/resources/status/.gitted/objects/37/fcb02ccc1a85d1941e7f106d52dc3702dcf0d0
new file mode 100644
index 000000000..b75481b51
--- /dev/null
+++ b/tests/resources/status/.gitted/objects/37/fcb02ccc1a85d1941e7f106d52dc3702dcf0d0
Binary files differ
diff --git a/tests/resources/status/.gitted/objects/e8/ee89e15bbe9b20137715232387b3de5b28972e b/tests/resources/status/.gitted/objects/e8/ee89e15bbe9b20137715232387b3de5b28972e
new file mode 100644
index 000000000..cfc2413d5
--- /dev/null
+++ b/tests/resources/status/.gitted/objects/e8/ee89e15bbe9b20137715232387b3de5b28972e
Binary files differ
diff --git a/tests/resources/status/.gitted/refs/heads/master b/tests/resources/status/.gitted/refs/heads/master
index b46871fd6..3e2e2a07a 100644
--- a/tests/resources/status/.gitted/refs/heads/master
+++ b/tests/resources/status/.gitted/refs/heads/master
@@ -1 +1 @@
-735b6a258cd196a8f7c9428419b02c1dca93fd75
+26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f
diff --git a/tests/resources/status/subdir.txt b/tests/resources/status/subdir.txt
new file mode 100644
index 000000000..e8ee89e15
--- /dev/null
+++ b/tests/resources/status/subdir.txt
@@ -0,0 +1,2 @@
+Is it a bird?
+Is it a plane?
diff --git a/tests/t00-core.c b/tests/t00-core.c
index 703504bf8..94824b438 100644
--- a/tests/t00-core.c
+++ b/tests/t00-core.c
@@ -99,8 +99,8 @@ BEGIN_TEST(vector2, "remove duplicates")
must_be_true(x.length == 2);
git_vector_free(&x);
- free(ptrs[0]);
- free(ptrs[1]);
+ git__free(ptrs[0]);
+ git__free(ptrs[1]);
END_TEST
@@ -112,7 +112,7 @@ BEGIN_TEST(path0, "get the dirname of a path")
must_be_true(strcmp(dir, B) == 0); \
must_be_true((dir2 = git_path_dirname(A)) != NULL); \
must_be_true(strcmp(dir2, B) == 0); \
- free(dir2); \
+ git__free(dir2); \
}
DIRNAME_TEST(NULL, ".");
@@ -141,7 +141,7 @@ BEGIN_TEST(path1, "get the base name of a path")
must_be_true(strcmp(base, B) == 0); \
must_be_true((base2 = git_path_basename(A)) != NULL); \
must_be_true(strcmp(base2, B) == 0); \
- free(base2); \
+ git__free(base2); \
}
BASENAME_TEST(NULL, ".");
@@ -250,21 +250,21 @@ static int setup(walk_data *d)
{
name_data *n;
- if (p_mkdir(top_dir, 0755) < 0)
+ if (p_mkdir(top_dir, 0777) < 0)
return error("can't mkdir(\"%s\")", top_dir);
if (p_chdir(top_dir) < 0)
return error("can't chdir(\"%s\")", top_dir);
if (strcmp(d->sub, ".") != 0)
- if (p_mkdir(d->sub, 0755) < 0)
+ if (p_mkdir(d->sub, 0777) < 0)
return error("can't mkdir(\"%s\")", d->sub);
strcpy(path_buffer, d->sub);
state_loc = d;
for (n = d->names; n->name; n++) {
- git_file fd = p_creat(n->name, 0600);
+ git_file fd = p_creat(n->name, 0666);
if (fd < 0)
return GIT_ERROR;
p_close(fd);
@@ -479,14 +479,14 @@ BEGIN_TEST(filebuf1, "make sure GIT_FILEBUF_APPEND works as expected")
int fd;
char test[] = "test";
- fd = p_creat(test, 0644);
+ fd = p_creat(test, 0666);
must_pass(fd);
must_pass(p_write(fd, "libgit2 rocks\n", 14));
must_pass(p_close(fd));
must_pass(git_filebuf_open(&file, test, GIT_FILEBUF_APPEND));
must_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));
- must_pass(git_filebuf_commit(&file));
+ must_pass(git_filebuf_commit(&file, 0666));
must_pass(p_unlink(test));
END_TEST
@@ -499,7 +499,7 @@ BEGIN_TEST(filebuf2, "make sure git_filebuf_write writes large buffer correctly"
memset(buf, 0xfe, sizeof(buf));
must_pass(git_filebuf_open(&file, test, 0));
must_pass(git_filebuf_write(&file, buf, sizeof(buf)));
- must_pass(git_filebuf_commit(&file));
+ must_pass(git_filebuf_commit(&file, 0666));
must_pass(p_unlink(test));
END_TEST
@@ -510,27 +510,27 @@ static int setup_empty_tmp_dir(void)
{
char path[GIT_PATH_MAX];
- if (p_mkdir(empty_tmp_dir, 0755))
+ if (p_mkdir(empty_tmp_dir, 0777))
return -1;
git_path_join(path, empty_tmp_dir, "/one");
- if (p_mkdir(path, 0755))
+ if (p_mkdir(path, 0777))
return -1;
git_path_join(path, empty_tmp_dir, "/one/two_one");
- if (p_mkdir(path, 0755))
+ if (p_mkdir(path, 0777))
return -1;
git_path_join(path, empty_tmp_dir, "/one/two_two");
- if (p_mkdir(path, 0755))
+ if (p_mkdir(path, 0777))
return -1;
git_path_join(path, empty_tmp_dir, "/one/two_two/three");
- if (p_mkdir(path, 0755))
+ if (p_mkdir(path, 0777))
return -1;
git_path_join(path, empty_tmp_dir, "/two");
- if (p_mkdir(path, 0755))
+ if (p_mkdir(path, 0777))
return -1;
return 0;
@@ -547,7 +547,7 @@ BEGIN_TEST(rmdir1, "make sure non-empty dir cannot be deleted recusively")
must_pass(setup_empty_tmp_dir());
git_path_join(file, empty_tmp_dir, "/two/file.txt");
- fd = p_creat(file, 0755);
+ fd = p_creat(file, 0777);
must_pass(fd);
must_pass(p_close(fd));
must_fail(git_futils_rmdir_r(empty_tmp_dir, 0));
diff --git a/tests/t01-rawobj.c b/tests/t01-rawobj.c
index 255208532..8b05f3394 100644
--- a/tests/t01-rawobj.c
+++ b/tests/t01-rawobj.c
@@ -217,7 +217,7 @@ BEGIN_TEST(oid12, "compare oids (allocate + format)")
out = git_oid_allocfmt(&in);
must_be_true(out);
must_be_true(strcmp(exp, out) == 0);
- free(out);
+ git__free(out);
END_TEST
BEGIN_TEST(oid13, "compare oids (path format)")
@@ -390,7 +390,7 @@ BEGIN_TEST(oid17, "stress test for the git_oid_shorten object")
/* cleanup */
for (i = 0; i < MAX_OIDS; ++i)
- free(oids[i]);
+ git__free(oids[i]);
git_oid_shorten_free(os);
diff --git a/tests/t03-objwrite.c b/tests/t03-objwrite.c
index 31f611a5c..7563d0e3a 100644
--- a/tests/t03-objwrite.c
+++ b/tests/t03-objwrite.c
@@ -31,7 +31,7 @@ static char *odb_dir = "test-objects";
static int make_odb_dir(void)
{
- if (p_mkdir(odb_dir, 0755) < 0) {
+ if (p_mkdir(odb_dir, GIT_OBJECT_DIR_MODE) < 0) {
int err = errno;
fprintf(stderr, "can't make directory \"%s\"", odb_dir);
if (err == EEXIST)
diff --git a/tests/t04-commit.c b/tests/t04-commit.c
index 3fb4d370c..d0bb1b583 100644
--- a/tests/t04-commit.c
+++ b/tests/t04-commit.c
@@ -162,7 +162,7 @@ BEGIN_TEST(parse1, "parse the signature line in a commit")
must_be_true(strcmp(_email, person.email) == 0);\
must_be_true(_time == person.when.time);\
must_be_true(_offset == person.when.offset);\
- free(person.name); free(person.email);\
+ git__free(person.name); git__free(person.email);\
}
#define TEST_SIGNATURE_FAIL(_string, _header) { \
@@ -170,7 +170,7 @@ BEGIN_TEST(parse1, "parse the signature line in a commit")
size_t len = strlen(_string);\
git_signature person = {NULL, NULL, {0, 0}}; \
must_fail(git_signature__parse(&person, &ptr, ptr + len, _header, '\n'));\
- free(person.name); free(person.email);\
+ git__free(person.name); git__free(person.email);\
}
TEST_SIGNATURE_PASS(
@@ -690,6 +690,10 @@ BEGIN_TEST(write0, "write a new commit object from memory to disk")
must_be_true(strcmp(git_commit_message(commit), COMMIT_MESSAGE) == 0);
+#ifndef GIT_WIN32
+ must_be_true((loose_object_mode(REPOSITORY_FOLDER, (git_object *)commit) & 0777) == GIT_OBJECT_FILE_MODE);
+#endif
+
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)commit));
git_commit_close(commit);
@@ -759,9 +763,11 @@ BEGIN_TEST(root0, "create a root commit")
must_pass(git_reference_set_target(head, head_old));
must_pass(git_reference_delete(branch));
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)commit));
- free(head_old);
+ git__free(head_old);
git_commit_close(commit);
git_repository_free(repo);
+
+ git_reference_free(head);
END_TEST
BEGIN_SUITE(commit)
diff --git a/tests/t06-index.c b/tests/t06-index.c
index 621e742b3..44562d004 100644
--- a/tests/t06-index.c
+++ b/tests/t06-index.c
@@ -176,10 +176,10 @@ BEGIN_TEST(add0, "add a new file to the index")
must_pass(git_index_entrycount(index) == 0);
/* Create a new file in the working directory */
- must_pass(git_futils_mkpath2file(TEMP_REPO_FOLDER "myrepo/test.txt"));
+ must_pass(git_futils_mkpath2file(TEMP_REPO_FOLDER "myrepo/test.txt", 0777));
must_pass(git_filebuf_open(&file, TEMP_REPO_FOLDER "myrepo/test.txt", 0));
must_pass(git_filebuf_write(&file, "hey there\n", 10));
- must_pass(git_filebuf_commit(&file));
+ must_pass(git_filebuf_commit(&file, 0666));
/* Store the expected hash of the file/blob
* This has been generated by executing the following
diff --git a/tests/t07-hashtable.c b/tests/t07-hashtable.c
index c0e852259..41d52af19 100644
--- a/tests/t07-hashtable.c
+++ b/tests/t07-hashtable.c
@@ -103,7 +103,7 @@ BEGIN_TEST(table1, "fill the hashtable with random entries")
}
git_hashtable_free(table);
- free(objects);
+ git__free(objects);
END_TEST
@@ -145,7 +145,7 @@ BEGIN_TEST(table2, "make sure the table resizes automatically")
}
git_hashtable_free(table);
- free(objects);
+ git__free(objects);
END_TEST
@@ -179,7 +179,7 @@ BEGIN_TEST(tableit0, "iterate through all the contents of the table")
must_be_true(objects[i].visited);
git_hashtable_free(table);
- free(objects);
+ git__free(objects);
END_TEST
diff --git a/tests/t08-tag.c b/tests/t08-tag.c
index 216fb9dfc..44efb584d 100644
--- a/tests/t08-tag.c
+++ b/tests/t08-tag.c
@@ -189,12 +189,14 @@ BEGIN_TEST(write0, "write a tag to the repository and read it again")
must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/the-tag"));
must_be_true(git_oid_cmp(git_reference_oid(ref_tag), &tag_id) == 0);
must_pass(git_reference_delete(ref_tag));
+#ifndef GIT_WIN32
+ must_be_true((loose_object_mode(REPOSITORY_FOLDER, (git_object *)tag) & 0777) == GIT_OBJECT_FILE_MODE);
+#endif
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)tag));
git_tag_close(tag);
git_repository_free(repo);
-
END_TEST
BEGIN_TEST(write2, "Attempt to write a tag bearing the same name than an already existing tag")
@@ -263,6 +265,7 @@ BEGIN_TEST(write3, "Replace an already existing tag")
close_temp_repo(repo);
+ git_reference_free(ref_tag);
END_TEST
BEGIN_TEST(write4, "write a lightweight tag to the repository and read it again")
@@ -293,6 +296,8 @@ BEGIN_TEST(write4, "write a lightweight tag to the repository and read it again"
must_pass(git_tag_delete(repo, "light-tag"));
git_repository_free(repo);
+
+ git_reference_free(ref_tag);
END_TEST
BEGIN_TEST(write5, "Attempt to write a lightweight tag bearing the same name than an already existing tag")
@@ -331,6 +336,8 @@ BEGIN_TEST(delete0, "Delete an already existing tag")
must_fail(git_reference_lookup(&ref_tag, repo, "refs/tags/e90810b"));
close_temp_repo(repo);
+
+ git_reference_free(ref_tag);
END_TEST
BEGIN_SUITE(tag)
diff --git a/tests/t09-tree.c b/tests/t09-tree.c
index 3af06ea67..2341a1ca4 100644
--- a/tests/t09-tree.c
+++ b/tests/t09-tree.c
@@ -200,6 +200,10 @@ BEGIN_TEST(write3, "write a hierarchical tree from a memory")
// check data is correct
must_pass(git_tree_lookup(&tree, repo, &id_hiearar));
must_be_true(2 == git_tree_entrycount(tree));
+#ifndef GIT_WIN32
+ must_be_true((loose_object_dir_mode(TEMP_REPO_FOLDER, (git_object *)tree) & 0777) == GIT_OBJECT_DIR_MODE);
+ must_be_true((loose_object_mode(TEMP_REPO_FOLDER, (git_object *)tree) & 0777) == GIT_OBJECT_FILE_MODE);
+#endif
git_tree_close(tree);
close_temp_repo(repo);
diff --git a/tests/t10-refs.c b/tests/t10-refs.c
index c7bfe4eea..e5e722992 100644
--- a/tests/t10-refs.c
+++ b/tests/t10-refs.c
@@ -42,8 +42,8 @@ BEGIN_TEST(readtag0, "lookup a loose tag reference")
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&reference, repo, loose_tag_ref_name));
- must_be_true(reference->type & GIT_REF_OID);
- must_be_true((reference->type & GIT_REF_PACKED) == 0);
+ must_be_true(git_reference_type(reference) & GIT_REF_OID);
+ must_be_true(git_reference_is_packed(reference) == 0);
must_be_true(strcmp(reference->name, loose_tag_ref_name) == 0);
must_pass(git_object_lookup(&object, repo, git_reference_oid(reference), GIT_OBJ_ANY));
@@ -56,6 +56,8 @@ BEGIN_TEST(readtag0, "lookup a loose tag reference")
git_object_close(object);
git_repository_free(repo);
+
+ git_reference_free(reference);
END_TEST
BEGIN_TEST(readtag1, "lookup a loose tag reference that doesn't exist")
@@ -66,6 +68,8 @@ BEGIN_TEST(readtag1, "lookup a loose tag reference that doesn't exist")
must_fail(git_reference_lookup(&reference, repo, non_existing_tag_ref_name));
git_repository_free(repo);
+
+ git_reference_free(reference);
END_TEST
static const char *head_tracker_sym_ref_name = "head-tracker";
@@ -81,12 +85,12 @@ BEGIN_TEST(readsym0, "lookup a symbolic reference")
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&reference, repo, GIT_HEAD_FILE));
- must_be_true(reference->type & GIT_REF_SYMBOLIC);
- must_be_true((reference->type & GIT_REF_PACKED) == 0);
+ must_be_true(git_reference_type(reference) & GIT_REF_SYMBOLIC);
+ must_be_true(git_reference_is_packed(reference) == 0);
must_be_true(strcmp(reference->name, GIT_HEAD_FILE) == 0);
must_pass(git_reference_resolve(&resolved_ref, reference));
- must_be_true(resolved_ref->type == GIT_REF_OID);
+ must_be_true(git_reference_type(resolved_ref) == GIT_REF_OID);
must_pass(git_object_lookup(&object, repo, git_reference_oid(resolved_ref), GIT_OBJ_ANY));
must_be_true(object != NULL);
@@ -97,6 +101,9 @@ BEGIN_TEST(readsym0, "lookup a symbolic reference")
git_object_close(object);
git_repository_free(repo);
+
+ git_reference_free(reference);
+ git_reference_free(resolved_ref);
END_TEST
BEGIN_TEST(readsym1, "lookup a nested symbolic reference")
@@ -108,12 +115,12 @@ BEGIN_TEST(readsym1, "lookup a nested symbolic reference")
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&reference, repo, head_tracker_sym_ref_name));
- must_be_true(reference->type & GIT_REF_SYMBOLIC);
- must_be_true((reference->type & GIT_REF_PACKED) == 0);
+ must_be_true(git_reference_type(reference) & GIT_REF_SYMBOLIC);
+ must_be_true(git_reference_is_packed(reference) == 0);
must_be_true(strcmp(reference->name, head_tracker_sym_ref_name) == 0);
must_pass(git_reference_resolve(&resolved_ref, reference));
- must_be_true(resolved_ref->type == GIT_REF_OID);
+ must_be_true(git_reference_type(resolved_ref) == GIT_REF_OID);
must_pass(git_object_lookup(&object, repo, git_reference_oid(resolved_ref), GIT_OBJ_ANY));
must_be_true(object != NULL);
@@ -124,6 +131,9 @@ BEGIN_TEST(readsym1, "lookup a nested symbolic reference")
git_object_close(object);
git_repository_free(repo);
+
+ git_reference_free(reference);
+ git_reference_free(resolved_ref);
END_TEST
BEGIN_TEST(readsym2, "lookup the HEAD and resolve the master branch")
@@ -133,17 +143,22 @@ BEGIN_TEST(readsym2, "lookup the HEAD and resolve the master branch")
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&reference, repo, head_tracker_sym_ref_name));
- must_pass(git_reference_resolve(&resolved_ref, reference));
- comp_base_ref = resolved_ref;
+ must_pass(git_reference_resolve(&comp_base_ref, reference));
+ git_reference_free(reference);
must_pass(git_reference_lookup(&reference, repo, GIT_HEAD_FILE));
must_pass(git_reference_resolve(&resolved_ref, reference));
must_pass(git_oid_cmp(git_reference_oid(comp_base_ref), git_reference_oid(resolved_ref)));
+ git_reference_free(reference);
+ git_reference_free(resolved_ref);
must_pass(git_reference_lookup(&reference, repo, current_head_target));
must_pass(git_reference_resolve(&resolved_ref, reference));
must_pass(git_oid_cmp(git_reference_oid(comp_base_ref), git_reference_oid(resolved_ref)));
+ git_reference_free(reference);
+ git_reference_free(resolved_ref);
+ git_reference_free(comp_base_ref);
git_repository_free(repo);
END_TEST
@@ -160,6 +175,10 @@ BEGIN_TEST(readsym3, "lookup the master branch and then the HEAD")
must_pass(git_oid_cmp(git_reference_oid(master_ref), git_reference_oid(resolved_ref)));
git_repository_free(repo);
+
+ git_reference_free(reference);
+ git_reference_free(resolved_ref);
+ git_reference_free(master_ref);
END_TEST
static const char *packed_head_name = "refs/heads/packed";
@@ -173,8 +192,8 @@ BEGIN_TEST(readpacked0, "lookup a packed reference")
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&reference, repo, packed_head_name));
- must_be_true(reference->type & GIT_REF_OID);
- must_be_true((reference->type & GIT_REF_PACKED) != 0);
+ must_be_true(git_reference_type(reference) & GIT_REF_OID);
+ must_be_true(git_reference_is_packed(reference));
must_be_true(strcmp(reference->name, packed_head_name) == 0);
must_pass(git_object_lookup(&object, repo, git_reference_oid(reference), GIT_OBJ_ANY));
@@ -183,6 +202,8 @@ BEGIN_TEST(readpacked0, "lookup a packed reference")
git_object_close(object);
git_repository_free(repo);
+
+ git_reference_free(reference);
END_TEST
BEGIN_TEST(readpacked1, "assure that a loose reference is looked up before a packed reference")
@@ -192,11 +213,13 @@ BEGIN_TEST(readpacked1, "assure that a loose reference is looked up before a pac
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&reference, repo, packed_head_name));
must_pass(git_reference_lookup(&reference, repo, packed_test_head_name));
- must_be_true(reference->type & GIT_REF_OID);
- must_be_true((reference->type & GIT_REF_PACKED) == 0);
+ must_be_true(git_reference_type(reference) & GIT_REF_OID);
+ must_be_true(git_reference_is_packed(reference) == 0);
must_be_true(strcmp(reference->name, packed_test_head_name) == 0);
git_repository_free(repo);
+
+ git_reference_free(reference);
END_TEST
BEGIN_TEST(create0, "create a new symbolic reference")
@@ -219,13 +242,13 @@ BEGIN_TEST(create0, "create a new symbolic reference")
/* Ensure the reference can be looked-up... */
must_pass(git_reference_lookup(&looked_up_ref, repo, new_head_tracker));
- must_be_true(looked_up_ref->type & GIT_REF_SYMBOLIC);
- must_be_true((looked_up_ref->type & GIT_REF_PACKED) == 0);
+ must_be_true(git_reference_type(looked_up_ref) & GIT_REF_SYMBOLIC);
+ must_be_true(git_reference_is_packed(looked_up_ref) == 0);
must_be_true(strcmp(looked_up_ref->name, new_head_tracker) == 0);
/* ...peeled.. */
must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
- must_be_true(resolved_ref->type == GIT_REF_OID);
+ must_be_true(git_reference_type(resolved_ref) == GIT_REF_OID);
/* ...and that it points to the current master tip */
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
@@ -240,6 +263,10 @@ BEGIN_TEST(create0, "create a new symbolic reference")
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
close_temp_repo(repo2);
+
+ git_reference_free(new_reference);
+ git_reference_free(looked_up_ref);
+ git_reference_free(resolved_ref);
END_TEST
BEGIN_TEST(create1, "create a deep symbolic reference")
@@ -261,6 +288,10 @@ BEGIN_TEST(create1, "create a deep symbolic reference")
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
close_temp_repo(repo);
+
+ git_reference_free(new_reference);
+ git_reference_free(looked_up_ref);
+ git_reference_free(resolved_ref);
END_TEST
BEGIN_TEST(create2, "create a new OID reference")
@@ -283,8 +314,8 @@ BEGIN_TEST(create2, "create a new OID reference")
/* Ensure the reference can be looked-up... */
must_pass(git_reference_lookup(&looked_up_ref, repo, new_head));
- must_be_true(looked_up_ref->type & GIT_REF_OID);
- must_be_true((looked_up_ref->type & GIT_REF_PACKED) == 0);
+ must_be_true(git_reference_type(looked_up_ref) & GIT_REF_OID);
+ must_be_true(git_reference_is_packed(looked_up_ref) == 0);
must_be_true(strcmp(looked_up_ref->name, new_head) == 0);
/* ...and that it points to the current master tip */
@@ -299,6 +330,9 @@ BEGIN_TEST(create2, "create a new OID reference")
must_be_true(git_oid_cmp(&id, git_reference_oid(looked_up_ref)) == 0);
close_temp_repo(repo2);
+
+ git_reference_free(new_reference);
+ git_reference_free(looked_up_ref);
END_TEST
BEGIN_TEST(create3, "Can not create a new OID reference which targets at an unknown id")
@@ -349,6 +383,9 @@ BEGIN_TEST(overwrite0, "Overwrite an existing symbolic reference")
must_be_true(!strcmp(git_reference_target(ref), ref_master_name));
close_temp_repo(repo);
+
+ git_reference_free(ref);
+ git_reference_free(branch_ref);
END_TEST
BEGIN_TEST(overwrite1, "Overwrite an existing object id reference")
@@ -359,14 +396,14 @@ BEGIN_TEST(overwrite1, "Overwrite an existing object id reference")
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
- must_be_true(ref->type & GIT_REF_OID);
+ must_be_true(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
/* Create it */
must_pass(git_reference_create_oid(&ref, repo, ref_name, &id, 0));
must_pass(git_reference_lookup(&ref, repo, ref_test_name));
- must_be_true(ref->type & GIT_REF_OID);
+ must_be_true(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
/* Ensure we can't overwrite unless we force it */
@@ -378,6 +415,8 @@ BEGIN_TEST(overwrite1, "Overwrite an existing object id reference")
must_be_true(!git_oid_cmp(&id, git_reference_oid(ref)));
close_temp_repo(repo);
+
+ git_reference_free(ref);
END_TEST
BEGIN_TEST(overwrite2, "Overwrite an existing object id reference with a symbolic one")
@@ -388,7 +427,7 @@ BEGIN_TEST(overwrite2, "Overwrite an existing object id reference with a symboli
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
- must_be_true(ref->type & GIT_REF_OID);
+ must_be_true(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
must_pass(git_reference_create_oid(&ref, repo, ref_name, &id, 0));
@@ -401,6 +440,8 @@ BEGIN_TEST(overwrite2, "Overwrite an existing object id reference with a symboli
must_be_true(!strcmp(git_reference_target(ref), ref_master_name));
close_temp_repo(repo);
+
+ git_reference_free(ref);
END_TEST
BEGIN_TEST(overwrite3, "Overwrite an existing symbolic reference with an object id one")
@@ -411,7 +452,7 @@ BEGIN_TEST(overwrite3, "Overwrite an existing symbolic reference with an object
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
- must_be_true(ref->type & GIT_REF_OID);
+ must_be_true(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
/* Create the symbolic ref */
@@ -426,17 +467,18 @@ BEGIN_TEST(overwrite3, "Overwrite an existing symbolic reference with an object
must_be_true(!git_oid_cmp(git_reference_oid(ref), &id));
close_temp_repo(repo);
+
+ git_reference_free(ref);
END_TEST
BEGIN_TEST(pack0, "create a packfile for an empty folder")
git_repository *repo;
char temp_path[GIT_PATH_MAX];
- const int mode = 0755; /* or 0777 ? */
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
git_path_join_n(temp_path, 3, repo->path_repository, GIT_REFS_HEADS_DIR, "empty_dir");
- must_pass(git_futils_mkdir_r(temp_path, mode));
+ must_pass(git_futils_mkdir_r(temp_path, GIT_REFS_DIR_MODE));
must_pass(git_reference_packall(repo));
@@ -452,7 +494,7 @@ BEGIN_TEST(pack1, "create a packfile from all the loose rn a repo")
/* Ensure a known loose ref can be looked up */
must_pass(git_reference_lookup(&reference, repo, loose_tag_ref_name));
- must_be_true((reference->type & GIT_REF_PACKED) == 0);
+ must_be_true(git_reference_is_packed(reference) == 0);
must_be_true(strcmp(reference->name, loose_tag_ref_name) == 0);
/*
@@ -468,7 +510,7 @@ BEGIN_TEST(pack1, "create a packfile from all the loose rn a repo")
/* Ensure the known ref can still be looked up but is now packed */
must_pass(git_reference_lookup(&reference, repo, loose_tag_ref_name));
- must_be_true((reference->type & GIT_REF_PACKED) != 0);
+ must_be_true(git_reference_is_packed(reference));
must_be_true(strcmp(reference->name, loose_tag_ref_name) == 0);
/* Ensure the known ref has been removed from the loose folder structure */
@@ -476,6 +518,8 @@ BEGIN_TEST(pack1, "create a packfile from all the loose rn a repo")
must_pass(!git_futils_exists(temp_path));
close_temp_repo(repo);
+
+ git_reference_free(reference);
END_TEST
BEGIN_TEST(rename0, "rename a loose reference")
@@ -494,7 +538,7 @@ BEGIN_TEST(rename0, "rename a loose reference")
must_pass(git_reference_lookup(&looked_up_ref, repo, loose_tag_ref_name));
/* ... which is indeed loose */
- must_be_true((looked_up_ref->type & GIT_REF_PACKED) == 0);
+ must_be_true(git_reference_is_packed(looked_up_ref) == 0);
/* Now that the reference is renamed... */
must_pass(git_reference_rename(looked_up_ref, new_name, 0));
@@ -508,14 +552,17 @@ BEGIN_TEST(rename0, "rename a loose reference")
must_be_true(!strcmp(another_looked_up_ref->name, new_name));
/* .. the ref is still loose... */
- must_be_true((another_looked_up_ref->type & GIT_REF_PACKED) == 0);
- must_be_true((looked_up_ref->type & GIT_REF_PACKED) == 0);
+ must_be_true(git_reference_is_packed(another_looked_up_ref) == 0);
+ must_be_true(git_reference_is_packed(looked_up_ref) == 0);
/* ...and the ref can be found in the file system */
git_path_join(temp_path, repo->path_repository, new_name);
must_pass(git_futils_exists(temp_path));
close_temp_repo(repo);
+
+ git_reference_free(looked_up_ref);
+ git_reference_free(another_looked_up_ref);
END_TEST
BEGIN_TEST(rename1, "rename a packed reference (should make it loose)")
@@ -534,7 +581,7 @@ BEGIN_TEST(rename1, "rename a packed reference (should make it loose)")
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
/* .. and it's packed */
- must_be_true((looked_up_ref->type & GIT_REF_PACKED) != 0);
+ must_be_true(git_reference_is_packed(looked_up_ref) != 0);
/* Now that the reference is renamed... */
must_pass(git_reference_rename(looked_up_ref, brand_new_name, 0));
@@ -548,14 +595,17 @@ BEGIN_TEST(rename1, "rename a packed reference (should make it loose)")
must_be_true(!strcmp(another_looked_up_ref->name, brand_new_name));
/* .. the ref is no longer packed... */
- must_be_true((another_looked_up_ref->type & GIT_REF_PACKED) == 0);
- must_be_true((looked_up_ref->type & GIT_REF_PACKED) == 0);
+ must_be_true(git_reference_is_packed(another_looked_up_ref) == 0);
+ must_be_true(git_reference_is_packed(looked_up_ref) == 0);
/* ...and the ref now happily lives in the file system */
git_path_join(temp_path, repo->path_repository, brand_new_name);
must_pass(git_futils_exists(temp_path));
close_temp_repo(repo);
+
+ git_reference_free(looked_up_ref);
+ git_reference_free(another_looked_up_ref);
END_TEST
BEGIN_TEST(rename2, "renaming a packed reference does not pack another reference which happens to be in both loose and pack state")
@@ -574,13 +624,13 @@ BEGIN_TEST(rename2, "renaming a packed reference does not pack another reference
must_pass(git_reference_lookup(&another_looked_up_ref, repo, packed_test_head_name));
/* Ensure it's loose */
- must_be_true((another_looked_up_ref->type & GIT_REF_PACKED) == 0);
+ must_be_true(git_reference_is_packed(another_looked_up_ref) == 0);
/* Lookup the reference to rename */
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
/* Ensure it's packed */
- must_be_true((looked_up_ref->type & GIT_REF_PACKED) != 0);
+ must_be_true(git_reference_is_packed(looked_up_ref) != 0);
/* Now that the reference is renamed... */
must_pass(git_reference_rename(looked_up_ref, brand_new_name, 0));
@@ -589,12 +639,15 @@ BEGIN_TEST(rename2, "renaming a packed reference does not pack another reference
must_pass(git_reference_lookup(&another_looked_up_ref, repo, packed_test_head_name));
/* Ensure it's loose */
- must_be_true((another_looked_up_ref->type & GIT_REF_PACKED) == 0);
+ must_be_true(git_reference_is_packed(another_looked_up_ref) == 0);
/* Ensure the other ref still exists on the file system */
must_pass(git_futils_exists(temp_path));
close_temp_repo(repo);
+
+ git_reference_free(looked_up_ref);
+ git_reference_free(another_looked_up_ref);
END_TEST
BEGIN_TEST(rename3, "can not rename a reference with the name of an existing reference")
@@ -614,6 +667,8 @@ BEGIN_TEST(rename3, "can not rename a reference with the name of an existing ref
must_be_true(!strcmp(looked_up_ref->name, packed_head_name));
close_temp_repo(repo);
+
+ git_reference_free(looked_up_ref);
END_TEST
BEGIN_TEST(rename4, "can not rename a reference with an invalid name")
@@ -636,6 +691,8 @@ BEGIN_TEST(rename4, "can not rename a reference with an invalid name")
must_be_true(!strcmp(looked_up_ref->name, packed_test_head_name));
close_temp_repo(repo);
+
+ git_reference_free(looked_up_ref);
END_TEST
BEGIN_TEST(rename5, "can force-rename a packed reference with the name of an existing loose and packed reference")
@@ -661,6 +718,8 @@ BEGIN_TEST(rename5, "can force-rename a packed reference with the name of an exi
must_fail(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
close_temp_repo(repo);
+
+ git_reference_free(looked_up_ref);
END_TEST
BEGIN_TEST(rename6, "can force-rename a loose reference with the name of an existing loose reference")
@@ -686,6 +745,8 @@ BEGIN_TEST(rename6, "can force-rename a loose reference with the name of an exis
must_fail(git_reference_lookup(&looked_up_ref, repo, "refs/heads/br2"));
close_temp_repo(repo);
+
+ git_reference_free(looked_up_ref);
END_TEST
static const char *ref_one_name = "refs/heads/one/branch";
@@ -700,7 +761,7 @@ BEGIN_TEST(rename7, "can not overwrite name of existing reference")
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
- must_be_true(ref->type & GIT_REF_OID);
+ must_be_true(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
@@ -718,6 +779,11 @@ BEGIN_TEST(rename7, "can not overwrite name of existing reference")
must_fail(git_reference_lookup(&ref_one_new, repo, ref_one_name_new));
close_temp_repo(repo);
+
+ git_reference_free(ref);
+ git_reference_free(ref_one);
+ git_reference_free(ref_one_new);
+ git_reference_free(ref_two);
END_TEST
static const char *ref_two_name_new = "refs/heads/two/two";
@@ -730,7 +796,7 @@ BEGIN_TEST(rename8, "can be renamed to a new name prefixed with the old name")
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
- must_be_true(ref->type & GIT_REF_OID);
+ must_be_true(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
@@ -749,6 +815,10 @@ BEGIN_TEST(rename8, "can be renamed to a new name prefixed with the old name")
must_fail(git_reference_lookup(&looked_up_ref, repo, ref_two_name));
close_temp_repo(repo);
+
+ git_reference_free(ref);
+ git_reference_free(ref_two);
+ git_reference_free(looked_up_ref);
END_TEST
BEGIN_TEST(rename9, "can move a reference to a upper reference hierarchy")
@@ -759,7 +829,7 @@ BEGIN_TEST(rename9, "can move a reference to a upper reference hierarchy")
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
- must_be_true(ref->type & GIT_REF_OID);
+ must_be_true(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
@@ -795,7 +865,7 @@ BEGIN_TEST(delete0, "deleting a ref which is both packed and loose should remove
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_test_head_name));
/* Ensure it's the loose version that has been found */
- must_be_true((looked_up_ref->type & GIT_REF_PACKED) == 0);
+ must_be_true(git_reference_is_packed(looked_up_ref) == 0);
/* Now that the reference is deleted... */
must_pass(git_reference_delete(looked_up_ref));
@@ -807,6 +877,42 @@ BEGIN_TEST(delete0, "deleting a ref which is both packed and loose should remove
must_pass(!git_futils_exists(temp_path));
close_temp_repo(repo);
+
+ git_reference_free(another_looked_up_ref);
+END_TEST
+
+BEGIN_TEST(delete1, "can delete a just packed reference")
+ git_reference *ref;
+ git_repository *repo;
+ git_oid id;
+ const char *new_ref = "refs/heads/new_ref";
+
+ git_oid_fromstr(&id, current_master_tip);
+
+ must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
+
+ /* Create and write the new object id reference */
+ must_pass(git_reference_create_oid(&ref, repo, new_ref, &id, 0));
+
+ /* Lookup the reference */
+ must_pass(git_reference_lookup(&ref, repo, new_ref));
+
+ /* Ensure it's a loose reference */
+ must_be_true(git_reference_is_packed(ref) == 0);
+
+ /* Pack all existing references */
+ must_pass(git_reference_packall(repo));
+
+ /* Reload the reference from disk */
+ must_pass(git_reference_reload(ref));
+
+ /* Ensure it's a packed reference */
+ must_be_true(git_reference_is_packed(ref) == 1);
+
+ /* This should pass */
+ must_pass(git_reference_delete(ref));
+
+ close_temp_repo(repo);
END_TEST
static int ensure_refname_normalized(int is_oid_ref, const char *input_refname, const char *expected_refname)
@@ -1102,6 +1208,9 @@ BEGIN_TEST(reflog0, "write a reflog for a given reference and ensure it can be r
git_signature_free(committer);
git_reflog_free(reflog);
close_temp_repo(repo2);
+
+ git_reference_free(ref);
+ git_reference_free(lookedup_ref);
END_TEST
BEGIN_TEST(reflog1, "avoid writing an obviously wrong reflog")
@@ -1130,6 +1239,8 @@ BEGIN_TEST(reflog1, "avoid writing an obviously wrong reflog")
git_signature_free(committer);
close_temp_repo(repo);
+
+ git_reference_free(ref);
END_TEST
BEGIN_SUITE(refs)
@@ -1173,6 +1284,7 @@ BEGIN_SUITE(refs)
ADD_TEST(rename9);
ADD_TEST(delete0);
+ ADD_TEST(delete1);
ADD_TEST(list0);
ADD_TEST(list1);
diff --git a/tests/t12-repo.c b/tests/t12-repo.c
index de921f9ca..47dc852f3 100644
--- a/tests/t12-repo.c
+++ b/tests/t12-repo.c
@@ -173,7 +173,7 @@ END_TEST
BEGIN_TEST(init2, "Initialize and open a bare repo with a relative path escaping out of the current working directory")
char path_repository[GIT_PATH_MAX];
char current_workdir[GIT_PATH_MAX];
- const int mode = 0755; /* or 0777 ? */
+ const mode_t mode = 0777;
git_repository* repo;
must_pass(p_getcwd(current_workdir, sizeof(current_workdir)));
@@ -232,7 +232,7 @@ BEGIN_TEST(open2, "Open a bare repository with a relative path escaping out of t
char current_workdir[GIT_PATH_MAX];
char path_repository[GIT_PATH_MAX];
- const int mode = 0755; /* or 0777 ? */
+ const mode_t mode = 0777;
git_repository* repo;
/* Setup the repository to open */
@@ -286,6 +286,8 @@ BEGIN_TEST(detached0, "test if HEAD is detached")
must_be_true(git_repository_head_detached(repo) == 0);
git_repository_free(repo);
+
+ git_reference_free(ref);
END_TEST
BEGIN_TEST(orphan0, "test if HEAD is orphan")
@@ -305,6 +307,8 @@ BEGIN_TEST(orphan0, "test if HEAD is orphan")
must_be_true(git_repository_head_orphan(repo) == 0);
git_repository_free(repo);
+
+ git_reference_free(ref);
END_TEST
#define DISCOVER_FOLDER TEMP_REPO_FOLDER "discover.git"
@@ -351,7 +355,7 @@ static int write_file(const char *path, const char *content)
return error;
}
- file = git_futils_creat_withpath(path, 0644);
+ file = git_futils_creat_withpath(path, 0777, 0666);
if (file < GIT_SUCCESS)
return file;
@@ -384,7 +388,7 @@ BEGIN_TEST(discover0, "test discover")
char repository_path[GIT_PATH_MAX];
char sub_repository_path[GIT_PATH_MAX];
char found_path[GIT_PATH_MAX];
- int mode = 0755;
+ const mode_t mode = 0777;
git_futils_mkdir_r(DISCOVER_FOLDER, mode);
must_pass(append_ceiling_dir(ceiling_dirs, TEMP_REPO_FOLDER));
diff --git a/tests/t15-config.c b/tests/t15-config.c
index c4cb590f5..a97f82067 100644
--- a/tests/t15-config.c
+++ b/tests/t15-config.c
@@ -319,7 +319,7 @@ BEGIN_TEST(config16, "add a variable in a new section")
/* As the section wasn't removed, owerwrite the file */
must_pass(git_filebuf_open(&buf, CONFIG_BASE "/config10", 0));
must_pass(git_filebuf_write(&buf, "[empty]\n", strlen("[empty]\n")));
- must_pass(git_filebuf_commit(&buf));
+ must_pass(git_filebuf_commit(&buf, 0666));
END_TEST
BEGIN_TEST(config17, "prefixes aren't broken")
diff --git a/tests/t18-status.c b/tests/t18-status.c
index ee9c5c668..3b75472ad 100644
--- a/tests/t18-status.c
+++ b/tests/t18-status.c
@@ -37,7 +37,7 @@ static int file_create(const char *filename, const char *content)
{
int fd;
- fd = p_creat(filename, 0644);
+ fd = p_creat(filename, 0666);
if (fd == 0)
return GIT_ERROR;
if (p_write(fd, content, strlen(content)) != 0)
@@ -136,7 +136,7 @@ BEGIN_TEST(statuscb0, "test retrieving status for worktree of repository")
struct status_entry_counts counts;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
- must_pass(git_futils_mv_atomic(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
+ must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
memset(&counts, 0x0, sizeof(struct status_entry_counts));
@@ -223,7 +223,7 @@ BEGIN_TEST(statuscb2, "test retrieving status for a purged worktree of an valid
struct status_entry_counts counts;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
- must_pass(git_futils_mv_atomic(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
+ must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
/* Purging the working */
@@ -309,12 +309,12 @@ BEGIN_TEST(statuscb3, "test retrieving status for a worktree where a file and a
struct status_entry_counts counts;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
- must_pass(git_futils_mv_atomic(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
+ must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
- must_pass(git_futils_mv_atomic(TEMP_REPO_FOLDER "current_file", TEMP_REPO_FOLDER "swap"));
- must_pass(git_futils_mv_atomic(TEMP_REPO_FOLDER "subdir", TEMP_REPO_FOLDER "current_file"));
- must_pass(git_futils_mv_atomic(TEMP_REPO_FOLDER "swap", TEMP_REPO_FOLDER "subdir"));
+ must_pass(p_rename(TEMP_REPO_FOLDER "current_file", TEMP_REPO_FOLDER "swap"));
+ must_pass(p_rename(TEMP_REPO_FOLDER "subdir", TEMP_REPO_FOLDER "current_file"));
+ must_pass(p_rename(TEMP_REPO_FOLDER "swap", TEMP_REPO_FOLDER "subdir"));
must_pass(file_create(TEMP_REPO_FOLDER ".HEADER", "dummy"));
must_pass(file_create(TEMP_REPO_FOLDER "42-is-not-prime.sigh", "dummy"));
@@ -341,7 +341,7 @@ BEGIN_TEST(singlestatus0, "test retrieving status for single file")
int i;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
- must_pass(git_futils_mv_atomic(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
+ must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
for (i = 0; i < ENTRY_COUNT0; ++i) {
@@ -360,7 +360,7 @@ BEGIN_TEST(singlestatus1, "test retrieving status for nonexistent file")
int error;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
- must_pass(git_futils_mv_atomic(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
+ must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
// "nonexistent" does not exist in HEAD, Index or the worktree
@@ -400,7 +400,7 @@ BEGIN_TEST(singlestatus3, "test retrieving status for a new file in an empty rep
must_pass(remove_placeholders(TEST_STD_REPO_FOLDER, "dummy-marker.txt"));
git_path_join(file_path, TEMP_REPO_FOLDER, filename);
- fd = p_creat(file_path, 0644);
+ fd = p_creat(file_path, 0666);
must_pass(fd);
must_pass(p_write(fd, "new_file\n", 9));
must_pass(p_close(fd));
@@ -421,7 +421,7 @@ BEGIN_TEST(singlestatus4, "can't determine the status for a folder")
int error;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
- must_pass(git_futils_mv_atomic(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
+ must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
error = git_status_file(&status_flags, repo, "subdir");
diff --git a/tests/test_helpers.c b/tests/test_helpers.c
index cb95607e1..31e38bf6a 100644
--- a/tests/test_helpers.c
+++ b/tests/test_helpers.c
@@ -42,7 +42,7 @@ int write_object_data(char *file, void *data, size_t len)
int write_object_files(const char *odb_dir, object_data *d)
{
- if (p_mkdir(odb_dir, 0755) < 0) {
+ if (p_mkdir(odb_dir, GIT_OBJECT_DIR_MODE) < 0) {
int err = errno;
fprintf(stderr, "can't make directory \"%s\"", odb_dir);
if (err == EEXIST)
@@ -51,7 +51,7 @@ int write_object_files(const char *odb_dir, object_data *d)
return -1;
}
- if ((p_mkdir(d->dir, 0755) < 0) && (errno != EEXIST)) {
+ if ((p_mkdir(d->dir, GIT_OBJECT_DIR_MODE) < 0) && (errno != EEXIST)) {
fprintf(stderr, "can't make object directory \"%s\"\n", d->dir);
return -1;
}
@@ -82,7 +82,7 @@ int remove_object_files(const char *odb_dir, object_data *d)
return 0;
}
-int remove_loose_object(const char *repository_folder, git_object *object)
+void locate_loose_object(const char *repository_folder, git_object *object, char **out, char **out_folder)
{
static const char *objects_folder = "objects/";
@@ -104,6 +104,54 @@ int remove_loose_object(const char *repository_folder, git_object *object)
ptr += GIT_OID_HEXSZ + 1;
*ptr = 0;
+ *out = full_path;
+
+ if (out_folder)
+ *out_folder = top_folder;
+}
+
+int loose_object_mode(const char *repository_folder, git_object *object)
+{
+ char *object_path;
+ struct stat st;
+
+ locate_loose_object(repository_folder, object, &object_path, NULL);
+ if (p_stat(object_path, &st) < 0)
+ return 0;
+ free(object_path);
+
+ return st.st_mode;
+}
+
+int loose_object_dir_mode(const char *repository_folder, git_object *object)
+{
+ char *object_path;
+ size_t pos;
+ struct stat st;
+
+ locate_loose_object(repository_folder, object, &object_path, NULL);
+
+ pos = strlen(object_path);
+ while (pos--) {
+ if (object_path[pos] == '/') {
+ object_path[pos] = 0;
+ break;
+ }
+ }
+
+ if (p_stat(object_path, &st) < 0)
+ return 0;
+ free(object_path);
+
+ return st.st_mode;
+}
+
+int remove_loose_object(const char *repository_folder, git_object *object)
+{
+ char *full_path, *top_folder;
+
+ locate_loose_object(repository_folder, object, &full_path, &top_folder);
+
if (p_unlink(full_path) < 0) {
fprintf(stderr, "can't delete object file \"%s\"\n", full_path);
return -1;
@@ -116,7 +164,7 @@ int remove_loose_object(const char *repository_folder, git_object *object)
return -1;
}
- free(full_path);
+ git__free(full_path);
return GIT_SUCCESS;
}
@@ -141,7 +189,7 @@ int copy_file(const char *src, const char *dst)
if (git_futils_readbuffer(&source_buf, src) < GIT_SUCCESS)
return GIT_ENOTFOUND;
- dst_fd = git_futils_creat_withpath(dst, 0644);
+ dst_fd = git_futils_creat_withpath(dst, 0777, 0666);
if (dst_fd < 0)
goto cleanup;
diff --git a/tests/test_helpers.h b/tests/test_helpers.h
index 53361b7b1..16a3a2ced 100644
--- a/tests/test_helpers.h
+++ b/tests/test_helpers.h
@@ -63,6 +63,11 @@ extern int remove_object_files(const char *odb_dir, object_data *d);
extern int cmp_objects(git_rawobj *o, object_data *d);
+extern void locate_loose_object(const char *odb_dir, git_object *object, char **out, char **out_folder);
+
+extern int loose_object_mode(const char *odb_dir, git_object *object);
+extern int loose_object_dir_mode(const char *odb_dir, git_object *object);
+
extern int remove_loose_object(const char *odb_dir, git_object *object);
extern int cmp_files(const char *a, const char *b);
diff --git a/tests/test_lib.c b/tests/test_lib.c
index e67ad347a..9d3cba1a6 100755
--- a/tests/test_lib.c
+++ b/tests/test_lib.c
@@ -88,8 +88,8 @@ static void fail_test(git_test *tc, const char *file, int line, const char *mess
tc->failed = 1;
tc->message = strdup(message);
tc->failed_pos = strdup(buf);
- tc->error_stack = git_errno;
- git_errno = NULL;
+ tc->error_stack = GIT_GLOBAL->git_errno;
+ GIT_GLOBAL->git_errno = NULL;
if (last_error)
tc->error_message = strdup(last_error);
diff --git a/tests/test_lib.h b/tests/test_lib.h
index 9d90e4847..7552ebf12 100755
--- a/tests/test_lib.h
+++ b/tests/test_lib.h
@@ -7,6 +7,7 @@
#include <string.h>
#include "common.h"
+#include "global.h"
#include <git2.h>
#define DECLARE_SUITE(SNAME) extern git_testsuite *libgit2_suite_##SNAME(void)
diff --git a/tests/test_main.c b/tests/test_main.c
index c9f8da3a4..9961ffd6b 100644
--- a/tests/test_main.c
+++ b/tests/test_main.c
@@ -26,6 +26,8 @@
#include <string.h>
#include <git2.h>
+#include "posix.h"
+
#include "test_lib.h"
#include "test_helpers.h"
@@ -81,6 +83,8 @@ main(int GIT_UNUSED(argc), char *GIT_UNUSED(argv[]))
GIT_UNUSED_ARG(argc);
GIT_UNUSED_ARG(argv);
+ p_umask(0);
+
failures = 0;
for (i = 0; i < GIT_SUITE_COUNT; ++i)