/** * Remove the note for an object * * @param note S4 class git_note * @param author Signature of the notes commit author * @param committer Signature of the notes commit committer * @return R_NilValue */ SEXP git2r_note_remove(SEXP note, SEXP author, SEXP committer) { int err; SEXP repo; SEXP annotated; git_oid note_oid; git_signature *sig_author = NULL; git_signature *sig_committer = NULL; git_repository *repository = NULL; if (git2r_arg_check_note(note)) git2r_error(git2r_err_note_arg, __func__, "note"); if (git2r_arg_check_signature(author)) git2r_error(git2r_err_signature_arg, __func__, "author"); if (git2r_arg_check_signature(committer)) git2r_error(git2r_err_signature_arg, __func__, "committer"); repo = GET_SLOT(note, Rf_install("repo")); repository = git2r_repository_open(repo); if (!repository) git2r_error(git2r_err_invalid_repository, __func__, NULL); err = git2r_signature_from_arg(&sig_author, author); if (GIT_OK != err) goto cleanup; err = git2r_signature_from_arg(&sig_committer, committer); if (GIT_OK != err) goto cleanup; annotated = GET_SLOT(note, Rf_install("annotated")); err = git_oid_fromstr(¬e_oid, CHAR(STRING_ELT(annotated, 0))); if (GIT_OK != err) goto cleanup; err = git_note_remove( repository, CHAR(STRING_ELT(GET_SLOT(note, Rf_install("refname")), 0)), sig_author, sig_committer, ¬e_oid); cleanup: if (sig_author) git_signature_free(sig_author); if (sig_committer) git_signature_free(sig_committer); if (repository) git_repository_free(repository); if (GIT_OK != err) git2r_error(git2r_err_from_libgit2, __func__, giterr_last()->message); return R_NilValue; }
/** * 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; }
/** * 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; }
/** * Stash * * @param repo The repository * @param message Optional description * @param index All changes already added to the index are left * intact in the working directory. Default is FALSE * @param untracked All untracked files are also stashed and then * cleaned up from the working directory. Default is FALSE * @param ignored All ignored files are also stashed and then cleaned * up from the working directory. Default is FALSE * @param stasher Signature with stasher and time of stash * @return S3 class git_stash */ SEXP git2r_stash_save( SEXP repo, SEXP message, SEXP index, SEXP untracked, SEXP ignored, SEXP stasher) { int error, nprotect = 0; SEXP result = R_NilValue, class; git_oid oid; git_stash_flags flags = GIT_STASH_DEFAULT; git_commit *commit = NULL; git_repository *repository = NULL; git_signature *c_stasher = NULL; if (git2r_arg_check_logical(index)) git2r_error(__func__, NULL, "'index'", git2r_err_logical_arg); if (git2r_arg_check_logical(untracked)) git2r_error(__func__, NULL, "'untracked'", git2r_err_logical_arg); if (git2r_arg_check_logical(ignored)) git2r_error(__func__, NULL, "'ignored'", git2r_err_logical_arg); if (git2r_arg_check_signature(stasher)) git2r_error(__func__, NULL, "'stasher'", git2r_err_signature_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); if (LOGICAL(index)[0]) flags |= GIT_STASH_KEEP_INDEX; if (LOGICAL(untracked)[0]) flags |= GIT_STASH_INCLUDE_UNTRACKED; if (LOGICAL(ignored)[0]) flags |= GIT_STASH_INCLUDE_IGNORED; error = git2r_signature_from_arg(&c_stasher, stasher); if (error) goto cleanup; error = git_stash_save( &oid, repository, c_stasher, CHAR(STRING_ELT(message, 0)), flags); if (error) { if (GIT_ENOTFOUND == error) error = GIT_OK; goto cleanup; } PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_commit)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, class = Rf_allocVector(STRSXP, 2)); SET_STRING_ELT(class, 0, Rf_mkChar("git_stash")); SET_STRING_ELT(class, 1, Rf_mkChar("git_commit")); error = git2r_stash_init(&oid, repository, repo, result); cleanup: git_commit_free(commit); git_signature_free(c_stasher); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, GIT2R_ERROR_LAST(), NULL, NULL); return result; }
/** * Create tag targeting HEAD commit in repository. * * @param repo S4 class git_repository * @param name Name for the tag. * @param message The tag message. * @param tagger The tagger (author) of the tag * @return S4 object of class git_tag */ SEXP git2r_tag_create(SEXP repo, SEXP name, SEXP message, SEXP tagger) { SEXP result = R_NilValue; int err; git_oid oid; git_repository *repository = NULL; git_signature *sig_tagger = NULL; git_tag *tag = NULL; git_object *target = NULL; if (git2r_arg_check_string(name)) git2r_error(__func__, NULL, "'name'", git2r_err_string_arg); if (git2r_arg_check_string(message)) git2r_error(__func__, NULL, "'message'", git2r_err_string_arg); if (git2r_arg_check_signature(tagger)) git2r_error(__func__, NULL, "'tagger'", git2r_err_signature_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); err = git2r_signature_from_arg(&sig_tagger, tagger); if (err) goto cleanup; err = git_revparse_single(&target, repository, "HEAD^{commit}"); if (err) goto cleanup; err = git_tag_create( &oid, repository, CHAR(STRING_ELT(name, 0)), target, sig_tagger, CHAR(STRING_ELT(message, 0)), 0); if (err) goto cleanup; err = git_tag_lookup(&tag, repository, &oid); if (err) goto cleanup; PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_tag"))); git2r_tag_init(tag, repo, result); cleanup: if (tag) git_tag_free(tag); if (sig_tagger) git_signature_free(sig_tagger); if (target) git_object_free(target); if (repository) git_repository_free(repository); if (R_NilValue != result) UNPROTECT(1); if (err) git2r_error(__func__, giterr_last(), NULL, NULL); return result; }
/** * Commit * * @param repo S4 class git_repository * @param message The message for the commit * @param author S4 class git_signature * @param committer S4 class git_signature * @return S4 class git_commit */ SEXP git2r_commit( SEXP repo, SEXP message, SEXP author, SEXP committer) { int err; SEXP result = R_NilValue; git_signature *c_author = NULL; git_signature *c_committer = NULL; git_index *index = NULL; git_oid oid; git_repository *repository = NULL; git_commit *commit = NULL; if (git2r_arg_check_string(message)) git2r_error(git2r_err_string_arg, __func__, "message"); if (git2r_arg_check_signature(author)) git2r_error(git2r_err_signature_arg, __func__, "author"); if (git2r_arg_check_signature(committer)) git2r_error(git2r_err_signature_arg, __func__, "committer"); repository = git2r_repository_open(repo); if (!repository) git2r_error(git2r_err_invalid_repository, __func__, NULL); err = git2r_signature_from_arg(&c_author, author); if (GIT_OK != err) goto cleanup; err = git2r_signature_from_arg(&c_committer, committer); if (GIT_OK != err) goto cleanup; err = git2r_any_changes_in_index(repository); if (GIT_OK != err) goto cleanup; err = git_repository_index(&index, repository); if (GIT_OK != err) goto cleanup; err = git2r_commit_create( &oid, repository, index, CHAR(STRING_ELT(message, 0)), c_author, c_committer); if (GIT_OK != err) goto cleanup; err = git_commit_lookup(&commit, repository, &oid); if (GIT_OK != err) goto cleanup; PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_commit"))); git2r_commit_init(commit, repo, result); cleanup: if (c_author) git_signature_free(c_author); if (c_committer) git_signature_free(c_committer); if (index) git_index_free(index); if (repository) git_repository_free(repository); if (commit) git_commit_free(commit); if (R_NilValue != result) UNPROTECT(1); if (GIT_OK != err) git2r_error(git2r_err_from_libgit2, __func__, giterr_last()->message); return result; }
/** * Add a note for an object * * @param repo S4 class git_repository * @param sha The sha string of object * @param commit S4 class git_commit * @param message Content of the note to add * @param ref Canonical name of the reference to use * @param author Signature of the notes note author * @param committer Signature of the notes note committer * @param force Overwrite existing note * @return S4 class git_note */ SEXP git2r_note_create( SEXP repo, SEXP sha, SEXP message, SEXP ref, SEXP author, SEXP committer, SEXP force) { int err; SEXP result = R_NilValue; int overwrite = 0; git_oid note_oid; git_oid object_oid; git_signature *sig_author = NULL; git_signature *sig_committer = NULL; git_repository *repository = NULL; if (git2r_arg_check_sha(sha)) git2r_error(git2r_err_sha_arg, __func__, "sha"); if (git2r_arg_check_string(message)) git2r_error(git2r_err_string_arg, __func__, "message"); if (git2r_arg_check_string(ref)) git2r_error(git2r_err_string_arg, __func__, "ref"); if (git2r_arg_check_signature(author)) git2r_error(git2r_err_signature_arg, __func__, "author"); if (git2r_arg_check_signature(committer)) git2r_error(git2r_err_signature_arg, __func__, "committer"); if (git2r_arg_check_logical(force)) git2r_error(git2r_err_logical_arg, __func__, "force"); repository = git2r_repository_open(repo); if (!repository) git2r_error(git2r_err_invalid_repository, __func__, NULL); err = git2r_signature_from_arg(&sig_author, author); if (GIT_OK != err) goto cleanup; err = git2r_signature_from_arg(&sig_committer, committer); if (GIT_OK != err) goto cleanup; err = git_oid_fromstr(&object_oid, CHAR(STRING_ELT(sha, 0))); if (GIT_OK != err) goto cleanup; if (LOGICAL(force)[0]) overwrite = 1; err = git_note_create( ¬e_oid, repository, CHAR(STRING_ELT(ref, 0)), sig_author, sig_committer, &object_oid, CHAR(STRING_ELT(message, 0)), overwrite); if (GIT_OK != err) goto cleanup; PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_note"))); err = git2r_note_init(¬e_oid, &object_oid, repository, CHAR(STRING_ELT(ref, 0)), repo, result); cleanup: if (sig_author) git_signature_free(sig_author); if (sig_committer) git_signature_free(sig_committer); 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; }