{"action":"created","comment":{"url":"https://api.github.com/repos/projectkudu/kudu/pulls/comments/32177175","id":32177175,"diff_hunk":"@@ -0,0 +1,519 @@\n+﻿using System;\n+using System.Collections.Generic;\n+using System.Globalization;\n+using System.IO;\n+using System.Net.Http;\n+using System.Net.Http.Headers;\n+using System.Threading;\n+using System.Threading.Tasks;\n+using System.Web.Script.Serialization;\n+using Kudu.Contracts.Settings;\n+using Kudu.Contracts.Tracing;\n+using Kudu.Core;\n+using Kudu.Core.Deployment;\n+using Kudu.Core.Infrastructure;\n+using Kudu.Core.Tracing;\n+\n+namespace Kudu.Services.FetchHelpers\n+{\n+    internal class OneDriveHelper\n+    {\n+        private const string JsonMediaType = \"application/json\";\n+        private const string FormUrlEncodedMediaType = \"application/x-www-form-urlencoded\";\n+        private const string UserAgentHeader = \"User-Agent\";\n+        private const string MicrosoftAzure = \"Microsoft Azure\";\n+        private const string CursorKey = \"onedrive_cursor\";\n+        private const int DefaultBufferSize = 8192; // From http://msdn.microsoft.com/en-us/library/tyhc0kft.aspx\n+        private const int MaxRetryCount = 3;\n+        private const int MaxFilesPerSeconds = 5;\n+\n+        private readonly ITracer _tracer;\n+        private readonly IDeploymentSettingsManager _settings;\n+        private readonly IEnvironment _environment;\n+\n+        internal ILogger Logger\n+        {\n+            get;\n+            set;\n+        }\n+\n+        public OneDriveHelper(ITracer tracer,\n+            IDeploymentSettingsManager settings,\n+            IEnvironment environment)\n+        {\n+            _tracer = tracer;\n+            _settings = settings;\n+            _environment = environment;\n+        }\n+\n+        internal async Task Sync(OneDriveInfo info)\n+        {\n+            string cursor = _settings.GetValue(CursorKey);\n+            ChangesResult changes = null;\n+            using (_tracer.Step(\"Getting delta changes with cursor: {0} ...\", cursor))\n+            {\n+                changes = await GetChanges(info.AccessToken, info.RepositoryUrl, cursor);\n+            }\n+\n+            if (changes == null || changes.Count == 0)\n+            {\n+                _tracer.Trace(\"No changes need to be applied.\");\n+                LogMessage(Resources.OneDriveNoChangesFound);\n+                return;\n+            }\n+\n+            using (_tracer.Step(\"Applying {0} changes ...\", changes.Count))\n+            {\n+                LogMessage(Resources.OneDriveApplyingChanges, changes.Count);\n+\n+                // perform action seperately, so that can ensure timestamp on directory\n+                // e.g two changes:\n+                //  (new) file /a/b/c.txt\n+                //  (new) dir  /a/b\n+                //  if created dir first then create file. file creation will trigger folder timestamp change.\n+                //  which will result in \"/a/b\" has timestamp from the monent of file creation instead of the timestamp value from server, where value supposed to be set by code specifically.\n+                ApplyResult deletionResult = await ApplyChangesParallel(changes.DeletionChanges, info.AccessToken);\n+                ApplyResult fileChangeResult = await ApplyChangesParallel(changes.FileChanges, info.AccessToken);\n+                // apply folder changes at last to maintain same timestamp as in OneDrive\n+                ApplyResult directoryChangeResult = await ApplyChangesParallel(changes.DirectoryChanges, info.AccessToken);\n+\n+                int totalSuccessCount = deletionResult.SuccessCount + fileChangeResult.SuccessCount + directoryChangeResult.SuccessCount;\n+                int totalFailCount = deletionResult.FailureCount + fileChangeResult.FailureCount + directoryChangeResult.FailureCount;\n+                _tracer.Trace(\"{0} successed, {1} failed\", totalSuccessCount, totalFailCount);\n+                LogMessage(Resources.OneDriveApplyResult, totalSuccessCount, totalFailCount);\n+\n+                if (totalFailCount > 0)\n+                {\n+                    // signal deployment failied\n+                    throw new Exception(string.Format(CultureInfo.CurrentUICulture, Resources.OneDriveDeploymentFailure, totalFailCount));\n+                }\n+            }\n+\n+            // finally keep a copy of the new cursor\n+            _settings.SetValue(CursorKey, changes.Cursor);\n+        }\n+\n+        private void LogMessage(string format, params object[] args)\n+        {\n+            if (Logger != null)\n+            {\n+                Logger.Log(format, args);\n+            }\n+        }\n+\n+        private void LogException(Exception ex)\n+        {\n+            if (Logger != null)\n+            {\n+                Logger.Log(ex);\n+            }\n+        }\n+\n+        private void TraceMessage(string format, params object[] args)\n+        {\n+            lock (_tracer)\n+            {\n+                _tracer.Trace(format, args);\n+            }\n+        }\n+\n+        private HttpClient CreateHttpClient(string accessToken)","path":"Kudu.Services/FetchHelpers/OneDriveHelper.cs","position":120,"original_position":120,"commit_id":"276319d7d52012d3723654e30503a3e0f77b88be","original_commit_id":"276319d7d52012d3723654e30503a3e0f77b88be","user":{"login":"shrimpy","id":79823,"avatar_url":"https://avatars.githubusercontent.com/u/79823?v=3","gravatar_id":"","url":"https://api.github.com/users/shrimpy","html_url":"https://github.com/shrimpy","followers_url":"https://api.github.com/users/shrimpy/followers","following_url":"https://api.github.com/users/shrimpy/following{/other_user}","gists_url":"https://api.github.com/users/shrimpy/gists{/gist_id}","starred_url":"https://api.github.com/users/shrimpy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shrimpy/subscriptions","organizations_url":"https://api.github.com/users/shrimpy/orgs","repos_url":"https://api.github.com/users/shrimpy/repos","events_url":"https://api.github.com/users/shrimpy/events{/privacy}","received_events_url":"https://api.github.com/users/shrimpy/received_events","type":"User","site_admin":false},"body":"good idea. i will do it in a separate PR where i am working on test cases. ","created_at":"2015-06-10T23:24:37Z","updated_at":"2015-06-10T23:24:37Z","html_url":"https://github.com/projectkudu/kudu/pull/1579#discussion_r32177175","pull_request_url":"https://api.github.com/repos/projectkudu/kudu/pulls/1579","_links":{"self":{"href":"https://api.github.com/repos/projectkudu/kudu/pulls/comments/32177175"},"html":{"href":"https://github.com/projectkudu/kudu/pull/1579#discussion_r32177175"},"pull_request":{"href":"https://api.github.com/repos/projectkudu/kudu/pulls/1579"}}},"pull_request":{"url":"https://api.github.com/repos/projectkudu/kudu/pulls/1579","id":37318792,"html_url":"https://github.com/projectkudu/kudu/pull/1579","diff_url":"https://github.com/projectkudu/kudu/pull/1579.diff","patch_url":"https://github.com/projectkudu/kudu/pull/1579.patch","issue_url":"https://api.github.com/repos/projectkudu/kudu/issues/1579","number":1579,"state":"open","locked":false,"title":"Added sync support for OneDrive","user":{"login":"shrimpy","id":79823,"avatar_url":"https://avatars.githubusercontent.com/u/79823?v=3","gravatar_id":"","url":"https://api.github.com/users/shrimpy","html_url":"https://github.com/shrimpy","followers_url":"https://api.github.com/users/shrimpy/followers","following_url":"https://api.github.com/users/shrimpy/following{/other_user}","gists_url":"https://api.github.com/users/shrimpy/gists{/gist_id}","starred_url":"https://api.github.com/users/shrimpy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shrimpy/subscriptions","organizations_url":"https://api.github.com/users/shrimpy/orgs","repos_url":"https://api.github.com/users/shrimpy/repos","events_url":"https://api.github.com/users/shrimpy/events{/privacy}","received_events_url":"https://api.github.com/users/shrimpy/received_events","type":"User","site_admin":false},"body":"[Working on test cases. properly will send out a different PR]\r\n\r\nSample trace output:\r\n\r\n````xml\r\n<step title=\"Incoming Request\" date=\"2015-06-10T02:10:09.989\" instance=\"XIAOWU\" url=\"/deploy\" method=\"POST\" type=\"request\" pid=\"292044,20,337\" Content-Length=\"971\" Content-Type=\"application/json\" Accept=\"*/*\" Host=\"localhost:11288\" User-Agent=\"curl/7.30.0\" >\r\n  <step title=\"FetchHandler\" date=\"2015-06-10T02:10:09.993\" >\r\n    <step title=\"Attempting to fetch target branch master\" date=\"2015-06-10T02:10:09.996\" /><!-- duration: 2ms -->\r\n    <step title=\"Performing fetch based deployment\" date=\"2015-06-10T02:10:10.001\" >\r\n      <step title=\"Creating temporary deployment\" date=\"2015-06-10T02:10:10.003\" /><!-- duration: 7ms -->\r\n      <step title=\"Getting delta changes with cursor: aTE09NjM1Njk0OTg5NTg4OTA7SUQ9QTYwMzRGRkJDOTMzOThGRCExMzM7TFI9NjM1Njk0OTg5NjQxNjA7RVA9NDtTTz0y ...\" date=\"2015-06-10T02:10:10.026\" >\r\n        <step title=\"Converting https://api.onedrive.com/v1.0/drive/special/approot:/f1 to identify by id\" date=\"2015-06-10T02:10:10.028\" /><!-- duration: 974ms -->\r\n      </step><!-- duration: 1600ms -->\r\n      <step title=\"Applying 33 changes ...\" date=\"2015-06-10T02:10:11.629\" >\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T01-51-24_XIAOWU_002_POST_deploy_200_9s.xml ...\" date=\"2015-06-10T02:10:11.636\" /><!-- duration: 3ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T01-51-24_XIAOWU_001_Startup_POST_deploy_0s.xml ...\" date=\"2015-06-10T02:10:11.642\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T01-50-07_XIAOWU_006_Shutdown_0s.xml ...\" date=\"2015-06-10T02:10:11.647\" /><!-- duration: 3ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T01-52-02_XIAOWU_003_POST_deploy_200_2s.xml ...\" date=\"2015-06-10T02:10:11.652\" /><!-- duration: 1ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T01-55-22_XIAOWU_008_POST_deploy_200_3s.xml ...\" date=\"2015-06-10T02:10:11.655\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T02-08-24_XIAOWU_002_POST_deploy_200_25s.xml ...\" date=\"2015-06-10T02:10:11.658\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T01-53-41_XIAOWU_004_POST_deploy_200_2s.xml ...\" date=\"2015-06-10T02:10:11.662\" /><!-- duration: 1ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T01-40-53_XIAOWU_005_POST_deploy_200_4s.xml ...\" date=\"2015-06-10T02:10:11.665\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T01-53-59_XIAOWU_005_POST_deploy_200_2s.xml ...\" date=\"2015-06-10T02:10:11.669\" /><!-- duration: 1ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T01-54-18_XIAOWU_006_POST_deploy_200_2s.xml ...\" date=\"2015-06-10T02:10:11.672\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T01-55-05_XIAOWU_007_POST_deploy_200_3s.xml ...\" date=\"2015-06-10T02:10:11.676\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T01-55-52_XIAOWU_009_POST_deploy_200_2s.xml ...\" date=\"2015-06-10T02:10:11.680\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T02-08-24_XIAOWU_001_Startup_POST_deploy_0s.xml ...\" date=\"2015-06-10T02:10:12.300\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T02-07-30_XIAOWU_010_Shutdown_0s.xml ...\" date=\"2015-06-10T02:10:12.326\" /><!-- duration: 3ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T02-08-24_XIAOWU_002_POST_deploy_200_25s.xml ...\" date=\"2015-06-10T02:10:12.347\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\2015-06-10T02-09-22_XIAOWU_003_POST_deploy_200_2s.xml ...\" date=\"2015-06-10T02:10:12.364\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T01-51-24_XIAOWU_001_Startup_POST_deploy_0s.xml ...\" date=\"2015-06-10T02:10:12.368\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T01-40-53_XIAOWU_005_POST_deploy_200_4s.xml ...\" date=\"2015-06-10T02:10:12.434\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T01-50-07_XIAOWU_006_Shutdown_0s.xml ...\" date=\"2015-06-10T02:10:12.449\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T01-51-24_XIAOWU_002_POST_deploy_200_9s.xml ...\" date=\"2015-06-10T02:10:12.456\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T01-52-02_XIAOWU_003_POST_deploy_200_2s.xml ...\" date=\"2015-06-10T02:10:12.507\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T01-53-41_XIAOWU_004_POST_deploy_200_2s.xml ...\" date=\"2015-06-10T02:10:12.578\" /><!-- duration: 3ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T01-53-59_XIAOWU_005_POST_deploy_200_2s.xml ...\" date=\"2015-06-10T02:10:12.599\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T01-54-18_XIAOWU_006_POST_deploy_200_2s.xml ...\" date=\"2015-06-10T02:10:12.604\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T01-55-05_XIAOWU_007_POST_deploy_200_3s.xml ...\" date=\"2015-06-10T02:10:13.029\" /><!-- duration: 3ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T01-55-22_XIAOWU_008_POST_deploy_200_3s.xml ...\" date=\"2015-06-10T02:10:13.048\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T02-07-30_XIAOWU_010_Shutdown_0s.xml ...\" date=\"2015-06-10T02:10:13.100\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T01-55-52_XIAOWU_009_POST_deploy_200_2s.xml ...\" date=\"2015-06-10T02:10:13.124\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T02-08-24_XIAOWU_001_Startup_POST_deploy_0s.xml ...\" date=\"2015-06-10T02:10:13.131\" /><!-- duration: 2ms -->\r\n        <step title=\"Creating file E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb\\2015-06-10T02-09-22_XIAOWU_003_POST_deploy_200_2s.xml ...\" date=\"2015-06-10T02:10:13.151\" /><!-- duration: 3ms -->\r\n        <step title=\"Updating directory E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1 ...\" date=\"2015-06-10T02:10:14.142\" /><!-- duration: 3ms -->\r\n        <step title=\"Updating directory E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa ...\" date=\"2015-06-10T02:10:14.147\" /><!-- duration: 2ms -->\r\n        <step title=\"Updating directory E:\\Kudu-Test-Files\\KuduApps\\TestRunnerSiteXIAOWU-KUDU1\\site\\wwwroot\\f1\\aa\\bb ...\" date=\"2015-06-10T02:10:14.151\" /><!-- duration: 2ms -->\r\n        <step title=\"33 successed, 0 failed\" date=\"2015-06-10T02:10:14.155\" /><!-- duration: 2ms -->\r\n      </step><!-- duration: 2533ms -->\r\n    </step><!-- duration: 4169ms -->\r\n  </step><!-- duration: 4181ms -->\r\n  <step title=\"Outgoing response\" date=\"2015-06-10T02:10:14.176\" type=\"response\" statusCode=\"200\" statusText=\"OK\" Server=\"Microsoft-IIS/8.5\" Cache-Control=\"private\" X-AspNet-Version=\"4.0.30319\" /><!-- duration: 2ms -->\r\n</step><!-- duration: 4192ms -->\r\n\r\n````","created_at":"2015-06-10T02:16:34Z","updated_at":"2015-06-10T23:24:37Z","closed_at":null,"merged_at":null,"merge_commit_sha":"910b30325fc60a251eff81bfcd814d4b4f47466b","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/projectkudu/kudu/pulls/1579/commits","review_comments_url":"https://api.github.com/repos/projectkudu/kudu/pulls/1579/comments","review_comment_url":"https://api.github.com/repos/projectkudu/kudu/pulls/comments{/number}","comments_url":"https://api.github.com/repos/projectkudu/kudu/issues/1579/comments","statuses_url":"https://api.github.com/repos/projectkudu/kudu/statuses/276319d7d52012d3723654e30503a3e0f77b88be","head":{"label":"projectkudu:xiaowu-one-drive","ref":"xiaowu-one-drive","sha":"276319d7d52012d3723654e30503a3e0f77b88be","user":{"login":"projectkudu","id":927131,"avatar_url":"https://avatars.githubusercontent.com/u/927131?v=3","gravatar_id":"","url":"https://api.github.com/users/projectkudu","html_url":"https://github.com/projectkudu","followers_url":"https://api.github.com/users/projectkudu/followers","following_url":"https://api.github.com/users/projectkudu/following{/other_user}","gists_url":"https://api.github.com/users/projectkudu/gists{/gist_id}","starred_url":"https://api.github.com/users/projectkudu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/projectkudu/subscriptions","organizations_url":"https://api.github.com/users/projectkudu/orgs","repos_url":"https://api.github.com/users/projectkudu/repos","events_url":"https://api.github.com/users/projectkudu/events{/privacy}","received_events_url":"https://api.github.com/users/projectkudu/received_events","type":"Organization","site_admin":false},"repo":{"id":1939769,"name":"kudu","full_name":"projectkudu/kudu","owner":{"login":"projectkudu","id":927131,"avatar_url":"https://avatars.githubusercontent.com/u/927131?v=3","gravatar_id":"","url":"https://api.github.com/users/projectkudu","html_url":"https://github.com/projectkudu","followers_url":"https://api.github.com/users/projectkudu/followers","following_url":"https://api.github.com/users/projectkudu/following{/other_user}","gists_url":"https://api.github.com/users/projectkudu/gists{/gist_id}","starred_url":"https://api.github.com/users/projectkudu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/projectkudu/subscriptions","organizations_url":"https://api.github.com/users/projectkudu/orgs","repos_url":"https://api.github.com/users/projectkudu/repos","events_url":"https://api.github.com/users/projectkudu/events{/privacy}","received_events_url":"https://api.github.com/users/projectkudu/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/projectkudu/kudu","description":"Kudu is the engine behind git/hg deployments, WebJobs, and various other features in Azure Web Sites. It can also run outside of Azure.","fork":false,"url":"https://api.github.com/repos/projectkudu/kudu","forks_url":"https://api.github.com/repos/projectkudu/kudu/forks","keys_url":"https://api.github.com/repos/projectkudu/kudu/keys{/key_id}","collaborators_url":"https://api.github.com/repos/projectkudu/kudu/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/projectkudu/kudu/teams","hooks_url":"https://api.github.com/repos/projectkudu/kudu/hooks","issue_events_url":"https://api.github.com/repos/projectkudu/kudu/issues/events{/number}","events_url":"https://api.github.com/repos/projectkudu/kudu/events","assignees_url":"https://api.github.com/repos/projectkudu/kudu/assignees{/user}","branches_url":"https://api.github.com/repos/projectkudu/kudu/branches{/branch}","tags_url":"https://api.github.com/repos/projectkudu/kudu/tags","blobs_url":"https://api.github.com/repos/projectkudu/kudu/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/projectkudu/kudu/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/projectkudu/kudu/git/refs{/sha}","trees_url":"https://api.github.com/repos/projectkudu/kudu/git/trees{/sha}","statuses_url":"https://api.github.com/repos/projectkudu/kudu/statuses/{sha}","languages_url":"https://api.github.com/repos/projectkudu/kudu/languages","stargazers_url":"https://api.github.com/repos/projectkudu/kudu/stargazers","contributors_url":"https://api.github.com/repos/projectkudu/kudu/contributors","subscribers_url":"https://api.github.com/repos/projectkudu/kudu/subscribers","subscription_url":"https://api.github.com/repos/projectkudu/kudu/subscription","commits_url":"https://api.github.com/repos/projectkudu/kudu/commits{/sha}","git_commits_url":"https://api.github.com/repos/projectkudu/kudu/git/commits{/sha}","comments_url":"https://api.github.com/repos/projectkudu/kudu/comments{/number}","issue_comment_url":"https://api.github.com/repos/projectkudu/kudu/issues/comments{/number}","contents_url":"https://api.github.com/repos/projectkudu/kudu/contents/{+path}","compare_url":"https://api.github.com/repos/projectkudu/kudu/compare/{base}...{head}","merges_url":"https://api.github.com/repos/projectkudu/kudu/merges","archive_url":"https://api.github.com/repos/projectkudu/kudu/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/projectkudu/kudu/downloads","issues_url":"https://api.github.com/repos/projectkudu/kudu/issues{/number}","pulls_url":"https://api.github.com/repos/projectkudu/kudu/pulls{/number}","milestones_url":"https://api.github.com/repos/projectkudu/kudu/milestones{/number}","notifications_url":"https://api.github.com/repos/projectkudu/kudu/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/projectkudu/kudu/labels{/name}","releases_url":"https://api.github.com/repos/projectkudu/kudu/releases{/id}","created_at":"2011-06-23T05:36:20Z","updated_at":"2015-06-10T22:26:20Z","pushed_at":"2015-06-10T23:19:54Z","git_url":"git://github.com/projectkudu/kudu.git","ssh_url":"git@github.com:projectkudu/kudu.git","clone_url":"https://github.com/projectkudu/kudu.git","svn_url":"https://github.com/projectkudu/kudu","homepage":"","size":45648,"stargazers_count":931,"watchers_count":931,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":191,"mirror_url":null,"open_issues_count":122,"forks":191,"open_issues":122,"watchers":931,"default_branch":"master"}},"base":{"label":"projectkudu:master","ref":"master","sha":"3dbdec6319835ead7b9d6afa9e9eac9782642b59","user":{"login":"projectkudu","id":927131,"avatar_url":"https://avatars.githubusercontent.com/u/927131?v=3","gravatar_id":"","url":"https://api.github.com/users/projectkudu","html_url":"https://github.com/projectkudu","followers_url":"https://api.github.com/users/projectkudu/followers","following_url":"https://api.github.com/users/projectkudu/following{/other_user}","gists_url":"https://api.github.com/users/projectkudu/gists{/gist_id}","starred_url":"https://api.github.com/users/projectkudu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/projectkudu/subscriptions","organizations_url":"https://api.github.com/users/projectkudu/orgs","repos_url":"https://api.github.com/users/projectkudu/repos","events_url":"https://api.github.com/users/projectkudu/events{/privacy}","received_events_url":"https://api.github.com/users/projectkudu/received_events","type":"Organization","site_admin":false},"repo":{"id":1939769,"name":"kudu","full_name":"projectkudu/kudu","owner":{"login":"projectkudu","id":927131,"avatar_url":"https://avatars.githubusercontent.com/u/927131?v=3","gravatar_id":"","url":"https://api.github.com/users/projectkudu","html_url":"https://github.com/projectkudu","followers_url":"https://api.github.com/users/projectkudu/followers","following_url":"https://api.github.com/users/projectkudu/following{/other_user}","gists_url":"https://api.github.com/users/projectkudu/gists{/gist_id}","starred_url":"https://api.github.com/users/projectkudu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/projectkudu/subscriptions","organizations_url":"https://api.github.com/users/projectkudu/orgs","repos_url":"https://api.github.com/users/projectkudu/repos","events_url":"https://api.github.com/users/projectkudu/events{/privacy}","received_events_url":"https://api.github.com/users/projectkudu/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/projectkudu/kudu","description":"Kudu is the engine behind git/hg deployments, WebJobs, and various other features in Azure Web Sites. It can also run outside of Azure.","fork":false,"url":"https://api.github.com/repos/projectkudu/kudu","forks_url":"https://api.github.com/repos/projectkudu/kudu/forks","keys_url":"https://api.github.com/repos/projectkudu/kudu/keys{/key_id}","collaborators_url":"https://api.github.com/repos/projectkudu/kudu/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/projectkudu/kudu/teams","hooks_url":"https://api.github.com/repos/projectkudu/kudu/hooks","issue_events_url":"https://api.github.com/repos/projectkudu/kudu/issues/events{/number}","events_url":"https://api.github.com/repos/projectkudu/kudu/events","assignees_url":"https://api.github.com/repos/projectkudu/kudu/assignees{/user}","branches_url":"https://api.github.com/repos/projectkudu/kudu/branches{/branch}","tags_url":"https://api.github.com/repos/projectkudu/kudu/tags","blobs_url":"https://api.github.com/repos/projectkudu/kudu/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/projectkudu/kudu/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/projectkudu/kudu/git/refs{/sha}","trees_url":"https://api.github.com/repos/projectkudu/kudu/git/trees{/sha}","statuses_url":"https://api.github.com/repos/projectkudu/kudu/statuses/{sha}","languages_url":"https://api.github.com/repos/projectkudu/kudu/languages","stargazers_url":"https://api.github.com/repos/projectkudu/kudu/stargazers","contributors_url":"https://api.github.com/repos/projectkudu/kudu/contributors","subscribers_url":"https://api.github.com/repos/projectkudu/kudu/subscribers","subscription_url":"https://api.github.com/repos/projectkudu/kudu/subscription","commits_url":"https://api.github.com/repos/projectkudu/kudu/commits{/sha}","git_commits_url":"https://api.github.com/repos/projectkudu/kudu/git/commits{/sha}","comments_url":"https://api.github.com/repos/projectkudu/kudu/comments{/number}","issue_comment_url":"https://api.github.com/repos/projectkudu/kudu/issues/comments{/number}","contents_url":"https://api.github.com/repos/projectkudu/kudu/contents/{+path}","compare_url":"https://api.github.com/repos/projectkudu/kudu/compare/{base}...{head}","merges_url":"https://api.github.com/repos/projectkudu/kudu/merges","archive_url":"https://api.github.com/repos/projectkudu/kudu/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/projectkudu/kudu/downloads","issues_url":"https://api.github.com/repos/projectkudu/kudu/issues{/number}","pulls_url":"https://api.github.com/repos/projectkudu/kudu/pulls{/number}","milestones_url":"https://api.github.com/repos/projectkudu/kudu/milestones{/number}","notifications_url":"https://api.github.com/repos/projectkudu/kudu/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/projectkudu/kudu/labels{/name}","releases_url":"https://api.github.com/repos/projectkudu/kudu/releases{/id}","created_at":"2011-06-23T05:36:20Z","updated_at":"2015-06-10T22:26:20Z","pushed_at":"2015-06-10T23:19:54Z","git_url":"git://github.com/projectkudu/kudu.git","ssh_url":"git@github.com:projectkudu/kudu.git","clone_url":"https://github.com/projectkudu/kudu.git","svn_url":"https://github.com/projectkudu/kudu","homepage":"","size":45648,"stargazers_count":931,"watchers_count":931,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":191,"mirror_url":null,"open_issues_count":122,"forks":191,"open_issues":122,"watchers":931,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/projectkudu/kudu/pulls/1579"},"html":{"href":"https://github.com/projectkudu/kudu/pull/1579"},"issue":{"href":"https://api.github.com/repos/projectkudu/kudu/issues/1579"},"comments":{"href":"https://api.github.com/repos/projectkudu/kudu/issues/1579/comments"},"review_comments":{"href":"https://api.github.com/repos/projectkudu/kudu/pulls/1579/comments"},"review_comment":{"href":"https://api.github.com/repos/projectkudu/kudu/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/projectkudu/kudu/pulls/1579/commits"},"statuses":{"href":"https://api.github.com/repos/projectkudu/kudu/statuses/276319d7d52012d3723654e30503a3e0f77b88be"}}}}