[arvados-workbench2] created: 2.4.0-158-ge2ac5434

git repository hosting git at public.arvados.org
Tue Jul 26 01:55:47 UTC 2022


        at  e2ac5434eb436b0e8ca8205dfe83d4ef1bcdd4c5 (commit)


commit e2ac5434eb436b0e8ca8205dfe83d4ef1bcdd4c5
Author: Stephen Smith <stephen at curii.com>
Date:   Mon Jul 25 18:54:37 2022 -0400

    16070: Add optional linking to code snippet component. Base styles off of default theme for link color
    
    Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen at curii.com>

diff --git a/src/components/code-snippet/code-snippet.tsx b/src/components/code-snippet/code-snippet.tsx
index f156e3e8..83c378b8 100644
--- a/src/components/code-snippet/code-snippet.tsx
+++ b/src/components/code-snippet/code-snippet.tsx
@@ -3,9 +3,14 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import React from 'react';
-import { StyleRulesCallback, WithStyles, Typography, withStyles } from '@material-ui/core';
+import { StyleRulesCallback, WithStyles, Typography, withStyles, Link } from '@material-ui/core';
 import { ArvadosTheme } from 'common/custom-theme';
 import classNames from 'classnames';
+import { connect, DispatchProp } from 'react-redux';
+import { RootState } from 'store/store';
+import { FederationConfig, getNavUrl } from 'routes/routes';
+import { Dispatch } from 'redux';
+import { navigationNotAvailable } from 'store/navigation/navigation-action';
 
 type CssRules = 'root' | 'space';
 
@@ -24,17 +29,57 @@ export interface CodeSnippetDataProps {
     lines: string[];
     className?: string;
     apiResponse?: boolean;
+    linked?: boolean;
+}
+
+interface CodeSnippetAuthProps {
+    auth: FederationConfig;
 }
 
 type CodeSnippetProps = CodeSnippetDataProps & WithStyles<CssRules>;
 
-export const CodeSnippet = withStyles(styles)(
-    ({ classes, lines, className, apiResponse }: CodeSnippetProps) =>
+const mapStateToProps = (state: RootState): CodeSnippetAuthProps => ({
+    auth: state.auth,
+});
+
+export const CodeSnippet = withStyles(styles)(connect(mapStateToProps)(
+    ({ classes, lines, linked, className, apiResponse, dispatch, auth }: CodeSnippetProps & CodeSnippetAuthProps & DispatchProp) =>
         <Typography
         component="div"
         className={classNames(classes.root, className)}>
             <Typography className={apiResponse ? classes.space : className} component="pre">
-                {lines.join('\n')}
+                {linked ?
+                    lines.map((line, index) => <React.Fragment key={index}>{renderLinks(auth, dispatch)(line)}{`\n`}</React.Fragment>) :
+                    lines.join('\n')
+                }
             </Typography>
         </Typography>
-    );
+    ));
+
+const renderLinks = (auth: FederationConfig, dispatch: Dispatch) => (text: string): JSX.Element => {
+    // Matches UUIDs & PDHs
+    const REGEX = /[a-z0-9]{5}-[a-z0-9]{5}-[a-z0-9]{15}|[0-9a-f]{32}\+\d+/g;
+    const links = text.match(REGEX);
+    if (!links) {
+        return <>{text}</>;
+    }
+    return <>
+        {text.split(REGEX).map((part, index) =>
+            <React.Fragment key={index}>
+                {part}
+                {links[index] &&
+                <Link onClick={() => {
+                    const url = getNavUrl(links[index], auth)
+                    if (url) {
+                        window.open(`${window.location.origin}${url}`, '_blank');
+                    } else {
+                        dispatch(navigationNotAvailable(links[index]));
+                    }
+                }}
+                    style={ {cursor: 'pointer'} }>
+                    {links[index]}
+                </Link>}
+            </React.Fragment>
+        )}
+    </>;
+  };
diff --git a/src/components/default-code-snippet/default-code-snippet.tsx b/src/components/default-code-snippet/default-code-snippet.tsx
index 7ba97db4..bdcfc10f 100644
--- a/src/components/default-code-snippet/default-code-snippet.tsx
+++ b/src/components/default-code-snippet/default-code-snippet.tsx
@@ -6,8 +6,9 @@ import React from 'react';
 import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
 import { CodeSnippet, CodeSnippetDataProps } from 'components/code-snippet/code-snippet';
 import grey from '@material-ui/core/colors/grey';
