예제 #1
0
        static int Main(string[] args)
        {
            var optParams = parseOptions(args);
            if (optParams == null) {
                return -1;
            }

            var targetDir = optParams["target"];
            var package = new ReleasePackage(optParams["input"]);
            var targetFile = Path.Combine(targetDir, package.SuggestedReleaseFileName);

            package.CreateReleasePackage(targetFile, optParams["pkgdir"] != "" ? optParams["pkgdir"] : null);

            var releaseFile = Path.Combine(targetDir, "RELEASES");
            if (File.Exists(releaseFile)) {
                var releaseEntries = ReleaseEntry.ParseReleaseFile(File.ReadAllText(releaseFile, Encoding.UTF8));

                var latestFullRelease = releaseEntries
                    .Where(x => x.IsDelta == false)
                    .MaxBy(x => x.Version)
                    .Select(x => new ReleasePackage(Path.Combine(targetDir, x.Filename), true))
                    .FirstOrDefault();

                var deltaFile = Path.Combine(targetDir, package.SuggestedReleaseFileName.Replace("full", "delta"));
                Console.WriteLine("{0} {1}", latestFullRelease.InputPackageFile, deltaFile);
                package.CreateDeltaPackage(latestFullRelease, deltaFile);
            }

            ReleaseEntry.BuildReleasesFile(targetDir);

            return 0;
        }
예제 #2
0
        public void ApplyDeltaPackageSmokeTest()
        {
            var basePackage = new ReleasePackage(IntegrationTestHelper.GetPath("fixtures", "Shimmer.Core.1.0.0.0-full.nupkg"));
            var deltaPackage = new ReleasePackage(IntegrationTestHelper.GetPath("fixtures", "Shimmer.Core.1.1.0.0-delta.nupkg"));
            var expectedPackageFile = IntegrationTestHelper.GetPath("fixtures", "Shimmer.Core.1.1.0.0-full.nupkg");
            var outFile = Path.GetTempFileName() + ".nupkg";

            try {
                basePackage.ApplyDeltaPackage(deltaPackage, outFile);
                var result = new ZipPackage(outFile);
                var expected = new ZipPackage(expectedPackageFile);

                result.Id.ShouldEqual(expected.Id);
                result.Version.ShouldEqual(expected.Version);

                this.Log().Info("Expected file list:");
                expected.GetFiles().Select(x => x.Path).OrderBy(x => x).ForEach(x => this.Log().Info(x));

                this.Log().Info("Actual file list:");
                result.GetFiles().Select(x => x.Path).OrderBy(x => x).ForEach(x => this.Log().Info(x));

                Enumerable.Zip(
                    expected.GetFiles().Select(x => x.Path).OrderBy(x => x),
                    result.GetFiles().Select(x => x.Path).OrderBy(x => x),
                    (e, a) => e == a
                ).All(x => x).ShouldBeTrue();
            } finally {
                if (File.Exists(outFile)) {
                    File.Delete(outFile);
                }
            }
        }
예제 #3
0
파일: Program.cs 프로젝트: ralberts/Shimmer
        static int Main(string[] args)
        {
            #if DEBUG
            Debugger.Launch();
            #endif

            var optParams = ParseCommands.ParseOptions(args);
            if (optParams == null) {
                return -1;
            }

            var targetDir = optParams["target"];
            var package = new ReleasePackage(optParams["input"]);
            var targetFile = Path.Combine(targetDir, package.SuggestedReleaseFileName);

            string fullRelease;
            try {
                fullRelease = package.CreateReleasePackage(targetFile,
                    optParams["pkgdir"] != "" ? optParams["pkgdir"] : null,
                    input => (new Markdown()).Transform(input));
            }
            catch (Exception ex) {
                Console.Error.WriteLine();
                Console.Error.WriteLine("Unexpected exception occurred creating package:");
                Console.Error.WriteLine(ex);
                Console.Error.WriteLine();
                Console.Error.WriteLine();
                return -4;
            }

            Console.WriteLine("{0};", fullRelease);

            var releaseFile = Path.Combine(targetDir, "RELEASES");
            if (File.Exists(releaseFile)) {
                var releasesText = File.ReadAllText(releaseFile, Encoding.UTF8);
                var releaseEntries = ReleaseEntry.ParseReleaseFile(releasesText);

                var previousFullRelease = ReleaseEntry.GetPreviousRelease(releaseEntries, package, targetDir);

                if (previousFullRelease != null
                    && File.Exists(previousFullRelease.ReleasePackageFile)) {
                    var deltaFile = Path.Combine(targetDir, package.SuggestedReleaseFileName.Replace("full", "delta"));
                    Console.WriteLine("{0}; {1}", previousFullRelease.InputPackageFile, deltaFile);

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

                    var deltaBuilder = new DeltaPackageBuilder();
                    deltaBuilder.CreateDeltaPackage(previousFullRelease, package, deltaFile);
                }
            }

            ReleaseEntry.BuildReleasesFile(targetDir);

            return 0;
        }
예제 #4
0
        public ReleasePackage ApplyDeltaPackage(ReleasePackage deltaPackage, string outputFile)
        {
            Contract.Requires(deltaPackage != null);
            Contract.Requires(!String.IsNullOrEmpty(outputFile) && !File.Exists(outputFile));

            string workingPath;
            string deltaPath;

            using (Utility.WithTempDirectory(out deltaPath))
            using (Utility.WithTempDirectory(out workingPath))
            using (var deltaZip = new ZipFile(deltaPackage.InputPackageFile))
            using (var baseZip = new ZipFile(InputPackageFile)) {
                deltaZip.ExtractAll(deltaPath);
                baseZip.ExtractAll(workingPath);

                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))
                    .ForEach(file => {
                        pathsVisited.Add(Regex.Replace(file, @".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);
                    });

                using (var zf = new ZipFile(outputFile)) {
                    zf.AddDirectory(workingPath);
                    zf.Save();
                }
            }

            return new ReleasePackage(outputFile);
        }
