pfultz2 / cget

C++ package retrieval

Home Page:http://cget.readthedocs.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Broken links give subtle error.

somedadaism opened this issue · comments

Moving the cget directory after an install results in broken links which make the project unable to compile.
This is a somewhat difficult to spot error for a first time user (maybe it's just me).
Is there a way to avoid this by relative paths? Could be a nice feature for the project.

Using relative paths is probably a good idea.

I am working at a pull request to resolve the issue. Would you accept one?

Yes, definitely.

I have a first commit that resolves my original issue and passes all tests.
https://github.com/somedadaism/cget/tree/rel_symlink
But I believe there is further work required. I wanted to ask for some directions on that part.
Essentially the only change is in cget/utils.py in the function symlink_dir:

         +   relpath = os.path.relpath(os.path.join(root, file), d)
              try:
         -       os.symlink(os.path.join(root, file), os.path.join(d, file))
         +       if not os.path.isfile(os.path.join(d, file)):
         +           os.symlink(relpath, os.path.join(d, file))
 

If the condition if not os.path.isfile(os.path.join(d, file)): is dropped the above code will fail in roughly half the test cases with a FileExistsError.
As far as my investigation got me I suspect the reason for that to be that the method is sometimes run more than once for a given file and that the absolute path link could be removed between these two runs, while this failed for the relative link.
I troubleshot all occurrences of os.remove but none of them seem to be covered by the tests. Can you help me to improve on this issue?

Sorry for the late reply.

So the tests generally will do an install and then remove and another install. Since the removal fails, the second install fails as well.

The reason the removal fails is that it checks that the file its removing is in the cget/ directory here. This is done as a safeguard so it wont remove files cget isnt managing.

This can be fixed by changing it to compute the absolute path in rm_symlink_in:

def rm_symlink_in(file, prefix):
    if os.path.islink(file):
        f = os.readlink(file)
        if not os.path.isabs(f):
            f = os.path.normpath(os.path.join(os.path.dirname(file), f))
        if f.startswith(prefix):
            os.remove(file)