Exemple #1
0
int hiredis_odb_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid)
{
	hiredis_odb_backend *backend;
	int error;
	redisReply *reply;
	char *str_id = calloc(GIT_OID_HEXSZ + 1, sizeof(char));

	assert(len_p && type_p && _backend && oid);

	backend = (hiredis_odb_backend *) _backend;
	error = GIT_ERROR;

	git_oid_tostr(str_id, GIT_OID_HEXSZ, oid);

	reply = redisCommand(backend->db, "HMGET %s:%s:odb:%s %s %s", backend->prefix, backend->repo_path, str_id, "type", "size");

	if (reply && reply->type == REDIS_REPLY_ARRAY) {
		if (reply->element[0]->type != REDIS_REPLY_NIL &&
				reply->element[1]->type != REDIS_REPLY_NIL) {
			*type_p = (git_otype) atoi(reply->element[0]->str);
			*len_p = (size_t) atoi(reply->element[1]->str);
			error = GIT_OK;
		} else {
			giterr_set_str(GITERR_ODB, "Redis odb storage corrupted");
			error = GIT_ENOTFOUND;
		}
	} else {
		giterr_set_str(GITERR_ODB, "Redis odb storage error");
		error = GIT_ERROR;
	}

	free(str_id);
	freeReplyObject(reply);
	return error;
}
Exemple #2
0
int git_refdb_backend_hiredis(git_refdb_backend **backend_out, const char* prefix, const char* path, const char *host, int port, char* password)
{
	hiredis_refdb_backend *backend;
	redisReply *reply;

	backend = calloc(1, sizeof(hiredis_refdb_backend));
	if (backend == NULL)
		return GITERR_NOMEMORY;

	if (sharedConnection == NULL) {
		sharedConnection = redisConnect(host, port);
		if (sharedConnection->err) {
			free(backend);
			giterr_set_str(GITERR_REFERENCE, "Redis refdb storage couldn't connect to redis server");
			return GIT_ERROR;
		}

		if (password != NULL) {
			reply = redisCommand(sharedConnection, "AUTH %s", password);
			if (reply->type == REDIS_REPLY_ERROR) {
				freeReplyObject(reply);
				redisFree(sharedConnection);
				free(backend);
				giterr_set_str(GITERR_REFERENCE, "Redis refdb storage authentication with redis server failed");
				return GIT_ERROR;
			}
			freeReplyObject(reply);
		}
	}

	backend->db = sharedConnection;

	backend->prefix = strdup(prefix);
	backend->repo_path = strdup(path);

	backend->parent.exists = &hiredis_refdb_backend__exists;
	backend->parent.lookup = &hiredis_refdb_backend__lookup;
	backend->parent.iterator = &hiredis_refdb_backend__iterator;
	backend->parent.write = &hiredis_refdb_backend__write;
	backend->parent.del = &hiredis_refdb_backend__del;
	backend->parent.rename = &hiredis_refdb_backend__rename;
	backend->parent.compress = NULL;
	backend->parent.free = &hiredis_refdb_backend__free;

	backend->parent.has_log = &hiredis_refdb_backend__has_log;
	backend->parent.ensure_log = &hiredis_refdb_backend__ensure_log;
	backend->parent.reflog_read = &hiredis_refdb_backend__reflog_read;
	backend->parent.reflog_write = &hiredis_refdb_backend__reflog_write;
	backend->parent.reflog_rename = &hiredis_refdb_backend__reflog_rename;
	backend->parent.reflog_delete = &hiredis_refdb_backend__reflog_delete;

	*backend_out = (git_refdb_backend *) backend;

	return GIT_OK;
}
Exemple #3
0
int git_odb_backend_hiredis(git_odb_backend **backend_out, const char* prefix, const char* path, const char *host, int port, char* password)
{
	hiredis_odb_backend *backend;
	redisReply *reply;

	backend = calloc(1, sizeof (hiredis_odb_backend));
	if (backend == NULL)
		return GITERR_NOMEMORY;

	if (sharedConnection == NULL) {
		sharedConnection = redisConnect(host, port);
		if (sharedConnection->err) {
			free(backend);
			giterr_set_str(GITERR_REFERENCE, "Redis odb storage couldn't connect to redis server");
			return GIT_ERROR;
		}

		if (password != NULL) {
			reply = redisCommand(sharedConnection, "AUTH %s", password);
			if (reply == NULL || reply->type == REDIS_REPLY_ERROR) {
				freeReplyObject(reply);
				redisFree(sharedConnection);
				free(backend);
				giterr_set_str(GITERR_REFERENCE, "Redis odb storage authentication with redis server failed");
				return GIT_ERROR;
			}
			freeReplyObject(reply);
		}
	}

	backend->db = sharedConnection;

	backend->prefix = strdup(prefix);
	backend->repo_path = strdup(path);

	backend->parent.version = 1;

	backend->parent.read = &hiredis_odb_backend__read;
	backend->parent.write = &hiredis_odb_backend__write;
	backend->parent.read_prefix = &hiredis_odb_backend__read_prefix;
	backend->parent.read_header = &hiredis_odb_backend__read_header;
	backend->parent.exists = &hiredis_odb_backend__exists;
	backend->parent.free = &hiredis_odb_backend__free;

	backend->parent.writestream = NULL;
	backend->parent.foreach = NULL;

	*backend_out = (git_odb_backend *) backend;

	return GIT_OK;
}
Exemple #4
0
int hiredis_refdb_backend__iterator(git_reference_iterator **_iter, struct git_refdb_backend *_backend, const char *glob)
{
	hiredis_refdb_backend *backend;
	hiredis_refdb_iterator *iterator;
	int error = GIT_OK;
	redisReply *reply;

	assert(_backend);

	backend = (hiredis_refdb_backend *) _backend;

	reply = redisCommand(backend->db, "KEYS %s:%s:refdb:%s", backend->prefix, backend->repo_path, (glob != NULL ? glob : "refs/*"));
	if(reply->type != REDIS_REPLY_ARRAY) {
		freeReplyObject(reply);
		giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error");
		return GIT_ERROR;
	}

	iterator = calloc(1, sizeof(hiredis_refdb_iterator));

	iterator->backend = backend;
	iterator->keys = reply;

	iterator->parent.next = &hiredis_refdb_backend__iterator_next;
	iterator->parent.next_name = &hiredis_refdb_backend__iterator_next_name;
	iterator->parent.free = &hiredis_refdb_backend__iterator_free;

	*_iter = (git_reference_iterator *) iterator;

	return GIT_OK;
}
Exemple #5
0
/**
 * Retrieve parents of the commit under construction
 *
 * @param parents The vector of parents to create and populate.
 * @param n_parents The length of parents vector
 * @param repository The repository
 * @return 0 on succes, or error code
 */
