2929#include "commit-reach.h"
3030#include "khash.h"
3131#include "date.h"
32+ #include "gpg-interface.h"
3233
3334#define PACK_ID_BITS 16
3435#define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
@@ -2716,15 +2717,86 @@ static struct hash_list *parse_merge(unsigned int *count)
27162717 return list ;
27172718}
27182719
2720+ struct signature_data {
2721+ char * hash_algo ; /* "sha1" or "sha256" */
2722+ char * sig_format ; /* "openpgp", "x509", "ssh", "unknown" */
2723+ struct strbuf data ; /* The actual signature data */
2724+ };
2725+
2726+ static void parse_one_signature (struct signature_data * sig , const char * v )
2727+ {
2728+ char * args = xstrdup (v ); /* Will be freed when sig->hash_algo is freed */
2729+ char * space = strchr (args , ' ' );
2730+
2731+ if (!space )
2732+ die ("Expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', "
2733+ "got 'gpgsig %s'" , args );
2734+ * space ++ = '\0' ;
2735+
2736+ sig -> hash_algo = args ;
2737+ sig -> sig_format = space ;
2738+
2739+ /* Remove any trailing newline from format */
2740+ space = strchr (sig -> sig_format , '\n' );
2741+ if (space )
2742+ * space = '\0' ;
2743+
2744+ /* Validate hash algorithm */
2745+ if (strcmp (sig -> hash_algo , "sha1" ) &&
2746+ strcmp (sig -> hash_algo , "sha256" ))
2747+ die ("Unknown git hash algorithm in gpgsig: '%s'" , sig -> hash_algo );
2748+
2749+ /* Validate signature format */
2750+ if (!valid_signature_format (sig -> sig_format ))
2751+ die ("Invalid signature format in gpgsig: '%s'" , sig -> sig_format );
2752+ if (!strcmp (sig -> sig_format , "unknown" ))
2753+ warning ("'unknown' signature format in gpgsig" );
2754+
2755+ /* Read signature data */
2756+ read_next_command ();
2757+ parse_data (& sig -> data , 0 , NULL );
2758+ }
2759+
2760+ static void add_gpgsig_to_commit (struct strbuf * commit_data ,
2761+ const char * header ,
2762+ struct signature_data * sig )
2763+ {
2764+ struct string_list siglines = STRING_LIST_INIT_NODUP ;
2765+
2766+ if (!sig -> hash_algo )
2767+ return ;
2768+
2769+ strbuf_addstr (commit_data , header );
2770+ string_list_split_in_place (& siglines , sig -> data .buf , "\n" , -1 );
2771+ strbuf_add_separated_string_list (commit_data , "\n " , & siglines );
2772+ strbuf_addch (commit_data , '\n' );
2773+ string_list_clear (& siglines , 1 );
2774+ strbuf_release (& sig -> data );
2775+ free (sig -> hash_algo );
2776+ }
2777+
2778+ static void store_signature (struct signature_data * stored_sig ,
2779+ struct signature_data * new_sig ,
2780+ const char * hash_type )
2781+ {
2782+ if (stored_sig -> hash_algo ) {
2783+ warning ("Multiple %s signatures found, ignoring additional signature" ,
2784+ hash_type );
2785+ strbuf_release (& new_sig -> data );
2786+ free (new_sig -> hash_algo );
2787+ } else {
2788+ * stored_sig = * new_sig ;
2789+ }
2790+ }
2791+
27192792static void parse_new_commit (const char * arg )
27202793{
2721- static struct strbuf sig = STRBUF_INIT ;
27222794 static struct strbuf msg = STRBUF_INIT ;
2723- struct string_list siglines = STRING_LIST_INIT_NODUP ;
2795+ struct signature_data sig_sha1 = { NULL , NULL , STRBUF_INIT };
2796+ struct signature_data sig_sha256 = { NULL , NULL , STRBUF_INIT };
27242797 struct branch * b ;
27252798 char * author = NULL ;
27262799 char * committer = NULL ;
2727- char * sig_alg = NULL ;
27282800 char * encoding = NULL ;
27292801 struct hash_list * merge_list = NULL ;
27302802 unsigned int merge_count ;
@@ -2748,13 +2820,23 @@ static void parse_new_commit(const char *arg)
27482820 }
27492821 if (!committer )
27502822 die ("Expected committer but didn't get one" );
2751- if (skip_prefix (command_buf .buf , "gpgsig " , & v )) {
2752- sig_alg = xstrdup (v );
2753- read_next_command ();
2754- parse_data (& sig , 0 , NULL );
2823+
2824+ /* Process signatures (up to 2: one "sha1" and one "sha256") */
2825+ while (skip_prefix (command_buf .buf , "gpgsig " , & v )) {
2826+ struct signature_data sig = { NULL , NULL , STRBUF_INIT };
2827+
2828+ parse_one_signature (& sig , v );
2829+
2830+ if (!strcmp (sig .hash_algo , "sha1" ))
2831+ store_signature (& sig_sha1 , & sig , "SHA-1" );
2832+ else if (!strcmp (sig .hash_algo , "sha256" ))
2833+ store_signature (& sig_sha256 , & sig , "SHA-256" );
2834+ else
2835+ BUG ("parse_one_signature() returned unknown hash algo" );
2836+
27552837 read_next_command ();
2756- } else
2757- strbuf_setlen ( & sig , 0 );
2838+ }
2839+
27582840 if (skip_prefix (command_buf .buf , "encoding " , & v )) {
27592841 encoding = xstrdup (v );
27602842 read_next_command ();
@@ -2828,23 +2910,14 @@ static void parse_new_commit(const char *arg)
28282910 strbuf_addf (& new_data ,
28292911 "encoding %s\n" ,
28302912 encoding );
2831- if (sig_alg ) {
2832- if (!strcmp (sig_alg , "sha1" ))
2833- strbuf_addstr (& new_data , "gpgsig " );
2834- else if (!strcmp (sig_alg , "sha256" ))
2835- strbuf_addstr (& new_data , "gpgsig-sha256 " );
2836- else
2837- die ("Expected gpgsig algorithm sha1 or sha256, got %s" , sig_alg );
2838- string_list_split_in_place (& siglines , sig .buf , "\n" , -1 );
2839- strbuf_add_separated_string_list (& new_data , "\n " , & siglines );
2840- strbuf_addch (& new_data , '\n' );
2841- }
2913+
2914+ add_gpgsig_to_commit (& new_data , "gpgsig " , & sig_sha1 );
2915+ add_gpgsig_to_commit (& new_data , "gpgsig-sha256 " , & sig_sha256 );
2916+
28422917 strbuf_addch (& new_data , '\n' );
28432918 strbuf_addbuf (& new_data , & msg );
2844- string_list_clear (& siglines , 1 );
28452919 free (author );
28462920 free (committer );
2847- free (sig_alg );
28482921 free (encoding );
28492922
28502923 if (!store_object (OBJ_COMMIT , & new_data , NULL , & b -> oid , next_mark ))
0 commit comments