Git-Raw

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

    + add_conflict
    + get_conflict
    + merge
 - Added Index::Entry methods (Beta) (GH#146):
    + clone
 - Added Merge::File::Result methods (Beta) (GH#146):
    + automergeable
    + content
    + path
 - The supported authentication types are now supplied to the Remote's
   credentials callback.
 - Update libgit2 to 4c53489 (GH#147)
 - Removed Remote methods (GH#147) (Incompatible change):
    + check_cert()
 - Added Remote certificate callback (GH#148)

0.46      2014-09-19 12:42:13+02:00 Africa/Johannesburg

 - Fix more test cases that were failing if diff.mnemonicprefix is set (GH#143)
 - Revert previous attempt at getting WinHTTP to work

Changes  view on Meta::CPAN


 - Fix build with glibc < 2.17

0.25      2013-10-09 15:17:56 Europe/Rome

 - Update to libgit2 711333e
    + Rename Branch -> tracking() to upstream() (incompatible change)
    + Rename Remote -> fetchspec() to add_fetch and pushspec to add_push()
      They will not return the remote spec anymore (incompatible change)
 - Enable support for libssh2 at build-time
 - Add support for SSH key credentials via Cred -> keyfile()
 - Add Remote -> callbacks() method
 - Add Remote -> load() method

0.24      2013-03-31 13:06:30 Europe/Rome

 - Update libgit2 to d2a4a54
 - Config -> bool()/int()/str() now return undef when a configuration variable
   is not found, instead of segfaulting (GH#13)

0.23      2013-03-25 14:09:09 Europe/Rome

Raw.xs  view on Meta::CPAN

		}
	}

	PUTBACK;
	FREETMPS;
	LEAVE;

	return rv;
}

STATIC int git_credentials_cbb(git_cred **cred, const char *url,
		const char *usr_from_url, unsigned int allow, void *cbs) {
	dSP;
	int rv = 0;
	AV *types = newAV();
	Cred creds;

	if (allow & GIT_CREDTYPE_USERPASS_PLAINTEXT)
		av_push(types, newSVpv("userpass_plaintext", 0));
	if (allow & GIT_CREDTYPE_SSH_KEY)
		av_push(types, newSVpv("ssh_key", 0));

Raw.xs  view on Meta::CPAN


	ENTER;
	SAVETMPS;

	PUSHMARK(SP);
	mXPUSHs(newSVpv(url, 0));
	mXPUSHs(newSVpv(usr_from_url, 0));
	mXPUSHs(newRV_noinc((SV *)types));
	PUTBACK;

	call_sv(git_hv_code_entry((HV *)cbs, "credentials"), G_EVAL|G_SCALAR);

	SPAGAIN;

	if (SvTRUE(ERRSV)) {
		rv = GIT_PASSTHROUGH;
		(void) POPs;
	} else {
		SV *c = POPs;
		if (SvOK(c)) {
			creds = GIT_SV_TO_PTR(Cred, c);

Raw.xs  view on Meta::CPAN

		if ((stash_opts->progress_payload = get_callback_option(hopt, "apply_progress")))
			stash_opts->progress_cb = git_stash_apply_progress_cbb;

		SAVEFREESV(MUTABLE_SV(stash_opts->progress_payload));
	}
}

STATIC void git_hv_to_remote_callbacks(HV *opts, git_remote_callbacks *callbacks) {
	callbacks->payload = (void *)opts;

	if (get_callback_option(opts, "credentials"))
		callbacks->credentials = git_credentials_cbb;

	if (get_callback_option(opts, "certificate_check"))
		callbacks->certificate_check = git_certificate_check_cbb;

	if (get_callback_option(opts, "sideband_progress"))
		callbacks->sideband_progress = git_sideband_progress_cbb;

	if (get_callback_option(opts, "transfer_progress"))
		callbacks->transfer_progress = git_transfer_progress_cbb;

deps/libgit2/deps/ntlmclient/ntlm.c  view on Meta::CPAN

			&ntlm->hostname_utf16,
			&ntlm->hostname_utf16_len,
			ntlm,
			hostname,
			strlen(hostname)))
		return -1;

	return 0;
}

static void free_credentials(ntlm_client *ntlm)
{
	if (ntlm->password)
		ntlm_memzero(ntlm->password, strlen(ntlm->password));

	if (ntlm->password_utf16)
		ntlm_memzero(ntlm->password_utf16, ntlm->password_utf16_len);

	reset(ntlm->username);
	reset(ntlm->username_upper);
	reset(ntlm->userdomain);

deps/libgit2/deps/ntlmclient/ntlm.c  view on Meta::CPAN

	reset(ntlm->username_upper_utf16);
	reset(ntlm->userdomain_utf16);
	reset(ntlm->password_utf16);

	ntlm->username_utf16_len = 0;
	ntlm->username_upper_utf16_len = 0;
	ntlm->userdomain_utf16_len = 0;
	ntlm->password_utf16_len = 0;
}

int ntlm_client_set_credentials(
	ntlm_client *ntlm,
	const char *username,
	const char *domain,
	const char *password)
{
	NTLM_ASSERT_ARG(ntlm);
	ENSURE_INITIALIZED(ntlm);

	free_credentials(ntlm);

	if ((username && (ntlm->username = strdup(username)) == NULL) ||
		(domain && (ntlm->userdomain = strdup(domain)) == NULL) ||
		(password && (ntlm->password = strdup(password)) == NULL)) {
		ntlm_client_set_errmsg(ntlm, "out of memory");
		return -1;
	}

	if (username && supports_unicode(ntlm)) {
		if ((ntlm->username_upper = strdup(username)) == NULL) {

deps/libgit2/deps/ntlmclient/ntlm.c  view on Meta::CPAN

	ntlm->state = NTLM_STATE_NEGOTIATE;

	free_hostname(ntlm);

	memset(&ntlm->host_version, 0, sizeof(ntlm_version));

	reset(ntlm->target);
	reset(ntlm->target_utf16);
	ntlm->target_utf16_len = 0;

	free_credentials(ntlm);

	ntlm->nonce = 0;
	ntlm->timestamp = 0;

	memset(ntlm->lm_response, 0, NTLM_LM_RESPONSE_LEN);
	ntlm->lm_response_len = 0;

	memset(ntlm->ntlm_response, 0, NTLM_NTLM_RESPONSE_LEN);
	ntlm->ntlm_response_len = 0;

deps/libgit2/deps/ntlmclient/ntlmclient.h  view on Meta::CPAN

 * domain should be in ASCII.  These will not be sent to the remote host
 * but will instead be used to compute the LM, NTLM or NTLM2 responses,
 * which will be provided to the remote host during the response phase.
 *
 * @param ntlm the `ntlm_client` context to configure
 * @param username the username to authenticate with
 * @param domain the domain of the user authenticating
 * @param password the password to authenticate with
 * @return 0 on success, non-zero on failure
 */
NTLM_EXTERN(int) ntlm_client_set_credentials(
	ntlm_client *ntlm,
	const char *username,
	const char *domain,
	const char *password);

/**
 * Sets the authentication target, your idea of the remote host's
 * name.  The target should be provided as ASCII.  It will be
 * provided to the remote host during the response phase.
 *

deps/libgit2/deps/ntlmclient/ntlmclient.h  view on Meta::CPAN

 * @param message_len the length of the challenge message
 * @return 0 on success, non-zero on failure
 */
NTLM_EXTERN(int) ntlm_client_set_challenge(
	ntlm_client *ntlm,
	const unsigned char *message,
	size_t message_len);

/**
 * Computes a response message (aka a "Type 3" message) to complete
 * NTLM authentication with the server.  The credentials should be
 * set before calling this function.  This message should be delivered
 * to the server to complete authentication.  This buffer should not
 * be freed by the caller.
 *
 * @param out a pointer to the response message
 * @param out_len a pointer to the length of the response message
 * @param ntlm the `ntlm_client` context
 * @return 0 on success, non-zero on failure
 */
NTLM_EXTERN(int) ntlm_client_response(

deps/libgit2/include/git2/clone.h  view on Meta::CPAN

	 * These options are passed to the checkout step. To disable
	 * checkout, set the `checkout_strategy` to
	 * `GIT_CHECKOUT_NONE`.
	 */
	git_checkout_options checkout_opts;

	/**
	 * Options which control the fetch, including callbacks.
	 *
	 * The callbacks are used for reporting fetch progress, and for acquiring
	 * credentials in the event they are needed.
	 */
	git_fetch_options fetch_opts;

	/**
	 * Set to zero (false) to create a standard repo, or non-zero
	 * for a bare repo
	 */
	int bare;

	/**

deps/libgit2/include/git2/credential.h  view on Meta::CPAN

	 * (eg. SSH, with no username in its URL) does not know which username
	 * to use.
	 *
	 * @see git_credential_username_new
	 */
	GIT_CREDENTIAL_USERNAME = (1u << 5),

	/**
	 * An SSH key-based authentication request
	 *
	 * Allows credentials to be read from memory instead of files.
	 * Note that because of differences in crypto backend support, it might
	 * not be functional.
	 *
	 * @see git_credential_ssh_key_memory_new
	 */
	GIT_CREDENTIAL_SSH_MEMORY = (1u << 6)
} git_credential_t;

/**
 * The base structure for all credential types
 */
typedef struct git_credential git_credential;

typedef struct git_credential_userpass_plaintext git_credential_userpass_plaintext;

/** Username-only credential information */
typedef struct git_credential_username git_credential_username;

/** A key for NTLM/Kerberos "default" credentials */
typedef struct git_credential git_credential_default;

/**
 * A ssh key from disk
 */
typedef struct git_credential_ssh_key git_credential_ssh_key;

/**
 * Keyboard-interactive based ssh authentication
 */

deps/libgit2/include/git2/credential.h  view on Meta::CPAN

 * Credential acquisition callback.
 *
 * This callback is usually involved any time another system might need
 * authentication. As such, you are expected to provide a valid
 * git_credential object back, depending on allowed_types (a
 * git_credential_t bitmask).
 *
 * Note that most authentication details are your responsibility - this
 * callback will be called until the authentication succeeds, or you report
 * an error. As such, it's easy to get in a loop if you fail to stop providing
 * the same incorrect credentials.
 *
 * @param out The newly created credential object.
 * @param url The resource for which we are demanding a credential.
 * @param username_from_url The username that was embedded in a "user\@host"
 *                          remote url, or NULL if not included.
 * @param allowed_types A bitmask stating which credential types are OK to return.
 * @param payload The payload provided when specifying this callback.
 * @return 0 for success, < 0 to indicate an error, > 0 to indicate
 *       no credential was acquired
 */

deps/libgit2/include/git2/proxy.h  view on Meta::CPAN

	 */
	const char *url;

	/**
	 * This will be called if the remote host requires
	 * authentication in order to connect to it.
	 *
	 * Returning GIT_PASSTHROUGH will make libgit2 behave as
	 * though this field isn't set.
	 */
	git_credential_acquire_cb credentials;

	/**
	 * If cert verification fails, this will be called to let the
	 * user make the final decision of whether to allow the
	 * connection to proceed. Returns 0 to allow the connection
	 * or a negative value to indicate an error.
	 */
	git_transport_certificate_check_cb certificate_check;

	/**
	 * Payload to be provided to the credentials and certificate
	 * check callbacks.
	 */
	void *payload;
} git_proxy_options;

#define GIT_PROXY_OPTIONS_VERSION 1
#define GIT_PROXY_OPTIONS_INIT {GIT_PROXY_OPTIONS_VERSION}

/**
 * Initialize git_proxy_options structure

deps/libgit2/include/git2/remote.h  view on Meta::CPAN

	 */
	int GIT_CALLBACK(completion)(git_remote_completion_t type, void *data);

	/**
	 * This will be called if the remote host requires
	 * authentication in order to connect to it.
	 *
	 * Returning GIT_PASSTHROUGH will make libgit2 behave as
	 * though this field isn't set.
	 */
	git_credential_acquire_cb credentials;

	/**
	 * If cert verification fails, this will be called to let the
	 * user make the final decision of whether to allow the
	 * connection to proceed. Returns 0 to allow the connection
	 * or a negative value to indicate an error.
	 */
	git_transport_certificate_check_cb certificate_check;

	/**

deps/libgit2/include/git2/submodule.h  view on Meta::CPAN

	 * `GIT_CHECKOUT_NONE`. Generally you will want the use
	 * GIT_CHECKOUT_SAFE to update files in the working
	 * directory.
	 */
	git_checkout_options checkout_opts;

	/**
	 * Options which control the fetch, including callbacks.
	 *
	 * The callbacks to use for reporting fetch progress, and for acquiring
	 * credentials in the event they are needed.
	 */
	git_fetch_options fetch_opts;

	/**
	 * Allow fetching from the submodule's default remote if the target
	 * commit isn't found. Enabled by default.
	 */
	int allow_fetch;
} git_submodule_update_options;

deps/libgit2/include/git2/sys/credential.h  view on Meta::CPAN

 * a Linking Exception. For full terms see the included COPYING file.
 */
#ifndef INCLUDE_sys_git_credential_h__
#define INCLUDE_sys_git_credential_h__

#include "git2/common.h"
#include "git2/credential.h"

/**
 * @file git2/sys/cred.h
 * @brief Git credentials low-level implementation
 * @defgroup git_credential Git credentials low-level implementation
 * @ingroup Git
 * @{
 */
GIT_BEGIN_DECL

/**
 * The base structure for all credential types
 */
struct git_credential {
	git_credential_t credtype; /**< A type of credential */

	/** The deallocator for this type of credentials */
	void GIT_CALLBACK(free)(git_credential *cred);
};

/** A plaintext username and password */
struct git_credential_userpass_plaintext {
	git_credential parent; /**< The parent credential */
	char *username;        /**< The username to authenticate as */
	char *password;        /**< The password to use */
};

deps/libgit2/include/git2/sys/transport.h  view on Meta::CPAN

 * @param valid whether we believe the certificate is valid
 * @param hostname the hostname we connected to
 * @return the return value of the callback: 0 for no error, GIT_PASSTHROUGH
 *         to indicate that there is no callback registered (or the callback
 *         refused to validate the certificate and callers should behave as
 *         if no callback was set), or < 0 for an error
 */
GIT_EXTERN(int) git_transport_smart_certificate_check(git_transport *transport, git_cert *cert, int valid, const char *hostname);

/**
 * Call the credentials callback for this transport
 *
 * @param out the pointer where the creds are to be stored
 * @param transport a smart transport
 * @param user the user we saw on the url (if any)
 * @param methods available methods for authentication
 * @return the return value of the callback: 0 for no error, GIT_PASSTHROUGH
 *         to indicate that there is no callback registered (or the callback
 *         refused to provide credentials and callers should behave as if no
 *         callback was set), or < 0 for an error
 */
GIT_EXTERN(int) git_transport_smart_credentials(git_credential **out, git_transport *transport, const char *user, int methods);

/**
 * Get a copy of the remote connect options
 *
 * All data is copied and must be freed by the caller by calling
 * `git_remote_connect_options_dispose`.
 *
 * @param out options struct to fill
 * @param transport the transport to extract the data from.
 */

deps/libgit2/src/libgit2/transports/auth.h  view on Meta::CPAN

	GIT_HTTP_AUTH_NEGOTIATE = 2,
	GIT_HTTP_AUTH_NTLM = 4
} git_http_auth_t;

typedef struct git_http_auth_context git_http_auth_context;

struct git_http_auth_context {
	/** Type of scheme */
	git_http_auth_t type;

	/** Supported credentials */
	git_credential_t credtypes;

	/** Connection affinity or request affinity */
	unsigned connection_affinity : 1;

	/** Sets the challenge on the authentication context */
	int (*set_challenge)(git_http_auth_context *ctx, const char *challenge);

	/** Gets the next authentication token from the context */
	int (*next_token)(git_str *out, git_http_auth_context *ctx, git_credential *cred);

deps/libgit2/src/libgit2/transports/auth_ntlm.c  view on Meta::CPAN

	GIT_ASSERT_ARG(challenge);

	git__free(ctx->challenge);

	ctx->challenge = git__strdup(challenge);
	GIT_ERROR_CHECK_ALLOC(ctx->challenge);

	return 0;
}

static int ntlm_set_credentials(http_auth_ntlm_context *ctx, git_credential *_cred)
{
	git_credential_userpass_plaintext *cred;
	const char *sep, *username;
	char *domain = NULL, *domainuser = NULL;
	int error = 0;

	GIT_ASSERT(_cred->credtype == GIT_CREDENTIAL_USERPASS_PLAINTEXT);
	cred = (git_credential_userpass_plaintext *)_cred;

	if ((sep = strchr(cred->username, '\\')) != NULL) {

deps/libgit2/src/libgit2/transports/auth_ntlm.c  view on Meta::CPAN

		GIT_ERROR_CHECK_ALLOC(domain);

		domainuser = git__strdup(sep + 1);
		GIT_ERROR_CHECK_ALLOC(domainuser);

		username = domainuser;
	} else {
		username = cred->username;
	}

	if (ntlm_client_set_credentials(ctx->ntlm,
	    username, domain, cred->password) < 0) {
		git_error_set(GIT_ERROR_NET, "could not set credentials: %s",
		    ntlm_client_errmsg(ctx->ntlm));
		error = -1;
		goto done;
	}

done:
	git__free(domain);
	git__free(domainuser);
	return error;
}

deps/libgit2/src/libgit2/transports/auth_ntlm.c  view on Meta::CPAN

	if (ctx->complete)
		ntlm_client_reset(ctx->ntlm);

	/*
	 * Set us complete now since it's the default case; the one
	 * incomplete case (successfully created a client request)
	 * will explicitly set that it requires a second step.
	 */
	ctx->complete = true;

	if (cred && ntlm_set_credentials(ctx, cred) != 0)
		goto done;

	if (challenge_len < 4) {
		git_error_set(GIT_ERROR_NET, "no ntlm challenge sent from server");
		goto done;
	} else if (challenge_len == 4) {
		if (memcmp(ctx->challenge, "NTLM", 4) != 0) {
			git_error_set(GIT_ERROR_NET, "server did not request NTLM");
			goto done;
		}

deps/libgit2/src/libgit2/transports/credential.c  view on Meta::CPAN

		passphrase,
		GIT_CREDENTIAL_SSH_MEMORY);
#else
	GIT_UNUSED(cred);
	GIT_UNUSED(username);
	GIT_UNUSED(publickey);
	GIT_UNUSED(privatekey);
	GIT_UNUSED(passphrase);

	git_error_set(GIT_ERROR_INVALID,
		"this version of libgit2 was not built with ssh memory credentials.");
	return -1;
#endif
}

static int git_credential_ssh_key_type_new(
	git_credential **cred,
	const char *username,
	const char *publickey,
	const char *privatekey,
	const char *passphrase,

deps/libgit2/src/libgit2/transports/credential_helpers.c  view on Meta::CPAN

		void *payload)
{
	git_credential_userpass_payload *userpass = (git_credential_userpass_payload*)payload;
	const char *effective_username = NULL;

	GIT_UNUSED(url);

	if (!userpass || !userpass->password) return -1;

	/* Username resolution: a username can be passed with the URL, the
	 * credentials payload, or both. Here's what we do.  Note that if we get
	 * this far, we know that any password the url may contain has already
	 * failed at least once, so we ignore it.
	 *
	 * |  Payload    |   URL    |   Used    |
	 * +-------------+----------+-----------+
	 * |    yes      |   no     |  payload  |
	 * |    yes      |   yes    |  payload  |
	 * |    no       |   yes    |  url      |
	 * |    no       |   no     |  FAIL     |
	 */

deps/libgit2/src/libgit2/transports/http.c  view on Meta::CPAN

	"application/x-git-receive-pack-result",
	0,
	1
};

#define SERVER_TYPE_REMOTE "remote"
#define SERVER_TYPE_PROXY  "proxy"

#define OWNING_SUBTRANSPORT(s) ((http_subtransport *)(s)->parent.subtransport)

static int apply_url_credentials(
	git_credential **cred,
	unsigned int allowed_types,
	const char *username,
	const char *password)
{
	GIT_ASSERT_ARG(username);

	if (!password)
		password = "";

deps/libgit2/src/libgit2/transports/http.c  view on Meta::CPAN

	unsigned int allowed_schemetypes,
	unsigned int allowed_credtypes,
	git_credential_acquire_cb callback,
	void *callback_payload)
{
	int error = 1;

	if (server->cred)
		free_cred(&server->cred);

	/* Start with URL-specified credentials, if there were any. */
	if ((allowed_credtypes & GIT_CREDENTIAL_USERPASS_PLAINTEXT) &&
	    !server->url_cred_presented &&
	    server->url.username) {
		error = apply_url_credentials(&server->cred, allowed_credtypes, server->url.username, server->url.password);
		server->url_cred_presented = 1;

		/* treat GIT_PASSTHROUGH as if callback isn't set */
		if (error == GIT_PASSTHROUGH)
			error = 1;
	}

	if (error > 0 && callback) {
		error = callback(&server->cred, url, server->url.username, allowed_credtypes, callback_payload);

deps/libgit2/src/libgit2/transports/http.c  view on Meta::CPAN

	git_http_response *response)
{
	http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
	git_remote_connect_options *connect_opts = &transport->owner->connect_opts;

	if (response->server_auth_credtypes == 0) {
		git_error_set(GIT_ERROR_HTTP, "server requires authentication that we do not support");
		return GIT_EAUTH;
	}

	/* Otherwise, prompt for credentials. */
	return handle_auth(
		&transport->server,
		SERVER_TYPE_REMOTE,
		transport->owner->url,
		response->server_auth_schemetypes,
		response->server_auth_credtypes,
		connect_opts->callbacks.credentials,
		connect_opts->callbacks.payload);
}

GIT_INLINE(int) handle_proxy_auth(
	http_stream *stream,
	git_http_response *response)
{
	http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
	git_remote_connect_options *connect_opts = &transport->owner->connect_opts;

	if (response->proxy_auth_credtypes == 0) {
		git_error_set(GIT_ERROR_HTTP, "proxy requires authentication that we do not support");
		return GIT_EAUTH;
	}

	/* Otherwise, prompt for credentials. */
	return handle_auth(
		&transport->proxy,
		SERVER_TYPE_PROXY,
		connect_opts->proxy_opts.url,
		response->server_auth_schemetypes,
		response->proxy_auth_credtypes,
		connect_opts->proxy_opts.credentials,
		connect_opts->proxy_opts.payload);
}

static bool allow_redirect(http_stream *stream)
{
	http_subtransport *transport = OWNING_SUBTRANSPORT(stream);

	switch (transport->owner->connect_opts.follow_redirects) {
	case GIT_REMOTE_REDIRECT_INITIAL:
		return (stream->service->initial == 1);

deps/libgit2/src/libgit2/transports/http.c  view on Meta::CPAN

			return -1;
		}

		return 0;
	} else if (git_http_response_is_redirect(response)) {
		git_error_set(GIT_ERROR_HTTP, "unexpected redirect");
		return -1;
	}

	/* If we're in the middle of challenge/response auth, continue. */
	if (allow_replay && response->resend_credentials) {
		return 0;
	} else if (allow_replay && response->status == GIT_HTTP_STATUS_UNAUTHORIZED) {
		if ((error = handle_remote_auth(stream, response)) < 0)
			return error;

		return git_http_client_skip_body(transport->http_client);
	} else if (allow_replay && response->status == GIT_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED) {
		if ((error = handle_proxy_auth(stream, response)) < 0)
			return error;

deps/libgit2/src/libgit2/transports/http.c  view on Meta::CPAN

	bool use_proxy = false;
	int error;

	if ((error = git_net_url_joinpath(url,
		&transport->server.url, stream->service->url)) < 0 ||
	    (error = lookup_proxy(&use_proxy, transport)) < 0)
		return error;

	request->method = stream->service->method;
	request->url = url;
	request->credentials = transport->server.cred;
	request->proxy = use_proxy ? &transport->proxy.url : NULL;
	request->proxy_credentials = transport->proxy.cred;
	request->custom_headers = &transport->owner->connect_opts.custom_headers;

	if (stream->service->method == GIT_HTTP_METHOD_POST) {
		request->chunked = stream->service->chunked;
		request->content_length = stream->service->chunked ? 0 : len;
		request->content_type = stream->service->request_type;
		request->accept = stream->service->response_type;
		request->expect_continue = git_http__expect_continue;
	}

deps/libgit2/src/libgit2/transports/httpclient.c  view on Meta::CPAN

	ctx->client->keepalive = http_should_keep_alive(parser);

	/* Prepare for authentication */
	collect_authinfo(&ctx->response->server_auth_schemetypes,
	                 &ctx->response->server_auth_credtypes,
	                 &ctx->client->server.auth_challenges);
	collect_authinfo(&ctx->response->proxy_auth_schemetypes,
	                 &ctx->response->proxy_auth_credtypes,
	                 &ctx->client->proxy.auth_challenges);

	ctx->response->resend_credentials = resend_needed(ctx->client,
	                                                  ctx->response);

	/* Stop parsing. */
	http_parser_pause(parser, 1);

	if (ctx->response->content_type || ctx->response->chunked)
		ctx->client->state = READING_BODY;
	else
		ctx->client->state = DONE;

deps/libgit2/src/libgit2/transports/httpclient.c  view on Meta::CPAN

	case GIT_HTTP_METHOD_POST:
		return "POST";
	case GIT_HTTP_METHOD_CONNECT:
		return "CONNECT";
	}

	return NULL;
}

/*
 * Find the scheme that is suitable for the given credentials, based on the
 * server's auth challenges.
 */
static bool best_scheme_and_challenge(
	git_http_auth_scheme **scheme_out,
	const char **challenge_out,
	git_vector *challenges,
	git_credential *credentials)
{
	const char *challenge;
	size_t i, j;

	for (i = 0; i < ARRAY_SIZE(auth_schemes); i++) {
		git_vector_foreach(challenges, j, challenge) {
			git_http_auth_scheme *scheme = &auth_schemes[i];

			if (challenge_matches_scheme(challenge, scheme) &&
			    (scheme->credtypes & credentials->credtype)) {
				*scheme_out = scheme;
				*challenge_out = challenge;
				return true;
			}
		}
	}

	return false;
}

deps/libgit2/src/libgit2/transports/httpclient.c  view on Meta::CPAN

			}
		}
	}

	return NULL;
}

