Allow backslash (\) in filenames on Linux and macOS (fix #3936)

We required a new app.os object to skip some tests on non-Windows
platforms when we check for backslashes in app.fs functions.
This commit is contained in:
David Capello 2024-05-08 14:16:29 -03:00
parent 30a4000c7c
commit 6f09bde511
8 changed files with 165 additions and 25 deletions

2
laf

@ -1 +1 @@
Subproject commit 310350422e483c4b401d7eb9f1d7a647825149aa
Subproject commit c556ff98009d06041e2ab99eeb9464233f137725

View File

@ -161,6 +161,7 @@ if(ENABLE_SCRIPTING)
commands/cmd_run_script.cpp
script/app_command_object.cpp
script/app_fs_object.cpp
script/app_os_object.cpp
script/app_object.cpp
script/app_theme_object.cpp
script/brush_class.cpp

View File

@ -10,6 +10,6 @@
// Increment this value if the scripting API is modified between two
// released Aseprite versions.
#define API_VERSION 27
#define API_VERSION 28
#endif

View File

@ -0,0 +1,121 @@
// Aseprite
// Copyright (C) 2024 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/script/engine.h"
#include "app/script/luacpp.h"
#include "base/config.h"
#include "base/platform.h"
#include "updater/user_agent.h"
namespace app {
namespace script {
namespace {
struct AppOS { };
int AppOS_get_name(lua_State* L)
{
#if LAF_WINDOWS
lua_pushstring(L, "Windows");
#elif LAF_MACOS
lua_pushstring(L, "macOS");
#elif LAF_LINUX
lua_pushstring(L, "Linux");
#else
lua_pushnil(L);
#endif
return 1;
}
int AppOS_get_version(lua_State* L)
{
base::Platform p = base::get_platform();
push_version(L, p.osVer);
return 1;
}
int AppOS_get_fullName(lua_State* L)
{
lua_pushstring(L, updater::getFullOSString().c_str());
return 1;
}
int AppOS_get_windows(lua_State* L)
{
lua_pushboolean(L, base::Platform::os == base::Platform::OS::Windows);
return 1;
}
int AppOS_get_macos(lua_State* L)
{
lua_pushboolean(L, base::Platform::os == base::Platform::OS::macOS);
return 1;
}
int AppOS_get_linux(lua_State* L)
{
lua_pushboolean(L, base::Platform::os == base::Platform::OS::Linux);
return 1;
}
int AppOS_get_x64(lua_State* L)
{
lua_pushboolean(L, base::Platform::arch == base::Platform::Arch::x64);
return 1;
}
int AppOS_get_x86(lua_State* L)
{
lua_pushboolean(L, base::Platform::arch == base::Platform::Arch::x86);
return 1;
}
int AppOS_get_arm64(lua_State* L)
{
lua_pushboolean(L, base::Platform::arch == base::Platform::Arch::arm64);
return 1;
}
const Property AppOS_properties[] = {
{ "name", AppOS_get_name, nullptr },
{ "version", AppOS_get_version, nullptr },
{ "fullName", AppOS_get_fullName, nullptr },
{ "windows", AppOS_get_windows, nullptr },
{ "macos", AppOS_get_macos, nullptr },
{ "linux", AppOS_get_linux, nullptr },
{ "x64", AppOS_get_x64, nullptr },
{ "x86", AppOS_get_x86, nullptr },
{ "arm64", AppOS_get_arm64, nullptr },
{ nullptr, nullptr, nullptr }
};
const luaL_Reg AppOS_methods[] = {
{ nullptr, nullptr }
};
} // anonymous namespace
DEF_MTNAME(AppOS);
void register_app_os_object(lua_State* L)
{
REG_CLASS(L, AppOS);
REG_CLASS_PROPERTIES(L, AppOS);
lua_getglobal(L, "app");
lua_pushstring(L, "os");
push_new<AppOS>(L);
lua_rawset(L, -3);
lua_pop(L, 1);
}
} // namespace script
} // namespace app

View File

@ -165,6 +165,7 @@ int os_clock(lua_State* L)
void register_app_object(lua_State* L);
void register_app_pixel_color_object(lua_State* L);
void register_app_fs_object(lua_State* L);
void register_app_os_object(lua_State* L);
void register_app_command_object(lua_State* L);
void register_app_preferences_object(lua_State* L);
void register_json_object(lua_State* L);
@ -259,6 +260,7 @@ Engine::Engine()
register_app_object(L);
register_app_pixel_color_object(L);
register_app_fs_object(L);
register_app_os_object(L);
register_app_command_object(L);
register_app_preferences_object(L);
register_json_object(L);

View File

@ -19,45 +19,42 @@
namespace updater {
std::string getUserAgent()
std::string getFullOSString()
{
base::Platform p = base::get_platform();
std::stringstream userAgent;
// App name and version
userAgent << get_app_name() << "/" << get_app_version() << " (";
std::stringstream os;
#if LAF_WINDOWS
// ----------------------------------------------------------------------
// Windows
userAgent << "Windows";
os << "Windows";
switch (p.windowsType) {
case base::Platform::WindowsType::Server:
userAgent << " Server";
os << " Server";
break;
case base::Platform::WindowsType::NT:
userAgent << " NT";
os << " NT";
break;
}
userAgent << " " << p.osVer.str();
os << " " << p.osVer.str();
if (p.servicePack.major() > 0)
userAgent << " SP" << p.servicePack.major();
os << " SP" << p.servicePack.major();
if (p.isWow64)
userAgent << "; WOW64";
os << "; WOW64";
if (p.wineVer)
userAgent << "; Wine " << p.wineVer;
os << "; Wine " << p.wineVer;
#elif LAF_MACOS
userAgent << "macOS "
<< p.osVer.major() << "."
<< p.osVer.minor() << "."
<< p.osVer.patch();
os << "macOS "
<< p.osVer.major() << "."
<< p.osVer.minor() << "."
<< p.osVer.patch();
#else
@ -65,14 +62,23 @@ std::string getUserAgent()
// Unix like
if (!p.distroName.empty()) {
userAgent << p.distroName;
os << p.distroName;
if (!p.distroVer.empty())
userAgent << " " << p.distroVer;
os << " " << p.distroVer;
}
#endif
userAgent << ")";
return os.str();
}
std::string getUserAgent()
{
std::stringstream userAgent;
// App name and version
userAgent << get_app_name() << "/" << get_app_version()
<< " (" << getFullOSString() << ")";
return userAgent.str();
}

View File

@ -1,4 +1,5 @@
// Aseprite
// Copyright (C) 2024 Igara Studio S.A.
// Copyright (C) 2001-2015 David Capello
//
// This program is distributed under the terms of
@ -12,6 +13,7 @@
namespace updater {
std::string getFullOSString();
std::string getUserAgent();
} // namespace updater

View File

@ -8,21 +8,29 @@ local sep = fs.pathSeparator
assert('' == fs.filePath('first.png'))
assert('path' == fs.filePath('path/second.png'))
assert('C:\\path' == fs.filePath('C:\\path\\third.png'))
if app.os.windows then
assert('C:\\path' == fs.filePath('C:\\path\\third.png'))
end
assert('first.png' == fs.fileName('first.png'))
assert('second.png' == fs.fileName('path/second.png'))
assert('third.png' == fs.fileName('C:\\path\\third.png'))
if app.os.windows then
assert('third.png' == fs.fileName('C:\\path\\third.png'))
end
assert('png' == fs.fileExtension('path/file.png'))
assert('first' == fs.fileTitle('first.png'))
assert('second' == fs.fileTitle('path/second.png'))
assert('third' == fs.fileTitle('C:\\path\\third.png'))
if app.os.windows then
assert('third' == fs.fileTitle('C:\\path\\third.png'))
end
assert('first' == fs.filePathAndTitle('first.png'))
assert('path/second' == fs.filePathAndTitle('path/second.png'))
assert('C:\\path\\third' == fs.filePathAndTitle('C:\\path\\third.png'))
if app.os.windows then
assert('C:\\path\\third' == fs.filePathAndTitle('C:\\path\\third.png'))
end
assert('hi/bye' == fs.joinPath('hi/', 'bye'))
assert('hi/bye' .. sep .. 'smth.png' == fs.joinPath('hi/', 'bye', 'smth.png'))