+import { themeOptions } from 'common/custom-theme';
 
-const theme = createMuiTheme({
+const theme = createMuiTheme(Object.assign({}, themeOptions, {
     overrides: {
         MuiTypography: {
             body1: {
@@ -22,9 +23,9 @@ const theme = createMuiTheme({
         fontFamily: 'monospace',
         useNextVariants: true,
     }
-});
+}));
 
-export const DefaultCodeSnippet = (props: CodeSnippetDataProps) => 
+export const DefaultCodeSnippet = (props: CodeSnippetDataProps) =>
     <MuiThemeProvider theme={theme}>
         <CodeSnippet {...props} />
-    </MuiThemeProvider>;
\ No newline at end of file
+    </MuiThemeProvider>;
diff --git a/src/views/process-panel/process-cmd-card.tsx b/src/views/process-panel/process-cmd-card.tsx
index 36a0128b..4143501e 100644
--- a/src/views/process-panel/process-cmd-card.tsx
+++ b/src/views/process-panel/process-cmd-card.tsx
@@ -54,7 +54,7 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     },
 });
 
-export interface ProcessCmdCardDataProps {
+interface ProcessCmdCardDataProps {
   process: Process;
   onCopy: (text: string) => void;
 }
@@ -125,7 +125,7 @@ export const ProcessCmdCard = withStyles(styles)(
           }
         />
         <CardContent className={classes.content}>
-          <DefaultCodeSnippet lines={formattedCommand} />
+          <DefaultCodeSnippet lines={formattedCommand} linked />
         </CardContent>
       </Card>
     );

commit 829d595bb4b9e7c0a8a1dd38995b4b5e197841f5
Author: Stephen Smith <stephen at curii.com>
Date:   Wed Jul 20 21:06:03 2022 -0400

    16070: Replace process command dialog with command card
    
    Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen at curii.com>

diff --git a/src/components/code-snippet/code-snippet.tsx b/src/components/code-snippet/code-snippet.tsx
index f0a2b213..f156e3e8 100644
--- a/src/components/code-snippet/code-snippet.tsx
+++ b/src/components/code-snippet/code-snippet.tsx
@@ -33,10 +33,8 @@ export const CodeSnippet = withStyles(styles)(
         <Typography
         component="div"
         className={classNames(classes.root, className)}>
-            {
-                lines.map((line: string, index: number) => {
-                    return <Typography key={index} className={apiResponse ? classes.space : className} component="pre">{line}</Typography>;
-                })
-            }
+            <Typography className={apiResponse ? classes.space : className} component="pre">
+                {lines.join('\n')}
+            </Typography>
         </Typography>
-    );
\ No newline at end of file
+    );
diff --git a/src/store/processes/process-command-actions.ts b/src/store/processes/process-command-actions.ts
deleted file mode 100644
index d81a7c4d..00000000
--- a/src/store/processes/process-command-actions.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import { dialogActions } from 'store/dialog/dialog-actions';
-import { RootState } from 'store/store';
-import { Dispatch } from 'redux';
-import { getProcess } from 'store/processes/process';
-import shellescape from 'shell-escape';
-
-export const PROCESS_COMMAND_DIALOG_NAME = 'processCommandDialog';
-
-export interface ProcessCommandDialogData {
-    command: string;
-    processName: string;
-}
-
-export const openProcessCommandDialog = (processUuid: string) =>
-    (dispatch: Dispatch<any>, getState: () => RootState) => {
-        const process = getProcess(processUuid)(getState().resources);
-        if (process) {
-            const data: ProcessCommandDialogData = {
-                command: shellescape(process.containerRequest.command),
-                processName: process.containerRequest.name,
-            };
-            dispatch(dialogActions.OPEN_DIALOG({ id: PROCESS_COMMAND_DIALOG_NAME, data }));
-        }
-    };
diff --git a/src/views-components/context-menu/action-sets/process-resource-action-set.ts b/src/views-components/context-menu/action-sets/process-resource-action-set.ts
index 55b2d31f..65e29bef 100644
--- a/src/views-components/context-menu/action-sets/process-resource-action-set.ts
+++ b/src/views-components/context-menu/action-sets/process-resource-action-set.ts
@@ -20,7 +20,6 @@ import { toggleDetailsPanel } from 'store/details-panel/details-panel-action';
 import { snackbarActions, SnackbarKind } from "store/snackbar/snackbar-actions";
 import { openProcessInputDialog } from "store/processes/process-input-actions";
 import { navigateToOutput } from "store/process-panel/process-panel-actions";
