public static String Patch(string repo, string tag, string path, string filekey = "")
        {
            Queue<String> repoPaths;
            Updated = false;

            if (!Path.IsPathRooted(path))
            {
                path = InnerSpace.Path + "\\" + path;
            }

            if (File.Exists(path + "\\" + repo + "-ShaTree" + filekey + ".JSON"))
            {
                GitHubShaTree = JsonConvert.DeserializeObject<ShaTree>(File.ReadAllText(path + "\\" + repo + "-ShaTree" + filekey + ".JSON"));
            }

            if(GitHubShaTree == null)
            {
                GitHubShaTree = new ShaTree();
            }

            if (tag.IndexOf('/') > 0)
            {
                repoPaths = new Queue<string>(tag.Split(new char[] { '/' }));
                tag = repoPaths.Dequeue();
            }
            else
            {
                repoPaths = new Queue<string>();
            }

            GitHubClient = new WebClient();

            GitHubClientFiles = new WebClient();

            String GitHubData = "";
            JObject GitHubJSON;
            String GitHubURL;
            String GitHubSha;

            InnerSpace.Echo(String.Format("Updating {0} {1} in directory {2}", repo, tag, path));

            GitHubClient.Headers.Add("Accept: application/vnd.github.v3+json");
            try
            {
                GitHubData = GitHubClient.DownloadString(String.Format(patchurl + "/GetTree.php?repo={0}&branch={1}", repo, tag));
            }
            catch (WebException ex)
            {
                if (ex.Status == WebExceptionStatus.ProtocolError)
                {
                    if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.NotFound)
                    {
                        throw new InvalidBranchException();
                    }
                }
                throw ex;
            }

            GitHubJSON = JObject.Parse(GitHubData);

            JToken Tree = GitHubJSON["tree"];

            GitHubSha = (string)GitHubJSON["sha"];

            foreach (String repoPath in repoPaths)
            {
                foreach (JProperty fileProp in Tree.Values<JProperty>())
                {
                    JToken file = fileProp.Value;
                    if ((String)file["path"] == repoPath)
                    {
                        if ((String)file["type"] == "tree")
                        {
                            Tree = file["tree"];
                        }
                        else
                        {
                            if (GitHubShaTree.TreeSha != (String)file["sha"])
                            {
                                UpdateFile(path + "\\" + (String)file["path"], repo, (String)file["sha"]);
                                InnerSpace.Echo((String)file["path"] + " Downloaded");
                                GitHubShaTree.TreeSha = (String)file["sha"];
                            }
                            GitHubSha = GitHubShaTree.TreeSha;
                        }
                        break;
                    }
                }
            }

            if (GitHubShaTree.TreeSha != GitHubSha)
            {
                GitHubShaTree.TreeSha = GitHubSha;
                RecursiveTree(path, Tree, GitHubShaTree, repo);
            }

            File.WriteAllText(path + "\\" + repo + "-ShaTree" + filekey + ".JSON", JsonConvert.SerializeObject(GitHubShaTree));
            InnerSpace.Echo(String.Format("{0} {1} Updated in directory {2}", repo, tag, path));
            return GitHubShaTree.TreeSha;
        }
 static void RecursiveTree(String path, JToken Tree, ShaTree ThisShaTree, String repo)
 {
     Directory.CreateDirectory(path);
     foreach (JProperty fileProp in Tree.Values<JProperty>())
     {
         JToken file = fileProp.Value;
         if ((String)file["type"] == "tree")
         {
             if (!ThisShaTree.SubTrees.ContainsKey((String)file["path"]))
             {
                 ThisShaTree.SubTrees.Add((String)file["path"], new ShaTree());
             }
             RecursiveTree(path + "\\" + (String)file["path"], file["tree"], ThisShaTree.SubTrees[(String)file["path"]], repo);
         }
         else
         {
             if (((String)file["path"])[0] != '.')
             {
                 if (!ThisShaTree.FileShas.ContainsKey((String)file["path"]))
                 {
                     ThisShaTree.FileShas.Add((String)file["path"], "");
                 }
                 if (ThisShaTree.FileShas[(String)file["path"]] != (String)file["sha"])
                 {
                     ThisShaTree.FileShas[(String)file["path"]] = (String)file["sha"];
                     UpdateFile(path + "\\" + (String)file["path"], repo, (String)file["sha"]);
                     InnerSpace.Echo((String)file["path"] + " Downloaded");
                 }
             }
         }
     }
 }