From: Junio C Hamano Date: Thu, 24 Jan 2013 05:16:49 +0000 (-0800) Subject: Merge branch 'cr/push-force-tag-update' X-Git-Tag: v1.8.2-rc0~92 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/d82dd26964b9d7b39fb74367e5fcc3e3f4593324?ds=inline;hp=-c Merge branch 'cr/push-force-tag-update' Regression fix to stop "git push" complaining "target ref already exists", when it is not the real reason the command rejected the request (e.g. non-fast-forward). * cr/push-force-tag-update: push: fix "refs/tags/ hierarchy cannot be updated without --force" --- d82dd26964b9d7b39fb74367e5fcc3e3f4593324 diff --combined cache.h index c257953fa7,a942bbd59f..4022b5ba0a --- a/cache.h +++ b/cache.h @@@ -362,7 -362,6 +362,7 @@@ static inline enum object_type object_t #define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF" #define GIT_NOTES_REWRITE_REF_ENVIRONMENT "GIT_NOTES_REWRITE_REF" #define GIT_NOTES_REWRITE_MODE_ENVIRONMENT "GIT_NOTES_REWRITE_MODE" +#define GIT_LITERAL_PATHSPECS_ENVIRONMENT "GIT_LITERAL_PATHSPECS" /* * Repository-local GIT_* environment variables @@@ -474,8 -473,6 +474,8 @@@ extern int index_name_is_other(const st extern int ie_match_stat(const struct index_state *, struct cache_entry *, struct stat *, unsigned int); extern int ie_modified(const struct index_state *, struct cache_entry *, struct stat *, unsigned int); +#define PATHSPEC_ONESTAR 1 /* the pathspec pattern sastisfies GFNM_ONESTAR */ + struct pathspec { const char **raw; /* get_pathspec() result, not freed by free_pathspec() */ int nr; @@@ -485,8 -482,7 +485,8 @@@ struct pathspec_item { const char *match; int len; - unsigned int use_wildcard:1; + int nowildcard_len; + int flags; } *items; }; @@@ -494,8 -490,6 +494,8 @@@ extern int init_pathspec(struct pathspe extern void free_pathspec(struct pathspec *); extern int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec); +extern int limit_pathspec_to_literal(void); + #define HASH_WRITE_OBJECT 1 #define HASH_FORMAT_CHECK 2 extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags); @@@ -720,11 -714,10 +720,11 @@@ static inline int is_absolute_path(cons } int is_directory(const char *); const char *real_path(const char *path); +const char *real_path_if_valid(const char *path); const char *absolute_path(const char *path); const char *relative_path(const char *abs, const char *base); int normalize_path_copy(char *dst, const char *src); -int longest_ancestor_length(const char *path, const char *prefix_list); +int longest_ancestor_length(const char *path, struct string_list *prefixes); char *strip_path_suffix(const char *path, const char *suffix); int daemon_avoid_alias(const char *path); int offset_1st_component(const char *path); @@@ -1011,7 -1004,6 +1011,6 @@@ struct ref requires_force:1, merge:1, nonfastforward:1, - not_forwardable:1, update:1, deletion:1; enum { @@@ -1148,9 -1140,6 +1147,9 @@@ extern int check_repository_format_vers extern int git_env_bool(const char *, int); extern int git_config_system(void); extern int config_error_nonbool(const char *); +#ifdef __GNUC__ +#define config_error_nonbool(s) (config_error_nonbool(s), -1) +#endif extern const char *get_log_output_encoding(void); extern const char *get_commit_output_encoding(void); @@@ -1164,13 -1153,15 +1163,13 @@@ struct config_include_data #define CONFIG_INCLUDE_INIT { 0 } extern int git_config_include(const char *name, const char *value, void *data); -#define IDENT_NAME_GIVEN 01 -#define IDENT_MAIL_GIVEN 02 -#define IDENT_ALL_GIVEN (IDENT_NAME_GIVEN|IDENT_MAIL_GIVEN) -extern int user_ident_explicitly_given; -extern int user_ident_sufficiently_given(void); +extern int committer_ident_sufficiently_given(void); +extern int author_ident_sufficiently_given(void); extern const char *git_commit_encoding; extern const char *git_log_output_encoding; extern const char *git_mailmap_file; +extern const char *git_mailmap_blob; /* IO helper functions */ extern void maybe_flush_or_die(FILE *, const char *); diff --combined remote.c index 4b1153f02c,d3a1ca233b..9e21b1d787 --- a/remote.c +++ b/remote.c @@@ -1279,26 -1279,6 +1279,6 @@@ int match_push_refs(struct ref *src, st return 0; } - static inline int is_forwardable(struct ref* ref) - { - struct object *o; - - if (!prefixcmp(ref->name, "refs/tags/")) - return 0; - - /* old object must be a commit */ - o = parse_object(ref->old_sha1); - if (!o || o->type != OBJ_COMMIT) - return 0; - - /* new object must be commit-ish */ - o = deref_tag(parse_object(ref->new_sha1), NULL, 0); - if (!o || o->type != OBJ_COMMIT) - return 0; - - return 1; - } - void set_ref_status_for_push(struct ref *remote_refs, int send_mirror, int force_update) { @@@ -1320,32 -1300,23 +1300,23 @@@ } /* - * The below logic determines whether an individual - * refspec A:B can be pushed. The push will succeed - * if any of the following are true: + * Decide whether an individual refspec A:B can be + * pushed. The push will succeed if any of the + * following are true: * * (1) the remote reference B does not exist * * (2) the remote reference B is being removed (i.e., * pushing :B where no source is specified) * - * (3) the update meets all fast-forwarding criteria: - * - * (a) the destination is not under refs/tags/ - * (b) the old is a commit - * (c) the new is a descendant of the old - * - * NOTE: We must actually have the old object in - * order to overwrite it in the remote reference, - * and the new object must be commit-ish. These are - * implied by (b) and (c) respectively. + * (3) the destination is not under refs/tags/, and + * if the old and new value is a commit, the new + * is a descendant of the old. * * (4) it is forced using the +A:B notation, or by * passing the --force argument */ - ref->not_forwardable = !is_forwardable(ref); - ref->update = !ref->deletion && !is_null_sha1(ref->old_sha1); @@@ -1355,7 -1326,7 +1326,7 @@@ !has_sha1_file(ref->old_sha1) || !ref_newer(ref->new_sha1, ref->old_sha1); - if (ref->not_forwardable) { + if (!prefixcmp(ref->name, "refs/tags/")) { ref->requires_force = 1; if (!force_ref_update) { ref->status = REF_STATUS_REJECT_ALREADY_EXISTS; @@@ -1413,16 -1384,6 +1384,16 @@@ int branch_merge_matches(struct branch return refname_match(branch->merge[i]->src, refname, ref_fetch_rules); } +static int ignore_symref_update(const char *refname) +{ + unsigned char sha1[20]; + int flag; + + if (!resolve_ref_unsafe(refname, sha1, 0, &flag)) + return 0; /* non-existing refs are OK */ + return (flag & REF_ISSYMREF); +} + static struct ref *get_expanded_map(const struct ref *remote_refs, const struct refspec *refspec) { @@@ -1436,8 -1397,7 +1407,8 @@@ if (strchr(ref->name, '^')) continue; /* a dereference item */ if (match_name_with_pattern(refspec->src, ref->name, - refspec->dst, &expn_name)) { + refspec->dst, &expn_name) && + !ignore_symref_update(expn_name)) { struct ref *cpy = copy_ref(ref); cpy->peer_ref = alloc_ref(expn_name); @@@ -1512,8 -1472,8 +1483,8 @@@ int get_fetch_map(const struct ref *rem for (rmp = &ref_map; *rmp; ) { if ((*rmp)->peer_ref) { - if (check_refname_format((*rmp)->peer_ref->name + 5, - REFNAME_ALLOW_ONELEVEL)) { + if (prefixcmp((*rmp)->peer_ref->name, "refs/") || + check_refname_format((*rmp)->peer_ref->name, 0)) { struct ref *ignore = *rmp; error("* Ignoring funny ref '%s' locally", (*rmp)->peer_ref->name); @@@ -1681,16 -1641,13 +1652,16 @@@ int format_tracking_info(struct branch base = branch->merge[0]->dst; base = shorten_unambiguous_ref(base, 0); - if (!num_theirs) + if (!num_theirs) { strbuf_addf(sb, Q_("Your branch is ahead of '%s' by %d commit.\n", "Your branch is ahead of '%s' by %d commits.\n", num_ours), base, num_ours); - else if (!num_ours) + if (advice_status_hints) + strbuf_addf(sb, + _(" (use \"git push\" to publish your local commits)\n")); + } else if (!num_ours) { strbuf_addf(sb, Q_("Your branch is behind '%s' by %d commit, " "and can be fast-forwarded.\n", @@@ -1698,10 -1655,7 +1669,10 @@@ "and can be fast-forwarded.\n", num_theirs), base, num_theirs); - else + if (advice_status_hints) + strbuf_addf(sb, + _(" (use \"git pull\" to update your local branch)\n")); + } else { strbuf_addf(sb, Q_("Your branch and '%s' have diverged,\n" "and have %d and %d different commit each, " @@@ -1711,10 -1665,6 +1682,10 @@@ "respectively.\n", num_theirs), base, num_ours, num_theirs); + if (advice_status_hints) + strbuf_addf(sb, + _(" (use \"git pull\" to merge the remote branch into yours)\n")); + } return 1; }