void applyDiffToFile(string deltaPath, string relativeFilePath, string workingDirectory)
        {
            var inputFile   = Path.Combine(deltaPath, relativeFilePath);
            var finalTarget = Path.Combine(workingDirectory, Regex.Replace(relativeFilePath, @".diff$", ""));

            var tempTargetFile = default(string);

            Utility.WithTempFile(out tempTargetFile, localAppDirectory);

            try {
                // NB: Zero-length diffs indicate the file hasn't actually changed
                if (new FileInfo(inputFile).Length == 0)
                {
                    this.Log().Info("{0} exists unchanged, skipping", relativeFilePath);
                    return;
                }

                if (relativeFilePath.EndsWith(".diff", StringComparison.InvariantCultureIgnoreCase))
                {
                    this.Log().Info("Applying Diff to {0}", relativeFilePath);
                    var msDelta = new MsDeltaCompression();
                    msDelta.ApplyDelta(inputFile, finalTarget, tempTargetFile);

                    verifyPatchedFile(relativeFilePath, inputFile, tempTargetFile);
                }
                else
                {
                    using (var of = File.OpenWrite(tempTargetFile))
                        using (var inf = File.OpenRead(inputFile)) {
                            this.Log().Info("Adding new file: {0}", relativeFilePath);
                            inf.CopyTo(of);
                        }
                }

                if (File.Exists(finalTarget))
                {
                    File.Delete(finalTarget);
                }

                var targetPath = Directory.GetParent(finalTarget);
                if (!targetPath.Exists)
                {
                    targetPath.Create();
                }

                File.Move(tempTargetFile, finalTarget);
            } finally {
                if (File.Exists(tempTargetFile))
                {
                    Utility.DeleteFileHarder(tempTargetFile, true);
                }
            }
        }
            void updateLink(ShellLink shortcut, string newAppPath)
            {
                this.Log().Info("Processing shortcut '{0}'", shortcut.ShortCutFile);

                var target = Environment.ExpandEnvironmentVariables(shortcut.Target);
                var targetIsUpdateDotExe = target.EndsWith("update.exe", StringComparison.OrdinalIgnoreCase);

                this.Log().Info("Old shortcut target: '{0}'", target);
                if (!targetIsUpdateDotExe)
                {
                    target = Path.Combine(newAppPath, Path.GetFileName(shortcut.Target));
                }
                this.Log().Info("New shortcut target: '{0}'", target);

                shortcut.WorkingDirectory = newAppPath;
                shortcut.Target           = target;

                // NB: If the executable was in a previous version but not in this
                // one, we should disappear this pin.
                if (!File.Exists(target))
                {
                    shortcut.Dispose();
                    this.ErrorIfThrows(() => Utility.DeleteFileHarder(target), "Failed to delete outdated pinned shortcut to: " + target);
                    return;
                }

                this.Log().Info("Old iconPath is: '{0}'", shortcut.IconPath);
                if (!File.Exists(shortcut.IconPath) || shortcut.IconPath.IndexOf("app-", StringComparison.OrdinalIgnoreCase) > 1)
                {
                    var iconPath = Path.Combine(newAppPath, Path.GetFileName(shortcut.IconPath));

                    if (!File.Exists(iconPath) && targetIsUpdateDotExe)
                    {
                        var executable = shortcut.Arguments.Replace("--processStart ", "");
                        iconPath = Path.Combine(newAppPath, executable);
                    }

                    this.Log().Info("Setting iconPath to: '{0}'", iconPath);
                    shortcut.IconPath = iconPath;

                    if (!File.Exists(iconPath))
                    {
                        this.Log().Warn("Tried to use {0} for icon path but didn't exist, falling back to EXE", iconPath);

                        shortcut.IconPath  = target;
                        shortcut.IconIndex = 0;
                    }
                }

                this.ErrorIfThrows(() => Utility.Retry(() => shortcut.Save(), 2), "Couldn't write shortcut " + shortcut.ShortCutFile);
                this.Log().Info("Finished shortcut successfully");
            }
            Task <string> installPackageToAppDir(UpdateInfo updateInfo, ReleaseEntry release)
            {
                return(Task.Run(async() => {
                    var zipper = new FastZip();
                    var target = getDirectoryForRelease(release.Version);

                    // NB: This might happen if we got killed partially through applying the release
                    if (target.Exists)
                    {
                        this.Log().Warn("Found partially applied release folder, killing it: " + target.FullName);
                        await Utility.DeleteDirectory(target.FullName);
                    }

                    target.Create();

                    this.Log().Info("Writing files to app directory: {0}", target.FullName);
                    zipper.ExtractZip(
                        Path.Combine(updateInfo.PackageDirectory, release.Filename),
                        target.FullName, FastZip.Overwrite.Always, (o) => true, null, @"lib", true);

                    // Move all of the files out of the lib/ dirs in the NuGet package
                    // into our target App directory.
                    //
                    // NB: We sort this list in order to guarantee that if a Net20
                    // and a Net40 version of a DLL get shipped, we always end up
                    // with the 4.0 version.
                    var libDir = target.GetDirectories().First(x => x.Name.Equals("lib", StringComparison.OrdinalIgnoreCase));
                    var toMove = libDir.GetDirectories().OrderBy(x => x.Name);

                    toMove.ForEach(ld => {
                        ld.GetDirectories()
                        .ForEachAsync(subdir => subdir.MoveTo(subdir.FullName.Replace(ld.FullName, target.FullName)))
                        .Wait();

                        ld.GetFiles()
                        .ForEachAsync(file => {
                            var tgt = Path.Combine(target.FullName, file.Name);
                            this.Log().Info("Moving file {0} to {1}", file.FullName, tgt);
                            if (File.Exists(tgt))
                            {
                                Utility.DeleteFileHarder(tgt, true);
                            }
                            file.MoveTo(tgt);
                        })
                        .Wait();
                    });

                    await Utility.DeleteDirectory(libDir.FullName);
                    return target.FullName;
                }));
            }
