From eeeb69680edab76b83dc2d68d74b019a92bdd114 Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Mon, 8 Jul 2002 09:49:28 +0000 Subject: [PATCH] Some bugfixes and simplifications. * new/os.path.jam (join-imp): Bugfixes. (all-parents): Simplified. (glob-in-parents): New rule. * new/project-root.jam (load): Use 'glob-in-parent' instread of 'find-to-root', so that "project-root.load ." always work. * new/project.jam (find-jamfile): Make use of the 'glob-in-parents' rule. [SVN r14339] --- new/os.path.jam | 77 +++++++++++++++++++++++++++++++------------- new/project-root.jam | 7 +++- new/project.jam | 16 ++------- v2/build/project.jam | 16 ++------- v2/os.path.jam | 77 +++++++++++++++++++++++++++++++------------- v2/project-root.jam | 7 +++- 6 files changed, 124 insertions(+), 76 deletions(-) diff --git a/new/os.path.jam b/new/os.path.jam index f52714ae4..f92dcfc11 100644 --- a/new/os.path.jam +++ b/new/os.path.jam @@ -149,12 +149,13 @@ local rule join-imp ( elements + ) } else { - local parts = [ regex.match "((\.\./)*)(.*)" : $(path2) : 1 3 ] ; + # Separate the part with ".." from the rest. + local parts = [ regex.match "(\\.\\.(/\\.\\.)*)?/?(.*)" : $(path2) : 1 3 ] ; if $(parts[1]) { local up_tokens = [ regex.split $(parts[1]) "/" ] ; - for local i in $(up_tokens[1--2]) + for local i in $(up_tokens) { path1 = [ parent $(path1) ] ; } @@ -162,16 +163,28 @@ local rule join-imp ( elements + ) if $(path1) = . { - return $(parts[2]) ; + if $(parts[2]) + { + return $(parts[2]) ; + } + else + { + return . ; + } } else if $(path1) = / { + # TODO: consider if it's possible to have empty $(parts[2]) here. return /$(parts[2]) ; } - else + else if $(parts[2]) { return $(path1)/$(parts[2]) ; } + else + { + return $(path1) ; + } } } @@ -215,9 +228,9 @@ rule pwd ( ) # # Returns the list of files matching the given pattern in the specified directory. # -rule glob ( dir : pattern + ) +rule glob ( dir : patterns + ) { - return [ sequence.transform make : [ GLOB [ native $(dir) ] : $(pattern) ] ] ; + return [ sequence.transform make : [ GLOB [ native $(dir) ] : $(patterns) ] ] ; } # @@ -228,20 +241,12 @@ rule glob ( dir : pattern + ) rule all-parents ( path : upper_limit ? : cwd ? ) { cwd ?= [ pwd ] ; - local rpath ; - if ! [ is-rooted $(path) ] { - rpath = [ root $(path) $(cwd) ] ; - } else { - rpath = $(path) ; - } + local rpath = [ root $(path) $(cwd) ] ; if ! $(upper_limit) { upper_limit = / ; - } else { - if ! [ is-rooted $(upper_limit) ] { - upper_limit = [ root $(upper_limit) $(cwd) ] ; - } - } + } + upper_limit = [ root $(upper_limit) $(cwd) ] ; # Leave only directory names below 'upper_limits' # Assure pruned_path[2] will have no leading '/' @@ -250,14 +255,35 @@ rule all-parents ( path : upper_limit ? : cwd ? ) error "$(upper_limit) is not prefix of $(path)" ; } - local tokens = [ regex.split $(pruned_path[2]) "/" ] ; + if $(pruned_path[2]) + { + # Length of 'tokens' is equal to the number of paths to check. + local tokens = [ regex.split $(pruned_path[2]) "/" ] ; - local result ; - for local i in $(tokens) { - path = [ parent $(path) ] ; - result += $(path) ; + local result ; + for local i in $(tokens) { + path = [ parent $(path) ] ; + result += $(path) ; + } + return $(result) ; } - return $(result) ; +} + +# +# Search for 'pattern' in parent directories of 'dir', up till and including +# 'upper_limit', if it is specified, or till the filesystem root otherwise. +# +rule glob-in-parents ( dir : patterns + : upper-limit ? ) +{ + local result ; + local parent-dirs = [ os.path.all-parents $(dir) : $(upper-limit) ] ; + + while $(parent-dirs) && ! $(result) + { + result = [ os.path.glob $(parent-dirs[1]) : $(patterns) ] ; + parent-dirs = $(parent-dirs[2-]) ; + } + return $(result) ; } # @@ -348,6 +374,10 @@ rule __test__ ( ) { assert.result "../.." : join "../foo" "../.." ; assert.result "/foo" : join "/bar" "../foo" ; assert.result "foo/giz" : join "foo/giz" "." ; + assert.result "." : join lib2 ".." ; + assert.result "/" : join "/a" ".." ; + + assert.result /a/b : join /a/b/c .. ; assert.result "foo/bar/giz" : join "foo" "bar" "giz" ; assert.result "giz" : join "foo" ".." "giz" ; @@ -360,6 +390,7 @@ rule __test__ ( ) { catch only first element may be rooted ; local CWD = "/home/ghost/build" ; + assert.result : all-parents . : . : $(CWD) ; assert.result . .. ../.. ../../.. : all-parents "Jamfile" : "" : $(CWD) ; assert.result foo . .. ../.. ../../.. : all-parents "foo/Jamfile" : "" : $(CWD) ; assert.result ../Work .. ../.. ../../.. : all-parents "../Work/Jamfile" : "" : $(CWD) ; diff --git a/new/project-root.jam b/new/project-root.jam index 6616a27db..51087d0b1 100644 --- a/new/project-root.jam +++ b/new/project-root.jam @@ -9,6 +9,7 @@ # instance declared constants which also get interned into each loaded project. import modules ; +import os.path ; # Load the project-root file for the given directory. The directory can # be either the project-root itself, or any subdirectory. Fails if it can't @@ -20,7 +21,11 @@ rule load ( { # Find the project-root.jam corresponding to this directory. # - local location = [ find-to-root $(dir) : project-root.jam ] ; + local location = [ os.path.glob $(dir) : project-root.jam ] ; + if ! $(location) + { + location = [ os.path.glob-in-parents $(dir) : project-root.jam ] ; + } # No project-root file found. # diff --git a/new/project.jam b/new/project.jam index 7d575cfa5..6628d5e0a 100644 --- a/new/project.jam +++ b/new/project.jam @@ -248,20 +248,8 @@ local rule find-jamfile ( local jamfile-glob = ; if $(parent-root) { - if $(parent-root) != $(dir) { - # 'find-to-root' does not handle relative paths gracefully, - # so use os.path module - - local parent-dirs = [ os.path.all-parents $(dir) : $(parent-root) ] ; - # Remove dir and add parent-root to the list of searched dirs - parent-dirs = $(parent-dirs[2-]) $(parent-root) ; - - while $(parent-dirs) && ! $(jamfile-glob) - { - jamfile-glob = [ os.path.glob $(parent-dirs[1]) : $(JAMFILE) ] ; - parent-dirs = $(parent-dirs[2-]) ; - } - } + jamfile-glob = + [ os.path.glob-in-parents $(dir) : $(JAMFILE) : $(parent-root) ] ; } else { diff --git a/v2/build/project.jam b/v2/build/project.jam index 7d575cfa5..6628d5e0a 100644 --- a/v2/build/project.jam +++ b/v2/build/project.jam @@ -248,20 +248,8 @@ local rule find-jamfile ( local jamfile-glob = ; if $(parent-root) { - if $(parent-root) != $(dir) { - # 'find-to-root' does not handle relative paths gracefully, - # so use os.path module - - local parent-dirs = [ os.path.all-parents $(dir) : $(parent-root) ] ; - # Remove dir and add parent-root to the list of searched dirs - parent-dirs = $(parent-dirs[2-]) $(parent-root) ; - - while $(parent-dirs) && ! $(jamfile-glob) - { - jamfile-glob = [ os.path.glob $(parent-dirs[1]) : $(JAMFILE) ] ; - parent-dirs = $(parent-dirs[2-]) ; - } - } + jamfile-glob = + [ os.path.glob-in-parents $(dir) : $(JAMFILE) : $(parent-root) ] ; } else { diff --git a/v2/os.path.jam b/v2/os.path.jam index f52714ae4..f92dcfc11 100644 --- a/v2/os.path.jam +++ b/v2/os.path.jam @@ -149,12 +149,13 @@ local rule join-imp ( elements + ) } else { - local parts = [ regex.match "((\.\./)*)(.*)" : $(path2) : 1 3 ] ; + # Separate the part with ".." from the rest. + local parts = [ regex.match "(\\.\\.(/\\.\\.)*)?/?(.*)" : $(path2) : 1 3 ] ; if $(parts[1]) { local up_tokens = [ regex.split $(parts[1]) "/" ] ; - for local i in $(up_tokens[1--2]) + for local i in $(up_tokens) { path1 = [ parent $(path1) ] ; } @@ -162,16 +163,28 @@ local rule join-imp ( elements + ) if $(path1) = . { - return $(parts[2]) ; + if $(parts[2]) + { + return $(parts[2]) ; + } + else + { + return . ; + } } else if $(path1) = / { + # TODO: consider if it's possible to have empty $(parts[2]) here. return /$(parts[2]) ; } - else + else if $(parts[2]) { return $(path1)/$(parts[2]) ; } + else + { + return $(path1) ; + } } } @@ -215,9 +228,9 @@ rule pwd ( ) # # Returns the list of files matching the given pattern in the specified directory. # -rule glob ( dir : pattern + ) +rule glob ( dir : patterns + ) { - return [ sequence.transform make : [ GLOB [ native $(dir) ] : $(pattern) ] ] ; + return [ sequence.transform make : [ GLOB [ native $(dir) ] : $(patterns) ] ] ; } # @@ -228,20 +241,12 @@ rule glob ( dir : pattern + ) rule all-parents ( path : upper_limit ? : cwd ? ) { cwd ?= [ pwd ] ; - local rpath ; - if ! [ is-rooted $(path) ] { - rpath = [ root $(path) $(cwd) ] ; - } else { - rpath = $(path) ; - } + local rpath = [ root $(path) $(cwd) ] ; if ! $(upper_limit) { upper_limit = / ; - } else { - if ! [ is-rooted $(upper_limit) ] { - upper_limit = [ root $(upper_limit) $(cwd) ] ; - } - } + } + upper_limit = [ root $(upper_limit) $(cwd) ] ; # Leave only directory names below 'upper_limits' # Assure pruned_path[2] will have no leading '/' @@ -250,14 +255,35 @@ rule all-parents ( path : upper_limit ? : cwd ? ) error "$(upper_limit) is not prefix of $(path)" ; } - local tokens = [ regex.split $(pruned_path[2]) "/" ] ; + if $(pruned_path[2]) + { + # Length of 'tokens' is equal to the number of paths to check. + local tokens = [ regex.split $(pruned_path[2]) "/" ] ; - local result ; - for local i in $(tokens) { - path = [ parent $(path) ] ; - result += $(path) ; + local result ; + for local i in $(tokens) { + path = [ parent $(path) ] ; + result += $(path) ; + } + return $(result) ; } - return $(result) ; +} + +# +# Search for 'pattern' in parent directories of 'dir', up till and including +# 'upper_limit', if it is specified, or till the filesystem root otherwise. +# +rule glob-in-parents ( dir : patterns + : upper-limit ? ) +{ + local result ; + local parent-dirs = [ os.path.all-parents $(dir) : $(upper-limit) ] ; + + while $(parent-dirs) && ! $(result) + { + result = [ os.path.glob $(parent-dirs[1]) : $(patterns) ] ; + parent-dirs = $(parent-dirs[2-]) ; + } + return $(result) ; } # @@ -348,6 +374,10 @@ rule __test__ ( ) { assert.result "../.." : join "../foo" "../.." ; assert.result "/foo" : join "/bar" "../foo" ; assert.result "foo/giz" : join "foo/giz" "." ; + assert.result "." : join lib2 ".." ; + assert.result "/" : join "/a" ".." ; + + assert.result /a/b : join /a/b/c .. ; assert.result "foo/bar/giz" : join "foo" "bar" "giz" ; assert.result "giz" : join "foo" ".." "giz" ; @@ -360,6 +390,7 @@ rule __test__ ( ) { catch only first element may be rooted ; local CWD = "/home/ghost/build" ; + assert.result : all-parents . : . : $(CWD) ; assert.result . .. ../.. ../../.. : all-parents "Jamfile" : "" : $(CWD) ; assert.result foo . .. ../.. ../../.. : all-parents "foo/Jamfile" : "" : $(CWD) ; assert.result ../Work .. ../.. ../../.. : all-parents "../Work/Jamfile" : "" : $(CWD) ; diff --git a/v2/project-root.jam b/v2/project-root.jam index 6616a27db..51087d0b1 100644 --- a/v2/project-root.jam +++ b/v2/project-root.jam @@ -9,6 +9,7 @@ # instance declared constants which also get interned into each loaded project. import modules ; +import os.path ; # Load the project-root file for the given directory. The directory can # be either the project-root itself, or any subdirectory. Fails if it can't @@ -20,7 +21,11 @@ rule load ( { # Find the project-root.jam corresponding to this directory. # - local location = [ find-to-root $(dir) : project-root.jam ] ; + local location = [ os.path.glob $(dir) : project-root.jam ] ; + if ! $(location) + { + location = [ os.path.glob-in-parents $(dir) : project-root.jam ] ; + } # No project-root file found. #