diff --git a/doc/source/admin/galaxy_options.rst b/doc/source/admin/galaxy_options.rst index 539375070e7..1ca46ebcb9e 100644 --- a/doc/source/admin/galaxy_options.rst +++ b/doc/source/admin/galaxy_options.rst @@ -2502,9 +2502,9 @@ :Description: Serve static content, which must be enabled if you're not serving - it via a proxy server. These options should be self explanatory - and so are not documented individually. You can use these paths - (or ones in the proxy server) to point to your own styles. + it via a proxy server. You can use these paths (or ones in the + proxy server) to point to your own styles. The static_* options + that refer to paths are relative to the current working directory. :Default: ``true`` :Type: bool @@ -2514,10 +2514,8 @@ ~~~~~~~~~~~~~~~~~~~~~ :Description: - Serve static content, which must be enabled if you're not serving - it via a proxy server. These options should be self explanatory - and so are not documented individually. You can use these paths - (or ones in the proxy server) to point to your own styles. + Value of cache time for static content served by Galaxy. Ignored + if static_enabled is false. :Default: ``360`` :Type: int @@ -2527,24 +2525,32 @@ ~~~~~~~~~~~~~~ :Description: - Serve static content, which must be enabled if you're not serving - it via a proxy server. These options should be self explanatory - and so are not documented individually. You can use these paths - (or ones in the proxy server) to point to your own styles. + Path to the static content dir. Ignored if static_enabled is + false. :Default: ``static/`` :Type: str +~~~~~~~~~~~~~~~~~~~ +``static_dist_dir`` +~~~~~~~~~~~~~~~~~~~ + +:Description: + Path to the built Galaxy client application, static/dist/ in the + Galaxy source code after the build is complete. Ignored if + static_enabled is false. +:Default: ``static/dist/`` +:Type: str + + ~~~~~~~~~~~~~~~~~~~~~ ``static_images_dir`` ~~~~~~~~~~~~~~~~~~~~~ :Description: - Serve static content, which must be enabled if you're not serving - it via a proxy server. These options should be self explanatory - and so are not documented individually. You can use these paths - (or ones in the proxy server) to point to your own styles. -:Default: ``static/images`` + Path to the static images directory. Ignored if static_enabled is + false. +:Default: ``static/images/`` :Type: str @@ -2553,10 +2559,8 @@ ~~~~~~~~~~~~~~~~~~~~~~ :Description: - Serve static content, which must be enabled if you're not serving - it via a proxy server. These options should be self explanatory - and so are not documented individually. You can use these paths - (or ones in the proxy server) to point to your own styles. + Path to favicon.ico, not the directory that contains it (the name + is a misnomer). Ignored if static_enabled is false. :Default: ``static/favicon.ico`` :Type: str @@ -2566,10 +2570,8 @@ ~~~~~~~~~~~~~~~~~~~~~~ :Description: - Serve static content, which must be enabled if you're not serving - it via a proxy server. These options should be self explanatory - and so are not documented individually. You can use these paths - (or ones in the proxy server) to point to your own styles. + Path to the static scripts directory. Ignored if static_enabled is + false. :Default: ``static/scripts/`` :Type: str @@ -2579,11 +2581,9 @@ ~~~~~~~~~~~~~~~~~~~~ :Description: - Serve static content, which must be enabled if you're not serving - it via a proxy server. These options should be self explanatory - and so are not documented individually. You can use these paths - (or ones in the proxy server) to point to your own styles. -:Default: ``static/style`` + Path to the static style directory. Ignored if static_enabled is + false. +:Default: ``static/style/`` :Type: str @@ -2592,10 +2592,7 @@ ~~~~~~~~~~~~~~~~~~~~~ :Description: - Serve static content, which must be enabled if you're not serving - it via a proxy server. These options should be self explanatory - and so are not documented individually. You can use these paths - (or ones in the proxy server) to point to your own styles. + Path to robots.txt. Ignored if static_enabled is false. :Default: ``static/robots.txt`` :Type: str diff --git a/lib/galaxy/config/sample/galaxy.yml.sample b/lib/galaxy/config/sample/galaxy.yml.sample index 27f517a2e4b..7f5da5718ff 100644 --- a/lib/galaxy/config/sample/galaxy.yml.sample +++ b/lib/galaxy/config/sample/galaxy.yml.sample @@ -1533,51 +1533,40 @@ galaxy: #terms_url: null # Serve static content, which must be enabled if you're not serving it - # via a proxy server. These options should be self explanatory and so - # are not documented individually. You can use these paths (or ones - # in the proxy server) to point to your own styles. + # via a proxy server. You can use these paths (or ones in the proxy + # server) to point to your own styles. The static_* options that refer + # to paths are relative to the current working directory. #static_enabled: true - # Serve static content, which must be enabled if you're not serving it - # via a proxy server. These options should be self explanatory and so - # are not documented individually. You can use these paths (or ones - # in the proxy server) to point to your own styles. + # Value of cache time for static content served by Galaxy. Ignored if + # static_enabled is false. #static_cache_time: 360 - # Serve static content, which must be enabled if you're not serving it - # via a proxy server. These options should be self explanatory and so - # are not documented individually. You can use these paths (or ones - # in the proxy server) to point to your own styles. + # Path to the static content dir. Ignored if static_enabled is false. #static_dir: static/ - # Serve static content, which must be enabled if you're not serving it - # via a proxy server. These options should be self explanatory and so - # are not documented individually. You can use these paths (or ones - # in the proxy server) to point to your own styles. - #static_images_dir: static/images + # Path to the built Galaxy client application, static/dist/ in the + # Galaxy source code after the build is complete. Ignored if + # static_enabled is false. + #static_dist_dir: static/dist/ - # Serve static content, which must be enabled if you're not serving it - # via a proxy server. These options should be self explanatory and so - # are not documented individually. You can use these paths (or ones - # in the proxy server) to point to your own styles. + # Path to the static images directory. Ignored if static_enabled is + # false. + #static_images_dir: static/images/ + + # Path to favicon.ico, not the directory that contains it (the name is + # a misnomer). Ignored if static_enabled is false. #static_favicon_dir: static/favicon.ico - # Serve static content, which must be enabled if you're not serving it - # via a proxy server. These options should be self explanatory and so - # are not documented individually. You can use these paths (or ones - # in the proxy server) to point to your own styles. + # Path to the static scripts directory. Ignored if static_enabled is + # false. #static_scripts_dir: static/scripts/ - # Serve static content, which must be enabled if you're not serving it - # via a proxy server. These options should be self explanatory and so - # are not documented individually. You can use these paths (or ones - # in the proxy server) to point to your own styles. - #static_style_dir: static/style + # Path to the static style directory. Ignored if static_enabled is + # false. + #static_style_dir: static/style/ - # Serve static content, which must be enabled if you're not serving it - # via a proxy server. These options should be self explanatory and so - # are not documented individually. You can use these paths (or ones - # in the proxy server) to point to your own styles. + # Path to robots.txt. Ignored if static_enabled is false. #static_robots_txt: static/robots.txt # Incremental Display Options diff --git a/lib/galaxy/config/schemas/config_schema.yml b/lib/galaxy/config/schemas/config_schema.yml index e798a0a310d..98b49e587f5 100644 --- a/lib/galaxy/config/schemas/config_schema.yml +++ b/lib/galaxy/config/schemas/config_schema.yml @@ -1866,19 +1866,17 @@ mapping: required: false desc: | Serve static content, which must be enabled if you're not serving it via a - proxy server. These options should be self explanatory and so are not - documented individually. You can use these paths (or ones in the proxy - server) to point to your own styles. + proxy server. You can use these paths (or ones in the proxy server) to point to + your own styles. The static_* options that refer to paths are relative to the + current working directory. static_cache_time: type: int default: 360 required: false desc: | - Serve static content, which must be enabled if you're not serving it via a - proxy server. These options should be self explanatory and so are not - documented individually. You can use these paths (or ones in the proxy - server) to point to your own styles. + Value of cache time for static content served by Galaxy. Ignored if + static_enabled is false. static_dir: type: str @@ -1886,21 +1884,24 @@ mapping: per_host: true required: false desc: | - Serve static content, which must be enabled if you're not serving it via a - proxy server. These options should be self explanatory and so are not - documented individually. You can use these paths (or ones in the proxy - server) to point to your own styles. + Path to the static content dir. Ignored if static_enabled is false. - static_images_dir: + static_dist_dir: type: str - default: static/images + default: static/dist/ per_host: true required: false desc: | - Serve static content, which must be enabled if you're not serving it via a - proxy server. These options should be self explanatory and so are not - documented individually. You can use these paths (or ones in the proxy - server) to point to your own styles. + Path to the built Galaxy client application, static/dist/ in the Galaxy source + code after the build is complete. Ignored if static_enabled is false. + + static_images_dir: + type: str + default: static/images/ + per_host: true + required: false + desc: | + Path to the static images directory. Ignored if static_enabled is false. static_favicon_dir: type: str @@ -1908,10 +1909,8 @@ mapping: per_host: true required: false desc: | - Serve static content, which must be enabled if you're not serving it via a - proxy server. These options should be self explanatory and so are not - documented individually. You can use these paths (or ones in the proxy - server) to point to your own styles. + Path to favicon.ico, not the directory that contains it (the name is a + misnomer). Ignored if static_enabled is false. static_scripts_dir: type: str @@ -1919,21 +1918,15 @@ mapping: per_host: true required: false desc: | - Serve static content, which must be enabled if you're not serving it via a - proxy server. These options should be self explanatory and so are not - documented individually. You can use these paths (or ones in the proxy - server) to point to your own styles. + Path to the static scripts directory. Ignored if static_enabled is false. static_style_dir: type: str - default: static/style + default: static/style/ per_host: true required: false desc: | - Serve static content, which must be enabled if you're not serving it via a - proxy server. These options should be self explanatory and so are not - documented individually. You can use these paths (or ones in the proxy - server) to point to your own styles. + Path to the static style directory. Ignored if static_enabled is false. static_robots_txt: type: str @@ -1941,10 +1934,7 @@ mapping: per_host: true required: false desc: | - Serve static content, which must be enabled if you're not serving it via a - proxy server. These options should be self explanatory and so are not - documented individually. You can use these paths (or ones in the proxy - server) to point to your own styles. + Path to robots.txt. Ignored if static_enabled is false. display_chunk_size: type: int diff --git a/lib/galaxy/webapps/base/webapp.py b/lib/galaxy/webapps/base/webapp.py index 58d967d63f6..f995c39054e 100644 --- a/lib/galaxy/webapps/base/webapp.py +++ b/lib/galaxy/webapps/base/webapp.py @@ -66,9 +66,9 @@ from galaxy.web.framework.middleware.static import CacheableStaticURLParser as S try: import galaxy.web_client - default_static_dir = os.path.dirname(galaxy.web_client.__file__) + default_static_dist_dir = os.path.join(os.path.dirname(galaxy.web_client.__file__), "dist") except ImportError: - default_static_dir = "static/" + default_static_dist_dir = None # type: ignore[assignment] log = logging.getLogger(__name__) @@ -1160,17 +1160,19 @@ def build_url_map(app, global_conf, **local_conf): return Static(config_val, cache_time, directory_per_host=per_host_config) # Define static mappings from config - static_dir = get_static_from_config("static_dir", default_static_dir) + static_dir = get_static_from_config("static_dir", "static/") static_dir_bare = static_dir.directory.rstrip("/") + static_dist_dir = get_static_from_config("static_dist_dir", default_static_dist_dir or f"{static_dir_bare}/dist/") urlmap["/static"] = static_dir + urlmap["/static/dist"] = static_dist_dir urlmap["/images"] = get_static_from_config("static_images_dir", f"{static_dir_bare}/images") urlmap["/static/scripts"] = get_static_from_config("static_scripts_dir", f"{static_dir_bare}/scripts/") urlmap["/static/welcome.html"] = get_static_from_config( "static_welcome_html", f"{static_dir_bare}/welcome.html", sample=default_url_path("static/welcome.sample.html") ) - urlmap["/static/favicon.svg"] = get_static_from_config( - "static_favicon_dir", f"{static_dir_bare}/favicon.svg", sample=default_url_path("static/favicon.svg") + urlmap["/favicon.ico"] = get_static_from_config( + "static_favicon_dir", f"{static_dir_bare}/favicon.ico", sample=default_url_path("static/favicon.ico") ) urlmap["/robots.txt"] = get_static_from_config( "static_robots_txt", f"{static_dir_bare}/robots.txt", sample=default_url_path("static/robots.txt") diff --git a/packages/web_client/galaxy/web_client/install.py b/packages/web_client/galaxy/web_client/install.py index f78cfeda8f7..09df111bc51 100644 --- a/packages/web_client/galaxy/web_client/install.py +++ b/packages/web_client/galaxy/web_client/install.py @@ -24,7 +24,24 @@ The --mode option specifies how the web client is installed: Copy the Galaxy web client to DEST """ -CLIENT = os.path.join(os.path.dirname(__file__)) +TARGETS = { + "dist": os.path.join(os.path.dirname(__file__), "dist"), +} + +try: + import galaxy.webapps.base + + STATIC = os.path.join(os.path.dirname(galaxy.webapps.base.__file__), "static") + TARGETS.update({ + "style": os.path.join(STATIC, "style"), + "favicon.ico": os.path.join(STATIC, "favicon.ico"), + "favicon.svg": os.path.join(STATIC, "favicon.svg"), + "robots.txt": os.path.join(STATIC, "robots.txt"), + "welcome.sample.html": os.path.join(STATIC, "welcome.sample.html"), + }) +except ImportError: + # Consider this a soft fail, this package depends on nothing but is probably installed with galaxy-web-apps + pass def main(argv=None): @@ -32,12 +49,15 @@ def main(argv=None): argv = sys.argv[1:] args = _arg_parser().parse_args(argv) - dist = os.path.join(CLIENT, "dist") - assert os.path.exists(dist), f"ERROR: Cannot find web client at expected path: {dist}" - if args.mode in ("absolute", "relative"): - _symlink(args.dest, args.mode == "absolute", args.force_overwrite) - elif args.mode == "copy": - _copy(args.dest, args.force_overwrite) + assert os.path.exists(TARGETS["dist"]), f"ERROR: Cannot find web client at expected path: {TARGETS['dist']}" + + _try(functools.partial(os.makedirs, args.dest), args.dest, args.force_overwrite, dir_ok=True) + for dest, target in TARGETS.items(): + dest = os.path.join(args.dest, dest) + if args.mode in ("absolute", "relative"): + _symlink(dest, target, args.mode == "absolute", args.force_overwrite) + elif args.mode == "copy": + _copy(dest, target, args.force_overwrite) def _arg_parser(): @@ -51,30 +71,47 @@ def _arg_parser(): return parser -def _symlink(dest, absolute, force): +def _symlink(dest, target, absolute, force): if absolute: - target = os.path.abspath(CLIENT) + target = os.path.abspath(target) else: - target = os.path.relpath(CLIENT, start=dest) - _try(functools.partial(os.symlink, target, dest), dest, force) + target = os.path.relpath(target, start=os.path.dirname(dest)) + if _try(functools.partial(os.symlink, target, dest), dest, force, target=target): + print(f"link: {dest} -> {target}") -def _copy(dest, force): - _try(functools.partial(shutil.copytree, CLIENT, dest, dirs_exist_ok=False), dest, force) +def _copy(dest, target, force): + if os.path.isdir(target): + f = functools.partial(shutil.copytree, target, dest, dirs_exist_ok=False) + else: + f = functools.partial(_copy2, target, dest) + if _try(f, dest, force): + print(f"copy: {target} -> {dest}") -def _try(f, dest, force): +def _copy2(target, dest): + if os.path.exists(dest): + raise FileExistsError(dest) + shutil.copy2(target, dest) + + +def _try(f, dest, force, target=None, dir_ok=False): try: f() - except FileExistsError: + except (FileExistsError, shutil.SameFileError): + if dir_ok and os.path.isdir(dest) and not os.path.islink(dest): + return True + if target and os.path.islink(dest) and os.readlink(dest) == target: + return True if not force: print(f"ERROR: File exists, use --force-overwrite to overwrite: {dest}") - sys.exit(1) + return False if os.path.isdir(dest) and not os.path.islink(dest): shutil.rmtree(dest) else: os.unlink(dest) f() + return True if __name__ == "__main__": diff --git a/packages/web_client/setup.cfg b/packages/web_client/setup.cfg index e1e28f289bb..6410e454cd8 100644 --- a/packages/web_client/setup.cfg +++ b/packages/web_client/setup.cfg @@ -27,7 +27,7 @@ long_description = file: README.rst, HISTORY.rst long_description_content_type = text/x-rst name = galaxy-web-client url = https://github.com/galaxyproject/galaxy -version = 25.0.dev0 +version = 25.0.1.dev0 [options] include_package_data = True