1 Implementing Sparse Directory Support in SVN
2 (a.k.a. "sparse checkouts" / "incomplete directories")
11 4. Implementation Strategy
12 5. Compatibility Matters
19 Many users have very large trees of which they only want to
20 checkout certain parts. In Subversion <= 1.4, 'checkout -N' is not
23 Subversion 1.5 introduces the idea of "depth" (controlled via the
24 '--depth' and '--set-depth' options) as a replacement for mere
25 non-recursiveness (formerly controlled via the '-N' option). Depth
26 allows working copies to have exactly the contents the user wants,
27 leaving out everything else.
32 We have a new "depth" field in .svn/entries, which has (currently)
33 four possible values: depth-empty, depth-files, depth-immediates,
34 and depth-infinity. Only this_dir entries may have depths other
37 depth-empty ------> Updates will not pull in any files or
38 subdirectories not already present.
40 depth-files ------> Updates will pull in any files not already
41 present, but not subdirectories.
43 depth-immediates -> Updates will pull in any files or
44 subdirectories not already present; those
45 subdirectories' this_dir entries will
48 depth-infinity ---> Updates will pull in any files or
49 subdirectories not already present; those
50 subdirectories' this_dir entries will
51 have depth-infinity. Equivalent to
52 today's default update behavior.
54 The new '--depth' option limits how far an operation descends, and
55 the new '--set-depth' option changes the depth of a working copy tree.
57 The new options are explained in more detail in 'Usage' below, but
58 these two concepts will aid understanding:
60 "ambient depth" -----> The depth, or combination of depths,
61 of a given working copy.
63 "requested depth" ---> The depth the user requested for a
64 particular operation (e.g., checkout,
65 update, switch). This is sometimes
66 called the "operational depth".
68 When when running an operation in a working copy, the requested
69 depth never goes deeper than the ambient depth. For example, if
70 you run 'svn status --depth=infinity' in a working copy directory
71 that was checked out with '--depth=immediates', the status will go
72 as far as depth immediates. That is, it descends all the way
73 ("infinity") into what's available, but in this case what's
74 available is shallower than infinity.
89 Run checkout with --depth=empty or --depth=files. When you need
90 additional files or directories, pull them in with 'svn up NAME'
91 (passing --depth for directories as appropriate).
95 checkout without --depth or -N behaves the same as it does today,
96 which is the same as with --depth=infinity.
98 checkout --depth=(empty|files|immediates) creates a working copy
99 that is (empty | has only files | has files and empty subdirs).
101 Inside such a working copy, running 'svn up' by itself will update
102 only what is already present, but running 'svn up OMITTED_SUBDIR'
103 will cause OMITTED_SUBDIR to be brought in at depth-infinity, while
104 the rest of the parent working copy remains at its previous depth.
106 The --depth option limits how far an operation recurses. The
107 operation will reach whatever is inside the intersection of the
108 ambient depth and the requested depth (see 'Design' section for
111 The --depth option never changes the depth of an existing dir.
112 Instead, use the new '--set-depth=NEW_DEPTH' option for that.
113 Right now, --set-depth can only extend (that is, make deeper) a
114 directory. In the future, it will also be able to contract; see
117 For most commands, '-N' is a synonym for '--depth=files'. This
118 changes the existing -N behavior, but only in trivial ways.
120 'svn info' lists depth, iff invoked on a directory whose depth is
121 not the default (depth infinity).
128 Same as today; everything has depth-infinity.
130 svn co -N http://.../A
132 Today, this creates wc containing only mu. Now, this will be
133 identical to 'svn co --depth=files /A'.
135 svn co --depth=empty http://.../A Awc
137 Creates wc Awc, but empty: no files, no subdirectories.
139 Awc/.svn/entries this_dir depth-empty
141 svn co --depth=files http://.../A Awc1
143 Creates wc Awc1 with all files (i.e., Awc1/mu) but no
146 Awc1/.svn/entries this_dir depth-files
149 svn co --depth=immediates http://.../A Awc2
151 Creates wc Awc2 with all files and all subdirectories, but
152 subdirectories are empty.
154 Awc2/.svn/entries this_dir depth-immediates
157 Awc2/B/.svn/entries this_dir depth-empty
158 Awc2/C/.svn/entries this_dir depth-empty
163 Since B is not yet checked out, add it at depth infinity.
165 Awc/.svn/entries this_dir depth-empty
167 Awc/B/.svn/entries this_dir depth-infinity
169 Awc/B/E/.svn/entries this_dir depth-infinity
175 Since A is already checked out, don't change its depth, just
176 update it. B and everything under it is at depth-infinity,
177 so it will be updated just as today.
179 svn up --depth=immediates Awc/D
181 Since D is not yet checked out, add it at depth-immediates.
183 Awc/.svn/entries this_dir depth-empty
186 Awc/D/.svn/entries this_dir depth-immediates
188 Awc/D/G/.svn/entries this_dir depth-empty
191 svn up --depth=infinity Awc
193 Update Awc at depth-empty, and Awc/B at depth-infinity, since
194 those are the ambient depths of those two directories already.
196 Awc/.svn/entries this_dir depth-empty
198 Awc/B/.svn/entries this_dir depth-infinity
201 svn up --set-depth=infinity Awc
203 Pull everything into Awc, resulting in a working copy that is
204 just as if it had been checked out with no --depth flag at all.
206 Awc/.svn/entries this_dir depth-infiniti
209 ########################################################################
211 # ###################################################### #
213 # ### THIS IS NOT YET IMPLEMENTED, SEE ISSUE #2843 ### #
215 # ###################################################### #
217 # svn up --depth=empty Awc/B/E #
219 # Remove everything under E, but leave E as an empty directory #
220 # since B is depth-infinity. #
222 # Awc/.svn/entries this_dir depth-infinity #
225 # Awc/B/.svn/entries this_dir depth-infinity #
227 # Awc/B/E/.svn/entries this_dir depth-empty #
230 ########################################################################
233 4. Implementation Strategy
234 ==========================
236 It would be nice if all this could be accomplished with just simple
237 tweaks to how we drive the update reporter (svn_ra_reporter2_t).
238 However, it's not that easy.
240 Handling 'checkout --depth=empty' would be easy. It should get us
241 an empty directory at depth-empty, with no files and no subdirs,
242 and if we just report it as at HEAD every time, the server will
243 never send updates down (hmmm, this could be a problem for getting
244 dir property updates, though). Then any files or subdirs we have
245 explicitly included we can just report at their respective
246 revisions, and get proper updates; at least that'll work for the
249 But consider 'checkout --depth=immediates'. The desired state is a
250 depth-immediates directory D, with all files up-to-date, and with
251 skeleton subdirs at depth empty. Plain updates should preserve this
254 If we report D as at its BASE revision, files at their BASE
255 revisions, and subdirs at HEAD, then:
257 - When new files appear in the repos, they'll get sent down (good)
258 - When new subdirs appear, they'll get sent down in full (bad)
260 But if we don't report subdirs as at HEAD, then the server will try to
261 update them (bad). And if we report D at HEAD, then the working copy
262 won't receive new files that have appeared in the repository since D's
263 BASE revision (note that we *can* get updates for files we already
264 have, though, by continuing to report them at their respective BASEs).
266 The same logic applies to subdirectories at depth-files or
269 So, for efficient depth handling, the client directly reports the
270 desired depth to the server; i.e., we extend the RA protocol.
272 Meanwhile, legacy servers will send back a bunch of information the
273 client doesn't want, and the client just ignores it, and the user
274 never knows except for the fact that everything seems slow (but
275 once their servers are upgraded, it'll speed up).
277 5. Compatibility Matters
278 ========================
280 This feature introduces two new concepts into the RA protocol which
281 will not be understood by older servers:
283 * Reported Depths -- the depths associated with individual paths
284 included by the client in the description (via the
285 svn_ra_reporter_t) of its working copy state.
287 * Requested Depth -- the single depth value used to limit the
288 scope of the server's response to the client.
290 As such, it's useful to understand how these concepts will be
291 handled across the compatibility matrix of depth-aware and
292 non-depth-aware clients and servers.
294 NOTE: in the sections below, it is not necessarily that case that a
295 value or state which is said to be "transmitted" literally has a
296 presence in the RA protocol. Some such bits of state have default
297 values in the protocol and can therefore be effectively transmitted
298 while not literally identifiable in a network trace of the
299 client-server traffic.
301 Depth-aware Clients (DACs)
303 DACs will transmit reported depths (with "infinity" as the
304 default) and will transmit a requested depth (with "unknown" as
305 the default). They will also -- for the sake of older,
306 non-depth-aware servers (NDASs) -- transmit a requested recurse
307 value derived from the requested depth:
317 When speaking to an NDAS, the requested recurse value is the
318 only thing the server understands , but is obviously more
319 "grainy" than the requested depth concept. The DAC, therefore,
320 must filter out any additional, unwanted data that the server
321 transmits in its response. (This filtering will happen in the
322 RA implementation itself so the RA APIs behave as expected
323 regardless of the server's pedigree.)
325 When speaking to a depth-aware server (DAS), the requested
326 recurse value is ignored. A requested depth of "unknown" means
327 "only send information about the stuff in my report,
328 depth-aware-ily". Other requested depth values are honored by
329 the server properly, and the DAC must handle the transformation
330 of any working copy depths from their pre-update to their
331 post-update depths and content as described in `3. Examples'.
333 Non-depth-aware Clients (NDACs)
335 NDACs will never transmit reported depths and never transmit a
336 requested depth. But they will transmit a requested recurse
337 value (either "yes" or "no", with "yes" being the default). (A
338 DAS uses the presence of a requested depth in the actual protocol
339 to distinguish DACs from NDACs, and knows to ignore the
340 requested recurse value transmitted by a DAC.)
342 When speaking to an NDAS, what happens happens. It's the past,
343 man -- you don't get to define the interaction this late in the
346 When speaking to a DAS, the not-reported depths are treated like
347 reported depths of "infinity", and the reported recurse values
348 "yes" and "no" map to depths of "infinity" and "files",
354 A new enum type 'svn_depth_t depth' is defined in svn_types.h.
355 Both client and server side now understand the concept of depth,
356 and the basic update use cases handle depth. See depth_tests.py.
358 On the client side, most of the svn_client.h interfaces that
359 formerly took 'svn_boolean_t recurse' have been revved and their
360 successors take 'svn_depth_t depth' instead. (The -N option is
361 deprecated, but it still works: it simply maps to --depth=files,
362 which results in the same behavior as -N used to.)
364 Some of this recurse-becomes-depth change has propagated down into
365 libsvn_wc, which now stores a depth field in svn_wc_entry_t (and
366 therefore in .svn/entries). The update reporter knows to report
367 differing depths to the server, in the same way it already reports
368 differing revisions. In other words, take the concept of "mixed
369 revision" working copies and extend it to "mixed depth" working
372 On the server side, most of the significant changes are in
373 libsvn_repos/reporter.c. The code that receives update reports now
374 receives notice of paths that have different depths from their
375 parent, and of course the overall update operation has a global
376 depth, which applies whenever not shadowed by some local depth for
379 The RA code on both sides knows how to send and receive depths; the
380 relevant svn_ra_* APIs now take depth arguments, which sometimes
381 supersede older 'recurse' booleans. In these cases, the RA layer
382 does the usual compatibility dance: receiving "recurse=FALSE" from
383 an older client causes the server to behave as if "depth=files"
384 had been transmitted.
389 The list of outstanding issues is shown by this issue tracker query
390 (showing Summary fields that start with "[sparse-directories]"):
392 <http://subversion.tigris.org/issues/buglist.cgi?component=subversion&issue_status=NEW&issue_status=STARTED&issue_status=REOPENED&short_desc=%5Bsparse-directories%5D&short_desc_type=casesubstring>