blob: f2c97c1ac97f51088b64d302a1de05d624269604 [file] [log] [blame]
// Copyright (C) 2012 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.client.changes;
import com.google.gerrit.client.actions.ActionInfo;
import com.google.gerrit.client.changes.ChangeInfo.CommitInfo;
import com.google.gerrit.client.changes.ChangeInfo.GitPerson;
import com.google.gerrit.client.changes.ChangeInfo.MessageInfo;
import com.google.gerrit.client.changes.ChangeInfo.RevisionInfo;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.ui.ListenableValue;
import com.google.gerrit.common.data.AccountInfo;
import com.google.gerrit.common.data.AccountInfoCache;
import com.google.gerrit.common.data.ChangeDetail;
import com.google.gerrit.common.data.PatchSetDetail;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.common.data.SubmitTypeRecord;
import com.google.gerrit.common.data.UiCommandDetail;
import com.google.gerrit.extensions.common.ListChangesOption;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetInfo;
import com.google.gerrit.reviewdb.client.PatchSetInfo.ParentInfo;
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.client.UserIdentity;
import com.google.gwt.core.client.JsArray;
import com.google.gwtjsonrpc.common.AsyncCallback;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
public class ChangeDetailCache extends ListenableValue<ChangeDetail> {
public static class NewGerritCallback extends
com.google.gerrit.client.rpc.GerritCallback<ChangeInfo> {
@Override
public void onSuccess(ChangeInfo detail) {
setChangeDetail(reverse(detail));
}
}
public static class IgnoreErrorCallback implements AsyncCallback<ChangeDetail> {
@Override
public void onSuccess(ChangeDetail info) {
setChangeDetail(info);
}
@Override
public void onFailure(Throwable caught) {
}
}
public static ChangeDetail reverse(ChangeInfo info) {
info.revisions().copyKeysIntoChildren("name");
RevisionInfo rev = current(info);
ChangeDetail r = new ChangeDetail();
r.setAllowsAnonymous(rev.has_fetch() && rev.fetch().containsKey("http"));
r.setCanAbandon(can(info.actions(), "abandon"));
r.setCanEditCommitMessage(can(rev.actions(), "message"));
r.setCanCherryPick(can(rev.actions(), "cherrypick"));
r.setCanPublish(can(rev.actions(), "publish"));
r.setCanRebase(can(rev.actions(), "rebase"));
r.setCanRestore(can(info.actions(), "restore"));
r.setCanRevert(can(info.actions(), "revert"));
r.setCanDeleteDraft(can(info.actions(), "/"));
r.setCanEditTopicName(can(info.actions(), "topic"));
r.setCanSubmit(can(rev.actions(), "submit"));
r.setCanEdit(true);
r.setChange(toChange(info));
r.setStarred(info.starred());
r.setPatchSets(toPatchSets(info));
r.setMessages(toMessages(info));
r.setAccounts(users(info));
r.setCurrentPatchSetId(new PatchSet.Id(info.legacy_id(), rev._number()));
r.setCurrentPatchSetDetail(toPatchSetDetail(info));
r.setSubmitRecords(new ArrayList<SubmitRecord>());
// Obtained later in ChangeScreen.
r.setSubmitTypeRecord(new SubmitTypeRecord());
r.getSubmitTypeRecord().status = SubmitTypeRecord.Status.RULE_ERROR;
r.setPatchSetsWithDraftComments(new HashSet<PatchSet.Id>());
r.setDependsOn(new ArrayList<com.google.gerrit.common.data.ChangeInfo>());
r.setNeededBy(new ArrayList<com.google.gerrit.common.data.ChangeInfo>());
return r;
}
private static PatchSetDetail toPatchSetDetail(ChangeInfo info) {
RevisionInfo rev = current(info);
PatchSetDetail p = new PatchSetDetail();
p.setPatchSet(toPatchSet(info, rev));
p.setProject(info.project_name_key());
p.setInfo(new PatchSetInfo(p.getPatchSet().getId()));
p.getInfo().setRevId(rev.name());
p.getInfo().setParents(new ArrayList<ParentInfo>());
p.getInfo().setAuthor(toUser(rev.commit().author()));
p.getInfo().setCommitter(toUser(rev.commit().committer()));
p.getInfo().setSubject(rev.commit().subject());
p.getInfo().setMessage(rev.commit().message());
if (rev.commit().parents() != null) {
for (CommitInfo c : Natives.asList(rev.commit().parents())) {
p.getInfo().getParents().add(new ParentInfo(
new RevId(c.commit()),
c.subject()));
}
}
p.setPatches(new ArrayList<Patch>());
p.setCommands(new ArrayList<UiCommandDetail>());
rev.files();
return p;
}
private static UserIdentity toUser(GitPerson p) {
UserIdentity u = new UserIdentity();
u.setName(p.name());
u.setEmail(p.email());
u.setDate(p.date());
return u;
}
public static AccountInfoCache users(ChangeInfo info) {
Map<Integer, AccountInfo> r = new HashMap<>();
add(r, info.owner());
if (info.messages() != null) {
for (MessageInfo m : Natives.asList(info.messages())) {
add(r, m.author());
}
}
return new AccountInfoCache(r.values());
}
private static void add(Map<Integer, AccountInfo> r,
com.google.gerrit.client.account.AccountInfo user) {
if (user != null && !r.containsKey(user._account_id())) {
AccountInfo a = new AccountInfo(new Account.Id(user._account_id()));
a.setPreferredEmail(user.email());
a.setFullName(user.name());
r.put(user._account_id(), a);
}
}
private static boolean can(NativeMap<ActionInfo> m, String n) {
return m != null && m.containsKey(n) && m.get(n).enabled();
}
private static List<ChangeMessage> toMessages(ChangeInfo info) {
List<ChangeMessage> msgs = new ArrayList<>();
for (MessageInfo m : Natives.asList(info.messages())) {
ChangeMessage o = new ChangeMessage(
new ChangeMessage.Key(
info.legacy_id(),
m.date().toString()),
m.author() != null
? new Account.Id(m.author()._account_id())
: null,
m.date(),
m._revisionNumber() > 0
? new PatchSet.Id(info.legacy_id(), m._revisionNumber())
: null);
o.setMessage(m.message());
msgs.add(o);
}
return msgs;
}
private static List<PatchSet> toPatchSets(ChangeInfo info) {
JsArray<RevisionInfo> all = info.revisions().values();
RevisionInfo.sortRevisionInfoByNumber(all);
List<PatchSet> r = new ArrayList<>(all.length());
for (RevisionInfo rev : Natives.asList(all)) {
r.add(toPatchSet(info, rev));
}
return r;
}
private static PatchSet toPatchSet(ChangeInfo info, RevisionInfo rev) {
PatchSet p = new PatchSet(
new PatchSet.Id(info.legacy_id(), rev._number()));
p.setCreatedOn(rev.commit().committer().date());
p.setDraft(rev.draft());
p.setRevision(new RevId(rev.name()));
return p;
}
public static Change toChange(ChangeInfo info) {
RevisionInfo rev = current(info);
PatchSetInfo p = new PatchSetInfo(
new PatchSet.Id(
info.legacy_id(),
rev._number()));
p.setSubject(info.subject());
Change c = new Change(
new Change.Key(info.change_id()),
info.legacy_id(),
new Account.Id(info.owner()._account_id()),
new Branch.NameKey(
info.project_name_key(),
info.branch()),
info.created());
c.setTopic(info.topic());
c.setStatus(info.status());
c.setCurrentPatchSet(p);
c.setLastUpdatedOn(info.updated());
c.setMergeable(info.mergeable());
return c;
}
private static RevisionInfo current(ChangeInfo info) {
RevisionInfo rev = info.revision(info.current_revision());
if (rev == null) {
JsArray<RevisionInfo> all = info.revisions().values();
RevisionInfo.sortRevisionInfoByNumber(all);
rev = all.get(all.length() - 1);
}
return rev;
}
public static void setChangeDetail(ChangeDetail detail) {
Change.Id chgId = detail.getChange().getId();
ChangeCache.get(chgId).getChangeDetailCache().set(detail);
StarredChanges.fireChangeStarEvent(chgId, detail.isStarred());
}
private final Change.Id changeId;
public ChangeDetailCache(final Change.Id chg) {
changeId = chg;
}
public void refresh() {
RestApi call = ChangeApi.detail(changeId.get());
ChangeList.addOptions(call, EnumSet.of(
ListChangesOption.CURRENT_ACTIONS,
ListChangesOption.ALL_REVISIONS,
ListChangesOption.ALL_COMMITS));
call.get(new NewGerritCallback());
}
}