static int git2r_retrieve_parents(
    git_commit ***parents,
    size_t *n_parents,
    git_repository *repository)
{
    int err;
    git_oid oid;
    git2r_merge_head_cb_data cb_data = {0, NULL, NULL};
    git_repository_state_t state;

    err = git_repository_head_unborn(repository);
    if (1 == err) {
        *n_parents = 0;
        return GIT_OK;
    } else if (0 != err) {
        return err;
    }

    state = git_repository_state(repository);
    if (state == GIT_REPOSITORY_STATE_MERGE) {
        /* Count number of merge heads */
        err = git_repository_mergehead_foreach(
            repository,
            git2r_repository_mergehead_foreach_cb,
            &cb_data);
        if (GIT_OK != err)
            return err;
    }

    *parents = calloc(cb_data.n + 1, sizeof(git_commit*));
    if (!parents) {
        giterr_set_str(GITERR_NONE, git2r_err_alloc_memory_buffer);
        return GIT_ERROR;
    }
    *n_parents = cb_data.n + 1;

    err = git_reference_name_to_id(&oid, repository, "HEAD");
    if (GIT_OK != err)
        return err;

    err = git_commit_lookup(&**parents, repository, &oid);
    if (GIT_OK != err)
        return err;

    if (state == GIT_REPOSITORY_STATE_MERGE) {
        /* Append merge heads to parents */
        cb_data.n = 0;
        cb_data.repository = repository;
        cb_data.parents = *parents + 1;
        err = git_repository_mergehead_foreach(
            repository,
            git2r_repository_mergehead_foreach_cb,
            &cb_data);
        if (GIT_OK != err)
            return err;
    }

    return GIT_OK;
}
int RemoteProgressCommand::RemoteProgressCallback(const char* str, int len, void* data)
{
	((CGitProgressList::Payload*)data)->list->SetProgressLabelText(CUnicodeUtils::GetUnicode(CStringA(str, len)));
	if (((CGitProgressList::Payload*)data)->list->m_bCancelled)
	{
		giterr_set_str(GITERR_NONE, "User cancelled.");
		return GIT_EUSER;
	}
	return 0;
}
Exemple #7
0
int git__page_size(size_t *page_size)
{
	long sc_page_size = sysconf(_SC_PAGE_SIZE);
	if (sc_page_size < 0) {
		giterr_set_str(GITERR_OS, "Can't determine system page size");
		return -1;
	}
	*page_size = (size_t) sc_page_size;
	return 0;
}
Exemple #8
0
int hiredis_refdb_backend__lookup(git_reference **out, git_refdb_backend *_backend, const char *ref_name)
{
	hiredis_refdb_backend *backend;
	int error = GIT_OK;
	redisReply *reply;
	git_oid oid;

	assert(ref_name && _backend);

	backend = (hiredis_refdb_backend *) _backend;

	reply = redisCommand(backend->db, "HMGET %s:%s:refdb:%s type target", backend->prefix, backend->repo_path, ref_name);
	if(reply->type == REDIS_REPLY_ARRAY) {
		if (reply->element[0]->type != REDIS_REPLY_NIL && reply->element[1]->type != REDIS_REPLY_NIL) {
			git_ref_t type = (git_ref_t) atoi(reply->element[0]->str);

			if (type == GIT_REF_OID) {
				git_oid_fromstr(&oid, reply->element[1]->str);
				*out = git_reference__alloc(ref_name, &oid, NULL);
			} else if (type == GIT_REF_SYMBOLIC) {
				*out = git_reference__alloc_symbolic(ref_name, reply->element[1]->str);
			} else {
				giterr_set_str(GITERR_REFERENCE, "Redis refdb storage corrupted (unknown ref type returned)");
				error = GIT_ERROR;
			}

		} else {
			giterr_set_str(GITERR_REFERENCE, "Redis refdb couldn't find ref");
			error = GIT_ENOTFOUND;
		}
	} else {
		giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error");
		error = GIT_ERROR;
	}

	freeReplyObject(reply);
	return error;
}
Exemple #9
0
/**
 * Check for any changes in index
 *
 * @param repository The repository
 * @return 0 if ok, else error code.
 */
