private ResolvedCabinet ResolveCabinet(string cabinetPath, IEnumerable <FileFacade> fileFacades)
        {
            ResolvedCabinet resolved = null;

            List <BindFileWithPath> filesWithPath = fileFacades.Select(f => new BindFileWithPath()
            {
                Id = f.File.File, Path = f.WixFile.Source
            }).ToList();

            foreach (IBinderFileManager fileManager in this.FileManagers)
            {
                resolved = fileManager.ResolveCabinet(cabinetPath, filesWithPath);
                if (null != resolved)
                {
                    break;
                }
            }

            return(resolved);
        }
        /// <summary>
        /// Creates a work item to create a cabinet.
        /// </summary>
        /// <param name="output">Output for the current database.</param>
        /// <param name="cabinetDir">Directory to create cabinet in.</param>
        /// <param name="mediaRow">MediaRow containing information about the cabinet.</param>
        /// <param name="fileFacades">Collection of files in this cabinet.</param>
        /// <param name="fileTransfers">Array of files to be transfered.</param>
        /// <returns>created CabinetWorkItem object</returns>
        private CabinetWorkItem CreateCabinetWorkItem(Output output, string cabinetDir, MediaRow mediaRow, CompressionLevel compressionLevel, IEnumerable <FileFacade> fileFacades, List <FileTransfer> fileTransfers)
        {
            CabinetWorkItem cabinetWorkItem  = null;
            string          tempCabinetFileX = Path.Combine(this.TempFilesLocation, mediaRow.Cabinet);

            // check for an empty cabinet
            if (!fileFacades.Any())
            {
                string cabinetName = mediaRow.Cabinet;

                // remove the leading '#' from the embedded cabinet name to make the warning easier to understand
                if (cabinetName.StartsWith("#", StringComparison.Ordinal))
                {
                    cabinetName = cabinetName.Substring(1);
                }

                // If building a patch, remind them to run -p for torch.
                if (OutputType.Patch == output.Type)
                {
                    Messaging.Instance.OnMessage(WixWarnings.EmptyCabinet(mediaRow.SourceLineNumbers, cabinetName, true));
                }
                else
                {
                    Messaging.Instance.OnMessage(WixWarnings.EmptyCabinet(mediaRow.SourceLineNumbers, cabinetName));
                }
            }

            ResolvedCabinet resolvedCabinet = this.ResolveCabinet(tempCabinetFileX, fileFacades);

            // create a cabinet work item if it's not being skipped
            if (CabinetBuildOption.BuildAndCopy == resolvedCabinet.BuildOption || CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption)
            {
                int maxThreshold = 0; // default to the threshold for best smartcabbing (makes smallest cabinet).

                cabinetWorkItem = new CabinetWorkItem(fileFacades, resolvedCabinet.Path, maxThreshold, compressionLevel /*, this.FileManager*/);
            }
            else // reuse the cabinet from the cabinet cache.
            {
                Messaging.Instance.OnMessage(WixVerboses.ReusingCabCache(mediaRow.SourceLineNumbers, mediaRow.Cabinet, resolvedCabinet.Path));

                try
                {
                    // Ensure the cached cabinet timestamp is current to prevent perpetual incremental builds. The
                    // problematic scenario goes like this. Imagine two cabinets in the cache. Update a file that
                    // goes into one of the cabinets. One cabinet will get rebuilt, the other will be copied from
                    // the cache. Now the file (an input) has a newer timestamp than the reused cabient (an output)
                    // causing the project to look like it perpetually needs a rebuild until all of the reused
                    // cabinets get newer timestamps.
                    File.SetLastWriteTime(resolvedCabinet.Path, DateTime.Now);
                }
                catch (Exception e)
                {
                    Messaging.Instance.OnMessage(WixWarnings.CannotUpdateCabCache(mediaRow.SourceLineNumbers, resolvedCabinet.Path, e.Message));
                }
            }

            if (mediaRow.Cabinet.StartsWith("#", StringComparison.Ordinal))
            {
                Table streamsTable = output.EnsureTable(this.TableDefinitions["_Streams"]);

                Row streamRow = streamsTable.CreateRow(mediaRow.SourceLineNumbers);
                streamRow[0] = mediaRow.Cabinet.Substring(1);
                streamRow[1] = resolvedCabinet.Path;
            }
            else
            {
                string       destinationPath = Path.Combine(cabinetDir, mediaRow.Cabinet);
                FileTransfer transfer;
                if (FileTransfer.TryCreate(resolvedCabinet.Path, destinationPath, CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption, "Cabinet", mediaRow.SourceLineNumbers, out transfer))
                {
                    transfer.Built = true;
                    fileTransfers.Add(transfer);
                }
            }

            return(cabinetWorkItem);
        }