예제 #5
0
        public ReleasePackage ApplyDeltaPackage(ReleasePackage basePackage, ReleasePackage deltaPackage, string outputFile)
        {
            Contract.Requires(deltaPackage != null);
            Contract.Requires(!String.IsNullOrEmpty(outputFile) && !File.Exists(outputFile));

            string workingPath;
            string deltaPath;

            using (Utility.WithTempDirectory(out deltaPath))
                using (Utility.WithTempDirectory(out workingPath))
                    using (var deltaZip = new ZipFile(deltaPackage.InputPackageFile))
                        using (var baseZip = new ZipFile(basePackage.InputPackageFile)) {
                            deltaZip.ExtractAll(deltaPath);
                            baseZip.ExtractAll(workingPath);

                            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))
                            .ForEach(file => {
                                pathsVisited.Add(Regex.Replace(file, @".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);
                            });

                            using (var zf = new ZipFile(outputFile)) {
                                zf.AddDirectory(workingPath);
                                zf.Save();
                            }
                        }

            return(new ReleasePackage(outputFile));
        }
예제 #6
0
 public void CanLoadPackageWhichHasNoDependencies()
 {
     var inputPackage = IntegrationTestHelper.GetPath("fixtures", "Shimmer.Core.NoDependencies.1.0.0.0.nupkg");
     var outputPackage = Path.GetTempFileName() + ".nupkg";
     var fixture = new ReleasePackage(inputPackage);
     var sourceDir = IntegrationTestHelper.GetPath("..", "packages");
     try {
         fixture.CreateReleasePackage(outputPackage, sourceDir);
     }
     finally {
         File.Delete(outputPackage);
     }
 }
예제 #7
0
        public ReleasePackage CreateDeltaPackage(ReleasePackage basePackage, ReleasePackage newPackage, string outputFile)
        {
            Contract.Requires(basePackage != null && basePackage.ReleasePackageFile != null);
            Contract.Requires(!String.IsNullOrEmpty(outputFile) && !File.Exists(outputFile));

            string baseTempPath = null;
            string tempPath     = null;

            using (Utility.WithTempDirectory(out baseTempPath))
                using (Utility.WithTempDirectory(out tempPath)) {
                    var baseTempInfo = new DirectoryInfo(baseTempPath);
                    var tempInfo     = new DirectoryInfo(tempPath);

                    using (var zf = new ZipFile(basePackage.ReleasePackageFile)) {
                        zf.ExtractAll(baseTempInfo.FullName);
                    }

                    using (var zf = new ZipFile(newPackage.ReleasePackageFile)) {
                        zf.ExtractAll(tempInfo.FullName);
                    }

                    // Collect a list of relative paths under 'lib' and map them
                    // to their full name. We'll use this later to determine in
                    // the new version of the package whether the file exists or
                    // not.
                    var baseLibFiles = baseTempInfo.GetAllFilesRecursively()
                                       .Where(x => x.FullName.ToLowerInvariant().Contains("lib" + Path.DirectorySeparatorChar))
                                       .ToDictionary(k => k.FullName.Replace(baseTempInfo.FullName, ""), v => v.FullName);

                    var newLibDir = tempInfo.GetDirectories().First(x => x.Name.ToLowerInvariant() == "lib");

                    newLibDir.GetAllFilesRecursively()
                    .ForEach(libFile => createDeltaForSingleFile(libFile, tempInfo, baseLibFiles));

                    ReleasePackage.addDeltaFilesToContentTypes(tempInfo.FullName);

                    using (var zf = new ZipFile(outputFile)) {
                        zf.AddDirectory(tempInfo.FullName);
                        zf.Save();
                    }
                }

            return(new ReleasePackage(outputFile));
        }
예제 #8
0
        public void CanResolveMultipleLevelsOfDependencies()
        {
            var inputPackage = IntegrationTestHelper.GetPath("fixtures", "SampleUpdatingApp.1.0.0.0.nupkg");
            var outputPackage = Path.GetTempFileName() + ".nupkg";
            var sourceDir = IntegrationTestHelper.GetPath("..", "packages");

            var fixture = new ReleasePackage(inputPackage);
            (new DirectoryInfo(sourceDir)).Exists.ShouldBeTrue();

            try {
                fixture.CreateReleasePackage(outputPackage, sourceDir);

                this.Log().Info("Resulting package is at {0}", outputPackage);
                var pkg = new ZipPackage(outputPackage);

                int refs = pkg.FrameworkAssemblies.Count();
                this.Log().Info("Found {0} refs", refs);
                refs.ShouldEqual(0);

                this.Log().Info("Files in release package:");
                pkg.GetFiles().ForEach(x => this.Log().Info(x.Path));

                var filesToLookFor = new[] {
                    "System.Reactive.Core.dll",
                    "ReactiveUI.dll",
                    "MarkdownSharp.dll",
                    "SampleUpdatingApp.exe",
                };

                filesToLookFor.ForEach(name => {
                    this.Log().Info("Looking for {0}", name);
                    pkg.GetFiles().Any(y => y.Path.ToLowerInvariant().Contains(name.ToLowerInvariant())).ShouldBeTrue();
                });
            } finally {
                File.Delete(outputPackage);
            }
        }
