From e7848b5a9d38c894155bb12e9a1590ebdc032522 Mon Sep 17 00:00:00 2001 From: Joey Ballentine Date: Sat, 13 Jan 2024 14:45:32 -0500 Subject: [PATCH 1/8] Add "Manual/Copy" install mode to dependency manager --- src/common/pip.ts | 2 +- src/renderer/contexts/DependencyContext.tsx | 123 ++++++++++++++------ 2 files changed, 90 insertions(+), 35 deletions(-) diff --git a/src/common/pip.ts b/src/common/pip.ts index e9d99e301..5765e18d0 100644 --- a/src/common/pip.ts +++ b/src/common/pip.ts @@ -57,7 +57,7 @@ export const runPip = async ( }); }; -const getFindLinks = (dependencies: readonly PyPiPackage[]): string[] => { +export const getFindLinks = (dependencies: readonly PyPiPackage[]): string[] => { const links = new Set(); for (const p of dependencies) { if (p.findLink) { diff --git a/src/renderer/contexts/DependencyContext.tsx b/src/renderer/contexts/DependencyContext.tsx index 75bd58145..f63689580 100644 --- a/src/renderer/contexts/DependencyContext.tsx +++ b/src/renderer/contexts/DependencyContext.tsx @@ -21,16 +21,18 @@ import { ModalHeader, ModalOverlay, Progress, + Select, Spacer, Spinner, - Switch, Tag, Text, Textarea, Tooltip, VStack, useDisclosure, + useToast, } from '@chakra-ui/react'; +import { clipboard } from 'electron'; import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { BsQuestionCircle, BsTerminalFill } from 'react-icons/bs'; import { HiOutlineRefresh } from 'react-icons/hi'; @@ -46,7 +48,7 @@ import { Version, } from '../../common/common-types'; import { log } from '../../common/log'; -import { OnStdio, runPipInstall, runPipUninstall } from '../../common/pip'; +import { OnStdio, getFindLinks, runPipInstall, runPipUninstall } from '../../common/pip'; import { noop } from '../../common/util'; import { versionGt } from '../../common/version'; import { Markdown } from '../components/Markdown'; @@ -56,6 +58,12 @@ import { BackendContext } from './BackendContext'; import { GlobalContext } from './GlobalNodeState'; import { SettingsContext } from './SettingsContext'; +const installModes = { + NORMAL: 'Normal Install', + DIRECT_PIP: 'Direct Pip', + MANUAL_COPY: 'Manual/Copy', +}; + export interface DependencyContextValue { openDependencyManager: () => void; availableUpdates: number; @@ -382,7 +390,7 @@ export const DependencyProvider = memo(({ children }: React.PropsWithChildren Promise) => { if (isRunningShell) throw new Error('Cannot run two pip commands at once'); @@ -444,25 +454,65 @@ export const DependencyProvider = memo(({ children }: React.PropsWithChildren { - setInstallingPackage(p); + const copyCommandToClipboard = (command: string) => { + clipboard.writeText(command); + toast({ + title: 'Command copied to clipboard.', + description: + 'Open up anm external terminal, paste the command, and run it. When it is done running, manually restart chaiNNer.', + status: 'success', + duration: 9000, + isClosable: true, + }); + }; + + const installPackage = (pkg: Package) => { + if (installMode === installModes.MANUAL_COPY) { + const deps = pkg.dependencies.map((p) => `${p.pypiName}==${p.version}`); + const findLinks = getFindLinks(pkg.dependencies).flatMap((l) => [ + '--extra-index-url', + l, + ]); + const args = [ + pythonInfo.python, + '-m', + 'pip', + 'install', + '--upgrade', + ...deps, + ...findLinks, + '--no-cache-dir', + '--disable-pip-version-check', + ]; + const cmd = args.join(' '); + copyCommandToClipboard(cmd); + return; + } + setInstallingPackage(pkg); changePackages(() => runPipInstall( pythonInfo, - p.dependencies, - usePipDirectly ? undefined : setProgress, + pkg.dependencies, + installMode === installModes.NORMAL ? setProgress : undefined, onStdio ) ); }; - const uninstallPackage = (p: Package) => { - setUninstallingPackage(p); + const uninstallPackage = (pkg: Package) => { + if (installMode === installModes.MANUAL_COPY) { + const deps = pkg.dependencies.map((p) => p.pypiName); + const args = [pythonInfo.python, '-m', 'pip', 'uninstall', ...deps]; + const cmd = args.join(' '); + copyCommandToClipboard(cmd); + return; + } + setUninstallingPackage(pkg); changePackages(() => runPipUninstall( pythonInfo, - p.dependencies, - usePipDirectly ? undefined : setProgress, + pkg.dependencies, + installMode === installModes.NORMAL ? setProgress : undefined, onStdio ) ); @@ -531,29 +581,34 @@ export const DependencyProvider = memo(({ children }: React.PropsWithChildren - + - { - setUsePipDirectly(!usePipDirectly); - }} - /> - Use Pip Directly - -
- -
-
+ + + +
+ +
+
+