mirror of
				https://git.proxmox.com/git/libgit2
				synced 2025-11-04 07:09:14 +00:00 
			
		
		
		
	transport: make local transport accept a file Uri containing percent-encoded characters
This makes libgit2 compliant with the following scenario $ git ls-remote file:///d:/temp/dwm%20tinou 732d790b702db4b8985f5104fc44642654f6a6b6 HEAD 732d790b702db4b8985f5104fc44642654f6a6b6 refs/heads/master 732d790b702db4b8985f5104fc44642654f6a6b6 refs/remotes/origin/HEAD 732d790b702db4b8985f5104fc44642654f6a6b6 refs/remotes/origin/master $ mv "/d/temp/dwm tinou" /d/temp/dwm+tinou $ git ls-remote file:///d:/temp/dwm%20tinou fatal: 'd:/temp/dwm tinou' does not appear to be a git repository fatal: The remote end hung up unexpectedly $ git ls-remote file:///d:/temp/dwm+tinou 732d790b702db4b8985f5104fc44642654f6a6b6 HEAD 732d790b702db4b8985f5104fc44642654f6a6b6 refs/heads/master 732d790b702db4b8985f5104fc44642654f6a6b6 refs/remotes/origin/HEAD 732d790b702db4b8985f5104fc44642654f6a6b6 refs/remotes/origin/master
This commit is contained in:
		
							parent
							
								
									2017a15d6c
								
							
						
					
					
						commit
						e2580375dc
					
				@ -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://");
 | 
			
		||||
		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);
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
	} 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");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -132,6 +132,7 @@ extern void test_index_rename__single_file(void);
 | 
			
		||||
extern void test_network_remotelocal__cleanup(void);
 | 
			
		||||
extern void test_network_remotelocal__initialize(void);
 | 
			
		||||
extern void test_network_remotelocal__retrieve_advertised_references(void);
 | 
			
		||||
extern void test_network_remotelocal__retrieve_advertised_references_from_spaced_repository(void);
 | 
			
		||||
extern void test_network_remotes__cleanup(void);
 | 
			
		||||
extern void test_network_remotes__fnmatch(void);
 | 
			
		||||
extern void test_network_remotes__initialize(void);
 | 
			
		||||
 | 
			
		||||
@ -205,7 +205,8 @@ static const struct clay_func _clay_cb_index_rename[] = {
 | 
			
		||||
    {"single_file", &test_index_rename__single_file}
 | 
			
		||||
};
 | 
			
		||||
static const struct clay_func _clay_cb_network_remotelocal[] = {
 | 
			
		||||
    {"retrieve_advertised_references", &test_network_remotelocal__retrieve_advertised_references}
 | 
			
		||||
    {"retrieve_advertised_references", &test_network_remotelocal__retrieve_advertised_references},
 | 
			
		||||
	{"retrieve_advertised_references_from_spaced_repository", &test_network_remotelocal__retrieve_advertised_references_from_spaced_repository}
 | 
			
		||||
};
 | 
			
		||||
