Search for changes created or reviewed by a user

This change introduces two new operators in the search box:
"owner:username" and "reviewer:username".

The search is performed on the following columns from accounts:
ssh_user_name ('cbeust'), preferred_email ('cbeust@google.com') and
full_name ('Cedric Beust').
This commit is contained in:
Cedric Beust
2009-06-15 12:07:10 -07:00
committed by Shawn O. Pearce
parent 6a6aa2f262
commit cd693f1b51
5 changed files with 108 additions and 17 deletions

View File

@@ -28,7 +28,7 @@ menuPeople = People
menuGroups = Groups
menuProjects = Projects
searchHint = Change # or SHA-1
searchHint = Change #, SHA-1 or user name
searchButton = Search
rpcStatusLoading = Loading ...

View File

@@ -19,6 +19,7 @@ import com.google.gerrit.client.data.AccountInfoCacheFactory;
import com.google.gerrit.client.data.ChangeInfo;
import com.google.gerrit.client.data.SingleListChangeInfo;
import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.AccountExternalId;
import com.google.gerrit.client.reviewdb.Change;
import com.google.gerrit.client.reviewdb.ChangeAccess;
import com.google.gerrit.client.reviewdb.ChangeApproval;
@@ -174,6 +175,7 @@ public class ChangeListServiceImpl extends BaseServiceImplementation implements
private ResultSet<Change> searchQuery(final ReviewDb db, String query,
final int limit, final String key, final Comparator<Change> cmp)
throws OrmException {
List<Change> result = new ArrayList<Change>();
final HashSet<Change.Id> want = new HashSet<Change.Id>();
query = query.trim();
@@ -191,27 +193,23 @@ public class ChangeListServiceImpl extends BaseServiceImplementation implements
for (PatchSet p : patches) {
want.add(p.getId().getParentKey());
}
} else if (query.contains("owner:")) {
String[] parsedQuery = query.split(":");
if (parsedQuery.length > 1) {
filterBySortKey(result, changesCreatedBy(db, parsedQuery[1]), cmp, key);
}
} else if (query.contains("reviewer:")) {
String[] parsedQuery = query.split(":");
if (parsedQuery.length > 1) {
want.addAll(changesReviewedBy(db, parsedQuery[1]));
}
}
if (want.isEmpty()) {
if (result.isEmpty() && want.isEmpty()) {
return new ListResultSet<Change>(Collections.<Change> emptyList());
}
List<Change> result = new ArrayList<Change>();
final ResultSet<Change> rs = db.changes().get(want);
if (cmp == QUERY_PREV) {
for (Change c : rs) {
if (c.getSortKey().compareTo(key) > 0) {
result.add(c);
}
}
} else /* cmp == QUERY_NEXT */{
for (Change c : rs) {
if (c.getSortKey().compareTo(key) < 0) {
result.add(c);
}
}
}
filterBySortKey(result, db.changes().get(want), cmp, key);
Collections.sort(result, cmp);
if (limit < result.size()) {
// GWT emulation unfortunately lacks subList(int,int).
@@ -225,6 +223,23 @@ public class ChangeListServiceImpl extends BaseServiceImplementation implements
return new ListResultSet<Change>(result);
}
private static void filterBySortKey(final List<Change> dst,
final Iterable<Change> src, final Comparator<Change> cmp, final String key) {
if (cmp == QUERY_PREV) {
for (Change c : src) {
if (c.getSortKey().compareTo(key) > 0) {
dst.add(c);
}
}
} else /* cmp == QUERY_NEXT */{
for (Change c : src) {
if (c.getSortKey().compareTo(key) < 0) {
dst.add(c);
}
}
}
}
public void forAccount(final Account.Id id,
final AsyncCallback<AccountDashboardInfo> callback) {
final Account.Id me = Common.getAccountId();
@@ -401,6 +416,70 @@ public class ChangeListServiceImpl extends BaseServiceImplementation implements
return existing;
}
/**
* @return a set of all the account ID's matching the given user name in
* either of the following columns: ssh name, email address, full name
*/
private static Set<Account.Id> getAccountSources(final ReviewDb db,
final String userName) throws OrmException {
Set<Account.Id> result = new HashSet<Account.Id>();
String a = userName;
String b = userName + "\u9fa5";
addAll(result, db.accounts().suggestBySshUserName(a, b, 10));
addAll(result, db.accounts().suggestByFullName(a, b, 10));
for (AccountExternalId extId : db.accountExternalIds()
.suggestByEmailAddress(a, b, 10)) {
result.add(extId.getKey().getParentKey());
}
return result;
}
private static void addAll(Set<Account.Id> result, ResultSet<Account> rs) {
for (Account account : rs) {
result.add(account.getId());
}
}
/**
* @return a set of all the changes created by userName. This method tries to
* find userName in 1) the ssh user names, 2) the full names and 3)
* the email addresses. The returned changes are unique and sorted by
* time stamp, newer first.
*/
private List<Change> changesCreatedBy(final ReviewDb db, final String userName)
throws OrmException {
final List<Change> resultChanges = new ArrayList<Change>();
for (Account.Id account : getAccountSources(db, userName)) {
for (Change change : db.changes().byOwnerOpen(account)) {
resultChanges.add(change);
}
for (Change change : db.changes().byOwnerClosedAll(account)) {
resultChanges.add(change);
}
}
return resultChanges;
}
/**
* @return a set of all the changes reviewed by userName. This method tries to
* find userName in 1) the ssh user names, 2) the full names and the
* email addresses. The returned changes are unique and sorted by time
* stamp, newer first.
*/
private Set<Change.Id> changesReviewedBy(final ReviewDb db, final String userName)
throws OrmException {
final Set<Change.Id> resultChanges = new HashSet<Change.Id>();
for (Account.Id account : getAccountSources(db, userName)) {
for (ChangeApproval a : db.changeApprovals().openByUser(account)) {
resultChanges.add(a.getChangeId());
}
for (ChangeApproval a : db.changeApprovals().closedByUserAll(account)) {
resultChanges.add(a.getChangeId());
}
}
return resultChanges;
}
private abstract class QueryNext implements Action<SingleListChangeInfo> {
protected final String pos;
protected final int limit;

View File

@@ -42,4 +42,9 @@ public interface AccountAccess extends Access<Account, Account.Id> {
@Query("WHERE preferredEmail >= ? AND preferredEmail <= ? ORDER BY preferredEmail LIMIT ?")
ResultSet<Account> suggestByPreferredEmail(String nameA, String nameB,
int limit) throws OrmException;
@Query("WHERE sshUserName >= ? AND sshUserName <= ? ORDER BY sshUserName LIMIT ?")
ResultSet<Account> suggestBySshUserName(String nameA, String nameB, int limit)
throws OrmException;
}

View File

@@ -30,6 +30,9 @@ public interface ChangeAccess extends Access<Change, Change.Id> {
@Query("WHERE owner = ? AND open = false ORDER BY lastUpdatedOn DESC LIMIT 5")
ResultSet<Change> byOwnerClosed(Account.Id id) throws OrmException;
@Query("WHERE owner = ? AND open = false ORDER BY lastUpdatedOn")
ResultSet<Change> byOwnerClosedAll(Account.Id id) throws OrmException;
@Query("WHERE dest = ? AND status = '" + Change.STATUS_SUBMITTED
+ "' ORDER BY lastUpdatedOn")
ResultSet<Change> submitted(Branch.NameKey dest) throws OrmException;

View File

@@ -39,4 +39,8 @@ public interface ChangeApprovalAccess extends
+ " ORDER BY changeSortKey DESC LIMIT 10")
ResultSet<ChangeApproval> closedByUser(Account.Id account)
throws OrmException;
@Query("WHERE changeOpen = false AND key.accountId = ? ORDER BY changeSortKey")
ResultSet<ChangeApproval> closedByUserAll(Account.Id account)
throws OrmException;
}