コード例 #1
0
ファイル: git-access.c プロジェクト: rainzhangtime/subsurface
static git_repository *update_local_repo(const char *localdir, const char *remote, const char *branch, enum remote_transport rt)
{
	int error;
	git_repository *repo = NULL;

	if (verbose)
		fprintf(stderr, "git storage: update local repo\n");

	error = git_repository_open(&repo, localdir);
	if (error) {
		if (is_subsurface_cloud)
			(void)cleanup_local_cache(remote, branch);
		else
			report_error("Unable to open git cache repository at %s: %s", localdir, giterr_last()->message);
		return NULL;
	}
	sync_with_remote(repo, remote, branch, rt);
	return repo;
}
コード例 #2
0
ファイル: reflog.c プロジェクト: csware/libgit2
void test_refs_reflog_reflog__reading_a_reflog_with_invalid_format_returns_error(void)
{
	git_reflog *reflog;
	const git_error *error;
	const char *refname = "refs/heads/newline";
	const char *refmessage =
		"Reflog*message with a newline and enough content after it to pass the GIT_REFLOG_SIZE_MIN check inside reflog_parse.";
	git_reference *ref;
	git_oid id;
	git_buf logpath = GIT_BUF_INIT, logcontents = GIT_BUF_INIT;
	char *star;

	git_oid_fromstr(&id, current_master_tip);

	/* create a new branch */
	cl_git_pass(git_reference_create(&ref, g_repo, refname, &id, 1, refmessage));

	/* corrupt the branch reflog by introducing a newline inside the reflog message (we replace '*' with '\n') */
	git_buf_join_n(&logpath, '/', 3, git_repository_path(g_repo), GIT_REFLOG_DIR, refname);
	cl_git_pass(git_futils_readbuffer(&logcontents, git_buf_cstr(&logpath)));
	cl_assert((star = strchr(git_buf_cstr(&logcontents), '*')) != NULL);
	*star = '\n';
	cl_git_rewritefile(git_buf_cstr(&logpath), git_buf_cstr(&logcontents));

	/* confirm that the file was rewritten successfully and now contains a '\n' in the expected location */
	cl_git_pass(git_futils_readbuffer(&logcontents, git_buf_cstr(&logpath)));
	cl_assert(strstr(git_buf_cstr(&logcontents), "Reflog\nmessage") != NULL);

	/* clear the error state so we can capture the error generated by git_reflog_read */
	giterr_clear();

	cl_git_fail(git_reflog_read(&reflog, g_repo, refname));

	error = giterr_last();

	cl_assert(error != NULL);
	cl_assert_equal_s("unable to parse OID - contains invalid characters", error->message);

	git_reference_free(ref);
	git_buf_dispose(&logpath);
	git_buf_dispose(&logcontents);
}
コード例 #3
0
ファイル: clone.c プロジェクト: jwes/luagi
int luagi_clone( lua_State *L )
{
   const char *url = luaL_checkstring( L, 1 );
   const char *local_path = luaL_checkstring( L, 2 );
   git_clone_options options;

   parse_options( &options, L, 3 );

   git_repository **repo = (git_repository **) lua_newuserdata( L, sizeof(git_repository *) );
   
   if( git_clone( repo, url, local_path, &options) ) 
   {
      const git_error* err = giterr_last();
      lua_pushnil( L );
      lua_pushfstring( L, "unable to clone repository from %s to %s --> %s", url, local_path, err->message );
      return 2;
   }
   ltk_setmetatable( L, REPO_NAME );
   return 1;
}
コード例 #4
0
ファイル: rugged.c プロジェクト: jacobvosmaer/rugged
void rugged_exception_raise(void)
{
	VALUE err_klass, err_obj;
	const git_error *error;
	const char *err_message;

	error = giterr_last();

	if (error && error->klass > 0 && error->klass < RUGGED_ERROR_COUNT) {
		err_klass = rb_eRuggedErrors[error->klass];
		err_message = error->message;
	} else {
		err_klass = rb_eRuntimeError;
		err_message = "Rugged operation failed";
	}

	err_obj = rb_exc_new2(err_klass, err_message);
	giterr_clear();
	rb_exc_raise(err_obj);
}
コード例 #5
0
ファイル: main.c プロジェクト: lunixbochs/libgit2-memory
int main(int argc, char **argv) {
    if (argc < 2) {
        printf("Usage: %s <repo url>\n", argv[0]);
        return 1;
    }
    git_libgit2_init();

    git_repository *repo = NULL;
    git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
    opts.repository_cb = repository_create_memory_cb;
    const char *url = argv[1];
    const char *path = "repo";
    int error = git_clone(&repo, url, path, &opts);
    if (error) {
        fprintf(stderr, "%s\n", giterr_last()->message);
    }

    git_libgit2_shutdown();
    return 0;
}
コード例 #6
0
ファイル: rugged.c プロジェクト: b-k-schneider/sonic-pi
void rugged_exception_raise(void)
{
	VALUE err_klass, err_obj;
	const git_error *error;
	const char *err_message;

	error = giterr_last();

	if (error && error->klass >= 0 && error->klass < RUGGED_ERROR_COUNT) {
		err_klass = rb_eRuggedErrors[error->klass];
		err_message = error->message;
	} else {
		err_klass = rb_eRuggedErrors[2]; /* InvalidError */
		err_message = "Unknown Error";
	}

	err_obj = rb_exc_new2(err_klass, err_message);
	giterr_clear();
	rb_exc_raise(err_obj);
}
コード例 #7
0
ファイル: winhttp.c プロジェクト: DavidMolinari/sonic-pi
static int send_request(winhttp_stream *s, size_t len, int ignore_length)
{
	int request_failed = 0, cert_valid = 1, error = 0;
	DWORD ignore_flags;

	if ((error = do_send_request(s, len, ignore_length)) < 0)
		request_failed = 1;

	if (request_failed) {
		if (GetLastError() != ERROR_WINHTTP_SECURE_FAILURE) {
			giterr_set(GITERR_OS, "failed to send request");
			return -1;
		} else {
			cert_valid = 0;
		}
	}

	giterr_clear();
	if ((error = certificate_check(s, cert_valid)) < 0) {
		if (!giterr_last())
			giterr_set(GITERR_OS, "user cancelled certificate check");

		return error;
	}

	/* if neither the request nor the certificate check returned errors, we're done */
	if (!request_failed)
		return 0;

	ignore_flags = no_check_cert_flags;
	
	if (!WinHttpSetOption(s->request, WINHTTP_OPTION_SECURITY_FLAGS, &ignore_flags, sizeof(ignore_flags))) {
		giterr_set(GITERR_OS, "failed to set security options");
		return -1;
	}

	if ((error = do_send_request(s, len, ignore_length)) < 0)
		giterr_set(GITERR_OS, "failed to send request");

	return error;
}
コード例 #8
0
ファイル: level1.c プロジェクト: Posnet/gpu-cuda
// Copied from libgit2 examples
static int log_lg2(int error, const char *message, const char *extra){
    const git_error *lg2err;
    const char *lg2msg = "", *lg2spacer = "";

    if (!error)
        return error;

    if ((lg2err = giterr_last()) != NULL && lg2err->message != NULL) {
        lg2msg = lg2err->message;
        lg2spacer = " - ";
    }

    if (extra)
        fprintf(stderr, "%s '%s' [%d]%s%s\n",
                message, extra, error, lg2spacer, lg2msg);
    else
        fprintf(stderr, "%s [%d]%s%s\n",
                message, error, lg2spacer, lg2msg);

    return error;
}
コード例 #9
0
ファイル: git-access.c プロジェクト: ngdmcc/subsurface
static int update_remote(git_repository *repo, git_remote *origin, git_reference *local, git_reference *remote, enum remote_transport rt)
{
	git_push_options opts = GIT_PUSH_OPTIONS_INIT;
	git_strarray refspec;
	const char *name = git_reference_name(local);

	refspec.count = 1;
	refspec.strings = (char **)&name;

#if USE_LIBGIT23_API
	if (rt == RT_SSH)
		opts.callbacks.credentials = credential_ssh_cb;
	else if (rt == RT_HTTPS)
		opts.callbacks.credentials = credential_https_cb;
	opts.callbacks.certificate_check = certificate_check_cb;
#endif
	if (git_remote_push(origin, &refspec, &opts))
		return report_error("Unable to update remote with current local cache state (%s)", giterr_last()->message);

	return 0;
}
コード例 #10
0
/**
 * Make the repository HEAD directly point to the commit.
 *
 * @param commit S4 class git_commit
 * @return R_NilValue
 */
