@@ -424,6 +424,7 @@ class MetaData:
424424 self .keyhash = None
425425 self .template = None
426426 self .defaultbranch = None
427+ self .gpgkeys = []
427428
428429 def init (self , gpgkeys , template , defaultbranch ):
429430 'initialize the metadata'
@@ -447,6 +448,14 @@ class MetaData:
447448 self .write ()
448449 return self
449450
451+ def addkey (self , gpgkeys ):
452+ 'add gpg key'
453+ self .gpgkeys += gpgkeys
454+ cryptedkey = subprocess .check_output (
455+ ['gpg' , '-q' , '-e' ] + ['-r' + k for k in self .gpgkeys ],
456+ input = MetaData .KEYVER + b'\x00 ' + self .key )
457+ self .files ['key' ] = self .repo .create_blob (cryptedkey )
458+
450459 def read (self ):
451460 'read the metadata'
452461 self .files = {}
@@ -468,6 +477,13 @@ class MetaData:
468477 keyver , self .key = data .split (b'\x00 ' , 1 )
469478 assert keyver == MetaData .KEYVER , \
470479 f'Key format is { keyver } , expected { MetaData .KEYVER } '
480+ keydata = subprocess .check_output (
481+ ['gpg' , '-q' , '--list-packets' ],
482+ input = obj .read_raw ()).decode ('utf-8' ).split ('\n ' )
483+ for k in keydata :
484+ match = re .search (r'^:pubkey enc packet:.*keyid ([0-9A-F]+)' , k )
485+ if match :
486+ self .gpgkeys .append (match .group (1 ))
471487 self .files ['sig' ] = tree ['sig' ].id
472488 obj = tree ['msg' ]
473489 self .files ['msg' ] = obj .id
@@ -568,12 +584,27 @@ def init_command(args):
568584 crypt .push ([])
569585
570586
587+ def addkey_command (args ):
588+ 'add key to incrypt repository'
589+ try :
590+ url = pygit2 .Repository ('.' ).remotes [args .remote ].url
591+ except (KeyError , ValueError ):
592+ url = args .remote
593+ assert url .startswith ('incrypt::' ), \
594+ f'url `{ url } ` must start with incrypt::'
595+ crypt = CryptRepo ('.' , url [9 :])
596+ crypt .meta .addkey (args .keys )
597+ crypt .push ([])
598+
599+
571600def trust_command (args ):
572601 'trust incrypt repository'
573- remotes = pygit2 .Repository ('.' ).remotes
574- url = remotes [args .remote ].url if args .remote in remotes else args .remote
602+ try :
603+ url = pygit2 .Repository ('.' ).remotes [args .remote ].url
604+ except (KeyError , ValueError ):
605+ url = args .remote
575606 assert url .startswith ('incrypt::' ), \
576- 'url must start with incrypt::'
607+ f 'url ` { url } ` must start with incrypt::'
577608 crypt = CryptRepo ('.' , url [9 :], forcetrust = True )
578609 if args .sign :
579610 crypt .meta .sign ()
@@ -607,6 +638,13 @@ def tool():
607638 init_parser .add_argument (
608639 'keys' , nargs = '+' , help = 'GPG keys used to encrypt the data' )
609640 init_parser .set_defaults (func = init_command )
641+ addkey_parser = subparsers .add_parser (
642+ 'addkey' , help = 'Add an encryption key' )
643+ addkey_parser .add_argument (
644+ 'remote' , type = str , help = 'Name of the remote' )
645+ addkey_parser .add_argument (
646+ 'keys' , nargs = '+' , help = 'GPG keys to add' )
647+ addkey_parser .set_defaults (func = addkey_command )
610648 trust_parser = subparsers .add_parser (
611649 'trust' , help = 'Trust the remote repository' )
612650 trust_parser .add_argument (
0 commit comments