Ejemplo n.º 1
0
        public static string GetStatusString(bool includeProgress = false)
        {
            switch (State)
            {
            case UpdateStates.Checking:
                return(LocalisationManager.GetString(OsuString.CommonUpdater_CheckingForUpdates));

            case UpdateStates.Error:
                if (LastError is MissingFrameworkVersionException)
                {
                    return(LocalisationManager.GetString(OsuString.GameBase_UpdateFailedFrameworkVersion));
                }
                else
                {
                    return(LocalisationManager.GetString(OsuString.CommonUpdater_ErrorOccurred));
                }

            case UpdateStates.NeedsRestart:
                return(LocalisationManager.GetString(OsuString.CommonUpdater_RestartRequired));

            case UpdateStates.Updating:
                lock (ActiveFiles)
                {
                    totalUpdatableFiles = Math.Max(ActiveFiles.Count, totalUpdatableFiles);

                    string progress = includeProgress && Percentage > 0 ? " (" + (int)Percentage + "%)" : string.Empty;

                    if (ActiveFiles.Count == 0 || totalUpdatableFiles == 0)
                    {
                        return(LocalisationManager.GetString(OsuString.CommonUpdater_PerformingUpdates));
                    }

                    int runningCount = ActiveFiles.FindAll(f => f.isRunning).Count;

                    if (runningCount > 1)
                    {
                        if (totalUpdatableFiles == ActiveFiles.Count)
                        {
                            return(string.Format(LocalisationManager.GetString(OsuString.CommonUpdater_DownloadingRequiredFiles), totalUpdatableFiles) + progress);
                        }
                        else
                        {
                            //has at least one file finished.
                            return(string.Format(LocalisationManager.GetString(OsuString.CommonUpdater_DownloadingRequiredFiles2), totalUpdatableFiles - ActiveFiles.Count, totalUpdatableFiles) + progress);
                        }
                    }

                    DownloadableFileInfo lastRunning = ActiveFiles.FindLast(f => f.isRunning);
                    if (lastRunning != null)
                    {
                        if (lastRunning.isPatching)
                        {
                            return(String.Format(LocalisationManager.GetString(OsuString.CommonUpdater_PatchingFilePercentage), lastRunning.filename) + progress);
                        }
                        else
                        {
                            return(String.Format(LocalisationManager.GetString(OsuString.CommonUpdater_DownloadingFile), lastRunning.filename + (lastRunning.url_patch != null ? @"_patch" : string.Empty)) + progress);
                        }
                    }

                    return(LocalisationManager.GetString(OsuString.CommonUpdater_PerformingUpdates));
                }

            default:
                return(LocalisationManager.GetString(OsuString.CommonUpdater_Updated));
            }
        }
Ejemplo n.º 2
0
 private static void smethod_11(DownloadableFileInfo downloadableFileInfo_0)
 {
     Class214.list_0.Remove(downloadableFileInfo_0);
 }
