commit fff8bfc8d831faf76a80b44b15c6b6c190a1cd52 (HEAD, refs/remotes/origin/master) Author: Paul Eggert Date: Tue Feb 9 00:26:00 2016 -0800 Avoid aligned_alloc static/extern collision * src/alloc.c (aligned_alloc): Define to private name when a static function, to avoid collision with lisp.h extern decl. Reported by John Yates in: http://lists.gnu.org/archive/html/emacs-devel/2016-02/msg00439.html diff --git a/src/alloc.c b/src/alloc.c index 92945bc..7364d7c 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1133,6 +1133,7 @@ lisp_free (void *block) # define USE_ALIGNED_ALLOC 1 # elif !defined HYBRID_MALLOC && defined HAVE_POSIX_MEMALIGN # define USE_ALIGNED_ALLOC 1 +# define aligned_alloc my_aligned_alloc /* Avoid collision with lisp.h. */ static void * aligned_alloc (size_t alignment, size_t size) { commit 68f06909711dc87eb7af7d32424578db6667a395 Author: Michal Nazarewicz Date: Tue Feb 9 14:07:05 2016 +1100 Make `message-beginning-of-line' aware of folded headers * lisp/gnus/message.pl (message-beginning-of-header): New function which moves point to the beginning of a mail header. The function is aware of folded headers and with non-nil argument looks for the true beginning of a header while with nil argument moves to the indented text of header's value. (message-beginning-of-line): Function is now aware of folded headers and either moves point to the indention of a header or, in visual-line-mode, searches for the beginning of the header. diff --git a/etc/NEWS b/etc/NEWS index bcb70d4..3f5f5b0 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -772,6 +772,11 @@ there are now top-level domains added all the time. Message will no longer warn about sending emails to top-level domains it hasn't heard about. +*** `message-beginning-of-line' (bound to C-a) understands folded headers. +In `visual-line-mode' it will look for the true beginning of a header +while in non-`visual-line-mode' it will move the point to the indented +header’s value. + +++ ** Images are automatically scaled before displaying based on the `image-scaling-factor' variable (if Emacs supports scaling the images diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index 9460710..5551820 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -6349,35 +6349,77 @@ they are." (defvar visual-line-mode) (declare-function beginning-of-visual-line "simple" (&optional n)) +(defun message-beginning-of-header (handle-folded) + "Move point to beginning of header’s value. + +When point is at the first header line, moves it after the colon +and spaces separating header name and header value. + +When point is in a continuation line of a folded header (i.e. the +line starts with a space), the behaviour depends on HANDLE-FOLDED +argument. If it’s nil, function moves the point to the start of +the header continuation; otherwise, function locates the +beginning of the header and moves point past the colon as is the +case of single-line headers. + +No check whether point is inside of a header or body of the +message is performed. + +Returns point or nil if beginning of header’s value could not be +found. In the latter case, the point is still moved to the +beginning of line (possibly after attempting to move it to the +beginning of a folded header)." + ;; https://www.rfc-editor.org/rfc/rfc2822.txt, section 2.2.3. says that when + ;; unfolding a single WSP should be consumed. WSP is defined as a space + ;; character or a horizontal tab. + (beginning-of-line) + (when handle-folded + (while (and (> (point) (point-min)) + (or (eq (char-after) ?\s) (eq (char-after) ?\t))) + (beginning-of-line 0))) + (when (or (eq (char-after) ?\s) (eq (char-after) ?\t) + (search-forward ":" (point-at-eol) t)) + ;; We are a bit more lacks than the RFC and allow any positive number of WSP + ;; characters. + (skip-chars-forward " \t" (point-at-eol)) + (point))) + (defun message-beginning-of-line (&optional n) "Move point to beginning of header value or to beginning of line. The prefix argument N is passed directly to `beginning-of-line'. This command is identical to `beginning-of-line' if point is -outside the message header or if the option `message-beginning-of-line' -is nil. - -If point is in the message header and on a (non-continued) header -line, move point to the beginning of the header value or the beginning of line, -whichever is closer. If point is already at beginning of line, move point to -beginning of header value. Therefore, repeated calls will toggle point -between beginning of field and beginning of line." +outside the message header or if the option +`message-beginning-of-line' is nil. + +If point is in the message header and on a header line, move +point to the beginning of the header value or the beginning of +line, whichever is closer. If point is already at beginning of +line, move point to beginning of header value. Therefore, +repeated calls will toggle point between beginning of field and +beginning of line. + +When called without a prefix argument, header value spanning +multiple lines is treated as a single line. Otherwise, even if +N is 1, when point is on a continuation header line, it will be +moved to the beginning " (interactive "p") (let ((zrs 'zmacs-region-stays)) (when (and (featurep 'xemacs) (interactive-p) (boundp zrs)) (set zrs t))) - (if (and message-beginning-of-line - (message-point-in-header-p)) - (let* ((here (point)) - (bol (progn (beginning-of-line n) (point))) - (eol (point-at-eol)) - (eoh (re-search-forward ": *" eol t))) - (goto-char - (if (and eoh (or (< eoh here) (= bol here))) - eoh bol))) - (if (and (boundp 'visual-line-mode) visual-line-mode) - (beginning-of-visual-line n) - (beginning-of-line n)))) + (cond + ;; Go to beginning of header or beginning of line. + ((and message-beginning-of-line (message-point-in-header-p)) + (let* ((point (point)) + (bol (progn (beginning-of-line n) (point))) + (boh (message-beginning-of-header (and (boundp 'visual-line-mode) + visual-line-mode)))) + (goto-char (if (and boh (or (< boh point) (= bol point))) boh bol)))) + ;; Go to beginning of visual line + ((and (boundp 'visual-line-mode) visual-line-mode) + (beginning-of-visual-line n)) + ;; Go to beginning of line. + ((beginning-of-line n)))) (defun message-buffer-name (type &optional to group) "Return a new (unique) buffer name based on TYPE and TO." commit 824a87f41f53eea3aa8ffcb9f065ce149213ebfb Author: Michal Nazarewicz Date: Tue Feb 9 14:05:34 2016 +1100 Optimise ‘point in message header’ check * lisp/gnus/message.el (message-point-in-header-p): Replace two unbound regular expression matches with a single bound string match thus reducing amount of work the function is doing. diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index 8a7ed4f..9460710 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -3524,12 +3524,12 @@ Message buffers and is not meant to be called directly." (defun message-point-in-header-p () "Return t if point is in the header." (save-excursion - (and - (not - (re-search-backward - (concat "^" (regexp-quote mail-header-separator) "\n") nil t)) - (re-search-forward - (concat "^" (regexp-quote mail-header-separator) "\n") nil t)))) + (save-restriction + (widen) + (let ((bound (+ (point-at-eol) 1)) case-fold-search) + (goto-char (point-min)) + (not (search-forward (concat "\n" mail-header-separator "\n") + bound t)))))) (defun message-do-auto-fill () "Like `do-auto-fill', but don't fill in message header." commit 8722e849f75ceafb82a1c17105e8ab76077a8ebc Author: Lars Ingebrigtsen Date: Tue Feb 9 13:51:45 2016 +1100 Make the `R' command get the correct relative s * lisp/net/eww.el (eww-readable): Preserve the base URL so that image expansions are fetched from the right place (bug#22605). diff --git a/lisp/net/eww.el b/lisp/net/eww.el index 6a5fb4b..fdac464 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -625,11 +625,13 @@ the like." (condition-case nil (decode-coding-region (point-min) (point-max) 'utf-8) (coding-system-error nil)) - (libxml-parse-html-region (point-min) (point-max))))) + (libxml-parse-html-region (point-min) (point-max)))) + (base (plist-get eww-data :url))) (eww-score-readability dom) (eww-save-history) (eww-display-html nil nil - (eww-highest-readability dom) + (list 'base (list (cons 'href base)) + (eww-highest-readability dom)) nil (current-buffer)) (dolist (elem '(:source :url :title :next :previous :up)) (plist-put eww-data elem (plist-get old-data elem))) commit 54b198af77449135980ce36fcfb42a5eea18c5c4 Author: Lars Ingebrigtsen Date: Tue Feb 9 13:36:15 2016 +1100 Add a mode to list and cancel timers * doc/lispref/os.texi (Timers): Menton `timer-list'. * lisp/emacs-lisp/timer-list.el: New file. diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index c5e3672..d57cbcf 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -1849,6 +1849,12 @@ one of these functions; the arrival of the specified time will not cause anything special to happen. @end defun +@findex timer-list +The @code{timer-list} command lists all the currently active timers. +There's only one command available in the buffer displayed: @kbd{c} +(@code{timer-list-cancel}) that will cancel the timer on the line +under point. + @node Idle Timers @section Idle Timers @cindex idle timers diff --git a/etc/NEWS b/etc/NEWS index fd56f0c..bcb70d4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -269,6 +269,10 @@ puny.el library, so that one can visit web sites like ** The new M-s M-w key binding uses eww to search the web for the text in the region. ++++ +** The new `timer-list' command lists all active timers in a buffer +where you can cancel them with the `c' command. + ** M-x suggests shorthands and ignores obsolete commands for completion. ** x-select-enable-clipboard is renamed select-enable-clipboard. x-select-enable-primary and renamed select-enable-primary. diff --git a/lisp/emacs-lisp/timer-list.el b/lisp/emacs-lisp/timer-list.el new file mode 100644 index 0000000..b54902a --- /dev/null +++ b/lisp/emacs-lisp/timer-list.el @@ -0,0 +1,108 @@ +;;; timer-list.el --- list active timers in a buffer + +;; Copyright (C) 2016 Free Software Foundation, Inc. + +;; Maintainer: emacs-devel@gnu.org +;; Package: emacs + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;;; Code: + +;;;###autoload +(defun timer-list () + "List all timers in a buffer." + (interactive) + (pop-to-buffer-same-window (get-buffer-create "*timer-list*")) + (let ((inhibit-read-only t)) + (erase-buffer) + (timer-list-mode) + (dolist (timer (append timer-list timer-idle-list)) + (insert (format "%4s %10s %8s %s" + ;; Idle. + (if (aref timer 7) + "*" + " ") + ;; Next time. + (let ((time (float-time (list (aref timer 1) + (aref timer 2) + (aref timer 3))))) + (format "%.2f" + (if (aref timer 7) + time + (- (float-time (list (aref timer 1) + (aref timer 2) + (aref timer 3))) + (float-time))))) + ;; Repeat. + (let ((repeat (aref timer 4))) + (cond + ((numberp repeat) + (format "%.2f" (/ repeat 60))) + ((null repeat) + "-") + (t + (format "%s" repeat)))) + ;; Function. + (let ((function (aref timer 5))) + (replace-regexp-in-string + "\n" " " + (cond + ((byte-code-function-p function) + (replace-regexp-in-string + "[^-A-Za-z0-9 ]" "" + (format "%s" function))) + (t + (format "%s" function))))))) + (put-text-property (line-beginning-position) + (1+ (line-beginning-position)) + 'timer timer) + (insert "\n"))) + (goto-char (point-min))) + +(defvar timer-list-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "c" 'timer-list-cancel) + (easy-menu-define nil map "" + '("Timers" + ["Cancel" timer-list-cancel t])) + map)) + +(define-derived-mode timer-list-mode special-mode "timer-list" + "Mode for listing and controlling timers." + (setq truncate-lines t) + (buffer-disable-undo) + (setq buffer-read-only t) + (setq header-line-format + (format "%4s %10s %8s %s" + "Idle" "Next" "Repeat" "Function"))) + +(defun timer-list-cancel () + "Cancel the timer on the line under point." + (interactive) + (let ((timer (get-text-property (line-beginning-position) 'timer)) + (inhibit-read-only t)) + (unless timer + (error "No timer on the current line")) + (cancel-timer timer) + (delete-region (line-beginning-position) + (line-beginning-position 2)))) + +(provide 'timer-list) + +;;; timer-list.el ends here commit c93cc660ac85db9e7932ffae6bd886034defffba Author: Lars Ingebrigtsen Date: Tue Feb 9 12:44:32 2016 +1100 Add new commands to allow changing the size of images * lisp/image.el (image-increase-size, image-decrease-size): New commands. (image-change-size): New function. diff --git a/lisp/image.el b/lisp/image.el index 82a10a3..b69d3b1 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -913,6 +913,35 @@ has no effect." (imagemagick-register-types) +(defun image-increase-size (n) + "Increase the image size by a factor of N. +If N is 3, then the image size will be increased by 30%. The +default is 20%." + (interactive "P") + (image-change-size (if n + (1+ (/ n 10)) + 1.2))) + +(defun image-decrease-size (n) + "Decrease the image size by a factor of N. +If N is 3, then the image size will be decreased by 30%. The +default is 20%." + (interactive "P") + (image-change-size (if n + (- 1 (/ n 10)) + 0.8))) + +(defun image-change-size (factor) + (unless (fboundp 'imagemagick-types) + (error "Can't rescale images without ImageMagick support")) + (let ((image (get-text-property (point) 'display))) + (when (or (not (consp image)) + (not (eq (car image) 'image))) + (error "No image under point")) + (plist-put (cdr image) :type 'imagemagick) + (plist-put (cdr image) :scale + (* (or (plist-get (cdr image) :scale) 1) factor)))) + (provide 'image) ;;; image.el ends here commit 4a24af2d2b2be168e37947ceb1a3906eb1da0e55 Author: Lars Ingebrigtsen Date: Tue Feb 9 12:34:48 2016 +1100 Allow the image scale to be a floating point number * src/image.c (compute_image_size): The scale can be a floating point number. diff --git a/src/image.c b/src/image.c index bc5863f..ea5d231 100644 --- a/src/image.c +++ b/src/image.c @@ -8085,7 +8085,7 @@ compute_image_size (size_t width, size_t height, desired_height = NATNUMP (value) ? min (XFASTINT (value), INT_MAX) : -1; value = image_spec_value (spec, QCscale, NULL); - if (NATNUMP (value)) + if (NUMBERP (value)) scale = extract_float (value); width = width * scale; height = height * scale; commit 8e7703e83248e4de57b87ff58891b2b832b57fe7 Author: Lars Ingebrigtsen Date: Tue Feb 9 10:24:34 2016 +1100 Add an IPv6 test * test/lisp/net/network-stream-tests.el (connect-to-tls-ipv6-nowait): Add an ipv6 test, too. diff --git a/test/lisp/net/network-stream-tests.el b/test/lisp/net/network-stream-tests.el index fedeea8..734f077 100644 --- a/test/lisp/net/network-stream-tests.el +++ b/test/lisp/net/network-stream-tests.el @@ -164,7 +164,7 @@ "--x509certfile" "lisp/net/cert.pem" "--port" "44330")) -(ert-deftest connect-to-tls () +(ert-deftest connect-to-tls-ipv4-wait () (skip-unless (executable-find "gnutls-serv")) (skip-unless (gnutls-available-p)) (let ((server (make-tls-server)) @@ -196,4 +196,38 @@ (setq issuer (split-string issuer ",")) (should (equal (nth 3 issuer) "O=Emacs Test Servicess LLC"))))) +(ert-deftest connect-to-tls-ipv6-nowait () + (skip-unless (executable-find "gnutls-serv")) + (skip-unless (gnutls-available-p)) + (let ((server (make-tls-server)) + (times 0) + proc status) + (sleep-for 1) + (with-current-buffer (process-buffer server) + (message "gnutls-serv: %s" (buffer-string))) + + ;; It takes a while for gnutls-serv to start. + (while (and (null (ignore-errors + (setq proc (make-network-process + :name "bar" + :buffer (generate-new-buffer "*foo*") + :family 'ipv6 + :nowait t + :host "::1" + :service 44330)))) + (< (setq times (1+ times)) 10)) + (sit-for 0.1)) + (should proc) + (gnutls-negotiate :process proc + :type 'gnutls-x509pki + :hostname "localhost") + (delete-process server) + (setq status (gnutls-peer-status proc)) + (should (consp status)) + (delete-process proc) + (let ((issuer (plist-get (plist-get status :certificate) :issuer))) + (should (stringp issuer)) + (setq issuer (split-string issuer ",")) + (should (equal (nth 3 issuer) "O=Emacs Test Servicess LLC"))))) + ;;; network-stream-tests.el ends here commit fbde8feb79f2e74725c0ca17049fb9a8a9fb6ef2 Author: Lars Ingebrigtsen Date: Tue Feb 9 10:16:14 2016 +1100 Use gnutls-serv instead of openssh * test/lisp/net/network-stream-tests.el (make-tls-server): Use gnutls-serv instead of openssh. diff --git a/test/lisp/net/network-stream-tests.el b/test/lisp/net/network-stream-tests.el index 863064d..fedeea8 100644 --- a/test/lisp/net/network-stream-tests.el +++ b/test/lisp/net/network-stream-tests.el @@ -158,23 +158,23 @@ (delete-process server))) (defun make-tls-server () - (start-process "openssl" (generate-new-buffer "*tls*") "openssl" - "s_server" "-key" "lisp/net/key.pem" - "-cert" "lisp/net/cert.pem" - "-accept" "44330" - "-www")) + (start-process "gnutls" (generate-new-buffer "*tls*") + "gnutls-serv" "--http" + "--x509keyfile" "lisp/net/key.pem" + "--x509certfile" "lisp/net/cert.pem" + "--port" "44330")) (ert-deftest connect-to-tls () - (skip-unless (executable-find "openssl")) + (skip-unless (executable-find "gnutls-serv")) (skip-unless (gnutls-available-p)) (let ((server (make-tls-server)) (times 0) proc status) (sleep-for 1) (with-current-buffer (process-buffer server) - (message "openssl: %s" (buffer-string))) + (message "gnutls-serv: %s" (buffer-string))) - ;; It takes a while for openssl to start. + ;; It takes a while for gnutls-serv to start. (while (and (null (ignore-errors (setq proc (make-network-process :name "bar" commit de76a167dc09dc695a5acebabb7ab354a6bf556e Author: Daniel Colascione Date: Mon Feb 8 10:52:54 2016 -0800 Performance improvements for vc-hg Teach vc-hg how to read some Mercurial internal data structures, allowing us to avoid the need to run hg status -A, which is very slow for large repositories. Fall back to running hg if anything looks funny. vc-hg now puts the _working directory_ revision in the modeline instead of the file revision, which greatly improves performance and which allows us to again skip running hg in the case that we have an active bookmark. * lisp/vc/vc-hg.el (vc-hg-state): Try calling `vc-hg-statefast' (vc-hg-symbolic-revision-styles) (vc-hg-use-file-version-for-mode-line-version) (vc-hg-parse-hg-data-structures): New user preferences (vc-hg--active-bookmark-internal, vc-hg--run-log) (vc-hg--symbolic-revision, vc-hg-mode-line-string) (vc-hg--read-u8, vc-hg--read-u32-be) (vc-hg--raw-dirstate-search, vc-hg--cached-dirstate-search) (vc-hg--parts-to-string, vc-hg--pcre-to-elisp-re) (vc-hg--glob-to-pcre, vc-hg--hgignore-add-pcre) (vc-hg--hgignore-add-glob, vc-hg--hgignore-add-path) (vc-hg--slurp-hgignore-1, vc-hg--slurp-hgignore) (vc-hg--ignore-patterns-valid-p) (vc-hg--ignore-patterns-ignored-p, vc-hg--time-to-fixnum) (vc-hg--file-ignored-p, vc-hg--read-repo-requirements) (vc-hg--requirements-understood-p, vc-hg--dirstate-scan-cache) (vc-hg-state-fast): New functions. (vc-hg--hgignore-patterns, vc-hg--hgignore-filenames) (vc-hg--cached-ignore-patterns, vc-hg--dirstate-scan-cache) (vc-hg--dirstate-scan-cache): New internal variables. * lisp/vc/vc-hooks.el (vc-refresh-state): Invoke vc find-file-hook before updating modeline. diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el index 2d8bab7..702772c 100644 --- a/lisp/vc/vc-hg.el +++ b/lisp/vc/vc-hg.el @@ -48,7 +48,7 @@ ;; - dir-printer (fileinfo) OK ;; * working-revision (file) OK ;; * checkout-model (files) OK -;; - mode-line-string (file) NOT NEEDED +;; - mode-line-string (file) OK ;; STATE-CHANGING FUNCTIONS ;; * register (files &optional rev comment) OK ;; * create-repo () OK @@ -197,6 +197,11 @@ highlighting the Log View buffer." (defun vc-hg-state (file) "Hg-specific version of `vc-state'." + (let ((state (vc-hg-state-fast file))) + (if (eq state 'unsupported) (vc-hg-state-slow file) state))) + +(defun vc-hg-state-slow (file) + "Determine status of FILE by running hg." (setq file (expand-file-name file)) (let* ((status nil) @@ -245,6 +250,130 @@ highlighting the Log View buffer." "parent" "--template" "{rev}"))) "0")) +(defcustom vc-hg-symbolic-revision-styles + '(builtin-active-bookmark + "{if(bookmarks,sub(' ',',',bookmarks),if(phabdiff,phabdiff,shortest(node,6)))}") + "List of ways to present versions symbolically. The version +that we use is the first one that successfully produces a +non-empty string. + +Each entry in the list can be either: + +- The symbol `builtin-active-bookmark', which indicates that we +should use the active bookmark if one exists. A template can +supply this information as well, but `builtin-active-bookmark' is +handled entirely inside Emacs and so is more efficient than using +the generic Mercurial mechanism. + +- A string giving the Mercurial template to supply to \"hg +parent\". \"hg help template\" may be useful reading. + +- A function to call; it should accept two arguments (a revision +and an optional path to which to limit history) and produce a +string. The function is called with `default-directory' set to +within the repository. + +If no list entry produces a useful revision, return `nil'." + :type '(repeat (choice + (const :tag "Active bookmark" 'bookmark) + (string :tag "Hg template") + (function :tag "Custom"))) + :version "25.2" + :group 'vc-hg) + +(defcustom vc-hg-use-file-version-for-mode-line-version nil + "When enabled, the modeline will contain revision informtion for the visited file. +When not, the revision in the modeline is for the repository +working copy. `nil' is the much faster setting for +large repositories." + :type 'boolean + :version "25.2" + :group 'vc-hg) + +(defun vc-hg--active-bookmark-internal (rev) + (when (equal rev ".") + (let* ((current-bookmarks-file ".hg/bookmarks.current")) + (when (file-exists-p current-bookmarks-file) + (ignore-errors + (with-temp-buffer + (insert-file-contents current-bookmarks-file) + (buffer-substring-no-properties + (point-min) (point-max)))))))) + +(defun vc-hg--run-log (template rev path) + (ignore-errors + (with-output-to-string + (if path + (vc-hg-command + standard-output 0 nil + "log" "-f" "-l1" "--template" template path) + (vc-hg-command + standard-output 0 nil + "log" "-r" rev "-l1" "--template" template))))) + +(defun vc-hg--symbolic-revision (rev &optional path) + "Make a Mercurial revision human-readable. +REV is a Mercurial revision. `default-directory' is assumed to +be in the repository root of interest. PATH, if set, is a +specific file to query." + (let ((symbolic-revision nil) + (styles vc-hg-symbolic-revision-styles)) + (while (and (not symbolic-revision) styles) + (let ((style (pop styles))) + (setf symbolic-revision + (cond ((and (null path) (eq style 'builtin-active-bookmark)) + (vc-hg--active-bookmark-internal rev)) + ((stringp style) + (vc-hg--run-log style rev path)) + ((functionp style) + (funcall style rev path)))))) + symbolic-revision)) + +(defun vc-hg-mode-line-string (file) + "Hg-specific version of `vc-mode-line-string'." + (let* ((backend-name "Hg") + (truename (file-truename file)) + (state (vc-state truename)) + (state-echo nil) + (face nil) + (rev (and state + (let ((default-directory + (expand-file-name (vc-hg-root truename)))) + (vc-hg--symbolic-revision + "." + (and vc-hg-use-file-version-for-mode-line-version + truename))))) + (rev (or rev "???"))) + (propertize + (cond ((or (eq state 'up-to-date) + (eq state 'needs-update)) + (setq state-echo "Up to date file") + (setq face 'vc-up-to-date-state) + (concat backend-name "-" rev)) + ((eq state 'added) + (setq state-echo "Locally added file") + (setq face 'vc-locally-added-state) + (concat backend-name "@" rev)) + ((eq state 'conflict) + (setq state-echo "File contains conflicts after the last merge") + (setq face 'vc-conflict-state) + (concat backend-name "!" rev)) + ((eq state 'removed) + (setq state-echo "File removed from the VC system") + (setq face 'vc-removed-state) + (concat backend-name "!" rev)) + ((eq state 'missing) + (setq state-echo "File tracked by the VC system, but missing from the file system") + (setq face 'vc-missing-state) + (concat backend-name "?" rev)) + (t + (setq state-echo "Locally modified file") + (setq face 'vc-edited-state) + (concat backend-name ":" rev))) + 'face face + 'help-echo (concat state-echo " under the " backend-name + " version control system")))) + ;;; History functions (defcustom vc-hg-log-switches nil @@ -435,6 +564,488 @@ Optional arg REVISION is a revision to annotate from." ;; TODO: update *vc-change-log* buffer so can see @ if --graph )) +;;; Native data structure reading + +(defcustom vc-hg-parse-hg-data-structures t + "If true, try directly parsing Mercurial data structures +directly instead of always running Mercurial. We try to be safe +against Mercurial data structure format changes and always fall +back to running Mercurial directly." + :type 'boolean + :version "25.2" + :group 'vc-hg) + +(defsubst vc-hg--read-u8 () + "Read and advance over an unsigned byte. +Return a fixnum." + (prog1 (char-after) + (forward-char))) + +(defsubst vc-hg--read-u32-be () + "Read and advance over a big-endian unsigned 32-bit integer. +Return a fixnum; on overflow, result is undefined." + ;; Because elisp bytecode has an instruction for multiply and + ;; doesn't have one for lsh, it's somewhat counter-intuitively + ;; faster to multiply than to shift. + (+ (* (vc-hg--read-u8) (* 256 256 256)) + (* (vc-hg--read-u8) (* 256 256)) + (* (vc-hg--read-u8) 256) + (identity (vc-hg--read-u8)))) + +(defun vc-hg--raw-dirstate-search (dirstate fname) + (with-temp-buffer + (set-buffer-multibyte nil) + (insert-file-contents-literally dirstate) + (let* ((result nil) + (flen (length fname)) + (case-fold-search nil) + (inhibit-changing-match-data t) + ;; Find a conservative bound for the loop below by using + ;; Boyer-Moore on the raw dirstate without parsing it; we + ;; know we can't possibly find fname _after_ the last place + ;; it appears, so we can bail out early if we try to parse + ;; past it, which especially helps when the file we're + ;; trying to find isn't in dirstate at all. There's no way + ;; to similarly bound the starting search position, since + ;; the file format is such that we need to parse it from + ;; the beginning to find record boundaries. + (search-limit + (progn + (goto-char (point-max)) + (or (search-backward fname (+ (point-min) 40) t) + (point-min))))) + ;; 40 is just after the header, which contains the working + ;; directory parents + (goto-char (+ (point-min) 40)) + ;; Iterate over all dirstate entries; we might run this loop + ;; hundreds of thousands of times, so performance is important + ;; here + (while (< (point) search-limit) + ;; 1+4*4 is the length of the dirstate item header, which we + ;; spell as a literal for performance, since the elisp + ;; compiler lacks constant propagation + (forward-char (1+ (* 3 4))) + (let ((this-flen (vc-hg--read-u32-be))) + (if (and (or (eq this-flen flen) + (and (> this-flen flen) + (eq (char-after (+ (point) flen)) 0))) + (search-forward fname (+ (point) flen) t)) + (progn + (backward-char (+ flen (1+ (* 4 4)))) + (setf result + (list (vc-hg--read-u8) ; status + (vc-hg--read-u32-be) ; mode + (vc-hg--read-u32-be) ; size (of file) + (vc-hg--read-u32-be) ; mtime + )) + (goto-char (point-max))) + (forward-char this-flen)))) + result))) + +(define-error 'vc-hg-unsupported-syntax "unsupported hgignore syntax") + +(defconst vc-hg--pcre-c-escapes + '((?a . ?\a) + (?b . ?\b) + (?f . ?\f) + (?n . ?\n) + (?r . ?\r) + (?t . ?\t) + (?n . ?\n) + (?r . ?\r) + (?t . ?\t) + (?v . ?\v))) + +(defconst vc-hg--pcre-metacharacters + '(?. ?^ ?$ ?* ?+ ?? ?{ ?\\ ?\[ ?\| ?\()) + +(defconst vc-hg--elisp-metacharacters + '(?. ?* ?+ ?? ?\[ ?$ ?\\)) + +(defun vc-hg--escape-for-pcre (c) + (if (memq c vc-hg--pcre-metacharacters) + (string ?\\ c) + c)) + +(defun vc-hg--parts-to-string (parts) + "Build a string from list PARTS. Each element is a character or string." + (let ((parts2 nil)) + (while parts + (let* ((partcell (prog1 parts (setf parts (cdr parts)))) + (part (car partcell))) + (if (stringp part) + (setf parts2 (nconc (append part nil) parts2)) + (setcdr partcell parts2) + (setf parts2 partcell)))) + (apply #'string parts2))) + +(defun vc-hg--pcre-to-elisp-re (pcre prefix) + "Transform PCRE, a Mercurial file PCRE, into an elisp RE against PREFIX. +PREFIX is the directory name of the directory against which these +patterns are rooted. We understand only a subset of PCRE syntax; +if we don't understand a construct, we signal +`vc-hg-unsupported-syntax'." + (cl-assert (string-match "^/\\(.*/\\)?$" prefix)) + (let ((parts nil) + (i 0) + (anchored nil) + (state 'normal) + (pcrelen (length pcre))) + (while (< i pcrelen) + (let ((c (aref pcre i))) + (cond ((eq state 'normal) + (cond ((string-match + (rx (| "}\\?" (: "(?" (not (any ":"))))) + pcre i) + (signal 'vc-hg-unsupported-syntax (list pcre))) + ((eq c ?\\) + (setf state 'backslash)) + ((eq c ?\[) + (setf state 'charclass-enter) + (push c parts)) + ((eq c ?^) + (if (eq i 0) (setf anchored t) + (signal 'vc-hg-unsupported-syntax (list pcre)))) + ((eq c ?$) + ;; Patterns can also match directories exactly, + ;; ignoring everything under a matched directory + (push "\\(?:$\\|/\\)" parts)) + ((memq c '(?| ?\( ?\))) + (push ?\\ parts) + (push c parts)) + (t (push c parts)))) + ((eq state 'backslash) + (cond ((memq c '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 + ?A ?b ?B ?d ?D ?s ?S ?w ?W ?Z ?x)) + (signal 'vc-hg-unsupported-syntax (list pcre))) + ((memq c vc-hg--elisp-metacharacters) + (push ?\\ parts) + (push c parts)) + (t (push (or (cdr (assq c vc-hg--pcre-c-escapes)) c) parts))) + (setf state 'normal)) + ((eq state 'charclass-enter) + (push c parts) + (setf state + (if (eq c ?\\) + 'charclass + 'charclass-backslash))) + ((eq state 'charclass-backslash) + (if (memq c '(?0 ?x)) + (signal 'vc-hg-unsupported-syntax (list pcre))) + (push (or (cdr (assq c vc-hg--pcre-c-escapes)) c) parts) + (setf state 'charclass)) + ((eq state 'charclass) + (push c parts) + (cond ((eq c ?\\) (setf state 'charclass-backslash)) + ((eq c ?\]) (setf state 'normal)))) + (t (error "invalid state"))) + (setf i (1+ i)))) + (unless (eq state 'normal) + (signal 'vc-hg-unsupported-syntax (list pcre))) + (concat + "^" + prefix + (if anchored "" "\\(?:.*/\\)?") + (vc-hg--parts-to-string parts)))) + +(defun vc-hg--glob-to-pcre (glob) + "Transform a glob pattern into a Mercurial file pattern regex." + (let ((parts nil) (i 0) (n (length glob)) (group 0) c) + (cl-macrolet ((peek () '(and (< i n) (aref glob i)))) + (while (< i n) + (setf c (aref glob i)) + (cl-incf i) + (cond ((not (memq c '(?* ?? ?\[ ?\{ ?\} ?, ?\\))) + (push (vc-hg--escape-for-pcre c) parts)) + ((eq c ?*) + (cond ((eq (peek) ?*) + (cl-incf i) + (cond ((eq (peek) ?/) + (cl-incf i) + (push "(?:.*/)?" parts)) + (t + (push ".*" parts)))) + (t (push "[^/]*" parts)))) + ((eq c ??) + (push ?. parts)) + ((eq c ?\[) + (let ((j i)) + (when (and (< j n) (memq (aref glob j) '(?! ?\]))) + (cl-incf j)) + (while (and (< j n) (not (eq (aref glob j) ?\]))) + (cl-incf j)) + (cond ((>= j n) + (push "\\[" parts)) + (t + (let ((x (substring glob i j))) + (setf x (replace-regexp-in-string + "\\\\" "\\\\" x t t)) + (setf i (1+ j)) + (cond ((eq (aref x 0) ?!) + (setf (aref x 0) ?^)) + ((eq (aref x 0) ?^) + (setf x (concat "\\" x)))) + (push ?\[ parts) + (push x parts) + (push ?\] parts)))))) + ((eq c ?\{) + (cl-incf group) + (push "(?:" parts)) + ((eq c ?\}) + (push ?\) parts) + (cl-decf group)) + ((and (eq c ?,) (> group 0)) + (push ?| parts)) + ((eq c ?\\) + (if (eq i n) + (push "\\\\" parts) + (cl-incf i) + (push ?\\ parts) + (push c parts))) + (t + (push (vc-hg--escape-for-pcre c) parts))))) + (concat (vc-hg--parts-to-string parts) "$"))) + +(defvar vc-hg--hgignore-patterns) +(defvar vc-hg--hgignore-filenames) + +(defun vc-hg--hgignore-add-pcre (pcre prefix) + (push (vc-hg--pcre-to-elisp-re pcre prefix) vc-hg--hgignore-patterns)) + +(defun vc-hg--hgignore-add-glob (glob prefix) + (push (vc-hg--pcre-to-elisp-re (vc-hg--glob-to-pcre glob) prefix) + vc-hg--hgignore-patterns)) + +(defun vc-hg--hgignore-add-path (path prefix) + (let ((parts nil)) + (dotimes (i (length path)) + (push (vc-hg--escape-for-pcre (aref path i)) parts)) + (vc-hg--hgignore-add-pcre + (concat "^" (vc-hg--parts-to-string parts) "$") + prefix))) + +(defun vc-hg--slurp-hgignore-1 (hgignore prefix) + (let ((default-syntax 'vc-hg--hgignore-add-glob)) + (with-temp-buffer + (let ((attr (file-attributes hgignore))) + (when attr (insert-file-contents hgignore)) + (push (list hgignore (nth 5 attr) (nth 7 attr)) + vc-hg--hgignore-filenames)) + (while (not (eobp)) + ;; This list of pattern-file commands isn't complete, but it + ;; should cover the common cases. Remember that we fall back + ;; to regular hg commands if we see something we don't like. + (save-restriction + (narrow-to-region (point) (point-at-eol)) + (cond ((looking-at "[ \t]*\\(?:#.*\\)?$")) + ((looking-at "syntax:[ \t]*re[ \t]*$") + (setf default-syntax 'vc-hg--hgignore-add-pcre)) + ((looking-at "syntax:[ \t]*glob[ \t]*$") + (setf default-syntax 'vc-hg--hgignore-add-glob)) + ((looking-at "path:\\(.+?\\)[ \t]*$") + (vc-hg--hgignore-add-path (match-string 1) prefix)) + ((looking-at "glob:\\(.+?\\)[ \t]*$") + (vc-hg--hgignore-add-glob (match-string 1) prefix)) + ((looking-at "re:\\(.+?\\)[ \t]*$") + (vc-hg--hgignore-add-pcre (match-string 1) prefix)) + ((looking-at "\\(sub\\)?include:\\(.+?\\)[ \t]*$") + (let* ((sub (equal (match-string 1) "sub")) + (arg (match-string 2)) + (included-file + (if (string-match "^/" arg) arg + (concat (file-name-directory hgignore) arg)))) + (vc-hg--slurp-hgignore-1 + included-file + (if sub (file-name-directory included-file) prefix)))) + ((looking-at "[a-zA-Z0-9_]*:") + (signal 'vc-hg-unsupported-syntax (list (match-string 0)))) + ((looking-at ".*$") + (funcall default-syntax (match-string 0) prefix)))) + (forward-line 1))))) + +(cl-defstruct (vc-hg--ignore-patterns + (:copier nil) + (:constructor vc-hg--ignore-patterns-make)) + repo + ignore-patterns + file-sources) + +(defun vc-hg--slurp-hgignore (repo) + "Read hg ignore patterns from REPO. +REPO must be the directory name of an hg repository." + (cl-assert (string-match "^/\\(.*/\\)?$" repo)) + (let* ((hgignore (concat repo ".hgignore")) + (vc-hg--hgignore-patterns nil) + (vc-hg--hgignore-filenames nil)) + (vc-hg--slurp-hgignore-1 hgignore repo) + (vc-hg--ignore-patterns-make + :repo repo + :ignore-patterns (nreverse vc-hg--hgignore-patterns) + :file-sources (nreverse vc-hg--hgignore-filenames)))) + +(defun vc-hg--ignore-patterns-valid-p (hgip) + "Return whether the cached ignore patterns in HGIP are still valid" + (let ((valid t) + (file-sources (vc-hg--ignore-patterns-file-sources hgip))) + (while (and file-sources valid) + (let* ((fs (pop file-sources)) + (saved-mtime (nth 1 fs)) + (saved-size (nth 2 fs)) + (attr (file-attributes (nth 0 fs))) + (current-mtime (nth 5 attr)) + (current-size (nth 7 attr))) + (unless (and (equal saved-mtime current-mtime) + (equal saved-size current-size)) + (setf valid nil)))) + valid)) + +(defun vc-hg--ignore-patterns-ignored-p (hgip filename) + "Test whether the ignore pattern set HGIP says to ignore FILENAME. +FILENAME must be the file's true absolute name." + (let ((patterns (vc-hg--ignore-patterns-ignore-patterns hgip)) + (inhibit-changing-match-data t) + (ignored nil)) + (while (and patterns (not ignored)) + (setf ignored (string-match (pop patterns) filename))) + ignored)) + +(defun vc-hg--time-to-fixnum (ts) + (+ (* 65536 (car ts)) (cadr ts))) + +(defvar vc-hg--cached-ignore-patterns nil + "Cached pre-parsed hg ignore patterns.") + +(defun vc-hg--file-ignored-p (repo repo-relative-filename) + (let ((hgip vc-hg--cached-ignore-patterns)) + (unless (and hgip + (equal repo (vc-hg--ignore-patterns-repo hgip)) + (vc-hg--ignore-patterns-valid-p hgip)) + (setf vc-hg--cached-ignore-patterns nil) + (setf hgip (vc-hg--slurp-hgignore repo)) + (setf vc-hg--cached-ignore-patterns hgip)) + (vc-hg--ignore-patterns-ignored-p + hgip + (concat repo repo-relative-filename)))) + +(defun vc-hg--read-repo-requirements (repo) + (cl-assert (string-match "^/\\(.*/\\)?$" repo)) + (let* ((requires-filename (concat repo ".hg/requires"))) + (and (file-exists-p requires-filename) + (with-temp-buffer + (set-buffer-multibyte nil) + (insert-file-contents-literally requires-filename) + (split-string (buffer-substring-no-properties + (point-min) (point-max))))))) + +(defconst vc-hg-supported-requirements + '("dotencode" + "fncache" + "generaldelta" + "lz4revlog" + "remotefilelog" + "revlogv1" + "store") + "List of Mercurial repository requirements we understand; if a +repository requires features not present in this list, we avoid +attempting to parse Mercurial data structures.") + +(defun vc-hg--requirements-understood-p (repo) + "Check that we understand the format of the given repository. +REPO is the directory name of a Mercurial repository." + (null (cl-set-difference (vc-hg--read-repo-requirements repo) + vc-hg-supported-requirements + :test #'equal))) + +(defvar vc-hg--dirstate-scan-cache nil + "Cache of the last result of `vc-hg--raw-dirstate-search'. +Avoids the need to repeatedly scan dirstate on repeated calls to +`vc-hg-state', as we see during registration queries.") + +(defun vc-hg--cached-dirstate-search (dirstate dirstate-attr ascii-fname) + (let* ((mtime (nth 5 dirstate-attr)) + (size (nth 7 dirstate-attr)) + (cache vc-hg--dirstate-scan-cache) + ) + (if (and cache + (equal dirstate (pop cache)) + (equal mtime (pop cache)) + (equal size (pop cache)) + (equal ascii-fname (pop cache))) + (pop cache) + (let ((result (vc-hg--raw-dirstate-search dirstate ascii-fname))) + (setf vc-hg--dirstate-scan-cache + (list dirstate mtime size ascii-fname result)) + result)))) + +(defun vc-hg-state-fast (filename) + "Like `vc-hg-state', but parse internal data structures directly. +Returns one of the usual `vc-state' enumeration values or +`unsupported' if we need to take the slow path and run the +hg binary." + (let* (truename + repo + dirstate + dirstate-attr + repo-relative-filename + ascii-fname) + (if (or + ;; Explicit user disable + (not vc-hg-parse-hg-data-structures) + ;; It'll probably be faster to run hg remotely + (file-remote-p filename) + (progn + (setf truename (file-truename filename)) + (file-remote-p truename)) + (not (setf repo (vc-hg-root truename))) + ;; dirstate must exist + (not (progn + (setf repo (expand-file-name repo)) + (cl-assert (string-match "^/\\(.*/\\)?$" repo)) + (setf dirstate (concat repo ".hg/dirstate")) + (setf dirstate-attr (file-attributes dirstate)))) + ;; Repository must be in an understood format + (not (vc-hg--requirements-understood-p repo)) + ;; Dirstate too small to be valid + (< (nth 7 dirstate-attr) 40) + ;; We want to store 32-bit unsigned values in fixnums + (< most-positive-fixnum 4294967295) + (progn + (setf repo-relative-filename + (file-relative-name truename repo)) + (setf ascii-fname + (string-as-unibyte + (let (last-coding-system-used) + (encode-coding-string + repo-relative-filename + 'us-ascii t)))) + ;; We only try dealing with ASCII filenames + (not (equal ascii-fname repo-relative-filename)))) + 'unsupported + (let* ((dirstate-entry + (vc-hg--cached-dirstate-search + dirstate dirstate-attr ascii-fname)) + (state (car dirstate-entry)) + (stat (file-attributes + (concat repo repo-relative-filename)))) + (cond ((eq state ?r) 'removed) + ((and (not state) stat) + (condition-case nil + (if (vc-hg--file-ignored-p repo repo-relative-filename) + 'ignored + 'unregistered) + (vc-hg-unsupported-syntax 'unsupported))) + ((and state (not stat)) 'missing) + ((eq state ?n) + (let ((vc-hg-size (nth 2 dirstate-entry)) + (vc-hg-mtime (nth 3 dirstate-entry)) + (fs-size (nth 7 stat)) + (fs-mtime (vc-hg--time-to-fixnum (nth 5 stat)))) + (if (and (eql vc-hg-size fs-size) (eql vc-hg-mtime fs-mtime)) + 'up-to-date + 'edited))) + ((eq state ?a) 'added) + (state 'unsupported)))))) + ;;; Miscellaneous (defun vc-hg-previous-revision (_file rev) diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el index 2be46c5..0c1718e 100644 --- a/lisp/vc/vc-hooks.el +++ b/lisp/vc/vc-hooks.el @@ -807,15 +807,15 @@ In the latter case, VC mode is deactivated for this buffer." (add-hook 'vc-mode-line-hook 'vc-mode-line nil t) (let (backend) (cond - ((setq backend (with-demoted-errors (vc-backend buffer-file-name))) + ((setq backend (with-demoted-errors (vc-backend buffer-file-name))) + ;; Let the backend setup any buffer-local things he needs. + (vc-call-backend backend 'find-file-hook) ;; Compute the state and put it in the mode line. (vc-mode-line buffer-file-name backend) (unless vc-make-backup-files ;; Use this variable, not make-backup-files, ;; because this is for things that depend on the file name. - (set (make-local-variable 'backup-inhibited) t)) - ;; Let the backend setup any buffer-local things he needs. - (vc-call-backend backend 'find-file-hook)) + (set (make-local-variable 'backup-inhibited) t))) ((let* ((truename (and buffer-file-truename (expand-file-name buffer-file-truename))) (link-type (and truename commit 4c629d8a8d640354690ce207dff09c7fda070d2a Author: Glenn Morris Date: Mon Feb 8 08:48:47 2016 -0800 ; ChangeLog fixes. diff --git a/ChangeLog.2 b/ChangeLog.2 index 58284d0..5efa1ab 100644 --- a/ChangeLog.2 +++ b/ChangeLog.2 @@ -1,44 +1,34 @@ 2016-02-06 Lars Ingebrigtsen - message-valid-fqdn-regexp no longer exists - * lisp/gnus/gnus-art.el (gnus-button-valid-fqdn-regexp): Don't use the no-longer-existing message-valid-fqdn-regexp variable. 2016-02-06 Lars Ingebrigtsen Remove message-valid-fqdn-regexp, since it changes too much now - * lisp/gnus/message.el (message-valid-fqdn-regexp): Remove. (message-bogus-recipient-p): Don't use it any more. (message-make-fqdn): Ditto. Suggested by Lars-Johan Liman. -2016-02-06 Paul van der Walt - - Match "Re :" as a "Re:" prefix +2016-02-06 Paul van der Walt (tiny change) * lisp/gnus/message.el (message-subject-re-regexp): Also match "Re :" as a "Re:" prefix (commonly used in France). 2016-02-06 Adam Sjøgren - lisp/net/shr.el (shr-tag-del, shr-tag-ins): New functions. - * lisp/net/shr.el (shr-tag-del, shr-tag-ins): New functions. 2016-02-06 David Edmondson src/process.c Correctly convert AF_INET6 addresses - * src/process.c (conv_lisp_to_sockaddr): AF_INET6 addresses are converted to a list of 16 bit quantities by - conv_sockaddr_to_lisp(). conv_lisp_to_sockaddr() should follow the + conv_sockaddr_to_lisp(). conv_lisp_to_sockaddr() should follow the same scheme rather than expecting a (longer) list of 8 bit quantities. -2016-02-06 Martin Jesper Low Madsen - - Search for host/port combinations in auth-source on OS X +2016-02-06 Martin Jesper Low Madsen (tiny change) * lisp/gnus/auth-source.el (auth-source-macos-keychain-search): Search for all host/port (or protocol) combinations for a match in commit 5825f42e7a2ed27610f83234038fcf91ec44222e Author: Glenn Morris Date: Mon Feb 8 08:43:52 2016 -0800 ; Some standardization of copyright and license notices in recent new files diff --git a/test/lisp/net/network-stream-tests.el b/test/lisp/net/network-stream-tests.el index ad7c1fc..863064d 100644 --- a/test/lisp/net/network-stream-tests.el +++ b/test/lisp/net/network-stream-tests.el @@ -4,6 +4,8 @@ ;; Author: Lars Ingebrigtsen +;; This file is part of GNU Emacs. + ;; GNU Emacs 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 diff --git a/test/lisp/url/url-auth-tests.el b/test/lisp/url/url-auth-tests.el index 36c177f..e767b05 100644 --- a/test/lisp/url/url-auth-tests.el +++ b/test/lisp/url/url-auth-tests.el @@ -1,21 +1,23 @@ ;;; url-auth-tests.el --- Test suite for url-auth. -;; Copyright (C) 2015 Free Software Foundation, Inc. +;; Copyright (C) 2015-2016 Free Software Foundation, Inc. ;; Author: Jarno Malmari -;; This program is free software; you can redistribute it and/or modify +;; This file is part of GNU Emacs. + +;; GNU Emacs 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. -;; This program is distributed in the hope that it will be useful, +;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: