From 9119cf9d89257717b486c59b73bacc7c375501fc Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Fri, 04 Nov 2011 17:24:45 -0400
Subject: [PATCH] Search added to gbapi. Search dialog for Manager. Misc Manager fixes.

---
 src/com/gitblit/wicket/GitBlitWebApp.properties |    3 
 src/com/gitblit/client/BranchRenderer.java      |   36 +++
 src/com/gitblit/client/GitblitClient.java       |   23 ++
 src/com/gitblit/client/RepositoriesPanel.java   |   34 +++
 src/com/gitblit/client/SearchDialog.java        |  329 +++++++++++++++++++++++++++++++++++++++++
 src/com/gitblit/wicket/pages/BasePage.java      |    1 
 build.xml                                       |    5 
 src/com/gitblit/client/MessageRenderer.java     |   19 +
 src/com/gitblit/client/SubscriptionsDialog.java |    2 
 9 files changed, 435 insertions(+), 17 deletions(-)

diff --git a/build.xml b/build.xml
index 854b5f1..085bc28 100644
--- a/build.xml
+++ b/build.xml
@@ -454,6 +454,7 @@
 			<resource file="${basedir}/resources/health_16x16.png" />
 			<resource file="${basedir}/resources/feed_16x16.png" />
 			<resource file="${basedir}/resources/bullet_feed.png" />
+			<resource file="${basedir}/resources/search-icon.png" />
 			<resource file="${basedir}/resources/blank.png" />
 			<resource file="${basedir}/src/com/gitblit/wicket/GitBlitWebApp.properties" />
 				
@@ -490,6 +491,7 @@
 				<classpath refid="master-classpath" />
 				<classfilter>
 					<exclude name="com.google.gson." />
+					<exclude name="com.sun.syndication." />
 				</classfilter>
 				<manifest>
 					<attribute name="Specification-Version" value="${gb.version}" />
@@ -506,6 +508,9 @@
 					<include name="gson*.jar" />
 					<exclude name="gson*-sources.jar" />
 					<exclude name="gson*-javadoc.jar" />
+					<include name="rome*.jar" />
+					<exclude name="rome*-sources.jar" />
+					<exclude name="rome*-javadoc.jar" />
 				</fileset>
 			</zip>
 		</target>
diff --git a/src/com/gitblit/client/BranchRenderer.java b/src/com/gitblit/client/BranchRenderer.java
index 532a432..586d050 100644
--- a/src/com/gitblit/client/BranchRenderer.java
+++ b/src/com/gitblit/client/BranchRenderer.java
@@ -18,7 +18,9 @@
 import java.awt.Color;
 import java.awt.Component;
 
+import javax.swing.JList;
 import javax.swing.JTable;
+import javax.swing.ListCellRenderer;
 import javax.swing.table.DefaultTableCellRenderer;
 
 /**
@@ -28,7 +30,7 @@
  * @author James Moger
  * 
  */
-public class BranchRenderer extends DefaultTableCellRenderer {
+public class BranchRenderer extends DefaultTableCellRenderer implements ListCellRenderer {
 
 	private static final long serialVersionUID = 1L;
 
@@ -39,7 +41,32 @@
 	public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
 			boolean hasFocus, int row, int column) {
 		super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
-		String name = value.toString();
+		if (value == null) {
+			return this;
+		}
+		setText(value.toString());
+		if (isSelected) {
+			setForeground(table.getSelectionForeground());
+		}
+		return this;
+	}
+
+	@Override
+	public Component getListCellRendererComponent(JList list, Object value, int index,
+			boolean isSelected, boolean cellHasFocus) {
+		setText(value.toString());
+		if (isSelected) {
+			setBackground(list.getSelectionBackground());
+			setForeground(list.getSelectionForeground());
+		} else {
+			setBackground(list.getBackground());
+		}
+		return this;
+	}
+
+	@Override
+	public void setText(String text) {
+		String name = text;
 		Color fg = getForeground();
 		if (name.startsWith(R_HEADS)) {
 			name = name.substring(R_HEADS.length());
@@ -48,8 +75,7 @@
 			name = name.substring(R_REMOTES.length());
 			fg = Color.decode("#6C6CBF");
 		}
-		setText(name);
-		setForeground(isSelected ? table.getSelectionForeground() : fg);
-		return this;
+		setForeground(fg);
+		super.setText(name);
 	}
 }
\ No newline at end of file
diff --git a/src/com/gitblit/client/GitblitClient.java b/src/com/gitblit/client/GitblitClient.java
index dcc7dfc..e8460f5 100644
--- a/src/com/gitblit/client/GitblitClient.java
+++ b/src/com/gitblit/client/GitblitClient.java
@@ -25,6 +25,7 @@
 import java.util.Map;
 import java.util.Set;
 