static const char *init_auth_context(
	git_http_server *server,
	git_vector *challenges,
	git_credential *credentials)
{
	git_http_auth_scheme *scheme;
	const char *challenge;
	int error;

	if (!best_scheme_and_challenge(&scheme, &challenge, challenges, credentials)) {
		git_error_set(GIT_ERROR_HTTP, "could not find appropriate mechanism for credentials");
		return NULL;
	}

	error = scheme->init_context(&server->auth_context, &server->url);

	if (error == GIT_PASSTHROUGH) {
		git_error_set(GIT_ERROR_HTTP, "'%s' authentication is not supported", scheme->name);
		return NULL;
	}

deps/libgit2/src/libgit2/transports/httpclient.c  view on Meta::CPAN

{
	if (!server->auth_context)
		return;

	if (server->auth_context->free)
		server->auth_context->free(server->auth_context);

	server->auth_context = NULL;
}

static int apply_credentials(
	git_str *buf,
	git_http_server *server,
	const char *header_name,
	git_credential *credentials)
{
	git_http_auth_context *auth = server->auth_context;
	git_vector *challenges = &server->auth_challenges;
	const char *challenge;
	git_str token = GIT_STR_INIT;
	int error = 0;

	/* We've started a new request without creds; free the context. */
	if (auth && !credentials) {
		free_auth_context(server);
		return 0;
	}

	/* We haven't authenticated, nor were we asked to.  Nothing to do. */
	if (!auth && !git_vector_length(challenges))
		return 0;

	if (!auth) {
		challenge = init_auth_context(server, challenges, credentials);
		auth = server->auth_context;

		if (!challenge || !auth) {
			error = -1;
			goto done;
		}
	} else if (auth->set_challenge) {
		challenge = challenge_for_context(challenges, auth);
	}

	if (auth->set_challenge && challenge &&
	    (error = auth->set_challenge(auth, challenge)) < 0)
		goto done;

	if ((error = auth->next_token(&token, auth, credentials)) < 0)
		goto done;

	if (auth->is_complete && auth->is_complete(auth)) {
		/*
		 * If we're done with an auth mechanism with connection affinity,
		 * we don't need to send any more headers and can dispose the context.
		 */
		if (auth->connection_affinity)
			free_auth_context(server);
	} else if (!token.size) {

deps/libgit2/src/libgit2/transports/httpclient.c  view on Meta::CPAN

	}

	if (token.size > 0)
		error = git_str_printf(buf, "%s: %s\r\n", header_name, token.ptr);

done:
	git_str_dispose(&token);
	return error;
}

GIT_INLINE(int) apply_server_credentials(
	git_str *buf,
	git_http_client *client,
	git_http_request *request)
{
	return apply_credentials(buf,
	                         &client->server,
	                         "Authorization",
	                         request->credentials);
}

GIT_INLINE(int) apply_proxy_credentials(
	git_str *buf,
	git_http_client *client,
	git_http_request *request)
{
	return apply_credentials(buf,
	                         &client->proxy,
	                         "Proxy-Authorization",
	                         request->proxy_credentials);
}

static int puts_host_and_port(git_str *buf, git_net_url *url, bool force_port)
{
	bool ipv6 = git_net_url_is_ipv6(url);

	if (ipv6)
		git_str_putc(buf, '[');

	git_str_puts(buf, url->host);

deps/libgit2/src/libgit2/transports/httpclient.c  view on Meta::CPAN

	git_str_puts(buf, " HTTP/1.1\r\n");

	git_str_puts(buf, "User-Agent: ");
	git_http__user_agent(buf);
	git_str_puts(buf, "\r\n");

	git_str_puts(buf, "Host: ");
	puts_host_and_port(buf, &client->server.url, true);
	git_str_puts(buf, "\r\n");

	if ((error = apply_proxy_credentials(buf, client, request) < 0))
		return -1;

	git_str_puts(buf, "\r\n");

	return git_str_oom(buf) ? -1 : 0;
}

static bool use_connect_proxy(git_http_client *client)
{
    return client->proxy.url.host && !strcmp(client->server.url.scheme, "https");

deps/libgit2/src/libgit2/transports/httpclient.c  view on Meta::CPAN

	if (request->chunked)
		git_str_puts(buf, "Transfer-Encoding: chunked\r\n");

	if (request->content_length > 0)
		git_str_printf(buf, "Content-Length: %"PRIuZ "\r\n",
			request->content_length);

	if (request->expect_continue)
		git_str_printf(buf, "Expect: 100-continue\r\n");

	if ((error = apply_server_credentials(buf, client, request)) < 0 ||
	    (!use_connect_proxy(client) &&
			(error = apply_proxy_credentials(buf, client, request)) < 0))
		return error;

	if (request->custom_headers) {
		for (i = 0; i < request->custom_headers->count; i++) {
			const char *hdr = request->custom_headers->strings[i];

			if (hdr)
				git_str_printf(buf, "%s\r\n", hdr);
		}
	}

deps/libgit2/src/libgit2/transports/httpclient.h  view on Meta::CPAN


/** An HTTP request */
typedef struct {
	git_http_method method;            /**< Method for the request */
	git_net_url *url;                  /**< Full request URL */
	git_net_url *proxy;                /**< Proxy to use */

	/* Headers */
	const char *accept;                /**< Contents of the Accept header */
	const char *content_type;          /**< Content-Type header (for POST) */
	git_credential *credentials;       /**< Credentials to authenticate with */
	git_credential *proxy_credentials; /**< Credentials for proxy */
	git_strarray *custom_headers;      /**< Additional headers to deliver */

	/* To POST a payload, either set content_length OR set chunked. */
	size_t content_length;             /**< Length of the POST body */
	unsigned chunked : 1,              /**< Post with chunking */
	         expect_continue : 1;      /**< Use expect/continue negotiation */
} git_http_request;

typedef struct {
	int status;

deps/libgit2/src/libgit2/transports/httpclient.h  view on Meta::CPAN

	char *location;

	/* Authentication headers */
	unsigned server_auth_schemetypes; /**< Schemes requested by remote */
	unsigned server_auth_credtypes;   /**< Supported cred types for remote */

	unsigned proxy_auth_schemetypes;  /**< Schemes requested by proxy */
	unsigned proxy_auth_credtypes;    /**< Supported cred types for proxy */

	unsigned chunked : 1,             /**< Response body is chunked */
	         resend_credentials : 1;  /**< Resend with authentication */
} git_http_response;

typedef struct {
	/** Certificate check callback for the remote */
	git_transport_certificate_check_cb server_certificate_check_cb;
	void *server_certificate_check_payload;

	/** Certificate check callback for the proxy */
	git_transport_certificate_check_cb proxy_certificate_check_cb;
	void *proxy_certificate_check_payload;

deps/libgit2/src/libgit2/transports/smart.c  view on Meta::CPAN

	GIT_ASSERT_ARG(transport);
	GIT_ASSERT_ARG(cert);
	GIT_ASSERT_ARG(hostname);

	if (!connect_opts->callbacks.certificate_check)
		return GIT_PASSTHROUGH;

	return connect_opts->callbacks.certificate_check(cert, valid, hostname, connect_opts->callbacks.payload);
}

int git_transport_smart_credentials(git_credential **out, git_transport *transport, const char *user, int methods)
{
	transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
	git_remote_connect_options *connect_opts = &t->connect_opts;

	GIT_ASSERT_ARG(out);
	GIT_ASSERT_ARG(transport);

	if (!connect_opts->callbacks.credentials)
		return GIT_PASSTHROUGH;

	return connect_opts->callbacks.credentials(out, t->url, user, methods, connect_opts->callbacks.payload);
}

int git_transport_remote_connect_options(
		git_remote_connect_options *out,
		git_transport *transport)
{
	transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);

	GIT_ASSERT_ARG(out);
	GIT_ASSERT_ARG(transport);

deps/libgit2/src/libgit2/transports/ssh.c  view on Meta::CPAN

	}

	return 0;
}

