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
1 change: 1 addition & 0 deletions HISTORY.org
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Release history

** Main branch change
- Feat: Integrate with magit worktree feature
- Feat: Modernize PR review tool

** 1.55
Expand Down
41 changes: 41 additions & 0 deletions ai-code-git.el
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ Candidate values:
:type 'string
:group 'ai-code)

(defcustom ai-code-git-worktree-root
(expand-file-name "ai-code-worktrees" user-emacs-directory)
"Directory used to host centralized Git worktrees for all repositories."
:type 'directory
:group 'ai-code)

(declare-function ai-code--insert-prompt "ai-code-prompt-mode" (prompt-text))
(declare-function ai-code--ensure-files-directory "ai-code-prompt-mode" ())
(declare-function ai-code--git-root "ai-code-file" (&optional dir))
Expand Down Expand Up @@ -755,6 +761,41 @@ buffer from which this command was invoked, instead of visiting the file."
(insert "@" choice)))
(find-file (expand-file-name choice base-dir))))))))

(defun ai-code--git-worktree-repo-dir (git-root)
"Return centralized worktree directory for repository at GIT-ROOT."
(let ((repo-name (file-name-nondirectory (directory-file-name git-root))))
(expand-file-name repo-name ai-code-git-worktree-root)))
Comment thread
tninja marked this conversation as resolved.
Comment thread
tninja marked this conversation as resolved.

;;;###autoload
(defun ai-code-git-worktree-branch (branch start-point)
"Create BRANCH and check it out in a new centralized worktree.
The worktree path is
`ai-code-git-worktree-root/REPO-NAME/BRANCH'."
(interactive
(magit-branch-read-args "Create and checkout branch"))
(let* ((git-root (ai-code--validate-git-repository))
(repo-worktree-dir (ai-code--git-worktree-repo-dir git-root))
(path (expand-file-name branch repo-worktree-dir))
(parent-dir (file-name-directory path)))
(unless (file-directory-p repo-worktree-dir)
(make-directory repo-worktree-dir t))
(when (and parent-dir
(not (file-directory-p parent-dir)))
(make-directory parent-dir t))
(when (zerop (magit-call-git "worktree" "add" "-b" branch
(file-truename path) start-point))
(magit-diff-visit-directory path))))

;;;###autoload
(defun ai-code-git-worktree-action (&optional prefix)
"Dispatch worktree action by PREFIX.
Without PREFIX, call `ai-code-git-worktree-branch'.
With PREFIX (for example C-u), call `magit-worktree-status'."
(interactive "P")
(if prefix
(call-interactively #'magit-worktree-status)
(call-interactively #'ai-code-git-worktree-branch)))

(provide 'ai-code-git)

;;; ai-code-git.el ends here
1 change: 1 addition & 0 deletions ai-code.el
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ Shows the current backend label to the right."
("<SPC>" "Send command (C-u: context)" ai-code-send-command)
("@" "Context (add/show/clear)" ai-code-context-action)
("C" "Create file or dir with AI" ai-code-create-file-or-dir)
("w" "New worktree branch (C-u: status)" ai-code-git-worktree-action)
]

["AI Agile Development"
Expand Down
57 changes: 57 additions & 0 deletions test/test_ai-code-git.el
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,63 @@ When .gitignore is missing some entries, they should be added."
"https://github.com/acme/demo/pull/999")))
(should (string-match-p "Review this pull request\\." prompt))))

(ert-deftest ai-code-test-git-worktree-branch-creates-repo-directory-and-adds-worktree ()
"Create repo worktree directory and invoke git worktree add with expected path."
(let* ((temp-worktree-root (make-temp-file "ai-code-worktree-root-" t))
(ai-code-git-worktree-root temp-worktree-root)
(git-root "/tmp/sample-repo/")
(branch "feature/new-branch")
(start-point "main")
(repo-dir (expand-file-name "sample-repo" temp-worktree-root))
(worktree-path (expand-file-name branch repo-dir))
(worktree-parent-dir (file-name-directory worktree-path))
captured-git-args
Comment thread
tninja marked this conversation as resolved.
captured-visited-path)
(unwind-protect
(cl-letf (((symbol-function 'ai-code--validate-git-repository)
(lambda () git-root))
((symbol-function 'magit-run-git)
(lambda (&rest _args)
(ert-fail "`magit-run-git' should not be used for worktree add status check")))
((symbol-function 'magit-call-git)
(lambda (&rest args)
(setq captured-git-args args)
0))
((symbol-function 'magit-diff-visit-directory)
(lambda (path)
(setq captured-visited-path path))))
(should-not (file-directory-p repo-dir))
(ai-code-git-worktree-branch branch start-point)
(should (file-directory-p repo-dir))
(should (file-directory-p worktree-parent-dir))
(should (equal captured-git-args
(list "worktree"
"add"
"-b"
branch
(file-truename worktree-path)
start-point)))
(should (equal captured-visited-path worktree-path)))
(delete-directory temp-worktree-root t))))

(ert-deftest ai-code-test-git-worktree-action-without-prefix-calls-worktree-branch ()
"Without prefix arg, dispatch to `ai-code-git-worktree-branch'."
(let (captured-fn)
(cl-letf (((symbol-function 'call-interactively)
(lambda (fn &optional _record-flag _keys)
(setq captured-fn fn))))
(ai-code-git-worktree-action nil)
(should (eq captured-fn #'ai-code-git-worktree-branch)))))

(ert-deftest ai-code-test-git-worktree-action-with-prefix-calls-magit-worktree-status ()
"With prefix arg, dispatch to `magit-worktree-status'."
(let (captured-fn)
(cl-letf (((symbol-function 'call-interactively)
(lambda (fn &optional _record-flag _keys)
(setq captured-fn fn))))
(ai-code-git-worktree-action '(4))
(should (eq captured-fn #'magit-worktree-status)))))

(defun ai-code-test--run-pull-or-review-diff-file (choice pr-url &optional review-mode-choice)
"Run `ai-code-pull-or-review-diff-file' with CHOICE and optional PR-URL.
REVIEW-MODE-CHOICE is used for review mode selection when prompted.
Expand Down
Loading