* Michael W Thelen <thelenm@cs.utah.edu> [2004-07-03 15:25]:
> Anyway, this discussion is a bit separate from the actual patch. In a
> little while I'll send a new patch containing what you suggested: only
> the (b) special case handling, with the other changes removed.
Okay, here's a new patch. It only contains the changes necessary to fix
the problem of running 'svn log' on a working copy at BASE revision 0.
This time I also delved into the wondrous world of Python and added a
test case. I'm hoping that it actually does what I think it does, and
tests this change. Happily, the test fails on /trunk but passes after
applying this patch. :-) Just a warning that you may want to inspect
the Python code particularly closely.
I think I'll also produce a patch for the changes I was proposing
before, just so you have the clearest possible idea (i.e. source code)
of what I'm suggesting.
Log:
Fix and document the special case when the user runs "svn log" with no
arguments in a working copy at BASE revision 0. This case is handled as if
the user requested -rBASE:1. But if the repository is not empty, we don't
want to print the log message for r1, since the working copy is at r0.
Also add a test case.
* subversion/include/svn_client.h
(svn_client_log): Add documentation for this special case.
* subversion/libsvn_client/log.c
(svn_client_log): Detect the special case condition and if it occurs, invoke
the log message receiver manually with a message for revision 0.
* subversion/tests/clients/cmdline/log_tests.py
(log_with_wc_at_revision_zero): New test case for the above functionality.
(parse_log_output): Add support for recognizing a revision 0 log message,
since it is radically different from normal log messages.
(check_log_chain): Only test log message text for revisions greater than 0.
Also, fail if there are extra log messages in the list after checking all
expected messages.
Index: subversion/include/svn_client.h
===================================================================
--- subversion/include/svn_client.h (revision 10131)
+++ subversion/include/svn_client.h (working copy)
@@ -753,6 +753,19 @@
* revision 1. That works fine, except when there are no commits in
* the repository, hence this special case.
*
+ * Special case for working copies at revision 0:
+ *
+ * If @a start->kind is @c svn_opt_revision_base, and @a end->kind is
+ * @c svn_opt_revision_number && @a end->number is @c 1, then handle an
+ * a working copy at revision 0 specially: instead of invoking @a receiver
+ * on revisions 0 through 1, only invoke @a receiver on revision 0, passing
+ * @c NULL for changed paths and empty strings for the author and date. This
+ * is because that particular combination of @a start and @a end usually
+ * indicates the common case of log invocation from the working copy -- the
+ * user wants to see all log messages from the BASE revision back through
+ * revision 1. That works fine, except when the BASE revision is 0, hence
+ * this special case.
+ *
* If @a ctx->notify_func is non-null, then call @a ctx->notify_func/baton
* with a 'skip' signal on any unversioned targets.
*
Index: subversion/libsvn_client/log.c
===================================================================
--- subversion/libsvn_client/log.c (revision 10131)
+++ subversion/libsvn_client/log.c (working copy)
@@ -113,7 +113,7 @@
apr_array_header_t *target_urls;
apr_array_header_t *real_targets;
int i;
-
+
/* Get URLs for each target */
target_urls = apr_array_make (pool, 1, sizeof (const char *));
real_targets = apr_array_make (pool, 1, sizeof (const char *));
@@ -135,7 +135,6 @@
svn_wc_notify_state_unknown,
SVN_INVALID_REVNUM);
-
continue;
}
if (! entry->url)
@@ -243,20 +242,46 @@
if (start_is_local)
SVN_ERR (svn_client__get_revision_number
(&start_revnum, ra_lib, session, start, target, pool));
-
+
if (end_is_local)
SVN_ERR (svn_client__get_revision_number
(&end_revnum, ra_lib, session, end, target, pool));
- err = ra_lib->get_log (session,
- condensed_targets,
- start_revnum,
- end_revnum,
- discover_changed_paths,
- strict_node_history,
- receiver,
- receiver_baton,
- pool);
+ /* Special case: If the BASE revision is 0 but the HEAD revision
+ * of the repository is > 0, then we'll get the log message for
+ * revision 1 when running "svn log" with no arguments in the
+ * working copy. That's because the default behavior of "svn log"
+ * in a working copy is to give revisions BASE through 1, on the
+ * assumption that BASE >= 1. So if we see a start revision of
+ * BASE and an end revision of 1, then we just invoke the receiver
+ * manually on a hand-constructed log message for revision 0. */
+ if ((start->kind == svn_opt_revision_base)
+ && (start_revnum == 0)
+ && (end->kind == svn_opt_revision_number)
+ && (end->value.number == 1))
+ {
+ err = SVN_NO_ERROR;
+
+ /* Log receivers are free to handle revision 0 specially... But
+ just in case some don't, we make up a message here. */
+ SVN_ERR (receiver (receiver_baton,
+ NULL, 0, "", "",
+ _("No commits in BASE revision"),
+ pool));
+ }
+ else
+ {
+ err = ra_lib->get_log (session,
+ condensed_targets,
+ start_revnum,
+ end_revnum,
+ discover_changed_paths,
+ strict_node_history,
+ receiver,
+ receiver_baton,
+ pool);
+ }
+
if (err)
break;
}
@@ -273,7 +298,7 @@
receiver_baton,
pool);
}
-
+
/* Special case: If there have been no commits, we'll get an error
* for requesting log of a revision higher than 0. But the
* default behavior of "svn log" is to give revisions HEAD through
@@ -293,12 +318,12 @@
&& (end->value.number == 1)))
{
svn_revnum_t youngest_rev;
-
+
SVN_ERR (ra_lib->get_latest_revnum (session, &youngest_rev, pool));
if (youngest_rev == 0)
{
err = SVN_NO_ERROR;
-
+
/* Log receivers are free to handle revision 0 specially... But
just in case some don't, we make up a message here. */
SVN_ERR (receiver (receiver_baton,
@@ -307,6 +332,6 @@
}
}
}
-
+
return err;
}
Index: subversion/tests/clients/cmdline/log_tests.py
===================================================================
--- subversion/tests/clients/cmdline/log_tests.py (revision 10131)
+++ subversion/tests/clients/cmdline/log_tests.py (working copy)
@@ -255,6 +255,22 @@
if this_item:
this_item['msg'] = msg
chain.append (this_item)
+ this_item = None
+ elif this_line == "No commit for revision 0.\n":
+ # Add previous log message
+ if this_item:
+ this_item['msg'] = msg
+ chain.append (this_item)
+ this_item = {}
+ this_item['revision'] = '0'
+ this_item['author'] = '(no author)'
+ this_item['date'] = '1970-01-01 00:00:00 -0000 (Thu, 01 Jan 1970)'
+ this_item['msg'] = this_line
+ chain.append (this_item)
+ this_item = None
+ # Remove the message separator line - it comes after the r0 log message,
+ # not before it.
+ log_lines.pop (0)
else: # if didn't see separator now, then something's wrong
raise SVNLogParseError, "trailing garbage after log message"
@@ -297,14 +313,17 @@
or author == '(no author)')): raise svntest.Failure
# Check that the log message looks right:
msg_re = re.compile ('Log message for revision ' + `saw_rev`)
- if (not msg_re.search (msg)): raise svntest.Failure
+ if (saw_rev > 0 and not msg_re.search (msg)): raise svntest.Failure
### todo: need some multi-line log messages mixed in with the
### one-liners. Easy enough, just make the prime revisions use REV
### lines, and the rest use 1 line, or something, so it's
### predictable based on REV.
+ # If any log messages are still on the chain, that's a failure
+ if chain: raise svntest.Failure
+
######################################################################
# Tests
#
@@ -515,7 +534,21 @@
'log', '-r', '2', mu2_path)
svntest.actions.run_and_verify_svn (None, [], SVNAnyOutput,
'log', '-r', '2', mu2_URL)
-
+
+#----------------------------------------------------------------------
+def log_with_wc_at_revision_zero(sbox):
+ "'svn log', no args, top of wc at BASE revision 0"
+
+ guarantee_repos_and_wc(sbox)
+
+ svntest.main.run_svn (None, 'up', '-r', '0', sbox.wc_dir)
+ output, err = svntest.actions.run_and_verify_svn(
+ None, None, [], 'log', sbox.wc_dir)
+
+ log_chain = parse_log_output (output)
+ if check_log_chain (log_chain, [0]):
+ raise svntest.Failure
+
########################################################################
# Run the tests
@@ -530,6 +563,7 @@
log_with_path_args,
url_missing_in_head,
log_through_copyfrom_history,
+ log_with_wc_at_revision_zero,
]
if __name__ == '__main__':
-- Mike
--
Michael W. Thelen
Never express yourself more clearly than you are able to think.
-- Niels Bohr
Received on Sun Jul 4 02:52:59 2004