diff options
| author | Ken Brown | 2019-07-15 09:32:49 -0400 |
|---|---|---|
| committer | Ken Brown | 2019-07-21 10:40:54 -0400 |
| commit | 8b13ec1d7022b05ce71982c83f320d5272b92de7 (patch) | |
| tree | 19e21f261d255ca52d9de7fe7e181579cde0c056 /src | |
| parent | 0c48c0d0b241c1f3d089be033a7dea3a9b947ca5 (diff) | |
| download | emacs-8b13ec1d7022b05ce71982c83f320d5272b92de7.tar.gz emacs-8b13ec1d7022b05ce71982c83f320d5272b92de7.zip | |
Fix expand-file-name for names starting with '~'
* src/fileio.c: (file_name_absolute_no_tilde_p):
New static function.
(Fexpand_file_name): If the current buffer's default-directory
starts with "~user" where "user" is not a valid user name, don't
give the '~' a special meaning. Just treat the value of
default-directory as a relative name. (Bug#36502)
* test/src/fileio-tests.el
(fileio-tests--relative-default-directory): Add a test.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fileio.c | 68 |
1 files changed, 44 insertions, 24 deletions
diff --git a/src/fileio.c b/src/fileio.c index 7f83267956c..4c7625cad4a 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -737,6 +737,13 @@ For that reason, you should normally use `make-temp-file' instead. */) | |||
| 737 | empty_unibyte_string, Qnil); | 737 | empty_unibyte_string, Qnil); |
| 738 | } | 738 | } |
| 739 | 739 | ||
| 740 | /* NAME must be a string. */ | ||
| 741 | static bool | ||
| 742 | file_name_absolute_no_tilde_p (Lisp_Object name) | ||
| 743 | { | ||
| 744 | return IS_ABSOLUTE_FILE_NAME (SSDATA (name)); | ||
| 745 | } | ||
| 746 | |||
| 740 | DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, | 747 | DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, |
| 741 | doc: /* Convert filename NAME to absolute, and canonicalize it. | 748 | doc: /* Convert filename NAME to absolute, and canonicalize it. |
| 742 | Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative | 749 | Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative |
| @@ -807,41 +814,54 @@ the root directory. */) | |||
| 807 | error ("Invalid handler in `file-name-handler-alist'"); | 814 | error ("Invalid handler in `file-name-handler-alist'"); |
| 808 | } | 815 | } |
| 809 | 816 | ||
| 817 | /* As a last resort, we may have to use the root as | ||
| 818 | default_directory below. */ | ||
| 819 | Lisp_Object root; | ||
| 820 | #ifdef DOS_NT | ||
| 821 | /* "/" is not considered a root directory on DOS_NT, so using it | ||
| 822 | as default_directory causes an infinite recursion in, e.g., | ||
| 823 | the following: | ||
| 824 | |||
| 825 | (let (default-directory) | ||
| 826 | (expand-file-name "a")) | ||
| 827 | |||
| 828 | To avoid this, we use the root of the current drive. */ | ||
| 829 | root = build_string (emacs_root_dir ()); | ||
| 830 | #else | ||
| 831 | root = build_string ("/"); | ||
| 832 | #endif | ||
| 810 | 833 | ||
| 811 | /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */ | 834 | /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */ |
| 812 | if (NILP (default_directory)) | 835 | if (NILP (default_directory)) |
| 813 | { | 836 | { |
| 814 | Lisp_Object dir = BVAR (current_buffer, directory); | 837 | Lisp_Object dir = BVAR (current_buffer, directory); |
| 815 | /* The buffer's default-directory should be absolute. If it | 838 | /* The buffer's default-directory should be absolute or should |
| 816 | isn't, try to expand it relative to invocation-directory. | 839 | start with `~'. If it isn't absolute, we replace it by its |
| 817 | But we have to be careful to avoid an infinite loop, because | 840 | expansion relative to a known absolute name ABSDIR, which is |
| 818 | the code in emacs.c that sets Vinvocation_directory might | 841 | the invocation-directory if the latter is absolute, or the |
| 819 | call Fexpand_file_name. */ | 842 | root otherwise. |
| 843 | |||
| 844 | In case default-directory starts with `~' or `~user', where | ||
| 845 | USER is a valid user name, this correctly expands it (and | ||
| 846 | ABSDIR plays no role). If USER is not a valid user name, the | ||
| 847 | leading `~' loses its special meaning and is retained as part | ||
| 848 | of the expanded name. */ | ||
| 820 | if (STRINGP (dir)) | 849 | if (STRINGP (dir)) |
| 821 | { | 850 | { |
| 822 | if (!NILP (Ffile_name_absolute_p (dir))) | 851 | if (file_name_absolute_no_tilde_p (dir)) |
| 823 | default_directory = dir; | 852 | default_directory = dir; |
| 824 | else if (STRINGP (Vinvocation_directory) | 853 | else |
| 825 | && !NILP (Ffile_name_absolute_p (Vinvocation_directory))) | 854 | { |
| 826 | default_directory = Fexpand_file_name (dir, Vinvocation_directory); | 855 | Lisp_Object absdir |
| 856 | = STRINGP (Vinvocation_directory) | ||
| 857 | && file_name_absolute_no_tilde_p (Vinvocation_directory) | ||
| 858 | ? Vinvocation_directory : root; | ||
| 859 | default_directory = Fexpand_file_name (dir, absdir); | ||
| 860 | } | ||
| 827 | } | 861 | } |
| 828 | } | 862 | } |
| 829 | if (! STRINGP (default_directory)) | 863 | if (! STRINGP (default_directory)) |
| 830 | { | 864 | default_directory = root; |
| 831 | #ifdef DOS_NT | ||
| 832 | /* "/" is not considered a root directory on DOS_NT, so using "/" | ||
| 833 | here causes an infinite recursion in, e.g., the following: | ||
| 834 | |||
| 835 | (let (default-directory) | ||
| 836 | (expand-file-name "a")) | ||
| 837 | |||
| 838 | To avoid this, we set default_directory to the root of the | ||
| 839 | current drive. */ | ||
| 840 | default_directory = build_string (emacs_root_dir ()); | ||
| 841 | #else | ||
| 842 | default_directory = build_string ("/"); | ||
| 843 | #endif | ||
| 844 | } | ||
| 845 | 865 | ||
| 846 | handler = Ffind_file_name_handler (default_directory, Qexpand_file_name); | 866 | handler = Ffind_file_name_handler (default_directory, Qexpand_file_name); |
| 847 | if (!NILP (handler)) | 867 | if (!NILP (handler)) |