2 * dump_editor.c: The svn_delta_editor_t editor used by svnrdump to
5 * ====================================================================
6 * Licensed to the Apache Software Foundation (ASF) under one
7 * or more contributor license agreements. See the NOTICE file
8 * distributed with this work for additional information
9 * regarding copyright ownership. The ASF licenses this file
10 * to you under the Apache License, Version 2.0 (the
11 * "License"); you may not use this file except in compliance
12 * with the License. You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing,
17 * software distributed under the License is distributed on an
18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 * KIND, either express or implied. See the License for the
20 * specific language governing permissions and limitations
22 * ====================================================================
26 #include "svn_pools.h"
27 #include "svn_repos.h"
29 #include "svn_props.h"
30 #include "svn_dirent_uri.h"
32 #include "svn17_compat.h"
33 #include "dump_editor.h"
35 #define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
37 /* The baton used by the dump editor. */
38 struct dump_edit_baton
{
39 /* The output stream we write the dumpfile to */
42 /* Pool for per-edit-session allocations */
45 /* Properties which were modified during change_file_prop
46 * or change_dir_prop. */
49 /* Properties which were deleted during change_file_prop
50 * or change_dir_prop. */
51 apr_hash_t
*deleted_props
;
53 /* Temporary buffer to write property hashes to in human-readable
54 * form. ### Is this really needed? */
55 svn_stringbuf_t
*propstring
;
57 /* Temporary file to write delta to along with its checksum. */
60 /* The checksum of the file the delta is being applied to */
61 const char *base_checksum
;
63 /* Flags to trigger dumping props and text */
64 svn_boolean_t dump_props
;
65 svn_boolean_t dump_text
;
66 svn_boolean_t dump_props_pending
;
69 /* Make a directory baton to represent the directory at path (relative
72 * COPYFROM_PATH/COPYFROM_REV are the path/revision against which this
73 * directory should be compared for changes. If the copyfrom
74 * information is valid, the directory will be compared against its
77 * PARENT_DIR_BATON is the directory baton of this directory's parent,
78 * or NULL if this is the top-level directory of the edit. ADDED
79 * indicates if this directory is newly added in this revision.
80 * Perform all allocations in POOL. */
81 static struct dir_baton
*
82 make_dir_baton(const char *path
,
83 const char *copyfrom_path
,
84 svn_revnum_t copyfrom_rev
,
86 void *parent_dir_baton
,
90 struct dump_edit_baton
*eb
= edit_baton
;
91 struct dir_baton
*pb
= parent_dir_baton
;
92 struct dir_baton
*new_db
= apr_pcalloc(pool
, sizeof(*new_db
));
95 /* Disallow a path relative to nothing. */
96 SVN_ERR_ASSERT_NO_RETURN(!path
|| pb
);
98 /* Construct the full path of this node. */
100 abspath
= svn_uri_join("/", path
, pool
);
104 /* Remove leading slashes from copyfrom paths. */
105 if (copyfrom_path
&& strcmp(copyfrom_path
, "/"))
106 copyfrom_path
= ((*copyfrom_path
== '/') ?
107 copyfrom_path
+ 1 : copyfrom_path
);
110 new_db
->parent_dir_baton
= pb
;
111 new_db
->abspath
= abspath
;
112 new_db
->copyfrom_path
= copyfrom_path
?
113 apr_pstrdup(pool
, copyfrom_path
) : NULL
;
114 new_db
->copyfrom_rev
= copyfrom_rev
;
115 new_db
->added
= added
;
116 new_db
->written_out
= FALSE
;
117 new_db
->deleted_entries
= apr_hash_make(pool
);
122 /* Extract and dump properties stored in edit baton EB, using POOL for
123 * any temporary allocations. If TRIGGER_VAR is not NULL, it is set to FALSE.
124 * Unless DUMP_DATA_TOO is set, only property headers are dumped.
127 dump_props(struct dump_edit_baton
*eb
,
128 svn_boolean_t
*trigger_var
,
129 svn_boolean_t dump_data_too
,
132 svn_stream_t
*propstream
;
134 if (trigger_var
&& !*trigger_var
)
137 svn_stringbuf_setempty(eb
->propstring
);
138 propstream
= svn_stream_from_stringbuf(eb
->propstring
, eb
->pool
);
139 SVN_ERR(svn_hash_write_incremental(eb
->props
, eb
->deleted_props
,
140 propstream
, "PROPS-END", pool
));
141 SVN_ERR(svn_stream_close(propstream
));
143 /* Prop-delta: true */
144 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
145 SVN_REPOS_DUMPFILE_PROP_DELTA
148 /* Prop-content-length: 193 */
149 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
150 SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
151 ": %" APR_SIZE_T_FMT
"\n", eb
->propstring
->len
));
155 /* Content-length: 14 */
156 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
157 SVN_REPOS_DUMPFILE_CONTENT_LENGTH
158 ": %" APR_SIZE_T_FMT
"\n\n",
159 eb
->propstring
->len
));
161 /* The properties. */
162 SVN_ERR(svn_stream_write(eb
->stream
, eb
->propstring
->data
,
163 &(eb
->propstring
->len
)));
165 /* No text is going to be dumped. Write a couple of newlines and
166 wait for the next node/ revision. */
167 SVN_ERR(svn_stream_printf(eb
->stream
, pool
, "\n\n"));
169 /* Cleanup so that data is never dumped twice. */
170 apr_hash_clear(eb
->props
);
171 apr_hash_clear(eb
->deleted_props
);
173 *trigger_var
= FALSE
;
180 * Write out a node record for PATH of type KIND under EB->FS_ROOT.
181 * ACTION describes what is happening to the node (see enum
182 * svn_node_action). Write record to writable EB->STREAM, using
183 * EB->BUFFER to write in chunks.
185 * If the node was itself copied, IS_COPY is TRUE and the
186 * path/revision of the copy source are in COPYFROM_PATH/COPYFROM_REV.
187 * If IS_COPY is FALSE, yet COPYFROM_PATH/COPYFROM_REV are valid, this
188 * node is part of a copied subtree.
191 dump_node(struct dump_edit_baton
*eb
,
192 const char *path
, /* an absolute path. */
193 svn_node_kind_t kind
,
194 enum svn_node_action action
,
195 svn_boolean_t is_copy
,
196 const char *copyfrom_path
,
197 svn_revnum_t copyfrom_rev
,
200 /* Remove leading slashes from path and copyfrom_path */
201 if (path
&& strcmp(path
, "/"))
202 path
= ((*path
== '/') ? path
+ 1 : path
);
204 if (copyfrom_path
&& strcmp(copyfrom_path
, "/"))
205 copyfrom_path
= ((*copyfrom_path
== '/') ?
206 copyfrom_path
+ 1 : copyfrom_path
);
208 /* Node-path: commons/STATUS */
209 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
210 SVN_REPOS_DUMPFILE_NODE_PATH
": %s\n", path
));
212 /* Node-kind: file */
213 if (kind
== svn_node_file
)
214 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
215 SVN_REPOS_DUMPFILE_NODE_KIND
": file\n"));
216 else if (kind
== svn_node_dir
)
217 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
218 SVN_REPOS_DUMPFILE_NODE_KIND
": dir\n"));
221 /* Write the appropriate Node-action header */
224 case svn_node_action_change
:
225 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
226 SVN_REPOS_DUMPFILE_NODE_ACTION
230 case svn_node_action_replace
:
233 /* Node-action: replace */
234 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
235 SVN_REPOS_DUMPFILE_NODE_ACTION
238 eb
->dump_props_pending
= TRUE
;
241 /* More complex case: is_copy is true, and copyfrom_path/
242 copyfrom_rev are present: delete the original, and then re-add
245 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
246 SVN_REPOS_DUMPFILE_NODE_ACTION
249 /* Recurse: Print an additional add-with-history record. */
250 SVN_ERR(dump_node(eb
, path
, kind
, svn_node_action_add
,
251 is_copy
, copyfrom_path
, copyfrom_rev
, pool
));
253 /* We can leave this routine quietly now, don't need to dump any
254 content; that was already done in the second record. */
255 eb
->dump_props
= FALSE
;
258 case svn_node_action_delete
:
259 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
260 SVN_REPOS_DUMPFILE_NODE_ACTION
263 /* We can leave this routine quietly now, don't need to dump
265 SVN_ERR(svn_stream_printf(eb
->stream
, pool
, "\n\n"));
266 eb
->dump_props
= FALSE
;
269 case svn_node_action_add
:
270 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
271 SVN_REPOS_DUMPFILE_NODE_ACTION
": add\n"));
275 /* eb->dump_props_pending for files is handled in close_file
276 which is called immediately. However, directories are not
277 closed until all the work inside them has been done;
278 eb->dump_props_pending for directories is handled in all the
279 functions that can possibly be called after add_directory:
280 add_directory, open_directory, delete_entry, close_directory,
281 add_file, open_file. change_dir_prop is a special case. */
283 eb
->dump_props_pending
= TRUE
;
287 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
288 SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV
290 SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH
292 copyfrom_rev
, copyfrom_path
));
294 /* Ugly hack: If a directory was copied from a previous revision,
295 nothing else can be done, and close_file won't be called to
296 write two blank lines. Write them here otherwise the `svnadmin
297 load` parser will fail. */
298 if (kind
== svn_node_dir
)
299 SVN_ERR(svn_stream_printf(eb
->stream
, pool
, "\n\n"));
304 /* Dump property headers */
305 SVN_ERR(dump_props(eb
, &(eb
->dump_props
), FALSE
, pool
));
311 open_root(void *edit_baton
,
312 svn_revnum_t base_revision
,
316 struct dump_edit_baton
*eb
= edit_baton
;
317 /* Allocate a special pool for the edit_baton to avoid pool
319 eb
->pool
= svn_pool_create(pool
);
320 eb
->props
= apr_hash_make(eb
->pool
);
321 eb
->deleted_props
= apr_hash_make(eb
->pool
);
322 eb
->propstring
= svn_stringbuf_create("", eb
->pool
);
324 *root_baton
= make_dir_baton(NULL
, NULL
, SVN_INVALID_REVNUM
,
325 edit_baton
, NULL
, FALSE
, pool
);
330 delete_entry(const char *path
,
331 svn_revnum_t revision
,
335 struct dir_baton
*pb
= parent_baton
;
336 const char *mypath
= apr_pstrdup(pool
, path
);
338 /* Some pending properties to dump? */
339 SVN_ERR(dump_props(pb
->eb
, &(pb
->eb
->dump_props_pending
), TRUE
, pool
));
341 /* Add this path to the deleted_entries of the parent directory
343 apr_hash_set(pb
->deleted_entries
, mypath
, APR_HASH_KEY_STRING
, pb
);
349 add_directory(const char *path
,
351 const char *copyfrom_path
,
352 svn_revnum_t copyfrom_rev
,
356 struct dir_baton
*pb
= parent_baton
;
358 struct dir_baton
*new_db
359 = make_dir_baton(path
, copyfrom_path
, copyfrom_rev
, pb
->eb
, pb
, TRUE
, pool
);
360 svn_boolean_t is_copy
;
362 /* Some pending properties to dump? */
363 SVN_ERR(dump_props(pb
->eb
, &(pb
->eb
->dump_props_pending
), TRUE
, pool
));
365 /* This might be a replacement -- is the path already deleted? */
366 val
= apr_hash_get(pb
->deleted_entries
, path
, APR_HASH_KEY_STRING
);
368 /* Detect an add-with-history */
369 is_copy
= ARE_VALID_COPY_ARGS(copyfrom_path
, copyfrom_rev
);
372 SVN_ERR(dump_node(pb
->eb
, path
,
374 val
? svn_node_action_replace
: svn_node_action_add
,
376 is_copy
? copyfrom_path
: NULL
,
377 is_copy
? copyfrom_rev
: SVN_INVALID_REVNUM
,
381 /* Delete the path, it's now been dumped */
382 apr_hash_set(pb
->deleted_entries
, path
, APR_HASH_KEY_STRING
, NULL
);
384 new_db
->written_out
= TRUE
;
386 *child_baton
= new_db
;
391 open_directory(const char *path
,
393 svn_revnum_t base_revision
,
397 struct dir_baton
*pb
= parent_baton
;
398 struct dir_baton
*new_db
;
399 const char *copyfrom_path
= NULL
;
400 svn_revnum_t copyfrom_rev
= SVN_INVALID_REVNUM
;
402 /* Some pending properties to dump? */
403 SVN_ERR(dump_props(pb
->eb
, &(pb
->eb
->dump_props_pending
), TRUE
, pool
));
405 /* If the parent directory has explicit comparison path and rev,
406 record the same for this one. */
407 if (pb
&& ARE_VALID_COPY_ARGS(pb
->copyfrom_path
, pb
->copyfrom_rev
))
409 copyfrom_path
= svn_uri_join(pb
->copyfrom_path
,
410 svn_relpath_basename(path
, pool
),
412 copyfrom_rev
= pb
->copyfrom_rev
;
415 new_db
= make_dir_baton(path
, copyfrom_path
, copyfrom_rev
, pb
->eb
, pb
,
417 *child_baton
= new_db
;
422 close_directory(void *dir_baton
,
425 struct dir_baton
*db
= dir_baton
;
426 struct dump_edit_baton
*eb
= db
->eb
;
427 apr_hash_index_t
*hi
;
428 apr_pool_t
*iterpool
= svn_pool_create(pool
);
430 /* Some pending properties to dump? */
431 SVN_ERR(dump_props(eb
, &(eb
->dump_props_pending
), TRUE
, pool
));
433 /* Dump the directory entries */
434 for (hi
= apr_hash_first(pool
, db
->deleted_entries
); hi
;
435 hi
= apr_hash_next(hi
))
439 apr_hash_this(hi
, &key
, NULL
, NULL
);
442 svn_pool_clear(iterpool
);
444 SVN_ERR(dump_node(db
->eb
, path
, svn_node_unknown
, svn_node_action_delete
,
445 FALSE
, NULL
, SVN_INVALID_REVNUM
, iterpool
));
448 svn_pool_destroy(iterpool
);
453 add_file(const char *path
,
455 const char *copyfrom_path
,
456 svn_revnum_t copyfrom_rev
,
460 struct dir_baton
*pb
= parent_baton
;
462 svn_boolean_t is_copy
;
464 /* Some pending properties to dump? */
465 SVN_ERR(dump_props(pb
->eb
, &(pb
->eb
->dump_props_pending
), TRUE
, pool
));
467 /* This might be a replacement -- is the path already deleted? */
468 val
= apr_hash_get(pb
->deleted_entries
, path
, APR_HASH_KEY_STRING
);
470 /* Detect add-with-history. */
471 is_copy
= ARE_VALID_COPY_ARGS(copyfrom_path
, copyfrom_rev
);
474 SVN_ERR(dump_node(pb
->eb
, path
,
476 val
? svn_node_action_replace
: svn_node_action_add
,
478 is_copy
? copyfrom_path
: NULL
,
479 is_copy
? copyfrom_rev
: SVN_INVALID_REVNUM
,
483 /* delete the path, it's now been dumped. */
484 apr_hash_set(pb
->deleted_entries
, path
, APR_HASH_KEY_STRING
, NULL
);
486 /* Build a nice file baton to pass to change_file_prop and
488 *file_baton
= pb
->eb
;
494 open_file(const char *path
,
496 svn_revnum_t ancestor_revision
,
500 struct dir_baton
*pb
= parent_baton
;
501 const char *copyfrom_path
= NULL
;
502 svn_revnum_t copyfrom_rev
= SVN_INVALID_REVNUM
;
503 apr_array_header_t
*compose_path
;
505 /* Some pending properties to dump? */
506 SVN_ERR(dump_props(pb
->eb
, &(pb
->eb
->dump_props_pending
), TRUE
, pool
));
508 compose_path
= apr_array_make(pool
, 2, sizeof(const char *));
510 /* If the parent directory has explicit copyfrom path and rev,
511 record the same for this one. */
512 if (pb
&& ARE_VALID_COPY_ARGS(pb
->copyfrom_path
, pb
->copyfrom_rev
))
514 APR_ARRAY_PUSH(compose_path
, const char *) = pb
->copyfrom_path
;
515 APR_ARRAY_PUSH(compose_path
, const char *) =
516 svn_relpath_basename(path
, pool
);
517 copyfrom_path
= svn_path_compose(compose_path
, pool
);
518 copyfrom_rev
= pb
->copyfrom_rev
;
521 SVN_ERR(dump_node(pb
->eb
, path
, svn_node_file
, svn_node_action_change
,
522 FALSE
, copyfrom_path
, copyfrom_rev
, pool
));
524 /* Build a nice file baton to pass to change_file_prop and
526 *file_baton
= pb
->eb
;
532 change_dir_prop(void *parent_baton
,
534 const svn_string_t
*value
,
537 struct dir_baton
*db
= parent_baton
;
539 if (svn_property_kind(NULL
, name
) != svn_prop_regular_kind
)
543 apr_hash_set(db
->eb
->props
, apr_pstrdup(pool
, name
),
544 APR_HASH_KEY_STRING
, svn_string_dup(value
, pool
));
546 apr_hash_set(db
->eb
->deleted_props
, apr_pstrdup(pool
, name
),
547 APR_HASH_KEY_STRING
, "");
549 if (! db
->written_out
)
551 /* If db->written_out is set, it means that the node information
552 corresponding to this directory has already been written: don't
553 do anything; dump_props_pending will take care of dumping the
554 props. If it not, dump the node itself before dumping the
557 SVN_ERR(dump_node(db
->eb
, db
->abspath
, svn_node_dir
,
558 svn_node_action_change
, FALSE
, db
->copyfrom_path
,
559 db
->copyfrom_rev
, pool
));
561 SVN_ERR(dump_props(db
->eb
, NULL
, TRUE
, pool
));
562 db
->written_out
= TRUE
;
568 change_file_prop(void *file_baton
,
570 const svn_string_t
*value
,
573 struct dump_edit_baton
*eb
= file_baton
;
575 if (svn_property_kind(NULL
, name
) != svn_prop_regular_kind
)
579 apr_hash_set(eb
->props
, apr_pstrdup(pool
, name
),
580 APR_HASH_KEY_STRING
, svn_string_dup(value
, pool
));
582 apr_hash_set(eb
->deleted_props
, apr_pstrdup(pool
, name
),
583 APR_HASH_KEY_STRING
, "");
585 /* Dump the property headers and wait; close_file might need
586 to write text headers too depending on whether
587 apply_textdelta is called */
588 eb
->dump_props_pending
= TRUE
;
594 window_handler(svn_txdelta_window_t
*window
, void *baton
)
596 struct handler_baton
*hb
= baton
;
597 struct dump_edit_baton
*eb
= hb
->eb
;
598 static svn_error_t
*err
;
600 err
= hb
->apply_handler(window
, hb
->apply_baton
);
601 if (window
!= NULL
&& !err
)
607 /* Write information about the filepath to hb->eb */
608 eb
->delta_abspath
= apr_pstrdup(eb
->pool
, hb
->delta_abspath
);
611 svn_pool_destroy(hb
->pool
);
616 apply_textdelta(void *file_baton
, const char *base_checksum
,
618 svn_txdelta_window_handler_t
*handler
,
619 void **handler_baton
)
621 struct dump_edit_baton
*eb
= file_baton
;
623 /* Custom handler_baton allocated in a separate pool */
624 apr_pool_t
*handler_pool
= svn_pool_create(pool
);
625 struct handler_baton
*hb
= apr_pcalloc(handler_pool
, sizeof(*hb
));
626 hb
->pool
= handler_pool
;
629 /* Use a temporary file to measure the text-content-length */
630 SVN_ERR(svn_stream_open_unique(&(hb
->delta_filestream
), &hb
->delta_abspath
,
631 NULL
, svn_io_file_del_none
, hb
->pool
,
634 /* Prepare to write the delta to the temporary file. */
635 svn_txdelta_to_svndiff2(&(hb
->apply_handler
), &(hb
->apply_baton
),
636 hb
->delta_filestream
, 0, hb
->pool
);
637 eb
->dump_text
= TRUE
;
638 eb
->base_checksum
= apr_pstrdup(pool
, base_checksum
);
640 /* The actual writing takes place when this function has
641 finished. Set handler and handler_baton now so for
643 *handler
= window_handler
;
650 close_file(void *file_baton
,
651 const char *text_checksum
,
654 struct dump_edit_baton
*eb
= file_baton
;
655 apr_file_t
*delta_file
;
656 svn_stream_t
*delta_filestream
;
657 apr_finfo_t
*info
= apr_pcalloc(pool
, sizeof(apr_finfo_t
));
659 /* Some pending properties to dump? */
660 SVN_ERR(dump_props(eb
, &(eb
->dump_props_pending
), FALSE
, pool
));
662 /* The prop headers have already been dumped in dump_node; now dump
666 /* Text-delta: true */
667 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
668 SVN_REPOS_DUMPFILE_TEXT_DELTA
671 SVN_ERR(svn_io_stat(info
, eb
->delta_abspath
, APR_FINFO_SIZE
, pool
));
673 if (eb
->base_checksum
)
674 /* Text-delta-base-md5: */
675 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
676 SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_MD5
680 /* Text-content-length: 39 */
681 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
682 SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH
684 (unsigned long)info
->size
));
686 /* Text-content-md5: 82705804337e04dcd0e586bfa2389a7f */
687 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
688 SVN_REPOS_DUMPFILE_TEXT_CONTENT_MD5
693 /* Content-length: 1549 */
694 /* If both text and props are absent, skip this header */
695 if (eb
->dump_props
|| eb
->dump_props_pending
)
696 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
697 SVN_REPOS_DUMPFILE_CONTENT_LENGTH
699 (unsigned long)info
->size
+ eb
->propstring
->len
));
700 else if (eb
->dump_text
)
701 SVN_ERR(svn_stream_printf(eb
->stream
, pool
,
702 SVN_REPOS_DUMPFILE_CONTENT_LENGTH
704 (unsigned long)info
->size
));
706 /* Dump the props; the propstring should have already been
707 written in dump_node or above */
708 if (eb
->dump_props
|| eb
->dump_props_pending
)
710 SVN_ERR(svn_stream_write(eb
->stream
, eb
->propstring
->data
,
711 &(eb
->propstring
->len
)));
714 eb
->dump_props
= eb
->dump_props_pending
= FALSE
;
715 apr_hash_clear(eb
->props
);
716 apr_hash_clear(eb
->deleted_props
);
722 /* Open the temporary file, map it to a stream, copy
723 the stream to eb->stream, close and delete the
725 SVN_ERR(svn_io_file_open(&delta_file
, eb
->delta_abspath
, APR_READ
,
726 APR_OS_DEFAULT
, pool
));
727 delta_filestream
= svn_stream_from_aprfile2(delta_file
, TRUE
, pool
);
728 SVN_ERR(svn_stream_copy3(delta_filestream
, eb
->stream
, NULL
, NULL
, pool
));
731 SVN_ERR(svn_io_file_close(delta_file
, pool
));
732 SVN_ERR(svn_stream_close(delta_filestream
));
733 SVN_ERR(svn_io_remove_file2(eb
->delta_abspath
, TRUE
, pool
));
734 eb
->dump_text
= FALSE
;
737 SVN_ERR(svn_stream_printf(eb
->stream
, pool
, "\n\n"));
743 close_edit(void *edit_baton
, apr_pool_t
*pool
)
745 struct dump_edit_baton
*eb
= edit_baton
;
746 svn_pool_destroy(eb
->pool
);
752 get_dump_editor(const svn_delta_editor_t
**editor
,
754 svn_stream_t
*stream
,
757 struct dump_edit_baton
*eb
;
758 svn_delta_editor_t
*de
;
760 eb
= apr_pcalloc(pool
, sizeof(struct dump_edit_baton
));
763 de
= svn_delta_default_editor(pool
);
764 de
->open_root
= open_root
;
765 de
->delete_entry
= delete_entry
;
766 de
->add_directory
= add_directory
;
767 de
->open_directory
= open_directory
;
768 de
->close_directory
= close_directory
;
769 de
->change_dir_prop
= change_dir_prop
;
770 de
->change_file_prop
= change_file_prop
;
771 de
->apply_textdelta
= apply_textdelta
;
772 de
->add_file
= add_file
;
773 de
->open_file
= open_file
;
774 de
->close_file
= close_file
;
775 de
->close_edit
= close_edit
;
777 /* Set the edit_baton and editor. */