static int request_creds(git_credential **out, ssh_subtransport *t, const char *user, int auth_methods)
{
	int error, no_callback = 0;
	git_credential *cred = NULL;

	if (!t->owner->connect_opts.callbacks.credentials) {
		no_callback = 1;
	} else {
		error = t->owner->connect_opts.callbacks.credentials(
			&cred,
			t->owner->url,
			user,
			auth_methods,
			t->owner->connect_opts.callbacks.payload);

		if (error == GIT_PASSTHROUGH) {
			no_callback = 1;
		} else if (error < 0) {
			return error;
		} else if (!cred) {
			git_error_set(GIT_ERROR_SSH, "callback failed to initialize SSH credentials");
			return -1;
		}
	}

	if (no_callback) {
		git_error_set(GIT_ERROR_SSH, "authentication required but no callback set");
		return GIT_EAUTH;
	}

	if (!(cred->credtype & auth_methods)) {
		cred->free(cred);
		git_error_set(GIT_ERROR_SSH, "authentication callback returned unsupported credentials type");
		return GIT_EAUTH;
	}

	*out = cred;

	return 0;
}

static int _git_ssh_session_create(
	LIBSSH2_SESSION **session,

deps/libgit2/src/libgit2/transports/winhttp.c  view on Meta::CPAN

	git_smart_subtransport parent;
	transport_smart *owner;

	winhttp_server server;
	winhttp_server proxy;

	HINTERNET session;
	HINTERNET connection;
} winhttp_subtransport;

