On Fri, Feb 11, 2022 at 09:22:25AM +0100, Martin Obermeir wrote:
> Hi,
> 
> When using `svn copy --pin-externals` to create a tag, svn:externals with a
> relative path get pinned a non existing path: They get pinned to the
> revision before the commit, but the path doesn't exist yet in that revision.
> I expected them to be pinned to the revision which gets created during the
> svn copy operation.
> 
> In the example below:
>   actual result: A/D - ../B/lambda@2 lambda
>   expected result: A/D - ../B/lambda@3 lambda
> 
> Please find the script to reproduce this attached. Commented excerpt:
> 
>   cd A/D/
>   svn propset svn:externals "../B/lambda lambda" . # relative path
>   svn commit -m "msg1" # creates revision 2
>   cd ../..
>   svn copy --pin-externals ${URL}/trunk ${URL}/tags/pinnedExternals -m
> "msg2" # creates revision 3
>   svn switch ^/tags/pinnedExternals
>   # gives warnings:
>   #   svn: warning: W205011: Error handling externals definition for
> 'A/D/lambda':
>   #   svn: warning: W170000: URL
> 'file:///tmp/pinExternalsBug/repos/tags/pinnedExternals/A/B/lambda' at
> revision 2 doesn't exist
>   svn propget -R svn:externals
>   # gives: A/D - ../B/lambda@2 lambda
>   #   i.e. pinned to revision 2, but the path doesn't exist (created in
> revision 3)
>   #   I would expect: A/D - ../B/lambda@3 lambda
> 
> 
> Tested on Kubuntu 20.04.3 LTS and SUSE Linux Enterprise Server 15 SP3 
> (x86_64) with:
> - todays trunk (Revision: 1897960): svn, version 1.15.0-dev (under
> development) compiled Feb 11 2022, 08:01:11 on x86_64-pc-linux-gnu
> - svn, version 1.14.1 (r1886195)
> - svn, version 1.13.0 (r1867053)   compiled Mar 24 2020, 12:33:36 on
> x86_64-pc-linux-gnu
> - svn, version 1.10.6 (r1863367)
> 
> Best regards
> Martin


Hi Martin,

Thank you for this report. This is a problem which was already present in
the commit which added this feature (https://svn.apache.org/r1659395).

I am afraid it is impossible to implement a solution for the issue as
you have presented it because your desired solution has an inherent
chicken-and-egg problem:

The external definition is created by the client as part of creating the
new commit. At this time, the new revision number is not yet known.
The client only learns about the new revision number after the commit has
been created on the server. And the client must prepare properties which
contain external definitions as part of creating the commit. So there is
an inherent contradiction between the behaviour you would like to see and
the way the system works internally.

The revision number cannot even be inferred as something like HEAD+1 because
the server can process commits from multiple clients in parallel while clients
upload data, assigning a new number to whichever commit finishes first.

The best suggestion I have is to only refer to already existing source paths
in externals definitions added with your commit which creates your new tag.
This means instead of using a relative external that points inside the path
space of your new tag, use a path that points into trunk or some other branch
where the same files and directories already exist. Because any tag created
by a URL-URL copy is a copy of something that already exists somewhere else
in the repository, this should always be possible, should it not?
Once the tag has been created and the new revision number is known, you
could then make a subsequent commit which manually pins the external to a
path which now exists inside the tag's path space, if you prefer that.

Does this make sense?

The behaviour exposed by your script is certainly not ideal.
In the URL-URL copy case the client does not check whether the pinned
paths even exist!
The client could at least check whether the path is is pinning does in
fact exist. It could either error out if the path cannot be found, or
simply leave the external alone and avoid pinning it.

Verifying externals in general is not an easy problem. If an external
definition is wrong or no longer working due to circumstances such as
URLs having become unusable, SVN will error out when trying to use the
external. There is little we can do about that, as it is somewhat
inherent in the design of the externals feature. Any external that is
valid today could become invalid tomorrow.

Regards,
Stefan

Reply via email to