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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import llnl.util.tty as tty
from llnl.util.filesystem import mkdirp
from llnl.util.symlink import symlink
import spack.util.editor as ed
def pre_install(spec):
"""This hook handles global license setup for licensed software."""
pkg = spec.package
if pkg.license_required and not pkg.spec.external:
set_up_license(pkg)
def set_up_license(pkg):
"""Prompt the user, letting them know that a license is required.
For packages that rely on license files, a global license file is
created and opened for editing.
For packages that rely on environment variables to point to a
license, a warning message is printed.
For all other packages, documentation on how to set up a license
is printed."""
# If the license can be stored in a file, create one
if pkg.license_files:
license_path = pkg.global_license_file
if not os.path.exists(license_path):
# Create a new license file
write_license_file(pkg, license_path)
# use spack.util.executable so the editor does not hang on return here
ed.editor(license_path, exec_fn=ed.executable)
else:
# Use already existing license file
tty.msg("Found already existing license %s" % license_path)
# If not a file, what about an environment variable?
elif pkg.license_vars:
tty.warn(
"A license is required to use %s. Please set %s to the "
"full pathname to the license file, or port@host if you"
" store your license keys on a dedicated license server"
% (pkg.name, " or ".join(pkg.license_vars))
)
# If not a file or variable, suggest a website for further info
elif pkg.license_url:
tty.warn(
"A license is required to use %s. See %s for details" % (pkg.name, pkg.license_url)
)
# If all else fails, you're on your own
else:
tty.warn("A license is required to use %s" % pkg.name)
def write_license_file(pkg, license_path):
"""Writes empty license file.
Comments give suggestions on alternative methods of
installing a license."""
# License files
linktargets = ""
for f in pkg.license_files:
linktargets += "\t%s\n" % f
# Environment variables
envvars = ""
if pkg.license_vars:
for varname in pkg.license_vars:
envvars += "\t%s\n" % varname
# Documentation
url = ""
if pkg.license_url:
url += "\t%s\n" % pkg.license_url
# Assemble. NB: pkg.license_comment will be prepended upon output.
txt = """
A license is required to use package '{0}'.
* If your system is already properly configured for such a license, save this
file UNCHANGED. The system may be configured if:
- A license file is installed in a default location.
""".format(
pkg.name
)
if envvars:
txt += """\
- One of the following environment variable(s) is set for you, possibly via
a module file:
{0}
""".format(
envvars
)
txt += """\
* Otherwise, depending on the license you have, enter AT THE BEGINNING of
this file:
- the contents of your license file, or
- the address(es) of your license server.
After installation, the following symlink(s) will be added to point to
this Spack-global file (relative to the installation prefix).
{0}
""".format(
linktargets
)
if url:
txt += """\
* For further information on licensing, see:
{0}
""".format(
url
)
txt += """\
Recap:
- You may not need to modify this file at all.
- Otherwise, enter your license or server address AT THE BEGINNING.
"""
# Global license directory may not already exist
if not os.path.exists(os.path.dirname(license_path)):
os.makedirs(os.path.dirname(license_path))
# Output
with open(license_path, "w") as f:
for line in txt.splitlines():
f.write("{0}{1}\n".format(pkg.license_comment, line))
f.close()
def post_install(spec, explicit=None):
"""This hook symlinks local licenses to the global license for
licensed software.
"""
pkg = spec.package
if pkg.license_required and not pkg.spec.external:
symlink_license(pkg)
def symlink_license(pkg):
"""Create local symlinks that point to the global license file."""
target = pkg.global_license_file
for filename in pkg.license_files:
link_name = os.path.join(pkg.prefix, filename)
link_name = os.path.abspath(link_name)
license_dir = os.path.dirname(link_name)
if not os.path.exists(license_dir):
mkdirp(license_dir)
# If example file already exists, overwrite it with a symlink
if os.path.lexists(link_name):
os.remove(link_name)
if os.path.exists(target):
symlink(target, link_name)
tty.msg("Added local symlink %s to global license file" % link_name)
|