Merge "Add an example hook script for checking valid commits"
diff --git a/gerrit-common/pom.xml b/gerrit-common/pom.xml
index af03191..adac3a8 100644
--- a/gerrit-common/pom.xml
+++ b/gerrit-common/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-common</artifactId>
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
index 5a85ef5..33295bc 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
@@ -33,11 +33,13 @@
   public static final String SETTINGS_NEW_AGREEMENT = "settings,new-agreement";
   public static final String REGISTER = "register";
 
+  public static final String TOP = "n,z";
+
   public static final String MINE = "mine";
   public static final String MINE_STARRED = "mine,starred";
   public static final String MINE_DRAFTS = "mine,drafts";
+  public static final String MINE_WATCHED = "mine,watched," + TOP;
 
-  public static final String TOP = "n,z";
   public static final String ALL_ABANDONED = "all,abandoned," + TOP;
   public static final String ALL_MERGED = "all,merged," + TOP;
   public static final String ALL_OPEN = "all,open," + TOP;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeListService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeListService.java
index 3473373..6f6fc09 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeListService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeListService.java
@@ -36,6 +36,14 @@
   void allOpenNext(String pos, int limit,
       AsyncCallback<SingleListChangeInfo> callback);
 
+  @SignInRequired
+  void myWatchedOpenPrev(String pos, int limit,
+      AsyncCallback<SingleListChangeInfo> callback);
+
+  @SignInRequired
+  void myWatchedOpenNext(String pos, int limit,
+      AsyncCallback<SingleListChangeInfo> callback);
+
   /** Get all open changes more recent than pos, fetching at most limit rows. */
   void byProjectOpenPrev(Project.NameKey project, String pos, int limit,
       AsyncCallback<SingleListChangeInfo> callback);
diff --git a/gerrit-gwtdebug/pom.xml b/gerrit-gwtdebug/pom.xml
index d0ef9d7..279afff 100644
--- a/gerrit-gwtdebug/pom.xml
+++ b/gerrit-gwtdebug/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-gwtdbug</artifactId>
diff --git a/gerrit-gwtui/pom.xml b/gerrit-gwtui/pom.xml
index c09a424..faceed7 100644
--- a/gerrit-gwtui/pom.xml
+++ b/gerrit-gwtui/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-gwtui</artifactId>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
index 7db92ad..de2f084 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
@@ -39,6 +39,7 @@
 import com.google.gerrit.client.changes.AllAbandonedChangesScreen;
 import com.google.gerrit.client.changes.AllMergedChangesScreen;
 import com.google.gerrit.client.changes.AllOpenChangesScreen;
+import com.google.gerrit.client.changes.MineWatchedOpenChangesScreen;
 import com.google.gerrit.client.changes.ByProjectAbandonedChangesScreen;
 import com.google.gerrit.client.changes.ByProjectMergedChangesScreen;
 import com.google.gerrit.client.changes.ByProjectOpenChangesScreen;
@@ -154,6 +155,11 @@
       return new MineDraftsScreen();
 
     } else {
+      String p = "mine,watched,";
+      if (token.startsWith(p)) {
+        return new MineWatchedOpenChangesScreen(skip(p, token));
+      }
+
       return new NotFoundScreen();
     }
   }
@@ -175,6 +181,7 @@
     if (token.startsWith(p)) {
       return new AllOpenChangesScreen(skip(p, token));
     }
