int ssh_certificate_check(git_cert *cert, int valid, const char *host, void *payload) { git_cert_hostkey *key; git_oid expected = {{0}}, actual = {{0}}; GIT_UNUSED(valid); GIT_UNUSED(payload); cl_assert(_remote_ssh_fingerprint); cl_git_pass(git_oid_fromstrp(&expected, _remote_ssh_fingerprint)); cl_assert_equal_i(GIT_CERT_HOSTKEY_LIBSSH2, cert->cert_type); key = (git_cert_hostkey *) cert; /* * We need to figure out how long our input was to check for * the type. Here we abuse the fact that both hashes fit into * our git_oid type. */ if (strlen(_remote_ssh_fingerprint) == 32 && key->type & GIT_CERT_SSH_MD5) { memcpy(&actual.id, key->hash_md5, 16); } else if (strlen(_remote_ssh_fingerprint) == 40 && key->type & GIT_CERT_SSH_SHA1) { memcpy(&actual, key->hash_sha1, 20); } else { cl_fail("Cannot find a usable SSH hash"); } cl_assert(!memcmp(&expected, &actual, 20)); cl_assert_equal_s("localhost", host); return GIT_EUSER; }
static int note_list_create_cb( const git_oid *blob_oid, const git_oid *annotated_obj_id, void *payload) { git_oid expected_note_oid, expected_target_oid; struct note_create_payload *notes = payload; size_t i; for (i = 0; notes[i].note_oid != NULL; i++) { cl_git_pass(git_oid_fromstr(&expected_note_oid, notes[i].note_oid)); if (git_oid_cmp(&expected_note_oid, blob_oid) != 0) continue; cl_git_pass(git_oid_fromstr(&expected_target_oid, notes[i].object_oid)); if (git_oid_cmp(&expected_target_oid, annotated_obj_id) != 0) continue; notes[i].seen = 1; return 0; } cl_fail("Did not see expected note"); return 0; }
void verify_remote_refs(const git_remote_head *actual_refs[], size_t actual_refs_len, const expected_ref expected_refs[], size_t expected_refs_len) { size_t i, j = 0; git_buf msg = GIT_BUF_INIT; const git_remote_head *actual; char *oid_str; bool master_present = false; /* We don't care whether "master" is present on the other end or not */ for (i = 0; i < actual_refs_len; i++) { actual = actual_refs[i]; if (!strcmp(actual->name, "refs/heads/master")) { master_present = true; break; } } if (expected_refs_len + (master_present ? 1 : 0) != actual_refs_len) goto failed; for (i = 0; i < actual_refs_len; i++) { actual = actual_refs[i]; if (master_present && !strcmp(actual->name, "refs/heads/master")) continue; if (strcmp(expected_refs[j].name, actual->name) || git_oid_cmp(expected_refs[j].oid, &actual->oid)) goto failed; j++; } return; failed: git_buf_puts(&msg, "Expected and actual refs differ:\nEXPECTED:\n"); for(i = 0; i < expected_refs_len; i++) { cl_assert(oid_str = git_oid_allocfmt(expected_refs[i].oid)); cl_git_pass(git_buf_printf(&msg, "%s = %s\n", expected_refs[i].name, oid_str)); git__free(oid_str); } git_buf_puts(&msg, "\nACTUAL:\n"); for (i = 0; i < actual_refs_len; i++) { actual = actual_refs[i]; if (master_present && !strcmp(actual->name, "refs/heads/master")) continue; cl_assert(oid_str = git_oid_allocfmt(&actual->oid)); cl_git_pass(git_buf_printf(&msg, "%s = %s\n", actual->name, oid_str)); git__free(oid_str); } cl_fail(git_buf_cstr(&msg)); git_buf_free(&msg); }
static void assert_branch_list_contains(git_strarray *branches, const char* expected_branch_name) { unsigned int i; for (i = 0; i < branches->count; i++) { if (strcmp(expected_branch_name, branches->strings[i]) == 0) return; } cl_fail("expected branch not found in list."); }
static int hunk_cb( const git_diff_delta *delta, const git_diff_hunk *hunk, void *payload) { GIT_UNUSED(delta); GIT_UNUSED(hunk); GIT_UNUSED(payload); cl_fail("did not expect hunk callback"); return 0; }
static int cb_status__expected_path(const char *p, unsigned int s, void *payload) { const char *expected_path = (const char *)payload; GIT_UNUSED(s); if (payload == NULL) cl_fail("Unexpected path"); cl_assert_equal_s(expected_path, p); return 0; }
static void assert_branch_has_been_found(struct expectations *findings, const char* expected_branch_name) { int pos = 0; for (pos = 0; findings[pos].branch_name; ++pos) { if (strcmp(expected_branch_name, findings[pos].branch_name) == 0) { cl_assert_equal_i(1, findings[pos].encounters); return; } } cl_fail("expected branch not found in list."); }
static void do_verify_push_status(record_callbacks_data *data, const push_status expected[], const size_t expected_len) { git_vector *actual = &data->statuses; push_status *iter; bool failed = false; size_t i; if (expected_len != actual->length) failed = true; else git_vector_foreach(actual, i, iter) if (strcmp(expected[i].ref, iter->ref) || (expected[i].success != iter->success) || (expected[i].msg && (!iter->msg || strcmp(expected[i].msg, iter->msg)))) { failed = true; break; } if (failed) { git_buf msg = GIT_BUF_INIT; git_buf_puts(&msg, "Expected and actual push statuses differ:\nEXPECTED:\n"); for(i = 0; i < expected_len; i++) { git_buf_printf(&msg, "%s: %s\n", expected[i].ref, expected[i].success ? "success" : "failed"); } git_buf_puts(&msg, "\nACTUAL:\n"); git_vector_foreach(actual, i, iter) { if (iter->success) git_buf_printf(&msg, "%s: success\n", iter->ref); else git_buf_printf(&msg, "%s: failed with message: %s", iter->ref, iter->msg); } cl_fail(git_buf_cstr(&msg)); git_buf_dispose(&msg); } git_vector_foreach(actual, i, iter) { push_status *s = (push_status *)iter; git__free(s->ref); git__free(s->msg); git__free(s); }
static int wildcard_filter_apply( git_filter *self, void **payload, git_buf *to, const git_buf *from, const git_filter_source *source) { const char *filtername = *payload; if (filtername && strcmp(filtername, "wcflip") == 0) return bitflip_filter_apply(self, payload, to, from, source); else if (filtername && strcmp(filtername, "wcreverse") == 0) return reverse_filter_apply(self, payload, to, from, source); cl_fail("Unexpected attribute"); return GIT_PASSTHROUGH; }
void test_index_racy__empty_file_after_smudge(void) { git_index *index; git_diff *diff; git_buf path = GIT_BUF_INIT; int i, found_race = 0; const git_index_entry *entry; /* Make sure we do have a timestamp */ cl_git_pass(git_repository_index(&index, g_repo)); cl_git_pass(git_index_write(index)); cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "A")); /* Make sure writing the file, adding and rewriting happen in the same second */ for (i = 0; i < 10; i++) { struct stat st; cl_git_mkfile(path.ptr, "A"); cl_git_pass(git_index_add_bypath(index, "A")); cl_git_mkfile(path.ptr, "B"); cl_git_pass(git_index_write(index)); cl_git_mkfile(path.ptr, ""); cl_git_pass(p_stat(path.ptr, &st)); cl_assert(entry = git_index_get_bypath(index, "A", 0)); if (entry->mtime.seconds == (int32_t) st.st_mtime) { found_race = 1; break; } } if (!found_race) cl_fail("failed to find race after 10 attempts"); cl_assert_equal_i(0, entry->file_size); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, NULL)); cl_assert_equal_i(1, git_diff_num_deltas(diff)); }
char test_core_merge__compare_with_parents_merge_base(const char * commit_id, const char * filename) { char * cmd; int readfd; asprintf(&cmd,"(cd " REPODIR " ; git diff --name-status $(git merge-base $(git show --pretty=format:%%p %s))..%s | ( grep '\\<%s\\>' || true ) )", commit_id, commit_id, filename); if(g_debug) printf("repo_contains: running %s\n", cmd); pid_t pid = popen3(cmd, NULL, &readfd, NULL); char result=0; ssize_t bytes_read = read(readfd,&result,1); int status=0; waitpid(pid,&status,0); free(cmd); if(!WIFEXITED(status) || WEXITSTATUS(status)!=0 ) { cl_fail("git diff failed"); } if( bytes_read==0 ) return 0; return result; }
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); }