72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
## Backports from Fossil
This list is for potential backports from fossil which should be investigated more closely to determine whether they need to be adapted for use in this library:
- Improved diff output with `--from BRANCH` when it names a branch which was just merged into the local checkout: <s>[](fossil:edb3a3a06369c1e7bd29)</s>
[](fossil:960c9e8bd69531eb)
# `fsl_cx` "id bag" caches can hypothetically get out of sync
Discovered 2021-11-18: A hypothetical problem which has not yet appeared but can potentially do so in the face of a long-running app which performs "just the right" rollbacks between non-rolled-back operations...
Each fossil context object (`fsl_cx`) stores several `fsl_id_bag` objects which keep track of various RIDs for caching and fast-tracking purposes. It is hypothetically possible, in a long-running application (as opposed to the various `f-apps`) that those caches may pick up RIDs which have since been rolled back and thus are no longer in the database. That in itself is harmless, but future db ops may re-inject those same RIDs, leading to semantic mismatches between the caches and the in-db records.
On solution would be to store a copy of each such cache at the start of each transaction and revert its contents if a transaction rolls back. The minor catch with that is that the db layer doesn't "really" know about `fsl_cx` state (it does a little but, but that's unfortunate) and doesn't currently have a way to communicate to the `fsl_cx` that a transaction has finished. Another solution, though heavier, would be to abstract all access to those caches via internal APIs and use two ID bags for each cache: one for use while a transaction is active and one for state which has survived a transaction (or run without one). When a transaction rolls back, clear the "staging" bags and when one commits, move those records into the long-term bags.
A simpler solution would be to simply clear those caches in any operations which use them and end up performing a rollback. Though that sounds easy, a higher-level call might trigger a callback even after a lower-level one has succeeded, so we would need to be fairly conservative with where we cleared these caches. Hmm.
# f-apps-specific
## f-vdiff
#### Recognize Renames
f-vdiff, when comparing to the local checkout, needs to be able to recognize renames. Case in point:
```
[stephan@nuc:~/fossil/fossil]$ f-vdiff . .
f-vdiff: ERROR #107 (FSL_RC_NOT_FOUND): Cannot stat file; /home/stephan/fossil/fossil/src/codecheck1.c
```
That file, along with many others, was moved to `../tools` in this checkout. We have the state necessary to do this check (namely, the vfile table), it just needs to get done).
#### Optionally show full content of added/removed files
For newly-added/removed files, f-vdiff politely only shows "added" or "removed," not the whole content. Thought it's ostensibly easy to add an option to do this, f-vdiff's internal structure didn't really foresee that possibility and retrofitting it now requires some reworking.
## f-revert
`f-revert` needs to be smart enough to know when it can/should/must clear the vmerge table, or it should refuse to work on individual files so long as a merge is pending. That said, fossil is not at all picky in that regard. Though it ostensibly prohibits checkins of partial merges, it has always had a workaround of using revert to back out parts of a merge change and checking in the remaining merge. When it reverts files, it does not bother to keep the vmerge table in sync, but downstream code simply ignores the missing pieces.
|