Fix compiler warning due to missing function prototype.
[svn.git] / notes / wc-ng-design
blobfb6e668992a2b0445d24feeb0bb33d7b14f11899
1                                                                 -*- Text -*-
3 Content
4 =======
6  * Context
7  * Requirements
8  * Nice-to-have's
9  * Non-goals
10  * Open items / discussion points
11  * Problems in wc-1.0
12  * Possible solutions
13  * Prerequisites for a good wc implementation
14  * Modularization
15  * Implementation proposals for
16    - metadata storage/access abstraction
17    - BASE tree storage/access abstraction
18    - WORKING tree storage/access abstraction
19    - TARGET & MERGE-END tree storage/access abstraction
20    - transactional manipulation API proposal
21    - delta-application algorithm
22       (in light of metadata, tree and textual conflicts)
23    - 
26 Context
27 =======
29 The working copy library has traditionally been a complex piece of
30 machinery and libsvn_wc-1.0 (wc-1.0 hereafter) was more a result of
31 evolution than it was a result of design.  This can't be said to be
32 anybody's fault as much as it was unawareness of the developers at
33 the time with the problem(s) inherent to versioning trees instead of
34 files (as was the usual context within CVS).  As a result, the WC
35 has been one of the most fragile areas of the Subversion versioning
36 model.
38 The wc is where a large number of issues come together which can
39 be considered separate issues in the remainder of the system, or
40 don't have any effect on the rest of the system at all.  The following
41 things come to mind:
43  * Different behaviours required by different use-cases (users)
44    For example: some users want mtime's at checkout time
45      to be the checkout time, some want it to be the historical
46      value at check-in time (and others want different variants).
47  * Different filesystems behave differently, yet Subversion
48    is a cross platform tool and tries to behave the same on all
49    filesystems (timestamp resolution may be an example of this).
51 When considering the wc-1.0 design, one finds that there are a lot
52 of situations where the exact state of the versioned tree isn't
53 defined.  When explicitly considering which trees relate to the
54 working copy at one time or another, the following trees can be
55 found:
57  * BASE: The tree as it was in unmodified form
58  * WORKING: The tree as it is in modified form, based on the
59      administrative information recorded by the transforming
60      'svn ..' commands
61      Note: This tree will -as far as text bases goes- generally
62            overlap with BASE, but isn't required to;
63            e.g. "add-with-history"
64  * ACTUAL: The tree as it is in modified form on the local disk.
65     This tree may differ from WORKING when having been modified
66     with non-Subversion transforming commands (such as plain 'rm').
68 In the context of the 'svn update' command:
70  * BASE-TARGET: The tree to which BASE is being updated and for
71      which the changes w.r.t. BASE are integrated into
72      WORKING and ACTUAL
73  * WORKING-TARGET, ACTUAL-TARGET: Trees in which the above mentioned
74      changes have been integrated, but which haven't "gone live" yet;
75      these trees generally represent "in transition" or "intermediary"
76      state with the intent to become the final tree.
78 Additionally, three more trees may be related to the working copy
79 when considering the 'svn merge' command:
81  * START: The tree used as the base state for the 'merge' command
82  * END: The tree used as the ending state for the 'merge' command
83     The difference between these trees will be merged into the
84     WORKING and ACTUAL trees.
86 In the following example 10 == START and 15 == END:
87   $ svn merge -r10:15 http://svn.example.com/svn/ .
89 Please note that the WORKING-TARGET and ACTUAL-TARGET trees also
90 apply to 'svn merge' as they can result in 'add with history' schedules,
91 which will place text bases in the WORKING-TARGET tree.  Also note
92 that -since merge is by definition an 'edit' operation- the BASE and
93 BASE-TARGET trees are not concerned with a merge.
95 ###EHU: To which trees do BASE and TARGET refer when we're in a subdir
96 of a replaced tree? And which trees do they refer to in a subdir of
97 a replaced tree which itself is replaced? (Preliminary answer: the
98 base in a replaced subdir should probably be the base as defined by
99 the parent which got copied in, not the base as was deleted, because
100 otherwise it won't be possible to delete files from the replaced subdir:
101 there would be no way to express a deletion against the new dir.)
105 Requirements
106 ============
108  * Developer sanity
109    From this requirement, a number of additional ones follow:
110     - Very explicit tree state management; clear difference between
111       each of the 5 states we may be looking at
112     - It must be "fun" to code wc-ng enhancements
113  * Speed
114    (Note: a trade off may be required for 'checkout' vs 'status' speed)
115  * Cross-node-type working copy changes
116  * Flexibility
117    The model should make it easy to support
118      - central vs local metadata storage
119      - Last modified timestamp behaviours
120      - .svn-less working copy subtrees
121      - different file-changed detection schemes
122         (e.g. full tree scan as in wc-1.0 as well as 'p4 edit')
123  * Graceful (defined) fallback for non-supported operations
124    When a checkout tries to create a symlink on an OS which supports
125    them, on a filesystem which doesn't, we should cope without
126    canceling the complete checkout.  Same for marking metadata read-only.
127  * Gracefully handle symlinks in relation to any special-handling of
128    files (don't special-handle symlinks!)
129  * Clear/reparable tree state
130    Other than our current loggy system, I mean here: "there is a command
131    by which the user can restart the command he/she last issued and
132    Subversion will help complete that command", which differs from our
133    loggy system in the way that it will return the working copy to a
134    defined (but to the user unknown) state.
135  * Transactional/ repairable tree state (with which I mean something
136    which achieves the same as our loggy system, but better).
137  * Case sensitive filesystem aware / resilient
138  * Working copy stability; a number of scenario's with switch and
139    update obstructions used to leave the working copy unrecoverable
140  * Client side 'true renames' support where one side can't be committed
141    without the other (relates to issue #876)
142  * Change detection should become entirely internal to libsvn_wc (referring
143    to the fact that libsvn_client currently calls svn_wait_for_timestamps()),
144    even though under 'use-commit-times=yes', this waiting is
145    completely useless.
146  * Last-modified recording as a preparation for solving issue #1256 and
147    as defined in this mail, also linked from the issue:
148    http://svn.haxx.se/dev/archive-2006-10/0193.shtml
149  * Representing "this node is part of a replaced-with-history tree and
150    I'm *not* in the replacement tree" as well as "... and I'm deleted
151    from the replacement tree" [issues #1962 and #2690]
154 Would-be-very-nice-to-have's
155 ============================
157  * Multiple users with a single working copy (aka shared working copy)
158  * Ending up with an implementation which can use current WCs
159    (without conversion)
160  * Working copies/ metadata storages without local storage of text-bases
161    (other than a few cached ones)
164 Non-goals
165 =========
167  * Off-line commits
168  * Distributed VC
170 Open items / discussion points
171 ==============================
173  * Files changed during the window "sent as part of commit" to
174     "post commit wc processing"; these are currently explicitly
175     supported. Do we want to keep this support (at the cost of speed)?
176  * Single working copy lock. Should we have one lock which locks the
177     entire working copy, disabling any parallel actions on disjoint
178     parts of the working copy?
179  * Meta data physical read-only marking (as in wc-1.0). Is it still
180     required, or should it become advisory (ie ignore errors on failure)?
181  * Is issue #1599 a real use-case we need to address?
182     (Loosing and regaining authz access with updates in between)
185 Problems in wc-1.0
186 ==================
188  * There's no way to clear unused parts of the entries cache
189  * The code is littered with path calculations in order
190    to access different parts of the working copy (incl. admin areas)
191  * The code is littered with direct accesses to both wc files and
192    admin area files
193  * It's not always clear at which time log files are being processed
194    (ie transactions are being committed), meaning it's not always
195    clear at which version of a tree one is looking at: the pre or post
196    transformation versions...
197  * There's no support for nested transactions (even though some
198    functions want to start a new transaction, regardless whether one
199    was already started)
200  * It's very hard to determine when an action needs to be written
201    to a transaction or needs to be executed directly
202  * All code assumes local access to admin (meta)data
203  * The transaction system contains non-runnable commands
204  * It's possible to generate combinations of commands, each of which
205    is runnable, but the series isn't
206  * Long if() blocks to sort through all possible states of
207    WORKING, ACTUAL and BASE, without calling it that.
208  * Large if() blocks dealing with the difference between file and
209    directory nodes
210  * Many special-handling if()s for svn:special files
211  * Manipulation of paths, URLs and base-text paths in 1 function
212  * 'Switchedness' of subdirectories has to be derived from the
213    URLs of the parent and the child, but copied nodes also have
214    non-parent-child source URLs... (confusing)
215  * Duplication of data: a 'copied' boolean and a 'copy_source' URL field
216  * Checkouts fail when checking out files of different casing to a case
217    insensitive filesystem
218  * Checkouts fail when marking working copy admin data as read-only
219    is a non-supported FS operation (VFAT or Samba mounts on Linux have
220    this behaviour)
221  * Obstructed updates leave operations half done; in case of a switch,
222    it's not always possible to switch back (because the switch itself
223    may have left now-unversioned items behind)
224  * Directories which have their own children merged into them (which happens
225    when merging a directory-add) won't correctly fold the children into
226    schedule==normal, but instead leave them as schedule==add, resulting in
227    a double commit (through HTTP, other RA layers fold the double add, but
228    that's not the point) [see issue #1962]
229  * transaction files (ie log files) are XML files, requiring correct
230    encoding of characters and other values; given the short expected
231    life-time of a log file and the fact that we're almost completely sure
232    the log file is going to be read by the WC library anyway (no interchange
233    problems), this is a waste of processing time
234  * No strict separation between public and internal APIs: many public
235    APIs also used internally, growing arguments which *should* only
236    matter for internal use
239 Possible solutions
240 ==================
242 Developer sanity
243 ----------------
244 Strict separation between modules should help keep code focused at one
245 task.  Probably some of the required user-specific behaviours can (and
246 should) be hidden behind vtables; for example: setting the file stamp
247 to the commit time, last recorded time or leaving it at the current time
248 should be abstracted from.
250 Access to 'text bases' is another one of these areas: most routines in
251 wc-1.0 don't actually need access to a file (a stream would be fine as
252 well), but since the files are there, availability is assumed.
253 When abstracting all access into streams, the actual administration of
254 the BASE tree can be abstracted from: for all we know the 'tree storage
255 module' may be reading the stream directly off the repository server.
256 [The only module in wc-1.0 which *requires* access to the files is
257 the diff/merge library, because it rewinds to the start of the file
258 during its processing; an operation not supported by streams... and even
259 then, if these routines are passed file handles, they'll be quite
260 happy, meaning they still don't need to know where the text base /
261 source file is...]
263 In order to keep developers sane, it should be extremely clear at any
264 one time - when operating on a tree - which tree is being operated upon.
266 One way to prevent the lengthy 'if()' blocks currently in wc-1.0, would be
267 to design a dispatch mechanism based on the path-state in WORKING/BASE and the
268 required transformation, dispatching to (small) functions which perform
269 solely that specific task.
270 #####XBC Do please note that this suggests yet another instance of
271          pure polymorphism coded in C. This runs contrary to the
272          developer sanity requirement.
275 Speed
276 -----
277 wc-1.0 assumes the WORKING tree and the ACTUAL tree match, but then
278 goes out of its way to assure they actually do when deemed important.
279 The result is a library which calls stat() a lot more often than need be.
281 One of the possible improvements would be to make wc-ng read all of
282 the ACTUAL state (concentrated in one place, using apr_stat()), keeping
283 it around as long as required, matching it with the WORKING state before
284 operating on either (not only when deemed important!).
286 Working from the ACTUAL tree will also prove to be a step toward clarity
287 regarding the exact tree which is being operated upon.
289 [This suggestion from wc-improvements also applies to wc-ng:]
290 Most operations are I/O bound and have CPU to spare.  Consider the virtue
291 of compressed text bases in order to reduce the amount of I/O required.
293 Another idea to reduce I/O is to eliminate atomic-rename-into-place for
294 the metadata part of the working copy: if a file is completely written,
295 store the name of the base-text/prop-text in the entries file, which gets
296 rewritten on most wc-transformations anyway.
299 Cross node type change representation
300 -------------------------------------
301 ####EHU To be done
303 Flexibility of metadata storage
304 -------------------------------
305 There are 3 known models for storing metadata as requested by different
306 groups of users:
308  - in-subtree metadata storage (.svn subdir model, as in wc-1.0)
309  - in-'tree root' metadata storage (working copy central)
310  - detached metadata storage (user-central)
312 A solution to implementing each of these behaviours in order to satisfy
313 the wide range of use-cases they solve, would be to define a module
314 interface and implement this interface three times (possibly using vtables).
316 Note that using within-module vtables should be less problematic than our
317 post-1.0 experiences with public vtables (such as the ra-layer vtable):
318 implementation details are allowed to differ between releases (even patch
319 releases).
322 Transaction duration / memory management
323 ----------------------------------------
324 The current pool-based memory management system is very good at managing
325 memory in a transaction-based processing model.  In the wc library, a
326 'transaction' often spans more than one call into the library.  We either
327 need a sane way to handle this kind of situation using pools, or we may
328 need a different memory management strategy in wc-ng.
330 Working copy stability
331 ----------------------
332 In light of obstructed updates it may not always be desirable to be able
333 to resume the current operation (as currently is the case): in some cases
334 the user may want to abort the operation, in other cases the user may
335 want to resolve the obstruction before re-executing the operation.
337 The solution to this problem could be 'atomic updates': receiving the
338 full working copy transformation, verifying prerequisites, creating
339 replacement files and directories and when all that succeeds, update
340 the working copy.
342 Full workin' copy unit tests:
343 Exactly because the working copy is such an important part of the
344 Subversion experience *and* because of the 'reputation' of wc-1.0,
345 we need a way to ensure wc-ng completely performs according to our
346 expectations.  *The* way to ensure we're able to test the most contrived
347 edge-cases is to develop a full unit testing test-suite while developing
348 wc-ng.  This will both be a measure to ensure working copy stability
349 as well as developer sanity: in the early stages of the wc-ng develop-
350 ment process, we'll be able to assess how well the design holds up
351 under more difficult 'weather'.
353 Transactional updates
354 ---------------------
356 .. where 'update' is meant as 'user command', not 'svn update' per se.
358 When applied to files, this can be summarized as:
360  * Receive transformations (update, delete, add) from
361    the server,
364 Prerequisites for a good wc implementation
365 ==========================================
367 These prerequisites are to be addressed, either as definitions
368 in this document, or elsewhere in the subversion (source) tree:
369  * Well defined behaviour for cross-node type updates/merges/..
370    (tree conflicts in particular)
371  * Well defined behaviour for special file handling
372  * Well defined behaviour for operations on locally missing items
373      (see issue #1082)
374  * Well defined change detection scheme for each of the different
375      last-modified handling strategies
376  * No special handling of symlinks: they are first class versioned objects
377  * Well defined behaviour for property changes on updates/merges/...
378    (this is a problem which may resemble tree conflicts!),
379    including 'svn:' special properties
380  * File name manipulation routines (availability)
381  * File name comparison routines (!) (availability; which compensate
382      for the different ways Unicode characters can be represented
383      [re: NFC/NFD Unicode issue])
384  * URL manipulation routines (availability)
385  * URL comparison routines (availability; which compensate for
386      different ways the same URL can be encoded; see issue #2490)
387  * Modularization
388  * Agree on a UI to pull in other parts of the same repository
389    (NOT svn:externals) [relates to issue #1167]
390 #####XBC I submit this is a server-side feature that the client
391          (i.e. the WC library) should not know about.
392  * Agree on behaviour for update on moved items (relates to issue #1736)
393  * Case-sensitivity detection code to probe working copy filesystem
396 Modularization
397 ==============
399 Strict separation must be applied to a number of modules which can be
400 recognised.  This will help prevent spaghetti code as in wc-1.0 where
401 one piece of code manipulates paths to a working copy file, its URL
402 *and* the path to the base file.
404 For now, these APIs can be separated:
406  - the public API (presumably not to be used by any internal
407      processing, but presents functionality to working copy users)
408 #####XBC This is really required of all our module public APIs.
409  - tree administration API (required for BASE, TARGET and WORKING)
410      Admins which files are part of the tree, which ones map to
411      which repositories and which textbase / propbase files belong
412      to which local files. [should provide checkpointing functionality
413      for use with transactional tree modifications API]
414  - tree access API (required for BASE, WORKING, TARGET and ACTUAL)
415      Gives access to the content of the nodes in a tree
416        - props
417        - text bases (for files)
418        - child nodes (for directories)
419  - transactional tree modifications API (applicable to all trees,
420      ###EHU do we provide the same interface to BASE/WORKING as for ACTUAL?)
421  - tree transformation (required for update/switch/merge updating
422      BASE, WORKING and ACTUAL), meaning all of tree changes, file
423      changes and metadata changes
424  - Working-copy changedness detection API
425  - Metadata access API (used by tree administration module(s))
426  - Event hooks (in order to be able to implement different
427    timestamp-setting strategies and possibly more)
429 These APIs will be implemented by these (currently known) modules:
431  - tree administration
432    * wc_adm
433  - tree access
434    * wc_acc
435  - transactional tree modifications
436    * wc_log
437  - tree transformation
438    * wc_trans
439  - working copy changedness detection
440    wc_detect vtable-based API implemented by these modules:
441      * tree crawler ('inspired' by wc-1.0)
442      * tree marker (inspired by 'p4 edit')
443  - metadata access API
444    wc_macc vtable-based API implemented by these modules:
445      * tree spread ('inspired' by wc-1.0)
446      * tree root (storing all metadata in the tree root (think darcs))
447      * central depot (storing 'somewhere' locally, possibly $HOME)
448         this central store would open up the possibility to share
449         text bases/prop bases across checkouts
450      * non-local (retrieving all text and prop-bases from the server,
451         except for a number of cached ones) ###EHU: maybe this is
452         orthogonal to the question where metadata is stored: in all
453         situations, you *could* choose not to keep local copies
454  - Event hooks for the union of all paths in (BASE, WORKING)
455    wc_hook event based single-callback API
456    for e.g. these events:
457         + props updated
458         + base text updated
459         + wc file updated
460         + update completed
461         + lock acquired
462         + lock released
463        (+ lock can't be acquired [in order to 'unprotect'
464            svn:needs-lock protected files which have been removed
465            from the repository?])
466    to be implemented by these modules:
467      * use-commit-times
468      * versioned-mtimes
469      * versioned-execute-perm
470      * versioned-other-unix-perms
471     (* versioned-windows-perms?)
472      * needs-lock-updater
474 Justification for the large number of modules, with a modest number
475 of different APIs is that the problem is really quite complex as shown
476 earlier in this document.
478 Over the years, a large number of use cases have developed around
479 Subversion where different user groups have shown very valid use cases
480 for conflicting behaviours.  Presumably, most of these we want to
481 retain.  Some of the unimplemented ones have open issues indicating
482 there's at least an active interest.  In order to prevent locking out
483 some of the current use cases adding support for the open issues, we
484 need a flexible modularized model.  This model will also prevent that
485 we'll end up duplicating lots of code to support the different use cases.
486 #####XBC Such flexibility will bring the WC to the kind of
487          purgatory the RA layers are in. We promise feature and semantics
488          parity between them, and the result is that even a small change
489          in that layer requires knowledge of three different protocols
490          and four different implementations.
492 Given the assumption of 'little code duplication', the choice for
493 having several modules which implement the same API (vtable) is
494 justifiable.
497 Implementation proposals
498 ========================
500 Classification of svn_wc_entry_t fields to BASE/WORKING
501 -------------------------------------------------------
503 [Note: This section is mainly to clarify the difference between the BASE
504 and WORKING trees, it's not here to mean that we actually need all these
505 fields in wc-ng!]
507 Here are the mappings of all fields from svn_wc_entry_t to the BASE and
508 WORKING trees:
510  +-------------------------------+------+---------+
511  |       svn_wc_entry_t          | BASE | WORKING |
512  +-------------------------------+------+---------+
513  | name                          |  x   |    x (1)|
514  | revision                      |  x   |    x (2)|
515  | url                           |  x   |    x (2)|
516  | repos                         |  x   |    x (3)|
517  | uuid                          |  x   |    x (3)|
518  | kind                          |  x   |    x    |
519  | absent                        |  x   |         |
520  | copyfrom_url                  |      |    x    |
521  | copyfrom_rev                  |      |    x    |
522  | conflict_old                  |      |    x    |
523  | conflict_new                  |      |    x    |
524  | conflict_wrk                  |      |    x    |
525  | prejfile                      |      |    x    |
526  | text_time                     |      |    =    |
527  | prop_time                     |      |    =    |
528  | checksum                      |  x   |    x (2)|
529  | cmt_rev                       |  x   |    x (2)|
530  | cmt_date                      |  x   |    x (2)|
531  | cmt_author                    |  x   |    x (2)|
532  | lock_token                    |  x(6)|         |
533  | lock_owner                    |  x   |         |
534  | lock_comment                  |  x   |         |
535  | lock_creation_date            |  x   |         |
536  | has_props                     |  x   |    x (4)|
537  | has_prop_mods                 |      |    =    |
538  | cachable_props                |  x(5)|    x (4)|
539  | present_props                 |  x   |    x (4)|
540  | changelist                    |      |    x    |
541  | working_size                  |      |    =    |
542  | keep_local                    |      |    =    |
543  | depth                         |  x   |    x    |
544  | schedule                      |      |         |
545  | copied                        |      |         |
546  | deleted                       |      |         |
547  | incomplete                    |      |         |
548  +-------------------------------+------+---------+
550 (1) if this one differs from BASE, it must point to the source of a rename
551 (2) for an add-with-history
552 (3) or can we assume single-repository working copies?
553 (4) can differ from BASE for add-with-history
554 (5) why is this a field at all; can't the WC code know?
555 (6) locks apply to in-repository paths, hence BASE
557 The fields marked with '=' are implementation details of internal detection
558 mechanisms, which means they don't belong in the public interface.
560 Fields with no check are to become obsolete. 'schedule', 'copied' and
561 'deleted' can be deducded from the difference between the BASE and WORKING
562 or WORKING and ACTUAL trees.  'incomplete' should become obsolete when the
563 goal of 'atomic updates' can be realised, in which case the tree can't be
564 in an incomplete yet locked state.  This would also invalidate issue #1879.
567 Other sections
568 --------------
569  remain to be done