Hi stsp!
Attaching a patch showing a suggestion on how to split up
patch_target_t. Maybe you have some insights on this, before I rush out
and start grooking around and making changes to your design.
What 'svn patch' does
----------------------
1) Match hunks
2) Apply hunks to a stream backed up by a tmp file
3) Install. copy the tmp file to the target location
4) Notify the user on what has happened, e.g. fuzz, offset and rejects
The problem
-------------
Each property is essentially like it's own text file. 'svn patch' must
be generic enough to be able to perform the above actions on both
properties and texts.
Alternatives
--------------
* Simplify. Don't use the unidiff format but just copy the content
straight off and apply it.
* Duplicate. Create special code for handling props, e.g. have both
match_hunk() and match_property_hunk() and so on.
Proposed solution
-------------------
Use patch_target_t as a container for sub-patch_targets that can be either
file-text or a property. Store tree change info needed for step 3)
installing and step 4) notifying.
Use patch_target_stream_t for step 1) matching and step 2) applying. It
should contain streams to the property or text target and the hunks
associated with the specific file/property.
A scratch log message (the attached patch only contains changes to the
structs):
* subversion/libsvn_client/patch.c
(patch_target_stream_t): New. A struct used for handling the match and
apply step of 'svn patch'. It can be either associated with the
content of a file or a property.
(patch_target_t): Move some fields to patch_target_stream_t and
introduce it as a new field.
(get_hunk_info,
scan_for_match,
match_hunk): These funcs makes up step 1) matching. Use
patch_target_stream_t instead of patch_target_t.
(apply_hunk,
reject_hunk): These funcs makes up step 2) applying. Use
patch_target_stream_t instead of patch_target_t.
(init_patch_target): Create the patch_target_stream_t objects.
(apply_one_patch): Loop through the available property hunks in the
patch and do step 1) matching. Loop through the property hunks in
the patch and do step 2) applying.
(...): More things to do.
Cheers,
Daniel
Index: subversion/libsvn_client/patch.c
===================================================================
--- subversion/libsvn_client/patch.c (revision 956349)
+++ subversion/libsvn_client/patch.c (arbetskopia)
@@ -61,28 +61,14 @@ typedef struct {
int fuzz;
} hunk_info_t;
+/* ### Better naming. This struct contains streams and hunks associated with
+ * ### a target, be it a file or a property of a file. sub_patch_target_t?`*/
typedef struct {
- /* The patch being applied. */
- const svn_patch_t *patch;
- /* The target path as it appeared in the patch file,
- * but in canonicalised form. */
- const char *canon_path_from_patchfile;
+ /* The name of the property associated with this 'stream' or NULL if it's
+ * a text 'stream'. */
+ const char *prop_name;
- /* The target path, relative to the working copy directory the
- * patch is being applied to. A patch strip count applies to this
- * and only this path. This is never NULL. */
- const char *local_relpath;
-
- /* The absolute path of the target on the filesystem.
- * Any symlinks the path from the patch file may contain are resolved.
- * Is not always known, so it may be NULL. */
- char *local_abspath;
-
- /* The target file, read-only, seekable. This is NULL in case the target
- * file did not exist prior to patch application. */
- apr_file_t *file;
-
/* A stream to read lines form the target file. This is NULL in case
* the target file did not exist prior to patch application. */
svn_stream_t *stream;
@@ -100,13 +86,6 @@ typedef struct {
/* Path to the temporary file underlying the result stream. */
const char *patched_path;
- /* The reject stream, write-only, not seekable.
- * Hunks that are rejected will be written to this stream. */
- svn_stream_t *reject;
-
- /* Path to the temporary file underlying the reject stream. */
- const char *reject_path;
-
/* The line last read from the target file. */
svn_linenum_t current_line;
@@ -119,13 +98,48 @@ typedef struct {
* last line read from the target file was using. */
const char *eol_str;
+ /* True if end-of-file was reached while reading from the target. */
+ svn_boolean_t eof;
+
+ /* An array containing hunk_info_t structures for hunks already matched. */
+ apr_array_header_t *hunks;
+
+} patch_target_stream_t;
+
+
+typedef struct {
+ /* The patch being applied. */
+ const svn_patch_t *patch;
+
+ /* The target path as it appeared in the patch file,
+ * but in canonicalised form. */
+ const char *canon_path_from_patchfile;
+
+ /* The target path, relative to the working copy directory the
+ * patch is being applied to. A patch strip count applies to this
+ * and only this path. This is never NULL. */
+ const char *local_relpath;
+
+ /* The absolute path of the target on the filesystem.
+ * Any symlinks the path from the patch file may contain are resolved.
+ * Is not always known, so it may be NULL. */
+ char *local_abspath;
+
+ /* The target file, read-only, seekable. This is NULL in case the target
+ * file did not exist prior to patch application. */
+ apr_file_t *file;
+
+ /* The reject stream, write-only, not seekable.
+ * Hunks that are rejected will be written to this stream. */
+ svn_stream_t *reject;
+
+ /* Path to the temporary file underlying the reject stream. */
+ const char *reject_path;
+
/* An array containing stream markers marking the beginning
* each line in the target stream. */
apr_array_header_t *lines;
- /* An array containing hunk_info_t structures for hunks already matched. */
- apr_array_header_t *hunks;
-
/* The node kind of the target as found in WC-DB prior
* to patch application. */
svn_node_kind_t db_kind;
@@ -136,9 +150,6 @@ typedef struct {
/* True if the target was locally deleted prior to patching. */
svn_boolean_t locally_deleted;
- /* True if end-of-file was reached while reading from the target. */
- svn_boolean_t eof;
-
/* True if the target had to be skipped for some reason. */
svn_boolean_t skipped;
@@ -169,6 +180,14 @@ typedef struct {
/* The keywords of the target. */
apr_hash_t *keywords;
+ /* The streams for the file.
+ * ### C'mon the naming and doc strings suck.. */
+ patch_target_stream_t *file_stream;
+
+ /* An array containing patch_target_stream_t * objects for properties.
+ * ### .. This one sucks too. */
+ apr_array_header_t *property_streams;
+
/* The pool the target is allocated in. */
apr_pool_t *pool;
} patch_target_t;