예제 #9
0
        public void ReleasePackageIntegrationTest()
        {
            var inputPackage = IntegrationTestHelper.GetPath("fixtures", "Shimmer.Core.1.0.0.0.nupkg");
            var outputPackage = Path.GetTempFileName() + ".nupkg";
            var sourceDir = IntegrationTestHelper.GetPath("..", "packages");

            var fixture = new ReleasePackage(inputPackage);
            (new DirectoryInfo(sourceDir)).Exists.ShouldBeTrue();

            try {
                fixture.CreateReleasePackage(outputPackage, sourceDir);

                this.Log().Info("Resulting package is at {0}", outputPackage);
                var pkg = new ZipPackage(outputPackage);

                int refs = pkg.References.Count();
                this.Log().Info("Found {0} refs", refs);
                refs.ShouldEqual(0);

                this.Log().Info("Files in release package:");
                pkg.GetFiles().ForEach(x => this.Log().Info(x.Path));

                pkg.GetFiles().Any(x => x.Path.ToLowerInvariant().Contains(@"lib\sl")).ShouldBeFalse();
                pkg.GetFiles().Any(x => x.Path.ToLowerInvariant().Contains(@".xml")).ShouldBeFalse();
            } finally {
                File.Delete(outputPackage);
            }
        }
예제 #10
0
        IObservable<ReleaseEntry> createFullPackagesFromDeltas(IEnumerable<ReleaseEntry> releasesToApply, ReleaseEntry currentVersion)
        {
            Contract.Requires(releasesToApply != null);

            // If there are no deltas in our list, we're already done
            if (!releasesToApply.Any() || releasesToApply.All(x => !x.IsDelta)) {
                return Observable.Return(releasesToApply.MaxBy(x => x.Version).First());
            }

            if (!releasesToApply.All(x => x.IsDelta)) {
                return Observable.Throw<ReleaseEntry>(new Exception("Cannot apply combinations of delta and full packages"));
            }

            // Smash together our base full package and the nearest delta
            var ret = Observable.Start(() => {
                var basePkg = new ReleasePackage(Path.Combine(rootAppDirectory, "packages", currentVersion.Filename));
                var deltaPkg = new ReleasePackage(Path.Combine(rootAppDirectory, "packages", releasesToApply.First().Filename));

                var deltaBuilder = new DeltaPackageBuilder();

                return deltaBuilder.ApplyDeltaPackage(basePkg, deltaPkg,
                    Regex.Replace(deltaPkg.InputPackageFile, @"-delta.nupkg$", ".nupkg", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant));
            }, RxApp.TaskpoolScheduler);

            if (releasesToApply.Count() == 1) {
                return ret.Select(x => ReleaseEntry.GenerateFromFile(x.InputPackageFile));
            }

            return ret.SelectMany(x => {
                var fi = fileSystem.GetFileInfo(x.InputPackageFile);
                var entry = ReleaseEntry.GenerateFromFile(fi.OpenRead(), x.InputPackageFile);

                // Recursively combine the rest of them
                return createFullPackagesFromDeltas(releasesToApply.Skip(1), entry);
            });
        }
예제 #11
0
        public ReleasePackage CreateDeltaPackage(ReleasePackage basePackage, ReleasePackage newPackage, string outputFile)
        {
            Contract.Requires(basePackage != null);
            Contract.Requires(!String.IsNullOrEmpty(outputFile) && !File.Exists(outputFile));

            if (basePackage.Version > newPackage.Version)
            {
                var message = String.Format(
                    "You cannot create a delta package based on version {0} as it is a later version than {1}",
                    basePackage.Version,
                    newPackage.Version);
                throw new InvalidOperationException(message);
            }

            if (basePackage.ReleasePackageFile == null)
            {
                throw new ArgumentException("The base package's release file is null", "basePackage");
            }

            if (!File.Exists(basePackage.ReleasePackageFile))
            {
                throw new FileNotFoundException("The base package release does not exist", basePackage.ReleasePackageFile);
            }

            if (!File.Exists(newPackage.ReleasePackageFile))
            {
                throw new FileNotFoundException("The new package release does not exist", newPackage.ReleasePackageFile);
            }

            string baseTempPath = null;
            string tempPath     = null;

            using (Utility.WithTempDirectory(out baseTempPath))
                using (Utility.WithTempDirectory(out tempPath)) {
                    var baseTempInfo = new DirectoryInfo(baseTempPath);
                    var tempInfo     = new DirectoryInfo(tempPath);

                    using (var zf = new ZipFile(basePackage.ReleasePackageFile)) {
                        zf.ExtractAll(baseTempInfo.FullName);
                    }

                    using (var zf = new ZipFile(newPackage.ReleasePackageFile)) {
                        zf.ExtractAll(tempInfo.FullName);
                    }

                    // Collect a list of relative paths under 'lib' and map them
                    // to their full name. We'll use this later to determine in
                    // the new version of the package whether the file exists or
                    // not.
                    var baseLibFiles = baseTempInfo.GetAllFilesRecursively()
                                       .Where(x => x.FullName.ToLowerInvariant().Contains("lib" + Path.DirectorySeparatorChar))
                                       .ToDictionary(k => k.FullName.Replace(baseTempInfo.FullName, ""), v => v.FullName);

                    var newLibDir = tempInfo.GetDirectories().First(x => x.Name.ToLowerInvariant() == "lib");

                    newLibDir.GetAllFilesRecursively()
                    .ForEach(libFile => createDeltaForSingleFile(libFile, tempInfo, baseLibFiles));

                    ReleasePackage.addDeltaFilesToContentTypes(tempInfo.FullName);

                    using (var zf = new ZipFile(outputFile)) {
                        zf.AddDirectory(tempInfo.FullName);
                        zf.Save();
                    }
                }

            return(new ReleasePackage(outputFile));
        }