SEXP git2r_repository_set_head_detached(SEXP commit)
{
    int err;
    SEXP sha;
    git_oid oid;
    git_commit *treeish = NULL;
    git_repository *repository = NULL;

    if (git2r_arg_check_commit(commit))
        git2r_error(git2r_err_commit_arg, __func__, "commit");

    repository = git2r_repository_open(GET_SLOT(commit, Rf_install("repo")));
    if (!repository)
        git2r_error(git2r_err_invalid_repository, __func__, NULL);

    sha = GET_SLOT(commit, Rf_install("sha"));
    err = git_oid_fromstr(&oid, CHAR(STRING_ELT(sha, 0)));
    if (GIT_OK != err)
        goto cleanup;

    err = git_commit_lookup(&treeish, repository, &oid);
    if (GIT_OK != err)
        goto cleanup;

    err = git_repository_set_head_detached(
        repository,
        git_commit_id(treeish));

cleanup:
    if (treeish)
        git_commit_free(treeish);

    if (repository)
        git_repository_free(repository);

    if (GIT_OK != err)
        git2r_error(git2r_err_from_libgit2, __func__, giterr_last()->message);

    return R_NilValue;
}
コード例 #11
0
ファイル: crlf.c プロジェクト: 1336/libgit2
void test_filter_crlf__with_safecrlf(void)
{
	git_filter_list *fl;
	git_filter *crlf;
	git_buf in = {0}, out = GIT_BUF_INIT;

	cl_repo_set_bool(g_repo, "core.safecrlf", true);

	cl_git_pass(git_filter_list_new(
		&fl, g_repo, GIT_FILTER_TO_ODB, 0));

	crlf = git_filter_lookup(GIT_FILTER_CRLF);
	cl_assert(crlf != NULL);

	cl_git_pass(git_filter_list_push(fl, crlf, NULL));

	/* Normalized \r\n succeeds with safecrlf */
	in.ptr = "Normal\r\nCRLF\r\nline-endings.\r\n";
	in.size = strlen(in.ptr);

	cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
	cl_assert_equal_s("Normal\nCRLF\nline-endings.\n", out.ptr);

	/* Mix of line endings fails with safecrlf */
	in.ptr = "Mixed\nup\r\nLF\nand\r\nCRLF\nline-endings.\r\n";
	in.size = strlen(in.ptr);

	cl_git_fail(git_filter_list_apply_to_data(&out, fl, &in));
	cl_assert_equal_i(giterr_last()->klass, GITERR_FILTER);

	/* Normalized \n is reversible, so does not fail with safecrlf */
	in.ptr = "Normal\nLF\nonly\nline-endings.\n";
	in.size = strlen(in.ptr);

	cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
	cl_assert_equal_s(in.ptr, out.ptr);

	git_filter_list_free(fl);
	git_buf_free(&out);
}
コード例 #12
0
ファイル: diff.c プロジェクト: jwes/luagi
int luagi_diff_index_to_workdir( lua_State *L )
{
   git_repository **repo = checkrepo( L, 1 );
   git_index **index = checkindex_at( L, 2 );

   git_diff_options opts;
   luagi_diff_init_options( L, 3, &opts );
   
   git_diff **diff = (git_diff **) lua_newuserdata( L, sizeof( git_diff *) );

   if( git_diff_index_to_workdir( diff, *repo, *index, &opts ) )
   {
      const git_error *err = giterr_last();
      lua_pushnil( L );
      lua_pushstring( L, err->message );
      return 2;
   }

   ltk_setmetatable( L, LUAGI_DIFF_FUNCS );

   return 1; 
}
コード例 #13
0
ファイル: clone.c プロジェクト: 1336/libgit2
int do_clone(git_repository *repo, int argc, char **argv)
{
	progress_data pd = {{0}};
	git_repository *cloned_repo = NULL;
	git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
	git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
	const char *url = argv[1];
	const char *path = argv[2];
	int error;

	(void)repo; // unused

	// Validate args
	if (argc < 3) {
		printf ("USAGE: %s <url> <path>\n", argv[0]);
		return -1;
	}

	// Set up options
	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
	checkout_opts.progress_cb = checkout_progress;
	checkout_opts.progress_payload = &pd;
	clone_opts.checkout_opts = checkout_opts;
	clone_opts.fetch_opts.callbacks.sideband_progress = sideband_progress;
	clone_opts.fetch_opts.callbacks.transfer_progress = &fetch_progress;
	clone_opts.fetch_opts.callbacks.credentials = cred_acquire_cb;
	clone_opts.fetch_opts.callbacks.payload = &pd;

	// Do the clone
	error = git_clone(&cloned_repo, url, path, &clone_opts);
	printf("\n");
	if (error != 0) {
		const git_error *err = giterr_last();
		if (err) printf("ERROR %d: %s\n", err->klass, err->message);
		else printf("ERROR %d: no detailed info\n", error);
	}
	else if (cloned_repo) git_repository_free(cloned_repo);
	return error;
}
コード例 #14
0
/**
 * Make the repository HEAD point to the specified reference.
 *
 * @param repo S4 class git_repository
 * @param ref_name Canonical name of the reference the HEAD should point at
 * @return R_NilValue
 */
