{"action":"created","comment":{"url":"https://api.github.com/repos/CodeConnect/SourceBrowser/pulls/comments/23235807","id":23235807,"diff_hunk":"@@ -31,64 +31,86 @@ public ActionResult Submit(string githubUrl)\n                 return View(\"Index\");\n             }\n \n-            string repoRootPath = string.Empty;\n-            try\n-            {\n-                repoRootPath = retriever.RetrieveProject();\n-            }\n-            catch (Exception ex)\n+            // Check if this repo already exists\n+            if (!BrowserRepository.TryLockRepository(retriever.UserName, retriever.RepoName))\n             {\n-                ViewBag.Error = \"There was an error downloading this repository.\";\n-                return View(\"Index\");\n+\t            // Repo exists. Redirect the user to that repository.\n+\t            return Redirect(\"/Browse/\" + retriever.UserName + \"/\" + retriever.RepoName);\n             }\n-\n-            // Generate the source browser files for this solution\n-            var solutionPaths = GetSolutionPaths(repoRootPath);\n-            if (solutionPaths.Length == 0)\n-            {\n-                ViewBag.Error = \"No C# solution was found. Ensure that a valid .sln file exists within your repository.\";\n-                return View(\"Index\");\n-            }\n-\n-            var organizationPath = System.Web.Hosting.HostingEnvironment.MapPath(\"~/\") + \"SB_Files\\\\\" + retriever.UserName;\n-            var repoPath = Path.Combine(organizationPath, retriever.RepoName);\n-\n-            // TODO: Use parallel for.\n-            // TODO: Process all solutions.\n-            // For now, we're assuming the shallowest and shortest .sln file is the one we're interested in\n-            foreach (var solutionPath in solutionPaths.OrderBy(n => n.Length).Take(1))\n+            // We have locked the repository and marked it as processing.\n+            // Whenever we return or exit on an exception, we need to unlock this repository\n+            bool processingSuccessful = false;\n+            try\n             {\n-                Generator.Model.WorkspaceModel workspaceModel;\n+                string repoRootPath = string.Empty;\n                 try\n                 {\n-                    workspaceModel = UploadRepository.ProcessSolution(solutionPath, repoRootPath);\n+                    repoRootPath = retriever.RetrieveProject();\n                 }\n                 catch (Exception ex)\n                 {\n-                    ViewBag.Error = \"There was an error processing solution \" + Path.GetFileName(solutionPath);\n+                    ViewBag.Error = \"There was an error downloading this repository.\";\n                     return View(\"Index\");\n                 }\n \n-                //One pass to lookup all declarations\n-                var typeTransformer = new TokenLookupTransformer();\n-                typeTransformer.Visit(workspaceModel);\n-                var tokenLookup = typeTransformer.TokenLookup;\n+                // Generate the source browser files for this solution\n+                var solutionPaths = GetSolutionPaths(repoRootPath);\n+                if (solutionPaths.Length == 0)\n+                {\n+                    ViewBag.Error = \"No C# solution was found. Ensure that a valid .sln file exists within your repository.\";\n+                    return View(\"Index\");\n+                }\n \n-                //Another pass to generate HTMLs\n-                var htmlTransformer = new HtmlTransformer(tokenLookup, repoPath);\n-                htmlTransformer.Visit(workspaceModel);\n+                var organizationPath = System.Web.Hosting.HostingEnvironment.MapPath(\"~/\") + \"SB_Files\\\\\" + retriever.UserName;\n+                var repoPath = Path.Combine(organizationPath, retriever.RepoName);\n \n-                var searchTransformer = new SearchIndexTransformer(retriever.UserName, retriever.RepoName);\n-                searchTransformer.Visit(workspaceModel);\n+                // TODO: Use parallel for.\n+                // TODO: Process all solutions.\n+                // For now, we're assuming the shallowest and shortest .sln file is the one we're interested in\n+                foreach (var solutionPath in solutionPaths.OrderBy(n => n.Length).Take(1))\n+                {\n+                    Generator.Model.WorkspaceModel workspaceModel;\n+                    try\n+                    {\n+                        workspaceModel = UploadRepository.ProcessSolution(solutionPath, repoRootPath);\n+                    }\n+                    catch (Exception ex)\n+                    {\n+                        ViewBag.Error = \"There was an error processing solution \" + Path.GetFileName(solutionPath);\n+                        return View(\"Index\");\n+                    }\n \n+                    //One pass to lookup all declarations\n+                    var typeTransformer = new TokenLookupTransformer();\n+                    typeTransformer.Visit(workspaceModel);\n+                    var tokenLookup = typeTransformer.TokenLookup;\n \n+                    //Another pass to generate HTMLs\n+                    var htmlTransformer = new HtmlTransformer(tokenLookup, repoPath);\n+                    htmlTransformer.Visit(workspaceModel);\n \n-                // Generate HTML of the tree view\n-                var treeViewTransformer = new TreeViewTransformer(repoPath, retriever.UserName, retriever.RepoName);\n-                treeViewTransformer.Visit(workspaceModel);\n-            }\n+                    var searchTransformer = new SearchIndexTransformer(retriever.UserName, retriever.RepoName);\n+                    searchTransformer.Visit(workspaceModel);\n \n-            return Redirect(\"/Browse/\" + retriever.UserName + \"/\" + retriever.RepoName);\n+                    // Generate HTML of the tree view\n+                    var treeViewTransformer = new TreeViewTransformer(repoPath, retriever.UserName, retriever.RepoName);\n+                    treeViewTransformer.Visit(workspaceModel);\n+                }\n+\n+                processingSuccessful = true;\n+                return Redirect(\"/Browse/\" + retriever.UserName + \"/\" + retriever.RepoName);\n+            }\n+            finally\n+            {\n+                if (processingSuccessful)\n+                {\n+                    BrowserRepository.MarkRepositoryReady(retriever.UserName, retriever.RepoName);\n+                }\n+                else\n+                {\n+                    BrowserRepository.UnlockRepository(retriever.UserName, retriever.RepoName);","path":"src/SourceBrowser.Site/Controllers/UploadController.cs","position":119,"original_position":122,"commit_id":"2db7dd1de372d01e57e5976f37649cabc020ee44","original_commit_id":"30ebf80769d49ba0920a62a8d7d6e7b5ecb79679","user":{"login":"AmadeusW","id":1673956,"avatar_url":"https://avatars.githubusercontent.com/u/1673956?v=3","gravatar_id":"","url":"https://api.github.com/users/AmadeusW","html_url":"https://github.com/AmadeusW","followers_url":"https://api.github.com/users/AmadeusW/followers","following_url":"https://api.github.com/users/AmadeusW/following{/other_user}","gists_url":"https://api.github.com/users/AmadeusW/gists{/gist_id}","starred_url":"https://api.github.com/users/AmadeusW/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AmadeusW/subscriptions","organizations_url":"https://api.github.com/users/AmadeusW/orgs","repos_url":"https://api.github.com/users/AmadeusW/repos","events_url":"https://api.github.com/users/AmadeusW/events{/privacy}","received_events_url":"https://api.github.com/users/AmadeusW/received_events","type":"User","site_admin":false},"body":"yes you're totally right!!","created_at":"2015-01-20T16:49:26Z","updated_at":"2015-01-20T16:49:26Z","html_url":"https://github.com/CodeConnect/SourceBrowser/pull/87#discussion_r23235807","pull_request_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/pulls/87","_links":{"self":{"href":"https://api.github.com/repos/CodeConnect/SourceBrowser/pulls/comments/23235807"},"html":{"href":"https://github.com/CodeConnect/SourceBrowser/pull/87#discussion_r23235807"},"pull_request":{"href":"https://api.github.com/repos/CodeConnect/SourceBrowser/pulls/87"}}},"pull_request":{"url":"https://api.github.com/repos/CodeConnect/SourceBrowser/pulls/87","id":27551198,"html_url":"https://github.com/CodeConnect/SourceBrowser/pull/87","diff_url":"https://github.com/CodeConnect/SourceBrowser/pull/87.diff","patch_url":"https://github.com/CodeConnect/SourceBrowser/pull/87.patch","issue_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/issues/87","number":87,"state":"open","locked":false,"title":"Closes #81; Works on #82","user":{"login":"AmadeusW","id":1673956,"avatar_url":"https://avatars.githubusercontent.com/u/1673956?v=3","gravatar_id":"","url":"https://api.github.com/users/AmadeusW","html_url":"https://github.com/AmadeusW","followers_url":"https://api.github.com/users/AmadeusW/followers","following_url":"https://api.github.com/users/AmadeusW/following{/other_user}","gists_url":"https://api.github.com/users/AmadeusW/gists{/gist_id}","starred_url":"https://api.github.com/users/AmadeusW/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AmadeusW/subscriptions","organizations_url":"https://api.github.com/users/AmadeusW/orgs","repos_url":"https://api.github.com/users/AmadeusW/repos","events_url":"https://api.github.com/users/AmadeusW/events{/privacy}","received_events_url":"https://api.github.com/users/AmadeusW/received_events","type":"User","site_admin":false},"body":"Uses `SB_Files\\UserName\\RepoName\\repo.lock` file to indicate whether the repository is being processed or ready. If the `repo.lock` file exists, upload action redirects the user to the browse action, thereby closing #81.\r\n\r\nIntroduces project `SourceBrowser.Shared` that contains constants, exceptions, and anything that any project may need (to prevent circular dependencies)\r\n`SourceBrowser.Shared.Constants` defines contents of repo.lock. `BrowserRepository` is the class in `SourceBrowser.Site` project that interacts with the file.\r\n\r\nLays groundwork for #82 by introducing `AwaitLookup.cshtml` page.\r\nThe \"await\" page is visible to users who attempt browsing a repo which is being currently uploaded. In the future, this page should use SignalR to communicate with the server and show live updates of the processing, and to refresh when the processing has finished.","created_at":"2015-01-17T03:16:38Z","updated_at":"2015-01-20T16:49:26Z","closed_at":null,"merged_at":null,"merge_commit_sha":"119735551a977f59d2619623165f16d363107aaa","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/pulls/87/commits","review_comments_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/pulls/87/comments","review_comment_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/pulls/comments/{number}","comments_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/issues/87/comments","statuses_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/statuses/2db7dd1de372d01e57e5976f37649cabc020ee44","head":{"label":"AmadeusW:uploadUX","ref":"uploadUX","sha":"2db7dd1de372d01e57e5976f37649cabc020ee44","user":{"login":"AmadeusW","id":1673956,"avatar_url":"https://avatars.githubusercontent.com/u/1673956?v=3","gravatar_id":"","url":"https://api.github.com/users/AmadeusW","html_url":"https://github.com/AmadeusW","followers_url":"https://api.github.com/users/AmadeusW/followers","following_url":"https://api.github.com/users/AmadeusW/following{/other_user}","gists_url":"https://api.github.com/users/AmadeusW/gists{/gist_id}","starred_url":"https://api.github.com/users/AmadeusW/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AmadeusW/subscriptions","organizations_url":"https://api.github.com/users/AmadeusW/orgs","repos_url":"https://api.github.com/users/AmadeusW/repos","events_url":"https://api.github.com/users/AmadeusW/events{/privacy}","received_events_url":"https://api.github.com/users/AmadeusW/received_events","type":"User","site_admin":false},"repo":{"id":26420400,"name":"SourceBrowser","full_name":"AmadeusW/SourceBrowser","owner":{"login":"AmadeusW","id":1673956,"avatar_url":"https://avatars.githubusercontent.com/u/1673956?v=3","gravatar_id":"","url":"https://api.github.com/users/AmadeusW","html_url":"https://github.com/AmadeusW","followers_url":"https://api.github.com/users/AmadeusW/followers","following_url":"https://api.github.com/users/AmadeusW/following{/other_user}","gists_url":"https://api.github.com/users/AmadeusW/gists{/gist_id}","starred_url":"https://api.github.com/users/AmadeusW/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AmadeusW/subscriptions","organizations_url":"https://api.github.com/users/AmadeusW/orgs","repos_url":"https://api.github.com/users/AmadeusW/repos","events_url":"https://api.github.com/users/AmadeusW/events{/privacy}","received_events_url":"https://api.github.com/users/AmadeusW/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/AmadeusW/SourceBrowser","description":"C# in. HTML out.","fork":true,"url":"https://api.github.com/repos/AmadeusW/SourceBrowser","forks_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/forks","keys_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/keys{/key_id}","collaborators_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/teams","hooks_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/hooks","issue_events_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/issues/events{/number}","events_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/events","assignees_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/assignees{/user}","branches_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/branches{/branch}","tags_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/tags","blobs_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/git/refs{/sha}","trees_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/git/trees{/sha}","statuses_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/statuses/{sha}","languages_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/languages","stargazers_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/stargazers","contributors_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/contributors","subscribers_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/subscribers","subscription_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/subscription","commits_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/commits{/sha}","git_commits_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/git/commits{/sha}","comments_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/comments{/number}","issue_comment_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/issues/comments/{number}","contents_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/contents/{+path}","compare_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/compare/{base}...{head}","merges_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/merges","archive_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/downloads","issues_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/issues{/number}","pulls_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/pulls{/number}","milestones_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/milestones{/number}","notifications_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/labels{/name}","releases_url":"https://api.github.com/repos/AmadeusW/SourceBrowser/releases{/id}","created_at":"2014-11-10T04:05:54Z","updated_at":"2015-01-19T22:54:52Z","pushed_at":"2015-01-20T03:34:57Z","git_url":"git://github.com/AmadeusW/SourceBrowser.git","ssh_url":"git@github.com:AmadeusW/SourceBrowser.git","clone_url":"https://github.com/AmadeusW/SourceBrowser.git","svn_url":"https://github.com/AmadeusW/SourceBrowser","homepage":null,"size":3620,"stargazers_count":0,"watchers_count":0,"language":"CSS","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":"CodeConnect:master","ref":"master","sha":"dda98e32696e56506c5398cfdf7e9866ed3e971e","user":{"login":"CodeConnect","id":9244729,"avatar_url":"https://avatars.githubusercontent.com/u/9244729?v=3","gravatar_id":"","url":"https://api.github.com/users/CodeConnect","html_url":"https://github.com/CodeConnect","followers_url":"https://api.github.com/users/CodeConnect/followers","following_url":"https://api.github.com/users/CodeConnect/following{/other_user}","gists_url":"https://api.github.com/users/CodeConnect/gists{/gist_id}","starred_url":"https://api.github.com/users/CodeConnect/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CodeConnect/subscriptions","organizations_url":"https://api.github.com/users/CodeConnect/orgs","repos_url":"https://api.github.com/users/CodeConnect/repos","events_url":"https://api.github.com/users/CodeConnect/events{/privacy}","received_events_url":"https://api.github.com/users/CodeConnect/received_events","type":"Organization","site_admin":false},"repo":{"id":25234974,"name":"SourceBrowser","full_name":"CodeConnect/SourceBrowser","owner":{"login":"CodeConnect","id":9244729,"avatar_url":"https://avatars.githubusercontent.com/u/9244729?v=3","gravatar_id":"","url":"https://api.github.com/users/CodeConnect","html_url":"https://github.com/CodeConnect","followers_url":"https://api.github.com/users/CodeConnect/followers","following_url":"https://api.github.com/users/CodeConnect/following{/other_user}","gists_url":"https://api.github.com/users/CodeConnect/gists{/gist_id}","starred_url":"https://api.github.com/users/CodeConnect/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CodeConnect/subscriptions","organizations_url":"https://api.github.com/users/CodeConnect/orgs","repos_url":"https://api.github.com/users/CodeConnect/repos","events_url":"https://api.github.com/users/CodeConnect/events{/privacy}","received_events_url":"https://api.github.com/users/CodeConnect/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/CodeConnect/SourceBrowser","description":"C# in. HTML out.","fork":false,"url":"https://api.github.com/repos/CodeConnect/SourceBrowser","forks_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/forks","keys_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/teams","hooks_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/hooks","issue_events_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/issues/events{/number}","events_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/events","assignees_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/assignees{/user}","branches_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/branches{/branch}","tags_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/tags","blobs_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/git/refs{/sha}","trees_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/statuses/{sha}","languages_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/languages","stargazers_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/stargazers","contributors_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/contributors","subscribers_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/subscribers","subscription_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/subscription","commits_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/commits{/sha}","git_commits_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/git/commits{/sha}","comments_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/comments{/number}","issue_comment_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/issues/comments/{number}","contents_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/contents/{+path}","compare_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/merges","archive_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/downloads","issues_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/issues{/number}","pulls_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/pulls{/number}","milestones_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/milestones{/number}","notifications_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/labels{/name}","releases_url":"https://api.github.com/repos/CodeConnect/SourceBrowser/releases{/id}","created_at":"2014-10-15T02:09:09Z","updated_at":"2015-01-20T16:27:16Z","pushed_at":"2015-01-20T16:27:16Z","git_url":"git://github.com/CodeConnect/SourceBrowser.git","ssh_url":"git@github.com:CodeConnect/SourceBrowser.git","clone_url":"https://github.com/CodeConnect/SourceBrowser.git","svn_url":"https://github.com/CodeConnect/SourceBrowser","homepage":"http://sourcebrowser.io","size":18932,"stargazers_count":6,"watchers_count":6,"language":"CSS","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":20,"forks":5,"open_issues":20,"watchers":6,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/CodeConnect/SourceBrowser/pulls/87"},"html":{"href":"https://github.com/CodeConnect/SourceBrowser/pull/87"},"issue":{"href":"https://api.github.com/repos/CodeConnect/SourceBrowser/issues/87"},"comments":{"href":"https://api.github.com/repos/CodeConnect/SourceBrowser/issues/87/comments"},"review_comments":{"href":"https://api.github.com/repos/CodeConnect/SourceBrowser/pulls/87/comments"},"review_comment":{"href":"https://api.github.com/repos/CodeConnect/SourceBrowser/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/CodeConnect/SourceBrowser/pulls/87/commits"},"statuses":{"href":"https://api.github.com/repos/CodeConnect/SourceBrowser/statuses/2db7dd1de372d01e57e5976f37649cabc020ee44"}}}}