/// <summary>
        /// Invoked after all files are downloaded to add data from manifest and ensure there are no orphan or missing files.
        /// </summary>
        /// <returns>True if manifest was loaded without error or manifest does not exist. False otherwise.</returns>
        public bool LoadManifest()
        {
            string manifestPath = PathExtensions.Combine(directory, Manifest.fileName);

            if (!File.Exists(manifestPath))
            {
                Logger.WriteLine("WARNING: " + name.fullName + " has no manifest.");
                return(true);
            }
            Manifest manifest; Serialization.ReadJson(manifestPath, out manifest);

            assetFileName   = manifest.assetFileName;
            requiredPlugins = manifest.requiredPlugins;

            if (manifest.files == null || manifest.files.Length == 0)
            {
                Logger.WriteLine("ERROR: Manifest for " + name.fullName + " has no files.");
                return(false);
            }

            bool error = false;

            HashSet <string> orphans = new HashSet <string>(_files.Keys);

            foreach (var f in manifest.FilesAndRequirements())
            {
                if (!orphans.Remove(f.Key))
                {
                    Logger.WriteLine("ERROR: " + f.Key + " listed on manifest for " + name.fullName + " is missing");
                    error = true;
                }
            }

            foreach (string o in orphans)
            {
                Logger.WriteLine(o + " is not listed on manifest for " + name.fullName + ", deleting");
                File.Delete(GetFullPath(o));
            }

            if (error)
            {
                return(false);
            }

            Logger.WriteLine(name.fullName + " manifest loaded");
            _files.Clear();
            foreach (var f in manifest.FilesAndRequirements())
            {
                _files.Add(f.Key, f.Value);
            }
            return(true);
        }
        private Plugin AddLocallyCompiled(PluginBuilder builder)
        {
            PluginName name = new PluginName(builder.author, builder.repository);
            Plugin     plugin;

            if (!_data.TryGetDownloaded(name, out plugin))
            {
                plugin = new Plugin(_directory, new PluginConfig(name, true));
            }
            else
            {
                plugin.EraseAllFiles();
            }

            plugin.version = builder.version;
            Logger.WriteLine("plugin: " + name.fullName + ", compiled version: " + plugin.version);

            plugin.requiredPlugins = builder.requires;

            Directory.CreateDirectory(plugin.directory);

            foreach (var fileSource in builder.files)
            {
                string fileDestination = fileSource.targetFolder == null?
                                         PathExtensions.Combine(plugin.directory, Path.GetFileName(fileSource.source)) :
                                             PathExtensions.Combine(plugin.directory, fileSource.targetFolder, Path.GetFileName(fileSource.source));

                if (!Path.GetFullPath(fileDestination).StartsWith(plugin.directory))
                {
                    throw new Exception(Path.GetFullPath(fileDestination) + " is outside of plugin's directory");
                }

                Logger.WriteLine("Copy: " + fileSource.source + " to " + fileDestination);
                Directory.CreateDirectory(Path.GetDirectoryName(fileDestination));
                File.Copy(fileSource.source, fileDestination, true);
                plugin.AddFile(fileDestination, fileSource.requires);
            }

            plugin.locallyCompiled = true;

            _data.AddConfig(plugin.config);
            _data.AddDownloaded(plugin);

            if (name.author == "Rynchodon" && name.repository == SeplRepo)
            {
                Robocopy();
            }

            return(plugin);
        }
        private GitChecks(PluginBuilder builder, string pathToGit)
        {
            this._builder   = builder;
            this._pathToGit = pathToGit;

            foreach (string path in PathExtensions.PathsToRoot(builder.files.First().source))
            {
                string gitDirectory = PathExtensions.Combine(path, ".git");
                if (Directory.Exists(gitDirectory))
                {
                    _repoDirectory = path;
                    break;
                }
            }
        }
        /// <summary>
        /// Get the commit hash of local head.
        /// </summary>
        /// <returns>The commit hash of local head.</returns>
        private string LocalHead()
        {
            string headPath = PathExtensions.Combine(_repoDirectory, ".git", "HEAD");
            string head;

            using (StreamReader reader = new StreamReader(headPath))
                head = reader.ReadLine();

            const string refstring = "ref: ";

            if (head.StartsWith(refstring))
            {
                headPath = PathExtensions.Combine(_repoDirectory, ".git", head.Substring(refstring.Length));
                using (StreamReader reader = new StreamReader(headPath))
                    head = reader.ReadLine();
            }

            return(head);
        }
