[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: PATCH: add relative_file_name procedure to encapsulate logic for "su
From: |
Jacob Bachmeyer |
Subject: |
Re: PATCH: add relative_file_name procedure to encapsulate logic for "subdir" variable [revised] |
Date: |
Tue, 04 Dec 2018 00:10:53 -0600 |
User-agent: |
Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.8.1.22) Gecko/20090807 MultiZilla/1.8.3.4e SeaMonkey/1.1.17 Mnenhy/0.7.6.0 |
Ben Elliston wrote:
On Mon, Dec 03, 2018 at 11:29:47PM -0600, Jacob Bachmeyer wrote:
In other words, it probably should remain as "relative_file_name",
since "realpath_relative" implies a different (and more extensive
operation) as I see it. At the least, "realpath_relative" would
apply "file normalize" to both arguments unconditionally, even
though this could produce surprising results in some situations
involving edge cases with symlinks. Those edge cases would also be
hard to debug, since users bit by them may not realize that symlinks
are involved in the problem. As a pure utility procedure,
"realpath" and variants could be useful, but could be dangerous to
call from the core due to this sensitivity to the filesystem that
this patch lacks.
Thanks for thinking about the suggestion -- I agree. I'm happy with
that, but can we use 'filename' without an underscore? It's a very
common convention and one less character to type. ;-)
While the GNU Coding Standards suggest using "file name" specifically; a
quick grep shows that DejaGnu already has proc unix_clean_filename and
no procedures that use "file_name" in their names, so consistency
suggests that the change should be made. A revised patch follows.
I do not see a difference either way as far as typing less:
relativ<M-/> is the same either way for me. :-)
----
ChangeLog entries:
* runtest.exp: Use new relative_filename procedure.
* doc/dejagnu.texi (relative_filename procedure): Add.
* lib/utils.exp (relative_filename): Add.
* testsuite/runtest.all/utils.test: Add tests for relative_filename.
----
patch:
----
diff --git a/doc/dejagnu.texi b/doc/dejagnu.texi
index d6f6881..373ef47 100644
--- a/doc/dejagnu.texi
+++ b/doc/dejagnu.texi
@@ -4671,6 +4671,7 @@ tool, and its version number.
@menu
* getdirs Procedure: getdirs procedure
+* relative_filename Procedure: relative_filename procedure
* find Procedure: find procedure
* which Procedure: which procedure
* grep Procedure: grep procedure
@@ -4683,7 +4684,7 @@ tool, and its version number.
* prune_system_crud Procedure: prune_system_crud procedure
@end menu
address@hidden getdirs procedure, find procedure, , Utility Procedures
address@hidden getdirs procedure, relative_filename procedure, Utility
Procedures, Utility Procedures
@subsubheading getdirs Procedure
@findex getdirs
@@ -4712,7 +4713,26 @@ the pattern. If no directories match the pattern, then
an empty list is
returned.
@end table
address@hidden find procedure, which procedure, getdirs procedure, Utility
Procedures
address@hidden relative_filename procedure, find procedure, getdirs procedure,
Utility Procedures
address@hidden relative_filename Procedure
address@hidden relative_filename
+
+Return a relative file name, given a starting point.
+
address@hidden
address@hidden@b{relative_filename} @i{base} @i{destination}}
address@hidden quotation
+
address@hidden @asis
+
address@hidden @code{base}
+The starting point for relative file name traversal.
+
address@hidden @code{destination}
+The absolute file name that should be reached by appending the return value to
@i{base}.
address@hidden table
+
address@hidden find procedure, which procedure, relative_filename procedure,
Utility Procedures
@subsubheading find Procedure
@findex find
@@ -5442,4 +5462,4 @@ This makes runtest exit. It is abbreviated as @emph{q}.
@bye
address@hidden LocalWords: subdirectory
address@hidden LocalWords: subdirectory prepend prepended testsuite filename
diff --git a/lib/utils.exp b/lib/utils.exp
index 45319f2..0bc759f 100644
--- a/lib/utils.exp
+++ b/lib/utils.exp
@@ -85,6 +85,44 @@ proc getdirs { args } {
}
+# Given a base and a destination, return a relative file name that refers
+# to the destination when used relative to the given base.
+proc relative_filename { base destination } {
+ if { [file pathtype $base] != "absolute" } {
+ set base [file normalize $base]
+ }
+ if { [file pathtype $destination] != "absolute" } {
+ set destination [file normalize $destination]
+ }
+
+ set base [file split $base]
+ set destination [file split $destination]
+
+ verbose "base: \[[llength $base]\] $base" 3
+ verbose "destination: \[[llength $destination]\] $destination" 3
+
+ set basecount [llength $base]
+ for {set i 0} {$i < $basecount
+ && [lindex $base $i] == [lindex $destination $i]} {incr i} {}
+ if { $i == $basecount } {
+ set tail [lrange $destination $i end]
+ } else {
+ set tail [lrange $destination $i end]
+ while { [incr i] <= $basecount } {
+ set tail [linsert $tail 0 ".."]
+ }
+ }
+
+ if { [llength $tail] == 0 } {
+ set result ""
+ } else {
+ set result [eval file join $tail]
+ }
+ verbose "result: $result" 3
+ return $result
+}
+
+
# Finds paths of all non-directory files, recursively, whose names match
# a pattern. Certain directory name are not searched (see proc getdirs).
# rootdir - search in this directory and its subdirectories, recursively.
diff --git a/runtest.exp b/runtest.exp
index b0ddfed..327131a 100644
--- a/runtest.exp
+++ b/runtest.exp
@@ -1771,15 +1771,8 @@ foreach current_target $target_list {
# set subdir to the tail of the dirname after $srcdir,
# for the driver files that want it. XXX this is silly.
# drivers should get a single var, not "$srcdir/$subdir"
- set subdir [file dirname $test_name]
- set p [expr {[string length $srcdir] - 1}]
- while {0 < $p && [string index $srcdir $p] == "/"} {
- incr p -1
- }
- if {[string range $subdir 0 $p] == $srcdir} {
- set subdir [string range $subdir [expr {$p + 1}] end]
- regsub "^/" $subdir "" subdir
- }
+ set subdir [relative_filename $srcdir \
+ [file dirname $test_name]]
# XXX not the right thing to do.
set runtests [list [file tail $test_name] ""]
@@ -1860,20 +1853,8 @@ foreach current_target $target_list {
# Get the path after the $srcdir so we know
# the subdir we're in.
- set subdir [file dirname $test_name]
- # We used to do
- # regsub $srcdir [file dirname $test_name] "" subdir
- # but what if [file dirname $test_name] contains regexp
- # characters? We lose. Instead...
- set first [string first $srcdir $subdir]
- if { $first >= 0 } {
- set first [expr {$first + [string length $srcdir]}]
- set subdir [string range $subdir $first end]
- regsub "^/" "$subdir" "" subdir
- }
- if { "$srcdir" == "$subdir" || "$srcdir" == "$subdir/"
} {
- set subdir ""
- }
+ set subdir [relative_filename $srcdir \
+ [file dirname $test_name]]
# Check to see if the range of tests is limited,
# set `runtests' to a list of two elements: the script
name
# and any arguments ("" if none).
diff --git a/testsuite/runtest.all/utils.test b/testsuite/runtest.all/utils.test
index be13982..b8e05da 100644
--- a/testsuite/runtest.all/utils.test
+++ b/testsuite/runtest.all/utils.test
@@ -42,6 +42,29 @@ if [lib_pat_test "getdirs" "${srcdir}/runtest.all/topdir"
"subdir1*subdir2" ] {
puts "PASSED: getdirs toplevel, two subdirs"
}
+# Test relative_filename:
+#
+if { [relative_filename "/foo/test" "/foo/test/bar/baz" ] == "bar/baz" } {
+ puts "PASSED: relative_filename, simple prefix"
+} else {
+ puts "FAILED: relative_filename, simple prefix"
+}
+if { [relative_filename "/foo/test" "/bar/test" ] == "../../bar/test" } {
+ puts "PASSED: relative_filename, up to top"
+} else {
+ puts "FAILED: relative_filename, up to top"
+}
+if { [relative_filename "/tmp/foo-test" "/tmp/bar/test" ] == "../bar/test" } {
+ puts "PASSED: relative_filename, up one level"
+} else {
+ puts "FAILED: relative_filename, up one level"
+}
+if { [relative_filename "/tmp/foo-test" "/tmp/foo-test" ] == "" } {
+ puts "PASSED: relative_filename, same name"
+} else {
+ puts "FAILED: relative_filename, same name"
+}
+
# Test find:
#
if [string match "*/subdir2/subfile2" "[find ${srcdir}/runtest.all/topdir/subdir2
sub*]"] {
----
-- Jacob