git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 5/2] push -s: receiving end

From
Junio C Hamano <gitster@pobox.com>
Date
Sep 8, 2011, 05:38 UTC
Message-ID
<7v7h5jzj8o.fsf_-_@alter.siamese.dyndns.org>
In-Reply-To
<7vehzrzm0e.fsf@alter.siamese.dyndns.org>

This stores the GPG signed push certificate in the receiving repository using the notes mechanism. The certificate is appended to a note in the refs/notes/signed-push tree for each object that appears on the right hand side of the push certificate, i.e. the object that was pushed to update the tip of a ref.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 * This is largely untested, so take it with a large grain of salt.
   This concludes tonight's hacking session for me.
 builtin/receive-pack.c |   74 +++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 307fc3b..257f2a5 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -11,6 +11,11 @@
 #include "transport.h"
 #include "string-list.h"
 #include "sha1-array.h"
+#include "gpg-interface.h"
+#include "notes.h"
+#include "notes-merge.h"
+#include "blob.h"
+#include "tag.h"
 
 static const char receive_pack_usage[] = "git receive-pack <git-dir>";
 
@@ -156,6 +161,7 @@ struct command {
 };
 
 static const char pre_receive_hook[] = "hooks/pre-receive";
+static const char pre_receive_signature_hook[] = "hooks/pre-receive-signature";
 static const char post_receive_hook[] = "hooks/post-receive";
 
 static void rp_error(const char *err, ...) __attribute__((format (printf, 1, 2)));
@@ -581,6 +587,22 @@ static void check_aliased_updates(struct command *commands)
 	string_list_clear(&ref_list, 0);
 }
 
+static void get_note_text(struct strbuf *buf, struct notes_tree *t,
+			  const unsigned char *object)
+{
+	const unsigned char *sha1 = get_note(t, object);
+	char *text;
+	unsigned long len;
+	enum object_type type;
+
+	if (!sha1)
+		return;
+	text = read_sha1_file(sha1, &type, &len);
+	if (text && len && type == OBJ_BLOB)
+		strbuf_add(buf, text, len);
+	free(text);
+}
+
 static int record_signed_push(char *cert)
 {
 	/*
@@ -591,19 +613,57 @@ static int record_signed_push(char *cert)
 	 *
 	 * You could also feed the signed push certificate to GPG,
 	 * verify the signer identity, and all the other fun stuff,
-	 * including feeding it to "pre-push-verify-signature" hook.
-	 *
-	 * Here we just throw it to stderr to demonstrate that the
-	 * codepath is being exercised.
+	 * including feeding it to "pre-receive-signature" hook.
 	 */
+	size_t total, payload;
 	char *cp, *ep;
-	for (cp = cert; *cp; cp = ep) {
+	int ret = 0;
+	struct notes_tree *t;
+	struct strbuf nbuf = STRBUF_INIT;
+
+	init_notes(NULL, "refs/notes/signed-push", NULL, 0);
+	t = &default_notes_tree;
+
+	total = strlen(cert);
+	payload = parse_signature(cert, total);
+	for (cp = cert; cp < cert + payload; cp = ep) {
+		unsigned char sha1[20], nsha1[20];
+
 		ep = strchrnul(cp, '\n');
 		if (*ep == '\n')
 			ep++;
-		fprintf(stderr, "RSP: %.*s", (int)(ep - cp), cp);
+		if (prefixcmp(cp, "Update: "))
+			continue;
+		cp += strlen("Update: ");
+		if (get_sha1_hex(cp, sha1) || cp[40] != ' ')
+			continue;
+		cp += 41;
+		if (get_sha1_hex(cp, sha1) || cp[40] != ' ')
+			continue;
+
+		get_note_text(&nbuf, t, sha1);
+		if (nbuf.len)
+			strbuf_addch(&nbuf, '\n');
+		strbuf_add(&nbuf, cert, total);
+		if (write_sha1_file(nbuf.buf, nbuf.len, blob_type, nsha1) ||
+		    add_note(t, sha1, nsha1, NULL))
+			ret = error(_("unable to write note object"));
+		strbuf_reset(&nbuf);
 	}
-	return 0;
+
+	if (!ret) {
+		unsigned char commit[20];
+		unsigned char parent[20];
+		struct ref_lock *lock;
+
+		resolve_ref(t->ref, parent, 0, NULL);
+		lock = lock_any_ref_for_update(t->ref, parent, 0);
+		create_notes_commit(t, NULL, "push", commit);
+		ret = write_ref_sha1(lock, commit, "push");
+	}
+	free_notes(t);
+
+	return ret;
 }
 
 static void execute_commands(struct command *commands, const char *unpacker_error)
-- 
1.7.7.rc0.188.g3793ac
Previous: Junio C HamanoNext: Johan Herland
Message 17 of 26 in “send-pack: typofix error message”
  1. 1/2 send-pack: typofix error messageJunio C Hamano, Sep 7, 2011
  2. 2/2 push -s: skeletonJunio C Hamano, Sep 7, 2011
  3. Shawn PearceSep 7, 2011
  4. Junio C HamanoSep 7, 2011
  5. Shawn PearceSep 7, 2011
  6. Junio C HamanoSep 8, 2011
  7. Nguyen Thai Ngoc DuySep 7, 2011
  8. Junio C HamanoSep 7, 2011
  9. Robin H. JohnsonSep 7, 2011
  10. Jeff KingSep 8, 2011
  11. Robin H. JohnsonSep 9, 2011
  12. Joey HessSep 9, 2011
  13. Drew NorthupSep 9, 2011
  14. Jeff KingSep 9, 2011
  15. 3/2 Split GPG interface into its own helper libraryJunio C Hamano, Sep 8, 2011
  16. 4/2 push -s: send signed push certificateJunio C Hamano, Sep 8, 2011
  17. 5/2 push -s: receiving endJunio C Hamano, Sep 8, 2011
  18. Johan HerlandSep 8, 2011
  19. Junio C HamanoSep 8, 2011
  20. Jeff KingSep 8, 2011
  21. Junio C HamanoSep 8, 2011
  22. Jeff KingSep 8, 2011
  23. Junio C HamanoSep 8, 2011
  24. Jeff KingSep 9, 2011
  25. Junio C HamanoSep 9, 2011
  26. Jeff KingSep 9, 2011

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.