public async Task ApplyReleaseWhichRemovesAFile()
        {
            string tempDir;

            using (Utility.WithTempDirectory(out tempDir)) {
                string appDir      = Path.Combine(tempDir, "theApp");
                string packagesDir = Path.Combine(appDir, "packages");
                Directory.CreateDirectory(packagesDir);

                new[] {
                    "Squirrel.Core.1.1.0.0-full.nupkg",
                    "Squirrel.Core.1.2.0.0-full.nupkg",
                }.ForEach(x => File.Copy(IntegrationTestHelper.GetPath("fixtures", x), Path.Combine(packagesDir, x)));

                var fixture = new UpdateManager.ApplyReleasesImpl(appDir);

                var baseEntry       = ReleaseEntry.GenerateFromFile(Path.Combine(packagesDir, "Squirrel.Core.1.1.0.0-full.nupkg"));
                var latestFullEntry = ReleaseEntry.GenerateFromFile(Path.Combine(packagesDir, "Squirrel.Core.1.2.0.0-full.nupkg"));

                var updateInfo = UpdateInfo.Create(baseEntry, new[] { latestFullEntry }, packagesDir, FrameworkVersion.Net40);
                updateInfo.ReleasesToApply.Contains(latestFullEntry).ShouldBeTrue();

                var progress = new List <int>();
                await fixture.ApplyReleases(updateInfo, false, progress.Add);

                this.Log().Info("Progress: [{0}]", String.Join(",", progress));

                progress
                .Aggregate(0, (acc, x) => { x.ShouldBeGreaterThan(acc); return(x); })
                .ShouldEqual(100);

                var rootDirectory = Path.Combine(tempDir, "theApp", "app-1.2.0.0");

                new[] {
                    new { Name = "NLog.dll", Version = new Version("2.0.0.0") },
                    new { Name = "NSync.Core.dll", Version = new Version("1.1.0.0") },
                }.ForEach(x => {
                    var path = Path.Combine(rootDirectory, x.Name);
                    this.Log().Info("Looking for {0}", path);
                    File.Exists(path).ShouldBeTrue();
                });

                var removedFile  = Path.Combine("sub", "Ionic.Zip.dll");
                var deployedPath = Path.Combine(rootDirectory, removedFile);
                File.Exists(deployedPath).ShouldBeFalse();
            }
        }
        public void ApplyReleasesWithOneReleaseFile()
        {
            string tempDir;

            using (Utility.WithTempDirectory(out tempDir)) {
                string packagesDir = Path.Combine(tempDir, "theApp", "packages");
                Directory.CreateDirectory(packagesDir);

                new[] {
                    "Squirrel.Core.1.0.0.0-full.nupkg",
                    "Squirrel.Core.1.1.0.0-full.nupkg",
                }.ForEach(x => File.Copy(IntegrationTestHelper.GetPath("fixtures", x), Path.Combine(packagesDir, x)));

                var fixture = new UpdateManager("http://lol", "theApp", FrameworkVersion.Net40, tempDir, null, new FakeUrlDownloader());

                var baseEntry       = ReleaseEntry.GenerateFromFile(Path.Combine(packagesDir, "Squirrel.Core.1.0.0.0-full.nupkg"));
                var latestFullEntry = ReleaseEntry.GenerateFromFile(Path.Combine(packagesDir, "Squirrel.Core.1.1.0.0-full.nupkg"));

                var updateInfo = UpdateInfo.Create(baseEntry, new[] { latestFullEntry }, packagesDir, FrameworkVersion.Net40);
                updateInfo.ReleasesToApply.Contains(latestFullEntry).ShouldBeTrue();

                using (fixture) {
                    var progress = new ReplaySubject <int>();
                    fixture.ApplyReleases(updateInfo, progress).First();
                    this.Log().Info("Progress: [{0}]", String.Join(",", progress));

                    progress.Buffer(2, 1).All(x => x.Count != 2 || x[1] > x[0]).First().ShouldBeTrue();
                    progress.Last().ShouldEqual(100);
                }

                var filesToFind = new[] {
                    new { Name = "NLog.dll", Version = new Version("2.0.0.0") },
                    new { Name = "NSync.Core.dll", Version = new Version("1.1.0.0") },
                    new { Name = Path.Combine("sub", "Ionic.Zip.dll"), Version = new Version("1.9.1.8") },
                };

                filesToFind.ForEach(x => {
                    var path = Path.Combine(tempDir, "theApp", "app-1.1.0.0", x.Name);
                    this.Log().Info("Looking for {0}", path);
                    File.Exists(path).ShouldBeTrue();

                    var vi      = FileVersionInfo.GetVersionInfo(path);
                    var verInfo = new Version(vi.FileVersion ?? "1.0.0.0");
                    x.Version.ShouldEqual(verInfo);
                });
            }
        }