SEXP git2r_repository_set_head(SEXP repo, SEXP ref_name)
{
    int err;
    git_repository *repository = NULL;

    if (git2r_arg_check_string(ref_name))
        git2r_error(git2r_err_string_arg, __func__, "ref_name");

    repository = git2r_repository_open(repo);
    if (!repository)
        git2r_error(git2r_err_invalid_repository, __func__, NULL);

    err = git_repository_set_head(repository, CHAR(STRING_ELT(ref_name, 0)));

    if (repository)
        git_repository_free(repository);

    if (GIT_OK != err)
        git2r_error(git2r_err_from_libgit2, __func__, giterr_last()->message);

    return R_NilValue;
}
コード例 #15
0
ファイル: rugged_commit.c プロジェクト: Angeldude/sonic-pi
/*
 *  call-seq:
 *    Commit.extract_signature(repo, commit, field_name) -> [str, str]
 *
 *  Returns +commit+'s signature in 'field' and the signed data
 *
 *  The signature is done over the contents of the commit without the
 *  signature block in the header, which is the data in the second
 *  element in the return array.
 */
static VALUE rb_git_commit_extract_signature(int argc, VALUE *argv, VALUE self)
{
	int error;
	VALUE ret;
	git_oid commit_id;
	const char *field;
	git_repository *repo;
	git_buf signature = {0}, signed_data = {0};
	VALUE rb_repo, rb_commit, rb_field = Qnil;

	rb_scan_args(argc, argv, "21", &rb_repo, &rb_commit, &rb_field);

	rugged_check_repo(rb_repo);
	Data_Get_Struct(rb_repo, git_repository, repo);

	error = git_oid_fromstr(&commit_id, StringValueCStr(rb_commit));
	rugged_exception_check(error);

	field = NIL_P(rb_field) ? NULL : StringValueCStr(rb_field);
	error = git_commit_extract_signature(&signature, &signed_data, repo, &commit_id, field);
	if (error < 0) {
		git_buf_free(&signature);
		git_buf_free(&signed_data);
	}

	if (error == GIT_ENOTFOUND && giterr_last()->klass == GITERR_OBJECT ) {
		ret = Qnil;
	} else {
		rugged_exception_check(error);

		ret = rb_ary_new3(2, rb_str_new(signature.ptr, signature.size),
				     rb_str_new(signed_data.ptr, signed_data.size));
	}

	git_buf_free(&signature);
	git_buf_free(&signed_data);

	return ret;
}
コード例 #16
0
ファイル: git-access.c プロジェクト: pestophagous/subsurface
static git_repository *create_local_repo(const char *localdir, const char *remote, const char *branch, enum remote_transport rt)
{
	int error;
	git_repository *cloned_repo = NULL;
	git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
#if USE_LIBGIT23_API
	opts.fetch_opts.callbacks.transfer_progress = &transfer_progress_cb;
	if (rt == RT_SSH)
		opts.fetch_opts.callbacks.credentials = credential_ssh_cb;
	else if (rt == RT_HTTPS)
		opts.fetch_opts.callbacks.credentials = credential_https_cb;
	opts.repository_cb = repository_create_cb;
	opts.fetch_opts.callbacks.certificate_check = certificate_check_cb;
#endif
	opts.checkout_branch = branch;
	if (rt == RT_HTTPS && !canReachCloudServer())
		return 0;
	error = git_clone(&cloned_repo, remote, localdir, &opts);
	if (error) {
		char *msg = giterr_last()->message;
		int len = sizeof("Reference 'refs/remotes/origin/' not found") + strlen(branch);
		char *pattern = malloc(len);
		snprintf(pattern, len, "Reference 'refs/remotes/origin/%s' not found", branch);
		if (strstr(remote, prefs.cloud_git_url) && strstr(msg, pattern)) {
			/* we're trying to open the remote branch that corresponds
			 * to our cloud storage and the branch doesn't exist.
			 * So we need to create the branch and push it to the remote */
			cloned_repo = create_and_push_remote(localdir, remote, branch);
#if !defined(DEBUG)
		} else if (strstr(remote, prefs.cloud_git_url)) {
			report_error(translate("gettextFromC", "Error connecting to Subsurface cloud storage"));
#endif
		} else {
			report_error(translate("gettextFromC", "git clone of %s failed (%s)"), remote, msg);
		}
		free(pattern);
	}
	return cloned_repo;
}
コード例 #17
0
ファイル: git2r_remote.c プロジェクト: jennybc/git2r
/**
 * Remove an existing remote
 *
 * All remote-tracking branches and configuration settings for the
 * remote will be removed.
 * @param repo S4 class git_repository
 * @param name The name of the remote to remove
 * @return R_NilValue
 */
