static void assert_config_entry_on_init_bytype(const char *config_key, int expected_value, bool is_bare) { git_config *config; int current_value; git_buf repo_path = GIT_BUF_INIT; cl_set_cleanup(&cleanup_repository, "config_entry"); cl_git_pass(git_buf_puts(&repo_path, "config_entry/test.")); if (!is_bare) cl_git_pass(git_buf_puts(&repo_path, "non.")); cl_git_pass(git_buf_puts(&repo_path, "bare.git")); cl_git_pass(git_repository_init(&_repo, git_buf_cstr(&repo_path), is_bare)); git_buf_free(&repo_path); git_repository_config(&config, _repo); if (expected_value >= 0) { cl_git_pass(git_config_get_bool(¤t_value, config, config_key)); cl_assert_equal_i(expected_value, current_value); } else { int error = git_config_get_bool(¤t_value, config, config_key); cl_assert_equal_i(expected_value, error); } git_config_free(config); }
static int buffer_want_with_caps(git_remote_head *head, git_transport_caps *caps, git_buf *buf) { git_buf str = GIT_BUF_INIT; char oid[GIT_OID_HEXSZ +1] = {0}; unsigned int len; if (caps->ofs_delta) git_buf_puts(&str, GIT_CAP_OFS_DELTA " "); if (caps->multi_ack) git_buf_puts(&str, GIT_CAP_MULTI_ACK " "); if (git_buf_oom(&str)) return -1; len = (unsigned int) (strlen("XXXXwant ") + GIT_OID_HEXSZ + 1 /* NUL */ + git_buf_len(&str) + 1 /* LF */); git_buf_grow(buf, git_buf_len(buf) + len); git_oid_fmt(oid, &head->oid); git_buf_printf(buf, "%04xwant %s %s\n", len, oid, git_buf_cstr(&str)); git_buf_free(&str); return git_buf_oom(buf); }
static int gen_request(git_buf *buf, const char *path, const char *host, const char *op, const char *service, ssize_t content_length, int ls) { if (path == NULL) /* Is 'git fetch http://host.com/' valid? */ path = "/"; if (ls) { git_buf_printf(buf, "%s %s/info/refs?service=git-%s HTTP/1.1\r\n", op, path, service); } else { git_buf_printf(buf, "%s %s/git-%s HTTP/1.1\r\n", op, path, service); } git_buf_puts(buf, "User-Agent: git/1.0 (libgit2 " LIBGIT2_VERSION ")\r\n"); git_buf_printf(buf, "Host: %s\r\n", host); if (content_length > 0) { git_buf_printf(buf, "Accept: application/x-git-%s-result\r\n", service); git_buf_printf(buf, "Content-Type: application/x-git-%s-request\r\n", service); git_buf_printf(buf, "Content-Length: %"PRIuZ "\r\n", content_length); } else { git_buf_puts(buf, "Accept: */*\r\n"); } git_buf_puts(buf, "\r\n"); if (git_buf_oom(buf)) return -1; return 0; }
int git_reference_dwim(git_reference **out, git_repository *repo, const char *refname) { int error = 0, i; bool fallbackmode = true, foundvalid = false; git_reference *ref; git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT; static const char* formatters[] = { "%s", GIT_REFS_DIR "%s", GIT_REFS_TAGS_DIR "%s", GIT_REFS_HEADS_DIR "%s", GIT_REFS_REMOTES_DIR "%s", GIT_REFS_REMOTES_DIR "%s/" GIT_HEAD_FILE, NULL }; if (*refname) git_buf_puts(&name, refname); else { git_buf_puts(&name, GIT_HEAD_FILE); fallbackmode = false; } for (i = 0; formatters[i] && (fallbackmode || i == 0); i++) { git_buf_clear(&refnamebuf); if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0) goto cleanup; if (!git_reference_is_valid_name(git_buf_cstr(&refnamebuf))) { error = GIT_EINVALIDSPEC; continue; } foundvalid = true; error = git_reference_lookup_resolved(&ref, repo, git_buf_cstr(&refnamebuf), -1); if (!error) { *out = ref; error = 0; goto cleanup; } if (error != GIT_ENOTFOUND) goto cleanup; } cleanup: if (error && !foundvalid) { /* never found a valid reference name */ giterr_set(GITERR_REFERENCE, "Could not use '%s' as valid reference name", git_buf_cstr(&name)); } git_buf_free(&name); git_buf_free(&refnamebuf); return error; }
static int buffer_want_with_caps(const git_remote_head *head, transport_smart_caps *caps, git_buf *buf) { git_buf str = GIT_BUF_INIT; char oid[GIT_OID_HEXSZ +1] = {0}; unsigned int len; /* Prefer side-band-64k if the server supports both */ if (caps->side_band) { if (caps->side_band_64k) git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND_64K); else git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND); } if (caps->ofs_delta) git_buf_puts(&str, GIT_CAP_OFS_DELTA " "); if (caps->multi_ack) git_buf_puts(&str, GIT_CAP_MULTI_ACK " "); if (caps->include_tag) git_buf_puts(&str, GIT_CAP_INCLUDE_TAG " "); if (git_buf_oom(&str)) return -1; len = (unsigned int) (strlen("XXXXwant ") + GIT_OID_HEXSZ + 1 /* NUL */ + git_buf_len(&str) + 1 /* LF */); git_buf_grow(buf, git_buf_len(buf) + len); git_oid_fmt(oid, &head->oid); git_buf_printf(buf, "%04xwant %s %s\n", len, oid, git_buf_cstr(&str)); git_buf_free(&str); return git_buf_oom(buf); }
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); }
void test_buf_basic__resize(void) { git_buf buf1 = GIT_BUF_INIT; git_buf_puts(&buf1, test_string); cl_assert(git_buf_oom(&buf1) == 0); cl_assert_equal_s(git_buf_cstr(&buf1), test_string); git_buf_puts(&buf1, test_string); cl_assert(strlen(git_buf_cstr(&buf1)) == strlen(test_string) * 2); git_buf_free(&buf1); }
static int negotiate_init_context( http_auth_negotiate_context *ctx, const gitno_connection_data *connection_data) { OM_uint32 status_major, status_minor; gss_OID item, *oid; gss_OID_set mechanism_list; size_t i; /* Query supported mechanisms looking for SPNEGO) */ if (GSS_ERROR(status_major = gss_indicate_mechs(&status_minor, &mechanism_list))) { negotiate_err_set(status_major, status_minor, "could not query mechanisms"); return -1; } if (mechanism_list) { for (oid = negotiate_oids; *oid; oid++) { for (i = 0; i < mechanism_list->count; i++) { item = &mechanism_list->elements[i]; if (item->length == (*oid)->length && memcmp(item->elements, (*oid)->elements, item->length) == 0) { ctx->oid = *oid; break; } } if (ctx->oid) break; } } gss_release_oid_set(&status_minor, &mechanism_list); if (!ctx->oid) { giterr_set(GITERR_NET, "Negotiate authentication is not supported"); return -1; } git_buf_puts(&ctx->target, "HTTP@"); git_buf_puts(&ctx->target, connection_data->host); if (git_buf_oom(&ctx->target)) return -1; ctx->gss_context = GSS_C_NO_CONTEXT; ctx->configured = 1; return 0; }
static int disambiguate_refname(git_reference **out, git_repository *repo, const char *refname) { int error = 0, i; bool fallbackmode = true; git_reference *ref; git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT; static const char* formatters[] = { "%s", GIT_REFS_DIR "%s", GIT_REFS_TAGS_DIR "%s", GIT_REFS_HEADS_DIR "%s", GIT_REFS_REMOTES_DIR "%s", GIT_REFS_REMOTES_DIR "%s/" GIT_HEAD_FILE, NULL }; if (*refname) git_buf_puts(&name, refname); else { git_buf_puts(&name, GIT_HEAD_FILE); fallbackmode = false; } for (i = 0; formatters[i] && (fallbackmode || i == 0); i++) { git_buf_clear(&refnamebuf); if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0) goto cleanup; if (!git_reference_is_valid_name(git_buf_cstr(&refnamebuf))) { error = GIT_EINVALIDSPEC; continue; } error = git_reference_lookup_resolved(&ref, repo, git_buf_cstr(&refnamebuf), -1); if (!error) { *out = ref; error = 0; goto cleanup; } if (error != GIT_ENOTFOUND) goto cleanup; } cleanup: git_buf_free(&name); git_buf_free(&refnamebuf); return error; }
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 buffer_want_with_caps(const git_remote_head *head, transport_smart_caps *caps, git_buf *buf) { git_buf str = GIT_BUF_INIT; char oid[GIT_OID_HEXSZ +1] = {0}; size_t len; /* Prefer multi_ack_detailed */ if (caps->multi_ack_detailed) git_buf_puts(&str, GIT_CAP_MULTI_ACK_DETAILED " "); else if (caps->multi_ack) git_buf_puts(&str, GIT_CAP_MULTI_ACK " "); /* Prefer side-band-64k if the server supports both */ if (caps->side_band_64k) git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND_64K); else if (caps->side_band) git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND); if (caps->include_tag) git_buf_puts(&str, GIT_CAP_INCLUDE_TAG " "); if (caps->thin_pack) git_buf_puts(&str, GIT_CAP_THIN_PACK " "); if (caps->ofs_delta) git_buf_puts(&str, GIT_CAP_OFS_DELTA " "); if (git_buf_oom(&str)) return -1; len = strlen("XXXXwant ") + GIT_OID_HEXSZ + 1 /* NUL */ + git_buf_len(&str) + 1 /* LF */; if (len > 0xffff) { giterr_set(GITERR_NET, "tried to produce packet with invalid length %" PRIuZ, len); return -1; } git_buf_grow_by(buf, len); git_oid_fmt(oid, &head->oid); git_buf_printf(buf, "%04xwant %s %s\n", (unsigned int)len, oid, git_buf_cstr(&str)); git_buf_dispose(&str); GITERR_CHECK_ALLOC_BUF(buf); return 0; }
//no check is performed on ceiling_dirs length, so be sure it's long enough static void append_ceiling_dir(git_buf *ceiling_dirs, const char *path) { git_buf pretty_path = GIT_BUF_INIT; char ceiling_separator[2] = { GIT_PATH_LIST_SEPARATOR, '\0' }; cl_git_pass(git_path_prettify_dir(&pretty_path, path, NULL)); if (ceiling_dirs->size > 0) git_buf_puts(ceiling_dirs, ceiling_separator); git_buf_puts(ceiling_dirs, pretty_path.ptr); git_buf_free(&pretty_path); cl_assert(git_buf_oom(ceiling_dirs) == 0); }
static int disambiguate_refname(git_reference **out, git_repository *repo, const char *refname) { int error, i; bool fallbackmode = true; git_reference *ref; git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT; static const char* formatters[] = { "%s", "refs/%s", "refs/tags/%s", "refs/heads/%s", "refs/remotes/%s", "refs/remotes/%s/HEAD", NULL }; if (*refname) git_buf_puts(&name, refname); else { git_buf_puts(&name, GIT_HEAD_FILE); fallbackmode = false; } for (i = 0; formatters[i] && (fallbackmode || i == 0); i++) { git_buf_clear(&refnamebuf); if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0) goto cleanup; error = git_reference_lookup_resolved(&ref, repo, git_buf_cstr(&refnamebuf), -1); if (!error) { *out = ref; error = 0; goto cleanup; } if (error != GIT_ENOTFOUND) goto cleanup; } cleanup: git_buf_free(&name); git_buf_free(&refnamebuf); return error; }
static int refspec_transform( git_buf *out, const char *from, const char *to, const char *name) { const char *from_star, *to_star; size_t replacement_len, star_offset; git_buf_sanitize(out); git_buf_clear(out); /* * There are two parts to each side of a refspec, the bit * before the star and the bit after it. The star can be in * the middle of the pattern, so we need to look at each bit * individually. */ from_star = strchr(from, '*'); to_star = strchr(to, '*'); assert(from_star && to_star); /* star offset, both in 'from' and in 'name' */ star_offset = from_star - from; /* the first half is copied over */ git_buf_put(out, to, to_star - to); /* * Copy over the name, but exclude the trailing part in "from" starting * after the glob */ replacement_len = strlen(name + star_offset) - strlen(from_star + 1); git_buf_put(out, name + star_offset, replacement_len); return git_buf_puts(out, to_star + 1); }
/* let's try some producer/consumer tests */ void test_core_buffer__4(void) { git_buf buf = GIT_BUF_INIT; int i; for (i = 0; i < 10; ++i) { git_buf_puts(&buf, "1234"); /* add 4 */ cl_assert(git_buf_oom(&buf) == 0); git_buf_consume(&buf, buf.ptr + 2); /* eat the first two */ cl_assert(strlen(git_buf_cstr(&buf)) == (size_t)((i + 1) * 2)); } /* we have appended 1234 10x and removed the first 20 letters */ cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf)); git_buf_consume(&buf, NULL); cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf)); git_buf_consume(&buf, "invalid pointer"); cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf)); git_buf_consume(&buf, buf.ptr); cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf)); git_buf_consume(&buf, buf.ptr + 1); cl_assert_equal_s("2341234123412341234", git_buf_cstr(&buf)); git_buf_consume(&buf, buf.ptr + buf.size); cl_assert_equal_s("", git_buf_cstr(&buf)); git_buf_free(&buf); }
/* test basic data concatenation */ void test_core_buffer__0(void) { git_buf buf = GIT_BUF_INIT; cl_assert(buf.size == 0); git_buf_puts(&buf, test_string); cl_assert(git_buf_oom(&buf) == 0); cl_assert_equal_s(test_string, git_buf_cstr(&buf)); git_buf_puts(&buf, test_string); cl_assert(git_buf_oom(&buf) == 0); cl_assert_equal_s(test_string_x2, git_buf_cstr(&buf)); git_buf_free(&buf); }
static int retrieve_base_commit_and_message( git_commit **b_commit, git_buf *stash_message, git_repository *repo) { git_reference *head = NULL; int error; if ((error = retrieve_head(&head, repo)) < 0) return error; if (strcmp("HEAD", git_reference_name(head)) == 0) error = git_buf_puts(stash_message, "(no branch): "); else error = git_buf_printf( stash_message, "%s: ", git_reference_name(head) + strlen(GIT_REFS_HEADS_DIR)); if (error < 0) goto cleanup; if ((error = git_commit_lookup( b_commit, repo, git_reference_target(head))) < 0) goto cleanup; if ((error = append_commit_description(stash_message, *b_commit)) < 0) goto cleanup; cleanup: git_reference_free(head); return error; }
static int prepare_worktree_commit_message( git_buf* msg, const char *user_message) { git_buf buf = GIT_BUF_INIT; int error; if ((error = git_buf_set(&buf, git_buf_cstr(msg), git_buf_len(msg))) < 0) return error; git_buf_clear(msg); if (!user_message) git_buf_printf(msg, "WIP on %s", git_buf_cstr(&buf)); else { const char *colon; if ((colon = strchr(git_buf_cstr(&buf), ':')) == NULL) goto cleanup; git_buf_puts(msg, "On "); git_buf_put(msg, git_buf_cstr(&buf), colon - buf.ptr); git_buf_printf(msg, ": %s\n", user_message); } error = (git_buf_oom(msg) || git_buf_oom(&buf)) ? -1 : 0; cleanup: git_buf_free(&buf); return error; }
static int write_tag_annotation( git_oid *oid, git_repository *repo, const char *tag_name, const git_object *target, const git_signature *tagger, const char *message) { git_buf tag = GIT_BUF_INIT; git_odb *odb; git_oid__writebuf(&tag, "object ", git_object_id(target)); git_buf_printf(&tag, "type %s\n", git_object_type2string(git_object_type(target))); git_buf_printf(&tag, "tag %s\n", tag_name); git_signature__writebuf(&tag, "tagger ", tagger); git_buf_putc(&tag, '\n'); if (git_buf_puts(&tag, message) < 0) goto on_error; if (git_repository_odb__weakptr(&odb, repo) < 0) goto on_error; if (git_odb_write(oid, odb, tag.ptr, tag.size, GIT_OBJ_TAG) < 0) goto on_error; git_buf_free(&tag); return 0; on_error: git_buf_free(&tag); giterr_set(GITERR_OBJECT, "Failed to create tag annotation."); return -1; }
static void create_paths(const char *root, int depth) { git_buf fullpath = GIT_BUF_INIT; size_t root_len; int i; cl_git_pass(git_buf_puts(&fullpath, root)); cl_git_pass(git_buf_putc(&fullpath, '/')); root_len = fullpath.size; for (i = 0; i < 8; i++) { bool file = (depth == 0 || (i % 2) == 0); git_buf_truncate(&fullpath, root_len); cl_git_pass(git_buf_printf(&fullpath, "item%d", i)); if (file) { cl_git_rewritefile(fullpath.ptr, "This is a file!\n"); } else { cl_must_pass(p_mkdir(fullpath.ptr, 0777)); if (depth > 0) create_paths(fullpath.ptr, (depth - 1)); } } git_buf_dispose(&fullpath); }
int git_futils_mktmp(git_buf *path_out, const char *filename, mode_t mode) { int fd; mode_t mask; p_umask(mask = p_umask(0)); git_buf_sets(path_out, filename); git_buf_puts(path_out, "_git2_XXXXXX"); if (git_buf_oom(path_out)) return -1; if ((fd = p_mkstemp(path_out->ptr)) < 0) { giterr_set(GITERR_OS, "Failed to create temporary file '%s'", path_out->ptr); return -1; } if (p_chmod(path_out->ptr, (mode & ~mask))) { giterr_set(GITERR_OS, "Failed to set permissions on file '%s'", path_out->ptr); return -1; } return fd; }
static int rebase_open_merge(git_rebase *rebase) { git_buf state_path = GIT_BUF_INIT, buf = GIT_BUF_INIT, cmt = GIT_BUF_INIT; git_oid id; git_rebase_operation *operation; size_t i, msgnum = 0, end; int error; if ((error = git_buf_puts(&state_path, rebase->state_path)) < 0) goto done; /* Read 'msgnum' if it exists (otherwise, let msgnum = 0) */ if ((error = rebase_readint(&msgnum, &buf, &state_path, MSGNUM_FILE)) < 0 && error != GIT_ENOTFOUND) goto done; if (msgnum) { rebase->started = 1; rebase->current = msgnum - 1; } /* Read 'end' */ if ((error = rebase_readint(&end, &buf, &state_path, END_FILE)) < 0) goto done; /* Read 'current' if it exists */ if ((error = rebase_readoid(&id, &buf, &state_path, CURRENT_FILE)) < 0 && error != GIT_ENOTFOUND) goto done; /* Read cmt.* */ git_array_init_to_size(rebase->operations, end); GITERR_CHECK_ARRAY(rebase->operations); for (i = 0; i < end; i++) { git_buf_clear(&cmt); if ((error = git_buf_printf(&cmt, "cmt.%" PRIuZ, (i+1))) < 0 || (error = rebase_readoid(&id, &buf, &state_path, cmt.ptr)) < 0) goto done; operation = rebase_operation_alloc(rebase, GIT_REBASE_OPERATION_PICK, &id, NULL); GITERR_CHECK_ALLOC(operation); } /* Read 'onto_name' */ if ((error = rebase_readfile(&buf, &state_path, ONTO_NAME_FILE)) < 0) goto done; rebase->onto_name = git_buf_detach(&buf); done: git_buf_free(&cmt); git_buf_free(&state_path); git_buf_free(&buf); return error; }
const char* cl_git_path_url(const char *path) { static char url[4096]; const char *in_buf; git_buf path_buf = GIT_BUF_INIT; git_buf url_buf = GIT_BUF_INIT; cl_git_pass(git_path_prettify_dir(&path_buf, path, NULL)); cl_git_pass(git_buf_puts(&url_buf, "file://")); #ifdef GIT_WIN32 /* * A FILE uri matches the following format: file://[host]/path * where "host" can be empty and "path" is an absolute path to the resource. * * In this test, no hostname is used, but we have to ensure the leading triple slashes: * * *nix: file:///usr/home/... * Windows: file:///C:/Users/... */ cl_git_pass(git_buf_putc(&url_buf, '/')); #endif in_buf = git_buf_cstr(&path_buf); /* * A very hacky Url encoding that only takes care of escaping the spaces */ while (*in_buf) { if (*in_buf == ' ') cl_git_pass(git_buf_puts(&url_buf, "%20")); else cl_git_pass(git_buf_putc(&url_buf, *in_buf)); in_buf++; } cl_assert(url_buf.size < 4096); strncpy(url, git_buf_cstr(&url_buf), 4096); git_buf_free(&url_buf); git_buf_free(&path_buf); return url; }
static int gen_request( git_buf *buf, http_stream *s, size_t content_length) { http_subtransport *t = OWNING_SUBTRANSPORT(s); const char *path = t->connection_data.path ? t->connection_data.path : "/"; git_buf_printf(buf, "%s %s%s HTTP/1.1\r\n", s->verb, path, s->service_url); git_buf_puts(buf, "User-Agent: git/1.0 (libgit2 " LIBGIT2_VERSION ")\r\n"); git_buf_printf(buf, "Host: %s\r\n", t->connection_data.host); if (s->chunked || content_length > 0) { git_buf_printf(buf, "Accept: application/x-git-%s-result\r\n", s->service); git_buf_printf(buf, "Content-Type: application/x-git-%s-request\r\n", s->service); if (s->chunked) git_buf_puts(buf, "Transfer-Encoding: chunked\r\n"); else git_buf_printf(buf, "Content-Length: %"PRIuZ "\r\n", content_length); } else git_buf_puts(buf, "Accept: */*\r\n"); /* Apply credentials to the request */ if (t->cred && t->cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT && t->auth_mechanism == GIT_HTTP_AUTH_BASIC && apply_basic_credential(buf, t->cred) < 0) return -1; /* Use url-parsed basic auth if username and password are both provided */ if (!t->cred && t->connection_data.user && t->connection_data.pass) { if (!t->url_cred && git_cred_userpass_plaintext_new(&t->url_cred, t->connection_data.user, t->connection_data.pass) < 0) return -1; if (apply_basic_credential(buf, t->url_cred) < 0) return -1; } git_buf_puts(buf, "\r\n"); if (git_buf_oom(buf)) return -1; return 0; }
/** * Append to 'out' properly marking continuations when there's a newline in 'content' */ static void format_header_field(git_buf *out, const char *field, const char *content) { const char *lf; assert(out && field && content); git_buf_puts(out, field); git_buf_putc(out, ' '); while ((lf = strchr(content, '\n')) != NULL) { git_buf_put(out, content, lf - content); git_buf_puts(out, "\n "); content = lf + 1; } git_buf_puts(out, content); git_buf_putc(out, '\n'); }
static void expect_unquote_fail(const char *quoted) { git_buf buf = GIT_BUF_INIT; cl_git_pass(git_buf_puts(&buf, quoted)); cl_git_fail(git_buf_unquote(&buf)); git_buf_dispose(&buf); }
int git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name) { git_buf_sanitize(out); if (!spec->pattern) return git_buf_puts(out, spec->src); return refspec_transform(out, spec->dst, spec->src, name); }
static int remote_name(git_buf *buf, git_repository *repo, const char *canonical_branch_name) { git_strarray remote_list = {0}; size_t i; git_remote *remote; const git_refspec *fetchspec; int error = 0; char *remote_name = NULL; assert(buf && repo && canonical_branch_name); /* Verify that this is a remote branch */ if (!git_reference__is_remote(canonical_branch_name)) { giterr_set(GITERR_INVALID, "Reference '%s' is not a remote branch.", canonical_branch_name); error = GIT_ERROR; goto cleanup; } /* Get the remotes */ if ((error = git_remote_list(&remote_list, repo)) < 0) goto cleanup; /* Find matching remotes */ for (i = 0; i < remote_list.count; i++) { if ((error = git_remote_load(&remote, repo, remote_list.strings[i])) < 0) continue; fetchspec = git_remote__matching_dst_refspec(remote, canonical_branch_name); if (fetchspec) { /* If we have not already set out yet, then set * it to the matching remote name. Otherwise * multiple remotes match this reference, and it * is ambiguous. */ if (!remote_name) { remote_name = remote_list.strings[i]; } else { git_remote_free(remote); error = GIT_EAMBIGUOUS; goto cleanup; } } git_remote_free(remote); } if (remote_name) { git_buf_clear(buf); error = git_buf_puts(buf, remote_name); } else { error = GIT_ENOTFOUND; } cleanup: git_strarray_free(&remote_list); return error; }
void giterr_set(int error_class, const char *string, ...) { git_buf buf = GIT_BUF_INIT; va_list arglist; #ifdef GIT_WIN32 DWORD win32_error_code = (error_class == GITERR_OS) ? GetLastError() : 0; #endif int error_code = (error_class == GITERR_OS) ? errno : 0; va_start(arglist, string); git_buf_vprintf(&buf, string, arglist); va_end(arglist); if (error_class == GITERR_OS) { #ifdef GIT_WIN32 if (win32_error_code) { char *lpMsgBuf; if (FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, win32_error_code, 0, (LPSTR)&lpMsgBuf, 0, NULL)) { git_buf_PUTS(&buf, ": "); git_buf_puts(&buf, lpMsgBuf); LocalFree(lpMsgBuf); } SetLastError(0); } else #endif if (error_code) { git_buf_PUTS(&buf, ": "); git_buf_puts(&buf, strerror(error_code)); } if (error_code) errno = 0; } if (!git_buf_oom(&buf)) set_error(error_class, git_buf_detach(&buf)); }
static int apply_basic_credential(HINTERNET request, git_cred *cred) { git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; git_buf buf = GIT_BUF_INIT, raw = GIT_BUF_INIT; wchar_t *wide = NULL; int error = -1, wide_len = 0; git_buf_printf(&raw, "%s:%s", c->username, c->password); if (git_buf_oom(&raw) || git_buf_puts(&buf, "Authorization: Basic ") < 0 || git_buf_put_base64(&buf, git_buf_cstr(&raw), raw.size) < 0) goto on_error; wide_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, git_buf_cstr(&buf), -1, NULL, 0); if (!wide_len) { giterr_set(GITERR_OS, QT_TRANSLATE_NOOP("libgit2", "Failed to measure string for wide conversion")); goto on_error; } wide = git__malloc(wide_len * sizeof(wchar_t)); if (!wide) goto on_error; if (!MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, git_buf_cstr(&buf), -1, wide, wide_len)) { giterr_set(GITERR_OS, QT_TRANSLATE_NOOP("libgit2", "Failed to convert string to wide form")); goto on_error; } if (!WinHttpAddRequestHeaders(request, wide, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD)) { giterr_set(GITERR_OS, QT_TRANSLATE_NOOP("libgit2", "Failed to add a header to the request")); goto on_error; } error = 0; on_error: /* We were dealing with plaintext passwords, so clean up after ourselves a bit. */ if (wide) memset(wide, 0x0, wide_len * sizeof(wchar_t)); if (buf.size) memset(buf.ptr, 0x0, buf.size); if (raw.size) memset(raw.ptr, 0x0, raw.size); git__free(wide); git_buf_free(&buf); git_buf_free(&raw); return error; }