Пример #4
0
        public static List <ReleaseEntry> BuildReleasesFile(string releasePackagesDir)
        {
            var packagesDir = new DirectoryInfo(releasePackagesDir);

            // Generate release entries for all of the local packages
            var entriesQueue = new ConcurrentQueue <ReleaseEntry>();

            Parallel.ForEach(packagesDir.GetFiles("*.nupkg"), x =>
            {
                using (var file = x.OpenRead())
                {
                    entriesQueue.Enqueue(GenerateFromFile(file, x.Name));
                }
            });

            // Write the new RELEASES file to a temp file then move it into
            // place
            var entries  = entriesQueue.ToList();
            var tempFile = default(string);

            Utility.WithTempFile(out tempFile, releasePackagesDir);

            try
            {
                using (var of = File.OpenWrite(tempFile))
                {
                    if (entries.Count > 0)
                    {
                        WriteReleaseFile(entries, of);
                    }
                }

                var target = Path.Combine(packagesDir.FullName, "RELEASES");
                if (File.Exists(target))
                {
                    File.Delete(target);
                }

                File.Move(tempFile, target);
            }
            finally
            {
                if (File.Exists(tempFile))
                {
                    Utility.DeleteFileHarder(tempFile, true);
                }
            }

            return(entries);
        }