-import { openProcessCommandDialog } from "store/processes/process-command-actions";
 import { openAdvancedTabDialog } from "store/advanced-tab/advanced-tab";
 import { TogglePublicFavoriteAction } from "../actions/public-favorite-action";
 import { togglePublicFavorite } from "store/public-favorites/public-favorites-actions";
@@ -69,13 +68,6 @@ export const readOnlyProcessResourceActionSet: ContextMenuActionSet = [[
             }
         }
     },
-    {
-        icon: CommandIcon,
-        name: "Command",
-        execute: (dispatch, resource) => {
-            dispatch<any>(openProcessCommandDialog(resource.uuid));
-        }
-    },
     {
         icon: DetailsIcon,
         name: "View details",
@@ -135,4 +127,4 @@ export const processResourceAdminActionSet: ContextMenuActionSet = [[
             });
         }
     },
-]];
\ No newline at end of file
+]];
diff --git a/src/views-components/process-command-dialog/process-command-dialog.tsx b/src/views-components/process-command-dialog/process-command-dialog.tsx
deleted file mode 100644
index 7695837e..00000000
--- a/src/views-components/process-command-dialog/process-command-dialog.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import React from "react";
-import { Dialog, DialogActions, Button, StyleRulesCallback, WithStyles, withStyles, Tooltip, IconButton, CardHeader } from '@material-ui/core';
-import { withDialog } from "store/dialog/with-dialog";
-import { PROCESS_COMMAND_DIALOG_NAME } from 'store/processes/process-command-actions';
-import { WithDialogProps } from 'store/dialog/with-dialog';
-import { ProcessCommandDialogData } from 'store/processes/process-command-actions';
-import { DefaultCodeSnippet } from "components/default-code-snippet/default-code-snippet";
-import { compose } from 'redux';
-import CopyToClipboard from "react-copy-to-clipboard";
-import { CopyIcon } from 'components/icon/icon';
-
-type CssRules = 'codeSnippet' | 'copyToClipboard';
-
-const styles: StyleRulesCallback<CssRules> = theme => ({
-    codeSnippet: {
-        marginLeft: theme.spacing.unit * 3,
-        marginRight: theme.spacing.unit * 3,
-    },
-    copyToClipboard: {
-        marginRight: theme.spacing.unit,
-    }
-});
-
-export const ProcessCommandDialog = compose(
-    withDialog(PROCESS_COMMAND_DIALOG_NAME),
-    withStyles(styles),
-)(
-    (props: WithDialogProps<ProcessCommandDialogData> & WithStyles<CssRules>) =>
-        <Dialog
-            open={props.open}
-            maxWidth="md"
-            onClose={props.closeDialog}
-            style={{ alignSelf: 'stretch' }}>
-            <CardHeader
-                title={`Command - ${props.data.processName}`}
-                action={
-                    <Tooltip title="Copy to clipboard">
-                        <CopyToClipboard text={props.data.command}>
-                            <IconButton className={props.classes.copyToClipboard}>
-                                <CopyIcon />
-                            </IconButton>
-                        </CopyToClipboard>
-                    </Tooltip>
-                } />
-            <DefaultCodeSnippet
-                className={props.classes.codeSnippet}
-                lines={[props.data.command]} />
-            <DialogActions>
-                <Button
-                    variant='text'
-                    color='primary'
-                    onClick={props.closeDialog}>
-                    Close
-                </Button>
-            </DialogActions>
-        </Dialog>
-);
\ No newline at end of file
diff --git a/src/views/process-panel/process-cmd-card.tsx b/src/views/process-panel/process-cmd-card.tsx
new file mode 100644
index 00000000..36a0128b
--- /dev/null
+++ b/src/views/process-panel/process-cmd-card.tsx
@@ -0,0 +1,133 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import React from 'react';
+import {
+    StyleRulesCallback,
+    WithStyles,
+    withStyles,
+    Card,
+    CardHeader,
+    IconButton,
+    CardContent,
+    Tooltip,
+    Typography,
+    Grid,
+} from '@material-ui/core';
+import { ArvadosTheme } from 'common/custom-theme';
+import { CloseIcon, CommandIcon, CopyIcon } from 'components/icon/icon';
+import { MPVPanelProps } from 'components/multi-panel-view/multi-panel-view';
+import { DefaultCodeSnippet } from 'components/default-code-snippet/default-code-snippet';
+import { Process } from 'store/processes/process';
+import shellescape from 'shell-escape';
+import CopyToClipboard from 'react-copy-to-clipboard';
+
+type CssRules = 'card' | 'content' | 'title' | 'header' | 'avatar' | 'iconHeader';
+
+const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
+    card: {
+        height: '100%'
+    },
+    header: {
+        paddingTop: theme.spacing.unit,
+        paddingBottom: theme.spacing.unit,
+    },
+    iconHeader: {
+        fontSize: '1.875rem',
+        color: theme.customs.colors.green700,
+    },
+    avatar: {
+        alignSelf: 'flex-start',
+        paddingTop: theme.spacing.unit * 0.5
+    },
+    content: {
+        padding: theme.spacing.unit * 1.0,
+        paddingTop: theme.spacing.unit * 0.5,
+        '&:last-child': {
+            paddingBottom: theme.spacing.unit * 1,
+        }
+    },
+    title: {
+        overflow: 'hidden',
+        paddingTop: theme.spacing.unit * 0.5
+    },
+});
+
+export interface ProcessCmdCardDataProps {
+  process: Process;
+  onCopy: (text: string) => void;
+}
+
+type ProcessCmdCardProps = ProcessCmdCardDataProps & WithStyles<CssRules> & MPVPanelProps;
+
+export const ProcessCmdCard = withStyles(styles)(
+  ({
+    process,
+    onCopy,
+    classes,
+    doHidePanel,
+  }: ProcessCmdCardProps) => {
+    const command = process.containerRequest.command.map((v) =>
+      shellescape([v]) // Escape each arg separately
+    );
+
+    let formattedCommand = [...command];
+    formattedCommand.forEach((item, i, arr) => {
+      // Indent lines after the first
+      const indent = i > 0 ? '  ' : '';
+      // Escape newlines on every non-last arg when there are multiple lines
+      const lineBreak = arr.length > 1 && i < arr.length - 1 ? ' \\' : '';
+      arr[i] = `${indent}${item}${lineBreak}`;
+    });
+
+    return (
+      <Card className={classes.card}>
+        <CardHeader
+          className={classes.header}
+          classes={{
+            content: classes.title,
+            avatar: classes.avatar,
+          }}
+          avatar={<CommandIcon className={classes.iconHeader} />}
+          title={
+            <Typography noWrap variant="h6" color="inherit">
+              Command
+            </Typography>
+          }
+          action={
+            <Grid container direction="row" alignItems="center">
+              <Grid item>
+                <Tooltip title="Copy to clipboard" disableFocusListener>
+                  <IconButton>
+                    <CopyToClipboard
+                      text={command.join(" ")}
+                      onCopy={() => onCopy("Command copied to clipboard")}
+                    >
+                      <CopyIcon />
+                    </CopyToClipboard>
+                  </IconButton>
+                </Tooltip>
+              </Grid>
+              <Grid item>
+                {doHidePanel && (
+                  <Tooltip
+                    title={`Close Command Panel`}
+                    disableFocusListener
+                  >
+                    <IconButton onClick={doHidePanel}>
+                      <CloseIcon />
+                    </IconButton>
+                  </Tooltip>
+                )}
+              </Grid>
+            </Grid>
+          }
+        />
+        <CardContent className={classes.content}>
+          <DefaultCodeSnippet lines={formattedCommand} />
+        </CardContent>
+      </Card>
+    );
+  }
+);
diff --git a/src/views/process-panel/process-panel-root.tsx b/src/views/process-panel/process-panel-root.tsx
index 4f95d0d8..f8ff8430 100644
--- a/src/views/process-panel/process-panel-root.tsx
+++ b/src/views/process-panel/process-panel-root.tsx
@@ -15,6 +15,7 @@ import { ProcessDetailsCard } from './process-details-card';
 import { getProcessPanelLogs, ProcessLogsPanel } from 'store/process-logs-panel/process-logs-panel';
 import { ProcessLogsCard } from './process-log-card';
 import { FilterOption } from 'views/process-panel/process-log-form';
