To handle cloud filesystem paths on windows correctly, provide a way to run

fnmatch without fnmatch.

PiperOrigin-RevId: 294349136
Change-Id: Iebc466c2b3974ae5f4bd7524a8d51624df4cb70c
This commit is contained in:
Gunhan Gulsoy 2020-02-10 18:09:34 -08:00 committed by TensorFlower Gardener
parent 1a287cbaee
commit 5659465166
9 changed files with 29 additions and 2 deletions

View File

@ -1396,6 +1396,7 @@ filegroup(
"protobuf_util.cc", "protobuf_util.cc",
"raw_coding.h", "raw_coding.h",
"refcount.h", "refcount.h",
"regexp.h",
"scanner.cc", "scanner.cc",
"scanner.h", "scanner.h",
"setround.cc", "setround.cc",

View File

@ -113,6 +113,7 @@ cc_library(
"//tensorflow/core/platform:path", "//tensorflow/core/platform:path",
"//tensorflow/core/platform:platform_port", "//tensorflow/core/platform:platform_port",
"//tensorflow/core/platform:protobuf", "//tensorflow/core/platform:protobuf",
"//tensorflow/core/platform:regexp",
"//tensorflow/core/platform:setround", "//tensorflow/core/platform:setround",
"//tensorflow/core/platform:status", "//tensorflow/core/platform:status",
"//tensorflow/core/platform:str_util", "//tensorflow/core/platform:str_util",

View File

@ -762,6 +762,7 @@ def tf_portable_deps_no_runtime(use_lite_protos = False):
"//tensorflow/core/util:stats_calculator_portable", "//tensorflow/core/util:stats_calculator_portable",
"//tensorflow/core:mobile_additional_lib_deps", "//tensorflow/core:mobile_additional_lib_deps",
"//tensorflow/core:protos_all_cc_impl", "//tensorflow/core:protos_all_cc_impl",
"@com_googlesource_code_re2//:re2",
"@farmhash_archive//:farmhash", "@farmhash_archive//:farmhash",
] + tf_protobuf_deps(use_lite_protos) ] + tf_protobuf_deps(use_lite_protos)

View File

@ -26,12 +26,20 @@ limitations under the License.
#include "tensorflow/core/platform/env.h" #include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/errors.h" #include "tensorflow/core/platform/errors.h"
#include "tensorflow/core/platform/platform.h" #include "tensorflow/core/platform/platform.h"
#include "tensorflow/core/platform/regexp.h"
#include "tensorflow/core/platform/scanner.h" #include "tensorflow/core/platform/scanner.h"
#include "tensorflow/core/platform/str_util.h" #include "tensorflow/core/platform/str_util.h"
#include "tensorflow/core/platform/strcat.h" #include "tensorflow/core/platform/strcat.h"
namespace tensorflow { namespace tensorflow {
bool FileSystem::Match(const string& filename, const string& pattern) {
string regexp(pattern);
RE2::GlobalReplace(&regexp, "\\*", "[^/]*");
RE2::GlobalReplace(&regexp, "\\?", ".");
return RE2::FullMatch(filename, regexp);
}
string FileSystem::TranslateName(const string& name) const { string FileSystem::TranslateName(const string& name) const {
// If the name is empty, CleanPath returns "." which is incorrect and // If the name is empty, CleanPath returns "." which is incorrect and
// we should return the empty path instead. // we should return the empty path instead.

View File

@ -146,6 +146,13 @@ class FileSystem {
virtual tensorflow::Status GetMatchingPaths(const string& pattern, virtual tensorflow::Status GetMatchingPaths(const string& pattern,
std::vector<string>* results) = 0; std::vector<string>* results) = 0;
/// \brief Checks if the given filename matches the pattern.
///
/// This function provides the equivalent of posix fnmatch, however it is
/// implemented without fnmatch to ensure that this can be used for cloud
/// filesystems on windows. For windows filesystems, it uses PathMatchSpec.
virtual bool Match(const string& filename, const string& pattern);
/// \brief Obtains statistics for the given path. /// \brief Obtains statistics for the given path.
virtual tensorflow::Status Stat(const string& fname, virtual tensorflow::Status Stat(const string& fname,
FileStatistics* stat) = 0; FileStatistics* stat) = 0;

View File

@ -119,7 +119,7 @@ Status GetMatchingPaths(FileSystem* fs, Env* env, const string& pattern,
// Match all obtained files to the input pattern. // Match all obtained files to the input pattern.
for (const auto& f : all_files) { for (const auto& f : all_files) {
if (env->MatchPath(f, eval_pattern)) { if (fs->Match(f, eval_pattern)) {
results->push_back(f); results->push_back(f);
} }
} }

View File

@ -18,7 +18,8 @@ limitations under the License.
#include "tensorflow/core/platform/platform.h" #include "tensorflow/core/platform/platform.h"
#if defined(PLATFORM_GOOGLE) || defined(PLATFORM_GOOGLE_ANDROID) #if defined(PLATFORM_GOOGLE) || defined(PLATFORM_GOOGLE_ANDROID) || \
defined(PLATFORM_GOOGLE_IOS) || defined(PLATFORM_PORTABLE_GOOGLE)
#include "third_party/re2/re2.h" #include "third_party/re2/re2.h"
#else #else
#include "re2/re2.h" #include "re2/re2.h"

View File

@ -548,6 +548,12 @@ Status WindowsFileSystem::GetMatchingPaths(const string& pattern,
return Status::OK(); return Status::OK();
} }
bool WindowsFileSystem::Match(const string& filename, const string& pattern) {
std::wstring ws_path(Utf8ToWideChar(path));
std::wstring ws_pattern(Utf8ToWideChar(pattern));
return PathMatchSpecW(ws_path.c_str(), ws_pattern.c_str()) == TRUE;
}
Status WindowsFileSystem::Stat(const string& fname, FileStatistics* stat) { Status WindowsFileSystem::Stat(const string& fname, FileStatistics* stat) {
Status result; Status result;
struct _stat sbuf; struct _stat sbuf;

View File

@ -52,6 +52,8 @@ class WindowsFileSystem : public FileSystem {
Status GetMatchingPaths(const string& pattern, Status GetMatchingPaths(const string& pattern,
std::vector<string>* result) override; std::vector<string>* result) override;
bool Match(const string& filename, const string& pattern) override;
Status Stat(const string& fname, FileStatistics* stat) override; Status Stat(const string& fname, FileStatistics* stat) override;
Status DeleteFile(const string& fname) override; Status DeleteFile(const string& fname) override;