mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-02 14:37:30 +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_rtype;
|
||||
|
||||
|
||||
typedef struct git_refspec git_refspec;
|
||||
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
|
||||
|
||||
|
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