예제 #12
0
        public void CreateDeltaPackageIntegrationTest()
        {
            var basePackage = IntegrationTestHelper.GetPath("fixtures", "Shimmer.Core.1.0.0.0.nupkg");
            var newPackage = IntegrationTestHelper.GetPath("fixtures", "Shimmer.Core.1.1.0.0.nupkg");

            var sourceDir = IntegrationTestHelper.GetPath("..", "packages");
            (new DirectoryInfo(sourceDir)).Exists.ShouldBeTrue();

            var baseFixture = new ReleasePackage(basePackage);
            var fixture = new ReleasePackage(newPackage);

            var tempFiles = Enumerable.Range(0, 3)
                .Select(_ => Path.GetTempPath() + Guid.NewGuid().ToString() + ".nupkg")
                .ToArray();

            try {
                baseFixture.CreateReleasePackage(tempFiles[0], sourceDir);
                fixture.CreateReleasePackage(tempFiles[1], sourceDir);

                (new FileInfo(baseFixture.ReleasePackageFile)).Exists.ShouldBeTrue();
                (new FileInfo(fixture.ReleasePackageFile)).Exists.ShouldBeTrue();

                fixture.CreateDeltaPackage(baseFixture, tempFiles[2]);

                var fullPkg = new ZipPackage(tempFiles[1]);
                var deltaPkg = new ZipPackage(tempFiles[2]);

                fullPkg.Id.ShouldEqual(deltaPkg.Id);
                fullPkg.Version.CompareTo(deltaPkg.Version).ShouldEqual(0);

                deltaPkg.GetFiles().Count().ShouldBeGreaterThan(0);

                this.Log().Info("Files in delta package:");
                deltaPkg.GetFiles().ForEach(x => this.Log().Info(x.Path));

                // v1.1 adds a dependency on DotNetZip
                deltaPkg.GetFiles()
                    .Any(x => x.Path.ToLowerInvariant().Contains("ionic.zip"))
                    .ShouldBeTrue();

                // All the other files should be diffs and shasums
                deltaPkg.GetFiles().Any(x => !x.Path.ToLowerInvariant().Contains("ionic.zip")).ShouldBeTrue();
                deltaPkg.GetFiles()
                    .Where(x => !x.Path.ToLowerInvariant().Contains("ionic.zip"))
                    .All(x => x.Path.ToLowerInvariant().EndsWith("diff") || x.Path.ToLowerInvariant().EndsWith("shasum"))
                    .ShouldBeTrue();

                // Every .diff file should have a shasum file
                deltaPkg.GetFiles().Any(x => x.Path.ToLowerInvariant().EndsWith(".diff")).ShouldBeTrue();
                deltaPkg.GetFiles()
                    .Where(x => x.Path.ToLowerInvariant().EndsWith(".diff"))
                    .ForEach(x => {
                        var lookingFor = x.Path.Replace(".diff", ".shasum");
                        this.Log().Info("Looking for corresponding shasum file: {0}", lookingFor);
                        deltaPkg.GetFiles().Any(y => y.Path == lookingFor).ShouldBeTrue();
                    });

                // Delta packages should be smaller than the original!
                var fileInfos = tempFiles.Select(x => new FileInfo(x)).ToArray();
                this.Log().Info("Base Size: {0}, Current Size: {1}, Delta Size: {2}",
                    fileInfos[0].Length, fileInfos[1].Length, fileInfos[2].Length);

                (fileInfos[2].Length - fileInfos[1].Length).ShouldBeLessThan(0);
            } finally {
                tempFiles.ForEach(File.Delete);
            }
        }
예제 #13
0
        public ReleasePackage CreateDeltaPackage(ReleasePackage baseFixture, string outputFile)
        {
            Contract.Requires(baseFixture != null && baseFixture.ReleasePackageFile != null);
            Contract.Requires(!String.IsNullOrEmpty(outputFile) && !File.Exists(outputFile));

            string baseTempPath = null;
            string tempPath = null;

            using (Utility.WithTempDirectory(out baseTempPath))
            using (Utility.WithTempDirectory(out tempPath)) {
                var baseTempInfo = new DirectoryInfo(baseTempPath);
                var tempInfo = new DirectoryInfo(tempPath);

                using (var zf = new ZipFile(baseFixture.ReleasePackageFile)) {
                    zf.ExtractAll(baseTempInfo.FullName);
                }

                using (var zf = new ZipFile(ReleasePackageFile)) {
                    zf.ExtractAll(tempInfo.FullName);
                }

                // Collect a list of relative paths under 'lib' and map them
                // to their full name. We'll use this later to determine in
                // the new version of the package whether the file exists or
                // not.
                var baseLibFiles = baseTempInfo.GetAllFilesRecursively()
                    .Where(x => x.FullName.ToLowerInvariant().Contains("lib" + Path.DirectorySeparatorChar))
                    .ToDictionary(k => k.FullName.Replace(baseTempInfo.FullName, ""), v => v.FullName);

                var newLibDir = tempInfo.GetDirectories().First(x => x.Name.ToLowerInvariant() == "lib");

                // 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
                newLibDir.GetAllFilesRecursively().ForEach(libFile => {
                    var relativePath = libFile.FullName.Replace(tempInfo.FullName, "");

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

                    var oldData = File.ReadAllBytes(baseLibFiles[relativePath]);
                    var newData = File.ReadAllBytes(libFile.FullName);

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

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

                    this.Log().Info("Delta patching {0} => {1}", baseLibFiles[relativePath], libFile.FullName);
                    using (var of = File.Create(libFile.FullName + ".diff")) {
                        BinaryPatchUtility.Create(oldData, newData, of);

                        var rl = ReleaseEntry.GenerateFromFile(new MemoryStream(newData), libFile.Name + ".shasum");
                        File.WriteAllText(libFile.FullName + ".shasum", rl.EntryAsString, Encoding.UTF8);
                        libFile.Delete();
                    }
                });

                addDeltaFilesToContentTypes(tempInfo.FullName);

                using (var zf = new ZipFile(outputFile)) {
                    zf.AddDirectory(tempInfo.FullName);
                    zf.Save();
                }
            }

            return new ReleasePackage(outputFile);
        }