static int git2r_any_changes_in_index(git_repository *repository)
{
    int err;
    int changes_in_index = 0;
    size_t i, count;
    git_status_list *status = NULL;
    git_status_options opts = GIT_STATUS_OPTIONS_INIT;
    opts.show  = GIT_STATUS_SHOW_INDEX_ONLY;

    err = git_status_list_new(&status, repository, &opts);
    if (GIT_OK != err)
        goto cleanup;

    count = git_status_list_entrycount(status);
    for (i = 0; i < count; ++i) {
        const git_status_entry *s = git_status_byindex(status, i);

        if (s->status == GIT_STATUS_CURRENT)
            continue;

        if (s->status & GIT_STATUS_INDEX_NEW)
            changes_in_index = 1;
        else if (s->status & GIT_STATUS_INDEX_MODIFIED)
            changes_in_index = 1;
        else if (s->status & GIT_STATUS_INDEX_DELETED)
            changes_in_index = 1;
        else if (s->status & GIT_STATUS_INDEX_RENAMED)
            changes_in_index = 1;
        else if (s->status & GIT_STATUS_INDEX_TYPECHANGE)
            changes_in_index = 1;

        if (changes_in_index)
            break;
    }

    if (!changes_in_index) {
        giterr_set_str(GITERR_NONE, git2r_err_nothing_added_to_commit);
        err = GIT_ERROR;
    }

cleanup:
    if (status)
        git_status_list_free(status);

    return err;
}
Exemple #10
0
int hiredis_odb_backend__read_prefix(git_oid *out_oid,
		void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend,
		const git_oid *short_oid, size_t len)
{
	if (len >= GIT_OID_HEXSZ) {
		/* Just match the full identifier */
		int error = hiredis_odb_backend__read(data_p, len_p, type_p, _backend, short_oid);
		if (error == GIT_OK)
			git_oid_cpy(out_oid, short_oid);

		return error;
	}

	/* TODO prefix */
	giterr_set_str(GITERR_ODB, "Redis odb doesn't not implement oid prefix lookup");
	return GIT_EINVALID;
}
Exemple #11
0
/**
 * Create and populate a vector of git_annotated_commit objects from
 * the given fetch head data.
 *
 * @param out Pointer the vector of git_annotated_commit objects.
 * @param repository The repository.
 * @param fetch_heads List of S4 class git_fetch_head objects.
 * @param n Length of fetch_heads list.
 * @return 0 on success, or error code
 */