static const struct clay_func _clay_cb_network_remotes[] = {
 | 
			
		||||
    {"fnmatch", &test_network_remotes__fnmatch},
 | 
			
		||||
@ -419,7 +420,7 @@ static const struct clay_suite _clay_suites[] = {
 | 
			
		||||
        "network::remotelocal",
 | 
			
		||||
        {"initialize", &test_network_remotelocal__initialize},
 | 
			
		||||
        {"cleanup", &test_network_remotelocal__cleanup},
 | 
			
		||||
        _clay_cb_network_remotelocal, 1
 | 
			
		||||
        _clay_cb_network_remotelocal, 2
 | 
			
		||||
    },
 | 
			
		||||
	{
 | 
			
		||||
        "network::remotes",
 | 
			
		||||
@ -550,7 +551,7 @@ static const struct clay_suite _clay_suites[] = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static size_t _clay_suite_count = 39;
 | 
			
		||||
static size_t _clay_callback_count = 125;
 | 
			
		||||
static size_t _clay_callback_count = 126;
 | 
			
		||||
 | 
			
		||||
/* Core test functions */
 | 
			
		||||
static void
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@
 | 
			
		||||
#include "transport.h"
 | 
			
		||||
#include "buffer.h"
 | 
			
		||||
#include "path.h"
 | 
			
		||||
#include "posix.h"
 | 
			
		||||
 | 
			
		||||
static git_repository *repo;
 | 
			
		||||
static git_buf file_path_buf = GIT_BUF_INIT;
 | 
			
		||||
@ -9,9 +10,11 @@ static git_remote *remote;
 | 
			
		||||
 | 
			
		||||
static void build_local_file_url(git_buf *out, const char *fixture)
 | 
			
		||||
{
 | 
			
		||||
	const char *in_buf;
 | 
			
		||||
 | 
			
		||||
	git_buf path_buf = GIT_BUF_INIT;
 | 
			
		||||
 | 
			
		||||
	cl_git_pass(git_path_prettify_dir(&path_buf, cl_fixture(fixture), NULL));
 | 
			
		||||
	cl_git_pass(git_path_prettify_dir(&path_buf, fixture, NULL));
 | 
			
		||||
	cl_git_pass(git_buf_puts(out, "file://"));
 | 
			
		||||
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
@ -27,21 +30,27 @@ static void build_local_file_url(git_buf *out, const char *fixture)
 | 
			
		||||
	cl_git_pass(git_buf_putc(out, '/'));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	cl_git_pass(git_buf_puts(out, git_buf_cstr(&path_buf)));
 | 
			
		||||
	in_buf = git_buf_cstr(&path_buf);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * A very hacky Url encoding that only takes care of escaping the spaces
 | 
			
		||||
	 */
 | 
			
		||||
	while (*in_buf) {
 | 
			
		||||
		if (*in_buf == ' ')
 | 
			
		||||
			cl_git_pass(git_buf_puts(out, "%20"));
 | 
			
		||||
		else
 | 
			
		||||
			cl_git_pass(git_buf_putc(out, *in_buf));
 | 
			
		||||
 | 
			
		||||
		in_buf++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	git_buf_free(&path_buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_network_remotelocal__initialize(void)
 | 
			
		||||
{
 | 
			
		||||
	cl_fixture("remotelocal");
 | 
			
		||||
	cl_git_pass(git_repository_init(&repo, "remotelocal/", 0));
 | 
			
		||||
	cl_assert(repo != NULL);
 | 
			
		||||
 | 
			
		||||
	build_local_file_url(&file_path_buf, "testrepo.git");
 | 
			
		||||
 | 
			
		||||
	cl_git_pass(git_remote_new(&remote, repo, git_buf_cstr(&file_path_buf), NULL));
 | 
			
		||||
	cl_git_pass(git_remote_connect(remote, GIT_DIR_FETCH));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_network_remotelocal__cleanup(void)
 | 
			
		||||
@ -62,11 +71,38 @@ static int count_ref__cb(git_remote_head *head, void *payload)
 | 
			
		||||
	return GIT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void connect_to_local_repository(const char *local_repository)
 | 
			
		||||
{
 | 
			
		||||
	build_local_file_url(&file_path_buf, local_repository);
 | 
			
		||||
 | 
			
		||||
	cl_git_pass(git_remote_new(&remote, repo, git_buf_cstr(&file_path_buf), NULL));
 | 
			
		||||
	cl_git_pass(git_remote_connect(remote, GIT_DIR_FETCH));
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_network_remotelocal__retrieve_advertised_references(void)
 | 
			
		||||
{
 | 
			
		||||
	int how_many_refs = 0;
 | 
			
		||||
 | 
			
		||||
	connect_to_local_repository(cl_fixture("testrepo.git"));
 | 
			
		||||
 | 
			
		||||
	cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs));
 | 
			
		||||
 | 
			
		||||
	cl_assert(how_many_refs == 12); /* 1 HEAD + 9 refs + 2 peeled tags */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_network_remotelocal__retrieve_advertised_references_from_spaced_repository(void)
 | 
			
		||||
{
 | 
			
		||||
	int how_many_refs = 0;
 | 
			
		||||
 | 
			
		||||
	cl_fixture_sandbox("testrepo.git");
 | 
			
		||||
	cl_git_pass(p_rename("testrepo.git", "spaced testrepo.git"));
 | 
			
		||||
 | 
			
		||||
	connect_to_local_repository("spaced testrepo.git");
 | 
			
		||||
 | 
			
		||||
	cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs));
 | 
			
		||||
 | 
			
		||||
	cl_assert(how_many_refs == 12); /* 1 HEAD */
 | 
			
		||||
 | 
			
		||||
	cl_fixture_cleanup("spaced testrepo.git");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user