From 11d51ca63184b760e2537bbe08c5ca4c63bd4854 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 26 Oct 2011 16:43:55 -0700 Subject: windows: Add support for non-UTF codepages Our previous assumption that all paths in Windows are encoded in UTF-8 is rather weak, specially when considering that Git is encoding-agnostic. These set of functions allow the user to change the library's active codepage globally, so it is possible to access paths and files on all international versions of Windows. Note that the default encoding here is UTF-8 because we assume that 99% of all Git repositories will be in UTF-8. Also, if you use non-ascii characters in paths, anywhere, please burn on a fire. --- include/git2/windows.h | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 include/git2/windows.h (limited to 'include/git2') 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 + -- cgit v1.2.1 From da37654d04617b4dacce6e7a4796007d2854624d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 27 Oct 2011 22:33:31 -0700 Subject: tree: Add traversal in post-order --- include/git2/tree.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'include/git2') diff --git a/include/git2/tree.h b/include/git2/tree.h index 8d638f723..68d82351a 100644 --- a/include/git2/tree.h +++ b/include/git2/tree.h @@ -282,6 +282,36 @@ GIT_EXTERN(int) git_treebuilder_write(git_oid *oid, git_repository *repo, git_tr * entry, GIT_EINVALIDPATH or an error code */ GIT_EXTERN(int) git_tree_frompath(git_tree **parent_out, git_tree *root, const char *treeentry_path); + +/** Callback for the tree traversal method */ +typedef int (*git_treewalk_cb)(const char *root, git_tree_entry *entry); + +/** 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); + /** @} */ GIT_END_DECL #endif -- cgit v1.2.1 From 3286c408eccb18c525ca123383f3ebf5097441bc Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 28 Oct 2011 14:51:13 -0700 Subject: global: Properly use `git__` memory wrappers Ensure that all memory related functions (malloc, calloc, strdup, free, etc) are using their respective `git__` wrappers. --- include/git2/oid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/git2') 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); -- cgit v1.2.1 From a46ec45746f965f2895098e058979225d92d66e5 Mon Sep 17 00:00:00 2001 From: schu Date: Wed, 10 Aug 2011 16:19:42 +0200 Subject: refs: split internal and external references Currently libgit2 shares pointers to its internal reference cache with the user. This leads to several problems like invalidation of reference pointers when reordering the cache or manipulation of the cache from user side. Give each user its own git_reference instead of leaking the internal representation (struct reference). Add the following new API functions: * git_reference_free * git_reference_is_packed Signed-off-by: schu --- include/git2/refs.h | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'include/git2') diff --git a/include/git2/refs.h b/include/git2/refs.h index c319bfb3d..773ae445c 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. @@ -173,7 +170,9 @@ 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. + * + * The reference will be immediately renamed in-memory * and on disk. * */ @@ -200,9 +199,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 +249,21 @@ 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 is packed + * + * @param ref git_reference + * @return 0 in case it's not packed; 1 otherwise + */ +GIT_EXTERN(int) git_reference_is_packed(git_reference *ref); + +/** + * Free the given reference + * + * @param ref git_reference + */ +GIT_EXTERN(void) git_reference_free(git_reference *ref); + /** @} */ GIT_END_DECL #endif -- cgit v1.2.1 From d4a0b124d00c70933d7c6ac9065c401cc2d70b2e Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 30 Oct 2011 21:58:33 -0700 Subject: refs: Partial rewrite for read-only refs This new version of the references code is significantly faster and hopefully easier to read. External API stays the same. A new method `git_reference_reload()` has been added to force updating a memory reference from disk. In-memory references are no longer updated automagically -- this was killing us. If a reference is deleted externally and the user doesn't reload the memory object, nothing critical happens: any functions using that reference should fail gracefully (e.g. deletion, renaming, and so on). All generated references from the API are read only and must be free'd by the user. There is no reference counting and no traces of generated references are kept in the library. There is no longer an internal representation for references. There is only one reference struct `git_reference`, and symbolic/oid targets are stored inside an union. Packfile references are stored using an optimized struct with flex array for reference names. This should significantly reduce the memory cost of loading the packfile from disk. --- include/git2/refs.h | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) (limited to 'include/git2') diff --git a/include/git2/refs.h b/include/git2/refs.h index 773ae445c..82c5d8881 100644 --- a/include/git2/refs.h +++ b/include/git2/refs.h @@ -116,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 @@ -170,11 +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 given git_reference will be updated. + * 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); @@ -186,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); @@ -250,13 +265,33 @@ 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 is packed + * Check if a reference has been loaded from a packfile * - * @param ref git_reference + * @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 * -- cgit v1.2.1 From a15c550db8b0552902e58c9bf2194005fb7fb0e9 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 16 Nov 2011 14:09:44 +0100 Subject: threads: Fix the shared global state with TLS See `global.c` for a description of what we're doing. When libgit2 is built with GIT_THREADS support, the threading system must be explicitly initialized with `git_threads_init()`. --- include/git2/common.h | 13 ---------- include/git2/thread-utils.h | 60 --------------------------------------------- include/git2/threads.h | 48 ++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 73 deletions(-) delete mode 100644 include/git2/thread-utils.h create mode 100644 include/git2/threads.h (limited to 'include/git2') 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 #include @@ -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/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 + -- cgit v1.2.1 From 9432af36fc62ee22d76fb927b8be73e123ba3f3c Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 17 Nov 2011 01:23:19 +0100 Subject: Rename `git_tree_frompath` to `git_tree_get_subtree` That makes more sense to me. --- include/git2/tree.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'include/git2') diff --git a/include/git2/tree.h b/include/git2/tree.h index 68d82351a..2ff167f44 100644 --- a/include/git2/tree.h +++ b/include/git2/tree.h @@ -269,19 +269,19 @@ 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); -- cgit v1.2.1 From 2ba14f2367b14187e1714f32c11236476c22ddfa Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 17 Nov 2011 02:13:46 +0100 Subject: tree: Add payload to `git_tree_walk` --- include/git2/tree.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/git2') diff --git a/include/git2/tree.h b/include/git2/tree.h index 2ff167f44..bd89de34f 100644 --- a/include/git2/tree.h +++ b/include/git2/tree.h @@ -284,7 +284,7 @@ GIT_EXTERN(int) git_treebuilder_write(git_oid *oid, git_repository *repo, git_tr 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); +typedef int (*git_treewalk_cb)(const char *root, git_tree_entry *entry, void *payload); /** Tree traversal modes */ enum git_treewalk_mode { @@ -310,7 +310,7 @@ enum git_treewalk_mode { * @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); +GIT_EXTERN(int) git_tree_walk(git_tree *walk, git_treewalk_cb callback, int mode, void *payload); /** @} */ GIT_END_DECL -- cgit v1.2.1 From 2cbca8b06cb7cab08d916438a63e19734256b3fa Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 18 Nov 2011 01:43:27 +0100 Subject: include: Unify internal include strategies Do not add the `git2` path to internal includes, or that will cause an extra path dependency. --- include/git2/indexer.h | 4 ++-- include/git2/refspec.h | 2 +- include/git2/remote.h | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'include/git2') 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/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 -- cgit v1.2.1