static int git2r_merge_heads_from_fetch_heads(
    git_annotated_commit ***merge_heads,
    git_repository *repository,
    SEXP fetch_heads,
    size_t n)
{
    int err = GIT_OK;
    size_t i;

    *merge_heads = calloc(n, sizeof(git_annotated_commit*));
    if (!(*merge_heads)) {
        giterr_set_str(GITERR_NONE, git2r_err_alloc_memory_buffer);
        return GIT_ERROR;
    }

    for (i = 0; i < n; i++) {
        int err;
        git_oid oid;
        SEXP fh = VECTOR_ELT(fetch_heads, i);

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

        err = git_annotated_commit_from_fetchhead(
            &((*merge_heads)[i]),
            repository,
            CHAR(STRING_ELT(GET_SLOT(fh, Rf_install("ref_name")), 0)),
            CHAR(STRING_ELT(GET_SLOT(fh, Rf_install("remote_url")), 0)),
            &oid);
        if (err)
            goto cleanup;
    }

cleanup:
    if (err) {
        if (*merge_heads)
            git2r_merge_heads_free(*merge_heads, n);
        *merge_heads = NULL;
    }

    return err;
}
Exemple #12
0
int hiredis_refdb_backend__del(git_refdb_backend *_backend, const char *ref_name, const git_oid *old, const char *old_target)
{
	hiredis_refdb_backend *backend;
	int error = GIT_OK;
	redisReply *reply;

	assert(ref_name && _backend);

	backend = (hiredis_refdb_backend *) _backend;

	reply = redisCommand(backend->db, "DEL %s:%s:refdb:%s", backend->prefix, backend->repo_path, ref_name);
	if(reply->type == REDIS_REPLY_ERROR) {
		giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error");
		error = GIT_ERROR;
	}

	freeReplyObject(reply);
	return error;
}
Exemple #13
0
int hiredis_refdb_backend__exists(int *exists, git_refdb_backend *_backend, const char *ref_name)
{
	hiredis_refdb_backend *backend;
	int error = GIT_OK;
	redisReply *reply;

	assert(ref_name && _backend);

	backend = (hiredis_refdb_backend *) _backend;

	reply = redisCommand(backend->db, "EXISTS %s:%s:refdb:%s", backend->prefix, backend->repo_path, ref_name);
	if (reply->type == REDIS_REPLY_INTEGER) {
		*exists = reply->integer;
	} else {
		giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error");
		error = GIT_ERROR;
	}

	freeReplyObject(reply);
	return error;
}
Exemple #14
0
int hiredis_refdb_backend__rename(git_reference **out, git_refdb_backend *_backend, const char *old_name,
	const char *new_name, int force, const git_signature *who, const char *message)
{
	hiredis_refdb_backend *backend;
	int error = GIT_OK;
	redisReply *reply;

	assert(old_name && new_name && _backend);

	backend = (hiredis_refdb_backend *) _backend;

	reply = redisCommand(backend->db, "RENAME %s:%s:refdb:%s %s:%s:refdb:%s",
						backend->prefix, backend->repo_path, old_name, backend->prefix, backend->repo_path, new_name);
	if(reply->type == REDIS_REPLY_ERROR) {
		freeReplyObject(reply);

		giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error");
		return GIT_ERROR;
	}

	freeReplyObject(reply);
	return hiredis_refdb_backend__lookup(out, _backend, new_name);
}
Exemple #15
0
int hiredis_refdb_backend__write(git_refdb_backend *_backend, const git_reference *ref, int force, const git_signature *who,
	const char *message, const git_oid *old, const char *old_target)
{
	hiredis_refdb_backend *backend;
	int error = GIT_OK;
	redisReply *reply;

	const char *name = git_reference_name(ref);
	const git_oid *target;
	const char *symbolic_target;
	char oid_str[GIT_OID_HEXSZ + 1];

	assert(ref && _backend);

	backend = (hiredis_refdb_backend *) _backend;

	target = git_reference_target(ref);

	/* FIXME handle force correctly */

	if (target) {
		git_oid_nfmt(oid_str, sizeof(oid_str), target);
		reply = redisCommand(backend->db, "HMSET %s:%s:refdb:%s type %d target %s", backend->prefix, backend->repo_path, name, GIT_REF_OID, oid_str);
	} else {
		symbolic_target = git_reference_symbolic_target(ref);
		reply = redisCommand(backend->db, "HMSET %s:%s:refdb:%s type %d target %s", backend->prefix, backend->repo_path, name, GIT_REF_SYMBOLIC, symbolic_target);
	}

	if(reply->type == REDIS_REPLY_ERROR) {
		giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error");
		error = GIT_ERROR;
	}

	freeReplyObject(reply);
	return error;
}
Exemple #16
0
/**
 * Merge branch into HEAD
 *
 * @param branch S4 class git_branch to merge into HEAD.
 * @param merger Who is performing the merge
 * @param commit_on_success Commit merge commit, if one was created
 * during a normal merge
 * @return S4 class git_merge_result
 */