Ejemplo n.º 3
0
        private static UpdateStates doUpdate()
        {
            //ensure we have the correct version of .net available.
            if (ReleaseStream.ToString().Contains(@"40") && !DotNetFramework.CheckInstalled(FrameworkVersion.dotnet4))
            {
                Log(@"Not updating due to missing .NET 4 installation");
                LastError = new MissingFrameworkVersionException(FrameworkVersion.dotnet4);
                return(UpdateStates.Error);
            }

            try
            {
                ConfigManagerCompact.LoadConfig();

                //ensure we are starting clean.
                //note that we don't clear a pending update just yet because there are scenarios we can use this (see variable stagedAndWaitingToUpdate below).
                Cleanup(10000, false);

                List <DownloadableFileInfo> streamFiles = null;

                string rawString = string.Empty;

                try
                {
                    Log(@"Requesting update information...");

                    var sn = new pWebRequest <List <DownloadableFileInfo> >(string.Format(CENTRAL_UPDATE_URL + @"?action=check&stream={0}&time={1}", ReleaseStream.ToString().ToLower(), DateTime.Now.Ticks));
                    sn.BlockingPerform();
                    rawString = sn.ResponseString;

                    if (rawString == @"fallback")
                    {
                        Log(@"Server has requested an emergency fallback!");
                        return(UpdateStates.EmergencyFallback);
                    }

                    streamFiles = sn.ResponseObject;
                }
                catch (Exception e)
                {
                    LastError = e;
                    LastErrorExtraInformation = rawString;

                    Log(LastError.ToString());
                    Log(rawString);
                    return(UpdateStates.Error);
                }

                if (streamFiles == null || streamFiles.Count == 0)
                {
                    LastError = new Exception($@"update file returned no results ({rawString})");
                    Log(LastError.ToString());
                    return(UpdateStates.Error);
                }

tryAgain:
                bool stagedAndWaitingToUpdate = Directory.Exists(STAGING_COMPLETE_FOLDER);
                List <DownloadableFileInfo> updateFiles = new List <DownloadableFileInfo>();

                foreach (DownloadableFileInfo file in streamFiles)
                {
                    if (stagedAndWaitingToUpdate)
                    {
                        Log(@"A pending update is already waiting. Checking what we're working with...");

                        //special case where we already have a pending update.
                        //if we find *any* file which doesn't match, we should remove the folder and restart the process.

                        string pendingFilename = STAGING_COMPLETE_FOLDER + @"/" + file.filename;

                        if (File.Exists(pendingFilename))
                        {
                            Log(file.filename + @": PENDING");
                            //pending file exists and matches this update precisely.
                            if (getMd5(pendingFilename) == file.file_hash)
                            {
                                continue;
                            }
                        }
                        else if (File.Exists(file.filename) && getMd5(file.filename, true) == file.file_hash)
                        {
                            Log(file.filename + @": LATEST");
                            //current version is already newest.
                            continue;
                        }

                        Log(file.filename + @": MISMATCH");

                        //something isn't up-to-date. let's run the update process again without our pending version.
                        Reset(false);

                        goto tryAgain;
                    }

                    if (!File.Exists(file.filename))
                    {
                        updateFiles.Add(file);
                        Log(file.filename + @": NEW");
                    }
                    else if (getMd5(file.filename, true) != file.file_hash)
                    {
                        Log(file.filename + @": CHANGED (cached)");
                        updateFiles.Add(file);                                                                     //cached md5 check failed.
                    }
                    else if (file.filename == @"osu!.exe" && getMd5(file.filename, true) != getMd5(file.filename)) //special intensive check for main osu!.exe
                    {
                        Log(file.filename + @": CHANGED");
                        ConfigManagerCompact.ResetHashes();
                        goto tryAgain;
                    }
                }

                if (stagedAndWaitingToUpdate)
                {
                    Log(@"Pending updating is waiting and requires no further changes.");
                    //return early, as we've already done the rest of the process below in a previous run.
                    return(MoveInPlace() ? UpdateStates.Completed : UpdateStates.NeedsRestart);
                }

                if (updateFiles.Count == 0)
                {
                    Log(@"No changes to apply!");

                    if (!DotNetFramework.CheckInstalled(FrameworkVersion.dotnet4))
                    {
                        Log(@"Becuase we had no changes, let's let the user know they need a newer framework in the future");

                        //if there are no pending updates but the user doesn't have dotnet4 available, we should tell them to get it.
                        LastError = new MissingFrameworkVersionException(FrameworkVersion.dotnet4);
                        return(UpdateStates.Error);
                    }

                    return(UpdateStates.NoUpdate);
                }

                totalUpdatableFiles = updateFiles.Count;

                if (!Directory.Exists(STAGING_FOLDER))
                {
                    Log(@"Creating staging folder");
                    DirectoryInfo di = Directory.CreateDirectory(STAGING_FOLDER);
                    di.Attributes = FileAttributes.Directory | FileAttributes.Hidden;
                }

                setCallbackStatus(UpdateStates.Updating);

                lock (ActiveFiles) ActiveFiles.AddRange(updateFiles);

                foreach (DownloadableFileInfo f in updateFiles)
                {
                    DownloadableFileInfo file = f;

                    Log(@"Processing {0}...", file.ToString());

                    if (File.Exists(file.filename))
                    {
                        Log(@"Exists locally; checking for patchability...");
                        string localHash = getMd5(file.filename);

                        //check for patchability...
                        try
                        {
                            var sn = new pWebRequest <List <DownloadableFileInfo> >(@"{0}?action=path&stream={1}&target={2}&existing={3}&time={4}",
                                                                                    CENTRAL_UPDATE_URL,
                                                                                    ReleaseStream.ToString().ToLower(),
                                                                                    file.file_version,
                                                                                    localHash,
                                                                                    DateTime.Now.Ticks);

                            sn.BlockingPerform();

                            List <DownloadableFileInfo> patchFiles = sn.ResponseObject;

                            if (patchFiles.Count > 1)
                            {
                                Log(@"Server returned {0} patch files", patchFiles.Count.ToString());
                                //copy the local version to the staging path.

                                File.Copy(file.filename, STAGING_FOLDER + @"/" + file.filename);

                                bool success = false;

                                lock (ActiveFiles)
                                    ActiveFiles.AddRange(patchFiles.GetRange(0, patchFiles.Count - 1));
                                totalUpdatableFiles += patchFiles.Count - 1;

                                try
                                {
                                    //we now know we have a patchable path, so let's try patching!
                                    foreach (DownloadableFileInfo patch in patchFiles)
                                    {
                                        try
                                        {
                                            if (patch.file_version == file.file_version)
                                            {
                                                Log(@"Reached end of patch chain ({0} / {1}), checking file checksum...",
                                                    patch.file_version.ToString(), patch.file_hash);

                                                //reached the end of patching.
                                                if (getMd5(STAGING_FOLDER + @"/" + file.filename) != file.file_hash)
                                                {
                                                    Log(@"Patching FAILED!");
                                                    throw new Exception(@"patching failed to end with correct checksum.");
                                                }

                                                Log(@"Patching success!");
                                                success = true;
                                                break; //patching successful!
                                            }

                                            string localPatchFilename = STAGING_FOLDER + @"/" + patch.filename + @"_patch";

                                            Log(@"Applying patch {0} (to {1})...", patch.file_version.ToString(), patch.file_hash);
                                            patch.Perform(true);
                                        }
                                        finally
                                        {
                                            lock (ActiveFiles) ActiveFiles.Remove(patch);
                                        }
                                    }

                                    if (success)
                                    {
                                        lock (ActiveFiles) ActiveFiles.Remove(file);
                                        continue;
                                    }
                                }
                                finally
                                {
                                    lock (ActiveFiles)
                                        patchFiles.ForEach(pf => ActiveFiles.Remove(pf));
                                }
                            }

                            Log(@"No patches available; falling back to full download");
                        }
                        catch (Exception e)
                        {
                            Log(@"Error occured during patching: " + e);
                            //an error occurred when trying to patch; fallback to a full update.
                        }
                    }

                    Log(@"Beginning download of {0} ({1})...", file.filename, file.url_full);
                    file.PerformThreaded(delegate
                    {
                        lock (ActiveFiles) ActiveFiles.Remove(file);
                        Log(@"Completed download of {0} ({1} files remain)!", file.filename, ActiveFiles.Count);
                    },
                                         delegate
                    {
                        Log(@"Failed download of {0}! Error: {1}", file.filename, file.Error);
                        //error occurred
                    });
                }

                while (ActiveFiles.Count > 0)
                {
                    foreach (DownloadableFileInfo dfi in ActiveFiles)
                    {
                        if (dfi.Error != null)
                        {
                            LastError = dfi.Error;
                            return(UpdateStates.Error);
                        }
                    }
                    Thread.Sleep(100);
                }

                if (State == UpdateStates.Updating)
                {
                    if (Directory.Exists(STAGING_COMPLETE_FOLDER))
                    {
                        Directory.Delete(STAGING_COMPLETE_FOLDER, true);
                    }

                    GeneralHelper.RecursiveMove(STAGING_FOLDER, STAGING_COMPLETE_FOLDER);

                    ConfigManagerCompact.Configuration[@"_ReleaseStream"] = ReleaseStream.ToString();

                    return(MoveInPlace() ? UpdateStates.Completed : UpdateStates.NeedsRestart);
                }

                return(UpdateStates.NoUpdate);
            }
            catch (ThreadAbortException)
            {
                Log(@"Thread was aborted!");
                foreach (DownloadableFileInfo dfi in ActiveFiles)
                {
                    dfi.Abort();
                }
                return(UpdateStates.NoUpdate);
            }
            catch (Exception e)
            {
                Log(@"Error: " + e.ToString());
                LastError = e;
                return(UpdateStates.Error);
            }
            finally
            {
                Log(@"Saving out global config");
                ConfigManagerCompact.SaveConfig();
                updateThread = null;
            }
        }