Skip to content

Commit 3efdaf3

Browse files
committed
Add function to create a temporary directory
1 parent b11d33f commit 3efdaf3

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

elisp/private/tools/system.cc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,6 +1300,38 @@ absl::Status TemporaryFile::Write(const std::string_view contents) {
13001300
return absl::OkStatus();
13011301
}
13021302

1303+
absl::StatusOr<FileName> CreateTemporaryDirectory() {
1304+
#ifdef _WIN32
1305+
absl::Status status;
1306+
for (int i = 0; i < 10; i++) {
1307+
std::array<wchar_t, L_tmpnam + 1> buffer;
1308+
const wchar_t* absl_nullable name = _wtmpnam(buffer.data());
1309+
if (name == nullptr) {
1310+
return absl::UnavailableError("Cannot create temporary name");
1311+
}
1312+
absl::StatusOr<FileName> result = FileName::FromString(name);
1313+
if (!result.ok()) return result.status();
1314+
status = CreateDirectory(*result);
1315+
if (status.ok()) return *std::move(result);
1316+
LOG(ERROR) << status;
1317+
}
1318+
CHECK(!status.ok());
1319+
return status;
1320+
#else
1321+
const char* const absl_nullable dir = std::getenv("TMPDIR");
1322+
std::string buffer = absl::StrCat(
1323+
dir == nullptr || *dir == '\0' ? "/tmp" : dir, "/elisp.XXXXXX");
1324+
char* const absl_nullable name = mkdtemp(Pointer(buffer));
1325+
if (name == nullptr) return ErrnoStatus("mkdtemp", buffer);
1326+
const absl::StatusOr<FileName> result = FileName::FromString(name);
1327+
if (!result.ok()) {
1328+
if (rmdir(name) != 0) LOG(ERROR) << ErrnoStatus("rmdir", name);
1329+
return result.status();
1330+
}
1331+
return *std::move(result);
1332+
#endif
1333+
}
1334+
13031335
static void FlushEverything() {
13041336
std::cout.flush();
13051337
std::wcout.flush();

elisp/private/tools/system.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,8 @@ class TemporaryFile final {
378378
std::FILE* absl_nullable file_;
379379
};
380380

381+
absl::StatusOr<FileName> CreateTemporaryDirectory();
382+
381383
struct RunOptions final {
382384
// If set, change to this directory in the subprocess.
383385
std::optional<FileName> directory;

tests/tools/system_test.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,19 @@ TEST(TemporaryFileTest, CreateWorks) {
871871
EXPECT_THAT(ReadFile(file->name()), IsOkAndHolds("Foo\n"));
872872
}
873873

874+
TEST(CreateTemporaryDirectoryTest, Works) {
875+
absl::StatusOr<FileName> dir = CreateTemporaryDirectory();
876+
ASSERT_THAT(dir, IsOk());
877+
878+
const absl::Cleanup cleanup = [&dir] {
879+
EXPECT_THAT(RemoveTree(*dir), IsOk());
880+
};
881+
882+
FileName file = dir->Child(RULES_ELISP_NATIVE_LITERAL("file")).value();
883+
EXPECT_THAT(WriteFile(file, "contents"), IsOk());
884+
EXPECT_THAT(ReadFile(file), IsOkAndHolds("contents"));
885+
}
886+
874887
[[maybe_unused]] static NativeString GetEnv(const NativeChar* const name) {
875888
const NativeChar* const absl_nullable value =
876889
#ifdef _WIN32

0 commit comments

Comments
 (0)