Refactor app paths

This commit is contained in:
Ken Van Hoeylandt 2025-09-21 18:36:05 +02:00
parent 56bab5897a
commit 07cd32d6b4
9 changed files with 107 additions and 65 deletions

View File

@ -1,8 +1,21 @@
//
// Created by ken on 20/09/2025.
//
#pragma once
#ifndef TACTILITY_PATHS_H
#define TACTILITY_PATHS_H
#include <string>
#endif //TACTILITY_PATHS_H
namespace tt {
bool findFirstMountedSdCardPath(std::string& path);
std::string getSystemRootPath();
std::string getTempPath();
std::string getAppInstallPath();
std::string getAppInstallPath(const std::string& appId);
std::string getUserPath();
std::string getAppUserPath(const std::string& appId);
}

View File

@ -94,9 +94,7 @@ std::shared_ptr<AppContext> _Nullable getCurrentAppContext();
/** @return the currently running app (it is only ever null before the splash screen is shown) */
std::shared_ptr<App> _Nullable getCurrentApp();
std::string getTempPath();
std::string getInstallPath();
bool isValidId(const std::string& id);
bool install(const std::string& path);

View File

@ -72,6 +72,15 @@ struct AppManifest {
/** Optional icon. */
std::string icon = {};
/** Optional description */
std::string description = {};
/** Optional author name */
std::string authorName = {};
/** Optional author website */
std::string authorWebsite = {};
/** App category helps with listing apps in Launcher, app list or settings apps. */
Category category = Category::User;

View File

@ -1,3 +1,54 @@
//
// Created by ken on 20/09/2025.
//
#include <Tactility/Paths.h>
#include <Tactility/app/App.h>
#include <Tactility/MountPoints.h>
#include <Tactility/hal/sdcard/SdCardDevice.h>
namespace tt {
bool findFirstMountedSdCardPath(std::string& path) {
// const auto sdcards = hal::findDevices<hal::sdcard::SdCardDevice>(hal::Device::Type::SdCard);
bool is_set = false;
hal::findDevices<hal::sdcard::SdCardDevice>(hal::Device::Type::SdCard, [&is_set, &path](const auto& device) {
if (device->isMounted()) {
path = device->getMountPath();
is_set = true;
return false; // stop iterating
} else {
return true;
}
});
return is_set;
}
std::string getSystemRootPath() {
std::string root_path;
if (!findFirstMountedSdCardPath(root_path)) {
root_path = file::MOUNT_POINT_DATA;
}
return root_path;
}
std::string getTempPath() {
return getSystemRootPath() + "/tmp";
}
std::string getAppInstallPath() {
return getSystemRootPath() + "/app";
}
std::string getUserPath() {
return getSystemRootPath() + "/user";
}
std::string getAppInstallPath(const std::string& appId) {
assert(app::isValidId(appId));
return std::format("{}/{}", getAppInstallPath(), appId);
}
std::string getAppUserPath(const std::string& appId) {
assert(app::isValidId(appId));
return std::format("{}/app/{}", getUserPath(), appId);
}
}

View File

@ -194,7 +194,7 @@ static void registerInstalledApps(const std::string& path) {
static void registerInstalledAppsFromSdCard(const std::shared_ptr<hal::sdcard::SdCardDevice>& sdcard) {
auto sdcard_root_path = sdcard->getMountPath();
auto app_path = std::format("{}/apps", sdcard_root_path);
auto app_path = std::format("{}/app", sdcard_root_path);
sdcard->getLock()->lock();
if (file::isDirectory(app_path)) {
registerInstalledApps(app_path);

View File

@ -1,3 +1,4 @@
#include <regex>
#include <Tactility/app/App.h>
#include <Tactility/service/loader/Loader.h>
@ -19,4 +20,9 @@ std::shared_ptr<App> _Nullable getCurrentApp() {
return service::loader::getCurrentApp();
}
bool isValidId(const std::string& id) {
const auto pattern = std::regex("^[a-zA-Z0-9_-\\.]+$");
return std::regex_match(id, pattern);
}
}

View File

@ -1,3 +1,5 @@
#include "Tactility/Paths.h"
#include <Tactility/app/App.h>
#include <Tactility/MountPoints.h>
@ -103,44 +105,13 @@ static bool untar(const std::string& tarPath, const std::string& destinationPath
return success;
}
bool findFirstMountedSdCardPath(std::string& path) {
// const auto sdcards = hal::findDevices<hal::sdcard::SdCardDevice>(hal::Device::Type::SdCard);
bool is_set = false;
hal::findDevices<hal::sdcard::SdCardDevice>(hal::Device::Type::SdCard, [&is_set, &path](const auto& device) {
if (device->isMounted()) {
path = device->getMountPath();
is_set = true;
return false; // stop iterating
} else {
return true;
}
});
return is_set;
}
std::string getTempPath() {
std::string root_path;
if (!findFirstMountedSdCardPath(root_path)) {
root_path = file::MOUNT_POINT_DATA;
}
return root_path + "/tmp";
}
std::string getInstallPath() {
std::string root_path;
if (!findFirstMountedSdCardPath(root_path)) {
root_path = file::MOUNT_POINT_DATA;
}
return root_path + "/apps";
}
bool install(const std::string& path) {
// TODO: Make better: lock for each path type properly (source vs target)
// We lock and unlock frequently because SPI SD card devices share
// the lock with the display. We don't want to lock the display for very long.
auto app_parent_path = getInstallPath();
auto app_parent_path = getAppInstallPath();
TT_LOG_I(TAG, "Installing app %s to %s", path.c_str(), app_parent_path.c_str());
auto lock = file::getLock(app_parent_path)->asScopedLock();
@ -225,8 +196,8 @@ bool install(const std::string& path) {
bool uninstall(const std::string& appId) {
TT_LOG_I(TAG, "Uninstalling app %s", appId.c_str());
auto app_path = getInstallPath() + "/" + appId;
return file::withLock<bool>(app_path, [&app_path, &appId]() {
auto app_path = getAppInstallPath(appId);
return file::withLock<bool>(app_path, [&app_path, &appId] {
if (!file::isDirectory(app_path)) {
TT_LOG_E(TAG, "App %s not found at ", app_path.c_str());
return false;

View File

@ -15,24 +15,18 @@ static void mount(const std::shared_ptr<SdCardDevice>& sdcard, const std::string
});
}
static std::string getMountPath(int index, int count) {
return (count == 1) ? TT_SDCARD_MOUNT_POINT : std::format("{}{}", TT_SDCARD_MOUNT_POINT, index);
}
void mountAll() {
auto sdcards = hal::findDevices<SdCardDevice>(Device::Type::SdCard);
if (!sdcards.empty()) {
if (sdcards.size() == 1) {
// Fixed mount path name
auto sdcard = sdcards[0];
if (!sdcard->isMounted()) {
mount(sdcard, TT_SDCARD_MOUNT_POINT);
}
} else {
// Numbered mount path name
for (int i = 0; i < sdcards.size(); i++) {
auto sdcard = sdcards[i];
if (!sdcard->isMounted()) {
std::string mount_path = TT_SDCARD_MOUNT_POINT + std::to_string(i);
mount(sdcard, mount_path);
}
}
// Numbered mount path name
for (int i = 0; i < sdcards.size(); i++) {
auto sdcard = sdcards[i];
if (!sdcard->isMounted() && sdcard->getMountBehaviour() == SdCardDevice::MountBehaviour::AtBoot) {
std::string mount_path = getMountPath(i, sdcards.size());
mount(sdcard, mount_path);
}
}
}

View File

@ -4,10 +4,10 @@
#include <Tactility/app/App.h>
#include <Tactility/app/AppRegistration.h>
#include <Tactility/app/ElfApp.h>
#include <Tactility/file/File.h>
#include <Tactility/network/HttpdReq.h>
#include <Tactility/network/Url.h>
#include <Tactility/Paths.h>
#include <Tactility/service/development/DevelopmentSettings.h>
#include <Tactility/service/ServiceManifest.h>
#include <Tactility/service/ServiceRegistration.h>
@ -247,7 +247,7 @@ esp_err_t DevelopmentService::handleAppInstall(httpd_req_t* request) {
}
content_left -= content_read;
const std::string tmp_path = app::getTempPath();
const std::string tmp_path = getTempPath();
auto lock = file::getLock(tmp_path)->asScopedLock();
lock.lock();