Пример #5
0
        internal void Publish(Plugin plugin, PluginBuilder pluginBuilder)
        {
            if (!HasOAuthToken)
            {
                throw new ArgumentException("Need oAuthToken");
            }

            CreateRelease release = new CreateRelease(plugin.version, pluginBuilder.release);

            string zipFileName;

            if (pluginBuilder.zipFileName != null)
            {
                zipFileName = Path.GetFileName(pluginBuilder.zipFileName);
            }
            else
            {
                zipFileName = plugin.name.repository;
            }

            if (!zipFileName.EndsWith(".zip"))
            {
                zipFileName = zipFileName + ".zip";
            }

            string zipFilePath = PathExtensions.Combine(plugin.directory, zipFileName);

            try
            {
                plugin.Zip(zipFilePath);
                if (PublishRelease(release, zipFilePath))
                {
                    MessageBox.Show("Release posted");
                }
            }
            finally
            {
                if (File.Exists(zipFilePath))
                {
                    File.Delete(zipFilePath);
                }
            }
        }
Пример #6
0
        private string SearchForGit()
        {
            HashSet <string> searchLocations = new HashSet <string>();

            foreach (string envPath in Environment.GetEnvironmentVariable("PATH").Split(';'))
            {
                if (string.IsNullOrWhiteSpace(envPath))
                {
                    Logger.WriteLine("empty string in PATH");
                }
                else
                {
                    searchLocations.Add(envPath);
                }
            }

            foreach (string envVar in new string[] { "ProgramFiles", "ProgramFiles(x86)", "ProgramW6432" })
            {
                string path = Environment.GetEnvironmentVariable(envVar);
                if (string.IsNullOrWhiteSpace(path))
                {
                    Logger.WriteLine("No environment variable: " + envVar);
                }
                else
                {
                    searchLocations.Add(PathExtensions.Combine(path, "Git", "bin"));
                    searchLocations.Add(PathExtensions.Combine(path, "Git", "cmd"));
                }
            }

            foreach (string location in searchLocations)
            {
                string gitExe = PathExtensions.Combine(location, "git.exe");
                if (File.Exists(gitExe))
                {
                    Logger.WriteLine("git @ " + gitExe);
                    return(gitExe);
                }
            }
            return(null);
        }
        /// <summary>
        /// Update PluginLoader.dll and PluginManager.exe from download folder using robocopy.
        /// </summary>
        private void Robocopy()
        {
            if (_instance != this || _startedRobocopy)
            {
                return;
            }
            _startedRobocopy = true;

            PluginName seplName         = new PluginName("Rynchodon", SeplRepo);
            string     seplDownloadPath = PathExtensions.Combine(_directory, "plugin", seplName.fullName);

            string license = PathExtensions.Combine(seplDownloadPath, "License.rtf");

            if (File.Exists(license))
            {
                File.Copy(license, PathExtensions.Combine(_directory, "License.rtf"), true);
            }

            string readme = PathExtensions.Combine(seplDownloadPath, "Readme.txt");

            if (File.Exists(readme))
            {
                File.Copy(readme, PathExtensions.Combine(_directory, "Readme.txt"), true);
            }

            Logger.WriteLine("starting robocopy");

            string first = '"' + seplDownloadPath + "\" \"";

            string copyDll = first + _directory + "\" " + Dll + " /COPY:DATSO /W:1 /xx";
            string copyExe = first + _directory + "\" " + Exe + " /COPY:DATSO /W:1 /xx";

            Process robocopy = new Process();

            robocopy.StartInfo.FileName    = "cmd.exe";
            robocopy.StartInfo.Arguments   = "/C robocopy " + copyDll + " & robocopy " + copyExe;
            robocopy.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            robocopy.Start();
        }