Beispiel #3
0
        public ResolvedCabinet ResolveCabinet(string cabinetPath, IEnumerable <FileFacade> fileFacades)
        {
            var filesWithPath = fileFacades.Select(f => new BindFileWithPath()
            {
                Id = f.File.File, Path = f.WixFile.Source.Path
            }).ToList();

            ResolvedCabinet resolved = null;

            foreach (var extension in this.BackendExtensions)
            {
                resolved = extension.ResolveCabinet(cabinetPath, filesWithPath);

                if (null != resolved)
                {
                    return(resolved);
                }
            }

            // By default cabinet should be built and moved to the suggested location.
            resolved = new ResolvedCabinet()
            {
                BuildOption = CabinetBuildOption.BuildAndMove, Path = cabinetPath
            };

            // If a cabinet cache path was provided, change the location for the cabinet
            // to be built to and check if there is a cabinet that can be reused.
            if (!String.IsNullOrEmpty(this.CabCachePath))
            {
                string cabinetName = Path.GetFileName(cabinetPath);
                resolved.Path = Path.Combine(this.CabCachePath, cabinetName);

                if (CheckFileExists(resolved.Path))
                {
                    // Assume that none of the following are true:
                    // 1. any files are added or removed
                    // 2. order of files changed or names changed
                    // 3. modified time changed
                    bool cabinetValid = true;

                    var cabinet = new Cabinet(resolved.Path);
                    List <CabinetFileInfo> fileList = cabinet.Enumerate();

                    if (filesWithPath.Count() != fileList.Count)
                    {
                        cabinetValid = false;
                    }
                    else
                    {
                        int i = 0;
                        foreach (BindFileWithPath file in filesWithPath)
                        {
                            // First check that the file identifiers match because that is quick and easy.
                            CabinetFileInfo cabFileInfo = fileList[i];
                            cabinetValid = (cabFileInfo.FileId == file.Id);
                            if (cabinetValid)
                            {
                                // Still valid so ensure the file sizes are the same.
                                FileInfo fileInfo = new FileInfo(file.Path);
                                cabinetValid = (cabFileInfo.Size == fileInfo.Length);
                                if (cabinetValid)
                                {
                                    // Still valid so ensure the source time stamp hasn't changed.
                                    cabinetValid = cabFileInfo.SameAsDateTime(fileInfo.LastWriteTime);
                                }
                            }

                            if (!cabinetValid)
                            {
                                break;
                            }

                            i++;
                        }
                    }

                    resolved.BuildOption = cabinetValid ? CabinetBuildOption.Copy : CabinetBuildOption.BuildAndCopy;
                }
            }

            return(resolved);
        }
