ruby-changes:46785
From: nobu <ko1@a...>
Date: Fri, 26 May 2017 16:04:48 +0900 (JST)
Subject: [ruby-changes:46785] nobu:r58901 (trunk): dir.c: yield without base part
nobu 2017-05-26 16:04:43 +0900 (Fri, 26 May 2017) New Revision: 58901 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=58901 Log: dir.c: yield without base part * dir.c (glob_helper): yield globbed part only without the base directory path part if the base is given. [Feature#13056] Modified files: trunk/dir.c trunk/test/ruby/test_dir.rb Index: dir.c =================================================================== --- dir.c (revision 58900) +++ dir.c (revision 58901) @@ -1588,7 +1588,7 @@ glob_free_pattern(struct glob_pattern *l https://github.com/ruby/ruby/blob/trunk/dir.c#L1588 } static char * -join_path(const char *path, long len, int dirsep, const char *name, size_t namlen) +join_path(const char *path, size_t len, int dirsep, const char *name, size_t namlen) { char *buf = GLOB_ALLOC_N(char, len+namlen+(dirsep?1:0)+1); @@ -1778,6 +1778,7 @@ struct glob_args { https://github.com/ruby/ruby/blob/trunk/dir.c#L1778 void (*func)(const char *, VALUE, void *); const char *path; const char *base; + size_t baselen; VALUE value; rb_encoding *enc; }; @@ -1864,7 +1865,8 @@ static int https://github.com/ruby/ruby/blob/trunk/dir.c#L1865 glob_helper( int fd, const char *path, - long pathlen, + size_t baselen, + size_t namelen, int dirsep, /* '/' should be placed before appending child entry's name to 'path'. */ rb_pathtype_t pathtype, /* type of 'path' */ struct glob_pattern **beg, @@ -1879,6 +1881,7 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1881 struct glob_pattern **cur, **new_beg, **new_end; int plain = 0, magical = 0, recursive = 0, match_all = 0, match_dir = 0; int escape = !(flags & FNM_NOESCAPE); + size_t pathlen = baselen + namelen; for (cur = beg; cur < end; ++cur) { struct glob_pattern *p = *cur; @@ -1929,13 +1932,15 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1932 } } if (match_all && pathtype > path_noent) { - status = glob_call_func(funcs->match, path, arg, enc); + const char *subpath = path + baselen + (baselen && path[baselen] == '/'); + status = glob_call_func(funcs->match, subpath, arg, enc); if (status) return status; } if (match_dir && pathtype == path_directory) { - char *tmp = join_path(path, pathlen, dirsep, "", 0); + const char *subpath = path + baselen + (baselen && path[baselen] == '/'); + char *tmp = join_path(subpath, namelen, dirsep, "", 0); if (!tmp) return -1; - status = glob_call_func(funcs->match, tmp, arg, enc); + status = glob_call_func(funcs->match, tmp + (baselen ? dirsep : 0), arg, enc); GLOB_FREE(tmp); if (status) return status; } @@ -2067,7 +2072,7 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L2072 } } - status = glob_helper(fd, buf, name - buf + namlen, 1, + status = glob_helper(fd, buf, baselen, name - buf - baselen + namlen, 1, new_pathtype, new_beg, new_end, flags, funcs, arg, enc); GLOB_FREE(buf); @@ -2132,7 +2137,8 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L2137 if (!buf) break; } #endif - status = glob_helper(fd, buf, pathlen + strlen(buf + pathlen), 1, + status = glob_helper(fd, buf, baselen, + namelen + strlen(buf + pathlen), 1, new_pathtype, new_beg, new_end, flags, funcs, arg, enc); GLOB_FREE(buf); @@ -2155,7 +2161,7 @@ ruby_glob0(const char *path, int fd, con https://github.com/ruby/ruby/blob/trunk/dir.c#L2161 struct glob_pattern *list; const char *root, *start; char *buf; - size_t n; + size_t n, baselen = 0; int status, dirsep = FALSE; start = root = path; @@ -2169,6 +2175,7 @@ ruby_glob0(const char *path, int fd, con https://github.com/ruby/ruby/blob/trunk/dir.c#L2175 n = root - start; if (!n && base) { n = strlen(base); + baselen = n; start = base; dirsep = TRUE; } @@ -2182,7 +2189,8 @@ ruby_glob0(const char *path, int fd, con https://github.com/ruby/ruby/blob/trunk/dir.c#L2189 GLOB_FREE(buf); return -1; } - status = glob_helper(fd, buf, n, dirsep, path_unknown, &list, &list + 1, + status = glob_helper(fd, buf, baselen, n-baselen, dirsep, + path_unknown, &list, &list + 1, flags, funcs, arg, enc); glob_free_pattern(list); GLOB_FREE(buf); @@ -2493,6 +2501,9 @@ dir_s_aref(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/dir.c#L2501 * * The optional +base+ keyword argument specifies the base directory for * interpreting relative pathnames instead of the current working directory. + * As the results are not prefixed with the base directory name in this + * case, you will need to prepend the base directory name if you want real + * paths. * * Note that the pattern is not a regexp, it's closer to a shell glob. * See File::fnmatch for the meaning of the +flags+ parameter. @@ -2552,8 +2563,8 @@ dir_s_aref(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/dir.c#L2563 * # "lib/song.rb", * # "lib/song/karaoke.rb"] * - * Dir.glob(rbfiles, base: "lib") #=> ["lib/song.rb", - * # "lib/song/karaoke.rb"] + * Dir.glob(rbfiles, base: "lib") #=> ["song.rb", + * # "song/karaoke.rb"] * * libdirs = File.join("**", "lib") * Dir.glob(libdirs) #=> ["lib"] Index: test/ruby/test_dir.rb =================================================================== --- test/ruby/test_dir.rb (revision 58900) +++ test/ruby/test_dir.rb (revision 58901) @@ -203,14 +203,14 @@ class TestDir < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_dir.rb#L203 end def test_glob_base - files = %w[a/foo.c c/bar.c].map {|n| File.join(@root, n)} - files.each {|n| File.write(n, "")} + files = %w[a/foo.c c/bar.c] + files.each {|n| File.write(File.join(@root, n), "")} assert_equal(files, Dir.glob("*/*.c", base: @root).sort) end def test_glob_base_dir - files = %w[a/foo.c c/bar.c].map {|n| File.join(@root, n)} - files.each {|n| File.write(n, "")} + files = %w[a/foo.c c/bar.c] + files.each {|n| File.write(File.join(@root, n), "")} assert_equal(files, Dir.open(@root) {|d| Dir.glob("*/*.c", base: d)}.sort) end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/