mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-30 22:24:56 +00:00
Custom transport: minor cleanups
* Move the transport registration mechanisms into a new header under 'sys/' because this is advanced stuff. * Remove the 'priority' argument from the registration as it adds unnecessary complexity. (Since transports cannot decline to operate, only the highest priority transport is ever executed.) Users who require per-priority transports can implement that in their custom transport themselves. * Simplify registration further by taking a scheme (eg "http") instead of a prefix (eg "http://").
This commit is contained in:
parent
e62f96dea5
commit
c180c06586
@ -12,6 +12,12 @@ v0.21 + 1
|
||||
|
||||
* LF -> CRLF filter now runs when * text = auto (with Git for Windows 1.9.4)
|
||||
|
||||
* The git_transport structure definition has moved into the sys/transport.h
|
||||
file.
|
||||
|
||||
* The git_transport_register function no longer takes a priority and takes
|
||||
a URL scheme name (eg "http") instead of a prefix like "http://"
|
||||
|
||||
* The git_remote_set_transport function now sets a transport factory function,
|
||||
rather than a pre-existing transport instance.
|
||||
|
||||
|
@ -418,21 +418,6 @@ GIT_EXTERN(int) git_remote_list(git_strarray *out, git_repository *repo);
|
||||
*/
|
||||
GIT_EXTERN(void) git_remote_check_cert(git_remote *remote, int check);
|
||||
|
||||
/**
|
||||
* Sets a custom transport factory for the remote. The caller can use this
|
||||
* function to override the transport used for this remote when performing
|
||||
* network operations.
|
||||
*
|
||||
* @param remote the remote to configure
|
||||
* @param transport_cb the function to use to create a transport
|
||||
* @param payload opaque parameter passed to transport_cb
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_remote_set_transport(
|
||||
git_remote *remote,
|
||||
git_transport_cb transport_cb,
|
||||
void *payload);
|
||||
|
||||
/**
|
||||
* Argument to the completion callback which tells it which operation
|
||||
* finished.
|
||||
|
354
include/git2/sys/transport.h
Normal file
354
include/git2/sys/transport.h
Normal file
@ -0,0 +1,354 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_sys_git_transport_h
|
||||
#define INCLUDE_sys_git_transport_h
|
||||
|
||||
#include "git2/net.h"
|
||||
#include "git2/types.h"
|
||||
|
||||
/**
|
||||
* @file git2/sys/transport.h
|
||||
* @brief Git custom transport registration interfaces and functions
|
||||
* @defgroup git_transport Git custom transport registration
|
||||
* @ingroup Git
|
||||
* @{
|
||||
*/
|
||||
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
typedef enum {
|
||||
GIT_TRANSPORTFLAGS_NONE = 0,
|
||||
/* If the connection is secured with SSL/TLS, the authenticity
|
||||
* of the server certificate should not be verified. */
|
||||
GIT_TRANSPORTFLAGS_NO_CHECK_CERT = 1
|
||||
} git_transport_flags_t;
|
||||
|
||||
typedef struct git_transport git_transport;
|
||||
|
||||
struct git_transport {
|
||||
unsigned int version;
|
||||
/* Set progress and error callbacks */
|
||||
int (*set_callbacks)(
|
||||
git_transport *transport,
|
||||
git_transport_message_cb progress_cb,
|
||||
git_transport_message_cb error_cb,
|
||||
void *payload);
|
||||
|
||||
/* Connect the transport to the remote repository, using the given
|
||||
* direction. */
|
||||
int (*connect)(
|
||||
git_transport *transport,
|
||||
const char *url,
|
||||
git_cred_acquire_cb cred_acquire_cb,
|
||||
void *cred_acquire_payload,
|
||||
int direction,
|
||||
int flags);
|
||||
|
||||
/* This function may be called after a successful call to
|
||||
* connect(). The array returned is owned by the transport and
|
||||
* is guranteed until the next call of a transport function. */
|
||||
int (*ls)(
|
||||
const git_remote_head ***out,
|
||||
size_t *size,
|
||||
git_transport *transport);
|
||||
|
||||
/* Executes the push whose context is in the git_push object. */
|
||||
int (*push)(git_transport *transport, git_push *push);
|
||||
|
||||
/* This function may be called after a successful call to connect(), when
|
||||
* the direction is FETCH. The function performs a negotiation to calculate
|
||||
* the wants list for the fetch. */
|
||||
int (*negotiate_fetch)(
|
||||
git_transport *transport,
|
||||
git_repository *repo,
|
||||
const git_remote_head * const *refs,
|
||||
size_t count);
|
||||
|
||||
/* This function may be called after a successful call to negotiate_fetch(),
|
||||
* when the direction is FETCH. This function retrieves the pack file for
|
||||
* the fetch from the remote end. */
|
||||
int (*download_pack)(
|
||||
git_transport *transport,
|
||||
git_repository *repo,
|
||||
git_transfer_progress *stats,
|
||||
git_transfer_progress_cb progress_cb,
|
||||
void *progress_payload);
|
||||
|
||||
/* Checks to see if the transport is connected */
|
||||
int (*is_connected)(git_transport *transport);
|
||||
|
||||
/* Reads the flags value previously passed into connect() */
|
||||
int (*read_flags)(git_transport *transport, int *flags);
|
||||
|
||||
/* Cancels any outstanding transport operation */
|
||||
void (*cancel)(git_transport *transport);
|
||||
|
||||
/* This function is the reverse of connect() -- it terminates the
|
||||
* connection to the remote end. */
|
||||
int (*close)(git_transport *transport);
|
||||
|
||||
/* Frees/destructs the git_transport object. */
|
||||
void (*free)(git_transport *transport);
|
||||
};
|
||||
|
||||
#define GIT_TRANSPORT_VERSION 1
|
||||
#define GIT_TRANSPORT_INIT {GIT_TRANSPORT_VERSION}
|
||||
|
||||
/**
|
||||
* Initializes a `git_transport` with default values. Equivalent to
|
||||
* creating an instance with GIT_TRANSPORT_INIT.
|
||||
*
|
||||
* @param opts the `git_transport` struct to initialize
|
||||
* @param version Version of struct; pass `GIT_TRANSPORT_VERSION`
|
||||
* @return Zero on success; -1 on failure.
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_init(
|
||||
git_transport *opts,
|
||||
unsigned int version);
|
||||
|
||||
/**
|
||||
* Function to use to create a transport from a URL. The transport database
|
||||
* is scanned to find a transport that implements the scheme of the URI (i.e.
|
||||
* git:// or http://) and a transport object is returned to the caller.
|
||||
*
|
||||
* @param out The newly created transport (out)
|
||||
* @param owner The git_remote which will own this transport
|
||||
* @param url The URL to connect to
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_new(git_transport **out, git_remote *owner, const char *url);
|
||||
|
||||
/**
|
||||
* Create an ssh transport with custom git command paths
|
||||
*
|
||||
* This is a factory function suitable for setting as the transport
|
||||
* callback in a remote (or for a clone in the options).
|
||||
*
|
||||
* The payload argument must be a strarray pointer with the paths for
|
||||
* the `git-upload-pack` and `git-receive-pack` at index 0 and 1.
|
||||
*
|
||||
* @param out the resulting transport
|
||||
* @param owner the owning remote
|
||||
* @param payload a strarray with the paths
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_ssh_with_paths(git_transport **out, git_remote *owner, void *payload);
|
||||
|
||||
/* Signature of a function which creates a transport */
|
||||
typedef int (*git_transport_cb)(git_transport **out, git_remote *owner, void *param);
|
||||
|
||||
/**
|
||||
* Add a custom transport definition, to be used in addition to the built-in
|
||||
* set of transports that come with libgit2.
|
||||
*
|
||||
* The caller is responsible for synchronizing calls to git_transport_register
|
||||
* and git_transport_unregister with other calls to the library that
|
||||
* instantiate transports.
|
||||
*
|
||||
* @param prefix The scheme (ending in "://") to match, i.e. "git://"
|
||||
* @param cb The callback used to create an instance of the transport
|
||||
* @param param A fixed parameter to pass to cb at creation time
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_register(
|
||||
const char *prefix,
|
||||
git_transport_cb cb,
|
||||
void *param);
|
||||
|
||||
/**
|
||||
*
|
||||
* Unregister a custom transport definition which was previously registered
|
||||
* with git_transport_register.
|
||||
*
|
||||
* @param prefix From the previous call to git_transport_register
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_unregister(
|
||||
const char *prefix);
|
||||
|
||||
/* Transports which come with libgit2 (match git_transport_cb). The expected
|
||||
* value for "param" is listed in-line below. */
|
||||
|
||||
/**
|
||||
* Create an instance of the dummy transport.
|
||||
*
|
||||
* @param out The newly created transport (out)
|
||||
* @param owner The git_remote which will own this transport
|
||||
* @param payload You must pass NULL for this parameter.
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_dummy(
|
||||
git_transport **out,
|
||||
git_remote *owner,
|
||||
/* NULL */ void *payload);
|
||||
|
||||
/**
|
||||
* Create an instance of the local transport.
|
||||
*
|
||||
* @param out The newly created transport (out)
|
||||
* @param owner The git_remote which will own this transport
|
||||
* @param payload You must pass NULL for this parameter.
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_local(
|
||||
git_transport **out,
|
||||
git_remote *owner,
|
||||
/* NULL */ void *payload);
|
||||
|
||||
/**
|
||||
* Create an instance of the smart transport.
|
||||
*
|
||||
* @param out The newly created transport (out)
|
||||
* @param owner The git_remote which will own this transport
|
||||
* @param payload A pointer to a git_smart_subtransport_definition
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_smart(
|
||||
git_transport **out,
|
||||
git_remote *owner,
|
||||
/* (git_smart_subtransport_definition *) */ void *payload);
|
||||
|
||||
/*
|
||||
*** End of base transport interface ***
|
||||
*** Begin interface for subtransports for the smart transport ***
|
||||
*/
|
||||
|
||||
/* The smart transport knows how to speak the git protocol, but it has no
|
||||
* knowledge of how to establish a connection between it and another endpoint,
|
||||
* or how to move data back and forth. For this, a subtransport interface is
|
||||
* declared, and the smart transport delegates this work to the subtransports.
|
||||
* Three subtransports are implemented: git, http, and winhttp. (The http and
|
||||
* winhttp transports each implement both http and https.) */
|
||||
|
||||
/* Subtransports can either be RPC = 0 (persistent connection) or RPC = 1
|
||||
* (request/response). The smart transport handles the differences in its own
|
||||
* logic. The git subtransport is RPC = 0, while http and winhttp are both
|
||||
* RPC = 1. */
|
||||
|
||||
/* Actions that the smart transport can ask
|
||||
* a subtransport to perform */
|
||||
typedef enum {
|
||||
GIT_SERVICE_UPLOADPACK_LS = 1,
|
||||
GIT_SERVICE_UPLOADPACK = 2,
|
||||
GIT_SERVICE_RECEIVEPACK_LS = 3,
|
||||
GIT_SERVICE_RECEIVEPACK = 4,
|
||||
} git_smart_service_t;
|
||||
|
||||
typedef struct git_smart_subtransport git_smart_subtransport;
|
||||
typedef struct git_smart_subtransport_stream git_smart_subtransport_stream;
|
||||
|
||||
/* A stream used by the smart transport to read and write data
|
||||
* from a subtransport */
|
||||
struct git_smart_subtransport_stream {
|
||||
/* The owning subtransport */
|
||||
git_smart_subtransport *subtransport;
|
||||
|
||||
int (*read)(
|
||||
git_smart_subtransport_stream *stream,
|
||||
char *buffer,
|
||||
size_t buf_size,
|
||||
size_t *bytes_read);
|
||||
|
||||
int (*write)(
|
||||
git_smart_subtransport_stream *stream,
|
||||
const char *buffer,
|
||||
size_t len);
|
||||
|
||||
void (*free)(
|
||||
git_smart_subtransport_stream *stream);
|
||||
};
|
||||
|
||||
/* An implementation of a subtransport which carries data for the
|
||||
* smart transport */
|
||||
struct git_smart_subtransport {
|
||||
int (* action)(
|
||||
git_smart_subtransport_stream **out,
|
||||
git_smart_subtransport *transport,
|
||||
const char *url,
|
||||
git_smart_service_t action);
|
||||
|
||||
/* Subtransports are guaranteed a call to close() between
|
||||
* calls to action(), except for the following two "natural" progressions
|
||||
* of actions against a constant URL.
|
||||
*
|
||||
* 1. UPLOADPACK_LS -> UPLOADPACK
|
||||
* 2. RECEIVEPACK_LS -> RECEIVEPACK */
|
||||
int (*close)(git_smart_subtransport *transport);
|
||||
|
||||
void (*free)(git_smart_subtransport *transport);
|
||||
};
|
||||
|
||||
/* A function which creates a new subtransport for the smart transport */
|
||||
typedef int (*git_smart_subtransport_cb)(
|
||||
git_smart_subtransport **out,
|
||||
git_transport* owner);
|
||||
|
||||
typedef struct git_smart_subtransport_definition {
|
||||
/* The function to use to create the git_smart_subtransport */
|
||||
git_smart_subtransport_cb callback;
|
||||
|
||||
/* True if the protocol is stateless; false otherwise. For example,
|
||||
* http:// is stateless, but git:// is not. */
|
||||
unsigned rpc;
|
||||
} git_smart_subtransport_definition;
|
||||
|
||||
/* Smart transport subtransports that come with libgit2 */
|
||||
|
||||
/**
|
||||
* Create an instance of the http subtransport. This subtransport
|
||||
* also supports https. On Win32, this subtransport may be implemented
|
||||
* using the WinHTTP library.
|
||||
*
|
||||
* @param out The newly created subtransport
|
||||
* @param owner The smart transport to own this subtransport
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_smart_subtransport_http(
|
||||
git_smart_subtransport **out,
|
||||
git_transport* owner);
|
||||
|
||||
/**
|
||||
* Create an instance of the git subtransport.
|
||||
*
|
||||
* @param out The newly created subtransport
|
||||
* @param owner The smart transport to own this subtransport
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_smart_subtransport_git(
|
||||
git_smart_subtransport **out,
|
||||
git_transport* owner);
|
||||
|
||||
/**
|
||||
* Create an instance of the ssh subtransport.
|
||||
*
|
||||
* @param out The newly created subtransport
|
||||
* @param owner The smart transport to own this subtransport
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_smart_subtransport_ssh(
|
||||
git_smart_subtransport **out,
|
||||
git_transport* owner);
|
||||
|
||||
/**
|
||||
* Sets a custom transport factory for the remote. The caller can use this
|
||||
* function to override the transport used for this remote when performing
|
||||
* network operations.
|
||||
*
|
||||
* @param remote the remote to configure
|
||||
* @param transport_cb the function to use to create a transport
|
||||
* @param payload opaque parameter passed to transport_cb
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_remote_set_transport(
|
||||
git_remote *remote,
|
||||
git_transport_cb transport_cb,
|
||||
void *payload);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
@ -20,10 +20,6 @@
|
||||
*/
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
/*
|
||||
*** Begin interface for credentials acquisition ***
|
||||
*/
|
||||
|
||||
/** Authentication type requested */
|
||||
typedef enum {
|
||||
/* git_cred_userpass_plaintext */
|
||||
@ -227,335 +223,6 @@ typedef int (*git_cred_acquire_cb)(
|
||||
unsigned int allowed_types,
|
||||
void *payload);
|
||||
|
||||
/*
|
||||
*** End interface for credentials acquisition ***
|
||||
*** Begin base transport interface ***
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
GIT_TRANSPORTFLAGS_NONE = 0,
|
||||
/* If the connection is secured with SSL/TLS, the authenticity
|
||||
* of the server certificate should not be verified. */
|
||||
GIT_TRANSPORTFLAGS_NO_CHECK_CERT = 1
|
||||
} git_transport_flags_t;
|
||||
|
||||
typedef int (*git_transport_message_cb)(const char *str, int len, void *data);
|
||||
|
||||
typedef struct git_transport git_transport;
|
||||
|
||||
struct git_transport {
|
||||
unsigned int version;
|
||||
/* Set progress and error callbacks */
|
||||
int (*set_callbacks)(
|
||||
git_transport *transport,
|
||||
git_transport_message_cb progress_cb,
|
||||
git_transport_message_cb error_cb,
|
||||
void *payload);
|
||||
|
||||
/* Connect the transport to the remote repository, using the given
|
||||
* direction. */
|
||||
int (*connect)(
|
||||
git_transport *transport,
|
||||
const char *url,
|
||||
git_cred_acquire_cb cred_acquire_cb,
|
||||
void *cred_acquire_payload,
|
||||
int direction,
|
||||
int flags);
|
||||
|
||||
/* This function may be called after a successful call to
|
||||
* connect(). The array returned is owned by the transport and
|
||||
* is guranteed until the next call of a transport function. */
|
||||
int (*ls)(
|
||||
const git_remote_head ***out,
|
||||
size_t *size,
|
||||
git_transport *transport);
|
||||
|
||||
/* Executes the push whose context is in the git_push object. */
|
||||
int (*push)(git_transport *transport, git_push *push);
|
||||
|
||||
/* This function may be called after a successful call to connect(), when
|
||||
* the direction is FETCH. The function performs a negotiation to calculate
|
||||
* the wants list for the fetch. */
|
||||
int (*negotiate_fetch)(
|
||||
git_transport *transport,
|
||||
git_repository *repo,
|
||||
const git_remote_head * const *refs,
|
||||
size_t count);
|
||||
|
||||
/* This function may be called after a successful call to negotiate_fetch(),
|
||||
* when the direction is FETCH. This function retrieves the pack file for
|
||||
* the fetch from the remote end. */
|
||||
int (*download_pack)(
|
||||
git_transport *transport,
|
||||
git_repository *repo,
|
||||
git_transfer_progress *stats,
|
||||
git_transfer_progress_cb progress_cb,
|
||||
void *progress_payload);
|
||||
|
||||
/* Checks to see if the transport is connected */
|
||||
int (*is_connected)(git_transport *transport);
|
||||
|
||||
/* Reads the flags value previously passed into connect() */
|
||||
int (*read_flags)(git_transport *transport, int *flags);
|
||||
|
||||
/* Cancels any outstanding transport operation */
|
||||
void (*cancel)(git_transport *transport);
|
||||
|
||||
/* This function is the reverse of connect() -- it terminates the
|
||||
* connection to the remote end. */
|
||||
int (*close)(git_transport *transport);
|
||||
|
||||
/* Frees/destructs the git_transport object. */
|
||||
void (*free)(git_transport *transport);
|
||||
};
|
||||
|
||||
#define GIT_TRANSPORT_VERSION 1
|
||||
#define GIT_TRANSPORT_INIT {GIT_TRANSPORT_VERSION}
|
||||
|
||||
/**
|
||||
* Initializes a `git_transport` with default values. Equivalent to
|
||||
* creating an instance with GIT_TRANSPORT_INIT.
|
||||
*
|
||||
* @param opts the `git_transport` struct to initialize
|
||||
* @param version Version of struct; pass `GIT_TRANSPORT_VERSION`
|
||||
* @return Zero on success; -1 on failure.
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_init(
|
||||
git_transport *opts,
|
||||
unsigned int version);
|
||||
|
||||
/**
|
||||
* Function to use to create a transport from a URL. The transport database
|
||||
* is scanned to find a transport that implements the scheme of the URI (i.e.
|
||||
* git:// or http://) and a transport object is returned to the caller.
|
||||
*
|
||||
* @param out The newly created transport (out)
|
||||
* @param owner The git_remote which will own this transport
|
||||
* @param url The URL to connect to
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_new(git_transport **out, git_remote *owner, const char *url);
|
||||
|
||||
/**
|
||||
* Create an ssh transport with custom git command paths
|
||||
*
|
||||
* This is a factory function suitable for setting as the transport
|
||||
* callback in a remote (or for a clone in the options).
|
||||
*
|
||||
* The payload argument must be a strarray pointer with the paths for
|
||||
* the `git-upload-pack` and `git-receive-pack` at index 0 and 1.
|
||||
*
|
||||
* @param out the resulting transport
|
||||
* @param owner the owning remote
|
||||
* @param payload a strarray with the paths
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_ssh_with_paths(git_transport **out, git_remote *owner, void *payload);
|
||||
|
||||
/* Signature of a function which creates a transport */
|
||||
typedef int (*git_transport_cb)(git_transport **out, git_remote *owner, void *param);
|
||||
|
||||
/**
|
||||
* Add a custom transport definition, to be used in addition to the built-in
|
||||
* set of transports that come with libgit2.
|
||||
*
|
||||
* The caller is responsible for synchronizing calls to git_transport_register
|
||||
* and git_transport_unregister with other calls to the library that
|
||||
* instantiate transports.
|
||||
*
|
||||
* @param prefix The scheme (ending in "://") to match, i.e. "git://"
|
||||
* @param priority The priority of this transport relative to others with
|
||||
* the same prefix. Built-in transports have a priority of 1.
|
||||
* @param cb The callback used to create an instance of the transport
|
||||
* @param param A fixed parameter to pass to cb at creation time
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_register(
|
||||
const char *prefix,
|
||||
unsigned priority,
|
||||
git_transport_cb cb,
|
||||
void *param);
|
||||
|
||||
/**
|
||||
*
|
||||
* Unregister a custom transport definition which was previously registered
|
||||
* with git_transport_register.
|
||||
*
|
||||
* @param prefix From the previous call to git_transport_register
|
||||
* @param priority From the previous call to git_transport_register
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_unregister(
|
||||
const char *prefix,
|
||||
unsigned priority);
|
||||
|
||||
/* Transports which come with libgit2 (match git_transport_cb). The expected
|
||||
* value for "param" is listed in-line below. */
|
||||
|
||||
/**
|
||||
* Create an instance of the dummy transport.
|
||||
*
|
||||
* @param out The newly created transport (out)
|
||||
* @param owner The git_remote which will own this transport
|
||||
* @param payload You must pass NULL for this parameter.
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_dummy(
|
||||
git_transport **out,
|
||||
git_remote *owner,
|
||||
/* NULL */ void *payload);
|
||||
|
||||
/**
|
||||
* Create an instance of the local transport.
|
||||
*
|
||||
* @param out The newly created transport (out)
|
||||
* @param owner The git_remote which will own this transport
|
||||
* @param payload You must pass NULL for this parameter.
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_local(
|
||||
git_transport **out,
|
||||
git_remote *owner,
|
||||
/* NULL */ void *payload);
|
||||
|
||||
/**
|
||||
* Create an instance of the smart transport.
|
||||
*
|
||||
* @param out The newly created transport (out)
|
||||
* @param owner The git_remote which will own this transport
|
||||
* @param payload A pointer to a git_smart_subtransport_definition
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_smart(
|
||||
git_transport **out,
|
||||
git_remote *owner,
|
||||
/* (git_smart_subtransport_definition *) */ void *payload);
|
||||
|
||||
/*
|
||||
*** End of base transport interface ***
|
||||
*** Begin interface for subtransports for the smart transport ***
|
||||
*/
|
||||
|
||||
/* The smart transport knows how to speak the git protocol, but it has no
|
||||
* knowledge of how to establish a connection between it and another endpoint,
|
||||
* or how to move data back and forth. For this, a subtransport interface is
|
||||
* declared, and the smart transport delegates this work to the subtransports.
|
||||
* Three subtransports are implemented: git, http, and winhttp. (The http and
|
||||
* winhttp transports each implement both http and https.) */
|
||||
|
||||
/* Subtransports can either be RPC = 0 (persistent connection) or RPC = 1
|
||||
* (request/response). The smart transport handles the differences in its own
|
||||
* logic. The git subtransport is RPC = 0, while http and winhttp are both
|
||||
* RPC = 1. */
|
||||
|
||||
/* Actions that the smart transport can ask
|
||||
* a subtransport to perform */
|
||||
typedef enum {
|
||||
GIT_SERVICE_UPLOADPACK_LS = 1,
|
||||
GIT_SERVICE_UPLOADPACK = 2,
|
||||
GIT_SERVICE_RECEIVEPACK_LS = 3,
|
||||
GIT_SERVICE_RECEIVEPACK = 4,
|
||||
} git_smart_service_t;
|
||||
|
||||
typedef struct git_smart_subtransport git_smart_subtransport;
|
||||
typedef struct git_smart_subtransport_stream git_smart_subtransport_stream;
|
||||
|
||||
/* A stream used by the smart transport to read and write data
|
||||
* from a subtransport */
|
||||
struct git_smart_subtransport_stream {
|
||||
/* The owning subtransport */
|
||||
git_smart_subtransport *subtransport;
|
||||
|
||||
int (*read)(
|
||||
git_smart_subtransport_stream *stream,
|
||||
char *buffer,
|
||||
size_t buf_size,
|
||||
size_t *bytes_read);
|
||||
|
||||
int (*write)(
|
||||
git_smart_subtransport_stream *stream,
|
||||
const char *buffer,
|
||||
size_t len);
|
||||
|
||||
void (*free)(
|
||||
git_smart_subtransport_stream *stream);
|
||||
};
|
||||
|
||||
/* An implementation of a subtransport which carries data for the
|
||||
* smart transport */
|
||||
struct git_smart_subtransport {
|
||||
int (* action)(
|
||||
git_smart_subtransport_stream **out,
|
||||
git_smart_subtransport *transport,
|
||||
const char *url,
|
||||
git_smart_service_t action);
|
||||
|
||||
/* Subtransports are guaranteed a call to close() between
|
||||
* calls to action(), except for the following two "natural" progressions
|
||||
* of actions against a constant URL.
|
||||
*
|
||||
* 1. UPLOADPACK_LS -> UPLOADPACK
|
||||
* 2. RECEIVEPACK_LS -> RECEIVEPACK */
|
||||
int (*close)(git_smart_subtransport *transport);
|
||||
|
||||
void (*free)(git_smart_subtransport *transport);
|
||||
};
|
||||
|
||||
/* A function which creates a new subtransport for the smart transport */
|
||||
typedef int (*git_smart_subtransport_cb)(
|
||||
git_smart_subtransport **out,
|
||||
git_transport* owner);
|
||||
|
||||
typedef struct git_smart_subtransport_definition {
|
||||
/* The function to use to create the git_smart_subtransport */
|
||||
git_smart_subtransport_cb callback;
|
||||
|
||||
/* True if the protocol is stateless; false otherwise. For example,
|
||||
* http:// is stateless, but git:// is not. */
|
||||
unsigned rpc;
|
||||
} git_smart_subtransport_definition;
|
||||
|
||||
/* Smart transport subtransports that come with libgit2 */
|
||||
|
||||
/**
|
||||
* Create an instance of the http subtransport. This subtransport
|
||||
* also supports https. On Win32, this subtransport may be implemented
|
||||
* using the WinHTTP library.
|
||||
*
|
||||
* @param out The newly created subtransport
|
||||
* @param owner The smart transport to own this subtransport
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_smart_subtransport_http(
|
||||
git_smart_subtransport **out,
|
||||
git_transport* owner);
|
||||
|
||||
/**
|
||||
* Create an instance of the git subtransport.
|
||||
*
|
||||
* @param out The newly created subtransport
|
||||
* @param owner The smart transport to own this subtransport
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_smart_subtransport_git(
|
||||
git_smart_subtransport **out,
|
||||
git_transport* owner);
|
||||
|
||||
/**
|
||||
* Create an instance of the ssh subtransport.
|
||||
*
|
||||
* @param out The newly created subtransport
|
||||
* @param owner The smart transport to own this subtransport
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_smart_subtransport_ssh(
|
||||
git_smart_subtransport **out,
|
||||
git_transport* owner);
|
||||
|
||||
/*
|
||||
*** End interface for subtransports for the smart transport ***
|
||||
*/
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
|
@ -243,6 +243,16 @@ typedef struct git_transfer_progress {
|
||||
*/
|
||||
typedef int (*git_transfer_progress_cb)(const git_transfer_progress *stats, void *payload);
|
||||
|
||||
/**
|
||||
* Type for messages delivered by the transport. Return a negative value
|
||||
* to cancel the network operation.
|
||||
*
|
||||
* @param str The message from the transport
|
||||
* @param len The length of the message
|
||||
* @param payload Payload provided by the caller
|
||||
*/
|
||||
typedef int (*git_transport_message_cb)(const char *str, int len, void *payload);
|
||||
|
||||
/**
|
||||
* Opaque structure representing a submodule.
|
||||
*/
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "git2/remote.h"
|
||||
#include "git2/transport.h"
|
||||
#include "git2/sys/transport.h"
|
||||
|
||||
#include "refspec.h"
|
||||
#include "vector.h"
|
||||
|
144
src/transport.c
144
src/transport.c
@ -9,11 +9,11 @@
|
||||
#include "git2/remote.h"
|
||||
#include "git2/net.h"
|
||||
#include "git2/transport.h"
|
||||
#include "git2/sys/transport.h"
|
||||
#include "path.h"
|
||||
|
||||
typedef struct transport_definition {
|
||||
char *prefix;
|
||||
unsigned priority;
|
||||
git_transport_cb fn;
|
||||
void *param;
|
||||
} transport_definition;
|
||||
@ -24,51 +24,54 @@ static git_smart_subtransport_definition git_subtransport_definition = { git_sma
|
||||
static git_smart_subtransport_definition ssh_subtransport_definition = { git_smart_subtransport_ssh, 0 };
|
||||
#endif
|
||||
|
||||
static transport_definition local_transport_definition = { "file://", 1, git_transport_local, NULL };
|
||||
static transport_definition local_transport_definition = { "file://", git_transport_local, NULL };
|
||||
#ifdef GIT_SSH
|
||||
static transport_definition ssh_transport_definition = { "ssh://", 1, git_transport_smart, &ssh_subtransport_definition };
|
||||
static transport_definition ssh_transport_definition = { "ssh://", git_transport_smart, &ssh_subtransport_definition };
|
||||
#else
|
||||
static transport_definition dummy_transport_definition = { NULL, 1, git_transport_dummy, NULL };
|
||||
static transport_definition dummy_transport_definition = { NULL, git_transport_dummy, NULL };
|
||||
#endif
|
||||
|
||||
static transport_definition transports[] = {
|
||||
{"git://", 1, git_transport_smart, &git_subtransport_definition},
|
||||
{"http://", 1, git_transport_smart, &http_subtransport_definition},
|
||||
{"https://", 1, git_transport_smart, &http_subtransport_definition},
|
||||
{"file://", 1, git_transport_local, NULL},
|
||||
{ "git://", git_transport_smart, &git_subtransport_definition },
|
||||
{ "http://", git_transport_smart, &http_subtransport_definition },
|
||||
{ "https://", git_transport_smart, &http_subtransport_definition },
|
||||
{ "file://", git_transport_local, NULL },
|
||||
#ifdef GIT_SSH
|
||||
{"ssh://", 1, git_transport_smart, &ssh_subtransport_definition},
|
||||
{ "ssh://", git_transport_smart, &ssh_subtransport_definition },
|
||||
#endif
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static git_vector additional_transports = GIT_VECTOR_INIT;
|
||||
static git_vector custom_transports = GIT_VECTOR_INIT;
|
||||
|
||||
#define GIT_TRANSPORT_COUNT (sizeof(transports)/sizeof(transports[0])) - 1
|
||||
|
||||
static int transport_find_fn(const char *url, git_transport_cb *callback, void **param)
|
||||
static int transport_find_fn(
|
||||
git_transport_cb *out,
|
||||
const char *url,
|
||||
void **param)
|
||||
{
|
||||
size_t i = 0;
|
||||
unsigned priority = 0;
|
||||
transport_definition *definition = NULL, *definition_iter;
|
||||
transport_definition *d, *definition = NULL;
|
||||
|
||||
// First, check to see if it's an obvious URL, which a URL scheme
|
||||
for (i = 0; i < GIT_TRANSPORT_COUNT; ++i) {
|
||||
definition_iter = &transports[i];
|
||||
|
||||
if (strncasecmp(url, definition_iter->prefix, strlen(definition_iter->prefix)))
|
||||
continue;
|
||||
|
||||
if (definition_iter->priority > priority)
|
||||
definition = definition_iter;
|
||||
/* Find a user transport who wants to deal with this URI */
|
||||
git_vector_foreach(&custom_transports, i, d) {
|
||||
if (strncasecmp(url, d->prefix, strlen(d->prefix)) == 0) {
|
||||
definition = d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
git_vector_foreach(&additional_transports, i, definition_iter) {
|
||||
if (strncasecmp(url, definition_iter->prefix, strlen(definition_iter->prefix)))
|
||||
continue;
|
||||
/* Find a system transport for this URI */
|
||||
if (!definition) {
|
||||
for (i = 0; i < GIT_TRANSPORT_COUNT; ++i) {
|
||||
d = &transports[i];
|
||||
|
||||
if (definition_iter->priority > priority)
|
||||
definition = definition_iter;
|
||||
if (strncasecmp(url, d->prefix, strlen(d->prefix)) == 0) {
|
||||
definition = d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GIT_WIN32
|
||||
@ -100,9 +103,9 @@ static int transport_find_fn(const char *url, git_transport_cb *callback, void *
|
||||
#endif
|
||||
|
||||
if (!definition)
|
||||
return -1;
|
||||
return GIT_ENOTFOUND;
|
||||
|
||||
*callback = definition->fn;
|
||||
*out = definition->fn;
|
||||
*param = definition->param;
|
||||
|
||||
return 0;
|
||||
@ -128,10 +131,11 @@ int git_transport_new(git_transport **out, git_remote *owner, const char *url)
|
||||
void *param;
|
||||
int error;
|
||||
|
||||
if (transport_find_fn(url, &fn, ¶m) < 0) {
|
||||
if ((error = transport_find_fn(&fn, url, ¶m)) == GIT_ENOTFOUND) {
|
||||
giterr_set(GITERR_NET, "Unsupported URL protocol");
|
||||
return -1;
|
||||
}
|
||||
} else if (error < 0)
|
||||
return error;
|
||||
|
||||
if ((error = fn(&transport, owner, param)) < 0)
|
||||
return error;
|
||||
@ -144,59 +148,79 @@ int git_transport_new(git_transport **out, git_remote *owner, const char *url)
|
||||
}
|
||||
|
||||
int git_transport_register(
|
||||
const char *prefix,
|
||||
unsigned priority,
|
||||
const char *scheme,
|
||||
git_transport_cb cb,
|
||||
void *param)
|
||||
{
|
||||
transport_definition *d;
|
||||
git_buf prefix = GIT_BUF_INIT;
|
||||
transport_definition *d, *definition = NULL;
|
||||
size_t i;
|
||||
int error = 0;
|
||||
|
||||
d = git__calloc(sizeof(transport_definition), 1);
|
||||
GITERR_CHECK_ALLOC(d);
|
||||
assert(scheme);
|
||||
assert(cb);
|
||||
|
||||
d->prefix = git__strdup(prefix);
|
||||
|
||||
if (!d->prefix)
|
||||
if ((error = git_buf_printf(&prefix, "%s://", scheme)) < 0)
|
||||
goto on_error;
|
||||
|
||||
d->priority = priority;
|
||||
d->fn = cb;
|
||||
d->param = param;
|
||||
git_vector_foreach(&custom_transports, i, d) {
|
||||
if (strcasecmp(d->prefix, prefix.ptr) == 0) {
|
||||
error = GIT_EEXISTS;
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
if (git_vector_insert(&additional_transports, d) < 0)
|
||||
definition = git__calloc(1, sizeof(transport_definition));
|
||||
GITERR_CHECK_ALLOC(definition);
|
||||
|
||||
definition->prefix = git_buf_detach(&prefix);
|
||||
definition->fn = cb;
|
||||
definition->param = param;
|
||||
|
||||
if (git_vector_insert(&custom_transports, definition) < 0)
|
||||
goto on_error;
|
||||
|
||||
return 0;
|
||||
|
||||
on_error:
|
||||
git__free(d->prefix);
|
||||
git__free(d);
|
||||
return -1;
|
||||
git_buf_free(&prefix);
|
||||
git__free(definition);
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_transport_unregister(
|
||||
const char *prefix,
|
||||
unsigned priority)
|
||||
int git_transport_unregister(const char *scheme)
|
||||
{
|
||||
git_buf prefix = GIT_BUF_INIT;
|
||||
transport_definition *d;
|
||||
unsigned i;
|
||||
size_t i;
|
||||
int error = 0;
|
||||
|
||||
git_vector_foreach(&additional_transports, i, d) {
|
||||
if (d->priority == priority && !strcasecmp(d->prefix, prefix)) {
|
||||
if (git_vector_remove(&additional_transports, i) < 0)
|
||||
return -1;
|
||||
assert(scheme);
|
||||
|
||||
if ((error = git_buf_printf(&prefix, "%s://", scheme)) < 0)
|
||||
goto done;
|
||||
|
||||
git_vector_foreach(&custom_transports, i, d) {
|
||||
if (strcasecmp(d->prefix, prefix.ptr) == 0) {
|
||||
if ((error = git_vector_remove(&custom_transports, i)) < 0)
|
||||
goto done;
|
||||
|
||||
git__free(d->prefix);
|
||||
git__free(d);
|
||||
|
||||
if (!additional_transports.length)
|
||||
git_vector_free(&additional_transports);
|
||||
if (!custom_transports.length)
|
||||
git_vector_free(&custom_transports);
|
||||
|
||||
return 0;
|
||||
error = 0;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
return GIT_ENOTFOUND;
|
||||
error = GIT_ENOTFOUND;
|
||||
|
||||
done:
|
||||
git_buf_free(&prefix);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* from remote.h */
|
||||
@ -205,7 +229,7 @@ int git_remote_valid_url(const char *url)
|
||||
git_transport_cb fn;
|
||||
void *param;
|
||||
|
||||
return !transport_find_fn(url, &fn, ¶m);
|
||||
return !transport_find_fn(&fn, url, ¶m);
|
||||
}
|
||||
|
||||
int git_remote_supported_url(const char* url)
|
||||
@ -213,7 +237,7 @@ int git_remote_supported_url(const char* url)
|
||||
git_transport_cb fn;
|
||||
void *param;
|
||||
|
||||
if (transport_find_fn(url, &fn, ¶m) < 0)
|
||||
if (transport_find_fn(&fn, url, ¶m) < 0)
|
||||
return 0;
|
||||
|
||||
return fn != &git_transport_dummy;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "git2.h"
|
||||
#include "buffer.h"
|
||||
#include "netops.h"
|
||||
#include "git2/sys/transport.h"
|
||||
|
||||
#define OWNING_SUBTRANSPORT(s) ((git_subtransport *)(s)->parent.subtransport)
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "netops.h"
|
||||
#include "buffer.h"
|
||||
#include "push.h"
|
||||
#include "git2/sys/transport.h"
|
||||
|
||||
#define GIT_SIDE_BAND_DATA 1
|
||||
#define GIT_SIDE_BAND_PROGRESS 2
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "git2/clone.h"
|
||||
#include "git2/transport.h"
|
||||
#include "git2/sys/transport.h"
|
||||
#include "fileops.h"
|
||||
|
||||
static int custom_transport(
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <git2/sys/config.h>
|
||||
#include <git2/sys/odb_backend.h>
|
||||
#include <git2/sys/refdb_backend.h>
|
||||
#include <git2/sys/transport.h>
|
||||
|
||||
#define STRINGIFY(s) #s
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user