static int refspec_transform( git_buf *out, const char *from, const char *to, const char *name) { size_t to_len = to ? strlen(to) : 0; size_t from_len = from ? strlen(from) : 0; size_t name_len = name ? strlen(name) : 0; git_buf_sanitize(out); if (git_buf_set(out, to, to_len) < 0) return -1; if (to_len > 0) { /* No '*' at the end of 'to' means that refspec is mapped to one * specific branch, so no actual transformation is needed. */ if (out->ptr[to_len - 1] != '*') return 0; git_buf_shorten(out, 1); /* remove trailing '*' copied from 'to' */ } if (from_len > 0) /* ignore trailing '*' from 'from' */ from_len--; if (from_len > name_len) from_len = name_len; return git_buf_put(out, name + from_len, name_len - from_len); }
void test_clone_local__should_clone_local(void) { git_buf buf = GIT_BUF_INIT; /* we use a fixture path because it needs to exist for us to want to clone */ const char *path = cl_fixture("testrepo.git"); cl_git_pass(file_url(&buf, "", path)); cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_AUTO)); cl_assert_equal_i(1, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL)); cl_assert_equal_i(1, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_NO_LINKS)); cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_NO_LOCAL)); cl_git_pass(file_url(&buf, "localhost", path)); cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_AUTO)); cl_assert_equal_i(1, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL)); cl_assert_equal_i(1, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_NO_LINKS)); cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_NO_LOCAL)); cl_git_pass(file_url(&buf, "other-host.mycompany.com", path)); cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_AUTO)); cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL)); cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_NO_LINKS)); cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_NO_LOCAL)); /* Ensure that file:/// urls are percent decoded: .git == %2e%67%69%74 */ cl_git_pass(file_url(&buf, "", path)); git_buf_shorten(&buf, 4); cl_git_pass(git_buf_puts(&buf, "%2e%67%69%74")); cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_AUTO)); cl_assert_equal_i(1, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL)); cl_assert_equal_i(1, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_NO_LINKS)); cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_NO_LOCAL)); cl_assert_equal_i(1, git_clone__should_clone_local(path, GIT_CLONE_LOCAL_AUTO)); cl_assert_equal_i(1, git_clone__should_clone_local(path, GIT_CLONE_LOCAL)); cl_assert_equal_i(1, git_clone__should_clone_local(path, GIT_CLONE_LOCAL_NO_LINKS)); cl_assert_equal_i(0, git_clone__should_clone_local(path, GIT_CLONE_NO_LOCAL)); git_buf_free(&buf); }
int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) { git_mwindow *w = NULL; unsigned int i, long_offsets = 0, left; int error; struct git_pack_idx_header hdr; git_buf filename = GIT_BUF_INIT; struct entry *entry; git_oid trailer_hash, file_hash; git_hash_ctx ctx; git_filebuf index_file = {0}; void *packfile_trailer; if (git_hash_ctx_init(&ctx) < 0) return -1; /* Test for this before resolve_deltas(), as it plays with idx->off */ if (idx->off < idx->pack->mwf.size - 20) { giterr_set(GITERR_INDEXER, "Unexpected data at the end of the pack"); return -1; } packfile_trailer = git_mwindow_open(&idx->pack->mwf, &w, idx->pack->mwf.size - GIT_OID_RAWSZ, GIT_OID_RAWSZ, &left); if (packfile_trailer == NULL) { git_mwindow_close(&w); goto on_error; } /* Compare the packfile trailer as it was sent to us and what we calculated */ git_oid_fromraw(&file_hash, (unsigned char*) packfile_trailer); git_mwindow_close(&w); git_hash_final(&trailer_hash, &idx->trailer); if (git_oid_cmp(&file_hash, &trailer_hash)) { giterr_set(GITERR_INDEXER, "packfile trailer mismatch"); return -1; } /* Freeze the number of deltas */ stats->total_deltas = stats->total_objects - stats->indexed_objects; if ((error = resolve_deltas(idx, stats)) < 0) return error; if (stats->indexed_objects != stats->total_objects) { giterr_set(GITERR_INDEXER, "early EOF"); return -1; } if (stats->local_objects > 0) { if (update_header_and_rehash(idx, stats) < 0) return -1; git_hash_final(&trailer_hash, &idx->trailer); write_at(idx, &trailer_hash, idx->pack->mwf.size - GIT_OID_RAWSZ, GIT_OID_RAWSZ); } git_vector_sort(&idx->objects); git_buf_sets(&filename, idx->pack->pack_name); git_buf_shorten(&filename, strlen("pack")); git_buf_puts(&filename, "idx"); if (git_buf_oom(&filename)) return -1; if (git_filebuf_open(&index_file, filename.ptr, GIT_FILEBUF_HASH_CONTENTS, idx->mode) < 0) goto on_error; /* Write out the header */ hdr.idx_signature = htonl(PACK_IDX_SIGNATURE); hdr.idx_version = htonl(2); git_filebuf_write(&index_file, &hdr, sizeof(hdr)); /* Write out the fanout table */ for (i = 0; i < 256; ++i) { uint32_t n = htonl(idx->fanout[i]); git_filebuf_write(&index_file, &n, sizeof(n)); } /* Write out the object names (SHA-1 hashes) */ git_vector_foreach(&idx->objects, i, entry, struct entry*) { git_filebuf_write(&index_file, &entry->oid, sizeof(git_oid)); git_hash_update(&ctx, &entry->oid, GIT_OID_RAWSZ); } git_hash_final(&idx->hash, &ctx); /* Write out the CRC32 values */ git_vector_foreach(&idx->objects, i, entry, struct entry*) { git_filebuf_write(&index_file, &entry->crc, sizeof(uint32_t)); } /* Write out the offsets */ git_vector_foreach(&idx->objects, i, entry, struct entry*) { uint32_t n; if (entry->offset == UINT32_MAX) n = htonl(0x80000000 | long_offsets++); else n = htonl(entry->offset); git_filebuf_write(&index_file, &n, sizeof(uint32_t)); } /* Write out the long offsets */ git_vector_foreach(&idx->objects, i, entry, struct entry*) { uint32_t split[2]; if (entry->offset != UINT32_MAX) continue; split[0] = htonl(entry->offset_long >> 32); split[1] = htonl(entry->offset_long & 0xffffffff); git_filebuf_write(&index_file, &split, sizeof(uint32_t) * 2); } /* Write out the packfile trailer to the index */ if (git_filebuf_write(&index_file, &trailer_hash, GIT_OID_RAWSZ) < 0) goto on_error; /* Write out the hash of the idx */ if (git_filebuf_hash(&trailer_hash, &index_file) < 0) goto on_error; git_filebuf_write(&index_file, &trailer_hash, sizeof(git_oid)); /* Figure out what the final name should be */ if (index_path(&filename, idx, ".idx") < 0) goto on_error; /* Commit file */ if (git_filebuf_commit_at(&index_file, filename.ptr) < 0) goto on_error; git_mwindow_free_all(&idx->pack->mwf); /* We need to close the descriptor here so Windows doesn't choke on commit_at */ if (p_close(idx->pack->mwf.fd) < 0) { giterr_set(GITERR_OS, "failed to close packfile"); goto on_error; } idx->pack->mwf.fd = -1; if (index_path(&filename, idx, ".pack") < 0) goto on_error; /* And don't forget to rename the packfile to its new place. */ p_rename(idx->pack->pack_name, git_buf_cstr(&filename)); git_buf_free(&filename); git_hash_ctx_cleanup(&ctx); return 0; on_error: git_mwindow_free_all(&idx->pack->mwf); git_filebuf_cleanup(&index_file); git_buf_free(&filename); git_hash_ctx_cleanup(&ctx); return -1; }