Thought I'd post the diff-so-far for review, while I go home and
sleep. This passes "make check" except for copy_tests.py and
diff_tests.py. I know what the problems are, just not solving them
tonight. :-)
Philip, if you want to take a look at the area around
"/* fooo working here */"
and make a stab at what the logic should be, that would be welcome,
but no worries either way.
-Karl
$ svn st
M ./subversion/clients/cmdline/checkout-cmd.c
M ./subversion/clients/cmdline/cl.h
M ./subversion/clients/cmdline/commit-cmd.c
M ./subversion/clients/cmdline/diff-cmd.c
M ./subversion/clients/cmdline/import-cmd.c
M ./subversion/clients/cmdline/log-cmd.c
M ./subversion/clients/cmdline/main.c
M ./subversion/clients/cmdline/switch-cmd.c
M ./subversion/clients/cmdline/update-cmd.c
M ./subversion/include/svn_client.h
M ./subversion/include/svn_error_codes.h
M ./subversion/libsvn_client/checkout.c
M ./subversion/libsvn_client/client.h
M ./subversion/libsvn_client/commit.c
M ./subversion/libsvn_client/copy.c
M ./subversion/libsvn_client/diff.c
M ./subversion/libsvn_client/log.c
A ./subversion/libsvn_client/revisions.c
M ./subversion/libsvn_client/switch.c
M ./subversion/libsvn_client/update.c
$ cat msg
Do things the new svn_client_revision_t way.
This is part of work on issue #422; it is preliminary to making diff
(and later merge) capable of taking two paths at arbitrary revisions.
* subversion/libsvn_client/client.h (svn_client__get_revision_number):
New prototype.
* subversion/libsvn_client/revisions.c
(svn_client__get_revision_number): New file, new func.
* subversion/include/svn_client.h (svn_client_revision_kind): Add
svn_client_revision_working kind. Doc improvements.
(svn_client_diff): Change prototype to use two new
svn_client_revision_t start and end parameters, instead of separate
start_revision, start_date, end_revision, end_date params. Also, move
`target' parameter to be immediately after revision params.
(svn_client_checkout, svn_client_update): Change type of `revision'
parameter to svn_client_revision_t, remove `tm' param. Doc fixes.
(svn_client_switch): Same, and change `switch_url' to just `url'.
(svn_client_import): Doc rewrite, but leave the revision parameter
alone, it's only for the xml case.
(svn_client_log): Change type of `revision' parameter to
svn_client_revision_t.
(svn_client_move, svn_client_copy): Rename `src_rev' parameter to
`src_revision', change its type to svn_client_revision_t.
* subversion/libsvn_client/diff.c (svn_client_diff): Adjust.
* subversion/libsvn_client/log.c (svn_client_log): Adjust. If no end
revision is given, default to the oldest commit.
* subversion/libsvn_client/copy.c (svn_client_move, svn_client_copy):
Adjust prototypes.
(setup_copy): Rename `src_rev' parameter to `src_revision', change its
type to svn_client_revision_t, fix head check.
(repos_to_repos_copy, repos_to_wc_copy): Rename `src_rev' parameter to
`src_revision', change its type to svn_client_revision_t, adjust
revision accordingly.
* subversion/libsvn_client/checkout.c (svn_client_checkout): Adjust
prototype, remove revision vs date logic, and instead just call
svn_client__get_revision_number. But also attempt an early manual
conversion of the revision, for svn_wc_get_checkout_editor et al.
* subversion/libsvn_client/switch.c (svn_client_switch): Same.
* subversion/libsvn_client/update.c (svn_client_update): Same.
* subversion/clients/cmdline/cl.h (svn_cl__opt_state_t): Fields
start_revision and end_revision become svn_client_revision_t,
replacing themselves and also start_date and end_date.
* subversion/clients/cmdline/main.c (main): Adjust initializations of
start_revision and end_revision.
(parse_revision): Adjust revision parsing.
(parse_date): Adjust date parsing. Fix doc typo.
* subversion/clients/cmdline/diff-cmd.c (svn_cl__diff): Don't pass
dates to svn_client_diff. Set up revisions correctly.
* subversion/clients/cmdline/switch-cmd.c (svn_cl__switch): Don't pass
date to svn_client_switch.
* subversion/clients/cmdline/update-cmd.c (svn_cl__update): Don't pass
date to svn_client_update.
* subversion/clients/cmdline/commit-cmd.c (svn_cl__commit): Attempt an
early manual conversion of revision, for the xml case.
* subversion/clients/cmdline/import-cmd.c (svn_cl__import): Same.
* subversion/include/svn_error_codes.h
(SVN_ERR_CLIENT_RA_ACCESS_REQUIRED, SVN_ERR_CLIENT_BAD_REVISION
SVN_ERR_CLIENT_VERSIONED_PATH_REQUIRED): New error codes.
Unrelated cleanups:
* subversion/libsvn_client/commit.c (send_to_repos): Change `base_dir'
param to `base_path', this matches both doc string and semantics.
$ svn diff
Index: ./subversion/include/svn_error_codes.h
===================================================================
--- ./subversion/include/svn_error_codes.h
+++ ./subversion/include/svn_error_codes.h Thu Jan 31 21:44:31 2002
@@ -366,6 +366,20 @@
SVN_ERRDEF (SVN_ERR_TEST_FAILED,
"Test failed")
+ /* BEGIN libsvn_client errors */
+
+ SVN_ERRDEF (SVN_ERR_CLIENT_VERSIONED_PATH_REQUIRED,
+ "A path under revision control is needed for this operation")
+
+ SVN_ERRDEF (SVN_ERR_CLIENT_RA_ACCESS_REQUIRED,
+ "Repository access is needed for this operation")
+
+ SVN_ERRDEF (SVN_ERR_CLIENT_BAD_REVISION,
+ "Bogus revision information given")
+
+ /* END libsvn_client errors */
+
+
/* BEGIN Client errors */
SVN_ERRDEF (SVN_ERR_CL_ARG_PARSING_ERROR,
Index: ./subversion/include/svn_client.h
===================================================================
--- ./subversion/include/svn_client.h
+++ ./subversion/include/svn_client.h Thu Jan 31 23:39:51 2002
@@ -57,8 +57,15 @@
-/*** Various ways of specifying revisions. ***/
+/* Various ways of specifying revisions.
+ *
+ * Note:
+ * In contexts where local mods are relevant, the `working' kind
+ * refers to the uncommitted "working" revision, which may be modified
+ * with respect to its base revision. In other contexts, `working'
+ * should behave the same as `committed' or `current'.
+ */
enum svn_client_revision_kind {
svn_client_revision_unspecified, /* No revision information given. */
svn_client_revision_number, /* revision given as number */
@@ -66,6 +73,7 @@
svn_client_revision_committed, /* rev of most recent change */
svn_client_revision_previous, /* (rev of most recent change) - 1 */
svn_client_revision_current, /* .svn/entries revision */
+ svn_client_revision_working, /* current, plus local mods */
svn_client_revision_head /* repository youngest */
};
@@ -161,28 +169,28 @@
/*** Milestone 4 Interfaces ***/
-/* Perform a checkout from URL, providing pre- and post-checkout hook
- editors and batons (BEFORE_EDITOR, BEFORE_EDIT_BATON /
- AFTER_EDITOR, AFTER_EDIT_BATON). These editors are purely optional
- and exist only for extensibility; pass four NULLs here if you
- don't need them.
-
- PATH will be the root directory of your checked out working copy.
-
- If XML_SRC is NULL, then the checkout will come from the repository
- and subdir specified by URL. An invalid REVISION will cause the
- "latest" tree to be fetched, while a valid REVISION will fetch a
- specific tree. Alternatively, a time TM can be used to implicitly
- select a revision. TM cannot be used at the same time as REVISION.
+/* Checkout a working copy of URL at REVISION, using PATH as the root
+ directory of the newly checked out working copy, and authenticating
+ with AUTH_BATON.
+
+ REVISION must be of kind svn_client_revision_number,
+ svn_client_revision_head, or svn_client_revision_date. In the xml
+ case (see below) svn_client_revision_unspecified is also allowed.
+ If REVISION does not meet these requirements, return the error
+ SVN_ERR_CLIENT_BAD_REVISION.
+
+ BEFORE_EDITOR, BEFORE_EDIT_BATON and AFTER_EDITOR, AFTER_EDIT_BATON
+ are pre- and post-checkout hook editors. They are optional; pass
+ four NULLs if you don't need them.
If XML_SRC is non-NULL, it is an xml file to check out from; in
this case, the working copy will record the URL as artificial
- ancestry information. An invalid REVISION implies that the
- revision *must* be present in the <delta-pkg> tag, while a valid
- REVISION will be simply be stored in the wc. (Note: a <delta-pkg>
- revision will *always* override the one passed in.)
+ ancestry information. If REVISION is
+ svn_client_revision_unspecified, then the revision *must* be
+ present in the <delta-pkg> tag; otherwise, store REVISION in the
+ wc. (Note: a <delta-pkg> revision still overrides REVISION.)
- This operation will use the provided memory POOL. */
+ Use POOL for any temporary allocation. */
svn_error_t *
svn_client_checkout (const svn_delta_edit_fns_t *before_editor,
void *before_edit_baton,
@@ -191,39 +199,37 @@
svn_client_auth_baton_t *auth_baton,
svn_stringbuf_t *URL,
svn_stringbuf_t *path,
- svn_revnum_t revision,
+ svn_client_revision_t *revision,
svn_boolean_t recurse,
- apr_time_t tm,
svn_stringbuf_t *xml_src,
apr_pool_t *pool);
-/* Perform an update of PATH (part of a working copy), providing pre-
- and post-checkout hook editors and batons (BEFORE_EDITOR,
- BEFORE_EDIT_BATON / AFTER_EDITOR, AFTER_EDIT_BATON). These editors
- are purely optional and exist only for extensibility; pass four
- NULLs here if you don't need them.
-
- If XML_SRC is NULL, then the update will come from the repository
- that PATH was originally checked-out from. An invalid REVISION
- will cause the PATH to be updated to the "latest" revision, while a
- valid REVISION will update to a specific tree. Alternatively, a
- time TM can be used to implicitly select a revision. TM cannot be
- used at the same time as REVISION.
+/* Update working tree PATH to REVISION, authenticating with
+ AUTH_BATON.
+
+ REVISION must be of kind svn_client_revision_number,
+ svn_client_revision_head, or svn_client_revision_date. In the xml
+ case (see below) svn_client_revision_unspecified is also allowed.
+ If REVISION does not meet these requirements, return the error
+ SVN_ERR_CLIENT_BAD_REVISION.
During an update, files may be restored from the text-base if they
- have been removed from the working copy. When this happens,
+ have been removed from the working copy. When this happens,
NOTIFY_RESTORE will be called with NOTIFY_BATON and the (relative)
- path of the file that has been restored. NOTIFY_RESTORE may be NULL
- if this information is not required.
+ path of the file that has been restored. NOTIFY_RESTORE may be
+ NULL if this information is not required.
- If XML_SRC is non-NULL, it is an xml file to update from. An
- invalid REVISION implies that the revision *must* be present in the
- <delta-pkg> tag, while a valid REVISION will be simply be stored in
- the wc. (Note: a <delta-pkg> revision will *always* override the
- one passed in.)
+ BEFORE_EDITOR, BEFORE_EDIT_BATON and AFTER_EDITOR, AFTER_EDIT_BATON
+ are pre- and post-update hook editors. They are optional; pass
+ four NULLs if you don't need them.
- This operation will use the provided memory POOL. */
+ If XML_SRC is non-NULL, it is an xml file to update from. If
+ REVISION is svn_client_revision_unspecified, then the revision
+ *must* be present in the <delta-pkg> tag; otherwise, store REVISION
+ in the wc. (Note: a <delta-pkg> revision still overrides REVISION.)
+
+ Use POOL for any temporary allocation. */
svn_error_t *
svn_client_update (const svn_delta_edit_fns_t *before_editor,
void *before_edit_baton,
@@ -232,28 +238,24 @@
svn_client_auth_baton_t *auth_baton,
svn_stringbuf_t *path,
svn_stringbuf_t *xml_src,
- svn_revnum_t revision,
- apr_time_t tm,
+ svn_client_revision_t *revision,
svn_boolean_t recurse,
svn_wc_notify_func_t notify_restore,
void *notify_baton,
apr_pool_t *pool);
+/* Switch working tree PATH to URL at REVISION, authenticating with
+ AUTH_BATON.
-/* Perform an update of PATH (part of a working copy), providing pre-
- and post-checkout hook editors and batons (BEFORE_EDITOR,
- BEFORE_EDIT_BATON / AFTER_EDITOR, AFTER_EDIT_BATON). These editors
- are purely optional and exist only for extensibility; pass four
- NULLs here if you don't need them.
-
- SWITCH_URL is the new URL that the working copy will be 'switched' to.
-
- An invalid REVISION will cause the PATH to be updated to the
- "latest" revision of SWITCH_URL, while a valid REVISION will update
- to a specific revision of SWITCH_URL. Alternatively, a time TM can
- be used to implicitly select a revision. TM cannot be used at the
- same time as REVISION.
+ Summary of purpose: this is normally used to switch a working
+ directory over to another line of development, such as a branch or
+ a tag. Switching an existing working directory is more efficient
+ than checking out URL from scratch.
+
+ REVISION must be of kind svn_client_revision_number,
+ svn_client_revision_head, or svn_client_revision_date; otherwise,
+ return SVN_ERR_CLIENT_BAD_REVISION.
During a switch, files may be restored from the text-base if they
have been removed from the working copy. When this happens,
@@ -261,7 +263,11 @@
path of the file that has been restored. NOTIFY_RESTORE may be NULL
if this information is not required.
- This operation will use the provided memory POOL. */
+ BEFORE_EDITOR, BEFORE_EDIT_BATON and AFTER_EDITOR, AFTER_EDIT_BATON
+ are pre- and post-switch hook editors. They are optional; pass
+ four NULLs if you don't need them.
+
+ Use POOL for any temporary allocation. */
svn_error_t *
svn_client_switch (const svn_delta_edit_fns_t *before_editor,
void *before_edit_baton,
@@ -269,9 +275,8 @@
void *after_edit_baton,
svn_client_auth_baton_t *auth_baton,
svn_stringbuf_t *path,
- svn_stringbuf_t *switch_url,
- svn_revnum_t revision,
- apr_time_t tm,
+ svn_stringbuf_t *url,
+ svn_client_revision_t *revision,
svn_boolean_t recurse,
svn_wc_notify_func_t notify_restore,
void *notify_baton,
@@ -348,48 +353,48 @@
apr_pool_t *pool);
-/* Import a tree, using optional pre- and post-commit hook editors
- (BEFORE_EDITOR, BEFORE_EDIT_BATON, and AFTER_EDITOR,
- AFTER_EDIT_BATON). These editors are purely optional and exist
- only for extensibility; pass four NULLs here if you don't need
- them.
-
- If the import succeeds, allocate (in POOL) and populate
- *COMMIT_INFO.
-
- Store LOG_MSG as the log of the commit.
-
- PATH is the path to local tree being imported. PATH can be a file
- or directory.
-
- URL is the repository directory where the imported data is placed.
+/* Import file or directory PATH into repository directory URL at
+ head, authenticating with AUTH_BATON, and using LOG_MSG as the log
+ message for the (implied) commit. Set *COMMIT_INFO to the results
+ of the commit, allocated in POOL.
NEW_ENTRY is the new entry created in the repository directory
- identified by URL.
+ identified by URL. NEW_ENTRY may be null (see below), but may not
+ be the empty string.
- If PATH is a file, that file is imported as NEW_ENTRY. If PATH is
- a directory, the contents of that directory are imported, under a
- new directory the NEW_ENTRY in the repository. Note and the
- directory itself is not imported; that is, the basename of PATH is
- not part of the import.
-
- If PATH is a directory and NEW_ENTRY is null, then the contents of
- PATH are imported directly into the repository directory identified
- by URL. NEW_ENTRY may not be the empty string.
-
- If NEW_ENTRY already exists in the youngest revision, return error.
+ If PATH is a directory, the contents of that directory are
+ imported, under a new directory named NEW_ENTRY under URL; or if
+ NEW_ENTRY is null, then the contents of PATH are imported directly
+ into the directory identified by URL. Note that the directory PATH
+ itself is not imported -- that is, the basename of PATH is not part
+ of the import.
+
+ If PATH is a file, that file is imported as NEW_ENTRY (which may
+ not be null).
+
+ In all cases, if NEW_ENTRY already exists in URL, return error.
+ BEFORE_EDITOR, BEFORE_EDIT_BATON, and AFTER_EDITOR,
+ AFTER_EDIT_BATON are pre- and post-import (i.e., post-commit) hook
+ editors. They are optional; pass four NULLs here if you don't need
+ them.
+
If XML_DST is non-NULL, it is a file in which to store the xml
result of the commit, and REVISION is used as the revision.
- Use POOL for all allocation.
+ Use POOL for any temporary allocation.
+ Note: REVISION is svn_revnum_t, rather than svn_client_revision_t,
+ because only the svn_client_revision_number kind would be useful
+ anyway.
+
### kff todo: This import is similar to cvs import, in that it does
not change the source tree into a working copy. However, this
behavior confuses most people, and I think eventually svn _should_
turn the tree into a working copy, or at least should offer the
option. However, doing so is a bit involved, and we don't need it
- right now. */
+ right now.
+*/
svn_error_t *svn_client_import (svn_client_commit_info_t **commit_info,
const svn_delta_edit_fns_t *before_editor,
void *before_edit_baton,
@@ -405,19 +410,18 @@
apr_pool_t *pool);
-/* Perform an commit, providing pre- and post-commit hook editors and
- batons (BEFORE_EDITOR, BEFORE_EDIT_BATON, and AFTER_EDITOR,
- AFTER_EDIT_BATON). These editors are purely optional and exist
- only for extensibility; pass four NULLs here if you don't need
- them.
+/* Commit file or directory PATH into repository, authenticating with
+ AUTH_BATON, and using LOG_MSG as the log message. Set *COMMIT_INFO
+ to the results of the commit, allocated in POOL.
- If the commit succeeds, allocate (in POOL) and populate
- *COMMIT_INFO.
-
TARGETS is an array of svn_stringbuf_t * paths to commit. They need
not be canonicalized nor condensed; this function will take care of
that.
+ BEFORE_EDITOR, BEFORE_EDIT_BATON, and AFTER_EDITOR,
+ AFTER_EDIT_BATON are pre- and post-commit hook editors. They are
+ optional; pass four NULLs here if you don't need them.
+
If XML_DST is NULL, then the commit will write to a repository, and
the REVISION argument is ignored.
@@ -426,10 +430,14 @@
will be updated appropriately. If REVISION is invalid, the working
copy remains unchanged.
- This operation will use the provided memory POOL.
+ Note: REVISION is svn_revnum_t, rather than svn_client_revision_t,
+ because only the svn_client_revision_number kind would be useful
+ anyway.
- If no error is returned, and *COMMITTED_REV is set to
- SVN_INVALID_REVNUM, then the commit was a no-op; nothing needed to
+ Use POOL for any temporary allocation.
+
+ If no error is returned and (*COMMIT_INFO)->revision is set to
+ SVN_INVALID_REVNUM, then the commit was a no-op; nothing needed to
be committed.
*/
svn_error_t *
@@ -501,8 +509,8 @@
svn_error_t *
svn_client_log (svn_client_auth_baton_t *auth_baton,
const apr_array_header_t *targets,
- svn_revnum_t start,
- svn_revnum_t end,
+ svn_client_revision_t *start,
+ svn_client_revision_t *end,
svn_boolean_t discover_changed_paths,
svn_log_message_receiver_t receiver,
void *receiver_baton,
@@ -510,30 +518,25 @@
/* Given a TARGET which is either a path in the working copy or an URL,
- compare it against the given repository version(s).
-
- START_REVISION/START_DATE and END_REVISION/END_DATE are the two
- repository versions, for each specify either the revision of the
- date. If the two revisions are the different the two repository versions
- are compared. If the two revisions are the same the working copy is
- compared against the repository.
+ compare it against the given repository version(s). START and END
+ are the two revisions to be compared; if either has a `kind' of
+ `svn_client_revision_unspecified' or an unrecognized `kind', return
+ the error SVN_ERR_CLIENT_BAD_REVISION.
If TARGET is a directory and RECURSE is true, this will be a recursive
operation.
DIFF_OPTIONS is used to pass additional command line options to the diff
- processes invoked to compare files. DIFF_OPTIONS is an array of
+ processes invoked to compare files. DIFF_OPTIONS is an array of
svn_stringbuf_t * items.
AUTH_BATON is used to communicate with the repository.
*/
-svn_error_t *svn_client_diff (svn_stringbuf_t *target,
- const apr_array_header_t *diff_options,
+svn_error_t *svn_client_diff (const apr_array_header_t *diff_options,
svn_client_auth_baton_t *auth_baton,
- svn_revnum_t start_revision,
- apr_time_t start_date,
- svn_revnum_t end_revision,
- apr_time_t end_date,
+ svn_client_revision_t *start,
+ svn_client_revision_t *end,
+ svn_stringbuf_t *target,
svn_boolean_t recurse,
apr_pool_t *pool);
@@ -564,7 +567,7 @@
SRC_PATH must be a file or directory under version control, or the
URL of a versioned item in the repository. If SRC_PATH is a URL,
- SRC_REV is used to choose the revision from which to copy the
+ SRC_REVISION is used to choose the revision from which to copy the
SRC_PATH. DST_PATH must be a file or directory under version
control, or a repository URL, existent or not.
@@ -592,7 +595,7 @@
svn_error_t *
svn_client_copy (svn_client_commit_info_t **commit_info,
svn_stringbuf_t *src_path,
- svn_revnum_t src_rev,
+ svn_client_revision_t *src_revision,
svn_stringbuf_t *dst_path,
svn_client_auth_baton_t *auth_baton,
svn_stringbuf_t *message,
@@ -614,7 +617,7 @@
- DST_PATH must also be a repository URL (existent or not).
- - SRC_REV is used to choose the revision from which to copy the
+ - SRC_REVISION is used to choose the revision from which to copy the
SRC_PATH.
- AUTH_BATON and MESSAGE are used to commit the move.
@@ -626,7 +629,7 @@
- DST_PATH must also be a working copy path (existent or not).
- - SRC_REV, AUTH and MESSAGE are ignored.
+ - SRC_REVISION, AUTH and MESSAGE are ignored.
- This is a scheduling operation. No changes will happen to the
repository until a commit occurs. This scheduling can be
@@ -640,7 +643,7 @@
svn_error_t *
svn_client_move (svn_client_commit_info_t **commit_info,
svn_stringbuf_t *src_path,
- svn_revnum_t src_rev,
+ svn_client_revision_t *src_revision,
svn_stringbuf_t *dst_path,
svn_client_auth_baton_t *auth_baton,
svn_stringbuf_t *message,
Index: ./subversion/libsvn_client/switch.c
===================================================================
--- ./subversion/libsvn_client/switch.c
+++ ./subversion/libsvn_client/switch.c Thu Jan 31 22:15:34 2002
@@ -56,8 +56,7 @@
svn_client_auth_baton_t *auth_baton,
svn_stringbuf_t *path,
svn_stringbuf_t *switch_url,
- svn_revnum_t revision,
- apr_time_t tm,
+ svn_client_revision_t *revision,
svn_boolean_t recurse,
svn_wc_notify_func_t notify_restore,
void *notify_baton,
@@ -72,6 +71,7 @@
svn_error_t *err;
void *ra_baton, *session;
svn_ra_plugin_t *ra_lib;
+ svn_revnum_t revnum;
/* Sanity check. Without these, the switch is meaningless. */
assert (path != NULL);
@@ -79,13 +79,6 @@
assert (switch_url != NULL);
assert (switch_url->len > 0);
- /* If both REVISION and TM are specified, this is an error.
- They mostly likely contradict one another. */
- if ((revision != SVN_INVALID_REVNUM) && tm)
- return
- svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, 0, NULL, pool,
- "Cannot specify _both_ revision and time.");
-
/* Unlike 'svn up', we do *not* split the local path into an
anchor/target pair. We do this because we know that the target
isn't going to be deleted, because we're doing a switch. */
@@ -103,12 +96,19 @@
"svn_client_update: entry '%s' has no URL", path->data);
URL = svn_stringbuf_dup (entry->url, pool);
+ /* Get revnum set to something meaningful, so we can fetch the
+ switch editor. */
+ if (revision->kind == svn_client_revision_number)
+ revnum = revision->value.number; /* do the trivial conversion manually */
+ else
+ revnum = SVN_INVALID_REVNUM; /* no matter, do real conversion later */
+
/* Fetch the switch (update) editor. If REVISION is invalid, that's
okay; the RA driver will call editor->set_target_revision() later
on. */
SVN_ERR (svn_wc_get_switch_editor (path,
NULL,
- revision,
+ revnum,
switch_url,
recurse,
&switch_editor,
@@ -129,9 +129,8 @@
SVN_ERR (svn_client__open_ra_session (&session, ra_lib, URL, path,
TRUE, TRUE, auth_baton, pool));
- /* If TM is given, convert the time into a revision number. */
- if (tm)
- SVN_ERR (ra_lib->get_dated_revision (session, &revision, tm));
+ SVN_ERR (svn_client__get_revision_number
+ (&revnum, ra_lib, session, revision, path->data, pool));
/* ### Note: the whole RA interface below will probably change soon. */
@@ -139,7 +138,7 @@
invalid revnum, that means RA will use the latest revision. */
SVN_ERR (ra_lib->do_switch (session,
&reporter, &report_baton,
- revision,
+ revnum,
NULL,
recurse,
switch_url,
Index: ./subversion/libsvn_client/checkout.c
===================================================================
--- ./subversion/libsvn_client/checkout.c
+++ ./subversion/libsvn_client/checkout.c Thu Jan 31 21:59:31 2002
@@ -45,20 +45,27 @@
svn_client_auth_baton_t *auth_baton,
svn_stringbuf_t *URL,
svn_stringbuf_t *path,
- svn_revnum_t revision,
+ svn_client_revision_t *revision,
svn_boolean_t recurse,
- apr_time_t tm,
svn_stringbuf_t *xml_src,
apr_pool_t *pool)
{
const svn_delta_edit_fns_t *checkout_editor;
void *checkout_edit_baton;
svn_error_t *err;
+ svn_revnum_t revnum;
/* Sanity check. Without these, the checkout is meaningless. */
assert (path != NULL);
assert (URL != NULL);
+ /* Get revnum set to something meaningful, so we can fetch the
+ checkout editor. */
+ if (revision->kind == svn_client_revision_number)
+ revnum = revision->value.number; /* do the trivial conversion manually */
+ else
+ revnum = SVN_INVALID_REVNUM; /* no matter, do real conversion later */
+
/* Canonicalize the URL. */
svn_path_canonicalize (URL);
@@ -67,7 +74,7 @@
later on. */
SVN_ERR (svn_wc_get_checkout_editor (path,
URL,
- revision,
+ revnum,
recurse,
&checkout_editor,
&checkout_edit_baton,
@@ -90,28 +97,18 @@
SVN_ERR (svn_ra_get_ra_library (&ra_lib, ra_baton, URL->data, pool));
/* Open an RA session to URL. Note that we do not have an admin area
- for storing temp files. We do, however, want to store auth data
+ for storing temp files. We do, however, want to store auth data
after the checkout builds the WC. */
SVN_ERR (svn_client__open_ra_session (&session, ra_lib, URL, path,
TRUE, FALSE, auth_baton, pool));
- /* Decide which revision to get: */
-
- /* If both REVISION and TM are specified, this is an error.
- They mostly likely contradict one another. */
- if ((revision != SVN_INVALID_REVNUM) && tm)
- return
- svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, 0, NULL, pool,
- "Cannot specify _both_ revision and time.");
-
- /* If only TM is given, convert the time into a revision number. */
- else if (tm)
- SVN_ERR (ra_lib->get_dated_revision (session, &revision, tm));
+ SVN_ERR (svn_client__get_revision_number
+ (&revnum, ra_lib, session, revision, path->data, pool));
/* Tell RA to do a checkout of REVISION; if we pass an invalid
revnum, that means RA will fetch the latest revision. */
err = ra_lib->do_checkout (session,
- revision,
+ revnum,
recurse,
checkout_editor,
checkout_edit_baton);
@@ -146,7 +143,7 @@
checkout_editor,
checkout_edit_baton,
URL->data,
- revision,
+ revnum,
pool);
/* Sleep for one second to ensure timestamp integrity. */
Index: ./subversion/libsvn_client/diff.c
===================================================================
--- ./subversion/libsvn_client/diff.c
+++ ./subversion/libsvn_client/diff.c Fri Feb 1 00:45:57 2002
@@ -144,16 +144,15 @@
*/
svn_error_t *
-svn_client_diff (svn_stringbuf_t *path,
- const apr_array_header_t *diff_options,
+svn_client_diff (const apr_array_header_t *diff_options,
svn_client_auth_baton_t *auth_baton,
- svn_revnum_t start_revision,
- apr_time_t start_date,
- svn_revnum_t end_revision,
- apr_time_t end_date,
+ svn_client_revision_t *start,
+ svn_client_revision_t *end,
+ svn_stringbuf_t *path,
svn_boolean_t recurse,
apr_pool_t *pool)
{
+ svn_revnum_t start_revnum, end_revnum;
svn_string_t path_str;
svn_boolean_t path_is_url;
svn_boolean_t use_admin;
@@ -168,13 +167,14 @@
void *diff_edit_baton;
struct diff_cmd_baton diff_cmd_baton;
- /* If both a revision and a date/time are specified, this is an error.
- They mostly likely contradict one another. */
- if ((SVN_IS_VALID_REVNUM(start_revision) && start_date)
- || (SVN_IS_VALID_REVNUM(end_revision) && end_date))
- return
- svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, 0, NULL, pool,
- "Cannot specify _both_ revision and time.");
+ /* Sanity check. */
+ if ((start->kind == svn_client_revision_unspecified)
+ || (end->kind == svn_client_revision_unspecified))
+ {
+ return svn_error_create
+ (SVN_ERR_CLIENT_BAD_REVISION, 0, NULL, pool,
+ "svn_client_diff: caller failed to specify any revisions");
+ }
diff_cmd_baton.options = diff_options;
diff_cmd_baton.pool = pool;
@@ -201,44 +201,62 @@
URL = svn_stringbuf_create (entry->url->data, pool);
}
- /* ### TODO: awful revision handling */
- if (!path_is_url
- && !SVN_IS_VALID_REVNUM(start_revision) && end_revision == 1
- && !start_date && !end_date)
+ if ((! path_is_url)
+ && ((start->kind == svn_client_revision_committed)
+ || (start->kind == svn_client_revision_current))
+ && (end->kind == svn_client_revision_working))
{
- /* Not an url and no revisions, this is the 'quick' diff that does
- not contact the repository and simply uses the text base */
+ /* This is the 'quick' diff that does not contact the repository
+ and simply uses the text base. */
return svn_wc_diff (anchor,
target,
diff_cmd, &diff_cmd_baton,
recurse,
pool);
+ /* ### todo: see comments issue #422 about how libsvn_client's
+ diff implementation prints to stdout. Apparently same is
+ true for libsvn_wc! Both will need adjusting; strongly
+ suspect that the callback abstraction will be exactly what is
+ needed to make merge share code -- that is, the same library
+ functions will be called, but with different callbacks that
+ Do The Right Thing. Random Thought: these callbacks probably
+ won't be svn_delta_edit_fns_t, because there's no depth-first
+ requirement and no need to tweak .svn/ metadata. Can be a
+ lot simpler than an editor, therefore */
}
- /* Establish the RA session */
+ /* Else we must contact the repository. */
+
+ /* Establish RA session */
SVN_ERR (svn_ra_init_ra_libs (&ra_baton, pool));
SVN_ERR (svn_ra_get_ra_library (&ra_lib, ra_baton, URL->data, pool));
/* ### TODO: We have to pass null for the base_dir here, since the
- working copy does not match the requested revision. It might be
+ working copy does not match the requested revision. It might be
possible to have a special ra session for diff, where get_wc_prop
cooperates with the editor and returns values when the file is in the
wc, and null otherwise. */
SVN_ERR (svn_client__open_ra_session (&session, ra_lib, URL, NULL,
FALSE, FALSE, auth_baton, pool));
- if (start_date)
- SVN_ERR (ra_lib->get_dated_revision (session, &start_revision, start_date));
- if (end_date)
- SVN_ERR (ra_lib->get_dated_revision (session, &end_revision, end_date));
-
- /* ### TODO: Warn the user? */
- if (path_is_url && start_revision == end_revision)
- return SVN_NO_ERROR;
+ /* ### todo: later, when we take two (or N) targets and a more
+ sophisticated indication of their interaction with start and end,
+ these calls will need to be rearranged. */
+ SVN_ERR (svn_client__get_revision_number
+ (&start_revnum, ra_lib, session, start, path->data, pool));
+ SVN_ERR (svn_client__get_revision_number
+ (&end_revnum, ra_lib, session, end, path->data, pool));
+
+ /* ### todo: For the moment, we'll maintain the two distinct diff
+ editors, svn_wc vs svn_client, in order to get this change done
+ in a finite amount of time. Next the two editors will be unified
+ into one "lazy" editor that uses local data whenever possible. */
- if (start_revision == end_revision)
+ /* fooo working here */
+
+ if (end->kind == svn_client_revision_working)
{
- /* The working copy is involved if only one revision is given */
+ /* The working copy is involved in this case. */
SVN_ERR (svn_wc_get_diff_editor (anchor, target,
diff_cmd, &diff_cmd_baton,
recurse,
@@ -247,7 +265,7 @@
SVN_ERR (ra_lib->do_update (session,
&reporter, &report_baton,
- end_revision,
+ end_revnum,
target,
recurse,
diff_editor, diff_edit_baton));
@@ -257,9 +275,9 @@
NULL, NULL, /* notification is N/A */
pool));
}
- else
+ else /* ### todo: there may be uncovered cases remaining */
{
- /* Pure repository comparison if two revisions are given */
+ /* Pure repository comparison. */
/* Open a second session used to request individual file
contents. Although a session can be used for multiple requests, it
@@ -282,18 +300,18 @@
&diff_cmd_baton,
recurse,
ra_lib, session2,
- start_revision,
+ start_revnum,
&diff_editor, &diff_edit_baton,
pool));
SVN_ERR (ra_lib->do_update (session,
&reporter, &report_baton,
- end_revision,
+ end_revnum,
target,
recurse,
diff_editor, diff_edit_baton));
- SVN_ERR (reporter->set_path (report_baton, "", start_revision));
+ SVN_ERR (reporter->set_path (report_baton, "", start_revnum));
SVN_ERR (reporter->finish_report (report_baton));
Index: ./subversion/libsvn_client/copy.c
===================================================================
--- ./subversion/libsvn_client/copy.c
+++ ./subversion/libsvn_client/copy.c Thu Jan 31 23:38:54 2002
@@ -104,7 +104,7 @@
static svn_error_t *
repos_to_repos_copy (svn_client_commit_info_t **commit_info,
svn_stringbuf_t *src_url,
- svn_revnum_t src_rev,
+ svn_client_revision_t *src_revision,
svn_stringbuf_t *dst_url,
svn_client_auth_baton_t *auth_baton,
svn_stringbuf_t *message,
@@ -124,6 +124,7 @@
svn_revnum_t committed_rev = SVN_INVALID_REVNUM;
const char *committed_date = NULL;
const char *committed_author = NULL;
+ svn_revnum_t src_revnum;
/* ### TODO: Currently, this function will violate the depth-first
rule of editors when doing a move of something up into one of its
@@ -183,19 +184,25 @@
SVN_ERR (svn_client__open_ra_session (&sess, ra_lib, top_url, NULL,
FALSE, FALSE, auth_baton, pool));
+ /* Pass null for the path, to ensure error if trying to get a
+ revision based on the working copy. */
+ SVN_ERR (svn_client__get_revision_number
+ (&src_revnum, ra_lib, sess, src_revision, NULL, pool));
+
SVN_ERR (ra_lib->get_latest_revnum (sess, &youngest));
/* Use YOUNGEST for copyfrom args if not provided. */
- if (! SVN_IS_VALID_REVNUM (src_rev))
- src_rev = youngest;
+ if (! SVN_IS_VALID_REVNUM (src_revnum))
+ src_revnum = youngest;
/* Verify that SRC_URL exists in the repository. */
SVN_ERR (ra_lib->check_path (&src_kind, sess,
- src_rel ? src_rel->data : NULL, src_rev));
+ src_rel ? src_rel->data : NULL, src_revnum));
if (src_kind == svn_node_none)
return svn_error_createf
(SVN_ERR_FS_NOT_FOUND, 0, NULL, pool,
- "path `%s' does not exist in revision `%ld'", src_url->data, src_rev);
+ "path `%s' does not exist in revision `%ld'",
+ src_url->data, src_revnum);
/* Figure out the basename that will result from this operation. */
SVN_ERR (ra_lib->check_path (&dst_kind, sess,
@@ -244,13 +251,13 @@
if (src_kind == svn_node_dir)
{
SVN_ERR (editor->add_directory (basename, batons[i], src_url,
- src_rev, &baton));
+ src_revnum, &baton));
SVN_ERR (editor->close_directory (baton));
}
else
{
SVN_ERR (editor->add_file (basename, batons[i], src_url,
- src_rev, &baton));
+ src_revnum, &baton));
SVN_ERR (editor->close_file (baton));
}
@@ -405,7 +412,7 @@
static svn_error_t *
repos_to_wc_copy (svn_stringbuf_t *src_url,
- svn_revnum_t src_rev,
+ svn_client_revision_t *src_revision,
svn_stringbuf_t *dst_path,
svn_client_auth_baton_t *auth_baton,
svn_stringbuf_t *message,
@@ -422,6 +429,7 @@
svn_node_kind_t src_kind, dst_kind;
const svn_delta_edit_fns_t *editor;
void *edit_baton;
+ svn_revnum_t src_revnum;
/* Get the RA vtable that matches URL. */
SVN_ERR (svn_ra_init_ra_libs (&ra_baton, pool));
@@ -434,14 +442,19 @@
SVN_ERR (svn_client__open_ra_session (&sess, ra_lib, src_url, NULL,
TRUE, FALSE, auth_baton, pool));
+ /* Pass null for the path, to ensure error if trying to get a
+ revision based on the working copy. */
+ SVN_ERR (svn_client__get_revision_number
+ (&src_revnum, ra_lib, sess, src_revision, NULL, pool));
+
/* Verify that SRC_URL exists in the repository. */
- SVN_ERR (ra_lib->check_path (&src_kind, sess, "", src_rev));
+ SVN_ERR (ra_lib->check_path (&src_kind, sess, "", src_revnum));
if (src_kind == svn_node_none)
{
- if (SVN_IS_VALID_REVNUM (src_rev))
+ if (SVN_IS_VALID_REVNUM (src_revnum))
return svn_error_createf
(SVN_ERR_FS_NOT_FOUND, 0, NULL, pool,
- "path `%s' not found in revision `%ld'", src_url->data, src_rev);
+ "path `%s' not found in revision `%ld'", src_url->data, src_revnum);
else
return svn_error_createf
(SVN_ERR_FS_NOT_FOUND, 0, NULL, pool,
@@ -497,7 +510,7 @@
/* Get a checkout editor and wrap it. */
SVN_ERR (svn_wc_get_checkout_editor (dst_path,
src_url,
- src_rev,
+ src_revnum,
1,
&editor,
&edit_baton,
@@ -510,9 +523,9 @@
/* Check out the new tree. The parent dir will get no entry, so
it will be as if the new tree isn't really there yet. */
- SVN_ERR (ra_lib->do_checkout (sess, src_rev, 1, editor, edit_baton));
+ SVN_ERR (ra_lib->do_checkout (sess, src_revnum, 1, editor, edit_baton));
- if (! SVN_IS_VALID_REVNUM(src_rev))
+ if (! SVN_IS_VALID_REVNUM(src_revnum))
{
/* If we just checked out from the "head" revision, that's fine,
but we don't want to pass a '-1' as a copyfrom_rev to
@@ -531,7 +544,7 @@
should be the copyfrom_revision when we commit later. */
svn_wc_entry_t *d_entry;
SVN_ERR (svn_wc_entry (&d_entry, dst_path, pool));
- src_rev = d_entry->revision;
+ src_revnum = d_entry->revision;
}
} /* end directory case */
@@ -559,7 +572,7 @@
/* Have the RA layer 'push' data at this stream. We pass a
relative path of "", because we opened SRC_URL, which is
already the full URL to the file. */
- SVN_ERR (ra_lib->get_file (sess, "", src_rev, fstream,
+ SVN_ERR (ra_lib->get_file (sess, "", src_revnum, fstream,
&fetched_rev, &props));
for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi))
@@ -579,12 +592,12 @@
"failed to close file '%s'.",
dst_path->data);
- /* Also, if SRC_REV is invalid ('head'), then FETCHED_REV is now
+ /* Also, if SRC_REVNUM is invalid ('head'), then FETCHED_REV is now
equal to the revision that was actually retrieved. This is
the value we want to use as 'copyfrom_rev' in the call to
svn_wc_add() below. */
- if (! SVN_IS_VALID_REVNUM (src_rev))
- src_rev = fetched_rev;
+ if (! SVN_IS_VALID_REVNUM (src_revnum))
+ src_revnum = fetched_rev;
}
/* Free the RA session. */
@@ -596,7 +609,7 @@
rewritten, wcprops removed, and everything marked as 'copied'.
See comment in svn_wc_add()'s doc about whether svn_wc_add is the
appropriate place for this. */
- SVN_ERR (svn_wc_add (dst_path, src_url, src_rev,
+ SVN_ERR (svn_wc_add (dst_path, src_url, src_revnum,
notify_added, notify_baton, pool));
@@ -607,7 +620,7 @@
static svn_error_t *
setup_copy (svn_client_commit_info_t **commit_info,
svn_stringbuf_t *src_path,
- svn_revnum_t src_rev,
+ svn_client_revision_t *src_revision,
svn_stringbuf_t *dst_path,
svn_client_auth_baton_t *auth_baton,
svn_stringbuf_t *message,
@@ -636,8 +649,13 @@
/* Disallow moves between the working copy and the repository. */
if (is_move)
{
- if (SVN_IS_VALID_REVNUM (src_rev))
- return svn_error_create
+ /* ### todo: this check could fail wrongly. For example,
+ someone could pass in an svn_client_revision_number that just
+ happens to be the HEAD. Not sure there's anything we can do
+ about that right now, as we don't want to muck up this
+ function with RA calls and such. */
+ if (src_revision->kind != svn_client_revision_head)
+ return svn_error_create
(SVN_ERR_UNSUPPORTED_FEATURE, 0, NULL, pool,
"move operations are only allowed on the HEAD revision");
@@ -681,7 +699,7 @@
pool));
else if ((src_is_url) && (! dst_is_url))
- SVN_ERR (repos_to_wc_copy (src_path, src_rev,
+ SVN_ERR (repos_to_wc_copy (src_path, src_revision,
dst_path, auth_baton, message,
before_editor, before_edit_baton,
after_editor, after_edit_baton,
@@ -689,8 +707,9 @@
pool));
else
- SVN_ERR (repos_to_repos_copy (commit_info, src_path, src_rev, dst_path,
- auth_baton, message, is_move, pool));
+ SVN_ERR (repos_to_repos_copy (commit_info, src_path, src_revision,
+ dst_path, auth_baton, message, is_move,
+ pool));
return SVN_NO_ERROR;
}
@@ -702,7 +721,7 @@
svn_error_t *
svn_client_copy (svn_client_commit_info_t **commit_info,
svn_stringbuf_t *src_path,
- svn_revnum_t src_rev,
+ svn_client_revision_t *src_revision,
svn_stringbuf_t *dst_path,
svn_client_auth_baton_t *auth_baton,
svn_stringbuf_t *message,
@@ -715,7 +734,7 @@
apr_pool_t *pool)
{
return setup_copy (commit_info,
- src_path, src_rev, dst_path, auth_baton, message,
+ src_path, src_revision, dst_path, auth_baton, message,
before_editor, before_edit_baton,
after_editor, after_edit_baton,
FALSE /* is_move */,
@@ -727,7 +746,7 @@
svn_error_t *
svn_client_move (svn_client_commit_info_t **commit_info,
svn_stringbuf_t *src_path,
- svn_revnum_t src_rev,
+ svn_client_revision_t *src_revision,
svn_stringbuf_t *dst_path,
svn_client_auth_baton_t *auth_baton,
svn_stringbuf_t *message,
@@ -738,7 +757,7 @@
apr_pool_t *pool)
{
return setup_copy (commit_info,
- src_path, src_rev, dst_path, auth_baton, message,
+ src_path, src_revision, dst_path, auth_baton, message,
NULL, NULL, /* no before_editor, before_edit_baton */
NULL, NULL, /* no after_editor, after_edit_baton */
TRUE /* is_move */,
Index: ./subversion/libsvn_client/log.c
===================================================================
--- ./subversion/libsvn_client/log.c
+++ ./subversion/libsvn_client/log.c Thu Jan 31 23:49:42 2002
@@ -48,8 +48,8 @@
svn_error_t *
svn_client_log (svn_client_auth_baton_t *auth_baton,
const apr_array_header_t *targets,
- svn_revnum_t start,
- svn_revnum_t end,
+ svn_client_revision_t *start,
+ svn_client_revision_t *end,
svn_boolean_t discover_changed_paths,
svn_log_message_receiver_t receiver,
void *receiver_baton,
@@ -61,6 +61,7 @@
svn_wc_entry_t *entry;
svn_stringbuf_t *basename;
apr_array_header_t *condensed_targets;
+ svn_revnum_t start_revnum, end_revnum;
SVN_ERR (svn_path_condense_targets (&basename, &condensed_targets,
targets, pool));
@@ -85,10 +86,18 @@
SVN_ERR (svn_client__open_ra_session (&session, ra_lib, URL, basename,
TRUE, TRUE, auth_baton, pool));
+ SVN_ERR (svn_client__get_revision_number
+ (&start_revnum, ra_lib, session, start, basename->data, pool));
+ SVN_ERR (svn_client__get_revision_number
+ (&end_revnum, ra_lib, session, end, basename->data, pool));
+
+ if (! SVN_IS_VALID_REVNUM (end_revnum))
+ end_revnum = 1; /* default to the oldest commit */
+
SVN_ERR (ra_lib->get_log (session,
condensed_targets, /* ### todo: or `targets'? */
- start,
- end,
+ start_revnum,
+ end_revnum,
discover_changed_paths,
receiver,
receiver_baton));
Index: ./subversion/libsvn_client/revisions.c
===================================================================
--- ./subversion/libsvn_client/revisions.c
+++ ./subversion/libsvn_client/revisions.c Fri Feb 1 00:22:20 2002
@@ -0,0 +1,136 @@
+/*
+ * revisions.c: discovering revisions
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2001 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+
+
+#include <apr_pools.h>
+
+#include "svn_error.h"
+#include "svn_string.h"
+#include "svn_ra.h"
+#include "svn_wc.h"
+#include "svn_client.h"
+#include "svn_path.h"
+#include "client.h"
+
+
+
+
+
+svn_error_t *
+svn_client__get_revision_number (svn_revnum_t *revnum,
+ svn_ra_plugin_t *ra_lib,
+ void *sess,
+ svn_client_revision_t *revision,
+ const char *path,
+ apr_pool_t *pool)
+{
+ /* ### When revision->kind == svn_client_revision_date, is there an
+ optimization such that we can compare revision->value->date with
+ the committed-date in the entries file (or rather, with some
+ range of which committed-date is one endpoint), and sometimes
+ avoid a trip over the RA layer? The only optimizations I can
+ think of involve examining other entries to build a timespan
+ across which committed-revision is known to be the head, but it
+ doesn't seem worth it. -kff */
+
+ /* Sanity check. */
+ if (((ra_lib == NULL) || (sess == NULL))
+ && ((revision->kind == svn_client_revision_date)
+ || (revision->kind == svn_client_revision_head)))
+ {
+ return svn_error_create
+ (SVN_ERR_CLIENT_RA_ACCESS_REQUIRED, 0, NULL, pool,
+ "svn_client__get_revision_number: "
+ "need ra_lib and session for date or head revisions.");
+ }
+
+ if (revision->kind == svn_client_revision_number)
+ *revnum = revision->value.number;
+ else if (revision->kind == svn_client_revision_date)
+ SVN_ERR (ra_lib->get_dated_revision (sess, revnum, revision->value.date));
+ else if (revision->kind == svn_client_revision_head)
+ SVN_ERR (ra_lib->get_latest_revnum (sess, revnum));
+ else if (revision->kind == svn_client_revision_unspecified)
+ *revnum = SVN_INVALID_REVNUM;
+ else if ((revision->kind == svn_client_revision_committed)
+ || (revision->kind == svn_client_revision_working)
+ || (revision->kind == svn_client_revision_current)
+ || (revision->kind == svn_client_revision_previous))
+ {
+ /* Darn it, I am not going to propagate the stringbuf madness
+ through to this function's interface. */
+ svn_stringbuf_t *path_strbuf;
+ svn_wc_entry_t *ent;
+
+ /* Sanity check. */
+ if (path == NULL)
+ return svn_error_create
+ (SVN_ERR_CLIENT_VERSIONED_PATH_REQUIRED, 0, NULL, pool,
+ "svn_client__get_revision_number: "
+ "need a version-controlled path to fetch local revision info.");
+
+ path_strbuf = svn_stringbuf_create (path, pool);
+ SVN_ERR (svn_wc_entry (&ent, path_strbuf, pool));
+
+ if (! ent)
+ return svn_error_createf
+ (SVN_ERR_UNVERSIONED_RESOURCE, 0, NULL, pool,
+ "svn_client__get_revision: '%s' not under revision control", path);
+
+ if ((revision->kind == svn_client_revision_current)
+ || (revision->kind == svn_client_revision_working))
+ *revnum = ent->revision;
+ else
+ {
+ /* ### todo: This whole svn_wc_entry_t thing is a mess, with
+ some kinds of data being "first class", in that they get
+ fields directly in the structure, while other kinds need
+ manual retrieval (augh!) from the hash. There are now
+ several places in Subversion like this, where we grab the
+ value from the entry's attribute hash, and convert it
+ from string to revnum. Wouldn't it be nice to make some
+ sort of accessor layer to svn_wc_entry_t? Or would that
+ just be adding more bureaucracy? Perhaps the committed
+ rev should simply be invited into the first class lounge,
+ where it can enjoy free martinis with current rev? */
+
+ svn_stringbuf_t *revstr = apr_hash_get (ent->attributes,
+ SVN_ENTRY_ATTR_COMMITTED_REV,
+ APR_HASH_KEY_STRING);
+
+ *revnum = SVN_STR_TO_REV (revstr->data);
+ if (revision->kind == svn_client_revision_previous)
+ (*revnum)--;
+ }
+ }
+ else
+ return svn_error_createf
+ (SVN_ERR_CLIENT_BAD_REVISION, 0, NULL, pool,
+ "svn_client__get_revision_number: "
+ "unrecognized revision type requested for '%s'", path);
+
+ return SVN_NO_ERROR;
+}
+
+
+
+/*
+ * local variables:
+ * eval: (load-file "../svn-dev.el")
+ * end: */
Index: ./subversion/libsvn_client/update.c
===================================================================
--- ./subversion/libsvn_client/update.c
+++ ./subversion/libsvn_client/update.c Thu Jan 31 22:23:11 2002
@@ -61,8 +61,7 @@
svn_client_auth_baton_t *auth_baton,
svn_stringbuf_t *path,
svn_stringbuf_t *xml_src,
- svn_revnum_t revision,
- apr_time_t tm,
+ svn_client_revision_t *revision,
svn_boolean_t recurse,
svn_wc_notify_func_t notify_restore,
void *notify_baton,
@@ -76,18 +75,12 @@
svn_stringbuf_t *URL;
svn_stringbuf_t *anchor, *target;
svn_error_t *err;
+ svn_revnum_t revnum;
/* Sanity check. Without this, the update is meaningless. */
assert (path != NULL);
assert (path->len > 0);
- /* If both REVISION and TM are specified, this is an error.
- They mostly likely contradict one another. */
- if ((revision != SVN_INVALID_REVNUM) && tm)
- return
- svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, 0, NULL, pool,
- "Cannot specify _both_ revision and time.");
-
/* Use PATH to get the update's anchor and targets. */
SVN_ERR (svn_wc_get_actual_target (path, &anchor, &target, pool));
@@ -103,12 +96,19 @@
"svn_client_update: entry '%s' has no URL", anchor->data);
URL = svn_stringbuf_dup (entry->url, pool);
+ /* Get revnum set to something meaningful, so we can fetch the
+ update editor. */
+ if (revision->kind == svn_client_revision_number)
+ revnum = revision->value.number; /* do the trivial conversion manually */
+ else
+ revnum = SVN_INVALID_REVNUM; /* no matter, do real conversion later */
+
/* Fetch the update editor. If REVISION is invalid, that's okay;
either the RA or XML driver will call editor->set_target_revision
later on. */
SVN_ERR (svn_wc_get_update_editor (anchor,
target,
- revision,
+ revnum,
recurse,
&update_editor,
&update_edit_baton,
@@ -134,15 +134,16 @@
SVN_ERR (svn_client__open_ra_session (&session, ra_lib, URL, anchor,
TRUE, TRUE, auth_baton, pool));
- /* If TM is given, convert the time into a revision number. */
- if (tm)
- SVN_ERR (ra_lib->get_dated_revision (session, &revision, tm));
-
+ /* ### todo: shouldn't svn_client__get_revision_number be able
+ to take a url as easily as a local path? */
+ SVN_ERR (svn_client__get_revision_number
+ (&revnum, ra_lib, session, revision, anchor->data, pool));
+
/* Tell RA to do a update of URL+TARGET to REVISION; if we pass an
invalid revnum, that means RA will use the latest revision. */
SVN_ERR (ra_lib->do_update (session,
&reporter, &report_baton,
- revision,
+ revnum,
target,
recurse,
update_editor, update_edit_baton));
@@ -185,7 +186,7 @@
update_editor,
update_edit_baton,
URL->data,
- revision,
+ revnum,
pool);
/* Sleep for one second to ensure timestamp integrity. */
Index: ./subversion/libsvn_client/client.h
===================================================================
--- ./subversion/libsvn_client/client.h
+++ ./subversion/libsvn_client/client.h Fri Feb 1 00:20:09 2002
@@ -30,6 +30,41 @@
#include "svn_client.h"
+
+/* Set *REVNUM to the revision number identified by REVISION.
+ *
+ * If REVISION->kind is svn_client_revision_number, just use
+ * REVISION->value.number, ignoring PATH, RA_LIB, and SESSION.
+ *
+ * Else if REVISION->kind is svn_client_revision_committed,
+ * svn_client_revision_previous, or svn_client_revision_current, or
+ * svn_client_revision_working, then the revision can be identified
+ * purely based on the working copy's administrative information for
+ * PATH, so RA_LIB and SESSION are ignored. If PATH is not under
+ * revision control, return SVN_ERR_UNVERSIONED_RESOURCE, or if PATH
+ * is null, return SVN_ERR_CLIENT_VERSIONED_PATH_REQUIRED.
+ *
+ * Else if REVISION->kind is svn_client_revision_date or
+ * svn_client_revision_head, then RA_LIB and SESSION are used to
+ * retrieve the revision from the repository (using
+ * REVISION->value.date in the former case), and PATH is ignored. If
+ * RA_LIB or SESSION is null, return SVN_ERR_CLIENT_RA_ACCESS_REQUIRED.
+ *
+ * Else if REVISION->kind is svn_client_revision_unspecified, set
+ * *REVNUM to SVN_INVALID_REVNUM.
+ *
+ * Else return SVN_ERR_CLIENT_BAD_REVISION.
+ *
+ * Use POOL for any temporary allocation.
+ */
+svn_error_t *svn_client__get_revision_number (svn_revnum_t *revnum,
+ svn_ra_plugin_t *ra_lib,
+ void *session,
+ svn_client_revision_t *revision,
+ const char *path,
+ apr_pool_t *pool);
+
+
/* ---------------------------------------------------------------- */
/*** RA callbacks ***/
Index: ./subversion/libsvn_client/commit.c
===================================================================
--- ./subversion/libsvn_client/commit.c
+++ ./subversion/libsvn_client/commit.c Thu Jan 31 20:50:59 2002
@@ -391,7 +391,7 @@
void *before_edit_baton,
const svn_delta_edit_fns_t *after_editor,
void *after_edit_baton,
- svn_stringbuf_t *base_dir,
+ svn_stringbuf_t *base_path,
apr_array_header_t *condensed_targets,
svn_stringbuf_t *url, /* null unless importing */
svn_stringbuf_t *new_entry, /* null except when importing */
@@ -426,7 +426,7 @@
the assignments to committed_date and committed_author near the
end of this function, as they'll need to allocate new storage. */
ccb.pool = pool;
- ccb.prefix_path = base_dir;
+ ccb.prefix_path = base_path;
committed_targets = apr_hash_make (pool);
if (url)
@@ -494,13 +494,13 @@
if (! is_import)
{
/* Construct full URL from PATH. */
- SVN_ERR (svn_wc_entry (&entry, base_dir, pool));
+ SVN_ERR (svn_wc_entry (&entry, base_path, pool));
url = entry->url;
if (entry->copied)
return svn_error_createf
(SVN_ERR_CL_COMMIT_IN_ADDED_DIR, 0, NULL, pool,
- "%s was already scheduled for addition.", base_dir->data);
+ "%s was already scheduled for addition.", base_path->data);
}
/* Make sure our log message at least exists, even if empty. */
@@ -514,7 +514,7 @@
/* Open an RA session to URL. */
/* (Notice that in the case of import, we do NOT want the RA
layer to attempt to store auth info in the wc.) */
- SVN_ERR (svn_client__open_ra_session (&session, ra_lib, url, base_dir,
+ SVN_ERR (svn_client__open_ra_session (&session, ra_lib, url, base_path,
!is_import, !is_import,
auth_baton, pool));
@@ -544,7 +544,7 @@
&test_edit_baton,
svn_stream_from_stdio (stdout, pool),
0,
- base_dir,
+ base_path,
pool));
svn_delta_compose_editors (&editor, &edit_baton,
@@ -563,7 +563,7 @@
if (is_import)
{
/* Crawl a directory tree, importing. */
- err = import (base_dir, new_entry, editor, edit_baton, pool);
+ err = import (base_path, new_entry, editor, edit_baton, pool);
if (err)
{
/* ignoring the return value of this. we're *already* about
@@ -580,14 +580,14 @@
if (xml_dst && xml_dst->data)
/* committing to XML */
- err = svn_wc_crawl_local_mods (base_dir,
+ err = svn_wc_crawl_local_mods (base_path,
condensed_targets,
editor, edit_baton,
NULL, NULL,
pool);
else
/* committing to RA layer */
- err = svn_wc_crawl_local_mods (base_dir,
+ err = svn_wc_crawl_local_mods (base_path,
condensed_targets,
editor, edit_baton,
&(ra_lib->get_latest_revnum), session,
Index: ./subversion/clients/cmdline/cl.h
===================================================================
--- ./subversion/clients/cmdline/cl.h
+++ ./subversion/clients/cmdline/cl.h Fri Feb 1 00:12:55 2002
@@ -57,15 +57,10 @@
commands. */
typedef struct svn_cl__opt_state_t
{
- /* You probably want start_revision to default SVN_INVALID_REVNUM
- (which means `head' to the RA layer), and end_revision to default
- to 0 or 1, which are the two possibilities for oldest revision. */
- svn_revnum_t start_revision; /* X in "svn blah -r X" or "svn blah -r X:Y" */
- svn_revnum_t end_revision; /* Y in "svn blah -r X:Y" */
-
- /* These should default to 0. */
- apr_time_t start_date; /* X in "svn blah -D X" or "svn blah -D X:Y" */
- apr_time_t end_date; /* Y in "svn blah -D X:Y" */
+ /* These get set as a result of revisions or dates being specified.
+ When only one revision is given, it is stored in start_revision,
+ and end_revision remains `svn_client_revision_unspecified'. */
+ svn_client_revision_t *start_revision, *end_revision;
svn_stringbuf_t *message; /* log message */
Index: ./subversion/clients/cmdline/checkout-cmd.c
===================================================================
--- ./subversion/clients/cmdline/checkout-cmd.c
+++ ./subversion/clients/cmdline/checkout-cmd.c Thu Jan 31 22:20:28 2002
@@ -122,7 +122,6 @@
local_dir,
opt_state->start_revision,
opt_state->nonrecursive ? FALSE : TRUE,
- opt_state->start_date,
opt_state->xml_file,
pool);
if (err)
Index: ./subversion/clients/cmdline/diff-cmd.c
===================================================================
--- ./subversion/clients/cmdline/diff-cmd.c
+++ ./subversion/clients/cmdline/diff-cmd.c Fri Feb 1 00:02:47 2002
@@ -56,18 +56,22 @@
auth_baton = svn_cl__make_auth_baton (opt_state, pool);
+ if (opt_state->start_revision->kind == svn_client_revision_unspecified)
+ opt_state->start_revision->kind = svn_client_revision_current;
+
+ if (opt_state->end_revision->kind == svn_client_revision_unspecified)
+ opt_state->end_revision->kind = svn_client_revision_working;
+
for (i = 0; i < condensed_targets->nelts; ++i)
{
svn_stringbuf_t *target
= ((svn_stringbuf_t **) (condensed_targets->elts))[i];
- SVN_ERR (svn_client_diff (target,
- options,
+ SVN_ERR (svn_client_diff (options,
auth_baton,
opt_state->start_revision,
- opt_state->start_date,
opt_state->end_revision,
- opt_state->end_date,
+ target,
opt_state->nonrecursive ? FALSE : TRUE,
pool));
}
Index: ./subversion/clients/cmdline/log-cmd.c
===================================================================
--- ./subversion/clients/cmdline/log-cmd.c
+++ ./subversion/clients/cmdline/log-cmd.c Thu Jan 31 23:46:02 2002
@@ -182,9 +182,6 @@
/* Add "." if user passed 0 arguments */
svn_cl__push_implicit_dot_target(targets, pool);
- /* ### todo: If opt_state->{start,end}_date, then convert to
- opt_state->{start,end}_revision here. */
-
lb.first_call = 1;
lb.pool = pool;
SVN_ERR (svn_client_log (auth_baton,
Index: ./subversion/clients/cmdline/update-cmd.c
===================================================================
--- ./subversion/clients/cmdline/update-cmd.c
+++ ./subversion/clients/cmdline/update-cmd.c Thu Jan 31 23:43:44 2002
@@ -80,7 +80,6 @@
target,
opt_state->xml_file,
opt_state->start_revision,
- opt_state->start_date,
opt_state->nonrecursive ? FALSE : TRUE,
(opt_state->quiet ? NULL : svn_cl__notify_restored), NULL,
pool));
Index: ./subversion/clients/cmdline/commit-cmd.c
===================================================================
--- ./subversion/clients/cmdline/commit-cmd.c
+++ ./subversion/clients/cmdline/commit-cmd.c Thu Jan 31 22:26:13 2002
@@ -454,6 +454,7 @@
svn_client_commit_info_t *commit_info = NULL;
svn_stringbuf_t *messagep=NULL;
svn_error_t *error;
+ svn_revnum_t revnum;
/* Take our message from ARGV or a FILE */
if (opt_state->filedata)
@@ -558,6 +559,12 @@
trace_dir,
pool));
+ /* Get revnum set to something meaningful, to cover the xml case. */
+ if (opt_state->start_revision->kind == svn_client_revision_number)
+ revnum = opt_state->start_revision->value.number;
+ else
+ revnum = SVN_INVALID_REVNUM; /* no matter, this is fine */
+
/* Commit. */
error = svn_client_commit (&commit_info,
NULL, NULL,
@@ -567,7 +574,7 @@
targets,
message,
opt_state->xml_file,
- opt_state->start_revision,
+ revnum,
pool);
if (error)
Index: ./subversion/clients/cmdline/switch-cmd.c
===================================================================
--- ./subversion/clients/cmdline/switch-cmd.c
+++ ./subversion/clients/cmdline/switch-cmd.c Thu Jan 31 23:43:32 2002
@@ -101,7 +101,6 @@
target,
switch_url,
opt_state->start_revision,
- opt_state->start_date,
opt_state->nonrecursive ? FALSE : TRUE,
(opt_state->quiet ? NULL : svn_cl__notify_restored), NULL,
pool));
Index: ./subversion/clients/cmdline/import-cmd.c
===================================================================
--- ./subversion/clients/cmdline/import-cmd.c
+++ ./subversion/clients/cmdline/import-cmd.c Thu Jan 31 22:27:40 2002
@@ -48,6 +48,7 @@
void *trace_edit_baton;
svn_client_auth_baton_t *auth_baton;
svn_client_commit_info_t *commit_info = NULL;
+ svn_revnum_t revnum;
/* Take our message from ARGV or a FILE */
if (opt_state->filedata)
@@ -127,6 +128,12 @@
printpath,
pool));
+ /* Get revnum set to something meaningful, to cover the xml case. */
+ if (opt_state->start_revision->kind == svn_client_revision_number)
+ revnum = opt_state->start_revision->value.number;
+ else
+ revnum = SVN_INVALID_REVNUM; /* no matter, this is fine */
+
SVN_ERR (svn_client_import (&commit_info,
NULL, NULL,
opt_state->quiet ? NULL : trace_editor,
@@ -137,7 +144,7 @@
new_entry,
message,
opt_state->xml_file,
- opt_state->start_revision,
+ revnum,
pool));
if (commit_info)
Index: ./subversion/clients/cmdline/main.c
===================================================================
--- ./subversion/clients/cmdline/main.c
+++ ./subversion/clients/cmdline/main.c Fri Feb 1 00:16:23 2002
@@ -574,25 +574,44 @@
*(left_rev + (sep - arg)) = '\0';
right_rev = (left_rev + (sep - arg)) + 1;
}
- else /* If no separator, set left_rev, right_rev to same string. */
- left_rev = right_rev = apr_pstrdup (pool, arg);
+ else
+ {
+ left_rev = apr_pstrdup (pool, arg);
+ right_rev = NULL;
+ }
/* Validate each revision individually. */
- if ((validate_revision (left_rev) != 0)
- || (validate_revision (right_rev) != 0))
+ if (validate_revision (left_rev) != 0)
+ return 1;
+ if (right_rev && (validate_revision (right_rev) != 0))
return 1;
/* Okay, no syntax problems, parse 'em. */
if ((left_rev[0] == 'h') || (left_rev[0] == 'H') || (left_rev[0] == '\0'))
- os->start_revision = SVN_INVALID_REVNUM;
+ os->start_revision->kind = svn_client_revision_head;
else
- os->start_revision = SVN_STR_TO_REV (left_rev);
+ {
+ os->start_revision->kind = svn_client_revision_number;
+ os->start_revision->value.number = SVN_STR_TO_REV (left_rev);
+ }
- if ((right_rev[0] == 'h') || (right_rev[0] == 'H') || (right_rev[0] == '\0'))
- os->end_revision = SVN_INVALID_REVNUM;
- else
- os->end_revision = SVN_STR_TO_REV (right_rev);
+ if (right_rev)
+ {
+ if ((right_rev[0] == 'h')
+ || (right_rev[0] == 'H')
+ || (right_rev[0] == '\0'))
+ {
+ os->end_revision->kind = svn_client_revision_head;
+ }
+ else
+ {
+ os->end_revision->kind = svn_client_revision_number;
+ os->end_revision->value.number = SVN_STR_TO_REV (right_rev);
+ }
+ }
+ else /* probably was already unspecified, but be safe */
+ os->end_revision->kind = svn_client_revision_unspecified;
return SVN_NO_ERROR;
}
@@ -602,7 +621,7 @@
* ARG, where ARG is "X", ":X", or "X:Y", like so:
*
* - If ARG is "X" set both OPT_STATE->start_date and
- OPT_STATE->end_date to X.
+ * OPT_STATE->end_date to X.
*
* - If ARG is "X:", set OPT_STATE->start_date to X and don't
* touch OPT_STATE->end_date.
@@ -650,17 +669,25 @@
/* Treat each string individually. */
if (*left_date)
- apr_ansi_time_to_apr_time (&(os->start_date),
- svn_parse_date (left_date, NULL));
+ {
+ os->start_revision->kind = svn_client_revision_date;
+ apr_ansi_time_to_apr_time (&(os->start_revision->value.date),
+ svn_parse_date (left_date, NULL));
+ }
if (*right_date)
- apr_ansi_time_to_apr_time (&(os->end_date),
- svn_parse_date (right_date, NULL));
+ {
+ os->end_revision->kind = svn_client_revision_date;
+ apr_ansi_time_to_apr_time (&(os->end_revision->value.date),
+ svn_parse_date (right_date, NULL));
+ }
}
else
{
- apr_ansi_time_to_apr_time (&(os->start_date),
+ os->start_revision->kind = svn_client_revision_date;
+ os->end_revision->kind = svn_client_revision_date;
+ apr_ansi_time_to_apr_time (&(os->start_revision->value.date),
svn_parse_date ((char *) arg, NULL));
- os->end_date = os->start_date;
+ os->end_revision->value.date = os->start_revision->value.date;
}
return SVN_NO_ERROR;
@@ -704,9 +731,14 @@
apr_initialize ();
pool = svn_pool_create (NULL);
memset (&opt_state, 0, sizeof (opt_state));
- opt_state.start_revision = SVN_INVALID_REVNUM; /* default to youngest */
- opt_state.end_revision = 1; /* default to oldest */
+ opt_state.start_revision
+ = apr_pcalloc (pool, sizeof (*(opt_state.start_revision)));
+ opt_state.start_revision->kind = svn_client_revision_unspecified;
+ opt_state.end_revision
+ = apr_pcalloc (pool, sizeof (*(opt_state.end_revision)));
+ opt_state.end_revision->kind = svn_client_revision_unspecified;
+
/* No args? Show usage. */
if (argc <= 1)
{
$
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Sat Oct 21 14:37:02 2006