summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt14
-rw-r--r--include/git2/refs.h8
-rw-r--r--include/git2/repository.h19
-rw-r--r--include/git2/sys/repository.h20
-rw-r--r--src/path.h5
-rw-r--r--src/refs.c67
-rw-r--r--src/refs.h2
-rw-r--r--tests-clar/clar_libgit2.c1
-rw-r--r--tests-clar/refs/unicode.c15
9 files changed, 87 insertions, 64 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 62ebbf4e5..c7414996b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,9 +27,14 @@ OPTION( BUILD_EXAMPLES "Build library usage example apps" OFF )
OPTION( TAGS "Generate tags" OFF )
OPTION( PROFILE "Generate profiling information" OFF )
OPTION( ENABLE_TRACE "Enables tracing support" OFF )
-OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF )
+OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF )
-OPTION( ANDROID "Build for android NDK" OFF )
+OPTION( ANDROID "Build for android NDK" OFF )
+
+OPTION( USE_ICONV "Link with and use iconv library" OFF )
+IF(APPLE)
+ SET( USE_ICONV ON )
+ENDIF()
IF(MSVC)
# This option is only available when building with MSVC. By default, libgit2
@@ -58,8 +63,11 @@ FUNCTION(TARGET_OS_LIBRARIES target)
TARGET_LINK_LIBRARIES(${target} socket nsl)
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
TARGET_LINK_LIBRARIES(${target} rt)
- ELSEIF(APPLE)
+ ENDIF()
+
+ IF(USE_ICONV)
TARGET_LINK_LIBRARIES(${target} iconv)
+ ADD_DEFINITIONS(-DGIT_USE_ICONV)
ENDIF()
IF(THREADSAFE)
diff --git a/include/git2/refs.h b/include/git2/refs.h
index 4871e9820..4041947f6 100644
--- a/include/git2/refs.h
+++ b/include/git2/refs.h
@@ -453,7 +453,7 @@ GIT_EXTERN(int) git_reference_is_remote(git_reference *ref);
GIT_EXTERN(int) git_reference_is_tag(git_reference *ref);
typedef enum {
- GIT_REF_FORMAT_NORMAL = 0,
+ GIT_REF_FORMAT_NORMAL = 0u,
/**
* Control whether one-level refnames are accepted
@@ -461,7 +461,7 @@ typedef enum {
* components). Those are expected to be written only using
* uppercase letters and underscore (FETCH_HEAD, ...)
*/
- GIT_REF_FORMAT_ALLOW_ONELEVEL = (1 << 0),
+ GIT_REF_FORMAT_ALLOW_ONELEVEL = (1u << 0),
/**
* Interpret the provided name as a reference pattern for a
@@ -470,14 +470,14 @@ typedef enum {
* in place of a one full pathname component
* (e.g., foo/<star>/bar but not foo/bar<star>).
*/
- GIT_REF_FORMAT_REFSPEC_PATTERN = (1 << 1),
+ GIT_REF_FORMAT_REFSPEC_PATTERN = (1u << 1),
/**
* Interpret the name as part of a refspec in shorthand form
* so the `ONELEVEL` naming rules aren't enforced and 'master'
* becomes a valid name.
*/
- GIT_REF_FORMAT_REFSPEC_SHORTHAND = (1 << 2),
+ GIT_REF_FORMAT_REFSPEC_SHORTHAND = (1u << 2),
} git_reference_normalize_t;
/**
diff --git a/include/git2/repository.h b/include/git2/repository.h
index 28d8400f2..b4d561992 100644
--- a/include/git2/repository.h
+++ b/include/git2/repository.h
@@ -288,25 +288,6 @@ GIT_EXTERN(int) git_repository_init_ext(
git_repository_init_options *opts);
/**
- * Update the filesystem config settings for an open repository
- *
- * When a repository is initialized, config values are set based on the
- * properties of the filesystem that the repository is on, such as
- * "core.ignorecase", "core.filemode", "core.symlinks", etc. If the
- * repository is moved to a new filesystem, these properties may no
- * longer be correct and API calls may not behave as expected. This
- * call reruns the phase of repository initialization that sets those
- * properties to compensate for the current filesystem of the repo.
- *
- * @param repo A repository object
- * @param recurse_submodules Should submodules be reset recursively
- * @returrn 0 on success, < 0 on error
- */
-GIT_EXTERN(int) git_repository_reset_filesystem(
- git_repository *repo,
- int recurse_submodules);
-
-/**
* Retrieve and resolve the reference pointed at by HEAD.
*
* The returned `git_reference` will be owned by caller and
diff --git a/include/git2/sys/repository.h b/include/git2/sys/repository.h
index ba3d65ae5..e77b1dcba 100644
--- a/include/git2/sys/repository.h
+++ b/include/git2/sys/repository.h
@@ -27,7 +27,6 @@ GIT_BEGIN_DECL
*/
GIT_EXTERN(int) git_repository_new(git_repository **out);
-
/**
* Reset all the internal state in a repository.
*
@@ -42,6 +41,25 @@ GIT_EXTERN(int) git_repository_new(git_repository **out);
GIT_EXTERN(void) git_repository__cleanup(git_repository *repo);
/**
+ * Update the filesystem config settings for an open repository
+ *
+ * When a repository is initialized, config values are set based on the
+ * properties of the filesystem that the repository is on, such as
+ * "core.ignorecase", "core.filemode", "core.symlinks", etc. If the
+ * repository is moved to a new filesystem, these properties may no
+ * longer be correct and API calls may not behave as expected. This
+ * call reruns the phase of repository initialization that sets those
+ * properties to compensate for the current filesystem of the repo.
+ *
+ * @param repo A repository object
+ * @param recurse_submodules Should submodules be reset recursively
+ * @returrn 0 on success, < 0 on error
+ */
+GIT_EXTERN(int) git_repository_reset_filesystem(
+ git_repository *repo,
+ int recurse_submodules);
+
+/**
* Set the configuration file for this repository
*
* This configuration file will be used for all configuration
diff --git a/src/path.h b/src/path.h
index 175756938..eaf94d486 100644
--- a/src/path.h
+++ b/src/path.h
@@ -365,11 +365,6 @@ extern int git_path_set_error(
/* check if non-ascii characters are present in filename */
extern bool git_path_has_non_ascii(const char *path, size_t pathlen);
-/* only enable iconv on Mac for now */
-#ifdef __APPLE__
-#define GIT_USE_ICONV 1
-#endif
-
#define GIT_PATH_REPO_ENCODING "UTF-8"
#ifdef __APPLE__
diff --git a/src/refs.c b/src/refs.c
index c045ab9dc..0da02a666 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -138,6 +138,22 @@ int git_reference_name_to_id(
return 0;
}
+static int reference_normalize_for_repo(
+ char *out,
+ size_t out_size,
+ git_repository *repo,
+ const char *name)
+{
+ int precompose;
+ unsigned int flags = GIT_REF_FORMAT_ALLOW_ONELEVEL;
+
+ if (!git_repository__cvar(&precompose, repo, GIT_CVAR_PRECOMPOSE) &&
+ precompose)
+ flags |= GIT_REF_FORMAT__PRECOMPOSE_UNICODE;
+
+ return git_reference_normalize_name(out, out_size, name, flags);
+}
+
int git_reference_lookup_resolved(
git_reference **ref_out,
git_repository *repo,
@@ -159,13 +175,13 @@ int git_reference_lookup_resolved(
else if (max_nesting < 0)
max_nesting = DEFAULT_NESTING_LEVEL;
- strncpy(scan_name, name, GIT_REFNAME_MAX);
scan_type = GIT_REF_SYMBOLIC;
- if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
- return -1;
+ if ((error = reference_normalize_for_repo(
+ scan_name, sizeof(scan_name), repo, name)) < 0)
+ return error;
- if ((error = git_reference__normalize_name_lax(scan_name, GIT_REFNAME_MAX, name)) < 0)
+ if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
return error;
for (nesting = max_nesting;
@@ -173,7 +189,7 @@ int git_reference_lookup_resolved(
nesting--)
{
if (nesting != max_nesting) {
- strncpy(scan_name, ref->target.symbolic, GIT_REFNAME_MAX);
+ strncpy(scan_name, ref->target.symbolic, sizeof(scan_name));
git_reference_free(ref);
}
@@ -711,17 +727,18 @@ static bool is_all_caps_and_underscore(const char *name, size_t len)
return true;
}
+/* Inspired from https://github.com/git/git/blob/f06d47e7e0d9db709ee204ed13a8a7486149f494/refs.c#L36-100 */
int git_reference__normalize_name(
git_buf *buf,
const char *name,
unsigned int flags)
{
- // Inspired from https://github.com/git/git/blob/f06d47e7e0d9db709ee204ed13a8a7486149f494/refs.c#L36-100
-
char *current;
int segment_len, segments_count = 0, error = GIT_EINVALIDSPEC;
unsigned int process_flags;
bool normalize = (buf != NULL);
+ git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
+
assert(name);
process_flags = flags;
@@ -733,6 +750,13 @@ int git_reference__normalize_name(
if (normalize)
git_buf_clear(buf);
+ if ((flags & GIT_REF_FORMAT__PRECOMPOSE_UNICODE) != 0) {
+ size_t namelen = strlen(current);
+ if ((error = git_path_iconv_init_precompose(&ic)) < 0 ||
+ (error = git_path_iconv(&ic, &current, &namelen)) < 0)
+ goto cleanup;
+ }
+
while (true) {
segment_len = ensure_segment_validity(current);
if (segment_len < 0) {
@@ -809,6 +833,8 @@ cleanup:
if (error && normalize)
git_buf_free(buf);
+ git_path_iconv_clear(&ic);
+
return error;
}
@@ -983,9 +1009,9 @@ static int peel_error(int error, git_reference *ref, const char* msg)
}
int git_reference_peel(
- git_object **peeled,
- git_reference *ref,
- git_otype target_type)
+ git_object **peeled,
+ git_reference *ref,
+ git_otype target_type)
{
git_reference *resolved = NULL;
git_object *target = NULL;
@@ -1027,24 +1053,19 @@ cleanup:
return error;
}
-int git_reference__is_valid_name(
- const char *refname,
- unsigned int flags)
+int git_reference__is_valid_name(const char *refname, unsigned int flags)
{
- int error;
-
- error = git_reference__normalize_name(NULL, refname, flags) == 0;
- giterr_clear();
+ if (git_reference__normalize_name(NULL, refname, flags) < 0) {
+ giterr_clear();
+ return false;
+ }
- return error;
+ return true;
}
-int git_reference_is_valid_name(
- const char *refname)
+int git_reference_is_valid_name(const char *refname)
{
- return git_reference__is_valid_name(
- refname,
- GIT_REF_FORMAT_ALLOW_ONELEVEL);
+ return git_reference__is_valid_name(refname, GIT_REF_FORMAT_ALLOW_ONELEVEL);
}
const char *git_reference_shorthand(git_reference *ref)
diff --git a/src/refs.h b/src/refs.h
index 4b91c25e8..80c7703fc 100644
--- a/src/refs.h
+++ b/src/refs.h
@@ -46,6 +46,8 @@
#define GIT_STASH_FILE "stash"
#define GIT_REFS_STASH_FILE GIT_REFS_DIR GIT_STASH_FILE
+#define GIT_REF_FORMAT__PRECOMPOSE_UNICODE (1u << 16)
+
#define GIT_REFNAME_MAX 1024
struct git_reference {
diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c
index 82ec5c065..9f65953f5 100644
--- a/tests-clar/clar_libgit2.c
+++ b/tests-clar/clar_libgit2.c
@@ -1,6 +1,7 @@
#include "clar_libgit2.h"
#include "posix.h"
#include "path.h"
+#include "git2/sys/repository.h"
void cl_git_report_failure(
int error, const char *file, int line, const char *fncall)
diff --git a/tests-clar/refs/unicode.c b/tests-clar/refs/unicode.c
index b29c63e2b..b56012869 100644
--- a/tests-clar/refs/unicode.c
+++ b/tests-clar/refs/unicode.c
@@ -4,17 +4,13 @@ static git_repository *repo;
void test_refs_unicode__initialize(void)
{
- cl_fixture_sandbox("testrepo.git");
-
- cl_git_pass(git_repository_open(&repo, "testrepo.git"));
+ repo = cl_git_sandbox_init("testrepo.git");
}
void test_refs_unicode__cleanup(void)
{
- git_repository_free(repo);
+ cl_git_sandbox_cleanup();
repo = NULL;
-
- cl_fixture_cleanup("testrepo.git");
}
void test_refs_unicode__create_and_lookup(void)
@@ -23,13 +19,12 @@ void test_refs_unicode__create_and_lookup(void)
git_repository *repo2;
const char *REFNAME = "refs/heads/" "\303\205" "ngstr" "\303\266" "m";
- const char *REFNAME_DECOMPOSED =
- "refs/heads/" "A" "\314\212" "ngstro" "\314\210" "m";
const char *master = "refs/heads/master";
/* Create the reference */
cl_git_pass(git_reference_lookup(&ref0, repo, master));
- cl_git_pass(git_reference_create(&ref1, repo, REFNAME, git_reference_target(ref0), 0));
+ cl_git_pass(git_reference_create(
+ &ref1, repo, REFNAME, git_reference_target(ref0), 0));
cl_assert_equal_s(REFNAME, git_reference_name(ref1));
git_reference_free(ref0);
@@ -45,6 +40,8 @@ void test_refs_unicode__create_and_lookup(void)
#if GIT_USE_ICONV
/* Lookup reference by decomposed unicode name */
+#define REFNAME_DECOMPOSED "refs/heads/" "A" "\314\212" "ngstro" "\314\210" "m"
+
cl_git_pass(git_reference_lookup(&ref2, repo2, REFNAME_DECOMPOSED));
cl_assert_equal_i(
0, git_oid_cmp(git_reference_target(ref1), git_reference_target(ref2)));