private void DownloadPackage(PackageDescription package) { string cachefile = GetCacheFileName(package); if (!File.Exists(cachefile)) { WebRequest webreq = WebRequest.Create(FeedUrl + package.InterfaceVersion + "/" + package.Version + "/" + package.Name + ".zip"); try { using (Stream s = webreq.GetResponse().GetResponseStream()) { if (File.Exists(cachefile)) { File.Delete(cachefile); } using (var fs = new FileStream(cachefile, FileMode.Create)) { s.CopyTo(fs); } } } catch { File.Delete(cachefile); throw; } } }
private bool VerifyInstalledPackage(PackageDescription pack) { foreach (KeyValuePair <string, PackageDescription.FileInfo> kvp in pack.Files) { if (kvp.Value.Hash != null) { using (SHA256 hash = SHA256.Create()) { try { using (FileStream fs = new FileStream(Path.Combine(InstallRootPath, kvp.Key), FileMode.Open, FileAccess.Read)) { hash.ComputeHash(fs); } } catch (FileNotFoundException) { return(false); } catch (DirectoryNotFoundException) { return(false); } if (!IsHashEqual(hash.Hash, kvp.Value.Hash)) { return(false); } } } } return(true); }
private CoreUpdater() { InstallRootPath = Path.GetFullPath(Path.Combine(Assembly.GetExecutingAssembly().Location, "../..")); PackageCachePath = Path.Combine(InstallRootPath, "data/dl-cache"); Directory.CreateDirectory(PackageCachePath); InstalledPackagesPath = Path.Combine(InstallRootPath, "bin/installed-packages"); BinariesPath = Path.Combine(InstallRootPath, "bin"); PluginsPath = Path.Combine(InstallRootPath, "bin/plugins"); Directory.CreateDirectory(InstalledPackagesPath); InterfaceVersion = string.Empty; if (LoadUpdaterConfig() && FeedUrl?.Length != 0) { try { using (Stream i = new FileStream(Path.Combine(InstalledPackagesPath, "SilverSim.Updater.Cfg.spkg"), FileMode.Open)) { var desc = new PackageDescription(i); InterfaceVersion = desc.InterfaceVersion; } } catch { /* if interface version is not set, we simply switch to disabled */ InterfaceVersion = string.Empty; } } PrintLog(LogType.Info, "Cleanup up old installation files"); foreach (string deletefile in Directory.GetFiles(Path.Combine(InstallRootPath, "bin"), "*.delete", SearchOption.AllDirectories)) { File.Delete(deletefile); } }
public PackageDescription(PackageDescription desc) { Version = desc.Version; InterfaceVersion = desc.InterfaceVersion; License = desc.License; Description = desc.Description; Name = desc.Name; Hash = desc.Hash; SkipDelivery = desc.SkipDelivery; foreach (KeyValuePair <string, string> kvp in desc.Dependencies) { m_Dependencies.Add(kvp.Key, kvp.Value); } foreach (KeyValuePair <string, PackageDescription.FileInfo> kvp in desc.Files) { m_Files.Add(kvp.Key, kvp.Value); } foreach (Configuration cfg in desc.DefaultConfigurations) { m_DefaultConfigurations.Add(cfg); } foreach (PreloadAssembly info in desc.PreloadAssemblies) { m_PreloadAssembles.Add(info); } }
private PackageDescription InstallPackageNoDependencies(string packagename, string version = "") { PackageDescription current = version?.Length == 0 ? new PackageDescription(FeedUrl + InterfaceVersion + "/" + packagename + ".spkg") : new PackageDescription(FeedUrl + InterfaceVersion + "/" + version + "/" + packagename + ".spkg"); PrintLog(LogType.Info, "Installing package " + packagename + " (" + current.Version + ") without dependency check"); DownloadPackage(current); UnpackPackage(current); PrintLog(LogType.Info, "Installed package " + packagename + " (" + current.Version + ") without dependency check"); return(current); }
public void UninstallPackage(string packagename) { m_RwLock.AcquireReaderLock(-1); try { foreach (PackageDescription packsearch in m_InstalledPackages.Values) { if (packsearch.Dependencies.Keys.Contains(packagename)) { throw new PackageDependencyFoundException(packsearch.Name); } } } finally { m_RwLock.ReleaseReaderLock(); } PrintLog(LogType.Info, "Uninstalling package " + packagename); PackageDescription pack = m_InstalledPackages[packagename]; File.Delete(Path.Combine(InstalledPackagesPath, pack.Name + ".spkg")); foreach (KeyValuePair <string, PackageDescription.FileInfo> kvp in pack.Files) { string fPath = Path.Combine(InstallRootPath, kvp.Key); if (DoesFileRequireReplacement(kvp.Key) && !File.Exists(fPath + ".delete")) { File.Move(fPath, fPath + ".delete"); } if (File.Exists(fPath)) { File.Delete(fPath); } } m_RwLock.AcquireWriterLock(-1); try { m_InstalledPackages.Remove(pack.Name); } finally { m_RwLock.ReleaseWriterLock(); } PrintLog(LogType.Info, "Uninstalled package " + packagename); }
public bool TryGetAvailablePackageDetails(string pkgname, out PackageDescription desc) { desc = null; m_RwLock.AcquireReaderLock(-1); try { PackageDescription found; if (m_AvailablePackages.TryGetValue(pkgname, out found)) { desc = new PackageDescription(found); return(true); } } finally { m_RwLock.ReleaseReaderLock(); } return(false); }
public void InstallPackage(string packagename) { var requiredPackages = new Dictionary <string, PackageDescription>(); var newDependencies = new Dictionary <string, string> { [packagename] = string.Empty }; while (newDependencies.Count != 0) { string pkg = newDependencies.Keys.First(); string version = newDependencies[pkg]; newDependencies.Remove(pkg); PackageDescription current = version?.Length == 0 ? new PackageDescription(FeedUrl + InterfaceVersion + "/" + pkg + ".spkg") : new PackageDescription(FeedUrl + InterfaceVersion + "/" + version + "/" + pkg + ".spkg"); requiredPackages.Add(current.Name, current); foreach (KeyValuePair <string, string> dep in current.Dependencies) { if (requiredPackages.ContainsKey(dep.Key) || (m_InstalledPackages.ContainsKey(dep.Key) && (dep.Value?.Length == 0 || dep.Value == m_InstalledPackages[dep.Key].Version))) { continue; } if (!newDependencies.ContainsKey(dep.Key)) { newDependencies.Add(dep.Key, dep.Value); } } } foreach (PackageDescription package in requiredPackages.Values) { PrintLog(LogType.Info, "Installing package " + package.Name + " (" + package.Version + ")"); DownloadPackage(package); UnpackPackage(package); PrintLog(LogType.Info, "Installed package " + package.Name + " (" + package.Version + ")"); } }
public void LoadInstalledPackageDescriptions() { string[] pkgfiles = Directory.GetFiles(InstalledPackagesPath, "*.spkg"); m_RwLock.AcquireWriterLock(-1); try { m_InstalledPackages.Clear(); foreach (string pkgfile in pkgfiles) { using (var i = new FileStream(pkgfile, FileMode.Open)) { PackageDescription desc; try { desc = new PackageDescription(i); } catch (Exception e) { throw new InvalidDataException("Failed to load package description " + pkgfile, e); } try { m_InstalledPackages.Add(desc.Name, desc); } catch { throw new ArgumentException(string.Format("Installed package {0} is duplicate in {1}.", desc.Name, pkgfile)); } } } } finally { m_RwLock.ReleaseWriterLock(); } }
private void UnpackPackage(PackageDescription package) { string cachefile = GetCacheFileName(package); try { using (SHA256 hash = SHA256.Create()) { using (var fs = new FileStream(cachefile, FileMode.Open, FileAccess.Read)) { hash.ComputeHash(fs); } if (!IsHashEqual(hash.Hash, package.Hash)) { throw new InvalidPackageHashException("Package " + package.Name + " is invalid"); } } } catch { File.Delete(cachefile); throw; } m_RwLock.AcquireWriterLock(-1); try { package.WriteFile(Path.Combine(InstalledPackagesPath, package.Name + ".spkg")); using (var fs = new FileStream(cachefile, FileMode.Open)) { using (var zip = new ZipArchive(fs)) { foreach (ZipArchiveEntry entry in zip.Entries) { using (Stream i = entry.Open()) { string targetFile = Path.Combine(InstallRootPath, entry.FullName); if (DoesFileRequireReplacement(entry.FullName)) { if (!File.Exists(targetFile + ".delete") && File.Exists(targetFile)) { try { File.Delete(targetFile); } catch { File.Move(targetFile, targetFile + ".delete"); } } if (File.Exists(targetFile + ".delete")) { IsRestartRequired = true; } } if (File.Exists(targetFile)) { File.Delete(targetFile); } string targetDir = Path.GetFullPath(Path.Combine(targetFile, "..")); if (!Directory.Exists(targetDir)) { Directory.CreateDirectory(targetDir); } using (var o = new FileStream(targetFile, FileMode.Create)) { i.CopyTo(o); } } } } } m_InstalledPackages[package.Name] = new PackageDescription(package); } finally { m_RwLock.ReleaseWriterLock(); } }
public void VerifyInstallation() { List <PackageDescription> installedpackages; m_RwLock.AcquireReaderLock(-1); try { installedpackages = new List <PackageDescription>(m_InstalledPackages.Values); } finally { m_RwLock.ReleaseReaderLock(); } foreach (PackageDescription pack in installedpackages) { PrintLog(LogType.Info, "Verifying package " + pack.Name + " (" + pack.Version + ")"); if (!VerifyInstalledPackage(pack)) { PrintLog(LogType.Info, "Re-Installing package " + pack.Name + " (" + pack.Version + ")"); DownloadPackage(pack); UnpackPackage(pack); PrintLog(LogType.Info, "Re-Installed package " + pack.Name + " (" + pack.Version + ")"); } } var unresolvedDependencies = new Dictionary <string, string>(); m_RwLock.AcquireReaderLock(-1); try { foreach (PackageDescription pack in m_InstalledPackages.Values) { foreach (KeyValuePair <string, string> kvp in pack.Dependencies) { if (!m_InstalledPackages.ContainsKey(kvp.Key) && !unresolvedDependencies.ContainsKey(kvp.Key)) { unresolvedDependencies.Add(kvp.Key, kvp.Value); } } } } finally { m_RwLock.ReleaseReaderLock(); } while (unresolvedDependencies.Count != 0) { KeyValuePair <string, string> unresolvedPackage = unresolvedDependencies.First <KeyValuePair <string, string> >(); unresolvedDependencies.Remove(unresolvedPackage.Key); m_RwLock.AcquireReaderLock(-1); try { if (m_InstalledPackages.ContainsKey(unresolvedPackage.Key)) { /* do not re-install if already installed */ continue; } } finally { m_RwLock.ReleaseReaderLock(); } PackageDescription pack = InstallPackageNoDependencies(unresolvedPackage.Key, unresolvedPackage.Value); m_RwLock.AcquireReaderLock(-1); try { foreach (KeyValuePair <string, string> kvp in pack.Dependencies) { if (!m_InstalledPackages.ContainsKey(kvp.Key) && !unresolvedDependencies.ContainsKey(kvp.Key)) { unresolvedDependencies.Add(kvp.Key, kvp.Value); } } } finally { m_RwLock.ReleaseReaderLock(); } } }
private string GetCacheFileName(PackageDescription package) => Path.Combine(PackageCachePath, package.InterfaceVersion + "-" + package.Version + "-" + package.Name + ".zip");
public bool UpdatePackageFeed() { if (InterfaceVersion?.Length == 0) { /* debugging does not have any package data normally, so we skip loading the feed */ PrintLog(LogType.Error, "Update system is disabled"); return(false); } PrintLog(LogType.Info, "Updating package feed"); var additionalpackagestofetch = new List <string>(); using (var reader = new XmlTextReader(FeedUrl + InterfaceVersion + "/packages.list") { DtdProcessing = DtdProcessing.Ignore, XmlResolver = null }) { while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: string packagename = string.Empty; bool isHidden = false; if (reader.MoveToFirstAttribute()) { do { switch (reader.Name) { case "name": packagename = reader.Value; break; case "hidden": isHidden = bool.Parse(reader.Value); break; default: break; } }while (reader.MoveToNextAttribute()); if (packagename?.Length != 0) { m_HiddenPackages[packagename] = isHidden; if (!m_AvailablePackages.ContainsKey(packagename)) { additionalpackagestofetch.Add(packagename); } } } break; default: break; } } } foreach (KeyValuePair <string, PackageDescription> kvp in m_InstalledPackages) { var current = new PackageDescription(FeedUrl + InterfaceVersion + "/" + kvp.Key + ".spkg"); m_RwLock.AcquireWriterLock(-1); try { m_AvailablePackages[current.Name] = current; } finally { m_RwLock.ReleaseWriterLock(); } } foreach (string package in additionalpackagestofetch) { var current = new PackageDescription(FeedUrl + InterfaceVersion + "/" + package + ".spkg"); m_RwLock.AcquireWriterLock(-1); try { m_AvailablePackages[current.Name] = current; } finally { m_RwLock.ReleaseWriterLock(); } } PrintLog(LogType.Info, "Updated package feed"); return(true); }
public bool TryGetPackageDetails(string pkgname, out PackageDescription desc) { return(TryGetInstalledPackageDetails(pkgname, out desc) || TryGetAvailablePackageDetails(pkgname, out desc)); }