Skip to content

Commit 8fb262f

Browse files
committed
Suppress empty directories from TFileMerger's partial merge.
Partial merging creates a full directory hierarchy in an output file, even if the user didn't ask for the directories to be merged. Fix #19330.
1 parent 0c33e8f commit 8fb262f

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

io/io/src/TFileMerger.cxx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -591,8 +591,15 @@ Bool_t TFileMerger::MergeOne(TDirectory *target, TList *sourcelist, Int_t type,
591591
// GetPath(), so we can still figure out where we are in the recursion
592592

593593
// If this folder is a onlyListed object, merge everything inside.
594-
if (onlyListed) type &= ~kOnlyListed;
595-
status = MergeRecursive(newdir, sourcelist, type);
594+
const auto mergeType = onlyListed ? type &= ~kOnlyListed : type;
595+
status = MergeRecursive(newdir, sourcelist, mergeType);
596+
597+
if ((type & kOnlyListed) && !(type & kIncremental) && !onlyListed && newdir->GetNkeys() == 0) {
598+
// None of the children were merged, and the directory is not listed
599+
delete newdir;
600+
newdir = nullptr;
601+
target->rmdir(obj->GetName());
602+
}
596603
// Delete newdir directory after having written it (merged)
597604
if (!(type&kIncremental)) delete newdir;
598605
if (onlyListed) type |= kOnlyListed;

io/io/test/TFileMergerTests.cxx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,35 @@ TEST(TFileMerger, ChangeFile)
221221
gSystem->Unlink("file6640mergerinput_2.root");
222222
gSystem->Unlink("file6640mergeroutput.root");
223223
}
224+
225+
TEST(TFileMerger, SelectiveMergeWithDirectories)
226+
{
227+
constexpr auto input = "selectiveMerge_input.root";
228+
constexpr auto output = "selectiveMerge_output.root";
229+
{
230+
TH1F histo("histo", "Histo", 2, 0, 1);
231+
TFile infile(input, "recreate");
232+
auto dir = infile.mkdir("A");
233+
dir->WriteObject(&histo, "Histo_A");
234+
dir = infile.mkdir("B");
235+
dir->WriteObject(&histo, "Histo_B");
236+
}
237+
238+
{
239+
TFileMerger fileMerger(false);
240+
fileMerger.AddFile(input);
241+
fileMerger.AddObjectNames("A");
242+
fileMerger.OutputFile(output);
243+
fileMerger.PartialMerge(TFileMerger::kOnlyListed | TFileMerger::kAll | TFileMerger::kRegular);
244+
}
245+
246+
TFile outfile(output);
247+
auto dir_A = dynamic_cast<TDirectory *>(outfile.Get("A"));
248+
ASSERT_NE(dir_A, nullptr);
249+
EXPECT_NE(dir_A->Get("Histo_A"), nullptr);
250+
251+
EXPECT_EQ(outfile.Get("B"), nullptr);
252+
253+
std::remove(input);
254+
std::remove(output);
255+
}

0 commit comments

Comments
 (0)