Set author as tooltip of "last change" on repositories page (issue-238)
diff --git a/releases.moxie b/releases.moxie
index 78bc340..8cff771 100644
--- a/releases.moxie
+++ b/releases.moxie
@@ -60,6 +60,7 @@
 	 - Support header color customizations (issue 209)

 	 - Support username substitution in web.otherUrls (issue 213)

 	 - Option to force client-side basic authentication instead of form-based authentication if web.authenticateViewPages=true (issue 222)

+	 - Set author as tooltip of last change column in the repositories panel (issue-238)

 	 - Setting to automatically create an user account based on an authenticated user principal from the servlet container (issue-246)

 	 - Added WindowsUserService to authenticate users against Windows accounts (issue-250)

 	 - Global and per-repository setting to exclude authors from metrics (issue-251)

diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java
index ca21717..6f2f70c 100644
--- a/src/main/java/com/gitblit/GitBlit.java
+++ b/src/main/java/com/gitblit/GitBlit.java
@@ -121,6 +121,7 @@
 import com.gitblit.utils.FederationUtils;
 import com.gitblit.utils.HttpUtils;
 import com.gitblit.utils.JGitUtils;
+import com.gitblit.utils.JGitUtils.LastChange;
 import com.gitblit.utils.JsonUtils;
 import com.gitblit.utils.MetricUtils;
 import com.gitblit.utils.ObjectCache;
@@ -1669,7 +1670,9 @@
 				model.hasCommits = JGitUtils.hasCommits(r);
 			}
 
-			model.lastChange = JGitUtils.getLastChange(r);
+			LastChange lc = JGitUtils.getLastChange(r);
+			model.lastChange = lc.when;
+			model.lastChangeAuthor = lc.who;
 			if (!model.skipSizeCalculation) {
 				ByteFormat byteFormat = new ByteFormat();
 				model.size = byteFormat.format(calculateSize(model));
@@ -1973,7 +1976,9 @@
 			model.name = repositoryName;
 		}
 		model.hasCommits = JGitUtils.hasCommits(r);
-		model.lastChange = JGitUtils.getLastChange(r);
+		LastChange lc = JGitUtils.getLastChange(r);
+		model.lastChange = lc.when;
+		model.lastChangeAuthor = lc.who;
 		model.projectPath = StringUtils.getFirstPathElement(repositoryName);
 		
 		StoredConfig config = r.getConfig();
diff --git a/src/main/java/com/gitblit/models/RepositoryModel.java b/src/main/java/com/gitblit/models/RepositoryModel.java
index 5eb51b4..2996265 100644
--- a/src/main/java/com/gitblit/models/RepositoryModel.java
+++ b/src/main/java/com/gitblit/models/RepositoryModel.java
@@ -46,6 +46,7 @@
 	public String description;

 	public List<String> owners;

 	public Date lastChange;

+	public String lastChangeAuthor;

 	public boolean hasCommits;

 	public boolean showRemoteBranches;

 	public boolean useTickets;

diff --git a/src/main/java/com/gitblit/utils/JGitUtils.java b/src/main/java/com/gitblit/utils/JGitUtils.java
index 9dabebe..8676d74 100644
--- a/src/main/java/com/gitblit/utils/JGitUtils.java
+++ b/src/main/java/com/gitblit/utils/JGitUtils.java
@@ -439,39 +439,56 @@
 		}

 		return false;

 	}

+	

+	/**

+	 * Encapsulates the result of cloning or pulling from a repository.

+	 */

+	public static class LastChange {

+		public Date when;

+		public String who;

+		

+		LastChange() {

+			when = new Date(0);			

+		}

+		

+		LastChange(long lastModified) {

+			this.when = new Date(lastModified);

+		}

+	}

 

 	/**

-	 * Returns the date of the most recent commit on a branch. If the repository

-	 * does not exist Date(0) is returned. If it does exist but is empty, the

-	 * last modified date of the repository folder is returned.

+	 * Returns the date and author of the most recent commit on a branch. If the

+	 * repository does not exist Date(0) is returned. If it does exist but is

+	 * empty, the last modified date of the repository folder is returned.

 	 * 

 	 * @param repository

-	 * @return

+	 * @return a LastChange object

 	 */

