From c279445ec07bc2b14893bd6f878260d4b7a65bda Mon Sep 17 00:00:00 2001
From: Stefan Wunsch <stefan.wunsch@cern.ch>
Date: Tue, 28 Jan 2020 16:22:22 +0100
Subject: [PATCH] [ROOT-10508] Fix TTreeProcessorMT for unnamed chain as friend

* Retrieves correctly the name of the trees building the chain if the
  chain itself does not has a name. This happens if the default
  constructor for TChain is used and the name of the tree is retrieved
  via the string given to `TChain::AddFile("file.root/treeName")`.
* This does not fix the issue entirely since the FriendInfo needs a
  refactoring. The FriendInfo assumes that in a chain each tree has the
  same name, which could not hold true.
---
 tree/treeplayer/src/TTreeProcessorMT.cxx | 39 +++++++++++++++---------
 1 file changed, 25 insertions(+), 14 deletions(-)

diff --git a/tree/treeplayer/src/TTreeProcessorMT.cxx b/tree/treeplayer/src/TTreeProcessorMT.cxx
index 0823eadf448..edb1a607be0 100644
--- a/tree/treeplayer/src/TTreeProcessorMT.cxx
+++ b/tree/treeplayer/src/TTreeProcessorMT.cxx
@@ -328,26 +328,37 @@ Internal::FriendInfo TTreeProcessorMT::GetFriendInfo(TTree &tree)
 
    for (auto fr : *friends) {
       const auto frTree = static_cast<TFriendElement *>(fr)->GetTree();
+      const bool isChain = frTree->IsA() == TChain::Class();
 
-      // Check if friend tree has an alias
-      const auto realName = frTree->GetName();
-      const auto alias = tree.GetFriendAlias(frTree);
-      if (alias) {
-         friendNames.emplace_back(std::make_pair(realName, std::string(alias)));
-      } else {
-         friendNames.emplace_back(std::make_pair(realName, ""));
-      }
-
-      // Store the file names of the friend tree
       friendFileNames.emplace_back();
       auto &fileNames = friendFileNames.back();
-      const bool isChain = tree.IsA() == TChain::Class();
+
+      // Check if friend tree/chain has an alias
+      const auto alias_c = tree.GetFriendAlias(frTree);
+      const std::string alias = alias_c != nullptr ? alias_c : "";
+
       if (isChain) {
-         const auto frChain = static_cast<TChain *>(frTree);
-         for (auto f : *(frChain->GetListOfFiles())) {
+         // Note that each TChainElement returned by chain.GetListOfFiles has a name
+         // equal to the tree name of this TChain and a title equal to the filename.
+         // Accessing the information like this ensures that we get the correct
+         // filenames and treenames if the treename is given as part of the filename
+         // via chain.AddFile(file.root/myTree) and as well if the tree name is given
+         // in the constructor via TChain(myTree) and a file is added later by chain.AddFile(file.root).
+
+         // Get name of the trees building the chain
+         const auto chainFiles = static_cast<TChain*>(frTree)->GetListOfFiles();
+         const auto realName = chainFiles->First()->GetName();
+         friendNames.emplace_back(std::make_pair(realName, alias));
+         // Get filenames stored in the title member
+         for (auto f : *chainFiles) {
             fileNames.emplace_back(f->GetTitle());
          }
       } else {
+         // Get name of the tree
+         const auto realName = frTree->GetName();
+         friendNames.emplace_back(std::make_pair(realName, alias));
+
+         // Get filename
          const auto f = frTree->GetCurrentFile();
          if (!f)
             throw std::runtime_error("Friend trees with no associated file are not supported.");
@@ -549,4 +560,4 @@ unsigned int TTreeProcessorMT::GetMaxTasksPerFilePerWorker()
 void TTreeProcessorMT::SetMaxTasksPerFilePerWorker(unsigned int maxTasksPerFile)
 {
    fgMaxTasksPerFilePerWorker = maxTasksPerFile;
-}
\ No newline at end of file
+}
-- 
GitLab