mirror of
https://github.com/jedisct1/libsodium.git
synced 2024-12-19 18:15:18 -07:00
Update the dotnet-core release script
This commit is contained in:
parent
927dfe8e2e
commit
fb5e0e45f4
@ -8,8 +8,8 @@ WINDOWS = [
|
||||
# --------------------- ----------------- #
|
||||
# Runtime ID Platform #
|
||||
# --------------------- ----------------- #
|
||||
('win-x64', 'x64'),
|
||||
('win-x86', 'Win32'),
|
||||
("win-x64", "x64"),
|
||||
("win-x86", "Win32"),
|
||||
# --------------------- ----------------- #
|
||||
]
|
||||
|
||||
@ -17,7 +17,7 @@ MACOS = [
|
||||
# --------------------- ----------------- #
|
||||
# Runtime ID Codename #
|
||||
# --------------------- ----------------- #
|
||||
('osx-x64', 'mojave'),
|
||||
("osx-x64", "mojave"),
|
||||
# --------------------- ----------------- #
|
||||
]
|
||||
|
||||
@ -25,26 +25,25 @@ LINUX = [
|
||||
# --------------------- ----------------- #
|
||||
# Runtime ID Docker Image #
|
||||
# --------------------- ----------------- #
|
||||
('linux-x64', 'debian:stretch'),
|
||||
("linux-x64", "debian:stretch"),
|
||||
# --------------------- ----------------- #
|
||||
]
|
||||
|
||||
EXTRAS = ['LICENSE', 'AUTHORS', 'ChangeLog']
|
||||
EXTRAS = ["LICENSE", "AUTHORS", "ChangeLog"]
|
||||
|
||||
PROPSFILE = 'libsodium.props'
|
||||
MAKEFILE = 'Makefile'
|
||||
BUILDDIR = 'build'
|
||||
CACHEDIR = 'cache'
|
||||
TEMPDIR = 'temp'
|
||||
PROPSFILE = "libsodium.props"
|
||||
MAKEFILE = "Makefile"
|
||||
BUILDDIR = "build"
|
||||
CACHEDIR = "cache"
|
||||
TEMPDIR = "temp"
|
||||
|
||||
PACKAGE = 'libsodium'
|
||||
LIBRARY = 'libsodium'
|
||||
PACKAGE = "libsodium"
|
||||
LIBRARY = "libsodium"
|
||||
|
||||
DOCKER = 'sudo docker'
|
||||
DOCKER = "sudo docker"
|
||||
|
||||
|
||||
class Version:
|
||||
|
||||
def __init__(self, libsodium_version, package_version):
|
||||
self.libsodium_version = libsodium_version
|
||||
self.package_version = package_version
|
||||
@ -52,225 +51,252 @@ class Version:
|
||||
self.builddir = os.path.join(BUILDDIR, libsodium_version)
|
||||
self.tempdir = os.path.join(TEMPDIR, libsodium_version)
|
||||
self.projfile = os.path.join(
|
||||
self.builddir, '{0}.{1}.pkgproj'.format(PACKAGE, package_version))
|
||||
self.propsfile = os.path.join(
|
||||
self.builddir, '{0}.props'.format(PACKAGE))
|
||||
self.builddir, "{0}.{1}.pkgproj".format(PACKAGE, package_version)
|
||||
)
|
||||
self.propsfile = os.path.join(self.builddir, "{0}.props".format(PACKAGE))
|
||||
self.pkgfile = os.path.join(
|
||||
BUILDDIR, '{0}.{1}.nupkg'.format(PACKAGE, package_version))
|
||||
BUILDDIR, "{0}.{1}.nupkg".format(PACKAGE, package_version)
|
||||
)
|
||||
|
||||
|
||||
class WindowsItem:
|
||||
|
||||
def __init__(self, version, rid, platform):
|
||||
self.url = 'https://download.libsodium.org/libsodium/releases/libsodium-{0}-msvc.zip'.format(
|
||||
version.libsodium_version)
|
||||
self.cachefile = os.path.join(
|
||||
CACHEDIR, re.sub(r'[^A-Za-z0-9.]', '-', self.url))
|
||||
self.url = "https://download.libsodium.org/libsodium/releases/libsodium-{0}-stable-msvc.zip".format(
|
||||
version.libsodium_version
|
||||
)
|
||||
self.cachefile = os.path.join(CACHEDIR, re.sub(r"[^A-Za-z0-9.]", "-", self.url))
|
||||
self.packfile = os.path.join(
|
||||
version.builddir, 'runtimes', rid, 'native', LIBRARY + '.dll')
|
||||
self.itemfile = '{0}/Release/v140/dynamic/libsodium.dll'.format(
|
||||
platform)
|
||||
version.builddir, "runtimes", rid, "native", LIBRARY + ".dll"
|
||||
)
|
||||
self.itemfile = "{0}/Release/v140/dynamic/libsodium.dll".format(platform)
|
||||
self.tempdir = os.path.join(version.tempdir, rid)
|
||||
self.tempfile = os.path.join(
|
||||
self.tempdir, os.path.normpath(self.itemfile))
|
||||
self.tempfile = os.path.join(self.tempdir, os.path.normpath(self.itemfile))
|
||||
|
||||
def make(self, f):
|
||||
f.write('\n')
|
||||
f.write('{0}: {1}\n'.format(self.packfile, self.tempfile))
|
||||
f.write('\t@mkdir -p $(dir $@)\n')
|
||||
f.write('\tcp -f $< $@\n')
|
||||
f.write('\n')
|
||||
f.write('{0}: {1}\n'.format(self.tempfile, self.cachefile))
|
||||
f.write('\t@mkdir -p $(dir $@)\n')
|
||||
f.write('\tcd {0} && unzip -q -DD -o {1} \'{2}\'\n'.format(
|
||||
f.write("\n")
|
||||
f.write("{0}: {1}\n".format(self.packfile, self.tempfile))
|
||||
f.write("\t@mkdir -p $(dir $@)\n")
|
||||
f.write("\tcp -f $< $@\n")
|
||||
f.write("\n")
|
||||
f.write("{0}: {1}\n".format(self.tempfile, self.cachefile))
|
||||
f.write("\t@mkdir -p $(dir $@)\n")
|
||||
f.write(
|
||||
"\tcd {0} && unzip -q -DD -o {1} '{2}'\n".format(
|
||||
self.tempdir,
|
||||
os.path.relpath(self.cachefile, self.tempdir),
|
||||
self.itemfile
|
||||
))
|
||||
self.itemfile,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class MacOSItem:
|
||||
|
||||
def __init__(self, version, rid, codename):
|
||||
self.url = 'https://bintray.com/homebrew/bottles/download_file?file_path=libsodium-{0}.{1}.bottle.tar.gz'.format(
|
||||
version.libsodium_version, codename)
|
||||
self.cachefile = os.path.join(
|
||||
CACHEDIR, re.sub(r'[^A-Za-z0-9.]', '-', self.url))
|
||||
self.url = "https://bintray.com/homebrew/bottles/download_file?file_path=libsodium-{0}.{1}.bottle.tar.gz".format(
|
||||
version.libsodium_version, codename
|
||||
)
|
||||
self.cachefile = os.path.join(CACHEDIR, re.sub(r"[^A-Za-z0-9.]", "-", self.url))
|
||||
self.packfile = os.path.join(
|
||||
version.builddir, 'runtimes', rid, 'native', LIBRARY + '.dylib')
|
||||
self.itemfile = 'libsodium/{0}/lib/libsodium.dylib'.format(
|
||||
version.libsodium_version)
|
||||
version.builddir, "runtimes", rid, "native", LIBRARY + ".dylib"
|
||||
)
|
||||
self.itemfile = "libsodium/{0}/lib/libsodium.dylib".format(
|
||||
version.libsodium_version
|
||||
)
|
||||
self.tempdir = os.path.join(version.tempdir, rid)
|
||||
self.tempfile = os.path.join(
|
||||
self.tempdir, os.path.normpath(self.itemfile))
|
||||
self.tempfile = os.path.join(self.tempdir, os.path.normpath(self.itemfile))
|
||||
|
||||
def make(self, f):
|
||||
f.write('\n')
|
||||
f.write('{0}: {1}\n'.format(self.packfile, self.tempfile))
|
||||
f.write('\t@mkdir -p $(dir $@)\n')
|
||||
f.write('\tcp -f $< $@\n')
|
||||
f.write('\n')
|
||||
f.write('{0}: {1}\n'.format(self.tempfile, self.cachefile))
|
||||
f.write('\t@mkdir -p $(dir $@)\n')
|
||||
f.write('\tcd {0} && tar xzmf {1} \'{2}\'\n'.format(
|
||||
f.write("\n")
|
||||
f.write("{0}: {1}\n".format(self.packfile, self.tempfile))
|
||||
f.write("\t@mkdir -p $(dir $@)\n")
|
||||
f.write("\tcp -f $< $@\n")
|
||||
f.write("\n")
|
||||
f.write("{0}: {1}\n".format(self.tempfile, self.cachefile))
|
||||
f.write("\t@mkdir -p $(dir $@)\n")
|
||||
f.write(
|
||||
"\tcd {0} && tar xzmf {1} '{2}'\n".format(
|
||||
self.tempdir,
|
||||
os.path.relpath(self.cachefile, self.tempdir),
|
||||
os.path.dirname(self.itemfile)
|
||||
))
|
||||
os.path.dirname(self.itemfile),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class LinuxItem:
|
||||
|
||||
def __init__(self, version, rid, docker_image):
|
||||
self.url = 'https://download.libsodium.org/libsodium/releases/libsodium-{0}.tar.gz'.format(
|
||||
version.libsodium_version)
|
||||
self.cachefile = os.path.join(
|
||||
CACHEDIR, re.sub(r'[^A-Za-z0-9.]', '-', self.url))
|
||||
self.url = "https://download.libsodium.org/libsodium/releases/libsodium-{0}.tar.gz".format(
|
||||
version.libsodium_version
|
||||
)
|
||||
self.cachefile = os.path.join(CACHEDIR, re.sub(r"[^A-Za-z0-9.]", "-", self.url))
|
||||
self.packfile = os.path.join(
|
||||
version.builddir, 'runtimes', rid, 'native', LIBRARY + '.so')
|
||||
version.builddir, "runtimes", rid, "native", LIBRARY + ".so"
|
||||
)
|
||||
self.tempdir = os.path.join(version.tempdir, rid)
|
||||
self.tempfile = os.path.join(self.tempdir, 'libsodium.so')
|
||||
self.tempfile = os.path.join(self.tempdir, "libsodium.so")
|
||||
self.docker_image = docker_image
|
||||
self.recipe = rid
|
||||
|
||||
def make(self, f):
|
||||
recipe = self.recipe
|
||||
while not os.path.exists(os.path.join('recipes', recipe)):
|
||||
m = re.fullmatch(
|
||||
r'([^.-]+)((([.][^.-]+)*)[.][^.-]+)?([-].*)?', recipe)
|
||||
while not os.path.exists(os.path.join("recipes", recipe)):
|
||||
m = re.fullmatch(r"([^.-]+)((([.][^.-]+)*)[.][^.-]+)?([-].*)?", recipe)
|
||||
if m.group(5) is None:
|
||||
recipe = 'build'
|
||||
recipe = "build"
|
||||
break
|
||||
elif m.group(2) is None:
|
||||
recipe = m.group(1)
|
||||
else:
|
||||
recipe = m.group(1) + m.group(3) + m.group(5)
|
||||
|
||||
f.write('\n')
|
||||
f.write('{0}: {1}\n'.format(self.packfile, self.tempfile))
|
||||
f.write('\t@mkdir -p $(dir $@)\n')
|
||||
f.write('\tcp -f $< $@\n')
|
||||
f.write('\n')
|
||||
f.write('{0}: {1}\n'.format(self.tempfile, self.cachefile))
|
||||
f.write('\t@mkdir -p $(dir $@)\n')
|
||||
f.write('\t{0} run --rm '.format(DOCKER) +
|
||||
'-v $(abspath recipes):/io/recipes ' +
|
||||
'-v $(abspath $<):/io/libsodium.tar.gz ' +
|
||||
'-v $(abspath $(dir $@)):/io/output ' +
|
||||
'{0} sh -x -e /io/recipes/{1}\n'.format(self.docker_image, recipe))
|
||||
f.write("\n")
|
||||
f.write("{0}: {1}\n".format(self.packfile, self.tempfile))
|
||||
f.write("\t@mkdir -p $(dir $@)\n")
|
||||
f.write("\tcp -f $< $@\n")
|
||||
f.write("\n")
|
||||
f.write("{0}: {1}\n".format(self.tempfile, self.cachefile))
|
||||
f.write("\t@mkdir -p $(dir $@)\n")
|
||||
f.write(
|
||||
"\t{0} run --rm ".format(DOCKER)
|
||||
+ "-v $(abspath recipes):/io/recipes "
|
||||
+ "-v $(abspath $<):/io/libsodium.tar.gz "
|
||||
+ "-v $(abspath $(dir $@)):/io/output "
|
||||
+ "{0} sh -x -e /io/recipes/{1}\n".format(self.docker_image, recipe)
|
||||
)
|
||||
|
||||
|
||||
class ExtraItem:
|
||||
|
||||
def __init__(self, version, filename):
|
||||
self.url = 'https://download.libsodium.org/libsodium/releases/libsodium-{0}.tar.gz'.format(
|
||||
version.libsodium_version)
|
||||
self.cachefile = os.path.join(
|
||||
CACHEDIR, re.sub(r'[^A-Za-z0-9.]', '-', self.url))
|
||||
self.url = "https://download.libsodium.org/libsodium/releases/libsodium-{0}.tar.gz".format(
|
||||
version.libsodium_version
|
||||
)
|
||||
self.cachefile = os.path.join(CACHEDIR, re.sub(r"[^A-Za-z0-9.]", "-", self.url))
|
||||
self.packfile = os.path.join(version.builddir, filename)
|
||||
self.itemfile = 'libsodium-{0}/{1}'.format(
|
||||
version.libsodium_version, filename)
|
||||
self.tempdir = os.path.join(version.tempdir, 'extras')
|
||||
self.tempfile = os.path.join(
|
||||
self.tempdir, os.path.normpath(self.itemfile))
|
||||
self.itemfile = "libsodium-{0}/{1}".format(version.libsodium_version, filename)
|
||||
self.tempdir = os.path.join(version.tempdir, "extras")
|
||||
self.tempfile = os.path.join(self.tempdir, os.path.normpath(self.itemfile))
|
||||
|
||||
def make(self, f):
|
||||
f.write('\n')
|
||||
f.write('{0}: {1}\n'.format(self.packfile, self.tempfile))
|
||||
f.write('\t@mkdir -p $(dir $@)\n')
|
||||
f.write('\tcp -f $< $@\n')
|
||||
f.write('\n')
|
||||
f.write('{0}: {1}\n'.format(self.tempfile, self.cachefile))
|
||||
f.write('\t@mkdir -p $(dir $@)\n')
|
||||
f.write('\tcd {0} && tar xzmf {1} \'{2}\'\n'.format(
|
||||
f.write("\n")
|
||||
f.write("{0}: {1}\n".format(self.packfile, self.tempfile))
|
||||
f.write("\t@mkdir -p $(dir $@)\n")
|
||||
f.write("\tcp -f $< $@\n")
|
||||
f.write("\n")
|
||||
f.write("{0}: {1}\n".format(self.tempfile, self.cachefile))
|
||||
f.write("\t@mkdir -p $(dir $@)\n")
|
||||
f.write(
|
||||
"\tcd {0} && tar xzmf {1} '{2}'\n".format(
|
||||
self.tempdir,
|
||||
os.path.relpath(self.cachefile, self.tempdir),
|
||||
self.itemfile
|
||||
))
|
||||
self.itemfile,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def main(args):
|
||||
m = re.fullmatch(
|
||||
r'((\d+\.\d+\.\d+)(\.\d+)?)(?:-(\w+(?:[_.-]\w+)*))?', args[1]) if len(args) == 2 else None
|
||||
m = (
|
||||
re.fullmatch(r"((\d+\.\d+\.\d+)(\.\d+)?)(?:-(\w+(?:[_.-]\w+)*))?", args[1])
|
||||
if len(args) == 2
|
||||
else None
|
||||
)
|
||||
|
||||
if m is None:
|
||||
print('Usage:')
|
||||
print(' python3 prepare.py <version>')
|
||||
print("Usage:")
|
||||
print(" python3 prepare.py <version>")
|
||||
print()
|
||||
print('Examples:')
|
||||
print(' python3 prepare.py 1.0.17-preview-01')
|
||||
print(' python3 prepare.py 1.0.17-preview-02')
|
||||
print(' python3 prepare.py 1.0.17-preview-03')
|
||||
print(' python3 prepare.py 1.0.17')
|
||||
print(' python3 prepare.py 1.0.17.1-preview-01')
|
||||
print(' python3 prepare.py 1.0.17.1')
|
||||
print(' python3 prepare.py 1.0.17.2')
|
||||
print("Examples:")
|
||||
print(" python3 prepare.py 1.0.17-preview-01")
|
||||
print(" python3 prepare.py 1.0.17-preview-02")
|
||||
print(" python3 prepare.py 1.0.17-preview-03")
|
||||
print(" python3 prepare.py 1.0.17")
|
||||
print(" python3 prepare.py 1.0.17.1-preview-01")
|
||||
print(" python3 prepare.py 1.0.17.1")
|
||||
print(" python3 prepare.py 1.0.17.2")
|
||||
return 1
|
||||
|
||||
version = Version(m.group(2), m.group(0))
|
||||
|
||||
items = [WindowsItem(version, rid, platform) for (rid, platform) in WINDOWS] + \
|
||||
[MacOSItem(version, rid, codename) for (rid, codename) in MACOS] + \
|
||||
[LinuxItem(version, rid, docker_image) for (rid, docker_image) in LINUX] + \
|
||||
[ExtraItem(version, filename) for filename in EXTRAS]
|
||||
items = (
|
||||
[WindowsItem(version, rid, platform) for (rid, platform) in WINDOWS]
|
||||
+ [MacOSItem(version, rid, codename) for (rid, codename) in MACOS]
|
||||
+ [LinuxItem(version, rid, docker_image) for (rid, docker_image) in LINUX]
|
||||
+ [ExtraItem(version, filename) for filename in EXTRAS]
|
||||
)
|
||||
|
||||
downloads = {item.cachefile: item.url for item in items}
|
||||
|
||||
with open(MAKEFILE, 'w') as f:
|
||||
f.write('all: {0}\n'.format(version.pkgfile))
|
||||
with open(MAKEFILE, "w") as f:
|
||||
f.write("all: {0}\n".format(version.pkgfile))
|
||||
|
||||
for download in sorted(downloads):
|
||||
f.write('\n')
|
||||
f.write('{0}:\n'.format(download))
|
||||
f.write('\t@mkdir -p $(dir $@)\n')
|
||||
f.write('\tcurl -f#Lo $@ \'{0}\'\n'.format(downloads[download]))
|
||||
f.write("\n")
|
||||
f.write("{0}:\n".format(download))
|
||||
f.write("\t@mkdir -p $(dir $@)\n")
|
||||
f.write("\tcurl -f#Lo $@ '{0}'\n".format(downloads[download]))
|
||||
|
||||
for item in items:
|
||||
item.make(f)
|
||||
|
||||
f.write('\n')
|
||||
f.write('{0}: {1}\n'.format(version.propsfile, PROPSFILE))
|
||||
f.write('\t@mkdir -p $(dir $@)\n')
|
||||
f.write('\tcp -f $< $@\n')
|
||||
f.write("\n")
|
||||
f.write("{0}: {1}\n".format(version.propsfile, PROPSFILE))
|
||||
f.write("\t@mkdir -p $(dir $@)\n")
|
||||
f.write("\tcp -f $< $@\n")
|
||||
|
||||
f.write('\n')
|
||||
f.write('{0}: {1}\n'.format(version.projfile, version.propsfile))
|
||||
f.write('\t@mkdir -p $(dir $@)\n')
|
||||
f.write('\techo \'' +
|
||||
'<Project Sdk="Microsoft.NET.Sdk">' +
|
||||
'<Import Project="{0}" />'.format(os.path.relpath(version.propsfile, os.path.dirname(version.projfile))) +
|
||||
'<PropertyGroup>' +
|
||||
'<Version>{0}</Version>'.format(version.package_version) +
|
||||
'</PropertyGroup>' +
|
||||
'</Project>\' > $@\n')
|
||||
|
||||
f.write('\n')
|
||||
f.write('{0}:'.format(version.pkgfile))
|
||||
f.write(' \\\n\t\t{0}'.format(version.projfile))
|
||||
f.write(' \\\n\t\t{0}'.format(version.propsfile))
|
||||
f.write("\n")
|
||||
f.write("{0}: {1}\n".format(version.projfile, version.propsfile))
|
||||
f.write("\t@mkdir -p $(dir $@)\n")
|
||||
f.write(
|
||||
"\techo '"
|
||||
+ '<Project Sdk="Microsoft.NET.Sdk">'
|
||||
+ '<Import Project="{0}" />'.format(
|
||||
os.path.relpath(version.propsfile, os.path.dirname(version.projfile))
|
||||
)
|
||||
+ "<PropertyGroup>"
|
||||
+ "<Version>{0}</Version>".format(version.package_version)
|
||||
+ "</PropertyGroup>"
|
||||
+ "</Project>' > $@\n"
|
||||
)
|
||||
|
||||
f.write("\n")
|
||||
f.write("{0}:".format(version.pkgfile))
|
||||
f.write(" \\\n\t\t{0}".format(version.projfile))
|
||||
f.write(" \\\n\t\t{0}".format(version.propsfile))
|
||||
for item in items:
|
||||
f.write(' \\\n\t\t{0}'.format(item.packfile))
|
||||
f.write(" \\\n\t\t{0}".format(item.packfile))
|
||||
f.write("\n")
|
||||
f.write("\t@mkdir -p $(dir $@)\n")
|
||||
f.write(
|
||||
"\t{0} run --rm ".format(DOCKER)
|
||||
+ "-v $(abspath recipes):/io/recipes "
|
||||
+ "-v $(abspath $(dir $<)):/io/input "
|
||||
+ "-v $(abspath $(dir $@)):/io/output "
|
||||
+ "{0} sh -x -e /io/recipes/{1} {2}\n".format(
|
||||
"microsoft/dotnet:2.0-sdk",
|
||||
"pack",
|
||||
os.path.relpath(version.projfile, version.builddir),
|
||||
)
|
||||
)
|
||||
|
||||
f.write('\n')
|
||||
f.write('\t@mkdir -p $(dir $@)\n')
|
||||
f.write('\t{0} run --rm '.format(DOCKER) +
|
||||
'-v $(abspath recipes):/io/recipes ' +
|
||||
'-v $(abspath $(dir $<)):/io/input ' +
|
||||
'-v $(abspath $(dir $@)):/io/output ' +
|
||||
'{0} sh -x -e /io/recipes/{1} {2}\n'.format('microsoft/dotnet:2.0-sdk', 'pack', os.path.relpath(version.projfile, version.builddir)))
|
||||
f.write("\n")
|
||||
f.write("test: {0}\n".format(version.pkgfile))
|
||||
f.write(
|
||||
"\t{0} run --rm ".format(DOCKER)
|
||||
+ "-v $(abspath recipes):/io/recipes "
|
||||
+ "-v $(abspath $(dir $<)):/io/packages "
|
||||
+ '{0} sh -x -e /io/recipes/{1} "{2}"\n'.format(
|
||||
"microsoft/dotnet:2.0-sdk", "test", version.package_version
|
||||
)
|
||||
)
|
||||
|
||||
f.write('\n')
|
||||
f.write('test: {0}\n'.format(version.pkgfile))
|
||||
f.write('\t{0} run --rm '.format(DOCKER) +
|
||||
'-v $(abspath recipes):/io/recipes ' +
|
||||
'-v $(abspath $(dir $<)):/io/packages ' +
|
||||
'{0} sh -x -e /io/recipes/{1} "{2}"\n'.format('microsoft/dotnet:2.0-sdk', 'test', version.package_version))
|
||||
|
||||
print('prepared', MAKEFILE, 'to make', version.pkgfile,
|
||||
'for libsodium', version.libsodium_version)
|
||||
print(
|
||||
"prepared",
|
||||
MAKEFILE,
|
||||
"to make",
|
||||
version.pkgfile,
|
||||
"for libsodium",
|
||||
version.libsodium_version,
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user