# Buggy code
def user_run_dir(self):
    # Try to ensure that (/var)/run/user/$(id -u) exists so that
    #  `gpgconf --create-socketdir` can be run later.
    #
    # NOTE(opadron): This action helps prevent a large class of
    #                "file-name-too-long" errors in gpg.

    try:
        has_suitable_gpgconf = bool(_GpgConstants.gpgconf_string)
    except SpackGPGError:
        has_suitable_gpgconf = False

    # If there is no suitable gpgconf, don't even bother trying to
    # precreate a user run dir.
    if not has_suitable_gpgconf:
        return None

    result = None
    for var_run in ("/run", "/var/run"):
        if not os.path.exists(var_run):
            continue

        var_run_user = os.path.join(var_run, "user")
        try:
            if not os.path.exists(var_run_user):
                os.mkdir(var_run_user)
                os.chmod(var_run_user, 0o777)

            user_dir = os.path.join(var_run_user, str(os.getuid()))

            if not os.path.exists(user_dir):
                os.mkdir(user_dir)
                os.chmod(user_dir, 0o700)

        # If the above operation fails due to lack of permissions, then
        # just carry on without running gpgconf and hope for the best.
        #
        # NOTE(opadron): Without a dir in which to create a socket for IPC,
        #                gnupg may fail if GNUPGHOME is set to a path that
        #                is too long, where "too long" in this context is
        #                actually quite short; somewhere in the
        #                neighborhood of more than 100 characters.
        #
        # TODO(opadron): Maybe a warning should be printed in this case?
        except OSError as exc:
            if exc.errno not in (errno.EPERM, errno.EACCES):
                raise
            user_dir = None

        # return the last iteration that provides a usable user run dir
        if user_dir is not None:
            result = user_dir

    return result


# Traceback (FileNotFoundError)
$> spack -d gpg trust e4s.pub
==> [2020-12-28-17:57:13.255469] Imported gpg from built-in commands
==> [2020-12-28-17:57:13.257931] Imported gpg from built-in commands
==> [2020-12-28-17:57:13.258679] '/usr/bin/gpgconf' '--version'
==> [2020-12-28-17:57:13.260456] '/usr/bin/gpgconf' '--dry-run' '--create-socketdir'
gpgconf: invalid option "--create-socketdir"
==> [2020-12-28-17:57:13.262194] '/usr/bin/gpg2' '--version'
==> [2020-12-28-17:57:13.264410] 'None' '--create-socketdir'
==> [2020-12-28-17:57:13.265610] ProcessError: None: No such file or directory: 'None'
Command: 'None' '--create-socketdir'
==> [2020-12-28-17:57:13.265703] Error: None: No such file or directory: 'None'
Command: 'None' '--create-socketdir'
Traceback (most recent call last):
File "/opt/spack/lib/spack/spack/util/executable.py", line 170, in __call__
env=env)
File "/usr/local/lib/python3.7/subprocess.py", line 775, in __init__
restore_signals, start_new_session)
File "/usr/local/lib/python3.7/subprocess.py", line 1522, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'None': 'None'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/opt/spack/lib/spack/spack/main.py", line 762, in main
return _invoke_command(command, parser, args, unknown)
File "/opt/spack/lib/spack/spack/main.py", line 490, in _invoke_command
return_val = command(parser, args)
File "/opt/spack/lib/spack/spack/cmd/gpg.py", line 201, in gpg
args.func(args)
File "/opt/spack/lib/spack/spack/cmd/gpg.py", line 159, in gpg_trust
spack.util.gpg.trust(args.keyfile)
File "/opt/spack/lib/spack/spack/util/gpg.py", line 410, in trust
return get_global_gpg_instance().trust(*args, **kwargs)
File "/opt/spack/lib/spack/spack/util/gpg.py", line 345, in trust
self('--import', keyfile)
File "/opt/spack/lib/spack/spack/util/gpg.py", line 307, in __call__
if self.prep:
File "/opt/spack/lib/spack/llnl/util/lang.py", line 197, in _memoized_function
func.cache[args] = func(*args)
File "/opt/spack/lib/spack/spack/util/gpg.py", line 290, in prep
self.gpgconf_exe('--create-socketdir')
File "/opt/spack/lib/spack/spack/util/executable.py", line 204, in __call__
'%s: %s' % (self.exe[0], e.strerror), 'Command: ' + cmd_line)
spack.util.executable.ProcessError: None: No such file or directory: 'None'
Command: 'None' '--create-socketdir'

# Fixed code
def user_run_dir(self):
    # Try to ensure that (/var)/run/user/$(id -u) exists so that
    #  `gpgconf --create-socketdir` can be run later.
    #
    # NOTE(opadron): This action helps prevent a large class of
    #                "file-name-too-long" errors in gpg.

    try:
        has_suitable_gpgconf = bool(GpgConstants.gpgconf_string)
    except SpackGPGError:
        has_suitable_gpgconf = False

    # If there is no suitable gpgconf, don't even bother trying to
    # precreate a user run dir.
    if not has_suitable_gpgconf:
        return None

    result = None
    for var_run in ("/run", "/var/run"):
        if not os.path.exists(var_run):
            continue

        var_run_user = os.path.join(var_run, "user")
        try:
            if not os.path.exists(var_run_user):
                os.mkdir(var_run_user)
                os.chmod(var_run_user, 0o777)

            user_dir = os.path.join(var_run_user, str(os.getuid()))

            if not os.path.exists(user_dir):
                os.mkdir(user_dir)
                os.chmod(user_dir, 0o700)

        # If the above operation fails due to lack of permissions, then
        # just carry on without running gpgconf and hope for the best.
        #
        # NOTE(opadron): Without a dir in which to create a socket for IPC,
        #                gnupg may fail if GNUPGHOME is set to a path that
        #                is too long, where "too long" in this context is
        #                actually quite short; somewhere in the
        #                neighborhood of more than 100 characters.
        #
        # TODO(opadron): Maybe a warning should be printed in this case?
        except OSError as exc:
            if exc.errno not in (errno.EPERM, errno.EACCES):
                raise
            user_dir = None

        # return the last iteration that provides a usable user run dir
        if user_dir is not None:
            result = user_dir

    return result