static int apply_userpass_credentials(HINTERNET request, DWORD target, int mechanisms, git_credential *cred)
{
	git_credential_userpass_plaintext *c = (git_credential_userpass_plaintext *)cred;
	wchar_t *user = NULL, *pass = NULL;
	int user_len = 0, pass_len = 0, error = 0;
	DWORD native_scheme;

	if (mechanisms & GIT_WINHTTP_AUTH_NEGOTIATE) {
		native_scheme = WINHTTP_AUTH_SCHEME_NEGOTIATE;
	} else if (mechanisms & GIT_WINHTTP_AUTH_NTLM) {
		native_scheme = WINHTTP_AUTH_SCHEME_NTLM;

deps/libgit2/src/libgit2/transports/winhttp.c  view on Meta::CPAN

		goto done;
	}

	if ((error = user_len = git__utf8_to_16_alloc(&user, c->username)) < 0)
		goto done;

	if ((error = pass_len = git__utf8_to_16_alloc(&pass, c->password)) < 0)
		goto done;

	if (!WinHttpSetCredentials(request, target, native_scheme, user, pass, NULL)) {
		git_error_set(GIT_ERROR_OS, "failed to set credentials");
		error = -1;
	}

done:
	if (user_len > 0)
		git__memzero(user, user_len * sizeof(wchar_t));

	if (pass_len > 0)
		git__memzero(pass, pass_len * sizeof(wchar_t));

	git__free(user);
	git__free(pass);

	return error;
}

