summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Martin <phy1729@gmail.com>2020-07-03 21:10:27 -0500
committerMatthew Martin <phy1729@gmail.com>2020-07-03 21:17:58 -0500
commit4e471c3f899b485e7a4122c75da1500c2d509236 (patch)
treec2f4237de04d7eb6ca4c10ca2057d9eb3cf8d7d7
parentb53f465481920171159d8d471f97be81d2e14fc4 (diff)
downloadzsh-4e471c3f899b485e7a4122c75da1500c2d509236.tar.gz
zsh-4e471c3f899b485e7a4122c75da1500c2d509236.zip
46168: Update $PWD and call chpwd hook after normalizing path
-rw-r--r--ChangeLog5
-rw-r--r--Src/builtin.c35
-rw-r--r--Test/B01cd.ztst19
3 files changed, 40 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index b76d1988e..fa1c74563 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2020-07-03 Matthew Martin <phy1729@gmail.com>
+
+ * 46168: Src/builtin.c, Test/B01cd.ztst: Update $PWD and call
+ chpwd hook after normalizing path.
+
2020-07-03 Daniel Shahaf <d.s@daniel.shahaf.name>
* unposted (cf. users/24972, users/24978): Doc/Zsh/expn.yo:
diff --git a/Src/builtin.c b/Src/builtin.c
index 770930579..ff84ce936 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -841,7 +841,6 @@ int
bin_cd(char *nam, char **argv, Options ops, int func)
{
LinkNode dir;
- struct stat st1, st2;
if (isset(RESTRICTED)) {
zwarnnam(nam, "restricted");
@@ -860,23 +859,6 @@ bin_cd(char *nam, char **argv, Options ops, int func)
}
cd_new_pwd(func, dir, OPT_ISSET(ops, 'q'));
- if (stat(unmeta(pwd), &st1) < 0) {
- setjobpwd();
- zsfree(pwd);
- pwd = NULL;
- pwd = metafy(zgetcwd(), -1, META_DUP);
- } else if (stat(".", &st2) < 0) {
- if (chdir(unmeta(pwd)) < 0)
- zwarn("unable to chdir(%s): %e", pwd, errno);
- } else if (st1.st_ino != st2.st_ino || st1.st_dev != st2.st_dev) {
- if (chasinglinks) {
- setjobpwd();
- zsfree(pwd);
- pwd = NULL;
- pwd = metafy(zgetcwd(), -1, META_DUP);
- } else if (chdir(unmeta(pwd)) < 0)
- zwarn("unable to chdir(%s): %e", pwd, errno);
- }
unqueue_signals();
return 0;
}
@@ -1210,6 +1192,7 @@ static void
cd_new_pwd(int func, LinkNode dir, int quiet)
{
char *new_pwd, *s;
+ struct stat st1, st2;
int dirstacksize;
if (func == BIN_PUSHD)
@@ -1239,6 +1222,22 @@ cd_new_pwd(int func, LinkNode dir, int quiet)
}
}
+ if (stat(unmeta(new_pwd), &st1) < 0) {
+ zsfree(new_pwd);
+ new_pwd = NULL;
+ new_pwd = metafy(zgetcwd(), -1, META_DUP);
+ } else if (stat(".", &st2) < 0) {
+ if (chdir(unmeta(new_pwd)) < 0)
+ zwarn("unable to chdir(%s): %e", new_pwd, errno);
+ } else if (st1.st_ino != st2.st_ino || st1.st_dev != st2.st_dev) {
+ if (chasinglinks) {
+ zsfree(new_pwd);
+ new_pwd = NULL;
+ new_pwd = metafy(zgetcwd(), -1, META_DUP);
+ } else if (chdir(unmeta(new_pwd)) < 0)
+ zwarn("unable to chdir(%s): %e", new_pwd, errno);
+ }
+
/* shift around the pwd variables, to make oldpwd and pwd relate to the
current (i.e. new) pwd */
zsfree(oldpwd);
diff --git a/Test/B01cd.ztst b/Test/B01cd.ztst
index 21e751dcb..bc6757549 100644
--- a/Test/B01cd.ztst
+++ b/Test/B01cd.ztst
@@ -33,7 +33,7 @@
#
# Tests should use subdirectories ending in `.tmp'. These will be
# removed with all the contents even if the test is aborted.
- mkdir cdtst.tmp cdtst.tmp/real cdtst.tmp/sub
+ mkdir cdtst.tmp cdtst.tmp/foo cdtst.tmp/real cdtst.tmp/sub
ln -s ../real cdtst.tmp/sub/fake
@@ -149,6 +149,23 @@ F:something is broken. But you already knew that.
-f:(workers/45367) cd -P squashes multiple leading slashes
>/dev
+ chpwd_hook() { hook_pwd=$PWD; }
+ chpwd_functions=(chpwd_hook)
+ cd $mydir/cdtst.tmp/foo &&
+ (cd $mydir && mv $mydir/cdtst.tmp/{foo,bar}) &&
+ print $PWD &&
+ print $hook_pwd &&
+ cd . &&
+ print $PWD &&
+ print $hook_pwd
+ chpwd_functions=()
+ unfunction chpwd_hook
+0q:cd . with moved PWD
+>$mydir/cdtst.tmp/foo
+>$mydir/cdtst.tmp/foo
+>$mydir/cdtst.tmp/bar
+>$mydir/cdtst.tmp/bar
+
%clean
# This optional section cleans up after the test, if necessary,
# e.g. killing processes etc. This is in addition to the removal of *.tmp