Add REST endpoint for included in

Change-Id: I686bc67ae01afc58b07d7b8cb53f9028d1e96d1a
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index fc23dda..e2a8fbe 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -976,6 +976,36 @@
   HTTP/1.1 204 No Content
 ----
 
+[[get-included-in]]
+Get Included In
+~~~~~~~~~~~~~~~
+[verse]
+'GET /changes/link:#change-id[\{change-id\}]/in'
+
+Retrieves the branches and tags in which a change is included. As result
+an link:#included-in-info[IncludedInInfo] entity is returned.
+
+.Request
+----
+  GET /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/in HTTP/1.0
+----
+
+.Response
+----
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json;charset=UTF-8
+
+  )]}'
+  {
+    "kind": "gerritcodereview#includedininfo",
+    "branches": [
+      "master"
+    ],
+    "tags": []
+  }
+----
+
 [[reviewer-endpoints]]
 Reviewer Endpoints
 ------------------
@@ -3275,6 +3305,22 @@
 topic.
 |===========================
 
+[[included-in-info]]
+IncludedInInfo
+~~~~~~~~~~~~~~
+The `IncludedInInfo` entity contains information about the branches a
+change was merged into and tags it was tagged with.
+
+[options="header",width="50%",cols="1,6"]
+|==========================
+|Field Name |Description
+|`kind`     |`gerritcodereview#includedininfo`
+|`branches` | The list of branches this change was merged into.
+Each branch is listed without the 'refs/head/' prefix.
+|`tags`     | The list of tags this change was tagged with.
+Each tag is listed without the 'refs/tags/' prefix.
+|==========================
+
 
 GERRIT
 ------
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java
new file mode 100644
index 0000000..26e7846
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java
@@ -0,0 +1,88 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.change;
+
+import com.google.gerrit.common.data.IncludedInDetail;
+import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.project.ChangeControl;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+import java.io.IOException;
+import java.util.Collection;
+
+class IncludedIn implements RestReadView<ChangeResource> {
+
+  private final ReviewDb db;
+  private final GitRepositoryManager repoManager;
+
+  @Inject
+  IncludedIn(ReviewDb db, GitRepositoryManager repoManager) {
+    this.db = db;
+    this.repoManager = repoManager;
+  }
+
+  @Override
+  public Object apply(ChangeResource rsrc) throws OrmException, IOException,
+      BadRequestException, ResourceConflictException {
+    ChangeControl ctl = rsrc.getControl();
+    PatchSet ps =
+        db.patchSets().get(ctl.getChange().currentPatchSetId());
+    Repository r =
+        repoManager.openRepository(ctl.getProject().getNameKey());
+    try {
+      RevWalk rw = new RevWalk(r);
+      try {
+        rw.setRetainBody(false);
+        RevCommit rev;
+        try {
+          rev = rw.parseCommit(ObjectId.fromString(ps.getRevision().get()));
+        } catch (IncorrectObjectTypeException err) {
+          throw new BadRequestException(err.getMessage());
+        } catch (MissingObjectException err) {
+          throw new ResourceConflictException(err.getMessage());
+        }
+        return new IncludedInInfo(IncludedInResolver.resolve(r, rw, rev));
+      } finally {
+        rw.release();
+      }
+    } finally {
+      r.close();
+    }
+  }
+
+  static class IncludedInInfo {
+    String kind = "gerritcodereview#includedininfo";
+    Collection<String> branches;
+    Collection<String> tags;
+
+    IncludedInInfo(IncludedInDetail in) {
+      branches = in.getBranches();
+      tags = in.getTags();
+    }
+  }
+}
\ No newline at end of file
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Module.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Module.java
index d1fd730..7fb09b5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Module.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Module.java
@@ -47,6 +47,7 @@
     get(CHANGE_KIND).to(GetChange.class);
     get(CHANGE_KIND, "detail").to(GetDetail.class);
     get(CHANGE_KIND, "topic").to(GetTopic.class);
+    get(CHANGE_KIND, "in").to(IncludedIn.class);
     put(CHANGE_KIND, "topic").to(PutTopic.class);
     delete(CHANGE_KIND, "topic").to(PutTopic.class);
     delete(CHANGE_KIND).to(DeleteDraftChange.class);