mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-03 21:56:39 +00:00
Lay down the fundations for the network code
Signed-off-by: Carlos Martín Nieto <carlos@cmartin.tk>
This commit is contained in:
parent
c5b2622d68
commit
8f866daee5
33
include/git2/net.h
Normal file
33
include/git2/net.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef INCLUDE_net_h__
|
||||||
|
#define INCLUDE_net_h__
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "oid.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need this because we need to know whether we should call
|
||||||
|
* git-upload-pack or git-receive-pack on the remote end when get_refs
|
||||||
|
* gets called.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum git_net_direction {
|
||||||
|
INTENT_PUSH,
|
||||||
|
INTENT_PULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is what we give out on ->ls()
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct git_remote_head {
|
||||||
|
git_oid oid;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct git_headarray {
|
||||||
|
unsigned int len;
|
||||||
|
struct git_remote_head *heads;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
56
include/git2/transport.h
Normal file
56
include/git2/transport.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, version 2,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* In addition to the permissions in the GNU General Public License,
|
||||||
|
* the authors give you unlimited permission to link the compiled
|
||||||
|
* version of this file into combinations with other programs,
|
||||||
|
* and to distribute those combinations without any restriction
|
||||||
|
* coming from the use of this file. (The General Public License
|
||||||
|
* restrictions do apply in other respects; for example, they cover
|
||||||
|
* modification of the file, and distribution when not linked into
|
||||||
|
* a combined executable.)
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef INCLUDE_git_transport_h__
|
||||||
|
#define INCLUDE_git_transport_h__
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "net.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file git2/transport.h
|
||||||
|
* @brief Git protocol transport abstraction
|
||||||
|
* @defgroup git_transport Git protocol transport abstraction
|
||||||
|
* @ingroup Git
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
GIT_BEGIN_DECL
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the appropriate transport for an URL.
|
||||||
|
* @param tranport the transport for the url
|
||||||
|
* @param url the url of the repo
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_transport_get(git_transport *transport, const char *url);
|
||||||
|
|
||||||
|
GIT_EXTERN(int) git_transport_connect(git_transport *transport, git_net_direction direction);
|
||||||
|
/*
|
||||||
|
GIT_EXTERN(const git_vector *) git_transport_get_refs(git_transport *transport);
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_transport_add(git_transport *transport, const char *prefix);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
GIT_END_DECL
|
||||||
|
#endif
|
@ -167,9 +167,20 @@ typedef enum {
|
|||||||
GIT_REF_LISTALL = GIT_REF_OID|GIT_REF_SYMBOLIC|GIT_REF_PACKED,
|
GIT_REF_LISTALL = GIT_REF_OID|GIT_REF_SYMBOLIC|GIT_REF_PACKED,
|
||||||
} git_rtype;
|
} git_rtype;
|
||||||
|
|
||||||
|
|
||||||
typedef struct git_refspec git_refspec;
|
typedef struct git_refspec git_refspec;
|
||||||
typedef struct git_remote git_remote;
|
typedef struct git_remote git_remote;
|
||||||
|
|
||||||
|
/** A transport to use */
|
||||||
|
typedef struct git_transport git_transport;
|
||||||
|
|
||||||
|
/** Whether to push or pull */
|
||||||
|
typedef enum git_net_direction git_net_direction;
|
||||||
|
|
||||||
|
typedef int (*git_transport_cb)(git_transport *transport);
|
||||||
|
|
||||||
|
typedef struct git_headarray git_headarray;
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
GIT_END_DECL
|
GIT_END_DECL
|
||||||
|
|
||||||
|
77
src/transport.c
Normal file
77
src/transport.c
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#include "common.h"
|
||||||
|
#include "git2/types.h"
|
||||||
|
#include "git2/transport.h"
|
||||||
|
#include "git2/net.h"
|
||||||
|
#include "transport.h"
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char *prefix;
|
||||||
|
git_transport_cb fn;
|
||||||
|
} transports[] = {
|
||||||
|
{"git://", git_transport_dummy},
|
||||||
|
{"http://", git_transport_dummy},
|
||||||
|
{"https://", git_transport_dummy},
|
||||||
|
{"file://", git_transport_local},
|
||||||
|
{"git+ssh://", git_transport_dummy},
|
||||||
|
{"ssh+git://", git_transport_dummy},
|
||||||
|
{NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static git_transport_cb transport_fill_fn(const char *url)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (transports[i].prefix == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!strncasecmp(url, transports[i].prefix, strlen(transports[i].prefix)))
|
||||||
|
return transports[i].fn;
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we still haven't found the transport, we assume we mean a
|
||||||
|
* local file.
|
||||||
|
* TODO: Parse "example.com:project.git" as an SSH URL
|
||||||
|
*/
|
||||||
|
return git_transport_local;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************
|
||||||
|
* Public API *
|
||||||
|
**************/
|
||||||
|
|
||||||
|
int git_transport_dummy(git_transport *GIT_UNUSED(transport))
|
||||||
|
{
|
||||||
|
GIT_UNUSED_ARG(transport);
|
||||||
|
return git__throw(GIT_ENOTIMPLEMENTED, "This protocol isn't implemented. Sorry");
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_transport_new(git_transport **out, git_repository *repo, const char *url)
|
||||||
|
{
|
||||||
|
git_transport_cb fn;
|
||||||
|
git_transport *transport;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
fn = transport_fill_fn(url);
|
||||||
|
|
||||||
|
transport = git__malloc(sizeof(git_transport));
|
||||||
|
if (transport == NULL)
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
|
transport->url = git__strdup(url);
|
||||||
|
if (transport->url == NULL)
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
|
transport->repo = repo;
|
||||||
|
|
||||||
|
error = fn(transport);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
return git__rethrow(error, "Failed to create new transport");
|
||||||
|
|
||||||
|
*out = transport;
|
||||||
|
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
79
src/transport.h
Normal file
79
src/transport.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#ifndef INCLUDE_transport_h__
|
||||||
|
#define INCLUDE_transport_h__
|
||||||
|
|
||||||
|
#include "git2/transport.h"
|
||||||
|
#include "git2/net.h"
|
||||||
|
#include "vector.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A day in the life of a network operation
|
||||||
|
* ========================================
|
||||||
|
*
|
||||||
|
* The library gets told to ls-remote/push/fetch on/to/from some
|
||||||
|
* remote. We look at the URL of the remote and fill the function
|
||||||
|
* table with whatever is appropriate (the remote may be git over git,
|
||||||
|
* ssh or http(s). It may even be an hg or svn repository, the library
|
||||||
|
* at this level doesn't care, it just calls the helpers.
|
||||||
|
*
|
||||||
|
* The first call is to ->connect() which connects to the remote,
|
||||||
|
* making use of the direction if necessary. This function must also
|
||||||
|
* store the remote heads and any other information it needs.
|
||||||
|
*
|
||||||
|
* If we just want to execute ls-remote, ->ls() gets
|
||||||
|
* called. Otherwise, the have/want/need list needs to be built via
|
||||||
|
* ->wanthaveneed(). We can then ->push() or ->pull(). When we're
|
||||||
|
* done, we call ->close() to close the connection. ->free() takes
|
||||||
|
* care of freeing all the resources.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct git_transport {
|
||||||
|
/**
|
||||||
|
* Where the repo lives
|
||||||
|
*/
|
||||||
|
char *url;
|
||||||
|
/**
|
||||||
|
* Where each transport stores its private/instance data
|
||||||
|
*/
|
||||||
|
void *private;
|
||||||
|
/**
|
||||||
|
* The repo we want to act on
|
||||||
|
*/
|
||||||
|
git_repository *repo;
|
||||||
|
/**
|
||||||
|
* Whether we want to push or fetch
|
||||||
|
*/
|
||||||
|
git_net_direction direction;
|
||||||
|
/**
|
||||||
|
* Connect and store the remote heads
|
||||||
|
*/
|
||||||
|
int (*connect)(struct git_transport *transport, git_net_direction intent);
|
||||||
|
/**
|
||||||
|
* Give a list of references, useful for ls-remote
|
||||||
|
*/
|
||||||
|
int (*ls)(struct git_transport *transport, git_headarray *headarray);
|
||||||
|
/**
|
||||||
|
* Calculate want/have/need. May not even be needed.
|
||||||
|
*/
|
||||||
|
int (*wanthaveneed)(struct git_transport *transport, void *something);
|
||||||
|
/**
|
||||||
|
* Build the pack
|
||||||
|
*/
|
||||||
|
int (*build_pack)(struct git_transport *transport);
|
||||||
|
/**
|
||||||
|
* Push the changes over
|
||||||
|
*/
|
||||||
|
int (*push)(struct git_transport *transport);
|
||||||
|
/**
|
||||||
|
* Fetch the changes
|
||||||
|
*/
|
||||||
|
int (*fetch)(struct git_transport *transport);
|
||||||
|
/**
|
||||||
|
* Close the connection
|
||||||
|
*/
|
||||||
|
int (*close)(struct git_transport *transport);
|
||||||
|
};
|
||||||
|
|
||||||
|
int git_transport_local(struct git_transport *transport);
|
||||||
|
int git_transport_dummy(struct git_transport *transport);
|
||||||
|
|
||||||
|
#endif
|
41
src/transport_local.c
Normal file
41
src/transport_local.c
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#include "common.h"
|
||||||
|
#include "git2/types.h"
|
||||||
|
#include "git2/transport.h"
|
||||||
|
#include "git2/net.h"
|
||||||
|
#include "git2/repository.h"
|
||||||
|
#include "transport.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to open the url as a git directory. The direction doesn't
|
||||||
|
* matter in this case because we're calulating the heads ourselves.
|
||||||
|
*/
|
||||||
|
static int local_connect(git_transport *transport, git_net_direction GIT_UNUSED(dir))
|
||||||
|
{
|
||||||
|
git_repository *repo;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = git_repository_open(&repo, transport->url);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
return git__rethrow(error, "Can't open remote");
|
||||||
|
|
||||||
|
transport->private = repo;
|
||||||
|
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int local_ls(git_transport *transport, git_headarray *array)
|
||||||
|
{
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************
|
||||||
|
* Public API *
|
||||||
|
**************/
|
||||||
|
|
||||||
|
int git_transport_local(git_transport *transport)
|
||||||
|
{
|
||||||
|
transport->connect = local_connect;
|
||||||
|
transport->ls = local_ls;
|
||||||
|
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user