Skip to content

Commit b82ec1f

Browse files
authored
feat: rename flags (#71)
Also include all changes in initial toolbox tree.
1 parent 6adc84f commit b82ec1f

File tree

5 files changed

+62
-46
lines changed

5 files changed

+62
-46
lines changed

docs/git-draft.adoc

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,23 @@ IMPORTANT: `git-draft` is WIP.
1818
== Synopsis
1919

2020
[verse]
21-
git draft [options] [--generate] [--accept... | --no-accept] [--bot BOT]
22-
[--edit] [--reset | --no-reset] [TEMPLATE [VARIABLE...]]
23-
git draft [options] --finalize
24-
git draft [options] --show-templates [--json | [--edit] TEMPLATE]
21+
git draft [options] [--new] [--accept... | --no-accept] [--bot BOT]
22+
[--edit] [TEMPLATE [VARIABLE...]]
23+
git draft [options] --quit
24+
git draft [options] --templates [--json | [--edit] TEMPLATE]
2525

2626

2727
== Description
2828

29-
`git-draft` is a git-centric way to develop using AI.
29+
`git-draft` is a git-centric way to edit code with AI.
3030

3131

3232
== Options
3333

3434
-a::
3535
--accept::
3636
--no-accept::
37-
Check out generated changes automatically.
37+
Merge generated changes automatically.
3838
Can be repeated.
3939

4040
-b BOT::
@@ -43,18 +43,9 @@ git draft [options] --show-templates [--json | [--edit] TEMPLATE]
4343

4444
-e::
4545
--edit::
46-
Enable interactive editing of prompts and templates.
46+
Enable interactive editing of draft prompts and templates.
4747
See `--generate` and `--show-templates` for details.
4848

49-
-F::
50-
--finalize::
51-
Go back to the draft's origin branch with the current working directory.
52-
53-
-G::
54-
--generate::
55-
Add an AI-generated commit.
56-
If the `--edit` option is set, an interactive editor will be open with the rendered prompt to allow modification before it is forwarded to the bot.
57-
5849
-h::
5950
--help::
6051
Show help message and exit.
@@ -66,12 +57,21 @@ git draft [options] --show-templates [--json | [--edit] TEMPLATE]
6657
--log::
6758
Show log path and exit.
6859

60+
-N::
61+
--new::
62+
Create an AI-generated draft.
63+
If the `--edit` option is set, an interactive editor will be open with the rendered prompt to allow modification before it is forwarded to the bot.
64+
65+
-Q::
66+
--quit::
67+
Go back to the draft's origin branch with the current working directory.
68+
6969
--root::
7070
Repository search root.
7171

7272
-T::
73-
--show-templates::
74-
Lists available templates.
73+
--templates::
74+
With no argument, lists available templates.
7575
With an template name argument, displays the corresponding template's contents or, if the `--edit` option is set, opens an interactive editor.
7676

7777
--version::

src/git_draft/__main__.py

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def new_parser() -> optparse.OptionParser:
3232
parser.disable_interspersed_args()
3333

3434
parser.add_option(
35-
"--log",
35+
"--log-path",
3636
help="show log path and exit",
3737
action="store_true",
3838
)
@@ -60,21 +60,21 @@ def callback(
6060
**kwargs,
6161
)
6262

63-
add_command("finalize", help="apply current draft to original branch")
64-
add_command("generate", help="create or update draft from a prompt")
65-
add_command("show-templates", short="T", help="show template information")
63+
add_command("new", help="create a new draft from a prompt")
64+
add_command("quit", help="return to original branch")
65+
add_command("templates", short="T", help="show template information")
6666

6767
parser.add_option(
6868
"-a",
6969
"--accept",
70-
help="accept draft, may be repeated",
70+
help="merge draft, may be repeated",
7171
action="count",
7272
)
7373
parser.add_option(
7474
"-b",
7575
"--bot",
7676
dest="bot",
77-
help="bot name",
77+
help="AI bot name",
7878
)
7979
parser.add_option(
8080
"-e",
@@ -91,7 +91,7 @@ def callback(
9191

9292
parser.add_option(
9393
"--no-accept",
94-
help="do not update worktree from draft",
94+
help="do not merge draft",
9595
dest="accept",
9696
action="store_const",
9797
const=0,
@@ -106,16 +106,18 @@ class Accept(enum.Enum):
106106
MANUAL = 0
107107
MERGE = enum.auto()
108108
MERGE_THEIRS = enum.auto()
109-
FINALIZE = enum.auto()
109+
MERGE_THEN_QUIT = enum.auto()
110110

111111
def merge_strategy(self) -> DraftMergeStrategy | None:
112-
match self.value:
112+
match self:
113113
case Accept.MANUAL:
114114
return None
115115
case Accept.MERGE:
116116
return "ignore-all-space"
117-
case _:
117+
case Accept.MERGE_THEIRS | Accept.MERGE_THEN_QUIT:
118118
return "theirs"
119+
case _:
120+
raise UnreachableError()
119121

120122

121123
class ToolPrinter(ToolVisitor):
@@ -175,10 +177,15 @@ def main() -> None: # noqa: PLR0912 PLR0915
175177
(opts, args) = new_parser().parse_args()
176178

177179
log_path = ensure_state_home() / "log"
178-
if opts.log:
180+
if opts.log_path:
179181
print(log_path)
180182
return
181-
logging.basicConfig(level=config.log_level, filename=str(log_path))
183+
logging.basicConfig(
184+
level=config.log_level,
185+
filename=str(log_path),
186+
format="%(asctime)s %(name)-12s %(levelname)-8s %(message)s",
187+
datefmt="%m-%d %H:%M",
188+
)
182189

183190
repo = Repo.enclosing(Path(opts.root) if opts.root else Path.cwd())
184191
drafter = Drafter.create(repo, Store.persistent())
@@ -210,7 +217,7 @@ def main() -> None: # noqa: PLR0912 PLR0915
210217
prompt = sys.stdin.read()
211218

212219
accept = Accept(opts.accept or 0)
213-
drafter.generate_draft(
220+
draft = drafter.generate_draft(
214221
prompt,
215222
bot,
216223
prompt_transform=open_editor if editable else None,
@@ -219,18 +226,18 @@ def main() -> None: # noqa: PLR0912 PLR0915
219226
)
220227
match accept:
221228
case Accept.MANUAL:
222-
print("Generated draft.")
229+
print(f"Generated draft. [ref={draft.ref}].")
223230
case Accept.MERGE | Accept.MERGE_THEIRS:
224-
print("Merged draft.")
225-
case Accept.FINALIZE:
226-
drafter.finalize_folio()
227-
print("Finalized draft.")
231+
print(f"Generated and merged draft. [ref={draft.ref}]")
232+
case Accept.MERGE_THEN_QUIT:
233+
drafter.quit_folio()
234+
print(f"Generated and applied draft. [ref={draft.ref}]")
228235
case _:
229236
raise UnreachableError()
230-
case "finalize":
231-
drafter.finalize_folio()
232-
print("Finalized draft folio.")
233-
case "show-templates":
237+
case "quit":
238+
drafter.quit_folio()
239+
print("Applied draft.")
240+
case "templates":
234241
if args:
235242
name = args[0]
236243
tpl = find_template(name)

src/git_draft/drafter.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,10 @@ def generate_draft(
144144
parent_commit_rev = self._commit_tree(
145145
toolbox.tree_sha(), "HEAD", "sync(prompt)"
146146
)
147+
_logger.info("Created sync commit. [sha=%s]", parent_commit_rev)
147148
else:
148149
parent_commit_rev = "HEAD"
150+
_logger.info("Skipping sync commit, tree is clean.")
149151
commit_sha = self._record_change(
150152
change, parent_commit_rev, folio, seqno
151153
)
@@ -177,9 +179,10 @@ def generate_draft(
177179
for o in operation_recorder.operations
178180
],
179181
)
180-
_logger.info("Created new change in folio %s.", folio.id)
182+
_logger.info("Created new draft in folio %s.", folio.id)
181183

182184
if merge_strategy:
185+
_logger.info("Merging draft. [strategy=%s]", merge_strategy)
183186
if parent_commit_rev != "HEAD":
184187
# If there was a sync(prompt) commit, we move forward to it.
185188
# This will avoid conflicts with changes that happened earlier.
@@ -194,6 +197,11 @@ def generate_draft(
194197
"draft! merge",
195198
commit_sha,
196199
)
200+
self._repo.git(
201+
"update-ref",
202+
f"refs/heads/{folio.upstream_branch_name()}",
203+
"HEAD",
204+
)
197205

198206
return Draft(
199207
folio=folio,
@@ -203,7 +211,7 @@ def generate_draft(
203211
token_count=change.action.token_count,
204212
)
205213

206-
def finalize_folio(self) -> Folio:
214+
def quit_folio(self) -> Folio:
207215
folio = _active_folio(self._repo)
208216
if not folio:
209217
raise RuntimeError("Not currently on a draft branch")

src/git_draft/toolbox.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ def __init__(
155155

156156
@classmethod
157157
def for_working_dir(cls, repo: Repo) -> tuple[Self, bool]:
158-
toolbox = cls(repo, "HEAD")
159-
head_tree_sha = toolbox.tree_sha()
158+
index_tree_sha = repo.git("write-tree").stdout
159+
toolbox = cls(repo, index_tree_sha)
160160

161161
# Apply any changes from the working directory.
162162
deleted = set[SHA]()
@@ -170,6 +170,7 @@ def for_working_dir(cls, repo: Repo) -> tuple[Self, bool]:
170170
continue # Deleted files also show up as modified
171171
toolbox._write_from_disk(PurePosixPath(path), path)
172172

173+
head_tree_sha = repo.git("rev-parse", "HEAD^{tree}").stdout
173174
return toolbox, toolbox.tree_sha() != head_tree_sha
174175

175176
def with_visitors(self, visitors: Sequence[ToolVisitor]) -> Self:

tests/git_draft/drafter_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,11 @@ def test_generate_reuse_branch(self) -> None:
144144
def test_delete_unknown_file(self) -> None:
145145
self._drafter.generate_draft("hello", _SimpleBot({"p1": None}))
146146

147-
def test_finalize_keeps_changes(self) -> None:
147+
def test_quit_keeps_changes(self) -> None:
148148
self._fs.write("p1.txt", "a1")
149149
self._drafter.generate_draft("hello", _SimpleBot.prompt(), "theirs")
150150
self._fs.write("p1.txt", "a2")
151-
self._drafter.finalize_folio()
151+
self._drafter.quit_folio()
152152
assert self._fs.read("p1.txt") == "a2"
153153
assert self._fs.read("PROMPT") == "hello"
154154

0 commit comments

Comments
 (0)