Skip to content

Commit

Permalink
Allow backslash (\) in filenames on Linux and macOS (fix aseprite#3936)
Browse files Browse the repository at this point in the history
We required a new app.os object to skip some tests on non-Windows
platforms when we check for backslashes in app.fs functions.
  • Loading branch information
dacap committed May 8, 2024
1 parent 30a4000 commit 763f5a6
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 25 deletions.
2 changes: 1 addition & 1 deletion laf
Submodule laf updated 1 files
+5 −1 base/fs.cpp
1 change: 1 addition & 0 deletions src/app/CMakeLists.txt
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/app/script/api_version.h
Expand Up @@ -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
121 changes: 121 additions & 0 deletions src/app/script/app_os_object.cpp
@@ -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
2 changes: 2 additions & 0 deletions src/app/script/engine.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
44 changes: 25 additions & 19 deletions src/updater/user_agent.cpp
Expand Up @@ -19,60 +19,66 @@

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

// ----------------------------------------------------------------------
// 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();
}

Expand Down
2 changes: 2 additions & 0 deletions src/updater/user_agent.h
@@ -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
Expand All @@ -12,6 +13,7 @@

namespace updater {

std::string getFullOSString();
std::string getUserAgent();

} // namespace updater
Expand Down
16 changes: 12 additions & 4 deletions tests/scripts/app_fs.lua
Expand Up @@ -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'))
Expand Down

0 comments on commit 763f5a6

Please sign in to comment.