Пример #5
0
        public static List <ReleaseEntry> BuildReleasesFile(string releasePackagesDir)
        {
            DirectoryInfo info = new DirectoryInfo(releasePackagesDir);
            ConcurrentQueue <ReleaseEntry> entriesQueue = new ConcurrentQueue <ReleaseEntry>();

            Parallel.ForEach <FileInfo>(info.GetFiles("*.nupkg"), delegate(FileInfo x) {
                using (FileStream stream = x.OpenRead())
                {
                    entriesQueue.Enqueue(GenerateFromFile(stream, x.Name, null));
                }
            });
            List <ReleaseEntry> releaseEntries = entriesQueue.ToList <ReleaseEntry>();
            string path = null;

            Utility.WithTempFile(out path, releasePackagesDir);
            try
            {
                using (FileStream stream = File.OpenWrite(path))
                {
                    if (releaseEntries.Count > 0)
                    {
                        WriteReleaseFile(releaseEntries, stream);
                    }
                }
                string str2 = Path.Combine(info.FullName, "RELEASES");
                if (File.Exists(str2))
                {
                    File.Delete(str2);
                }
                File.Move(path, str2);
            }
            finally
            {
                if (File.Exists(path))
                {
                    Utility.DeleteFileHarder(path, true);
                }
            }
            return(releaseEntries);
        }
            void fixPinnedExecutables(SemanticVersion newCurrentVersion, bool removeAll = false)
            {
                if (Environment.OSVersion.Version < new Version(6, 1))
                {
                    this.Log().Warn("fixPinnedExecutables: Found OS Version '{0}', exiting...", Environment.OSVersion.VersionString);
                    return;
                }

                var newCurrentFolder = "app-" + newCurrentVersion;
                var newAppPath       = Path.Combine(rootAppDirectory, newCurrentFolder);

                var taskbarPath = Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                    "Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\TaskBar");

                if (!Directory.Exists(taskbarPath))
                {
                    this.Log().Info("fixPinnedExecutables: PinnedExecutables directory doesn't exitsts, skiping...");
                    return;
                }

                var resolveLink = new Func <FileInfo, ShellLink>(file => {
                    try {
                        this.Log().Info("Examining Pin: " + file);
                        return(new ShellLink(file.FullName));
                    } catch (Exception ex) {
                        var message = String.Format("File '{0}' could not be converted into a valid ShellLink", file.FullName);
                        this.Log().WarnException(message, ex);
                        return(null);
                    }
                });

                var shellLinks = (new DirectoryInfo(taskbarPath)).GetFiles("*.lnk").Select(resolveLink).ToArray();

                foreach (var shortcut in shellLinks)
                {
                    try {
                        if (shortcut == null)
                        {
                            continue;
                        }
                        if (String.IsNullOrWhiteSpace(shortcut.Target))
                        {
                            continue;
                        }
                        if (!shortcut.Target.StartsWith(rootAppDirectory, StringComparison.OrdinalIgnoreCase))
                        {
                            continue;
                        }

                        if (removeAll)
                        {
                            Utility.DeleteFileHarder(shortcut.ShortCutFile);
                        }
                        else
                        {
                            updateLink(shortcut, newAppPath);
                        }
                    } catch (Exception ex) {
                        var message = String.Format("fixPinnedExecutables: shortcut failed: {0}", shortcut.Target);
                        this.Log().ErrorException(message, ex);
                    }
                }
            }
