diff options
Diffstat (limited to 'src/WixToolset.Core/Bind/ResolveFieldsCommand.cs')
-rw-r--r-- | src/WixToolset.Core/Bind/ResolveFieldsCommand.cs | 215 |
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 | |||
3 | namespace 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 | } | ||