aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2018-08-12 01:29:00 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2018-08-24 03:24:10 +0530
commit04e25e5975af1c75a34fee49bc94a7a664966440 (patch)
treee1ae64229ffdde64c5d2719a652d52e23af14907
parent1311b8a748d42b663d439504d81c5e633446f330 (diff)
downloadmeson-04e25e5975af1c75a34fee49bc94a7a664966440.zip
meson-04e25e5975af1c75a34fee49bc94a7a664966440.tar.gz
meson-04e25e5975af1c75a34fee49bc94a7a664966440.tar.bz2
install_subdir: Also copy dangling symlinks
Fixes https://github.com/mesonbuild/meson/issues/3914
-rw-r--r--mesonbuild/minstall.py20
-rwxr-xr-xrun_unittests.py26
2 files changed, 39 insertions, 7 deletions
diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py
index 11c8e5f..14f2fa1 100644
--- a/mesonbuild/minstall.py
+++ b/mesonbuild/minstall.py
@@ -191,12 +191,16 @@ class Installer:
def should_preserve_existing_file(self, from_file, to_file):
if not self.options.only_changed:
return False
+ # Always replace danging symlinks
+ if os.path.islink(from_file) and not os.path.isfile(from_file):
+ return False
from_time = os.stat(from_file).st_mtime
to_time = os.stat(to_file).st_mtime
return from_time <= to_time
def do_copyfile(self, from_file, to_file):
- if not os.path.isfile(from_file):
+ outdir = os.path.split(to_file)[0]
+ if not os.path.isfile(from_file) and not os.path.islink(from_file):
raise RuntimeError('Tried to install something that isn\'t a file:'
'{!r}'.format(from_file))
# copyfile fails if the target file already exists, so remove it to
@@ -210,11 +214,13 @@ class Installer:
append_to_log(self.lf, '# Preserving old file %s\n' % to_file)
print('Preserving existing file %s.' % to_file)
return False
- os.unlink(to_file)
- outdir = os.path.split(to_file)[0]
+ os.remove(to_file)
print('Installing %s to %s' % (from_file, outdir))
- shutil.copyfile(from_file, to_file)
- shutil.copystat(from_file, to_file)
+ if os.path.islink(from_file):
+ shutil.copy(from_file, outdir, follow_symlinks=False)
+ else:
+ shutil.copyfile(from_file, to_file)
+ shutil.copystat(from_file, to_file)
selinux_updates.append(to_file)
append_to_log(self.lf, to_file)
return True
@@ -277,7 +283,7 @@ class Installer:
if os.path.isdir(abs_dst):
print('Tried to copy file %s but a directory of that name already exists.' % abs_dst)
if os.path.exists(abs_dst):
- os.unlink(abs_dst)
+ os.remove(abs_dst)
parent_dir = os.path.dirname(abs_dst)
if not os.path.isdir(parent_dir):
os.mkdir(parent_dir)
@@ -431,7 +437,7 @@ class Installer:
try:
symlinkfilename = os.path.join(outdir, alias)
try:
- os.unlink(symlinkfilename)
+ os.remove(symlinkfilename)
except FileNotFoundError:
pass
os.symlink(to, symlinkfilename)
diff --git a/run_unittests.py b/run_unittests.py
index 363cbcd..56bdf79 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -3703,6 +3703,32 @@ endian = 'little'
# Ensure that the otool output does not contain self.installdir
self.assertNotRegex(out, self.installdir + '.*dylib ')
+ def test_install_subdir_symlinks(self):
+ '''
+ Test that installation of broken symlinks works fine.
+ https://github.com/mesonbuild/meson/issues/3914
+ '''
+ testdir = os.path.join(self.common_test_dir, '66 install subdir')
+ subdir = os.path.join(testdir, 'sub/sub1')
+ curdir = os.getcwd()
+ os.chdir(subdir)
+ # Can't distribute broken symlinks in the source tree because it breaks
+ # the creation of zipapps. Create it dynamically and run the test by
+ # hand.
+ src = '../../nonexistent.txt'
+ os.symlink(src, 'test.txt')
+ try:
+ self.init(testdir)
+ self.build()
+ self.install()
+ link = os.path.join(self.installdir, 'usr', 'share', 'sub1', 'test.txt')
+ self.assertTrue(os.path.islink(link), msg=link)
+ self.assertEqual(src, os.readlink(link))
+ self.assertFalse(os.path.isfile(link), msg=link)
+ finally:
+ os.remove(os.path.join(subdir, 'test.txt'))
+ os.chdir(curdir)
+
class LinuxArmCrossCompileTests(BasePlatformTests):
'''