+
     return new NotFoundScreen();
   }
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
index 641db80..e1b0c15 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
@@ -409,7 +409,8 @@
     if (signedIn) {
       m = new LinkMenuBar();
       addLink(m, C.menuMyChanges(), PageLinks.MINE);
-      addLink(m, C.menyMyDrafts(), PageLinks.MINE_DRAFTS);
+      addLink(m, C.menuMyDrafts(), PageLinks.MINE_DRAFTS);
+      addLink(m, C.menuMyWatchedChanges(), PageLinks.MINE_WATCHED);
       addLink(m, C.menuMyStarredChanges(), PageLinks.MINE_STARRED);
       menuLeft.add(m, C.menuMine());
       menuLeft.selectTab(1);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
index b4ffe34..1775e0c 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
@@ -47,7 +47,8 @@
 
   String menuMine();
   String menuMyChanges();
-  String menyMyDrafts();
+  String menuMyDrafts();
+  String menuMyWatchedChanges();
   String menuMyStarredChanges();
 
   String menuAdmin();
@@ -76,5 +77,6 @@
   String jumpAllMerged();
   String jumpMine();
   String jumpMineDrafts();
+  String jumpMineWatched();
   String jumpMineStarred();
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
index 4acbe17..cc1f3b5 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
@@ -30,8 +30,9 @@
 
 menuMine = My
 menuMyChanges = Changes
-menyMyDrafts = Drafts
+menuMyDrafts = Drafts
 menuMyStarredChanges = Starred Changes
+menuMyWatchedChanges = Watched Changes
 
 menuAdmin = Admin
 menuPeople = People
@@ -58,5 +59,6 @@
 jumpAllOpen = Go to all open changes
 jumpAllMerged = Go to all merged changes
 jumpMine = Go to my dashboard
+jumpMineWatched = Go to watched changes
 jumpMineDrafts = Go to drafts
 jumpMineStarred = Go to starred changes
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/JumpKeys.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/JumpKeys.java
index 6c789bf..df0a618 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/JumpKeys.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/JumpKeys.java
@@ -52,6 +52,12 @@
           Gerrit.display(PageLinks.MINE_DRAFTS);
         }
       });
