]> arthur.barton.de Git - bup.git/commitdiff
vfs2: add try_resolve() and use it in ls
authorRob Browning <rlb@defaultvalue.org>
Sun, 3 Dec 2017 17:31:18 +0000 (11:31 -0600)
committerRob Browning <rlb@defaultvalue.org>
Sun, 17 Dec 2017 22:01:38 +0000 (16:01 -0600)
Create a vfs2 version of try_resolve and use it in ls to handle bad
symlinks correctly.

Signed-off-by: Rob Browning <rlb@defaultvalue.org>
Tested-by: Rob Browning <rlb@defaultvalue.org>
lib/bup/ls.py
lib/bup/vfs2.py
t/test-ls.sh

index 4c4d614d37bceaaa5f0b2d69e02895dbd3b077d0..6149ab533e0dbfc6921e5ba202ddf5e186cc001d 100644 (file)
@@ -114,8 +114,7 @@ def do_ls(args, default='.', onabort=None, spec_prefix=''):
             if opt.directory:
                 resolved = vfs.lresolve(repo, path)
             else:
-                # FIXME: deal with invalid symlinks i.e. old vfs try_resolve
-                resolved = vfs.resolve(repo, path)
+                resolved = vfs.try_resolve(repo, path)
 
             leaf_name, leaf_item = resolved[-1]
             if not leaf_item:
index 5fbcc6a43a0cbcc26a03cbcdbbe8ea0a785c25b6..ece4eb0a27b307ff01c4fab7c19fb2516726bd6f 100644 (file)
@@ -826,6 +826,24 @@ def resolve(repo, path, parent=None, want_meta=True):
         assert not S_ISLNK(item_mode(leaf_item))
     return result
 