SEXP git2r_remote_remove(SEXP repo, SEXP name)
{
    int err;
    git_repository *repository = NULL;

    if (git2r_arg_check_string(name))
        git2r_error(__func__, NULL, "'name'", git2r_err_string_arg);

    repository = git2r_repository_open(repo);
    if (!repository)
        git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL);

    err = git_remote_delete(repository, CHAR(STRING_ELT(name, 0)));

    if (repository)
	git_repository_free(repository);

    if (err)
	git2r_error(__func__, giterr_last(), NULL, NULL);

    return R_NilValue;
}
コード例 #18
0
void GitWrapper::initializeGitRepository(QString folder)
{
    GIT_RETURN_IF_DISABLED()
    QMutexLocker l(&gitMutex);
    // this is not thread safe, we use locking elsewhere
    git_repository *repo = NULL;
    QByteArray ba = folder.toUtf8();

    const char *cString = ba.data();

    int error = git_repository_init(&repo, cString, false);
    if (error < 0) {
        const git_error *e = giterr_last();
        kDebug() << e->message;
    }

    git_signature *sig = NULL;
    git_index *index = NULL;
    git_oid tree_id;
    git_oid commit_id;
    git_tree *tree = NULL;


    // no error handling at the moment
    git_signature_now(&sig, "AutoGit", "auto@localhost");
    git_repository_index(&index, repo);
    git_index_write_tree(&tree_id, index);
    git_tree_lookup(&tree, repo, &tree_id);
    git_commit_create_v(&commit_id, repo, "HEAD", sig, sig, NULL, "Initial commit", tree, 0);

    git_signature_free(sig);
    git_index_free(index);
    git_tree_free(tree);

    //first commit
    commitPattern(repo, "*", "Initial full commit");
    git_repository_free(repo);
}
コード例 #19
0
ファイル: diff.c プロジェクト: jwes/luagi
int luagi_diff_tree_to_tree( lua_State *L )
{
   git_repository **repo = checkrepo( L, 1 );
   git_tree **old_tree = checktree_at( L, 2 );
   git_tree **new_tree = checktree_at( L, 3 );

   git_diff_options opts;
   luagi_diff_init_options( L, 4, &opts );
   
   git_diff **diff = (git_diff **) lua_newuserdata( L, sizeof( git_diff *) );

   if( git_diff_tree_to_tree( diff, *repo, *old_tree, *new_tree, &opts ) )
   {
      const git_error *err = giterr_last();
      lua_pushnil( L );
      lua_pushstring( L, err->message );
      return 2;
   }

   ltk_setmetatable( L, LUAGI_DIFF_FUNCS );

   return 1;
}
コード例 #20
0
/**
 * Find repository base path for given path
 *
 * @param path A character vector specifying the path to a file or folder
 * @return R_NilValue if repository cannot be found or
 * a character vector of length one with path to repository's git dir
 * e.g. /path/to/my/repo/.git
 */
