All,
Attached is my first patch for Subversion, so go easy with the
flames :) This is to change the order in which files are shown
by and 'svn diff', such that all files in a directory are shown
first, alphabetically, then all directories, also alphabetically.
I put the function svn_repos_sort_by_type_and_path() in
libsvn_repos, since that is the only consumer of the function.
However, it sorts entries of type svn_fs_dirent_t, so perhaps
a better location would have been libsvn_fs. I am not sure this
is a generically useful function outside of libsvn_repos which
is why it is where it currently is. I originally had the function
as a static inside both delta.c and reporter.c, but thats a bit
wasteful so I make it a visible function.
A similar function was needed in libsvn_wc, but there there is
only a single consumer of it, so I made it static instead of
adding a new API. That version differs from the one in libsvn_repos
only in the data types it sorts on (svn_wc_entry_t).
Please feel free to whack me upside the head with a big SVN
cluestick if this patch is not up to par.
Kean
[[[
Patch by: Kean Johnston <jkj@sco.com>
* subversion/libsvn_repos/delta.c,
subversion/libsvn_repos/reporter.c:
(delta_dirs): Sort the hash before processing it, so that diffs arrive
files first, alphabetically, then directories, alphabetically. Sort using
the new svn_repos_sort_by_type_and_path() function.
* subversion/libsvn_repos/repos.h:
Include svn_sorts.h for declaration of svn_sort__item_t, and
svn_sort__hash().
(svn_repos_sort_by_type_and_path): Declare new function used for sorting
diffs so they arrive in a more sensible order.
* subversion/libsvn_repos/repos.c:
(svn_repos_sort_by_type_and_path): New function to sort an svn_fs_dirent_t
hash first by type (svn_node_file before svn_node_dir) and then by name,
using svn_path_compare_paths().
* subversion/libsvn_wc/diff.c:
Added include of svn_sorts.h for svn_sort__hash.
(sort_by_type_and_path): New local function for sorting the entries list
first by file type (svn_node_file before svn_node_dir), and then by the
standard order imposed by svn_path_compare_paths().
(directory_elements_diff): Sort the hash before processing it, so that
diffs arrive files first, alphabetically, then directories, alphabetically.
]]]
Index: subversion/libsvn_repos/delta.c
===================================================================
--- subversion/libsvn_repos/delta.c (revision 17442)
+++ subversion/libsvn_repos/delta.c (working copy)
@@ -928,6 +928,8 @@
apr_hash_t *s_entries = 0, *t_entries = 0;
apr_hash_index_t *hi;
apr_pool_t *subpool;
+ apr_array_header_t *sorted;
+ int i;
assert (target_path);
@@ -955,8 +957,14 @@
still remaining the source entries hash represent entries that no
longer exist in target. Use editor calls to delete those entries
from the target tree. */
- for (hi = apr_hash_first (pool, t_entries); hi; hi = apr_hash_next (hi))
+
+ sorted = svn_sort__hash (t_entries, svn_repos_sort_by_type_and_path, pool);
+
+ /* Loop over the dirents in the target. */
+ for (i = 0; i < sorted->nelts; ++i)
{
+ const svn_sort__item_t *item = &APR_ARRAY_IDX(sorted, i,
+ const svn_sort__item_t);
const svn_fs_dirent_t *s_entry, *t_entry;
const void *key;
void *val;
@@ -970,8 +978,11 @@
svn_pool_clear (subpool);
/* KEY is the entry name in target, VAL the dirent */
- apr_hash_this (hi, &key, &klen, &val);
- t_entry = val;
+ val = item->value;
+ t_entry = item->value;
+ key = item->key;
+ klen = item->klen;
+
tgt_kind = t_entry->kind;
t_fullpath = svn_path_join (target_path, t_entry->name, subpool);
e_fullpath = svn_path_join (edit_path, t_entry->name, subpool);
Index: subversion/libsvn_repos/reporter.c
===================================================================
--- subversion/libsvn_repos/reporter.c (revision 17442)
+++ subversion/libsvn_repos/reporter.c (working copy)
@@ -693,6 +693,8 @@
void *val;
const char *name, *s_fullpath, *t_fullpath, *e_fullpath;
path_info_t *info;
+ apr_array_header_t *sorted;
+ int i;
/* Compare the property lists. If we're starting empty, pass a NULL
source path so that we add all the properties.
@@ -776,12 +778,16 @@
}
}
+ sorted = svn_sort__hash (t_entries, svn_repos_sort_by_type_and_path, pool);
+
/* Loop over the dirents in the target. */
- for (hi = apr_hash_first (pool, t_entries); hi; hi = apr_hash_next (hi))
+ for (i = 0; i < sorted->nelts; ++i)
{
+ const svn_sort__item_t *item = &APR_ARRAY_IDX(sorted, i,
+ const svn_sort__item_t);
+
+ t_entry = item->value;
svn_pool_clear (subpool);
- apr_hash_this (hi, NULL, NULL, &val);
- t_entry = val;
/* Compose the report, editor, and target paths for this entry. */
e_fullpath = svn_path_join (e_path, t_entry->name, subpool);
Index: subversion/libsvn_repos/repos.c
===================================================================
--- subversion/libsvn_repos/repos.c (revision 17442)
+++ subversion/libsvn_repos/repos.c (working copy)
@@ -2146,3 +2146,24 @@
*dirent = ent;
return SVN_NO_ERROR;
}
+
+
+int
+svn_repos_sort_by_type_and_path (const svn_sort__item_t *item1,
+ const svn_sort__item_t *item2)
+{
+ const svn_fs_dirent_t *entry1;
+ const svn_fs_dirent_t *entry2;
+ const char *astr, *bstr;
+
+ astr = item1->key;
+ bstr = item2->key;
+ entry1 = item1->value;
+ entry2 = item2->value;
+
+ if ((entry1->kind == svn_node_file) && (entry2->kind == svn_node_dir))
+ return -1;
+ else if ((entry2->kind == svn_node_file) && (entry1->kind == svn_node_dir))
+ return 1;
+ return svn_path_compare_paths (astr, bstr);
+}
Index: subversion/libsvn_repos/repos.h
===================================================================
--- subversion/libsvn_repos/repos.h (revision 17442)
+++ subversion/libsvn_repos/repos.h (working copy)
@@ -22,6 +22,7 @@
#include <apr_hash.h>
#include "svn_fs.h"
+#include "svn_sorts.h"
#ifdef __cplusplus
extern "C" {
@@ -240,6 +241,14 @@
apr_pool_t *pool);
+/* Sort an svn_fs_direct_t hash first by file type (such that nodes of type
+ svn_node_file appear before svn_node_dir nodes), and then alphabetically
+ as defined by svn_path_compare_paths.
+
+ This function is intended as a callback for svn_sort__hash(). */
+int
+svn_repos_sort_by_type_and_path (const svn_sort__item_t *item1,
+ const svn_sort__item_t *item2);
#ifdef __cplusplus
}
#endif /* __cplusplus */
Index: subversion/libsvn_wc/diff.c
===================================================================
--- subversion/libsvn_wc/diff.c (revision 17442)
+++ subversion/libsvn_wc/diff.c (working copy)
@@ -50,6 +50,7 @@
#include "svn_pools.h"
#include "svn_path.h"
+#include "svn_sorts.h"
#include "wc.h"
#include "props.h"
@@ -621,6 +622,38 @@
return SVN_NO_ERROR;
}
+
+/*
+ * This function is called to sort the directory entries. The idea is to
+ * have all of the files diffed first, in alphabetical order, then all
+ * of the directories, in alphabetical order. So this modified version of
+ * svn_sort_compare_items_as_paths will check the entry type, and always
+ * return -1 if a file and a directory are being compared, a normal return
+ * or -1, 0 or 1 if the entry types match.
+ */
+static int
+sort_by_type_and_path (const svn_sort__item_t *a,
+ const svn_sort__item_t *b)
+{
+ const svn_wc_entry_t *entry1;
+ const svn_wc_entry_t *entry2;
+ const char *astr, *bstr;
+
+ astr = a->key;
+ bstr = b->key;
+ entry1 = a->value;
+ entry2 = b->value;
+ assert(astr[a->klen] == '\0');
+ assert(bstr[b->klen] == '\0');
+
+ if ((entry1->kind == svn_node_file) && (entry2->kind == svn_node_dir))
+ return -1;
+ else if ((entry2->kind == svn_node_file) && (entry1->kind == svn_node_dir))
+ return 1;
+ return svn_path_compare_paths (astr, bstr);
+}
+
+
/* Called when the directory is closed to compare any elements that have
* not yet been compared. This identifies local, working copy only
* changes. At this stage we are dealing with files/directories that do
@@ -634,10 +667,11 @@
svn_boolean_t added)
{
apr_hash_t *entries;
- apr_hash_index_t *hi;
svn_boolean_t in_anchor_not_target;
apr_pool_t *subpool;
svn_wc_adm_access_t *adm_access;
+ apr_array_header_t *sorted;
+ int i;
/* This directory should have been unchanged or replaced, not added,
since an added directory can only contain added files and these will
@@ -691,9 +725,12 @@
subpool = svn_pool_create (dir_baton->pool);
- for (hi = apr_hash_first (dir_baton->pool, entries); hi;
- hi = apr_hash_next (hi))
+ sorted = svn_sort__hash (entries, sort_by_type_and_path, dir_baton->pool);
+
+ for (i = 0; i < sorted->nelts; ++i)
{
+ const svn_sort__item_t *item = &APR_ARRAY_IDX(sorted, i,
+ const svn_sort__item_t);
const void *key;
void *val;
const svn_wc_entry_t *entry;
@@ -702,9 +739,9 @@
svn_pool_clear (subpool);
- apr_hash_this (hi, &key, NULL, &val);
- name = key;
- entry = val;
+ name = item->key;
+ key = item->key;
+ entry = item->value;
/* Skip entry for the directory itself. */
if (strcmp (key, SVN_WC_ENTRY_THIS_DIR) == 0)
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Sat Nov 19 22:28:40 2005