feat(dirs): profile isolation via AW_PROFILE appname suffix - #149
Conversation
Greptile SummaryThe PR derives the platform-directory application name from
Confidence Score: 4/5The PR is not yet safe to merge because the previously reported logfile-boundary bug remains present and can return another service or mode's logfile. The prior reply states that timestamp-boundary matching fixed digit-leading and prefix-extending collisions, but current HEAD still filters with Files Needing Attention: aw_core/log.py Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart LR
E[AW_PROFILE] --> A[_get_appname]
A -->|unset or empty| D[activitywatch]
A -->|profile set| P[activitywatch-profile]
D --> X[platformdirs roots]
P --> X
X --> R[data / config / cache / log]
Reviews (3): Last reviewed commit: "feat(dirs): profile isolation via AW_PRO..." | Re-trigger Greptile |
|
@greptileai review |
|
CI-green and mergeable (Greptile 5/5) — waiting only on a maintainer click. This PR is ready to merge, but the bot has pull-only access to this repo and can't self-merge — surfacing it here so it isn't lost. The monitoring loop will stop re-flagging it now that this note is posted. |
When AW_PROFILE is set, all platform directories (data, config, cache, log) are rooted under activitywatch-<profile> instead of activitywatch. This gives every profile a completely separate on-disk tree — identical to the Chrome/Firefox model suggested in ActivityWatch/activitywatch#1399. Mechanism: _get_appname() reads AW_PROFILE at call time and passes it to every platformdirs call. No profile parameter needs to be threaded through the datastore or log layers because those already use get_data_dir() and get_log_dir() internally. Backwards compatibility: - Unset or empty AW_PROFILE → bare 'activitywatch' appname, identical to today. - The existing -testing/-research file suffixes in the datastore layer are redundant under full directory isolation but harmless to leave in place. Part of ActivityWatch/activitywatch#1399 (aw-core layer).
d126c03 to
6e785fc
Compare
testing: bool into named instance profiles|
Design pivot from the prior implementation: The earlier version threaded a This is the approach @ErikBjare suggested in the RFC thread: per-profile appname ( The force-push replaces the earlier commits entirely. All 189 existing tests still pass; 11 new tests cover the appname derivation and the disjoint-dirs invariant for default/testing/research. |
|
@greptileai review |
Profile-aware dirs from ActivityWatch/aw-core#149 are on git master but not on PyPI — 0.5.17 was cut in 2024. AW_PROFILE export is a no-op until the next aw-core release; this lock bump is just current PyPI.
* feat(cli): add --profile flag to aw-cli, remove testing-based log filename filter --profile NAME selects a named instance profile, resolving to the activitywatch-<profile> platform dirs introduced in #149. --testing remains as an alias for --profile testing. The qt subcommand now forwards --profile <name> to aw-qt (which gained profile support in aw-qt#128). The logs subcommand relies on AW_PROFILE being set in the environment (done by the group callback) so get_log_dir() already returns the profile-specific directory; no filename-based filtering is needed. find_oldest_log() drops the `testing` parameter accordingly. Step 6 of ActivityWatch/activitywatch#1399. * fix(cli): preserve inherited AW_PROFILE when no --profile flag given Without this fix, running 'aw-cli <cmd>' with AW_PROFILE already set in the environment would silently clear it, making directory/log lookups fall back to the default profile instead of the inherited one. Addresses Greptile's inherited-profile regression note on #151.
Implements the aw-core layer of ActivityWatch/activitywatch#1399.
The mechanism
When
AW_PROFILEis set, all platform directories (data, config, cache, log)are rooted under
activitywatch-<profile>instead ofactivitywatch.This gives every profile a completely separate on-disk tree — the Chrome/Firefox
model suggested in the RFC thread by @ErikBjare.
Cleanup is trivial:
rm -rf ~/.local/share/activitywatch-research/removes theresearch profile completely, touching nothing else.
Changed
aw_core/dirs.py— adds_get_appname()(3 lines) that readsAW_PROFILEand returns
activitywatch-<profile>or bareactivitywatch. Everyget_{data,config,cache,log}_dircall passes this name to platformdirs.tests/test_dirs.py— 11 new tests: appname derivation + disjoint-dirscheck for default/testing/research; all 189 existing tests still pass.
Why this is simpler than the prior approach
The earlier version of this PR threaded a
profile=parameter through thedatastore and log layers. That was unnecessary: those layers already call
get_data_dir()andget_log_dir(), so making the dir functionsprofile-aware gives full isolation with zero changes to datastore or log code.
Backwards compatibility
Unset or empty
AW_PROFILE→ bareactivitywatchappname, identical to thecurrent layout. The existing
-testing/-researchfile-level suffixes inthe datastore layer are redundant under full directory isolation but harmless.
What comes next (other PRs / other repos)
Per ActivityWatch/activitywatch#1399:
OnceLock<String> PROFILE+dirs.rsroot suffix (Phase 3b)dirs.rschange (hard-coded.join("activitywatch")→ appname)--profile NAMEflag setsAW_PROFILEbefore spawning childrenAW_PROFILE=researchinto the launch script