Пример #7
0
        public ReleasePackage ApplyDeltaPackage(ReleasePackage basePackage, ReleasePackage deltaPackage, string outputFile, Action <int> progress = null)
        {
            Contract.Requires(deltaPackage != null);
            Contract.Requires(!String.IsNullOrEmpty(outputFile) && !File.Exists(outputFile));
            if (progress == null)
            {
                progress = i => { }
            }
            ;

            string workingPath;
            string deltaPath;

            using (Utility.WithTempDirectory(out deltaPath, localAppDirectory))
                using (Utility.WithTempDirectory(out workingPath, localAppDirectory)) {
                    var fz = new FastZip();
                    fz.ExtractZip(deltaPackage.InputPackageFile, deltaPath, null);
                    // The percentages here are somewhat arbitrary and reflect typical Bloom file sizes.
                    // Probably not appropriate to push upstream.
                    // If you are thinking about improving this using FastZip's Progress event, check with JohnT.
                    // I experimented with it and found that the PercentCompleted which it reports is useless,
                    // toggling between 0 and 100% repeatedly...possibly it applies to a particular file?
                    // I also found that it is VERY expensive to turn on progress reporting while unzipping;
                    // seems to slow the process down to the point of making it take two to three times as long.
                    // This may of course improve in a later version of the library.
                    progress(10);
                    fz.ExtractZip(basePackage.InputPackageFile, workingPath, null);
                    progress(35);

                    var pathsVisited = new List <string>();

                    var deltaPathRelativePaths = new DirectoryInfo(deltaPath).GetAllFilesRecursively()
                                                 .Select(x => x.FullName.Replace(deltaPath + Path.DirectorySeparatorChar, ""))
                                                 .ToArray();

                    // Apply all of the .diff files
                    deltaPathRelativePaths
                    .Where(x => x.StartsWith("lib", StringComparison.InvariantCultureIgnoreCase))
                    .Where(x => !x.EndsWith(".shasum", StringComparison.InvariantCultureIgnoreCase))
                    .Where(x => !x.EndsWith(".diff", StringComparison.InvariantCultureIgnoreCase) ||
                           !deltaPathRelativePaths.Contains(x.Replace(".diff", ".bsdiff")))
                    .ForEach(file => {
                        pathsVisited.Add(Regex.Replace(file, @"\.(bs)?diff$", "").ToLowerInvariant());
                        applyDiffToFile(deltaPath, file, workingPath);
                    });

                    // Delete all of the files that were in the old package but
                    // not in the new one.
                    new DirectoryInfo(workingPath).GetAllFilesRecursively()
                    .Select(x => x.FullName.Replace(workingPath + Path.DirectorySeparatorChar, "").ToLowerInvariant())
                    .Where(x => x.StartsWith("lib", StringComparison.InvariantCultureIgnoreCase) && !pathsVisited.Contains(x))
                    .ForEach(x => {
                        this.Log().Info("{0} was in old package but not in new one, deleting", x);
                        File.Delete(Path.Combine(workingPath, x));
                    });

                    // Update all the files that aren't in 'lib' with the delta
                    // package's versions (i.e. the nuspec file, etc etc).
                    deltaPathRelativePaths
                    .Where(x => !x.StartsWith("lib", StringComparison.InvariantCultureIgnoreCase))
                    .ForEach(x => {
                        this.Log().Info("Updating metadata file: {0}", x);
                        File.Copy(Path.Combine(deltaPath, x), Path.Combine(workingPath, x), true);
                    });
                    progress(50);

                    this.Log().Info("Repacking into full package: {0}", outputFile);
                    fz.CreateZip(outputFile, workingPath, true, null);
                    progress(100);
                }

            return(new ReleasePackage(outputFile));
        }

        void createDeltaForSingleFile(FileInfo targetFile, DirectoryInfo workingDirectory, Dictionary <string, string> baseFileListing)
        {
            // NB: There are three cases here that we'll handle:
            //
            // 1. Exists only in new => leave it alone, we'll use it directly.
            // 2. Exists in both old and new => write a dummy file so we know
            //    to keep it.
            // 3. Exists in old but changed in new => create a delta file
            //
            // The fourth case of "Exists only in old => delete it in new"
            // is handled when we apply the delta package
            var relativePath = targetFile.FullName.Replace(workingDirectory.FullName, "");

            if (!baseFileListing.ContainsKey(relativePath))
            {
                this.Log().Info("{0} not found in base package, marking as new", relativePath);
                return;
            }

            var oldData = File.ReadAllBytes(baseFileListing[relativePath]);
            var newData = File.ReadAllBytes(targetFile.FullName);

            if (bytesAreIdentical(oldData, newData))
            {
                this.Log().Info("{0} hasn't changed, writing dummy file", relativePath);

                File.Create(targetFile.FullName + ".diff").Dispose();
                File.Create(targetFile.FullName + ".shasum").Dispose();
                targetFile.Delete();
                return;
            }

            this.Log().Info("Delta patching {0} => {1}", baseFileListing[relativePath], targetFile.FullName);
            var msDelta = new MsDeltaCompression();

            try {
                msDelta.CreateDelta(baseFileListing[relativePath], targetFile.FullName, targetFile.FullName + ".diff");
            } catch (Win32Exception) {
                this.Log().Warn("We couldn't create a delta for {0}, attempting to create bsdiff", targetFile.Name);

                var of = default(FileStream);
                try {
                    of = File.Create(targetFile.FullName + ".bsdiff");
                    BinaryPatchUtility.Create(oldData, newData, of);

                    // NB: Create a dummy corrupt .diff file so that older
                    // versions which don't understand bsdiff will fail out
                    // until they get upgraded, instead of seeing the missing
                    // file and just removing it.
                    File.WriteAllText(targetFile.FullName + ".diff", "1");
                } catch (Exception ex) {
                    this.Log().WarnException(String.Format("We really couldn't create a delta for {0}", targetFile.Name), ex);
                    return;
                } finally {
                    if (of != null)
                    {
                        of.Dispose();
                    }
                }
            }

            var rl = ReleaseEntry.GenerateFromFile(new MemoryStream(newData), targetFile.Name + ".shasum");

            File.WriteAllText(targetFile.FullName + ".shasum", rl.EntryAsString, Encoding.UTF8);
            targetFile.Delete();
        }

        void applyDiffToFile(string deltaPath, string relativeFilePath, string workingDirectory)
        {
            var inputFile   = Path.Combine(deltaPath, relativeFilePath);
            var finalTarget = Path.Combine(workingDirectory, Regex.Replace(relativeFilePath, @"\.(bs)?diff$", ""));

            var tempTargetFile = default(string);

            Utility.WithTempFile(out tempTargetFile, localAppDirectory);

            try {
                // NB: Zero-length diffs indicate the file hasn't actually changed
                if (new FileInfo(inputFile).Length == 0)
                {
                    this.Log().Info("{0} exists unchanged, skipping", relativeFilePath);
                    return;
                }

                if (relativeFilePath.EndsWith(".bsdiff", StringComparison.InvariantCultureIgnoreCase))
                {
                    using (var of = File.OpenWrite(tempTargetFile))
                        using (var inf = File.OpenRead(finalTarget)) {
                            this.Log().Info("Applying BSDiff to {0}", relativeFilePath);
                            BinaryPatchUtility.Apply(inf, () => File.OpenRead(inputFile), of);
                        }

                    verifyPatchedFile(relativeFilePath, inputFile, tempTargetFile);
                }
                else if (relativeFilePath.EndsWith(".diff", StringComparison.InvariantCultureIgnoreCase))
                {
                    this.Log().Info("Applying MSDiff to {0}", relativeFilePath);
                    var msDelta = new MsDeltaCompression();
                    msDelta.ApplyDelta(inputFile, finalTarget, tempTargetFile);

                    verifyPatchedFile(relativeFilePath, inputFile, tempTargetFile);
                }
                else
                {
                    using (var of = File.OpenWrite(tempTargetFile))
                        using (var inf = File.OpenRead(inputFile)) {
                            this.Log().Info("Adding new file: {0}", relativeFilePath);
                            inf.CopyTo(of);
                        }
                }

                if (File.Exists(finalTarget))
                {
                    File.Delete(finalTarget);
                }

                var targetPath = Directory.GetParent(finalTarget);
                if (!targetPath.Exists)
                {
                    targetPath.Create();
                }

                File.Move(tempTargetFile, finalTarget);
            } finally {
                if (File.Exists(tempTargetFile))
                {
                    Utility.DeleteFileHarder(tempTargetFile, true);
                }
            }
        }

        void verifyPatchedFile(string relativeFilePath, string inputFile, string tempTargetFile)
        {
            var shaFile = Regex.Replace(inputFile, @"\.(bs)?diff$", ".shasum");
            var expectedReleaseEntry = ReleaseEntry.ParseReleaseEntry(File.ReadAllText(shaFile, Encoding.UTF8));
            var actualReleaseEntry   = ReleaseEntry.GenerateFromFile(tempTargetFile);

            if (expectedReleaseEntry.Filesize != actualReleaseEntry.Filesize)
            {
                this.Log().Warn("Patched file {0} has incorrect size, expected {1}, got {2}", relativeFilePath,
                                expectedReleaseEntry.Filesize, actualReleaseEntry.Filesize);
                throw new ChecksumFailedException()
                      {
                          Filename = relativeFilePath
                      };
            }

            if (expectedReleaseEntry.SHA1 != actualReleaseEntry.SHA1)
            {
                this.Log().Warn("Patched file {0} has incorrect SHA1, expected {1}, got {2}", relativeFilePath,
                                expectedReleaseEntry.SHA1, actualReleaseEntry.SHA1);
                throw new ChecksumFailedException()
                      {
                          Filename = relativeFilePath
                      };
            }
        }

        bool bytesAreIdentical(byte[] oldData, byte[] newData)
        {
            if (oldData == null || newData == null)
            {
                return(oldData == newData);
            }
            if (oldData.LongLength != newData.LongLength)
            {
                return(false);
            }

            for (long i = 0; i < newData.LongLength; i++)
            {
                if (oldData[i] != newData[i])
                {
                    return(false);
                }
            }

            return(true);
        }
    }
        void createDeltaForSingleFile(FileInfo targetFile, DirectoryInfo workingDirectory, Dictionary <string, string> baseFileListing)
        {
            // NB: There are three cases here that we'll handle:
            //
            // 1. Exists only in new => leave it alone, we'll use it directly.
            // 2. Exists in both old and new => write a dummy file so we know
            //    to keep it.
            // 3. Exists in old but changed in new => create a delta file
            //
            // The fourth case of "Exists only in old => delete it in new"
            // is handled when we apply the delta package
            var relativePath = targetFile.FullName.Replace(workingDirectory.FullName, "");

            if (!baseFileListing.ContainsKey(relativePath))
            {
                this.Log().Info("{0} not found in base package, marking as new", relativePath);
                return;
            }

            var oldData = File.ReadAllBytes(baseFileListing[relativePath]);
            var newData = File.ReadAllBytes(targetFile.FullName);

            if (bytesAreIdentical(oldData, newData))
            {
                this.Log().Info("{0} hasn't changed, writing dummy file", relativePath);

                File.Create(targetFile.FullName + ".diff").Dispose();
                File.Create(targetFile.FullName + ".shasum").Dispose();
                targetFile.Delete();
                return;
            }

            this.Log().Info("Delta patching {0} => {1}", baseFileListing[relativePath], targetFile.FullName);
            var msDelta = new MsDeltaCompression();

            if (targetFile.Extension.Equals(".exe", StringComparison.OrdinalIgnoreCase) ||
                targetFile.Extension.Equals(".dll", StringComparison.OrdinalIgnoreCase) ||
                targetFile.Extension.Equals(".node", StringComparison.OrdinalIgnoreCase))
            {
                try
                {
                    msDelta.CreateDelta(baseFileListing[relativePath], targetFile.FullName, targetFile.FullName + ".diff");
                    goto exit;
                }
                catch (Exception)
                {
                    this.Log().Warn("We couldn't create a delta for {0}, attempting to create bsdiff", targetFile.Name);
                }
            }

            try
            {
                using (FileStream of = File.Create(targetFile.FullName + ".bsdiff"))
                {
                    BinaryPatchUtility.Create(oldData, newData, of);

                    // NB: Create a dummy corrupt .diff file so that older
                    // versions which don't understand bsdiff will fail out
                    // until they get upgraded, instead of seeing the missing
                    // file and just removing it.
                    File.WriteAllText(targetFile.FullName + ".diff", "1");
                }
            }
            catch (Exception ex)
            {
                this.Log().WarnException(String.Format("We really couldn't create a delta for {0}", targetFile.Name), ex);

                Utility.DeleteFileHarder(targetFile.FullName + ".bsdiff", true);
                Utility.DeleteFileHarder(targetFile.FullName + ".diff", true);
                return;
            }

exit:

            var rl = ReleaseEntry.GenerateFromFile(new MemoryStream(newData), targetFile.Name + ".shasum");

            File.WriteAllText(targetFile.FullName + ".shasum", rl.EntryAsString, Encoding.UTF8);
            targetFile.Delete();
        }