Пример #8
0
        /// <summary>
        /// Download an update for a plugin.
        /// </summary>
        /// <returns>True iff the plugin was updated.</returns>
        internal bool Update(Plugin plugin)
        {
            Release[] releases = GetReleases();
            if (releases == null)
            {
                // already complained about it in depth
                return(false);
            }

            int seVersion = Loader.GetCurrentSeVersion();

            Release mostRecent = null;

            foreach (Release rel in releases)
            {
                if (rel.draft)
                {
                    continue;
                }
                if (rel.prerelease && !plugin.config.downloadPrerelease)
                {
                    continue;
                }

                // skip if release was compiled with a newer version of SE
                if (seVersion < rel.version.SeVersion)
                {
                    continue;
                }

                if (mostRecent == null || mostRecent.version.CompareTo(rel.version) < 0)
                {
                    mostRecent = rel;
                }
            }

            if (mostRecent == null)
            {
                Logger.WriteLine("ERROR: No available releases");
                return(false);
            }

            Logger.WriteLine("Latest release version: " + mostRecent.version + ", Current version: " + plugin.version);

            int relative = mostRecent.version.CompareTo(plugin.version);

            if (relative == 0)
            {
                Logger.WriteLine("Up-to-date: " + plugin.version);
                return(false);
            }
            if (relative < 0)             // current version is newer than latest release
            {
                if (plugin.locallyCompiled)
                {
                    Logger.WriteLine("Keeping locally compiled version: " + plugin.version);
                    return(false);
                }
                Logger.WriteLine("Roll back version: " + plugin.version + " to " + mostRecent.version);
            }

            if (mostRecent.assets == null || mostRecent.assets.Length == 0)
            {
                Logger.WriteLine("ERROR: Release has no assets");
                return(false);
            }

            // warn if a locally compiled version is going to be replaced by a downloaded version
            if (plugin.locallyCompiled && MessageBox.Show("Plugin: " + plugin.name.fullName + "\nLocally compiled version: " + plugin.version + "\nLatest release version: " + mostRecent.version + "\n\nOverwrite locally compiled plugin?", "Warning", MessageBoxButtons.YesNo) == DialogResult.No)
            {
                Logger.WriteLine("Not overwriting locally compiled plugin");
                return(false);
            }

            plugin.EraseAllFiles();

            Logger.WriteLine("Downloading version: " + mostRecent.version);

            Directory.CreateDirectory(plugin.directory);

            string targetAssetName = plugin.assetFileName;

            if (targetAssetName != null)
            {
                bool found = false;
                foreach (Release.Asset asset in mostRecent.assets)
                {
                    if (asset.name == targetAssetName)
                    {
                        Logger.WriteLine("Target asset: " + targetAssetName);
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    targetAssetName = null;
                }
            }

            foreach (Release.Asset asset in mostRecent.assets)
            {
                // If an asset file name has been specified and it exists, only download that asset. Otherwise, download all assets.
                if (targetAssetName != null && asset.name != targetAssetName)
                {
                    Logger.WriteLine("Not downloading: " + asset.name);
                    continue;
                }

                Logger.WriteLine("Downloading asset: " + asset.name);
                HttpWebRequest request = WebRequest.CreateHttp(asset.browser_download_url);
                request.Accept    = "application/octet-stream";
                request.UserAgent = _userAgent;

                WebResponse response         = request.GetResponse();
                Stream      responseStream   = response.GetResponseStream();
                string      assetDestination = PathExtensions.Combine(plugin.directory, asset.name);
                if (!PathExtensions.IsInPath(assetDestination, plugin.directory))
                {
                    Logger.WriteLine("Access denied: " + assetDestination);
                    continue;
                }

                if (asset.name.EndsWith(".zip"))
                {
                    try
                    {
                        using (FileStream zipFile = new FileStream(assetDestination, FileMode.CreateNew))
                            responseStream.CopyTo(zipFile);

                        Logger.WriteLine("Unpacking: " + asset.name);
                        using (ZipArchive archive = ZipFile.OpenRead(assetDestination))
                            foreach (ZipArchiveEntry entry in archive.Entries)
                            {
                                string entryDestination = PathExtensions.Combine(plugin.directory, entry.FullName);
                                if (!PathExtensions.IsInPath(entryDestination, plugin.directory))
                                {
                                    Logger.WriteLine("Access denied: " + entryDestination);
                                    continue;
                                }

                                Directory.CreateDirectory(Path.GetDirectoryName(entryDestination));

                                if (File.Exists(entryDestination))
                                {
                                    Logger.WriteLine("WARNING: File exists: " + entry.FullName + ", it will not be extracted from " + asset.name);
                                }
                                else
                                {
                                    try
                                    {
                                        entry.ExtractToFile(entryDestination);
                                        Logger.WriteLine("Unpacked entry: " + entry.FullName);
                                    }
                                    catch (Exception ex)
                                    {
                                        Logger.WriteLine(ex.Message);
                                        Logger.WriteLine("Failed to unpack: " + entry.FullName);
                                        if (File.Exists(entryDestination))
                                        {
                                            File.Delete(entryDestination);
                                        }
                                        continue;
                                    }
                                    plugin.AddFile(entryDestination);
                                }
                            }
                    }
                    finally
                    {
                        if (File.Exists(assetDestination))
                        {
                            File.Delete(assetDestination);
                        }
                    }
                }
                else
                {
                    if (File.Exists(assetDestination))
                    {
                        Logger.WriteLine("WARNING: File exists: " + asset.name + ", it will not be downloaded");
                    }
                    else
                    {
                        using (FileStream file = new FileStream(assetDestination, FileMode.CreateNew))
                            responseStream.CopyTo(file);
                        plugin.AddFile(assetDestination);
                    }
                }

                responseStream.Dispose();
                response.Dispose();
            }

            if (!plugin.LoadManifest())
            {
                Logger.WriteLine("Failed to load manifest");
                return(false);
            }

            plugin.version         = mostRecent.version;
            plugin.locallyCompiled = false;

            return(true);
        }
 private string GetFullPath(string relativePath)
 {
     return(PathExtensions.Combine(directory, relativePath));
 }
 public Plugin(string seplDirectory, PluginConfig config)
 {
     this.config    = config;
     this.directory = PathExtensions.Combine(seplDirectory, "plugin", name.fullName);
 }
Пример #11
0
 private string GetFilePath()
 {
     return(PathExtensions.Combine(_directory, fileName));
 }