const char *msg;
strcpy(quickref, status_abbrev(ref->old_sha1));
- if (ref->nonfastforward) {
+ if (ref->requires_force) {
strcat(quickref, "...");
type = '+';
msg = "forced update";
print_ref_status('!', "[rejected]", ref, ref->peer_ref,
"non-fast-forward", porcelain);
break;
+ case REF_STATUS_REJECT_ALREADY_EXISTS:
+ print_ref_status('!', "[rejected]", ref, ref->peer_ref,
+ "already exists", porcelain);
+ break;
case REF_STATUS_REMOTE_REJECT:
print_ref_status('!', "[remote rejected]", ref,
ref->deletion ? NULL : ref->peer_ref,
*reject_reasons |= REJECT_NON_FF_HEAD;
else
*reject_reasons |= REJECT_NON_FF_OTHER;
+ } else if (ref->status == REF_STATUS_REJECT_ALREADY_EXISTS) {
+ *reject_reasons |= REJECT_ALREADY_EXISTS;
}
}
}
die("Aborting.");
}
+static int run_pre_push_hook(struct transport *transport,
+ struct ref *remote_refs)
+{
+ int ret = 0, x;
+ struct ref *r;
+ struct child_process proc;
+ struct strbuf buf;
+ const char *argv[4];
+
+ if (!(argv[0] = find_hook("pre-push")))
+ return 0;
+
+ argv[1] = transport->remote->name;
+ argv[2] = transport->url;
+ argv[3] = NULL;
+
+ memset(&proc, 0, sizeof(proc));
+ proc.argv = argv;
+ proc.in = -1;
+
+ if (start_command(&proc)) {
+ finish_command(&proc);
+ return -1;
+ }
+
+ strbuf_init(&buf, 256);
+
+ for (r = remote_refs; r; r = r->next) {
+ if (!r->peer_ref) continue;
+ if (r->status == REF_STATUS_REJECT_NONFASTFORWARD) continue;
+ if (r->status == REF_STATUS_UPTODATE) continue;
+
+ strbuf_reset(&buf);
+ strbuf_addf( &buf, "%s %s %s %s\n",
+ r->peer_ref->name, sha1_to_hex(r->new_sha1),
+ r->name, sha1_to_hex(r->old_sha1));
+
+ if (write_in_full(proc.in, buf.buf, buf.len) != buf.len) {
+ ret = -1;
+ break;
+ }
+ }
+
+ strbuf_release(&buf);
+
+ x = close(proc.in);
+ if (!ret)
+ ret = x;
+
+ x = finish_command(&proc);
+ if (!ret)
+ ret = x;
+
+ return ret;
+}
+
int transport_push(struct transport *transport,
int refspec_nr, const char **refspec, int flags,
unsigned int *reject_reasons)
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) && !is_bare_repository()) {
struct ref *ref = remote_refs;
for (; ref; ref = ref->next)