+      jumps.add(new KeyCommand(0, 'w', Gerrit.C.jumpMineWatched()) {
+        @Override
+        public void onKeyPress(final KeyPressEvent event) {
+          Gerrit.display(PageLinks.MINE_WATCHED);
+        }
+      });
       jumps.add(new KeyCommand(0, 's', Gerrit.C.jumpMineStarred()) {
         @Override
         public void onKeyPress(final KeyPressEvent event) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllAbandonedChangesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllAbandonedChangesScreen.java
index 39b6162..af8aa63 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllAbandonedChangesScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllAbandonedChangesScreen.java
@@ -18,7 +18,7 @@
 import com.google.gerrit.reviewdb.Change;
 
 
-public class AllAbandonedChangesScreen extends AllSingleListScreen {
+public class AllAbandonedChangesScreen extends PagedSingleListScreen {
   public AllAbandonedChangesScreen(final String positionToken) {
     super("all,abandoned", positionToken);
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllMergedChangesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllMergedChangesScreen.java
index 9c4931a..f952337 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllMergedChangesScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllMergedChangesScreen.java
@@ -18,7 +18,7 @@
 import com.google.gerrit.reviewdb.Change;
 
 
-public class AllMergedChangesScreen extends AllSingleListScreen {
+public class AllMergedChangesScreen extends PagedSingleListScreen {
   public AllMergedChangesScreen(final String positionToken) {
     super("all,merged", positionToken);
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllOpenChangesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllOpenChangesScreen.java
index 9405066..45171e1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllOpenChangesScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllOpenChangesScreen.java
@@ -18,7 +18,7 @@
 
 
 
-public class AllOpenChangesScreen extends AllSingleListScreen {
+public class AllOpenChangesScreen extends PagedSingleListScreen {
   public AllOpenChangesScreen(final String positionToken) {
     super("all,open", positionToken);
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ByProjectAbandonedChangesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ByProjectAbandonedChangesScreen.java
index 79d00ef..de74452 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ByProjectAbandonedChangesScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ByProjectAbandonedChangesScreen.java
@@ -18,7 +18,7 @@
 import com.google.gerrit.reviewdb.Project;
 
 
-public class ByProjectAbandonedChangesScreen extends AllSingleListScreen {
+public class ByProjectAbandonedChangesScreen extends PagedSingleListScreen {
   private final Project.NameKey projectKey;
 
   public ByProjectAbandonedChangesScreen(final Project.NameKey proj,
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ByProjectMergedChangesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ByProjectMergedChangesScreen.java
index 55caf90..8a21840 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ByProjectMergedChangesScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ByProjectMergedChangesScreen.java
@@ -18,7 +18,7 @@
 import com.google.gerrit.reviewdb.Project;
 
 
-public class ByProjectMergedChangesScreen extends AllSingleListScreen {
+public class ByProjectMergedChangesScreen extends PagedSingleListScreen {
   private final Project.NameKey projectKey;
 
   public ByProjectMergedChangesScreen(final Project.NameKey proj,
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ByProjectOpenChangesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ByProjectOpenChangesScreen.java
index f9525a4..b55e86b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ByProjectOpenChangesScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ByProjectOpenChangesScreen.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.reviewdb.Project;
 
 
-public class ByProjectOpenChangesScreen extends AllSingleListScreen {
+public class ByProjectOpenChangesScreen extends PagedSingleListScreen {
   private final Project.NameKey projectKey;
 
   public ByProjectOpenChangesScreen(final Project.NameKey proj,
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
index 4e34d25..b5b4786 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
@@ -25,6 +25,7 @@
   String changesRecentlyClosed();
 
   String starredHeading();
+  String watchedHeading();
   String draftsHeading();
   String allOpenChanges();
   String allAbandonedChanges();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
index 7211c94..63e06f0 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
@@ -4,6 +4,7 @@
 statusLongAbandoned = Abandoned
 
 starredHeading = Starred Changes
+watchedHeading = Open Changes of Watched Projects
 draftsHeading = Changes with unpublished drafts
 changesRecentlyClosed = Recently closed
 allOpenChanges = All open changes
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeQueryResultsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeQueryResultsScreen.java
index 001a06f..ec4a4a5 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeQueryResultsScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeQueryResultsScreen.java
@@ -24,7 +24,7 @@
 
 
 
-public class ChangeQueryResultsScreen extends AllSingleListScreen {
+public class ChangeQueryResultsScreen extends PagedSingleListScreen {
   private final String query;
 
   public ChangeQueryResultsScreen(final String encQuery,
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/MineDraftsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/MineDraftsScreen.java
index 2b935ba..75f42b1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/MineDraftsScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/MineDraftsScreen.java
@@ -26,7 +26,7 @@
   @Override
   protected void onInitUI() {
     super.onInitUI();
-    setWindowTitle(Gerrit.C.menyMyDrafts());
+    setWindowTitle(Gerrit.C.menuMyDrafts());
     setPageTitle(Util.C.draftsHeading());
   }
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/MineWatchedOpenChangesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/MineWatchedOpenChangesScreen.java
new file mode 100644
index 0000000..8e31b36
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/MineWatchedOpenChangesScreen.java
@@ -0,0 +1,41 @@
+// Copyright (C) 2010 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.Gerrit;
+
+public class MineWatchedOpenChangesScreen extends PagedSingleListScreen {
+  public MineWatchedOpenChangesScreen(final String positionToken) {
+    super("mine,watched", positionToken);
+    setRequiresSignIn(true);
+  }
+
+  @Override
+  protected void onInitUI() {
+    super.onInitUI();
+    setWindowTitle(Gerrit.C.menuMyWatchedChanges());
+    setPageTitle(Util.C.watchedHeading());
+  }
+
+  @Override
+  protected void loadPrev() {
+    Util.LIST_SVC.myWatchedOpenPrev(pos, pageSize, loadCallback());
+  }
+
+  @Override
+  protected void loadNext() {
+    Util.LIST_SVC.myWatchedOpenNext(pos, pageSize, loadCallback());
+  }
+}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllSingleListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PagedSingleListScreen.java
similarity index 97%
rename from gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllSingleListScreen.java
rename to gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PagedSingleListScreen.java
index 941d762..6ca102f 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AllSingleListScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PagedSingleListScreen.java
@@ -31,7 +31,7 @@
 import java.util.List;
 
 
-public abstract class AllSingleListScreen extends Screen {
+public abstract class PagedSingleListScreen extends Screen {
   protected static final String MIN_SORTKEY = "";
   protected static final String MAX_SORTKEY = "z";
 
@@ -46,7 +46,7 @@
   protected boolean useLoadPrev;
   protected String pos;
 
-  protected AllSingleListScreen(final String anchorToken,
+  protected PagedSingleListScreen(final String anchorToken,
       final String positionToken) {
     anchorPrefix = anchorToken;
     useLoadPrev = positionToken.startsWith("p,");
diff --git a/gerrit-httpd/pom.xml b/gerrit-httpd/pom.xml
index 39b2788..b02b142 100644
--- a/gerrit-httpd/pom.xml
+++ b/gerrit-httpd/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-httpd</artifactId>
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
index 0c25404..ce350a3 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
@@ -64,6 +64,7 @@
     serve("/mine").with(screen(PageLinks.MINE));
     serve("/open").with(screen(PageLinks.ALL_OPEN));
     serve("/settings").with(screen(PageLinks.SETTINGS));
+    serve("/watched").with(screen(PageLinks.MINE_WATCHED));
     serve("/starred").with(screen(PageLinks.MINE_STARRED));
 
     serveRegex( //
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/ChangeListServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/ChangeListServiceImpl.java
index d71a781..56f5a0f 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/ChangeListServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/ChangeListServiceImpl.java
@@ -36,6 +36,7 @@
 import com.google.gerrit.reviewdb.TrackingId;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.account.AccountInfoCacheFactory;
+import com.google.gerrit.server.config.WildProjectName;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -89,16 +90,19 @@
   private final Provider<CurrentUser> currentUser;
   private final ChangeControl.Factory changeControlFactory;
   private final AccountInfoCacheFactory.Factory accountInfoCacheFactory;
+  private final Project.NameKey wildProject;
 
   @Inject
   ChangeListServiceImpl(final Provider<ReviewDb> schema,
       final Provider<CurrentUser> currentUser,
       final ChangeControl.Factory changeControlFactory,
-      final AccountInfoCacheFactory.Factory accountInfoCacheFactory) {
+      final AccountInfoCacheFactory.Factory accountInfoCacheFactory,
+      final @WildProjectName Project.NameKey wildProject) {
     super(schema, currentUser);
     this.currentUser = currentUser;
     this.changeControlFactory = changeControlFactory;
     this.accountInfoCacheFactory = accountInfoCacheFactory;
+    this.wildProject = wildProject;
   }
 
   private boolean canRead(final Change c) {
@@ -131,6 +135,43 @@
     });
   }
 
+  public void myWatchedOpenPrev(final String pos, final int pageSize,
+      final AsyncCallback<SingleListChangeInfo> callback) {
+    run(callback, new QueryPrev(pageSize, pos) {
+      @Override
+      ResultSet<Change> query(ReviewDb db, int slim, String sortKey)
+          throws OrmException {
+        return db.changes().allOpenPrev(sortKey, slim);
+      }
+
+      @Override
+      protected boolean accept(Change c) {
+        return isWatched(c);
+      }
+    });
+  }
+
+  public void myWatchedOpenNext(final String pos, final int pageSize,
+      final AsyncCallback<SingleListChangeInfo> callback) {
+    run(callback, new QueryNext(pageSize, pos) {
+      @Override
+      ResultSet<Change> query(ReviewDb db, int slim, String sortKey)
+          throws OrmException {
+        return db.changes().allOpenNext(sortKey, slim);
+      }
+
+      @Override
+      protected boolean accept(Change c) {
+        return isWatched(c);
+      }
+    });
+  }
+
+  private boolean isWatched(Change c) {
+    Set<Project.NameKey> watchedProjects = currentUser.get().getWatchedProjects();
+    return watchedProjects.contains(c.getProject()) || watchedProjects.contains(wildProject);
+  }
+
   public void byProjectOpenPrev(final Project.NameKey project,
       final String pos, final int pageSize,
       final AsyncCallback<SingleListChangeInfo> callback) {
@@ -569,7 +610,7 @@
         final ResultSet<Change> rs = query(db, slim, sortKey);
         for (final Change c : rs) {
           results = true;
-          if (canRead(c)) {
+          if (canRead(c) && accept(c)) {
             final ChangeInfo ci = new ChangeInfo(c);
             ac.want(ci.getOwner());
             ci.setStarred(starred.contains(ci.getId()));
@@ -589,6 +630,10 @@
       return d;
     }
 
+    protected boolean accept(final Change c) {
+      return true;
+    }
+
     boolean finish(final ArrayList<ChangeInfo> list) {
       final boolean atEnd = list.size() <= limit;
       if (list.size() == slim) {
diff --git a/gerrit-launcher/pom.xml b/gerrit-launcher/pom.xml
index 3c9c979..1000777 100644
--- a/gerrit-launcher/pom.xml
+++ b/gerrit-launcher/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-launcher</artifactId>
diff --git a/gerrit-main/pom.xml b/gerrit-main/pom.xml
index a46aa4f..10cb14a 100644
--- a/gerrit-main/pom.xml
+++ b/gerrit-main/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-main</artifactId>
diff --git a/gerrit-patch-commonsnet/pom.xml b/gerrit-patch-commonsnet/pom.xml
index 5bbae03..df64d13 100644
--- a/gerrit-patch-commonsnet/pom.xml
+++ b/gerrit-patch-commonsnet/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-patch-commonsnet</artifactId>
diff --git a/gerrit-patch-jgit/pom.xml b/gerrit-patch-jgit/pom.xml
index f30eace..68a08c3 100644
--- a/gerrit-patch-jgit/pom.xml
+++ b/gerrit-patch-jgit/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-patch-jgit</artifactId>
diff --git a/gerrit-pgm/pom.xml b/gerrit-pgm/pom.xml
index f658f52..66c5349 100644
--- a/gerrit-pgm/pom.xml
+++ b/gerrit-pgm/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-pgm</artifactId>
diff --git a/gerrit-prettify/pom.xml b/gerrit-prettify/pom.xml
index 45f7cc5..fb0860e 100644
--- a/gerrit-prettify/pom.xml
+++ b/gerrit-prettify/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-prettify</artifactId>
diff --git a/gerrit-reviewdb/pom.xml b/gerrit-reviewdb/pom.xml
index d81b068..5626739 100644
--- a/gerrit-reviewdb/pom.xml
+++ b/gerrit-reviewdb/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-reviewdb</artifactId>
diff --git a/gerrit-server/pom.xml b/gerrit-server/pom.xml
index bf32075..e3ce9a0 100644
--- a/gerrit-server/pom.xml
+++ b/gerrit-server/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-server</artifactId>
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/AnonymousUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/AnonymousUser.java
index a171497..ff6f43d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/AnonymousUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/AnonymousUser.java
@@ -16,6 +16,7 @@
 
 import com.google.gerrit.reviewdb.AccountGroup;
 import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.Project.NameKey;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
@@ -42,6 +43,11 @@
   }
 
   @Override
+  public Set<NameKey> getWatchedProjects() {
+    return Collections.emptySet();
+  }
+
+  @Override
   public String toString() {
     return "ANONYMOUS";
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/CurrentUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/CurrentUser.java
index 17e69c7..207d5cc 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/CurrentUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/CurrentUser.java
@@ -16,6 +16,7 @@
 
 import com.google.gerrit.reviewdb.AccountGroup;
 import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.Project;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.inject.servlet.RequestScoped;
 
@@ -59,6 +60,9 @@
   /** Set of changes starred by this user. */
   public abstract Set<Change.Id> getStarredChanges();
 
+  /** Set of project that are watched by this user */
+  public abstract Set<Project.NameKey> getWatchedProjects();
+
   /** Is the user a non-interactive user? */
   public boolean isBatchUser() {
     return getEffectiveGroups().contains(authConfig.getBatchUsersGroup());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/IdentifiedUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/IdentifiedUser.java
index 6900538..60d6d81 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/IdentifiedUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/IdentifiedUser.java
@@ -16,9 +16,12 @@
 
 import com.google.gerrit.reviewdb.Account;
 import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.AccountProjectWatch;
 import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.Project;
 import com.google.gerrit.reviewdb.ReviewDb;
 import com.google.gerrit.reviewdb.StarredChange;
+import com.google.gerrit.reviewdb.Project.NameKey;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.account.AccountState;
 import com.google.gerrit.server.account.Realm;
@@ -138,6 +141,7 @@
   private Set<String> emailAddresses;
   private Set<AccountGroup.Id> effectiveGroups;
   private Set<Change.Id> starredChanges;
+  private Set<Project.NameKey> watchedProjects;
 
   private IdentifiedUser(final AccessPath accessPath,
       final AuthConfig authConfig, final Provider<String> canonicalUrl,
@@ -206,8 +210,6 @@
             .byAccount(getAccountId())) {
           h.add(sc.getChangeId());
         }
-      } catch (ProvisionException e) {
-        log.warn("Cannot query starred by user changes", e);
       } catch (OrmException e) {
         log.warn("Cannot query starred by user changes", e);
       }
@@ -216,6 +218,27 @@
     return starredChanges;
   }
 
+  @Override
+  public Set<Project.NameKey> getWatchedProjects() {
+    if (watchedProjects == null) {
+      if (dbProvider == null) {
+        throw new OutOfScopeException("Not in request scoped user");
+      }
+      final Set<Project.NameKey> h = new HashSet<Project.NameKey>();
+      try {
+        for (AccountProjectWatch projectWatch : dbProvider.get()
+            .accountProjectWatches().byAccount(getAccountId())) {
+          h.add(projectWatch.getProjectNameKey());
+        }
+      } catch (OrmException e) {
+        log.warn("Cannot query project watches of a user", e);
+      }
+      watchedProjects = Collections.unmodifiableSet(h);
+    }
+
+    return watchedProjects;
+  }
+
   public PersonIdent newRefLogIdent() {
     return newRefLogIdent(new Date(), TimeZone.getDefault());
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/PeerDaemonUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/PeerDaemonUser.java
index 26e510f..d44643b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/PeerDaemonUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/PeerDaemonUser.java
@@ -16,6 +16,7 @@
 
 import com.google.gerrit.reviewdb.AccountGroup;
 import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.Project.NameKey;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
@@ -57,6 +58,11 @@
     return Collections.emptySet();
   }
 
+  @Override
+  public Set<NameKey> getWatchedProjects() {
+    return Collections.emptySet();
+  }
+
   public SocketAddress getRemoteAddress() {
     return peer;
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ReplicationUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/ReplicationUser.java
index 1b010a6..b21df8a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ReplicationUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ReplicationUser.java
@@ -16,6 +16,7 @@
 
 import com.google.gerrit.reviewdb.AccountGroup;
 import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.Project.NameKey;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
@@ -71,6 +72,11 @@
     return Collections.emptySet();
   }
 
+  @Override
+  public Set<NameKey> getWatchedProjects() {
+    return Collections.emptySet();
+  }
+
   public boolean isEverythingVisible() {
     return getEffectiveGroups() == EVERYTHING_VISIBLE;
   }
diff --git a/gerrit-sshd/pom.xml b/gerrit-sshd/pom.xml
index 32bcf57..2bb4713 100644
--- a/gerrit-sshd/pom.xml
+++ b/gerrit-sshd/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-sshd</artifactId>
diff --git a/gerrit-util-cli/pom.xml b/gerrit-util-cli/pom.xml
index 6db5241..20f28e1 100644
--- a/gerrit-util-cli/pom.xml
+++ b/gerrit-util-cli/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-util-cli</artifactId>
diff --git a/gerrit-util-ssl/pom.xml b/gerrit-util-ssl/pom.xml
index 39d3ce0..220ae47 100644
--- a/gerrit-util-ssl/pom.xml
+++ b/gerrit-util-ssl/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-util-ssl</artifactId>
diff --git a/gerrit-war/pom.xml b/gerrit-war/pom.xml
index 524dc5b..9f40581 100644
--- a/gerrit-war/pom.xml
+++ b/gerrit-war/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.1-SNAPSHOT</version>
+    <version>2.1.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-war</artifactId>
diff --git a/pom.xml b/pom.xml
index cbc1e08..dde9a0b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-parent</artifactId>
   <packaging>pom</packaging>
-  <version>2.1-SNAPSHOT</version>
+  <version>2.1.4-SNAPSHOT</version>
 
   <name>Gerrit Code Review - Parent</name>
   <url>http://code.google.com/p/gerrit/</url>