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;

Reply via email to