SEXP git2r_merge_branch(SEXP branch, SEXP merger, SEXP commit_on_success)
{
    int err;
    SEXP result = R_NilValue;
    const char *name;
    git_buf buf = GIT_BUF_INIT;
    git_branch_t type;
    git_annotated_commit **merge_heads = NULL;
    git_reference *reference = NULL;
    git_repository *repository = NULL;
    git_signature *who = NULL;

    if (git2r_arg_check_branch(branch))
        git2r_error(__func__, NULL, "'branch'", git2r_err_branch_arg);
    if (git2r_arg_check_logical(commit_on_success))
        git2r_error(__func__, NULL, "'commit_on_success'", git2r_err_logical_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;

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

    name = CHAR(STRING_ELT(GET_SLOT(branch, Rf_install("name")), 0));
    type = INTEGER(GET_SLOT(branch, Rf_install("type")))[0];
    err = git_branch_lookup(&reference, repository, name, type);
    if (err)
        goto cleanup;

    merge_heads = calloc(1, sizeof(git_annotated_commit*));
    if (NULL == merge_heads) {
        giterr_set_str(GITERR_NONE, git2r_err_alloc_memory_buffer);
        goto cleanup;
    }

    err = git_annotated_commit_from_ref(
        &(merge_heads[0]),
        repository,
        reference);
    if (err)
        goto cleanup;

    err = git_buf_printf(&buf, "merge %s", name);
    if (err)
        goto cleanup;

    PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_merge_result")));
    err = git2r_merge(
        result,
        repository,
        (const git_annotated_commit **)merge_heads,
        1,
        GIT_MERGE_PREFERENCE_NONE,
        buf.ptr,
        who,
        LOGICAL(commit_on_success)[0]);

cleanup:
    git_buf_free(&buf);

    if (who)
        git_signature_free(who);

    if (merge_heads)
        git2r_merge_heads_free(merge_heads, 1);

    if (reference)
        git_reference_free(reference);

    if (repository)
        git_repository_free(repository);

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

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

    return result;
}
Exemple #17
0
/**
 * @param merge_result S4 class git_merge_result
 * @repository The repository
 * @param merge_head The merge head to merge
 * @param n The number of merge heads
 * @param preference The merge preference option (None [0], No
 * Fast-Forward [1] or Only Fast-Forward [2])
 * @param name The name of the merge in the reflog
 * @param merger Who is performing the merge
 * @param commit_on_success Commit merge commit, if one was created
 * during a normal merge
 * @return 0 on success, or error code
 */
static int git2r_merge(
    SEXP merge_result,
    git_repository *repository,
    const git_annotated_commit **merge_heads,
    size_t n,
    git_merge_preference_t preference,
    const char *name,
    git_signature *merger,
    int commit_on_success)
{
    int err;
    git_merge_analysis_t merge_analysis;
    git_merge_preference_t merge_preference;
    git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
    git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT;

    merge_opts.rename_threshold = 50;
    merge_opts.target_limit = 200;

    checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;

    err = git_merge_analysis(
        &merge_analysis,
        &merge_preference,
        repository,
        merge_heads,
        n);
    if (err)
        return err;

    if (merge_analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE) {
        SET_SLOT(merge_result,
                 Rf_install("up_to_date"),
                 ScalarLogical(1));
        return GIT_OK;
    } else {
        SET_SLOT(merge_result,
                 Rf_install("up_to_date"),
                 ScalarLogical(0));
    }

    if (GIT_MERGE_PREFERENCE_NONE == preference)
        preference = merge_preference;

    switch (preference) {
    case GIT_MERGE_PREFERENCE_NONE:
        if (merge_analysis & GIT_MERGE_ANALYSIS_FASTFORWARD) {
            if (1 != n) {
                giterr_set_str(
                    GITERR_NONE,
                    "Unable to perform Fast-Forward merge "
                    "with mith multiple merge heads.");
                return GIT_ERROR;
            }

            err = git2r_fast_forward_merge(
                merge_result,
                merge_heads[0],
                repository,
                name);
        } else if (merge_analysis & GIT_MERGE_ANALYSIS_NORMAL) {
            err = git2r_normal_merge(
                merge_result,
                merge_heads,
                n,
                repository,
                name,
                merger,
                commit_on_success,
                &checkout_opts,
                &merge_opts);
        }
        break;
    case GIT_MERGE_PREFERENCE_NO_FASTFORWARD:
        if (merge_analysis & GIT_MERGE_ANALYSIS_NORMAL) {
            err = git2r_normal_merge(
                merge_result,
                merge_heads,
                n,
                repository,
                name,
                merger,
                commit_on_success,
                &checkout_opts,
                &merge_opts);
        }
        break;
    case GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY:
        if (merge_analysis & GIT_MERGE_ANALYSIS_FASTFORWARD) {
            if (1 != n) {
                giterr_set_str(
                    GITERR_NONE,
                    "Unable to perform Fast-Forward merge "
                    "with mith multiple merge heads.");
                return GIT_ERROR;
            }

            err = git2r_fast_forward_merge(
                merge_result,
                merge_heads[0],
                repository,
                name);
        } else {
            giterr_set_str(GITERR_NONE, "Unable to perform Fast-Forward merge.");
            return GIT_ERROR;
        }
        break;
    default:
        giterr_set_str(GITERR_NONE, "Unknown merge option");
        return GIT_ERROR;
    }

    return GIT_OK;
}
Exemple #18
0
int git_pkt_parse_line(
	git_pkt **head, const char *line, const char **out, size_t bufflen)
{
	int ret;
	int32_t len;

	/* Not even enough for the length */
	if (bufflen > 0 && bufflen < PKT_LEN_SIZE)
		return GIT_EBUFS;

	len = parse_len(line);
	if (len < 0) {
		/*
		 * If we fail to parse the length, it might be because the
		 * server is trying to send us the packfile already.
		 */
		if (bufflen >= 4 && !git__prefixcmp(line, "PACK")) {
			giterr_clear();
			*out = line;
			return pack_pkt(head);
		}

		return (int)len;
	}

	/*
	 * If we were given a buffer length, then make sure there is
	 * enough in the buffer to satisfy this line
	 */
	if (bufflen > 0 && bufflen < (size_t)len)
		return GIT_EBUFS;

	/*
	 * The length has to be exactly 0 in case of a flush
	 * packet or greater than PKT_LEN_SIZE, as the decoded
	 * length includes its own encoded length of four bytes.
	 */
	if (len != 0 && len < PKT_LEN_SIZE)
		return GIT_ERROR;

	line += PKT_LEN_SIZE;
	/*
	 * The Git protocol does not specify empty lines as part
	 * of the protocol. Not knowing what to do with an empty
	 * line, we should return an error upon hitting one.
	 */
	if (len == PKT_LEN_SIZE) {
		giterr_set_str(GITERR_NET, "Invalid empty packet");
		return GIT_ERROR;
	}

	if (len == 0) { /* Flush pkt */
		*out = line;
		return flush_pkt(head);
	}

	len -= PKT_LEN_SIZE; /* the encoded length includes its own size */

	if (*line == GIT_SIDE_BAND_DATA)
		ret = data_pkt(head, line, len);
	else if (*line == GIT_SIDE_BAND_PROGRESS)
		ret = sideband_progress_pkt(head, line, len);
	else if (*line == GIT_SIDE_BAND_ERROR)
		ret = sideband_error_pkt(head, line, len);
	else if (!git__prefixcmp(line, "ACK"))
		ret = ack_pkt(head, line, len);
	else if (!git__prefixcmp(line, "NAK"))
		ret = nak_pkt(head);
	else if (!git__prefixcmp(line, "ERR "))
		ret = err_pkt(head, line, len);
	else if (*line == '#')
		ret = comment_pkt(head, line, len);
	else if (!git__prefixcmp(line, "ok"))
		ret = ok_pkt(head, line, len);
	else if (!git__prefixcmp(line, "ng"))
		ret = ng_pkt(head, line, len);
	else if (!git__prefixcmp(line, "unpack"))
		ret = unpack_pkt(head, line, len);
	else
		ret = ref_pkt(head, line, len);

	*out = line + len;

	return ret;
}
Exemple #19
0
static int handle(KDriver const *driver, KImplementation const *impl, int requested)
{
	char const *url = k_dictionary_get(k_implementation_get_values(impl), "href");
	char const *tag = k_dictionary_get(k_implementation_get_values(impl), "tag");
	char const *path = k_dictionary_get(k_implementation_get_meta(impl), "name");

	git_repository* repo = NULL;
	git_remote* origin = NULL;

	if (git_repository_open(&repo, path) == GIT_OK)
	{
		if (git_remote_load(&origin, repo, "origin") != GIT_OK)
		{
			git_repository_free(repo);
			return -1;
		}

		if (strcmp(url, git_remote_url(origin)) != 0)
		{
			giterr_set_str(GITERR_INVALID, "different origin");
			git_repository_free(repo);
			return -1;
		}
	}
	else
	{
		if (git_repository_init(&repo, path, 0) != GIT_OK)
		{
			return -1;
		}

		if (git_remote_create(&origin, repo, "origin", url) != GIT_OK)
		{
			git_repository_free(repo);
			return -1;
		}
	}

	git_remote_set_update_fetchhead(origin, 0);
	git_remote_set_cred_acquire_cb(origin, cred_acquire, NULL);

	if (git_remote_connect(origin, GIT_DIRECTION_FETCH) != GIT_OK)
	{
		git_remote_free(origin);
		git_repository_free(repo);
		return -1;
	}

	if (git_remote_download(origin, transfer_progress, NULL) != GIT_OK)
	{
		git_remote_free(origin);
		git_repository_free(repo);
		return -1;
	}

	if (git_remote_update_tips(origin) != GIT_OK)
	{
		git_remote_free(origin);
		git_repository_free(repo);
		return -1;
	}

	git_object* object = NULL;

	if (git_revparse_single(&object, repo, tag) != GIT_OK)
	{
		git_remote_free(origin);
		git_repository_free(repo);
		return -1;
	}

	if (git_repository_set_head_detached(repo, git_object_id(object)) != GIT_OK)
	{
		git_object_free(object);
		git_remote_free(origin);
		git_repository_free(repo);
		return -1;
	}

	git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT;
	checkout_opts.version = GIT_CHECKOUT_OPTS_VERSION;
	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
	checkout_opts.progress_cb = checkout_progress;
	checkout_opts.progress_payload = NULL;

	if (git_checkout_tree(repo, object, &checkout_opts) != GIT_OK)
	{
		git_object_free(object);
		git_remote_free(origin);
		git_repository_free(repo);
		return -1;
	}

	git_object_free(object);
	git_remote_free(origin);
	git_repository_free(repo);
	return 0;
}
int CGitProgressList::UpdateProgress(const git_transfer_progress* stat)
{
	static unsigned int start = 0;
	unsigned int dt = GetCurrentTime() - start;
	double speed = 0;
	
	if (m_bCancelled)
	{
		giterr_set_str(GITERR_NONE, "User cancelled.");
		return GIT_EUSER;
	}

	if (dt > 100)
	{
		start = GetCurrentTime();
		size_t ds = stat->received_bytes - m_TotalBytesTransferred;
		speed = ds * 1000.0/dt;
		m_TotalBytesTransferred = stat->received_bytes;
	}
	else
		return 0;

	int progress;
	progress = stat->received_objects + stat->indexed_objects;

	if ((stat->total_objects > 1000) && m_pProgControl && (!m_pProgControl->IsWindowVisible()))
		m_pProgControl->ShowWindow(SW_SHOW);

	if (m_pProgressLabelCtrl && m_pProgressLabelCtrl->IsWindowVisible())
		m_pProgressLabelCtrl->ShowWindow(SW_SHOW);

	if (m_pProgControl)
	{
		m_pProgControl->SetPos(progress);
		m_pProgControl->SetRange32(0, 2 * stat->total_objects);
	}
	if (m_pTaskbarList && m_pPostWnd)
	{
		m_pTaskbarList->SetProgressState(m_pPostWnd->GetSafeHwnd(), TBPF_NORMAL);
		m_pTaskbarList->SetProgressValue(m_pPostWnd->GetSafeHwnd(), progress, 2 * stat->total_objects);
	}

	CString progText;
	if (stat->received_bytes < 1024)
		m_sTotalBytesTransferred.Format(IDS_SVN_PROGRESS_TOTALBYTESTRANSFERRED, (int64_t)stat->received_bytes);
	else if (stat->received_bytes < 1200000)
		m_sTotalBytesTransferred.Format(IDS_SVN_PROGRESS_TOTALTRANSFERRED, (int64_t)stat->received_bytes / 1024);
	else
		m_sTotalBytesTransferred.Format(IDS_SVN_PROGRESS_TOTALMBTRANSFERRED, (double)((double)stat->received_bytes / 1048576.0));

	CString str;
	if(speed < 1024)
		str.Format(_T("%.0f B/s"), speed);
	else if(speed < 1024 * 1024)
		str.Format(_T("%.2f KiB/s"), speed / 1024);
	else
		str.Format(_T("%.2f MiB/s"), speed / 1048576.0);

	progText.Format(IDS_SVN_PROGRESS_TOTALANDSPEED, (LPCTSTR)m_sTotalBytesTransferred, (LPCTSTR)str);
	if (m_pProgressLabelCtrl)
		m_pProgressLabelCtrl->SetWindowText(progText);

	SetTimer(TRANSFERTIMER, 2000, NULL);

	return 0;
}
Exemple #21
0
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";
	ssh_stream *s;
	LIBSSH2_SESSION* session=NULL;
	LIBSSH2_CHANNEL* channel=NULL;

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

	s = (ssh_stream *)*stream;

	if (!git__prefixcmp(url, prefix_ssh)) {
		if (gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port) < 0)
			goto on_error;
	} else {
		if (git_ssh_extract_url_parts(&host, &user, url) < 0)
			goto on_error;
		port = git__strdup(default_port);
		GITERR_CHECK_ALLOC(port);
	}

	if (gitno_connect(&s->socket, host, port, 0) < 0)
		goto on_error;

	if (user && pass) {
		if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0)
			goto on_error;
	} else if (t->owner->cred_acquire_cb) {
		if (t->owner->cred_acquire_cb(
				&t->cred, t->owner->url, user,
				GIT_CREDTYPE_USERPASS_PLAINTEXT |
				GIT_CREDTYPE_SSH_KEY |
				GIT_CREDTYPE_SSH_CUSTOM,
				t->owner->cred_acquire_payload) < 0)
			goto on_error;

		if (!t->cred) {
			giterr_set(GITERR_SSH, "Callback failed to initialize SSH credentials");
			goto on_error;
		}
	} else {
		giterr_set(GITERR_SSH, "Cannot set up SSH connection without credentials");
		goto on_error;
	}
	assert(t->cred);

	if (!user && !git_cred_has_username(t->cred)) {
		giterr_set_str(GITERR_NET, "Cannot authenticate without a username");
		goto on_error;
	}

	if (_git_ssh_session_create(&session, s->socket) < 0)
		goto on_error;

	if (_git_ssh_authenticate_session(session, user, t->cred) < 0)
		goto on_error;

	channel = libssh2_channel_open_session(session);
	if (!channel) {
		ssh_error(session, "Failed to open SSH channel");
		goto on_error;
	}

	libssh2_channel_set_blocking(channel, 1);

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

	t->current_stream = s;
	git__free(host);
	git__free(port);
	git__free(path);
	git__free(user);
	git__free(pass);

	return 0;

