{"action":"created","comment":{"url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/comments/42121951","id":42121951,"diff_hunk":"@@ -0,0 +1,140 @@\n+﻿// Copyright (c) .NET Foundation. All rights reserved.\n+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n+\n+using System;\n+using System.Collections.Generic;\n+using System.IO;\n+using System.Linq;\n+using System.Threading.Tasks;\n+using NuGet.Configuration;\n+\n+namespace NuGet.CommandLine.Commands\n+{\n+    [Command(typeof(NuGetCommand), \"clearcache\", \"ClearCacheCommandDescription\", MaxArgs = 0,\n+        UsageSummaryResourceName = \"ClearCacheCommandSummary\",\n+        UsageExampleResourceName = \"ClearCacheCommandExamples\")]\n+    public class ClearCacheCommand\n+        : Command\n+    {\n+        [Option(typeof(NuGetCommand), \"ClearCacheCommandClearGlobalPackagesDescription\")]\n+        public bool ClearGlobalPackages { get; set; }\n+\n+        public override Task ExecuteCommandAsync()\n+        {\n+            int commandResult = 0;\n+\n+            // Clear the NuGet machine cache\n+            if (!string.IsNullOrEmpty(MachineCache.Default?.Source))\n+            {\n+                Console.WriteLine(\n+                    LocalizedResourceManager.GetString(nameof(NuGetResources.ClearCacheCommand_ClearingNuGetCache)),\n+                    MachineCache.Default.Source);\n+\n+                commandResult = ClearCacheDirectory(MachineCache.Default.Source);\n+            }\n+\n+            // Clear NuGet v3 HTTP cache\n+            var localAppDataFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);\n+            var httpCacheFolderPath = Path.Combine(localAppDataFolderPath, \"NuGet\", \"v3-cache\");\n+            if (!string.IsNullOrEmpty(httpCacheFolderPath))\n+            {\n+                Console.WriteLine(\n+                    LocalizedResourceManager.GetString(nameof(NuGetResources.ClearCacheCommand_ClearingNuGetHttpCache)),\n+                    httpCacheFolderPath);\n+\n+                var result = ClearCacheDirectory(httpCacheFolderPath);\n+                if (commandResult == 0)\n+                {\n+                    commandResult = result;\n+                }\n+            }\n+\n+            if (ClearGlobalPackages)\n+            {\n+                // also clear the global NuGet packages cache\n+                var globalPackagesFolderPath = SettingsUtility.GetGlobalPackagesFolder(Settings);\n+\n+                Console.WriteLine(\n+                    LocalizedResourceManager.GetString(nameof(NuGetResources.ClearCacheCommand_ClearingNuGetGlobalPackagesCache)),\n+                    globalPackagesFolderPath);\n+\n+                var result = ClearCacheDirectory(globalPackagesFolderPath);\n+                if (commandResult == 0)\n+                {\n+                    commandResult = result;\n+                }\n+            }\n+\n+            if (commandResult != 0)\n+            {\n+                throw new CommandLineException(LocalizedResourceManager.GetString(nameof(NuGetResources.ClearCacheCommand_CacheClearFailed)));\n+            }\n+\n+            return Task.FromResult(commandResult);\n+        }\n+\n+        private int ClearCacheDirectory(string folderPath)\n+        {\n+            // Calling DeleteRecursive rather than Directory.Delete(..., recursive: true)\n+            // due to an infrequent exception which can be thrown from that API\n+            var failedDeletes = new List<string>();\n+            DeleteRecursive(folderPath, failedDeletes);\n+\n+            if (failedDeletes.Any())\n+            {\n+                Console.WriteWarning(\n+                    LocalizedResourceManager.GetString(nameof(NuGetResources.ClearCacheCommand_CachePartiallyCleared)));\n+\n+                foreach (var failedDelete in failedDeletes.OrderBy(f => f, StringComparer.OrdinalIgnoreCase))\n+                {\n+                    Console.WriteWarning(\n+                        LocalizedResourceManager.GetString(nameof(NuGetResources.ClearCacheCommand_FailedToDeletePath)),\n+                        failedDelete);\n+                }\n+                return 1;\n+            }\n+            else\n+            {\n+                Console.WriteLine(LocalizedResourceManager.GetString(nameof(NuGetResources.ClearCacheCommand_CacheCleared)));\n+                return 0;\n+            }\n+        }\n+\n+        private static void DeleteRecursive(string deletePath, List<string> failedDeletes)\n+        {\n+            if (!Directory.Exists(deletePath))","path":"src/NuGet.Clients/NuGet.CommandLine/Commands/ClearCacheCommand.cs","position":96,"original_position":105,"commit_id":"b87b9e1ce3af03fd0ad24e8321366eb6a41cd96a","original_commit_id":"a62e9c911b75b946fb8fb0971cd97349b337e91d","user":{"login":"xavierdecoster","id":880728,"avatar_url":"https://avatars.githubusercontent.com/u/880728?v=3","gravatar_id":"","url":"https://api.github.com/users/xavierdecoster","html_url":"https://github.com/xavierdecoster","followers_url":"https://api.github.com/users/xavierdecoster/followers","following_url":"https://api.github.com/users/xavierdecoster/following{/other_user}","gists_url":"https://api.github.com/users/xavierdecoster/gists{/gist_id}","starred_url":"https://api.github.com/users/xavierdecoster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xavierdecoster/subscriptions","organizations_url":"https://api.github.com/users/xavierdecoster/orgs","repos_url":"https://api.github.com/users/xavierdecoster/repos","events_url":"https://api.github.com/users/xavierdecoster/events{/privacy}","received_events_url":"https://api.github.com/users/xavierdecoster/received_events","type":"User","site_admin":false},"body":"I figured somebody must have solved this issue before, so I took a look at how DNU clears the cache.\r\nThis piece of code may look familiar :)\r\nhttps://github.com/aspnet/dnx/blob/dev/src/Microsoft.Dnx.Tooling/Utils/FileOperationUtils.cs#L15\r\n\r\nThe infrequent exception has to do with write permissions on files in the target (sub)folders. If there are readonly files in the cache location, the following exception will be thrown by `Directory.Delete(..., recursive: true)`: \r\n\r\n>  Exception thrown: 'System.UnauthorizedAccessException' in mscorlib.dll\r\n\r\nHowever, the part that tries to make these files writable seems missing, so I added that: https://github.com/NuGet/NuGet.Client/commit/b87b9e1ce3af03fd0ad24e8321366eb6a41cd96a\r\n\r\nNote that I still call into `Directory.Delete(..., recursive: true)` to delete the actual directory: https://github.com/NuGet/NuGet.Client/pull/13/files#diff-16d0285c2ebe50837c5df60fd56b56a1R122\r\n\r\nRegarding hard links, `Directory.Delete(..., recursive: true)` will remove the symbolic links but not the actual files that were linked to: https://msdn.microsoft.com/en-us/library/fxeahc5f.aspx\r\n\r\nQuoting MSDN:\r\n>  The behavior of this method differs slightly when deleting a directory that contains a reparse point, such as a symbolic link or a mount point. If the reparse point is a directory, such as a mount point, it is unmounted and the mount point is deleted. This method does not recurse through the reparse point. If the reparse point is a symbolic link to a file, the reparse point is deleted and not the target of the symbolic link.\r\nIn some cases, if you have the specified directory open in File Explorer, the Delete method may not be able to delete it.","created_at":"2015-10-15T13:13:43Z","updated_at":"2015-10-15T13:13:43Z","html_url":"https://github.com/NuGet/NuGet.Client/pull/13#discussion_r42121951","pull_request_url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/13","_links":{"self":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/comments/42121951"},"html":{"href":"https://github.com/NuGet/NuGet.Client/pull/13#discussion_r42121951"},"pull_request":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/13"}}},"pull_request":{"url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/13","id":47152587,"html_url":"https://github.com/NuGet/NuGet.Client/pull/13","diff_url":"https://github.com/NuGet/NuGet.Client/pull/13.diff","patch_url":"https://github.com/NuGet/NuGet.Client/pull/13.patch","issue_url":"https://api.github.com/repos/NuGet/NuGet.Client/issues/13","number":13,"state":"open","locked":false,"title":"implement clearcache command","user":{"login":"xavierdecoster","id":880728,"avatar_url":"https://avatars.githubusercontent.com/u/880728?v=3","gravatar_id":"","url":"https://api.github.com/users/xavierdecoster","html_url":"https://github.com/xavierdecoster","followers_url":"https://api.github.com/users/xavierdecoster/followers","following_url":"https://api.github.com/users/xavierdecoster/following{/other_user}","gists_url":"https://api.github.com/users/xavierdecoster/gists{/gist_id}","starred_url":"https://api.github.com/users/xavierdecoster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xavierdecoster/subscriptions","organizations_url":"https://api.github.com/users/xavierdecoster/orgs","repos_url":"https://api.github.com/users/xavierdecoster/repos","events_url":"https://api.github.com/users/xavierdecoster/events{/privacy}","received_events_url":"https://api.github.com/users/xavierdecoster/received_events","type":"User","site_admin":false},"body":"https://github.com/NuGet/Home/issues/1516\r\n\r\ncc @emgarten @yishaigalatzer ","created_at":"2015-10-08T13:32:12Z","updated_at":"2015-10-15T13:13:43Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5955aac6c48235d90617d9b187230181401c411a","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/13/commits","review_comments_url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/13/comments","review_comment_url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/comments{/number}","comments_url":"https://api.github.com/repos/NuGet/NuGet.Client/issues/13/comments","statuses_url":"https://api.github.com/repos/NuGet/NuGet.Client/statuses/b87b9e1ce3af03fd0ad24e8321366eb6a41cd96a","head":{"label":"NuGet:Issue1516","ref":"Issue1516","sha":"b87b9e1ce3af03fd0ad24e8321366eb6a41cd96a","user":{"login":"NuGet","id":968310,"avatar_url":"https://avatars.githubusercontent.com/u/968310?v=3","gravatar_id":"","url":"https://api.github.com/users/NuGet","html_url":"https://github.com/NuGet","followers_url":"https://api.github.com/users/NuGet/followers","following_url":"https://api.github.com/users/NuGet/following{/other_user}","gists_url":"https://api.github.com/users/NuGet/gists{/gist_id}","starred_url":"https://api.github.com/users/NuGet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NuGet/subscriptions","organizations_url":"https://api.github.com/users/NuGet/orgs","repos_url":"https://api.github.com/users/NuGet/repos","events_url":"https://api.github.com/users/NuGet/events{/privacy}","received_events_url":"https://api.github.com/users/NuGet/received_events","type":"Organization","site_admin":false},"repo":{"id":19330736,"name":"NuGet.Client","full_name":"NuGet/NuGet.Client","owner":{"login":"NuGet","id":968310,"avatar_url":"https://avatars.githubusercontent.com/u/968310?v=3","gravatar_id":"","url":"https://api.github.com/users/NuGet","html_url":"https://github.com/NuGet","followers_url":"https://api.github.com/users/NuGet/followers","following_url":"https://api.github.com/users/NuGet/following{/other_user}","gists_url":"https://api.github.com/users/NuGet/gists{/gist_id}","starred_url":"https://api.github.com/users/NuGet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NuGet/subscriptions","organizations_url":"https://api.github.com/users/NuGet/orgs","repos_url":"https://api.github.com/users/NuGet/repos","events_url":"https://api.github.com/users/NuGet/events{/privacy}","received_events_url":"https://api.github.com/users/NuGet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/NuGet/NuGet.Client","description":"Core client libraries for NuGet Services","fork":false,"url":"https://api.github.com/repos/NuGet/NuGet.Client","forks_url":"https://api.github.com/repos/NuGet/NuGet.Client/forks","keys_url":"https://api.github.com/repos/NuGet/NuGet.Client/keys{/key_id}","collaborators_url":"https://api.github.com/repos/NuGet/NuGet.Client/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/NuGet/NuGet.Client/teams","hooks_url":"https://api.github.com/repos/NuGet/NuGet.Client/hooks","issue_events_url":"https://api.github.com/repos/NuGet/NuGet.Client/issues/events{/number}","events_url":"https://api.github.com/repos/NuGet/NuGet.Client/events","assignees_url":"https://api.github.com/repos/NuGet/NuGet.Client/assignees{/user}","branches_url":"https://api.github.com/repos/NuGet/NuGet.Client/branches{/branch}","tags_url":"https://api.github.com/repos/NuGet/NuGet.Client/tags","blobs_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/refs{/sha}","trees_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/trees{/sha}","statuses_url":"https://api.github.com/repos/NuGet/NuGet.Client/statuses/{sha}","languages_url":"https://api.github.com/repos/NuGet/NuGet.Client/languages","stargazers_url":"https://api.github.com/repos/NuGet/NuGet.Client/stargazers","contributors_url":"https://api.github.com/repos/NuGet/NuGet.Client/contributors","subscribers_url":"https://api.github.com/repos/NuGet/NuGet.Client/subscribers","subscription_url":"https://api.github.com/repos/NuGet/NuGet.Client/subscription","commits_url":"https://api.github.com/repos/NuGet/NuGet.Client/commits{/sha}","git_commits_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/commits{/sha}","comments_url":"https://api.github.com/repos/NuGet/NuGet.Client/comments{/number}","issue_comment_url":"https://api.github.com/repos/NuGet/NuGet.Client/issues/comments{/number}","contents_url":"https://api.github.com/repos/NuGet/NuGet.Client/contents/{+path}","compare_url":"https://api.github.com/repos/NuGet/NuGet.Client/compare/{base}...{head}","merges_url":"https://api.github.com/repos/NuGet/NuGet.Client/merges","archive_url":"https://api.github.com/repos/NuGet/NuGet.Client/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/NuGet/NuGet.Client/downloads","issues_url":"https://api.github.com/repos/NuGet/NuGet.Client/issues{/number}","pulls_url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls{/number}","milestones_url":"https://api.github.com/repos/NuGet/NuGet.Client/milestones{/number}","notifications_url":"https://api.github.com/repos/NuGet/NuGet.Client/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/NuGet/NuGet.Client/labels{/name}","releases_url":"https://api.github.com/repos/NuGet/NuGet.Client/releases{/id}","created_at":"2014-04-30T23:46:11Z","updated_at":"2015-10-14T13:47:33Z","pushed_at":"2015-10-15T13:11:59Z","git_url":"git://github.com/NuGet/NuGet.Client.git","ssh_url":"git@github.com:NuGet/NuGet.Client.git","clone_url":"https://github.com/NuGet/NuGet.Client.git","svn_url":"https://github.com/NuGet/NuGet.Client","homepage":null,"size":14588,"stargazers_count":6,"watchers_count":6,"language":"C#","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":10,"mirror_url":null,"open_issues_count":16,"forks":10,"open_issues":16,"watchers":6,"default_branch":"dev"}},"base":{"label":"NuGet:dev","ref":"dev","sha":"07ef21d117cfc895ceec698ded56d69a8c1ab0d2","user":{"login":"NuGet","id":968310,"avatar_url":"https://avatars.githubusercontent.com/u/968310?v=3","gravatar_id":"","url":"https://api.github.com/users/NuGet","html_url":"https://github.com/NuGet","followers_url":"https://api.github.com/users/NuGet/followers","following_url":"https://api.github.com/users/NuGet/following{/other_user}","gists_url":"https://api.github.com/users/NuGet/gists{/gist_id}","starred_url":"https://api.github.com/users/NuGet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NuGet/subscriptions","organizations_url":"https://api.github.com/users/NuGet/orgs","repos_url":"https://api.github.com/users/NuGet/repos","events_url":"https://api.github.com/users/NuGet/events{/privacy}","received_events_url":"https://api.github.com/users/NuGet/received_events","type":"Organization","site_admin":false},"repo":{"id":19330736,"name":"NuGet.Client","full_name":"NuGet/NuGet.Client","owner":{"login":"NuGet","id":968310,"avatar_url":"https://avatars.githubusercontent.com/u/968310?v=3","gravatar_id":"","url":"https://api.github.com/users/NuGet","html_url":"https://github.com/NuGet","followers_url":"https://api.github.com/users/NuGet/followers","following_url":"https://api.github.com/users/NuGet/following{/other_user}","gists_url":"https://api.github.com/users/NuGet/gists{/gist_id}","starred_url":"https://api.github.com/users/NuGet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NuGet/subscriptions","organizations_url":"https://api.github.com/users/NuGet/orgs","repos_url":"https://api.github.com/users/NuGet/repos","events_url":"https://api.github.com/users/NuGet/events{/privacy}","received_events_url":"https://api.github.com/users/NuGet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/NuGet/NuGet.Client","description":"Core client libraries for NuGet Services","fork":false,"url":"https://api.github.com/repos/NuGet/NuGet.Client","forks_url":"https://api.github.com/repos/NuGet/NuGet.Client/forks","keys_url":"https://api.github.com/repos/NuGet/NuGet.Client/keys{/key_id}","collaborators_url":"https://api.github.com/repos/NuGet/NuGet.Client/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/NuGet/NuGet.Client/teams","hooks_url":"https://api.github.com/repos/NuGet/NuGet.Client/hooks","issue_events_url":"https://api.github.com/repos/NuGet/NuGet.Client/issues/events{/number}","events_url":"https://api.github.com/repos/NuGet/NuGet.Client/events","assignees_url":"https://api.github.com/repos/NuGet/NuGet.Client/assignees{/user}","branches_url":"https://api.github.com/repos/NuGet/NuGet.Client/branches{/branch}","tags_url":"https://api.github.com/repos/NuGet/NuGet.Client/tags","blobs_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/refs{/sha}","trees_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/trees{/sha}","statuses_url":"https://api.github.com/repos/NuGet/NuGet.Client/statuses/{sha}","languages_url":"https://api.github.com/repos/NuGet/NuGet.Client/languages","stargazers_url":"https://api.github.com/repos/NuGet/NuGet.Client/stargazers","contributors_url":"https://api.github.com/repos/NuGet/NuGet.Client/contributors","subscribers_url":"https://api.github.com/repos/NuGet/NuGet.Client/subscribers","subscription_url":"https://api.github.com/repos/NuGet/NuGet.Client/subscription","commits_url":"https://api.github.com/repos/NuGet/NuGet.Client/commits{/sha}","git_commits_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/commits{/sha}","comments_url":"https://api.github.com/repos/NuGet/NuGet.Client/comments{/number}","issue_comment_url":"https://api.github.com/repos/NuGet/NuGet.Client/issues/comments{/number}","contents_url":"https://api.github.com/repos/NuGet/NuGet.Client/contents/{+path}","compare_url":"https://api.github.com/repos/NuGet/NuGet.Client/compare/{base}...{head}","merges_url":"https://api.github.com/repos/NuGet/NuGet.Client/merges","archive_url":"https://api.github.com/repos/NuGet/NuGet.Client/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/NuGet/NuGet.Client/downloads","issues_url":"https://api.github.com/repos/NuGet/NuGet.Client/issues{/number}","pulls_url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls{/number}","milestones_url":"https://api.github.com/repos/NuGet/NuGet.Client/milestones{/number}","notifications_url":"https://api.github.com/repos/NuGet/NuGet.Client/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/NuGet/NuGet.Client/labels{/name}","releases_url":"https://api.github.com/repos/NuGet/NuGet.Client/releases{/id}","created_at":"2014-04-30T23:46:11Z","updated_at":"2015-10-14T13:47:33Z","pushed_at":"2015-10-15T13:11:59Z","git_url":"git://github.com/NuGet/NuGet.Client.git","ssh_url":"git@github.com:NuGet/NuGet.Client.git","clone_url":"https://github.com/NuGet/NuGet.Client.git","svn_url":"https://github.com/NuGet/NuGet.Client","homepage":null,"size":14588,"stargazers_count":6,"watchers_count":6,"language":"C#","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":10,"mirror_url":null,"open_issues_count":16,"forks":10,"open_issues":16,"watchers":6,"default_branch":"dev"}},"_links":{"self":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/13"},"html":{"href":"https://github.com/NuGet/NuGet.Client/pull/13"},"issue":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/issues/13"},"comments":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/issues/13/comments"},"review_comments":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/13/comments"},"review_comment":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/13/commits"},"statuses":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/statuses/b87b9e1ce3af03fd0ad24e8321366eb6a41cd96a"}}}}