summaryrefslogtreecommitdiff
path: root/src/tools/heat/DirectoryHarvester.cs
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2022-07-26 17:20:39 -0700
committerRob Mensching <rob@firegiant.com>2022-08-01 20:25:19 -0700
commita627ca9b720047e633a8fe72003ab9bee31006c5 (patch)
tree2bc8a924bb4141ab718e74d08f6459a0ffe8d573 /src/tools/heat/DirectoryHarvester.cs
parent521eb3c9cf38823a2c4019abb85dc0b3200b92cb (diff)
downloadwix-a627ca9b720047e633a8fe72003ab9bee31006c5.tar.gz
wix-a627ca9b720047e633a8fe72003ab9bee31006c5.tar.bz2
wix-a627ca9b720047e633a8fe72003ab9bee31006c5.zip
Create WixToolset.Heat.nupkg to distribute heat.exe and Heat targets
Moves Heat functionality to the "tools" layer and packages it all up in WixToolset.Heat.nupkg for distribution in WiX v4. Completes 6838
Diffstat (limited to 'src/tools/heat/DirectoryHarvester.cs')
-rw-r--r--src/tools/heat/DirectoryHarvester.cs308
1 files changed, 308 insertions, 0 deletions
diff --git a/src/tools/heat/DirectoryHarvester.cs b/src/tools/heat/DirectoryHarvester.cs
new file mode 100644
index 00000000..c1cc3edb
--- /dev/null
+++ b/src/tools/heat/DirectoryHarvester.cs
@@ -0,0 +1,308 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Harvesters
4{
5 using System;
6 using System.IO;
7 using WixToolset.Data;
8 using WixToolset.Harvesters.Data;
9 using WixToolset.Harvesters.Extensibility;
10 using Wix = WixToolset.Harvesters.Serialize;
11
12 /// <summary>
13 /// Harvest WiX authoring for a directory from the file system.
14 /// </summary>
15 public sealed class DirectoryHarvester : BaseHarvesterExtension
16 {
17 private FileHarvester fileHarvester;
18
19 private const string ComponentPrefix = "cmp";
20 private const string DirectoryPrefix = "dir";
21 private const string FilePrefix = "fil";
22
23 /// <summary>
24 /// Instantiate a new DirectoryHarvester.
25 /// </summary>
26 public DirectoryHarvester()
27 {
28 this.fileHarvester = new FileHarvester();
29 this.SetUniqueIdentifiers = true;
30 }
31
32 /// <summary>
33 /// Gets or sets what type of elements are to be generated.
34 /// </summary>
35 /// <value>The type of elements being generated.</value>
36 public GenerateType GenerateType { get; set; }
37
38 /// <summary>
39 /// Gets or sets the option to keep empty directories.
40 /// </summary>
41 /// <value>The option to keep empty directories.</value>
42 public bool KeepEmptyDirectories { get; set; }
43
44 /// <summary>
45 /// Gets or sets the rooted DirectoryRef Id if the user has supplied it.
46 /// </summary>
47 /// <value>The DirectoryRef Id to use as the root.</value>
48 public string RootedDirectoryRef { get; set; }
49
50 /// <summary>
51 /// Gets of sets the option to set unique identifiers.
52 /// </summary>
53 /// <value>The option to set unique identifiers.</value>
54 public bool SetUniqueIdentifiers { get; set; }
55
56 /// <summary>
57 /// Gets or sets the option to suppress including the root directory as an element.
58 /// </summary>
59 /// <value>The option to suppress including the root directory as an element.</value>
60 public bool SuppressRootDirectory { get; set; }
61
62 /// <summary>
63 /// Harvest a directory.
64 /// </summary>
65 /// <param name="argument">The path of the directory.</param>
66 /// <returns>The harvested directory.</returns>
67 public override Wix.Fragment[] Harvest(string argument)
68 {
69 if (null == argument)
70 {
71 throw new ArgumentNullException("argument");
72 }
73
74 Wix.IParentElement harvestParent = this.HarvestDirectory(argument, true, this.GenerateType);
75 Wix.ISchemaElement harvestElement;
76
77 if (this.GenerateType == GenerateType.PayloadGroup)
78 {
79 Wix.PayloadGroup payloadGroup = (Wix.PayloadGroup)harvestParent;
80 payloadGroup.Id = this.RootedDirectoryRef;
81 harvestElement = payloadGroup;
82 }
83 else
84 {
85 Wix.Directory directory = (Wix.Directory)harvestParent;
86
87 Wix.DirectoryRef directoryRef = new Wix.DirectoryRef();
88 directoryRef.Id = this.RootedDirectoryRef;
89
90 if (this.SuppressRootDirectory)
91 {
92 foreach (Wix.ISchemaElement element in directory.Children)
93 {
94 directoryRef.AddChild(element);
95 }
96 }
97 else
98 {
99 directoryRef.AddChild(directory);
100 }
101 harvestElement = directoryRef;
102 }
103
104 Wix.Fragment fragment = new Wix.Fragment();
105 fragment.AddChild(harvestElement);
106
107 return new Wix.Fragment[] { fragment };
108 }
109
110 /// <summary>
111 /// Harvest a directory.
112 /// </summary>
113 /// <param name="path">The path of the directory.</param>
114 /// <param name="harvestChildren">The option to harvest child directories and files.</param>
115 /// <returns>The harvested directory.</returns>
116 public Wix.Directory HarvestDirectory(string path, bool harvestChildren)
117 {
118 if (null == path)
119 {
120 throw new ArgumentNullException("path");
121 }
122
123 return (Wix.Directory)this.HarvestDirectory(path, harvestChildren, GenerateType.Components);
124 }
125
126 /// <summary>
127 /// Harvest a directory.
128 /// </summary>
129 /// <param name="path">The path of the directory.</param>
130 /// <param name="harvestChildren">The option to harvest child directories and files.</param>
131 /// <param name="generateType">The type to generate.</param>
132 /// <returns>The harvested directory.</returns>
133 private Wix.IParentElement HarvestDirectory(string path, bool harvestChildren, GenerateType generateType)
134 {
135 if (File.Exists(path))
136 {
137 throw new WixException(ErrorMessages.ExpectedDirectoryGotFile("dir", path));
138 }
139
140 if (null == this.RootedDirectoryRef)
141 {
142 this.RootedDirectoryRef = "TARGETDIR";
143 }
144
145 // use absolute paths
146 path = Path.GetFullPath(path);
147
148 // Remove any trailing separator to ensure Path.GetFileName() will return the directory name.
149 path = path.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
150
151 Wix.IParentElement harvestParent;
152 if (generateType == GenerateType.PayloadGroup)
153 {
154 harvestParent = new Wix.PayloadGroup();
155 }
156 else
157 {
158 Wix.Directory directory = new Wix.Directory();
159 directory.Name = Path.GetFileName(path);
160 directory.FileSource = path;
161
162 if (this.SetUniqueIdentifiers)
163 {
164 if (this.SuppressRootDirectory)
165 {
166 directory.Id = this.Core.GenerateIdentifier(DirectoryPrefix, this.RootedDirectoryRef);
167 }
168 else
169 {
170 directory.Id = this.Core.GenerateIdentifier(DirectoryPrefix, this.RootedDirectoryRef, directory.Name);
171 }
172 }
173 harvestParent = directory;
174 }
175
176 if (harvestChildren)
177 {
178 try
179 {
180 int fileCount = this.HarvestDirectory(path, "SourceDir\\", harvestParent, generateType);
181
182 if (generateType != GenerateType.PayloadGroup)
183 {
184 // its an error to not harvest anything with the option to keep empty directories off
185 if (0 == fileCount && !this.KeepEmptyDirectories)
186 {
187 throw new WixException(HarvesterErrors.EmptyDirectory(path));
188 }
189 }
190 }
191 catch (DirectoryNotFoundException)
192 {
193 throw new WixException(HarvesterErrors.DirectoryNotFound(path));
194 }
195 }
196
197 return harvestParent;
198 }
199
200 /// <summary>
201 /// Harvest a directory.
202 /// </summary>
203 /// <param name="path">The path of the directory.</param>
204 /// <param name="relativePath">The relative path that will be used when harvesting.</param>
205 /// <param name="harvestParent">The directory for this path.</param>
206 /// <param name="generateType"></param>
207 /// <returns>The number of files harvested.</returns>
208 private int HarvestDirectory(string path, string relativePath, Wix.IParentElement harvestParent, GenerateType generateType)
209 {
210 int fileCount = 0;
211 Wix.Directory directory = generateType != GenerateType.PayloadGroup ? (Wix.Directory)harvestParent : null;
212
213 // harvest the child directories
214 foreach (string childDirectoryPath in Directory.GetDirectories(path))
215 {
216 var childDirectoryName = Path.GetFileName(childDirectoryPath);
217 Wix.IParentElement newParent;
218 Wix.Directory childDirectory = null;
219
220 if (generateType == GenerateType.PayloadGroup)
221 {
222 newParent = harvestParent;
223 }
224 else
225 {
226 childDirectory = new Wix.Directory();
227 newParent = childDirectory;
228
229 childDirectory.Name = childDirectoryName;
230 childDirectory.FileSource = childDirectoryPath;
231
232 if (this.SetUniqueIdentifiers)
233 {
234 childDirectory.Id = this.Core.GenerateIdentifier(DirectoryPrefix, directory.Id, childDirectory.Name);
235 }
236 }
237
238 int childFileCount = this.HarvestDirectory(childDirectoryPath, String.Concat(relativePath, childDirectoryName, "\\"), newParent, generateType);
239
240 if (generateType != GenerateType.PayloadGroup)
241 {
242 // keep the directory if it contained any files (or empty directories are being kept)
243 if (0 < childFileCount || this.KeepEmptyDirectories)
244 {
245 directory.AddChild(childDirectory);
246 }
247 }
248
249 fileCount += childFileCount;
250 }
251
252 // harvest the files
253 string[] files = Directory.GetFiles(path);
254 if (0 < files.Length)
255 {
256 foreach (string filePath in Directory.GetFiles(path))
257 {
258 string fileName = Path.GetFileName(filePath);
259 string source = String.Concat(relativePath, fileName);
260
261 Wix.ISchemaElement newChild;
262 if (generateType == GenerateType.PayloadGroup)
263 {
264 Wix.Payload payload = new Wix.Payload();
265 newChild = payload;
266
267 payload.SourceFile = source;
268 }
269 else
270 {
271 Wix.Component component = new Wix.Component();
272 newChild = component;
273
274 Wix.File file = this.fileHarvester.HarvestFile(filePath);
275 file.Source = source;
276
277 if (this.SetUniqueIdentifiers)
278 {
279 file.Id = this.Core.GenerateIdentifier(FilePrefix, directory.Id, fileName);
280 component.Id = this.Core.GenerateIdentifier(ComponentPrefix, directory.Id, file.Id);
281 }
282
283 component.AddChild(file);
284 }
285
286 harvestParent.AddChild(newChild);
287 }
288 }
289 else if (generateType != GenerateType.PayloadGroup && 0 == fileCount && this.KeepEmptyDirectories)
290 {
291 Wix.Component component = new Wix.Component();
292 component.KeyPath = Wix.YesNoType.yes;
293
294 if (this.SetUniqueIdentifiers)
295 {
296 component.Id = this.Core.GenerateIdentifier(ComponentPrefix, directory.Id);
297 }
298
299 Wix.CreateFolder createFolder = new Wix.CreateFolder();
300 component.AddChild(createFolder);
301
302 directory.AddChild(component);
303 }
304
305 return fileCount + files.Length;
306 }
307 }
308}