update packages
This commit is contained in:
@@ -103,11 +103,11 @@ this."
|
||||
(ignore-error file-missing
|
||||
(apply #'process-lines-ignore-status program args))))
|
||||
|
||||
(defvar magit-git-w32-path-hack nil
|
||||
(defvar magit--git-w32-path-hack nil
|
||||
"Alist of (EXE . (PATHENTRY)).
|
||||
This specifies what additional PATH setting needs to be added to
|
||||
the environment in order to run the non-wrapper git executables
|
||||
successfully.")
|
||||
successfully. Set when `magit-git-executable' is (re)initialized.")
|
||||
|
||||
(defcustom magit-git-executable
|
||||
(or (and (eq system-type 'windows-nt)
|
||||
@@ -121,7 +121,7 @@ successfully.")
|
||||
exec "-c"
|
||||
"alias.X=!x() { which \"$1\" | cygpath -mf -; }; x"
|
||||
"X" "git")))
|
||||
(hack-entry (assoc core-exe magit-git-w32-path-hack))
|
||||
(hack-entry (assoc core-exe magit--git-w32-path-hack))
|
||||
;; Running the libexec/git-core executable
|
||||
;; requires some extra PATH entries.
|
||||
(path-hack
|
||||
@@ -135,7 +135,7 @@ successfully.")
|
||||
;; idempotent.
|
||||
(if hack-entry
|
||||
(setcdr hack-entry path-hack)
|
||||
(push (cons core-exe path-hack) magit-git-w32-path-hack))
|
||||
(push (cons core-exe path-hack) magit--git-w32-path-hack))
|
||||
core-exe)))
|
||||
(and (eq system-type 'darwin)
|
||||
(executable-find "git"))
|
||||
@@ -155,48 +155,57 @@ option."
|
||||
:group 'magit-process
|
||||
:type 'string)
|
||||
|
||||
(defvar magit--overriding-githook-directory nil)
|
||||
(defcustom magit-run-hooks-from-githooks t
|
||||
"Whether Git hooks may run Lisp hooks.
|
||||
|
||||
(defcustom magit-overriding-githook-directory nil
|
||||
"Directory containing the Git hook scripts used by Magit.
|
||||
By default the Lisp hook `magit-common-git-post-commit-functions' is
|
||||
run by the Git hooks `post-commit', `post-merge' and `post-rewrite'.
|
||||
Use `magit-user-githook-file' (which see) to define additional hooks.
|
||||
|
||||
No Magit-specific Git hook scripts are used if this is nil, which it
|
||||
is the default. This feature is still experimental.
|
||||
|
||||
Git does not allow overriding just an individual hook. It is only
|
||||
possible to point Git at an alternative directory containing hook
|
||||
scripts, using the Git variable `core.hooksPath'. When doing that,
|
||||
the hooks located in `$GIT_DIR/hooks' are ignored.
|
||||
|
||||
If `magit', use the directory containing Git hook scripts distributed
|
||||
with Magit. To counteract Git's limited granularity, Magit provides a
|
||||
script for every Git hook, most of which only run the respective script
|
||||
located in `$GIT_DIR/hooks', provided it exists and is executable.
|
||||
|
||||
A few Git hooks additionally run Lisp hooks:
|
||||
|
||||
- `post-commit' runs `magit-git-post-commit-functions'
|
||||
- `post-merge' runs `magit-git-post-merge-functions'
|
||||
- `post-rewrite' runs `magit-git-post-rewrite-functions'
|
||||
|
||||
All of these hooks also run `magit-common-git-post-rewrite-functions'.
|
||||
For many uses this hook variable is more useful than the three above.
|
||||
|
||||
If you want to teach additional Git hooks to run Lisp hooks, you have to
|
||||
copy Magit's hook script directory elsewhere, modify the hook scripts in
|
||||
question, and point this variable at the used directory.
|
||||
|
||||
Magit only sets `core.hooksPath' when calling Git asynchronously. Doing
|
||||
the same when calling Git synchronously would cause Git and Magit to wait
|
||||
on one another."
|
||||
:package-version '(magit . "4.5.0")
|
||||
Git hooks can only run Lisp hooks, if Magit invokes Git asynchronously
|
||||
and on the local machine, and at least Git v2.54.0 is used."
|
||||
:package-version '(magit . "4.6.0")
|
||||
:group 'magit-process
|
||||
:set (lambda (symbol value)
|
||||
(set-default-toplevel-value symbol value)
|
||||
(setq magit--overriding-githook-directory nil))
|
||||
:type '(choice (const :tag "Do not shadow Git's hook directory" nil)
|
||||
(const :tag "Use Magit's hook directory" magit)
|
||||
(directory :tag "Custom directory")))
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom magit-user-githook-file (locate-user-emacs-file "magit-githooks")
|
||||
"File containing user Git hook to Lisp hook mappings.
|
||||
|
||||
Magit ships with one such mapping, defined in the included file
|
||||
\"githooks/config\", which looks like this:
|
||||
|
||||
[hook \"magit-common-post-commit\"]
|
||||
event = post-commit
|
||||
event = post-merge
|
||||
event = post-rewrite
|
||||
command = magit-run-git-hook magit-common-git-post-commit-functions
|
||||
|
||||
That file should not be edited by users, as those edits would be lost
|
||||
when Magit is updated; instead the file specified by this option, has
|
||||
to be used, to add additional mappings.
|
||||
|
||||
See the git-hook(1) and githooks(5) manpages for details about the
|
||||
Git part. The command should always use the \"magit-run-git-hook\"
|
||||
executable, which takes the name of the Lisp hook to be run as the
|
||||
first argument.
|
||||
|
||||
See also `magit-run-hooks-from-githooks'."
|
||||
:package-version '(magit . "4.6.0")
|
||||
:group 'magit-process
|
||||
:type 'file)
|
||||
|
||||
(defvar magit-githook-directory nil
|
||||
"Directory containing files Magit needs to map Git to Lisp hooks.
|
||||
|
||||
This directory must contains two files; \"config\", which maps Git
|
||||
hooks to the `magit-common-git-post-commit-functions' hook, and an
|
||||
executable \"magit-run-git-hook\", which is used in that, and
|
||||
potentially other hooks.
|
||||
|
||||
The value of this variable is set by `magit-process-git-arguments',
|
||||
when it is first needed. Users can set it to another directory,
|
||||
but that should rarely be necessary. Additional hook mappings
|
||||
should instead be defined in `magit-user-githook-file'.")
|
||||
|
||||
(defcustom magit-git-global-arguments
|
||||
`("--no-pager" "--literal-pathspecs"
|
||||
@@ -209,17 +218,16 @@ on one another."
|
||||
(list "-c" "i18n.logOutputEncoding=UTF-8")))
|
||||
"Global Git arguments.
|
||||
|
||||
The arguments set here are used every time the git executable is
|
||||
run as a subprocess. They are placed right after the executable
|
||||
itself and before the git command - as in `git HERE... COMMAND
|
||||
REST'. See the manpage `git(1)' for valid arguments.
|
||||
The arguments set here are used every time the git executable is run
|
||||
as a subprocess. They are placed right after the executable itself
|
||||
and before the git command - as in \"git HERE... COMMAND REST\".
|
||||
See the manpage `git(1)' for valid arguments.
|
||||
|
||||
Be careful what you add here, especially if you are using Tramp
|
||||
to connect to servers with ancient Git versions. Never remove
|
||||
anything that is part of the default value, unless you really
|
||||
know what you are doing. And think very hard before adding
|
||||
something; it will be used every time Magit runs Git for any
|
||||
purpose."
|
||||
Be careful what you add here, especially if you are using Tramp to
|
||||
connect to servers with ancient Git versions. Never remove anything
|
||||
that is part of the default value, unless you really know what you
|
||||
are doing. And think very hard before adding something; it will be
|
||||
used every time Magit runs Git for any purpose."
|
||||
:package-version '(magit . "4.3.2")
|
||||
:group 'magit-commands
|
||||
:group 'magit-process
|
||||
@@ -262,7 +270,7 @@ is called by functions like `magit-list-branch-names' to generate
|
||||
the collection of refs. By default, refs are sorted according to
|
||||
their full refname (i.e., \"refs/...\").
|
||||
|
||||
Any value accepted by the `--sort' flag of \"git for-each-ref\" can
|
||||
Any value accepted by the \"--sort\" flag of \"git for-each-ref\" can
|
||||
be used. For example, \"-creatordate\" places refs with more
|
||||
recent committer or tagger dates earlier in the list. A list of
|
||||
strings can also be given in order to pass multiple sort keys to
|
||||
@@ -281,6 +289,28 @@ framework ultimately determines how the collection is displayed."
|
||||
:group 'magit-miscellaneous
|
||||
:type '(choice string (repeat string)))
|
||||
|
||||
(defcustom magit-cygwin-mount-points
|
||||
(and (eq system-type 'windows-nt)
|
||||
(compat-call
|
||||
sort (mapcar (lambda (mount)
|
||||
(if (string-match "^\\(.*\\) on \\(.*\\) type" mount)
|
||||
(cons (file-name-as-directory (match-str 2 mount))
|
||||
(file-name-as-directory (match-str 1 mount)))
|
||||
(lwarn '(magit) :error
|
||||
"Failed to parse Cygwin mount: %S" mount)))
|
||||
;; If --exec-path is not a native Windows path,
|
||||
;; then we probably have a cygwin git.
|
||||
(and-let ((dirs (magit--early-process-lines
|
||||
magit-git-executable "--exec-path")))
|
||||
(and (not (string-match-p "\\`[a-zA-Z]:" (car dirs)))
|
||||
(magit--early-process-lines "mount"))))
|
||||
:lessp #'< :reverse t :key (pcase-lambda (`(,cyg . ,_win)) (length cyg))))
|
||||
"Alist of (CYGWIN . WIN32) directory names.
|
||||
Sorted from longest to shortest CYGWIN name."
|
||||
:package-version '(magit . "2.3.0")
|
||||
:group 'magit-process
|
||||
:type '(alist :key-type string :value-type directory))
|
||||
|
||||
;;; Git
|
||||
|
||||
(defvar magit-git-debug nil
|
||||
@@ -325,9 +355,9 @@ See info node `(magit)Debugging Tools' for more information."
|
||||
`(if magit--refresh-cache
|
||||
(let ((,k ,key))
|
||||
(if-let ((,hit (assoc ,k (cdr magit--refresh-cache))))
|
||||
(progn (cl-incf (caar magit--refresh-cache))
|
||||
(progn (incf (caar magit--refresh-cache))
|
||||
(cdr ,hit))
|
||||
(cl-incf (cdar magit--refresh-cache))
|
||||
(incf (cdar magit--refresh-cache))
|
||||
(let ((value ,(macroexp-progn body)))
|
||||
(push (cons ,k value)
|
||||
(cdr magit--refresh-cache))
|
||||
@@ -342,14 +372,15 @@ rebase sequences.")
|
||||
|
||||
(defmacro magit-with-editor (&rest body)
|
||||
"Like `with-editor*' but let-bind some more variables.
|
||||
Also respect the value of `magit-with-editor-envvar'."
|
||||
Also respect the value of `magit-with-editor-envvar', prevent the
|
||||
process buffer from popping up, and on Windows possibly employ a
|
||||
kludge to fix an unusable value of `shell-file-name'."
|
||||
(declare (indent 0) (debug (body)))
|
||||
`(let ((magit-process-popup-time -1)
|
||||
;; The user may have customized `shell-file-name' to
|
||||
;; something which results in `w32-shell-dos-semantics' nil
|
||||
;; (which changes the quoting style used by
|
||||
;; `shell-quote-argument'), but Git for Windows expects shell
|
||||
;; quoting in the dos style.
|
||||
;; The user may have customized `shell-file-name' to something
|
||||
;; which results in `w32-shell-dos-semantics' being nil (which
|
||||
;; changes the quoting style used by `shell-quote-argument'),
|
||||
;; but Git for Windows expects shell quoting in the dos style.
|
||||
(shell-file-name (if (and (eq system-type 'windows-nt)
|
||||
;; If we have Cygwin mount points,
|
||||
;; the git flavor is cygwin, so dos
|
||||
@@ -381,9 +412,16 @@ is remote."
|
||||
magit-remote-git-executable
|
||||
magit-git-executable))
|
||||
|
||||
(defun magit-process-git-arguments--length ()
|
||||
(+ (length magit-git-global-arguments)
|
||||
(if magit--overriding-githook-directory 2 0)))
|
||||
(defun magit-process-git-arguments--split (program args)
|
||||
(if (equal program (magit-git-executable))
|
||||
(let* ((length (length magit-git-global-arguments))
|
||||
(global (seq-take args length))
|
||||
(local (seq-drop args length)))
|
||||
(while (equal (car local) "-c")
|
||||
(setq global (append global (seq-take local 2)))
|
||||
(setq local (seq-drop local 2)))
|
||||
(list global local))
|
||||
(list nil args)))
|
||||
|
||||
(defun magit-process-git-arguments (args &optional async)
|
||||
"Prepare ARGS for a function that invokes Git.
|
||||
@@ -393,34 +431,44 @@ pass arguments through this function before handing them to Git,
|
||||
to do the following.
|
||||
|
||||
* Prepend `magit-git-global-arguments' to ARGS.
|
||||
* If ASYNC is non-nil and `magit-overriding-githook-directory' is non-nil
|
||||
and valid, set `core.hooksPath' by adding additional arguments to ARGS.
|
||||
* If ASYNC is non-nil, potentially add additional arguments to load
|
||||
the hook configuration in \"/path/to/magit/githooks/config\" and/or
|
||||
`magit-user-githook-file'.
|
||||
* Flatten ARGS, removing nil arguments.
|
||||
* If `system-type' is `windows-nt', encode ARGS to `w32-ansi-code-page'."
|
||||
(cond ((not async))
|
||||
(magit--overriding-githook-directory)
|
||||
((eq magit-overriding-githook-directory 'magit)
|
||||
(setq magit--overriding-githook-directory
|
||||
(expand-file-name "git-hooks"
|
||||
(locate-dominating-file
|
||||
(locate-library "magit.el") "git-hooks"))))
|
||||
((and magit-overriding-githook-directory
|
||||
(file-directory-p magit-overriding-githook-directory))
|
||||
(setq magit--overriding-githook-directory
|
||||
magit-overriding-githook-directory)))
|
||||
(setq args
|
||||
(append magit-git-global-arguments
|
||||
(and magit--overriding-githook-directory
|
||||
(list "-c" (format "core.hooksPath=%s"
|
||||
magit--overriding-githook-directory)))
|
||||
(flatten-tree args)))
|
||||
(let ((githookp (and async
|
||||
(magit-git-version>= "2.54")
|
||||
(not (file-remote-p default-directory)))))
|
||||
(cond
|
||||
((not githookp))
|
||||
(magit-githook-directory)
|
||||
((and (stringp magit-run-hooks-from-githooks)
|
||||
(file-directory-p magit-run-hooks-from-githooks))
|
||||
(setq magit-githook-directory
|
||||
(magit-convert-filename-for-git
|
||||
magit-run-hooks-from-githooks)))
|
||||
(magit-run-hooks-from-githooks
|
||||
(setq magit-githook-directory
|
||||
(magit-convert-filename-for-git
|
||||
(expand-file-name "githooks"
|
||||
(locate-dominating-file
|
||||
(locate-library "magit.el") "githooks"))))))
|
||||
(setq args
|
||||
(append magit-git-global-arguments
|
||||
(and githookp
|
||||
magit-githook-directory
|
||||
`("-c" ,(format "include.path=%s/config"
|
||||
magit-githook-directory)
|
||||
,@(and magit-user-githook-file
|
||||
(file-exists-p magit-user-githook-file)
|
||||
`("-c" ,(concat "include.path="
|
||||
magit-user-githook-file)))))
|
||||
(flatten-tree args))))
|
||||
(if (and (eq system-type 'windows-nt) (boundp 'w32-ansi-code-page))
|
||||
;; On w32, the process arguments *must* be encoded in the
|
||||
;; current code-page (see #3250).
|
||||
(mapcar (lambda (arg)
|
||||
(encode-coding-string
|
||||
arg (intern (format "cp%d" w32-ansi-code-page))))
|
||||
args)
|
||||
(let ((coding (intern (format "cp%d" w32-ansi-code-page))))
|
||||
(mapcar (##encode-coding-string % coding) args))
|
||||
args))
|
||||
|
||||
(defun magit-git-exit-code (&rest args)
|
||||
@@ -663,7 +711,7 @@ executable."
|
||||
(list (concat
|
||||
(file-remote-p default-directory)
|
||||
(or (magit-git-string "--exec-path")
|
||||
(error "`git --exec-path' failed"))))
|
||||
(error "\"git --exec-path\" failed"))))
|
||||
exec-suffixes
|
||||
#'file-executable-p)
|
||||
(executable-find command t)))
|
||||
@@ -795,10 +843,10 @@ See info node `(magit)Debugging Tools' for more information."
|
||||
|
||||
(defun magit-config-get-from-cached-list (key)
|
||||
(gethash
|
||||
;; `git config --list' downcases first and last components of the key.
|
||||
(let* ((key (replace-regexp-in-string "\\`[^.]+" #'downcase key t t))
|
||||
(key (replace-regexp-in-string "[^.]+\\'" #'downcase key t t)))
|
||||
key)
|
||||
(thread$ key
|
||||
;; "git config --list" downcases first and last components.
|
||||
(replace-regexp-in-string "\\`[^.]+" #'downcase $ t t)
|
||||
(replace-regexp-in-string "[^.]+\\'" #'downcase $ t t))
|
||||
(magit--with-refresh-cache (cons (magit-toplevel) 'config)
|
||||
(let ((configs (make-hash-table :test #'equal)))
|
||||
(dolist (conf (magit-git-items "config" "--list" "-z"))
|
||||
@@ -860,7 +908,8 @@ Also see `magit-git-config-p'."
|
||||
(dolist (v values)
|
||||
(magit-call-git "config" arg "--add" var v))))
|
||||
|
||||
;;; Files
|
||||
;;; Repository
|
||||
;;;; Repository Locations
|
||||
|
||||
(defun magit--safe-default-directory (&optional file)
|
||||
(catch 'unsafe-default-dir
|
||||
@@ -910,9 +959,9 @@ not located inside a Git repository, then return nil."
|
||||
;; Kludge: git-annex converts submodule gitdirs to symlinks. See #3599.
|
||||
(when (file-symlink-p (directory-file-name gitdir))
|
||||
(setq gitdir (file-truename gitdir)))
|
||||
;; We want to delete the entry for `topdir' here, rather than within
|
||||
;; (unless ...), in case a `--separate-git-dir' repository was switched to
|
||||
;; the standard structure (i.e., "topdir/.git/").
|
||||
;; We want to delete the entry for `topdir' here, rather than
|
||||
;; within (unless ...), in case a "--separate-git-dir" repository
|
||||
;; was switched to the standard structure (i.e., "topdir/.git/").
|
||||
(setq magit--separated-gitdirs (cl-delete topdir
|
||||
magit--separated-gitdirs
|
||||
:key #'car :test #'equal))
|
||||
@@ -925,20 +974,19 @@ not located inside a Git repository, then return nil."
|
||||
|
||||
From within the working tree or control directory of a repository
|
||||
return the absolute path to the toplevel directory of the working
|
||||
tree. As a special case, from within a bare repository return
|
||||
the control directory instead. When called outside a repository
|
||||
then return nil.
|
||||
tree. As a special case, from within a bare repository return the
|
||||
control directory instead. When called outside a repository, return
|
||||
nil.
|
||||
|
||||
When optional DIRECTORY is non-nil then return the toplevel for
|
||||
that directory instead of the one for `default-directory'.
|
||||
When optional DIRECTORY is non-nil, return the toplevel for that
|
||||
directory, instead of the one for `default-directory'.
|
||||
|
||||
Try to respect the option `find-file-visit-truename', i.e., when
|
||||
the value of that option is nil, then avoid needlessly returning
|
||||
the truename. When a symlink to a sub-directory of the working
|
||||
tree is involved, or when called from within a sub-directory of
|
||||
the gitdir or from the toplevel of a gitdir, which itself is not
|
||||
located within the working tree, then it is not possible to avoid
|
||||
returning the truename."
|
||||
Try to respect the option `find-file-visit-truename', i.e., when the
|
||||
value of that option is nil, avoid needlessly returning the truename.
|
||||
When a symlink to a sub-directory of the working tree is involved,
|
||||
or when called from within a sub-directory of the gitdir or from the
|
||||
toplevel of a gitdir, which itself is not located within the working
|
||||
tree, then it is not possible to avoid returning the truename."
|
||||
(magit--with-refresh-cache
|
||||
(cons (or directory default-directory) 'magit-toplevel)
|
||||
(magit--with-safe-default-directory directory
|
||||
@@ -949,14 +997,13 @@ returning the truename."
|
||||
(;; Always honor these settings.
|
||||
[_(not find-file-visit-truename)]
|
||||
[_(not (getenv "GIT_WORK_TREE"))]
|
||||
;; `--show-cdup' is the relative path to the toplevel
|
||||
;; from `(file-truename default-directory)'. Here we
|
||||
;; pretend it is relative to `default-directory', and
|
||||
;; go to that directory. Then we check whether
|
||||
;; `--show-toplevel' still returns the same value and
|
||||
;; whether `--show-cdup' now is the empty string. If
|
||||
;; both is the case, then we are at the toplevel of
|
||||
;; the same working tree, but also avoided needlessly
|
||||
;; "--show-cdup" is the relative path to the toplevel from
|
||||
;; (file-truename default-directory). Here we pretend it is
|
||||
;; relative to `default-directory', and go to that directory.
|
||||
;; Then we check whether "--show-toplevel" still returns the
|
||||
;; same value and whether "--show-cdup" now is the empty
|
||||
;; string. If both is the case, then we are at the toplevel
|
||||
;; of the same working tree, but also avoided needlessly
|
||||
;; following any symlinks.
|
||||
[updir (file-name-as-directory
|
||||
(magit-rev-parse-safe "--show-cdup"))]
|
||||
@@ -988,8 +1035,7 @@ returning the truename."
|
||||
;; This has long been fixed, but old repository may still
|
||||
;; exist that contain such a file. See #2364.
|
||||
[_(not (equal wtree ".git"))]
|
||||
(concat (file-remote-p default-directory)
|
||||
(file-name-directory wtree)))
|
||||
(file-name-directory (expand-file-name wtree default-directory)))
|
||||
;; The working directory may not be the parent
|
||||
;; directory of .git if it was set up with
|
||||
;; "git init --separate-git-dir". See #2955.
|
||||
@@ -1006,6 +1052,8 @@ returning the truename."
|
||||
`(let ((default-directory (magit--toplevel-safe)))
|
||||
,@body))
|
||||
|
||||
;;;; Repository Predicates
|
||||
|
||||
(define-error 'magit-outside-git-repo "Not inside Git repository")
|
||||
(define-error 'magit-corrupt-git-config "Corrupt Git configuration")
|
||||
(define-error 'magit-git-executable-not-found "Git executable cannot be found")
|
||||
@@ -1087,25 +1135,8 @@ a bare repository."
|
||||
(file-directory-p (expand-file-name "refs" directory))
|
||||
(file-directory-p (expand-file-name "objects" directory))))))
|
||||
|
||||
(defun magit-file-relative-name (&optional file tracked)
|
||||
"Return the path of FILE relative to the repository root.
|
||||
|
||||
If optional FILE is nil or omitted, return the relative path of
|
||||
the file being visited in the current buffer, if any, else nil.
|
||||
If the file is not inside a Git repository, then return nil.
|
||||
|
||||
If TRACKED is non-nil, return the path only if it matches a
|
||||
tracked file."
|
||||
(with-current-buffer (or (buffer-base-buffer) (current-buffer))
|
||||
(and-let* ((file (or file
|
||||
(magit-buffer-file-name)
|
||||
(and (derived-mode-p 'dired-mode)
|
||||
default-directory)))
|
||||
(dir (magit-toplevel (magit--safe-default-directory
|
||||
(file-name-parent-directory file))))
|
||||
(_(or (not tracked)
|
||||
(magit-file-tracked-p file))))
|
||||
(file-relative-name file dir))))
|
||||
;;; Files
|
||||
;;;; File Predicates
|
||||
|
||||
(defun magit-file-ignored-p (file)
|
||||
(magit-git-string "ls-files" "--others" "--ignored" "--exclude-standard"
|
||||
@@ -1115,31 +1146,40 @@ tracked file."
|
||||
(magit-git-success "ls-files" "--error-unmatch"
|
||||
"--" (magit-convert-filename-for-git file)))
|
||||
|
||||
;;;; File Lists
|
||||
|
||||
(defun magit-list-files (&rest args)
|
||||
(apply #'magit-git-items "ls-files" "-z" "--full-name" args))
|
||||
(magit-with-toplevel
|
||||
(apply #'magit-git-items "ls-files" "-z" args)))
|
||||
|
||||
(defun magit-tracked-files (&rest args)
|
||||
(magit-list-files "--cached" args))
|
||||
|
||||
(defun magit-untracked-files (&optional all files &rest args)
|
||||
(defun magit-untracked-files (&optional include-ignored directory)
|
||||
"Return a list of untracked files.
|
||||
|
||||
Note that when using \"--directory\", the rules from \".gitignore\"
|
||||
files from sub-directories are ignore, which is probably a Git bug.
|
||||
See also `magit-list-untracked-files', which does not have this
|
||||
issue."
|
||||
(magit-list-files "--other" args
|
||||
(and (not all) "--exclude-standard")
|
||||
"--" files))
|
||||
|
||||
(defun magit--untracked-files (&optional directory all)
|
||||
If optional INCLUDE-IGNORED is non-nil, include ignored files.
|
||||
If optional DIRECTORY is non-nil, then limit to that directory.
|
||||
DIRECTORY can also be a list of files and directories."
|
||||
(magit-with-toplevel
|
||||
(seq-keep (##and (eq (aref % 0) ??)
|
||||
(seq-keep (##and (memq (aref % 0) '(?? ?!))
|
||||
(substring % 3))
|
||||
(magit-git-items "status" "-z" "--porcelain"
|
||||
(if all
|
||||
"--untracked-files=all"
|
||||
"--untracked-files=normal")
|
||||
(and include-ignored "--ignored")
|
||||
"--untracked-files=all"
|
||||
"--" directory))))
|
||||
|
||||
(defun magit--untracked-directories (&optional include-ignored directory)
|
||||
"Return a list of directories containing only untracked files.
|
||||
If optional INCLUDE-IGNORED is non-nil, consider ignored files.
|
||||
If optional DIRECTORY is non-nil, then limit to that directory.
|
||||
DIRECTORY can also be a list of files and directories."
|
||||
(magit-with-toplevel
|
||||
(seq-keep (##and (memq (aref % 0) '(?? ?!))
|
||||
(eq (aref % (1- (length %))) ?/)
|
||||
(substring % 3))
|
||||
(magit-git-items "status" "-z" "--porcelain"
|
||||
(and include-ignored "--ignored")
|
||||
"--untracked-files=normal"
|
||||
"--" directory))))
|
||||
|
||||
(defun magit-list-untracked-files (&optional files)
|
||||
@@ -1213,14 +1253,13 @@ See also `magit-untracked-files'."
|
||||
(magit-list-files "-v" args)))
|
||||
|
||||
(defun magit-revision-files (rev)
|
||||
(magit-with-toplevel
|
||||
(magit-git-items "ls-tree" "-z" "-r" "--name-only" rev)))
|
||||
(magit-git-items "ls-tree" "-z" "--full-tree" "-r" "--name-only" rev))
|
||||
|
||||
(defun magit-revision-directories (rev)
|
||||
"List directories that contain a tracked file in revision REV."
|
||||
(magit-with-toplevel
|
||||
(mapcar #'file-name-as-directory
|
||||
(magit-git-items "ls-tree" "-z" "-r" "-d" "--name-only" rev))))
|
||||
(mapcar #'file-name-as-directory
|
||||
(magit-git-items "ls-tree" "-z" "--full-tree" "-r" "-d" "--name-only"
|
||||
rev)))
|
||||
|
||||
(defun magit-changed-files (rev-or-range &optional other-rev)
|
||||
"Return list of files the have changed between two revisions.
|
||||
@@ -1238,6 +1277,28 @@ range. Otherwise, it can be any revision or range accepted by
|
||||
"--diff-filter=R" revA revB)
|
||||
3)))
|
||||
|
||||
;;;; File Names
|
||||
|
||||
(defun magit-file-relative-name (&optional file tracked)
|
||||
"Return the path of FILE relative to the repository root.
|
||||
|
||||
If optional FILE is nil or omitted, return the relative path of
|
||||
the file being visited in the current buffer, if any, else nil.
|
||||
If the file is not inside a Git repository, then return nil.
|
||||
|
||||
If TRACKED is non-nil, return the path only if it matches a
|
||||
tracked file."
|
||||
(with-current-buffer (or (buffer-base-buffer) (current-buffer))
|
||||
(and-let* ((file (or file
|
||||
(magit-buffer-file-name)
|
||||
(and (derived-mode-p 'dired-mode)
|
||||
default-directory)))
|
||||
(dir (magit-toplevel (magit--safe-default-directory
|
||||
(file-name-parent-directory file))))
|
||||
(_(or (not tracked)
|
||||
(magit-file-tracked-p file))))
|
||||
(file-relative-name file dir))))
|
||||
|
||||
(defun magit--rev-file-name (file rev other-rev)
|
||||
"For FILE, potentially renamed between REV and OTHER-REV, return name in REV.
|
||||
Return nil, if FILE appears neither in REV nor OTHER-REV,
|
||||
@@ -1246,46 +1307,6 @@ or if no rename is detected."
|
||||
(and$ (magit-renamed-files rev other-rev)
|
||||
(car (rassoc file $)))))
|
||||
|
||||
(defun magit-file-status (&rest args)
|
||||
(magit--with-temp-process-buffer
|
||||
(save-excursion (magit-git-insert "status" "-z" args))
|
||||
(let ((pos (point)) status)
|
||||
(while (> (skip-chars-forward "[:print:]") 0)
|
||||
(let ((x (char-after pos))
|
||||
(y (char-after (1+ pos)))
|
||||
(file (buffer-substring (+ pos 3) (point))))
|
||||
(forward-char)
|
||||
(cond ((memq x '(?R ?C))
|
||||
(setq pos (point))
|
||||
(skip-chars-forward "[:print:]")
|
||||
(push (list file (buffer-substring pos (point)) x y) status)
|
||||
(forward-char))
|
||||
((push (list file nil x y) status))))
|
||||
(setq pos (point)))
|
||||
status)))
|
||||
|
||||
(defcustom magit-cygwin-mount-points
|
||||
(and (eq system-type 'windows-nt)
|
||||
(cl-sort (mapcar
|
||||
(lambda (mount)
|
||||
(if (string-match "^\\(.*\\) on \\(.*\\) type" mount)
|
||||
(cons (file-name-as-directory (match-str 2 mount))
|
||||
(file-name-as-directory (match-str 1 mount)))
|
||||
(lwarn '(magit) :error
|
||||
"Failed to parse Cygwin mount: %S" mount)))
|
||||
;; If --exec-path is not a native Windows path,
|
||||
;; then we probably have a cygwin git.
|
||||
(and-let ((dirs (magit--early-process-lines
|
||||
magit-git-executable "--exec-path")))
|
||||
(and (not (string-match-p "\\`[a-zA-Z]:" (car dirs)))
|
||||
(magit--early-process-lines "mount"))))
|
||||
#'> :key (pcase-lambda (`(,cyg . ,_win)) (length cyg))))
|
||||
"Alist of (CYGWIN . WIN32) directory names.
|
||||
Sorted from longest to shortest CYGWIN name."
|
||||
:package-version '(magit . "2.3.0")
|
||||
:group 'magit-process
|
||||
:type '(alist :key-type string :value-type directory))
|
||||
|
||||
(defun magit-expand-git-file-name (filename)
|
||||
(unless (file-name-absolute-p filename)
|
||||
(setq filename (expand-file-name filename)))
|
||||
@@ -1322,6 +1343,8 @@ Sorted from longest to shortest CYGWIN name."
|
||||
t)
|
||||
path))
|
||||
|
||||
;;;; File Miscellaneous
|
||||
|
||||
(defun magit-file-at-point (&optional expand assert)
|
||||
(cond-let
|
||||
([file (magit-section-case
|
||||
@@ -1339,6 +1362,24 @@ Sorted from longest to shortest CYGWIN name."
|
||||
(and (derived-mode-p 'magit-log-mode)
|
||||
(car magit-buffer-log-files))))
|
||||
|
||||
(defun magit-file-status (&rest args)
|
||||
(magit--with-temp-process-buffer
|
||||
(save-excursion (magit-git-insert "status" "-z" args))
|
||||
(let ((pos (point)) status)
|
||||
(while (> (skip-chars-forward "[:print:]") 0)
|
||||
(let ((x (char-after pos))
|
||||
(y (char-after (1+ pos)))
|
||||
(file (buffer-substring (+ pos 3) (point))))
|
||||
(forward-char)
|
||||
(cond ((memq x '(?R ?C))
|
||||
(setq pos (point))
|
||||
(skip-chars-forward "[:print:]")
|
||||
(push (list file (buffer-substring pos (point)) x y) status)
|
||||
(forward-char))
|
||||
((push (list file nil x y) status))))
|
||||
(setq pos (point)))
|
||||
status)))
|
||||
|
||||
;;; Blobs
|
||||
|
||||
(defun magit-blob-p (obj)
|
||||
@@ -1437,30 +1478,30 @@ are considered."
|
||||
;;; Revisions and References
|
||||
|
||||
(defun magit-rev-parse (&rest args)
|
||||
"Execute `git rev-parse ARGS', returning first line of output.
|
||||
"Execute \"git rev-parse ARGS\", returning first line of output.
|
||||
If there is no output, return nil."
|
||||
(apply #'magit-git-string "rev-parse" args))
|
||||
|
||||
(defun magit-rev-parse-safe (&rest args)
|
||||
"Execute `git rev-parse ARGS', returning first line of output.
|
||||
"Execute \"git rev-parse ARGS\", returning first line of output.
|
||||
If there is no output, return nil. Like `magit-rev-parse' but
|
||||
ignore `magit-git-debug'."
|
||||
(apply #'magit-git-str "rev-parse" args))
|
||||
|
||||
(defun magit-rev-parse-true (&rest args)
|
||||
"Execute `git rev-parse ARGS', returning t if it prints \"true\".
|
||||
"Execute \"git rev-parse ARGS\", returning t if it prints \"true\".
|
||||
If it prints \"false\", then return nil. For any other output
|
||||
signal an error."
|
||||
(magit-git-true "rev-parse" args))
|
||||
|
||||
(defun magit-rev-parse-false (&rest args)
|
||||
"Execute `git rev-parse ARGS', returning t if it prints \"false\".
|
||||
"Execute \"git rev-parse ARGS\", returning t if it prints \"false\".
|
||||
If it prints \"true\", then return nil. For any other output
|
||||
signal an error."
|
||||
(magit-git-false "rev-parse" args))
|
||||
|
||||
(defun magit-rev-parse-p (&rest args)
|
||||
"Execute `git rev-parse ARGS', returning t if it prints \"true\".
|
||||
"Execute \"git rev-parse ARGS\", returning t if it prints \"true\".
|
||||
Return t if the first (and usually only) output line is the
|
||||
string \"true\", otherwise return nil."
|
||||
(equal (magit-git-str "rev-parse" args) "true"))
|
||||
@@ -1643,9 +1684,8 @@ to, or to some other symbolic-ref that points to the same ref."
|
||||
(branch (oref it value))
|
||||
(commit (or (magit--painted-branch-at-point)
|
||||
(magit-name-branch (oref it value))))
|
||||
(pullreq (and (fboundp 'forge--pullreq-branch)
|
||||
(magit-branch-p
|
||||
(forge--pullreq-branch (oref it value)))))
|
||||
(pullreq (and (fboundp 'forge--pullreq-branch-active)
|
||||
(forge--pullreq-branch-active (oref it value))))
|
||||
(related-refs (magit--painted-branch-at-point))
|
||||
((unpulled unpushed)
|
||||
(magit-ref-abbrev
|
||||
@@ -1699,11 +1739,10 @@ to, or to some other symbolic-ref that points to the same ref."
|
||||
(let ((rev (oref it value)))
|
||||
(or (magit-name-branch rev) rev))))
|
||||
(tag (magit-ref-maybe-qualify (oref it value) "tags/"))
|
||||
(pullreq (or (and (fboundp 'forge--pullreq-branch)
|
||||
(magit-branch-p
|
||||
(forge--pullreq-branch (oref it value))))
|
||||
(magit-ref-p (format "refs/pullreqs/%s"
|
||||
(oref (oref it value) number)))))
|
||||
(pullreq (or (and (fboundp 'forge--pullreq-branch-active)
|
||||
(forge--pullreq-branch-active (oref it value)))
|
||||
(and (fboundp 'forge--pullreq-ref)
|
||||
(forge--pullreq-ref (oref it value)))))
|
||||
((unpulled unpushed)
|
||||
(magit-ref-abbrev
|
||||
(replace-regexp-in-string "\\.\\.\\.?" "" (oref it value)))))
|
||||
@@ -1762,7 +1801,7 @@ The amount of time spent searching is limited by
|
||||
((setq prev (magit-rev-verify (format "@{-%d}" i)))
|
||||
(or (not (setq prev (magit-rev-branch prev)))
|
||||
(equal prev current))))
|
||||
(cl-incf i))
|
||||
(incf i))
|
||||
prev))
|
||||
|
||||
(defun magit--set-default-branch (newname oldname)
|
||||
@@ -1906,7 +1945,11 @@ according to the branch type."
|
||||
(magit--with-refresh-cache
|
||||
(list default-directory 'magit-get-push-branch branch verify)
|
||||
(and-let*
|
||||
((branch (magit-ref-abbrev (or branch (magit-get-current-branch))))
|
||||
((branch (cond ((not branch)
|
||||
(magit-get-current-branch))
|
||||
((string-prefix-p "refs/" branch)
|
||||
(magit-ref-abbrev branch))
|
||||
(branch)))
|
||||
(remote (magit-get-push-remote branch))
|
||||
(target (concat remote "/" branch)))
|
||||
(and (or (not verify)
|
||||
@@ -2054,11 +2097,11 @@ where COMMITS is the number of commits in TAG but not in REV."
|
||||
When NAMESPACES is non-nil, list refs from these namespaces
|
||||
rather than those from `magit-list-refs-namespaces'.
|
||||
|
||||
FORMAT is passed to the `--format' flag of `git for-each-ref'
|
||||
FORMAT is passed to the \"--format\" flag of \"git for-each-ref\"
|
||||
and defaults to \"%(refname)\".
|
||||
|
||||
SORTBY is a key or list of keys to pass to the `--sort' flag
|
||||
of `git for-each-ref' to sort the refs within each namespace.
|
||||
SORTBY is a key or list of keys to pass to the \"--sort\" flag
|
||||
of \"git for-each-ref\" to sort the refs within each namespace.
|
||||
When nil, use `magit-list-refs-sortby'. If both are nil, use
|
||||
\"version:refname\", but only for \"refs/tags\"."
|
||||
(let ((format (concat "--format=%(symref)" (or format "%(refname)")))
|
||||
@@ -2079,20 +2122,32 @@ When nil, use `magit-list-refs-sortby'. If both are nil, use
|
||||
(or namespaces magit-list-refs-namespaces))))))
|
||||
|
||||
(defun magit-list-branches ()
|
||||
"Return list of local and remote-tracking branches."
|
||||
(magit-list-refs (list "refs/heads" "refs/remotes")))
|
||||
|
||||
(defun magit-list-local-branches ()
|
||||
"Return list of local branches."
|
||||
(magit-list-refs "refs/heads"))
|
||||
|
||||
(defun magit-list-remote-branches (&optional remote)
|
||||
"Return list of remote-tracking branches.
|
||||
If optional REMOTE is non-nil, return only branches from that remote."
|
||||
(magit-list-refs (concat "refs/remotes/" remote)))
|
||||
|
||||
(defun magit-list-related-branches (relation &optional rev &rest args)
|
||||
"Return list of branches related to REV.
|
||||
RELATION must be one of \"--contains\", \"--no-contains\", \"--merged\",
|
||||
\"--no-merged\" and \"--points-at\". If optional REV is nil, default to
|
||||
the \"HEAD\" commit. Optional ARGS are additional arguments passed to
|
||||
\"git branch\"."
|
||||
(seq-remove (##string-match-p "\\(\\`(HEAD\\|HEAD -> \\)" %)
|
||||
(mapcar (##substring % 2)
|
||||
(magit-git-lines "branch" args relation rev))))
|
||||
|
||||
(defun magit-list-containing-branches (&optional rev &rest args)
|
||||
"Return list of branches containing REV.
|
||||
If optional REV is nil, default to the \"HEAD\" commit.
|
||||
Optional ARGS are additional arguments passed to \"git branch\"."
|
||||
(magit-list-related-branches "--contains" rev args))
|
||||
|
||||
(defun magit-list-publishing-branches (&optional rev)
|
||||
@@ -2100,17 +2155,25 @@ When nil, use `magit-list-refs-sortby'. If both are nil, use
|
||||
magit-published-branches))
|
||||
|
||||
(defun magit-list-merged-branches (&optional rev &rest args)
|
||||
"Return list of branches merged into REV.
|
||||
If optional REV is nil, default to the \"HEAD\" commit.
|
||||
Optional ARGS are additional arguments passed to \"git branch\"."
|
||||
(magit-list-related-branches "--merged" rev args))
|
||||
|
||||
(defun magit-list-unmerged-branches (&optional rev &rest args)
|
||||
"Return list of branches not merged into REV.
|
||||
If optional REV is nil, default to the \"HEAD\" commit.
|
||||
Optional ARGS are additional arguments passed to \"git branch\"."
|
||||
(magit-list-related-branches "--no-merged" rev args))
|
||||
|
||||
(defun magit-list-unmerged-to-upstream-branches ()
|
||||
"Return list of branches not merged into their respective upstreams."
|
||||
(seq-filter (##and-let ((upstream (magit-get-upstream-branch %)))
|
||||
(member % (magit-list-unmerged-branches upstream)))
|
||||
(magit-list-local-branch-names)))
|
||||
|
||||
(defun magit-list-branches-pointing-at (rev)
|
||||
"Return list of branches pointing at REV."
|
||||
(let ((re (format "\\`%s refs/\\(heads\\|remotes\\)/\\(.*\\)\\'"
|
||||
(magit-rev-verify rev))))
|
||||
(seq-keep (##and (string-match re %)
|
||||
@@ -2277,36 +2340,73 @@ specified using `core.worktree'."
|
||||
(if (> (length line) 8) (substring line 9) t)))))
|
||||
(nreverse worktrees)))
|
||||
|
||||
(defun magit-symbolic-ref-p (name)
|
||||
(magit-git-success "symbolic-ref" "--quiet" name))
|
||||
(defun magit-symbolic-ref-p (string)
|
||||
"Return t if STRING is a reference, nil otherwise.
|
||||
Signal an error if STRING is not a string."
|
||||
(cl-assert (stringp string))
|
||||
(magit-git-success "symbolic-ref" "--quiet" string))
|
||||
|
||||
(defun magit-ref-p (rev)
|
||||
(or (car (member rev (magit-list-refs "refs/")))
|
||||
(car (member rev (magit-list-refnames "refs/")))))
|
||||
(defun magit-ref-p (string)
|
||||
"Return t if STRING is a reference, nil otherwise.
|
||||
Signal an error if STRING is not a string."
|
||||
(cl-assert (stringp string))
|
||||
(and (magit-ref-fullname string)
|
||||
(not (magit-symbolic-ref-p string))))
|
||||
|
||||
(defun magit-branch-p (rev)
|
||||
(or (car (member rev (magit-list-branches)))
|
||||
(car (member rev (magit-list-branch-names)))))
|
||||
(defun magit-branch-p (string)
|
||||
"Return t if STRING is a local or remote-tracking branch, nil otherwise.
|
||||
Signal an error if STRING is not a string."
|
||||
(cl-assert (stringp string))
|
||||
(or (magit-local-branch-p string)
|
||||
(magit-remote-branch-p string)))
|
||||
|
||||
(defun magit-local-branch-p (rev)
|
||||
(or (car (member rev (magit-list-local-branches)))
|
||||
(car (member rev (magit-list-local-branch-names)))))
|
||||
(defun magit-local-branch-p (string)
|
||||
"Return t if STRING is a local branch.
|
||||
Signal an error if STRING is not a string."
|
||||
(cl-assert (stringp string))
|
||||
(magit-git-success "show-ref" "--quiet" "--branches" string))
|
||||
|
||||
(defun magit-remote-branch-p (rev)
|
||||
(or (car (member rev (magit-list-remote-branches)))
|
||||
(car (member rev (magit-list-remote-branch-names)))))
|
||||
(defun magit-remote-branch-p (string)
|
||||
"Return t if STRING is a remote-tracking branch, nil otherwise.
|
||||
Signal an error if STRING is not a string."
|
||||
(cl-assert (stringp string))
|
||||
(seq-some (lambda (line)
|
||||
(let ((ref (cadr (split-string line " "))))
|
||||
(or (equal string ref)
|
||||
(equal string (substring ref 5))
|
||||
(equal string (substring ref 13)))))
|
||||
(magit-git-lines "show-ref" string)))
|
||||
|
||||
(defun magit-tag-p (string)
|
||||
"Return t if STRING is an annotated or lightweight tag, nil otherwise.
|
||||
Signal an error if STRING is not a string."
|
||||
(cl-assert (stringp string))
|
||||
(magit-git-success "show-ref" "--quiet" "--tags" string))
|
||||
|
||||
(defun magit-annotated-tag-p (string)
|
||||
"Return t if STRING is an annotated tag, nil otherwise.
|
||||
Signal an error if STRING is not a string."
|
||||
(cl-assert (stringp string))
|
||||
(equal (magit-object-type string) "tag"))
|
||||
|
||||
(defun magit-lightweight-tag-p (string)
|
||||
"Return t if STRING is a lightweight (un-annotated) tag, nil otherwise.
|
||||
Signal an error if STRING is not a string."
|
||||
(cl-assert (stringp string))
|
||||
(and (magit-tag-p string)
|
||||
(not (magit-annotated-tag-p string))))
|
||||
|
||||
(defun magit-remote-p (string)
|
||||
"Return t if STRING is a remote, nil otherwise.
|
||||
Signal an error if STRING is not a string."
|
||||
(cl-assert (stringp string))
|
||||
(and (member string (magit-list-remotes)) t))
|
||||
|
||||
(defun magit-branch-set-face (branch)
|
||||
(magit--propertize-face branch (if (magit-local-branch-p branch)
|
||||
'magit-branch-local
|
||||
'magit-branch-remote)))
|
||||
|
||||
(defun magit-tag-p (obj)
|
||||
(equal (magit-object-type obj) "tag"))
|
||||
|
||||
(defun magit-remote-p (string)
|
||||
(car (member string (magit-list-remotes))))
|
||||
|
||||
(defvar magit-main-branch-names
|
||||
'("main" "master" "trunk" "development")
|
||||
"Branch names reserved for use by the primary branch.
|
||||
@@ -2373,7 +2473,8 @@ If `first-parent' is set, traverse only first parents."
|
||||
(magit-rev-parse (magit-abbrev-arg "short") rev))
|
||||
|
||||
(defun magit--abbrev-if-oid (obj)
|
||||
(cond ((or (magit-ref-p obj) (member obj '("{index}" "{worktree}"))) obj)
|
||||
(cond ((member obj '("{index}" "{worktree}")) obj)
|
||||
((magit-ref-p obj) obj)
|
||||
((magit-rev-parse (magit-abbrev-arg "short") obj))
|
||||
(obj)))
|
||||
|
||||
@@ -2399,7 +2500,7 @@ If `first-parent' is set, traverse only first parents."
|
||||
(car (split-string (buffer-string))))))
|
||||
|
||||
(defun magit-rev-format (format &optional rev args)
|
||||
;; Prefer `git log --no-walk' to `git show --no-patch' because it
|
||||
;; Prefer "git log --no-walk" to "git show --no-patch" because it
|
||||
;; performs better in some scenarios.
|
||||
(let ((str (magit-git-string "log" "--no-walk"
|
||||
(concat "--format=" format) args
|
||||
@@ -2409,7 +2510,7 @@ If `first-parent' is set, traverse only first parents."
|
||||
str)))
|
||||
|
||||
(defun magit-rev-insert-format (format &optional rev args)
|
||||
;; Prefer `git log --no-walk' to `git show --no-patch' because it
|
||||
;; Prefer "git log --no-walk" to "git show --no-patch" because it
|
||||
;; performs better in some scenarios.
|
||||
(magit-git-insert "log" "--no-walk"
|
||||
(concat "--format=" format) args
|
||||
@@ -2987,8 +3088,17 @@ out. Only existing branches can be selected."
|
||||
(magit-get-remote))))
|
||||
|
||||
(defun magit-read-module-path (prompt &optional predicate)
|
||||
;; Predicates are evaluate with the minibuffer as the current buffer.
|
||||
;; Unlike for other completion frameworks, Helm does not ensure that
|
||||
;; the value of `default-directory' in that buffer is the same as in
|
||||
;; the buffer from which completion was invoked.
|
||||
(magit-completing-read prompt (magit-list-module-paths)
|
||||
predicate t nil nil
|
||||
(and predicate
|
||||
(let ((dir default-directory))
|
||||
(lambda (module)
|
||||
(let ((default-directory dir))
|
||||
(funcall predicate module)))))
|
||||
t nil nil
|
||||
(magit-module-at-point predicate)))
|
||||
|
||||
(defun magit-module-confirm (verb &optional predicate)
|
||||
@@ -3017,23 +3127,24 @@ out. Only existing branches can be selected."
|
||||
|
||||
;;; Git Hooks
|
||||
|
||||
(defun magit-run-git-hook (githook &rest args)
|
||||
(dolist (githook (ensure-list githook))
|
||||
(let* ((githook (symbol-name githook))
|
||||
(hook (save-match-data
|
||||
(if (string-match "\\`common-" githook)
|
||||
(intern (format "magit-common-git-%s-functions"
|
||||
(substring githook (match-end 0))))
|
||||
(intern (format "magit-git-%s-functions" githook))))))
|
||||
(when (and (boundp hook)
|
||||
(symbol-value hook))
|
||||
(magit--client-message "Running %s..." hook)
|
||||
(apply #'run-hook-with-args hook args)
|
||||
(magit--client-message "Running %s...done" hook))))
|
||||
;; Emacsclient prints the returned value to stdout. We cannot prevent
|
||||
;; that, but we can use something that looks like we actually *wanted*
|
||||
;; to print (which we don't).
|
||||
'---)
|
||||
(defun magit-run-git-hook (hook &rest args)
|
||||
"Run the Lisp HOOK with the specified arguments ARGS.
|
||||
|
||||
ARGS are the arguments (a possibly empty list of strings), which
|
||||
the Git hook was called with. HOOK is a string naming a hook.
|
||||
|
||||
This function is only intended to be called via \"emacsclient\", by
|
||||
an executable by the same name, which in turn is only intended to
|
||||
be called by Git hooks."
|
||||
(setq hook (intern hook))
|
||||
(when (and (boundp hook)
|
||||
(symbol-value hook))
|
||||
(magit--client-message "Running %s..." hook)
|
||||
(advice-add 'message :override #'magit--client-message)
|
||||
(unwind-protect (apply #'run-hook-with-args hook args)
|
||||
(advice-remove 'message #'magit--client-message))
|
||||
(magit--client-message "Running %s...done" hook))
|
||||
'---) ; Emacsclient insists on printing the value.
|
||||
|
||||
(defun magit--client-message (format-string &rest args)
|
||||
;; See `server-process-filter'.
|
||||
@@ -3063,11 +3174,15 @@ Instead use `magit-commit-p' or `magit-commit-oid'.")
|
||||
;; Local Variables:
|
||||
;; read-symbol-shorthands: (
|
||||
;; ("and$" . "cond-let--and$")
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("thread$" . "cond-let--thread$")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("and-let*" . "cond-let--and-let*")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let*" . "cond-let--if-let*")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when-let*" . "cond-let--when-let*")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let*" . "cond-let--while-let*")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
;; ("match-str" . "match-string-no-properties"))
|
||||
|
||||
Reference in New Issue
Block a user