Example #1
0
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);
}
Example #2
0
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";
}
Example #3
0
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]);
}
Example #4
0
/*----------------------------------------------------------------------------*/
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;
}
Example #5
0
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);
}
Example #6
0
/*----------------------------------------------------------------------------*/
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;
}
Example #7
0
/*----------------------------------------------------------------------------*/
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;
}
Example #8
0
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 */
	}
}
Example #9
0
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 */
	}
}