Beispiel #4
0
        public virtual ResolvedCabinet ResolveCabinet(string cabinetPath, IEnumerable <BindFileWithPath> filesWithPath)
        {
            if (null == filesWithPath)
            {
                throw new ArgumentNullException("fileRows");
            }

            // By default cabinet should be built and moved to the suggested location.
            ResolvedCabinet resolved = new ResolvedCabinet()
            {
                BuildOption = CabinetBuildOption.BuildAndMove, Path = cabinetPath
            };

            // If a cabinet cache path was provided, change the location for the cabinet
            // to be built to and check if there is a cabinet that can be reused.
            if (!String.IsNullOrEmpty(this.Core.CabCachePath))
            {
                string cabinetName = Path.GetFileName(cabinetPath);
                resolved.Path = Path.Combine(this.Core.CabCachePath, cabinetName);

                if (BinderFileManager.CheckFileExists(resolved.Path))
                {
                    // Assume that none of the following are true:
                    // 1. any files are added or removed
                    // 2. order of files changed or names changed
                    // 3. modified time changed
                    bool cabinetValid = true;

                    // Need to force garbage collection of WixEnumerateCab to ensure the handle
                    // associated with it is closed before it is reused.
                    using (Cab.WixEnumerateCab wixEnumerateCab = new Cab.WixEnumerateCab())
                    {
                        List <CabinetFileInfo> fileList = wixEnumerateCab.Enumerate(resolved.Path);

                        if (filesWithPath.Count() != fileList.Count)
                        {
                            cabinetValid = false;
                        }
                        else
                        {
                            int i = 0;
                            foreach (BindFileWithPath file in filesWithPath)
                            {
                                // First check that the file identifiers match because that is quick and easy.
                                CabinetFileInfo cabFileInfo = fileList[i];
                                cabinetValid = (cabFileInfo.FileId == file.Id);
                                if (cabinetValid)
                                {
                                    // Still valid so ensure the file sizes are the same.
                                    FileInfo fileInfo = new FileInfo(file.Path);
                                    cabinetValid = (cabFileInfo.Size == fileInfo.Length);
                                    if (cabinetValid)
                                    {
                                        // Still valid so ensure the source time stamp hasn't changed. Thus we need
                                        // to convert the source file time stamp into a cabinet compatible data/time.
                                        ushort sourceCabDate;
                                        ushort sourceCabTime;

                                        WixToolset.Core.Native.CabInterop.DateTimeToCabDateAndTime(fileInfo.LastWriteTime, out sourceCabDate, out sourceCabTime);
                                        cabinetValid = (cabFileInfo.Date == sourceCabDate && cabFileInfo.Time == sourceCabTime);
                                    }
                                }

                                if (!cabinetValid)
                                {
                                    break;
                                }

                                i++;
                            }
                        }
                    }

                    resolved.BuildOption = cabinetValid ? CabinetBuildOption.Copy : CabinetBuildOption.BuildAndCopy;
                }
            }

            return(resolved);
        }
        public virtual ResolvedCabinet ResolveCabinet(string cabinetPath, FileRowCollection fileRows)
        {
            if (fileRows == null)
            {
                throw new ArgumentNullException("fileRows");
            }

            // By default cabinet should be built and moved to the suggested location.
            ResolvedCabinet resolved = new ResolvedCabinet()
            {
                BuildOption = CabinetBuildOption.BuildAndMove, Path = cabinetPath
            };

            // No special behavior specified, use the default.
            if (null == this.Core.CabCachePath && !this.Core.ReuseCabinets)
            {
                return(resolved);
            }

            // If a cabinet cache path was provided, change the location for the cabinet
            // to be built to.
            if (null != this.Core.CabCachePath)
            {
                string cabinetName = Path.GetFileName(cabinetPath);
                resolved.Path = Path.Combine(this.Core.CabCachePath, cabinetName);
            }

            // If we still think we're going to reuse the cabinet check to see if the cabinet exists first.
            if (this.Core.ReuseCabinets)
            {
                bool cabinetValid = false;

                if (BinderFileManager.CheckFileExists(resolved.Path))
                {
                    // check to see if
                    // 1. any files are added or removed
                    // 2. order of files changed or names changed
                    // 3. modified time changed
                    cabinetValid = true;

                    // Need to force garbage collection of WixEnumerateCab to ensure the handle
                    // associated with it is closed before it is reused.
                    using (Cab.WixEnumerateCab wixEnumerateCab = new Cab.WixEnumerateCab())
                    {
                        ArrayList fileList = wixEnumerateCab.Enumerate(resolved.Path);

                        if (fileRows.Count != fileList.Count)
                        {
                            cabinetValid = false;
                        }
                        else
                        {
                            int i = 0;
                            foreach (FileRow fileRow in fileRows)
                            {
                                // First check that the file identifiers match because that is quick and easy.
                                CabinetFileInfo cabFileInfo = fileList[i] as CabinetFileInfo;
                                cabinetValid = (cabFileInfo.FileId == fileRow.File);
                                if (cabinetValid)
                                {
                                    // Still valid so ensure the source time stamp hasn't changed. Thus we need
                                    // to convert the source file time stamp into a cabinet compatible data/time.
                                    DateTime sourceFileTime = File.GetLastWriteTime(fileRow.Source);
                                    ushort   sourceCabDate;
                                    ushort   sourceCabTime;

                                    Cab.Interop.CabInterop.DateTimeToCabDateAndTime(sourceFileTime, out sourceCabDate, out sourceCabTime);
                                    cabinetValid = (cabFileInfo.Date == sourceCabDate && cabFileInfo.Time == sourceCabTime);
                                }

                                if (!cabinetValid)
                                {
                                    break;
                                }

                                i++;
                            }
                        }
                    }
                }

                resolved.BuildOption = cabinetValid ? CabinetBuildOption.Copy : CabinetBuildOption.BuildAndCopy;
            }

            return(resolved);
        }