static int apply_default_credentials(HINTERNET request, DWORD target, int mechanisms)
{
	DWORD autologon_level = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW;
	DWORD native_scheme = 0;

	if ((mechanisms & GIT_WINHTTP_AUTH_NEGOTIATE) != 0) {
		native_scheme = WINHTTP_AUTH_SCHEME_NEGOTIATE;
	} else if ((mechanisms & GIT_WINHTTP_AUTH_NTLM) != 0) {
		native_scheme = WINHTTP_AUTH_SCHEME_NTLM;
	} else {
		git_error_set(GIT_ERROR_HTTP, "invalid authentication scheme");

deps/libgit2/src/libgit2/transports/winhttp.c  view on Meta::CPAN

	/*
	 * Autologon policy must be "low" to use default creds.
	 * This is safe as the user has explicitly requested it.
	 */
	if (!WinHttpSetOption(request, WINHTTP_OPTION_AUTOLOGON_POLICY, &autologon_level, sizeof(DWORD))) {
		git_error_set(GIT_ERROR_OS, "could not configure logon policy");
		return -1;
	}

	if (!WinHttpSetCredentials(request, target, native_scheme, NULL, NULL, NULL)) {
		git_error_set(GIT_ERROR_OS, "could not configure credentials");
		return -1;
	}

	return 0;
}

static int acquire_url_cred(
	git_credential **cred,
	unsigned int allowed_types,
	const char *username,

deps/libgit2/src/libgit2/transports/winhttp.c  view on Meta::CPAN


				if (SUCCEEDED(pISM->lpVtbl->MapUrlToZone(pISM, wide_url, &dwZone, 0)) &&
					(URLZONE_LOCAL_MACHINE == dwZone ||
					URLZONE_INTRANET == dwZone ||
					URLZONE_TRUSTED == dwZone)) {
					git_credential *existing = *cred;

					if (existing)
						existing->free(existing);

					/* Then use default Windows credentials to authenticate this request */
					error = git_credential_default_new(cred);
				}

				pISM->lpVtbl->Release(pISM);
			}

			/* Only uninitialize if the call to CoInitializeEx was successful. */
			if (SUCCEEDED(hCoInitResult))
				CoUninitialize();
		}

