static void execute_commands_non_atomic(struct command *commands, struct shallow_info *si) { struct command *cmd; struct strbuf err = STRBUF_INIT; for (cmd = commands; cmd; cmd = cmd->next) { if (!should_process_cmd(cmd)) continue; transaction = ref_transaction_begin(&err); if (!transaction) { rp_error("%s", err.buf); strbuf_reset(&err); cmd->error_string = "transaction failed to start"; continue; } cmd->error_string = update(cmd, si); if (!cmd->error_string && ref_transaction_commit(transaction, &err)) { rp_error("%s", err.buf); strbuf_reset(&err); cmd->error_string = "failed to update ref"; } ref_transaction_free(transaction); } strbuf_release(&err); }
static void check_aliased_update(struct command *cmd, struct string_list *list) { struct strbuf buf = STRBUF_INIT; const char *dst_name; struct string_list_item *item; struct command *dst_cmd; unsigned char sha1[GIT_SHA1_RAWSZ]; char cmd_oldh[GIT_SHA1_HEXSZ + 1], cmd_newh[GIT_SHA1_HEXSZ + 1], dst_oldh[GIT_SHA1_HEXSZ + 1], dst_newh[GIT_SHA1_HEXSZ + 1]; int flag; strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name); dst_name = resolve_ref_unsafe(buf.buf, 0, sha1, &flag); strbuf_release(&buf); if (!(flag & REF_ISSYMREF)) return; if (!dst_name) { rp_error("refusing update to broken symref '%s'", cmd->ref_name); cmd->skip_update = 1; cmd->error_string = "broken symref"; return; } dst_name = strip_namespace(dst_name); if ((item = string_list_lookup(list, dst_name)) == NULL) return; cmd->skip_update = 1; dst_cmd = (struct command *) item->util; if (!hashcmp(cmd->old_sha1, dst_cmd->old_sha1) && !hashcmp(cmd->new_sha1, dst_cmd->new_sha1)) return; dst_cmd->skip_update = 1; find_unique_abbrev_r(cmd_oldh, cmd->old_sha1, DEFAULT_ABBREV); find_unique_abbrev_r(cmd_newh, cmd->new_sha1, DEFAULT_ABBREV); find_unique_abbrev_r(dst_oldh, dst_cmd->old_sha1, DEFAULT_ABBREV); find_unique_abbrev_r(dst_newh, dst_cmd->new_sha1, DEFAULT_ABBREV); rp_error("refusing inconsistent update between symref '%s' (%s..%s) and" " its target '%s' (%s..%s)", cmd->ref_name, cmd_oldh, cmd_newh, dst_cmd->ref_name, dst_oldh, dst_newh); cmd->error_string = dst_cmd->error_string = "inconsistent aliased update"; }
static void refuse_unconfigured_deny_delete_current(void) { int i; for (i = 0; i < ARRAY_SIZE(refuse_unconfigured_deny_delete_current_msg); i++) rp_error("%s", refuse_unconfigured_deny_delete_current_msg[i]); }
/*----------------------------------------------------------------------------*/ char *ngx_http_rp_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_http_rp_loc_conf_t *prev = parent; ngx_http_rp_loc_conf_t *conf = child; struct stat stat_buf; ngx_conf_merge_str_value(conf->bazaar_dir, prev->bazaar_dir, c_bazaar_dir); ngx_conf_merge_str_value(conf->bazaar_server, prev->bazaar_server, c_bazaar_server); ngx_conf_merge_str_value(conf->tmp_dir, prev->tmp_dir, c_tmp_dir); if(stat((const char *)conf->bazaar_dir.data, &stat_buf) < 0) { rp_error(cf->log, "Can not open local Bazaar directory (%s): %s", conf->bazaar_dir.data, strerror(errno)); return NGX_CONF_ERROR; } if(((stat_buf.st_mode & S_IFMT) != S_IFDIR) || !(stat_buf.st_mode & S_IRUSR)) { rp_error(cf->log, "Can not open local Bazaar directory (%s): " "Permission denied", conf->bazaar_dir.data); return NGX_CONF_ERROR; } if(stat((const char *)conf->tmp_dir.data, &stat_buf) < 0) { rp_error(cf->log, "Can not open local tmp directory (%s): %s", conf->tmp_dir.data, strerror(errno)); return NGX_CONF_ERROR; } if(((stat_buf.st_mode & S_IFMT) != S_IFDIR) || !(stat_buf.st_mode & S_IRUSR)) { rp_error(cf->log, "Can not open local tmp directory (%s): " "Permission denied", conf->tmp_dir.data); return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static void execute_commands_atomic(struct command *commands, struct shallow_info *si) { struct command *cmd; struct strbuf err = STRBUF_INIT; const char *reported_error = "atomic push failure"; transaction = ref_transaction_begin(&err); if (!transaction) { rp_error("%s", err.buf); strbuf_reset(&err); reported_error = "transaction failed to start"; goto failure; } for (cmd = commands; cmd; cmd = cmd->next) { if (!should_process_cmd(cmd)) continue; cmd->error_string = update(cmd, si); if (cmd->error_string) goto failure; } if (ref_transaction_commit(transaction, &err)) { rp_error("%s", err.buf); reported_error = "atomic transaction failed"; goto failure; } goto cleanup; failure: for (cmd = commands; cmd; cmd = cmd->next) if (!cmd->error_string) cmd->error_string = reported_error; cleanup: ref_transaction_free(transaction); strbuf_release(&err); }
/*----------------------------------------------------------------------------*/ ngx_int_t rp_module_redirect(ngx_http_request_t *r, const char *loc) { ngx_table_elt_t *location; location = ngx_list_push(&r->headers_out.headers); if (location == NULL) { rp_error(r->connection->log, "Can not allocate memory"); return NGX_ERROR; } location->hash = 1; ngx_str_set(&location->key, "Location"); ngx_str_set(&location->value, loc); location->value.len = strlen(loc); ngx_http_clear_location(r); r->headers_out.location = location; return NGX_HTTP_MOVED_TEMPORARILY; }
/*----------------------------------------------------------------------------*/ ngx_int_t rp_module_send_response(ngx_http_request_t *r, cJSON **json_root) { ngx_buf_t *b; ngx_chain_t out; ngx_int_t rc; char *out_buffer; int out_buffer_len; cJSON *j_params; cJSON *j_status; b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if(b == NULL) { rp_error(r->connection->log, "Can not allocate memory"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } out.buf = b; out.next = NULL; r->headers_out.content_type_len = strlen(json_content_str); r->headers_out.content_type.len = strlen(json_content_str); r->headers_out.content_type.data = (u_char *)json_content_str; out_buffer = cJSON_PrintUnformatted(*json_root, r->pool); if(out_buffer == NULL) { rp_error(r->connection->log, "Creating output buffer failed"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } out_buffer_len = strlen(out_buffer); b->pos = (u_char *)out_buffer; b->last = (u_char *)out_buffer + out_buffer_len; b->memory = 1; b->last_buf = b->last_in_chain = 1; b->sync = b->flush = 1; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = out_buffer_len; /* Debug purpopses - output params & status */ j_params = cJSON_GetObjectItem(*json_root, "params"); if(j_params != NULL) { int params_cnt = -1; int i; params_cnt = cJSON_GetArraySize(j_params); rp_debug(r->connection->log, "Output parameters: "); for(i = 0; i < params_cnt; i++) { rp_debug(r->connection->log, "\t%d - %f", i, (float)cJSON_GetArrayItem(j_params, i)->valuedouble); } } j_status = cJSON_GetObjectItem(*json_root, "status"); //if(j_status != NULL) { // rp_debug(r->connection->log, "Output status (req :%d): %s", r->method, // j_status->valuestring); //} cJSON_Delete(*json_root, r->pool); rc = ngx_http_send_header(r); /* If error while sending OK output we re-send it */ if((rc == NGX_ERROR) && (r->method == NGX_HTTP_GET) && j_status && (j_status->valuestring[0] = 'O') && (j_status->valuestring[1] == 'K')) { rp_data_clear_signals_dirty(); } if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } /* TODO: Be sure that outputting is always flushed! Had some problems * at this part. */ /* send the buffer chain of your response */ /* Temp, got from ruby-forum.com - put socket to blocking */ ngx_blocking(r->connection->fd); rc = ngx_http_output_filter(r, &out); while(rc == NGX_AGAIN) { r->connection->write->ready = 1; rc = ngx_http_output_filter(r, &out); if(rc == NGX_ERROR) break; } ngx_nonblocking(r->connection->fd); rc = ngx_http_output_filter(r, NULL); return NGX_DONE; }
static const char *update(struct command *cmd) { const char *name = cmd->ref_name; struct strbuf namespaced_name_buf = STRBUF_INIT; const char *namespaced_name; unsigned char *old_sha1 = cmd->old_sha1; unsigned char *new_sha1 = cmd->new_sha1; struct ref_lock *lock; /* only refs/... are allowed */ if (prefixcmp(name, "refs/") || check_refname_format(name + 5, 0)) { rp_error("refusing to create funny ref '%s' remotely", name); return "funny refname"; } strbuf_addf(&namespaced_name_buf, "%s%s", get_git_namespace(), name); namespaced_name = strbuf_detach(&namespaced_name_buf, NULL); if (is_ref_checked_out(namespaced_name)) { switch (deny_current_branch) { case DENY_IGNORE: break; case DENY_WARN: rp_warning("updating the current branch"); break; case DENY_REFUSE: case DENY_UNCONFIGURED: rp_error("refusing to update checked out branch: %s", name); if (deny_current_branch == DENY_UNCONFIGURED) refuse_unconfigured_deny(); return "branch is currently checked out"; } } if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) { error("unpack should have generated %s, " "but I can't find it!", sha1_to_hex(new_sha1)); return "bad pack"; } if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) { if (deny_deletes && !prefixcmp(name, "refs/heads/")) { rp_error("denying ref deletion for %s", name); return "deletion prohibited"; } if (!strcmp(namespaced_name, head_name)) { switch (deny_delete_current) { case DENY_IGNORE: break; case DENY_WARN: rp_warning("deleting the current branch"); break; case DENY_REFUSE: case DENY_UNCONFIGURED: if (deny_delete_current == DENY_UNCONFIGURED) refuse_unconfigured_deny_delete_current(); rp_error("refusing to delete the current branch: %s", name); return "deletion of the current branch prohibited"; } } } if (deny_non_fast_forwards && !is_null_sha1(new_sha1) && !is_null_sha1(old_sha1) && !prefixcmp(name, "refs/heads/")) { struct object *old_object, *new_object; struct commit *old_commit, *new_commit; struct commit_list *bases, *ent; old_object = parse_object(old_sha1); new_object = parse_object(new_sha1); if (!old_object || !new_object || old_object->type != OBJ_COMMIT || new_object->type != OBJ_COMMIT) { error("bad sha1 objects for %s", name); return "bad ref"; } old_commit = (struct commit *)old_object; new_commit = (struct commit *)new_object; bases = get_merge_bases(old_commit, new_commit, 1); for (ent = bases; ent; ent = ent->next) if (!hashcmp(old_sha1, ent->item->object.sha1)) break; free_commit_list(bases); if (!ent) { rp_error("denying non-fast-forward %s" " (you should pull first)", name); return "non-fast-forward"; } } if (run_update_hook(cmd)) { rp_error("hook declined to update %s", name); return "hook declined"; } if (is_null_sha1(new_sha1)) { if (!parse_object(old_sha1)) { old_sha1 = NULL; if (ref_exists(name)) { rp_warning("Allowing deletion of corrupt ref."); } else { rp_warning("Deleting a non-existent ref."); cmd->did_not_exist = 1; } } if (delete_ref(namespaced_name, old_sha1, 0)) { rp_error("failed to delete %s", name); return "failed to delete"; } return NULL; /* good */ } else { lock = lock_any_ref_for_update(namespaced_name, old_sha1, 0); if (!lock) { rp_error("failed to lock %s", name); return "failed to lock"; } if (write_ref_sha1(lock, new_sha1, "push")) { return "failed to write"; /* error() already called */ } return NULL; /* good */ } }
static const char *update(struct command *cmd, struct shallow_info *si) { const char *name = cmd->ref_name; struct strbuf namespaced_name_buf = STRBUF_INIT; const char *namespaced_name, *ret; unsigned char *old_sha1 = cmd->old_sha1; unsigned char *new_sha1 = cmd->new_sha1; /* only refs/... are allowed */ if (!starts_with(name, "refs/") || check_refname_format(name + 5, 0)) { rp_error("refusing to create funny ref '%s' remotely", name); return "funny refname"; } strbuf_addf(&namespaced_name_buf, "%s%s", get_git_namespace(), name); namespaced_name = strbuf_detach(&namespaced_name_buf, NULL); if (is_ref_checked_out(namespaced_name)) { switch (deny_current_branch) { case DENY_IGNORE: break; case DENY_WARN: rp_warning("updating the current branch"); break; case DENY_REFUSE: case DENY_UNCONFIGURED: rp_error("refusing to update checked out branch: %s", name); if (deny_current_branch == DENY_UNCONFIGURED) refuse_unconfigured_deny(); return "branch is currently checked out"; case DENY_UPDATE_INSTEAD: ret = update_worktree(new_sha1); if (ret) return ret; break; } } if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) { error("unpack should have generated %s, " "but I can't find it!", sha1_to_hex(new_sha1)); return "bad pack"; } if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) { if (deny_deletes && starts_with(name, "refs/heads/")) { rp_error("denying ref deletion for %s", name); return "deletion prohibited"; } if (head_name && !strcmp(namespaced_name, head_name)) { switch (deny_delete_current) { case DENY_IGNORE: break; case DENY_WARN: rp_warning("deleting the current branch"); break; case DENY_REFUSE: case DENY_UNCONFIGURED: case DENY_UPDATE_INSTEAD: if (deny_delete_current == DENY_UNCONFIGURED) refuse_unconfigured_deny_delete_current(); rp_error("refusing to delete the current branch: %s", name); return "deletion of the current branch prohibited"; default: return "Invalid denyDeleteCurrent setting"; } } } if (deny_non_fast_forwards && !is_null_sha1(new_sha1) && !is_null_sha1(old_sha1) && starts_with(name, "refs/heads/")) { struct object *old_object, *new_object; struct commit *old_commit, *new_commit; old_object = parse_object(old_sha1); new_object = parse_object(new_sha1); if (!old_object || !new_object || old_object->type != OBJ_COMMIT || new_object->type != OBJ_COMMIT) { error("bad sha1 objects for %s", name); return "bad ref"; } old_commit = (struct commit *)old_object; new_commit = (struct commit *)new_object; if (!in_merge_bases(old_commit, new_commit)) { rp_error("denying non-fast-forward %s" " (you should pull first)", name); return "non-fast-forward"; } } if (run_update_hook(cmd)) { rp_error("hook declined to update %s", name); return "hook declined"; } if (is_null_sha1(new_sha1)) { struct strbuf err = STRBUF_INIT; if (!parse_object(old_sha1)) { old_sha1 = NULL; if (ref_exists(name)) { rp_warning("Allowing deletion of corrupt ref."); } else { rp_warning("Deleting a non-existent ref."); cmd->did_not_exist = 1; } } if (ref_transaction_delete(transaction, namespaced_name, old_sha1, 0, "push", &err)) { rp_error("%s", err.buf); strbuf_release(&err); return "failed to delete"; } strbuf_release(&err); return NULL; /* good */ } else { struct strbuf err = STRBUF_INIT; if (shallow_update && si->shallow_ref[cmd->index] && update_shallow_ref(cmd, si)) return "shallow error"; if (ref_transaction_update(transaction, namespaced_name, new_sha1, old_sha1, 0, "push", &err)) { rp_error("%s", err.buf); strbuf_release(&err); return "failed to update ref"; } strbuf_release(&err); return NULL; /* good */ } }