Repository: spack/spack

Issue:
spack bootstrap mirror does not work
### Steps to reproduce

I tried to make a bootstrap mirror into a local directory with
```console
$ spack --debug bootstrap mirror bootstrap-behind-firewall
==> [2022-06-15-15:19:26.252534] Imported bootstrap from built-in commands
==> [2022-06-15-15:19:26.257927] Imported bootstrap from built-in commands
==> [2022-06-15-15:19:26.283499] [BOOTSTRAP ROOT SPEC] clingo-bootstrap@spack+python %gcc target=x86_64
==> [2022-06-15-15:19:26.308218] [BOOTSTRAP ROOT SPEC] gnupg@2.3: %gcc target=x86_64
==> [2022-06-15-15:19:26.314048] [BOOTSTRAP ROOT SPEC] patchelf@0.13.1:0.13.99 %gcc target=x86_64
==> [2022-06-15-15:19:26.314177] Adding "clingo-bootstrap@spack+python %gcc target=x86_64" and dependencies to the mirror at bootstrap-behind-firewall/bootstrap_cache
==> [2022-06-15-15:19:26.316924] Reading config file /nethome/mabraham/git/spack/etc/spack/defaults/config.yaml
==> [2022-06-15-15:19:26.339950] Reading config file /nethome/mabraham/git/spack/etc/spack/defaults/bootstrap.yaml
==> [2022-06-15-15:19:26.376157] Reading config file /nethome/mabraham/git/spack/etc/spack/defaults/config.yaml
==> [2022-06-15-15:19:26.398895] DATABASE LOCK TIMEOUT: 3s
==> [2022-06-15-15:19:26.398987] PACKAGE LOCK TIMEOUT: No timeout
==> [2022-06-15-15:19:26.399508] Reading config file /nethome/mabraham/git/spack/etc/spack/defaults/bootstrap.yaml
==> [2022-06-15-15:19:26.407404] DATABASE LOCK TIMEOUT: 3s
==> [2022-06-15-15:19:26.407472] PACKAGE LOCK TIMEOUT: No timeout
==> [2022-06-15-15:19:26.407552] [BOOTSTRAP CONFIG SCOPE] name=_builtin
==> [2022-06-15-15:19:26.407986] [BOOTSTRAP CONFIG SCOPE] name=defaults, path=/nethome/mabraham/git/spack/etc/spack/defaults
==> [2022-06-15-15:19:26.408045] [BOOTSTRAP CONFIG SCOPE] name=defaults/linux, path=/nethome/mabraham/git/spack/etc/spack/defaults/linux
==> [2022-06-15-15:19:26.408095] [BOOTSTRAP CONFIG SCOPE] name=bootstrap, path=/nethome/mabraham/.spack/bootstrap/config
==> [2022-06-15-15:19:26.408134] [BOOTSTRAP CONFIG SCOPE] name=bootstrap/linux, path=/nethome/mabraham/.spack/bootstrap/config/linux
==> [2022-06-15-15:19:26.409327] Reading config file /nethome/mabraham/.spack/bootstrap/config/linux/compilers.yaml
==> [2022-06-15-15:19:26.464263] [BOOTSTRAP ROOT SPEC] clingo-bootstrap@spack+python %gcc target=x86_64
==> [2022-06-15-15:19:26.464423] [BOOTSTRAP MODULE clingo] Try importing from Python
==> [2022-06-15-15:19:26.464947] Reading config file /nethome/mabraham/git/spack/etc/spack/defaults/bootstrap.yaml
==> [2022-06-15-15:19:29.619450] Reading config file /nethome/mabraham/git/spack/etc/spack/defaults/config.yaml
==> [2022-06-15-15:19:29.744988] [BOOTSTRAP MODULE clingo] The installed spec "clingo-bootstrap@spack+python %gcc target=x86_64 ^python@3.8 /kt74l7kjzrlp3cgtj2576o33mhsrgyrw" provides the "clingo" Python module
==> [2022-06-15-15:19:29.745700] Reading config file /nethome/mabraham/git/spack/etc/spack/defaults/concretizer.yaml
==> [2022-06-15-15:19:29.752146] Reading config file /nethome/mabraham/git/spack/etc/spack/defaults/repos.yaml
==> [2022-06-15-15:19:29.787169] Reading config file /nethome/mabraham/git/spack/etc/spack/defaults/config.yaml
==> [2022-06-15-15:19:29.812446] Reading config file /nethome/mabraham/git/spack/etc/spack/defaults/mirrors.yaml
==> [2022-06-15-15:19:32.992360] Reading config file /nethome/mabraham/.spack/linux/compilers.yaml
==> [2022-06-15-15:19:33.027948] Reading config file /nethome/mabraham/git/spack/etc/spack/defaults/packages.yaml
==> [2022-06-15-15:19:33.061067] Reading config file /nethome/mabraham/.spack/packages.yaml
==> [2022-06-15-15:19:46.406690] build(clingo-bootstrap)
==> [2022-06-15-15:19:46.406834] build(bison)
==> [2022-06-15-15:19:46.406888] build(cmake)
==> [2022-06-15-15:19:46.406937] build(python)
==> [2022-06-15-15:19:46.406983] build(re2c)
==> [2022-06-15-15:19:46.407026] build(bzip2)
==> [2022-06-15-15:19:46.407071] build(expat)
==> [2022-06-15-15:19:46.407111] build(gdbm)
==> [2022-06-15-15:19:46.407153] build(gettext)
==> [2022-06-15-15:19:46.407193] build(libffi)
==> [2022-06-15-15:19:46.407233] build(ncurses)
==> [2022-06-15-15:19:46.407272] build(openssl)
==> [2022-06-15-15:19:46.407312] build(readline)
==> [2022-06-15-15:19:46.407352] build(sqlite)
==> [2022-06-15-15:19:46.407391] build(util-linux-uuid)
==> [2022-06-15-15:19:46.407432] build(xz)
==> [2022-06-15-15:19:46.407472] build(zlib)
==> [2022-06-15-15:19:46.407511] build(m4)
==> [2022-06-15-15:19:46.407550] build(libsigsegv)
==> [2022-06-15-15:19:46.407589] build(libiconv)
==> [2022-06-15-15:19:46.407628] build(libxml2)
==> [2022-06-15-15:19:46.407668] build(tar)
==> [2022-06-15-15:19:46.407708] build(libbsd)
==> [2022-06-15-15:19:46.407746] build(libmd)
==> [2022-06-15-15:19:46.407786] build(diffutils)
==> [2022-06-15-15:19:46.407825] build(perl)
==> [2022-06-15-15:19:46.407864] build(pigz)
==> [2022-06-15-15:19:46.407902] build(zstd)
==> [2022-06-15-15:19:46.407942] build(pkgconf)
==> [2022-06-15-15:19:46.407981] build(berkeley-db)
==> [2022-06-15-15:19:46.422658] Ordered hashes [m4]: m4/72/bfdffa7c2eb01021d5849b36972c069693654ad826c1a20b53534009a4ec7a89, m4/73/9dc5fbd0d5cb1037ab1e6d0ecc74a30df218d0a94bdd5a02759a97f62daca573
==> [2022-06-15-15:19:46.423218] Ordered hashes [berkeley-db]: berkeley-db/90/b231fcc4d5cff05e5c3a4814f6a5af0e9a966428dc2176540d2c05aff41de522
==> [2022-06-15-15:19:46.423695] Ordered hashes [zlib]: zlib/43/0d38234384870bfd34dfcb738a9083952656f0c766a0f5990b1893076b084b76
==> [2022-06-15-15:19:46.424121] Ordered hashes [cmake]: cmake/29/b48396c0e4f61756248156b6cebe9bc0d7a22228639b47b5aa77c9330588ce88
==> [2022-06-15-15:19:46.425112] Ordered hashes [python]: python/5/0d98e93189bc278fbc37a50ed7f183bd8aaf249a8e1670a465f0db6bb4f8cf87, python/6/f2fd060afc4b4618fe8104c4c5d771f36dc55b1db5a4623785a4ea707ec72fb4, python/9/4c2457325f2b608b1b6a2c63087df8c26e07db3e3d493caf36a56f0ecf6fb768
==> [2022-06-15-15:19:46.453748] Module name: CMake/3.19.7
==> [2022-06-15-15:19:46.454066] Package directory variable prefix: CMAKE
Traceback (most recent call last):
  File "/nethome/mabraham/git/spack/bin/spack", line 98, in <module>
    sys.exit(spack.main.main())
  File "/nethome/mabraham/git/spack/lib/spack/spack/main.py", line 893, in main
    return _main(argv)
  File "/nethome/mabraham/git/spack/lib/spack/spack/main.py", line 848, in _main
    return finish_parse_and_run(parser, cmd_name, env_format_error)
  File "/nethome/mabraham/git/spack/lib/spack/spack/main.py", line 876, in finish_parse_and_run
    return _invoke_command(command, parser, args, unknown)
  File "/nethome/mabraham/git/spack/lib/spack/spack/main.py", line 533, in _invoke_command
    return_val = command(parser, args)
  File "/nethome/mabraham/git/spack/lib/spack/spack/cmd/bootstrap.py", line 450, in bootstrap
    callbacks[args.subcommand](args)
  File "/nethome/mabraham/git/spack/lib/spack/spack/cmd/bootstrap.py", line 395, in _mirror
    spack.mirror.create(mirror_dir, [node])
  File "/nethome/mabraham/git/spack/lib/spack/spack/mirror.py", line 512, in create
    parsed = url_util.parse(path)
  File "/nethome/mabraham/git/spack/lib/spack/spack/util/url.py", line 79, in parse
    require_url_format(url)
  File "/nethome/mabraham/git/spack/lib/spack/spack/util/url.py", line 348, in require_url_format
    raise ValueError('Invalid url format from url: %s' % url)
ValueError: Invalid url format from url: bootstrap-behind-firewall/bootstrap_cache
```

