Merge pull request #82 from tfarina/disk-interface

Factor out DiskInterface class into its own source/header files.
This commit is contained in:
Evan Martin 2011-08-23 09:17:23 -07:00
commit b0dac493c4
5 changed files with 102 additions and 60 deletions

View File

@ -132,7 +132,7 @@ if platform not in ('mingw'):
n.comment('Core source files all build into ninja library.')
for name in ['build', 'build_log', 'clean', 'eval_env', 'graph', 'graphviz',
'parsers', 'util', 'stat_cache',
'ninja_jumble']:
'ninja_jumble', 'disk_interface']:
objs += cxx(name)
if platform == 'mingw':
objs += cxx('subprocess-win32')

51
src/disk_interface.cc Normal file
View File

@ -0,0 +1,51 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "disk_interface.h"
namespace {
std::string DirName(const std::string& path) {
#ifdef WIN32
const char kPathSeparator = '\\';
#else
const char kPathSeparator = '/';
#endif
std::string::size_type slash_pos = path.rfind(kPathSeparator);
if (slash_pos == std::string::npos)
return std::string(); // Nothing to do.
while (slash_pos > 0 && path[slash_pos - 1] == kPathSeparator)
--slash_pos;
return path.substr(0, slash_pos);
}
} // namespace
bool DiskInterface::MakeDirs(const std::string& path) {
std::string dir = DirName(path);
if (dir.empty())
return true; // Reached root; assume it's there.
int mtime = Stat(dir);
if (mtime < 0)
return false; // Error.
if (mtime > 0)
return true; // Exists already; we're done.
// Directory doesn't exist. Try creating its parent first.
bool success = MakeDirs(dir);
if (!success)
return false;
return MakeDir(dir);
}

49
src/disk_interface.h Normal file
View File

@ -0,0 +1,49 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef NINJA_DISK_INTERFACE_H_
#define NINJA_DISK_INTERFACE_H_
#include <string>
/// Interface for accessing the disk.
///
/// Abstract so it can be mocked out for tests. The real implementation
/// is RealDiskInterface.
struct DiskInterface {
virtual ~DiskInterface() {}
/// stat() a file, returning the mtime, or 0 if missing and -1 on
/// other errors.
virtual int Stat(const std::string& path) = 0;
/// Create a directory, returning false on failure.
virtual bool MakeDir(const std::string& path) = 0;
/// Read a file to a string. Fill in |err| on error.
virtual std::string ReadFile(const std::string& path, std::string* err) = 0;
/// Remove the file named @a path. It behaves like 'rm -f path' so no errors
/// are reported if it does not exists.
/// @returns 0 if the file has been removed,
/// 1 if the file does not exist, and
/// -1 if an error occurs.
virtual int RemoveFile(const std::string& path) = 0;
/// Create all the parent directories for path; like mkdir -p
/// `basename path`.
bool MakeDirs(const std::string& path);
};
#endif // NINJA_DISK_INTERFACE_H_

View File

@ -23,6 +23,7 @@
#include <string>
#include <vector>
#include "disk_interface.h"
#include "eval_env.h"
#include "stat_cache.h"
@ -33,32 +34,6 @@ struct FileStat;
struct Node;
struct Rule;
/// Interface for accessing the disk.
///
/// Abstract so it can be mocked out for tests. The real implementation
/// is RealDiskInterface.
struct DiskInterface {
virtual ~DiskInterface() {}
/// stat() a file, returning the mtime, or 0 if missing and -1 on
/// other errors.
virtual int Stat(const string& path) = 0;
/// Create a directory, returning false on failure.
virtual bool MakeDir(const string& path) = 0;
/// Read a file to a string. Fill in |err| on error.
virtual string ReadFile(const string& path, string* err) = 0;
/// Remove the file named @a path. It behaves like 'rm -f path' so no errors
/// are reported if it does not exists.
/// @returns 0 if the file has been removed,
/// 1 if the file does not exist, and
/// -1 if an error occurs.
virtual int RemoveFile(const string& path) = 0;
/// Create all the parent directories for path; like mkdir -p
/// `basename path`.
bool MakeDirs(const string& path);
};
/// Implementation of DiskInterface that actually hits the disk.
struct RealDiskInterface : public DiskInterface {
virtual ~RealDiskInterface() {}

View File

@ -41,39 +41,6 @@ int RealDiskInterface::Stat(const string& path) {
return true;
}
string DirName(const string& path) {
#ifdef WIN32
const char kPathSeparator = '\\';
#else
const char kPathSeparator = '/';
#endif
string::size_type slash_pos = path.rfind(kPathSeparator);
if (slash_pos == string::npos)
return ""; // Nothing to do.
while (slash_pos > 0 && path[slash_pos - 1] == kPathSeparator)
--slash_pos;
return path.substr(0, slash_pos);
}
bool DiskInterface::MakeDirs(const string& path) {
string dir = DirName(path);
if (dir.empty())
return true; // Reached root; assume it's there.
int mtime = Stat(dir);
if (mtime < 0)
return false; // Error.
if (mtime > 0)
return true; // Exists already; we're done.
// Directory doesn't exist. Try creating its parent first.
bool success = MakeDirs(dir);
if (!success)
return false;
return MakeDir(dir);
}
string RealDiskInterface::ReadFile(const string& path, string* err) {
string contents;
int ret = ::ReadFile(path, &contents, err);