1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 06:27:45 +00:00

HackStudio: Convert ProjectTemplate::create_project to ErrorOr

This lets us also use the Core::System APIs, which reduces the amount of
error checking code.
This commit is contained in:
Sam Atkins 2024-01-11 16:45:22 +00:00 committed by Andrew Kaster
parent 63c6eae918
commit 16543a1918
2 changed files with 11 additions and 22 deletions

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2021, Nick Vella <nick@nxk.io> * Copyright (c) 2021, Nick Vella <nick@nxk.io>
* Copyright (c) 2024, Sam Atkins <atkinssj@serenityos.org>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
@ -10,6 +11,7 @@
#include <AK/StringBuilder.h> #include <AK/StringBuilder.h>
#include <LibCore/ConfigFile.h> #include <LibCore/ConfigFile.h>
#include <LibCore/DirIterator.h> #include <LibCore/DirIterator.h>
#include <LibCore/System.h>
#include <LibFileSystem/FileSystem.h> #include <LibFileSystem/FileSystem.h>
#include <fcntl.h> #include <fcntl.h>
#include <spawn.h> #include <spawn.h>
@ -61,27 +63,22 @@ RefPtr<ProjectTemplate> ProjectTemplate::load_from_manifest(ByteString const& ma
return adopt_ref(*new ProjectTemplate(id, name, description, icon, priority)); return adopt_ref(*new ProjectTemplate(id, name, description, icon, priority));
} }
Result<void, ByteString> ProjectTemplate::create_project(ByteString const& name, ByteString const& path) ErrorOr<void> ProjectTemplate::create_project(ByteString const& name, ByteString const& path)
{ {
// Check if a file or directory already exists at the project path // Check if a file or directory already exists at the project path
if (FileSystem::exists(path)) if (FileSystem::exists(path))
return ByteString("File or directory already exists at specified location."); return Error::from_string_literal("File or directory already exists at specified location.");
dbgln("Creating project at path '{}' with name '{}'", path, name); dbgln("Creating project at path '{}' with name '{}'", path, name);
// Verify that the template content directory exists. If it does, copy it's contents. // Verify that the template content directory exists. If it does, copy it's contents.
// Otherwise, create an empty directory at the project path. // Otherwise, create an empty directory at the project path.
if (FileSystem::is_directory(content_path())) { if (FileSystem::is_directory(content_path())) {
auto result = FileSystem::copy_file_or_directory(path, content_path());
dbgln("Copying {} -> {}", content_path(), path); dbgln("Copying {} -> {}", content_path(), path);
if (result.is_error()) TRY(FileSystem::copy_file_or_directory(path, content_path()));
return ByteString::formatted("Failed to copy template contents. Error code: {}", static_cast<Error const&>(result.error()));
} else { } else {
dbgln("No template content directory found for '{}', creating an empty directory for the project.", m_id); dbgln("No template content directory found for '{}', creating an empty directory for the project.", m_id);
int rc; TRY(Core::System::mkdir(path, 0755));
if ((rc = mkdir(path.characters(), 0755)) < 0) {
return ByteString::formatted("Failed to mkdir empty project directory, error: {}, rc: {}.", strerror(errno), rc);
}
} }
// Check for an executable post-create script in $TEMPLATES_DIR/$ID.postcreate, // Check for an executable post-create script in $TEMPLATES_DIR/$ID.postcreate,
@ -96,24 +93,17 @@ Result<void, ByteString> ProjectTemplate::create_project(ByteString const& name,
// Generate a namespace-safe project name (replace hyphens with underscores) // Generate a namespace-safe project name (replace hyphens with underscores)
auto namespace_safe = name.replace("-"sv, "_"sv, ReplaceMode::All); auto namespace_safe = name.replace("-"sv, "_"sv, ReplaceMode::All);
pid_t child_pid;
char const* argv[] = { postcreate_script_path.characters(), name.characters(), path.characters(), namespace_safe.characters(), nullptr }; char const* argv[] = { postcreate_script_path.characters(), name.characters(), path.characters(), namespace_safe.characters(), nullptr };
if ((errno = posix_spawn(&child_pid, postcreate_script_path.characters(), nullptr, nullptr, const_cast<char**>(argv), environ))) { pid_t child_pid = TRY(Core::System::posix_spawn(postcreate_script_path, nullptr, nullptr, const_cast<char**>(argv), environ));
perror("posix_spawn");
return ByteString("Failed to spawn project post-create script.");
}
// Command spawned, wait for exit. // Command spawned, wait for exit.
int status; auto waitpid_result = TRY(Core::System::waitpid(child_pid, 0));
if (waitpid(child_pid, &status, 0) < 0) int child_error = WEXITSTATUS(waitpid_result.status);
return ByteString("Failed to spawn project post-create script.");
int child_error = WEXITSTATUS(status);
dbgln("Post-create script exited with code {}", child_error); dbgln("Post-create script exited with code {}", child_error);
if (child_error != 0) if (child_error != 0)
return ByteString("Project post-creation script exited with non-zero error code."); return Error::from_string_literal("Project post-creation script exited with non-zero error code.");
} }
return {}; return {};

View file

@ -10,7 +10,6 @@
#include <AK/ByteString.h> #include <AK/ByteString.h>
#include <AK/LexicalPath.h> #include <AK/LexicalPath.h>
#include <AK/RefCounted.h> #include <AK/RefCounted.h>
#include <AK/Result.h>
#include <AK/Weakable.h> #include <AK/Weakable.h>
#include <LibGUI/Icon.h> #include <LibGUI/Icon.h>
@ -24,7 +23,7 @@ public:
explicit ProjectTemplate(ByteString const& id, ByteString const& name, ByteString const& description, const GUI::Icon& icon, int priority); explicit ProjectTemplate(ByteString const& id, ByteString const& name, ByteString const& description, const GUI::Icon& icon, int priority);
Result<void, ByteString> create_project(ByteString const& name, ByteString const& path); ErrorOr<void> create_project(ByteString const& name, ByteString const& path);
ByteString const& id() const { return m_id; } ByteString const& id() const { return m_id; }
ByteString const& name() const { return m_name; } ByteString const& name() const { return m_name; }