예제 #1
0
파일: remote.c 프로젝트: certik/git
int for_each_remote(each_remote_fn fn, void *priv)
{
	int i, result = 0;
	read_config();
	for (i = 0; i < remotes_nr && !result; i++) {
		struct remote *r = remotes[i];
		if (!r)
			continue;
		if (!r->fetch)
			r->fetch = parse_fetch_refspec(r->fetch_refspec_nr,
						       r->fetch_refspec);
		if (!r->push)
			r->push = parse_push_refspec(r->push_refspec_nr,
						     r->push_refspec);
		result = fn(r, priv);
	}
	return result;
}
예제 #2
0
static int push_check(int argc, const char **argv, const char *prefix)
{
	struct remote *remote;

	if (argc < 2)
		die("submodule--helper push-check requires at least 1 argument");

	/*
	 * The remote must be configured.
	 * This is to avoid pushing to the exact same URL as the parent.
	 */
	remote = pushremote_get(argv[1]);
	if (!remote || remote->origin == REMOTE_UNCONFIGURED)
		die("remote '%s' not configured", argv[1]);

	/* Check the refspec */
	if (argc > 2) {
		int i, refspec_nr = argc - 2;
		struct ref *local_refs = get_local_heads();
		struct refspec *refspec = parse_push_refspec(refspec_nr,
							     argv + 2);

		for (i = 0; i < refspec_nr; i++) {
			struct refspec *rs = refspec + i;

			if (rs->pattern || rs->matching)
				continue;

			/*
			 * LHS must match a single ref
			 * NEEDSWORK: add logic to special case 'HEAD' once
			 * working with submodules in a detached head state
			 * ceases to be the norm.
			 */
			if (count_refspec_match(rs->src, local_refs, NULL) != 1)
				die("src refspec '%s' must name a ref",
				    rs->src);
		}
		free_refspec(refspec_nr, refspec);
	}

	return 0;
}
예제 #3
0
파일: remote.c 프로젝트: certik/git
struct remote *remote_get(const char *name)
{
	struct remote *ret;

	read_config();
	if (!name)
		name = default_remote_name;
	ret = make_remote(name, 0);
	if (valid_remote_nick(name)) {
		if (!ret->url)
			read_remotes_file(ret);
		if (!ret->url)
			read_branches_file(ret);
	}
	if (!ret->url)
		add_url_alias(ret, name);
	if (!ret->url)
		return NULL;
	ret->fetch = parse_fetch_refspec(ret->fetch_refspec_nr, ret->fetch_refspec);
	ret->push = parse_push_refspec(ret->push_refspec_nr, ret->push_refspec);
	return ret;
}
예제 #4
0
파일: transport.c 프로젝트: DoWonJin/git
int transport_push(struct transport *transport,
		   int refspec_nr, const char **refspec, int flags,
		   unsigned int *reject_reasons)
{
	*reject_reasons = 0;
	transport_verify_remote_names(refspec_nr, refspec);

	if (transport_color_config() < 0)
		return -1;

	if (transport->vtable->push_refs) {
		struct ref *remote_refs;
		struct ref *local_refs = get_local_heads();
		int match_flags = MATCH_REFS_NONE;
		int verbose = (transport->verbose > 0);
		int quiet = (transport->verbose < 0);
		int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
		int pretend = flags & TRANSPORT_PUSH_DRY_RUN;
		int push_ret, ret, err;
		struct refspec *tmp_rs;
		struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
		int i;

		if (check_push_refs(local_refs, refspec_nr, refspec) < 0)
			return -1;

		tmp_rs = parse_push_refspec(refspec_nr, refspec);
		for (i = 0; i < refspec_nr; i++) {
			const char *prefix = NULL;

			if (tmp_rs[i].dst)
				prefix = tmp_rs[i].dst;
			else if (tmp_rs[i].src && !tmp_rs[i].exact_sha1)
				prefix = tmp_rs[i].src;

			if (prefix) {
				const char *glob = strchr(prefix, '*');
				if (glob)
					argv_array_pushf(&ref_prefixes, "%.*s",
							 (int)(glob - prefix),
							 prefix);
				else
					expand_ref_prefix(&ref_prefixes, prefix);
			}
		}

		remote_refs = transport->vtable->get_refs_list(transport, 1,
							       &ref_prefixes);

		argv_array_clear(&ref_prefixes);
		free_refspec(refspec_nr, tmp_rs);

		if (flags & TRANSPORT_PUSH_ALL)
			match_flags |= MATCH_REFS_ALL;
		if (flags & TRANSPORT_PUSH_MIRROR)
			match_flags |= MATCH_REFS_MIRROR;
		if (flags & TRANSPORT_PUSH_PRUNE)
			match_flags |= MATCH_REFS_PRUNE;
		if (flags & TRANSPORT_PUSH_FOLLOW_TAGS)
			match_flags |= MATCH_REFS_FOLLOW_TAGS;

		if (match_push_refs(local_refs, &remote_refs,
				    refspec_nr, refspec, match_flags)) {
			return -1;
		}

		if (transport->smart_options &&
		    transport->smart_options->cas &&
		    !is_empty_cas(transport->smart_options->cas))
			apply_push_cas(transport->smart_options->cas,
				       transport->remote, remote_refs);

		set_ref_status_for_push(remote_refs,
			flags & TRANSPORT_PUSH_MIRROR,
			flags & TRANSPORT_PUSH_FORCE);

		if (!(flags & TRANSPORT_PUSH_NO_HOOK))
			if (run_pre_push_hook(transport, remote_refs))
				return -1;

		if ((flags & (TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND |
			      TRANSPORT_RECURSE_SUBMODULES_ONLY)) &&
		    !is_bare_repository()) {
			struct ref *ref = remote_refs;
			struct oid_array commits = OID_ARRAY_INIT;

			for (; ref; ref = ref->next)
				if (!is_null_oid(&ref->new_oid))
					oid_array_append(&commits,
							  &ref->new_oid);

			if (!push_unpushed_submodules(&commits,
						      transport->remote,
						      refspec, refspec_nr,
						      transport->push_options,
						      pretend)) {
				oid_array_clear(&commits);
				die("Failed to push all needed submodules!");
			}
			oid_array_clear(&commits);
		}

		if (((flags & TRANSPORT_RECURSE_SUBMODULES_CHECK) ||
		     ((flags & (TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND |
				TRANSPORT_RECURSE_SUBMODULES_ONLY)) &&
		      !pretend)) && !is_bare_repository()) {
			struct ref *ref = remote_refs;
			struct string_list needs_pushing = STRING_LIST_INIT_DUP;
			struct oid_array commits = OID_ARRAY_INIT;

			for (; ref; ref = ref->next)
				if (!is_null_oid(&ref->new_oid))
					oid_array_append(&commits,
							  &ref->new_oid);

			if (find_unpushed_submodules(&commits, transport->remote->name,
						&needs_pushing)) {
				oid_array_clear(&commits);
				die_with_unpushed_submodules(&needs_pushing);
			}
			string_list_clear(&needs_pushing, 0);
			oid_array_clear(&commits);
		}

		if (!(flags & TRANSPORT_RECURSE_SUBMODULES_ONLY))
			push_ret = transport->vtable->push_refs(transport, remote_refs, flags);
		else
			push_ret = 0;
		err = push_had_errors(remote_refs);
		ret = push_ret | err;

		if (!quiet || err)
			transport_print_push_status(transport->url, remote_refs,
					verbose | porcelain, porcelain,
					reject_reasons);

		if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
			set_upstreams(transport, remote_refs, pretend);

		if (!(flags & (TRANSPORT_PUSH_DRY_RUN |
			       TRANSPORT_RECURSE_SUBMODULES_ONLY))) {
			struct ref *ref;
			for (ref = remote_refs; ref; ref = ref->next)
				transport_update_tracking_ref(transport->remote, ref, verbose);
		}

		if (porcelain && !push_ret)
			puts("Done");
		else if (!quiet && !ret && !transport_refs_pushed(remote_refs))
			fprintf(stderr, "Everything up-to-date\n");

		return ret;
	}
	return 1;
}
예제 #5
0
파일: remote.c 프로젝트: certik/git
/*
 * Note. This is used only by "push"; refspec matching rules for
 * push and fetch are subtly different, so do not try to reuse it
 * without thinking.
 */