deps/libgit2/src/libgit2/transports/winhttp.c  view on Meta::CPAN

	}

	if (s->request) {
		WinHttpCloseHandle(s->request);
		s->request = NULL;
	}

	s->sent_request = 0;
}

static int apply_credentials(
	HINTERNET request,
	git_net_url *url,
	int target,
	git_credential *creds,
	int mechanisms)
{
	int error = 0;

	GIT_UNUSED(url);

	/* If we have creds, just apply them */
	if (creds && creds->credtype == GIT_CREDENTIAL_USERPASS_PLAINTEXT)
		error = apply_userpass_credentials(request, target, mechanisms, creds);
	else if (creds && creds->credtype == GIT_CREDENTIAL_DEFAULT)
		error = apply_default_credentials(request, target, mechanisms);

	return error;
}

static int winhttp_stream_connect(winhttp_stream *s)
{
	winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
	git_str buf = GIT_STR_INIT;
	char *proxy_url = NULL;
	wchar_t ct[MAX_CONTENT_TYPE_LEN];

deps/libgit2/src/libgit2/transports/winhttp.c  view on Meta::CPAN

			NULL,
			WINHTTP_NO_REFERER,
			types,
			git__strcmp(t->server.url.scheme, "https") == 0 ? WINHTTP_FLAG_SECURE : 0);

	if (!s->request) {
		git_error_set(GIT_ERROR_OS, "failed to open request");
		goto on_error;
	}

	/* Never attempt default credentials; we'll provide them explicitly. */
	if (!WinHttpSetOption(s->request, WINHTTP_OPTION_AUTOLOGON_POLICY, &autologon_policy, sizeof(DWORD)))
		return -1;

	if (!WinHttpSetTimeouts(s->request, default_timeout, default_connect_timeout, default_timeout, default_timeout)) {
		git_error_set(GIT_ERROR_OS, "failed to set timeouts for WinHTTP");
		goto on_error;
	}

	proxy_opts = &t->owner->connect_opts.proxy_opts;
	if (proxy_opts->type == GIT_PROXY_AUTO) {

deps/libgit2/src/libgit2/transports/winhttp.c  view on Meta::CPAN

			WINHTTP_OPTION_PROXY,
			&proxy_info,
			sizeof(WINHTTP_PROXY_INFO))) {
			git_error_set(GIT_ERROR_OS, "failed to set proxy");
			git__free(proxy_wide);
			goto on_error;
		}

		git__free(proxy_wide);

		if ((error = apply_credentials(s->request, &t->proxy.url, WINHTTP_AUTH_TARGET_PROXY, t->proxy.cred, t->proxy.auth_mechanisms)) < 0)
			goto on_error;
	}

	/* Disable WinHTTP redirects so we can handle them manually. Why, you ask?
	 * http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/b2ff8879-ab9f-4218-8f09-16d25dff87ae
	 */
	if (!WinHttpSetOption(s->request,
		WINHTTP_OPTION_DISABLE_FEATURE,
		&disable_redirects,
		sizeof(disable_redirects))) {

deps/libgit2/src/libgit2/transports/winhttp.c  view on Meta::CPAN

			}

			if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L,
				WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
				git_error_set(GIT_ERROR_OS, "failed to add a header to the request");
				goto on_error;
			}
		}
	}

	if ((error = apply_credentials(s->request, &t->server.url, WINHTTP_AUTH_TARGET_SERVER, t->server.cred, t->server.auth_mechanisms)) < 0)
		goto on_error;

	/* We've done everything up to calling WinHttpSendRequest. */

	error = 0;

on_error:
	if (error < 0)
		winhttp_stream_close(s);

