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)
{
continue;
}
- /* This part determines what can overwrite what.
- * The rules are:
- *
- * (0) you can always use --force or +A:B notation to
- * selectively force individual ref pairs.
- *
- * (1) if the old thing does not exist, it is OK.
+ /*
+ * Decide whether an individual refspec A:B can be
+ * pushed. The push will succeed if any of the
+ * following are true:
*
- * (2) if the destination is under refs/tags/ you are
- * not allowed to overwrite it; tags are expected
- * to be static once created
+ * (1) the remote reference B does not exist
*
- * (3) if you do not have the old thing, you are not allowed
- * to overwrite it; you would not know what you are losing
- * otherwise.
+ * (2) the remote reference B is being removed (i.e.,
+ * pushing :B where no source is specified)
*
- * (4) if old is a commit and new is a descendant of old
- * (implying new is commit-ish), it is OK.
+ * (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.
*
- * (5) regardless of all of the above, removing :B is
- * always allowed.
+ * (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);
-
- if (ref->update) {
- ref->nonfastforward =
+ if (!ref->deletion && !is_null_sha1(ref->old_sha1)) {
+ int nonfastforward =
!has_sha1_file(ref->old_sha1)
- || !ref_newer(ref->new_sha1, ref->old_sha1);
+ || !ref_newer(ref->new_sha1, ref->old_sha1);
- if (ref->not_forwardable) {
- ref->requires_force = 1;
+ if (!prefixcmp(ref->name, "refs/tags/")) {
if (!force_ref_update) {
ref->status = REF_STATUS_REJECT_ALREADY_EXISTS;
continue;
}
- } else if (ref->nonfastforward) {
- ref->requires_force = 1;
+ ref->forced_update = 1;
+ } else if (nonfastforward) {
if (!force_ref_update) {
ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
continue;
}
+ ref->forced_update = 1;
}
}
}