File: sign_ca.py

package info (click to toggle)
cmake-format 0.6.13-7
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,436 kB
  • sloc: python: 16,990; makefile: 14
file content (161 lines) | stat: -rw-r--r-- 4,775 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
"""
Generate the copyright assignment document from the template, and optionally
sign it with gpg.
"""

import argparse
import collections
import io
import json
import os
import subprocess
import sys
import tempfile


def get_signature_packet(infile):
  """
  Return the ascii-armored signature packet between the lines:
  -----BEGIN PGP SIGNATURE-----

  <packet-content>
  -----END PGP SIGNATURE-----
  """

  lineiter = iter(infile)
  for line in lineiter:
    if "BEGIN PGP SIGNATURE" in line:
      break

  packetlines = []
  next(lineiter)
  for line in lineiter:
    if "END PGP SIGNATURE" in line:
      return packetlines
    packetlines.append(line.strip())

  raise ValueError("no PGP BEGIN/END tags in file content!")


def generate_document(args):
  thisdir = os.path.dirname(os.path.realpath(__file__))
  with io.open(os.path.join(thisdir, "individual_ca.txt"),
               encoding="utf-8") as infile:
    output_text = infile.read()
  output_text = output_text.replace(r"{{signer_name}}", args.name)
  output_text = output_text.replace(r"{{signer_email}}", args.email)

  with io.open(args.output_text, "w", encoding="utf-8") as outfile:
    outfile.write(output_text)

  if args.only_template:
    print(
        "The contributor agreement has been written to {}, please sign it with "
        "GPG and include the signature in your first contribution"
        .format(args.output_text))
    return

  argv = ["gpg", "--output", args.output_sig]
  if args.signkey is not None:
    argv.extend(["--default-key", args.signkey])
  argv.extend(["--armor", "--detach-sign", args.output_text])
  subprocess.call(argv)
  print(
      "The contributor agreement has been written to {}, and the signature "
      "has been written to {}"
      .format(args.output_text, args.output_sig))


def setup_parser(parser):
  """
  Configure command line parser
  """
  default_name = None
  try:
    default_name = subprocess.check_output(
        ["git", "config", "user.name"]).decode("utf-8").strip()
  except subprocess.CalledProcessError:
    pass

  default_email = None
  try:
    default_email = subprocess.check_output(
        ["git", "config", "user.email"]).decode("utf-8").strip()
  except subprocess.CalledProcessError:
    pass

  default_signkey = None
  try:
    default_signkey = subprocess.check_output(
        ["git", "config", "user.signingkey"]).decode("utf-8").strip()
  except subprocess.CalledProcessError:
    pass

  parser.add_argument(
      "-n", "--name",
      default=default_name,
      required=(default_name is None),
      help=("Your name (to fill in the agreement template). Default={}"
            .format(default_name)))

  parser.add_argument(
      "-e", "--email",
      default=default_email,
      required=(default_email is None),
      help=("Your name (to fill in the agreement template). Default={}"
            .format(default_email)))

  parser.add_argument(
      "-k", "--signkey",
      default=default_signkey,
      help=("Which signing key to use if you don't want to use your gpg "
            "default. Default={}".format(default_signkey)))

  default_outpath = os.path.join(tempfile.gettempdir(), "cmake-format-ca.txt")
  default_sigout = os.path.join(tempfile.gettempdir(), "cmake-format-ca.sig")
  parser.add_argument(
      "-o", "--output-text", default=default_outpath,
      help=r"Where to write out the agreement text. Default is"
           r"/{tempdir}/cmake-format-ca.txt")
  parser.add_argument(
      "-s", "--output-sig", default=default_sigout,
      help=r"Where to write out the signature. Default is"
           r"/{tempdir}/cmake-format-ca.sig")

  parser.add_argument(
      "-t", "--only-template", action="store_true",
      help="Don't attempt to sign the document with gpg, just fill in the"
           " template and write to a file.")


def main():
  parser = argparse.ArgumentParser(description=__doc__)
  setup_parser(parser)
  args = parser.parse_args()
  generate_document(args)
  if args.only_template:
    return 0

  with io.open(args.output_sig, "r", encoding="utf-8") as infile:
    packetlines = get_signature_packet(infile)

  dataitem = collections.OrderedDict([
      ("template", "individual"),
      ("version", "1.0"),
      ("name", args.name),
      ("email", args.email),
      ("signature", packetlines)
  ])

  thisdir = os.path.dirname(os.path.realpath(__file__))
  database_path = os.path.join(thisdir, "signature_db.json")
  with io.open(database_path, "r", encoding="utf-8") as infile:
    database = json.load(infile, object_pairs_hook=collections.OrderedDict)
  database.append(dataitem)
  with io.open(database_path, "w", encoding="utf-8") as outfile:
    json.dump(database, outfile, indent=2)
  return 0


if __name__ == "__main__":
  sys.exit(main())