-	public static Date getLastChange(Repository repository) {

+	public static LastChange getLastChange(Repository repository) {

 		if (!hasCommits(repository)) {

 			// null repository

 			if (repository == null) {

-				return new Date(0);

+				return new LastChange();

 			}

 			// fresh repository

-			return new Date(repository.getDirectory().lastModified());

+			return new LastChange(repository.getDirectory().lastModified());

 		}

 

 		List<RefModel> branchModels = getLocalBranches(repository, true, -1);

 		if (branchModels.size() > 0) {

 			// find most recent branch update

-			Date lastChange = new Date(0);

+			LastChange lastChange = new LastChange();			

 			for (RefModel branchModel : branchModels) {

-				if (branchModel.getDate().after(lastChange)) {

-					lastChange = branchModel.getDate();

+				if (branchModel.getDate().after(lastChange.when)) {

+					lastChange.when = branchModel.getDate();

+					lastChange.who = branchModel.getAuthorIdent().getName();

 				}

 			}

 			return lastChange;

 		}

 		

 		// default to the repository folder modification date

-		return new Date(repository.getDirectory().lastModified());

+		return new LastChange(repository.getDirectory().lastModified());

 	}

 

 	/**

diff --git a/src/main/java/com/gitblit/wicket/pages/OverviewPage.java b/src/main/java/com/gitblit/wicket/pages/OverviewPage.java
index 8848767..ff6326d 100644
--- a/src/main/java/com/gitblit/wicket/pages/OverviewPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/OverviewPage.java
@@ -98,7 +98,7 @@
 		add(ownersView);

 		

 		add(WicketUtils.createTimestampLabel("repositoryLastChange",

-				JGitUtils.getLastChange(r), getTimeZone(), getTimeUtils()));

+				JGitUtils.getLastChange(r).when, getTimeZone(), getTimeUtils()));

 		add(new Label("repositorySize", model.size));

 		

 		if (metricsTotal == null) {

diff --git a/src/main/java/com/gitblit/wicket/pages/SummaryPage.java b/src/main/java/com/gitblit/wicket/pages/SummaryPage.java
index 1afa967..c231b2b 100644
--- a/src/main/java/com/gitblit/wicket/pages/SummaryPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/SummaryPage.java
@@ -116,7 +116,7 @@
 		add(ownersView);

 		

 		add(WicketUtils.createTimestampLabel("repositoryLastChange",

-				JGitUtils.getLastChange(r), getTimeZone(), getTimeUtils()));

+				JGitUtils.getLastChange(r).when, getTimeZone(), getTimeUtils()));

 		add(new Label("repositorySize", getRepositoryModel().size));

 		if (metricsTotal == null) {

 			add(new Label("branchStats", ""));

diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java
index e0f9393..1b7d0e0 100644
--- a/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java
@@ -322,6 +322,9 @@
 				Label lastChangeLabel = new Label("repositoryLastChange", lastChange);

 				row.add(lastChangeLabel);

 				WicketUtils.setCssClass(lastChangeLabel, getTimeUtils().timeAgoCss(entry.lastChange));

+				if (!StringUtils.isEmpty(entry.lastChangeAuthor)) {

+					WicketUtils.setHtmlTooltip(lastChangeLabel, getString("gb.author") + ": " + entry.lastChangeAuthor);

+				}

 

 				boolean showOwner = user != null && entry.isOwner(user.username);

 				boolean myPersonalRepository = showOwner && entry.isUsersPersonalRepository(user.username);

diff --git a/src/test/java/com/gitblit/tests/JGitUtilsTest.java b/src/test/java/com/gitblit/tests/JGitUtilsTest.java
index ce72a46..375dbd5 100644
--- a/src/test/java/com/gitblit/tests/JGitUtilsTest.java
+++ b/src/test/java/com/gitblit/tests/JGitUtilsTest.java
@@ -118,11 +118,11 @@
 

 	@Test

 	public void testLastCommit() throws Exception {

-		assertEquals(new Date(0), JGitUtils.getLastChange(null));

+		assertEquals(new Date(0), JGitUtils.getLastChange(null).when);

 

 		Repository repository = GitBlitSuite.getHelloworldRepository();

 		assertTrue(JGitUtils.getCommit(repository, null) != null);

-		Date date = JGitUtils.getLastChange(repository);

+		Date date = JGitUtils.getLastChange(repository).when;

 		repository.close();

 		assertNotNull("Could not get last repository change date!", date);

 	}

@@ -140,7 +140,7 @@
 			assertNull(JGitUtils.getFirstCommit(repository, null));

 			assertEquals(folder.lastModified(), JGitUtils.getFirstChange(repository, null)

 					.getTime());

-			assertEquals(folder.lastModified(), JGitUtils.getLastChange(repository).getTime());

+			assertEquals(folder.lastModified(), JGitUtils.getLastChange(repository).when.getTime());

 			assertNull(JGitUtils.getCommit(repository, null));

 			repository.close();

 			RepositoryCache.close(repository);