Example #1
0
 public Local(ILogger logger, string overrideRootPath = null)
 {
     _repo        = overrideRootPath ?? LocalHelpers.GetRootDir(GitExecutable, logger);
     _logger      = logger;
     _gitClient   = new LocalGitClient(GitExecutable, _logger);
     _fileManager = new GitFileManager(_gitClient, _logger);
 }
        /// <summary>
        ///     Updates local copies of the files.
        /// </summary>
        /// <param name="filesToCommit">Files to update locally</param>
        /// <param name="repoUri">Base path of the repo</param>
        /// <param name="branch">Unused</param>
        /// <param name="commitMessage">Unused</param>
        /// <returns></returns>
        public async Task CommitFilesAsync(List <GitFile> filesToCommit, string repoUri, string branch, string commitMessage)
        {
            string repoDir = LocalHelpers.GetRootDir(_gitExecutable, _logger);

            try
            {
                using (LibGit2Sharp.Repository localRepo = new LibGit2Sharp.Repository(repoDir))
                {
                    foreach (GitFile file in filesToCommit)
                    {
                        switch (file.Operation)
                        {
                        case GitFileOperation.Add:
                            string parentDirectory = Directory.GetParent(file.FilePath).FullName;

                            if (!Directory.Exists(parentDirectory))
                            {
                                Directory.CreateDirectory(parentDirectory);
                            }

                            string fullPath = Path.Combine(repoUri, file.FilePath);
                            using (var streamWriter = new StreamWriter(fullPath))
                            {
                                string finalContent;
                                switch (file.ContentEncoding)
                                {
                                case ContentEncoding.Utf8:
                                    finalContent = file.Content;
                                    break;

                                case ContentEncoding.Base64:
                                    byte[] bytes = Convert.FromBase64String(file.Content);
                                    finalContent = Encoding.UTF8.GetString(bytes);
                                    break;

                                default:
                                    throw new DarcException($"Unknown file content encoding {file.ContentEncoding}");
                                }
                                finalContent = NormalizeLineEndings(fullPath, finalContent);
                                await streamWriter.WriteAsync(finalContent);

                                LibGit2SharpHelpers.AddFileToIndex(localRepo, file, fullPath, _logger);
                            }
                            break;

                        case GitFileOperation.Delete:
                            if (File.Exists(file.FilePath))
                            {
                                File.Delete(file.FilePath);
                            }
                            break;
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                throw new DarcException($"Something went wrong when checking out {repoUri} in {repoDir}", exc);
            }
        }
Example #3
0
        public override async Task <int> ExecuteAsync()
        {
            DependencyType type = _options.Type.ToLower() == "toolset" ? DependencyType.Toolset : DependencyType.Product;

            Local local = new Local(LocalHelpers.GetGitDir(Logger), Logger);

            DependencyDetail dependency = new DependencyDetail
            {
                Name    = _options.Name,
                Version = _options.Version ?? string.Empty,
                RepoUri = _options.RepoUri ?? string.Empty,
                Commit  = _options.Commit ?? string.Empty
            };

            try
            {
                await local.AddDependencyAsync(dependency, type);

                return(Constants.SuccessCode);
            }
            catch (Exception exc)
            {
                Logger.LogError(exc, $"Failed to add dependency '{dependency.Name}' to repository.");
                return(Constants.ErrorCode);
            }
        }
        public override async Task <int> ExecuteAsync()
        {
            try
            {
                Local local = new Local(LocalHelpers.GetGitDir(Logger), Logger);
                IEnumerable <DependencyDetail> dependencies = await local.GetDependenciesAsync(
                    _options.AssetName);

                DarcSettings darcSettings = null;

                if (_options.Remote)
                {
                    if (string.IsNullOrEmpty(_options.RepoUri))
                    {
                        Logger.LogError("If '--remote' is set '--repo-uri' is required.");

                        return(Constants.ErrorCode);
                    }

                    darcSettings = LocalSettings.GetDarcSettings(
                        _options,
                        Logger,
                        _options.RepoUri);
                    Remote remote = new Remote(darcSettings, Logger);
                    dependencies = await remote.GetDependenciesAsync(
                        _options.RepoUri,
                        _options.Branch,
                        _options.AssetName);
                }

                List <DependencyGraph> graph = await CreateGraphAsync(dependencies, darcSettings);

                if (graph == null)
                {
                    return(Constants.ErrorCode);
                }

                if (_options.Flat)
                {
                    LogFlatDependencyGraph(graph);
                }
                else
                {
                    LogDependencyGraph(graph);
                }

                return(Constants.SuccessCode);
            }
            catch (Exception exc)
            {
                Logger.LogError(exc, "Something failed while getting the dependency graph.");

                return(Constants.ErrorCode);
            }
        }
Example #5
0
        private static string GetRepoPath(
            string repoUri,
            string commit,
            IEnumerable <string> remotesMap,
            string reposFolder,
            ILogger logger,
            string gitExecutable)
        {
            string repoPath = null;

            if (remotesMap != null)
            {
                if (_remotesMapping == null)
                {
                    _remotesMapping = CreateRemotesMapping(remotesMap);
                }

                if (!_remotesMapping.ContainsKey(repoPath))
                {
                    throw new DarcException($"A key matching '{repoUri}' was not " +
                                            $"found in the mapping. Please make sure to include it...");
                }

                repoPath = _remotesMapping[repoPath];
            }
            else
            {
                string folder = null;

                if (!string.IsNullOrEmpty(reposFolder))
                {
                    folder = reposFolder;
                }
                else
                {
                    // If a repo folder or a mapping was not set we use the current parent's
                    // parent folder.
                    string parent = LocalHelpers.GetRootDir(gitExecutable, logger);
                    folder = Directory.GetParent(parent).FullName;
                }

                repoPath = LocalHelpers.GetRepoPathFromFolder(gitExecutable, folder, commit, logger);

                if (string.IsNullOrEmpty(repoPath))
                {
                    throw new DarcException($"Commit '{commit}' was not found in any " +
                                            $"folder in '{folder}'. Make sure a folder for '{repoUri}' exists " +
                                            $"and it has all the latest changes...");
                }
            }

            return(repoPath);
        }
Example #6
0
 public JsonResult Delete(int id)
 {
     try
     {
         core.DeleteProducto(id);
         LocalHelpers.ShowDataDeleteSuccessMessage();
         return(Json(new { result = "Ok" }, JsonRequestBehavior.AllowGet));
     }
     catch (Exception ex)
     {
         LocalHelpers.ShowMessage("Ocurrio el siguiente error: " + ex, MessageType.Error);
         return(Json(new { result = string.Format("Err:{0}", ex.Message) }, JsonRequestBehavior.AllowGet));
     }
 }
 public JsonResult Delete(String tipoDocumento, String numeroDocumento)
 {
     try
     {
         core.DeleteRestaurante(tipoDocumento, numeroDocumento);
         LocalHelpers.ShowDataDeleteSuccessMessage();
         return(Json(new { result = "Ok" }, JsonRequestBehavior.AllowGet));
     }
     catch (Exception ex)
     {
         LocalHelpers.ShowMessage("Ocurrio el siguiente error: " + ex, MessageType.Error);
         return(Json(new { result = string.Format("Err:{0}", ex.Message) }, JsonRequestBehavior.AllowGet));
     }
 }
        public Task <List <GitFile> > GetFilesAtCommitAsync(string repoUri, string commit, string path)
        {
            string repoDir      = LocalHelpers.GetRootDir(_gitExecutable, _logger);
            string sourceFolder = Path.Combine(repoDir, path);

            return(Task.Run(() => Directory.GetFiles(
                                sourceFolder,
                                "*.*",
                                SearchOption.AllDirectories).Select(
                                file =>
            {
                return new GitFile(
                    file.Remove(0, repoDir.Length + 1).Replace("\\", "/"),
                    File.ReadAllText(file)
                    );
            }
                                ).ToList()));
        }
Example #9
0
        public override async Task <int> ExecuteAsync()
        {
            Local local = new Local(LocalHelpers.GetGitDir(Logger), Logger);

            try
            {
                IEnumerable <DependencyDetail> dependencies = await local.GetDependenciesAsync(_options.Name);

                if (!string.IsNullOrEmpty(_options.Name))
                {
                    DependencyDetail dependency = dependencies.Where(d => d.Name.Equals(_options.Name, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();

                    if (dependency == null)
                    {
                        throw new Exception($"A dependency with name '{_options.Name}' was not found...");
                    }

                    LogDependency(dependency);
                }

                foreach (DependencyDetail dependency in dependencies)
                {
                    LogDependency(dependency);

                    Console.WriteLine();
                }

                return(Constants.SuccessCode);
            }
            catch (Exception exc)
            {
                if (!string.IsNullOrEmpty(_options.Name))
                {
                    Logger.LogError(exc, $"Something failed while querying for local dependency '{_options.Name}'.");
                }
                else
                {
                    Logger.LogError(exc, "Something failed while querying for local dependencies.");
                }

                return(Constants.ErrorCode);
            }
        }
        /// <summary>
        /// Verify that the repository has a correct dependency structure.
        /// </summary>
        /// <param name="options">Command line options</param>
        /// <returns>Process exit code.</returns>
        public override async Task <int> ExecuteAsync()
        {
            Local local = new Local(LocalHelpers.GetGitDir(Logger), Logger);

            try
            {
                if (!(await local.Verify()))
                {
                    Console.WriteLine("Dependency verification failed.");
                    return(Constants.ErrorCode);
                }
                Console.WriteLine("Dependency verification succeeded.");
                return(Constants.SuccessCode);
            }
            catch (Exception e)
            {
                Logger.LogError(e, "Error: Failed to verify repository dependency state.");
                return(Constants.ErrorCode);
            }
        }
Example #11
0
        public ActionResult Edit(ProductoModel model)
        {
            try
            {
                if (model.ProductoId > 0)
                {
                    //core.ModifyProducto(model);
                    LocalHelpers.ShowDataUpdateSuccessMessage();
                }
                else
                {
                    core.AddProducto(model);
                    LocalHelpers.ShowDataInsertSuccessMessage();
                }
            }
            catch (Exception ex)
            {
                LocalHelpers.ShowMessage(ex.Message, MessageType.Error);
            }

            return(RedirectToAction("Index"));
        }
        /// <summary>
        /// Normalize line endings of content.
        /// </summary>
        /// <param name="filePath">Path of file</param>
        /// <param name="content">Content to normalize</param>
        /// <returns>Normalized content</returns>
        /// <remarks>
        ///     Normalize based on the following rules:
        ///     - Auto CRLF is assumed.
        ///     - Check the git attributes the file to determine whether it has a specific setting for the file.  If so, use that.
        ///     - If no setting, or if auto, then determine whether incoming content differs in line ends vs. the
        ///       OS setting, and replace if needed.
        /// </remarks>
        private string NormalizeLineEndings(string filePath, string content)
        {
            const string crlf = "\r\n";
            const string lf   = "\n";
            // Check gitAttributes to determine whether the file has eof handling set.
            string eofAttr = LocalHelpers.ExecuteCommand(_gitExecutable, $"check-attr eol -- {filePath}", _logger);

            if (string.IsNullOrEmpty(eofAttr) ||
                eofAttr.Contains("eol: unspecified") ||
                eofAttr.Contains("eol: auto"))
            {
                if (Environment.NewLine != crlf)
                {
                    return(content.Replace(crlf, Environment.NewLine));
                }
                else if (Environment.NewLine == crlf && !content.Contains(crlf))
                {
                    return(content.Replace(lf, Environment.NewLine));
                }
            }
            else if (eofAttr.Contains("eol: crlf"))
            {
                // Test to avoid adding extra \r.
                if (!content.Contains(crlf))
                {
                    return(content.Replace(lf, crlf));
                }
            }
            else if (eofAttr.Contains("eol: lf"))
            {
                return(content.Replace(crlf, lf));
            }
            else
            {
                throw new DarcException($"Unknown eof setting '{eofAttr}' for file '{filePath};");
            }
            return(content);
        }
Example #13
0
        public override async Task <int> ExecuteAsync()
        {
            try
            {
                IEnumerable <DependencyDetail> rootDependencies = null;
                DependencyGraph graph;
                RemoteFactory   remoteFactory = new RemoteFactory(_options);

                if (!_options.Local)
                {
                    NodeDiff diffOption = NodeDiff.None;
                    // Check node diff options
                    switch (_options.DeltaFrom.ToLowerInvariant())
                    {
                    case "none":
                        break;

                    case "newest-in-channel":
                        diffOption = NodeDiff.LatestInChannel;
                        break;

                    case "newest-in-graph":
                        diffOption = NodeDiff.LatestInGraph;
                        break;

                    default:
                        Console.WriteLine("Unknown --delta-from option, please see help.");
                        return(Constants.ErrorCode);
                    }

                    // If the repo uri and version are set, then call the graph
                    // build operation based on those.  Both should be set in this case.
                    // If they are not set, then gather the initial set based on the local repository,
                    // and then call the graph build with that root set.

                    if (!string.IsNullOrEmpty(_options.RepoUri))
                    {
                        if (string.IsNullOrEmpty(_options.Version))
                        {
                            Console.WriteLine("If --repo is set, --version should be supplied");
                            return(Constants.ErrorCode);
                        }

                        Console.WriteLine($"Getting root dependencies from {_options.RepoUri}@{_options.Version}...");

                        // Grab root dependency set. The graph build can do this, but
                        // if an original asset name is passed, then this will do the initial filtering.
                        IRemote rootRepoRemote = await remoteFactory.GetRemoteAsync(_options.RepoUri, Logger);

                        rootDependencies = await rootRepoRemote.GetDependenciesAsync(
                            _options.RepoUri,
                            _options.Version,
                            _options.AssetName);
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(_options.Version))
                        {
                            Console.WriteLine("If --version is supplied, then --repo is required");
                            return(Constants.ErrorCode);
                        }

                        Console.WriteLine($"Getting root dependencies from local repository...");

                        // Grab root dependency set from local repo
                        Local local = new Local(Logger);
                        rootDependencies = await local.GetDependenciesAsync(
                            _options.AssetName);
                    }

                    Console.WriteLine($"Building repository dependency graph...");

                    rootDependencies = FilterToolsetDependencies(rootDependencies);

                    if (!rootDependencies.Any())
                    {
                        Console.WriteLine($"No root dependencies found, exiting.");
                        return(Constants.ErrorCode);
                    }

                    DependencyGraphBuildOptions graphBuildOptions = new DependencyGraphBuildOptions()
                    {
                        IncludeToolset = _options.IncludeToolset,
                        LookupBuilds   = diffOption != NodeDiff.None || !_options.SkipBuildLookup,
                        NodeDiff       = diffOption
                    };

                    // Build graph
                    graph = await DependencyGraph.BuildRemoteDependencyGraphAsync(
                        remoteFactory,
                        rootDependencies,
                        _options.RepoUri ?? LocalHelpers.GetRootDir(Logger),
                        _options.Version ?? LocalHelpers.GetGitCommit(Logger),
                        graphBuildOptions,
                        Logger);
                }
                else
                {
                    Console.WriteLine($"Getting root dependencies from local repository...");

                    Local local = new Local(Logger);
                    rootDependencies = await local.GetDependenciesAsync(
                        _options.AssetName);

                    rootDependencies = FilterToolsetDependencies(rootDependencies);

                    if (!rootDependencies.Any())
                    {
                        Console.WriteLine($"No root dependencies found, exiting.");
                        return(Constants.ErrorCode);
                    }

                    Console.WriteLine($"Building repository dependency graph from local information...");

                    DependencyGraphBuildOptions graphBuildOptions = new DependencyGraphBuildOptions()
                    {
                        IncludeToolset = _options.IncludeToolset,
                        LookupBuilds   = false,
                        NodeDiff       = NodeDiff.None
                    };

                    // Build graph using only local resources
                    graph = await DependencyGraph.BuildLocalDependencyGraphAsync(
                        rootDependencies,
                        graphBuildOptions,
                        Logger,
                        LocalHelpers.GetRootDir(Logger),
                        LocalHelpers.GetGitCommit(Logger),
                        _options.ReposFolder,
                        _options.RemotesMap);
                }

                if (_options.Flat)
                {
                    await LogFlatDependencyGraph(graph);
                }
                else
                {
                    await LogDependencyGraph(graph);
                }

                if (!string.IsNullOrEmpty(_options.GraphVizOutputFile))
                {
                    await LogGraphViz(graph);
                }

                return(Constants.SuccessCode);
            }
            catch (Exception exc)
            {
                Logger.LogError(exc, "Something failed while getting the dependency graph.");
                return(Constants.ErrorCode);
            }
        }
Example #14
0
 public UxManager(string gitLocation, ILogger logger)
 {
     _editorPath = LocalHelpers.GetEditorPath(gitLocation, logger);
     _rootDir    = LocalHelpers.GetRootDir(gitLocation, logger);
     _logger     = logger;
 }
Example #15
0
        /// <summary>
        /// Cloning big repos takes a considerable amount of time when checking out the files. When
        /// working on batched subscription, the operation could take more than an hour causing the
        /// GitHub token to expire. By doing sparse and shallow checkout, we only deal with the files
        /// we need avoiding to check the complete repo shaving time from the overall push process
        /// </summary>
        /// <param name="filesToCommit">Collection of files to update.</param>
        /// <param name="repoUri">The repository to push the files to.</param>
        /// <param name="branch">The branch to push the files to.</param>
        /// <param name="commitMessage">The commmit message.</param>
        /// <returns></returns>
        protected async Task CommitFilesAsync(
            List <GitFile> filesToCommit,
            string repoUri,
            string branch,
            string commitMessage,
            ILogger logger,
            string pat,
            string dotnetMaestroName,
            string dotnetMaestroEmail)
        {
            logger.LogInformation("Pushing files to {branch}", branch);
            string tempRepoFolder = Path.Combine(TemporaryRepositoryPath, Path.GetRandomFileName());
            string remote         = "origin";

            try
            {
                string clonedRepo = null;

                logger.LogInformation("Sparse and shallow checkout of branch {branch} in {repoUri}...", branch, repoUri);
                clonedRepo = LocalHelpers.SparseAndShallowCheckout(GitExecutable, repoUri, branch, tempRepoFolder, logger, remote, dotnetMaestroName, dotnetMaestroEmail, pat);

                foreach (GitFile file in filesToCommit)
                {
                    string filePath = Path.Combine(clonedRepo, file.FilePath);

                    if (file.Operation == GitFileOperation.Add)
                    {
                        if (!File.Exists(filePath))
                        {
                            string parentFolder = Directory.GetParent(filePath).FullName;

                            Directory.CreateDirectory(parentFolder);
                        }

                        using (FileStream stream = File.Create(filePath))
                        {
                            byte[] contentBytes = GetUtf8ContentBytes(file.Content, file.ContentEncoding);
                            await stream.WriteAsync(contentBytes, 0, contentBytes.Length);
                        }
                    }
                    else if (file.Operation == GitFileOperation.Delete)
                    {
                        File.Delete(filePath);
                    }

                    LocalHelpers.ExecuteCommand(GitExecutable, $"add {filePath}", logger, clonedRepo);
                }

                LocalHelpers.ExecuteCommand(GitExecutable, $"commit -m \"{commitMessage}\"", logger, clonedRepo);
                LocalHelpers.ExecuteCommand(GitExecutable, $"-c core.askpass= -c credential.helper= push {remote} {branch}", logger, clonedRepo);
            }
            catch (Exception exc)
            {
                // This was originally a DarcException. Making it an actual Exception so we get to see in AppInsights if something failed while
                // commiting the changes
                throw new Exception($"Something went wrong when pushing the files to repo {repoUri} in branch {branch}", exc);
            }
            finally
            {
                try
                {
                    // .git/objects hierarchy are marked as read-only so we need to unset the read-only attribute otherwise an UnauthorizedAccessException is thrown.
                    GitFileManager.NormalizeAttributes(tempRepoFolder);
                    Directory.Delete(tempRepoFolder, true);
                }
                catch (DirectoryNotFoundException)
                {
                    // If the directory wasn't found, that means that the clone operation above failed
                    // but this error isn't interesting at all.
                }
                catch (Exception exc)
                {
                    throw new Exception($"Something went wrong while trying to delete the folder {tempRepoFolder}", exc);
                }
            }
        }
        private static async Task <IEnumerable <DependencyDetail> > GetDependenciesAsync(
            IRemoteFactory remoteFactory,
            bool remote,
            ILogger logger,
            string repoUri,
            string commit,
            bool includeToolset,
            IEnumerable <string> remotesMap,
            string reposFolder,
            string testPath = null)
        {
            try
            {
                IEnumerable <DependencyDetail> dependencies = null;

                if (!string.IsNullOrEmpty(testPath))
                {
                    testPath = Path.Combine(
                        testPath,
                        repoUri,
                        commit);

                    if (Directory.Exists(testPath))
                    {
                        Local local = new Local(logger, testPath);
                        dependencies = await local.GetDependenciesAsync();
                    }
                }
                else if (remote)
                {
                    IRemote remoteClient = await remoteFactory.GetRemoteAsync(repoUri, logger);

                    dependencies = await remoteClient.GetDependenciesAsync(
                        repoUri,
                        commit);
                }
                else
                {
                    string repoPath = GetRepoPath(repoUri, commit, remotesMap, reposFolder, logger);

                    if (!string.IsNullOrEmpty(repoPath))
                    {
                        Local  local        = new Local(logger);
                        string fileContents = LocalHelpers.GitShow(
                            repoPath,
                            commit,
                            VersionFiles.VersionDetailsXml,
                            logger);
                        dependencies = local.GetDependenciesFromFileContents(fileContents);
                    }
                }

                if (!includeToolset)
                {
                    dependencies = dependencies.Where(dependency => dependency.Type != DependencyType.Toolset);
                }
                return(dependencies);
            }
            catch (DependencyFileNotFoundException)
            {
                // This is not an error. Dependencies can be specified with explicit shas that
                // may not have eng/Version.Details.xml at that point.
                logger.LogWarning($"{repoUri}@{commit} does not have an eng/Version.Details.xml.");
                return(null);
            }
            catch (Exception exc)
            {
                logger.LogError(exc, $"Something failed while trying the fetch the " +
                                $"dependencies of repo '{repoUri}' at sha " +
                                $"'{commit}'");
                throw;
            }
        }
Example #17
0
        public void Start()
        {
            // log version
            Lib.Log("Version : " + Lib.KerbalismVersion + " - Build : " + Lib.KerbalismDevBuild);

            if (LocalHelpers.GenerateEnglishLoc)
            {
                LocalHelpers.GenerateLoc();
            }

            if (LocalHelpers.UpdateNonEnglishLoc)
            {
                LocalHelpers.RegenerateNonEnglishLoc();
            }

            Lib.Log("Forcing KSP to load resources...");
            PartResourceLibrary.Instance.LoadDefinitions();

            // parse settings
            Settings.Parse();
            // parse profile
            Profile.Parse();
            // detect features
            Features.Detect();

            // get configs from DB
            UrlDir.UrlFile root = null;
            foreach (UrlDir.UrlConfig url in GameDatabase.Instance.root.AllConfigs)
            {
                root = url.parent; break;
            }

            // inject MM patches on-the-fly, so that profile/features can be queried with NEEDS[]
            Inject(root, "Profile", Lib.UppercaseFirst(Settings.Profile));
            if (Features.Reliability)
            {
                Inject(root, "Feature", "Reliability");
            }
            if (Features.Deploy)
            {
                Inject(root, "Feature", "Deploy");
            }
            if (Features.SpaceWeather)
            {
                Inject(root, "Feature", "SpaceWeather");
            }
            if (Features.Automation)
            {
                Inject(root, "Feature", "Automation");
            }
            if (Features.Science)
            {
                Inject(root, "Feature", "Science");
            }
            if (Features.Radiation)
            {
                Inject(root, "Feature", "Radiation");
            }
            if (Features.Shielding)
            {
                Inject(root, "Feature", "Shielding");
            }
            if (Features.LivingSpace)
            {
                Inject(root, "Feature", "LivingSpace");
            }
            if (Features.Comfort)
            {
                Inject(root, "Feature", "Comfort");
            }
            if (Features.Poisoning)
            {
                Inject(root, "Feature", "Poisoning");
            }
            if (Features.Pressure)
            {
                Inject(root, "Feature", "Pressure");
            }
            if (Features.Habitat)
            {
                Inject(root, "Feature", "Habitat");
            }
            if (Features.Supplies)
            {
                Inject(root, "Feature", "Supplies");
            }

            // inject harmony patches
            Harmony harmony = new Harmony("Kerbalism");

            harmony.PatchAll(Assembly.GetExecutingAssembly());
            var methods = harmony.GetPatchedMethods();

            // register loading callbacks
            if (HighLogic.LoadedScene == GameScenes.LOADING)
            {
                GameEvents.OnPartLoaderLoaded.Add(SaveHabitatData);
            }
        }
        private static string GetRepoPath(
            DependencyDetail dependency,
            IEnumerable <string> remotesMap,
            string reposFolder,
            ILogger logger)
        {
            string repoPath = null;

            if (remotesMap != null)
            {
                if (_remotesMapping == null)
                {
                    _remotesMapping = CreateRemotesMapping(remotesMap);
                }

                if (!_remotesMapping.ContainsKey(repoPath))
                {
                    throw new DarcException($"A key matching '{dependency.RepoUri}' was not " +
                                            $"found in the mapping. Please make sure to include it...");
                }

                repoPath = _remotesMapping[repoPath];
            }
            else
            {
                string folder = null;

                if (!string.IsNullOrEmpty(reposFolder))
                {
                    folder = reposFolder;
                }
                else
                {
                    // If a repo folder or a mapping was not set we use the current parent's
                    // parent folder.
                    string gitDir = LocalHelpers.GetGitDir(logger);
                    string parent = Directory.GetParent(gitDir).FullName;
                    folder = Directory.GetParent(parent).FullName;
                }

                // There are cases when the sha is not specified in Version.Details.xml
                // since owners want that Maestro++ fills this in. Without a sha we
                // cannot walk the graph. We do not fail the process but display/return
                // a dependency with no sha and for that graph path that would be the end of the walk
                if (string.IsNullOrEmpty(dependency.Commit))
                {
                    return(null);
                }

                repoPath = LocalHelpers.GetRepoPathFromFolder(folder, dependency.Commit, logger);

                if (string.IsNullOrEmpty(repoPath))
                {
                    throw new DarcException($"Commit '{dependency.Commit}' was not found in any " +
                                            $"folder in '{folder}'. Make sure a folder for '{dependency.RepoUri}' exists " +
                                            $"and it has all the latest changes...");
                }
            }

            return(repoPath);
        }
        private static async Task <IEnumerable <DependencyDetail> > GetDependenciesAsync(
            DarcSettings darcSettings,
            bool remote,
            ILogger logger,
            DependencyGraphNode node,
            IEnumerable <string> remotesMap,
            string reposFolder,
            string testPath = null)
        {
            try
            {
                IEnumerable <DependencyDetail> dependencies = null;

                if (!string.IsNullOrEmpty(testPath))
                {
                    testPath = Path.Combine(
                        testPath,
                        node.DependencyDetail.RepoUri,
                        node.DependencyDetail.Commit);

                    if (!string.IsNullOrEmpty(node.DependencyDetail.Commit) &&
                        Directory.Exists(testPath))
                    {
                        Local local = new Local(
                            Path.Combine(
                                testPath,
                                ".git"),
                            logger);
                        dependencies = await local.GetDependenciesAsync();
                    }
                }
                else if (remote)
                {
                    Remote remoteClient = new Remote(darcSettings, logger);
                    dependencies = await remoteClient.GetDependenciesAsync(
                        node.DependencyDetail.RepoUri,
                        node.DependencyDetail.Commit);
                }
                else
                {
                    string repoPath = GetRepoPath(node.DependencyDetail, remotesMap, reposFolder, logger);

                    if (!string.IsNullOrEmpty(repoPath))
                    {
                        // Local's constructor expects the repo's .git folder to be passed in. In this
                        // particular case we could pass any folder under 'repoPath' or even a fake one
                        // but we use .git to keep things consistent to what Local expects
                        Local  local        = new Local($"{repoPath}/.git", logger);
                        string fileContents = LocalHelpers.GitShow(
                            repoPath,
                            node.DependencyDetail.Commit,
                            VersionFiles.VersionDetailsXml,
                            logger);
                        dependencies = local.GetDependenciesFromFileContents(fileContents);
                    }
                }

                return(dependencies);
            }
            catch (Exception exc)
            {
                logger.LogError(exc, $"Something failed while trying the fetch the " +
                                $"dependencies of repo '{node.DependencyDetail.RepoUri}' at sha " +
                                $"'{node.DependencyDetail.Commit}'");
                throw;
            }
        }
Example #20
0
 public UxManager(ILogger logger)
 {
     _editorPath = LocalHelpers.GetEditorPath(logger);
     _rootDir    = LocalHelpers.GetRootDir(logger);
     _logger     = logger;
 }
Example #21
0
        /// <summary>
        ///     Download and install git to the a temporary location.
        ///     Git is used by DarcLib, and the Service Fabric nodes do not have it installed natively.
        ///
        ///     The file is assumed to be on a public endpoint.
        ///     We return the git client executable so that this call may be easily wrapped in RetryAsync
        /// </summary>
        public async Task <string> GetPathToLocalGitAsync()
        {
            // Determine whether we need to do any downloading at all.
            if (!string.IsNullOrEmpty(_gitExecutable) && File.Exists(_gitExecutable))
            {
                // We should also mke sure that the git executable that exists runs properly
                try
                {
                    LocalHelpers.CheckGitInstallation(_gitExecutable, _logger);
                    return(_gitExecutable);
                }
                catch
                {
                    _logger.LogWarning($"Something went wrong with validating git executable at {_gitExecutable}. Downloading new version.");
                }
            }

            await _semaphoreSlim.WaitAsync();

            try
            {
                // Determine whether another thread ended up getting the lock and downloaded git
                // in the meantime.
                if (string.IsNullOrEmpty(_gitExecutable) || !File.Exists(_gitExecutable))
                {
                    using (_operations.BeginOperation($"Installing a local copy of git"))
                    {
                        string   gitLocation    = _configuration.GetValue <string>("GitDownloadLocation", null);
                        string[] pathSegments   = new Uri(gitLocation, UriKind.Absolute).Segments;
                        string   remoteFileName = pathSegments[pathSegments.Length - 1];

                        string gitRoot    = _tempFiles.GetFilePath("git-portable");
                        string targetPath = Path.Combine(gitRoot, Path.GetFileNameWithoutExtension(remoteFileName));
                        string gitZipFile = Path.Combine(gitRoot, remoteFileName);

                        _logger.LogInformation($"Downloading git from '{gitLocation}' to '{gitZipFile}'");

                        if (Directory.Exists(targetPath))
                        {
                            Directory.Delete(targetPath, true);
                        }

                        Directory.CreateDirectory(targetPath);

                        using (HttpClient client = new HttpClient())
                            using (FileStream outStream = new FileStream(gitZipFile, FileMode.Create, FileAccess.Write))
                                using (var inStream = await client.GetStreamAsync(gitLocation))
                                {
                                    await inStream.CopyToAsync(outStream);
                                }

                        _logger.LogInformation($"Extracting '{gitZipFile}' to '{targetPath}'");

                        ZipFile.ExtractToDirectory(gitZipFile, targetPath, overwriteFiles: true);

                        _gitExecutable = Path.Combine(targetPath, "bin", "git.exe");
                    }
                }
            }
            finally
            {
                _semaphoreSlim.Release();
            }

            // Will throw if something is wrong with the git executable, forcing a retry
            LocalHelpers.CheckGitInstallation(_gitExecutable, _logger);
            return(_gitExecutable);
        }
        /// <summary>
        /// Update local dependencies based on a specific channel.
        /// </summary>
        /// <param name="options">Command line options</param>
        /// <returns>Process exit code.</returns>
        public override async Task <int> ExecuteAsync()
        {
            try
            {
                DarcSettings darcSettings = darcSettings = LocalSettings.GetDarcSettings(_options, Logger);

                // TODO: PAT only used for pulling the arcade eng/common dir,
                // so hardcoded to GitHub PAT right now. Must be more generic in the future.
                darcSettings.GitType = GitRepoType.GitHub;
                LocalSettings localSettings = LocalSettings.LoadSettingsFile(_options);

                darcSettings.PersonalAccessToken = localSettings != null && !string.IsNullOrEmpty(localSettings.GitHubToken) ?
                                                   localSettings.GitHubToken :
                                                   _options.GitHubPat;

                Remote remote = new Remote(darcSettings, Logger);
                Local  local  = new Local(LocalHelpers.GetGitDir(Logger), Logger);
                List <DependencyDetail> dependenciesToUpdate = new List <DependencyDetail>();
                bool   someUpToDate = false;
                string finalMessage = $"Local dependencies updated from channel '{_options.Channel}'.";

                // First we need to figure out what to query for.  Load Version.Details.xml and
                // find all repository uris, optionally restricted by the input dependency parameter.
                IEnumerable <DependencyDetail> dependencies = await local.GetDependenciesAsync(_options.Name);

                if (!dependencies.Any())
                {
                    Console.WriteLine("Found no dependencies to update.");
                    return(Constants.ErrorCode);
                }

                if (!string.IsNullOrEmpty(_options.Name) && !string.IsNullOrEmpty(_options.Version))
                {
                    DependencyDetail dependency = dependencies.First();
                    dependency.Version = _options.Version;
                    dependenciesToUpdate.Add(dependency);

                    Console.WriteLine($"Updating '{dependency.Name}': '{dependency.Version}' => '{_options.Version}'");

                    finalMessage = $"Local dependency {_options.Name} updated to version '{_options.Version}'.";
                }
                else if (!string.IsNullOrEmpty(_options.PackagesFolder))
                {
                    try
                    {
                        dependenciesToUpdate.AddRange(GetDependenciesFromPackagesFolder(_options.PackagesFolder, dependencies));
                    }
                    catch (DarcException exc)
                    {
                        Logger.LogError(exc, $"Error: Failed to update dependencies based on folder '{_options.PackagesFolder}'");
                        return(Constants.ErrorCode);
                    }

                    finalMessage = $"Local dependencies updated based on packages folder {_options.PackagesFolder}.";
                }
                else
                {
                    // Start channel query.
                    var channel = remote.GetChannelAsync(_options.Channel);

                    // Limit the number of BAR queries by grabbing the repo URIs and making a hash set.
                    var repositoryUrisForQuery = dependencies.Select(dependency => dependency.RepoUri).ToHashSet();
                    ConcurrentDictionary <string, Task <Build> > getLatestBuildTaskDictionary = new ConcurrentDictionary <string, Task <Build> >();

                    Channel channelInfo = await channel;
                    if (channelInfo == null)
                    {
                        Console.WriteLine($"Could not find a channel named '{_options.Channel}'.");
                        return(Constants.ErrorCode);
                    }

                    foreach (string repoToQuery in repositoryUrisForQuery)
                    {
                        var latestBuild = remote.GetLatestBuildAsync(repoToQuery, channelInfo.Id.Value);
                        getLatestBuildTaskDictionary.TryAdd(repoToQuery, latestBuild);
                    }

                    // Now walk dependencies again and attempt the update
                    foreach (DependencyDetail dependency in dependencies)
                    {
                        Build build;
                        try
                        {
                            build = await getLatestBuildTaskDictionary[dependency.RepoUri];
                        }
                        catch (ApiErrorException e) when(e.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
                        {
                            Logger.LogTrace($"No build of '{dependency.RepoUri}' found on channel '{_options.Channel}'.");
                            continue;
                        }

                        Asset buildAsset = build.Assets.Where(asset => asset.Name.Equals(dependency.Name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                        if (buildAsset == null)
                        {
                            Logger.LogTrace($"Dependency '{dependency.Name}' not found in latest build of '{dependency.RepoUri}' on '{_options.Channel}', skipping.");
                            continue;
                        }

                        if (buildAsset.Version == dependency.Version &&
                            buildAsset.Name == dependency.Name &&
                            build.Repository == dependency.RepoUri &&
                            build.Commit == dependency.Commit)
                        {
                            // No changes
                            someUpToDate = true;
                            continue;
                        }

                        DependencyDetail updatedDependency = new DependencyDetail
                        {
                            // TODO: Not needed, but not currently provided in Build info. Will be available on next rollout.
                            Branch = null,
                            Commit = build.Commit,
                            // If casing changes, ensure that the dependency name gets updated.
                            Name    = buildAsset.Name,
                            RepoUri = build.Repository,
                            Version = buildAsset.Version
                        };

                        dependenciesToUpdate.Add(updatedDependency);

                        // Print out what we are going to do.
                        Console.WriteLine($"Updating '{dependency.Name}': '{dependency.Version}' => '{updatedDependency.Version}'" +
                                          $" (from build '{build.BuildNumber}' of '{build.Repository}')");
                        // Notify on casing changes.
                        if (buildAsset.Name != dependency.Name)
                        {
                            Console.WriteLine($"  Dependency name normalized to '{updatedDependency.Name}'");
                        }

                        dependenciesToUpdate.Add(updatedDependency);
                    }
                }

                if (!dependenciesToUpdate.Any())
                {
                    // If we found some dependencies already up to date,
                    // then we consider this a success. Otherwise, we didn't even
                    // find matching dependencies so we should let the user know.
                    if (someUpToDate)
                    {
                        Console.WriteLine($"All dependencies are up to date.");
                        return(Constants.SuccessCode);
                    }
                    else
                    {
                        Console.WriteLine($"Found no dependencies to update.");
                        return(Constants.ErrorCode);
                    }
                }

                if (_options.DryRun)
                {
                    return(Constants.SuccessCode);
                }

                // Now call the local updater to run the update
                await local.UpdateDependenciesAsync(dependenciesToUpdate, remote);

                Console.WriteLine(finalMessage);

                return(Constants.SuccessCode);
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"Error: Failed to update dependencies to channel {_options.Channel}");
                return(Constants.ErrorCode);
            }
        }