Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Follow symlinks in SVN

I have a linux directory (and don't need any windows checkout):

/home/me/projects/project1

In this project, I need SVN (1.8.8) to follow a symlink "link1":

/home/me/projects/project1/link1/<some_directories_and_files>

But SVN won't let me do that, it just add link1 but not its content. If I try to add its content, I get an error:

svn add link1/*
svn: E145001: Can't schedule an addition of '/home/me/projects/project1/link1/first_directory' below a not-directory node

I tried converting link1 to hard link but I can't do that either:

ln /path/to/my/linked/directory link1
ln: ‘/path/to/my/linked/directory’: hard link not allowed for directory

Any idea? How do you handle this kind of configuration? I just need to commit everything from /home/me/projects/project1 from a simple svn commit

like image 337
Cyrille Avatar asked Jul 20 '14 13:07

Cyrille


1 Answers

If I understand your problem, you have:

project1/
project1/link1 -> ../../some/where/else

If you do a simple svn add link1 it adds a symlink entry to the subversion repository, but what you're trying to accomplish is getting the stuff under somewhere else into the tree.

If this is the case, then you're fighting in the wrong direction, you should make the real files and directories under link1, and make the target locations symlinks into the link1 directory. That would be a simple solution to the problem.

Another solution would be to make the location ../../some/where/else an svn location in it's own right, and make link1 an externals definition to that location. When you commit in the main directory, the externals would be committed at the same time which would achieve storing the information; however to ensure that the other location was kept in sync, you would have to make sure to update it to the same version as the stored data.

In my case, on my desktop, I have a settings directory:

$HOME/settings

This is a checked out copy of a directory containing .bashrc, .profile, .vimrc, .vim, etc. files and folders from an svn repo. All my profile files and directories were symlinks into this folder, so for example .profile -> settings/.profile, etc. When I make changes, they are reflected in the svn tree, which I can commit back to in order to ensure that I don't lose my config settings when I go to another system.

If you really want svn to follow symlinks as hardlinks (You can't make directory hardlinks because it would be a bad thing™), then you'll have to hack the svn client source so that it did what you wanted; but this would be a maintenance nightmare.

You could get away with making the symlink into a bind mount point directed at the target, but that has it's own issues - you would need to be root to accomplish this, and it ends up leaving funny entries in your /proc/mounts to accomplish this:

mount --bind /absolute/path/to/some/where/else project1/link1

Bind mounting does not work when mounting to inside the svn tree since the working copy format changes introduced by svn 1.7 - svn operations attempt to move files from .svn/tmp to the target folder, which would be a cross device link. The workaround in this case is to go from the inside out, i.e.:

mount --bind project/link1 /absolute/path/to/somewhere/else

With the change in the svn working copy format of a single .svn folder for the checked out tree, you will need to perform all subsequent operations from the true svn location, as it won’t work from the bind mounted folder, on the assumption that you have not mounted the entire checked out tree at that target location.

like image 113
Petesh Avatar answered Sep 19 '22 20:09

Petesh