+def try_resolve(repo, path, parent=None, want_meta=True):
+    """If path does not refer to a symlink, does not exist, or refers to a
+    valid symlink, behave exactly like resolve().  If path refers to
+    an invalid symlink, behave like lresolve.
+
+    """
+    res = lresolve(repo, path, parent=parent, want_meta=want_meta)
+    leaf_name, leaf_item = res[-1]
+    if not leaf_item:
+        return res
+    if not S_ISLNK(item_mode(leaf_item)):
+        return res
+    deref = resolve(repo, leaf_name, parent=res[:-1], want_meta=want_meta)
+    deref_name, deref_item = deref[-1]
+    if deref_item:
+        return deref
+    return res
+
 def augment_item_meta(repo, item, include_size=False):
     """Ensure item has a Metadata instance for item.meta.  If item.meta is
     currently a mode, replace it with a compatible "fake" Metadata
index 88c1759476aecc9ada185c01694f86df1081fa88..1f668b5d5405e8cae5423fbed247666e1cb137a1 100755 (executable)
@@ -26,6 +26,7 @@ WVPASS chmod u+x src/executable
 WVPASS chmod -R u=rwX,g-rwx,o-rwx .
 WVPASS touch -t 200910032348 src/.dotfile src/*
 (WVPASS cd src; WVPASS ln -s file symlink) || exit $?
+(WVPASS cd src; WVPASS ln -s not-there bad-symlink) || exit $?
 WVPASS touch -t 200910032348 src
 WVPASS touch -t 200910032348 .
 WVPASS bup index src
@@ -64,13 +65,15 @@ WVPASSEQ "$(WVPASS bup ls /src)" \
 "1977-09-05-125600
 latest"
 
-WVPASSEQ "$(WVPASS bup ls src/latest)" "executable
+WVPASSEQ "$(WVPASS bup ls src/latest)" "bad-symlink
+executable
 fifo
 file
 socket
 symlink"
 
 WVPASSEQ "$(WVPASS bup ls -A src/latest)" ".dotfile
+bad-symlink
 executable
 fifo
 file
@@ -80,19 +83,22 @@ symlink"
 WVPASSEQ "$(WVPASS bup ls -a src/latest)" ".
 ..
 .dotfile
+bad-symlink
 executable
 fifo
 file
 socket
 symlink"
 
-WVPASSEQ "$(WVPASS bup ls -F src/latest)" "executable*
+WVPASSEQ "$(WVPASS bup ls -F src/latest)" "bad-symlink@
+executable*
 fifo|
 file
 socket=
 symlink@"
 
-WVPASSEQ "$(WVPASS bup ls --file-type src/latest)" "executable
+WVPASSEQ "$(WVPASS bup ls --file-type src/latest)" "bad-symlink@
+executable
 fifo|
 file
 socket=
@@ -126,10 +132,33 @@ drwxr-xr-x 0/0 0 1970-01-01 00:00 ../
 drwxr-xr-x 0/0 0 1970-01-01 00:00 .tag/
 drwxr-xr-x 0/0 0 1970-01-01 00:00 src/"
 
-symlink_mode="$(WVPASS ls -l src/symlink | cut -b -10)" || exit $?
 socket_mode="$(WVPASS ls -l src/socket | cut -b -10)" || exit $?
 
-symlink_bup_info="$(WVPASS bup ls -l src/latest | grep symlink)" \
+
+bad_symlink_mode="$(WVPASS ls -l src/bad-symlink | cut -b -10)" || exit $?
+
+bad_symlink_bup_info="$(WVPASS bup ls -l src/latest | grep bad-symlink)" \
+    || exit $?
+bad_symlink_date="$(WVPASS echo "$bad_symlink_bup_info" \
+  | WVPASS perl -ne 'm/.*? (\d+) (\d\d\d\d-\d\d-\d\d \d\d:\d\d)/ and print $2')" \
+    || exit $?
+
+test "$bad_symlink_date" || exit 1
+
+if test "$(uname -s)" != NetBSD; then
+    bad_symlink_size="$(WVPASS bup-python -c "import os
+print os.lstat('src/bad-symlink').st_size")" || exit $?
+else
+    # NetBSD appears to return varying sizes, so for now, just ignore it.
+    bad_symlink_size="$(WVPASS echo "$bad_symlink_bup_info" \
+      | WVPASS perl -ne 'm/.*? (\d+) (\d\d\d\d-\d\d-\d\d \d\d:\d\d)/ and print $1')" \
+        || exit $?
+fi
+
+
+symlink_mode="$(WVPASS ls -l src/symlink | cut -b -10)" || exit $?
+
+symlink_bup_info="$(WVPASS bup ls -l src/latest | grep -E '[^-]symlink')" \
     || exit $?
 symlink_date="$(WVPASS echo "$symlink_bup_info" \
   | WVPASS perl -ne 'm/.*? (\d+) (\d\d\d\d-\d\d-\d\d \d\d:\d\d)/ and print $2')" \
@@ -147,6 +176,7 @@ else
         || exit $?
 fi
 
+
 uid="$(WVPASS id -u)" || exit $?
 gid="$(WVPASS bup-python -c 'import os; print os.stat("src").st_gid')" || exit $?
 user="$(WVPASS id -un)" || exit $?
@@ -154,7 +184,8 @@ group="$(WVPASS bup-python -c 'import grp, os;
 print grp.getgrgid(os.stat("src").st_gid)[0]')" || exit $?
 
 WVPASSEQ "$(bup ls -l src/latest | tr -s ' ' ' ')" \
-"-rwx------ $user/$group 0 2009-10-03 23:48 executable
+"$bad_symlink_mode $user/$group $bad_symlink_size $bad_symlink_date bad-symlink -> not-there
+-rwx------ $user/$group 0 2009-10-03 23:48 executable
 prw------- $user/$group 0 2009-10-03 23:48 fifo
 -rw------- $user/$group 1024 2009-10-03 23:48 file
 $socket_mode $user/$group 0 2009-10-03 23:48 socket
@@ -164,6 +195,7 @@ WVPASSEQ "$(bup ls -la src/latest | tr -s ' ' ' ')" \
 "drwx------ $user/$group 0 2009-10-03 23:48 .
 drwxr-xr-x 0/0 0 1970-01-01 00:00 ..
 -rw------- $user/$group 0 2009-10-03 23:48 .dotfile
+$bad_symlink_mode $user/$group $bad_symlink_size $bad_symlink_date bad-symlink -> not-there
 -rwx------ $user/$group 0 2009-10-03 23:48 executable
 prw------- $user/$group 0 2009-10-03 23:48 fifo
 -rw------- $user/$group 1024 2009-10-03 23:48 file
@@ -172,6 +204,7 @@ $symlink_mode $user/$group $symlink_size $symlink_date symlink -> file"
 
 WVPASSEQ "$(bup ls -lA src/latest | tr -s ' ' ' ')" \
 "-rw------- $user/$group 0 2009-10-03 23:48 .dotfile
+$bad_symlink_mode $user/$group $bad_symlink_size $bad_symlink_date bad-symlink -> not-there
 -rwx------ $user/$group 0 2009-10-03 23:48 executable
 prw------- $user/$group 0 2009-10-03 23:48 fifo
 -rw------- $user/$group 1024 2009-10-03 23:48 file
@@ -179,21 +212,24 @@ $socket_mode $user/$group 0 2009-10-03 23:48 socket
 $symlink_mode $user/$group $symlink_size $symlink_date symlink -> file"
 
 WVPASSEQ "$(bup ls -lF src/latest | tr -s ' ' ' ')" \
-"-rwx------ $user/$group 0 2009-10-03 23:48 executable*
+"$bad_symlink_mode $user/$group $bad_symlink_size $bad_symlink_date bad-symlink@ -> not-there
+-rwx------ $user/$group 0 2009-10-03 23:48 executable*
 prw------- $user/$group 0 2009-10-03 23:48 fifo|
 -rw------- $user/$group 1024 2009-10-03 23:48 file
 $socket_mode $user/$group 0 2009-10-03 23:48 socket=
 $symlink_mode $user/$group $symlink_size $symlink_date symlink@ -> file"
 
 WVPASSEQ "$(bup ls -l --file-type src/latest | tr -s ' ' ' ')" \
-"-rwx------ $user/$group 0 2009-10-03 23:48 executable
+"$bad_symlink_mode $user/$group $bad_symlink_size $bad_symlink_date bad-symlink@ -> not-there
+-rwx------ $user/$group 0 2009-10-03 23:48 executable
 prw------- $user/$group 0 2009-10-03 23:48 fifo|
 -rw------- $user/$group 1024 2009-10-03 23:48 file
 $socket_mode $user/$group 0 2009-10-03 23:48 socket=
 $symlink_mode $user/$group $symlink_size $symlink_date symlink@ -> file"
 
 WVPASSEQ "$(bup ls -ln src/latest | tr -s ' ' ' ')" \
-"-rwx------ $uid/$gid 0 2009-10-03 23:48 executable
+"$bad_symlink_mode $uid/$gid $bad_symlink_size $bad_symlink_date bad-symlink -> not-there
+-rwx------ $uid/$gid 0 2009-10-03 23:48 executable
 prw------- $uid/$gid 0 2009-10-03 23:48 fifo
 -rw------- $uid/$gid 1024 2009-10-03 23:48 file
 $socket_mode $uid/$gid 0 2009-10-03 23:48 socket
@@ -217,16 +253,28 @@ WVPASSEQ "$(bup ls -ds --commit-hash "src/latest" | tr -s ' ' ' ')" \
 
 WVSTART "ls (dates TZ != UTC)"
 export TZ=America/Chicago
-symlink_date_central="$(bup ls -l src/latest | grep symlink)"
+bad_symlink_date_central="$(bup ls -l src/latest | grep bad-symlink)"
+bad_symlink_date_central="$(echo "$bad_symlink_date_central" \
+  | perl -ne 'm/.*? (\d+) (\d\d\d\d-\d\d-\d\d \d\d:\d\d)/ and print $2')"
+symlink_date_central="$(bup ls -l src/latest | grep -E '[^-]symlink')"
 symlink_date_central="$(echo "$symlink_date_central" \
   | perl -ne 'm/.*? (\d+) (\d\d\d\d-\d\d-\d\d \d\d:\d\d)/ and print $2')"
 WVPASSEQ "$(bup ls -ln src/latest | tr -s ' ' ' ')" \
-"-rwx------ $uid/$gid 0 2009-10-03 18:48 executable
+"$bad_symlink_mode $uid/$gid $bad_symlink_size $bad_symlink_date_central bad-symlink -> not-there
+-rwx------ $uid/$gid 0 2009-10-03 18:48 executable
 prw------- $uid/$gid 0 2009-10-03 18:48 fifo
 -rw------- $uid/$gid 1024 2009-10-03 18:48 file
 $socket_mode $uid/$gid 0 2009-10-03 18:48 socket
 $symlink_mode $uid/$gid $symlink_size $symlink_date_central symlink -> file"
-unset TZ
+export TZ=UTC
+
+
+WVSTART "ls bad-symlink"
+WVPASSEQ "$(bup ls "src/latest/bad-symlink")" "src/latest/bad-symlink"
+
+WVSTART "ls -l bad-symlink"
+WVPASSEQ "$(bup ls -l src/latest/bad-symlink | tr -s ' ' ' ')" \
+"$bad_symlink_mode $user/$group $bad_symlink_size $bad_symlink_date src/latest/bad-symlink -> not-there"
 
 
 WVPASS rm -rf "$tmpdir"