static int generate_push_cert(struct strbuf *req_buf, const struct ref *remote_refs, struct send_pack_args *args, const char *cap_string, const char *push_cert_nonce) { const struct ref *ref; struct string_list_item *item; char *signing_key = xstrdup(get_signing_key()); const char *cp, *np; struct strbuf cert = STRBUF_INIT; int update_seen = 0; strbuf_addstr(&cert, "certificate version 0.1\n"); strbuf_addf(&cert, "pusher %s ", signing_key); datestamp(&cert); strbuf_addch(&cert, '\n'); if (args->url && *args->url) { char *anon_url = transport_anonymize_url(args->url); strbuf_addf(&cert, "pushee %s\n", anon_url); free(anon_url); } if (push_cert_nonce[0]) strbuf_addf(&cert, "nonce %s\n", push_cert_nonce); if (args->push_options) for_each_string_list_item(item, args->push_options) strbuf_addf(&cert, "push-option %s\n", item->string); strbuf_addstr(&cert, "\n"); for (ref = remote_refs; ref; ref = ref->next) { if (check_to_send_update(ref, args) < 0) continue; update_seen = 1; strbuf_addf(&cert, "%s %s %s\n", oid_to_hex(&ref->old_oid), oid_to_hex(&ref->new_oid), ref->name); } if (!update_seen) goto free_return; if (sign_buffer(&cert, &cert, signing_key)) die(_("failed to sign the push certificate")); packet_buf_write(req_buf, "push-cert%c%s", 0, cap_string); for (cp = cert.buf; cp < cert.buf + cert.len; cp = np) { np = next_line(cp, cert.buf + cert.len - cp); packet_buf_write(req_buf, "%.*s", (int)(np - cp), cp); } packet_buf_write(req_buf, "push-cert-end\n"); free_return: free(signing_key); strbuf_release(&cert); return update_seen; }
static int print_one_push_status(struct ref *ref, const char *dest, int count, int porcelain, int summary_width) { if (!count) { char *url = transport_anonymize_url(dest); fprintf(porcelain ? stdout : stderr, "To %s\n", url); free(url); } switch(ref->status) { case REF_STATUS_NONE: print_ref_status('X', "[no match]", ref, NULL, NULL, porcelain, summary_width); break; case REF_STATUS_REJECT_NODELETE: print_ref_status('!', "[rejected]", ref, NULL, "remote does not support deleting refs", porcelain, summary_width); break; case REF_STATUS_UPTODATE: print_ref_status('=', "[up to date]", ref, ref->peer_ref, NULL, porcelain, summary_width); break; case REF_STATUS_REJECT_NONFASTFORWARD: print_ref_status('!', "[rejected]", ref, ref->peer_ref, "non-fast-forward", porcelain, summary_width); break; case REF_STATUS_REJECT_ALREADY_EXISTS: print_ref_status('!', "[rejected]", ref, ref->peer_ref, "already exists", porcelain, summary_width); break; case REF_STATUS_REJECT_FETCH_FIRST: print_ref_status('!', "[rejected]", ref, ref->peer_ref, "fetch first", porcelain, summary_width); break; case REF_STATUS_REJECT_NEEDS_FORCE: print_ref_status('!', "[rejected]", ref, ref->peer_ref, "needs force", porcelain, summary_width); break; case REF_STATUS_REJECT_STALE: print_ref_status('!', "[rejected]", ref, ref->peer_ref, "stale info", porcelain, summary_width); break; case REF_STATUS_REJECT_SHALLOW: print_ref_status('!', "[rejected]", ref, ref->peer_ref, "new shallow roots not allowed", porcelain, summary_width); break; case REF_STATUS_REMOTE_REJECT: print_ref_status('!', "[remote rejected]", ref, ref->deletion ? NULL : ref->peer_ref, ref->remote_status, porcelain, summary_width); break; case REF_STATUS_EXPECTING_REPORT: print_ref_status('!', "[remote failure]", ref, ref->deletion ? NULL : ref->peer_ref, "remote failed to report status", porcelain, summary_width); break; case REF_STATUS_ATOMIC_PUSH_FAILED: print_ref_status('!', "[rejected]", ref, ref->peer_ref, "atomic push failed", porcelain, summary_width); break; case REF_STATUS_OK: print_ok_ref_status(ref, porcelain, summary_width); break; } return 1; }
static int store_updated_refs(const char *raw_url, const char *remote_name, struct ref *ref_map) { FILE *fp; struct commit *commit; int url_len, i, note_len, shown_url = 0, rc = 0; char note[1024]; const char *what, *kind; struct ref *rm; char *url, *filename = dry_run ? "/dev/null" : git_path("FETCH_HEAD"); fp = fopen(filename, "a"); if (!fp) return error("cannot open %s: %s\n", filename, strerror(errno)); if (raw_url) url = transport_anonymize_url(raw_url); else url = xstrdup("foreign"); for (rm = ref_map; rm; rm = rm->next) { struct ref *ref = NULL; if (rm->peer_ref) { ref = xcalloc(1, sizeof(*ref) + strlen(rm->peer_ref->name) + 1); strcpy(ref->name, rm->peer_ref->name); hashcpy(ref->old_sha1, rm->peer_ref->old_sha1); hashcpy(ref->new_sha1, rm->old_sha1); ref->force = rm->peer_ref->force; } commit = lookup_commit_reference_gently(rm->old_sha1, 1); if (!commit) rm->merge = 0; if (!strcmp(rm->name, "HEAD")) { kind = ""; what = ""; } else if (!prefixcmp(rm->name, "refs/heads/")) { kind = "branch"; what = rm->name + 11; } else if (!prefixcmp(rm->name, "refs/tags/")) { kind = "tag"; what = rm->name + 10; } else if (!prefixcmp(rm->name, "refs/remotes/")) { kind = "remote branch"; what = rm->name + 13; } else { kind = ""; what = rm->name; } url_len = strlen(url); for (i = url_len - 1; url[i] == '/' && 0 <= i; i--) ; url_len = i + 1; if (4 < i && !strncmp(".git", url + i - 3, 4)) url_len = i - 3; note_len = 0; if (*what) { if (*kind) note_len += sprintf(note + note_len, "%s ", kind); note_len += sprintf(note + note_len, "'%s' of ", what); } note[note_len] = '\0'; fprintf(fp, "%s\t%s\t%s", sha1_to_hex(commit ? commit->object.sha1 : rm->old_sha1), rm->merge ? "" : "not-for-merge", note); for (i = 0; i < url_len; ++i) if ('\n' == url[i]) fputs("\\n", fp); else fputc(url[i], fp); fputc('\n', fp); if (ref) { rc |= update_local_ref(ref, what, note); free(ref); } else sprintf(note, "* %-*s %-*s -> FETCH_HEAD", TRANSPORT_SUMMARY_WIDTH, *kind ? kind : "branch", REFCOL_WIDTH, *what ? what : "HEAD"); if (*note) { if (verbosity >= 0 && !shown_url) { fprintf(stderr, "From %.*s\n", url_len, url); shown_url = 1; } if (verbosity >= 0) fprintf(stderr, " %s\n", note); } } free(url); fclose(fp); if (rc & STORE_REF_ERROR_DF_CONFLICT) error("some local refs could not be updated; try running\n" " 'git remote prune %s' to remove any old, conflicting " "branches", remote_name); return rc; }