Unverified Commit e95a5590 authored by Marius van den Beek's avatar Marius van den Beek Committed by GitHub
Browse files

Merge pull request #20516 from natefoo/web-client-static-fixes

[25.0] Fixes for static handling and the web_client package
parents 43feb0ef 39285ff3
Loading
Loading
Loading
Loading
+30 −33
Original line number Diff line number Diff line
@@ -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

+22 −33
Original line number Diff line number Diff line
@@ -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
+23 −33
Original line number Diff line number Diff line
@@ -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_dist_dir:
        type: str
        default: static/dist/
        per_host: true
        required: false
        desc: |
          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
        default: static/images/
        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 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
+7 −5
Original line number Diff line number Diff line
@@ -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")
+53 −16
Original line number Diff line number Diff line
@@ -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}"
    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(args.dest, args.mode == "absolute", args.force_overwrite)
            _symlink(dest, target, args.mode == "absolute", args.force_overwrite)
        elif args.mode == "copy":
        _copy(args.dest, args.force_overwrite)
            _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(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, target, force):
    if os.path.isdir(target):
        f = functools.partial(shutil.copytree, target, dest, dirs_exist_ok=False)
    else:
        target = os.path.relpath(CLIENT, start=dest)
    _try(functools.partial(os.symlink, target, dest), dest, force)
        f = functools.partial(_copy2, target, dest)
    if _try(f, dest, force):
        print(f"copy: {target} -> {dest}")


def _copy(dest, force):
    _try(functools.partial(shutil.copytree, CLIENT, dest, dirs_exist_ok=False), dest, force)
def _copy2(target, dest):
    if os.path.exists(dest):
        raise FileExistsError(dest)
    shutil.copy2(target, dest)


def _try(f, dest, force):
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__":
Loading