on_error:
	s->session = NULL;
	s->channel = NULL;
	t->current_stream = NULL;

	if (*stream)
		ssh_stream_free(*stream);

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

	if (session)
		libssh2_session_free(session);

	return -1;
}
Exemple #22
0
void giterr_set_regex(const regex_t *regex, int error_code)
{
	char error_buf[1024];
	regerror(error_code, regex, error_buf, sizeof(error_buf));
	giterr_set_str(GITERR_REGEX, error_buf);
}
Exemple #23
0
/**
 * 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;
}
Exemple #24
0
/**
 * Find object specified by revision
 *
 * @param repo S4 class git_repository
 * @param revision The revision string, see
 * http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions
 * @return S4 object of class git_commit, git_tag or git_tree.
 */
SEXP git2r_revparse_single(SEXP repo, SEXP revision)
{
    int err;
    SEXP result = R_NilValue;
    git_repository *repository = NULL;
    git_object *treeish = NULL;

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

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

    err = git_revparse_single(
        &treeish,
        repository,
        CHAR(STRING_ELT(revision, 0)));
    if (GIT_OK != err)
        goto cleanup;

    switch (git_object_type(treeish)) {
    case GIT_OBJ_COMMIT:
        PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_commit")));
        git2r_commit_init((git_commit*)treeish, repo, result);
        break;
    case GIT_OBJ_TAG:
        PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_tag")));
        git2r_tag_init((git_tag*)treeish, repo, result);
        break;
    case GIT_OBJ_TREE:
        PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_tree")));
        git2r_tree_init((git_tree*)treeish, repo, result);
        break;
    default:
        giterr_set_str(GITERR_NONE, git2r_err_revparse_single);
        err = GIT_ERROR;
        break;
    }

cleanup:
    if (treeish)
        git_object_free(treeish);

    if (repository)
        git_repository_free(repository);

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

    if (GIT_OK != err) {
        if (GIT_ENOTFOUND == err) {
            git2r_error(
                git2r_err_from_libgit2,
                __func__,
                "Requested object could not be found");
        } else {
            git2r_error(
                git2r_err_from_libgit2,
                __func__,
                giterr_last()->message);
        }
    }

    return result;
}