+import com.gitblit.Constants;
 import com.gitblit.GitBlitException.ForbiddenException;
 import com.gitblit.GitBlitException.NotAllowedException;
 import com.gitblit.GitBlitException.UnauthorizedException;
@@ -213,17 +214,31 @@
 		return status;
 	}
 
+	public List<String> getBranches(String repository) {
+		List<FeedModel> feeds = getAvailableFeeds(repository);
+		List<String> branches = new ArrayList<String>();
+		for (FeedModel feed : feeds) {
+			branches.add(feed.branch);
+		}
+		Collections.sort(branches);
+		return branches;
+	}
+
 	public List<FeedModel> getAvailableFeeds() {
 		return availableFeeds;
 	}
 
 	public List<FeedModel> getAvailableFeeds(RepositoryModel repository) {
+		return getAvailableFeeds(repository.name);
+	}
+
+	public List<FeedModel> getAvailableFeeds(String repository) {
 		List<FeedModel> repositoryFeeds = new ArrayList<FeedModel>();
 		if (repository == null) {
 			return repositoryFeeds;
 		}
 		for (FeedModel feed : availableFeeds) {
-			if (feed.repository.equalsIgnoreCase(repository.name)) {
+			if (feed.repository.equalsIgnoreCase(repository)) {
 				repositoryFeeds.add(feed);
 			}
 		}
@@ -292,6 +307,12 @@
 		return syndicatedEntries;
 	}
 
+	public List<SyndicatedEntryModel> search(String repository, String branch, String fragment,
+			Constants.SearchType type, int numberOfEntries) throws IOException {
+		return SyndicationUtils.readSearchFeed(url, repository, branch, fragment, type,
+				numberOfEntries, account, password);
+	}
+
 	public List<FederationModel> refreshFederationRegistrations() throws IOException {
 		List<FederationModel> list = RpcUtils.getFederationRegistrations(url, account, password);
 		federationRegistrations.clear();
diff --git a/src/com/gitblit/client/MessageRenderer.java b/src/com/gitblit/client/MessageRenderer.java
index c848cef..2ff3527 100644
--- a/src/com/gitblit/client/MessageRenderer.java
+++ b/src/com/gitblit/client/MessageRenderer.java
@@ -53,6 +53,10 @@
 
 	private final JLabel branchLabel;
 
+	public MessageRenderer() {
+		this(null);
+	}
+
 	public MessageRenderer(GitblitClient gitblit) {
 		super(new FlowLayout(FlowLayout.LEFT, 10, 1));
 		this.gitblit = gitblit;
@@ -75,12 +79,17 @@
 		messageLabel.setForeground(isSelected ? table.getSelectionForeground() : table
 				.getForeground());
 		SyndicatedEntryModel entry = (SyndicatedEntryModel) value;
-		
-		// show message in BOLD if its a new entry
-		if (entry.published.after(gitblit.getLastFeedRefresh(entry.repository, entry.branch))) {
-			messageLabel.setText("<html><body><b>" + entry.title);
-		} else {
+
+		if (gitblit == null) {
+			// no gitblit client, just display message
 			messageLabel.setText(entry.title);
+		} else {
+			// show message in BOLD if its a new entry
+			if (entry.published.after(gitblit.getLastFeedRefresh(entry.repository, entry.branch))) {
+				messageLabel.setText("<html><body><b>" + entry.title);
+			} else {
+				messageLabel.setText(entry.title);
+			}
 		}
 
 		// reset ref label
diff --git a/src/com/gitblit/client/RepositoriesPanel.java b/src/com/gitblit/client/RepositoriesPanel.java
index 20b9080..3e156e9 100644
--- a/src/com/gitblit/client/RepositoriesPanel.java
+++ b/src/com/gitblit/client/RepositoriesPanel.java
@@ -134,6 +134,15 @@
 			}
 		});
 
+		final JButton searchRepository = new JButton(Translation.get("gb.search") + "...");
+		searchRepository.setEnabled(false);
+		searchRepository.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				RepositoryModel model = getSelectedRepositories().get(0);
+				searchRepository(model);
+			}
+		});
+
 		SubscribedRepositoryRenderer nameRenderer = new SubscribedRepositoryRenderer(gitblit);
 		IndicatorsRenderer typeRenderer = new IndicatorsRenderer();
 
@@ -164,10 +173,18 @@
 					return;
 				}
 				boolean singleSelection = table.getSelectedRowCount() == 1;
