66#include "diff.h"
77#include "revision.h"
88#include "notes.h"
9+ #include "gpg-interface.h"
910
1011int save_commit_buffer = 1 ;
1112
@@ -840,6 +841,86 @@ struct commit_list *reduce_heads(struct commit_list *heads)
840841 return result ;
841842}
842843
844+ static const char gpg_sig_header [] = "gpgsig" ;
845+ static const int gpg_sig_header_len = sizeof (gpg_sig_header ) - 1 ;
846+
847+ static int do_sign_commit (struct strbuf * buf , const char * keyid )
848+ {
849+ struct strbuf sig = STRBUF_INIT ;
850+ int inspos , copypos ;
851+
852+ /* find the end of the header */
853+ inspos = strstr (buf -> buf , "\n\n" ) - buf -> buf + 1 ;
854+
855+ if (!keyid || !* keyid )
856+ keyid = get_signing_key ();
857+ if (sign_buffer (buf , & sig , keyid )) {
858+ strbuf_release (& sig );
859+ return -1 ;
860+ }
861+
862+ for (copypos = 0 ; sig .buf [copypos ]; ) {
863+ const char * bol = sig .buf + copypos ;
864+ const char * eol = strchrnul (bol , '\n' );
865+ int len = (eol - bol ) + !!* eol ;
866+
867+ if (!copypos ) {
868+ strbuf_insert (buf , inspos , gpg_sig_header , gpg_sig_header_len );
869+ inspos += gpg_sig_header_len ;
870+ }
871+ strbuf_insert (buf , inspos ++ , " " , 1 );
872+ strbuf_insert (buf , inspos , bol , len );
873+ inspos += len ;
874+ copypos += len ;
875+ }
876+ strbuf_release (& sig );
877+ return 0 ;
878+ }
879+
880+ int parse_signed_commit (const unsigned char * sha1 ,
881+ struct strbuf * payload , struct strbuf * signature )
882+ {
883+ unsigned long size ;
884+ enum object_type type ;
885+ char * buffer = read_sha1_file (sha1 , & type , & size );
886+ int in_signature , saw_signature = -1 ;
887+ char * line , * tail ;
888+
889+ if (!buffer || type != OBJ_COMMIT )
890+ goto cleanup ;
891+
892+ line = buffer ;
893+ tail = buffer + size ;
894+ in_signature = 0 ;
895+ saw_signature = 0 ;
896+ while (line < tail ) {
897+ const char * sig = NULL ;
898+ char * next = memchr (line , '\n' , tail - line );
899+
900+ next = next ? next + 1 : tail ;
901+ if (in_signature && line [0 ] == ' ' )
902+ sig = line + 1 ;
903+ else if (!prefixcmp (line , gpg_sig_header ) &&
904+ line [gpg_sig_header_len ] == ' ' )
905+ sig = line + gpg_sig_header_len + 1 ;
906+ if (sig ) {
907+ strbuf_add (signature , sig , next - sig );
908+ saw_signature = 1 ;
909+ in_signature = 1 ;
910+ } else {
911+ if (* line == '\n' )
912+ /* dump the whole remainder of the buffer */
913+ next = tail ;
914+ strbuf_add (payload , line , next - line );
915+ in_signature = 0 ;
916+ }
917+ line = next ;
918+ }
919+ cleanup :
920+ free (buffer );
921+ return saw_signature ;
922+ }
923+
843924static void handle_signed_tag (struct commit * parent , struct commit_extra_header * * * tail )
844925{
845926 struct merge_remote_desc * desc ;
@@ -975,13 +1056,14 @@ void free_commit_extra_headers(struct commit_extra_header *extra)
9751056
9761057int commit_tree (const char * msg , unsigned char * tree ,
9771058 struct commit_list * parents , unsigned char * ret ,
978- const char * author )
1059+ const char * author , const char * sign_commit )
9791060{
9801061 struct commit_extra_header * extra = NULL , * * tail = & extra ;
9811062 int result ;
9821063
9831064 append_merge_tag_headers (parents , & tail );
984- result = commit_tree_extended (msg , tree , parents , ret , author , extra );
1065+ result = commit_tree_extended (msg , tree , parents , ret ,
1066+ author , sign_commit , extra );
9851067 free_commit_extra_headers (extra );
9861068 return result ;
9871069}
@@ -993,7 +1075,8 @@ static const char commit_utf8_warn[] =
9931075
9941076int commit_tree_extended (const char * msg , unsigned char * tree ,
9951077 struct commit_list * parents , unsigned char * ret ,
996- const char * author , struct commit_extra_header * extra )
1078+ const char * author , const char * sign_commit ,
1079+ struct commit_extra_header * extra )
9971080{
9981081 int result ;
9991082 int encoding_is_utf8 ;
@@ -1043,6 +1126,9 @@ int commit_tree_extended(const char *msg, unsigned char *tree,
10431126 if (encoding_is_utf8 && !is_utf8 (buffer .buf ))
10441127 fprintf (stderr , commit_utf8_warn );
10451128
1129+ if (sign_commit && do_sign_commit (& buffer , sign_commit ))
1130+ return -1 ;
1131+
10461132 result = write_sha1_file (buffer .buf , buffer .len , commit_type , ret );
10471133 strbuf_release (& buffer );
10481134 return result ;
0 commit comments