/usr/bin/repomapper is in reposurgeon 3.37-1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
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 | #! /usr/bin/python3
# SPDX-License-Identifier: BSD-2-Clause
"""
repomapper - update and manipulate contributor maps
"""
# This code runs under both Python 2 and Python 3: preserve this property!
from __future__ import print_function
import sys, re, getopt, io
binary_encoding = 'latin-1'
def make_std_wrapper(stream):
"Standard input/output wrapper factory function"
# This ensures that the encoding of standard output and standard
# error on Python 3 matches the binary encoding we use to turn
# bytes to Unicode in polystr above; it has no effect on Python 2
# since the output streams are binary
if isinstance(stream, io.TextIOWrapper):
# newline="\n" ensures that Python 3 won't mangle line breaks
# line_buffering=True ensures that interactive command sessions work as expected
return io.TextIOWrapper(stream.buffer, encoding=binary_encoding, newline="\n", line_buffering=True)
return stream
#sys.stdin = make_std_wrapper(sys.stdin)
sys.stdout = make_std_wrapper(sys.stdout)
#sys.stderr = make_std_wrapper(sys.stderr)
class Contributor:
"Associate a usename with a DVCS-style ID."
def __init__(self, name, fullname, email, tz):
self.name = name
self.fullname = fullname
self.email = email
self.tz = tz
def incomplete(self):
"Does this entry need completion?"
return self.name == self.fullname or "@" not in self.email
def __str__(self):
out = "%s = %s <%s>" % (self.name, self.fullname, self.email)
if self.tz:
out += " " + self.tz
out += "\n"
if "x" == b"x":
return out.encode('latin-1')
return out
class ContribMap:
"A map of contributors."
def __init__(self, fn):
self.payload = {}
for line in open(fn, "rb"):
line = line.decode(binary_encoding)
m = re.match(r"([^ ]+) *= ([^<]+)*<([^<]+)> *(.*)", line)
if m is None:
sys.stderr.write("repomapper: malformed attribution line %s.\n" % repr(line))
sys.exit(1)
name = m.group(1)
fullname = m.group(2).strip()
email = m.group(3)
tz = m.group(4)
self.payload[name] = Contributor(name, fullname, email, tz)
def suffix(self, addr):
"Add an address suffix to entries lacking one."
for (_name, obj) in self.payload.items():
if '@' not in obj.email:
obj.email += "@" + addr
def write(self, fp, incomplete=False):
"Write the current state of this contrib map."
keys = list(self.payload.keys())
keys.sort()
for name in keys:
if incomplete and not self.payload[name].incomplete():
continue
fp.write(str(self.payload[name]))
if __name__ == '__main__':
host = ""
passwdfile = None
updatefile = None
incomplete = False
(options, arguments) = getopt.getopt(sys.argv[1:], "h:ip:u:",
["host=", "passwd="])
for (opt, val) in options:
if opt == '-h' or opt == '--host':
host = val
elif opt == '-i':
incomplete = True
elif opt == '-p' or opt == '--passwd':
passwdfile = val
elif opt == "-u":
updatefile = val
if len(arguments) < 1:
sys.stderr.write("repomapper: requires a contrib-map file argument.\n")
sys.exit(1)
# Read in an ordered dictionary of existing attributions.
contribmap = ContribMap(arguments[0])
# Apply the -h option
if host:
contribmap.suffix(host)
# With -p, read the password data
if passwdfile:
passwd = {}
for line in open(passwdfile, "rb"):
line = line.decode(binary_encoding)
try:
(name, _hash, _uid, _gid, gecos, _home, _dir) = line.split(":")
if "," in gecos:
gecos = gecos.split(",").pop(0)
passwd[name] = gecos
except ValueError:
sys.stderr.write("repomapper: malformed passwd line.\n")
sys.exit(1)
# Attempt to fill in the contribmap
for (name, obj) in contribmap.payload.items():
if name not in passwd:
sys.stderr.write("repomapper: %s not in password file.\n" % name)
elif obj.fullname == name:
contribmap.payload[name].fullname = passwd[name]
elif obj.fullname.lower() != passwd[name].lower():
sys.stderr.write("repomapper: %s -> %s should be %s.\n" % (name, obj.fullname, passwd[name]))
# Now dump the result
contribmap.write(sys.stdout, incomplete=False)
raise SystemExit(0)
# With -u, copy in all complete entries in the update file
if updatefile:
updatemap = ContribMap(updatefile)
for (name, obj) in updatemap.payload.items():
if name not in contribmap.payload:
contribmap.payload[name] = obj
# Now dump the result
contribmap.write(sys.stdout, incomplete=False)
raise SystemExit(0)
# By default, report on incomplete entries
contribmap.write(sys.stdout, incomplete=incomplete)
# end
|