private void DownloadVoodooStorePackages(Action callback)
        {
            var voodooStorePackagesTxt = packagesFolderPath + Path.DirectorySeparatorChar + "voodooStorePackages.txt";

            if (!File.Exists(voodooStorePackagesTxt) || string.IsNullOrEmpty(githubToken))
            {
                Debug.Log($"No Voodoo Store packages manifest exists or Github token is empty.");
                callback();
                return;
            }

            var temporaryCachePath = Application.temporaryCachePath;

            new Thread(() => {
                var lines = File.ReadAllLines(voodooStorePackagesTxt);

                if (lines.Length <= 0)
                {
                    handler.Enqueue(callback);
                    return;
                }

                for (var i = 0; i < lines.Length; i++)
                {
                    var line = lines[i];

                    var outputPath = temporaryCachePath + Path.DirectorySeparatorChar +
                                     $"package{i}.unitypackage";

                    Debug.Log($"Downloading Voodoo package from {line}...");

                    try {
                        var result       = PackageTools.DownloadBlocking(line, githubToken, handler);
                        GitHubFile file  = JsonUtility.FromJson <GitHubFile>(result.Item1);
                        byte[] byteArray = Convert.FromBase64String(file.content);
                        File.WriteAllBytes(outputPath, byteArray);

                        queuedPackages.Enqueue(outputPath);
                        Debug.Log($"Voodoo package downloaded successfully and written to {outputPath}");
                    }
                    catch (Exception e) {
                        Debug.LogError(e);
                    }
                    finally {
                        handler.Enqueue(callback);
                    }
                }
            }).Start();
        }
        private async Task GetBranchFiles(string owner, string name, GitHubBranch branch, string path = "/", GitHubFile parent = null)
        {
            string AccessToken = await HttpContext.GetTokenAsync("access_token");

            var github = new GitHubClient(new ProductHeaderValue("AspNetCoreGitHubAuth"),
                                          new InMemoryCredentialStore(new Credentials(AccessToken)));

            IReadOnlyList <RepositoryContent> contents = await github.Repository.Content.GetAllContentsByRef(owner, name, path, branch.Name);

            foreach (RepositoryContent c in contents)
            {
                GitHubFile thisFile = new GitHubFile();
                lock (thisLock)
                {
                    thisFile.BranchId = _context.GitHubBranches.Where(b => b.BranchId == branch.BranchId).Single().BranchId;
                }
                thisFile.DownloadPath    = c.DownloadUrl;
                thisFile.Name            = c.Name;
                thisFile.Path            = c.Path;
                thisFile.FileValue       = 0;
                thisFile.ApprovedValue   = 0;
                thisFile.RejectedValue   = 0;
                thisFile.UnchangedValue  = 0;
                thisFile.UnapprovedValue = 0;
                if (parent == null)
                {
                    thisFile.ParentId = -1;
                }
                else
                {
                    thisFile.ParentId = parent.FileId;
                }
                if (c.Type == "dir")
                {
                    thisFile.IsDir  = true;
                    thisFile.IsFile = false;
                    lock (thisLock)
                    {
                        _context.GitHubFiles.Add(thisFile);
                        _context.SaveChanges();
                    }
                    try
                    {
                        await GetBranchFiles(owner, name, branch, thisFile.Path, thisFile);
                    }
                    catch
                    {
                    }
                }
                else
                {
                    thisFile.IsDir  = false;
                    thisFile.IsFile = true;
                    lock (thisLock)
                    {
                        _context.GitHubFiles.Add(thisFile);
                        _context.SaveChanges();
                    }
                }
            }
        }
        private static async Task <string> GetRawFileContent(GitHubFile file)
        {
            var blob = await gitHubClient.GetBlob(file.Url);

            return(blob.DecodeBase64String().Replace("???", ""));
        }
        private void BuildNodeTree(GitHubFile file, int?nodeId = null)
        {
            int    currentBracketCount        = 0;
            bool   childNodeGenerationStarted = false;
            CsNode thisNode = new CsNode();

            if (nodeId == null)
            {
                thisNode.ParentNode   = null;
                thisNode.ParentNodeId = null;
                thisNode.FileId       = file.FileId;
                thisNode.File         = file;
                thisNode.NodeName     = "File";
                thisNode.LineIds      = new List <int>();
                thisNode.ChildNodeIds = new List <int>();
                List <GitHubLine> linesInFile;
                lock (thisLock)
                {
                    linesInFile = _context.GitHubLines.Where(l => l.FileId == file.FileId).ToList();
                }
                foreach (GitHubLine l in linesInFile)
                {
                    thisNode.LineIds.Add(l.LineInFile);
                }
                thisNode.LineIds = thisNode.LineIds.OrderBy(l => l).ToList();
                lock (thisLock)
                {
                    _context.CsNodes.Add(thisNode);
                    _context.SaveChanges();
                }
            }
            else
            {
                currentBracketCount = -1;
                lock (thisLock)
                {
                    thisNode = _context.CsNodes.Where(n => n.Id == nodeId).Single();
                }
            }

            List <GitHubLine> fileLines;

            lock (thisLock)
            {
                fileLines = _context.GitHubLines.Where(l => l.FileId == file.FileId).OrderBy(l => l.LineInFile).ToList();
            }
            CsNode childNode = new CsNode
            {
                NodeName     = "",
                ParentNodeId = thisNode.Id,
                ParentNode   = thisNode,
                LineIds      = new List <int>(),
                FileId       = file.FileId,
                File         = file,
                ChildNodeIds = new List <int>(),
            };
            int firstLine = thisNode.LineIds.Min(i => i);
            int lastLine  = thisNode.LineIds.Max(i => i);

            for (int i = firstLine - 1; i < lastLine; i++)
            {
                string thisLine = fileLines[i].Content;
                string nextLine = null;
                if (i + 1 < fileLines.Count)
                {
                    nextLine = fileLines[i + 1].Content;
                }
                else
                {
                    nextLine = "";
                }
                if ((thisLine.Contains("namespace") || thisLine.Contains("class") || (thisLine.Contains('(') && thisLine.Contains(')') && !thisLine.Contains(';'))) && currentBracketCount == 0 && childNodeGenerationStarted == false)
                {
                    childNode = new CsNode();
                    childNodeGenerationStarted = true;
                    if (thisLine.Contains("namespace"))
                    {
                        childNode.NodeName = "Namespace";
                    }
                    else if (thisLine.Contains("class"))
                    {
                        childNode.NodeName = "Class";
                    }
                    else if (thisLine.Contains('(') && thisLine.Contains(')') && !thisLine.Contains(';'))
                    {
                        childNode.NodeName = "Method";
                    }
                    else
                    {
                        childNode.NodeName = "Error";
                    }
                    childNode.ParentNodeId = thisNode.Id;
                    childNode.ParentNode   = thisNode;
                    childNode.LineIds      = new List <int>();
                    childNode.FileId       = file.FileId;
                    childNode.File         = file;
                    childNode.ChildNodeIds = new List <int>();
                    childNode.LineIds.Add(fileLines[i].LineInFile);
                    if (thisLine.Contains('{'))
                    {
                        currentBracketCount++;
                    }
                }
                else
                {
                    if (childNodeGenerationStarted == true)
                    {
                        childNode.LineIds.Add(fileLines[i].LineInFile);
                    }
                    if (thisLine.Contains('{'))
                    {
                        currentBracketCount++;
                    }
                    else if (thisLine.Contains('}'))
                    {
                        currentBracketCount--;
                    }

                    if (currentBracketCount == 0 && childNodeGenerationStarted == true)
                    {
                        childNodeGenerationStarted = false;
                        lock (thisLock)
                        {
                            _context.CsNodes.Add(childNode);
                            _context.SaveChanges();
                            thisNode = _context.CsNodes.Where(n => n.Id == thisNode.Id).Single();
                            thisNode.ChildNodeIds.Add(childNode.Id);
                            _context.CsNodes.Update(thisNode);
                            _context.SaveChanges();
                        }
                    }
                }
            }
            foreach (int childNodeId in thisNode.ChildNodeIds)
            {
                CsNode thisChildNode = _context.CsNodes.Where(n => n.Id == childNodeId).Single();
                BuildNodeTree(file, thisChildNode.Id);
            }
        }