From b52dadd99b83c353dc4ca218d56a8a9d2495e921 Mon Sep 17 00:00:00 2001 From: kubajj Date: Tue, 10 Aug 2021 13:04:22 +0200 Subject: [PATCH 1/2] Add parent packages into dependency tree --- src/fpm/dependency.f90 | 107 +++++++++++++++----- test/fpm_test/test_package_dependencies.f90 | 4 +- 2 files changed, 84 insertions(+), 27 deletions(-) diff --git a/src/fpm/dependency.f90 b/src/fpm/dependency.f90 index bd85b6f014..7c1394562c 100644 --- a/src/fpm/dependency.f90 +++ b/src/fpm/dependency.f90 @@ -57,14 +57,15 @@ module fpm_dependency use, intrinsic :: iso_fortran_env, only : output_unit use fpm_environment, only : get_os_type, OS_WINDOWS - use fpm_error, only : error_t, fatal_error + use fpm_error, only : error_t, fatal_error, fpm_stop use fpm_filesystem, only : exists, join_path, mkdir, canon_path, windows_path use fpm_git, only : git_target_revision, git_target_default, git_revision use fpm_manifest, only : package_config_t, dependency_config_t, & get_package_data use fpm_strings, only : string_t, operator(.in.) - use fpm_toml, only : toml_table, toml_key, toml_error, toml_serializer, & - toml_parse, get_value, set_value, add_table + use fpm_toml, only : toml_table, toml_array, toml_key, toml_error, & + & toml_serializer, toml_parse, toml_stat, get_value, set_value, & + & add_table, add_array, len use fpm_versioning, only : version_t, new_version, char implicit none private @@ -92,6 +93,8 @@ module fpm_dependency logical :: done = .false. !> Dependency should be updated logical :: update = .false. + !> List of indices of parent nodes in the tree + integer, allocatable :: parent(:) contains !> Update dependency from project manifest procedure :: register @@ -191,7 +194,7 @@ subroutine new_dependency_tree(self, verbosity, cache) end subroutine new_dependency_tree !> Create a new dependency node from a configuration - pure subroutine new_dependency_node(self, dependency, version, proj_dir, update) + pure subroutine new_dependency_node(self, dependency, version, proj_dir, update, parent) !> Instance of the dependency node type(dependency_node_t), intent(out) :: self !> Dependency configuration data @@ -202,6 +205,8 @@ pure subroutine new_dependency_node(self, dependency, version, proj_dir, update) character(len=*), intent(in), optional :: proj_dir !> Dependency should be updated logical, intent(in), optional :: update + !> Index of parent node + integer, intent(in), optional :: parent self%dependency_config_t = dependency @@ -217,6 +222,11 @@ pure subroutine new_dependency_node(self, dependency, version, proj_dir, update) self%update = update end if + if (present(parent)) then + allocate(self%parent(1)) + self%parent(1) = parent + end if + end subroutine new_dependency_node !> Add project dependencies, each depth level after each other. @@ -252,16 +262,16 @@ subroutine add_project(self, package, error) if (allocated(error)) return ! Resolve the root project - call self%resolve(root, error) + call self%resolve(root, error, parent=package%name) if (allocated(error)) return ! Add the root project dependencies (depth 1) - call self%add(package, root, .true., error) + call self%add(package, root, .true., error, parent=package%name) if (allocated(error)) return ! Now decent into the dependency tree, level for level do while(.not.self%finished()) - call self%resolve(root, error) + call self%resolve(root, error, parent=package%name) if (allocated(error)) exit end do if (allocated(error)) return @@ -274,7 +284,7 @@ subroutine add_project(self, package, error) end subroutine add_project !> Add a project and its dependencies to the dependency tree - recursive subroutine add_project_dependencies(self, package, root, main, error) + recursive subroutine add_project_dependencies(self, package, root, main, error, parent) !> Instance of the dependency tree class(dependency_tree_t), intent(inout) :: self !> Project configuration to add @@ -285,24 +295,26 @@ recursive subroutine add_project_dependencies(self, package, root, main, error) logical, intent(in) :: main !> Error handling type(error_t), allocatable, intent(out) :: error + !> Name of parent package + character(len=*), intent(in), optional :: parent integer :: ii if (allocated(package%dependency)) then - call self%add(package%dependency, error) + call self%add(package%dependency, error, parent=package%name) if (allocated(error)) return end if if (main) then if (allocated(package%dev_dependency)) then - call self%add(package%dev_dependency, error) + call self%add(package%dev_dependency, error, parent=package%name) if (allocated(error)) return end if if (allocated(package%executable)) then do ii = 1, size(package%executable) if (allocated(package%executable(ii)%dependency)) then - call self%add(package%executable(ii)%dependency, error) + call self%add(package%executable(ii)%dependency, error, parent=package%name) if (allocated(error)) exit end if end do @@ -312,7 +324,7 @@ recursive subroutine add_project_dependencies(self, package, root, main, error) if (allocated(package%example)) then do ii = 1, size(package%example) if (allocated(package%example(ii)%dependency)) then - call self%add(package%example(ii)%dependency, error) + call self%add(package%example(ii)%dependency, error, parent=package%name) if (allocated(error)) exit end if end do @@ -322,7 +334,7 @@ recursive subroutine add_project_dependencies(self, package, root, main, error) if (allocated(package%test)) then do ii = 1, size(package%test) if (allocated(package%test(ii)%dependency)) then - call self%add(package%test(ii)%dependency, error) + call self%add(package%test(ii)%dependency, error, parent=package%name) if (allocated(error)) exit end if end do @@ -333,13 +345,15 @@ recursive subroutine add_project_dependencies(self, package, root, main, error) end subroutine add_project_dependencies !> Add a list of dependencies to the dependency tree - subroutine add_dependencies(self, dependency, error) + subroutine add_dependencies(self, dependency, error, parent) !> Instance of the dependency tree class(dependency_tree_t), intent(inout) :: self !> Dependency configuration to add type(dependency_config_t), intent(in) :: dependency(:) !> Error handling type(error_t), allocatable, intent(out) :: error + !> Name of parent package + character(len=*), intent(in), optional :: parent integer :: ii, ndep @@ -349,7 +363,7 @@ subroutine add_dependencies(self, dependency, error) end if do ii = 1, size(dependency) - call self%add(dependency(ii), error) + call self%add(dependency(ii), error, parent=parent) if (allocated(error)) exit end do if (allocated(error)) return @@ -357,20 +371,41 @@ subroutine add_dependencies(self, dependency, error) end subroutine add_dependencies !> Add a single dependency to the dependency tree - pure subroutine add_dependency(self, dependency, error) +! pure subroutine add_dependency(self, dependency, error, parent) + subroutine add_dependency(self, dependency, error, parent) !> Instance of the dependency tree class(dependency_tree_t), intent(inout) :: self !> Dependency configuration to add type(dependency_config_t), intent(in) :: dependency !> Error handling type(error_t), allocatable, intent(out) :: error + !> Name of parent package + character(len=*), intent(in), optional :: parent - integer :: id + integer :: id, i, parent_id + logical :: found + parent_id = 0 + found = .false. + if (present(parent)) then + parent_id = self%find(parent) + if (parent_id < 1) call fpm_stop(1,'*add_dependency*:Error: No such package in dependency tree.') + end if id = self%find(dependency) if (id == 0) then self%ndep = self%ndep + 1 - call new_dependency_node(self%dep(self%ndep), dependency) + if (parent_id > 0) then + call new_dependency_node(self%dep(self%ndep), dependency, parent=parent_id) + else + call new_dependency_node(self%dep(self%ndep), dependency) + end if + else if (present(parent) .and. allocated(self%dep(id)%parent)) then + do i=1, size(self%dep(id)%parent) + if (self%dep(id)%parent(i)==parent_id) then + found=.true. + end if + end do + if (.not. found) self%dep(id)%parent = [self%dep(id)%parent, parent_id] end if end subroutine add_dependency @@ -420,18 +455,20 @@ subroutine update_dependency(self, name, error) end subroutine update_dependency !> Resolve all dependencies in the tree - subroutine resolve_dependencies(self, root, error) + subroutine resolve_dependencies(self, root, error, parent) !> Instance of the dependency tree class(dependency_tree_t), intent(inout) :: self !> Current installation prefix character(len=*), intent(in) :: root !> Error handling type(error_t), allocatable, intent(out) :: error + !> Name of parent package + character(len=*), intent(in), optional :: parent integer :: ii do ii = 1, self%ndep - call self%resolve(self%dep(ii), root, error) + call self%resolve(self%dep(ii), root, error, parent=parent) if (allocated(error)) exit end do @@ -440,7 +477,7 @@ subroutine resolve_dependencies(self, root, error) end subroutine resolve_dependencies !> Resolve a single dependency node - subroutine resolve_dependency(self, dependency, root, error) + subroutine resolve_dependency(self, dependency, root, error, parent) !> Instance of the dependency tree class(dependency_tree_t), intent(inout) :: self !> Dependency configuration to add @@ -449,6 +486,8 @@ subroutine resolve_dependency(self, dependency, root, error) character(len=*), intent(in) :: root !> Error handling type(error_t), allocatable, intent(out) :: error + !> Name of parent package + character(len=*), intent(in), optional :: parent type(package_config_t) :: package character(len=:), allocatable :: manifest, proj_dir, revision @@ -491,7 +530,7 @@ subroutine resolve_dependency(self, dependency, root, error) "at", dependency%proj_dir end if - call self%add(package, proj_dir, .false., error) + call self%add(package, proj_dir, .false., error, parent=parent) if (allocated(error)) return end subroutine resolve_dependency @@ -638,11 +677,12 @@ subroutine load_from_toml(self, table, error) !> Error handling type(error_t), allocatable, intent(out) :: error - integer :: ndep, ii + integer :: ndep, ii, ip logical :: unix - character(len=:), allocatable :: version, url, obj, rev, proj_dir + character(len=:), allocatable :: version, url, obj, rev, proj_dir, parent_name type(toml_key), allocatable :: list(:) type(toml_table), pointer :: ptr + type(toml_array), pointer :: p_array call table%get_keys(list) @@ -660,6 +700,7 @@ subroutine load_from_toml(self, table, error) call get_value(ptr, "git", url) call get_value(ptr, "obj", obj) call get_value(ptr, "rev", rev) + call get_value(ptr, "parent", p_array, requested=.false.) if (.not.allocated(proj_dir)) cycle self%ndep = self%ndep + 1 associate(dep => self%dep(self%ndep)) @@ -691,6 +732,13 @@ subroutine load_from_toml(self, table, error) else dep%path = proj_dir end if + if (associated(p_array)) then + allocate(dep%parent(len(p_array))) + do ip = 1, len(p_array) + call get_value(p_array, ip, parent_name) + dep%parent(ip) = self%find(parent_name) + end do + end if end associate end do if (allocated(error)) return @@ -746,12 +794,13 @@ subroutine dump_to_toml(self, table, error) !> Error handling type(error_t), allocatable, intent(out) :: error - integer :: ii + integer :: ii, ip type(toml_table), pointer :: ptr + type(toml_array), pointer :: parent_ptr character(len=:), allocatable :: proj_dir do ii = 1, self%ndep - associate(dep => self%dep(ii)) + associate(dep => self%dep(ii), deps => self%dep) call add_table(table, dep%name, ptr) if (.not.associated(ptr)) then call fatal_error(error, "Cannot create entry for "//dep%name) @@ -771,6 +820,12 @@ subroutine dump_to_toml(self, table, error) call set_value(ptr, "rev", dep%revision) end if end if + if (allocated(dep%parent) .and. size(dep%parent) > 0) then + call add_array(ptr, "parent", parent_ptr) + do ip=1,size(dep%parent) + call set_value(parent_ptr, ip, self%dep(dep%parent(ip))%name) + end do + end if end associate end do if (allocated(error)) return diff --git a/test/fpm_test/test_package_dependencies.f90 b/test/fpm_test/test_package_dependencies.f90 index a3192ff2f9..7e8a879361 100644 --- a/test/fpm_test/test_package_dependencies.f90 +++ b/test/fpm_test/test_package_dependencies.f90 @@ -212,7 +212,7 @@ end subroutine test_add_dependencies !> Resolve a single dependency node - subroutine resolve_dependency_once(self, dependency, root, error) + subroutine resolve_dependency_once(self, dependency, root, error, parent) !> Mock instance of the dependency tree class(mock_dependency_tree_t), intent(inout) :: self !> Dependency configuration to add @@ -221,6 +221,8 @@ subroutine resolve_dependency_once(self, dependency, root, error) character(len=*), intent(in) :: root !> Error handling type(error_t), allocatable, intent(out) :: error + !> Name of the parent package + character(len=*), intent(in), optional :: parent if (dependency%done) then call test_failed(error, "Should only visit this node once") From 7938def553c6ed675b6226eeb43d7096aad61f71 Mon Sep 17 00:00:00 2001 From: kubajj Date: Tue, 10 Aug 2021 14:29:57 +0200 Subject: [PATCH 2/2] Implement changes from suggestions in PR --- src/fpm/dependency.f90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fpm/dependency.f90 b/src/fpm/dependency.f90 index 7c1394562c..b5eaf06ad0 100644 --- a/src/fpm/dependency.f90 +++ b/src/fpm/dependency.f90 @@ -389,7 +389,7 @@ subroutine add_dependency(self, dependency, error, parent) found = .false. if (present(parent)) then parent_id = self%find(parent) - if (parent_id < 1) call fpm_stop(1,'*add_dependency*:Error: No such package in dependency tree.') + if (parent_id < 1) call fatal_error(error,'*add_dependency*:Error: No such package in dependency tree.') end if id = self%find(dependency) if (id == 0) then @@ -800,7 +800,7 @@ subroutine dump_to_toml(self, table, error) character(len=:), allocatable :: proj_dir do ii = 1, self%ndep - associate(dep => self%dep(ii), deps => self%dep) + associate(dep => self%dep(ii)) call add_table(table, dep%name, ptr) if (.not.associated(ptr)) then call fatal_error(error, "Cannot create entry for "//dep%name) @@ -822,7 +822,7 @@ subroutine dump_to_toml(self, table, error) end if if (allocated(dep%parent) .and. size(dep%parent) > 0) then call add_array(ptr, "parent", parent_ptr) - do ip=1,size(dep%parent) + do ip = 1, size(dep%parent) call set_value(parent_ptr, ip, self%dep(dep%parent(ip))%name) end do end if