Mark Grosberg <mark@nolab.conman.org> writes:
> Here is my updated patch. I now use a hash table as suggested by Brane to
> store the paths we've seen. Also, qsort() is now used to remove
> the "UNMARKED" entries.
>
> I also added an error message if no entries are specified. I've tested
> this with several combinations and pathalogical cases on my test repos.
>
> Let me know what you think. I would love to see this merged. This nit
> bugs me in CVS daily.
Hey Mark -- a minor nit (which I want to counterbalance in advance by
praising both the patch itself, and your responsiveness to feedback):
Always include the full log message with every post of a patch. You
can also give metadata like "Repost number 3 of the blah blah patch"
or whatever, but the patch and its log message should be treated as a
self-contained unit, always travelling together. Otherwise, whoever
reviews and/or applies the patch must search back through their old
mail (or worse, visit the mailing list archives) to dig up the log
message. And even then, they can't be *sure* it's still accurate for
the version of the patch just posted...
So, please repost this exact same patch, together with its log message
:-).
Thanks,
-Karl
> -----------------------------------------------------------------------
>
> Index: include/svn_error_codes.h
> ===================================================================
> --- include/svn_error_codes.h (revision 5857)
> +++ include/svn_error_codes.h (working copy)
> @@ -688,6 +688,11 @@
> SVN_ERR_CLIENT_CATEGORY_START + 8,
> "Revision range is not allowed")
>
> + SVN_ERRDEF (SVN_ERR_CLIENT_NO_WORK,
> + SVN_ERR_CLIENT_CATEGORY_START + 9,
> + "No work to do")
> +
> +
> /* misc errors */
>
> SVN_ERRDEF (SVN_ERR_BASE,
> Index: include/svn_client.h
> ===================================================================
> --- include/svn_client.h (revision 5857)
> +++ include/svn_client.h (working copy)
> @@ -292,6 +292,7 @@
> #define SVN_CLIENT_COMMIT_ITEM_TEXT_MODS 0x04
> #define SVN_CLIENT_COMMIT_ITEM_PROP_MODS 0x08
> #define SVN_CLIENT_COMMIT_ITEM_IS_COPY 0x10
> +#define SVN_CLIENT_COMMIT_ITEM_UNMARKED 0x20
> /** @} */
>
> /** The commit candidate structure. */
> Index: libsvn_client/commit_util.c
> ===================================================================
> --- libsvn_client/commit_util.c (revision 5857)
> +++ libsvn_client/commit_util.c (working copy)
> @@ -730,6 +730,14 @@
> = *((const svn_client_commit_item_t * const *) a);
> const svn_client_commit_item_t *item2
> = *((const svn_client_commit_item_t * const *) b);
> +
> + if ((item1->state_flags & SVN_CLIENT_COMMIT_ITEM_UNMARKED)
> + && (!(item2->state_flags & SVN_CLIENT_COMMIT_ITEM_UNMARKED)))
> + return 1;
> + if ((!(item1->state_flags & SVN_CLIENT_COMMIT_ITEM_UNMARKED))
> + && (item2->state_flags & SVN_CLIENT_COMMIT_ITEM_UNMARKED))
> + return -1;
> +
> return svn_path_compare_paths (item1->url, item2->url);
> }
>
> @@ -751,6 +759,20 @@
> qsort (ci->elts, ci->nelts,
> ci->elt_size, svn_client__sort_commit_item_urls);
>
> + /* Delete unrequested items. */
> + for (i = ci->nelts; i > 0; i--)
> + {
> + item = (((svn_client_commit_item_t **) ci->elts)[i - 1]);
> + if (!(item->state_flags & SVN_CLIENT_COMMIT_ITEM_UNMARKED))
> + break;
> + }
> +
> + ci->nelts = i;
> + if (ci->nelts == 0)
> + return svn_error_create (SVN_ERR_CLIENT_NO_WORK, NULL,
> + "No entires submitted for commit.");
> +
> +
> /* Loop through the URLs, finding the longest usable ancestor common
> to all of them, and making sure there are no duplicate URLs. */
> for (i = 0; i < ci->nelts; i++)
> Index: clients/cmdline/util.c
> ===================================================================
> --- clients/cmdline/util.c (revision 5857)
> +++ clients/cmdline/util.c (working copy)
> @@ -416,6 +416,154 @@
>
> #define EDITOR_EOF_PREFIX "--This line, and those below, will be ignored--"
>
> +/* Get the full path string for the specificed item. */
> +static const char *
> +get_item_path (svn_client_commit_item_t *item,
> + struct log_msg_baton *lmb,
> + apr_pool_t *pool)
> +{
> + const char *item_path = item->path;
> +
> + if (! item_path)
> + item_path = item->url;
> + else if (! *item_path)
> + item_path = ".";
> +
> + if (item_path && lmb->base_dir)
> + item_path = svn_path_is_child (lmb->base_dir, item_path, pool);
> +
> + /* If still no path, then just use current directory. */
> + if (! item_path)
> + item_path = ".";
> +
> + return item_path;
> +}
> +
> +/* Parse the edited comitted message and store the named paths
> + in the hash. */
> +static void
> +process_comitted_list(apr_hash_t *seen,
> + char *commited_list,
> + apr_pool_t *pool)
> +{
> + char *end_str, *prev_str = NULL;
> + int i;
> +
> + /* Find the generated message. */
> + end_str = commited_list;
> + while (end_str != NULL)
> + {
> + end_str = strstr (end_str, EDITOR_EOF_PREFIX);
> + if (end_str == NULL)
> + break;
> +
> + end_str = end_str + (sizeof(EDITOR_EOF_PREFIX) - 1);
> + prev_str = end_str;
> + }
> +
> + if (prev_str == NULL)
> + return;
> + while (*prev_str != '\0')
> + {
> + if (!apr_isspace (*prev_str))
> + break;
> + prev_str++;
> + }
> +
> + /* Now, parse each line and make sure that the commited item is named. */
> + for (;;)
> + {
> + char *end_of_path;
> +
> + /* Skip leading whitespace. */
> + for (;;)
> + {
> + if (*prev_str == '\0')
> + return;
> +
> + if (!apr_isspace (*prev_str))
> + break;
> + prev_str++;
> + }
> + if (*prev_str == '\0')
> + break;
> +
> + /* The next byte had better be one of the text mod's below. */
> + switch (*prev_str++)
> + {
> + case '_':
> + case 'R':
> + case 'A':
> + case 'D':
> + case 'M':
> + break;
> +
> + default:
> + return;
> + }
> +
> + /* The next byte had better be one of the prop mod's below. */
> + switch (*prev_str++)
> + {
> + case ' ':
> + case 'M':
> + break;
> +
> + default:
> + return;
> + }
> +
> + /* Skip more whitespace. */
> + for (;;)
> + {
> + if (*prev_str == '\0')
> + return;
> + if (!apr_isspace(*prev_str))
> + break;
> + prev_str++;
> + }
> +
> + /* Chop up the path. */
> + for (end_of_path = prev_str; *end_of_path != '\0'; end_of_path++)
> + {
> + if (*end_of_path == '\n')
> + break;
> + }
> + if (*end_of_path == '\0')
> + return;
> +
> + /* Truncate the string. The path is now in prev_str. */
> + *end_of_path++ = '\0';
> +
> + /* Note the existence. */
> + apr_hash_set(seen, prev_str, APR_HASH_KEY_STRING, "");
> +
> + /* Advance the pointer. */
> + prev_str = end_of_path;
> + }
> +}
> +
> +/* Find the paths that are marked in the seen hash and set their
> + unmarked flags. */
> +static void
> +flag_unmarked (struct log_msg_baton *lmb,
> + apr_array_header_t *commit_items,
> + apr_hash_t *seen,
> + apr_pool_t *pool)
> +{
> + int i;
> +
> + for (i = 0; i < commit_items->nelts; i++)
> + {
> + svn_client_commit_item_t *item
> + = ((svn_client_commit_item_t **) commit_items->elts)[i];
> + const char *path = get_item_path (item, lmb, pool);
> +
> + if (! apr_hash_get (seen, path, APR_HASH_KEY_STRING))
> + item->state_flags |= SVN_CLIENT_COMMIT_ITEM_UNMARKED;
> + }
> +}
> +
> /* This function is of type svn_client_get_commit_log_t. */
> svn_error_t *
> svn_cl__get_log_message (const char **log_msg,
> @@ -469,21 +617,9 @@
> {
> svn_client_commit_item_t *item
> = ((svn_client_commit_item_t **) commit_items->elts)[i];
> - const char *path = item->path;
> + const char *path = get_item_path (item, lmb, pool);
> char text_mod = '_', prop_mod = ' ';
>
> - if (! path)
> - path = item->url;
> - else if (! *path)
> - path = ".";
> -
> - if (path && lmb->base_dir)
> - path = svn_path_is_child (lmb->base_dir, path, pool);
> -
> - /* If still no path, then just use current directory. */
> - if (! path)
> - path = ".";
> -
> if ((item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
> && (item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD))
> text_mod = 'R';
> @@ -542,8 +678,16 @@
>
> /* Strip the prefix from the buffer. */
> if (message)
> + {
> + char *commited_list = apr_pstrdup (pool, msg2);
> + apr_hash_t *seen = apr_hash_make(pool);
> +
> + process_comitted_list (seen, commited_list, pool);
> + flag_unmarked (lmb, commit_items, seen, pool);
> +
> truncate_buffer_at_prefix (&message->len, message->data,
> EDITOR_EOF_PREFIX);
> + }
>
> if (message)
> {
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
> For additional commands, e-mail: dev-help@subversion.tigris.org
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri May 9 07:57:55 2003