Ejemplo n.º 1
0
/**
 * Get the tree pointed to by a commit
 *
 * @param commit S4 class git_commit or git_stash
 * @return S4 class git_tree
 */
SEXP git2r_commit_tree(SEXP commit)
{
    int err;
    SEXP result = R_NilValue;
    SEXP repo;
    git_commit *commit_obj = NULL;
    git_repository *repository = NULL;
    git_tree *tree = NULL;

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

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

    err = git2r_commit_lookup(&commit_obj, repository, commit);
    if (GIT_OK != err)
        goto cleanup;

    err = git_commit_tree(&tree, commit_obj);
    if (GIT_OK != err)
        goto cleanup;

    PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_tree")));
    git2r_tree_init((git_tree*)tree, repo, result);

cleanup:
    if (commit_obj)
        git_commit_free(commit_obj);

    if (tree)
        git_tree_free(tree);

    if (repository)
        git_repository_free(repository);

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

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

    return result;
}
Ejemplo n.º 2
0
/**
 * Lookup an object in a repository
 *
 * @param repo S4 class git_repository
 * @param hex 4 to 40 char hexadecimal string
 * @return S4 object with lookup
 */
SEXP git2r_object_lookup(SEXP repo, SEXP hex)
{
    int err;
    size_t len;
    SEXP result = R_NilValue;
    git_object *object = NULL;
    git_oid oid;
    git_repository *repository = NULL;

    if (git2r_error_check_hex_arg(hex))
        error("Invalid arguments to git2r_object_lookup");

    repository = git2r_repository_open(repo);
    if (!repository)
        error(git2r_err_invalid_repository);

    len = LENGTH(STRING_ELT(hex, 0));
    if (GIT_OID_HEXSZ == len) {
        git_oid_fromstr(&oid, CHAR(STRING_ELT(hex, 0)));
        err = git_object_lookup(&object, repository, &oid, GIT_OBJ_ANY);
        if (err < 0)
            goto cleanup;
    } else {
        git_oid_fromstrn(&oid, CHAR(STRING_ELT(hex, 0)), len);
        err = git_object_lookup_prefix(&object, repository, &oid, len, GIT_OBJ_ANY);
        if (err < 0)
            goto cleanup;
    }

    switch (git_object_type(object)) {
    case GIT_OBJ_COMMIT:
        PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_commit")));
        git2r_commit_init((git_commit*)object, repo, result);
        break;
    case GIT_OBJ_TREE:
        PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_tree")));
        git2r_tree_init((git_tree*)object, repo, result);
        break;
    case GIT_OBJ_BLOB:
        PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_blob")));
        git2r_blob_init((git_blob*)object, repo, result);
        break;
    case GIT_OBJ_TAG:
        PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_tag")));
        git2r_tag_init((git_tag*)object, repo, result);
        break;
    default:
        error("Unimplemented");
    }

cleanup:
    if (object)
        git_object_free(object);

    if (repository)
        git_repository_free(repository);

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

    if (err < 0)
        error("Error: %s\n", giterr_last()->message);

    return result;
}
Ejemplo n.º 3
0
/**
 * Invoked 'callback' for each tag
 *
 * @param name The name of the tag
 * @param oid The id of the tag
 * @param payload Payload data passed to 'git_tag_foreach'
 * @return 0 on success, else error code
 */
static int git2r_tag_foreach_cb(const char *name, git_oid *oid, void *payload)
{
    int err = 0;
    git_object *object = NULL;
    git2r_tag_foreach_cb_data *cb_data = (git2r_tag_foreach_cb_data*)payload;

    /* Check if we have a list to populate */
    if (R_NilValue != cb_data->tags) {
        int skip = 0;
        SEXP item;

        err = git_object_lookup(&object, cb_data->repository, oid, GIT_OBJ_ANY);
        if (err)
            goto cleanup;

        switch (git_object_type(object)) {
        case GIT_OBJ_COMMIT:
            SET_VECTOR_ELT(
                cb_data->tags,
                cb_data->n,
                item = NEW_OBJECT(MAKE_CLASS("git_commit")));
            git2r_commit_init((git_commit*)object, cb_data->repo, item);
            break;
        case GIT_OBJ_TREE:
            SET_VECTOR_ELT(
                cb_data->tags,
                cb_data->n,
                item = NEW_OBJECT(MAKE_CLASS("git_tree")));
            git2r_tree_init((git_tree*)object, cb_data->repo, item);
            break;
        case GIT_OBJ_BLOB:
            SET_VECTOR_ELT(
                cb_data->tags,
                cb_data->n,
                item = NEW_OBJECT(MAKE_CLASS("git_blob")));
            git2r_blob_init((git_blob*)object, cb_data->repo, item);
            break;
        case GIT_OBJ_TAG:
            SET_VECTOR_ELT(
                cb_data->tags,
                cb_data->n,
                item = NEW_OBJECT(MAKE_CLASS("git_tag")));
            git2r_tag_init((git_tag*)object, cb_data->repo, item);
            break;
        default:
            git2r_error(__func__, NULL, git2r_err_object_type, NULL);
        }


        if (git__prefixcmp(name, "refs/tags/") == 0)
            skip = strlen("refs/tags/");
        SET_STRING_ELT(
            getAttrib(cb_data->tags, R_NamesSymbol),
            cb_data->n,
            mkChar(name + skip));

        if (object)
            git_object_free(object);
        object = NULL;
    }

    cb_data->n += 1;

cleanup:
    if (object)
        git_object_free(object);

    return err;
}
Ejemplo n.º 4
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;
}