Merge pull request #125 from ddunbar/directory-permissions
[Basic] Introduce a FS method for creating directories.
diff --git a/include/llbuild/Basic/FileSystem.h b/include/llbuild/Basic/FileSystem.h
index 3cf86aa..497f15d 100644
--- a/include/llbuild/Basic/FileSystem.h
+++ b/include/llbuild/Basic/FileSystem.h
@@ -42,6 +42,12 @@
FileSystem() {}
virtual ~FileSystem();
+ /// Create the given directory if it does not exist.
+ ///
+ /// \returns True on success (the directory was created, or already exists).
+ virtual bool
+ createDirectory(const std::string& path) = 0;
+
/// Get a memory buffer for a given file on the file system.
///
/// \returns The file contents, on success, or null on error.
diff --git a/lib/Basic/FileSystem.cpp b/lib/Basic/FileSystem.cpp
index 85ab4f8..b941d51 100644
--- a/lib/Basic/FileSystem.cpp
+++ b/lib/Basic/FileSystem.cpp
@@ -30,6 +30,16 @@
public:
LocalFileSystem() {}
+ virtual bool
+ createDirectory(const std::string& path) override {
+ if (::mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
+ if (errno != EEXIST) {
+ return false;
+ }
+ }
+ return true;
+ }
+
virtual std::unique_ptr<llvm::MemoryBuffer>
getFileContents(const std::string& path) override {
auto result = llvm::MemoryBuffer::getFile(path);
diff --git a/lib/BuildSystem/BuildSystem.cpp b/lib/BuildSystem/BuildSystem.cpp
index 6239b9c..62be1e3 100644
--- a/lib/BuildSystem/BuildSystem.cpp
+++ b/lib/BuildSystem/BuildSystem.cpp
@@ -1871,7 +1871,8 @@
Task* task,
QueueJobContext* context) override {
auto output = getOutputs()[0];
- if (llvm::sys::fs::create_directories(output->getName())) {
+ if (!bsci.getDelegate().getFileSystem().createDirectory(
+ output->getName())) {
getBuildSystem(bsci.getBuildEngine()).error(
"", "unable to create directory '" + output->getName() + "'");
return CommandResult::Failed;
@@ -2079,7 +2080,7 @@
{
auto parent = llvm::sys::path::parent_path(output->getName());
if (!parent.empty()) {
- (void) llvm::sys::fs::create_directories(parent);
+ (void) bsci.getDelegate().getFileSystem().createDirectory(parent);
}
}
diff --git a/products/libllbuild/BuildSystem-C-API.cpp b/products/libllbuild/BuildSystem-C-API.cpp
index e864263..7824c7d 100644
--- a/products/libllbuild/BuildSystem-C-API.cpp
+++ b/products/libllbuild/BuildSystem-C-API.cpp
@@ -46,6 +46,15 @@
: cAPIDelegate(delegate),
localFileSystem(basic::createLocalFileSystem()) { }
+ virtual bool
+ createDirectory(const std::string& path) override {
+ if (!cAPIDelegate.fs_create_directory) {
+ return localFileSystem->createDirectory(path);
+ }
+
+ return cAPIDelegate.fs_create_directory(cAPIDelegate.context, path.c_str());
+ }
+
virtual std::unique_ptr<llvm::MemoryBuffer>
getFileContents(const std::string& path) override {
if (!cAPIDelegate.fs_get_file_contents) {
diff --git a/products/libllbuild/public-api/llbuild/buildsystem.h b/products/libllbuild/public-api/llbuild/buildsystem.h
index a8083b7..c70d266 100644
--- a/products/libllbuild/public-api/llbuild/buildsystem.h
+++ b/products/libllbuild/public-api/llbuild/buildsystem.h
@@ -158,6 +158,11 @@
///
/// @{
+ /// Create the given directory if it does not exist.
+ ///
+ /// \\returns True on success (the directory was created, or already exists).
+ bool (*fs_create_directory)(void* context, const char* path);
+
/// Get the file contents for the given path.
///
/// The contents *MUST* be returned in a new buffer allocated with \see
diff --git a/tests/BuildSystem/Build/Inputs/get-file-permissions b/tests/BuildSystem/Build/Inputs/get-file-permissions
new file mode 100755
index 0000000..cea8af3
--- /dev/null
+++ b/tests/BuildSystem/Build/Inputs/get-file-permissions
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+import os
+import stat
+import sys
+
+print(oct(stat.S_IMODE(os.stat(sys.argv[1]).st_mode)))
diff --git a/tests/BuildSystem/Build/mkdir.llbuild b/tests/BuildSystem/Build/mkdir.llbuild
index a327159..387824d 100644
--- a/tests/BuildSystem/Build/mkdir.llbuild
+++ b/tests/BuildSystem/Build/mkdir.llbuild
@@ -5,11 +5,14 @@
# RUN: cp %s %t.build/build.llbuild
# RUN: %{llbuild} buildsystem build --serial --chdir %t.build > %t.out
# RUN: %{FileCheck} --input-file=%t.out %s
+# RUN: %S/Inputs/get-file-permissions %t.build/subdir/subdir2 > %t.permissions
+# RUN: %{FileCheck} --input-file=%t.permissions --check-prefix=CHECK-PERMISSIONS %s
#
# CHECK: ECHO
# CHECK: MKDIR
# CHECK: MUTATE
# CHECK: TRIGGERED
+# CHECK-PERMISSIONS: 0755
# Check that a null build does nothing.