feat(xce-test-rc-file): task 1.1 rc-file path resolution with XDG precedence

Adds rcfile_resolve_path() (rcfile.c/rcfile.h): resolves $XDG_CONFIG_HOME/xce_test/rc
when set and non-empty, else $HOME/.config/xce_test/rc, else NULL. Standalone
libc-only module mirroring the configcompare.c pattern; wired into xce_test_src
and controller_unit_test_src, registered in controller_test.c's Unity runner.

6 unit tests in test_rcfile.c cover all XDG/HOME combinations plus a dedicated
env-var save/restore isolation test, addressing the cross-test leak risk found
during design review (controller_unit_test runs 80+ test files in one process).

Adds the xce-test-rc-file spec (requirements/design/tasks/research), including
design fixes from validation: getline()-based line reading (task 1.2, avoids
truncating long rc-file lines) and the env-isolation requirement above.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AgYRU3zDTqNGV5Jk8aiKLg
This commit is contained in:
Rongsong Shen 2026-08-26 13:48:27 +00:00
parent f9e8d97eac
commit 9de4db95d3
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
10 changed files with 632 additions and 1 deletions

View file

@ -0,0 +1,38 @@
#define _GNU_SOURCE
#include "rcfile.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Suffixes appended to the resolved base directory to form the rc-file
* path -- kept as two separate constants (rather than one shared tail)
* since the XDG_CONFIG_HOME branch is already rooted at a "config home"
* directory while the HOME fallback still needs the "/.config" segment. */
#define RCFILE_XDG_SUFFIX "/xce_test/rc"
#define RCFILE_HOME_SUFFIX "/.config/xce_test/rc"
char* rcfile_resolve_path(void)
{
const char* xdg_config_home = getenv("XDG_CONFIG_HOME");
if (xdg_config_home && *xdg_config_home) {
size_t len = strlen(xdg_config_home) + strlen(RCFILE_XDG_SUFFIX) + 1;
char* path = (char*)malloc(len);
if (!path)
return NULL;
snprintf(path, len, "%s%s", xdg_config_home, RCFILE_XDG_SUFFIX);
return path;
}
const char* home = getenv("HOME");
if (home && *home) {
size_t len = strlen(home) + strlen(RCFILE_HOME_SUFFIX) + 1;
char* path = (char*)malloc(len);
if (!path)
return NULL;
snprintf(path, len, "%s%s", home, RCFILE_HOME_SUFFIX);
return path;
}
return NULL;
}