Clearly it failed and the error message does not leave me with a path forward. If `mirror.py` needs a URL, then `bootstrap.py` should probably convert its directory by prefixing e.g. `file://` in order to pass one.

### Error message

```console
ValueError: Invalid url format from url: bootstrap-behind-firewall/bootstrap_cache
```

indicates a possible relationship with the problem behind #30132. `spack bootstrap mirror` takes a directory but later uses aspects of the implementation of `spack mirror` which expects a URL.

### Information on your system

```console
$ spack debug report
* **Spack:** 0.18.0 (4c6564f10aa516bc00c1d7dbfdeafe35128985fe)
* **Python:** 3.8.10
* **Platform:** linux-ubuntu20.04-broadwell
* **Concretizer:** clingo
(base)
```

### General information

- [X] I have run `spack debug report` and reported the version of Spack/Python/Platform
- [X] I have searched the issues of this repo and believe this is not a duplicate
- [X] I have run the failing commands in debug mode and reported the output


Discussion:
I'll look into fixing this. Currently you need to pass an absolute path to the command.

Resolving patch:
diff --git a/lib/spack/spack/cmd/bootstrap.py b/lib/spack/spack/cmd/bootstrap.py
--- a/lib/spack/spack/cmd/bootstrap.py
+++ b/lib/spack/spack/cmd/bootstrap.py
@@ -379,7 +379,9 @@ def _remove(args):
 
 
 def _mirror(args):
-    mirror_dir = os.path.join(args.root_dir, LOCAL_MIRROR_DIR)
+    mirror_dir = spack.util.path.canonicalize_path(
+        os.path.join(args.root_dir, LOCAL_MIRROR_DIR)
+    )
 
     # TODO: Here we are adding gnuconfig manually, but this can be fixed
     # TODO: as soon as we have an option to add to a mirror all the possible


Test patch: