Karl Fogel wrote on Thu, Aug 30, 2018 at 00:22:16 -0500: > echo "### 'new-foo' is still a symlink, by the way:" > echo "" > ls -l new-foo ⋮ > echo "### Okay, ready for the *real* weirdness? Good. Let's first do" > echo "### an 'svn status -q' just to see things are:" > echo "" > svn status -q > echo "" > echo "### Now try manually replacing 'new-foo' with its non-special" > echo "### content. I tried this thinking it might achieve my goal" > echo "### of having a regular file containing the text 'link foo'." > echo "### In other words, I did 'svn cat new-foo > new-foo', and..." > svn cat new-foo > new-foo > echo "" > echo "### ...now the original regular 'foo' has the non-special content!" > echo "### Yes, you read that right. Here's an 'svn status -q' now:" ⋮ > echo "### So now not only can I not commit 'new-foo', 'foo' is" > echo "### affected as well. Here's the output of 'svn diff':" > echo "" > svn diff > echo "" > echo "### That's just messed up." > echo ""
Karl, this part is entirely normal. When you do «echo bar > qux», your shell calls open(O_TRUNC), not unlink(). In your case, since new-foo is a symlink on disk, when you do «/some/command > new-foo», your shell calls open(O_TRUNC) on new-foo and writes the command's output to it… and, according to the semantics of symlinks, calling open(O_TRUNC) and write() on the symlink 'new-foo' is equivalent to calling those syscalls on the symlink's target, ./foo. This has nothing to do with svn and everything to do with shell syntax (the use of 'svn cat' is a red herring). > echo "### You can run 'svn rm --force new-foo foo; svn commit' if you" > echo "### want to clean up the working copy to re-run this script." > There are possibly two bugs here, one of them supremely weird. The attached > script shows the recipe, with commentary. > > (This is all with svn version 1.10.2 (r1835932) as packaged in Debian > GNU/Linux for x86_64-pc-linux-gnu.) > > The rest of this mail will assume you've run, or at least examined, the > reproduction script. > > I looked in the bug tracker and https://issues.apache.org/jira/browse/SVN-2622 > shows another way to reach the first (and less serious) of the two bugs > demonstrated in the attached script. No other tickets seem to be related. > That's "SVN-4622: Sym links can only be replaced in 2 steps", already fixed. > I'll tentatively propose the following new behavior: > > When someone does > > $ svn propdel svn:special some_version_controlled_symlink > > maybe Subversion should not only delete the property, but also replace the > symlink with a regular file containing "link <destination_text>" (i.e., the > file-content portion of the repository's representation of a symlink). The > user should be able to commit at this point and everything would Just Work. > > If the person doesn't commit, and instead does > > $ svn propset svn:special '*' some_version_controlled_symlink > > then it would go back to being a symlink as before (and would appear > unmodified). > This implies that if one creates a regular file containing just the text > "link <destination_text>", commits it, and then does > > $ svn propset svn:special '*' that_file > > then the working file should transform into the appropriate symlink > automagically, which could then be committed as a symlink (whether a broken > link or not doesn't matter). > This is exactly how one adds or edits a symlink on !HAVE_SYMLINK platforms, including Windows. (You can get this behaviour on Unix if you get configure to lie about the HAVE_SYMLINK test result.) I suppose it's a public API therefore, although it's a bit odd that our serialization format _is_ our public API; I'd have expected some sort of layering decoupling the two. > You may agree or disagree with the above-proposed new behavior -- I'm still a > bit tentative about it myself! But I think the current behavior, as > demonstrated in the attached script, cannot be right. I haven't filed an > issue, though, because I wanted to discuss here first and make sure. Cheers, Daniel