+import { ProcessCmdCard } from './process-cmd-card';
 
 type CssRules = 'root';
 
@@ -37,13 +38,14 @@ export interface ProcessPanelRootActionProps {
     cancelProcess: (uuid: string) => void;
     onLogFilterChange: (filter: FilterOption) => void;
     navigateToLog: (uuid: string) => void;
-    onLogCopyToClipboard: (uuid: string) => void;
+    onCopyToClipboard: (uuid: string) => void;
 }
 
 export type ProcessPanelRootProps = ProcessPanelRootDataProps & ProcessPanelRootActionProps & WithStyles<CssRules>;
 
 const panelsData: MPVPanelState[] = [
     {name: "Details"},
+    {name: "Command"},
     {name: "Logs", visible: true},
     {name: "Subprocesses"},
 ];
@@ -59,9 +61,14 @@ export const ProcessPanelRoot = withStyles(styles)(
                     cancelProcess={props.cancelProcess}
                 />
             </MPVPanelContent>
+            <MPVPanelContent forwardProps xs="auto" data-cy="process-cmd">
+                <ProcessCmdCard
+                    onCopy={props.onCopyToClipboard}
+                    process={process} />
+            </MPVPanelContent>
             <MPVPanelContent forwardProps xs maxHeight='50%' data-cy="process-logs">
                 <ProcessLogsCard
-                    onCopy={props.onLogCopyToClipboard}
+                    onCopy={props.onCopyToClipboard}
                     process={process}
                     lines={getProcessPanelLogs(processLogsPanel)}
                     selectedFilter={{
diff --git a/src/views/process-panel/process-panel.tsx b/src/views/process-panel/process-panel.tsx
index de6b13b3..7afaa04d 100644
--- a/src/views/process-panel/process-panel.tsx
+++ b/src/views/process-panel/process-panel.tsx
@@ -36,7 +36,7 @@ const mapStateToProps = ({ router, resources, processPanel, processLogsPanel }:
 };
 
 const mapDispatchToProps = (dispatch: Dispatch): ProcessPanelRootActionProps => ({
-    onLogCopyToClipboard: (message: string) => {
+    onCopyToClipboard: (message: string) => {
         dispatch<any>(snackbarActions.OPEN_SNACKBAR({
             message,
             hideDuration: 2000,
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index 28fae4cd..a6c49e34 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -33,7 +33,6 @@ import { MoveProjectDialog } from 'views-components/dialog-forms/move-project-di
 import { MoveCollectionDialog } from 'views-components/dialog-forms/move-collection-dialog';
 import { FilesUploadCollectionDialog } from 'views-components/dialog-forms/files-upload-collection-dialog';
 import { PartialCopyCollectionDialog } from 'views-components/dialog-forms/partial-copy-collection-dialog';
-import { ProcessCommandDialog } from 'views-components/process-command-dialog/process-command-dialog';
 import { RemoveProcessDialog } from 'views-components/process-remove-dialog/process-remove-dialog';
 import { MainContentBar } from 'views-components/main-content-bar/main-content-bar';
 import { Grid } from '@material-ui/core';
@@ -241,7 +240,6 @@ export const WorkbenchPanel =
             <PublicKeyDialog />
             <PartialCopyCollectionDialog />
             <PartialCopyToCollectionDialog />
-            <ProcessCommandDialog />
             <ProcessInputDialog />
             <RestoreCollectionVersionDialog />
             <RemoveApiClientAuthorizationDialog />

commit 6ab5c8019be196ba0e7ff401f2734f181f4f7ced
Author: Stephen Smith <stephen at curii.com>
Date:   Wed Jul 20 21:01:32 2022 -0400

    16070: Swap shell escaping library to improve command line display
    
    Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen at curii.com>

diff --git a/package.json b/package.json
index a8b3ee81..9e663ca6 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,7 @@
     "@types/react-virtualized-auto-sizer": "1.0.0",
     "@types/react-window": "1.8.2",
     "@types/redux-form": "7.4.12",
-    "@types/shell-quote": "1.6.0",
+    "@types/shell-escape": "^0.2.0",
     "axios": "^0.21.1",
     "babel-core": "6.26.3",
     "babel-runtime": "6.26.0",
@@ -71,7 +71,7 @@
     "redux-thunk": "2.3.0",
     "reselect": "4.0.0",
     "set-value": "2.0.1",
-    "shell-quote": "1.6.1",
+    "shell-escape": "^0.2.0",
     "sinon": "7.3",
     "tslint": "5.20.0",
     "tslint-etc": "1.6.0",
diff --git a/src/store/processes/process-command-actions.ts b/src/store/processes/process-command-actions.ts
index 9dec9b30..d81a7c4d 100644
--- a/src/store/processes/process-command-actions.ts
+++ b/src/store/processes/process-command-actions.ts
@@ -6,7 +6,7 @@ import { dialogActions } from 'store/dialog/dialog-actions';
 import { RootState } from 'store/store';
 import { Dispatch } from 'redux';
 import { getProcess } from 'store/processes/process';
-import { quote } from 'shell-quote';
+import shellescape from 'shell-escape';
 
 export const PROCESS_COMMAND_DIALOG_NAME = 'processCommandDialog';
 
@@ -20,7 +20,7 @@ export const openProcessCommandDialog = (processUuid: string) =>
         const process = getProcess(processUuid)(getState().resources);
         if (process) {
             const data: ProcessCommandDialogData = {
-                command: quote(process.containerRequest.command),
+                command: shellescape(process.containerRequest.command),
                 processName: process.containerRequest.name,
             };
             dispatch(dialogActions.OPEN_DIALOG({ id: PROCESS_COMMAND_DIALOG_NAME, data }));
diff --git a/yarn.lock b/yarn.lock
index 13ea553a..6dfb5b18 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2817,10 +2817,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/shell-quote at npm:1.6.0":
-  version: 1.6.0
-  resolution: "@types/shell-quote at npm:1.6.0"
-  checksum: 5d9f4e35c8df32d9994f8ae2f1a1fe8a6b7ee96794f803e0904ceae7ad7255a214954e85cd75bd847fe77458d3746430522e87237438f223b7d72a23c4928c0e
+"@types/shell-escape at npm:^0.2.0":
+  version: 0.2.0
+  resolution: "@types/shell-escape at npm:0.2.0"
+  checksum: 020696ed313eeb02deb2abcc581e8b570be6f9ee662892339965b524bb4fbdc9a97b6520d914117740ec11147b0b1aa52358b8e03fa214c2da99743adb196853
   languageName: node
   linkType: hard
 
@@ -3600,13 +3600,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"array-filter at npm:~0.0.0":
-  version: 0.0.1
-  resolution: "array-filter at npm:0.0.1"
-  checksum: 0e9afdf5e248c45821c6fe1232071a13a3811e1902c2c2a39d12e4495e8b0b25739fd95bffbbf9884b9693629621f6077b4ae16207b8f23d17710fc2465cebbb
-  languageName: node
-  linkType: hard
-
 "array-find-index at npm:^1.0.1":
   version: 1.0.2
   resolution: "array-find-index at npm:1.0.2"
@@ -3648,20 +3641,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"array-map at npm:~0.0.0":
-  version: 0.0.0
-  resolution: "array-map at npm:0.0.0"
-  checksum: 30d73fdc99956c8bd70daea40db5a7d78c5c2c75a03c64fc77904885e79adf7d5a0595076534f4e58962d89435f0687182ac929e65634e3d19931698cbac8149
-  languageName: node
-  linkType: hard
-
-"array-reduce at npm:~0.0.0":
-  version: 0.0.0
-  resolution: "array-reduce at npm:0.0.0"
-  checksum: d6226325271f477e3dd65b4d40db8597735b8d08bebcca4972e52d3c173d6c697533664fa8865789ea2d076bdaf1989bab5bdfbb61598be92074a67f13057c3a
-  languageName: node
-  linkType: hard
-
 "array-union at npm:^1.0.1":
   version: 1.0.2
   resolution: "array-union at npm:1.0.2"
@@ -3769,7 +3748,7 @@ __metadata:
     "@types/redux-devtools": 3.0.44
     "@types/redux-form": 7.4.12
     "@types/redux-mock-store": 1.0.2
-    "@types/shell-quote": 1.6.0
+    "@types/shell-escape": ^0.2.0
     "@types/sinon": 7.5
     "@types/uuid": 3.4.4
     axios: ^0.21.1
@@ -3829,7 +3808,7 @@ __metadata:
     redux-thunk: 2.3.0
     reselect: 4.0.0
     set-value: 2.0.1
-    shell-quote: 1.6.1
+    shell-escape: ^0.2.0
     sinon: 7.3
     ts-mock-imports: 1.3.7
     tslint: 5.20.0
@@ -16502,15 +16481,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"shell-quote at npm:1.6.1":
-  version: 1.6.1
-  resolution: "shell-quote at npm:1.6.1"
-  dependencies:
-    array-filter: ~0.0.0
-    array-map: ~0.0.0
-    array-reduce: ~0.0.0
-    jsonify: ~0.0.0
-  checksum: 982a4fdf2d474f0dc40885de4222f100ba457d7c75d46b532bf23b01774b8617bc62522c6825cb1fa7dd4c54c18e9dcbae7df2ca8983101841b6f2e6a7cacd2f
+"shell-escape at npm:^0.2.0":
+  version: 0.2.0
+  resolution: "shell-escape at npm:0.2.0"
+  checksum: 0d87f1ae22ad22a74e148348ceaf64721e3024f83c90afcfb527318ce10ece654dd62e103dd89a242f2f4e4ce3cecdef63e3d148c40e5fabca8ba6c508f97d9f
   languageName: node
   linkType: hard
 

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list