Permalink
Browse files

Merge remote-tracking branch 'nulltoken/topix/path_fromurl' into deve…

…lopment

Conflicts:
	tests-clay/clay.h
	tests-clay/clay_main.c
  • Loading branch information...
2 parents b0df89d + e258037 commit f2114d0a35b95efef294f7527dfd64fbef61d993 @vmg vmg committed Jan 4, 2012
Showing with 260 additions and 76 deletions.
  1. +5 −23 src/oid.c
  2. +74 −0 src/path.c
  3. +3 −0 src/path.h
  4. +15 −12 src/transports/local.c
  5. +23 −0 src/util.h
  6. +22 −0 tests-clay/core/hex.c
  7. +70 −7 tests-clay/core/path.c
  8. +44 −8 tests-clay/network/remotelocal.c
  9. +2 −13 tests-clay/object/raw/chars.c
  10. +2 −13 tests/t01-rawobj.c
View
@@ -11,24 +11,6 @@
#include <string.h>
#include <limits.h>
-static signed char from_hex[] = {
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20 */
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 30 */
--1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 40 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 50 */
--1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 60 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* a0 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* b0 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* c0 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* d0 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* e0 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* f0 */
-};
static char to_hex[] = "0123456789abcdef";
int git_oid_fromstrn(git_oid *out, const char *str, size_t length)
@@ -43,8 +25,8 @@ int git_oid_fromstrn(git_oid *out, const char *str, size_t length)
length = GIT_OID_HEXSZ;
for (p = 0; p < length - 1; p += 2) {
- v = (from_hex[(unsigned char)str[p + 0]] << 4)
- | from_hex[(unsigned char)str[p + 1]];
+ v = (git__fromhex(str[p + 0]) << 4)
+ | git__fromhex(str[p + 1]);
if (v < 0)
return git__throw(GIT_ENOTOID, "Failed to generate sha1. Given string is not a valid sha1 hash");
@@ -53,7 +35,7 @@ int git_oid_fromstrn(git_oid *out, const char *str, size_t length)
}
if (length % 2) {
- v = (from_hex[(unsigned char)str[p + 0]] << 4);
+ v = (git__fromhex(str[p + 0]) << 4);
if (v < 0)
return git__throw(GIT_ENOTOID, "Failed to generate sha1. Given string is not a valid sha1 hash");
@@ -346,7 +328,7 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid)
is_leaf = 0;
for (i = 0; i < GIT_OID_HEXSZ; ++i) {
- int c = from_hex[(int)text_oid[i]];
+ int c = git__fromhex(text_oid[i]);
trie_node *node;
if (c == -1)
@@ -360,7 +342,7 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid)
tail = node->tail;
node->tail = NULL;
- node = push_leaf(os, idx, from_hex[(int)tail[0]], &tail[1]);
+ node = push_leaf(os, idx, git__fromhex(tail[0]), &tail[1]);
if (node == NULL)
return GIT_ENOMEM;
}
View
@@ -237,3 +237,77 @@ void git_path_string_to_dir(char* path, size_t size)
}
}
+int git__percent_decode(git_buf *decoded_out, const char *input)
+{
+ int len, hi, lo, i, error = GIT_SUCCESS;
+ assert(decoded_out && input);
+
+ len = strlen(input);
+ git_buf_clear(decoded_out);
+
+ for(i = 0; i < len; i++)
+ {
+ char c = input[i];
+
+ if (c != '%')
+ goto append;
+
+ if (i >= len - 2)
+ goto append;
+
+ hi = git__fromhex(input[i + 1]);
+ lo = git__fromhex(input[i + 2]);
+
+ if (hi < 0 || lo < 0)
+ goto append;
+
+ c = (char)(hi << 4 | lo);
+ i += 2;
+
+append:
+ error = git_buf_putc(decoded_out, c);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to percent decode '%s'.", input);
+ }
+
+ return error;
+}
+
+int git_path_fromurl(git_buf *local_path_out, const char *file_url)
+{
+ int error = GIT_SUCCESS, offset = 0, len;
+
+ assert(local_path_out && file_url);
+
+ if (git__prefixcmp(file_url, "file://") != 0)
+ return git__throw(GIT_EINVALIDPATH,
+ "Parsing of '%s' failed. A file Uri is expected (ie. with 'file://' scheme).",
+ file_url);
+
+ offset += 7;
+ len = strlen(file_url);
+
+ if (offset < len && file_url[offset] == '/')
+ offset++;
+ else if (offset < len && git__prefixcmp(file_url + offset, "localhost/") == 0)
+ offset += 10;
+ else
+ return git__throw(GIT_EINVALIDPATH,
+ "Parsing of '%s' failed. A local file Uri is expected.", file_url);
+
+ if (offset >= len || file_url[offset] == '/')
+ return git__throw(GIT_EINVALIDPATH,
+ "Parsing of '%s' failed. Invalid file Uri format.", file_url);
+
+#ifndef _MSC_VER
+ offset--; /* A *nix absolute path starts with a forward slash */
+#endif
+
+ git_buf_clear(local_path_out);
+
+ error = git__percent_decode(local_path_out, file_url + offset);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Parsing of '%s' failed.", file_url);
+
+ return error;
+}
View
@@ -74,4 +74,7 @@ GIT_INLINE(void) git_path_mkposix(char *path)
# define git_path_mkposix(p) /* blank */
#endif
+extern int git__percent_decode(git_buf *decoded_out, const char *input);
+extern int git_path_fromurl(git_buf *local_path_out, const char *file_url);
+
#endif
@@ -13,6 +13,8 @@
#include "refs.h"
#include "transport.h"
#include "posix.h"
+#include "path.h"
+#include "buffer.h"
typedef struct {
git_transport parent;
@@ -148,7 +150,6 @@ static int local_ls(git_transport *transport, git_headlist_cb list_cb, void *pay
return GIT_SUCCESS;
}
-
/*
* Try to open the url as a git directory. The direction doesn't
* matter in this case because we're calulating the heads ourselves.
@@ -159,24 +160,26 @@ static int local_connect(git_transport *transport, int GIT_UNUSED(direction))
int error;
transport_local *t = (transport_local *) transport;
const char *path;
+ git_buf buf = GIT_BUF_INIT;
+
GIT_UNUSED_ARG(direction);
/* The repo layer doesn't want the prefix */
if (!git__prefixcmp(transport->url, "file://")) {
- path = transport->url + strlen("file://");
-
-#ifdef _MSC_VER
- /* skip the leading slash on windows before the drive letter */
- if (*path != '/')
- return git__throw(GIT_EINVALIDPATH, "Invalid local uri '%s'.", transport->url);
-
- path++;
-#endif
-
- } else
+ error = git_path_fromurl(&buf, transport->url);
+ if (error < GIT_SUCCESS) {
+ git_buf_free(&buf);
+ return git__rethrow(error, "Failed to parse remote path");
+ }
+ path = git_buf_cstr(&buf);
+
+ } else /* We assume transport->url is already a path */
path = transport->url;
error = git_repository_open(&repo, path);
+
+ git_buf_free(&buf);
+
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to open remote");
View
@@ -138,5 +138,28 @@ typedef void (*git_refcount_freeptr)(void *r);
#define GIT_REFCOUNT_OWNER(r) (((git_refcount *)(r))->owner)
+static signed char from_hex[] = {
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 30 */
+-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 40 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 50 */
+-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 60 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* a0 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* b0 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* c0 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* d0 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* e0 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* f0 */
+};
+
+GIT_INLINE(int) git__fromhex(char h)
+{
+ return from_hex[(unsigned char) h];
+}
#endif /* INCLUDE_util_h__ */
View
@@ -0,0 +1,22 @@
+#include "clay_libgit2.h"
+#include "util.h"
+
+void test_core_hex__fromhex(void)
+{
+ /* Passing cases */
+ cl_assert(git__fromhex('0') == 0x0);
+ cl_assert(git__fromhex('1') == 0x1);
+ cl_assert(git__fromhex('3') == 0x3);
+ cl_assert(git__fromhex('9') == 0x9);
+ cl_assert(git__fromhex('A') == 0xa);
+ cl_assert(git__fromhex('C') == 0xc);
+ cl_assert(git__fromhex('F') == 0xf);
+ cl_assert(git__fromhex('a') == 0xa);
+ cl_assert(git__fromhex('c') == 0xc);
+ cl_assert(git__fromhex('f') == 0xf);
+
+ /* Failing cases */
+ cl_assert(git__fromhex('g') == -1);
+ cl_assert(git__fromhex('z') == -1);
+ cl_assert(git__fromhex('X') == -1);
+}
@@ -70,7 +70,7 @@ check_joinpath_n(
/* get the dirname of a path */
-void test_core_path__0_dirname(void)
+void test_core_path__00_dirname(void)
{
check_dirname(NULL, ".");
check_dirname("", ".");
@@ -90,7 +90,7 @@ void test_core_path__0_dirname(void)
}
/* get the base name of a path */
-void test_core_path__1_basename(void)
+void test_core_path__01_basename(void)
{
check_basename(NULL, ".");
check_basename("", ".");
@@ -107,7 +107,7 @@ void test_core_path__1_basename(void)
}
/* get the latest component in a path */
-void test_core_path__2_topdir(void)
+void test_core_path__02_topdir(void)
{
check_topdir(".git/", ".git/");
check_topdir("/.git/", ".git/");
@@ -124,7 +124,7 @@ void test_core_path__2_topdir(void)
}
/* properly join path components */
-void test_core_path__5_joins(void)
+void test_core_path__05_joins(void)
{
check_joinpath("", "", "");
check_joinpath("", "a", "a");
@@ -159,7 +159,7 @@ void test_core_path__5_joins(void)
}
/* properly join path components for more than one path */
-void test_core_path__6_long_joins(void)
+void test_core_path__06_long_joins(void)
{
check_joinpath_n("", "", "", "", "");
check_joinpath_n("", "a", "", "", "a/");
@@ -212,7 +212,7 @@ check_string_to_dir(
}
/* convert paths to dirs */
-void test_core_path__7_path_to_dir(void)
+void test_core_path__07_path_to_dir(void)
{
check_path_to_dir("", "");
check_path_to_dir(".", "./");
@@ -240,7 +240,7 @@ void test_core_path__7_path_to_dir(void)
}
/* join path to itself */
-void test_core_path__8_self_join(void)
+void test_core_path__08_self_join(void)
{
git_buf path = GIT_BUF_INIT;
ssize_t asize = 0;
@@ -273,3 +273,66 @@ void test_core_path__8_self_join(void)
git_buf_free(&path);
}
+
+static void check_percent_decoding(const char *expected_result, const char *input)
+{
+ git_buf buf = GIT_BUF_INIT;
+
+ cl_git_pass(git__percent_decode(&buf, input));
+ cl_assert_strequal(expected_result, git_buf_cstr(&buf));
+
+ git_buf_free(&buf);
+}
+
+void test_core_path__09_percent_decode(void)
+{
+ check_percent_decoding("abcd", "abcd");
+ check_percent_decoding("a2%", "a2%");
+ check_percent_decoding("a2%3", "a2%3");
+ check_percent_decoding("a2%%3", "a2%%3");
+ check_percent_decoding("a2%3z", "a2%3z");
+ check_percent_decoding("a,", "a%2c");
+ check_percent_decoding("a21", "a2%31");
+ check_percent_decoding("a2%1", "a2%%31");
+ check_percent_decoding("a bc ", "a%20bc%20");
+ check_percent_decoding("Vicent Mart" "\355", "Vicent%20Mart%ED");
+}
+
+static void check_fromurl(const char *expected_result, const char *input, int should_fail)
+{
+ git_buf buf = GIT_BUF_INIT;
+
+ assert(should_fail || expected_result);
+
+ if (!should_fail) {
+ cl_git_pass(git_path_fromurl(&buf, input));
+ cl_assert_strequal(expected_result, git_buf_cstr(&buf));
+ } else
+ cl_git_fail(git_path_fromurl(&buf, input));
+
+ git_buf_free(&buf);
+}
+
+#ifdef _MSC_VER
+#define ABS_PATH_MARKER ""
+#else
+#define ABS_PATH_MARKER "/"
+#endif
+
+void test_core_path__10_fromurl(void)
+{
+ /* Failing cases */
+ check_fromurl(NULL, "a", 1);
+ check_fromurl(NULL, "http:///c:/Temp%20folder/note.txt", 1);
+ check_fromurl(NULL, "file://c:/Temp%20folder/note.txt", 1);
+ check_fromurl(NULL, "file:////c:/Temp%20folder/note.txt", 1);
+ check_fromurl(NULL, "file:///", 1);
+ check_fromurl(NULL, "file:////", 1);
+ check_fromurl(NULL, "file://servername/c:/Temp%20folder/note.txt", 1);
+
+ /* Passing cases */
+ check_fromurl(ABS_PATH_MARKER "c:/Temp folder/note.txt", "file:///c:/Temp%20folder/note.txt", 0);
+ check_fromurl(ABS_PATH_MARKER "c:/Temp folder/note.txt", "file://localhost/c:/Temp%20folder/note.txt", 0);
+ check_fromurl(ABS_PATH_MARKER "c:/Temp+folder/note.txt", "file:///c:/Temp+folder/note.txt", 0);
+ check_fromurl(ABS_PATH_MARKER "a", "file:///a", 0);
+}
Oops, something went wrong.

0 comments on commit f2114d0

Please sign in to comment.