Пример #9
0
            Task <string> installPackageToAppDir(UpdateInfo updateInfo, ReleaseEntry release, Action <int> progress)
            {
                return(Task.Run(async() =>
                {
                    var target = getDirectoryForRelease(release.Version);

                    // NB: This might happen if we got killed partially through applying the release
                    if (target.Exists)
                    {
                        this.Log().Warn("Found partially applied release folder, killing it: " + target.FullName);
                        await Utility.DeleteDirectory(target.FullName);
                    }

                    target.Create();

                    var totalSize = GetTotalUncompressedSize(updateInfo, release);
                    var currentExtractedSize = 0L;
                    using (var stream = File.OpenRead(Path.Combine(updateInfo.PackageDirectory, release.Filename)))
                    {
                        // progress.Report(new InstallerStep("Extracting"));

                        var zipIn = new ZipInputStream(stream);
                        var zipEntry = zipIn.GetNextEntry();

                        while (zipEntry != null)
                        {
                            var entryName = zipEntry.Name;
                            var pathParts = entryName.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);

                            var foundLib = false;
                            foreach (var part in pathParts)
                            {
                                if (part.Equals("lib", StringComparison.InvariantCulture))
                                {
                                    foundLib = true;
                                }
                            }

                            if (!foundLib)
                            {
                                zipEntry = zipIn.GetNextEntry();
                                continue;
                            }

                            var buffer = new byte[4096];
                            var fullZipToPath = Path.Combine(target.FullName, entryName.Replace('/', Path.DirectorySeparatorChar));
                            var directoryName = zipEntry.IsFile ? Path.GetDirectoryName(fullZipToPath) : fullZipToPath;
                            if (!string.IsNullOrEmpty(directoryName))
                            {
                                Directory.CreateDirectory(directoryName);
                            }

                            using (var streamWriter = File.Create(fullZipToPath))
                            {
                                currentExtractedSize += zipEntry.Size;
                                StreamUtils.Copy(zipIn, streamWriter, buffer);
                                progress((int)((double)currentExtractedSize * 100.0 / (double)totalSize));
                            }

                            zipEntry = zipIn.GetNextEntry();
                        }
                    }

                    this.Log().Info("Writing files to app directory: {0}", target.FullName);

                    // Move all of the files out of the lib/ dirs in the NuGet package
                    // into our target App directory.
                    //
                    // NB: We sort this list in order to guarantee that if a Net20
                    // and a Net40 version of a DLL get shipped, we always end up
                    // with the 4.0 version.
                    var libDir = target.GetDirectories().First(x => x.Name.Equals("lib", StringComparison.OrdinalIgnoreCase));
                    var toMove = libDir.GetDirectories().OrderBy(x => x.Name);

                    toMove.ForEach(ld => {
                        ld.GetDirectories()
                        .ForEachAsync(subdir => subdir.MoveTo(subdir.FullName.Replace(ld.FullName, target.FullName)))
                        .Wait();

                        ld.GetFiles()
                        .ForEachAsync(file => {
                            var tgt = Path.Combine(target.FullName, file.Name);
                            this.Log().Info("Moving file {0} to {1}", file.FullName, tgt);
                            if (File.Exists(tgt))
                            {
                                Utility.DeleteFileHarder(tgt, true);
                            }
                            file.MoveTo(tgt);
                        })
                        .Wait();
                    });

                    await Utility.DeleteDirectory(libDir.FullName);
                    return target.FullName;
                }));
            }
