hgext/gpg.py
changeset 46113 59fa3890d40a
parent 45942 89a2afe31e82
child 47012 d55b71393907
child 47062 f38bf44e077f
equal deleted inserted replaced
46112:d6afa9c149c3 46113:59fa3890d40a
     9 
     9 
    10 import binascii
    10 import binascii
    11 import os
    11 import os
    12 
    12 
    13 from mercurial.i18n import _
    13 from mercurial.i18n import _
       
    14 from mercurial.node import (
       
    15     bin,
       
    16     hex,
       
    17     nullid,
       
    18     short,
       
    19 )
    14 from mercurial import (
    20 from mercurial import (
    15     cmdutil,
    21     cmdutil,
    16     error,
    22     error,
    17     help,
    23     help,
    18     match,
    24     match,
    19     node as hgnode,
       
    20     pycompat,
    25     pycompat,
    21     registrar,
    26     registrar,
    22 )
    27 )
    23 from mercurial.utils import (
    28 from mercurial.utils import (
    24     dateutil,
    29     dateutil,
   153             ln += 1
   158             ln += 1
   154 
   159 
   155     # read the heads
   160     # read the heads
   156     fl = repo.file(b".hgsigs")
   161     fl = repo.file(b".hgsigs")
   157     for r in reversed(fl.heads()):
   162     for r in reversed(fl.heads()):
   158         fn = b".hgsigs|%s" % hgnode.short(r)
   163         fn = b".hgsigs|%s" % short(r)
   159         for item in parsefile(fl.read(r).splitlines(), fn):
   164         for item in parsefile(fl.read(r).splitlines(), fn):
   160             yield item
   165             yield item
   161     try:
   166     try:
   162         # read local signatures
   167         # read local signatures
   163         fn = b"localsigs"
   168         fn = b"localsigs"
   170 def getkeys(ui, repo, mygpg, sigdata, context):
   175 def getkeys(ui, repo, mygpg, sigdata, context):
   171     """get the keys who signed a data"""
   176     """get the keys who signed a data"""
   172     fn, ln = context
   177     fn, ln = context
   173     node, version, sig = sigdata
   178     node, version, sig = sigdata
   174     prefix = b"%s:%d" % (fn, ln)
   179     prefix = b"%s:%d" % (fn, ln)
   175     node = hgnode.bin(node)
   180     node = bin(node)
   176 
   181 
   177     data = node2txt(repo, node, version)
   182     data = node2txt(repo, node, version)
   178     sig = binascii.a2b_base64(sig)
   183     sig = binascii.a2b_base64(sig)
   179     keys = mygpg.verify(data, sig)
   184     keys = mygpg.verify(data, sig)
   180 
   185 
   221             continue
   226             continue
   222         revs.setdefault(r, [])
   227         revs.setdefault(r, [])
   223         revs[r].extend(keys)
   228         revs[r].extend(keys)
   224     for rev in sorted(revs, reverse=True):
   229     for rev in sorted(revs, reverse=True):
   225         for k in revs[rev]:
   230         for k in revs[rev]:
   226             r = b"%5d:%s" % (rev, hgnode.hex(repo.changelog.node(rev)))
   231             r = b"%5d:%s" % (rev, hex(repo.changelog.node(rev)))
   227             ui.write(b"%-30s %s\n" % (keystr(ui, k), r))
   232             ui.write(b"%-30s %s\n" % (keystr(ui, k), r))
   228 
   233 
   229 
   234 
   230 @command(b"sigcheck", [], _(b'hg sigcheck REV'), helpcategory=_HELP_CATEGORY)
   235 @command(b"sigcheck", [], _(b'hg sigcheck REV'), helpcategory=_HELP_CATEGORY)
   231 def sigcheck(ui, repo, rev):
   236 def sigcheck(ui, repo, rev):
   232     """verify all the signatures there may be for a particular revision"""
   237     """verify all the signatures there may be for a particular revision"""
   233     mygpg = newgpg(ui)
   238     mygpg = newgpg(ui)
   234     rev = repo.lookup(rev)
   239     rev = repo.lookup(rev)
   235     hexrev = hgnode.hex(rev)
   240     hexrev = hex(rev)
   236     keys = []
   241     keys = []
   237 
   242 
   238     for data, context in sigwalk(repo):
   243     for data, context in sigwalk(repo):
   239         node, version, sig = data
   244         node, version, sig = data
   240         if node == hexrev:
   245         if node == hexrev:
   241             k = getkeys(ui, repo, mygpg, data, context)
   246             k = getkeys(ui, repo, mygpg, data, context)
   242             if k:
   247             if k:
   243                 keys.extend(k)
   248                 keys.extend(k)
   244 
   249 
   245     if not keys:
   250     if not keys:
   246         ui.write(_(b"no valid signature for %s\n") % hgnode.short(rev))
   251         ui.write(_(b"no valid signature for %s\n") % short(rev))
   247         return
   252         return
   248 
   253 
   249     # print summary
   254     # print summary
   250     ui.write(_(b"%s is signed by:\n") % hgnode.short(rev))
   255     ui.write(_(b"%s is signed by:\n") % short(rev))
   251     for key in keys:
   256     for key in keys:
   252         ui.write(b" %s\n" % keystr(ui, key))
   257         ui.write(b" %s\n" % keystr(ui, key))
   253 
   258 
   254 
   259 
   255 def keystr(ui, key):
   260 def keystr(ui, key):
   307         opts[b'date'] = dateutil.parsedate(date)
   312         opts[b'date'] = dateutil.parsedate(date)
   308 
   313 
   309     if revs:
   314     if revs:
   310         nodes = [repo.lookup(n) for n in revs]
   315         nodes = [repo.lookup(n) for n in revs]
   311     else:
   316     else:
   312         nodes = [
   317         nodes = [node for node in repo.dirstate.parents() if node != nullid]
   313             node for node in repo.dirstate.parents() if node != hgnode.nullid
       
   314         ]
       
   315         if len(nodes) > 1:
   318         if len(nodes) > 1:
   316             raise error.Abort(
   319             raise error.Abort(
   317                 _(b'uncommitted merge - please provide a specific revision')
   320                 _(b'uncommitted merge - please provide a specific revision')
   318             )
   321             )
   319         if not nodes:
   322         if not nodes:
   320             nodes = [repo.changelog.tip()]
   323             nodes = [repo.changelog.tip()]
   321 
   324 
   322     for n in nodes:
   325     for n in nodes:
   323         hexnode = hgnode.hex(n)
   326         hexnode = hex(n)
   324         ui.write(
   327         ui.write(_(b"signing %d:%s\n") % (repo.changelog.rev(n), short(n)))
   325             _(b"signing %d:%s\n") % (repo.changelog.rev(n), hgnode.short(n))
       
   326         )
       
   327         # build data
   328         # build data
   328         data = node2txt(repo, n, sigver)
   329         data = node2txt(repo, n, sigver)
   329         sig = mygpg.sign(data)
   330         sig = mygpg.sign(data)
   330         if not sig:
   331         if not sig:
   331             raise error.Abort(_(b"error while signing"))
   332             raise error.Abort(_(b"error while signing"))
   358 
   359 
   359     message = opts[b'message']
   360     message = opts[b'message']
   360     if not message:
   361     if not message:
   361         # we don't translate commit messages
   362         # we don't translate commit messages
   362         message = b"\n".join(
   363         message = b"\n".join(
   363             [
   364             [b"Added signature for changeset %s" % short(n) for n in nodes]
   364                 b"Added signature for changeset %s" % hgnode.short(n)
       
   365                 for n in nodes
       
   366             ]
       
   367         )
   365         )
   368     try:
   366     try:
   369         editor = cmdutil.getcommiteditor(
   367         editor = cmdutil.getcommiteditor(
   370             editform=b'gpg.sign', **pycompat.strkwargs(opts)
   368             editform=b'gpg.sign', **pycompat.strkwargs(opts)
   371         )
   369         )
   377 
   375 
   378 
   376 
   379 def node2txt(repo, node, ver):
   377 def node2txt(repo, node, ver):
   380     """map a manifest into some text"""
   378     """map a manifest into some text"""
   381     if ver == b"0":
   379     if ver == b"0":
   382         return b"%s\n" % hgnode.hex(node)
   380         return b"%s\n" % hex(node)
   383     else:
   381     else:
   384         raise error.Abort(_(b"unknown signature version"))
   382         raise error.Abort(_(b"unknown signature version"))
   385 
   383 
   386 
   384 
   387 def extsetup(ui):
   385 def extsetup(ui):