{"action":"created","comment":{"url":"https://api.github.com/repos/dotnet/buildtools/pulls/comments/51984278","id":51984278,"diff_hunk":"@@ -0,0 +1,73 @@\n+﻿// Licensed to the .NET Foundation under one or more agreements.\n+// The .NET Foundation licenses this file to you under the MIT license.\n+// See the LICENSE file in the project root for more information.\n+\n+using System.Collections.Generic;\n+using System.Text;\n+using System.IO;\n+using Microsoft.Build.Framework;\n+using Microsoft.Build.Utilities;\n+\n+namespace Microsoft.DotNet.Build.Tasks\n+{\n+    public class GatherDirectoriesToRestore : Task\n+    {\n+        [Required]\n+        public string[] RootDirectories { get; set; }\n+\n+        [Output]\n+        public string[] DirectoriesToRestore { get; set; }\n+\n+        public int DirectoryListLength = 7000;\n+\n+        public override bool Execute()\n+        {\n+            HashSet<string> directoriesToRestore = new HashSet<string>();\n+\n+            foreach (string rootDirectory in RootDirectories)\n+            {\n+                AddDirectoriesToRestore(rootDirectory, rootDirectory, directoriesToRestore);\n+            }\n+\n+            List<string> resultBuilder = new List<string>();\n+            StringBuilder sb = new StringBuilder(DirectoryListLength);\n+\n+            foreach (string directoryPath in directoriesToRestore)\n+            {\n+                sb.Append('\"');\n+                sb.Append(directoryPath);\n+                sb.Append(\"\\\" \");\n+\n+                if (sb.Length >= DirectoryListLength)\n+                {\n+                    resultBuilder.Add(sb.ToString());\n+                    sb.Clear();\n+                }\n+            }\n+\n+            if (sb.Length > 0)\n+            {\n+                resultBuilder.Add(sb.ToString());\n+            }\n+\n+            DirectoriesToRestore = resultBuilder.ToArray();\n+\n+            return true;\n+        }\n+\n+        public void AddDirectoriesToRestore(string directoryToExplore, string directoryToAdd, HashSet<string> directoriesToRestore)\n+        {\n+            bool hasProjectJson = File.Exists(Path.Combine(directoryToExplore, \"project.json\"));\n+\n+            if (hasProjectJson)\n+            {\n+                directoriesToRestore.Add(directoryToAdd);\n+            }\n+\n+            foreach (string childDirectory in Directory.GetDirectories(directoryToExplore))\n+            {\n+                AddDirectoriesToRestore(childDirectory, hasProjectJson ? childDirectory : directoryToAdd, directoriesToRestore);","path":"src/Microsoft.DotNet.Build.Tasks/GatherFoldersToRestore.cs","position":69,"original_position":69,"commit_id":"813ffeac76b7304fe1c9bf394ea3fd2b15d1b0fd","original_commit_id":"813ffeac76b7304fe1c9bf394ea3fd2b15d1b0fd","user":{"login":"weshaggard","id":9010698,"avatar_url":"https://avatars.githubusercontent.com/u/9010698?v=3","gravatar_id":"","url":"https://api.github.com/users/weshaggard","html_url":"https://github.com/weshaggard","followers_url":"https://api.github.com/users/weshaggard/followers","following_url":"https://api.github.com/users/weshaggard/following{/other_user}","gists_url":"https://api.github.com/users/weshaggard/gists{/gist_id}","starred_url":"https://api.github.com/users/weshaggard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/weshaggard/subscriptions","organizations_url":"https://api.github.com/users/weshaggard/orgs","repos_url":"https://api.github.com/users/weshaggard/repos","events_url":"https://api.github.com/users/weshaggard/events{/privacy}","received_events_url":"https://api.github.com/users/weshaggard/received_events","type":"User","site_admin":false},"body":"I must be missing something (perhaps I should go to bed) but why is the directoryToAdd ever different then the directoryToExplore? Are you trying to find root directories or something? If that is so I think you might need to be caution about depending on dotnet restore doing a restore of anything beyond a single project.json file in the same directory. ","created_at":"2016-02-05T07:17:33Z","updated_at":"2016-02-05T07:17:33Z","html_url":"https://github.com/dotnet/buildtools/pull/427#discussion_r51984278","pull_request_url":"https://api.github.com/repos/dotnet/buildtools/pulls/427","_links":{"self":{"href":"https://api.github.com/repos/dotnet/buildtools/pulls/comments/51984278"},"html":{"href":"https://github.com/dotnet/buildtools/pull/427#discussion_r51984278"},"pull_request":{"href":"https://api.github.com/repos/dotnet/buildtools/pulls/427"}}},"pull_request":{"url":"https://api.github.com/repos/dotnet/buildtools/pulls/427","id":57955784,"html_url":"https://github.com/dotnet/buildtools/pull/427","diff_url":"https://github.com/dotnet/buildtools/pull/427.diff","patch_url":"https://github.com/dotnet/buildtools/pull/427.patch","issue_url":"https://api.github.com/repos/dotnet/buildtools/issues/427","number":427,"state":"open","locked":false,"title":"Add a custom helper command to speed up restores","user":{"login":"ellismg","id":9602953,"avatar_url":"https://avatars.githubusercontent.com/u/9602953?v=3","gravatar_id":"","url":"https://api.github.com/users/ellismg","html_url":"https://github.com/ellismg","followers_url":"https://api.github.com/users/ellismg/followers","following_url":"https://api.github.com/users/ellismg/following{/other_user}","gists_url":"https://api.github.com/users/ellismg/gists{/gist_id}","starred_url":"https://api.github.com/users/ellismg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ellismg/subscriptions","organizations_url":"https://api.github.com/users/ellismg/orgs","repos_url":"https://api.github.com/users/ellismg/repos","events_url":"https://api.github.com/users/ellismg/events{/privacy}","received_events_url":"https://api.github.com/users/ellismg/received_events","type":"User","site_admin":false},"body":"In CoreFX we spend a bunch of time restoring packages, because we end up invoking\r\ndotnet restore 300+ times to work around DNX bugs. This tool helps us batch up\r\nthese invocations which decreases the number of processes we have to launch and\r\nshould help dotnet restore do some additional caching\r\n\r\nThese problems may go away when we switch to a dotnet CLI which restores using\r\nnuget, but for now this has a measurable impact on package restore.\r\n\r\nIn my measurements, package restore where the \"packages\" folder did not exist (but\r\nthe NuGet/DNX caches had not been cleared) dropped from ~20 mins to ~4.5 and a\r\npackage restore where everything had already been restored previously (e.g. calling\r\nsync.cmd /p twice and measuring the second run) went from ~17 mins to ~50 seconds.","created_at":"2016-02-02T08:45:12Z","updated_at":"2016-02-05T07:17:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1c0d4f080a7ef16753d15ce4a13ebd8251110fdc","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/dotnet/buildtools/pulls/427/commits","review_comments_url":"https://api.github.com/repos/dotnet/buildtools/pulls/427/comments","review_comment_url":"https://api.github.com/repos/dotnet/buildtools/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dotnet/buildtools/issues/427/comments","statuses_url":"https://api.github.com/repos/dotnet/buildtools/statuses/813ffeac76b7304fe1c9bf394ea3fd2b15d1b0fd","head":{"label":"ellismg:add-dotnet-restore-batch-wrapper","ref":"add-dotnet-restore-batch-wrapper","sha":"813ffeac76b7304fe1c9bf394ea3fd2b15d1b0fd","user":{"login":"ellismg","id":9602953,"avatar_url":"https://avatars.githubusercontent.com/u/9602953?v=3","gravatar_id":"","url":"https://api.github.com/users/ellismg","html_url":"https://github.com/ellismg","followers_url":"https://api.github.com/users/ellismg/followers","following_url":"https://api.github.com/users/ellismg/following{/other_user}","gists_url":"https://api.github.com/users/ellismg/gists{/gist_id}","starred_url":"https://api.github.com/users/ellismg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ellismg/subscriptions","organizations_url":"https://api.github.com/users/ellismg/orgs","repos_url":"https://api.github.com/users/ellismg/repos","events_url":"https://api.github.com/users/ellismg/events{/privacy}","received_events_url":"https://api.github.com/users/ellismg/received_events","type":"User","site_admin":false},"repo":{"id":26611633,"name":"buildtools","full_name":"ellismg/buildtools","owner":{"login":"ellismg","id":9602953,"avatar_url":"https://avatars.githubusercontent.com/u/9602953?v=3","gravatar_id":"","url":"https://api.github.com/users/ellismg","html_url":"https://github.com/ellismg","followers_url":"https://api.github.com/users/ellismg/followers","following_url":"https://api.github.com/users/ellismg/following{/other_user}","gists_url":"https://api.github.com/users/ellismg/gists{/gist_id}","starred_url":"https://api.github.com/users/ellismg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ellismg/subscriptions","organizations_url":"https://api.github.com/users/ellismg/orgs","repos_url":"https://api.github.com/users/ellismg/repos","events_url":"https://api.github.com/users/ellismg/events{/privacy}","received_events_url":"https://api.github.com/users/ellismg/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ellismg/buildtools","description":"Build tools that are necessary for building the .NET Core projects","fork":true,"url":"https://api.github.com/repos/ellismg/buildtools","forks_url":"https://api.github.com/repos/ellismg/buildtools/forks","keys_url":"https://api.github.com/repos/ellismg/buildtools/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ellismg/buildtools/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ellismg/buildtools/teams","hooks_url":"https://api.github.com/repos/ellismg/buildtools/hooks","issue_events_url":"https://api.github.com/repos/ellismg/buildtools/issues/events{/number}","events_url":"https://api.github.com/repos/ellismg/buildtools/events","assignees_url":"https://api.github.com/repos/ellismg/buildtools/assignees{/user}","branches_url":"https://api.github.com/repos/ellismg/buildtools/branches{/branch}","tags_url":"https://api.github.com/repos/ellismg/buildtools/tags","blobs_url":"https://api.github.com/repos/ellismg/buildtools/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ellismg/buildtools/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ellismg/buildtools/git/refs{/sha}","trees_url":"https://api.github.com/repos/ellismg/buildtools/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ellismg/buildtools/statuses/{sha}","languages_url":"https://api.github.com/repos/ellismg/buildtools/languages","stargazers_url":"https://api.github.com/repos/ellismg/buildtools/stargazers","contributors_url":"https://api.github.com/repos/ellismg/buildtools/contributors","subscribers_url":"https://api.github.com/repos/ellismg/buildtools/subscribers","subscription_url":"https://api.github.com/repos/ellismg/buildtools/subscription","commits_url":"https://api.github.com/repos/ellismg/buildtools/commits{/sha}","git_commits_url":"https://api.github.com/repos/ellismg/buildtools/git/commits{/sha}","comments_url":"https://api.github.com/repos/ellismg/buildtools/comments{/number}","issue_comment_url":"https://api.github.com/repos/ellismg/buildtools/issues/comments{/number}","contents_url":"https://api.github.com/repos/ellismg/buildtools/contents/{+path}","compare_url":"https://api.github.com/repos/ellismg/buildtools/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ellismg/buildtools/merges","archive_url":"https://api.github.com/repos/ellismg/buildtools/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ellismg/buildtools/downloads","issues_url":"https://api.github.com/repos/ellismg/buildtools/issues{/number}","pulls_url":"https://api.github.com/repos/ellismg/buildtools/pulls{/number}","milestones_url":"https://api.github.com/repos/ellismg/buildtools/milestones{/number}","notifications_url":"https://api.github.com/repos/ellismg/buildtools/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ellismg/buildtools/labels{/name}","releases_url":"https://api.github.com/repos/ellismg/buildtools/releases{/id}","deployments_url":"https://api.github.com/repos/ellismg/buildtools/deployments","created_at":"2014-11-13T22:46:13Z","updated_at":"2014-11-13T22:46:14Z","pushed_at":"2016-02-05T06:09:35Z","git_url":"git://github.com/ellismg/buildtools.git","ssh_url":"git@github.com:ellismg/buildtools.git","clone_url":"https://github.com/ellismg/buildtools.git","svn_url":"https://github.com/ellismg/buildtools","homepage":"","size":2247,"stargazers_count":0,"watchers_count":0,"language":"C#","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"dotnet:master","ref":"master","sha":"9c05c61957116f7e60a98a12591869e7cc4d4e38","user":{"login":"dotnet","id":9141961,"avatar_url":"https://avatars.githubusercontent.com/u/9141961?v=3","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"repo":{"id":26295349,"name":"buildtools","full_name":"dotnet/buildtools","owner":{"login":"dotnet","id":9141961,"avatar_url":"https://avatars.githubusercontent.com/u/9141961?v=3","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dotnet/buildtools","description":"Build tools that are necessary for building the .NET Core projects","fork":false,"url":"https://api.github.com/repos/dotnet/buildtools","forks_url":"https://api.github.com/repos/dotnet/buildtools/forks","keys_url":"https://api.github.com/repos/dotnet/buildtools/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dotnet/buildtools/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dotnet/buildtools/teams","hooks_url":"https://api.github.com/repos/dotnet/buildtools/hooks","issue_events_url":"https://api.github.com/repos/dotnet/buildtools/issues/events{/number}","events_url":"https://api.github.com/repos/dotnet/buildtools/events","assignees_url":"https://api.github.com/repos/dotnet/buildtools/assignees{/user}","branches_url":"https://api.github.com/repos/dotnet/buildtools/branches{/branch}","tags_url":"https://api.github.com/repos/dotnet/buildtools/tags","blobs_url":"https://api.github.com/repos/dotnet/buildtools/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dotnet/buildtools/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dotnet/buildtools/git/refs{/sha}","trees_url":"https://api.github.com/repos/dotnet/buildtools/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dotnet/buildtools/statuses/{sha}","languages_url":"https://api.github.com/repos/dotnet/buildtools/languages","stargazers_url":"https://api.github.com/repos/dotnet/buildtools/stargazers","contributors_url":"https://api.github.com/repos/dotnet/buildtools/contributors","subscribers_url":"https://api.github.com/repos/dotnet/buildtools/subscribers","subscription_url":"https://api.github.com/repos/dotnet/buildtools/subscription","commits_url":"https://api.github.com/repos/dotnet/buildtools/commits{/sha}","git_commits_url":"https://api.github.com/repos/dotnet/buildtools/git/commits{/sha}","comments_url":"https://api.github.com/repos/dotnet/buildtools/comments{/number}","issue_comment_url":"https://api.github.com/repos/dotnet/buildtools/issues/comments{/number}","contents_url":"https://api.github.com/repos/dotnet/buildtools/contents/{+path}","compare_url":"https://api.github.com/repos/dotnet/buildtools/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dotnet/buildtools/merges","archive_url":"https://api.github.com/repos/dotnet/buildtools/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dotnet/buildtools/downloads","issues_url":"https://api.github.com/repos/dotnet/buildtools/issues{/number}","pulls_url":"https://api.github.com/repos/dotnet/buildtools/pulls{/number}","milestones_url":"https://api.github.com/repos/dotnet/buildtools/milestones{/number}","notifications_url":"https://api.github.com/repos/dotnet/buildtools/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dotnet/buildtools/labels{/name}","releases_url":"https://api.github.com/repos/dotnet/buildtools/releases{/id}","deployments_url":"https://api.github.com/repos/dotnet/buildtools/deployments","created_at":"2014-11-06T23:43:05Z","updated_at":"2016-01-28T19:29:29Z","pushed_at":"2016-02-05T06:09:35Z","git_url":"git://github.com/dotnet/buildtools.git","ssh_url":"git@github.com:dotnet/buildtools.git","clone_url":"https://github.com/dotnet/buildtools.git","svn_url":"https://github.com/dotnet/buildtools","homepage":"","size":2675,"stargazers_count":392,"watchers_count":392,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":170,"mirror_url":null,"open_issues_count":42,"forks":170,"open_issues":42,"watchers":392,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dotnet/buildtools/pulls/427"},"html":{"href":"https://github.com/dotnet/buildtools/pull/427"},"issue":{"href":"https://api.github.com/repos/dotnet/buildtools/issues/427"},"comments":{"href":"https://api.github.com/repos/dotnet/buildtools/issues/427/comments"},"review_comments":{"href":"https://api.github.com/repos/dotnet/buildtools/pulls/427/comments"},"review_comment":{"href":"https://api.github.com/repos/dotnet/buildtools/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dotnet/buildtools/pulls/427/commits"},"statuses":{"href":"https://api.github.com/repos/dotnet/buildtools/statuses/813ffeac76b7304fe1c9bf394ea3fd2b15d1b0fd"}}}}