Commit 8f866dae by Carlos Martín Nieto Committed by Carlos Martín Nieto

Lay down the fundations for the network code

Signed-off-by: Carlos Martín Nieto <carlos@cmartin.tk>
parent c5b2622d
#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
/*
* 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
......
#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;
}
#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
#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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment