C#: Unify project name handling and fix issues with the handling of some special characters
Co-authored-by: Raul Santos <raulsntos@gmail.com>
This commit is contained in:
parent
33957aee69
commit
92f13ba9ea
|
@ -67,14 +67,6 @@ String ProjectSettings::get_resource_path() const {
|
||||||
return resource_path;
|
return resource_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ProjectSettings::get_safe_project_name() const {
|
|
||||||
String safe_name = OS::get_singleton()->get_safe_dir_name(get("application/config/name"));
|
|
||||||
if (safe_name.is_empty()) {
|
|
||||||
safe_name = "UnnamedProject";
|
|
||||||
}
|
|
||||||
return safe_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
String ProjectSettings::get_imported_files_path() const {
|
String ProjectSettings::get_imported_files_path() const {
|
||||||
return get_project_data_path().path_join("imported");
|
return get_project_data_path().path_join("imported");
|
||||||
}
|
}
|
||||||
|
@ -930,10 +922,26 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const RBMap<Str
|
||||||
}
|
}
|
||||||
|
|
||||||
Error ProjectSettings::_save_custom_bnd(const String &p_file) { // add other params as dictionary and array?
|
Error ProjectSettings::_save_custom_bnd(const String &p_file) { // add other params as dictionary and array?
|
||||||
|
|
||||||
return save_custom(p_file);
|
return save_custom(p_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
bool _csproj_exists(String p_root_dir) {
|
||||||
|
Ref<DirAccess> dir = DirAccess::open(p_root_dir);
|
||||||
|
|
||||||
|
dir->list_dir_begin();
|
||||||
|
String file_name = dir->_get_next();
|
||||||
|
while (file_name != "") {
|
||||||
|
if (!dir->current_is_dir() && file_name.get_extension() == "csproj") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
file_name = dir->_get_next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_custom, const Vector<String> &p_custom_features, bool p_merge_with_current) {
|
Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_custom, const Vector<String> &p_custom_features, bool p_merge_with_current) {
|
||||||
ERR_FAIL_COND_V_MSG(p_path.is_empty(), ERR_INVALID_PARAMETER, "Project settings save path cannot be empty.");
|
ERR_FAIL_COND_V_MSG(p_path.is_empty(), ERR_INVALID_PARAMETER, "Project settings save path cannot be empty.");
|
||||||
|
|
||||||
|
@ -952,7 +960,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for the existence of a csproj file.
|
// Check for the existence of a csproj file.
|
||||||
if (FileAccess::exists(get_resource_path().path_join(get_safe_project_name() + ".csproj"))) {
|
if (_csproj_exists(get_resource_path())) {
|
||||||
// If there is a csproj file, add the C# feature if it doesn't already exist.
|
// If there is a csproj file, add the C# feature if it doesn't already exist.
|
||||||
if (!project_features.has("C#")) {
|
if (!project_features.has("C#")) {
|
||||||
project_features.append("C#");
|
project_features.append("C#");
|
||||||
|
|
|
@ -166,7 +166,6 @@ public:
|
||||||
String get_project_data_dir_name() const;
|
String get_project_data_dir_name() const;
|
||||||
String get_project_data_path() const;
|
String get_project_data_path() const;
|
||||||
String get_resource_path() const;
|
String get_resource_path() const;
|
||||||
String get_safe_project_name() const;
|
|
||||||
String get_imported_files_path() const;
|
String get_imported_files_path() const;
|
||||||
|
|
||||||
static ProjectSettings *get_singleton();
|
static ProjectSettings *get_singleton();
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
#include "signal_awaiter_utils.h"
|
#include "signal_awaiter_utils.h"
|
||||||
#include "utils/macros.h"
|
#include "utils/macros.h"
|
||||||
#include "utils/naming_utils.h"
|
#include "utils/naming_utils.h"
|
||||||
|
#include "utils/path_utils.h"
|
||||||
#include "utils/string_utils.h"
|
#include "utils/string_utils.h"
|
||||||
|
|
||||||
#define CACHED_STRING_NAME(m_var) (CSharpLanguage::get_singleton()->get_string_names().m_var)
|
#define CACHED_STRING_NAME(m_var) (CSharpLanguage::get_singleton()->get_string_names().m_var)
|
||||||
|
@ -740,11 +741,7 @@ bool CSharpLanguage::is_assembly_reloading_needed() {
|
||||||
return false; // Already up to date
|
return false; // Already up to date
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String assembly_name = GLOBAL_GET("dotnet/project/assembly_name");
|
String assembly_name = path::get_csharp_project_name();
|
||||||
|
|
||||||
if (assembly_name.is_empty()) {
|
|
||||||
assembly_name = ProjectSettings::get_singleton()->get_safe_project_name();
|
|
||||||
}
|
|
||||||
|
|
||||||
assembly_path = GodotSharpDirs::get_res_temp_assemblies_dir()
|
assembly_path = GodotSharpDirs::get_res_temp_assemblies_dir()
|
||||||
.path_join(assembly_name + ".dll");
|
.path_join(assembly_name + ".dll");
|
||||||
|
|
|
@ -57,27 +57,5 @@ namespace GodotTools.Core
|
||||||
path.StartsWith("\\", StringComparison.Ordinal) ||
|
path.StartsWith("\\", StringComparison.Ordinal) ||
|
||||||
path.StartsWith(_driveRoot, StringComparison.Ordinal);
|
path.StartsWith(_driveRoot, StringComparison.Ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ToSafeDirName(this string dirName, bool allowDirSeparator = false)
|
|
||||||
{
|
|
||||||
var invalidChars = new List<string> { ":", "*", "?", "\"", "<", ">", "|" };
|
|
||||||
|
|
||||||
if (allowDirSeparator)
|
|
||||||
{
|
|
||||||
// Directory separators are allowed, but disallow ".." to avoid going up the filesystem
|
|
||||||
invalidChars.Add("..");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
invalidChars.Add("/");
|
|
||||||
}
|
|
||||||
|
|
||||||
string safeDirName = dirName.Replace("\\", "/").Trim();
|
|
||||||
|
|
||||||
foreach (string invalidChar in invalidChars)
|
|
||||||
safeDirName = safeDirName.Replace(invalidChar, "-");
|
|
||||||
|
|
||||||
return safeDirName;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,7 @@ namespace GodotTools.Export
|
||||||
string ridOS = DetermineRuntimeIdentifierOS(platform);
|
string ridOS = DetermineRuntimeIdentifierOS(platform);
|
||||||
string ridArch = DetermineRuntimeIdentifierArch(arch);
|
string ridArch = DetermineRuntimeIdentifierArch(arch);
|
||||||
string runtimeIdentifier = $"{ridOS}-{ridArch}";
|
string runtimeIdentifier = $"{ridOS}-{ridArch}";
|
||||||
string projectDataDirName = $"{DetermineDataDirNameForProject()}_{arch}";
|
string projectDataDirName = $"data_{GodotSharpDirs.CSharpProjectName}_{arch}";
|
||||||
if (platform == OS.Platforms.MacOS)
|
if (platform == OS.Platforms.MacOS)
|
||||||
{
|
{
|
||||||
projectDataDirName = Path.Combine("Contents", "Resources", projectDataDirName);
|
projectDataDirName = Path.Combine("Contents", "Resources", projectDataDirName);
|
||||||
|
@ -258,12 +258,5 @@ namespace GodotTools.Export
|
||||||
platform = null;
|
platform = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string DetermineDataDirNameForProject()
|
|
||||||
{
|
|
||||||
string appName = (string)ProjectSettings.GetSetting("application/config/name");
|
|
||||||
string appNameSafe = appName.ToSafeDirName();
|
|
||||||
return $"data_{appNameSafe}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,21 +48,23 @@ namespace GodotTools.Internals
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string CSharpProjectName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Internal.godot_icall_GodotSharpDirs_CSharpProjectName(out godot_string dest);
|
||||||
|
using (dest)
|
||||||
|
return Marshaling.ConvertStringToManaged(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void DetermineProjectLocation()
|
public static void DetermineProjectLocation()
|
||||||
{
|
{
|
||||||
static string DetermineProjectName()
|
|
||||||
{
|
|
||||||
string projectAssemblyName = (string)ProjectSettings.GetSetting("application/config/name");
|
|
||||||
projectAssemblyName = projectAssemblyName.ToSafeDirName();
|
|
||||||
if (string.IsNullOrEmpty(projectAssemblyName))
|
|
||||||
projectAssemblyName = "UnnamedProject";
|
|
||||||
return projectAssemblyName;
|
|
||||||
}
|
|
||||||
|
|
||||||
_projectAssemblyName = (string)ProjectSettings.GetSetting("dotnet/project/assembly_name");
|
_projectAssemblyName = (string)ProjectSettings.GetSetting("dotnet/project/assembly_name");
|
||||||
if (string.IsNullOrEmpty(_projectAssemblyName))
|
if (string.IsNullOrEmpty(_projectAssemblyName))
|
||||||
{
|
{
|
||||||
_projectAssemblyName = DetermineProjectName();
|
_projectAssemblyName = CSharpProjectName;
|
||||||
ProjectSettings.SetSetting("dotnet/project/assembly_name", _projectAssemblyName);
|
ProjectSettings.SetSetting("dotnet/project/assembly_name", _projectAssemblyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,8 @@ namespace GodotTools.Internals
|
||||||
|
|
||||||
public static partial void godot_icall_GodotSharpDirs_DataEditorToolsDir(out godot_string r_dest);
|
public static partial void godot_icall_GodotSharpDirs_DataEditorToolsDir(out godot_string r_dest);
|
||||||
|
|
||||||
|
public static partial void godot_icall_GodotSharpDirs_CSharpProjectName(out godot_string r_dest);
|
||||||
|
|
||||||
public static partial void godot_icall_EditorProgress_Create(in godot_string task, in godot_string label,
|
public static partial void godot_icall_EditorProgress_Create(in godot_string task, in godot_string label,
|
||||||
int amount, bool canCancel);
|
int amount, bool canCancel);
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "../csharp_script.h"
|
#include "../csharp_script.h"
|
||||||
#include "../godotsharp_dirs.h"
|
#include "../godotsharp_dirs.h"
|
||||||
#include "../utils/macos_utils.h"
|
#include "../utils/macos_utils.h"
|
||||||
|
#include "../utils/path_utils.h"
|
||||||
#include "code_completion.h"
|
#include "code_completion.h"
|
||||||
|
|
||||||
#include "../interop_types.h"
|
#include "../interop_types.h"
|
||||||
|
@ -81,6 +82,10 @@ void godot_icall_GodotSharpDirs_DataEditorToolsDir(godot_string *r_dest) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void godot_icall_GodotSharpDirs_CSharpProjectName(godot_string *r_dest) {
|
||||||
|
memnew_placement(r_dest, String(path::get_csharp_project_name()));
|
||||||
|
}
|
||||||
|
|
||||||
void godot_icall_EditorProgress_Create(const godot_string *p_task, const godot_string *p_label, int32_t p_amount, bool p_can_cancel) {
|
void godot_icall_EditorProgress_Create(const godot_string *p_task, const godot_string *p_label, int32_t p_amount, bool p_can_cancel) {
|
||||||
String task = *reinterpret_cast<const String *>(p_task);
|
String task = *reinterpret_cast<const String *>(p_task);
|
||||||
String label = *reinterpret_cast<const String *>(p_label);
|
String label = *reinterpret_cast<const String *>(p_label);
|
||||||
|
@ -231,6 +236,7 @@ static const void *unmanaged_callbacks[]{
|
||||||
(void *)godot_icall_GodotSharpDirs_MonoUserDir,
|
(void *)godot_icall_GodotSharpDirs_MonoUserDir,
|
||||||
(void *)godot_icall_GodotSharpDirs_BuildLogsDirs,
|
(void *)godot_icall_GodotSharpDirs_BuildLogsDirs,
|
||||||
(void *)godot_icall_GodotSharpDirs_DataEditorToolsDir,
|
(void *)godot_icall_GodotSharpDirs_DataEditorToolsDir,
|
||||||
|
(void *)godot_icall_GodotSharpDirs_CSharpProjectName,
|
||||||
(void *)godot_icall_EditorProgress_Create,
|
(void *)godot_icall_EditorProgress_Create,
|
||||||
(void *)godot_icall_EditorProgress_Dispose,
|
(void *)godot_icall_EditorProgress_Dispose,
|
||||||
(void *)godot_icall_EditorProgress_Step,
|
(void *)godot_icall_EditorProgress_Step,
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "mono_gd/gd_mono.h"
|
#include "mono_gd/gd_mono.h"
|
||||||
|
#include "utils/path_utils.h"
|
||||||
|
|
||||||
namespace GodotSharpDirs {
|
namespace GodotSharpDirs {
|
||||||
|
|
||||||
|
@ -139,8 +140,7 @@ private:
|
||||||
api_assemblies_dir = api_assemblies_base_dir.path_join(GDMono::get_expected_api_build_config());
|
api_assemblies_dir = api_assemblies_base_dir.path_join(GDMono::get_expected_api_build_config());
|
||||||
#else // TOOLS_ENABLED
|
#else // TOOLS_ENABLED
|
||||||
String arch = Engine::get_singleton()->get_architecture_name();
|
String arch = Engine::get_singleton()->get_architecture_name();
|
||||||
String appname = GLOBAL_GET("application/config/name");
|
String appname_safe = path::get_csharp_project_name();
|
||||||
String appname_safe = OS::get_singleton()->get_safe_dir_name(appname);
|
|
||||||
String data_dir_root = exe_dir.path_join("data_" + appname_safe + "_" + arch);
|
String data_dir_root = exe_dir.path_join("data_" + appname_safe + "_" + arch);
|
||||||
if (!DirAccess::exists(data_dir_root)) {
|
if (!DirAccess::exists(data_dir_root)) {
|
||||||
data_dir_root = exe_dir.path_join("data_Godot_" + arch);
|
data_dir_root = exe_dir.path_join("data_Godot_" + arch);
|
||||||
|
|
|
@ -293,20 +293,10 @@ godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime
|
||||||
return godot_plugins_initialize;
|
return godot_plugins_initialize;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static String get_assembly_name() {
|
|
||||||
String assembly_name = GLOBAL_GET("dotnet/project/assembly_name");
|
|
||||||
|
|
||||||
if (assembly_name.is_empty()) {
|
|
||||||
assembly_name = ProjectSettings::get_singleton()->get_safe_project_name();
|
|
||||||
}
|
|
||||||
|
|
||||||
return assembly_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime_initialized) {
|
godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime_initialized) {
|
||||||
godot_plugins_initialize_fn godot_plugins_initialize = nullptr;
|
godot_plugins_initialize_fn godot_plugins_initialize = nullptr;
|
||||||
|
|
||||||
String assembly_name = get_assembly_name();
|
String assembly_name = path::get_csharp_project_name();
|
||||||
|
|
||||||
HostFxrCharString assembly_path = str_to_hostfxr(GodotSharpDirs::get_api_assemblies_dir()
|
HostFxrCharString assembly_path = str_to_hostfxr(GodotSharpDirs::get_api_assemblies_dir()
|
||||||
.path_join(assembly_name + ".dll"));
|
.path_join(assembly_name + ".dll"));
|
||||||
|
@ -331,7 +321,7 @@ godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime
|
||||||
}
|
}
|
||||||
|
|
||||||
godot_plugins_initialize_fn try_load_native_aot_library(void *&r_aot_dll_handle) {
|
godot_plugins_initialize_fn try_load_native_aot_library(void *&r_aot_dll_handle) {
|
||||||
String assembly_name = get_assembly_name();
|
String assembly_name = path::get_csharp_project_name();
|
||||||
|
|
||||||
#if defined(WINDOWS_ENABLED)
|
#if defined(WINDOWS_ENABLED)
|
||||||
String native_aot_so_path = GodotSharpDirs::get_api_assemblies_dir().path_join(assembly_name + ".dll");
|
String native_aot_so_path = GodotSharpDirs::get_api_assemblies_dir().path_join(assembly_name + ".dll");
|
||||||
|
@ -476,11 +466,7 @@ void GDMono::_init_godot_api_hashes() {
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
bool GDMono::_load_project_assembly() {
|
bool GDMono::_load_project_assembly() {
|
||||||
String assembly_name = GLOBAL_GET("dotnet/project/assembly_name");
|
String assembly_name = path::get_csharp_project_name();
|
||||||
|
|
||||||
if (assembly_name.is_empty()) {
|
|
||||||
assembly_name = ProjectSettings::get_singleton()->get_safe_project_name();
|
|
||||||
}
|
|
||||||
|
|
||||||
String assembly_path = GodotSharpDirs::get_res_temp_assemblies_dir()
|
String assembly_path = GodotSharpDirs::get_res_temp_assemblies_dir()
|
||||||
.path_join(assembly_name + ".dll");
|
.path_join(assembly_name + ".dll");
|
||||||
|
|
|
@ -231,4 +231,27 @@ String relative_to(const String &p_path, const String &p_relative_to) {
|
||||||
|
|
||||||
return relative_to_impl(path_abs_norm, relative_to_abs_norm);
|
return relative_to_impl(path_abs_norm, relative_to_abs_norm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String get_csharp_project_name() {
|
||||||
|
String name = ProjectSettings::get_singleton()->get_setting_with_override("dotnet/project/assembly_name");
|
||||||
|
if (name.is_empty()) {
|
||||||
|
name = ProjectSettings::get_singleton()->get_setting_with_override("application/config/name");
|
||||||
|
Vector<String> invalid_chars = Vector<String>({ //
|
||||||
|
// Windows reserved filename chars.
|
||||||
|
":", "*", "?", "\"", "<", ">", "|",
|
||||||
|
// Directory separators.
|
||||||
|
"/", "\\",
|
||||||
|
// Other chars that have been found to break assembly loading.
|
||||||
|
";", "'", "=", "," });
|
||||||
|
name = name.strip_edges();
|
||||||
|
for (int i = 0; i < invalid_chars.size(); i++) {
|
||||||
|
name = name.replace(invalid_chars[i], "-");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (name.is_empty()) {
|
||||||
|
name = "UnnamedProject";
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace path
|
} // namespace path
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#ifndef MONO_PATH_UTILS_H
|
#ifndef MONO_PATH_UTILS_H
|
||||||
#define MONO_PATH_UTILS_H
|
#define MONO_PATH_UTILS_H
|
||||||
|
|
||||||
#include "core/string/string_builder.h"
|
|
||||||
#include "core/string/ustring.h"
|
#include "core/string/ustring.h"
|
||||||
|
|
||||||
namespace path {
|
namespace path {
|
||||||
|
@ -58,6 +57,8 @@ String abspath(const String &p_path);
|
||||||
String realpath(const String &p_path);
|
String realpath(const String &p_path);
|
||||||
|
|
||||||
String relative_to(const String &p_path, const String &p_relative_to);
|
String relative_to(const String &p_path, const String &p_relative_to);
|
||||||
|
|
||||||
|
String get_csharp_project_name();
|
||||||
} // namespace path
|
} // namespace path
|
||||||
|
|
||||||
#endif // MONO_PATH_UTILS_H
|
#endif // MONO_PATH_UTILS_H
|
||||||
|
|
Loading…
Reference in New Issue