-				boolean selected = table.getSelectedRow() > -1;
-				browseRepository.setEnabled(singleSelection);
-				delRepository.setEnabled(selected);
-				subscribeRepository.setEnabled(singleSelection);
+				boolean selected = table.getSelectedRow() > -1;				
+				if (singleSelection) {
+					RepositoryModel repository = getSelectedRepositories().get(0);
+					browseRepository.setEnabled(repository.hasCommits);
+					searchRepository.setEnabled(repository.hasCommits);
+					subscribeRepository.setEnabled(repository.hasCommits);
+				} else {
+					browseRepository.setEnabled(false);
+					searchRepository.setEnabled(false);
+					subscribeRepository.setEnabled(false);
+				}
+				delRepository.setEnabled(selected);				
 				if (selected) {
 					int viewRow = table.getSelectedRow();
 					int modelRow = table.convertRowIndexToModel(viewRow);
@@ -216,6 +233,7 @@
 		repositoryControls.add(editRepository);
 		repositoryControls.add(delRepository);
 		repositoryControls.add(subscribeRepository);
+		repositoryControls.add(searchRepository);
 
 		setLayout(new BorderLayout(Utils.MARGIN, Utils.MARGIN));
 		header = new HeaderPanel(Translation.get("gb.repositories"), "gitweb-favicon.png");
@@ -449,4 +467,12 @@
 		}
 	}
 
+	protected void searchRepository(final RepositoryModel repository) {
+		SearchDialog searchDialog = new SearchDialog(gitblit);
+		if (repository != null) {
+			searchDialog.selectRepository(repository);
+		}
+		searchDialog.setLocationRelativeTo(this);
+		searchDialog.setVisible(true);
+	}
 }
