;;; shadowfile.el --- automatic file copying
-;; Copyright (C) 1993, 1994, 2001, 2002, 2003, 2004,
-;; 2005, 2006, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2011 Free Software Foundation, Inc.
;; Author: Boris Goldowsky <boris@gnu.org>
;; Keywords: comm files
;; This file is part of GNU Emacs.
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; 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, or (at your option)
-;; any later version.
+;; 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
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
:group 'files)
(defcustom shadow-noquery nil
- "*If t, always copy shadow files without asking.
-If nil \(the default), always ask. If not nil and not t, ask only if there
+ "If t, always copy shadow files without asking.
+If nil (the default), always ask. If not nil and not t, ask only if there
is no buffer currently visiting the file."
:type '(choice (const t) (const nil) (other :tag "Ask if no buffer" maybe))
:group 'shadow)
(defcustom shadow-inhibit-message nil
- "*If non-nil, do not display a message when a file needs copying."
+ "If non-nil, do not display a message when a file needs copying."
:type 'boolean
:group 'shadow)
(defcustom shadow-inhibit-overload nil
"If non-nil, shadowfile won't redefine \\[save-buffers-kill-emacs].
-Normally it overloads the function `save-buffers-kill-emacs' to check
-for files have been changed and need to be copied to other systems."
+Normally it overloads the function `save-buffers-kill-emacs' to check for
+files that have been changed and need to be copied to other systems."
:type 'boolean
:group 'shadow)
;;; The following two variables should in most cases initialize themselves
;;; correctly. They are provided as variables in case the defaults are wrong
-;;; on your machine \(and for efficiency).
+;;; on your machine (and for efficiency).
(defvar shadow-system-name (system-name)
"The complete hostname of this machine.")
;;;
(defvar shadow-clusters nil
- "List of host clusters \(see `shadow-define-cluster').")
+ "List of host clusters (see `shadow-define-cluster').")
(defvar shadow-literal-groups nil
"List of files that are shared between hosts.
;;; SITES
(defun shadow-site-cluster (site)
- "Given a SITE \(hostname or cluster name), return cluster it is in, or nil."
+ "Given a SITE (hostname or cluster name), return cluster it is in, or nil."
(or (assoc site shadow-clusters)
(shadow-find
(function (lambda (x)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun shadow-parse-fullname (fullname)
- "Parse FULLNAME into \(site user path) list.
-Leave it alone if it already is one. Returns nil if the argument is
+ "Parse FULLNAME into (site user path) list.
+Leave it alone if it already is one. Return nil if the argument is
not a full ange-ftp pathname."
(if (listp fullname)
fullname
(ange-ftp-ftp-name fullname)))
(defun shadow-parse-name (name)
- "Parse any NAME into \(site user name) list.
+ "Parse any NAME into (site user name) list.
Argument can be a simple name, full ange-ftp name, or already a hup list."
(or (shadow-parse-fullname name)
(list shadow-system-name
(defun shadow-expand-cluster-in-file-name (file)
"If hostname part of FILE is a cluster, expand it to cluster's primary hostname.
Will return the name bare if it is a local file."
- (let ((hup (shadow-parse-name file))
- cluster)
+ (let ((hup (shadow-parse-name file)))
(cond ((null hup) file)
((shadow-local-file hup))
((shadow-make-fullname (shadow-site-primary (nth 0 hup))
"Return t if PATTERN matches FILE.
If REGEXP is supplied and non-nil, the file part of the pattern is a regular
expression, otherwise it must match exactly. The sites and usernames must
-match---see `shadow-same-site'. The pattern must be in full ange-ftp format, but
-the file can be any valid filename. This function does not do any filename
-expansion or contraction, you must do that yourself first."
+match---see `shadow-same-site'. The pattern must be in full ange-ftp format,
+but the file can be any valid filename. This function does not do any
+filename expansion or contraction, you must do that yourself first."
(let* ((pattern-sup (shadow-parse-fullname pattern))
(file-sup (shadow-parse-name file)))
(and (shadow-same-site pattern-sup file-sup)
;;;###autoload
(defun shadow-define-cluster (name)
- "Edit \(or create) the definition of a cluster NAME.
+ "Edit (or create) the definition of a cluster NAME.
This is a group of hosts that share directories, so that copying to or from
one of them is sufficient to update the file on all of them. Clusters are
-defined by a name, the network address of a primary host \(the one we copy
-files to), and a regular expression that matches the hostnames of all the sites
-in the cluster."
+defined by a name, the network address of a primary host (the one we copy
+files to), and a regular expression that matches the hostnames of all the
+sites in the cluster."
(interactive (list (completing-read "Cluster name: " shadow-clusters () ())))
(let* ((old (shadow-get-cluster name))
(primary (read-string "Primary host: "
"Declare a single file to be shared between sites.
It may have different filenames on each site. When this file is edited, the
new version will be copied to each of the other locations. Sites can be
-specific hostnames, or names of clusters \(see `shadow-define-cluster')."
+specific hostnames, or names of clusters (see `shadow-define-cluster')."
(interactive)
(let* ((hup (shadow-parse-fullname
(shadow-contract-file-name (buffer-file-name))))
"Make each of a group of files be shared between hosts.
Prompts for regular expression; files matching this are shared between a list
of sites, which are also prompted for. The filenames must be identical on all
-hosts \(if they aren't, use `shadow-define-literal-group' instead of this function).
-Each site can be either a hostname or the name of a cluster \(see
+hosts (if they aren't, use `shadow-define-literal-group' instead of this
+function). Each site can be either a hostname or the name of a cluster (see
`shadow-define-cluster')."
(interactive)
(let ((regexp (read-string
call it manually."
(interactive "P")
(if (not shadow-files-to-copy)
- (if (interactive-p)
+ (if (called-interactively-p 'interactive)
(message "No files need to be shadowed."))
(save-excursion
(map-y-or-n-p (function
(defun shadow-make-group (regexp sites usernames)
"Make a description of a file group---
-actually a list of regexp ange-ftp file names---from REGEXP \(name of file to
+actually a list of regexp ange-ftp file names---from REGEXP (name of file to
be shadowed), list of SITES, and corresponding list of USERNAMES for each
site."
(if sites
(to (shadow-expand-cluster-in-file-name (cdr s))))
(when buffer
(set-buffer buffer)
- (save-restriction
- (widen)
- (condition-case i
- (progn
- (write-region (point-min) (point-max) to)
- (shadow-remove-from-todo s))
- (error (message "Shadow %s not updated!" (cdr s))))))))
+ (condition-case nil
+ (progn
+ (write-region nil nil to)
+ (shadow-remove-from-todo s))
+ (error (message "Shadow %s not updated!" (cdr s)))))))
(defun shadow-shadows-of (file)
"Return copy operations needed to update FILE.
Filename should have clusters expanded, but otherwise can have any format.
-Return value is a list of dotted pairs like \(from . to), where from
+Return value is a list of dotted pairs like (from . to), where from
and to are absolute file names."
(or (symbol-value (intern-soft file shadow-hashtable))
(let* ((absolute-file (shadow-expand-file-name
(defun shadow-remove-from-todo (pair)
"Remove PAIR from `shadow-files-to-copy'.
-PAIR must be (eq to) one of the elements of that list."
+PAIR must be `eq' to one of the elements of that list."
(setq shadow-files-to-copy
(shadow-remove-if (function (lambda (s) (eq s pair)))
shadow-files-to-copy)))
(defun shadow-read-files ()
"Visit and load `shadow-info-file' and `shadow-todo-file'.
Thus restores shadowfile's state from your last Emacs session.
-Returns t unless files were locked; then returns nil."
+Return t unless files were locked; then return nil."
(interactive)
(if (and (fboundp 'file-locked-p)
(or (stringp (file-locked-p shadow-info-file))
(defun shadow-save-todo-file ()
(if (and shadow-todo-buffer (buffer-modified-p shadow-todo-buffer))
- (save-excursion
- (set-buffer shadow-todo-buffer)
+ (with-current-buffer shadow-todo-buffer
(condition-case nil ; have to continue even in case of
(basic-save-buffer) ; error, otherwise kill-emacs might
(error ; not work!
(setq shadow-hashtable (make-vector 37 0)))
(defun shadow-insert-var (variable)
- "Prettily insert a `setq' command for VARIABLE,
-which, when later evaluated, will restore it to its current setting.
+ "Build a `setq' to restore VARIABLE.
+Prettily insert a `setq' command which, when later evaluated,
+will restore VARIABLE to its current setting.
VARIABLE must be the name of a variable whose value is a list."
(let ((standard-output (current-buffer)))
(insert (format "(setq %s" variable))
(buffer-list))))
(yes-or-no-p "Modified buffers exist; exit anyway? "))
(or (not (fboundp 'process-list))
- ;; process-list is not defined on VMS.
+ ;; process-list is not defined on MSDOS.
(let ((processes (process-list))
active)
(while processes
(file-name-as-directory (shadow-expand-file-name "~"))))
(if (null shadow-info-file)
(setq shadow-info-file
- (shadow-expand-file-name "~/.shadows")))
+ (shadow-expand-file-name (convert-standard-filename "~/.shadows"))))
(if (null shadow-todo-file)
(setq shadow-todo-file
- (shadow-expand-file-name "~/.shadow_todo")))
+ (shadow-expand-file-name
+ (convert-standard-filename "~/.shadow_todo"))))
(if (not (shadow-read-files))
(progn
(message "Shadowfile information files not found - aborting")
(provide 'shadowfile)
-;;; arch-tag: e2f4cdd7-2bab-4def-9130-9e69b412b79e
;;; shadowfile.el ends here