Skip to content

Commit cf17b22

Browse files
committed
Added a Dashboard page with a daily ref log of starred/owned repos
This is a work-in-progress and is mostly working like I want, but will require some refactoring to make it even more useful and less complex.
1 parent 9628271 commit cf17b22

26 files changed

+1136
-281
lines changed

NOTICE

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,4 +261,12 @@ Iconic
261261
Iconic, release under the
262262
Creative Commons Share Alike 3.0 License.
263263

264-
http://somerandomdude.com/work/iconic
264+
http://somerandomdude.com/work/iconic
265+
266+
---------------------------------------------------------------------------
267+
AngularJS
268+
---------------------------------------------------------------------------
269+
AngularJS, release under the
270+
MIT License.
271+
272+
http://angularjs.org/

releases.moxie

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ r17: {
4040

4141
additions:
4242
- Added simple star/unstar function to flag or bookmark interesting repositories
43+
- Added Dashboard page which shows a news feed for starred repositories and offers a filterable list of repositories you care about
4344
- Added a ui for the push log introduced in 1.2.1 (issue-177)
4445
- Added client application menus for Git, SourceTree, Tower, GitHub for Windows, GitHub for Mac, and SparkleShare
4546
- Added GO http/https connector thread pool size setting
@@ -88,6 +89,7 @@ r17: {
8889
dependencyChanges:
8990
- JGit 3.0.0-SNAPSHOT
9091
- Iconic font
92+
- AngularJS 1.0.7
9193

9294
settings:
9395
- { name: 'git.daemonBindInterface', defaultValue: 'localhost' }
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2013 gitblit.com.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.gitblit.models;
17+
18+
import java.io.Serializable;
19+
import java.util.Date;
20+
21+
import org.eclipse.jgit.lib.PersonIdent;
22+
23+
/**
24+
* Model class to simulate a push for presentation in the push log news feed
25+
* for a repository that does not have a Gitblit push log. Commits are grouped
26+
* by date and may be additionally split by ref.
27+
*
28+
* @author James Moger
29+
*/
30+
public class DailyLogEntry extends PushLogEntry implements Serializable {
31+
32+
private static final long serialVersionUID = 1L;
33+
34+
public DailyLogEntry(String repository, Date date) {
35+
super(repository, date, new UserModel("digest"));
36+
}
37+
38+
public DailyLogEntry(String repository, Date date, UserModel user) {
39+
super(repository, date, user);
40+
}
41+
42+
@Override
43+
public PersonIdent getCommitterIdent() {
44+
if (getAuthorCount() == 1) {
45+
return getCommits().get(0).getCommitterIdent();
46+
}
47+
48+
return super.getCommitterIdent();
49+
}
50+
51+
@Override
52+
public PersonIdent getAuthorIdent() {
53+
if (getAuthorCount() == 1) {
54+
return getCommits().get(0).getAuthorIdent();
55+
}
56+
57+
return super.getAuthorIdent();
58+
}
59+
}

src/main/java/com/gitblit/models/PushLogEntry.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ public class PushLogEntry implements Serializable, Comparable<PushLogEntry> {
5454
private final Map<String, ReceiveCommand.Type> refUpdates;
5555

5656
private final Map<String, String> refIdChanges;
57+
58+
private int authorCount;
5759

5860
/**
5961
* Constructor for specified duration of push from start date.
@@ -72,6 +74,7 @@ public PushLogEntry(String repository, Date date, UserModel user) {
7274
this.commits = new LinkedHashSet<RepositoryCommit>();
7375
this.refUpdates = new HashMap<String, ReceiveCommand.Type>();
7476
this.refIdChanges = new HashMap<String, String>();
77+
this.authorCount = -1;
7578
}
7679

7780
/**
@@ -152,6 +155,7 @@ public ReceiveCommand.Type getChangeType(String ref) {
152155
public RepositoryCommit addCommit(String branch, RevCommit commit) {
153156
RepositoryCommit commitModel = new RepositoryCommit(repository, branch, commit);
154157
if (commits.add(commitModel)) {
158+
authorCount = -1;
155159
return commitModel;
156160
}
157161
return null;
@@ -165,6 +169,7 @@ public RepositoryCommit addCommit(String branch, RevCommit commit) {
165169
*/
166170
public void addCommits(List<RepositoryCommit> list) {
167171
commits.addAll(list);
172+
authorCount = -1;
168173
}
169174

170175
/**
@@ -254,6 +259,18 @@ protected List<String> getChangedRefs(String baseRef) {
254259
return list;
255260
}
256261

262+
public int getAuthorCount() {
263+
if (authorCount == -1) {
264+
Set<String> authors = new HashSet<String>();
265+
for (RepositoryCommit commit : commits) {
266+
String name = commit.getAuthorIdent().getName();
267+
authors.add(name);
268+
}
269+
authorCount = authors.size();
270+
}
271+
return authorCount;
272+
}
273+
257274
/**
258275
* The total number of commits in the push.
259276
*

src/main/java/com/gitblit/utils/PushLogUtils.java

Lines changed: 151 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616
package com.gitblit.utils;
1717

1818
import java.io.IOException;
19+
import java.text.DateFormat;
1920
import java.text.MessageFormat;
21+
import java.text.SimpleDateFormat;
2022
import java.util.ArrayList;
23+
import java.util.Arrays;
2124
import java.util.Collection;
2225
import java.util.Collections;
2326
import java.util.Date;
@@ -50,6 +53,7 @@
5053
import org.slf4j.Logger;
5154
import org.slf4j.LoggerFactory;
5255

56+
import com.gitblit.models.DailyLogEntry;
5357
import com.gitblit.models.PathModel.PathChangeModel;
5458
import com.gitblit.models.PushLogEntry;
5559
import com.gitblit.models.RefModel;
@@ -109,6 +113,25 @@ public static RefModel getPushLogBranch(Repository repository) {
109113
return null;
110114
}
111115

116+
private static UserModel newUserModelFrom(PersonIdent ident) {
117+
String name = ident.getName();
118+
String username;
119+
String displayname;
120+
if (name.indexOf('/') > -1) {
121+
int slash = name.indexOf('/');
122+
displayname = name.substring(0, slash);
123+
username = name.substring(slash + 1);
124+
} else {
125+
displayname = name;
126+
username = ident.getEmailAddress();
127+
}
128+
129+
UserModel user = new UserModel(username);
130+
user.displayName = displayname;
131+
user.emailAddress = ident.getEmailAddress();
132+
return user;
133+
}
134+
112135
/**
113136
* Updates a push log.
114137
*
@@ -135,9 +158,15 @@ public static boolean updatePushLog(UserModel user, Repository repository,
135158
DirCache index = createIndex(repository, headId, commands);
136159
ObjectId indexTreeId = index.writeTree(odi);
137160

138-
PersonIdent ident =
139-
new PersonIdent(MessageFormat.format("{0}/{1}", user.getDisplayName(), user.username),
161+
PersonIdent ident;
162+
if (UserModel.ANONYMOUS.equals(user)) {
163+
// anonymous push
164+
ident = new PersonIdent("anonymous", "anonymous");
165+
} else {
166+
// construct real pushing account
167+
ident = new PersonIdent(MessageFormat.format("{0}/{1}", user.getDisplayName(), user.username),
140168
user.emailAddress == null ? user.username : user.emailAddress);
169+
}
141170

142171
// Create a commit object
143172
CommitBuilder commit = new CommitBuilder();
@@ -339,23 +368,9 @@ public static List<PushLogEntry> getPushLog(String repositoryName, Repository re
339368
continue;
340369
}
341370

342-
String name = push.getAuthorIdent().getName();
343-
String username;
344-
String displayname;
345-
if (name.indexOf('/') > -1) {
346-
int slash = name.indexOf('/');
347-
displayname = name.substring(0, slash);
348-
username = name.substring(slash + 1);
349-
} else {
350-
displayname = name;
351-
username = push.getAuthorIdent().getEmailAddress();
352-
}
353-
354-
UserModel user = new UserModel(username);
355-
user.displayName = displayname;
356-
user.emailAddress = push.getAuthorIdent().getEmailAddress();
357-
371+
UserModel user = newUserModelFrom(push.getAuthorIdent());
358372
Date date = push.getAuthorIdent().getWhen();
373+
359374
PushLogEntry log = new PushLogEntry(repositoryName, date, user);
360375
list.add(log);
361376
List<PathChangeModel> changedRefs = JGitUtils.getFilesInCommit(repository, push);
@@ -413,14 +428,22 @@ public static List<PushLogEntry> getPushLogByRef(String repositoryName, Reposito
413428
int maxCount) {
414429
// break the push log into ref push logs and then merge them back into a list
415430
Map<String, List<PushLogEntry>> refMap = new HashMap<String, List<PushLogEntry>>();
416-
for (PushLogEntry push : getPushLog(repositoryName, repository, offset, maxCount)) {
431+
List<PushLogEntry> pushes = getPushLog(repositoryName, repository, offset, maxCount);
432+
for (PushLogEntry push : pushes) {
417433
for (String ref : push.getChangedRefs()) {
418434
if (!refMap.containsKey(ref)) {
419435
refMap.put(ref, new ArrayList<PushLogEntry>());
420436
}
421437

422438
// construct new ref-specific push log entry
423-
PushLogEntry refPush = new PushLogEntry(push.repository, push.date, push.user);
439+
PushLogEntry refPush;
440+
if (push instanceof DailyLogEntry) {
441+
// simulated push log from commits grouped by date
442+
refPush = new DailyLogEntry(push.repository, push.date);
443+
} else {
444+
// real push log entry
445+
refPush = new PushLogEntry(push.repository, push.date, push.user);
446+
}
424447
refPush.updateRef(ref, push.getChangeType(ref), push.getOldId(ref), push.getNewId(ref));
425448
refPush.addCommits(push.getCommits(ref));
426449
refMap.get(ref).add(refPush);
@@ -451,15 +474,16 @@ public static List<PushLogEntry> getPushLogByRef(String repositoryName, Reposito
451474
public static List<PushLogEntry> getPushLogByRef(String repositoryName, Repository repository, Date minimumDate) {
452475
// break the push log into ref push logs and then merge them back into a list
453476
Map<String, List<PushLogEntry>> refMap = new HashMap<String, List<PushLogEntry>>();
454-
for (PushLogEntry push : getPushLog(repositoryName, repository, minimumDate)) {
477+
List<PushLogEntry> pushes = getPushLog(repositoryName, repository, minimumDate);
478+
for (PushLogEntry push : pushes) {
455479
for (String ref : push.getChangedRefs()) {
456480
if (!refMap.containsKey(ref)) {
457481
refMap.put(ref, new ArrayList<PushLogEntry>());
458482
}
459-
460-
// construct new ref-specific push log entry
461-
PushLogEntry refPush = new PushLogEntry(push.repository, push.date, push.user);
462-
refPush.updateRef(ref, push.getChangeType(ref), push.getOldId(ref), push.getNewId(ref));
483+
484+
// construct new ref-specific push log entry
485+
PushLogEntry refPush = new PushLogEntry(push.repository, push.date, push.user);
486+
refPush.updateRef(ref, push.getChangeType(ref), push.getOldId(ref), push.getNewId(ref));
463487
refPush.addCommits(push.getCommits(ref));
464488
refMap.get(ref).add(refPush);
465489
}
@@ -476,4 +500,106 @@ public static List<PushLogEntry> getPushLogByRef(String repositoryName, Reposito
476500

477501
return refPushLog;
478502
}
503+
504+
/**
505+
* Returns a commit log grouped by day.
506+
*
507+
* @param repositoryName
508+
* @param repository
509+
* @param minimumDate
510+
* @param offset
511+
* @param maxCount
512+
* if < 0, all pushes are returned.
513+
* @return a list of grouped commit log entries
514+
*/
515+
public static List<DailyLogEntry> getDailyLog(String repositoryName, Repository repository,
516+
Date minimumDate, int offset, int maxCount) {
517+
518+
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
519+
// df.setTimeZone(timezone);
520+
521+
Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository);
522+
Map<String, DailyLogEntry> tags = new HashMap<String, DailyLogEntry>();
523+
Map<String, DailyLogEntry> dailydigests = new HashMap<String, DailyLogEntry>();
524+
for (RefModel local : JGitUtils.getLocalBranches(repository, true, -1)) {
525+
String branch = local.getName();
526+
List<RevCommit> commits = JGitUtils.getRevLog(repository, branch, minimumDate);
527+
for (RevCommit commit : commits) {
528+
Date date = JGitUtils.getCommitDate(commit);
529+
String dateStr = df.format(date);
530+
if (!dailydigests.containsKey(dateStr)) {
531+
dailydigests.put(dateStr, new DailyLogEntry(repositoryName, date));
532+
}
533+
PushLogEntry digest = dailydigests.get(dateStr);
534+
digest.updateRef(branch, ReceiveCommand.Type.UPDATE, commit.getParents()[0].getId().getName(), commit.getName());
535+
RepositoryCommit repoCommit = digest.addCommit(branch, commit);
536+
if (repoCommit != null) {
537+
repoCommit.setRefs(allRefs.get(commit.getId()));
538+
if (!ArrayUtils.isEmpty(repoCommit.getRefs())) {
539+
// treat tags as special events in the log
540+
for (RefModel ref : repoCommit.getRefs()) {
541+
if (ref.getName().startsWith(Constants.R_TAGS)) {
542+
if (!tags.containsKey(dateStr)) {
543+
UserModel tagUser = newUserModelFrom(commit.getAuthorIdent());
544+
Date tagDate = commit.getAuthorIdent().getWhen();
545+
tags.put(dateStr, new DailyLogEntry(repositoryName, tagDate, tagUser));
546+
}
547+
PushLogEntry tagEntry = tags.get(dateStr);
548+
tagEntry.updateRef(ref.getName(), ReceiveCommand.Type.CREATE);
549+
tagEntry.addCommits(Arrays.asList(repoCommit));
550+
}
551+
}
552+
}
553+
}
554+
}
555+
}
556+
557+
List<DailyLogEntry> list = new ArrayList<DailyLogEntry>(dailydigests.values());
558+
list.addAll(tags.values());
559+
Collections.sort(list);
560+
return list;
561+
}
562+
563+
/**
564+
* Returns the list of commits separated by ref (e.g. each ref has it's own
565+
* PushLogEntry object for each day).
566+
*
567+
* @param repositoryName
568+
* @param repository
569+
* @param minimumDate
570+
* @return a list of push log entries separated by ref and date
571+
*/
572+
public static List<DailyLogEntry> getDailyLogByRef(String repositoryName, Repository repository, Date minimumDate) {
573+
// break the push log into ref push logs and then merge them back into a list
574+
Map<String, List<DailyLogEntry>> refMap = new HashMap<String, List<DailyLogEntry>>();
575+
List<DailyLogEntry> pushes = getDailyLog(repositoryName, repository, minimumDate, 0, -1);
576+
for (DailyLogEntry push : pushes) {
577+
for (String ref : push.getChangedRefs()) {
578+
if (!refMap.containsKey(ref)) {
579+
refMap.put(ref, new ArrayList<DailyLogEntry>());
580+
}
581+
582+
// construct new ref-specific push log entry
583+
DailyLogEntry refPush = new DailyLogEntry(push.repository, push.date, push.user);
584+
refPush.updateRef(ref, push.getChangeType(ref), push.getOldId(ref), push.getNewId(ref));
585+
refPush.addCommits(push.getCommits(ref));
586+
refMap.get(ref).add(refPush);
587+
}
588+
}
589+
590+
// merge individual ref pushes into master list
591+
List<DailyLogEntry> refPushLog = new ArrayList<DailyLogEntry>();
592+
for (List<DailyLogEntry> refPush : refMap.values()) {
593+
for (DailyLogEntry entry : refPush) {
594+
if (entry.getCommitCount() > 0) {
595+
refPushLog.add(entry);
596+
}
597+
}
598+
}
599+
600+
// sort ref push log
601+
Collections.sort(refPushLog);
602+
603+
return refPushLog;
604+
}
479605
}

0 commit comments

Comments
 (0)