deps/libgit2/src/libgit2/transports/winhttp.c  view on Meta::CPAN

			if (!WinHttpSetOption(s->request, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0)) {
				git_error_set(GIT_ERROR_OS, "failed to set client cert context");
				return -1;
			}
		}
	}

	return error;
}

static int acquire_credentials(
	HINTERNET request,
	winhttp_server *server,
	const char *url_str,
	git_credential_acquire_cb cred_cb,
	void *cred_cb_payload)
{
	int allowed_types;
	int error = 1;

	if (parse_unauthorized_response(&allowed_types, &server->auth_mechanisms, request) < 0)
		return -1;

	if (allowed_types) {
		git_credential_free(server->cred);
		server->cred = NULL;

		/* Start with URL-specified credentials, if there were any. */
		if (!server->url_cred_presented && server->url.username && server->url.password) {
			error = acquire_url_cred(&server->cred, allowed_types, server->url.username, server->url.password);
			server->url_cred_presented = 1;

			if (error < 0)
				return error;
		}

		/* Next use the user-defined callback, if there is one. */
		if (error > 0 && cred_cb) {

deps/libgit2/src/libgit2/transports/winhttp.c  view on Meta::CPAN

		/* Finally, invoke the fallback default credential lookup. */
		if (error > 0) {
			error = acquire_fallback_cred(&server->cred, url_str, allowed_types);

			if (error < 0)
				return error;
		}
	}

	/*
	 * No error occurred but we could not find appropriate credentials.
	 * This behaves like a pass-through.
	 */
	return error;
}

static int winhttp_stream_read(
	git_smart_subtransport_stream *stream,
	char *buffer,
	size_t buf_size,
	size_t *bytes_read)

deps/libgit2/src/libgit2/transports/winhttp.c  view on Meta::CPAN

				if (winhttp_connect(t) < 0)
					return -1;
			}

			git__free(location8);
			goto replay;
		}

		/* Handle authentication failures */
		if (status_code == HTTP_STATUS_DENIED) {
			int error = acquire_credentials(s->request,
				&t->server,
				t->owner->url,
				t->owner->connect_opts.callbacks.credentials,
				t->owner->connect_opts.callbacks.payload);

			if (error < 0) {
				return error;
			} else if (!error) {
				GIT_ASSERT(t->server.cred);
				winhttp_stream_close(s);
				goto replay;
			}
		} else if (status_code == HTTP_STATUS_PROXY_AUTH_REQ) {
			int error = acquire_credentials(s->request,
				&t->proxy,
				t->owner->connect_opts.proxy_opts.url,
				t->owner->connect_opts.proxy_opts.credentials,
				t->owner->connect_opts.proxy_opts.payload);

			if (error < 0) {
				return error;
			} else if (!error) {
				GIT_ASSERT(t->proxy.cred);
				winhttp_stream_close(s);
				goto replay;
			}
		}

lib/Git/Raw/Cred.pm  view on Meta::CPAN

package Git::Raw::Cred;
$Git::Raw::Cred::VERSION = '0.90';
use strict;
use warnings;

=head1 NAME

Git::Raw::Cred - Git credentials class

=head1 VERSION

version 0.90

=head1 DESCRIPTION

A L<Git::Raw::Cred> object is used to store credentials.

B<WARNING>: The API of this module is unstable and may change without warning
(any change will be appropriately documented in the changelog).

=head1 METHODS

=head2 userpass( $user, $pass )

Create a new credential object with the given username and password.

lib/Git/Raw/Remote.pm  view on Meta::CPAN

