public static bool IsFullyDownloaded(int version, Package package)
        {
            long actualSize = Utils.GetFolderSize(GetFolder(version, package));

            if (actualSize == 0)
            {
                return(false);
            }

            long expectedSize = ManifestData.GetDownloadSize(version, package);

            if (actualSize == expectedSize)
            {
                return(true);
            }
            Logging.Log($"Package {package} for version {version} is {actualSize} bytes, expected {expectedSize}");
            if (actualSize > expectedSize)
            {
                Logging.Log("Package has additional, unexpected data. Assuming it was fully downloaded...");
                return(true);
            }
            return(false);
        }
        private static void DownloadDepots(VersionUIComponent component)
        {
            var previousState = component.State;

            component.State = VersionState.DownloadPending; // Pending until we acquire the  lock
            lock (downloadLock) {
                int version = component.version;

                Logging.Log($"Downloading depots for {version}");
                var drive = new DriveInfo(new DirectoryInfo(ManifestData.DepotLocation).Root.FullName);
                if (!drive.IsReady)
                {
                    Logging.MessageBox("Drive unavailable", $"Steam install location is in drive {drive.Name}, which is unavailable.");
                    return;
                }

                var neededManifests = new List <SteamManifest>();
                if (!IsFullyDownloaded(version, Package.Main))
                {
                    neededManifests.AddRange(ManifestData.Get(version, Package.Main));
                }
                if (Settings.Default.ownsGehenna && !IsFullyDownloaded(version, Package.Gehenna))
                {
                    neededManifests.AddRange(ManifestData.Get(version, Package.Gehenna));
                }
                if (Settings.Default.ownsPrototype && !IsFullyDownloaded(version, Package.Prototype))
                {
                    neededManifests.AddRange(ManifestData.Get(version, Package.Prototype));
                }
                if (Settings.Default.wantsEditor && !IsFullyDownloaded(version, Package.Editor))
                {
                    neededManifests.AddRange(ManifestData.Get(version, Package.Editor));
                }
                if (neededManifests.Count == 0)
                {
                    Logging.Log($"Attempted to download manifests for {version}, but no manfiests applied.");
                    component.State = VersionState.Downloaded;
                    return;
                }

                if (Settings.Default.steamHack == false)
                {
                    // Note: There are intentional tab characters in this string -- that's because it's a verbatim string.
                    Logging.MessageBox("Unable to download",
                                       @"Steam has broken the download_depots command, so this version can't be downloaded.
To download versions, please change your beta participation in Steam, re-download the game, then re-launch the downpatcher.

Version	| Steam beta
------------|------------------------
440323	| NONE
326589	| previousversion
252786	| legacy_winxp
244371	| speedrun-244371");
                    component.State = previousState;
                    return;
                }

                double totalDownloadSize = 0;
                foreach (var manifest in neededManifests)
                {
                    totalDownloadSize += manifest.size;
                }

                long freeSpace = drive.TotalFreeSpace;
                if (drive.TotalFreeSpace < totalDownloadSize)
                {
                    Logging.MessageBox("Not enough space",
                                       $@"Steam install location is in drive {drive.Name}
has {Math.Round(freeSpace / 1000000000.0, 1)} GB of free space
but {Math.Round(totalDownloadSize / 1000000000.0, 1)} GB are required.");
                    return;
                }

                component.State = VersionState.Downloading;

                { // Keep steam interaction close together, to avoid accidental user interference
                    SteamCommand.OpenConsole();
                    Thread.Sleep(10);
                    foreach (var manifest in neededManifests)
                    {
                        SteamCommand.DownloadDepot(manifest.appId, manifest.depotId, manifest.manifestId);
                    }
                    MainWindow.SetForeground();
                }

                Thread.Sleep(5000); // Extra sleep to avoid a race condition where we check for depots before they're actually cleared.

                while (true)
                {
                    long actualSize = 0;
                    foreach (var manifest in neededManifests)
                    {
                        actualSize += Utils.GetFolderSize(manifest.location);
                    }
                    component.SetProgress(0.8 * actualSize / totalDownloadSize); // 80% - Downloading
                    if (actualSize == totalDownloadSize)
                    {
                        break;
                    }
                    Thread.Sleep(1000);
                }
                component.State = VersionState.Saving;

                long copied = 0;

                // @Performance: Start copying while downloads are in progress?
                foreach (var manifest in neededManifests)
                {
                    CopyAndOverwrite(manifest.location, GetFolder(version, manifest.package), delegate(long fileSize) {
                        copied += fileSize;
                        component.SetProgress(0.8 + 0.2 * (copied / totalDownloadSize)); // 20% - Copying
                    });
                }

                if (drive.TotalFreeSpace < 5 * totalDownloadSize)
                {
                    Logging.Log("Low on disk space, clearing download directory");
                    Directory.Delete(ManifestData.DepotLocation, true);
                }
                component.State = VersionState.Downloaded;
            }
        }