{"action":"created","comment":{"url":"https://api.github.com/repos/dimagi/commcare/pulls/comments/30643746","id":30643746,"diff_hunk":"@@ -282,116 +308,160 @@ public void rollbackCommits() {\n     }\n \n     /**\n+     * Install a resource by looping through its locations stopping at first\n+     * successful install.\n+     *\n+     * @param r        Resource to install\n+     * @param invalid  out-of-date locations to be avoided during resource\n+     *                 installation\n+     * @param upgrade  Has an older version of the resource been installed?\n+     * @param instance The CommCare instance (specific profile and version) to\n+     *                 prepare against\n+     * @param master   Backup resource table to look-up resources not found in\n+     *                 the current table\n+     * @throws UnresolvedResourceException       Raised when no definitions for\n+     *                                           resource 'r' can't be found\n+     * @throws UnfullfilledRequirementsException\n+     */\n+    private void findResourceLocationAndInstall(Resource r,\n+                                                Vector<Reference> invalid,\n+                                                boolean upgrade,\n+                                                CommCareInstance instance,\n+                                                ResourceTable master)\n+            throws UnresolvedResourceException, UnfullfilledRequirementsException {\n+\n+        // TODO: Possibly check if resource status is local and proceeding to\n+        // skip this huge (although in reality like one step) chunk\n+\n+        UnreliableSourceException theFailure = null;\n+        boolean handled = false;\n+\n+        for (ResourceLocation location : r.getLocations()) {\n+            if (handled) {\n+                break;\n+            }\n+            if (location.isRelative()) {\n+                for (Reference ref : gatherLocationsRefs(location, r, this, master)) {\n+                    if (!(location.getAuthority() == Resource.RESOURCE_AUTHORITY_LOCAL && invalid.contains(ref))) {\n+                        try {\n+                            handled = installResource(r, location, ref, this,\n+                                    instance, upgrade);\n+                        } catch (UnreliableSourceException use) {\n+                            theFailure = use;\n+                        }\n+                        if (handled) {\n+                            break;\n+                        }\n+                    }\n+                }\n+            } else {\n+                try {\n+                    handled = installResource(r, location,\n+                            ReferenceManager._().DeriveReference(location.getLocation()),\n+                            this, instance, upgrade);\n+                    if (handled) {\n+                        break;\n+                    }\n+                } catch (InvalidReferenceException ire) {\n+                    ire.printStackTrace();\n+                    // Continue until no resources can be found.\n+                } catch (UnreliableSourceException use) {\n+                    theFailure = use;\n+                }\n+            }\n+        }\n+\n+        if (!handled) {\n+            if (theFailure == null) {\n+                // no particular failure to point our finger at.\n+                throw new UnresolvedResourceException(r,\n+                        \"No external or local definition could be found for resource \" +\n+                                r.getResourceId());\n+            } else {\n+                // Expose the lossy failure rather than the generic one\n+                throw theFailure;\n+            }\n+        }\n+    }\n+\n+    /**\n      * Makes all of this table's resources available.\n      *\n-     * @param master   The global resource to prepare against. Used to establish whether resources need to be fetched\n-     *                 remotely\n+     * @param master   The global resource to prepare against. Used to\n+     *                 establish whether resources need to be fetched remotely\n      * @param instance The instance to prepare against\n-     * @throws UnresolvedResourceException       If a resource could not be identified and is required\n-     * @throws UnfullfilledRequirementsException If some resources are incompatible with the current version of CommCare\n+     * @throws UnresolvedResourceException       If a resource could not be\n+     *                                           identified and is required\n+     * @throws UnfullfilledRequirementsException If some resources are\n+     *                                           incompatible with the current\n+     *                                           version of CommCare\n      */\n     public void prepareResources(ResourceTable master, CommCareInstance instance)\n             throws UnresolvedResourceException, UnfullfilledRequirementsException {\n         this.prepareResources(master, instance, null);\n     }\n \n+\n     /**\n      * Makes some (or all) of the table's resources available\n      *\n-     * @param master       The global resource to prepare against. Used to establish whether resources need to be fetched\n-     *                     remotely\n+     * @param master       The global resource to prepare against. Used to\n+     *                     establish whether resources need to be fetched remotely\n      * @param instance     The instance to prepare against\n-     * @param toInitialize The ID of a single resource after which the table preparation can stop.\n-     * @throws UnresolvedResourceException       If a resource could not be identified and is required\n-     * @throws UnfullfilledRequirementsException If some resources are incompatible with the current version of CommCare\n+     * @param toInitialize The ID of a single resource after which the table\n+     *                     preparation can stop.\n+     * @throws UnresolvedResourceException       Required resource couldn't be\n+     *                                           identified\n+     * @throws UnfullfilledRequirementsException resource(s) incompatible with\n+     *                                           current CommCare version\n      */\n-    public void prepareResources(ResourceTable master, CommCareInstance instance, String toInitialize)\n+    public void prepareResources(ResourceTable master,\n+                                 CommCareInstance instance,\n+                                 String toInitialize)\n             throws UnresolvedResourceException, UnfullfilledRequirementsException {\n-        Stack<Resource> v = GetUnreadyResources();\n-        int round = -1;\n-        while (!v.isEmpty() &&\n-                (toInitialize == null ||\n-                        this.getResourceWithId(toInitialize).getStatus() == Resource.RESOURCE_STATUS_UNINITIALIZED)) {\n-            round++;\n-            while (!v.isEmpty()) {\n-                Resource r = v.pop();\n+\n+        Stack<Resource> unreadyResources = getUnreadyResources();\n+\n+        // install all unready resources. If toInitialize is set, stop after it\n+        // has been installed.\n+        while (idNeedsInit(toInitialize) && !unreadyResources.isEmpty()) {\n+            for (Resource r : unreadyResources) {\n                 boolean upgrade = false;\n-                // Make a reference set for all invalid references (this will get filled in for us)\n+\n                 Vector<Reference> invalid = new Vector<Reference>();\n \n                 // All operations regarding peers and master table\n                 if (master != null) {\n+                    // obtain resource peer by looking up the current resource\n+                    // in the master table\n                     Resource peer = master.getResourceWithId(r.getResourceId());\n                     if (peer != null) {\n-                        // TODO: For now we're assuming that Versions greater than the\n-                        // current are always acceptable\n+                        // TODO: For now we're assuming that Versions greater\n+                        // than the current are always acceptable\n                         if (!r.isNewer(peer)) {\n-                            // This resource doesn't need to be updated, copy the exisitng resource into\n-                            // this table\n+                            // This resource doesn't need to be updated, copy\n+                            // the existing resource into this table\n                             peer.mimick(r);\n                             commit(peer, Resource.RESOURCE_STATUS_INSTALLED);\n                             continue;\n-                        } else {\n-                            upgrade = true;\n                         }\n-                        invalid = ResourceTable.explodeLocalReferences(peer, master);\n+\n+                        // resource is newer than master version, so invalidate\n+                        // old local resource locations.\n+                        upgrade = true;\n+                        invalid = ResourceTable.gatherResourcesLocalRefs(peer, master);\n                     }\n                 }\n \n-                // Vector<Reference> refs = explodeAllReferences(r, this, master);\n-\n-                boolean handled = false;\n-                UnreliableSourceException theFailure = null;\n+                findResourceLocationAndInstall(r, invalid, upgrade, instance, master);\n \n-                // TODO: Possibly check if resource status is local and proceeding\n-                // to skip this huge (although in reality like one step) chunk\n-\n-                for (ResourceLocation location : r.getLocations()) {\n-                    if (handled) {\n-                        break;\n-                    }\n-                    if (location.isRelative()) {\n-                        for (Reference ref : explodeReferences(location, r, this, master)) {\n-                            if (location.getAuthority() == Resource.RESOURCE_AUTHORITY_LOCAL && invalid.contains(ref)) {\n-                            } else {\n-                                try {\n-                                    handled = installResource(r, location, ref, this, instance, upgrade);\n-                                } catch (UnreliableSourceException use) {\n-                                    theFailure = use;\n-                                }\n-                                if (handled) {\n-                                    break;\n-                                }\n-                            }\n-                        }\n-                    } else {\n-                        try {\n-                            handled = installResource(r, location, ReferenceManager._().DeriveReference(location.getLocation()), this, instance, upgrade);\n-                            if (handled) {\n-                                break;\n-                            }\n-                        } catch (InvalidReferenceException ire) {\n-                            ire.printStackTrace();\n-                            // Continue until no resources can be found.\n-                        } catch (UnreliableSourceException use) {\n-                            theFailure = use;\n-                        }\n-                    }\n-                }\n-                if (!handled) {\n-                    // If there wasn't a particular failure to point our finger at...\n-                    if (theFailure == null) {\n-                        throw new UnresolvedResourceException(r, \"No external or local definition could be found for resource \" + r.getResourceId());\n-                    } else {\n-                        // Otherwise, expose the lossy failure rather than the generic one\n-                        throw theFailure;\n-                    }\n-                }\n                 if (stateListener != null) {\n                     stateListener.resourceStateUpdated(this);\n                 }\n             }\n-            v = GetUnreadyResources();\n+            // Installing resources may have exposed more unready resources\n+            // that need installing.\n+            unreadyResources = getUnreadyResources();","path":"backend/src/org/commcare/resources/model/ResourceTable.java","position":471,"original_position":471,"commit_id":"46321f41357949c5849da3fa6c4582c94873d32d","original_commit_id":"46321f41357949c5849da3fa6c4582c94873d32d","user":{"login":"phillipm","id":94817,"avatar_url":"https://avatars.githubusercontent.com/u/94817?v=3","gravatar_id":"","url":"https://api.github.com/users/phillipm","html_url":"https://github.com/phillipm","followers_url":"https://api.github.com/users/phillipm/followers","following_url":"https://api.github.com/users/phillipm/following{/other_user}","gists_url":"https://api.github.com/users/phillipm/gists{/gist_id}","starred_url":"https://api.github.com/users/phillipm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/phillipm/subscriptions","organizations_url":"https://api.github.com/users/phillipm/orgs","repos_url":"https://api.github.com/users/phillipm/repos","events_url":"https://api.github.com/users/phillipm/events{/privacy}","received_events_url":"https://api.github.com/users/phillipm/received_events","type":"User","site_admin":false},"body":"Is this comment correct in its assumptions? If not, then this code needs to be further refactored.","created_at":"2015-05-19T20:37:42Z","updated_at":"2015-05-19T20:37:42Z","html_url":"https://github.com/dimagi/commcare/pull/78#discussion_r30643746","pull_request_url":"https://api.github.com/repos/dimagi/commcare/pulls/78","_links":{"self":{"href":"https://api.github.com/repos/dimagi/commcare/pulls/comments/30643746"},"html":{"href":"https://github.com/dimagi/commcare/pull/78#discussion_r30643746"},"pull_request":{"href":"https://api.github.com/repos/dimagi/commcare/pulls/78"}}},"pull_request":{"url":"https://api.github.com/repos/dimagi/commcare/pulls/78","id":35058856,"html_url":"https://github.com/dimagi/commcare/pull/78","diff_url":"https://github.com/dimagi/commcare/pull/78.diff","patch_url":"https://github.com/dimagi/commcare/pull/78.patch","issue_url":"https://api.github.com/repos/dimagi/commcare/issues/78","number":78,"state":"open","locked":false,"title":"Resource table refactor","user":{"login":"phillipm","id":94817,"avatar_url":"https://avatars.githubusercontent.com/u/94817?v=3","gravatar_id":"","url":"https://api.github.com/users/phillipm","html_url":"https://github.com/phillipm","followers_url":"https://api.github.com/users/phillipm/followers","following_url":"https://api.github.com/users/phillipm/following{/other_user}","gists_url":"https://api.github.com/users/phillipm/gists{/gist_id}","starred_url":"https://api.github.com/users/phillipm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/phillipm/subscriptions","organizations_url":"https://api.github.com/users/phillipm/orgs","repos_url":"https://api.github.com/users/phillipm/repos","events_url":"https://api.github.com/users/phillipm/events{/privacy}","received_events_url":"https://api.github.com/users/phillipm/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-05-09T01:23:04Z","updated_at":"2015-05-19T20:37:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"58757d4b287f4d7621e25c76ccd0e1122ab72109","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/dimagi/commcare/pulls/78/commits","review_comments_url":"https://api.github.com/repos/dimagi/commcare/pulls/78/comments","review_comment_url":"https://api.github.com/repos/dimagi/commcare/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dimagi/commcare/issues/78/comments","statuses_url":"https://api.github.com/repos/dimagi/commcare/statuses/46321f41357949c5849da3fa6c4582c94873d32d","head":{"label":"dimagi:resource-table-refactor","ref":"resource-table-refactor","sha":"46321f41357949c5849da3fa6c4582c94873d32d","user":{"login":"dimagi","id":94514,"avatar_url":"https://avatars.githubusercontent.com/u/94514?v=3","gravatar_id":"","url":"https://api.github.com/users/dimagi","html_url":"https://github.com/dimagi","followers_url":"https://api.github.com/users/dimagi/followers","following_url":"https://api.github.com/users/dimagi/following{/other_user}","gists_url":"https://api.github.com/users/dimagi/gists{/gist_id}","starred_url":"https://api.github.com/users/dimagi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dimagi/subscriptions","organizations_url":"https://api.github.com/users/dimagi/orgs","repos_url":"https://api.github.com/users/dimagi/repos","events_url":"https://api.github.com/users/dimagi/events{/privacy}","received_events_url":"https://api.github.com/users/dimagi/received_events","type":"Organization","site_admin":false},"repo":{"id":20939782,"name":"commcare","full_name":"dimagi/commcare","owner":{"login":"dimagi","id":94514,"avatar_url":"https://avatars.githubusercontent.com/u/94514?v=3","gravatar_id":"","url":"https://api.github.com/users/dimagi","html_url":"https://github.com/dimagi","followers_url":"https://api.github.com/users/dimagi/followers","following_url":"https://api.github.com/users/dimagi/following{/other_user}","gists_url":"https://api.github.com/users/dimagi/gists{/gist_id}","starred_url":"https://api.github.com/users/dimagi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dimagi/subscriptions","organizations_url":"https://api.github.com/users/dimagi/orgs","repos_url":"https://api.github.com/users/dimagi/repos","events_url":"https://api.github.com/users/dimagi/events{/privacy}","received_events_url":"https://api.github.com/users/dimagi/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dimagi/commcare","description":"","fork":false,"url":"https://api.github.com/repos/dimagi/commcare","forks_url":"https://api.github.com/repos/dimagi/commcare/forks","keys_url":"https://api.github.com/repos/dimagi/commcare/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dimagi/commcare/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dimagi/commcare/teams","hooks_url":"https://api.github.com/repos/dimagi/commcare/hooks","issue_events_url":"https://api.github.com/repos/dimagi/commcare/issues/events{/number}","events_url":"https://api.github.com/repos/dimagi/commcare/events","assignees_url":"https://api.github.com/repos/dimagi/commcare/assignees{/user}","branches_url":"https://api.github.com/repos/dimagi/commcare/branches{/branch}","tags_url":"https://api.github.com/repos/dimagi/commcare/tags","blobs_url":"https://api.github.com/repos/dimagi/commcare/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dimagi/commcare/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dimagi/commcare/git/refs{/sha}","trees_url":"https://api.github.com/repos/dimagi/commcare/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dimagi/commcare/statuses/{sha}","languages_url":"https://api.github.com/repos/dimagi/commcare/languages","stargazers_url":"https://api.github.com/repos/dimagi/commcare/stargazers","contributors_url":"https://api.github.com/repos/dimagi/commcare/contributors","subscribers_url":"https://api.github.com/repos/dimagi/commcare/subscribers","subscription_url":"https://api.github.com/repos/dimagi/commcare/subscription","commits_url":"https://api.github.com/repos/dimagi/commcare/commits{/sha}","git_commits_url":"https://api.github.com/repos/dimagi/commcare/git/commits{/sha}","comments_url":"https://api.github.com/repos/dimagi/commcare/comments{/number}","issue_comment_url":"https://api.github.com/repos/dimagi/commcare/issues/comments{/number}","contents_url":"https://api.github.com/repos/dimagi/commcare/contents/{+path}","compare_url":"https://api.github.com/repos/dimagi/commcare/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dimagi/commcare/merges","archive_url":"https://api.github.com/repos/dimagi/commcare/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dimagi/commcare/downloads","issues_url":"https://api.github.com/repos/dimagi/commcare/issues{/number}","pulls_url":"https://api.github.com/repos/dimagi/commcare/pulls{/number}","milestones_url":"https://api.github.com/repos/dimagi/commcare/milestones{/number}","notifications_url":"https://api.github.com/repos/dimagi/commcare/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dimagi/commcare/labels{/name}","releases_url":"https://api.github.com/repos/dimagi/commcare/releases{/id}","created_at":"2014-06-17T21:13:25Z","updated_at":"2015-05-01T15:55:40Z","pushed_at":"2015-05-19T20:32:43Z","git_url":"git://github.com/dimagi/commcare.git","ssh_url":"git@github.com:dimagi/commcare.git","clone_url":"https://github.com/dimagi/commcare.git","svn_url":"https://github.com/dimagi/commcare","homepage":null,"size":7457,"stargazers_count":2,"watchers_count":2,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"open_issues_count":2,"forks":3,"open_issues":2,"watchers":2,"default_branch":"master"}},"base":{"label":"dimagi:master","ref":"master","sha":"b281aeab46297e3c7458a893fb68191fa010205e","user":{"login":"dimagi","id":94514,"avatar_url":"https://avatars.githubusercontent.com/u/94514?v=3","gravatar_id":"","url":"https://api.github.com/users/dimagi","html_url":"https://github.com/dimagi","followers_url":"https://api.github.com/users/dimagi/followers","following_url":"https://api.github.com/users/dimagi/following{/other_user}","gists_url":"https://api.github.com/users/dimagi/gists{/gist_id}","starred_url":"https://api.github.com/users/dimagi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dimagi/subscriptions","organizations_url":"https://api.github.com/users/dimagi/orgs","repos_url":"https://api.github.com/users/dimagi/repos","events_url":"https://api.github.com/users/dimagi/events{/privacy}","received_events_url":"https://api.github.com/users/dimagi/received_events","type":"Organization","site_admin":false},"repo":{"id":20939782,"name":"commcare","full_name":"dimagi/commcare","owner":{"login":"dimagi","id":94514,"avatar_url":"https://avatars.githubusercontent.com/u/94514?v=3","gravatar_id":"","url":"https://api.github.com/users/dimagi","html_url":"https://github.com/dimagi","followers_url":"https://api.github.com/users/dimagi/followers","following_url":"https://api.github.com/users/dimagi/following{/other_user}","gists_url":"https://api.github.com/users/dimagi/gists{/gist_id}","starred_url":"https://api.github.com/users/dimagi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dimagi/subscriptions","organizations_url":"https://api.github.com/users/dimagi/orgs","repos_url":"https://api.github.com/users/dimagi/repos","events_url":"https://api.github.com/users/dimagi/events{/privacy}","received_events_url":"https://api.github.com/users/dimagi/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dimagi/commcare","description":"","fork":false,"url":"https://api.github.com/repos/dimagi/commcare","forks_url":"https://api.github.com/repos/dimagi/commcare/forks","keys_url":"https://api.github.com/repos/dimagi/commcare/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dimagi/commcare/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dimagi/commcare/teams","hooks_url":"https://api.github.com/repos/dimagi/commcare/hooks","issue_events_url":"https://api.github.com/repos/dimagi/commcare/issues/events{/number}","events_url":"https://api.github.com/repos/dimagi/commcare/events","assignees_url":"https://api.github.com/repos/dimagi/commcare/assignees{/user}","branches_url":"https://api.github.com/repos/dimagi/commcare/branches{/branch}","tags_url":"https://api.github.com/repos/dimagi/commcare/tags","blobs_url":"https://api.github.com/repos/dimagi/commcare/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dimagi/commcare/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dimagi/commcare/git/refs{/sha}","trees_url":"https://api.github.com/repos/dimagi/commcare/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dimagi/commcare/statuses/{sha}","languages_url":"https://api.github.com/repos/dimagi/commcare/languages","stargazers_url":"https://api.github.com/repos/dimagi/commcare/stargazers","contributors_url":"https://api.github.com/repos/dimagi/commcare/contributors","subscribers_url":"https://api.github.com/repos/dimagi/commcare/subscribers","subscription_url":"https://api.github.com/repos/dimagi/commcare/subscription","commits_url":"https://api.github.com/repos/dimagi/commcare/commits{/sha}","git_commits_url":"https://api.github.com/repos/dimagi/commcare/git/commits{/sha}","comments_url":"https://api.github.com/repos/dimagi/commcare/comments{/number}","issue_comment_url":"https://api.github.com/repos/dimagi/commcare/issues/comments{/number}","contents_url":"https://api.github.com/repos/dimagi/commcare/contents/{+path}","compare_url":"https://api.github.com/repos/dimagi/commcare/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dimagi/commcare/merges","archive_url":"https://api.github.com/repos/dimagi/commcare/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dimagi/commcare/downloads","issues_url":"https://api.github.com/repos/dimagi/commcare/issues{/number}","pulls_url":"https://api.github.com/repos/dimagi/commcare/pulls{/number}","milestones_url":"https://api.github.com/repos/dimagi/commcare/milestones{/number}","notifications_url":"https://api.github.com/repos/dimagi/commcare/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dimagi/commcare/labels{/name}","releases_url":"https://api.github.com/repos/dimagi/commcare/releases{/id}","created_at":"2014-06-17T21:13:25Z","updated_at":"2015-05-01T15:55:40Z","pushed_at":"2015-05-19T20:32:43Z","git_url":"git://github.com/dimagi/commcare.git","ssh_url":"git@github.com:dimagi/commcare.git","clone_url":"https://github.com/dimagi/commcare.git","svn_url":"https://github.com/dimagi/commcare","homepage":null,"size":7457,"stargazers_count":2,"watchers_count":2,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"open_issues_count":2,"forks":3,"open_issues":2,"watchers":2,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dimagi/commcare/pulls/78"},"html":{"href":"https://github.com/dimagi/commcare/pull/78"},"issue":{"href":"https://api.github.com/repos/dimagi/commcare/issues/78"},"comments":{"href":"https://api.github.com/repos/dimagi/commcare/issues/78/comments"},"review_comments":{"href":"https://api.github.com/repos/dimagi/commcare/pulls/78/comments"},"review_comment":{"href":"https://api.github.com/repos/dimagi/commcare/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dimagi/commcare/pulls/78/commits"},"statuses":{"href":"https://api.github.com/repos/dimagi/commcare/statuses/46321f41357949c5849da3fa6c4582c94873d32d"}}}}