/// <param name="output">Output to generate image for.</param> /// <param name="fileTransfers">Array of files to be transfered.</param> /// <param name="layoutDirectory">The directory in which the image should be layed out.</param> /// <param name="compressed">Flag if source image should be compressed.</param> /// <returns>The uncompressed file rows.</returns> public void Execute() { RowDictionary <WixMediaRow> wixMediaRows = new RowDictionary <WixMediaRow>(this.WixMediaTable); this.lastCabinetAddedToMediaTable = new Dictionary <string, string>(); this.SetCabbingThreadCount(); // Send Binder object to Facilitate NewCabNamesCallBack Callback CabinetBuilder cabinetBuilder = new CabinetBuilder(this.CabbingThreadCount, Marshal.GetFunctionPointerForDelegate(this.newCabNamesCallBack)); // Supply Compile MediaTemplate Attributes to Cabinet Builder int MaximumCabinetSizeForLargeFileSplitting; int MaximumUncompressedMediaSize; this.GetMediaTemplateAttributes(out MaximumCabinetSizeForLargeFileSplitting, out MaximumUncompressedMediaSize); cabinetBuilder.MaximumCabinetSizeForLargeFileSplitting = MaximumCabinetSizeForLargeFileSplitting; cabinetBuilder.MaximumUncompressedMediaSize = MaximumUncompressedMediaSize; foreach (var entry in this.FileRowsByCabinet) { MediaRow mediaRow = entry.Key; IEnumerable <FileFacade> files = entry.Value; CompressionLevel compressionLevel = this.DefaultCompressionLevel; WixMediaRow wixMediaRow = null; string mediaLayoutFolder = null; if (wixMediaRows.TryGetValue(mediaRow.GetKey(), out wixMediaRow)) { mediaLayoutFolder = wixMediaRow.Layout; if (wixMediaRow.CompressionLevel.HasValue) { compressionLevel = wixMediaRow.CompressionLevel.Value; } } string cabinetDir = this.ResolveMedia(mediaRow, mediaLayoutFolder, this.LayoutDirectory); CabinetWorkItem cabinetWorkItem = this.CreateCabinetWorkItem(this.Output, cabinetDir, mediaRow, compressionLevel, files, this.fileTransfers); if (null != cabinetWorkItem) { cabinetBuilder.Enqueue(cabinetWorkItem); } } // stop processing if an error previously occurred if (Messaging.Instance.EncounteredError) { return; } // create queued cabinets with multiple threads cabinetBuilder.CreateQueuedCabinets(); if (Messaging.Instance.EncounteredError) { return; } }
public void WhenTryingToGetAValueAndTheKeyExistsShould() { //Arrange var key = 01; var expectedValue = "expectedValue"; var comparer = Comparer <int> .Default; var mockEqualityService = MockRepository.GenerateMock <IComparer <Cell <int, string> > >(); var mockEqualityServiceProvider = MockRepository.GenerateMock <IEqualityServiceProvider <int> >(); mockEqualityServiceProvider.Stub(x => x.GetKeyComparer(comparer)).Return(comparer); mockEqualityService .Stub(s => s.Compare( Arg <Cell <int, string> > .Matches(x => x.Key == key), Arg <Cell <int, string> > .Matches(x => x.Key == key))) .Return(0); var sut = new RowDictionary <int, string>(comparer, mockEqualityServiceProvider); sut.Add(key, expectedValue); string resultValue; //Act var resultBooleanValue = sut.TryGetValue(key, out resultValue); //Assert Assert.That(resultBooleanValue, Is.True); Assert.That(resultValue, Is.EqualTo(expectedValue)); }
public void WhenTryingToGetAValueAndTheKeyDoesNotExistShould() { //Arrange var key = "key"; var thisKeyDoesNotExist = "thisKeyDoesNotExist"; var expectedValue = "expectedValue"; var comparer = (IComparer <string>)StringComparer.InvariantCultureIgnoreCase; var mockEqualityService = MockRepository.GenerateMock <IComparer <Cell <string, string> > >(); var mockEqualityServiceProvider = MockRepository.GenerateMock <IEqualityServiceProvider <string> >(); mockEqualityServiceProvider.Stub(x => x.GetKeyComparer(comparer)).Return(comparer); mockEqualityService .Stub(s => s.Compare( Arg <Cell <string, string> > .Matches(x => x.Key == key), Arg <Cell <string, string> > .Matches(x => x.Key == thisKeyDoesNotExist))) .Return(-1); var sut = new RowDictionary <string, string>(comparer, mockEqualityServiceProvider); sut.Add(key, expectedValue); string resultValue; //Act var resultBooleanValue = sut.TryGetValue(thisKeyDoesNotExist, out resultValue); //Assert Assert.That(resultBooleanValue, Is.False); }
public void ShouldBeAbleToAddANewValueAndRetriveTheSameValueUsingTheSameKey() { //Arrange var key = "key"; var expectedValue = "Hola mundo"; var sut = new RowDictionary <string, string>(); sut.Add(key, expectedValue); string result; //Act sut.TryGetValue(key, out result); //Assert Assert.That(result, Is.EqualTo(expectedValue)); }
public void ShouldBeAbleToRetrieveTheValueUsingTheKeyWhenThereIsOnlyOneValueInserted() { //Arrange var key = 01; var expectedValue = "expectedValue"; var sut = new RowDictionary <int, string>(); sut.Add(key, expectedValue); string result; //Act sut.TryGetValue(key, out result); //Assert Assert.That(result, Is.EqualTo(expectedValue)); }
public void ShouldBeAbleToRetrieveTheValueUsingTheKeyWhenTheKeyIsNonPrimitive() { //Arrange var myKey = new { FirstName = "ABC", LastName = "DFG" }; const string whenTheKeyIsAnObject = "WhenTheKeyIsAnObject"; var sut = new RowDictionary <object, string>(); sut.Add(myKey, whenTheKeyIsAnObject); string result; //Act sut.TryGetValue(myKey, out result); //Assert Assert.That(result, Is.EqualTo(whenTheKeyIsAnObject)); }
public void Execute() { List <FileFacade> facades = new List <FileFacade>(this.FileTable.Rows.Count); RowDictionary <WixFileRow> wixFiles = new RowDictionary <WixFileRow>(this.WixFileTable); RowDictionary <WixDeltaPatchFileRow> deltaPatchFiles = new RowDictionary <WixDeltaPatchFileRow>(this.WixDeltaPatchFileTable); foreach (FileRow file in this.FileTable.Rows) { WixDeltaPatchFileRow deltaPatchFile = null; deltaPatchFiles.TryGetValue(file.File, out deltaPatchFile); facades.Add(new FileFacade(file, wixFiles[file.File], deltaPatchFile)); } if (null != this.WixDeltaPatchSymbolPathsTable) { this.ResolveDeltaPatchSymbolPaths(deltaPatchFiles, facades); } this.FileFacades = facades; }
/// <summary> /// Assign files to cabinets based on Media authoring. /// </summary> /// <param name="mediaTable"></param> /// <param name="mergeModuleMediaRow"></param> /// <param name="fileFacades"></param> private void ManuallyAssignFiles(Table mediaTable, MediaRow mergeModuleMediaRow, IEnumerable <FileFacade> fileFacades, Dictionary <MediaRow, List <FileFacade> > filesByCabinetMedia, RowDictionary <MediaRow> mediaRows, List <FileFacade> uncompressedFiles) { if (OutputType.Module != this.Output.Type) { if (null != mediaTable) { Dictionary <string, MediaRow> cabinetMediaRows = new Dictionary <string, MediaRow>(StringComparer.InvariantCultureIgnoreCase); foreach (MediaRow mediaRow in mediaTable.Rows) { // If the Media row has a cabinet, make sure it is unique across all Media rows. if (!String.IsNullOrEmpty(mediaRow.Cabinet)) { MediaRow existingRow; if (cabinetMediaRows.TryGetValue(mediaRow.Cabinet, out existingRow)) { Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName(mediaRow.SourceLineNumbers, mediaRow.Cabinet)); Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet)); } else { cabinetMediaRows.Add(mediaRow.Cabinet, mediaRow); } } mediaRows.Add(mediaRow); } } foreach (MediaRow mediaRow in mediaRows.Values) { if (null != mediaRow.Cabinet) { filesByCabinetMedia.Add(mediaRow, new List <FileFacade>()); } } } foreach (FileFacade facade in fileFacades) { if (OutputType.Module == this.Output.Type) { filesByCabinetMedia[mergeModuleMediaRow].Add(facade); } else { MediaRow mediaRow; if (!mediaRows.TryGetValue(facade.WixFile.DiskId.ToString(CultureInfo.InvariantCulture), out mediaRow)) { Messaging.Instance.OnMessage(WixErrors.MissingMedia(facade.File.SourceLineNumbers, facade.WixFile.DiskId)); continue; } // When building a product, if the current file is not to be compressed or if // the package set not to be compressed, don't cab it. if (OutputType.Product == this.Output.Type && (YesNoType.No == facade.File.Compressed || (YesNoType.NotSet == facade.File.Compressed && !this.FilesCompressed))) { uncompressedFiles.Add(facade); } else // file is marked compressed. { List <FileFacade> cabinetFiles; if (filesByCabinetMedia.TryGetValue(mediaRow, out cabinetFiles)) { cabinetFiles.Add(facade); } else { Messaging.Instance.OnMessage(WixErrors.ExpectedMediaCabinet(facade.File.SourceLineNumbers, facade.File.File, facade.WixFile.DiskId)); } } } } }
public void Execute() { List <FileTransfer> fileTransfers = new List <FileTransfer>(); Hashtable directories = new Hashtable(); RowDictionary <WixMediaRow> wixMediaRows = new RowDictionary <WixMediaRow>(this.WixMediaTable); using (Database db = new Database(this.DatabasePath, OpenDatabase.ReadOnly)) { using (View directoryView = db.OpenExecuteView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`")) { while (true) { using (Record directoryRecord = directoryView.Fetch()) { if (null == directoryRecord) { break; } string sourceName = Installer.GetName(directoryRecord.GetString(3), true, this.LongNamesInImage); directories.Add(directoryRecord.GetString(1), new ResolvedDirectory(directoryRecord.GetString(2), sourceName)); } } } using (View fileView = db.OpenView("SELECT `Directory_`, `FileName` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_` AND `File`.`File`=?")) { using (Record fileQueryRecord = new Record(1)) { // for each file in the array of uncompressed files foreach (FileFacade facade in this.FileFacades) { MediaRow mediaRow = this.MediaRows.Get(facade.WixFile.DiskId); string relativeFileLayoutPath = null; WixMediaRow wixMediaRow = null; string mediaLayoutFolder = null; if (wixMediaRows.TryGetValue(mediaRow.GetKey(), out wixMediaRow)) { mediaLayoutFolder = wixMediaRow.Layout; } string mediaLayoutDirectory = this.ResolveMedia(mediaRow, mediaLayoutFolder, this.LayoutDirectory); // setup up the query record and find the appropriate file in the // previously executed file view fileQueryRecord[1] = facade.File.File; fileView.Execute(fileQueryRecord); using (Record fileRecord = fileView.Fetch()) { if (null == fileRecord) { throw new WixException(WixErrors.FileIdentifierNotFound(facade.File.SourceLineNumbers, facade.File.File)); } relativeFileLayoutPath = Binder.GetFileSourcePath(directories, fileRecord[1], fileRecord[2], this.Compressed, this.LongNamesInImage); } // finally put together the base media layout path and the relative file layout path string fileLayoutPath = Path.Combine(mediaLayoutDirectory, relativeFileLayoutPath); FileTransfer transfer; if (FileTransfer.TryCreate(facade.WixFile.Source, fileLayoutPath, false, "File", facade.File.SourceLineNumbers, out transfer)) { fileTransfers.Add(transfer); } } } } } this.FileTransfers = fileTransfers; }
public void Execute() { var fileFacadesByDiskId = new Dictionary <int, Dictionary <string, FileFacade> >(); // Index patch file facades by diskId+fileId. foreach (var facade in this.FileFacades) { if (!fileFacadesByDiskId.TryGetValue(facade.DiskId, out var mediaFacades)) { mediaFacades = new Dictionary <string, FileFacade>(); fileFacadesByDiskId.Add(facade.DiskId, mediaFacades); } mediaFacades.Add(facade.Id, facade); } var patchMediaRows = new RowDictionary <MediaRow>(this.Output.Tables["Media"]); // Index paired transforms by name without the "#" prefix. var pairedTransforms = this.SubStorages.Where(s => s.Name.StartsWith("#")).ToDictionary(s => s.Name, s => s.Data); // Copy File bind data into substorages foreach (var substorage in this.SubStorages.Where(s => !s.Name.StartsWith("#"))) { var mainTransform = substorage.Data; var mainMsiFileHashIndex = new RowDictionary <Row>(mainTransform.Tables["MsiFileHash"]); var pairedTransform = pairedTransforms["#" + substorage.Name]; // Copy Media.LastSequence. var pairedMediaTable = pairedTransform.Tables["Media"]; foreach (MediaRow pairedMediaRow in pairedMediaTable.Rows) { var patchMediaRow = patchMediaRows.Get(pairedMediaRow.DiskId); pairedMediaRow.LastSequence = patchMediaRow.LastSequence; } // Validate file row changes for keypath-related issues this.ValidateFileRowChanges(mainTransform); // Index File table of pairedTransform var pairedFileRows = new RowDictionary <FileRow>(pairedTransform.Tables["File"]); var mainFileTable = mainTransform.Tables["File"]; if (null != mainFileTable) { // Remove the MsiFileHash table because it will be updated later with the final file hash for each file mainTransform.Tables.Remove("MsiFileHash"); foreach (FileRow mainFileRow in mainFileTable.Rows) { if (RowOperation.Delete == mainFileRow.Operation) { continue; } else if (RowOperation.None == mainFileRow.Operation) { continue; } // Index patch files by diskId+fileId if (!fileFacadesByDiskId.TryGetValue(mainFileRow.DiskId, out var mediaFacades)) { mediaFacades = new Dictionary <string, FileFacade>(); fileFacadesByDiskId.Add(mainFileRow.DiskId, mediaFacades); } // copy data from the patch back to the transform if (mediaFacades.TryGetValue(mainFileRow.File, out var facade)) { var patchFileRow = facade.GetFileRow(); var pairedFileRow = pairedFileRows.Get(mainFileRow.File); for (var i = 0; i < patchFileRow.Fields.Length; i++) { var patchValue = patchFileRow.FieldAsString(i) ?? String.Empty; var mainValue = mainFileRow.FieldAsString(i) ?? String.Empty; if (1 == i) { // File.Component_ changes should not come from the shared file rows // that contain the file information as each individual transform might // have different changes (or no changes at all). } else if (6 == i) // File.Attributes should not changed for binary deltas { #if TODO_PATCHING_DELTA if (null != patchFileRow.Patch) { // File.Attribute should not change for binary deltas pairedFileRow.Attributes = mainFileRow.Attributes; mainFileRow.Fields[i].Modified = false; } #endif } else if (7 == i) // File.Sequence is updated in pairedTransform, not mainTransform { // file sequence is updated in Patch table instead of File table for delta patches #if TODO_PATCHING_DELTA if (null != patchFileRow.Patch) { pairedFileRow.Fields[i].Modified = false; } else #endif { pairedFileRow[i] = patchFileRow[i]; pairedFileRow.Fields[i].Modified = true; } mainFileRow.Fields[i].Modified = false; } else if (patchValue != mainValue) { mainFileRow[i] = patchFileRow[i]; mainFileRow.Fields[i].Modified = true; if (mainFileRow.Operation == RowOperation.None) { mainFileRow.Operation = RowOperation.Modify; } } } // Copy MsiFileHash row for this File. if (!mainMsiFileHashIndex.TryGetValue(patchFileRow.File, out var patchHashRow)) { //patchHashRow = patchFileRow.Hash; throw new NotImplementedException(); } if (null != patchHashRow) { var mainHashTable = mainTransform.EnsureTable(this.TableDefinitions["MsiFileHash"]); var mainHashRow = mainHashTable.CreateRow(mainFileRow.SourceLineNumbers); for (var i = 0; i < patchHashRow.Fields.Length; i++) { mainHashRow[i] = patchHashRow[i]; if (i > 1) { // assume all hash fields have been modified mainHashRow.Fields[i].Modified = true; } } // assume the MsiFileHash operation follows the File one mainHashRow.Operation = mainFileRow.Operation; } // copy MsiAssemblyName rows for this File #if TODO_PATCHING List <Row> patchAssemblyNameRows = patchFileRow.AssemblyNames; if (null != patchAssemblyNameRows) { var mainAssemblyNameTable = mainTransform.EnsureTable(this.TableDefinitions["MsiAssemblyName"]); foreach (var patchAssemblyNameRow in patchAssemblyNameRows) { // Copy if there isn't an identical modified/added row already in the transform. var foundMatchingModifiedRow = false; foreach (var mainAssemblyNameRow in mainAssemblyNameTable.Rows) { if (RowOperation.None != mainAssemblyNameRow.Operation && mainAssemblyNameRow.GetPrimaryKey('/').Equals(patchAssemblyNameRow.GetPrimaryKey('/'))) { foundMatchingModifiedRow = true; break; } } if (!foundMatchingModifiedRow) { var mainAssemblyNameRow = mainAssemblyNameTable.CreateRow(mainFileRow.SourceLineNumbers); for (var i = 0; i < patchAssemblyNameRow.Fields.Length; i++) { mainAssemblyNameRow[i] = patchAssemblyNameRow[i]; } // assume value field has been modified mainAssemblyNameRow.Fields[2].Modified = true; mainAssemblyNameRow.Operation = mainFileRow.Operation; } } } #endif // Add patch header for this file #if TODO_PATCHING_DELTA if (null != patchFileRow.Patch) { // Add the PatchFiles action automatically to the AdminExecuteSequence and InstallExecuteSequence tables. this.AddPatchFilesActionToSequenceTable(SequenceTable.AdminExecuteSequence, mainTransform, pairedTransform, mainFileRow); this.AddPatchFilesActionToSequenceTable(SequenceTable.InstallExecuteSequence, mainTransform, pairedTransform, mainFileRow); // Add to Patch table var patchTable = pairedTransform.EnsureTable(this.TableDefinitions["Patch"]); if (0 == patchTable.Rows.Count) { patchTable.Operation = TableOperation.Add; } var patchRow = patchTable.CreateRow(mainFileRow.SourceLineNumbers); patchRow[0] = patchFileRow.File; patchRow[1] = patchFileRow.Sequence; var patchFile = new FileInfo(patchFileRow.Source); patchRow[2] = (int)patchFile.Length; patchRow[3] = 0 == (PatchAttributeType.AllowIgnoreOnError & patchFileRow.PatchAttributes) ? 0 : 1; var streamName = patchTable.Name + "." + patchRow[0] + "." + patchRow[1]; if (Msi.MsiInterop.MsiMaxStreamNameLength < streamName.Length) { streamName = "_" + Guid.NewGuid().ToString("D").ToUpperInvariant().Replace('-', '_'); var patchHeadersTable = pairedTransform.EnsureTable(this.TableDefinitions["MsiPatchHeaders"]); if (0 == patchHeadersTable.Rows.Count) { patchHeadersTable.Operation = TableOperation.Add; } var patchHeadersRow = patchHeadersTable.CreateRow(mainFileRow.SourceLineNumbers); patchHeadersRow[0] = streamName; patchHeadersRow[1] = patchFileRow.Patch; patchRow[5] = streamName; patchHeadersRow.Operation = RowOperation.Add; } else { patchRow[4] = patchFileRow.Patch; } patchRow.Operation = RowOperation.Add; } #endif } else { // TODO: throw because all transform rows should have made it into the patch } } } this.Output.Tables.Remove("Media"); this.Output.Tables.Remove("File"); this.Output.Tables.Remove("MsiFileHash"); this.Output.Tables.Remove("MsiAssemblyName"); } }