Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
142 changes: 70 additions & 72 deletions src/git_draft/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,103 +4,101 @@
import logging
import optparse
import sys
import textwrap

from .bots import load_bot
from .common import Store, open_editor
from .common import Config, PROGRAM, Store, ensure_state_home, open_editor
from .manager import Manager


logging.basicConfig(level=logging.INFO)


EPILOG = """\
More information via `man git-draft` and https://mtth.github.io/git-draft.
"""
def new_parser() -> optparse.OptionParser:
parser = optparse.OptionParser(
prog=PROGRAM,
version=importlib.metadata.version("git_draft"),
)

parser.disable_interspersed_args()

parser = optparse.OptionParser(
prog="git-draft",
epilog=textwrap.dedent(EPILOG),
version=importlib.metadata.version("git_draft"),
)
parser.add_option(
"--log",
help="show log path and exit",
action="store_true",
)

parser.disable_interspersed_args()
def add_command(name: str, **kwargs) -> None:
def callback(_option, _opt, _value, parser) -> None:
parser.values.command = name

parser.add_option(
f"-{name[0].upper()}",
f"--{name}",
action="callback",
callback=callback,
**kwargs,
)

def add_command(name: str, **kwargs) -> None:
def callback(_option, _opt, _value, parser) -> None:
parser.values.command = name
add_command("discard", help="discard the current draft")
add_command("finalize", help="apply current draft to original branch")
add_command("generate", help="start a new draft from a prompt")

parser.add_option(
f"-{name[0].upper()}",
f"--{name}",
action="callback",
callback=callback,
**kwargs,
"-b",
"--bot",
dest="bot",
help="bot key",
default="openai",
)
parser.add_option(
"-c",
"--checkout",
help="check out generated changes",
action="store_true",
)
parser.add_option(
"-d",
"--delete",
help="delete draft after finalizing or discarding",
action="store_true",
)
parser.add_option(
"-p",
"--prompt",
dest="prompt",
help="draft generation prompt, read from stdin if unset",
)
parser.add_option(
"-r",
"--reset",
help="reset index before generating a new draft",
action="store_true",
)
parser.add_option(
"-s",
"--sync",
help="commit prior worktree changes separately",
action="store_true",
)


add_command("discard", help="discard the current draft")
add_command("finalize", help="apply the current draft to the original branch")
add_command("generate", help="start a new draft from a prompt")

parser.add_option(
"-a",
"--bot",
dest="bot",
help="bot key",
default="openai",
)
parser.add_option(
"-c",
"--checkout",
help="check out generated changes",
action="store_true",
)
parser.add_option(
"-d",
"--delete",
help="delete draft after finalizing or discarding",
action="store_true",
)
parser.add_option(
"-p",
"--prompt",
dest="prompt",
help="draft generation prompt, read from stdin if unset",
)
parser.add_option(
"-r",
"--reset",
help="reset index before generating a new draft",
action="store_true",
)
parser.add_option(
"-s",
"--sync",
help="commit prior worktree changes separately",
action="store_true",
)


EDITOR_PLACEHOLDER = """\
Enter your prompt here...
"""
return parser


def main() -> None:
(opts, _args) = parser.parse_args()
config = Config.load()
(opts, _args) = new_parser().parse_args()

manager = Manager.create(Store.persistent())
log_path = ensure_state_home() / "log"
if opts.log:
print(log_path)
return
logging.basicConfig(level=config.log_level, filename=str(log_path))

manager = Manager.create(Store.persistent())
command = getattr(opts, "command", "generate")
if command == "generate":
bot = load_bot(opts.bot, {})
prompt = opts.prompt
if not prompt:
if sys.stdin.isatty():
prompt = open_editor(textwrap.dedent(EDITOR_PLACEHOLDER))
prompt = open_editor("Enter your prompt here...")
else:
prompt = sys.stdin.read()
manager.generate_draft(
Expand Down
12 changes: 6 additions & 6 deletions src/git_draft/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import xdg_base_dirs


NAMESPACE = "git-draft"
PROGRAM = "git-draft"


@dataclasses.dataclass(frozen=True)
Expand All @@ -34,7 +34,7 @@ def default(cls) -> Self:

@staticmethod
def path() -> Path:
return xdg_base_dirs.xdg_config_home() / NAMESPACE / "config.toml"
return xdg_base_dirs.xdg_config_home() / PROGRAM / "config.toml"

@classmethod
def load(cls) -> Self:
Expand All @@ -45,7 +45,7 @@ def load(cls) -> Self:
except FileNotFoundError:
return cls.default()
else:
bot_data = data["bots"] or {}
bot_data = data.get("bots", {})
return cls(
log_level=logging.getLevelName(data["log_level"]),
bots={k: BotConfig(**v) for k, v in bot_data.items()},
Expand All @@ -63,8 +63,8 @@ class BotConfig:
pythonpath: str | None = None


def _ensure_state_home() -> Path:
path = xdg_base_dirs.xdg_state_home() / NAMESPACE
def ensure_state_home() -> Path:
path = xdg_base_dirs.xdg_state_home() / PROGRAM
path.mkdir(parents=True, exist_ok=True)
return path

Expand Down Expand Up @@ -121,7 +121,7 @@ def __init__(self, conn: sqlite3.Connection) -> None:

@classmethod
def persistent(cls) -> Store:
path = _ensure_state_home() / cls._name
path = ensure_state_home() / cls._name
conn = sqlite3.connect(str(path), autocommit=False)
return cls(conn)

Expand Down
2 changes: 1 addition & 1 deletion tests/git_draft/common_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def state_home(monkeypatch, tmp_path) -> None:


def test_ensure_state_home() -> None:
path = sut._ensure_state_home()
path = sut.ensure_state_home()
assert path.exists()


Expand Down