int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
	       int nr_refspec, const char **refspec, int flags)
{
	struct refspec *rs;
	int send_all = flags & MATCH_REFS_ALL;
	int send_mirror = flags & MATCH_REFS_MIRROR;
	static const char *default_refspec[] = { ":", 0 };

	if (!nr_refspec) {
		nr_refspec = 1;
		refspec = default_refspec;
	}
	rs = parse_push_refspec(nr_refspec, (const char **) refspec);
	if (match_explicit_refs(src, dst, dst_tail, rs, nr_refspec))
		return -1;

	/* pick the remainder */
	for ( ; src; src = src->next) {
		struct ref *dst_peer;
		const struct refspec *pat = NULL;
		char *dst_name;
		if (src->peer_ref)
			continue;

		pat = check_pattern_match(rs, nr_refspec, src);
		if (!pat)
			continue;

		if (pat->matching) {
			/*
			 * "matching refs"; traditionally we pushed everything
			 * including refs outside refs/heads/ hierarchy, but
			 * that does not make much sense these days.
			 */
			if (!send_mirror && prefixcmp(src->name, "refs/heads/"))
				continue;
			dst_name = xstrdup(src->name);

		} else {
			const char *dst_side = pat->dst ? pat->dst : pat->src;
			dst_name = xmalloc(strlen(dst_side) +
					   strlen(src->name) -
					   strlen(pat->src) + 2);
			strcpy(dst_name, dst_side);
			strcat(dst_name, src->name + strlen(pat->src));
		}
		dst_peer = find_ref_by_name(dst, dst_name);
		if (dst_peer) {
			if (dst_peer->peer_ref)
				/* We're already sending something to this ref. */
				goto free_name;

		} else {
			if (pat->matching && !(send_all || send_mirror))
				/*
				 * Remote doesn't have it, and we have no
				 * explicit pattern, and we don't have
				 * --all nor --mirror.
				 */
				goto free_name;

			/* Create a new one and link it */
			dst_peer = make_linked_ref(dst_name, dst_tail);
			hashcpy(dst_peer->new_sha1, src->new_sha1);
		}
		dst_peer->peer_ref = src;
		dst_peer->force = pat->force;
	free_name:
		free(dst_name);
	}
	return 0;
}