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:
* 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
rebase will offer to continue the rebase instead of trying to commit
your changes.

View file

@ -68,6 +68,17 @@
:group 'magit
: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
"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
@ -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" "--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)
(let ((cwd (expand-file-name 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)
(= (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
(read-directory-name "Git repository: "
(or (magit-get-top-dir default-directory)
default-directory))))
default-directory)))))
(defun magit-name-rev (rev)
(and rev
@ -1927,7 +1989,8 @@ in log buffer."
(defun magit-status (dir)
(interactive (list (or (and (not current-prefix-arg)
(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
(save-some-buffers (eq magit-save-some-buffers 'dontask)))
(let ((topdir (magit-get-top-dir dir)))
@ -1946,7 +2009,6 @@ in log buffer."
(switch-to-buffer buf)
(magit-mode-init topdir 'status #'magit-refresh-status)))))
;;; Staging and Unstaging
(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
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
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
changes to the repository from outside of Emacs. You can type @kbd{g}