On Fri, 15 Oct 1999, Jeffrey Juliano <[EMAIL PROTECTED]> wrote:
> ... thanks ... this email is kind of long.
It's also informative which is useful. :)
> I did a little poking in fileio.c and did some testes. I describe as
> far as I got, including an excerpt of fileio.c that may be part of the
> problem, and my test showing why I think so.
>
> I think I've uncovered either a bug in NTemacs, or a bug in rcp.el's
> assumptions. I prefer to believe it's a bug in NTemacs.
I suspect that some of the built in handling is, well, wrong. In fact, I
think that it's partly the problem of rcp, or rather, that efs and
ange-ftp have support in the C while RCP does not. :/
> Daniel Pittman wrote:
>>
>> Well, I can't speak for GNU Emacs, but on XEmacs 21.2, the following
>> snippet from 'src/fileio.c' might have the answer to why RCP paths
>> don't work quite right...
[...]
>> It looks like the /r: syntax is interpreted as a drive letter rather
>> than as a path by 'expand-file-name' - something that is called by
>> most of the file handling code...
>
> well, if I change rcp.el to instead expect /rf: as the prefix, it
> still fails in the same way. so does /rf@scp: prefix.
Darn. That's my quota of clever ideas, mostly. Well, almost.
> ----------------------------------------
>
> for those that don't know, NT allows paths like the following
>
> c:\foo ; standared for NT, emacs accepts
> c:/foo ; emacs also accepts this
> //machine_name/foo ; standard for NT, emacs accepts
> \\machine_name\foo ; emacs also accepts this
>
> and, it appears, some other form I'm not familiar with.
As Kai points out, NTFS file systems also allow streams with the syntax
'file:stream' where '$DATA' is the default stream (which gets written
when you open 'file' and anything else you choose to write is legal...
> The way the strings are parsed in fileio.c doesn't look very robust to
> extra colons in the string. They are parsed from right-to-left,
> looking for colon or slash characters. I don't know the utility
> functions well enough to figure out what happens with rcp-type
> filenames, but there is a potential for the string to get broken up
> incorrectly.
Mmmm. It seems that even of my XEmacs on Linux there is a bit of lossage
with regards to rcp filenames. Results below.
> so, I did a little test.
>
> (setq f "/r@scp:juliano@capefear:.emacs")
> "/r@scp:juliano@capefear:.emacs"
>
> (file-name-directory f) ; why is "scp:" both here
> "/r@scp:"
I get "/", which is just plain *wrong*
> (file-name-nondirectory f) ; and here?
> "r@scp:juliano@capefear:.emacs"
I get the same, again just wrong.
> (expand-file-name f)
> ;; when rcp.el not loaded, ange-ftp asks for password
> ;; when rcp.el loaded, ssh seg faults
This is expected, except the segfault part. That one, I don't know
about. Can you run an inferior SSH normally?
[... expected NT behavior ...]
> Not sure exactly why "r@scp:" is in both directory and non-directory,
> but I believe it after looking at fileio.c. Is this a bug in NT emacs,
> or incorrect use of file-name-(non)directory? what do you get with
> xemacs?
It gets it wrong. I think, sadly, that the C code for
'file-name-directory' and 'file-name-nondirectory' tries to kludge in
support for efs or ange-ftp, which is not the right thing(tm) to do.
Even on XEmacs, it gets it wrong for rcp paths. Time to handle those two
in Lisp, I fear. :/
The attached patch does so, workably according to my (crude) testing.
Please try it and see if it helps you at all.
The patch includes updates to the texi documentation which may not apply
cleanly. That does not matter, honest. :)
diff -ubNr --exclude=*~ --exclude=*.info --exclude=dir /home/daniel/.xemacs/rcp.kai/lisp/rcp.el /home/daniel/.xemacs/rcp/lisp/rcp.el
--- /home/daniel/.xemacs/rcp.kai/lisp/rcp.el Wed Oct 13 21:28:30 1999
+++ /home/daniel/.xemacs/rcp/lisp/rcp.el Sat Oct 16 10:27:21 1999
@@ -710,7 +710,9 @@
;; file-name-directory, file-name-nondirectory,
;; file-name-sans-versions, get-file-buffer.
(defconst rcp-file-name-handler-alist
- '((file-exists-p . rcp-handle-file-exists-p)
+ '((file-name-directory . rcp-handle-file-name-directory)
+ (file-name-nondirectory . rcp-handle-file-name-nondirectory)
+ (file-exists-p . rcp-handle-file-exists-p)
(file-directory-p . rcp-handle-file-directory-p)
(file-executable-p . rcp-handle-file-executable-p)
(file-accessible-directory-p . rcp-handle-file-accessible-directory-p)
@@ -764,6 +766,28 @@
;;; File Name Handler Functions:
+;; Path manipulation functions that grok RCP paths...
+(defun rcp-handle-file-name-directory (file)
+ "Like 'file-name-directory' but aware of RCP files."
+ ;; everything except the last filename thing is the directory
+ (let* ((v (rcp-dissect-file-name file))
+ (method (rcp-file-name-method v))
+ (user (rcp-file-name-user v))
+ (host (rcp-file-name-host v))
+ (path (rcp-file-name-path v)))
+ ;; run the command on the path portion only
+ ;; REVISIT: This should take into account the remote machine type, no?
+ ;; --daniel <[EMAIL PROTECTED]>
+ (rcp-make-rcp-file-name method host user
+ ;; This should not recurse...
+ (file-name-directory path))))
+
+(defun rcp-handle-file-name-nondirectory (file)
+ "Like 'file-name-nondirectory' but aware of RCP files."
+ (let ((v (rcp-dissect-file-name file)))
+ (file-name-nondirectory (rcp-file-name-path v))))
+
+
;; Basic functions.
(defun rcp-handle-file-exists-p (filename)
@@ -894,8 +918,8 @@
;; Existing files must be writable.
(zerop (rcp-run-test "-w" filename))
;; If file doesn't exist, check if directory is writable.
- (and (zerop (rcp-run-test "-d" (file-name-directory filename)))
- (zerop (rcp-run-test "-w" (file-name-directory filename))))))
+ (and (zerop (rcp-run-test "-d" (rcp-handle-file-name-directory filename)))
+ (zerop (rcp-run-test "-w" (rcp-handle-file-name-directory filename))))))
;; Other file name ops.
@@ -2277,7 +2317,7 @@
(rcp-pre-connection method user host)
(let* ((pw (rcp-read-passwd
(format "%s -l %s %s -- password: "
- (file-name-nondirectory (rcp-get-rlogin-program method))
+ (rcp-handle-file-name-nondirectory (rcp-get-rlogin-program method))
user host)))
(p (start-process (rcp-buffer-name method user host)
(rcp-get-buffer method user host)
diff -ubNr --exclude=*~ --exclude=*.info --exclude=dir /home/daniel/.xemacs/rcp.kai/texi/rcp.texi /home/daniel/.xemacs/rcp/texi/rcp.texi
--- /home/daniel/.xemacs/rcp.kai/texi/rcp.texi Mon Oct 11 06:06:32 1999
+++ /home/daniel/.xemacs/rcp/texi/rcp.texi Sat Oct 16 10:29:31 1999
@@ -9,17 +9,23 @@
@c NOTE: The 'UPDATED' value is updated by the 'time-stamp' function.
@c If you change it by hand, the modifications will not stay.
@set VERSION 1.155
-@set UPDATED Sunday, 10 October, 1999
+@set UPDATED Saturday, 16 October, 1999
@c Entries for @command{install-info} to use
@direntry
* RCP: (rcp). Emacs remote file access via rsh and rcp.
@end direntry
+@c Macro to make formatting of the rcp program name consistent.
+@macro rcp
+@sc{rcp}
+@end macro
+
@c Copying permissions, et al
@ifinfo
-This file documents RCP, a remote file editing package for Emacs.
+This file documents @rcp{}, a remote file editing package for
+Emacs and XEmacs.
Copyright @copyright{} 1999 Free Software Foundation, Inc.
@@ -86,25 +92,29 @@
This package provides remote file editing, similar to @cite{ange-ftp}.
The difference is that ange-ftp uses FTP to transfer files between the
-local and the remote host, whereas RCP uses a combination of rsh and rcp
-or other work-alike programs, such as ssh/scp.
+local and the remote host, whereas @rcp{} uses a combination of
+@command{rsh} and @command{rcp} or other work-alike programs, such as
+@command{ssh}/@command{scp}.
+
+This manual is for version @value{VERSION} of @rcp{}.
-This manual is for version @value{VERSION} of RCP.
It was last updated on @value{UPDATED}.
@end ifnottex
@menu
-* Copying:: RCP Copying conditions.
-* Overview:: What RCP can and cannot do.
+* Copying:: @rcp{} Copying conditions.
+* Overview:: What @rcp{} can and cannot do.
For the end user:
-* Installation:: Installing RCP with your (X)Emacs.
-* Usage:: An overview of the operation of RCP.
-* Configuration:: How to customize your RCP setup.
+* Installation:: Installing @rcp{} with your (X)Emacs.
+* Usage:: An overview of the operation of @rcp{}.
+* Configuration:: How to customize your @rcp{} setup.
For the developer:
* Version Control:: The inner workings of remote version control.
+* Files directories and paths:: How file names, directories and paths are mangled and managed.
+* Performance:: Caching and other performance boosters.
@end menu
@@ -132,8 +142,8 @@
@node Overview
@chapter An overview of RCP
-When RCP has been installed into your Emacs, you will be able to
-transparently access files on remote machines accessible to you.
+When @rcp{} has been installed into your Emacs, you will be able
+to transparently access files on remote machines accessible to you.
This access is achieved through a number of methods, grouped into two
types:
@@ -180,7 +190,7 @@
Usage is also simple: it's just like ange-ftp, but uses a different
syntax for the remote file names. The syntax used is as follows:
-@code{/@@METHOD:USER@@HOST:FILENAME}
+@code{/r@@METHOD:USER@@HOST:FILENAME}
This logs you in as USER to the remote HOST using METHOD, retrieving
FILENAME. The "USER@@" part can be omitted, in this case the current
@@ -190,7 +200,7 @@
@node Configuration
-@chapter Customizing RCP to work with your system
+@chapter Customizing @rcp{} to work with your system
See the rcp.el file for documentation on this.
@@ -212,17 +222,11 @@
Work is ongoing to improve the transparency of the system.
@menu
-* Version Controlled Files:: Determining if a file is under version
- control.
-* Remote Commands:: Executing the version control commands
- on the remote machine.
-* Changed workfiles:: Detecting if the working file has
- changed.
-* Checking out files:: Bringing the workfile out of the
- repository.
-
-* Miscellaneous Version Control:: Things related to Version Control
- that don't fit elsewhere
+* Version Controlled Files:: Determining if a file is under version control.
+* Remote Commands:: Executing the version control commands on the remote machine.
+* Changed workfiles:: Detecting if the working file has changed.
+* Checking out files:: Bringing the workfile out of the repository.
+* Miscellaneous Version Control:: Things related to Version Control that don't fit elsewhere
@end menu
@@ -285,16 +289,18 @@
@menu
* Remote File Ownership:: How VC determines who owns a workfile.
+* Back-end Versions:: How VC determines what release your RCS is.
@end menu
@node Remote File Ownership
@subsection How VC determines who owns a workfile
-Emacs provides the @code{user-full-name} function to return the login name
-of the current user as well as mapping from arbitrary user id values
-back to login names. The VC code uses this functionality to map from the
-uid of the owner of a workfile to the login name in some circumstances.
+Emacs provides the @code{user-full-name} function to return the login
+name of the current user as well as mapping from arbitrary user id
+values back to login names. The VC code uses this functionality to map
+from the uid of the owner of a workfile to the login name in some
+circumstances.
This will not, for obvious reasons, work if the remote system has a
different set of logins. As such, it is necessary to delegate to the
@@ -313,6 +319,71 @@
remote machine to determine the login name, delegating the problem of
mapping the uid to the login to the remote system which should know more
about it than I do.
+
+
+@node Back-end Versions
+@subsection How VC determines what release your RCS is
+
+VC needs to know what release your revision control binaries you are
+running as not all features VC supports are available with older
+versions of @command{rcs(1)}, @command{cvs(1)} or @command{sccs(1)}.
+
+The default implementation of VC determines this value the first time it
+is needed and then stores the value globally to avoid the overhead of
+executing a process and parsing it's output each time the information is
+needed.
+
+Unfortunately, life is not quite so easy when remote version control
+comes into the picture. Each remote machine may have a different version
+of the version control tools and, while this is painful, we need to
+ensure that unavailable features are not used remotely.
+
+To resolve this issue, @rcp{} currently takes the sledgehammer
+approach of making the release values of the revision control tools
+local to each @rcp{} buffer, forcing VC to determine these values
+again each time a new file is visited.
+
+This has, quite obviously, some performance implications. Thankfully,
+most of the common operations performed by VC do not actually require
+that the remote version be known. This makes the problem far less
+apparent.
+
+Eventually these values will be captured by @rcp{} on a system by
+system basis and the results cached to improve performance.
+
+
+@node Files directories and paths
+@chapter How file names, directories and paths are mangled and managed.
+
+@menu
+* Path deconstruction:: Breaking a path into it's components.
+@end menu
+
+
+@node Path deconstruction
+@section Breaking a path into it's components.
+
+@rcp{} filenames are somewhat different, obviously, to ordinary path
+names. As such, the lisp functions @code{file-name-directory} and
+@code{file-name-nondirectory} are overridden within the @rcp{} package.
+
+Their replacements are reasonably simplistic in their approach. They
+dissect the filename, call the original handler on the remote path and
+then rebuild the @rcp{} path with the result.
+
+This allows the platform specific hacks in the original handlers to take
+effect while preserving the @rcp{} path information.
+
+
+@node Performance
+@chapter Caching and other performance boosters
+
+Remote file editing is, by it's nature, considerably slower than local
+file editing. This is primarily caused by the high latency of accessing
+the remote resources---files and file information.
+
+To improve the performance of the @rcp{} code, local caching of
+information can be used to trade away local storage space for time.
Daniel
--
To be nobody-but-yourself -- in a world which is doing its best night and day,
to make you everybody else -- means to fight the hardest battle which any
human being can fight; and never stop fighting.
-- e.e. cummings