SEXP git2r_repository_discover(SEXP path)
{
    int err;
    SEXP result = R_NilValue;
    git_buf buf = GIT_BUF_INIT;

    if (git2r_arg_check_string(path))
        git2r_error(git2r_err_string_arg, __func__, "path");

    /* note that across_fs (arg #3) is set to 0 so this will stop when
     * a filesystem device change is detected while exploring parent
     * directories */
    err = git_repository_discover(&buf,
                                  CHAR(STRING_ELT(path, 0)),
                                  0,
                                  /* const char *ceiling_dirs */ NULL);
    if (GIT_OK != err) {
        /* NB just return R_NilValue if we can't discover the repo */
        if (GIT_ENOTFOUND == err)
            err = GIT_OK;
        goto cleanup;
    }

    PROTECT(result = allocVector(STRSXP, 1));
    SET_STRING_ELT(result, 0, mkChar(buf.ptr));

cleanup:
    git_buf_free(&buf);

    if (R_NilValue != result)
        UNPROTECT(1);

    if (GIT_OK != err)
        git2r_error(git2r_err_from_libgit2, __func__, giterr_last()->message);

    return result;
}
コード例 #21
0
void PhysiomeModelRepositoryWindowWindow::cloneWorkspace(const QString &pWorkspace)
{
    // Retrieve the name of an empty directory

    QString dirName = Core::getExistingDirectory(tr("Select Empty Directory"),
                                                 QString(), true);

    if (!dirName.isEmpty()) {
        // We have got a directory name where we can clone the workspace, so
        // clone it

        git_libgit2_init();

        git_repository *gitRepository = 0;
        QByteArray workspaceByteArray = pWorkspace.toUtf8();
        QByteArray dirNameByteArray = dirName.toUtf8();

        int res = git_clone(&gitRepository, workspaceByteArray.constData(),
                            dirNameByteArray.constData(), 0);

        if (res) {
            const git_error *gitError = giterr_last();

            QMessageBox::warning(qApp->activeWindow(),
                                 tr("Clone Workspace"),
                                 gitError?
                                     tr("Error %1: %2.").arg(QString::number(gitError->klass),
                                                             Core::formatMessage(gitError->message)):
                                     tr("An error occurred while trying to clone the workspace."),
                                 QMessageBox::Ok);
        } else if (gitRepository) {
            git_repository_free(gitRepository);
        }

        git_libgit2_shutdown();
    }
}
コード例 #22
0
/**
 * Check if head of repository is detached
 *
 * @param repo S4 class git_repository
 * @return TRUE if detached else FALSE
 */
SEXP git2r_repository_head_detached(SEXP repo)
{
    SEXP result;
    int head_detached;
    git_repository *repository;

    repository= git2r_repository_open(repo);
    if (!repository)
        git2r_error(git2r_err_invalid_repository, __func__, NULL);

    head_detached = git_repository_head_detached(repository);
    git_repository_free(repository);
    if (head_detached < 0)
        git2r_error(git2r_err_from_libgit2, __func__, giterr_last()->message);

    PROTECT(result = allocVector(LGLSXP, 1));
    if (1 == head_detached)
        LOGICAL(result)[0] = 1;
    else
        LOGICAL(result)[0] = 0;
    UNPROTECT(1);

    return result;
}
コード例 #23
0
/**
 * Check if repository is empty.
 *
 * @param repo S4 class git_repository
 * @return TRUE if empty else FALSE
 */
SEXP git2r_repository_is_empty(SEXP repo)
{
    SEXP result;
    int is_empty;
    git_repository *repository;

    repository= git2r_repository_open(repo);
    if (!repository)
        git2r_error(git2r_err_invalid_repository, __func__, NULL);

    is_empty = git_repository_is_empty(repository);
    git_repository_free(repository);
    if (is_empty < 0)
        git2r_error(git2r_err_from_libgit2, __func__, giterr_last()->message);

    PROTECT(result = allocVector(LGLSXP, 1));
    if (1 == is_empty)
        LOGICAL(result)[0] = 1;
    else
        LOGICAL(result)[0] = 0;
    UNPROTECT(1);

    return result;
}
コード例 #24
0
ファイル: git2r_merge.c プロジェクト: krlmlr/git2r
/**
 * Find a merge base between two commits
 *
 * @param one One of the commits
 * @param two The other commit
 * @return The commit of a merge base between 'one' and 'two'
 *         or NULL if not found
 */
SEXP git2r_merge_base(SEXP one, SEXP two)
{
    int err;
    SEXP result = R_NilValue;
    SEXP repo;
    SEXP sha;
    git_oid oid;
    git_oid oid_one;
    git_oid oid_two;
    git_commit *commit = NULL;
    git_repository *repository = NULL;

    if (git2r_arg_check_commit(one))
        git2r_error(__func__, NULL, "'one'", git2r_err_commit_arg);
    if (git2r_arg_check_commit(two))
        git2r_error(__func__, NULL, "'two'", git2r_err_commit_arg);

    repo = GET_SLOT(one, Rf_install("repo"));
    repository = git2r_repository_open(repo);
    if (!repository)
        git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL);

    sha = GET_SLOT(one, Rf_install("sha"));
    err = git_oid_fromstr(&oid_one, CHAR(STRING_ELT(sha, 0)));
    if (err)
        goto cleanup;

    sha = GET_SLOT(two, Rf_install("sha"));
    err = git_oid_fromstr(&oid_two, CHAR(STRING_ELT(sha, 0)));
    if (err)
        goto cleanup;

    err = git_merge_base(&oid, repository, &oid_one, &oid_two);
    if (err) {
        if (GIT_ENOTFOUND == err)
            err = GIT_OK;
        goto cleanup;
    }

    err = git_commit_lookup(&commit, repository, &oid);
    if (err)
        goto cleanup;

    PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_commit")));
    git2r_commit_init(commit, repo, result);

cleanup:
    if (commit)
        git_commit_free(commit);

    if (repository)
        git_repository_free(repository);

    if (R_NilValue != result)
        UNPROTECT(1);

    if (err)
        git2r_error(__func__, giterr_last(), NULL, NULL);

    return result;
}
コード例 #25
0
ファイル: git2r_remote.c プロジェクト: jennybc/git2r
/**
 * Get the remote's url
 *
 * Based on https://github.com/libgit2/libgit2/blob/babdc376c7/examples/network/ls-remote.c
 * @param repo S4 class git_repository
 * @param name Character vector with URL of remote.
 * @return Character vector for each reference with the associated commit IDs.
 */
SEXP git2r_remote_ls(SEXP name, SEXP repo, SEXP credentials)
{
    const char *name_ = NULL;
    SEXP result = R_NilValue;
    SEXP names = R_NilValue;
    git_remote *remote = NULL;
    int err;
    const git_remote_head **refs;
    size_t refs_len, i;
    git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
    git2r_transfer_data payload = GIT2R_TRANSFER_DATA_INIT;
    git_repository *repository = NULL;

    if (git2r_arg_check_string(name))
        git2r_error(__func__, NULL, "'name'", git2r_err_string_arg);
    if (git2r_arg_check_credentials(credentials))
        git2r_error(__func__, NULL, "'credentials'", git2r_err_credentials_arg);

    repository = git2r_repository_open(repo);
    if (!repository)
        git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL);

    name_ = CHAR(STRING_ELT(name, 0));
    err = git_remote_lookup(&remote, repository, name_);
    if (err) {
        err = git_remote_create_anonymous(&remote, repository, name_);
        if (err)
            goto cleanup;
    }

    payload.credentials = credentials;
    callbacks.payload = &payload;
    callbacks.credentials = &git2r_cred_acquire_cb;

    err = git_remote_connect(remote, GIT_DIRECTION_FETCH, &callbacks, NULL, NULL);
    if (err)
        goto cleanup;

    err = git_remote_ls(&refs, &refs_len, remote);
    if (err)
        goto cleanup;

    PROTECT(result = allocVector(STRSXP, refs_len));
    setAttrib(result, R_NamesSymbol, names = allocVector(STRSXP, refs_len));

    for (i = 0; i < refs_len; i++) {
        char oid[GIT_OID_HEXSZ + 1] = {0};
        git_oid_fmt(oid, &refs[i]->oid);
        SET_STRING_ELT(result, i, mkChar(oid));
        SET_STRING_ELT(names, i, mkChar(refs[i]->name));
    }

cleanup:
    if (repository)
        git_repository_free(repository);

    if (result != R_NilValue)
        UNPROTECT(1);

    if (err)
        git2r_error(__func__, giterr_last(), NULL, NULL);

    return(result);
}
コード例 #26
0
ファイル: git2r_remote.c プロジェクト: jennybc/git2r
/**
 * Fetch new data and update tips
 *
 * @param repo S4 class git_repository
 * @param name The name of the remote to fetch from
 * @param credentials The credentials for remote repository access.
 * @param msg The one line long message to be appended to the reflog
 * @param verbose Print information each time a reference is updated locally.
 * @param refspecs The refspecs to use for this fetch. Pass R_NilValue
 *        to use the base refspecs.
 * @return R_NilValue
 */
SEXP git2r_remote_fetch(
    SEXP repo,
    SEXP name,
    SEXP credentials,
    SEXP msg,
    SEXP verbose,
    SEXP refspecs)
{
    int err;
    SEXP result = R_NilValue;
    const git_transfer_progress *stats;
    git_remote *remote = NULL;
    git_repository *repository = NULL;
    git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
    git2r_transfer_data payload = GIT2R_TRANSFER_DATA_INIT;
    git_strarray refs = {0};

    if (git2r_arg_check_string(name))
        git2r_error(__func__, NULL, "'name'", git2r_err_string_arg);
    if (git2r_arg_check_credentials(credentials))
        git2r_error(__func__, NULL, "'credentials'", git2r_err_credentials_arg);
    if (git2r_arg_check_string(msg))
        git2r_error(__func__, NULL, "'msg'", git2r_err_string_arg);
    if (git2r_arg_check_logical(verbose))
        git2r_error(__func__, NULL, "'verbose'", git2r_err_logical_arg);
    if (refspecs != R_NilValue && git2r_arg_check_string_vec(refspecs))
        git2r_error(__func__, NULL, "'refspecs'", git2r_err_string_vec_arg);

    repository = git2r_repository_open(repo);
    if (!repository)
        git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL);

    err = git_remote_lookup(&remote, repository, CHAR(STRING_ELT(name, 0)));
    if (err)
        goto cleanup;

    if (refspecs != R_NilValue) {
        size_t i, len;

        /* Count number of non NA values */
        len = length(refspecs);
        for (i = 0; i < len; i++)
            if (NA_STRING != STRING_ELT(refspecs, i))
                refs.count++;

        if (refs.count) {
            /* Allocate the strings in refs */
            refs.strings = malloc(refs.count * sizeof(char*));
            if (!refs.strings) {
                giterr_set_str(GITERR_NONE, git2r_err_alloc_memory_buffer);
                err = GIT_ERROR;
                goto cleanup;
            }

            /* Populate the strings in refs */
            for (i = 0; i < refs.count; i++)
                if (NA_STRING != STRING_ELT(refspecs, i))
                    refs.strings[i] = (char *)CHAR(STRING_ELT(refspecs, i));
        }
    }

    if (LOGICAL(verbose)[0])
        payload.verbose = 1;
    payload.credentials = credentials;
    fetch_opts.callbacks.payload = &payload;
    fetch_opts.callbacks.credentials = &git2r_cred_acquire_cb;
    fetch_opts.callbacks.update_tips = &git2r_update_tips_cb;
    err = git_remote_fetch(remote, &refs, &fetch_opts, CHAR(STRING_ELT(msg, 0)));
    if (err)
        goto cleanup;

    stats = git_remote_stats(remote);
    PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_transfer_progress")));
    git2r_transfer_progress_init(stats, result);

cleanup:
    if (refs.strings)
        free(refs.strings);

    if (remote) {
        if (git_remote_connected(remote))
            git_remote_disconnect(remote);
        git_remote_free(remote);
    }

    if (repository)
        git_repository_free(repository);

    if (R_NilValue != result)
        UNPROTECT(1);

    if (err)
        git2r_error(
            __func__,
            giterr_last(),
            git2r_err_unable_to_authenticate,
            NULL);

    return result;
}
コード例 #27
0
int git_path_direach(
	git_buf *path,
	uint32_t flags,
	int (*fn)(void *, git_buf *),
	void *arg)
{
	int error = 0;
	ssize_t wd_len;
	DIR *dir;
	struct dirent *de;

#ifdef GIT_USE_ICONV
	git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
#endif

	GIT_UNUSED(flags);

	if (git_path_to_dir(path) < 0)
		return -1;

	wd_len = git_buf_len(path);

	if ((dir = opendir(path->ptr)) == NULL) {
		giterr_set(GITERR_OS, "Failed to open directory '%s'", path->ptr);
		if (errno == ENOENT)
			return GIT_ENOTFOUND;

		return -1;
	}

#ifdef GIT_USE_ICONV
	if ((flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0)
		(void)git_path_iconv_init_precompose(&ic);
#endif

	while ((de = readdir(dir)) != NULL) {
		char *de_path = de->d_name;
		size_t de_len = strlen(de_path);

		if (git_path_is_dot_or_dotdot(de_path))
			continue;

#ifdef GIT_USE_ICONV
		if ((error = git_path_iconv(&ic, &de_path, &de_len)) < 0)
			break;
#endif

		if ((error = git_buf_put(path, de_path, de_len)) < 0)
			break;

		giterr_clear();
		error = fn(arg, path);

		git_buf_truncate(path, wd_len); /* restore path */

		/* Only set our own error if the callback did not set one already */
		if (error != 0) {
			if (!giterr_last())
				giterr_set_after_callback(error);

			break;
		}
	}

	closedir(dir);

#ifdef GIT_USE_ICONV
	git_path_iconv_clear(&ic);
#endif

	return error;
}
コード例 #28
0
ファイル: ssh.c プロジェクト: Nemchinovrp/sonic-pi
static int _git_ssh_setup_conn(
	ssh_subtransport *t,
	const char *url,
	const char *cmd,
	git_smart_subtransport_stream **stream)
{
	char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL;
	const char *default_port="22";
	int auth_methods, error = 0;
	size_t i;
	ssh_stream *s;
	git_cred *cred = NULL;
	LIBSSH2_SESSION* session=NULL;
	LIBSSH2_CHANNEL* channel=NULL;

	t->current_stream = NULL;

	*stream = NULL;
	if (ssh_stream_alloc(t, url, cmd, stream) < 0)
		return -1;

	s = (ssh_stream *)*stream;
	s->session = NULL;
	s->channel = NULL;

	for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
		const char *p = ssh_prefixes[i];

		if (!git__prefixcmp(url, p)) {
			if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port)) < 0)
				goto done;

			goto post_extract;
		}
	}
	if ((error = git_ssh_extract_url_parts(&host, &user, url)) < 0)
		goto done;
	port = git__strdup(default_port);
	GITERR_CHECK_ALLOC(port);

post_extract:
	if ((error = git_socket_stream_new(&s->io, host, port)) < 0 ||
	    (error = git_stream_connect(s->io)) < 0)
		goto done;

	if ((error = _git_ssh_session_create(&session, s->io)) < 0)
		goto done;

	if (t->owner->certificate_check_cb != NULL) {
		git_cert_hostkey cert = {{ 0 }}, *cert_ptr;
		const char *key;

		cert.parent.cert_type = GIT_CERT_HOSTKEY_LIBSSH2;

		key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
		if (key != NULL) {
			cert.type |= GIT_CERT_SSH_SHA1;
			memcpy(&cert.hash_sha1, key, 20);
		}

		key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
		if (key != NULL) {
			cert.type |= GIT_CERT_SSH_MD5;
			memcpy(&cert.hash_md5, key, 16);
		}

		if (cert.type == 0) {
			giterr_set(GITERR_SSH, "unable to get the host key");
			error = -1;
			goto done;
		}

		/* We don't currently trust any hostkeys */
		giterr_clear();

		cert_ptr = &cert;

		error = t->owner->certificate_check_cb((git_cert *) cert_ptr, 0, host, t->owner->message_cb_payload);
		if (error < 0) {
			if (!giterr_last())
				giterr_set(GITERR_NET, "user cancelled hostkey check");

			goto done;
		}
	}

	/* we need the username to ask for auth methods */
	if (!user) {
		if ((error = request_creds(&cred, t, NULL, GIT_CREDTYPE_USERNAME)) < 0)
			goto done;

		user = git__strdup(((git_cred_username *) cred)->username);
		cred->free(cred);
		cred = NULL;
		if (!user)
			goto done;
	} else if (user && pass) {
		if ((error = git_cred_userpass_plaintext_new(&cred, user, pass)) < 0)
			goto done;
	}

	if ((error = list_auth_methods(&auth_methods, session, user)) < 0)
		goto done;

	error = GIT_EAUTH;
	/* if we already have something to try */
	if (cred && auth_methods & cred->credtype)
		error = _git_ssh_authenticate_session(session, cred);

	while (error == GIT_EAUTH) {
		if (cred) {
			cred->free(cred);
			cred = NULL;
		}

		if ((error = request_creds(&cred, t, user, auth_methods)) < 0)
			goto done;

		if (strcmp(user, git_cred__username(cred))) {
			giterr_set(GITERR_SSH, "username does not match previous request");
			error = -1;
			goto done;
		}

		error = _git_ssh_authenticate_session(session, cred);
	}

	if (error < 0)
		goto done;

	channel = libssh2_channel_open_session(session);
	if (!channel) {
		error = -1;
		ssh_error(session, "Failed to open SSH channel");
		goto done;
	}

	libssh2_channel_set_blocking(channel, 1);

	s->session = session;
	s->channel = channel;

	t->current_stream = s;

