int luagi_reference_create_matching( lua_State *L ) { git_repository **repo = checkrepo( L, 1 ); const char *name = luaL_checkstring( L, 2 ); if( git_reference_is_valid_name( name ) == 0 ) { luaL_error( L, "invalid name" ); return 0; } git_oid oid; if( luagi_check_oid( &oid, L, 3 ) ) { ltk_error_abort( L ); } git_oid curr_oid; if( luagi_check_oid( &curr_oid, L, 4 ) ) { ltk_error_abort( L ); } const char *log_message = luaL_checkstring( L, 6 ); int force = lua_toboolean( L, 7 ); git_reference **out = lua_newuserdata( L, sizeof( git_reference *) ); if( git_reference_create_matching( out, *repo, name, &oid, force, &curr_oid, log_message ) ) { return ltk_push_git_error( L ); } ltk_setmetatable( L, LUAGI_REFERENCE_FUNCS ); return 1; }
int git_reference_create( git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id, int force, const char *log_message) { return git_reference_create_matching(ref_out, repo, name, id, force, NULL, log_message); }
int git_rebase_finish( git_rebase *rebase, const git_signature *signature, const git_rebase_options *given_opts) { git_rebase_options opts; git_reference *terminal_ref = NULL, *branch_ref = NULL, *head_ref = NULL; git_commit *terminal_commit = NULL; git_buf branch_msg = GIT_BUF_INIT, head_msg = GIT_BUF_INIT; char onto[GIT_OID_HEXSZ]; int error; assert(rebase); GITERR_CHECK_VERSION(given_opts, GIT_REBASE_OPTIONS_VERSION, "git_rebase_options"); if ((error = rebase_normalize_opts(rebase->repo, &opts, given_opts)) < 0) goto done; git_oid_fmt(onto, &rebase->onto_id); if ((error = git_buf_printf(&branch_msg, "rebase finished: %s onto %.*s", rebase->orig_head_name, GIT_OID_HEXSZ, onto)) < 0 || (error = git_buf_printf(&head_msg, "rebase finished: returning to %s", rebase->orig_head_name)) < 0 || (error = git_repository_head(&terminal_ref, rebase->repo)) < 0 || (error = git_reference_peel((git_object **)&terminal_commit, terminal_ref, GIT_OBJ_COMMIT)) < 0 || (error = git_reference_create_matching(&branch_ref, rebase->repo, rebase->orig_head_name, git_commit_id(terminal_commit), 1, &rebase->orig_head_id, branch_msg.ptr)) < 0 || (error = git_reference_symbolic_create(&head_ref, rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1, head_msg.ptr)) < 0 || (error = rebase_copy_notes(rebase, signature, &opts)) < 0) goto done; error = rebase_cleanup(rebase); done: git_buf_free(&head_msg); git_buf_free(&branch_msg); git_commit_free(terminal_commit); git_reference_free(head_ref); git_reference_free(branch_ref); git_reference_free(terminal_ref); rebase_opts_free(&opts); return error; }
int git_reference_set_target( git_reference **out, git_reference *ref, const git_oid *id, const char *log_message) { int error; git_repository *repo; assert(out && ref && id); repo = ref->db->repo; if ((error = ensure_is_an_updatable_direct_reference(ref)) < 0) return error; return git_reference_create_matching(out, repo, ref->name, id, 1, &ref->target.oid, log_message); }
static int return_to_orig_head(git_rebase *rebase) { git_reference *terminal_ref = NULL, *branch_ref = NULL, *head_ref = NULL; git_commit *terminal_commit = NULL; git_buf branch_msg = GIT_BUF_INIT, head_msg = GIT_BUF_INIT; char onto[GIT_OID_HEXSZ]; int error = 0; git_oid_fmt(onto, &rebase->onto_id); if ((error = git_buf_printf(&branch_msg, "rebase finished: %s onto %.*s", rebase->orig_head_name, GIT_OID_HEXSZ, onto)) == 0 && (error = git_buf_printf(&head_msg, "rebase finished: returning to %s", rebase->orig_head_name)) == 0 && (error = git_repository_head(&terminal_ref, rebase->repo)) == 0 && (error = git_reference_peel((git_object **)&terminal_commit, terminal_ref, GIT_OBJ_COMMIT)) == 0 && (error = git_reference_create_matching(&branch_ref, rebase->repo, rebase->orig_head_name, git_commit_id(terminal_commit), 1, &rebase->orig_head_id, branch_msg.ptr)) == 0) error = git_reference_symbolic_create(&head_ref, rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1, head_msg.ptr); git_buf_free(&head_msg); git_buf_free(&branch_msg); git_commit_free(terminal_commit); git_reference_free(head_ref); git_reference_free(branch_ref); git_reference_free(terminal_ref); return error; }
void test_core_merge__demo_create_merge_commit(void) { AGBError * error; agb_error_new(&error); // Here we're going to try to use the merge iterator to create a merge commit that contains the right information. // Note - this version does not recurse into directories. (subtrees) git_treebuilder * builder; git_treebuilder_create(&builder, base_tree); AGBMergeIterator * it = agb_merge__create_iterator(head_tree, branch_tree, base_tree, agb_merge_iterator_options_NONE); for( ; agb_merge_iterator_is_valid(it) ; agb_merge_iterator_next(it) ) { AGBMergeEntry * entry = agb_merge_entry_from_iterator(it); int hasLocalChanged = !agb_git_oid_equal( agb_merge_entry_id(entry,AGB_MERGE_BASE), agb_merge_entry_id(entry,AGB_MERGE_LOCAL) ); int hasRemoteChanged = !agb_git_oid_equal( agb_merge_entry_id(entry,AGB_MERGE_BASE), agb_merge_entry_id(entry,AGB_MERGE_REMOTE) ); printf("-- %s %d %d\n", agb_merge_entry_name(entry), hasLocalChanged, hasRemoteChanged); if( !hasLocalChanged && !hasRemoteChanged) { continue; } if( hasLocalChanged && !hasRemoteChanged) { //We want the head version. if(agb_merge_entry_id(entry,AGB_MERGE_LOCAL) == NULL) { //TODO: Check error message. printf("REMOVING %s from tree\n", agb_merge_entry_name(entry) ); git_treebuilder_remove(builder, agb_merge_entry_name(entry) ); continue; } //TODO: Check for error printf("ADDING OR UPDATING %s to tree\n", agb_merge_entry_name(entry) ); int ok = git_treebuilder_insert(NULL, builder, agb_merge_entry_name(entry), agb_merge_entry_id(entry,AGB_MERGE_LOCAL), agb_merge_entry_filemode(entry,AGB_MERGE_LOCAL) ); if(ok!=0) { printf("Error duting add/update of tree builder: %s\n", giterr_last()->message); abort(); } continue; } if( !hasLocalChanged && hasRemoteChanged) { //We want the head version. if(agb_merge_entry_id(entry,AGB_MERGE_REMOTE) == NULL) { //TODO: Check error message. printf("REMOVING %s from tree\n", agb_merge_entry_name(entry) ); git_treebuilder_remove(builder, agb_merge_entry_name(entry) ); continue; } //TODO: Check for error printf("ADDING OR UPDATING %s to tree\n", agb_merge_entry_name(entry) ); int ok = git_treebuilder_insert(NULL, builder, agb_merge_entry_name(entry), agb_merge_entry_id(entry,AGB_MERGE_REMOTE), agb_merge_entry_filemode(entry,AGB_MERGE_REMOTE) ); if(ok!=0) { printf("Error duting add/update of tree builder: %s\n", giterr_last()->message); abort(); } continue; } printf("CONFLICT %s in tree\n", agb_merge_entry_name(entry) ); //TODO: CONFLICT - Handle it! } // Our tree builder should now be full... // Lets write it out to a tree // //TODO: Check for errors git_oid new_tree_oid = {}; git_treebuilder_write(&new_tree_oid, repo, builder); char hexid[GIT_OID_HEXSZ+1]; printf("Tree SHA is %s\n", git_oid_tostr(hexid,GIT_OID_HEXSZ+1, &new_tree_oid)); git_tree * new_tree = NULL; git_tree_lookup(&new_tree, repo, &new_tree_oid); // Now we need to create the commit. const git_commit** parents = (const git_commit**)malloc(sizeof(git_commit*)*2); parents[0] = head_commit; parents[1] = branch_commit; git_signature * author_signature = NULL; // Time since epoch // TODO: Get these correctly - // Could use git_signature_now instead... { git_time_t author_time = time(NULL); int timezone_offset = 0; int ok; if((ok=git_signature_new(&author_signature,"Someone","*****@*****.**", author_time, timezone_offset))!=0) { agb__error_translate(error,"git_signature_new failed",ok); goto cleanup_error; } } git_oid commit_id; int ok = git_commit_create( &commit_id, repo, NULL, author_signature, author_signature, "UTF-8", "An exciting commit", new_tree, 2, //Two parents parents ); if(ok!=0) { agb__error_translate(error,"git_commit_create failed",ok); goto cleanup_error; } // Then update the refs. //TODO: Do we need to release this ref? git_reference * ref; ok = git_reference_create_matching( &ref, repo, "refs/heads/branch_c", &commit_id, 1, NULL, author_signature, "merged by libagb"); if(ok!=0) { agb__error_translate(error,"git_reference_create failed",ok); goto cleanup_error; } git_signature_free(author_signature); // Now check we got the expected files cl_assert_equal_c('A', test_core_merge__compare_with_parents_merge_base("branch_c", "created_in_a.txt")); cl_assert_equal_c('A', test_core_merge__compare_with_parents_merge_base("branch_c", "created_in_b.txt")); return; cleanup_error: printf("ERROR: %s\n",error->message); if(author_signature) { git_signature_free(author_signature); } cl_fail(error->message); }