* Check the dependencies (recursively) of this content info * @param ci the content info to check the dependencies of */
| 954 | * @param ci the content info to check the dependencies of |
| 955 | */ |
| 956 | void ClientNetworkContentSocketHandler::CheckDependencyState(const ContentInfo &ci) |
| 957 | { |
| 958 | if (ci.IsSelected() || ci.state == ContentInfo::State::AlreadyHere) { |
| 959 | /* Selection is easy; just walk all children and set the |
| 960 | * autoselected state. That way we can see what we automatically |
| 961 | * selected and thus can unselect when a dependency is removed. */ |
| 962 | for (auto &dependency : ci.dependencies) { |
| 963 | ContentInfo *c = this->GetContent(dependency); |
| 964 | if (c == nullptr) { |
| 965 | this->DownloadContentInfo(dependency); |
| 966 | } else if (c->state == ContentInfo::State::Unselected) { |
| 967 | c->state = ContentInfo::State::Autoselected; |
| 968 | this->CheckDependencyState(*c); |
| 969 | } |
| 970 | } |
| 971 | return; |
| 972 | } |
| 973 | |
| 974 | if (ci.state != ContentInfo::State::Unselected) return; |
| 975 | |
| 976 | /* For unselection we need to find the parents of us. We need to |
| 977 | * unselect them. After that we unselect all children that we |
| 978 | * depend on and are not used as dependency for us, but only when |
| 979 | * we automatically selected them. */ |
| 980 | ConstContentVector parents; |
| 981 | this->ReverseLookupDependency(parents, ci); |
| 982 | for (const ContentInfo *c : parents) { |
| 983 | if (!c->IsSelected()) continue; |
| 984 | |
| 985 | this->Unselect(c->id); |
| 986 | } |
| 987 | |
| 988 | for (auto &dependency : ci.dependencies) { |
| 989 | const ContentInfo *c = this->GetContent(dependency); |
| 990 | if (c == nullptr) { |
| 991 | DownloadContentInfo(dependency); |
| 992 | continue; |
| 993 | } |
| 994 | if (c->state != ContentInfo::State::Autoselected) continue; |
| 995 | |
| 996 | /* Only unselect when WE are the only parent. */ |
| 997 | parents.clear(); |
| 998 | this->ReverseLookupDependency(parents, *c); |
| 999 | |
| 1000 | /* First check whether anything depends on us */ |
| 1001 | int sel_count = 0; |
| 1002 | bool force_selection = false; |
| 1003 | for (const ContentInfo *parent_ci : parents) { |
| 1004 | if (parent_ci->IsSelected()) sel_count++; |
| 1005 | if (parent_ci->state == ContentInfo::State::Selected) force_selection = true; |
| 1006 | } |
| 1007 | if (sel_count == 0) { |
| 1008 | /* Nothing depends on us */ |
| 1009 | this->Unselect(c->id); |
| 1010 | continue; |
| 1011 | } |
| 1012 | /* Something manually selected depends directly on us */ |
| 1013 | if (force_selection) continue; |
no test coverage detected