Пример #10
0
        private void applyDiffToFile(string deltaPath, string relativeFilePath, string workingDirectory)
        {
            string inputFile = Path.Combine(deltaPath, relativeFilePath);
            string path      = Path.Combine(workingDirectory, Regex.Replace(relativeFilePath, @"\.(bs)?diff$", ""));
            string str2      = null;

            Utility.WithTempFile(out str2, this.localAppDirectory);
            try
            {
                if (new FileInfo(inputFile).Length == 0)
                {
                    this.Log <DeltaPackageBuilder>().Info <string>("{0} exists unchanged, skipping", relativeFilePath);
                }
                else
                {
                    if (relativeFilePath.EndsWith(".bsdiff", StringComparison.InvariantCultureIgnoreCase))
                    {
                        using (FileStream stream = File.OpenWrite(str2))
                        {
                            using (FileStream stream2 = File.OpenRead(path))
                            {
                                this.Log <DeltaPackageBuilder>().Info <string>("Applying BSDiff to {0}", relativeFilePath);
                                BinaryPatchUtility.Apply(stream2, () => File.OpenRead(inputFile), stream);
                            }
                        }
                        this.verifyPatchedFile(relativeFilePath, inputFile, str2);
                    }
                    else if (relativeFilePath.EndsWith(".diff", StringComparison.InvariantCultureIgnoreCase))
                    {
                        this.Log <DeltaPackageBuilder>().Info <string>("Applying MSDiff to {0}", relativeFilePath);
                        new MsDeltaCompression().ApplyDelta(inputFile, path, str2);
                        this.verifyPatchedFile(relativeFilePath, inputFile, str2);
                    }
                    else
                    {
                        using (FileStream stream3 = File.OpenWrite(str2))
                        {
                            using (FileStream stream4 = File.OpenRead(inputFile))
                            {
                                this.Log <DeltaPackageBuilder>().Info <string>("Adding new file: {0}", relativeFilePath);
                                stream4.CopyTo(stream3);
                            }
                        }
                    }
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                    DirectoryInfo parent = Directory.GetParent(path);
                    if (!parent.Exists)
                    {
                        parent.Create();
                    }
                    File.Move(str2, path);
                }
            }
            finally
            {
                if (File.Exists(str2))
                {
                    Utility.DeleteFileHarder(str2, true);
                }
            }
        }