From 229ea63b4eac6147996576bd6ea5ec98852b3062 Mon Sep 17 00:00:00 2001 From: Fabien Chouteau Date: Mon, 6 Jul 2020 15:41:13 +0200 Subject: [PATCH] A couple of improvements on the handling of project files and paths (#463) * Alire.Releases: fix basename in Project_Files() * Alire.Releases.Project_Paths: Add empty path for gpr in the root dir of a crate * Alire.{Root|Release}: remove trailing path separator in Roots.Project_Paths Doing it here means that case "base_dir/" is also handled. i.e. return "base_dir" instead of "base_dir/" * Alire.Roots: Do not always add root dir of crates in Project_Paths The root dir will be included when necessary, i.e. when there is a project file. * testsuite/drivers/asserts.py: revert repr() on output compare It was useful to detect \r\n vs \n but make the test failure very difficult to analyze otherwise. * GPR_PROJECT_PATH tests: fix Windows vs UNIX paths * tests/auto-gpr-with/gpr_in_subdir: improve test explanation * Alire.Roots: expect UNIX dir separators from crates --- src/alire/alire-releases.adb | 23 ++++++++------- src/alire/alire-roots.adb | 29 ++++++++++++------- testsuite/drivers/alr.py | 2 +- testsuite/drivers/asserts.py | 8 ++--- testsuite/drivers/helpers.py | 13 +++++++-- .../basic}/my_index/index/ex/extern.toml | 0 .../basic}/my_index/index/index.toml | 0 .../my_index/index/li/libhello_nogprwith.toml | 0 .../basic}/test.py | 0 .../basic}/test.yaml | 0 .../my_index/index/gp/gpr_in_subdir.toml | 12 ++++++++ .../gpr_in_subdir/my_index/index/index.toml | 1 + .../tests/auto-gpr-with/gpr_in_subdir/test.py | 29 +++++++++++++++++++ .../auto-gpr-with/gpr_in_subdir/test.yaml | 7 +++++ testsuite/tests/setenv/basic/test.py | 27 ++++++++++------- testsuite/tests/setenv/linked-paths/test.py | 19 ++++++++++-- testsuite/tests/setenv/with-external/test.py | 7 +++++ 17 files changed, 137 insertions(+), 40 deletions(-) rename testsuite/tests/{workflows/auto-gpr-with => auto-gpr-with/basic}/my_index/index/ex/extern.toml (100%) rename testsuite/tests/{workflows/auto-gpr-with => auto-gpr-with/basic}/my_index/index/index.toml (100%) rename testsuite/tests/{workflows/auto-gpr-with => auto-gpr-with/basic}/my_index/index/li/libhello_nogprwith.toml (100%) rename testsuite/tests/{workflows/auto-gpr-with => auto-gpr-with/basic}/test.py (100%) rename testsuite/tests/{workflows/auto-gpr-with => auto-gpr-with/basic}/test.yaml (100%) create mode 100644 testsuite/tests/auto-gpr-with/gpr_in_subdir/my_index/index/gp/gpr_in_subdir.toml create mode 100644 testsuite/tests/auto-gpr-with/gpr_in_subdir/my_index/index/index.toml create mode 100644 testsuite/tests/auto-gpr-with/gpr_in_subdir/test.py create mode 100644 testsuite/tests/auto-gpr-with/gpr_in_subdir/test.yaml diff --git a/src/alire/alire-releases.adb b/src/alire/alire-releases.adb index 291aa383..4be7113a 100644 --- a/src/alire/alire-releases.adb +++ b/src/alire/alire-releases.adb @@ -397,12 +397,14 @@ package body Alire.Releases is return With_Paths; else for File of With_Paths loop - -- Has path or not - if Tail (File, '/') = "" then - Without.Append (File); -- As is - else - Without.Append (Tail (File, '/')); - end if; + + -- Basename + Without.Append (Split (Text => File, + Separator => '/', + Side => Tail, + From => Tail, + Raises => False)); + end loop; return Without; @@ -426,10 +428,11 @@ package body Alire.Releases is for File of Files loop if Contains (File, "/") then Paths.Include - (File (File'First .. Fixed.Index (File, "/", Backward) - 1)); - -- To match the output of root crate paths and Ada.Directories - -- full path normalization, a path separator in the last - -- position is not included. + (File (File'First .. Fixed.Index (File, "/", Backward))); + else + + -- The project file is at the root of the release + Paths.Include (""); end if; end loop; end return; diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index 4dd141ca..3b977c4f 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -117,16 +117,8 @@ package body Alire.Roots is Paths : Utils.String_Set; begin - -- Add root path from every release in the solution - for Rel of This.Solution.Releases.Including (Release (This)) loop - if Rel.Name = Release (This).Name then - null; -- The root project doesn't require its own path - else - Paths.Include (This.Release_Base (Rel.Name)); - end if; - - -- Add extra project paths + -- Add project paths from each release for Path of Rel.Project_Paths (This.Environment) loop Paths.Include (This.Release_Base (Rel.Name) / Path); @@ -141,7 +133,24 @@ package body Alire.Roots is end loop; end loop; - return Paths; + -- To match the output of root crate paths and Ada.Directories full path + -- normalization, a path separator in the last position is removed. + return Result : Utils.String_Set do + for Path of Paths loop + if Path'Length /= 0 + and then + + -- The paths provided by crates manifests are expected to use + -- UNIX directory separator. So we need to handle both UNIX and + -- OS separators. + Path (Path'Last) in '/' | GNAT.OS_Lib.Directory_Separator + then + Result.Include (Path (Path'First .. Path'Last - 1)); + else + Result.Include (Path); + end if; + end loop; + end return; end Project_Paths; -------------- diff --git a/testsuite/drivers/alr.py b/testsuite/drivers/alr.py index e826e144..14c29266 100644 --- a/testsuite/drivers/alr.py +++ b/testsuite/drivers/alr.py @@ -73,7 +73,7 @@ def run_alr(*args, **kwargs): print(' {}'.format(' '.join(quote_arg(arg) for arg in argv))) print('Exitted with status code {}'.format(p.status)) print('Output:') - print(repr(p.out)) + print(p.out) raise CalledProcessError('alr returned non-zero status code') # Convert CRLF line endings (Windows-style) to LF (Unix-style). This diff --git a/testsuite/drivers/asserts.py b/testsuite/drivers/asserts.py index feba4134..47219b59 100644 --- a/testsuite/drivers/asserts.py +++ b/testsuite/drivers/asserts.py @@ -17,9 +17,9 @@ def assert_eq(expected, actual, label=None): if expected != actual: text = ['Unexpected {}:'.format(label or 'output'), 'Expecting:', - indent(repr(str(expected))), + indent(str(expected)), 'But got:', - indent(repr(str(actual)))] + indent(str(actual))] assert False, '\n'.join(text) @@ -27,7 +27,7 @@ def assert_match(expected_re, actual, label=None, flags=0): if not re.match(expected_re, actual, flags=flags): text = ['Unexpected {}'.format(label or 'output'), 'Expecting a match on:', - indent(repr(expected_re)), + indent(expected_re), 'But got:', - indent(repr(actual))] + indent(actual)] assert False, '\n'.join(text) diff --git a/testsuite/drivers/helpers.py b/testsuite/drivers/helpers.py index cbddb716..8b40e3be 100644 --- a/testsuite/drivers/helpers.py +++ b/testsuite/drivers/helpers.py @@ -13,6 +13,15 @@ def contents(dir): for name in dirs + files]) +# Return the content of a text file +def content_of(filename): + out = '' + with open(filename, 'r') as f: + for l in f: + out += l + return out + + # Assert two values are equal or format the differences def compare(found, wanted): assert found == wanted, 'Got: {}\nWanted: {}'.format(found, wanted) @@ -29,8 +38,8 @@ def check_line_in(filename, line): if l.rstrip() == line: break else: - assert False, 'Could not find {} in {}'.format( - repr(line), filename) + assert False, 'Could not find {} in {}:\n{}'.format( + repr(line), filename, content_of (filename)) def path_separator(): diff --git a/testsuite/tests/workflows/auto-gpr-with/my_index/index/ex/extern.toml b/testsuite/tests/auto-gpr-with/basic/my_index/index/ex/extern.toml similarity index 100% rename from testsuite/tests/workflows/auto-gpr-with/my_index/index/ex/extern.toml rename to testsuite/tests/auto-gpr-with/basic/my_index/index/ex/extern.toml diff --git a/testsuite/tests/workflows/auto-gpr-with/my_index/index/index.toml b/testsuite/tests/auto-gpr-with/basic/my_index/index/index.toml similarity index 100% rename from testsuite/tests/workflows/auto-gpr-with/my_index/index/index.toml rename to testsuite/tests/auto-gpr-with/basic/my_index/index/index.toml diff --git a/testsuite/tests/workflows/auto-gpr-with/my_index/index/li/libhello_nogprwith.toml b/testsuite/tests/auto-gpr-with/basic/my_index/index/li/libhello_nogprwith.toml similarity index 100% rename from testsuite/tests/workflows/auto-gpr-with/my_index/index/li/libhello_nogprwith.toml rename to testsuite/tests/auto-gpr-with/basic/my_index/index/li/libhello_nogprwith.toml diff --git a/testsuite/tests/workflows/auto-gpr-with/test.py b/testsuite/tests/auto-gpr-with/basic/test.py similarity index 100% rename from testsuite/tests/workflows/auto-gpr-with/test.py rename to testsuite/tests/auto-gpr-with/basic/test.py diff --git a/testsuite/tests/workflows/auto-gpr-with/test.yaml b/testsuite/tests/auto-gpr-with/basic/test.yaml similarity index 100% rename from testsuite/tests/workflows/auto-gpr-with/test.yaml rename to testsuite/tests/auto-gpr-with/basic/test.yaml diff --git a/testsuite/tests/auto-gpr-with/gpr_in_subdir/my_index/index/gp/gpr_in_subdir.toml b/testsuite/tests/auto-gpr-with/gpr_in_subdir/my_index/index/gp/gpr_in_subdir.toml new file mode 100644 index 00000000..37ac1635 --- /dev/null +++ b/testsuite/tests/auto-gpr-with/gpr_in_subdir/my_index/index/gp/gpr_in_subdir.toml @@ -0,0 +1,12 @@ +[general] +description = "gpr file in subdirs" +licenses = [] +maintainers = ["example@example.com"] +maintainers-logins = ["mylogin"] + +# The dirX folder do not exist. This is not a problem since we won't try to +# compile this code. +project-files=["dir1/dir2/dir3/gpr_in_subdir.gpr"] + +['1.0'] +origin = "file://../../crates/libhello_1.0.0" diff --git a/testsuite/tests/auto-gpr-with/gpr_in_subdir/my_index/index/index.toml b/testsuite/tests/auto-gpr-with/gpr_in_subdir/my_index/index/index.toml new file mode 100644 index 00000000..319b3b37 --- /dev/null +++ b/testsuite/tests/auto-gpr-with/gpr_in_subdir/my_index/index/index.toml @@ -0,0 +1 @@ +version = "0.3" diff --git a/testsuite/tests/auto-gpr-with/gpr_in_subdir/test.py b/testsuite/tests/auto-gpr-with/gpr_in_subdir/test.py new file mode 100644 index 00000000..6709abf7 --- /dev/null +++ b/testsuite/tests/auto-gpr-with/gpr_in_subdir/test.py @@ -0,0 +1,29 @@ +""" +Test the with statement for a project file in sub dirs +""" + +from glob import glob +import os + +from drivers.alr import run_alr +from drivers.asserts import assert_eq, assert_match + +import re +import platform +from drivers.helpers import check_line_in + +# Get the "hello" project and enter its directory +run_alr('init', '--bin', 'myhello') +os.chdir(glob('myhello*')[0]) + +# Get dependencies that should also add a with statement in myhello.gpr +run_alr('with', 'libhello') +run_alr('with', 'gpr_in_subdir') + +check_line_in('myhello.gpr', 'with "libhello.gpr";') + +# When the crate declares a project file: `dir1/dir2/dir3/prj.gpr`, the with +# statement has to be `with "prj.gpr"`. Without the sub-dirs because +# GPR_PROJECT_PATH is already set with dirs that contain the project file. +check_line_in('myhello.gpr', 'with "gpr_in_subdir.gpr";') +print('SUCCESS') diff --git a/testsuite/tests/auto-gpr-with/gpr_in_subdir/test.yaml b/testsuite/tests/auto-gpr-with/gpr_in_subdir/test.yaml new file mode 100644 index 00000000..496a1d1a --- /dev/null +++ b/testsuite/tests/auto-gpr-with/gpr_in_subdir/test.yaml @@ -0,0 +1,7 @@ +driver: python-script +indexes: + basic_index: + in_fixtures: true + my_index: + in_fixtures: false + copy_crates_src: true diff --git a/testsuite/tests/setenv/basic/test.py b/testsuite/tests/setenv/basic/test.py index 44f5d8dd..f250caab 100644 --- a/testsuite/tests/setenv/basic/test.py +++ b/testsuite/tests/setenv/basic/test.py @@ -21,15 +21,22 @@ os.chdir(glob('hello*')[0]) p = run_alr('setenv', quiet=False) assert_eq(0, p.status) -if platform.system() == 'Windows': - assert_match('export TEST_GPR_EXTERNAL="gpr_ext_B"\n' - 'export GPR_PROJECT_PATH="[A-Z]:\\\\.*\\\\alire\\\\cache\\\\dependencies\\\\libhello_1\.0\.0_filesystem"\n' - 'export ALIRE="True"\n', - p.out, flags=re.S) -else: - assert_match('export TEST_GPR_EXTERNAL="gpr_ext_B"\n' - 'export GPR_PROJECT_PATH="/.*/alire/cache/dependencies/libhello_1\.0\.0_filesystem"\n' - 'export ALIRE="True"\n', - p.out, flags=re.S) +expected_gpr_path = [] +expected_gpr_path += [['.*', 'hello_1.0.1_filesystem']] +expected_gpr_path += [['.*', 'alire', 'cache', 'dependencies', 'libhello_1\.0\.0_filesystem']] + +for i, path in enumerate(expected_gpr_path): + if platform.system() == 'Windows': + expected_gpr_path[i] = "\\\\".join(path) + else: + expected_gpr_path[i] = "/".join(path) + +expected_gpr_path = os.pathsep.join(expected_gpr_path) + +assert_match('export TEST_GPR_EXTERNAL="gpr_ext_B"\n' + 'export GPR_PROJECT_PATH="' + expected_gpr_path + '"\n' + 'export ALIRE="True"\n', + p.out, flags=re.S) + print('SUCCESS') diff --git a/testsuite/tests/setenv/linked-paths/test.py b/testsuite/tests/setenv/linked-paths/test.py index 6ff67b8c..91fef9f4 100644 --- a/testsuite/tests/setenv/linked-paths/test.py +++ b/testsuite/tests/setenv/linked-paths/test.py @@ -5,6 +5,7 @@ properly added to the environment import os import re +import platform from drivers.alr import run_alr from drivers.asserts import assert_match @@ -17,11 +18,23 @@ os.chdir("xxx") # Link a folder with also contains crate definitions run_alr("with", "--use=../my_index/crates/crate_1234") +expected_gpr_path = [] +expected_gpr_path += [['.*', 'my_index', 'crates', 'crate_1234']] +expected_gpr_path += [['.*', 'my_index', 'crates', 'crate_1234', 'nested']] +expected_gpr_path += [['.*', 'xxx']] + +for i, path in enumerate(expected_gpr_path): + if platform.system() == 'Windows': + expected_gpr_path[i] = "\\\\".join(path) + else: + expected_gpr_path[i] = "/".join(path) + +expected_gpr_path = os.pathsep.join(expected_gpr_path) + # Check paths are proper (base and one extra nested) p = run_alr("setenv") -assert_match(('export GPR_PROJECT_PATH=".*/my_index/crates/crate_1234' + - path_separator() + '.*/my_index/crates/crate_1234/nested"\n' + - 'export ALIRE="True"\n').replace('/', re.escape(dir_separator())), +assert_match(('export GPR_PROJECT_PATH="' + expected_gpr_path + '"\n' + + 'export ALIRE="True"\n').replace('/', re.escape(dir_separator())), p.out) diff --git a/testsuite/tests/setenv/with-external/test.py b/testsuite/tests/setenv/with-external/test.py index 70553812..38202411 100644 --- a/testsuite/tests/setenv/with-external/test.py +++ b/testsuite/tests/setenv/with-external/test.py @@ -21,9 +21,16 @@ os.chdir('libhello_0.9.0_filesystem') p = run_alr('setenv', quiet=False) assert_eq(0, p.status) +expected_gpr_path="" +if platform.system() == 'Windows': + expected_gpr_path = '.*\\\\libhello_0.9.0_filesystem' +else: + expected_gpr_path = '.*/libhello_0.9.0_filesystem' + # Check the setenv output assert_match('warn: Generating incomplete environment' # Note: this warning is ' because of missing dependencies\n' # via stderr so it's OK + 'export GPR_PROJECT_PATH="' + expected_gpr_path + '"\n' 'export ALIRE="True"\n', p.out) -- 2.39.5