Compare commits
2 Commits
4153cae9c4
...
8e848894fa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e848894fa | ||
|
|
39e1155bf9 |
@@ -107,13 +107,18 @@ target_compile_options(${COMPONENT_LIB} PRIVATE
|
||||
-Wno-error=implicit-int
|
||||
)
|
||||
|
||||
# FATFS can't do POSIX rename-replace (f_rename fails if the target exists) and
|
||||
# has no hardlinks, so libgit2's p_rename (link-then-rename) can't overwrite the
|
||||
# config/refs/HEAD/index files its lock→commit writes depend on. Compile
|
||||
# posix.c's p_rename under a throwaway name — scoped to this ONE file so no other
|
||||
# TU is touched — and provide our own remove-then-rename p_rename in esp_stubs.c
|
||||
# (p_rename is the single atomic-rename path: filebuf/futils/indexer/refdb_fs).
|
||||
# posix.c holds three low-level fs primitives we must replace for FATFS; compile
|
||||
# the originals under throwaway names — scoped to this ONE file so no other TU is
|
||||
# touched — and provide FATFS-correct versions in esp_stubs.c:
|
||||
# p_rename — FATFS f_rename can't replace an existing target and FAT has no
|
||||
# hardlinks, so libgit2's link-then-rename can't overwrite config/refs/HEAD/
|
||||
# index during its lock→commit. Ours does remove-then-rename.
|
||||
# p_open / p_creat — libgit2 creates objects/packs mode 0444; FATFS turns that
|
||||
# into AM_RDO and then won't f_unlink them (and chmod can't clear it), so
|
||||
# objects become undeletable (breaks re-clone/fetch/repack). Ours force
|
||||
# owner-write so nothing is ever created read-only.
|
||||
set_source_files_properties(
|
||||
"${LG2}/src/util/posix.c"
|
||||
PROPERTIES COMPILE_DEFINITIONS "p_rename=libgit2_unused_p_rename"
|
||||
PROPERTIES COMPILE_DEFINITIONS
|
||||
"p_rename=libgit2_unused_p_rename;p_open=libgit2_unused_p_open;p_creat=libgit2_unused_p_creat"
|
||||
)
|
||||
|
||||
@@ -14,8 +14,17 @@
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h> /* stat() for the existence-gated utimes() below */
|
||||
#include <stdio.h> /* remove(), rename() for the p_rename replacement */
|
||||
#include <sys/stat.h> /* stat() + S_IWUSR for utimes()/p_open() below */
|
||||
#include <stdio.h> /* remove(), rename() for the p_rename replacement */
|
||||
#include <fcntl.h> /* open(), O_* flags for the p_open()/p_creat() shims */
|
||||
#include <stdarg.h> /* va_list for the variadic p_open() */
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0 /* no text/binary distinction on esp-idf */
|
||||
#endif
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0 /* no exec() on esp-idf, so close-on-exec is a no-op */
|
||||
#endif
|
||||
|
||||
/* One implicit root user/group. */
|
||||
uid_t getuid(void) { return 0; }
|
||||
@@ -106,3 +115,32 @@ int p_rename(const char *from, const char *to)
|
||||
(void)remove(to); /* ignore ENOENT when `to` doesn't exist yet */
|
||||
return rename(from, to) == 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
/* libgit2 creates loose objects and packfiles with mode 0444 (read-only) — the
|
||||
* git convention that objects are immutable. FATFS honours that as the AM_RDO
|
||||
* attribute and then refuses to f_unlink the file (EACCES), and esp-idf's FATFS
|
||||
* VFS chmod() can't clear AM_RDO — so a written object can NEVER be deleted,
|
||||
* which breaks re-clone recovery and (later) fetch/repack. We force owner-write
|
||||
* into every create mode so libgit2's files stay writable and therefore
|
||||
* deletable. Immutability is only a safety hint on an appliance where nothing
|
||||
* but libgit2 touches these files. posix.c's originals are compiled as
|
||||
* libgit2_unused_p_open/p_creat (see the component CMakeLists), so these are the
|
||||
* definitions every other TU links against. Mirrors posix.c's p_open/p_creat. */
|
||||
int p_open(const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
if (flags & O_CREAT) {
|
||||
va_list arg_list;
|
||||
va_start(arg_list, flags);
|
||||
mode = (mode_t)va_arg(arg_list, int);
|
||||
va_end(arg_list);
|
||||
mode |= S_IWUSR; /* never create read-only → FATFS won't set AM_RDO */
|
||||
}
|
||||
return open(path, flags | O_BINARY | O_CLOEXEC, mode);
|
||||
}
|
||||
|
||||
int p_creat(const char *path, mode_t mode)
|
||||
{
|
||||
return open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC,
|
||||
mode | S_IWUSR);
|
||||
}
|
||||
|
||||
@@ -76,6 +76,15 @@ const REPO_DIR: &str = "/spiflash/repo";
|
||||
/// The tracked file we append to. Stands in for the editor's note file(s).
|
||||
const NOTES_FILE: &str = "notes.md";
|
||||
|
||||
/// Debug/recovery + the read-only-delete test knob: when true, wipe REPO_DIR and
|
||||
/// re-clone from scratch every boot instead of opening the existing clone.
|
||||
/// Deleting the existing clone's objects only succeeds with the esp_stubs
|
||||
/// p_open/p_creat fix (libgit2 objects are otherwise mode 0444 → AM_RDO →
|
||||
/// un-deletable on FAT). Ships **false** — the product opens the persistent
|
||||
/// clone and fast-forwards; flip true to validate the RO-delete fix or to force
|
||||
/// a clean re-clone.
|
||||
const RECLONE_EACH_BOOT: bool = false;
|
||||
|
||||
/// GitHub's root CAs, embedded so the push can verify the server's TLS chain.
|
||||
/// Shared with `git_push` (same file). Written to FAT and handed to libgit2 via
|
||||
/// GIT_OPT_SET_SSL_CERT_LOCATIONS.
|
||||
@@ -235,6 +244,11 @@ fn publish() -> Result<String> {
|
||||
/// whether a clone happened. Clone carries the auth + cert callbacks (the remote
|
||||
/// may be private, and the TLS chain is verified either way).
|
||||
fn open_or_clone() -> Result<(Repository, bool)> {
|
||||
if RECLONE_EACH_BOOT && Path::new(REPO_DIR).exists() {
|
||||
log::warn!("RECLONE_EACH_BOOT — removing {REPO_DIR} to re-clone from scratch");
|
||||
fs::remove_dir_all(REPO_DIR)
|
||||
.context("RECLONE_EACH_BOOT wipe — deletes libgit2 objects, needs the RO-delete fix")?;
|
||||
}
|
||||
match Repository::open(REPO_DIR) {
|
||||
Ok(repo) => {
|
||||
log::info!("opened existing clone at {REPO_DIR}");
|
||||
|
||||
Reference in New Issue
Block a user