Files
roro9stack/src/services/gitea_releases.h
T
twislaandClaude Sonnet 5.5 510ce42a99 Updates from Gitea, step 3: install from Gitea, and IRC steps aside for it
A release downloads straight into the inactive slot through the existing
install path: the signature is checked after 160 bytes, before anything
is written, the hash at the end. Tried on the device against the real
server: a download cut short, a flipped byte in the signature and one in
the image are each refused with the running firmware untouched; the real
v0.10.0 installed, restarted, and confirmed itself on Probation.

A TLS connection to Gitea peaks at about 52 KB of heap whether or not the
certificate is verified. With IRC connected (66 KB free) a check left 3 KB
and a download 836 bytes. A check, list or install a person asks for now
makes IRC step aside (holdForUpdate) and come back after: the lowest free
heap during a full download with IRC connected is 38 KB. The daily check
never interrupts IRC; with IRC up it waits. A TLS connection starts with
80 KB free (it was 55).

Debug Builds get test knobs: update probe <host>, update damage cut|flip,
update pretend <version>.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-06 15:51:10 +02:00

49 lines
1.6 KiB
C++

#pragma once
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
#include <string>
#include <vector>
#include "release_info.h"
namespace roro {
// What the device knows of the project's releases on Gitea (docs/milestones/R1.md, #6): the latest,
// and a list of the last ten. The fetching runs on the Update Service's task; the screens read what
// came out, from the main loop.
class GiteaReleases {
public:
enum class Status : uint8_t { Never, Busy, Done, Failed };
static constexpr size_t kListSize = 10;
GiteaReleases() : lock_(xSemaphoreCreateMutex()) {}
// On the Update Service's task. True when the answer was read; otherwise error() says why.
bool fetchLatest();
bool fetchList();
void fail(const std::string& error) { finish(false, error); } // something stopped it before it began
Status status() const;
std::string error() const;
uint32_t seq() const; // grows with every answer that changed something
bool latest(release::Release& out) const; // false: not fetched yet
std::vector<release::Release> list() const;
bool find(const std::string& tag, release::Release& out) const; // in the list, or the latest
private:
bool fetch(const std::string& path, size_t max, std::vector<release::Release>& out);
void finish(bool ok, const std::string& error);
mutable SemaphoreHandle_t lock_;
Status status_ = Status::Never;
std::string error_;
uint32_t seq_ = 0;
bool haveLatest_ = false;
release::Release latest_;
std::vector<release::Release> list_;
};
} // namespace roro