• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

HicServices / RDMP / 9859858140

09 Jul 2024 03:24PM UTC coverage: 56.679% (-0.2%) from 56.916%
9859858140

push

github

JFriel
update

10912 of 20750 branches covered (52.59%)

Branch coverage included in aggregate %.

30965 of 53135 relevant lines covered (58.28%)

7908.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

33.33
/Rdmp.Core/DataExport/DataExtraction/ExtractionDirectory.cs
1
// Copyright (c) The University of Dundee 2018-2019
2
// This file is part of the Research Data Management Platform (RDMP).
3
// RDMP is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
4
// RDMP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
5
// You should have received a copy of the GNU General Public License along with RDMP. If not, see <https://www.gnu.org/licenses/>.
6

7
using System;
8
using System.Collections.Generic;
9
using System.IO;
10
using System.Linq;
11
using Rdmp.Core.Curation.Data;
12
using Rdmp.Core.DataExport.Data;
13
using Rdmp.Core.ReusableLibraryCode.Progress;
14

15
namespace Rdmp.Core.DataExport.DataExtraction;
16

17
/// <summary>
18
/// The target directory for a given ExtractionConfiguration on a given day.  This is where linked anonymised project extracts will appear when
19
/// an ExtractionConfiguration is executed.  It is also the location where the Release Engine will pick them up from when it bundles together a
20
/// release package.
21
/// </summary>
22
public class ExtractionDirectory : IExtractionDirectory
23
{
24
    public const string EXTRACTION_SUB_FOLDER_NAME = "Extractions";
25
    public const string STANDARD_EXTRACTION_PREFIX = "Extr_";
26
    public const string GLOBALS_DATA_NAME = "Globals";
27
    public const string CUSTOM_COHORT_DATA_FOLDER_NAME = "CohortCustomData";
28
    public const string MASTER_DATA_FOLDER_NAME = "MasterData";
29
    public const string METADATA_FOLDER_NAME = "MetadataShareDefs";
30

31
    public DirectoryInfo ExtractionDirectoryInfo { get; private set; }
518✔
32

33
    public ExtractionDirectory(string rootExtractionDirectory, IExtractionConfiguration configuration)
34
        : this(rootExtractionDirectory, configuration, DateTime.Now)
266✔
35
    {
36
    }
266✔
37

38
    private ExtractionDirectory(string rootExtractionDirectory, IExtractionConfiguration configuration,
266✔
39
        DateTime extractionDate)
266✔
40
    {
41
        if (string.IsNullOrWhiteSpace(rootExtractionDirectory))
266!
42
            throw new NullReferenceException("Extraction Directory not set");
×
43

44
        if (!rootExtractionDirectory.StartsWith("\\"))
266✔
45
            if (!Directory.Exists(rootExtractionDirectory))
266!
46
                throw new DirectoryNotFoundException($"Root directory \"{rootExtractionDirectory}\" does not exist");
×
47

48
        var root = new DirectoryInfo(Path.Combine(rootExtractionDirectory, EXTRACTION_SUB_FOLDER_NAME));
266✔
49
        if (!root.Exists)
266✔
50
            root.Create();
4✔
51

52
        var subdirectoryName = GetExtractionDirectoryPrefix(configuration);
266✔
53

54
        ExtractionDirectoryInfo = Directory.Exists(Path.Combine(root.FullName, subdirectoryName))
266✔
55
            ? new DirectoryInfo(Path.Combine(root.FullName, subdirectoryName))
266✔
56
            : root.CreateSubdirectory(subdirectoryName);
266✔
57
    }
266✔
58

59
    public static string GetExtractionDirectoryPrefix(IExtractionConfiguration configuration) =>
60
        STANDARD_EXTRACTION_PREFIX + configuration.ID;
270✔
61

62
    public DirectoryInfo GetDirectoryForDataset(IExtractableDataSet dataset)
63
    {
64
        if (dataset.ToString().Equals(CUSTOM_COHORT_DATA_FOLDER_NAME))
188!
65
            throw new Exception(
×
66
                $"You cannot call a dataset '{CUSTOM_COHORT_DATA_FOLDER_NAME}' because this string is reserved for cohort custom data the system spits out itself");
×
67

68
        if (!Catalogue.IsAcceptableName(dataset.Catalogue.Name, out var reason))
188✔
69
            throw new NotSupportedException(
2✔
70
                $"Cannot extract dataset {dataset} because it points at Catalogue with an invalid name, name is invalid because:{reason}");
2✔
71

72
        var datasetDirectory = dataset.ToString();
186✔
73
        try
74
        {
75
            return ExtractionDirectoryInfo.CreateSubdirectory(datasetDirectory);
186✔
76
        }
77
        catch (Exception e)
×
78
        {
79
            throw new Exception(
×
80
                $"Could not create a directory called '{datasetDirectory}' as a subfolder of Project extraction directory {ExtractionDirectoryInfo.Root}",
×
81
                e);
×
82
        }
83
    }
186✔
84

85
    public DirectoryInfo GetGlobalsDirectory() => ExtractionDirectoryInfo.CreateSubdirectory(GLOBALS_DATA_NAME);
66✔
86

87
    public static bool IsOwnerOf(IExtractionConfiguration configuration, DirectoryInfo directory)
88
    {
89
        //they passed a root directory like c:\bob?
90
        if (directory.Parent == null)
×
91
            return false;
×
92

93
        //The configuration number matches but directory isn't the currently configured Project extraction directory
94
        var p = configuration.Project;
×
95

96
        return directory.Parent.FullName == Path.Combine(p.ExtractionDirectory, EXTRACTION_SUB_FOLDER_NAME) &&
×
97
               directory.Name.StartsWith(STANDARD_EXTRACTION_PREFIX + configuration.ID);
×
98
    }
99

100
    public DirectoryInfo GetDirectoryForCohortCustomData() =>
101
        ExtractionDirectoryInfo.CreateSubdirectory(CUSTOM_COHORT_DATA_FOLDER_NAME);
×
102

103
    public DirectoryInfo GetDirectoryForMasterData() =>
104
        ExtractionDirectoryInfo.CreateSubdirectory(MASTER_DATA_FOLDER_NAME);
×
105

106
    public static void CleanupExtractionDirectory(object sender, string extractionDirectory,
107
        IEnumerable<IExtractionConfiguration> configurations, IDataLoadEventListener listener)
108
    {
109
        var projectExtractionDirectory =
×
110
            new DirectoryInfo(Path.Combine(extractionDirectory, EXTRACTION_SUB_FOLDER_NAME));
×
111
        var directoriesToDelete = new List<DirectoryInfo>();
×
112
        var filesToDelete = new List<FileInfo>();
×
113

114
        foreach (var extractionConfiguration in configurations)
×
115
        {
116
            var config = extractionConfiguration;
×
117
            var directoryInfos = projectExtractionDirectory.GetDirectories().Where(d => IsOwnerOf(config, d));
×
118

119
            foreach (var toCleanup in directoryInfos)
×
120
                AddDirectoryToCleanupList(toCleanup, true, directoriesToDelete, filesToDelete);
×
121
        }
122

123
        foreach (var fileInfo in filesToDelete)
×
124
        {
125
            listener.OnNotify(sender, new NotifyEventArgs(ProgressEventType.Information,
×
126
                $"Deleting: {fileInfo.FullName}"));
×
127
            try
128
            {
129
                fileInfo.Delete();
×
130
            }
×
131
            catch (Exception e)
×
132
            {
133
                listener.OnNotify(sender, new NotifyEventArgs(ProgressEventType.Error,
×
134
                    $"Error deleting: {fileInfo.FullName}", e));
×
135
            }
×
136
        }
137

138
        foreach (var directoryInfo in directoriesToDelete)
×
139
        {
140
            listener.OnNotify(sender, new NotifyEventArgs(ProgressEventType.Information,
×
141
                $"Recursively deleting folder: {directoryInfo.FullName}"));
×
142
            try
143
            {
144
                directoryInfo.Delete(true);
×
145
            }
×
146
            catch (Exception e)
×
147
            {
148
                listener.OnNotify(sender, new NotifyEventArgs(ProgressEventType.Error,
×
149
                    $"Error deleting: {directoryInfo.FullName}", e));
×
150
            }
×
151
        }
152
    }
×
153

154
    private static void AddDirectoryToCleanupList(DirectoryInfo toCleanup, bool isRoot,
155
        List<DirectoryInfo> directoriesToDelete, List<FileInfo> filesToDelete)
156
    {
157
        //only add root folders to the delete queue
158
        if (isRoot)
×
159
            if (!directoriesToDelete.Any(dir =>
×
160
                    dir.FullName.Equals(toCleanup.FullName))) //don't add the same folder twice
×
161
                directoriesToDelete.Add(toCleanup);
×
162

163
        filesToDelete.AddRange(toCleanup.EnumerateFiles());
×
164

165
        foreach (var dir in toCleanup.EnumerateDirectories())
×
166
            AddDirectoryToCleanupList(dir, false, directoriesToDelete, filesToDelete);
×
167
    }
×
168
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc