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,82 @@ 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", or "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 + 1 ;
2738+
2739+ /* Validate hash algorithm */
2740+ if (strcmp (sig -> hash_algo , "sha1" ) &&
2741+ strcmp (sig -> hash_algo , "sha256" ))
2742+ die ("Unknown git hash algorithm in gpgsig: '%s'" , sig -> hash_algo );
2743+
2744+ /* Validate signature format */
2745+ if (!valid_signature_format (sig -> sig_format ))
2746+ die ("Invalid signature format in gpgsig: '%s'" , sig -> sig_format );
2747+ if (!strcmp (sig -> sig_format , "unknown" ))
2748+ warning ("'unknown' signature format in gpgsig" );
2749+
2750+ /* Read signature data */
2751+ read_next_command ();
2752+ parse_data (& sig -> data , 0 , NULL );
2753+ }
2754+
2755+ static void add_gpgsig_to_commit (struct strbuf * commit_data ,
2756+ const char * header ,
2757+ struct signature_data * sig )
2758+ {
2759+ struct string_list siglines = STRING_LIST_INIT_NODUP ;
2760+
2761+ if (!sig -> hash_algo )
2762+ return ;
2763+
2764+ strbuf_addstr (commit_data , header );
2765+ string_list_split_in_place (& siglines , sig -> data .buf , "\n" , -1 );
2766+ strbuf_add_separated_string_list (commit_data , "\n " , & siglines );
2767+ strbuf_addch (commit_data , '\n' );
2768+ string_list_clear (& siglines , 1 );
2769+ strbuf_release (& sig -> data );
2770+ free (sig -> hash_algo );
2771+ }
2772+
2773+ static void store_signature (struct signature_data * stored_sig ,
2774+ struct signature_data * new_sig ,
2775+ const char * hash_type )
2776+ {
2777+ if (stored_sig -> hash_algo ) {
2778+ warning ("multiple %s signatures found, "
2779+ "ignoring additional signature" ,
2780+ hash_type );
2781+ strbuf_release (& new_sig -> data );
2782+ free (new_sig -> hash_algo );
2783+ } else {
2784+ * stored_sig = * new_sig ;
2785+ }
2786+ }
2787+
27192788static void parse_new_commit (const char * arg )
27202789{
2721- static struct strbuf sig = STRBUF_INIT ;
27222790 static struct strbuf msg = STRBUF_INIT ;
2723- struct string_list siglines = STRING_LIST_INIT_NODUP ;
2791+ struct signature_data sig_sha1 = { NULL , NULL , STRBUF_INIT };
2792+ struct signature_data sig_sha256 = { NULL , NULL , STRBUF_INIT };
27242793 struct branch * b ;
27252794 char * author = NULL ;
27262795 char * committer = NULL ;
2727- char * sig_alg = NULL ;
27282796 char * encoding = NULL ;
27292797 struct hash_list * merge_list = NULL ;
27302798 unsigned int merge_count ;
@@ -2748,13 +2816,23 @@ static void parse_new_commit(const char *arg)
27482816 }
27492817 if (!committer )
27502818 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 );
2819+
2820+ /* Process signatures (up to 2: one "sha1" and one "sha256") */
2821+ while (skip_prefix (command_buf .buf , "gpgsig " , & v )) {
2822+ struct signature_data sig = { NULL , NULL , STRBUF_INIT };
2823+
2824+ parse_one_signature (& sig , v );
2825+
2826+ if (!strcmp (sig .hash_algo , "sha1" ))
2827+ store_signature (& sig_sha1 , & sig , "SHA-1" );
2828+ else if (!strcmp (sig .hash_algo , "sha256" ))
2829+ store_signature (& sig_sha256 , & sig , "SHA-256" );
2830+ else
2831+ BUG ("parse_one_signature() returned unknown hash algo" );
2832+
27552833 read_next_command ();
2756- } else
2757- strbuf_setlen ( & sig , 0 );
2834+ }
2835+
27582836 if (skip_prefix (command_buf .buf , "encoding " , & v )) {
27592837 encoding = xstrdup (v );
27602838 read_next_command ();
@@ -2828,23 +2906,14 @@ static void parse_new_commit(const char *arg)
28282906 strbuf_addf (& new_data ,
28292907 "encoding %s\n" ,
28302908 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- }
2909+
2910+ add_gpgsig_to_commit (& new_data , "gpgsig " , & sig_sha1 );
2911+ add_gpgsig_to_commit (& new_data , "gpgsig-sha256 " , & sig_sha256 );
2912+
28422913 strbuf_addch (& new_data , '\n' );
28432914 strbuf_addbuf (& new_data , & msg );
2844- string_list_clear (& siglines , 1 );
28452915 free (author );
28462916 free (committer );
2847- free (sig_alg );
28482917 free (encoding );
28492918
28502919 if (!store_object (OBJ_COMMIT , & new_data , NULL , & b -> oid , next_mark ))
0 commit comments