static int retrieve_remote_tracking_reference(git_reference **base_ref, const char *identifier, git_repository *repo) { git_reference *tracking, *ref; int error = -1; if (*base_ref == NULL) { if ((error = git_reference_dwim(&ref, repo, identifier)) < 0) return error; } else { ref = *base_ref; *base_ref = NULL; } if (!git_reference_is_branch(ref)) { error = GIT_EINVALIDSPEC; goto cleanup; } if ((error = git_branch_upstream(&tracking, ref)) < 0) goto cleanup; *base_ref = tracking; cleanup: git_reference_free(ref); return error; }
static int retrieve_revobject_from_reflog(git_object **out, git_reference **base_ref, git_repository *repo, const char *identifier, size_t position) { git_reference *ref; git_oid oid; int error = -1; if (*base_ref == NULL) { if ((error = git_reference_dwim(&ref, repo, identifier)) < 0) return error; } else { ref = *base_ref; *base_ref = NULL; } if (position == 0) { error = git_object_lookup(out, repo, git_reference_target(ref), GIT_OBJ_ANY); goto cleanup; } if ((error = retrieve_oid_from_reflog(&oid, ref, position)) < 0) goto cleanup; error = git_object_lookup(out, repo, &oid, GIT_OBJ_ANY); cleanup: git_reference_free(ref); return error; }
//TODO: I think this leaks... const git_commit * commit_from_ref(const char * refname) { cl_assert(repo); git_reference * ref; git_reference_dwim(&ref, repo, refname); git_commit * retval; git_reference_peel( (git_object**)&retval, ref, GIT_OBJ_COMMIT); return retval; }
int luagi_reference_dwim( lua_State *L ) { git_repository **repo = checkrepo( L, 1 ); const char *shorthand = luaL_checkstring( L, 2 ); git_reference **out = lua_newuserdata( L, sizeof( git_reference * ) ); if( git_reference_dwim( out, *repo, shorthand ) ) { return ltk_push_git_error( L ); } ltk_setmetatable( L, LUAGI_REFERENCE_FUNCS ); return 1; }
int cmd_log(git_repository *repo, int argc, char **argv) { int err = 0; int rc; git_revwalk *walk; git_oid oid; git_reference *revision_ref = NULL; git_object *revision_obj = NULL; rc = EXIT_FAILURE; git_revwalk_new(&walk,repo); if (argc > 1) { if ((err = git_reference_dwim(&revision_ref, repo, argv[1]))) goto out; if ((err = git_reference_peel(&revision_obj, revision_ref, GIT_OBJ_ANY))) goto out; if ((err = git_revwalk_push(walk, git_object_id(revision_obj)))) goto out; } else { git_revwalk_push_head(walk); } while ((git_revwalk_next(&oid, walk)) == 0) { struct git_commit *wcommit; if (git_commit_lookup(&wcommit, repo, &oid) != 0) continue; print_commit(wcommit,"commit %C\nAuthor: %a\nDate: %d\n\n%m\n"); git_commit_free(wcommit); } git_revwalk_free(walk); rc = EXIT_SUCCESS; out: if (err != GIT_OK) libgit_error(); if (revision_obj) git_object_free(revision_obj); if (revision_ref) git_reference_free(revision_ref); return rc; }
static int revparse_lookup_object( git_object **object_out, git_reference **reference_out, git_repository *repo, const char *spec) { int error; git_reference *ref; if ((error = maybe_sha(object_out, repo, spec)) != GIT_ENOTFOUND) return error; error = git_reference_dwim(&ref, repo, spec); if (!error) { error = git_object_lookup( object_out, repo, git_reference_target(ref), GIT_OBJ_ANY); if (!error) *reference_out = ref; return error; } if (error != GIT_ENOTFOUND) return error; if ((strlen(spec) < GIT_OID_HEXSZ) && ((error = maybe_abbrev(object_out, repo, spec)) != GIT_ENOTFOUND)) return error; if ((error = maybe_describe(object_out, repo, spec)) != GIT_ENOTFOUND) return error; giterr_set(GITERR_REFERENCE, "revspec '%s' not found", spec); return GIT_ENOTFOUND; }
int cmd_push(git_repository *repo, int argc, char **argv) { int err = GIT_OK; int i; int rc = EXIT_FAILURE; git_strarray refs = {NULL, 0}; git_push_options push_options = GIT_PUSH_OPTIONS_INIT; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; char *ref_fullname = NULL; git_remote *r = NULL; for (i=1;i<argc;i++) { if (argv[i][0] == '-') { fprintf(stderr,"Unknown option \"%s\"\n",argv[i]); goto out; } if (r) { git_reference *ref; if (refs.count) { fprintf(stderr, "USAGE: %s <remote> <refspec>\n", argv[0]); goto out; } if (!git_reference_dwim(&ref, repo, argv[i])) { ref_fullname = strdup(git_reference_name(ref)); refs.strings = &ref_fullname; git_reference_free(ref); } else { refs.strings = &argv[i]; } refs.count = 1; } else { if ((err = git_remote_lookup(&r,repo,argv[i])) != GIT_OK) goto out; } } if (!r) { fprintf(stderr,"No remote given!\n"); goto out; } if (refs.count == 0) { git_strarray cfg_refs; if ((err = git_remote_get_push_refspecs(&cfg_refs, r))) goto out; if (!cfg_refs.count) { fprintf(stderr, "No refspec given and no refspec configured. " "Pushing is probably a noop.\n"); } git_strarray_free(&cfg_refs); } callbacks.credentials = cred_acquire_cb; callbacks.push_update_reference = push_update_reference_callback; callbacks.certificate_check = certificate_check; push_options.callbacks = callbacks; if ((err = git_remote_push(r, &refs, &push_options))) goto out; out: if (err != GIT_OK) libgit_error(); free(ref_fullname); if (r) git_remote_free(r); return rc; }
static int retrieve_previously_checked_out_branch_or_revision(git_object **out, git_reference **base_ref, git_repository *repo, const char *identifier, size_t position) { git_reference *ref = NULL; git_reflog *reflog = NULL; regex_t preg; int error = -1; size_t i, numentries, cur; const git_reflog_entry *entry; const char *msg; regmatch_t regexmatches[2]; git_buf buf = GIT_BUF_INIT; cur = position; if (*identifier != '\0' || *base_ref != NULL) return GIT_EINVALIDSPEC; if (build_regex(&preg, "checkout: moving from (.*) to .*") < 0) return -1; if (git_reference_lookup(&ref, repo, GIT_HEAD_FILE) < 0) goto cleanup; if (git_reflog_read(&reflog, repo, GIT_HEAD_FILE) < 0) goto cleanup; numentries = git_reflog_entrycount(reflog); for (i = 0; i < numentries; i++) { entry = git_reflog_entry_byindex(reflog, i); msg = git_reflog_entry_message(entry); if (!msg) continue; if (regexec(&preg, msg, 2, regexmatches, 0)) continue; cur--; if (cur > 0) continue; git_buf_put(&buf, msg+regexmatches[1].rm_so, regexmatches[1].rm_eo - regexmatches[1].rm_so); if ((error = git_reference_dwim(base_ref, repo, git_buf_cstr(&buf))) == 0) goto cleanup; if (error < 0 && error != GIT_ENOTFOUND) goto cleanup; error = maybe_abbrev(out, repo, git_buf_cstr(&buf)); goto cleanup; } error = GIT_ENOTFOUND; cleanup: git_reference_free(ref); git_buf_free(&buf); regfree(&preg); git_reflog_free(reflog); return error; }
int cmd_rebase(git_repository *repo, int argc, char **argv) { int err = GIT_OK; int rc = EXIT_FAILURE; git_signature *sig = NULL; const char *upstream_str; git_reference *upstream_ref = NULL; git_annotated_commit *upstream = NULL; git_reference *branch_ref = NULL; git_annotated_commit *branch = NULL; git_rebase *rebase = NULL; int abort = 0; int cont = 0; if (argc < 2) { fprintf(stderr, "USAGE: %s <upstream>\n", argv[0]); fprintf(stderr, "USAGE: %s --abort|--continue\n", argv[0]); goto out; } upstream_str = argv[1]; if (!strcmp(upstream_str, "--abort")) abort = 1; else if (!strcmp(upstream_str, "--continue")) cont = 1; if ((err = sgit_get_author_signature(repo, &sig))) goto out; if (abort) { if ((err = git_rebase_open(&rebase, repo))) goto out; if ((err = git_rebase_abort(rebase, sig))) goto out; } else { git_rebase_operation *oper; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_rebase_options rebase_opts = GIT_REBASE_OPTIONS_INIT; checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; if (cont) { if ((err = git_rebase_open(&rebase, repo))) goto out; } else { if ((err = git_reference_dwim(&upstream_ref, repo, upstream_str))) goto out; if ((err = git_annotated_commit_from_ref(&upstream, repo, upstream_ref))) goto out; if ((err = git_repository_head(&branch_ref,repo)) < 0) goto out; if ((err = git_annotated_commit_from_ref(&branch, repo, branch_ref))) goto out; if ((err = git_rebase_init(&rebase, repo, branch, upstream, NULL, NULL, NULL))) goto out; } while (!(err = git_rebase_next(&oper, rebase, &checkout_opts))) { git_oid oid; if ((err = git_rebase_commit(&oid, rebase, NULL, sig, NULL, NULL))) goto out; } if (err != GIT_ITEROVER && err != GIT_OK) goto out; if ((err = git_rebase_finish(rebase, sig, &rebase_opts))) goto out; } out: if (err != GIT_OK) libgit_error(); if (rebase) git_rebase_free(rebase); if (upstream) git_annotated_commit_free(upstream); if (upstream_ref) git_reference_free(upstream_ref); if (branch) git_annotated_commit_free(branch); if (branch_ref) git_reference_free(branch_ref); if (sig) git_signature_free(sig); return rc; }
int main() { git_libgit2_init(); git_repository* rep = nullptr; const git_annotated_commit* their_head[10]; git_merge_options merge_opt = GIT_MERGE_OPTIONS_INIT; git_checkout_options checkout_opt = GIT_CHECKOUT_OPTIONS_INIT; git_reference* branch = nullptr; git_index* index = nullptr; git_index_conflict_iterator* conflict_iterator = nullptr; git_oid new_tree_id; git_tree* new_tree = nullptr; git_signature* me = nullptr; git_reference* head = nullptr; git_commit* parent_our = nullptr; git_commit* parent_their = nullptr; git_oid commit_id; int error = 0; // git open error = git_repository_open(&rep, path); if (error < 0) { const git_error *e = giterr_last(); std::cout << "Error: " << error << " / " << e->klass << " : " << e->message << std::endl; goto SHUTDOWN; } // git merge <branch> git_reference_dwim(&branch, rep, "new"); git_annotated_commit_from_ref((git_annotated_commit **)&their_head[0], rep, branch); error = git_merge(rep, their_head, 1, &merge_opt, &checkout_opt); if (error < 0) { const git_error *e = giterr_last(); std::cout << "Error: " << error << " / " << e->klass << " : " << e->message << std::endl; goto SHUTDOWN; } git_repository_index(&index, rep); // reslove conflicts if (git_index_has_conflicts(index)) { const git_index_entry* ancestor_out = nullptr; const git_index_entry* our_out = nullptr; const git_index_entry* their_out = nullptr; git_index_conflict_iterator_new(&conflict_iterator, index); while (git_index_conflict_next(&ancestor_out, &our_out, &their_out, conflict_iterator) != GIT_ITEROVER) { if (ancestor_out) std::cout<< "ancestor: " << ancestor_out->path <<std::endl; if (our_out) std::cout<< "our: " << our_out->path <<std::endl; if (their_out) std::cout<< "their: " << their_out->path <<std::endl; // do sth. or rewrite file by code. ... // and remove the conflict // git_index_conflict_remove(index, "..."); } // git checkout --theirs <file> git_checkout_options opt = GIT_CHECKOUT_OPTIONS_INIT; opt.checkout_strategy |= GIT_CHECKOUT_USE_THEIRS; // const char* p = "file"; // opt.paths.strings = (char**)&p; // opt.paths.count = 1; git_checkout_index(rep, index, &opt); git_index_conflict_iterator_free(conflict_iterator); } // add and commit git_index_update_all(index, nullptr, nullptr, nullptr); git_index_write(index); git_index_write_tree(&new_tree_id, index); git_tree_lookup(&new_tree, rep, &new_tree_id); git_signature_now(&me, "XiaochenFTX", "*****@*****.**"); git_repository_head(&head, rep); git_commit_lookup(&parent_our, rep, git_reference_target(head)); git_commit_lookup(&parent_their, rep, git_reference_target(branch)); git_commit_create_v(&commit_id, rep, "HEAD", me, me, "UTF-8", "merge commit", new_tree, 2, parent_our, parent_their); git_repository_state_cleanup(rep); SHUTDOWN: git_repository_free(rep); git_libgit2_shutdown(); return 0; }