예제 #14
0
        public void ContentFilesAreIncludedInCreatedPackage()
        {
            var inputPackage = IntegrationTestHelper.GetPath("fixtures", "ProjectWithContent.1.0.0.0-beta.nupkg");
            var outputPackage = Path.GetTempFileName() + ".nupkg";
            var sourceDir = IntegrationTestHelper.GetPath("..", "packages");

            var fixture = new ReleasePackage(inputPackage);
            (new DirectoryInfo(sourceDir)).Exists.ShouldBeTrue();

            try
            {
                fixture.CreateReleasePackage(outputPackage, sourceDir);

                this.Log().Info("Resulting package is at {0}", outputPackage);
                var pkg = new ZipPackage(outputPackage);

                int refs = pkg.FrameworkAssemblies.Count();
                this.Log().Info("Found {0} refs", refs);
                refs.ShouldEqual(0);

                this.Log().Info("Files in release package:");

                var contentFiles = pkg.GetContentFiles();
                Assert.Equal(2, contentFiles.Count());

                var contentFilePaths = contentFiles.Select(f => f.EffectivePath);

                Assert.Contains("some-words.txt", contentFilePaths);
                Assert.Contains("dir\\item-in-subdirectory.txt", contentFilePaths);

                Assert.Equal(1, pkg.GetLibFiles().Count());
            }
            finally
            {
                File.Delete(outputPackage);
            }
        }
예제 #15
0
        public void DependentPackageNotFoundAndThrowsError()
        {
            string packagesDir;
            // use empty packages folder
            using (Utility.WithTempDirectory(out packagesDir)) {
                var inputPackage = IntegrationTestHelper.GetPath("fixtures", "ProjectDependsOnJsonDotNet.1.0.nupkg");

                var outputPackage = Path.GetTempFileName() + ".nupkg";

                try {
                    var package = new ReleasePackage(inputPackage);
                    Assert.Throws<Exception>(() =>
                        package.CreateReleasePackage(outputPackage, packagesDir));
                } finally {
                    File.Delete(outputPackage);
                }
            }
        }
예제 #16
0
        public void UsesTheRightVersionOfADependencyWhenMultipleAreInPackages()
        {
            var outputPackage = Path.GetTempFileName() + ".nupkg";
            string outputFile = null;

            var inputPackage = IntegrationTestHelper.GetPath("fixtures", "CaliburnMicroDemo.1.0.0.nupkg");

            var wrongPackage = "Caliburn.Micro.1.4.1.nupkg";
            var wrongPackagePath = IntegrationTestHelper.GetPath("fixtures", wrongPackage);
            var rightPackage = "Caliburn.Micro.1.5.2.nupkg";
            var rightPackagePath = IntegrationTestHelper.GetPath("fixtures", rightPackage);

            try {
                var sourceDir = IntegrationTestHelper.GetPath("..", "packages");
                (new DirectoryInfo(sourceDir)).Exists.ShouldBeTrue();

                File.Copy(wrongPackagePath, Path.Combine(sourceDir, wrongPackage), true);
                File.Copy(rightPackagePath, Path.Combine(sourceDir, rightPackage), true);

                var package = new ReleasePackage(inputPackage);
                var outputFileName = package.CreateReleasePackage(outputPackage, sourceDir);

                var zipPackage = new ZipPackage(outputFileName);

                var fileName = "Caliburn.Micro.dll";
                var dependency = zipPackage.GetLibFiles()
                    .Where(f => f.Path.EndsWith(fileName))
                    .Single(f => f.TargetFramework
                        == new FrameworkName(".NETFramework,Version=v4.0"));

                outputFile = new FileInfo(Path.Combine(sourceDir, fileName)).FullName;

                using (var of = File.Create(outputFile))
                {
                    dependency.GetStream().CopyTo(of);
                }

                var assemblyName = AssemblyName.GetAssemblyName(outputFile);
                Assert.Equal(1, assemblyName.Version.Major);
                Assert.Equal(5, assemblyName.Version.Minor);
            }
            finally {
                File.Delete(outputPackage);
                File.Delete(outputFile);
            }
        }
