aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/Bind/ResolveFieldsCommand.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core/Bind/ResolveFieldsCommand.cs')
-rw-r--r--src/WixToolset.Core/Bind/ResolveFieldsCommand.cs215
1 files changed, 215 insertions, 0 deletions
diff --git a/src/WixToolset.Core/Bind/ResolveFieldsCommand.cs b/src/WixToolset.Core/Bind/ResolveFieldsCommand.cs
new file mode 100644
index 00000000..4caec9b4
--- /dev/null
+++ b/src/WixToolset.Core/Bind/ResolveFieldsCommand.cs
@@ -0,0 +1,215 @@
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.Bind
4{
5 using System.Collections.Generic;
6 using WixToolset.Data;
7 using WixToolset.Extensibility;
8
9 /// <summary>
10 /// Resolve source fields in the tables included in the output
11 /// </summary>
12 internal class ResolveFieldsCommand : ICommand
13 {
14 public TableIndexedCollection Tables { private get; set; }
15
16 public ExtractEmbeddedFiles FilesWithEmbeddedFiles { private get; set; }
17
18 public BinderFileManagerCore FileManagerCore { private get; set; }
19
20 public IEnumerable<IBinderFileManager> FileManagers { private get; set; }
21
22 public bool SupportDelayedResolution { private get; set; }
23
24 public string TempFilesLocation { private get; set; }
25
26 public WixVariableResolver WixVariableResolver { private get; set; }
27
28 public IEnumerable<DelayedField> DelayedFields { get; private set; }
29
30 public void Execute()
31 {
32 List<DelayedField> delayedFields = this.SupportDelayedResolution ? new List<DelayedField>() : null;
33
34 foreach (Table table in this.Tables)
35 {
36 foreach (Row row in table.Rows)
37 {
38 foreach (Field field in row.Fields)
39 {
40 bool isDefault = true;
41 bool delayedResolve = false;
42
43 // Check to make sure we're in a scenario where we can handle variable resolution.
44 if (null != delayedFields)
45 {
46 // resolve localization and wix variables
47 if (field.Data is string)
48 {
49 field.Data = this.WixVariableResolver.ResolveVariables(row.SourceLineNumbers, field.AsString(), false, ref isDefault, ref delayedResolve);
50 if (delayedResolve)
51 {
52 delayedFields.Add(new DelayedField(row, field));
53 }
54 }
55 }
56
57 // Move to next row if we've hit an error resolving variables.
58 if (Messaging.Instance.EncounteredError) // TODO: make this error handling more specific to just the failure to resolve variables in this field.
59 {
60 continue;
61 }
62
63 // Resolve file paths
64 if (ColumnType.Object == field.Column.Type)
65 {
66 ObjectField objectField = (ObjectField)field;
67
68 // Skip file resolution if the file is to be deleted.
69 if (RowOperation.Delete == row.Operation)
70 {
71 continue;
72 }
73
74 // File is embedded and path to it was not modified above.
75 if (objectField.EmbeddedFileIndex.HasValue && isDefault)
76 {
77 string extractPath = this.FilesWithEmbeddedFiles.AddEmbeddedFileIndex(objectField.BaseUri, objectField.EmbeddedFileIndex.Value, this.TempFilesLocation);
78
79 // Set the path to the embedded file once where it will be extracted.
80 objectField.Data = extractPath;
81 }
82 else if (null != objectField.Data) // non-compressed file (or localized value)
83 {
84 try
85 {
86 if (OutputType.Patch != this.FileManagerCore.Output.Type) // Normal binding for non-Patch scenario such as link (light.exe)
87 {
88 // keep a copy of the un-resolved data for future replay. This will be saved into wixpdb file
89 if (null == objectField.UnresolvedData)
90 {
91 objectField.UnresolvedData = (string)objectField.Data;
92 }
93
94 // resolve the path to the file
95 objectField.Data = this.ResolveFile((string)objectField.Data, table.Name, row.SourceLineNumbers, BindStage.Normal);
96 }
97 else if (!(this.FileManagerCore.RebaseTarget || this.FileManagerCore.RebaseUpdated)) // Normal binding for Patch Scenario (normal patch, no re-basing logic)
98 {
99 // resolve the path to the file
100 objectField.Data = this.ResolveFile((string)objectField.Data, table.Name, row.SourceLineNumbers, BindStage.Normal);
101 }
102 else // Re-base binding path scenario caused by pyro.exe -bt -bu
103 {
104 // by default, use the resolved Data for file lookup
105 string filePathToResolve = (string)objectField.Data;
106
107 // if -bu is used in pyro command, this condition holds true and the tool
108 // will use pre-resolved source for new wixpdb file
109 if (this.FileManagerCore.RebaseUpdated)
110 {
111 // try to use the unResolved Source if it exists.
112 // New version of wixpdb file keeps a copy of pre-resolved Source. i.e. !(bindpath.test)\foo.dll
113 // Old version of winpdb file does not contain this attribute and the value is null.
114 if (null != objectField.UnresolvedData)
115 {
116 filePathToResolve = objectField.UnresolvedData;
117 }
118 }
119
120 objectField.Data = this.ResolveFile(filePathToResolve, table.Name, row.SourceLineNumbers, BindStage.Updated);
121 }
122 }
123 catch (WixFileNotFoundException)
124 {
125 // display the error with source line information
126 Messaging.Instance.OnMessage(WixErrors.FileNotFound(row.SourceLineNumbers, (string)objectField.Data));
127 }
128 }
129
130 isDefault = true;
131 if (null != objectField.PreviousData)
132 {
133 objectField.PreviousData = this.WixVariableResolver.ResolveVariables(row.SourceLineNumbers, objectField.PreviousData, false, ref isDefault);
134 if (!Messaging.Instance.EncounteredError) // TODO: make this error handling more specific to just the failure to resolve variables in this field.
135 {
136 // file is compressed in a cabinet (and not modified above)
137 if (objectField.PreviousEmbeddedFileIndex.HasValue && isDefault)
138 {
139 // when loading transforms from disk, PreviousBaseUri may not have been set
140 if (null == objectField.PreviousBaseUri)
141 {
142 objectField.PreviousBaseUri = objectField.BaseUri;
143 }
144
145 string extractPath = this.FilesWithEmbeddedFiles.AddEmbeddedFileIndex(objectField.PreviousBaseUri, objectField.PreviousEmbeddedFileIndex.Value, this.TempFilesLocation);
146
147 // set the path to the file once its extracted from the cabinet
148 objectField.PreviousData = extractPath;
149 }
150 else if (null != objectField.PreviousData) // non-compressed file (or localized value)
151 {
152 try
153 {
154 if (!this.FileManagerCore.RebaseTarget && !this.FileManagerCore.RebaseUpdated)
155 {
156 // resolve the path to the file
157 objectField.PreviousData = this.ResolveFile((string)objectField.PreviousData, table.Name, row.SourceLineNumbers, BindStage.Normal);
158 }
159 else
160 {
161 if (this.FileManagerCore.RebaseTarget)
162 {
163 // if -bt is used, it come here
164 // Try to use the original unresolved source from either target build or update build
165 // If both target and updated are of old wixpdb, it behaves the same as today, no re-base logic here
166 // If target is old version and updated is new version, it uses unresolved path from updated build
167 // If both target and updated are of new versions, it uses unresolved path from target build
168 if (null != objectField.UnresolvedPreviousData || null != objectField.UnresolvedData)
169 {
170 objectField.PreviousData = objectField.UnresolvedPreviousData ?? objectField.UnresolvedData;
171 }
172 }
173
174 // resolve the path to the file
175 objectField.PreviousData = this.ResolveFile((string)objectField.PreviousData, table.Name, row.SourceLineNumbers, BindStage.Target);
176
177 }
178 }
179 catch (WixFileNotFoundException)
180 {
181 // display the error with source line information
182 Messaging.Instance.OnMessage(WixErrors.FileNotFound(row.SourceLineNumbers, (string)objectField.PreviousData));
183 }
184 }
185 }
186 }
187 }
188 }
189 }
190 }
191
192 this.DelayedFields = delayedFields;
193 }
194
195 private string ResolveFile(string source, string type, SourceLineNumber sourceLineNumbers, BindStage bindStage = BindStage.Normal)
196 {
197 string path = null;
198 foreach (IBinderFileManager fileManager in this.FileManagers)
199 {
200 path = fileManager.ResolveFile(source, type, sourceLineNumbers, bindStage);
201 if (null != path)
202 {
203 break;
204 }
205 }
206
207 if (null == path)
208 {
209 throw new WixFileNotFoundException(sourceLineNumbers, source, type);
210 }
211
212 return path;
213 }
214 }
215}