{"action":"created","comment":{"url":"https://api.github.com/repos/Microsoft/msbuild/pulls/comments/187455056","pull_request_review_id":119241198,"id":187455056,"diff_hunk":"@@ -0,0 +1,211 @@\n+﻿// Copyright (c) Microsoft. All rights reserved.\n+// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n+\n+using Microsoft.Build.Framework;\n+using Microsoft.Build.Shared;\n+using Microsoft.Build.Utilities;\n+using System;\n+using System.Collections.ObjectModel;\n+using System.IO;\n+using System.IO.Compression;\n+using System.Linq;\n+\n+namespace Microsoft.Build.Tasks\n+{\n+    /// <summary>\n+    /// Represents a task that can extract a .zip archive.\n+    /// </summary>\n+    public sealed class Unzip : TaskExtension, ICancelableTask\n+    {\n+        /// <summary>\n+        /// Stores a collection of all destination files.\n+        /// </summary>\n+        private readonly Collection<ITaskItem> _destinationFiles = new Collection<ITaskItem>();\n+\n+        /// <summary>\n+        /// Stores a collection of all files that were unzipped.\n+        /// </summary>\n+        private readonly Collection<ITaskItem> _unzippedFiles = new Collection<ITaskItem>();\n+\n+        /// <summary>\n+        /// Stores a value indicating if a cancellation was requested.\n+        /// </summary>\n+        private bool _canceling;\n+\n+        /// <summary>\n+        /// Gets an array of <see cref=\"ITaskItem\"/> objects containing details about all of the destination files.\n+        /// </summary>\n+        [Output]\n+        public ITaskItem[] DestinationFiles => _destinationFiles.ToArray();\n+\n+        /// <summary>\n+        /// Gets or sets a <see cref=\"ITaskItem\"/> with a destination folder path to unzip the files to.\n+        /// </summary>\n+        [Required]\n+        public ITaskItem DestinationFolder { get; set; }\n+\n+        /// <summary>\n+        /// Gets or sets a value indicating whether read-only files should be overwritten.\n+        /// </summary>\n+        public bool OverwriteReadOnlyFiles { get; set; }\n+\n+        /// <summary>\n+        /// Gets or sets a value indicating whether files should be skipped if the destination is unchanged.\n+        /// </summary>\n+        public bool SkipUnchangedFiles { get; set; } = true;\n+\n+        /// <summary>\n+        /// Gets or sets an array of <see cref=\"ITaskItem\"/> objects containing the paths to .zip archive files to unzip.\n+        /// </summary>\n+        [Required]\n+        public ITaskItem[] SourceFiles { get; set; }\n+\n+        /// <summary>\n+        /// Gets an array of <see cref=\"ITaskItem\"/> objects containing details about only the files that were unzipped.\n+        /// </summary>\n+        [Output]\n+        public ITaskItem[] UnzippedFiles => _unzippedFiles.ToArray();\n+\n+        /// <inheritdoc cref=\"ICancelableTask.Cancel\"/>\n+        public void Cancel()\n+        {\n+            _canceling = true;\n+        }\n+\n+        /// <inheritdoc cref=\"Task.Execute\"/>\n+        public override bool Execute()\n+        {\n+            DirectoryInfo destinationDirectory;\n+            try\n+            {\n+                destinationDirectory = Directory.CreateDirectory(DestinationFolder.ItemSpec);\n+            }\n+            catch (Exception e)\n+            {\n+                Log.LogErrorFromResources(\"Unzip.ErrorCouldNotCreateDestinationDirectory\", DestinationFolder.ItemSpec, e.Message);\n+\n+                return false;\n+            }\n+\n+            foreach (ITaskItem sourceFile in SourceFiles.TakeWhile(i => !_canceling))\n+            {\n+                if (!File.Exists(sourceFile.ItemSpec))\n+                {\n+                    Log.LogErrorFromResources(\"Unzip.ErrorFileDoesNotExist\", sourceFile.ItemSpec);\n+                    continue;\n+                }\n+\n+                try\n+                {\n+                    using (FileStream stream = new FileStream(sourceFile.ItemSpec, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 0x1000, useAsync: false))\n+                    {\n+                        using (ZipArchive zipArchive = new ZipArchive(stream, ZipArchiveMode.Read, leaveOpen: false))\n+                        {\n+                            try\n+                            {\n+                                Extract(sourceFile, zipArchive, destinationDirectory);\n+                            }\n+                            catch (Exception e)\n+                            {\n+                                // Unhandled exception in Extract() is a bug!\n+                                Log.LogErrorFromException(e, showStackTrace: true);\n+                                return false;\n+                            }\n+                        }\n+                    }\n+                }\n+                catch (Exception e)\n+                {\n+                    // Should only be thrown if the archive could not be opened (Access denied, corrupt file, etc)\n+                    Log.LogErrorFromResources(\"Unzip.ErrorCouldNotOpenFile\", e.Message);\n+                }\n+            }\n+\n+            return !_canceling && !Log.HasLoggedErrors;\n+        }\n+\n+        /// <summary>\n+        /// Extracts all files to the specified directory.\n+        /// </summary>\n+        /// <param name=\"sourceTaskItem\">The original <see cref=\"ITaskItem\"/> containing details about the source file.</param>\n+        /// <param name=\"sourceArchive\">The <see cref=\"ZipArchive\"/> containing the files to extract.</param>\n+        /// <param name=\"destinationDirectory\">The <see cref=\"DirectoryInfo\"/> to extract files to.</param>\n+        private void Extract(ITaskItem sourceTaskItem, ZipArchive sourceArchive, DirectoryInfo destinationDirectory)\n+        {\n+            foreach (ZipArchiveEntry zipArchiveEntry in sourceArchive.Entries.TakeWhile(i => !_canceling))\n+            {\n+                FileInfo destinationPath = new FileInfo(Path.Combine(destinationDirectory.FullName, zipArchiveEntry.FullName));\n+\n+                if (!destinationPath.FullName.StartsWith(destinationDirectory.FullName, StringComparison.OrdinalIgnoreCase))\n+                {\n+                    // ExtractToDirectory() throws an IOException for this but since we're extracting one file at a time\n+                    // for logging and cancellation, we need to check for it ourselves.\n+                    Log.LogErrorFromResources(\"Unzip.ErrorExtractingResultsInFilesOutsideDestination\", destinationPath.FullName, destinationDirectory.FullName);\n+                    continue;\n+                }\n+                \n+                TaskItem taskItem = new TaskItem(EscapingUtilities.Escape(destinationPath.FullName));\n+\n+                sourceTaskItem.CopyMetadataTo(taskItem);\n+\n+                _destinationFiles.Add(taskItem);","path":"src/Tasks/Unzip.cs","position":151,"original_position":151,"commit_id":"7979242eca659493f80be9747d1da051ea19f157","original_commit_id":"7979242eca659493f80be9747d1da051ea19f157","user":{"login":"jeffkl","id":17556515,"avatar_url":"https://avatars2.githubusercontent.com/u/17556515?v=4","gravatar_id":"","url":"https://api.github.com/users/jeffkl","html_url":"https://github.com/jeffkl","followers_url":"https://api.github.com/users/jeffkl/followers","following_url":"https://api.github.com/users/jeffkl/following{/other_user}","gists_url":"https://api.github.com/users/jeffkl/gists{/gist_id}","starred_url":"https://api.github.com/users/jeffkl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jeffkl/subscriptions","organizations_url":"https://api.github.com/users/jeffkl/orgs","repos_url":"https://api.github.com/users/jeffkl/repos","events_url":"https://api.github.com/users/jeffkl/events{/privacy}","received_events_url":"https://api.github.com/users/jeffkl/received_events","type":"User","site_admin":false},"body":"Its what `<Copy />` does so I though I'd ... :expressionless: ... 😎 _copy_ it.\r\n\r\nTechnically you could copy a ton of files as well \r\n\r\n```xml\r\n<ItemGroup>\r\n  <Files Include=\"Folder\\**\" />\r\n</ItemGroup>\r\n\r\n<Copy\r\n  SourceFiles=\"@(Files)\"\r\n  DestinationFolder=\"Foo\"\r\n  />\r\n```\r\n\r\nAnd we'll waste all of the memory.  What should I do?","created_at":"2018-05-10T20:46:22Z","updated_at":"2018-05-10T20:46:22Z","html_url":"https://github.com/Microsoft/msbuild/pull/3291#discussion_r187455056","pull_request_url":"https://api.github.com/repos/Microsoft/msbuild/pulls/3291","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/Microsoft/msbuild/pulls/comments/187455056"},"html":{"href":"https://github.com/Microsoft/msbuild/pull/3291#discussion_r187455056"},"pull_request":{"href":"https://api.github.com/repos/Microsoft/msbuild/pulls/3291"}},"in_reply_to_id":187452009},"pull_request":{"url":"https://api.github.com/repos/Microsoft/msbuild/pulls/3291","id":187034739,"html_url":"https://github.com/Microsoft/msbuild/pull/3291","diff_url":"https://github.com/Microsoft/msbuild/pull/3291.diff","patch_url":"https://github.com/Microsoft/msbuild/pull/3291.patch","issue_url":"https://api.github.com/repos/Microsoft/msbuild/issues/3291","number":3291,"state":"open","locked":false,"title":"WIP: Add ZipDirectory and Unzip tasks","user":{"login":"jeffkl","id":17556515,"avatar_url":"https://avatars2.githubusercontent.com/u/17556515?v=4","gravatar_id":"","url":"https://api.github.com/users/jeffkl","html_url":"https://github.com/jeffkl","followers_url":"https://api.github.com/users/jeffkl/followers","following_url":"https://api.github.com/users/jeffkl/following{/other_user}","gists_url":"https://api.github.com/users/jeffkl/gists{/gist_id}","starred_url":"https://api.github.com/users/jeffkl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jeffkl/subscriptions","organizations_url":"https://api.github.com/users/jeffkl/orgs","repos_url":"https://api.github.com/users/jeffkl/repos","events_url":"https://api.github.com/users/jeffkl/events{/privacy}","received_events_url":"https://api.github.com/users/jeffkl/received_events","type":"User","site_admin":false},"body":"`ZipDirectory` task zips up a whole directory.  It will fail if the destination file already exists.  Zipping individual files is a lot harder because you have to calculated a base path for all files and make zip entries relative to that.  The code in the CLR that does this is very efficient by reusing string buffers and I didn't want to have to replicate the code.  So for now there's only `ZipDirectory` instead of a more generic `Zip`.\r\n\r\n`Unzip` unzips files from an archive to a directory.\r\n* Has `[Output]` properties to get the files that were unzipped\r\n* Defaults to skip unzipping files that are already up-to-date\r\n* Logs every file that was unzipped\r\n* Supports cancellation\r\n* Supports overwriting read-only files\r\n* Supports unzipping multiple files to the same directory\r\n\r\nI'll write unit tests after the team agrees on the design.\r\n\r\nFixes #1781 ","created_at":"2018-05-09T20:43:40Z","updated_at":"2018-05-10T20:46:22Z","closed_at":null,"merged_at":null,"merge_commit_sha":"52897007a6c74133b073fb020e8f342702108bba","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/Microsoft/msbuild/pulls/3291/commits","review_comments_url":"https://api.github.com/repos/Microsoft/msbuild/pulls/3291/comments","review_comment_url":"https://api.github.com/repos/Microsoft/msbuild/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Microsoft/msbuild/issues/3291/comments","statuses_url":"https://api.github.com/repos/Microsoft/msbuild/statuses/7979242eca659493f80be9747d1da051ea19f157","head":{"label":"jeffkl:zip","ref":"zip","sha":"7979242eca659493f80be9747d1da051ea19f157","user":{"login":"jeffkl","id":17556515,"avatar_url":"https://avatars2.githubusercontent.com/u/17556515?v=4","gravatar_id":"","url":"https://api.github.com/users/jeffkl","html_url":"https://github.com/jeffkl","followers_url":"https://api.github.com/users/jeffkl/followers","following_url":"https://api.github.com/users/jeffkl/following{/other_user}","gists_url":"https://api.github.com/users/jeffkl/gists{/gist_id}","starred_url":"https://api.github.com/users/jeffkl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jeffkl/subscriptions","organizations_url":"https://api.github.com/users/jeffkl/orgs","repos_url":"https://api.github.com/users/jeffkl/repos","events_url":"https://api.github.com/users/jeffkl/events{/privacy}","received_events_url":"https://api.github.com/users/jeffkl/received_events","type":"User","site_admin":false},"repo":{"id":64035216,"name":"msbuild","full_name":"jeffkl/msbuild","owner":{"login":"jeffkl","id":17556515,"avatar_url":"https://avatars2.githubusercontent.com/u/17556515?v=4","gravatar_id":"","url":"https://api.github.com/users/jeffkl","html_url":"https://github.com/jeffkl","followers_url":"https://api.github.com/users/jeffkl/followers","following_url":"https://api.github.com/users/jeffkl/following{/other_user}","gists_url":"https://api.github.com/users/jeffkl/gists{/gist_id}","starred_url":"https://api.github.com/users/jeffkl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jeffkl/subscriptions","organizations_url":"https://api.github.com/users/jeffkl/orgs","repos_url":"https://api.github.com/users/jeffkl/repos","events_url":"https://api.github.com/users/jeffkl/events{/privacy}","received_events_url":"https://api.github.com/users/jeffkl/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jeffkl/msbuild","description":"The Microsoft Build Engine (MSBuild) is the build platform for .NET and Visual Studio.","fork":true,"url":"https://api.github.com/repos/jeffkl/msbuild","forks_url":"https://api.github.com/repos/jeffkl/msbuild/forks","keys_url":"https://api.github.com/repos/jeffkl/msbuild/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jeffkl/msbuild/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jeffkl/msbuild/teams","hooks_url":"https://api.github.com/repos/jeffkl/msbuild/hooks","issue_events_url":"https://api.github.com/repos/jeffkl/msbuild/issues/events{/number}","events_url":"https://api.github.com/repos/jeffkl/msbuild/events","assignees_url":"https://api.github.com/repos/jeffkl/msbuild/assignees{/user}","branches_url":"https://api.github.com/repos/jeffkl/msbuild/branches{/branch}","tags_url":"https://api.github.com/repos/jeffkl/msbuild/tags","blobs_url":"https://api.github.com/repos/jeffkl/msbuild/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jeffkl/msbuild/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jeffkl/msbuild/git/refs{/sha}","trees_url":"https://api.github.com/repos/jeffkl/msbuild/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jeffkl/msbuild/statuses/{sha}","languages_url":"https://api.github.com/repos/jeffkl/msbuild/languages","stargazers_url":"https://api.github.com/repos/jeffkl/msbuild/stargazers","contributors_url":"https://api.github.com/repos/jeffkl/msbuild/contributors","subscribers_url":"https://api.github.com/repos/jeffkl/msbuild/subscribers","subscription_url":"https://api.github.com/repos/jeffkl/msbuild/subscription","commits_url":"https://api.github.com/repos/jeffkl/msbuild/commits{/sha}","git_commits_url":"https://api.github.com/repos/jeffkl/msbuild/git/commits{/sha}","comments_url":"https://api.github.com/repos/jeffkl/msbuild/comments{/number}","issue_comment_url":"https://api.github.com/repos/jeffkl/msbuild/issues/comments{/number}","contents_url":"https://api.github.com/repos/jeffkl/msbuild/contents/{+path}","compare_url":"https://api.github.com/repos/jeffkl/msbuild/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jeffkl/msbuild/merges","archive_url":"https://api.github.com/repos/jeffkl/msbuild/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jeffkl/msbuild/downloads","issues_url":"https://api.github.com/repos/jeffkl/msbuild/issues{/number}","pulls_url":"https://api.github.com/repos/jeffkl/msbuild/pulls{/number}","milestones_url":"https://api.github.com/repos/jeffkl/msbuild/milestones{/number}","notifications_url":"https://api.github.com/repos/jeffkl/msbuild/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jeffkl/msbuild/labels{/name}","releases_url":"https://api.github.com/repos/jeffkl/msbuild/releases{/id}","deployments_url":"https://api.github.com/repos/jeffkl/msbuild/deployments","created_at":"2016-07-23T20:37:16Z","updated_at":"2018-05-09T21:39:09Z","pushed_at":"2018-05-09T21:39:08Z","git_url":"git://github.com/jeffkl/msbuild.git","ssh_url":"git@github.com:jeffkl/msbuild.git","clone_url":"https://github.com/jeffkl/msbuild.git","svn_url":"https://github.com/jeffkl/msbuild","homepage":null,"size":26024,"stargazers_count":0,"watchers_count":0,"language":"C#","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"Microsoft:master","ref":"master","sha":"dc344b3f486806535a76c1b5cf312085d1b3eea0","user":{"login":"Microsoft","id":6154722,"avatar_url":"https://avatars2.githubusercontent.com/u/6154722?v=4","gravatar_id":"","url":"https://api.github.com/users/Microsoft","html_url":"https://github.com/Microsoft","followers_url":"https://api.github.com/users/Microsoft/followers","following_url":"https://api.github.com/users/Microsoft/following{/other_user}","gists_url":"https://api.github.com/users/Microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/Microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Microsoft/subscriptions","organizations_url":"https://api.github.com/users/Microsoft/orgs","repos_url":"https://api.github.com/users/Microsoft/repos","events_url":"https://api.github.com/users/Microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/Microsoft/received_events","type":"Organization","site_admin":false},"repo":{"id":32051890,"name":"msbuild","full_name":"Microsoft/msbuild","owner":{"login":"Microsoft","id":6154722,"avatar_url":"https://avatars2.githubusercontent.com/u/6154722?v=4","gravatar_id":"","url":"https://api.github.com/users/Microsoft","html_url":"https://github.com/Microsoft","followers_url":"https://api.github.com/users/Microsoft/followers","following_url":"https://api.github.com/users/Microsoft/following{/other_user}","gists_url":"https://api.github.com/users/Microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/Microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Microsoft/subscriptions","organizations_url":"https://api.github.com/users/Microsoft/orgs","repos_url":"https://api.github.com/users/Microsoft/repos","events_url":"https://api.github.com/users/Microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/Microsoft/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Microsoft/msbuild","description":"The Microsoft Build Engine (MSBuild) is the build platform for .NET and Visual Studio.","fork":false,"url":"https://api.github.com/repos/Microsoft/msbuild","forks_url":"https://api.github.com/repos/Microsoft/msbuild/forks","keys_url":"https://api.github.com/repos/Microsoft/msbuild/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Microsoft/msbuild/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Microsoft/msbuild/teams","hooks_url":"https://api.github.com/repos/Microsoft/msbuild/hooks","issue_events_url":"https://api.github.com/repos/Microsoft/msbuild/issues/events{/number}","events_url":"https://api.github.com/repos/Microsoft/msbuild/events","assignees_url":"https://api.github.com/repos/Microsoft/msbuild/assignees{/user}","branches_url":"https://api.github.com/repos/Microsoft/msbuild/branches{/branch}","tags_url":"https://api.github.com/repos/Microsoft/msbuild/tags","blobs_url":"https://api.github.com/repos/Microsoft/msbuild/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Microsoft/msbuild/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Microsoft/msbuild/git/refs{/sha}","trees_url":"https://api.github.com/repos/Microsoft/msbuild/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Microsoft/msbuild/statuses/{sha}","languages_url":"https://api.github.com/repos/Microsoft/msbuild/languages","stargazers_url":"https://api.github.com/repos/Microsoft/msbuild/stargazers","contributors_url":"https://api.github.com/repos/Microsoft/msbuild/contributors","subscribers_url":"https://api.github.com/repos/Microsoft/msbuild/subscribers","subscription_url":"https://api.github.com/repos/Microsoft/msbuild/subscription","commits_url":"https://api.github.com/repos/Microsoft/msbuild/commits{/sha}","git_commits_url":"https://api.github.com/repos/Microsoft/msbuild/git/commits{/sha}","comments_url":"https://api.github.com/repos/Microsoft/msbuild/comments{/number}","issue_comment_url":"https://api.github.com/repos/Microsoft/msbuild/issues/comments{/number}","contents_url":"https://api.github.com/repos/Microsoft/msbuild/contents/{+path}","compare_url":"https://api.github.com/repos/Microsoft/msbuild/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Microsoft/msbuild/merges","archive_url":"https://api.github.com/repos/Microsoft/msbuild/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Microsoft/msbuild/downloads","issues_url":"https://api.github.com/repos/Microsoft/msbuild/issues{/number}","pulls_url":"https://api.github.com/repos/Microsoft/msbuild/pulls{/number}","milestones_url":"https://api.github.com/repos/Microsoft/msbuild/milestones{/number}","notifications_url":"https://api.github.com/repos/Microsoft/msbuild/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Microsoft/msbuild/labels{/name}","releases_url":"https://api.github.com/repos/Microsoft/msbuild/releases{/id}","deployments_url":"https://api.github.com/repos/Microsoft/msbuild/deployments","created_at":"2015-03-12T02:04:46Z","updated_at":"2018-05-10T19:37:47Z","pushed_at":"2018-05-10T20:22:05Z","git_url":"git://github.com/Microsoft/msbuild.git","ssh_url":"git@github.com:Microsoft/msbuild.git","clone_url":"https://github.com/Microsoft/msbuild.git","svn_url":"https://github.com/Microsoft/msbuild","homepage":null,"size":25953,"stargazers_count":3460,"watchers_count":3460,"language":"C#","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":772,"mirror_url":null,"archived":false,"open_issues_count":831,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":772,"open_issues":831,"watchers":3460,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Microsoft/msbuild/pulls/3291"},"html":{"href":"https://github.com/Microsoft/msbuild/pull/3291"},"issue":{"href":"https://api.github.com/repos/Microsoft/msbuild/issues/3291"},"comments":{"href":"https://api.github.com/repos/Microsoft/msbuild/issues/3291/comments"},"review_comments":{"href":"https://api.github.com/repos/Microsoft/msbuild/pulls/3291/comments"},"review_comment":{"href":"https://api.github.com/repos/Microsoft/msbuild/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Microsoft/msbuild/pulls/3291/commits"},"statuses":{"href":"https://api.github.com/repos/Microsoft/msbuild/statuses/7979242eca659493f80be9747d1da051ea19f157"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"jeffkl"}}