Support for magit-repo-dirs and nice completion based on it.

Thanks to Travis B. Hartwell for the initial implementation!
This commit is contained in:
Marius Vollmer 2009-07-28 02:25:44 +03:00
parent 31b8be948a
commit ea6105fbbf
3 changed files with 97 additions and 8 deletions

7
NEWS
View file

@ -1,5 +1,12 @@
Changes in magit 0.8: Changes in magit 0.8:
* By setting magit-repo-dirs, you can get better repo completion.
Magit will offer all subdirectories (upto magit-repo-dirs level
deep) of the listed directories when magit-status asks for a
directory to work on.
You can get the old behavior with a double prefix to magit-status.
* Hitting 'c' or 'C' while resolving a conflict in the middle of a * Hitting 'c' or 'C' while resolving a conflict in the middle of a
rebase will offer to continue the rebase instead of trying to commit rebase will offer to continue the rebase instead of trying to commit
your changes. your changes.

View file

@ -68,6 +68,17 @@
:group 'magit :group 'magit
:type '(repeat string)) :type '(repeat string))
(defcustom magit-repo-dirs nil
"Directories containing Git repositories.
Magit will look into these directories for Git repositories and offers them as choices for magit-status."
:group 'magit
:type '(repeat string))
(defcustom magit-repo-dirs-depth 3
"When looking for Git repositors below the directories in magit-repo-dirs, Magit will only descend this many levels deep."
:group 'magit
:type 'integer)
(defcustom magit-save-some-buffers t (defcustom magit-save-some-buffers t
"Non-nil means that \\[magit-status] will save modified buffers before running. "Non-nil means that \\[magit-status] will save modified buffers before running.
Setting this to t will ask which buffers to save, setting it to 'dontask will Setting this to t will ask which buffers to save, setting it to 'dontask will
@ -272,6 +283,51 @@ Many Magit faces inherit from this one by default."
(magit-git-string "config" (magit-concat-with-delim "." keys) val) (magit-git-string "config" (magit-concat-with-delim "." keys) val)
(magit-git-string "config" "--unset" (magit-concat-with-delim "." keys)))) (magit-git-string "config" "--unset" (magit-concat-with-delim "." keys))))
(defun magit-remove-conflicts (alist)
(let ((dict (make-hash-table :test 'equal))
(result nil))
(dolist (a alist)
(puthash (car a) (cons (cdr a) (gethash (car a) dict))
dict))
(maphash (lambda (key value)
(if (= (length value) 1)
(push (cons key (car value)) result)
(let ((sub (magit-remove-conflicts
(mapcar (lambda (entry)
(let ((dir (directory-file-name
(subseq entry 0 (- (length key))))))
(cons (concat (file-name-nondirectory dir) "/" key)
entry)))
value))))
(setq result (append result sub)))))
dict)
result))
(defun magit-git-repo-p (dir)
(file-exists-p (expand-file-name ".git" dir)))
(defun magit-list-repos* (dir level)
(if (magit-git-repo-p dir)
(list dir)
(apply #'append
(mapcar (lambda (entry)
(unless (or (string= (substring entry -3) "/..")
(string= (substring entry -2) "/."))
(magit-list-repos* entry (+ level 1))))
(and (file-directory-p dir)
(< level magit-repo-dirs-depth)
(directory-files dir t nil t))))))
(defun magit-list-repos (dirs)
(magit-remove-conflicts
(apply #'append
(mapcar (lambda (dir)
(mapcar #'(lambda (repo)
(cons (file-name-nondirectory repo)
repo))
(magit-list-repos* dir 0)))
dirs))))
(defun magit-get-top-dir (cwd) (defun magit-get-top-dir (cwd)
(let ((cwd (expand-file-name cwd))) (let ((cwd (expand-file-name cwd)))
(and (file-directory-p cwd) (and (file-directory-p cwd)
@ -295,11 +351,17 @@ Many Magit faces inherit from this one by default."
(defun magit-ref-exists-p (ref) (defun magit-ref-exists-p (ref)
(= (magit-git-exit-code "show-ref" "--verify" ref) 0)) (= (magit-git-exit-code "show-ref" "--verify" ref) 0))
(defun magit-read-top-dir () (defun magit-read-top-dir (rawp)
(if (and (not rawp) magit-repo-dirs)
(let* ((repos (magit-list-repos magit-repo-dirs))
(reply (completing-read "Git repository: "
(magit-list-repos magit-repo-dirs))))
(file-name-as-directory
(cdr (assoc reply repos))))
(file-name-as-directory (file-name-as-directory
(read-directory-name "Git repository: " (read-directory-name "Git repository: "
(or (magit-get-top-dir default-directory) (or (magit-get-top-dir default-directory)
default-directory)))) default-directory)))))
(defun magit-name-rev (rev) (defun magit-name-rev (rev)
(and rev (and rev
@ -1927,7 +1989,8 @@ in log buffer."
(defun magit-status (dir) (defun magit-status (dir)
(interactive (list (or (and (not current-prefix-arg) (interactive (list (or (and (not current-prefix-arg)
(magit-get-top-dir default-directory)) (magit-get-top-dir default-directory))
(magit-read-top-dir)))) (magit-read-top-dir (and (listp current-prefix-arg)
(> (car current-prefix-arg) 4))))))
(if magit-save-some-buffers (if magit-save-some-buffers
(save-some-buffers (eq magit-save-some-buffers 'dontask))) (save-some-buffers (eq magit-save-some-buffers 'dontask)))
(let ((topdir (magit-get-top-dir dir))) (let ((topdir (magit-get-top-dir dir)))
@ -1946,7 +2009,6 @@ in log buffer."
(switch-to-buffer buf) (switch-to-buffer buf)
(magit-mode-init topdir 'status #'magit-refresh-status))))) (magit-mode-init topdir 'status #'magit-refresh-status)))))
;;; Staging and Unstaging ;;; Staging and Unstaging
(defun magit-stage-item () (defun magit-stage-item ()

View file

@ -166,8 +166,28 @@ will switch to the status buffer of that repository. Otherwise, it
will prompt for a directory. With a prefix argument, it will always will prompt for a directory. With a prefix argument, it will always
prompt. prompt.
You can set @code{magit-repo-dirs} to customize how
@code{magit-status} asks for the repository to work on. When
@code{magit-repo-dirs} is nil, @code{magit-status} will simply ask for
a directory.
If you specify a directory that is not a Git repository, @kbd{M-x If you specify a directory that is not a Git repository, @kbd{M-x
magit-status} will ask whether to create one. magit-status} will offer to initialize it as one.
When @code{magit-repo-dirs} is not nil, it is treated as a list of
directory names, and @code{magit-status} will find all Git
repositories in those directories and offer them for completion.
(Magit will only look @code{magit-repo-dirs-depth} levels deep,
however.)
With two prefix arguments, @code{magit-status} will always prompt for
a raw directory.
Thus, you would normally set @code{magit-repo-dirs} to the places
where you keep most of your Git repositories and switch between them
with @kbd{C-u M-x magit-status}. If you want to go to a repository
outside of your normal working areas, or if you want to create a new
repository, you would use @kbd{C-u C-u M-x magit-status}.
You need to explicitly refresh the status buffer when you have made You need to explicitly refresh the status buffer when you have made
changes to the repository from outside of Emacs. You can type @kbd{g} changes to the repository from outside of Emacs. You can type @kbd{g}