Compare commits

..

1 Commits

Author SHA1 Message Date
fc9fc2613b feat: initial implementation 2026-02-24 01:40:44 +01:00
3 changed files with 41 additions and 55 deletions

View File

@@ -208,7 +208,7 @@ If you develop a new program, and you want it to be of the greatest possible use
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
majjit
magit-clone-jj
Copyright (C) 2026 phundrak
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -221,7 +221,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
majjit Copyright (C) 2026 phundrak
magit-clone-jj Copyright (C) 2026 phundrak
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.

View File

@@ -1,3 +1,3 @@
# majjit
# magit-clone-jj
Simple package to clone repositories in Emacs using Magit and Jujutsu.

View File

@@ -1,10 +1,10 @@
;;; majjit.el --- Clone jujutsu repositories with Magit's interface -*- lexical-binding: t -*-
;;; magit-clone-jj.el --- Clone jujutsu repositories with Magit's interface -*- lexical-binding: t -*-
;; Author: Lucien Cartier-Tilet <lucien@phundrak.com>
;; Maintainer: Lucien Cartier-Tilet <lucien@phundrak.com>
;; Version: 0.1.0
;; Package-Requires: ((emacs "28.1") (magit "4.5.0"))
;; Homepage: https://labs.phundrak.com/phundrak/majjit
;; Homepage: https://labs.phundrak.com/phundrak/magit-clone-jj
;; Keywords: git tools vcs
@@ -32,41 +32,41 @@
(require 'magit)
(defgroup majjit nil
(defgroup magit-clone-jj nil
"Clone your jj repositories with Magit."
:group 'tools
:prefix "majjit-"
:link '(url-link :tag "https://labs.phundrak.com/phundrak/majjit"))
:prefix "magit-clone-jj-"
:link '(url-link :tag "https://labs.phundrak.com/phundrak/magit-clone-jj"))
(defcustom majjit-default-directory nil
(defcustom magit-clone-jj-default-directory nil
"See `magit-clone-default-directory'."
:package-version '(majjit . "0.1.0")
:group 'majjit
:package-version '(magit-clone-jj . "0.1.0")
:group 'magit-clone-jj
:type '(choice (const :tag "Value of default-directory")
(directory :tag "Constant directory")
(function :tag "Function's value")))
(defcustom majjit-executable "jj"
(defcustom magit-clone-jj-executable "jj"
"Local executable of jj."
:package-version '(majjit . "0.1.0")
:group 'majjit
:package-version '(magit-clone-jj . "0.1.0")
:group 'magit-clone-jj
:type 'path)
(defcustom majjit-remote-executable "jj"
(defcustom magit-clone-jj-remote-executable "jj"
"Remote executable of jj."
:package-version '(majjit . "0.1.0")
:group 'majjit
:package-version '(magit-clone-jj . "0.1.0")
:group 'magit-clone-jj
:type 'path)
(defcustom majjit-global-arguments
(defcustom magit-clone-jj-global-arguments
'("--color=never")
"Global jj arguments."
:package-version '(majjit . "0.1.0")
:group 'majjit
:package-version '(magit-clone-jj . "0.1.0")
:group 'magit-clone-jj
:type '(repeat string))
(defun majjit-sentinel (process event)
"Default sentinel used by `majjit-run-jj-async'."
(defun magit-clone-jj-sentinel (process event)
"Default sentinel used by `magit-clone-jj-run-jj-async'."
(when (memq (process-status process) '(exit signal))
(setq event (substring event 0 -1))
(when (string-match "^finished" event)
@@ -74,43 +74,42 @@
(when (eq process magit-this-process)
(setq magit-this-process nil))))
(defun majjit-executable ()
(defun magit-clone-jj-executable ()
"Return executable for jj.
See `magit-git-executable'."
(if (file-remote-p default-directory)
majjit-remote-executable
majjit-executable))
magit-clone-jj-remote-executable
magit-clone-jj-executable))
(defun majjit-run-jj-async (directory &rest args)
(defun magit-clone-jj-run-jj-async (directory &rest args)
"Start jujutsu and return the process object.
ARGS is flattened and then used as arguments to jujutsu. Once cloning is
done, open DIRECTORY with `find-file'.
ARGS is flattened and then used as arguments to jujutsu.
Inspired by `magit-start-git'."
(let ((default-process-coding-system (magit--process-coding-system))
(magit-git-global-arguments majjit-global-arguments))
(magit-git-global-arguments magit-clone-jj-global-arguments))
(apply #'magit-start-process
(majjit-executable)
(magit-clone-jj-executable)
nil
(magit-process-git-arguments args))
;; Don't refresh the buffer we're calling from.
(process-put magit-this-process 'inhibit-refresh t)
(set-process-sentinel magit-this-process
(lambda (process event)
(majjit-sentinel process event)
(magit-clone-jj-sentinel process event)
(find-file directory)))))
(defun majjit-read-args ()
(defun magit-clone-jj-read-args ()
"Get all the necessary args for cloning the repository."
(let* ((magit-clone-default-directory majjit-default-directory)
(let* ((magit-clone-default-directory magit-clone-jj-default-directory)
(magit-args (magit-clone-read-args)))
(list (car magit-args)
(cadr magit-args)
(yes-or-no-p "Colocate the repository? "))))
(defun majjit--check-valid-clone-directory (repository directory)
(defun magit-clone-jj--check-valid-clone-directory (repository directory)
"Check whether the target DIRECTORY is a valid target.
Taken from `magit-clone-internal'. Refer to it for use of REPOSITORY and
@@ -127,13 +126,13 @@ DIRECTORY."
(user-error "%s already exists" directory))))
(user-error "%s already exists and is not a directory" directory)))))
(defun majjit--internal (repository directory colocate-p)
(defun magit-clone-jj--internal (repository directory colocate-p)
"Clone REPOSITORY to DIRECTORY using jj.
If COLOCATE-P is t, colocate the repository with git."
(let ((directory (file-name-as-directory (expand-file-name directory))))
(majjit--check-valid-clone-directory repository directory)
(majjit-run-jj-async directory
(magit-clone-jj--check-valid-clone-directory repository directory)
(magit-clone-jj-run-jj-async directory
"git"
"clone"
(if colocate-p "--colocate" nil)
@@ -142,28 +141,15 @@ If COLOCATE-P is t, colocate the repository with git."
(magit-convert-filename-for-git directory))))
;;;###autoload
(defun majjit-clone-from-url (url)
"Clone a repository from a known URL."
(let ((directory (read-directory-name
"Clone to: "
(if (functionp majjit-default-directory)
(funcall majjit-default-directory)
majjit-default-directory)
nil nil
(magit-clone--url-to-name url)))
(colocate-p (yes-or-no-p "Colocate? ")))
(majjit--internal url directory colocate-p)))
;;;###autoload
(defun majjit-clone (repository directory colocate-p)
(defun magit-clone-jj (repository directory colocate-p)
"Clone a git REPOSITORY using jujutsu into a DIRECTORY.
If COLOCATE-P is t, then colocate the repository with git.
Depends on Magit. Inspired by `magit-clone-regular'."
(interactive (majjit-read-args))
(majjit--internal repository directory colocate-p))
(interactive (magit-clone-jj-read-args))
(magit-clone-jj--internal repository directory colocate-p))
(provide 'majjit)
(provide 'magit-clone-jj)
;;; majjit.el ends here
;;; magit-clone-jj.el ends here