diff --git a/src/com/gitblit/client/SearchDialog.java b/src/com/gitblit/client/SearchDialog.java
new file mode 100644
index 0000000..2f45611
--- /dev/null
+++ b/src/com/gitblit/client/SearchDialog.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2011 gitblit.com.
+ *
+ * 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.gitblit.client;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.IOException;
+import java.util.List;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.SwingWorker;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import com.gitblit.Constants;
+import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.SyndicatedEntryModel;
+import com.gitblit.utils.StringUtils;
+
+/**
+ * The search dialog allows searching of a repository branch. This matches the
+ * search implementation of the site.
+ * 
+ * @author James Moger
+ * 
+ */
+public class SearchDialog extends JFrame {
+
+	private static final long serialVersionUID = 1L;
+
+	private final GitblitClient gitblit;
+
+	private SyndicatedEntryTableModel tableModel;
+
+	private HeaderPanel header;
+
+	private JTable table;
+
+	private JComboBox repositorySelector;
+
+	private DefaultComboBoxModel branchChoices;
+
+	private JComboBox branchSelector;
+
+	private JComboBox searchTypeSelector;
+
+	private JTextField searchFragment;
+
+	private JComboBox maxHitsSelector;
+
+	public SearchDialog(GitblitClient gitblit) {
+		super();
+		this.gitblit = gitblit;
+		setTitle(Translation.get("gb.search"));
+		setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());
+		initialize();
+		setSize(900, 400);
+	}
+
+	private void initialize() {
+
+		final JButton search = new JButton(Translation.get("gb.search"));
+		search.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				search();
+			}
+		});
+
+		final JButton viewCommit = new JButton(Translation.get("gb.view"));
+		viewCommit.setEnabled(false);
+		viewCommit.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				viewCommit();
+			}
+		});
+
+		final JButton viewCommitDiff = new JButton(Translation.get("gb.commitdiff"));
+		viewCommitDiff.setEnabled(false);
+		viewCommitDiff.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				viewCommitDiff();
+			}
+		});
+
+		final JButton viewTree = new JButton(Translation.get("gb.tree"));
+		viewTree.setEnabled(false);
+		viewTree.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				viewTree();
+			}
+		});
+
+		JPanel controls = new JPanel(new FlowLayout(FlowLayout.CENTER, Utils.MARGIN, 0));
+		controls.add(viewCommit);
+		controls.add(viewCommitDiff);
+		controls.add(viewTree);
+
+		NameRenderer nameRenderer = new NameRenderer();
+		tableModel = new SyndicatedEntryTableModel();
+		header = new HeaderPanel(Translation.get("gb.search"), "search-icon.png");
+		table = Utils.newTable(tableModel, Utils.DATE_FORMAT);
+
+		String name = table.getColumnName(SyndicatedEntryTableModel.Columns.Author.ordinal());
+		table.setRowHeight(nameRenderer.getFont().getSize() + 8);
+		table.getColumn(name).setCellRenderer(nameRenderer);
+		name = table.getColumnName(SyndicatedEntryTableModel.Columns.Repository.ordinal());
+		table.getColumn(name).setCellRenderer(nameRenderer);
+
+		name = table.getColumnName(SyndicatedEntryTableModel.Columns.Branch.ordinal());
+		table.getColumn(name).setCellRenderer(new BranchRenderer());
+
+		name = table.getColumnName(SyndicatedEntryTableModel.Columns.Message.ordinal());
+		table.getColumn(name).setCellRenderer(new MessageRenderer());
+
+		table.addMouseListener(new MouseAdapter() {
+			public void mouseClicked(MouseEvent e) {
+				if (e.getClickCount() == 2) {
+					if (e.isControlDown()) {
+						viewCommitDiff();
+					} else {
+						viewCommit();
+					}
+				}
+			}
+		});
+
+		table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+			@Override
+			public void valueChanged(ListSelectionEvent e) {
+				if (e.getValueIsAdjusting()) {
+					return;
+				}
+				boolean singleSelection = table.getSelectedRowCount() == 1;
+				viewCommit.setEnabled(singleSelection);
+				viewCommitDiff.setEnabled(singleSelection);
+				viewTree.setEnabled(singleSelection);
+			}
+		});
+
+		repositorySelector = new JComboBox(gitblit.getRepositories().toArray());
+		repositorySelector.setRenderer(nameRenderer);
+		repositorySelector.setForeground(nameRenderer.getForeground());
+		repositorySelector.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent event) {
+				// repopulate the branch list based on repository selection
+				// preserve branch selection, if possible
+				String selectedBranch = null;
+				if (branchSelector.getSelectedIndex() > -1) {
+					selectedBranch = branchSelector.getSelectedItem().toString();
+				}
+				updateBranches();
+				if (selectedBranch != null) {
+					if (branchChoices.getIndexOf(selectedBranch) > -1) {
+						branchChoices.setSelectedItem(selectedBranch);
+					}
+				}
+			}
+		});
+
+		branchChoices = new DefaultComboBoxModel();
+		branchSelector = new JComboBox(branchChoices);
+		branchSelector.setRenderer(new BranchRenderer());
+
+		searchTypeSelector = new JComboBox(Constants.SearchType.values());
+		searchTypeSelector.setSelectedItem(Constants.SearchType.COMMIT);
+
+		maxHitsSelector = new JComboBox(new Integer[] { 25, 50, 75, 100 });
+		maxHitsSelector.setSelectedIndex(-1);
+
+		searchFragment = new JTextField(25);
+		searchFragment.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent event) {
+				search();
+			}
+		});
+
+		JPanel northControls = new JPanel(new FlowLayout(FlowLayout.LEFT, Utils.MARGIN, 0));
+		northControls.add(new JLabel(Translation.get("gb.repository")));
+		northControls.add(repositorySelector);
+		northControls.add(new JLabel(Translation.get("gb.branch")));
+		northControls.add(branchSelector);
+		northControls.add(new JLabel(Translation.get("gb.type")));
+		northControls.add(searchTypeSelector);
+		northControls.add(new JLabel(Translation.get("gb.maxHits")));
+		northControls.add(maxHitsSelector);
+		northControls.add(searchFragment);
+		northControls.add(search);
+
+		JPanel northPanel = new JPanel(new BorderLayout(0, Utils.MARGIN));
+		northPanel.add(header, BorderLayout.NORTH);
+		northPanel.add(northControls, BorderLayout.CENTER);
+
+		JPanel contentPanel = new JPanel() {
+
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public Insets getInsets() {
+				return Utils.INSETS;
+			}
+		};
+		contentPanel.setLayout(new BorderLayout(Utils.MARGIN, Utils.MARGIN));
+		contentPanel.add(northPanel, BorderLayout.NORTH);
+		contentPanel.add(new JScrollPane(table), BorderLayout.CENTER);
+		contentPanel.add(controls, BorderLayout.SOUTH);
+		setLayout(new BorderLayout());
+		add(contentPanel, BorderLayout.CENTER);
+		addWindowListener(new WindowAdapter() {
+			@Override
+			public void windowOpened(WindowEvent event) {
+				searchFragment.requestFocus();
+			}
+
+			@Override
+			public void windowActivated(WindowEvent event) {
+				searchFragment.requestFocus();
+			}
+		});
+	}
+
+	public void selectRepository(RepositoryModel repository) {
+		repositorySelector.setSelectedItem(repository);
+	}
+
+	private void updateBranches() {
+		String repository = null;
+		if (repositorySelector.getSelectedIndex() > -1) {
+			repository = repositorySelector.getSelectedItem().toString();
+		}
+		List<String> branches = gitblit.getBranches(repository);
+		branchChoices.removeAllElements();
+		for (String branch : branches) {
+			branchChoices.addElement(branch);
+		}
+	}
+
+	protected void search() {
+		final String repository = repositorySelector.getSelectedItem().toString();
+		final String branch = branchSelector.getSelectedIndex() > -1 ? branchSelector
+				.getSelectedItem().toString() : null;
+		final Constants.SearchType searchType = (Constants.SearchType) searchTypeSelector
+				.getSelectedItem();
+		final String fragment = searchFragment.getText();
+		final int maxEntryCount = maxHitsSelector.getSelectedIndex() > -1 ? ((Integer) maxHitsSelector
+				.getSelectedItem()) : -1;
+		if (StringUtils.isEmpty(fragment)) {
+			return;
+		}
+		SwingWorker<List<SyndicatedEntryModel>, Void> worker = new SwingWorker<List<SyndicatedEntryModel>, Void>() {
+			@Override
+			protected List<SyndicatedEntryModel> doInBackground() throws IOException {
+				return gitblit.search(repository, branch, fragment, searchType, maxEntryCount);
+			}
+
+			@Override
+			protected void done() {
+				try {
+					List<SyndicatedEntryModel> results = get();
+					updateTable(true, fragment, results);
+				} catch (Throwable t) {
+					Utils.showException(SearchDialog.this, t);
+				}
+			}
+		};
+		worker.execute();
+	}
+
+	protected void updateTable(boolean pack, String fragment, List<SyndicatedEntryModel> entries) {
+		tableModel.entries.clear();
+		tableModel.entries.addAll(entries);
+		tableModel.fireTableDataChanged();
+		setTitle(Translation.get("gb.search") + ": " + fragment + " (" + entries.size() + ")");
+		header.setText(getTitle());
+		if (pack) {
+			Utils.packColumns(table, Utils.MARGIN);
+		}
+	}
+
+	protected SyndicatedEntryModel getSelectedSyndicatedEntry() {
+		int viewRow = table.getSelectedRow();
+		int modelRow = table.convertRowIndexToModel(viewRow);
+		SyndicatedEntryModel entry = tableModel.get(modelRow);
+		return entry;
+	}
+
+	protected void viewCommit() {
+		SyndicatedEntryModel entry = getSelectedSyndicatedEntry();
+		Utils.browse(entry.link);
+	}
+
+	protected void viewCommitDiff() {
+		SyndicatedEntryModel entry = getSelectedSyndicatedEntry();
+		Utils.browse(entry.link.replace("/commit/", "/commitdiff/"));
+	}
+
+	protected void viewTree() {
+		SyndicatedEntryModel entry = getSelectedSyndicatedEntry();
+		Utils.browse(entry.link.replace("/commit/", "/tree/"));
+	}
+}
diff --git a/src/com/gitblit/client/SubscriptionsDialog.java b/src/com/gitblit/client/SubscriptionsDialog.java
index 64a88d9..20a6429 100644
--- a/src/com/gitblit/client/SubscriptionsDialog.java
+++ b/src/com/gitblit/client/SubscriptionsDialog.java
@@ -101,7 +101,7 @@
 		feedsTable.getColumn(repository).setCellRenderer(nameRenderer);
 
 		String branch = feedsTable.getColumnName(FeedsTableModel.Columns.Branch.ordinal());
-		feedsTable.getColumn(branch).setCellRenderer(nameRenderer);
+		feedsTable.getColumn(branch).setCellRenderer(new BranchRenderer());
 
 		String subscribed = feedsTable.getColumnName(FeedsTableModel.Columns.Subscribed.ordinal());
 		feedsTable.getColumn(subscribed).setCellRenderer(new BooleanCellRenderer());
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties
index 3ab1b7a..5193843 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -179,4 +179,5 @@
 gb.date = date
 gb.activity = activity
 gb.subscribe = subscribe
-gb.branch = branch
\ No newline at end of file
+gb.branch = branch
+gb.maxHits = max hits
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/pages/BasePage.java b/src/com/gitblit/wicket/pages/BasePage.java
index d31979d..f98e883 100644
--- a/src/com/gitblit/wicket/pages/BasePage.java
+++ b/src/com/gitblit/wicket/pages/BasePage.java
@@ -84,6 +84,7 @@
 			// Set Cookie
 			WebResponse response = (WebResponse) getRequestCycle().getResponse();
 			GitBlit.self().setCookie(response, user);
+			continueToOriginalDestination();
 		}
 	}
 

--
Gitblit v1.9.1