=head1 SYNOPSIS

    use Git::Raw;

    # open the Git repository at $path
    my $repo = Git::Raw::Repository -> open($path);

    # add a new remote
    my $remote = Git::Raw::Remote -> create($repo, 'origin', $url);

    # connect the remote and set the acquire credentials callback
    $remote -> connect('fetch', {
      'credentials' => sub {
        Git::Raw::Cred -> userpass($usr, $pwd)
      },
    });

    # fetch from the remote and update the local tips
    $remote -> download;
    $remote -> update_tips({
      'update_tips' => sub {
        my ($ref, $a, $b) = @_;
        print "Updated $ref: $a -> $b", "\n";

lib/Git/Raw/Remote.pm  view on Meta::CPAN

=head2 update_tips( [ \%callbacks ] )

Update the tips to the new status.

=head2 is_connected( )

Check if the remote is connected.

=head1 CALLBACKS

=head2 credentials

The callback to be called any time authentication is required to connect to the
remote repository. The callback receives a string C<$url> containing the URL of
the remote, the C<$user> extracted from the URL and a list of supported
authentication C<$types>. The callback should return either a L<Git::Raw::Cred>
object or alternatively C<undef> to abort the authentication process. C<$types>
may contain one or more of the following:

=over 4

lib/Git/Raw/Remote.pm  view on Meta::CPAN

=item * "ssh_interactive"

Keyboard-interactive based SSH authentication

=item * "username"

Username-only credential information.

=item * "default"

A key for NTLM/Kerberos default credentials.

=back

B<Note:> this callback may be invoked more than once.

=head2 certificate_check

Callback to be invoked if cert verification fails. The callback receives a
L<Git::Raw::Cert::X509> or L<Git::Raw::Cert::HostKey> object, a truthy
value C<$valid> and C<$host>. This callback should return a negative number to

t/10-clone.t  view on Meta::CPAN

my %features = Git::Raw -> features;
if ($features{'https'} == 0) {
	diag("HTTPS support not available, skipping HTTPS clone tests");
	done_testing;
	exit;
}

$url = 'https://github.com/libgit2/TestGitRepository.git';
$path = rel2abs(catfile('t', 'test_repo_clone'));

my ($credentials_fired, $certificate_check_fired, $update_tips_fired) = (0, 0, 0);
$repo = Git::Raw::Repository -> clone($url, $path, {}, {
	'callbacks' => {
		'certificate_check' => sub {
			my ($cert, $valid, $host) = @_;
			$certificate_check_fired = 1;

			isa_ok $cert, 'Git::Raw::Cert';
			isa_ok $cert, 'Git::Raw::Cert::X509';
			is $cert -> type, 'x509';

t/10-clone.t  view on Meta::CPAN


			like $ref, qr/refs/;
			ok !defined($a);
			ok defined($b);
		}
	}
});

ok !$repo -> is_empty;

is $credentials_fired, 0;
is $certificate_check_fired, 1;
is $update_tips_fired, 1;

$repo = undef;

rmtree catfile('t', 'test_repo_clone');


if ($^O eq 'MSWin32') {
	diag("Windows doesn't have a SSH server, skipping SSH clone tests");

t/10-clone.t  view on Meta::CPAN

}

my $remote_path = rel2abs(catfile('t', 'test_repo'));
my $remote_port = $ENV{AUTHOR_TESTING} ? 22 : 2222;
my $remote_url = "ssh://$ENV{USER}\@localhost:$remote_port$remote_path";
$path = rel2abs(catfile('t', 'test_repo_ssh'));

# Not a CV for callback
ok (!eval { $repo = Git::Raw::Repository -> clone($remote_url, $path, {}, {
		'callbacks' => {
			'credentials' => 'blah'
		}
	});
});
rmtree $path;
ok ! -e $path;

# Die'ing inside the callback
ok (!eval { $repo = Git::Raw::Repository -> clone($remote_url, $path, {}, {
		'callbacks' => {
			'credentials' => sub { die "Shouldn't break!" }
		}
	});
});
rmtree $path;
ok ! -e $path;

# Returning undef inside the callback
ok (!eval { $repo = Git::Raw::Repository -> clone($remote_url, $path, {}, {
		'callbacks' => {
			'credentials' => sub { return undef; }
		}
	});
});
rmtree $path;
ok ! -e $path;

# Invalid key files
ok (!eval { $repo = Git::Raw::Repository -> clone($remote_url, $path, {}, {
		'callbacks' => {
			'credentials' => sub {
				my ($url, $user) = @_;
					return Git::Raw::Cred -> sshkey(
						$user, 'invalid', 'invalid', 'invalid');
			}
		}
	});
});
rmtree $path;
ok ! -e $path;

# Incorrect authentication type (username and password)
ok (!eval { $repo = Git::Raw::Repository -> clone($remote_url, $path, {}, {
		'callbacks' => {
			'credentials' => sub {
				my ($url, $user, $types) = @_;
				return Git::Raw::Cred -> userpass(
					$user, 'password');
			}
		}
	});
});
rmtree $path;
ok ! -e $path;

# Incorrect authentication type (SSH interactive)
ok (!eval { $repo = Git::Raw::Repository -> clone($remote_url, $path, {}, {
		'callbacks' => {
			'credentials' => sub {
				my ($url, $user, $types) = @_;
				return Git::Raw::Cred -> sshinteractive(
					'metheunknownuser', sub {
						return ('badpassword');
					});
			}
		}
	});
});
rmtree $path;
ok ! -e $path;

# Incorrect authentication type (SSH agent)
my $badCount = 0;
ok (!eval { $repo = Git::Raw::Repository -> clone($remote_url, $path, {}, {
		'callbacks' => {
			'credentials' => sub {
				my ($url, $user, $types) = @_;
				if (++$badCount >= 2) {
					die "Skipping...";
				}
				return Git::Raw::Cred -> sshagent($user);
			}
		}
	});
});
rmtree $path;
ok ! -e $path;

($credentials_fired, $certificate_check_fired, $update_tips_fired) = (0, 0, 0);
$repo = Git::Raw::Repository -> clone($remote_url, $path, {
		'checkout_branch' => 'main'
	}, {
	'callbacks' => {
		'credentials' => sub {
			my ($url, $user) = @_;
			$credentials_fired = 1;

			my $ssh_dir = catfile($ENV{HOME}, '.ssh');
			ok -e $ssh_dir;

			my $public_key = catfile($ssh_dir, 'id_rsa.pub');
			my $private_key = catfile($ssh_dir, 'id_rsa');
			ok -f $public_key;
			ok -f $private_key;

			is $user, $ENV{USER};

t/10-clone.t  view on Meta::CPAN

			$update_tips_fired = 1;

			like $ref, qr/refs/;
			ok !defined($a);
			ok defined($b);
		}
	}
});

ok !$repo -> is_empty;
is $credentials_fired, 1;
is $certificate_check_fired, 1;
is $update_tips_fired, 1;
@remotes = $repo -> remotes;

is $remotes[0] -> name, 'origin';
is $remotes[0] -> url, $remote_url;

@remotes = ();
$repo = undef;

t/19-push.t  view on Meta::CPAN

	my ($name, $instruction, @prompts) = @_;

	is scalar(@prompts), 1;
	my $prompt = shift @prompts;
	like $prompt->{text}, qr/Password/;
	is $prompt->{echo}, 0;
	return ('blah');
};

my $tried_interactive = 0;
my $credentials = sub {
	my ($url, $user, $types) = @_;

	is ref($types), 'ARRAY';
	is scalar(grep { $_ eq 'ssh_key' } @$types), 1;
	is scalar(grep { $_ eq 'ssh_custom' } @$types), 1;
	is scalar(grep { $_ eq 'ssh_interactive' } @$types), 1;

	if (!$tried_interactive) {
		$tried_interactive = 1;
		return Git::Raw::Cred -> sshinteractive($user, $challenge);

t/19-push.t  view on Meta::CPAN

	my $public_key = File::Spec -> catfile($ssh_dir, 'id_rsa.pub');
	my $private_key = File::Spec -> catfile($ssh_dir, 'id_rsa');
	ok -f $public_key;
	ok -f $private_key;

	return Git::Raw::Cred -> sshkey($user, $public_key, $private_key);
};

$repo = Git::Raw::Repository -> clone($remote_url, $path, {}, {
	'callbacks' => {
		'credentials' => $credentials
	}
});

ok !$repo -> is_empty;
@remotes = $repo -> remotes;

my $config = $repo -> config;
$config -> str('user.name', 'some user');
$config -> str('user.email', 'someuser@somewhere.com');

t/19-push.t  view on Meta::CPAN

$index -> add('file_on_ssh_branch');
$index -> write;

my $me = Git::Raw::Signature -> default($repo);
my $commit = $repo -> commit("commit on file_on_ssh_branch\n", $me, $me, [$branch -> target],
	$index -> write_tree);

is scalar(@remotes), 1;
$remote = shift @remotes;

my ($credentials_fired, $sideband_fired, $update_tips_fired) = (0, 0, 0);
my ($pack_progress_fired, $transfer_progress_fired, $status_fired) = (0, 0, 0);
my ($negotation_fired, $transport_fired) = (0, 0);

my $callbacks = {
	'credentials' => sub {
		$credentials_fired = 1;
		return &{$credentials}(@_);
	},
	'sideband_progress' => sub {
		my ($msg) = @_;

		diag("Remote message (sideband): $msg");
		is $msg, "This is from the pre-receive hook! (Disallowing it)";
		$sideband_fired = 1;
	},
	'pack_progress' => sub {
		my ($stage, $current, $total) = @_;

t/19-push.t  view on Meta::CPAN

chmod 0755, $pre_receive_file;

# pre-receive hook kick
$remote -> connect('push', $callbacks);
is $remote -> push(["refs/heads/ssh_branch:refs/heads/ssh_branch"], {
	'callbacks' => $callbacks
}), 1;
diag("Pre-receive hook (successfully) declined the push");

is $sideband_fired, 1;
is $credentials_fired, 1;
is $pack_progress_fired, 1;
is $transfer_progress_fired, 1;
is $status_fired, 1;
is $update_tips_fired, 0;
is $negotation_fired, 1;
is $transport_fired, 1;

# setup a pre-receive hook that succeeds
$pre_receive_content = <<'EOS';
#!/usr/bin/env perl

$|++;

print STDERR "This is from the pre-receive hook! (Allowing it)";
exit(0);
EOS

write_file($pre_receive_file, $pre_receive_content);

$callbacks = {
	'credentials' => sub {
		$credentials_fired = 1;
		return &{$credentials}(@_);
	},
	'sideband_progress' => sub {
		my ($msg) = @_;

		diag("Remote message (sideband): $msg");
		is $msg, "This is from the pre-receive hook! (Allowing it)";
		$sideband_fired = 1;
	},
	'update_tips' => sub {
		my ($ref, $a, $b) = @_;



( run in 0.437 second using v1.01-cache-2.11-cpan-4d50c553e7e )