示例#3
0
            private UpdateInfo DetermineUpdateInfo(IEnumerable <ReleaseEntry> localReleases, IEnumerable <ReleaseEntry> remoteReleases, bool ignoreDeltaUpdates)
            {
                var packageDirectory = Utility.PackageDirectoryForAppDir(rootAppDirectory);

                localReleases = localReleases ?? Enumerable.Empty <ReleaseEntry>();

                if (remoteReleases == null)
                {
                    Log.WarnFormat("Release information couldn't be determined due to remote corrupt RELEASES file");
                    throw new Exception("Corrupt remote RELEASES file");
                }

                var latestFullRelease = Utility.FindCurrentVersion(remoteReleases);
                var currentRelease    = Utility.FindCurrentVersion(localReleases);

                if (latestFullRelease == currentRelease)
                {
                    Log.InfoFormat("No updates, remote and local are the same");

                    var info = UpdateInfo.Create(currentRelease, new[] { latestFullRelease }, packageDirectory);
                    return(info);
                }

                if (ignoreDeltaUpdates)
                {
                    remoteReleases = remoteReleases.Where(x => !x.IsDelta);
                }

                if (!localReleases.Any())
                {
                    Log.WarnFormat("First run or local directory is corrupt, starting from scratch");
                    return(UpdateInfo.Create(null, new[] { latestFullRelease }, packageDirectory));
                }

                if (localReleases.Max(x => x.Version) > remoteReleases.Max(x => x.Version))
                {
                    Log.WarnFormat("hwhat, local version is greater than remote version");
                    return(UpdateInfo.Create(Utility.FindCurrentVersion(localReleases), new[] { latestFullRelease }, packageDirectory));
                }

                return(UpdateInfo.Create(currentRelease, remoteReleases, packageDirectory));
            }
        public void WhenNoNewReleasesAreAvailableTheListIsEmpty()
        {
            string tempDir;

            using (Utility.WithTempDirectory(out tempDir)) {
                var appDir   = Directory.CreateDirectory(Path.Combine(tempDir, "theApp"));
                var packages = Path.Combine(appDir.FullName, "packages");
                Directory.CreateDirectory(packages);

                var package = "Squirrel.Core.1.0.0.0-full.nupkg";
                File.Copy(IntegrationTestHelper.GetPath("fixtures", package), Path.Combine(packages, package));

                var aGivenPackage = Path.Combine(packages, package);
                var baseEntry     = ReleaseEntry.GenerateFromFile(aGivenPackage);

                var updateInfo = UpdateInfo.Create(baseEntry, new[] { baseEntry }, "dontcare");

                Assert.Empty(updateInfo.ReleasesToApply);
            }
        }
        public void ExecutablesPinnedToTaskbarShouldPointToNewVersion()
        {
            string tempDir;

            using (Utility.WithTempDirectory(out tempDir)) {
                string packagesDir = Path.Combine(tempDir, "theApp", "packages");
                Directory.CreateDirectory(packagesDir);

                new[] {
                    "SampleUpdatingApp.1.0.0.0.nupkg",
                    "SampleUpdatingApp.1.1.0.0.nupkg",
                }.ForEach(x => File.Copy(IntegrationTestHelper.GetPath("fixtures", x), Path.Combine(packagesDir, x)));

                var fixture = new UpdateManager("http://lol", "theApp", FrameworkVersion.Net40, tempDir, null, new FakeUrlDownloader());

                var baseEntry       = ReleaseEntry.GenerateFromFile(Path.Combine(packagesDir, "SampleUpdatingApp.1.0.0.0.nupkg"));
                var latestFullEntry = ReleaseEntry.GenerateFromFile(Path.Combine(packagesDir, "SampleUpdatingApp.1.1.0.0.nupkg"));

                var updateInfo = UpdateInfo.Create(null, new[] { baseEntry }, packagesDir, FrameworkVersion.Net40);
                using (fixture) {
                    fixture.ApplyReleases(updateInfo).ToList().First();
                }

                var oldExecutable = Path.Combine(tempDir, "theApp", "app-1.0.0.0", "SampleUpdatingApp.exe");
                File.Exists(oldExecutable).ShouldBeTrue();
                TaskbarHelper.PinToTaskbar(oldExecutable);

                updateInfo = UpdateInfo.Create(baseEntry, new[] { latestFullEntry }, packagesDir, FrameworkVersion.Net40);
                using (fixture) {
                    fixture.ApplyReleases(updateInfo).ToList().First();
                }

                var newExecutable = Path.Combine(tempDir, "theApp", "app-1.1.0.0", "SampleUpdatingApp.exe");
                File.Exists(newExecutable).ShouldBeTrue();
                TaskbarHelper.IsPinnedToTaskbar(newExecutable).ShouldBeTrue();

                Utility.Retry(() => TaskbarHelper.UnpinFromTaskbar(newExecutable));
            }
        }
        static int Main(string[] args)
        {
            var command  = "";
            var target   = "";
            var appName  = default(string);
            var showHelp = false;

            var opts = new OptionSet()
            {
                { "c|command=", "One of 'check' or 'update' to return the latest update information, or to perform the update", v => command = v },
                { "t|update-target=", "The URL or directory to download updates from", v => target = v },
                { "n|app-name=", "(Optional) The name of the application, only necessary if updater.exe isn't in the install directory", v => appName = v },
                { "h|help", "Show this message and exit", v => showHelp = v != null },
            };

            opts.Parse(args);

            if (!new[] { "check", "update", "install", }.Any(x => command.ToLowerInvariant() == x))
            {
                Console.Error.WriteLine("Command must be either 'check' or 'update'");
                showHelp = true;
            }

            if (!Directory.Exists(target) && !File.Exists(target) && !isAUrl(target))
            {
                Console.Error.WriteLine("Target must be either a directory or a URL to check for updates");
                showHelp = true;
            }

            if (showHelp)
            {
                Console.WriteLine("\nSquirrel.Updater.exe - Check for updates or update an application");
                Console.WriteLine(@"Usage: Squirrel.Updater.exe [options]");

                Console.WriteLine("Options:");
                foreach (var v in opts)
                {
                    if (v.GetNames().Length != 2)
                    {
                        Console.WriteLine("  --{0} - {1}", v.GetNames()[0], v.Description);
                    }
                    else
                    {
                        Console.WriteLine("  -{0}/--{1} - {2}", v.GetNames()[0], v.GetNames()[1], v.Description);
                    }
                }

                return(0);
            }

            appName = appName ?? determineAppName();
            using (var mgr = new UpdateManager(target, appName, FrameworkVersion.Net40)) {
                if (command.ToLowerInvariant() == "check")
                {
                    var updateInfo = default(UpdateInfo);
                    try {
                        updateInfo = mgr.CheckForUpdate().First();

                        if (updateInfo.ReleasesToApply.Count > 0)
                        {
                            mgr.DownloadReleases(updateInfo.ReleasesToApply).First();
                        }
                    } catch (Exception ex) {
                        writeJsonForException(ex, "Failed to check for updates");
                        return(-1);
                    }

                    var releaseNotes = new Dictionary <ReleaseEntry, string>();

                    try {
                        releaseNotes = (updateInfo.ReleasesToApply.Count > 0) ? updateInfo.FetchReleaseNotes() : releaseNotes;
                    } catch (Exception ex) {
                        // TODO: Find a way to log this
                    }

                    Console.WriteLine(JsonConvert.SerializeObject(new {
                        UpdateInfo   = updateInfo,
                        ReleaseNotes = releaseNotes,
                    }));

                    return(0);
                }

                if (command.ToLowerInvariant() == "update")
                {
                    var result = default(ReleaseEntry);
                    try {
                        result = mgr.UpdateAppAsync().Result;
                    } catch (Exception ex) {
                        writeJsonForException(ex, "Failed to update application");
                        return(-1);
                    }

                    Console.WriteLine(JsonConvert.SerializeObject(result));
                    return(0);
                }

                if (command.ToLowerInvariant() == "install")
                {
                    var targetRelease = ReleaseEntry.GenerateFromFile(target);
                    mgr.ApplyReleases(UpdateInfo.Create(null, new[] { targetRelease }, Path.GetDirectoryName(target), FrameworkVersion.Net40)).First();
                    return(0);
                }
            }

            throw new Exception("How even did we get here?");
        }