Valentin David pushed to branch valentindavid/link_files_sort_resolved at BuildStream / buildstream
Commits:
-
00f6f506
by Valentin David at 2019-01-04T14:09:55Z
7 changed files:
- buildstream/utils.py
- tests/integration/compose-symlink-order.py
- tests/integration/compose-symlinks.py
- + tests/integration/project/elements/compose-symlinks/a-foo-symlink.bst
- + tests/integration/project/elements/compose-symlinks/compose-absolute-symlink.bst
- + tests/integration/project/elements/compose-symlinks/foo-dir.bst
- + tests/integration/project/elements/compose-symlinks/integration-move-dir.bst
Changes:
... | ... | @@ -787,6 +787,48 @@ def _ensure_real_directory(root, destpath): |
787 | 787 |
return destpath_resolved
|
788 | 788 |
|
789 | 789 |
|
790 |
+@functools.lru_cache(maxsize=1)
|
|
791 |
+def _symloop_max():
|
|
792 |
+ if hasattr(os, 'sysconf'):
|
|
793 |
+ try:
|
|
794 |
+ ret = os.sysconf('_SC_SYMLOOP_MAX')
|
|
795 |
+ if ret != -1:
|
|
796 |
+ return ret
|
|
797 |
+ except ValueError:
|
|
798 |
+ pass
|
|
799 |
+ return 8
|
|
800 |
+ |
|
801 |
+ |
|
802 |
+@functools.lru_cache(maxsize=64)
|
|
803 |
+def _sysroot_realpath(path, sysroot):
|
|
804 |
+ assert not os.path.isabs(path)
|
|
805 |
+ assert os.path.isabs(sysroot)
|
|
806 |
+ |
|
807 |
+ loop_count = _symloop_max()
|
|
808 |
+ while True:
|
|
809 |
+ full_path = os.path.join(sysroot, path)
|
|
810 |
+ st = os.lstat(full_path)
|
|
811 |
+ mode = st.st_mode
|
|
812 |
+ if not stat.S_ISLNK(mode):
|
|
813 |
+ break
|
|
814 |
+ loop_count = loop_count - 1
|
|
815 |
+ if loop_count < 0:
|
|
816 |
+ raise UtilError("Symlink loop detected: {}".format(os.path.join(sysroot, path)))
|
|
817 |
+ link_path = os.readlink(full_path)
|
|
818 |
+ if not os.path.isabs(link_path):
|
|
819 |
+ link_path = os.path.join('/', os.path.dirname(path), link_path)
|
|
820 |
+ path = os.path.relpath(os.path.normpath(link_path), '/')
|
|
821 |
+ |
|
822 |
+ parent = os.path.dirname(path)
|
|
823 |
+ if parent != '':
|
|
824 |
+ parent = _sysroot_realpath(parent, sysroot)
|
|
825 |
+ full_parent = os.path.join(sysroot, parent)
|
|
826 |
+ if not os.path.isdir(full_parent):
|
|
827 |
+ raise UtilError("Path is not a directory: {}".format(full_parent))
|
|
828 |
+ |
|
829 |
+ return os.path.join(parent, os.path.basename(path))
|
|
830 |
+ |
|
831 |
+ |
|
790 | 832 |
# _process_list()
|
791 | 833 |
#
|
792 | 834 |
# Internal helper for copying/moving/linking file lists
|
... | ... | @@ -817,10 +859,10 @@ def _process_list(srcdir, destdir, filelist, actionfunc, result, |
817 | 859 |
# those directories.
|
818 | 860 |
if not presorted:
|
819 | 861 |
resolved = []
|
862 |
+ _sysroot_realpath.cache_clear()
|
|
820 | 863 |
for f in filelist:
|
821 | 864 |
dirname = os.path.dirname(f)
|
822 |
- dirname = os.path.realpath(os.path.join(srcdir, dirname))
|
|
823 |
- dirname = os.path.relpath(dirname, srcdir)
|
|
865 |
+ dirname = _sysroot_realpath(dirname, srcdir)
|
|
824 | 866 |
if dirname == '.':
|
825 | 867 |
resolved.append(os.path.basename(f))
|
826 | 868 |
else:
|
... | ... | @@ -16,6 +16,7 @@ DATA_DIR = os.path.join( |
16 | 16 |
|
17 | 17 |
|
18 | 18 |
@pytest.mark.datafiles(DATA_DIR)
|
19 |
+@pytest.mark.skipif(not IS_LINUX or not HAVE_BWRAP, reason='Only available on linux with bubblewrap')
|
|
19 | 20 |
def test_compose_symlinks_bad_order(cli, tmpdir, datafiles):
|
20 | 21 |
project = str(datafiles)
|
21 | 22 |
checkout = os.path.join(cli.directory, 'checkout')
|
... | ... | @@ -41,3 +41,18 @@ def test_compose_symlinks(cli, tmpdir, datafiles): |
41 | 41 |
|
42 | 42 |
assert set(walk_dir(checkout)) == set(['/sbin', '/usr', '/usr/sbin',
|
43 | 43 |
'/usr/sbin/init', '/usr/sbin/dummy'])
|
44 |
+ |
|
45 |
+ |
|
46 |
+@pytest.mark.datafiles(DATA_DIR)
|
|
47 |
+def test_compose_absolute_symlinks(cli, tmpdir, datafiles):
|
|
48 |
+ project = str(datafiles)
|
|
49 |
+ checkout = os.path.join(cli.directory, 'checkout')
|
|
50 |
+ element_path = os.path.join(project, 'elements')
|
|
51 |
+ |
|
52 |
+ result = cli.run(project=project, args=['build', 'compose-symlinks/compose-absolute-symlink.bst'])
|
|
53 |
+ result.assert_success()
|
|
54 |
+ |
|
55 |
+ result = cli.run(project=project, args=['checkout', 'compose-symlinks/compose-absolute-symlink.bst', checkout])
|
|
56 |
+ result.assert_success()
|
|
57 |
+ |
|
58 |
+ assert os.readlink(os.path.join(checkout, 'foo')) == 'test/foo'
|
1 |
+kind: script
|
|
2 |
+ |
|
3 |
+depends:
|
|
4 |
+- filename: base.bst
|
|
5 |
+ type: build
|
|
6 |
+ |
|
7 |
+config:
|
|
8 |
+ commands:
|
|
9 |
+ - |
|
|
10 |
+ mkdir -p "%{install-root}/bar"
|
|
11 |
+ ln -s "/bar" "%{install-root}/foo"
|
1 |
+kind: compose
|
|
2 |
+ |
|
3 |
+depends:
|
|
4 |
+- filename: compose-symlinks/foo-dir.bst
|
|
5 |
+ type: build
|
|
6 |
+- filename: compose-symlinks/a-foo-symlink.bst
|
|
7 |
+ type: build
|
|
8 |
+- filename: compose-symlinks/integration-move-dir.bst
|
|
9 |
+ type: build
|
|
10 |
+ |
|
11 |
+config:
|
|
12 |
+ include-orphans: true
|
|
13 |
+ exclude:
|
|
14 |
+ - dummy
|
1 |
+kind: script
|
|
2 |
+ |
|
3 |
+depends:
|
|
4 |
+- filename: base.bst
|
|
5 |
+ type: build
|
|
6 |
+ |
|
7 |
+config:
|
|
8 |
+ commands:
|
|
9 |
+ - |
|
|
10 |
+ mkdir -p "%{install-root}/foo"
|
|
11 |
+ echo test >"%{install-root}/foo/foo.txt"
|
1 |
+kind: stack
|
|
2 |
+ |
|
3 |
+depends:
|
|
4 |
+- filename: base.bst
|
|
5 |
+ |
|
6 |
+public:
|
|
7 |
+ bst:
|
|
8 |
+ integration-commands:
|
|
9 |
+ - |
|
|
10 |
+ mkdir test
|
|
11 |
+ mv foo test/
|
|
12 |
+ mv bar test/
|
|
13 |
+ ln -s /test/foo /foo
|
|
14 |
+ ln -s /test/bar /bar
|