예제 #17
0
        public void ReleasePackageIntegrationTest()
        {
            var inputPackage = IntegrationTestHelper.GetPath("fixtures", "Shimmer.Core.1.0.0.0.nupkg");
            var outputPackage = Path.GetTempFileName() + ".nupkg";
            var sourceDir = IntegrationTestHelper.GetPath("..", "packages");

            var fixture = new ReleasePackage(inputPackage);
            (new DirectoryInfo(sourceDir)).Exists.ShouldBeTrue();

            try {
                fixture.CreateReleasePackage(outputPackage, sourceDir);

                this.Log().Info("Resulting package is at {0}", outputPackage);
                var pkg = new ZipPackage(outputPackage);

                int refs = pkg.FrameworkAssemblies.Count();
                this.Log().Info("Found {0} refs", refs);
                refs.ShouldEqual(0);

                this.Log().Info("Files in release package:");

                List<IPackageFile> files = pkg.GetFiles().ToList();
                files.ForEach(x => this.Log().Info(x.Path));

                List<string> nonDesktopPaths = new[] {"sl", "winrt", "netcore", "win8", "windows8", "MonoAndroid", "MonoTouch", "MonoMac", "wp", }
                    .Select(x => @"lib\" + x)
                    .ToList();

                files.Any(x => nonDesktopPaths.Any(y => x.Path.ToLowerInvariant().Contains(y.ToLowerInvariant()))).ShouldBeFalse();
                files.Any(x => x.Path.ToLowerInvariant().Contains(@".xml")).ShouldBeFalse();
            } finally {
                File.Delete(outputPackage);
            }
        }
예제 #18
0
        public ReleasePackage CreateDeltaPackage(ReleasePackage basePackage, ReleasePackage newPackage, string outputFile)
        {
            Contract.Requires(basePackage != null);
            Contract.Requires(!String.IsNullOrEmpty(outputFile) && !File.Exists(outputFile));

            if (basePackage.Version > newPackage.Version) {
                var message = String.Format(
                    "You cannot create a delta package based on version {0} as it is a later version than {1}",
                    basePackage.Version,
                    newPackage.Version);
                throw new InvalidOperationException(message);
            }

            if (basePackage.ReleasePackageFile == null) {
                throw new ArgumentException("The base package's release file is null", "basePackage");
            }

            if (!File.Exists(basePackage.ReleasePackageFile)) {
                throw new FileNotFoundException("The base package release does not exist", basePackage.ReleasePackageFile);
            }

            if (!File.Exists(newPackage.ReleasePackageFile)) {
                throw new FileNotFoundException("The new package release does not exist", newPackage.ReleasePackageFile);
            }

            string baseTempPath = null;
            string tempPath = null;

            using (Utility.WithTempDirectory(out baseTempPath))
            using (Utility.WithTempDirectory(out tempPath)) {
                var baseTempInfo = new DirectoryInfo(baseTempPath);
                var tempInfo = new DirectoryInfo(tempPath);

                using (var zf = new ZipFile(basePackage.ReleasePackageFile)) {
                    zf.ExtractAll(baseTempInfo.FullName);
                }

                using (var zf = new ZipFile(newPackage.ReleasePackageFile)) {
                    zf.ExtractAll(tempInfo.FullName);
                }

                // Collect a list of relative paths under 'lib' and map them
                // to their full name. We'll use this later to determine in
                // the new version of the package whether the file exists or
                // not.
                var baseLibFiles = baseTempInfo.GetAllFilesRecursively()
                    .Where(x => x.FullName.ToLowerInvariant().Contains("lib" + Path.DirectorySeparatorChar))
                    .ToDictionary(k => k.FullName.Replace(baseTempInfo.FullName, ""), v => v.FullName);

                var newLibDir = tempInfo.GetDirectories().First(x => x.Name.ToLowerInvariant() == "lib");

                newLibDir.GetAllFilesRecursively()
                    .ForEach(libFile => createDeltaForSingleFile(libFile, tempInfo, baseLibFiles));

                ReleasePackage.addDeltaFilesToContentTypes(tempInfo.FullName);

                using (var zf = new ZipFile(outputFile)) {
                    zf.AddDirectory(tempInfo.FullName);
                    zf.Save();
                }
            }

            return new ReleasePackage(outputFile);
        }
예제 #19
0
        public void DependentPackageFoundAndIncludedInReleasePackage()
        {
            var packagesDir = IntegrationTestHelper.GetPath("..", "packages");
            var inputPackage = IntegrationTestHelper.GetPath("fixtures", "ProjectDependsOnJsonDotNet.1.0.nupkg");

            var outputPackage = Path.GetTempFileName() + ".nupkg";

            try {
                var package = new ReleasePackage(inputPackage);
                package.CreateReleasePackage(outputPackage, packagesDir);
                Assert.True(File.Exists(outputPackage));
            } finally {
                File.Delete(outputPackage);
            }
        }
예제 #20
0
        public ReleasePackage CreateDeltaPackage(ReleasePackage baseFixture, string outputFile)
        {
            Contract.Requires(baseFixture != null && baseFixture.ReleasePackageFile != null);
            Contract.Requires(!String.IsNullOrEmpty(outputFile) && !File.Exists(outputFile));

            string baseTempPath = null;
            string tempPath     = null;

            using (Utility.WithTempDirectory(out baseTempPath))
                using (Utility.WithTempDirectory(out tempPath)) {
                    var baseTempInfo = new DirectoryInfo(baseTempPath);
                    var tempInfo     = new DirectoryInfo(tempPath);

                    using (var zf = new ZipFile(baseFixture.ReleasePackageFile)) {
                        zf.ExtractAll(baseTempInfo.FullName);
                    }

                    using (var zf = new ZipFile(ReleasePackageFile)) {
                        zf.ExtractAll(tempInfo.FullName);
                    }

                    // Collect a list of relative paths under 'lib' and map them
                    // to their full name. We'll use this later to determine in
                    // the new version of the package whether the file exists or
                    // not.
                    var baseLibFiles = baseTempInfo.GetAllFilesRecursively()
                                       .Where(x => x.FullName.ToLowerInvariant().Contains("lib" + Path.DirectorySeparatorChar))
                                       .ToDictionary(k => k.FullName.Replace(baseTempInfo.FullName, ""), v => v.FullName);

                    var newLibDir = tempInfo.GetDirectories().First(x => x.Name.ToLowerInvariant() == "lib");

                    // 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
                    newLibDir.GetAllFilesRecursively().ForEach(libFile => {
                        var relativePath = libFile.FullName.Replace(tempInfo.FullName, "");

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

                        var oldData = File.ReadAllBytes(baseLibFiles[relativePath]);
                        var newData = File.ReadAllBytes(libFile.FullName);

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

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

                        this.Log().Info("Delta patching {0} => {1}", baseLibFiles[relativePath], libFile.FullName);
                        using (var of = File.Create(libFile.FullName + ".diff")) {
                            BinaryPatchUtility.Create(oldData, newData, of);

                            var rl = ReleaseEntry.GenerateFromFile(new MemoryStream(newData), libFile.Name + ".shasum");
                            File.WriteAllText(libFile.FullName + ".shasum", rl.EntryAsString, Encoding.UTF8);
                            libFile.Delete();
                        }
                    });

                    addDeltaFilesToContentTypes(tempInfo.FullName);

                    using (var zf = new ZipFile(outputFile)) {
                        zf.AddDirectory(tempInfo.FullName);
                        zf.Save();
                    }
                }

            return(new ReleasePackage(outputFile));
        }
예제 #21
0
        public void SpecFileMarkdownRenderingTest()
        {
            var dontcare = IntegrationTestHelper.GetPath("fixtures", "Shimmer.Core.1.1.0.0.nupkg");
            var inputSpec = IntegrationTestHelper.GetPath("fixtures", "Shimmer.Core.1.1.0.0.nuspec");
            var fixture = new ReleasePackage(dontcare);

            var targetFile = Path.GetTempFileName();
            File.Copy(inputSpec, targetFile, true);

            try {
                // NB: For No Reason At All, renderReleaseNotesMarkdown is
                // invulnerable to ExposedObject. Whyyyyyyyyy
                var renderMinfo = fixture.GetType().GetMethod("renderReleaseNotesMarkdown",
                    BindingFlags.NonPublic | BindingFlags.Instance);
                renderMinfo.Invoke(fixture, new object[] {targetFile});

                var doc = XDocument.Load(targetFile);
                XNamespace ns = "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd";
                var relNotesElement = doc.Descendants(ns + "releaseNotes").First();
                var htmlText = relNotesElement.Value;

                this.Log().Info("HTML Text:\n{0}", htmlText);

                htmlText.Contains("## Release Notes").ShouldBeFalse();
            } finally {
                File.Delete(targetFile);
            }
        }
예제 #22
0
        public void WhenInputPackageTargetsMultipleFrameworksCrashHard()
        {
            var packagesDir = IntegrationTestHelper.GetPath("..", "packages");
            var inputPackage = IntegrationTestHelper.GetPath("fixtures", "ProjectTargetingMultiplePlatforms.1.0.0.0.nupkg");

            var outputPackage = Path.GetTempFileName() + ".nupkg";

            var package = new ReleasePackage(inputPackage);
            Assert.Throws<InvalidOperationException>(() => {
                package.CreateReleasePackage(outputPackage, packagesDir);
            });
        }
예제 #23
0
        public ReleasePackage CreateDeltaPackage(ReleasePackage basePackage, ReleasePackage newPackage, string outputFile)
        {
            Contract.Requires(basePackage != null && basePackage.ReleasePackageFile != null);
            Contract.Requires(!String.IsNullOrEmpty(outputFile) && !File.Exists(outputFile));

            string baseTempPath = null;
            string tempPath = null;

            using (Utility.WithTempDirectory(out baseTempPath))
            using (Utility.WithTempDirectory(out tempPath)) {
                var baseTempInfo = new DirectoryInfo(baseTempPath);
                var tempInfo = new DirectoryInfo(tempPath);

                using (var zf = new ZipFile(basePackage.ReleasePackageFile)) {
                    zf.ExtractAll(baseTempInfo.FullName);
                }

                using (var zf = new ZipFile(newPackage.ReleasePackageFile)) {
                    zf.ExtractAll(tempInfo.FullName);
                }

                // Collect a list of relative paths under 'lib' and map them
                // to their full name. We'll use this later to determine in
                // the new version of the package whether the file exists or
                // not.
                var baseLibFiles = baseTempInfo.GetAllFilesRecursively()
                    .Where(x => x.FullName.ToLowerInvariant().Contains("lib" + Path.DirectorySeparatorChar))
                    .ToDictionary(k => k.FullName.Replace(baseTempInfo.FullName, ""), v => v.FullName);

                var newLibDir = tempInfo.GetDirectories().First(x => x.Name.ToLowerInvariant() == "lib");

                newLibDir.GetAllFilesRecursively()
                    .ForEach(libFile => createDeltaForSingleFile(libFile, tempInfo, baseLibFiles));

                ReleasePackage.addDeltaFilesToContentTypes(tempInfo.FullName);

                using (var zf = new ZipFile(outputFile)) {
                    zf.AddDirectory(tempInfo.FullName);
                    zf.Save();
                }
            }

            return new ReleasePackage(outputFile);
        }
예제 #24
0
        public void WhenBasePackageReleaseIsNullThrowsException()
        {
            var basePackage = IntegrationTestHelper.GetPath("fixtures", "Shimmer.Core.1.0.0.0.nupkg");
            var newPackage = IntegrationTestHelper.GetPath("fixtures", "Shimmer.Core.1.1.0.0.nupkg");

            var sourceDir = IntegrationTestHelper.GetPath("..", "packages");
            (new DirectoryInfo(sourceDir)).Exists.ShouldBeTrue();

            var baseFixture = new ReleasePackage(basePackage);
            var fixture = new ReleasePackage(newPackage);

            var tempFile = Path.GetTempPath() + Guid.NewGuid() + ".nupkg";

            try
            {
                Assert.Throws<ArgumentException>(() =>
                {
                    var deltaBuilder = new DeltaPackageBuilder();
                    deltaBuilder.CreateDeltaPackage(baseFixture, fixture, tempFile);
                });
            }
            finally {
                File.Delete(tempFile);
            }
        }
예제 #25
0
        public void WhenNewPackageDoesNotExistThrowException()
        {
            var basePackage = IntegrationTestHelper.GetPath("fixtures", "Shimmer.Core.1.0.0.0.nupkg");
            var newPackage = IntegrationTestHelper.GetPath("fixtures", "Shimmer.Core.1.1.0.0.nupkg");

            var sourceDir = IntegrationTestHelper.GetPath("..", "packages");
            (new DirectoryInfo(sourceDir)).Exists.ShouldBeTrue();

            var baseFixture = new ReleasePackage(basePackage);
            var fixture = new ReleasePackage(newPackage);

            var tempFiles = Enumerable.Range(0, 3)
                .Select(_ => Path.GetTempPath() + Guid.NewGuid().ToString() + ".nupkg")
                .ToArray();

            try
            {
                baseFixture.CreateReleasePackage(tempFiles[0], sourceDir);
                fixture.CreateReleasePackage(tempFiles[1], sourceDir);

                (new FileInfo(baseFixture.ReleasePackageFile)).Exists.ShouldBeTrue();
                (new FileInfo(fixture.ReleasePackageFile)).Exists.ShouldBeTrue();

                // NOW WATCH AS THE FILE DISAPPEARS
                File.Delete(fixture.ReleasePackageFile);

                Assert.Throws<FileNotFoundException>(() =>
                {
                    var deltaBuilder = new DeltaPackageBuilder();
                    deltaBuilder.CreateDeltaPackage(baseFixture, fixture, tempFiles[2]);
                });
            }
            finally
            {
                tempFiles.ForEach(File.Delete);
            }
        }
예제 #26
0
        public void ApplyMultipleDeltaPackagesGeneratesCorrectHash()
        {
            var firstRelease = new ReleasePackage(IntegrationTestHelper.GetPath("fixtures", "ShimmerDesktopDemo-1.0.0-full.nupkg"), true);
            var secondRelease = new ReleasePackage(IntegrationTestHelper.GetPath("fixtures", "ShimmerDesktopDemo-1.1.0-full.nupkg"), true);
            var thirdRelease = new ReleasePackage(IntegrationTestHelper.GetPath("fixtures", "ShimmerDesktopDemo-1.2.0-full.nupkg"), true);

            string installDir, releasesDir;
            using(Utility.WithTempDirectory(out releasesDir))
            using (IntegrationTestHelper.WithFakeAlreadyInstalledApp("InstalledShimmerDesktopDemo-1.0.0.zip", out installDir)) {

                var firstDelta = Path.Combine(releasesDir, "ShimmerDesktopDemo-1.1.0-delta.nupkg");
                var secondDelta = Path.Combine(releasesDir, "ShimmerDesktopDemo-1.2.0-delta.nupkg");

                new[] { firstRelease, secondRelease, thirdRelease }
                .ForEach(file =>
                {
                    var packageFile = file.ReleasePackageFile;
                    var fileName = Path.GetFileName(packageFile);
                    File.Copy(packageFile, Path.Combine(releasesDir, fileName));
                });

                var deltaBuilder = new DeltaPackageBuilder();
                deltaBuilder.CreateDeltaPackage(firstRelease, secondRelease, firstDelta);
                deltaBuilder.CreateDeltaPackage(secondRelease, thirdRelease, secondDelta);

                ReleaseEntry.BuildReleasesFile(releasesDir);

                var updateManager = new UpdateManager(
                    releasesDir, "ShimmerDesktopDemo", FrameworkVersion.Net40, installDir);

                using (updateManager) {
                    var updateInfo = updateManager.CheckForUpdate().First();

                    Assert.Equal(2, updateInfo.ReleasesToApply.Count());

                    updateManager.DownloadReleases(updateInfo.ReleasesToApply).Wait();
                    updateManager.ApplyReleases(updateInfo).Wait();
                }

                string referenceDir;
                using (IntegrationTestHelper.WithFakeAlreadyInstalledApp("InstalledShimmerDesktopDemo-1.2.0.zip", out referenceDir)) {

                    var referenceVersion = Path.Combine(referenceDir, "ShimmerDesktopDemo", "app-1.2.0");
                    var installVersion = Path.Combine(installDir, "ShimmerDesktopDemo", "app-1.2.0");

                    var referenceFiles = Directory.GetFiles(referenceVersion);
                    var actualFiles = Directory.GetFiles(installVersion);

                    Assert.Equal(referenceFiles.Count(), actualFiles.Count());

                    var invalidFiles =
                        Enumerable.Zip(referenceFiles, actualFiles,
                        (reference, actual) => {

                            var refSha = Utility.CalculateStreamSHA1(File.OpenRead(reference));
                            var actualSha = Utility.CalculateStreamSHA1(File.OpenRead(actual));

                            return new { File = actual, Result = refSha == actualSha };
                        })
                        .Where(c => !c.Result).ToArray();

                    Assert.Empty(invalidFiles);
                }
            }
        }