done:
	if (error < 0) {
		ssh_stream_free(*stream);

		if (session)
			libssh2_session_free(session);
	}

	if (cred)
		cred->free(cred);

	git__free(host);
	git__free(port);
	git__free(path);
	git__free(user);
	git__free(pass);

	return error;
}
コード例 #29
0
ファイル: ssh.c プロジェクト: Nemchinovrp/sonic-pi
static int _git_ssh_authenticate_session(
	LIBSSH2_SESSION* session,
	git_cred* cred)
{
	int rc;

	do {
		giterr_clear();
		switch (cred->credtype) {
		case GIT_CREDTYPE_USERPASS_PLAINTEXT: {
			git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred;
			rc = libssh2_userauth_password(session, c->username, c->password);
			break;
		}
		case GIT_CREDTYPE_SSH_KEY: {
			git_cred_ssh_key *c = (git_cred_ssh_key *)cred;

			if (c->privatekey)
				rc = libssh2_userauth_publickey_fromfile(
					session, c->username, c->publickey,
					c->privatekey, c->passphrase);
			else
				rc = ssh_agent_auth(session, c);

			break;
		}
		case GIT_CREDTYPE_SSH_CUSTOM: {
			git_cred_ssh_custom *c = (git_cred_ssh_custom *)cred;

			rc = libssh2_userauth_publickey(
				session, c->username, (const unsigned char *)c->publickey,
				c->publickey_len, c->sign_callback, &c->payload);
			break;
		}
		case GIT_CREDTYPE_SSH_INTERACTIVE: {
			void **abstract = libssh2_session_abstract(session);
			git_cred_ssh_interactive *c = (git_cred_ssh_interactive *)cred;

			/* ideally, we should be able to set this by calling
			 * libssh2_session_init_ex() instead of libssh2_session_init().
			 * libssh2's API is inconsistent here i.e. libssh2_userauth_publickey()
			 * allows you to pass the `abstract` as part of the call, whereas
			 * libssh2_userauth_keyboard_interactive() does not!
			 *
			 * The only way to set the `abstract` pointer is by calling
			 * libssh2_session_abstract(), which will replace the existing
			 * pointer as is done below. This is safe for now (at time of writing),
			 * but may not be valid in future.
			 */
			*abstract = c->payload;

			rc = libssh2_userauth_keyboard_interactive(
				session, c->username, c->prompt_callback);
			break;
		}
#ifdef GIT_SSH_MEMORY_CREDENTIALS
		case GIT_CREDTYPE_SSH_MEMORY: {
			git_cred_ssh_key *c = (git_cred_ssh_key *)cred;

			assert(c->username);
			assert(c->privatekey);

			rc = libssh2_userauth_publickey_frommemory(
				session,
				c->username,
				strlen(c->username),
				c->publickey,
				c->publickey ? strlen(c->publickey) : 0,
				c->privatekey,
				strlen(c->privatekey),
				c->passphrase);
			break;
		}
#endif
		default:
			rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED;
		}
	} while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);

        if (rc == LIBSSH2_ERROR_PASSWORD_EXPIRED || rc == LIBSSH2_ERROR_AUTHENTICATION_FAILED)
                return GIT_EAUTH;

	if (rc != LIBSSH2_ERROR_NONE) {
		if (!giterr_last())
			ssh_error(session, "Failed to authenticate SSH session");
		return -1;
	}

	return 0;
}
コード例 #30
0
ファイル: git2r_merge.c プロジェクト: krlmlr/git2r
/**
 * Merge the given fetch head data into HEAD
 *
 * @param fetch_heads List of S4 class git_fetch_head objects.
 * @param merger Who made the merge, if the merge is non-fast forward
 * merge that creates a merge commit.
 * @return List of git_annotated_commit objects.
 */
SEXP git2r_merge_fetch_heads(SEXP fetch_heads, SEXP merger)
{
    int err;
    size_t n;
    SEXP result = R_NilValue;
    git_annotated_commit **merge_heads = NULL;
    git_repository *repository = NULL;
    git_signature *who = NULL;

    if (git2r_arg_check_fetch_heads(fetch_heads))
        git2r_error(__func__, NULL, "'fetch_heads'", git2r_err_fetch_heads_arg);
    if (git2r_arg_check_signature(merger))
        git2r_error(__func__, NULL, "'merger'", git2r_err_signature_arg);

    err = git2r_signature_from_arg(&who, merger);
    if (err)
        goto cleanup;

    n = LENGTH(fetch_heads);
    if (n) {
        SEXP repo = GET_SLOT(VECTOR_ELT(fetch_heads, 0), Rf_install("repo"));
        repository = git2r_repository_open(repo);
        if (!repository)
            git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL);
    }

    err = git2r_merge_heads_from_fetch_heads(
        &merge_heads,
        repository,
        fetch_heads,
        n);
    if (err)
        goto cleanup;

    PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_merge_result")));
    err = git2r_merge(
        result,
        repository,
        (const git_annotated_commit **)merge_heads,
        n,
        GIT_MERGE_PREFERENCE_NONE,
        "pull",
        who,
        1); /* Commit on success */
    if (err)
        goto cleanup;

cleanup:
    if (who)
        git_signature_free(who);

    if (merge_heads)
        git2r_merge_heads_free(merge_heads, n);

    if (repository)
        git_repository_free(repository);

    if (R_NilValue != result)
        UNPROTECT(1);

    if (err)
        git2r_error(__func__, giterr_last(), NULL, NULL);

    return result;
}