Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat/install snapshot #15

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,19 @@ will simply update the comfy.yaml file to reflect the local setup
* `comfy install --skip-manager`: Install ComfyUI without ComfyUI-Manager.
* `comfy --workspace=<path> install`: Install ComfyUI into `<path>/ComfyUI`.
* For `comfy install`, if no path specification like `--workspace, --recent, or --here` is provided, it will be implicitly installed in `<HOME>/comfy`.
* **(WIP)** `comfy install --snapshot=<comfy-lock.yaml path>`: Install ComfyUI and whole environments from snapshot.
* **(WIP)** Currently, only the installation of ComfyUI and custom nodes is being applied.


### Backup Snapshot [WIP]

To backup ComfyUI Environment:

`comfy backup --output=<.yaml path>`

This command is used to perform a full backup of the currently installed ComfyUI Environment.
**(WIP)** Currently, only the ComfyUI and Custom node information are backed up.

### Specifying execution path

* You can specify the path of ComfyUI where the command will be applied through path indicators as follows:
Expand Down Expand Up @@ -99,6 +110,7 @@ comfy allows you to easily install, update, and remove packages for ComfyUI. Her
`comfy package list`



### Managing Custom Nodes

comfy provides a convenient way to manage custom nodes for extending ComfyUI's functionality. Here are some examples:
Expand Down
53 changes: 53 additions & 0 deletions comfy_cli/cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import time
import uuid
import webbrowser
import yaml

from typing import Optional

import questionary
Expand Down Expand Up @@ -67,6 +69,46 @@ def init():
print(f"scan_dir took {end_time - start_time:.2f} seconds to run")


@app.command(help="Backup current snapshot")
@tracking.track_command()
def backup(
ctx: typer.Context,
output: Annotated[
str,
"--output",
typer.Option(show_default=False, help="Specify the output file path. (.yaml)"),
],
):

if not output.endswith(".yaml"):
print(f"[bold red]The output path must end with '.yaml'.[/bold red]")
raise typer.Exit(code=1)

output_path = os.path.abspath(output)

config_manager = workspace_manager.config_manager
ltdrdata marked this conversation as resolved.
Show resolved Hide resolved
tmp_path = (
os.path.join(config_manager.get_config_path(), "tmp", str(uuid.uuid4()))
+ ".yaml"
)
tmp_path = os.path.abspath(tmp_path)
custom_nodes.command.execute_cm_cli(
ctx, ["save-snapshot", "--output", tmp_path], silent=True
)

with open(tmp_path, "r", encoding="UTF-8") as yaml_file:
info = yaml.load(yaml_file, Loader=yaml.SafeLoader)
os.remove(tmp_path)

info["basic"] = "N/A" # TODO:
info["models"] = [] # TODO:

with open(output_path, "w") as yaml_file:
yaml.dump(info, yaml_file, allow_unicode=True)

print(f"Snapshot file is saved as `{output_path}`")


@app.command(help="Download and install ComfyUI and ComfyUI-Manager")
@tracking.track_command()
def install(
Expand All @@ -87,9 +129,15 @@ def install(
] = False,
amd: Annotated[bool, typer.Option(help="Install for AMD gpu")] = False,
commit: Annotated[str, typer.Option(help="Specify commit hash for ComfyUI")] = None,
snapshot: Annotated[
str, typer.Option(help="Specify path to comfy-lock.yaml ")
] = None,
):
checker = EnvChecker()

if snapshot is not None:
snapshot = os.path.abspath(snapshot)

# In the case of installation, since it involves installing in a non-existent path, get_workspace_path is not used.
specified_workspace = ctx.obj.get(constants.CONTEXT_KEY_WORKSPACE)
use_recent = ctx.obj.get(constants.CONTEXT_KEY_RECENT)
Expand Down Expand Up @@ -130,6 +178,11 @@ def install(
torch_mode,
commit=commit,
)

if snapshot is not None:
checker.check()
install_inner.apply_snapshot(ctx, checker, snapshot)

workspace_manager.set_recent_workspace(workspace_path)


Expand Down
10 changes: 8 additions & 2 deletions comfy_cli/command/custom_nodes/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
workspace_manager = WorkspaceManager()


def execute_cm_cli(ctx: typer.Context, args, channel=None, mode=None):
def execute_cm_cli(ctx: typer.Context, args, channel=None, mode=None, silent=False):
_config_manager = ConfigManager()

workspace_path = workspace_manager.get_workspace_path(ctx)
Expand Down Expand Up @@ -49,7 +49,13 @@ def execute_cm_cli(ctx: typer.Context, args, channel=None, mode=None):

print(f"Execute from: {comfyui_path}")

subprocess.run(cmd, env=new_env)
if silent:
subprocess.run(
cmd, env=new_env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
)
else:
subprocess.run(cmd, env=new_env)

workspace_manager.set_recent_workspace(workspace_path)


Expand Down
18 changes: 18 additions & 0 deletions comfy_cli/command/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import subprocess
from rich import print
import sys
import typer
from comfy_cli.command import custom_nodes


def install_comfyui_dependencies(repo_dir, torch_mode):
Expand Down Expand Up @@ -95,3 +97,19 @@ def execute(
os.chdir(repo_dir)

print("")


def apply_snapshot(ctx: typer.Context, checker, filepath):
if not os.path.exists(filepath):
print(f"[bold red]File not found: {filepath}[/bold red]")
raise typer.Exit(code=1)

if checker.get_comfyui_manager_path() is not None and os.path.exists(
checker.get_comfyui_manager_path()
):
print(
f"[bold red]If ComfyUI-Manager is not installed, the snapshot feature cannot be used.[/bold red]"
)
raise typer.Exit(code=1)

custom_nodes.command.restore_snapshot(ctx, filepath)
12 changes: 7 additions & 5 deletions comfy_cli/env_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def get_comfyui_manager_path(self):

# To check more robustly, verify up to the `.git` path.
manager_path = os.path.join(
self.comfy_repo.working_dir, "custom_nodes", "ComfyUI-Manager"
self.comfy_repo.working_dir, "ComfyUI", "custom_nodes", "ComfyUI-Manager"
)
return manager_path

Expand All @@ -113,7 +113,11 @@ def is_comfyui_manager_installed(self):

# To check more robustly, verify up to the `.git` path.
manager_git_path = os.path.join(
self.comfy_repo.working_dir, "custom_nodes", "ComfyUI-Manager", ".git"
self.comfy_repo.working_dir,
"ComfyUI",
"custom_nodes",
"ComfyUI-Manager",
".git",
)
return os.path.exists(manager_git_path)

Expand All @@ -130,9 +134,7 @@ def get_isolated_env(self):
return None

def check(self):
self.virtualenv_path = (
os.environ.get("VIRTUAL_ENV") if os.environ.get("VIRTUAL_ENV") else None
)
self.virtualenv_path = ()
self.conda_env = (
os.environ.get("CONDA_DEFAULT_ENV")
if os.environ.get("CONDA_DEFAULT_ENV")
Expand Down
2 changes: 1 addition & 1 deletion comfy_cli/workspace_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def get_workspace_comfy_path(self, context: typer.Context) -> str:
Retrieves the workspace path and appends '/ComfyUI' to it.
"""

return self.get_workspace_path(context) + "/ComfyUI"
return os.path.join(self.get_workspace_path(context), "ComfyUI")

def get_workspace_path(self, context: typer.Context) -> str:
"""
Expand Down
Loading