You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by ac...@apache.org on 2013/04/16 14:28:51 UTC

[01/50] git commit: [#5453] Make image assets local to tool

Updated Branches:
  refs/heads/acs2/5518 9213be0d1 -> 07a8bddf2


[#5453] Make image assets local to tool


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/e5abf088
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/e5abf088
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/e5abf088

Branch: refs/heads/acs2/5518
Commit: e5abf08843e214267cf87ae6a5e76f19995f4941
Parents: d250390
Author: Tim Van Steenburgh <tv...@gmail.com>
Authored: Tue Mar 5 21:44:54 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:36 2013 +0000

----------------------------------------------------------------------
 ForgeUserStats/forgeuserstats/main.py              |   10 +++++-----
 .../nf/userstats/images/stats_24.png               |  Bin 0 -> 654 bytes
 .../nf/userstats/images/stats_32.png               |  Bin 0 -> 715 bytes
 .../nf/userstats/images/stats_48.png               |  Bin 0 -> 925 bytes
 4 files changed, 5 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/e5abf088/ForgeUserStats/forgeuserstats/main.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/main.py b/ForgeUserStats/forgeuserstats/main.py
index dcecdb9..acc196d 100644
--- a/ForgeUserStats/forgeuserstats/main.py
+++ b/ForgeUserStats/forgeuserstats/main.py
@@ -71,8 +71,8 @@ class UserStatsListener(EventsListener):
 
 class ForgeUserStatsApp(Application):
     __version__ = version.__version__
-    tool_label='Statistics'
-    default_mount_label='Statistics'
+    tool_label='Stats'
+    default_mount_label='Stats'
     default_mount_point='stats'
     permissions = ['configure', 'read', 'write',
                     'unmoderated_post', 'post', 'moderate', 'admin']
@@ -81,9 +81,9 @@ class ForgeUserStatsApp(Application):
     config_options = Application.config_options
     default_external_feeds = []
     icons={
-        24:'images/stats_24.png',
-        32:'images/stats_32.png',
-        48:'images/stats_48.png'
+        24:'../../tool/userstats/images/stats_24.png',
+        32:'../../tool/userstats/images/stats_32.png',
+        48:'../../tool/userstats/images/stats_48.png'
     }
     root = ForgeUserStatsController()
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/e5abf088/ForgeUserStats/forgeuserstats/nf/userstats/images/stats_24.png
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/nf/userstats/images/stats_24.png b/ForgeUserStats/forgeuserstats/nf/userstats/images/stats_24.png
new file mode 100644
index 0000000..e3e9f5e
Binary files /dev/null and b/ForgeUserStats/forgeuserstats/nf/userstats/images/stats_24.png differ

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/e5abf088/ForgeUserStats/forgeuserstats/nf/userstats/images/stats_32.png
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/nf/userstats/images/stats_32.png b/ForgeUserStats/forgeuserstats/nf/userstats/images/stats_32.png
new file mode 100644
index 0000000..ba76a37
Binary files /dev/null and b/ForgeUserStats/forgeuserstats/nf/userstats/images/stats_32.png differ

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/e5abf088/ForgeUserStats/forgeuserstats/nf/userstats/images/stats_48.png
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/nf/userstats/images/stats_48.png b/ForgeUserStats/forgeuserstats/nf/userstats/images/stats_48.png
new file mode 100644
index 0000000..851e122
Binary files /dev/null and b/ForgeUserStats/forgeuserstats/nf/userstats/images/stats_48.png differ


[22/50] git commit: [#5453] `from PIL import Image` doesn't work all the time

Posted by ac...@apache.org.
[#5453] `from PIL import Image` doesn't work all the time


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/b08571f1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/b08571f1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/b08571f1

Branch: refs/heads/acs2/5518
Commit: b08571f17b65540cf75998e808042eaf3a2fec44
Parents: 0ce64c7
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Thu Apr 4 20:46:01 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 20:46:01 2013 +0000

----------------------------------------------------------------------
 Allura/allura/lib/graphics/graphic_methods.py |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b08571f1/Allura/allura/lib/graphics/graphic_methods.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/graphics/graphic_methods.py b/Allura/allura/lib/graphics/graphic_methods.py
index cd3151b..88892c1 100644
--- a/Allura/allura/lib/graphics/graphic_methods.py
+++ b/Allura/allura/lib/graphics/graphic_methods.py
@@ -1,8 +1,9 @@
+import StringIO
+
 from matplotlib.backends.backend_agg import FigureCanvasAgg
 from matplotlib.figure import Figure
-from matplotlib.text import Annotation
-from PIL import Image
-import StringIO
+import Image
+
 
 def create_histogram(data, tick_labels, y_label, title):
     fig = Figure(figsize=(10,5), dpi=80, facecolor='white')
@@ -23,7 +24,7 @@ def create_histogram(data, tick_labels, y_label, title):
     fig.subplots_adjust(bottom=0.3)
 
     canvas.draw()
-        
+
     s = canvas.tostring_rgb()
     l,b,w,h = fig.bbox.bounds
     w, h = int(w), int(h)
@@ -66,4 +67,3 @@ def create_progress_bar(value):
     im.save(output, 'PNG')
 
     return output.getvalue()
-


[36/50] git commit: [#4504] ticket:311 Hide hits count for queries with $USER var

Posted by ac...@apache.org.
[#4504] ticket:311 Hide hits count for queries with $USER var


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/f785c524
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/f785c524
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/f785c524

Branch: refs/heads/acs2/5518
Commit: f785c5246eb7905e6fd8f083f7219ef3431ad566
Parents: f8c30d4
Author: Igor Bondarenko <je...@gmail.com>
Authored: Wed Apr 10 09:13:26 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Fri Apr 12 17:07:49 2013 +0000

----------------------------------------------------------------------
 ForgeTracker/forgetracker/model/ticket.py |    2 ++
 ForgeTracker/forgetracker/tracker_main.py |    3 ++-
 2 files changed, 4 insertions(+), 1 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/f785c524/ForgeTracker/forgetracker/model/ticket.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index c491d7b..aa8dd88 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -119,6 +119,8 @@ class Globals(MappedClass):
         self._bin_counts_data = []
         for b in Bin.query.find(dict(
                 app_config_id=self.app_config_id)):
+            if b.terms and '$USER' in b.terms:
+                continue  # skip queries with $USER variable, hits will be inconsistent for them
             r = search_artifact(Ticket, b.terms, rows=0, short_timeout=False)
             hits = r is not None and r.hits or 0
             self._bin_counts_data.append(dict(summary=b.summary, hits=hits))

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/f785c524/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index 4a7562e..dfdd4a8 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -226,8 +226,9 @@ class ForgeTrackerApp(Application):
         milestones = []
         for bin in self.bins:
             label = bin.shorthand_id()
+            cls = '' if bin.terms and '$USER' in bin.terms else 'search_bin'
             search_bins.append(SitemapEntry(
-                    h.text.truncate(label, 72), bin.url(), className='search_bin'))
+                    h.text.truncate(label, 72), bin.url(), className=cls))
         for fld in c.app.globals.milestone_fields:
             milestones.append(SitemapEntry(h.text.truncate(fld.label, 72)))
             for m in getattr(fld, "milestones", []):


[24/50] git commit: [#2643] greatly increase antispam time window, to allow longer time for people to compose messages

Posted by ac...@apache.org.
[#2643] greatly increase antispam time window, to allow longer time for people to compose messages


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/7041d1a1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/7041d1a1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/7041d1a1

Branch: refs/heads/acs2/5518
Commit: 7041d1a1e2c9727aee0e3cb51c78d47c430c0160
Parents: 2dfbcfb
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Tue Apr 9 14:04:15 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Apr 9 14:04:15 2013 +0000

----------------------------------------------------------------------
 Allura/allura/lib/utils.py |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7041d1a1/Allura/allura/lib/utils.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index 6e2d3b8..9bf6cd8 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -294,8 +294,8 @@ class AntiSpam(object):
             if now is None: now = time.time()
             if obj.timestamp > now + 5:
                 raise ValueError, 'Post from the future'
-            if now - obj.timestamp > 60*60:
-                raise ValueError, 'Post from the 1hr+ past'
+            if now - obj.timestamp > 24*60*60:
+                raise ValueError, 'Post from the distant past'
             if obj.spinner != obj.make_spinner(obj.timestamp):
                 raise ValueError, 'Bad spinner value'
             for k in new_params.keys():


[14/50] git commit: [#5453] Fixing errors in userstats

Posted by ac...@apache.org.
[#5453] Fixing errors in userstats


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/91774b52
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/91774b52
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/91774b52

Branch: refs/heads/acs2/5518
Commit: 91774b525612211c2424a720ec9a182c6351d85f
Parents: 43731d3
Author: Stefano Invernizzi <st...@apache.org>
Authored: Wed Mar 13 01:25:10 2013 +0100
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:37 2013 +0000

----------------------------------------------------------------------
 ForgeUserStats/forgeuserstats/model/stats.py      |    4 ---
 ForgeUserStats/forgeuserstats/tests/test_model.py |   23 +++++++--------
 2 files changed, 11 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/91774b52/ForgeUserStats/forgeuserstats/model/stats.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/model/stats.py b/ForgeUserStats/forgeuserstats/model/stats.py
index 4171d52..b2f70a4 100644
--- a/ForgeUserStats/forgeuserstats/model/stats.py
+++ b/ForgeUserStats/forgeuserstats/model/stats.py
@@ -25,10 +25,6 @@ class UserStats(Stats):
         stats = cls(user_id=user._id,
             registration_date = datetime.utcnow())
         user.stats_id = stats._id
-        if session(stats):
-            session(stats).flush(stats)
-        if session(user):
-            session(user).flush(user)
         return stats
 
     def getLastMonthLogins(self):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/91774b52/ForgeUserStats/forgeuserstats/tests/test_model.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/tests/test_model.py b/ForgeUserStats/forgeuserstats/tests/test_model.py
index 3a9fcde..1f0236e 100644
--- a/ForgeUserStats/forgeuserstats/tests/test_model.py
+++ b/ForgeUserStats/forgeuserstats/tests/test_model.py
@@ -18,9 +18,8 @@ class TestUserStats(unittest.TestCase):
 
         setup_basic_test()
         setup_global_objects()
-        self.user = User.register(dict(username='test-new-user',
-            display_name='Test Stats'),
-            make_project=False)
+        self.user = User.by_username('test-user-2')
+        c.user = self.user
 
     def test_init_values(self):
         artifacts = self.user.stats.getArtifacts()
@@ -49,9 +48,9 @@ class TestUserStats(unittest.TestCase):
         assert lmcommits['number'] == 0
         assert lmcommits['lines'] == 0
 
-    @td.with_user_project('test-new-user')
+    @td.with_user_project('test-user-2')
     def test_create_artifact_stats(self):
-        p = Project.query.get(shortname='u/test-new-user')
+        p = Project.query.get(shortname='u/test-user-2')
         topic = TroveCategory.query.get(shortname='scientific')
 
         init_lm_art = self.user.stats.getLastMonthArtifacts()
@@ -126,9 +125,9 @@ class TestUserStats(unittest.TestCase):
         art_by_cat = self.user.stats.getArtifactsByCategory(detailed=False)
         assert art_by_cat[topic]['created'] == 1 and art_by_cat[topic]['modified'] == 0
 
-    @td.with_user_project('test-new-user')
+    @td.with_user_project('test-user-2')
     def test_modify_artifact_stats(self):
-        p = Project.query.get(shortname='u/test-new-user')
+        p = Project.query.get(shortname='u/test-user-2')
         topic = TroveCategory.query.get(shortname='scientific')
 
         init_lm_art = self.user.stats.getLastMonthArtifacts()
@@ -203,9 +202,9 @@ class TestUserStats(unittest.TestCase):
         art_by_cat = self.user.stats.getArtifactsByCategory(detailed=False)
         assert art_by_cat[topic]['created'] == 0 and art_by_cat[topic]['modified'] == 1
 
-    @td.with_user_project('test-new-user')
+    @td.with_user_project('test-user-2')
     def test_ticket_stats(self):
-        p = Project.query.get(shortname='u/test-new-user')
+        p = Project.query.get(shortname='u/test-user-2')
         topic = TroveCategory.query.get(shortname='scientific')
         create_time = datetime.utcnow() + timedelta(-5)
 
@@ -299,9 +298,9 @@ class TestUserStats(unittest.TestCase):
         assert lm_by_cat[topic]['averagesolvingtime'] == solving_time
 
     @with_git
-    @td.with_user_project('test-new-user')
+    @td.with_user_project('test-user-2')
     def test_commit_stats(self):
-        p = Project.query.get(shortname='u/test-new-user')
+        p = Project.query.get(shortname='u/test-user-2')
         topic = TroveCategory.query.get(shortname='scientific')
         commit_time = datetime.utcnow() + timedelta(-1)
 
@@ -353,7 +352,7 @@ class TestUserStats(unittest.TestCase):
         assert lm_by_cat[topic]['number'] == 1
         assert lm_by_cat[topic]['lines'] == 1
 
-    @td.with_user_project('test-new-user')
+    @td.with_user_project('test-user-2')
     def test_login_stats(self):
         init_logins = self.user.stats.tot_logins_count
         init_lm_logins = self.user.stats.getLastMonthLogins()


[48/50] git commit: [#4596] ticket:312 Sort tickets descending by default

Posted by ac...@apache.org.
[#4596] ticket:312 Sort tickets descending by default


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/630309ee
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/630309ee
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/630309ee

Branch: refs/heads/acs2/5518
Commit: 630309eed49f0bcb18ac36e086630ce20364ae56
Parents: 11c9c48
Author: Igor Bondarenko <je...@gmail.com>
Authored: Thu Apr 11 12:58:35 2013 +0000
Committer: Tim Van Steenburgh <tv...@gmail.com>
Committed: Tue Apr 16 00:46:03 2013 +0000

----------------------------------------------------------------------
 ForgeTracker/forgetracker/model/ticket.py |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/630309ee/ForgeTracker/forgetracker/model/ticket.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index aa8dd88..3660257 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -678,7 +678,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
         """
         limit, page, start = g.handle_paging(limit, page, default=25)
         q = cls.query.find(dict(query, app_config_id=app_config._id, deleted=deleted))
-        q = q.sort('ticket_num')
+        q = q.sort('ticket_num', pymongo.DESCENDING)
         if sort:
             field, direction = sort.split()
             if field.startswith('_'):
@@ -727,7 +727,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
         limit, page, start = g.handle_paging(limit, page, default=25)
         count = 0
         tickets = []
-        refined_sort = sort if sort else 'ticket_num_i asc'
+        refined_sort = sort if sort else 'ticket_num_i desc'
         if  'ticket_num_i' not in refined_sort:
             refined_sort += ',ticket_num_i asc'
         try:


[39/50] git commit: [#5453] Fix computation of average stats

Posted by ac...@apache.org.
[#5453] Fix computation of average stats


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/1dd8575c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/1dd8575c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/1dd8575c

Branch: refs/heads/acs2/5518
Commit: 1dd8575cbf82fe5c5237e5c0f5188ae7691cfe9f
Parents: 15b4e7a
Author: Stefano Invernizzi <st...@apache.org>
Authored: Sun Apr 14 21:58:55 2013 +0200
Committer: Stefano Invernizzi <st...@apache.org>
Committed: Sun Apr 14 21:58:55 2013 +0200

----------------------------------------------------------------------
 Allura/allura/model/stats.py |   17 ++++++++++-------
 1 files changed, 10 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/1dd8575c/Allura/allura/model/stats.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/stats.py b/Allura/allura/model/stats.py
index df4e45a..02c2fc4 100644
--- a/Allura/allura/model/stats.py
+++ b/Allura/allura/model/stats.py
@@ -97,7 +97,7 @@ class Stats(MappedClass):
                 tickets = val['tickets']
                 if tickets.assigned == 0:
                     return 0
-                return float(tickets.solved) / tickets.assigned
+                return round(float(tickets.solved) / tickets.assigned, 2)
         return 0
 
     @classmethod
@@ -106,8 +106,9 @@ class Stats(MappedClass):
         n = res.count()
         if n == 0:
             return 0, 0
-        maxcontribution=max([x.getCodeContribution() for x in res])
-        averagecontribution=sum([x.getCodeContribution() for x in res]) / n
+        values = [x.getCodeContribution() for x in res]
+        maxcontribution=max(values)
+        averagecontribution=sum(values) / n
         return maxcontribution, round(averagecontribution, 2)
 
     @classmethod
@@ -116,8 +117,9 @@ class Stats(MappedClass):
         n = res.count()
         if n == 0:
             return 0, 0
-        maxcontribution=max([x.getDiscussionContribution() for x in res])
-        averagecontribution=sum([x.getDiscussionContribution() for x in res])/n
+        values = [x.getDiscussionContribution() for x in res]
+        maxcontribution=max(values)
+        averagecontribution=sum(values)/n
         return maxcontribution, round(averagecontribution, 2)
 
     @classmethod
@@ -126,8 +128,9 @@ class Stats(MappedClass):
         n = res.count()
         if n == 0:
             return 0, 0
-        maxcontribution=max([x.getTicketsContribution() for x in res])
-        averagecontribution=sum([x.getTicketsContribution() for x in res])/n
+        values = [x.getTicketsContribution() for x in res]
+        maxcontribution=max(values)
+        averagecontribution=sum(values)/n
         return maxcontribution, round(averagecontribution, 2)
 
     def codeRanking(self):


[18/50] git commit: [#5453] make tool_label match, so tool sorting is blocked when userstats is installed as an anchored tool

Posted by ac...@apache.org.
[#5453] make tool_label match, so tool sorting is blocked when userstats is installed as an anchored tool


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/672ff3a5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/672ff3a5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/672ff3a5

Branch: refs/heads/acs2/5518
Commit: 672ff3a5e71a39b359ed0b8b530bbf05fe5cd315
Parents: e81542a
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Thu Mar 28 14:07:28 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:38 2013 +0000

----------------------------------------------------------------------
 ForgeUserStats/forgeuserstats/main.py |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/672ff3a5/ForgeUserStats/forgeuserstats/main.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/main.py b/ForgeUserStats/forgeuserstats/main.py
index acc196d..194c7d6 100644
--- a/ForgeUserStats/forgeuserstats/main.py
+++ b/ForgeUserStats/forgeuserstats/main.py
@@ -45,7 +45,7 @@ class UserStatsListener(EventsListener):
         if not stats:
             stats = UserStats.create(user)
 
-        if event_type == "assigned": 
+        if event_type == "assigned":
             stats.addAssignedTicket(ticket.mod_date, project)
         elif event_type == "revoked":
             stats.addRevokedTicket(ticket.mod_date, project)
@@ -71,7 +71,7 @@ class UserStatsListener(EventsListener):
 
 class ForgeUserStatsApp(Application):
     __version__ = version.__version__
-    tool_label='Stats'
+    tool_label='UserStats'
     default_mount_label='Stats'
     default_mount_point='stats'
     permissions = ['configure', 'read', 'write',
@@ -128,7 +128,7 @@ class ForgeUserStatsApp(Application):
         return links
 
     def install(self, project):
-        #It doesn't make any sense to install the tool twice on the same 
+        #It doesn't make any sense to install the tool twice on the same
         #project therefore, if it already exists, it doesn't install it
         #a second time.
         for tool in project.app_configs:


[29/50] git commit: add cautionary text to the taskd_cleanup --kill option

Posted by ac...@apache.org.
add cautionary text to the taskd_cleanup --kill option


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/06a70ab3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/06a70ab3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/06a70ab3

Branch: refs/heads/acs2/5518
Commit: 06a70ab322ce7b4cf21ad902051d007184b37847
Parents: 76800ef
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Wed Apr 10 21:30:11 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Wed Apr 10 21:30:11 2013 +0000

----------------------------------------------------------------------
 Allura/allura/command/taskd_cleanup.py |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/06a70ab3/Allura/allura/command/taskd_cleanup.py
----------------------------------------------------------------------
diff --git a/Allura/allura/command/taskd_cleanup.py b/Allura/allura/command/taskd_cleanup.py
index 0951f8b..96c32b7 100644
--- a/Allura/allura/command/taskd_cleanup.py
+++ b/Allura/allura/command/taskd_cleanup.py
@@ -13,7 +13,8 @@ class TaskdCleanupCommand(base.Command):
     parser = base.Command.standard_parser(verbose=True)
     parser.add_option('-k', '--kill-stuck-taskd',
             dest='kill', action='store_true',
-            help='automatically kill stuck taskd processes')
+            help='automatically kill stuck taskd processes.  Be careful with this, a taskd process '
+                 'may just be very busy on certain operations and not able to respond to our status request')
     parser.add_option('-n', '--num-retry-status-check',
             dest='num_retry', type='int', default=5,
             help='number of retries to read taskd status log after sending USR1 signal (5 by default)')
@@ -88,7 +89,7 @@ class TaskdCleanupCommand(base.Command):
             if self.options.kill:
                 base.log.info('...stuck taskd processes were killed')
             else:
-                base.log.info('...to kill these processes run command with -k flag')
+                base.log.info('...to kill these processes run command with -k flag if you are sure they are really stuck')
         if self.error_tasks:
             base.log.info('Tasks marked as \'error\': %s' % self.error_tasks)
 


[43/50] git commit: [#5481] ticket:313 anonymous access to the members page

Posted by ac...@apache.org.
[#5481] ticket:313 anonymous access to the members page


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/b2e7c48d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/b2e7c48d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/b2e7c48d

Branch: refs/heads/acs2/5518
Commit: b2e7c48d27126fbc0126fe426fe753b059d9136b
Parents: 18f106f
Author: Yuriy Arhipov <yu...@yandex.ru>
Authored: Fri Apr 5 13:00:21 2013 +0400
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Mon Apr 15 14:01:51 2013 +0000

----------------------------------------------------------------------
 Allura/allura/tests/functional/test_home.py |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b2e7c48d/Allura/allura/tests/functional/test_home.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_home.py b/Allura/allura/tests/functional/test_home.py
index 758132e..862ebf7 100644
--- a/Allura/allura/tests/functional/test_home.py
+++ b/Allura/allura/tests/functional/test_home.py
@@ -56,3 +56,17 @@ class TestProjectHome(TestController):
             'label': u'Test Admin (test-admin)'
         }]
         assert_equal(j['options'], expected)
+
+    def test_members(self):
+        r = self.app.get('/p/test/_members/')
+        assert '<td >Test Admin</td>' in r
+        assert '<td ><a href="/u/test-admin/">test-admin</a></td>' in r
+        assert '<td > Admin</br> </td>' in r
+        assert '<td >test-admin@users.localhost</td>' in r
+
+    def test_members_anonymous(self):
+        r = self.app.get('/p/test/_members/', extra_environ=dict(username='*anonymous'))
+        assert '<td >Test Admin</td>' in r
+        assert '<td ><a href="/u/test-admin/">test-admin</a></td>' in r
+        assert '<td > Admin</br> </td>' in r
+


[45/50] git commit: [#5481] ticket:313 fixed @, html and tests

Posted by ac...@apache.org.
[#5481] ticket:313 fixed @, html and  tests


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/57b33100
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/57b33100
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/57b33100

Branch: refs/heads/acs2/5518
Commit: 57b33100efe318e5e055843681debfe285183679
Parents: b2e7c48
Author: Yuriy Arhipov <yu...@yandex.ru>
Authored: Sun Apr 7 23:53:15 2013 +0400
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Mon Apr 15 14:01:51 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/project.py        |   18 +++++++-----------
 Allura/allura/lib/macro.py                  |    4 ++--
 Allura/allura/templates/members.html        |   10 +++++-----
 Allura/allura/tests/functional/test_home.py |   14 +++++++-------
 Allura/allura/tests/test_globals.py         |    4 +---
 5 files changed, 22 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/57b33100/Allura/allura/controllers/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index f91c543..6a05acf 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -322,18 +322,14 @@ class ProjectController(object):
     def _members(self, **kw):
         users = []
         for user in c.project.users():
-            roles = []
-            for role in user.project_role().roles:
-                r = M.ProjectRole.query.get(_id=role)
-                if r.name not in roles:
-                    roles.append(r.name)
+            roles = M.ProjectRole.query.find({'_id': {'$in': user.project_role().roles}})
+            roles = set([r.name for r in roles])
             users.append(dict(
-                display_name = user.display_name,
-                username = user.username,
-                url = user.url(),
-                roles = roles,
-                email_addresses = user.email_addresses,
-                skills = user.get_skills()))
+                display_name=user.display_name,
+                username=user.username,
+                url=user.url(),
+                roles=roles,
+                email_addresses=user.email_addresses))
         return dict(users=users)
 
     def _check_security(self):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/57b33100/Allura/allura/lib/macro.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/macro.py b/Allura/allura/lib/macro.py
index 4615828..829897b 100644
--- a/Allura/allura/lib/macro.py
+++ b/Allura/allura/lib/macro.py
@@ -345,12 +345,12 @@ def project_admins():
                 url=user_role.user.url(),
                 name=user_role.user.display_name))
             for user_role in admin_role.users_with_role())
-    return u'<p>Project Admins:<br/>{}</p>'.format(output)
+    return u'<h6>Project Admins:</h6><p>{}</p>'.format(output)
 
 template_members = string.Template('<a href="$url">Members</a><br/>')
 @macro()
 def members():
     output = ''.join(
             template_members.substitute(dict(
-                url=urljoin(c.project.url(),'_members'),)))
+                url=urljoin(c.project.url(), '_members'),)))
     return u'<p>{}</p>'.format(output)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/57b33100/Allura/allura/templates/members.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/members.html b/Allura/allura/templates/members.html
index 06d353a..468d14c 100644
--- a/Allura/allura/templates/members.html
+++ b/Allura/allura/templates/members.html
@@ -8,7 +8,7 @@
 <table>
     <thead>
     <tr>
-        <th >Developer</th>
+        <th>Developer</th>
         <th>Username</th>
         <th>Role/Position</th>
         <th>Email</th>
@@ -16,10 +16,10 @@
     </thead>
     {%for user in users%}
     <tr>
-        <td >{{ user.display_name }}</td>
-        <td ><a href="{{ user.url }}">{{ user.username }}</a></td>
-        <td >{% for role in user.roles%} {{ role }}</br> {%endfor%}</td>
-        <td >{% for email in user.email_addresses %}{{email}}{%endfor%}</td>
+        <td>{{ user.display_name }}</td>
+        <td><a href="{{ user.url }}">{{ user.username }}</a></td>
+        <td>{% for role in user.roles%} {{ role }}</br> {%endfor%}</td>
+        <td>{% for email in user.email_addresses %}{{email.replace('@', ' at ')}}{%endfor%}</td>
     </tr>
     {%endfor%}
 </table>

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/57b33100/Allura/allura/tests/functional/test_home.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_home.py b/Allura/allura/tests/functional/test_home.py
index 862ebf7..b465808 100644
--- a/Allura/allura/tests/functional/test_home.py
+++ b/Allura/allura/tests/functional/test_home.py
@@ -59,14 +59,14 @@ class TestProjectHome(TestController):
 
     def test_members(self):
         r = self.app.get('/p/test/_members/')
-        assert '<td >Test Admin</td>' in r
-        assert '<td ><a href="/u/test-admin/">test-admin</a></td>' in r
-        assert '<td > Admin</br> </td>' in r
-        assert '<td >test-admin@users.localhost</td>' in r
+        assert '<td>Test Admin</td>' in r
+        assert '<td><a href="/u/test-admin/">test-admin</a></td>' in r
+        assert '<td> Admin</br> </td>' in r
+        assert '<td>test-admin at users.localhost</td>' in r
 
     def test_members_anonymous(self):
         r = self.app.get('/p/test/_members/', extra_environ=dict(username='*anonymous'))
-        assert '<td >Test Admin</td>' in r
-        assert '<td ><a href="/u/test-admin/">test-admin</a></td>' in r
-        assert '<td > Admin</br> </td>' in r
+        assert '<td>Test Admin</td>' in r
+        assert '<td><a href="/u/test-admin/">test-admin</a></td>' in r
+        assert '<td> Admin</br> </td>' in r
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/57b33100/Allura/allura/tests/test_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index 4fa37cc..e52c00c 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -150,8 +150,6 @@ def test_macros():
     assert 'test content' in r
 
 def test_macro_members():
-    user = M.User.by_username('test-admin')
-    user.display_name = u'Test Ådmin'
     r = g.markdown_wiki.convert('[[members]]')
     assert_equal(r, u'<div class="markdown_content"><p><a href="/p/test/_members">Members</a><br /></p>\n</div>')
 
@@ -159,7 +157,7 @@ def test_macro_project_admins():
     user = M.User.by_username('test-admin')
     user.display_name = u'Test Ådmin'
     r = g.markdown_wiki.convert('[[project_admins]]')
-    assert_equal(r, u'<div class="markdown_content"><p>Project Admins:<br /><a href="/u/test-admin/">Test Ådmin</a><br /></p>\n</div>')
+    assert_equal(r, u'<div class="markdown_content"><h6>Project Admins:</h6><p><a href="/u/test-admin/">Test Ådmin</a><br /></p>\n</div>')
 
 def test_macro_project_admins_one_br():
     p_nbhd = M.Neighborhood.query.get(name='Projects')


[26/50] git commit: [#5494] Refactor mass edit ticket select checkboxes to use multi-value instead of name/join

Posted by ac...@apache.org.
[#5494] Refactor mass edit ticket select checkboxes to use multi-value instead of name/join

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/5207de0e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/5207de0e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/5207de0e

Branch: refs/heads/acs2/5518
Commit: 5207de0e2d9606fc11d3dd2bd2616941b573cf79
Parents: fa5d7e0
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Thu Apr 4 19:11:12 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Tue Apr 9 16:28:22 2013 +0000

----------------------------------------------------------------------
 .../templates/tracker_widgets/mass_edit.html       |    2 +-
 .../templates/tracker_widgets/mass_edit_form.html  |    1 -
 .../forgetracker/tests/functional/test_root.py     |    6 +++---
 ForgeTracker/forgetracker/tracker_main.py          |   11 ++---------
 .../forgetracker/widgets/resources/js/mass-edit.js |    4 +++-
 5 files changed, 9 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/5207de0e/ForgeTracker/forgetracker/templates/tracker_widgets/mass_edit.html
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/templates/tracker_widgets/mass_edit.html b/ForgeTracker/forgetracker/templates/tracker_widgets/mass_edit.html
index 07b3d22..381cf7a 100644
--- a/ForgeTracker/forgetracker/templates/tracker_widgets/mass_edit.html
+++ b/ForgeTracker/forgetracker/templates/tracker_widgets/mass_edit.html
@@ -17,7 +17,7 @@
       <tbody class="ticket-list">
         {% for t in tickets %}
         <tr>
-          <td><input type="checkbox" name="{{t._id}}" value=""/></td>
+          <td><input type="checkbox" name="ticket_ids" value="{{t._id}}"/></td>
           <td><a href="{{t.url()}}">{{t.ticket_num}}</a></td>
           <td><a href="{{t.url()}}">{{t.summary}}</a></td>
           <td>{{t._milestone}}</td>

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/5207de0e/ForgeTracker/forgetracker/templates/tracker_widgets/mass_edit_form.html
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/templates/tracker_widgets/mass_edit_form.html b/ForgeTracker/forgetracker/templates/tracker_widgets/mass_edit_form.html
index 7e6e738..1cb215b 100644
--- a/ForgeTracker/forgetracker/templates/tracker_widgets/mass_edit_form.html
+++ b/ForgeTracker/forgetracker/templates/tracker_widgets/mass_edit_form.html
@@ -72,6 +72,5 @@
       <!-- tg.url(c.app.url+'search/', dict(q=query, limit=limit, sort=sort))}}" class="btn link">Cancel</a>-->
     </div>
     <div class="grid-12" id="result"></div>
-    <input name="__selected" type="hidden" value="" id="id_selected" />
     <input name="__search" type="hidden" value="" id="id_search" />
 </form>

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/5207de0e/ForgeTracker/forgetracker/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index 8276692..b2fd554 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -243,7 +243,7 @@ class TestFunctionalController(TrackerTestController):
         r = self.app.get('/p/test/bugs/edit/?q=ticket')
         self.app.post('/p/test/bugs/update_tickets', {
                       '__search': '',
-                      '__selected': first_ticket._id,
+                      '__ticket_ids': [first_ticket._id],
                       '_milestone': '2.0',
                       })
         r = self.app.get('/p/test/bugs/1/')
@@ -252,7 +252,7 @@ class TestFunctionalController(TrackerTestController):
         assert '<li><strong>Milestone</strong>: 1.0 --&gt; 2.0</li>' not in r
         self.app.post('/p/test/bugs/update_tickets', {
                       '__search': '',
-                      '__selected': '%s,%s' % (
+                      '__ticket_ids': (
                           first_ticket._id,
                           second_ticket._id),
                       '_milestone': '1.0',
@@ -264,7 +264,7 @@ class TestFunctionalController(TrackerTestController):
 
         self.app.post('/p/test/bugs/update_tickets', {
                       '__search': '',
-                      '__selected': '%s,%s' % (
+                      '__ticket_ids': (
                           first_ticket._id,
                           second_ticket._id),
                       'status': 'accepted',

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/5207de0e/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index 7cde33e..dc14459 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -12,6 +12,7 @@ from itertools import ifilter
 import pkg_resources
 from tg import expose, validate, redirect, flash, url, config
 from tg.decorators import with_trailing_slash, without_trailing_slash
+from paste.deploy.converters import aslist
 from pylons import tmpl_context as c, app_globals as g
 from pylons import request, response
 from formencode import validators
@@ -737,7 +738,7 @@ class RootController(BaseController):
     @require_post()
     def update_tickets(self, **post_data):
         tickets = TM.Ticket.query.find(dict(
-                _id={'$in':[ObjectId(id) for id in post_data['__selected'].split(',')]},
+                _id={'$in':[ObjectId(id) for id in aslist(post_data['__ticket_ids'])]},
                 app_config_id=c.app.config._id)).all()
         for ticket in tickets:
             require_access(ticket, 'update')
@@ -802,14 +803,6 @@ class RootController(BaseController):
         flash('Updated {} ticket{}'.format(count, 's' if count != 1 else ''), 'ok')
         redirect('edit/' + post_data['__search'])
 
-# tickets
-# open tickets
-# closed tickets
-# new tickets in the last 7/14/30 days
-# of comments on tickets
-# of new comments on tickets in 7/14/30
-# of ticket changes in the last 7/14/30
-
     def tickets_since(self, when=None):
         count = 0
         if when:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/5207de0e/ForgeTracker/forgetracker/widgets/resources/js/mass-edit.js
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/widgets/resources/js/mass-edit.js b/ForgeTracker/forgetracker/widgets/resources/js/mass-edit.js
index f9ae973..9be18bb 100644
--- a/ForgeTracker/forgetracker/widgets/resources/js/mass-edit.js
+++ b/ForgeTracker/forgetracker/widgets/resources/js/mass-edit.js
@@ -17,6 +17,8 @@ $(function(){
             return false;
         }
 
-        $('#id_selected').val($checked.map(function(){ return this.name; }).get().join(','));
+        $checked.each(function() {
+            $('#update-values').append('<input type="hidden" name="__ticket_ids" value="'+$(this).val()+'"/>');
+        });
     });
 });


[15/50] git commit: [#5453] Fix svn test to work with user stats

Posted by ac...@apache.org.
[#5453] Fix svn test to work with user stats

Signed-off-by: Tim Van Steenburgh <tv...@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/43731d37
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/43731d37
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/43731d37

Branch: refs/heads/acs2/5518
Commit: 43731d379ffeec3a65155cd652187cd6f6e67f67
Parents: 719ec68
Author: Tim Van Steenburgh <tv...@gmail.com>
Authored: Tue Mar 12 20:04:01 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:37 2013 +0000

----------------------------------------------------------------------
 Allura/allura/model/contrib_stats.py             |    2 +-
 ForgeSVN/forgesvn/tests/model/test_repository.py |   14 +++++++++-----
 2 files changed, 10 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/43731d37/Allura/allura/model/contrib_stats.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/contrib_stats.py b/Allura/allura/model/contrib_stats.py
index 5a4751a..3799ea5 100644
--- a/Allura/allura/model/contrib_stats.py
+++ b/Allura/allura/model/contrib_stats.py
@@ -16,7 +16,7 @@ from allura.lib import helpers as h
 
 class Stats(MappedClass):
     class __mongometa__:
-        name='userstats'
+        name='basestats'
         session = main_orm_session
         unique_indexes = [ '_id']
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/43731d37/ForgeSVN/forgesvn/tests/model/test_repository.py
----------------------------------------------------------------------
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index 1613cf9..676a887 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -519,8 +519,12 @@ class TestRepo(_TestWithRepo):
         assert self.repo.guess_type('.gitignore') == ('text/plain', None)
 
     def test_refresh(self):
+        committer_name = 'Test Committer'
+        committer_email = 'test@example.com'
         ci = mock.Mock()
-        ci.authored.name = 'Test Committer'
+        ci.authored.name = committer_name
+        ci.committed.name = committer_name
+        ci.committed.email = committer_email
         ci.author_url = '/u/test-committer/'
         self.repo.count_revisions=mock.Mock(return_value=100)
         self.repo._impl.commit = mock.Mock(return_value=ci)
@@ -530,8 +534,8 @@ class TestRepo(_TestWithRepo):
         def refresh_commit_info(oid, seen, lazy=False):
             M.repo.CommitDoc(dict(
                     authored=dict(
-                        name='Test Committer',
-                        email='test@test.com'),
+                        name=committer_name,
+                        email=committer_email),
                     _id=oid)).m.insert()
         def set_heads():
             self.repo.heads = [ ming.base.Object(name='head', object_id='foo0', count=100) ]
@@ -545,13 +549,13 @@ class TestRepo(_TestWithRepo):
         notifications = M.Notification.query.find().all()
         for n in notifications:
             if '100 new commits' in n.subject:
-                assert "master,branch:  by Test Committer http://localhost/ci/foo99" in n.text
+                assert "master,branch:  by %s http://localhost/ci/foo99" % committer_name in n.text
                 break
         else:
             assert False, 'Did not find notification'
         assert M.Feed.query.find(dict(
             title='New commit',
-            author_name='Test Committer')).count()
+            author_name=committer_name)).count()
 
     def test_refresh_private(self):
         ci = mock.Mock()


[02/50] git commit: Fix matplotlib version; 1.1.1rc no longer on pypi

Posted by ac...@apache.org.
Fix matplotlib version; 1.1.1rc no longer on pypi


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/656a7b36
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/656a7b36
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/656a7b36

Branch: refs/heads/acs2/5518
Commit: 656a7b36e026b4aaf315d336ad46ea85938073af
Parents: 0cf61cb
Author: Tim Van Steenburgh <tv...@gmail.com>
Authored: Mon Feb 25 21:55:16 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:36 2013 +0000

----------------------------------------------------------------------
 requirements-common.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/656a7b36/requirements-common.txt
----------------------------------------------------------------------
diff --git a/requirements-common.txt b/requirements-common.txt
index 55697b2..e072ad9 100644
--- a/requirements-common.txt
+++ b/requirements-common.txt
@@ -48,7 +48,7 @@ WebOb==1.0.8
 # part of the stdlib, but with a version number.  see http://guide.python-distribute.org/pip.html#listing-installed-packages
 wsgiref==0.1.2
 numpy==1.6.1
-matplotlib==1.1.1rc
+matplotlib==1.1.1
 
 # tg2 deps (not used directly)
 Babel==0.9.6


[38/50] git commit: [#6077] even though Profile tool and ForgeUserStats may get installed automatically as part of the /u/ anchored tools, don't use them on user subproject menus

Posted by ac...@apache.org.
[#6077] even though Profile tool and ForgeUserStats may get installed automatically as part of the /u/ anchored tools, don't use them on user subproject menus


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/15b4e7a2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/15b4e7a2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/15b4e7a2

Branch: refs/heads/acs2/5518
Commit: 15b4e7a25d6a7e1984444919deccb2caf3fec61b
Parents: 9647941
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Fri Apr 12 20:57:27 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Fri Apr 12 21:21:58 2013 +0000

----------------------------------------------------------------------
 Allura/allura/ext/user_profile/user_main.py |    3 ++-
 Allura/allura/tests/functional/test_home.py |    4 ++--
 ForgeUserStats/forgeuserstats/main.py       |    4 ++++
 3 files changed, 8 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/15b4e7a2/Allura/allura/ext/user_profile/user_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/user_main.py b/Allura/allura/ext/user_profile/user_main.py
index 907271a..dd59304 100644
--- a/Allura/allura/ext/user_profile/user_main.py
+++ b/Allura/allura/ext/user_profile/user_main.py
@@ -48,7 +48,8 @@ class UserProfileApp(Application):
         return [SitemapEntry('Profile', '.')]
 
     def is_visible_to(self, user):
-        return True
+        # we don't work with user subprojects
+        return c.project.is_root
 
     def install(self, project):
         pr = c.user.project_role()

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/15b4e7a2/Allura/allura/tests/functional/test_home.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_home.py b/Allura/allura/tests/functional/test_home.py
index 1bb626a..758132e 100644
--- a/Allura/allura/tests/functional/test_home.py
+++ b/Allura/allura/tests/functional/test_home.py
@@ -5,7 +5,7 @@ from allura.tests import TestController
 from allura.tests import decorators as td
 from allura import model as M
 
-from nose.tools import assert_equal
+from nose.tools import assert_equal, assert_not_in
 
 
 class TestProjectHome(TestController):
@@ -35,7 +35,7 @@ class TestProjectHome(TestController):
 
         r = self.app.get('/u/test-admin/sub1/')
         assert r.location.endswith('admin/'), r.location
-        r.follow()
+        assert_not_in('Profile', r.follow().body)
 
     def test_user_search(self):
         r = self.app.get('/p/test/user_search?term=test', status=200)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/15b4e7a2/ForgeUserStats/forgeuserstats/main.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/main.py b/ForgeUserStats/forgeuserstats/main.py
index 95bfbfa..6cc4162 100644
--- a/ForgeUserStats/forgeuserstats/main.py
+++ b/ForgeUserStats/forgeuserstats/main.py
@@ -98,6 +98,10 @@ class ForgeUserStatsApp(Application):
     def main_menu(self):
         return [SitemapEntry(self.config.options.mount_label, '.')]
 
+    def is_visible_to(self, user):
+        # we don't work with user subprojects
+        return c.project.is_root
+
     @property
     @h.exceptionless([], log)
     def sitemap(self):


[17/50] git commit: [#5453] make Profile tool be anchored before userstats, and fixes:

Posted by ac...@apache.org.
[#5453] make Profile tool be anchored before userstats, and fixes:

* make profile icon show up properly everywhere
* make profile tool show up in menus properly
* remove special-casing for the profile tool being first; relies
  on anchored feature now
* update first_mount() to remove simple case (no auth check), to check
  is_visible_to so it is consistent with other menu checks, and to
  remove invalid old ForgeWikiApp type check


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/9d126701
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/9d126701
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/9d126701

Branch: refs/heads/acs2/5518
Commit: 9d126701fc8855930aeda63ee3cdcbf754d0064a
Parents: 672ff3a
Author: Dave Brondsema <db...@geek.net>
Authored: Mon Mar 25 16:09:11 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:38 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/project.py               |    6 +--
 Allura/allura/ext/user_profile/user_main.py        |   17 ++++++---
 Allura/allura/model/project.py                     |   28 ++++-----------
 Allura/allura/nf/allura/css/allura.css             |    6 ++--
 Allura/allura/nf/allura/css/site_style.css         |    2 +-
 .../allura/tests/functional/test_neighborhood.py   |    2 +-
 Allura/allura/websetup/bootstrap.py                |    2 +-
 7 files changed, 27 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9d126701/Allura/allura/controllers/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index 7a1551f..891e18f 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -105,7 +105,7 @@ class NeighborhoodController(object):
         if self.neighborhood.redirect:
             redirect(self.neighborhood.redirect)
         if not self.neighborhood.has_home_tool:
-            mount = c.project.first_mount()
+            mount = c.project.ordered_mounts()[0]
             if mount is not None:
                 if 'ac' in mount:
                     redirect(mount['ac'].options.mount_point + '/')
@@ -323,7 +323,7 @@ class ProjectController(object):
     @expose()
     @with_trailing_slash
     def index(self, **kw):
-        mount = c.project.first_mount('read')
+        mount = c.project.first_mount_visible(c.user)
         activity_enabled = config.get('activitystream.enabled', False)
         activity_enabled = request.cookies.get('activitystream.enabled', activity_enabled)
         activity_enabled = asbool(activity_enabled)
@@ -334,8 +334,6 @@ class ProjectController(object):
                 redirect(mount['ac'].options.mount_point + '/')
             elif 'sub' in mount:
                 redirect(mount['sub'].url())
-        elif c.project.app_instance('profile'):
-            redirect('profile/')
         else:
             redirect(c.project.app_configs[0].options.mount_point + '/')
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9d126701/Allura/allura/ext/user_profile/user_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/user_main.py b/Allura/allura/ext/user_profile/user_main.py
index 7754228..907271a 100644
--- a/Allura/allura/ext/user_profile/user_main.py
+++ b/Allura/allura/ext/user_profile/user_main.py
@@ -9,7 +9,7 @@ from tg import expose, redirect, validate, response
 from webob import exc
 
 from allura import version
-from allura.app import Application
+from allura.app import Application, SitemapEntry
 from allura.lib import helpers as h
 from allura.lib.helpers import DateTimeConverter
 from allura.lib.security import require_access
@@ -23,10 +23,11 @@ log = logging.getLogger(__name__)
 class UserProfileApp(Application):
     __version__ = version.__version__
     installable = False
+    tool_label = 'Profile'
     icons={
-        24:'images/sftheme/24x24/home_24.png',
-        32:'images/sftheme/32x32/home_32.png',
-        48:'images/sftheme/48x48/home_48.png'
+        24:'images/home_24.png',
+        32:'images/home_32.png',
+        48:'images/home_48.png'
     }
 
     def __init__(self, user, config):
@@ -38,11 +39,17 @@ class UserProfileApp(Application):
     @property
     @h.exceptionless([], log)
     def sitemap(self):
-        return []
+        return [SitemapEntry('Profile', '.')]
 
     def admin_menu(self):
         return []
 
+    def main_menu(self):
+        return [SitemapEntry('Profile', '.')]
+
+    def is_visible_to(self, user):
+        return True
+
     def install(self, project):
         pr = c.user.project_role()
         if pr:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9d126701/Allura/allura/model/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 39509ff..b0b45df 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -402,11 +402,6 @@ class Project(MappedClass, ActivityNode, ActivityObject):
         delta_ordinal = i
         max_ordinal = i
 
-        if self.is_user_project:
-            entries.append({'ordinal': delta_ordinal, 'entry':SitemapEntry('Profile', "%sprofile/" % self.url(), ui_icon="tool-home")})
-            max_ordinal = delta_ordinal
-            delta_ordinal = delta_ordinal + 1
-
         for sub in self.direct_subprojects:
             ordinal = sub.ordinal + delta_ordinal
             if ordinal > max_ordinal:
@@ -620,26 +615,17 @@ class Project(MappedClass, ActivityNode, ActivityObject):
                 result.append({'ordinal': int(ordinal), 'ac': ac, 'rank': rank})
         return sorted(result, key=lambda e: (e['ordinal'], e['rank']))
 
-    def first_mount(self, required_access=None):
-        '''Returns the first (toolbar order) mount, or the first mount to
-        which the user has the required access.'''
-        from forgewiki.wiki_main import ForgeWikiApp
+    def first_mount_visible(self, user):
         mounts = self.ordered_mounts()
-        if self.is_user_project:
-            for mount in mounts:
-                if 'ac' in mount and mount['ac'].tool_name == 'profile':
-                    return mount
-        if mounts and required_access is None:
-            return mounts[0]
         for mount in mounts:
             if 'sub' in mount:
-                obj = mount['sub']
+                sub = mount['sub']
+                if has_access(sub, 'read', user):
+                    return mount
             elif 'ac' in mount:
-                obj = self.app_instance(mount['ac'])
-            else:
-                continue
-            if has_access(obj, required_access) or isinstance(obj, ForgeWikiApp):
-                return mount
+                app = self.app_instance(mount['ac'])
+                if app.is_visible_to(user):
+                    return mount
         return None
 
     def next_mount_point(self, include_hidden=False):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9d126701/Allura/allura/nf/allura/css/allura.css
----------------------------------------------------------------------
diff --git a/Allura/allura/nf/allura/css/allura.css b/Allura/allura/nf/allura/css/allura.css
index f3863b8..613caa7 100644
--- a/Allura/allura/nf/allura/css/allura.css
+++ b/Allura/allura/nf/allura/css/allura.css
@@ -36,7 +36,7 @@ b.ico.ico-vote-up { background-image: url('../images/vote_up.png'); }
 b.ico.ico-vote-down { background-image: url('../images/vote_down.png'); }
 
 
-.ui-icon-tool-home {
+.ui-icon-tool-home, .ui-icon-tool-profile {
   background-image: url("../images/home_24.png");
   background-repeat: no-repeat;
 }
@@ -106,7 +106,7 @@ b.ico.ico-vote-down { background-image: url('../images/vote_down.png'); }
   background-repeat: no-repeat;
 }
 
-#top_nav .ui-icon-tool-home {
+#top_nav .ui-icon-tool-home, #top_nav .ui-icon-tool-profile {
   background-image: url("../images/home_32.png");
 }
 #top_nav .ui-icon-tool-wiki {
@@ -149,7 +149,7 @@ b.ico.ico-vote-down { background-image: url('../images/vote_down.png'); }
   background-image: url("../images/chat_32.png");
 }
 
-.big_icon.ui-icon-tool-home {
+.big_icon.ui-icon-tool-home, .big_icon.ui-icon-tool-profile {
   background-image: url("../images/home_48.png");
 }
 .big_icon.ui-icon-tool-wiki {

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9d126701/Allura/allura/nf/allura/css/site_style.css
----------------------------------------------------------------------
diff --git a/Allura/allura/nf/allura/css/site_style.css b/Allura/allura/nf/allura/css/site_style.css
index cc503f4..2f96715 100644
--- a/Allura/allura/nf/allura/css/site_style.css
+++ b/Allura/allura/nf/allura/css/site_style.css
@@ -2216,7 +2216,7 @@ div.attachment_thumb .file_type span {
 }
 
 /* forge tool icons */
-.ui-icon-tool-home {
+.ui-icon-tool-home, .ui-icon-tool-profile {
   background-repeat: no-repeat;
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9d126701/Allura/allura/tests/functional/test_neighborhood.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_neighborhood.py b/Allura/allura/tests/functional/test_neighborhood.py
index 815f557..f1d7e33 100644
--- a/Allura/allura/tests/functional/test_neighborhood.py
+++ b/Allura/allura/tests/functional/test_neighborhood.py
@@ -806,7 +806,7 @@ class TestNeighborhood(TestController):
     @td.with_user_project('test-user')
     def test_profile_topnav_menu(self):
         r = self.app.get('/u/test-user/', extra_environ=dict(username='test-user')).follow()
-        assert '<a href="/u/test-user/profile/" class="ui-icon-tool-home">' in r
+        assert '<a href="/u/test-user/profile/" class="ui-icon-tool-profile">' in r, r
 
     def test_user_project_creates_on_demand(self):
         M.User.register(dict(username='donald-duck'), make_project=False)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9d126701/Allura/allura/websetup/bootstrap.py
----------------------------------------------------------------------
diff --git a/Allura/allura/websetup/bootstrap.py b/Allura/allura/websetup/bootstrap.py
index 747504c..90c8e62 100644
--- a/Allura/allura/websetup/bootstrap.py
+++ b/Allura/allura/websetup/bootstrap.py
@@ -88,7 +88,7 @@ def bootstrap(command, conf, vars):
                                               google_analytics = False))
     n_users = M.Neighborhood(name='Users', url_prefix='/u/',
                              shortname_prefix='u/',
-                             anchored_tools='userstats:Statistics',
+                             anchored_tools='profile:Profile,userstats:Statistics',
                              features=dict(private_projects = True,
                                            max_projects = None,
                                            css = 'none',


[50/50] git commit: Fix pylons imports

Posted by ac...@apache.org.
Fix pylons imports


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/07a8bddf
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/07a8bddf
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/07a8bddf

Branch: refs/heads/acs2/5518
Commit: 07a8bddf2b3dda08fbf84cc0b052e51424670a63
Parents: 674348a
Author: Alvaro del Castillo <ac...@barrapunto.com>
Authored: Tue Apr 16 14:28:13 2013 +0200
Committer: Alvaro del Castillo <ac...@barrapunto.com>
Committed: Tue Apr 16 14:28:13 2013 +0200

----------------------------------------------------------------------
 AlluraBitergiaMetrics/bitergiametrics/main.py |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/07a8bddf/AlluraBitergiaMetrics/bitergiametrics/main.py
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/main.py b/AlluraBitergiaMetrics/bitergiametrics/main.py
index 1991971..df5ad9f 100644
--- a/AlluraBitergiaMetrics/bitergiametrics/main.py
+++ b/AlluraBitergiaMetrics/bitergiametrics/main.py
@@ -6,9 +6,11 @@ import urllib2
 # Non-stdlib imports
 import pkg_resources
 import pymongo
-from tg import expose, validate, redirect, flash
+from tg import expose, validate, redirect, response, flash
 from tg.decorators import with_trailing_slash, without_trailing_slash
-from pylons import g, c, request, response
+from tg.controllers import RestController
+from pylons import tmpl_context as c, app_globals as g
+from pylons import request, response
 from formencode import validators
 from webob import exc
 import MySQLdb


[07/50] git commit: Fix pylons globals imports

Posted by ac...@apache.org.
Fix pylons globals imports


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/86799b5f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/86799b5f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/86799b5f

Branch: refs/heads/acs2/5518
Commit: 86799b5fd68e38a8c349ff50a9db02bd500123d2
Parents: 656a7b3
Author: Tim Van Steenburgh <tv...@gmail.com>
Authored: Mon Feb 25 21:55:33 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:36 2013 +0000

----------------------------------------------------------------------
 Allura/allura/model/contrib_stats.py               |    3 ++-
 .../forgeuserstats/controllers/userstats.py        |    2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/86799b5f/Allura/allura/model/contrib_stats.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/contrib_stats.py b/Allura/allura/model/contrib_stats.py
index d9cada2..4d9e1e9 100644
--- a/Allura/allura/model/contrib_stats.py
+++ b/Allura/allura/model/contrib_stats.py
@@ -1,5 +1,6 @@
 import pymongo
-from pylons import c, g, request
+from pylons import tmpl_context as c, app_globals as g
+from pylons import request
 
 import bson
 from ming import schema as S

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/86799b5f/ForgeUserStats/forgeuserstats/controllers/userstats.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/controllers/userstats.py b/ForgeUserStats/forgeuserstats/controllers/userstats.py
index c77dded..40ad92c 100644
--- a/ForgeUserStats/forgeuserstats/controllers/userstats.py
+++ b/ForgeUserStats/forgeuserstats/controllers/userstats.py
@@ -5,7 +5,7 @@ from allura.controllers import BaseController
 import allura.model as M
 from allura.lib.graphics.graphic_methods import create_histogram, create_progress_bar
 from forgeuserstats.model.stats import UserStats
-from pylons import c
+from pylons import tmpl_context as c
 
 class ForgeUserStatsController(BaseController):
 


[42/50] git commit: [#5481] Refactored and improved [[members]] macro and replaced [[project_admins]] with it in the default wiki

Posted by ac...@apache.org.
[#5481] Refactored and improved [[members]] macro and replaced [[project_admins]] with it in the default wiki

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/69153ade
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/69153ade
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/69153ade

Branch: refs/heads/acs2/5518
Commit: 69153ade3ae8056821619824d7745fdd2e1e6ce0
Parents: 4328a16
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Fri Apr 12 21:00:05 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Mon Apr 15 14:01:51 2013 +0000

----------------------------------------------------------------------
 Allura/allura/lib/macro.py          |   42 +++++++++++++++++------------
 Allura/allura/lib/plugin.py         |    2 +-
 Allura/allura/tests/test_globals.py |   24 +++++++++++++++--
 ForgeWiki/forgewiki/wiki_main.py    |    3 +-
 4 files changed, 48 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/69153ade/Allura/allura/lib/macro.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/macro.py b/Allura/allura/lib/macro.py
index 0f2c65f..747ce58 100644
--- a/Allura/allura/lib/macro.py
+++ b/Allura/allura/lib/macro.py
@@ -4,10 +4,12 @@ import shlex
 import string
 import logging
 import traceback
+from operator import attrgetter
 
 import pymongo
 from pylons import tmpl_context as c, app_globals as g
 from pylons import request
+from paste.deploy.converters import asint
 from urlparse import urljoin
 
 from . import helpers as h
@@ -336,21 +338,27 @@ def img(src=None, **kw):
 template_project_admins = string.Template('<a href="$url">$name</a><br/>')
 @macro()
 def project_admins():
-    from allura import model as M
-    output = ''
-    admin_role = M.ProjectRole.query.get(project_id=c.project._id,name='Admin')
-    if admin_role:
-        output = ''.join(
-            template_project_admins.substitute(dict(
-                url=user_role.user.url(),
-                name=user_role.user.display_name))
-            for user_role in admin_role.users_with_role())
-    return u'<h6>Project Admins:</h6><div class="grid-10">{}</div><div style="clear: both;"></div>'.format(output)
-
-template_members = string.Template('<a href="$url">Members</a><br/>')
-@macro()
-def members():
+    admins = c.project.users_with_role('Admin')
     output = ''.join(
-            template_members.substitute(dict(
-                url=urljoin(c.project.url(), '_members'),)))
-    return u'<p>{}</p>'.format(output)
+        template_project_admins.substitute(dict(
+            url=user.url(),
+            name=user.display_name))
+        for user in admins)
+    return u'<h6>Project Admins:</h6><div class="grid-10" style="margin-left: 2em">{}</div><div style="clear: both;"></div>'.format(output)
+
+template_members = string.Template('<a href="$url">$name</a>$admin<br/>')
+@macro()
+def members(limit=20):
+    limit = asint(limit)
+    admins = set(c.project.users_with_role('Admin'))
+    members = sorted(c.project.users(), key=attrgetter('display_name'))
+    output = '<div style="margin-left: 0.5em; margin-bottom: 0.5em;">%s</div>' % ''.join(
+        template_members.substitute(dict(
+            url=user.url(),
+            name=user.display_name,
+            admin=' (admin)' if user in admins else '',
+            ))
+        for user in members[:limit])
+    if len(members) > limit:
+        output = output + '<a href="%s_members">All Members</a>' % c.project.url()
+    return u'<h6>Project Members:</h6><div style="margin-left: 1.5em;">{}</div><div style="clear: both;"></div>'.format(output)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/69153ade/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 77207a2..87e1e63 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -521,7 +521,7 @@ class ProjectRegistrationProvider(object):
                     if tool == 'wiki':
                         from forgewiki import model as WM
                         text = tool_config.get('home_text',
-                            '[[project_admins]]\n[[members]]\n[[download_button]]')
+                            '[[members limit=20]]\n[[download_button]]')
                         WM.Page.query.get(app_config_id=app.config._id).text = text
 
         if 'tool_order' in project_template:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/69153ade/Allura/allura/tests/test_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index 44c6850..1750bdc 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -149,16 +149,34 @@ def test_macros():
     r = g.markdown_wiki.convert('[[neighborhood_blog_posts]]')
     assert 'test content' in r
 
+@with_setup(teardown=setUp) # reset everything we changed
 def test_macro_members():
-    r = g.markdown_wiki.convert('[[members]]')
-    assert_equal(r, u'<div class="markdown_content"><p><a href="/p/test/_members">Members</a><br /></p>\n</div>')
+    p_nbhd = M.Neighborhood.query.get(name='Projects')
+    p_test = M.Project.query.get(shortname='test', neighborhood_id=p_nbhd._id)
+    p_test.add_user(M.User.by_username('test-user'), ['Developer'])
+    p_test.add_user(M.User.by_username('test-user-0'), ['Member'])
+    ThreadLocalORMSession.flush_all()
+    r = g.markdown_wiki.convert('[[members limit=2]]')
+    assert_equal(r,
+        '<div class="markdown_content">'
+            '<h6>Project Members:</h6>'
+            '<div style="margin-left: 1.5em;">'
+                '<div style="margin-left: 0.5em; margin-bottom: 0.5em;">'
+                    '<a href="/u/test-admin/">Test Admin</a> (admin)<br />'
+                    '<a href="/u/test-user/">Test User</a><br />'
+                '</div>'
+                '<a href="/p/test/_members">All Members</a>'
+            '</div><div style="clear: both;"></div>\n'
+        '</div>')
 
+@with_setup(teardown=setUp) # reset everything we changed
 def test_macro_project_admins():
     user = M.User.by_username('test-admin')
     user.display_name = u'Test Ådmin'
     r = g.markdown_wiki.convert('[[project_admins]]')
-    assert_equal(r, u'<div class="markdown_content"><h6>Project Admins:</h6><div class="grid-10"><a href="/u/test-admin/">Test Ådmin</a><br /></div><div style="clear: both;"></div>\n</div>')
+    assert_equal(r, u'<div class="markdown_content"><h6>Project Admins:</h6><div class="grid-10" style="margin-left: 2em;"><a href="/u/test-admin/">Test Ådmin</a><br /></div><div style="clear: both;"></div>\n</div>')
 
+@with_setup(teardown=setUp) # reset everything we changed
 def test_macro_project_admins_one_br():
     p_nbhd = M.Neighborhood.query.get(name='Projects')
     p_test = M.Project.query.get(shortname='test', neighborhood_id=p_nbhd._id)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/69153ade/ForgeWiki/forgewiki/wiki_main.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index ce253fb..b62762d 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -246,8 +246,7 @@ This is the default page, edit it as you see fit. To add a new page simply refer
 
 The wiki uses [Markdown](%s) syntax.
 
-[[project_admins]]
-[[members]]
+[[members limit=20]]
 [[download_button]]
 """ % url
                 p.commit()


[09/50] git commit: [#5453] Remove old stats.py file, improve userstats code

Posted by ac...@apache.org.
[#5453] Remove old stats.py file, improve userstats code


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/96f7e9a8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/96f7e9a8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/96f7e9a8

Branch: refs/heads/acs2/5518
Commit: 96f7e9a8024881a12150be5d6f4eb1909d0a61f1
Parents: 91774b5
Author: Stefano Invernizzi <st...@apache.org>
Authored: Sun Mar 24 11:00:39 2013 +0100
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:37 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py                  |   12 -
 Allura/allura/controllers/site_admin.py            |   24 -
 .../ext/user_profile/templates/user_index.html     |    9 -
 Allura/allura/lib/plugin.py                        |   14 +
 Allura/allura/model/contrib_stats.py               |  637 --------------
 Allura/allura/model/stats.py                       |  640 ++++++++++++++-
 Allura/allura/templates/site_admin.html            |    1 -
 Allura/allura/tests/functional/test_site_admin.py  |   15 -
 ForgeUserStats/forgeuserstats/model/stats.py       |    9 +-
 .../data/testgit.git/hooks/applypatch-msg.sample   |   15 -
 .../tests/data/testgit.git/hooks/commit-msg.sample |   24 -
 .../data/testgit.git/hooks/post-commit.sample      |    8 -
 .../tests/data/testgit.git/hooks/post-receive      |    1 -
 .../data/testgit.git/hooks/post-receive.sample     |   15 -
 .../data/testgit.git/hooks/post-update.sample      |    8 -
 .../data/testgit.git/hooks/pre-applypatch.sample   |   14 -
 .../tests/data/testgit.git/hooks/pre-commit.sample |   46 -
 .../tests/data/testgit.git/hooks/pre-rebase.sample |  169 ----
 .../testgit.git/hooks/prepare-commit-msg.sample    |   36 -
 .../tests/data/testgit.git/hooks/update            |    1 -
 .../tests/data/testgit.git/hooks/update.sample     |  128 ---
 21 files changed, 652 insertions(+), 1174 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 1b9c74e..8e18767 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -726,18 +726,6 @@ class SubscriptionsController(BaseController):
     @h.vardec
     @expose()
     @require_post()
-    def upload_sshkey(self, key=None):
-        ap = plugin.AuthenticationProvider.get(request)
-        try:
-            ap.upload_sshkey(c.user.username, key)
-        except AssertionError, ae:
-            flash('Error uploading key: %s' % ae, 'error')
-        flash('Key uploaded')
-        redirect('.')
-
-    @h.vardec
-    @expose()
-    @require_post()
     @validate(F.subscription_form, error_handler=index)
     def update_subscriptions(self, subscriptions=None, **kw):
         for s in subscriptions:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/Allura/allura/controllers/site_admin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index 096aba7..6d8fdd8 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -53,30 +53,6 @@ class SiteAdminController(object):
         neighborhoods.sort(key=lambda n:n[0])
         return dict(neighborhoods=neighborhoods)
 
-    @expose('jinja:allura:templates/site_admin_stats.html')
-    @without_trailing_slash
-    def stats(self, limit=25):
-        stats = defaultdict(lambda:defaultdict(list))
-        agg_timings = defaultdict(list)
-        for doc in M.Stats.m.find():
-            if doc.url.startswith('/_debug'): continue
-            doc_stats = stats[doc.url]
-            for t,val in doc.timers.iteritems():
-                doc_stats[t].append(val)
-                agg_timings[t].append(val)
-        for url, timings in stats.iteritems():
-            new_timings = dict(
-                (timer, round(sum(readings)/len(readings),3))
-                for timer, readings in timings.iteritems())
-            timings.update(new_timings)
-        agg_timings = dict(
-            (timer, round(sum(readings)/len(readings),3))
-            for timer, readings in agg_timings.iteritems())
-        stats = sorted(stats.iteritems(), key=lambda x:-x[1]['total'])
-        return dict(
-            agg_timings=agg_timings,
-            stats=stats[:int(limit)])
-
     @expose('jinja:allura:templates/site_admin_api_tickets.html')
     @without_trailing_slash
     def api_tickets(self, **data):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/Allura/allura/ext/user_profile/templates/user_index.html
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/templates/user_index.html b/Allura/allura/ext/user_profile/templates/user_index.html
index 2b17b79..2614953 100644
--- a/Allura/allura/ext/user_profile/templates/user_index.html
+++ b/Allura/allura/ext/user_profile/templates/user_index.html
@@ -236,15 +236,6 @@
     </div>
   </div>
 
-  {% if user.stats.visible %}
-    <div class="grid-24">
-      <div class="grid-24" style="margin:0;"><b>User statistics</b></div>
-      <div class="grid-24" style="margin-top:5px;margin-bottom:5px;">
-        <div><a href="{{c.project.url()}}userstats"/>Go to the personal statistics of this user</a></div>
-      </div>
-    </div>
-  {% endif %}
-
   {% if c.user.username == user.username %}
       <div class="address-list grid-18">
         <b>Email Addresses</b>

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index ed704d4..efc5d07 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -174,6 +174,15 @@ class AuthenticationProvider(object):
     def update_notifications(self, user):
         raise NotImplemented, 'update_notifications'
 
+    def user_registration_date(self, user):
+        '''
+        Returns the date in which a user registered himself/herself on the forge.
+
+        :param user: a :class:`User <allura.model.auth.User>`
+        :rtype: :class:`datetime <datetime.datetime>`
+        '''
+        raise NotImplementedError, 'user_registration_date'
+
 class LocalAuthenticationProvider(AuthenticationProvider):
     '''
     Stores user passwords on the User model, in mongo.  Uses per-user salt and
@@ -230,6 +239,11 @@ class LocalAuthenticationProvider(AuthenticationProvider):
     def update_notifications(self, user):
         return ''
 
+    def user_registration_date(self, user):
+        if user._id:
+            return user._id.generation_time
+        return datetime.utcnow()
+
 class LdapAuthenticationProvider(AuthenticationProvider):
     def register_user(self, user_doc):
         from allura import model as M

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/Allura/allura/model/contrib_stats.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/contrib_stats.py b/Allura/allura/model/contrib_stats.py
deleted file mode 100644
index 3799ea5..0000000
--- a/Allura/allura/model/contrib_stats.py
+++ /dev/null
@@ -1,637 +0,0 @@
-import pymongo
-from pylons import tmpl_context as c, app_globals as g
-from pylons import request
-
-import bson
-from ming import schema as S
-from ming import Field, Index, collection
-from ming.orm import session, state, Mapper
-from ming.orm import FieldProperty
-from ming.orm.declarative import MappedClass
-from datetime import datetime, timedelta
-import difflib
-
-from allura.model.session import main_orm_session
-from allura.lib import helpers as h
-
-class Stats(MappedClass):
-    class __mongometa__:
-        name='basestats'
-        session = main_orm_session
-        unique_indexes = [ '_id']
-
-    _id=FieldProperty(S.ObjectId)
-
-    visible = FieldProperty(bool, if_missing = True)
-    registration_date = FieldProperty(datetime)
-    general = FieldProperty([dict(
-        category = S.ObjectId,
-        messages = [dict(
-            messagetype = str,
-            created = int,
-            modified = int)],
-        tickets = dict(
-            solved = int,
-            assigned = int,
-            revoked = int,
-            totsolvingtime = int),
-        commits = [dict(
-            lines = int,
-            number = int,
-            language = S.ObjectId)])])
-
-    lastmonth=FieldProperty(dict(
-        messages=[dict(
-            datetime=datetime,
-            created=bool,
-            categories=[S.ObjectId],
-            messagetype=str)],
-        assignedtickets=[dict(
-            datetime=datetime,
-            categories=[S.ObjectId])],
-        revokedtickets=[dict(
-            datetime=datetime,
-            categories=[S.ObjectId])],
-        solvedtickets=[dict(
-            datetime=datetime,
-            categories=[S.ObjectId],
-            solvingtime=int)],
-        commits=[dict(
-            datetime=datetime,
-            categories=[S.ObjectId],
-            programming_languages=[S.ObjectId],
-            lines=int)]))
-
-    def getCodeContribution(self):
-        days=(datetime.today() - self.registration_date).days
-        if not days:
-            days=1
-        for val in self['general']:
-            if val['category'] is None:
-                for commits in val['commits']:
-                    if commits['language'] is None: 
-                        if days > 30:
-                            return round(float(commits.lines)/days*30, 2)
-                        else:
-                            return float(commits.lines)
-        return 0
-
-    def getDiscussionContribution(self):
-        days=(datetime.today() - self.registration_date).days
-        if not days:
-            days=1
-        for val in self['general']:
-            if val['category'] is None:
-                for artifact in val['messages']:
-                    if artifact['messagetype'] is None: 
-                        tot = artifact.created+artifact.modified
-                        if days > 30:
-                            return round(float(tot)/days*30,2)
-                        else:
-                            return float(tot)
-        return 0
-
-    def getTicketsContribution(self):
-        for val in self['general']:
-            if val['category'] is None:
-                tickets = val['tickets']
-                if tickets.assigned == 0:
-                    return 0
-                return float(tickets.solved) / tickets.assigned
-        return 0
-
-    @classmethod
-    def getMaxAndAverageCodeContribution(self):
-        lst = list(self.query.find())
-        n = len(lst)
-        if n == 0:
-            return 0, 0
-        maxcontribution=max([x.getCodeContribution() for x in lst])
-        averagecontribution=sum([x.getCodeContribution() for x in lst]) / n
-        return maxcontribution, round(averagecontribution, 2)
-
-    @classmethod
-    def getMaxAndAverageDiscussionContribution(self):
-        lst = list(self.query.find())
-        n = len(lst)
-        if n == 0:
-            return 0, 0
-        maxcontribution=max([x.getDiscussionContribution() for x in lst])
-        averagecontribution=sum([x.getDiscussionContribution() for x in lst])/n
-        return maxcontribution, round(averagecontribution, 2)
-
-    @classmethod
-    def getMaxAndAverageTicketsSolvingPercentage(self):
-        lst = list(self.query.find())
-        n = len(lst)
-        if n == 0:
-            return 0, 0
-        maxcontribution=max([x.getTicketsContribution() for x in lst])
-        averagecontribution=sum([x.getTicketsContribution() for x in lst])/n
-        return maxcontribution, round(averagecontribution, 2)
-
-    def codeRanking(self):
-        lst = list(self.query.find())
-        totn = len(lst)
-        codcontr = self.getCodeContribution()
-        upper = len([x for x in lst if x.getCodeContribution() > codcontr])
-        return round((totn - upper) * 100.0 / totn, 2)
-
-    def discussionRanking(self):
-        lst = list(self.query.find())
-        totn = len(lst)
-        disccontr = self.getDiscussionContribution()
-        upper=len([x for x in lst if x.getDiscussionContribution()>disccontr])
-        return round((totn - upper) * 100.0 / totn, 2)
-
-    def ticketsRanking(self):
-        lst = list(self.query.find())
-        totn = len(lst)
-        ticketscontr = self.getTicketsContribution()
-        upper=len([x for x in lst if x.getTicketsContribution()>ticketscontr])
-        return round((totn - upper) * 100.0 / totn, 2)
-
-    def getCommits(self, category = None):
-        i = getElementIndex(self.general, category = category)
-        if i is None: 
-            return dict(number=0, lines=0)
-        cat = self.general[i]
-        j = getElementIndex(cat.commits, language = None)
-        if j is None:
-            return dict(number=0, lines=0)
-        return dict(
-            number=cat.commits[j]['number'], 
-            lines=cat.commits[j]['lines'])
-
-    def getArtifacts(self, category = None, art_type = None):
-        i = getElementIndex(self.general, category = category)
-        if i is None:
-            return dict(created=0, modified=0)
-        cat = self.general[i]
-        j = getElementIndex(cat.messages, messagetype = art_type)
-        if j is None:
-            return dict(created=0, modified=0)
-        return dict(created=cat.messages[j].created, modified=cat.messages[j].modified)
-
-    def getTickets(self, category = None):
-        i = getElementIndex(self.general, category = category)
-        if i is None:
-            return dict(
-                assigned=0,
-                solved=0,
-                revoked=0,
-                averagesolvingtime=None)
-        if self.general[i].tickets.solved > 0:
-            tot = self.general[i].tickets.totsolvingtime 
-            number = self.general[i].tickets.solved
-            average = tot / number
-        else: 
-            average = None
-        return dict(
-            assigned=self.general[i].tickets.assigned,
-            solved=self.general[i].tickets.solved,
-            revoked=self.general[i].tickets.revoked,
-            averagesolvingtime=_convertTimeDiff(average))
-
-    def getCommitsByCategory(self):
-        from allura.model.project import TroveCategory
-
-        by_cat = {}
-        for entry in self.general:
-            cat = entry.category
-            i = getElementIndex(entry.commits, language = None)
-            if i is None: 
-                n, lines = 0, 0
-            else: 
-                n, lines = entry.commits[i].number, entry.commits[i].lines
-            if cat != None:
-                cat = TroveCategory.query.get(_id = cat)
-            by_cat[cat] = dict(number=n, lines=lines)
-        return by_cat
-
-    #For the moment, commit stats by language are not used, since each project
-    #can be linked to more than one programming language and we don't know how
-    #to which programming language should be credited a line of code modified
-    #within a project including two or more languages.
-    def getCommitsByLanguage(self):
-        langlist = []
-        by_lang = {}
-        i = getElementIndex(self.general, category=None)
-        if i is None: 
-            return dict(number=0, lines=0)
-        return dict([(el.language, dict(lines=el.lines, number=el.number))
-                     for el in self.general[i].commits])
-
-    def getArtifactsByCategory(self, detailed=False):
-        from allura.model.project import TroveCategory
-
-        by_cat = {}
-        for entry in self.general:
-            cat = entry.category
-            if cat != None: 
-                cat = TroveCategory.query.get(_id = cat)
-            if detailed: 
-                by_cat[cat] = entry.messages
-            else:
-                i = getElementIndex(entry.messages, messagetype=None)
-                if i is not None:
-                    by_cat[cat] = entry.messages[i]
-                else: 
-                    by_cat[cat] = dict(created=0, modified=0)
-        return by_cat
-
-    def getArtifactsByType(self, category=None):
-        i = getElementIndex(self.general, category = category)
-        if i is None: 
-            return {}
-        entry = self.general[i].messages
-        by_type = dict([(el.messagetype, dict(created=el.created,
-                                              modified=el.modified))
-                         for el in entry])
-        return by_type
-
-    def getTicketsByCategory(self):
-        from allura.model.project import TroveCategory
-
-        by_cat = {}
-        for entry in self.general:
-            cat = entry.category
-            if cat != None:
-                cat = TroveCategory.query.get(_id = cat)
-            a, s = entry.tickets.assigned, entry.tickets.solved
-            r, time = entry.tickets.solved, entry.tickets.totsolvingtime
-            if s:
-                average = time / s
-            else:
-                average = None
-            by_cat[cat] = dict(
-                assigned=a,
-                solved=s,
-                revoked=r, 
-                averagesolvingtime=_convertTimeDiff(average))
-        return by_cat
-
-    def getLastMonthCommits(self, category = None):
-        self.checkOldArtifacts() 
-        lineslist = [el.lines for el in self.lastmonth.commits
-                     if category in el.categories + [None]]
-        return dict(number=len(lineslist), lines=sum(lineslist))
-
-    def getLastMonthCommitsByCategory(self):
-        from allura.model.project import TroveCategory
-
-        self.checkOldArtifacts() 
-        seen = set()
-        catlist=[el.category for el in self.general
-                 if el.category not in seen and not seen.add(el.category)]
-
-        by_cat = {}
-        for cat in catlist:
-            lineslist = [el.lines for el in self.lastmonth.commits
-                         if cat in el.categories + [None]]
-            n = len(lineslist)
-            lines = sum(lineslist)
-            if cat != None:
-                cat = TroveCategory.query.get(_id = cat)
-            by_cat[cat] = dict(number=n, lines=lines)
-        return by_cat
-
-    def getLastMonthCommitsByLanguage(self):
-        from allura.model.project import TroveCategory
-
-        self.checkOldArtifacts() 
-        seen = set()
-        langlist=[el.language for el in self.general
-                  if el.language not in seen and not seen.add(el.language)]
-
-        by_lang = {}
-        for lang in langlist:
-            lineslist = [el.lines for el in self.lastmonth.commits
-                         if lang in el.programming_languages + [None]]
-            n = len(lineslist)
-            lines = sum(lineslist)
-            if lang != None:
-                lang = TroveCategory.query.get(_id = lang)
-            by_lang[lang] = dict(number=n, lines=lines)
-        return by_lang
-
-    def getLastMonthArtifacts(self, category = None, art_type = None):
-        self.checkOldArtifacts() 
-        cre, mod = reduce(
-            addtuple, 
-            [(int(el.created),1-int(el.created))
-                for el in self.lastmonth.messages
-                if (category is None or category in el.categories) and 
-                (el.messagetype == art_type or art_type is None)], 
-            (0,0))
-        return dict(created=cre, modified=mod)
-
-    def getLastMonthArtifactsByType(self, category = None):
-        self.checkOldArtifacts()
-        seen = set()
-        types=[el.messagetype for el in self.lastmonth.messages
-               if el.messagetype not in seen and not seen.add(el.messagetype)]
-
-        by_type = {}
-        for t in types:
-            cre, mod = reduce(
-                addtuple, 
-                [(int(el.created),1-int(el.created))
-                 for el in self.lastmonth.messages
-                 if el.messagetype == t and
-                 category in [None]+el.categories],
-                (0,0))
-            by_type[t] = dict(created=cre, modified=mod)
-        return by_type
-
-    def getLastMonthArtifactsByCategory(self):
-        from allura.model.project import TroveCategory
-
-        self.checkOldArtifacts() 
-        seen = set()
-        catlist=[el.category for el in self.general
-                 if el.category not in seen and not seen.add(el.category)]
-
-        by_cat = {}
-        for cat in catlist:
-            cre, mod = reduce(
-                addtuple, 
-                [(int(el.created),1-int(el.created))
-                 for el in self.lastmonth.messages 
-                 if cat in el.categories + [None]], (0,0))
-            if cat != None:
-                cat = TroveCategory.query.get(_id = cat)
-            by_cat[cat] = dict(created=cre, modified=mod)
-        return by_cat
-
-    def getLastMonthTickets(self, category = None):
-        from allura.model.project import TroveCategory
-
-        self.checkOldArtifacts()
-        a = len([el for el in self.lastmonth.assignedtickets
-                 if category in el.categories + [None]])
-        r = len([el for el in self.lastmonth.revokedtickets
-                 if category in el.categories + [None]])
-        s, time = reduce(
-            addtuple, 
-            [(1, el.solvingtime)
-             for el in self.lastmonth.solvedtickets
-             if category in el.categories + [None]],
-            (0,0))
-        if category!=None:
-            category = TroveCategory.query.get(_id=category)
-        if s > 0:
-            time = time / s
-        else:
-            time = None
-        return dict(
-            assigned=a,
-            revoked=r,
-            solved=s, 
-            averagesolvingtime=_convertTimeDiff(time))
-        
-    def getLastMonthTicketsByCategory(self):
-        from allura.model.project import TroveCategory
-
-        self.checkOldArtifacts()
-        seen = set()
-        catlist=[el.category for el in self.general
-                 if el.category not in seen and not seen.add(el.category)]
-        by_cat = {}
-        for cat in catlist:
-            a = len([el for el in self.lastmonth.assignedtickets
-                     if cat in el.categories + [None]])
-            r = len([el for el in self.lastmonth.revokedtickets
-                     if cat in el.categories + [None]])
-            s, time = reduce(addtuple, [(1, el.solvingtime)
-                                        for el in self.lastmonth.solvedtickets
-                                        if cat in el.categories+[None]],(0,0))
-            if cat != None:
-                cat = TroveCategory.query.get(_id = cat)
-            if s > 0: 
-                time = time / s
-            else:
-                time = None
-            by_cat[cat] = dict(
-                assigned=a,
-                revoked=r,
-                solved=s, 
-                averagesolvingtime=_convertTimeDiff(time))
-        return by_cat
-        
-    def checkOldArtifacts(self):
-        now = datetime.utcnow()
-        for m in self.lastmonth.messages:
-            if now - m.datetime > timedelta(30):
-                self.lastmonth.messages.remove(m)
-        for t in self.lastmonth.assignedtickets:
-            if now - t.datetime > timedelta(30):
-                self.lastmonth.assignedtickets.remove(t)
-        for t in self.lastmonth.revokedtickets:
-            if now - t.datetime > timedelta(30):
-                self.lastmonth.revokedtickets.remove(t)
-        for t in self.lastmonth.solvedtickets:
-            if now - t.datetime > timedelta(30):
-                self.lastmonth.solvedtickets.remove(t)
-        for c in self.lastmonth.commits:
-            if now - c.datetime > timedelta(30):
-                self.lastmonth.commits.remove(c)
-
-    def addNewArtifact(self, art_type, art_datetime, project):
-        self._updateArtifactsStats(art_type, art_datetime, project, "created")
-
-    def addModifiedArtifact(self, art_type, art_datetime, project):
-        self._updateArtifactsStats(art_type, art_datetime, project, "modified")
-
-    def addAssignedTicket(self, ticket_datetime, project):
-        topics = [t for t in project.trove_topic if t]
-        self._updateTicketsStats(topics, 'assigned')
-        self.lastmonth.assignedtickets.append(
-            dict(datetime=ticket_datetime, categories=topics))
-
-    def addRevokedTicket(self, ticket_datetime, project):
-        topics = [t for t in project.trove_topic if t]
-        self._updateTicketsStats(topics, 'revoked')
-        self.lastmonth.revokedtickets.append(
-            dict(datetime=ticket_datetime, categories=topics))
-        self.checkOldArtifacts()
-
-    def addClosedTicket(self, open_datetime, close_datetime, project):
-        topics = [t for t in project.trove_topic if t]
-        s_time=int((close_datetime-open_datetime).total_seconds())
-        self._updateTicketsStats(topics, 'solved', s_time = s_time)
-        self.lastmonth.solvedtickets.append(dict(
-            datetime=close_datetime,
-            categories=topics,
-            solvingtime=s_time))
-        self.checkOldArtifacts()
-
-    def addCommit(self, newcommit, commit_datetime, project):
-        def _computeLines(newblob, oldblob = None):
-            if oldblob:
-                listold = list(oldblob)
-            else:
-                listold = []
-            if newblob:
-                listnew = list(newblob)
-            else:
-                listnew = []
-
-            if oldblob is None:
-                lines = len(listnew)
-            elif newblob and newblob.has_html_view:
-                diff = difflib.unified_diff(
-                    listold, listnew,
-                    ('old' + oldblob.path()).encode('utf-8'),
-                    ('new' + newblob.path()).encode('utf-8'))
-                lines = len([l for l in diff if len(l) > 0 and l[0] == '+'])-1
-            else:
-                lines = 0
-            return lines
-
-        def _addCommitData(stats, topics, languages, lines):          
-            lt = topics + [None]
-            ll = languages + [None]
-            for t in lt:
-                i = getElementIndex(stats.general, category=t) 
-                if i is None:
-                    newstats = dict(
-                        category=t,
-                        commits=[],
-                        messages=[],
-                        tickets=dict(
-                            assigned=0,
-                            solved=0,
-                            revoked=0,
-                            totsolvingtime=0))
-                    stats.general.append(newstats)
-                    i = getElementIndex(stats.general, category=t)
-                for lang in ll:
-                    j = getElementIndex(
-                        stats.general[i]['commits'], language=lang)
-                    if j is None:
-                        stats.general[i]['commits'].append(dict(
-                            language=lang, lines=lines, number=1))
-                    else:
-                        stats.general[i]['commits'][j].lines += lines
-                        stats.general[i]['commits'][j].number += 1
-
-        topics = [t for t in project.trove_topic if t]
-        languages = [l for l in project.trove_language if l]
-
-        d = newcommit.diffs
-        if len(newcommit.parent_ids) > 0:
-            oldcommit = newcommit.repo.commit(newcommit.parent_ids[0])
-
-        totlines = 0
-        for changed in d.changed:
-            newblob = newcommit.tree.get_blob_by_path(changed)
-            oldblob = oldcommit.tree.get_blob_by_path(changed)
-            totlines+=_computeLines(newblob, oldblob)
-
-        for copied in d.copied:
-            newblob = newcommit.tree.get_blob_by_path(copied['new'])
-            oldblob = oldcommit.tree.get_blob_by_path(copied['old'])
-            totlines+=_computeLines(newblob, oldblob)
-
-        for added in d.added:
-            newblob = newcommit.tree.get_blob_by_path(added)
-            totlines+=_computeLines(newblob)
-
-        _addCommitData(self, topics, languages, totlines)
-
-        self.lastmonth.commits.append(dict(
-            datetime=commit_datetime, 
-            categories=topics, 
-            programming_languages=languages,
-            lines=totlines))
-        self.checkOldArtifacts()
-
-    def _updateArtifactsStats(self, art_type, art_datetime, project, action):
-        if action not in ['created', 'modified']: 
-            return
-        topics = [t for t in project.trove_topic if t]
-        lt = [None] + topics
-        for mtype in [None, art_type]:
-            for t in lt:
-                i = getElementIndex(self.general, category = t)
-                if i is None:
-                    msg = dict(
-                        category=t,
-                        commits=[],
-                        tickets=dict(
-                            solved=0,
-                            assigned=0,
-                            revoked=0,
-                            totsolvingtime=0),
-                        messages=[])
-                    self.general.append(msg)
-                    i = getElementIndex(self.general, category = t)
-                j = getElementIndex(
-                    self.general[i]['messages'], messagetype=mtype)
-                if j is None:
-                    entry = dict(messagetype=mtype, created=0, modified=0)
-                    entry[action] += 1
-                    self.general[i]['messages'].append(entry)
-                else:
-                    self.general[i]['messages'][j][action] += 1
-
-        self.lastmonth.messages.append(dict(
-            datetime=art_datetime,
-            created=(action == 'created'),
-            categories=topics,
-            messagetype=art_type))
-        self.checkOldArtifacts() 
-
-    def _updateTicketsStats(self, topics, action, s_time = None):
-        if action not in ['solved', 'assigned', 'revoked']:
-            return
-        lt = topics + [None]
-        for t in lt:
-            i = getElementIndex(self.general, category = t)
-            if i is None:
-                stats = dict(
-                    category=t,
-                    commits=[],
-                    tickets=dict(
-                        solved=0,
-                        assigned=0,
-                        revoked=0,
-                        totsolvingtime=0),
-                    messages=[])
-                self.general.append(stats)
-                i = getElementIndex(self.general, category = t)
-            self.general[i]['tickets'][action] += 1 
-            if action == 'solved': 
-                self.general[i]['tickets']['totsolvingtime']+=s_time
-
-def getElementIndex(el_list, **kw):
-    for i in range(len(el_list)):
-        for k in kw:
-            if el_list[i].get(k) != kw[k]:
-                break
-        else:
-            return i
-    return None
-
-def addtuple(l1, l2):
-    a, b = l1
-    x, y = l2
-    return (a+x, b+y)
-
-def _convertTimeDiff(int_seconds):
-    if int_seconds is None:
-        return None
-    diff = timedelta(seconds = int_seconds)
-    days, seconds = diff.days, diff.seconds
-    hours = seconds / 3600
-    seconds = seconds % 3600
-    minutes = seconds / 60
-    seconds = seconds % 60
-    return dict(
-        days=days, 
-        hours=hours, 
-        minutes=minutes,
-        seconds=seconds)
-
-Mapper.compile_all()

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/Allura/allura/model/stats.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/stats.py b/Allura/allura/model/stats.py
index ee1f297..df4e45a 100644
--- a/Allura/allura/model/stats.py
+++ b/Allura/allura/model/stats.py
@@ -1,13 +1,637 @@
-import logging
+import pymongo
+from pylons import tmpl_context as c, app_globals as g
+from pylons import request
 
-import ming
+import bson
+from ming import schema as S
+from ming import Field, Index, collection
+from ming.orm import session, state, Mapper
+from ming.orm import FieldProperty
+from ming.orm.declarative import MappedClass
+from datetime import datetime, timedelta
+import difflib
 
-from .session import main_doc_session
+from allura.model.session import main_orm_session
+from allura.lib import helpers as h
 
-log = logging.getLogger(__name__)
-
-class Stats(ming.Document):
+class Stats(MappedClass):
     class __mongometa__:
-        session = main_doc_session
-        name='stats'
+        name='basestats'
+        session = main_orm_session
+        unique_indexes = [ '_id']
+
+    _id=FieldProperty(S.ObjectId)
+
+    visible = FieldProperty(bool, if_missing = True)
+    registration_date = FieldProperty(datetime)
+    general = FieldProperty([dict(
+        category = S.ObjectId,
+        messages = [dict(
+            messagetype = str,
+            created = int,
+            modified = int)],
+        tickets = dict(
+            solved = int,
+            assigned = int,
+            revoked = int,
+            totsolvingtime = int),
+        commits = [dict(
+            lines = int,
+            number = int,
+            language = S.ObjectId)])])
+
+    lastmonth=FieldProperty(dict(
+        messages=[dict(
+            datetime=datetime,
+            created=bool,
+            categories=[S.ObjectId],
+            messagetype=str)],
+        assignedtickets=[dict(
+            datetime=datetime,
+            categories=[S.ObjectId])],
+        revokedtickets=[dict(
+            datetime=datetime,
+            categories=[S.ObjectId])],
+        solvedtickets=[dict(
+            datetime=datetime,
+            categories=[S.ObjectId],
+            solvingtime=int)],
+        commits=[dict(
+            datetime=datetime,
+            categories=[S.ObjectId],
+            programming_languages=[S.ObjectId],
+            lines=int)]))
+
+    def getCodeContribution(self):
+        days=(datetime.today() - self.registration_date).days
+        if not days:
+            days=1
+        for val in self['general']:
+            if val['category'] is None:
+                for commits in val['commits']:
+                    if commits['language'] is None: 
+                        if days > 30:
+                            return round(float(commits.lines)/days*30, 2)
+                        else:
+                            return float(commits.lines)
+        return 0
+
+    def getDiscussionContribution(self):
+        days=(datetime.today() - self.registration_date).days
+        if not days:
+            days=1
+        for val in self['general']:
+            if val['category'] is None:
+                for artifact in val['messages']:
+                    if artifact['messagetype'] is None: 
+                        tot = artifact.created+artifact.modified
+                        if days > 30:
+                            return round(float(tot)/days*30,2)
+                        else:
+                            return float(tot)
+        return 0
+
+    def getTicketsContribution(self):
+        for val in self['general']:
+            if val['category'] is None:
+                tickets = val['tickets']
+                if tickets.assigned == 0:
+                    return 0
+                return float(tickets.solved) / tickets.assigned
+        return 0
+
+    @classmethod
+    def getMaxAndAverageCodeContribution(self):
+        res = self.query.find()
+        n = res.count()
+        if n == 0:
+            return 0, 0
+        maxcontribution=max([x.getCodeContribution() for x in res])
+        averagecontribution=sum([x.getCodeContribution() for x in res]) / n
+        return maxcontribution, round(averagecontribution, 2)
+
+    @classmethod
+    def getMaxAndAverageDiscussionContribution(self):
+        res = self.query.find()
+        n = res.count()
+        if n == 0:
+            return 0, 0
+        maxcontribution=max([x.getDiscussionContribution() for x in res])
+        averagecontribution=sum([x.getDiscussionContribution() for x in res])/n
+        return maxcontribution, round(averagecontribution, 2)
+
+    @classmethod
+    def getMaxAndAverageTicketsSolvingPercentage(self):
+        res = self.query.find()
+        n = res.count()
+        if n == 0:
+            return 0, 0
+        maxcontribution=max([x.getTicketsContribution() for x in res])
+        averagecontribution=sum([x.getTicketsContribution() for x in res])/n
+        return maxcontribution, round(averagecontribution, 2)
+
+    def codeRanking(self):
+        res = self.query.find()
+        totn = res.count()
+        codcontr = self.getCodeContribution()
+        upper = len([x for x in res if x.getCodeContribution() > codcontr])
+        return round((totn - upper) * 100.0 / totn, 2)
+
+    def discussionRanking(self):
+        res = self.query.find()
+        totn = res.count()
+        disccontr = self.getDiscussionContribution()
+        upper=len([x for x in res if x.getDiscussionContribution()>disccontr])
+        return round((totn - upper) * 100.0 / totn, 2)
+
+    def ticketsRanking(self):
+        res = self.query.find()
+        totn = res.count()
+        ticketscontr = self.getTicketsContribution()
+        upper=len([x for x in res if x.getTicketsContribution()>ticketscontr])
+        return round((totn - upper) * 100.0 / totn, 2)
+
+    def getCommits(self, category = None):
+        i = getElementIndex(self.general, category = category)
+        if i is None: 
+            return dict(number=0, lines=0)
+        cat = self.general[i]
+        j = getElementIndex(cat.commits, language = None)
+        if j is None:
+            return dict(number=0, lines=0)
+        return dict(
+            number=cat.commits[j]['number'], 
+            lines=cat.commits[j]['lines'])
+
+    def getArtifacts(self, category = None, art_type = None):
+        i = getElementIndex(self.general, category = category)
+        if i is None:
+            return dict(created=0, modified=0)
+        cat = self.general[i]
+        j = getElementIndex(cat.messages, messagetype = art_type)
+        if j is None:
+            return dict(created=0, modified=0)
+        return dict(created=cat.messages[j].created, modified=cat.messages[j].modified)
+
+    def getTickets(self, category = None):
+        i = getElementIndex(self.general, category = category)
+        if i is None:
+            return dict(
+                assigned=0,
+                solved=0,
+                revoked=0,
+                averagesolvingtime=None)
+        if self.general[i].tickets.solved > 0:
+            tot = self.general[i].tickets.totsolvingtime 
+            number = self.general[i].tickets.solved
+            average = tot / number
+        else: 
+            average = None
+        return dict(
+            assigned=self.general[i].tickets.assigned,
+            solved=self.general[i].tickets.solved,
+            revoked=self.general[i].tickets.revoked,
+            averagesolvingtime=_convertTimeDiff(average))
+
+    def getCommitsByCategory(self):
+        from allura.model.project import TroveCategory
+
+        by_cat = {}
+        for entry in self.general:
+            cat = entry.category
+            i = getElementIndex(entry.commits, language = None)
+            if i is None: 
+                n, lines = 0, 0
+            else: 
+                n, lines = entry.commits[i].number, entry.commits[i].lines
+            if cat != None:
+                cat = TroveCategory.query.get(_id = cat)
+            by_cat[cat] = dict(number=n, lines=lines)
+        return by_cat
+
+    #For the moment, commit stats by language are not used, since each project
+    #can be linked to more than one programming language and we don't know how
+    #to which programming language should be credited a line of code modified
+    #within a project including two or more languages.
+    def getCommitsByLanguage(self):
+        langlist = []
+        by_lang = {}
+        i = getElementIndex(self.general, category=None)
+        if i is None: 
+            return dict(number=0, lines=0)
+        return dict([(el.language, dict(lines=el.lines, number=el.number))
+                     for el in self.general[i].commits])
+
+    def getArtifactsByCategory(self, detailed=False):
+        from allura.model.project import TroveCategory
+
+        by_cat = {}
+        for entry in self.general:
+            cat = entry.category
+            if cat != None: 
+                cat = TroveCategory.query.get(_id = cat)
+            if detailed: 
+                by_cat[cat] = entry.messages
+            else:
+                i = getElementIndex(entry.messages, messagetype=None)
+                if i is not None:
+                    by_cat[cat] = entry.messages[i]
+                else: 
+                    by_cat[cat] = dict(created=0, modified=0)
+        return by_cat
+
+    def getArtifactsByType(self, category=None):
+        i = getElementIndex(self.general, category = category)
+        if i is None: 
+            return {}
+        entry = self.general[i].messages
+        by_type = dict([(el.messagetype, dict(created=el.created,
+                                              modified=el.modified))
+                         for el in entry])
+        return by_type
+
+    def getTicketsByCategory(self):
+        from allura.model.project import TroveCategory
+
+        by_cat = {}
+        for entry in self.general:
+            cat = entry.category
+            if cat != None:
+                cat = TroveCategory.query.get(_id = cat)
+            a, s = entry.tickets.assigned, entry.tickets.solved
+            r, time = entry.tickets.solved, entry.tickets.totsolvingtime
+            if s:
+                average = time / s
+            else:
+                average = None
+            by_cat[cat] = dict(
+                assigned=a,
+                solved=s,
+                revoked=r, 
+                averagesolvingtime=_convertTimeDiff(average))
+        return by_cat
+
+    def getLastMonthCommits(self, category = None):
+        self.checkOldArtifacts() 
+        lineslist = [el.lines for el in self.lastmonth.commits
+                     if category in el.categories + [None]]
+        return dict(number=len(lineslist), lines=sum(lineslist))
+
+    def getLastMonthCommitsByCategory(self):
+        from allura.model.project import TroveCategory
+
+        self.checkOldArtifacts() 
+        seen = set()
+        catlist=[el.category for el in self.general
+                 if el.category not in seen and not seen.add(el.category)]
+
+        by_cat = {}
+        for cat in catlist:
+            lineslist = [el.lines for el in self.lastmonth.commits
+                         if cat in el.categories + [None]]
+            n = len(lineslist)
+            lines = sum(lineslist)
+            if cat != None:
+                cat = TroveCategory.query.get(_id = cat)
+            by_cat[cat] = dict(number=n, lines=lines)
+        return by_cat
+
+    def getLastMonthCommitsByLanguage(self):
+        from allura.model.project import TroveCategory
+
+        self.checkOldArtifacts() 
+        seen = set()
+        langlist=[el.language for el in self.general
+                  if el.language not in seen and not seen.add(el.language)]
+
+        by_lang = {}
+        for lang in langlist:
+            lineslist = [el.lines for el in self.lastmonth.commits
+                         if lang in el.programming_languages + [None]]
+            n = len(lineslist)
+            lines = sum(lineslist)
+            if lang != None:
+                lang = TroveCategory.query.get(_id = lang)
+            by_lang[lang] = dict(number=n, lines=lines)
+        return by_lang
+
+    def getLastMonthArtifacts(self, category = None, art_type = None):
+        self.checkOldArtifacts() 
+        cre, mod = reduce(
+            addtuple, 
+            [(int(el.created),1-int(el.created))
+                for el in self.lastmonth.messages
+                if (category is None or category in el.categories) and 
+                (el.messagetype == art_type or art_type is None)], 
+            (0,0))
+        return dict(created=cre, modified=mod)
+
+    def getLastMonthArtifactsByType(self, category = None):
+        self.checkOldArtifacts()
+        seen = set()
+        types=[el.messagetype for el in self.lastmonth.messages
+               if el.messagetype not in seen and not seen.add(el.messagetype)]
+
+        by_type = {}
+        for t in types:
+            cre, mod = reduce(
+                addtuple, 
+                [(int(el.created),1-int(el.created))
+                 for el in self.lastmonth.messages
+                 if el.messagetype == t and
+                 category in [None]+el.categories],
+                (0,0))
+            by_type[t] = dict(created=cre, modified=mod)
+        return by_type
+
+    def getLastMonthArtifactsByCategory(self):
+        from allura.model.project import TroveCategory
+
+        self.checkOldArtifacts() 
+        seen = set()
+        catlist=[el.category for el in self.general
+                 if el.category not in seen and not seen.add(el.category)]
+
+        by_cat = {}
+        for cat in catlist:
+            cre, mod = reduce(
+                addtuple, 
+                [(int(el.created),1-int(el.created))
+                 for el in self.lastmonth.messages 
+                 if cat in el.categories + [None]], (0,0))
+            if cat != None:
+                cat = TroveCategory.query.get(_id = cat)
+            by_cat[cat] = dict(created=cre, modified=mod)
+        return by_cat
+
+    def getLastMonthTickets(self, category = None):
+        from allura.model.project import TroveCategory
+
+        self.checkOldArtifacts()
+        a = len([el for el in self.lastmonth.assignedtickets
+                 if category in el.categories + [None]])
+        r = len([el for el in self.lastmonth.revokedtickets
+                 if category in el.categories + [None]])
+        s, time = reduce(
+            addtuple, 
+            [(1, el.solvingtime)
+             for el in self.lastmonth.solvedtickets
+             if category in el.categories + [None]],
+            (0,0))
+        if category!=None:
+            category = TroveCategory.query.get(_id=category)
+        if s > 0:
+            time = time / s
+        else:
+            time = None
+        return dict(
+            assigned=a,
+            revoked=r,
+            solved=s, 
+            averagesolvingtime=_convertTimeDiff(time))
+        
+    def getLastMonthTicketsByCategory(self):
+        from allura.model.project import TroveCategory
+
+        self.checkOldArtifacts()
+        seen = set()
+        catlist=[el.category for el in self.general
+                 if el.category not in seen and not seen.add(el.category)]
+        by_cat = {}
+        for cat in catlist:
+            a = len([el for el in self.lastmonth.assignedtickets
+                     if cat in el.categories + [None]])
+            r = len([el for el in self.lastmonth.revokedtickets
+                     if cat in el.categories + [None]])
+            s, time = reduce(addtuple, [(1, el.solvingtime)
+                                        for el in self.lastmonth.solvedtickets
+                                        if cat in el.categories+[None]],(0,0))
+            if cat != None:
+                cat = TroveCategory.query.get(_id = cat)
+            if s > 0: 
+                time = time / s
+            else:
+                time = None
+            by_cat[cat] = dict(
+                assigned=a,
+                revoked=r,
+                solved=s, 
+                averagesolvingtime=_convertTimeDiff(time))
+        return by_cat
+        
+    def checkOldArtifacts(self):
+        now = datetime.utcnow()
+        for m in self.lastmonth.messages:
+            if now - m.datetime > timedelta(30):
+                self.lastmonth.messages.remove(m)
+        for t in self.lastmonth.assignedtickets:
+            if now - t.datetime > timedelta(30):
+                self.lastmonth.assignedtickets.remove(t)
+        for t in self.lastmonth.revokedtickets:
+            if now - t.datetime > timedelta(30):
+                self.lastmonth.revokedtickets.remove(t)
+        for t in self.lastmonth.solvedtickets:
+            if now - t.datetime > timedelta(30):
+                self.lastmonth.solvedtickets.remove(t)
+        for c in self.lastmonth.commits:
+            if now - c.datetime > timedelta(30):
+                self.lastmonth.commits.remove(c)
+
+    def addNewArtifact(self, art_type, art_datetime, project):
+        self._updateArtifactsStats(art_type, art_datetime, project, "created")
+
+    def addModifiedArtifact(self, art_type, art_datetime, project):
+        self._updateArtifactsStats(art_type, art_datetime, project, "modified")
+
+    def addAssignedTicket(self, ticket_datetime, project):
+        topics = [t for t in project.trove_topic if t]
+        self._updateTicketsStats(topics, 'assigned')
+        self.lastmonth.assignedtickets.append(
+            dict(datetime=ticket_datetime, categories=topics))
+
+    def addRevokedTicket(self, ticket_datetime, project):
+        topics = [t for t in project.trove_topic if t]
+        self._updateTicketsStats(topics, 'revoked')
+        self.lastmonth.revokedtickets.append(
+            dict(datetime=ticket_datetime, categories=topics))
+        self.checkOldArtifacts()
+
+    def addClosedTicket(self, open_datetime, close_datetime, project):
+        topics = [t for t in project.trove_topic if t]
+        s_time=int((close_datetime-open_datetime).total_seconds())
+        self._updateTicketsStats(topics, 'solved', s_time = s_time)
+        self.lastmonth.solvedtickets.append(dict(
+            datetime=close_datetime,
+            categories=topics,
+            solvingtime=s_time))
+        self.checkOldArtifacts()
+
+    def addCommit(self, newcommit, commit_datetime, project):
+        def _computeLines(newblob, oldblob = None):
+            if oldblob:
+                listold = list(oldblob)
+            else:
+                listold = []
+            if newblob:
+                listnew = list(newblob)
+            else:
+                listnew = []
+
+            if oldblob is None:
+                lines = len(listnew)
+            elif newblob and newblob.has_html_view:
+                diff = difflib.unified_diff(
+                    listold, listnew,
+                    ('old' + oldblob.path()).encode('utf-8'),
+                    ('new' + newblob.path()).encode('utf-8'))
+                lines = len([l for l in diff if len(l) > 0 and l[0] == '+'])-1
+            else:
+                lines = 0
+            return lines
+
+        def _addCommitData(stats, topics, languages, lines):          
+            lt = topics + [None]
+            ll = languages + [None]
+            for t in lt:
+                i = getElementIndex(stats.general, category=t) 
+                if i is None:
+                    newstats = dict(
+                        category=t,
+                        commits=[],
+                        messages=[],
+                        tickets=dict(
+                            assigned=0,
+                            solved=0,
+                            revoked=0,
+                            totsolvingtime=0))
+                    stats.general.append(newstats)
+                    i = getElementIndex(stats.general, category=t)
+                for lang in ll:
+                    j = getElementIndex(
+                        stats.general[i]['commits'], language=lang)
+                    if j is None:
+                        stats.general[i]['commits'].append(dict(
+                            language=lang, lines=lines, number=1))
+                    else:
+                        stats.general[i]['commits'][j].lines += lines
+                        stats.general[i]['commits'][j].number += 1
+
+        topics = [t for t in project.trove_topic if t]
+        languages = [l for l in project.trove_language if l]
+
+        d = newcommit.diffs
+        if len(newcommit.parent_ids) > 0:
+            oldcommit = newcommit.repo.commit(newcommit.parent_ids[0])
+
+        totlines = 0
+        for changed in d.changed:
+            newblob = newcommit.tree.get_blob_by_path(changed)
+            oldblob = oldcommit.tree.get_blob_by_path(changed)
+            totlines+=_computeLines(newblob, oldblob)
+
+        for copied in d.copied:
+            newblob = newcommit.tree.get_blob_by_path(copied['new'])
+            oldblob = oldcommit.tree.get_blob_by_path(copied['old'])
+            totlines+=_computeLines(newblob, oldblob)
+
+        for added in d.added:
+            newblob = newcommit.tree.get_blob_by_path(added)
+            totlines+=_computeLines(newblob)
+
+        _addCommitData(self, topics, languages, totlines)
+
+        self.lastmonth.commits.append(dict(
+            datetime=commit_datetime, 
+            categories=topics, 
+            programming_languages=languages,
+            lines=totlines))
+        self.checkOldArtifacts()
+
+    def _updateArtifactsStats(self, art_type, art_datetime, project, action):
+        if action not in ['created', 'modified']: 
+            return
+        topics = [t for t in project.trove_topic if t]
+        lt = [None] + topics
+        for mtype in [None, art_type]:
+            for t in lt:
+                i = getElementIndex(self.general, category = t)
+                if i is None:
+                    msg = dict(
+                        category=t,
+                        commits=[],
+                        tickets=dict(
+                            solved=0,
+                            assigned=0,
+                            revoked=0,
+                            totsolvingtime=0),
+                        messages=[])
+                    self.general.append(msg)
+                    i = getElementIndex(self.general, category = t)
+                j = getElementIndex(
+                    self.general[i]['messages'], messagetype=mtype)
+                if j is None:
+                    entry = dict(messagetype=mtype, created=0, modified=0)
+                    entry[action] += 1
+                    self.general[i]['messages'].append(entry)
+                else:
+                    self.general[i]['messages'][j][action] += 1
+
+        self.lastmonth.messages.append(dict(
+            datetime=art_datetime,
+            created=(action == 'created'),
+            categories=topics,
+            messagetype=art_type))
+        self.checkOldArtifacts() 
+
+    def _updateTicketsStats(self, topics, action, s_time = None):
+        if action not in ['solved', 'assigned', 'revoked']:
+            return
+        lt = topics + [None]
+        for t in lt:
+            i = getElementIndex(self.general, category = t)
+            if i is None:
+                stats = dict(
+                    category=t,
+                    commits=[],
+                    tickets=dict(
+                        solved=0,
+                        assigned=0,
+                        revoked=0,
+                        totsolvingtime=0),
+                    messages=[])
+                self.general.append(stats)
+                i = getElementIndex(self.general, category = t)
+            self.general[i]['tickets'][action] += 1 
+            if action == 'solved': 
+                self.general[i]['tickets']['totsolvingtime']+=s_time
+
+def getElementIndex(el_list, **kw):
+    for i in range(len(el_list)):
+        for k in kw:
+            if el_list[i].get(k) != kw[k]:
+                break
+        else:
+            return i
+    return None
+
+def addtuple(l1, l2):
+    a, b = l1
+    x, y = l2
+    return (a+x, b+y)
+
+def _convertTimeDiff(int_seconds):
+    if int_seconds is None:
+        return None
+    diff = timedelta(seconds = int_seconds)
+    days, seconds = diff.days, diff.seconds
+    hours = seconds / 3600
+    seconds = seconds % 3600
+    minutes = seconds / 60
+    seconds = seconds % 60
+    return dict(
+        days=days, 
+        hours=hours, 
+        minutes=minutes,
+        seconds=seconds)
 
+Mapper.compile_all()

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/Allura/allura/templates/site_admin.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/site_admin.html b/Allura/allura/templates/site_admin.html
index b8b1b7d..5ba439b 100644
--- a/Allura/allura/templates/site_admin.html
+++ b/Allura/allura/templates/site_admin.html
@@ -16,7 +16,6 @@
   <div>&nbsp;</div>
   <ul>
     <li class="{{page=='index' and 'active' or ''}}"><a href="{{sidebar_rel}}."><b data-icon="{{g.icons['admin'].char}}" class="ico {{g.icons['admin'].css}}"></b>Home</a></li>
-    <li class="{{page=='stats' and 'active' or ''}}"><a href="{{sidebar_rel}}stats"><b data-icon="{{g.icons['stats'].char}}" class="ico {{g.icons['stats'].css}}"></b>Stats</a></li>
     <li class="{{page=='api_tickets' and 'active' or ''}}"><a href="{{sidebar_rel}}api_tickets"><b data-icon="{{g.icons['admin'].char}}" class="ico {{g.icons['admin'].css}}"></b>API Tickets</a></li>
     <li class="{{page=='add_subscribers' and 'active' or ''}}"><a href="{{sidebar_rel}}add_subscribers"><b data-icon="{{g.icons['admin'].char}}" class="ico {{g.icons['admin'].css}}"></b>Add Subscribers</a></li>
     <li class="{{page=='new_projects' and 'active' or ''}}"><a href="{{sidebar_rel}}new_projects"><b data-icon="{{g.icons['admin'].char}}" class="ico {{g.icons['admin'].css}}"></b>New Projects</a></li>

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/Allura/allura/tests/functional/test_site_admin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_site_admin.py b/Allura/allura/tests/functional/test_site_admin.py
index b5f2d10..3e1925a 100644
--- a/Allura/allura/tests/functional/test_site_admin.py
+++ b/Allura/allura/tests/functional/test_site_admin.py
@@ -23,21 +23,6 @@ class TestSiteAdmin(TestController):
         cells = stats_table.findAll('td')
         assert cells[0].contents[0] == 'Adobe', cells[0].contents[0]
 
-    def test_performance(self):
-        r = self.app.get('/nf/admin/stats', extra_environ=dict(
-                username='test-user'), status=403)
-        r = self.app.get('/nf/admin/stats', extra_environ=dict(
-                username='root'))
-        assert 'Forge Site Admin' in r.html.find('h2',{'class':'dark title'}).contents[0]
-        stats_table = r.html.find('table')
-        headers = stats_table.findAll('th')
-        assert headers[0].contents[0] == 'Url'
-        assert headers[1].contents[0] == 'Ming'
-        assert headers[2].contents[0] == 'Mongo'
-        assert headers[3].contents[0] == 'Render'
-        assert headers[4].contents[0] == 'Template'
-        assert headers[5].contents[0] == 'Total Time'
-
     def test_tickets_access(self):
         r = self.app.get('/nf/admin/api_tickets', extra_environ=dict(
                 username='test-user'), status=403)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/ForgeUserStats/forgeuserstats/model/stats.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/model/stats.py b/ForgeUserStats/forgeuserstats/model/stats.py
index b2f70a4..722b8d0 100644
--- a/ForgeUserStats/forgeuserstats/model/stats.py
+++ b/ForgeUserStats/forgeuserstats/model/stats.py
@@ -2,9 +2,11 @@ from ming.orm import FieldProperty
 from ming import schema as S
 from datetime import datetime, timedelta
 from ming.orm import session, Mapper
+from pylons import request
 
+from allura.lib import plugin
 from allura.model.session import main_orm_session
-from allura.model.contrib_stats import Stats
+from allura.model import Stats
 
 class UserStats(Stats):
     class __mongometa__:
@@ -19,11 +21,12 @@ class UserStats(Stats):
 
     @classmethod
     def create(cls, user):
+        auth_provider = plugin.AuthenticationProvider.get(request)
+        reg_date = auth_provider.user_registration_date(user)
         stats = cls.query.get(user_id = user._id)
         if stats:
             return stats
-        stats = cls(user_id=user._id,
-            registration_date = datetime.utcnow())
+        stats = cls(user_id=user._id, registration_date = reg_date)
         user.stats_id = stats._id
         return stats
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/applypatch-msg.sample
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/applypatch-msg.sample b/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/applypatch-msg.sample
deleted file mode 100755
index 8b2a2fe..0000000
--- a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/applypatch-msg.sample
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to check the commit log message taken by
-# applypatch from an e-mail message.
-#
-# The hook should exit with non-zero status after issuing an
-# appropriate message if it wants to stop the commit.  The hook is
-# allowed to edit the commit message file.
-#
-# To enable this hook, rename this file to "applypatch-msg".
-
-. git-sh-setup
-test -x "$GIT_DIR/hooks/commit-msg" &&
-	exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
-:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/commit-msg.sample
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/commit-msg.sample b/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/commit-msg.sample
deleted file mode 100755
index 6ef1d29..0000000
--- a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/commit-msg.sample
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to check the commit log message.
-# Called by git-commit with one argument, the name of the file
-# that has the commit message.  The hook should exit with non-zero
-# status after issuing an appropriate message if it wants to stop the
-# commit.  The hook is allowed to edit the commit message file.
-#
-# To enable this hook, rename this file to "commit-msg".
-
-# Uncomment the below to add a Signed-off-by line to the message.
-# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
-# hook is more suited to it.
-#
-# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
-# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
-
-# This example catches duplicate Signed-off-by lines.
-
-test "" = "$(grep '^Signed-off-by: ' "$1" |
-	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
-	echo >&2 Duplicate Signed-off-by lines.
-	exit 1
-}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-commit.sample
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-commit.sample b/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-commit.sample
deleted file mode 100755
index 2266821..0000000
--- a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-commit.sample
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-#
-# An example hook script that is called after a successful
-# commit is made.
-#
-# To enable this hook, rename this file to "post-commit".
-
-: Nothing

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-receive
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-receive b/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-receive
deleted file mode 100755
index 0f7a148..0000000
--- a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-receive
+++ /dev/null
@@ -1 +0,0 @@
-post-receive

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-receive.sample
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-receive.sample b/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-receive.sample
deleted file mode 100755
index 7a83e17..0000000
--- a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-receive.sample
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# An example hook script for the "post-receive" event.
-#
-# The "post-receive" script is run after receive-pack has accepted a pack
-# and the repository has been updated.  It is passed arguments in through
-# stdin in the form
-#  <oldrev> <newrev> <refname>
-# For example:
-#  aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
-#
-# see contrib/hooks/ for a sample, or uncomment the next line and
-# rename the file to "post-receive".
-
-#. /usr/share/doc/git-core/contrib/hooks/post-receive-email

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-update.sample
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-update.sample b/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-update.sample
deleted file mode 100755
index 5323b56..0000000
--- a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/post-update.sample
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to prepare a packed repository for use over
-# dumb transports.
-#
-# To enable this hook, rename this file to "post-update".
-
-exec git-update-server-info

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/pre-applypatch.sample
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/pre-applypatch.sample b/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/pre-applypatch.sample
deleted file mode 100755
index b1f187c..0000000
--- a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/pre-applypatch.sample
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to verify what is about to be committed
-# by applypatch from an e-mail message.
-#
-# The hook should exit with non-zero status after issuing an
-# appropriate message if it wants to stop the commit.
-#
-# To enable this hook, rename this file to "pre-applypatch".
-
-. git-sh-setup
-test -x "$GIT_DIR/hooks/pre-commit" &&
-	exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
-:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/pre-commit.sample
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/pre-commit.sample b/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/pre-commit.sample
deleted file mode 100755
index 439eefd..0000000
--- a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/pre-commit.sample
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to verify what is about to be committed.
-# Called by git-commit with no arguments.  The hook should
-# exit with non-zero status after issuing an appropriate message if
-# it wants to stop the commit.
-#
-# To enable this hook, rename this file to "pre-commit".
-
-if git-rev-parse --verify HEAD >/dev/null 2>&1
-then
-	against=HEAD
-else
-	# Initial commit: diff against an empty tree object
-	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
-fi
-
-# If you want to allow non-ascii filenames set this variable to true.
-allownonascii=$(git config hooks.allownonascii)
-
-# Cross platform projects tend to avoid non-ascii filenames; prevent
-# them from being added to the repository. We exploit the fact that the
-# printable range starts at the space character and ends with tilde.
-if [ "$allownonascii" != "true" ] &&
-	# Note that the use of brackets around a tr range is ok here, (it's
-	# even required, for portability to Solaris 10's /usr/bin/tr), since
-	# the square bracket bytes happen to fall in the designated range.
-	test "$(git diff --cached --name-only --diff-filter=A -z $against |
-	  LC_ALL=C tr -d '[ -~]\0')"
-then
-	echo "Error: Attempt to add a non-ascii file name."
-	echo
-	echo "This can cause problems if you want to work"
-	echo "with people on other platforms."
-	echo
-	echo "To be portable it is advisable to rename the file ..."
-	echo
-	echo "If you know what you are doing you can disable this"
-	echo "check using:"
-	echo
-	echo "  git config hooks.allownonascii true"
-	echo
-	exit 1
-fi
-
-exec git diff-index --check --cached $against --

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/pre-rebase.sample
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/pre-rebase.sample b/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/pre-rebase.sample
deleted file mode 100755
index be1b06e..0000000
--- a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/pre-rebase.sample
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2006, 2008 Junio C Hamano
-#
-# The "pre-rebase" hook is run just before "git-rebase" starts doing
-# its job, and can prevent the command from running by exiting with
-# non-zero status.
-#
-# The hook is called with the following parameters:
-#
-# $1 -- the upstream the series was forked from.
-# $2 -- the branch being rebased (or empty when rebasing the current branch).
-#
-# This sample shows how to prevent topic branches that are already
-# merged to 'next' branch from getting rebased, because allowing it
-# would result in rebasing already published history.
-
-publish=next
-basebranch="$1"
-if test "$#" = 2
-then
-	topic="refs/heads/$2"
-else
-	topic=`git symbolic-ref HEAD` ||
-	exit 0 ;# we do not interrupt rebasing detached HEAD
-fi
-
-case "$topic" in
-refs/heads/??/*)
-	;;
-*)
-	exit 0 ;# we do not interrupt others.
-	;;
-esac
-
-# Now we are dealing with a topic branch being rebased
-# on top of master.  Is it OK to rebase it?
-
-# Does the topic really exist?
-git show-ref -q "$topic" || {
-	echo >&2 "No such branch $topic"
-	exit 1
-}
-
-# Is topic fully merged to master?
-not_in_master=`git-rev-list --pretty=oneline ^master "$topic"`
-if test -z "$not_in_master"
-then
-	echo >&2 "$topic is fully merged to master; better remove it."
-	exit 1 ;# we could allow it, but there is no point.
-fi
-
-# Is topic ever merged to next?  If so you should not be rebasing it.
-only_next_1=`git-rev-list ^master "^$topic" ${publish} | sort`
-only_next_2=`git-rev-list ^master           ${publish} | sort`
-if test "$only_next_1" = "$only_next_2"
-then
-	not_in_topic=`git-rev-list "^$topic" master`
-	if test -z "$not_in_topic"
-	then
-		echo >&2 "$topic is already up-to-date with master"
-		exit 1 ;# we could allow it, but there is no point.
-	else
-		exit 0
-	fi
-else
-	not_in_next=`git-rev-list --pretty=oneline ^${publish} "$topic"`
-	perl -e '
-		my $topic = $ARGV[0];
-		my $msg = "* $topic has commits already merged to public branch:\n";
-		my (%not_in_next) = map {
-			/^([0-9a-f]+) /;
-			($1 => 1);
-		} split(/\n/, $ARGV[1]);
-		for my $elem (map {
-				/^([0-9a-f]+) (.*)$/;
-				[$1 => $2];
-			} split(/\n/, $ARGV[2])) {
-			if (!exists $not_in_next{$elem->[0]}) {
-				if ($msg) {
-					print STDERR $msg;
-					undef $msg;
-				}
-				print STDERR " $elem->[1]\n";
-			}
-		}
-	' "$topic" "$not_in_next" "$not_in_master"
-	exit 1
-fi
-
-exit 0
-
-################################################################
-
-This sample hook safeguards topic branches that have been
-published from being rewound.
-
-The workflow assumed here is:
-
- * Once a topic branch forks from "master", "master" is never
-   merged into it again (either directly or indirectly).
-
- * Once a topic branch is fully cooked and merged into "master",
-   it is deleted.  If you need to build on top of it to correct
-   earlier mistakes, a new topic branch is created by forking at
-   the tip of the "master".  This is not strictly necessary, but
-   it makes it easier to keep your history simple.
-
- * Whenever you need to test or publish your changes to topic
-   branches, merge them into "next" branch.
-
-The script, being an example, hardcodes the publish branch name
-to be "next", but it is trivial to make it configurable via
-$GIT_DIR/config mechanism.
-
-With this workflow, you would want to know:
-
-(1) ... if a topic branch has ever been merged to "next".  Young
-    topic branches can have stupid mistakes you would rather
-    clean up before publishing, and things that have not been
-    merged into other branches can be easily rebased without
-    affecting other people.  But once it is published, you would
-    not want to rewind it.
-
-(2) ... if a topic branch has been fully merged to "master".
-    Then you can delete it.  More importantly, you should not
-    build on top of it -- other people may already want to
-    change things related to the topic as patches against your
-    "master", so if you need further changes, it is better to
-    fork the topic (perhaps with the same name) afresh from the
-    tip of "master".
-
-Let's look at this example:
-
-		   o---o---o---o---o---o---o---o---o---o "next"
-		  /       /           /           /
-		 /   a---a---b A     /           /
-		/   /               /           /
-	       /   /   c---c---c---c B         /
-	      /   /   /             \         /
-	     /   /   /   b---b C     \       /
-	    /   /   /   /             \     /
-    ---o---o---o---o---o---o---o---o---o---o---o "master"
-
-
-A, B and C are topic branches.
-
- * A has one fix since it was merged up to "next".
-
- * B has finished.  It has been fully merged up to "master" and "next",
-   and is ready to be deleted.
-
- * C has not merged to "next" at all.
-
-We would want to allow C to be rebased, refuse A, and encourage
-B to be deleted.
-
-To compute (1):
-
-	git-rev-list ^master ^topic next
-	git-rev-list ^master        next
-
-	if these match, topic has not merged in next at all.
-
-To compute (2):
-
-	git-rev-list master..topic
-
-	if this is empty, it is fully merged to "master".

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/prepare-commit-msg.sample
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/prepare-commit-msg.sample b/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/prepare-commit-msg.sample
deleted file mode 100755
index 3652424..0000000
--- a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/prepare-commit-msg.sample
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to prepare the commit log message.
-# Called by git-commit with the name of the file that has the
-# commit message, followed by the description of the commit
-# message's source.  The hook's purpose is to edit the commit
-# message file.  If the hook fails with a non-zero status,
-# the commit is aborted.
-#
-# To enable this hook, rename this file to "prepare-commit-msg".
-
-# This hook includes three examples.  The first comments out the
-# "Conflicts:" part of a merge commit.
-#
-# The second includes the output of "git diff --name-status -r"
-# into the message, just before the "git status" output.  It is
-# commented because it doesn't cope with --amend or with squashed
-# commits.
-#
-# The third example adds a Signed-off-by line to the message, that can
-# still be edited.  This is rarely a good idea.
-
-case "$2,$3" in
-  merge,)
-    perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
-
-# ,|template,)
-#   perl -i.bak -pe '
-#      print "\n" . `git diff --cached --name-status -r`
-#	 if /^#/ && $first++ == 0' "$1" ;;
-
-  *) ;;
-esac
-
-# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
-# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/update
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/update b/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/update
deleted file mode 100755
index 4ea5e4d..0000000
--- a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/update
+++ /dev/null
@@ -1 +0,0 @@
-update

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96f7e9a8/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/update.sample
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/update.sample b/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/update.sample
deleted file mode 100755
index fd63b2d..0000000
--- a/ForgeUserStats/forgeuserstats/tests/data/testgit.git/hooks/update.sample
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to blocks unannotated tags from entering.
-# Called by git-receive-pack with arguments: refname sha1-old sha1-new
-#
-# To enable this hook, rename this file to "update".
-#
-# Config
-# ------
-# hooks.allowunannotated
-#   This boolean sets whether unannotated tags will be allowed into the
-#   repository.  By default they won't be.
-# hooks.allowdeletetag
-#   This boolean sets whether deleting tags will be allowed in the
-#   repository.  By default they won't be.
-# hooks.allowmodifytag
-#   This boolean sets whether a tag may be modified after creation. By default
-#   it won't be.
-# hooks.allowdeletebranch
-#   This boolean sets whether deleting branches will be allowed in the
-#   repository.  By default they won't be.
-# hooks.denycreatebranch
-#   This boolean sets whether remotely creating branches will be denied
-#   in the repository.  By default this is allowed.
-#
-
-# --- Command line
-refname="$1"
-oldrev="$2"
-newrev="$3"
-
-# --- Safety check
-if [ -z "$GIT_DIR" ]; then
-	echo "Don't run this script from the command line." >&2
-	echo " (if you want, you could supply GIT_DIR then run" >&2
-	echo "  $0 <ref> <oldrev> <newrev>)" >&2
-	exit 1
-fi
-
-if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
-	echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
-	exit 1
-fi
-
-# --- Config
-allowunannotated=$(git config --bool hooks.allowunannotated)
-allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
-denycreatebranch=$(git config --bool hooks.denycreatebranch)
-allowdeletetag=$(git config --bool hooks.allowdeletetag)
-allowmodifytag=$(git config --bool hooks.allowmodifytag)
-
-# check for no description
-projectdesc=$(sed -e '1q' "$GIT_DIR/description")
-case "$projectdesc" in
-"Unnamed repository"* | "")
-	echo "*** Project description file hasn't been set" >&2
-	exit 1
-	;;
-esac
-
-# --- Check types
-# if $newrev is 0000...0000, it's a commit to delete a ref.
-zero="0000000000000000000000000000000000000000"
-if [ "$newrev" = "$zero" ]; then
-	newrev_type=delete
-else
-	newrev_type=$(git-cat-file -t $newrev)
-fi
-
-case "$refname","$newrev_type" in
-	refs/tags/*,commit)
-		# un-annotated tag
-		short_refname=${refname##refs/tags/}
-		if [ "$allowunannotated" != "true" ]; then
-			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
-			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
-			exit 1
-		fi
-		;;
-	refs/tags/*,delete)
-		# delete tag
-		if [ "$allowdeletetag" != "true" ]; then
-			echo "*** Deleting a tag is not allowed in this repository" >&2
-			exit 1
-		fi
-		;;
-	refs/tags/*,tag)
-		# annotated tag
-		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
-		then
-			echo "*** Tag '$refname' already exists." >&2
-			echo "*** Modifying a tag is not allowed in this repository." >&2
-			exit 1
-		fi
-		;;
-	refs/heads/*,commit)
-		# branch
-		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
-			echo "*** Creating a branch is not allowed in this repository" >&2
-			exit 1
-		fi
-		;;
-	refs/heads/*,delete)
-		# delete branch
-		if [ "$allowdeletebranch" != "true" ]; then
-			echo "*** Deleting a branch is not allowed in this repository" >&2
-			exit 1
-		fi
-		;;
-	refs/remotes/*,commit)
-		# tracking branch
-		;;
-	refs/remotes/*,delete)
-		# delete tracking branch
-		if [ "$allowdeletebranch" != "true" ]; then
-			echo "*** Deleting a tracking branch is not allowed in this repository" >&2
-			exit 1
-		fi
-		;;
-	*)
-		# Anything else (is there anything else?)
-		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
-		exit 1
-		;;
-esac
-
-# --- Finished
-exit 0


[46/50] git commit: [#5481] Removed inline styles and use ULs for admins / members macros

Posted by ac...@apache.org.
[#5481] Removed inline styles and use ULs for admins / members macros

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/19585988
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/19585988
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/19585988

Branch: refs/heads/acs2/5518
Commit: 19585988b7ad24fe594bb79f1c09e9494acdaaf7
Parents: 69153ad
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Fri Apr 12 22:40:38 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Mon Apr 15 14:01:51 2013 +0000

----------------------------------------------------------------------
 Allura/allura/lib/macro.py                 |   17 +++++++++--------
 Allura/allura/nf/allura/css/site_style.css |    8 ++++++++
 Allura/allura/tests/test_globals.py        |   16 +++++++---------
 3 files changed, 24 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/19585988/Allura/allura/lib/macro.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/macro.py b/Allura/allura/lib/macro.py
index 747ce58..53ebd6b 100644
--- a/Allura/allura/lib/macro.py
+++ b/Allura/allura/lib/macro.py
@@ -7,6 +7,7 @@ import traceback
 from operator import attrgetter
 
 import pymongo
+import jinja2
 from pylons import tmpl_context as c, app_globals as g
 from pylons import request
 from paste.deploy.converters import asint
@@ -335,30 +336,30 @@ def img(src=None, **kw):
         return '<img src="./attachment/%s" %s/>' % (src, ' '.join(attrs))
 
 
-template_project_admins = string.Template('<a href="$url">$name</a><br/>')
+template_project_admins = string.Template('<li><a href="$url">$name</a></li>')
 @macro()
 def project_admins():
     admins = c.project.users_with_role('Admin')
     output = ''.join(
         template_project_admins.substitute(dict(
             url=user.url(),
-            name=user.display_name))
+            name=jinja2.escape(user.display_name)))
         for user in admins)
-    return u'<h6>Project Admins:</h6><div class="grid-10" style="margin-left: 2em">{}</div><div style="clear: both;"></div>'.format(output)
+    return u'<h6>Project Admins:</h6><ul class="md-users-list">{0}</ul>'.format(output)
 
-template_members = string.Template('<a href="$url">$name</a>$admin<br/>')
+template_members = string.Template('<li><a href="$url">$name</a>$admin</li>')
 @macro()
 def members(limit=20):
     limit = asint(limit)
     admins = set(c.project.users_with_role('Admin'))
     members = sorted(c.project.users(), key=attrgetter('display_name'))
-    output = '<div style="margin-left: 0.5em; margin-bottom: 0.5em;">%s</div>' % ''.join(
+    output = ''.join(
         template_members.substitute(dict(
             url=user.url(),
-            name=user.display_name,
+            name=jinja2.escape(user.display_name),
             admin=' (admin)' if user in admins else '',
             ))
         for user in members[:limit])
     if len(members) > limit:
-        output = output + '<a href="%s_members">All Members</a>' % c.project.url()
-    return u'<h6>Project Members:</h6><div style="margin-left: 1.5em;">{}</div><div style="clear: both;"></div>'.format(output)
+        output = output + '<li class="md-users-list-more"><a href="%s_members">All Members</a></li>' % c.project.url()
+    return u'<h6>Project Members:</h6><ul class="md-users-list">{0}</ul>'.format(output)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/19585988/Allura/allura/nf/allura/css/site_style.css
----------------------------------------------------------------------
diff --git a/Allura/allura/nf/allura/css/site_style.css b/Allura/allura/nf/allura/css/site_style.css
index 2f96715..3256ad0 100644
--- a/Allura/allura/nf/allura/css/site_style.css
+++ b/Allura/allura/nf/allura/css/site_style.css
@@ -2066,6 +2066,14 @@ nav .ico {
   padding: 0;
 }
 
+.markdown_content ul.md-users-list {
+    list-style: none;
+}
+.markdown_content ul.md-users-list li.md-users-list-more {
+    margin-left: -0.5em;
+    margin-top: 0.5em;
+}
+
 .media a {
   float: left;
   margin-right: 20px;

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/19585988/Allura/allura/tests/test_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index 1750bdc..c1dc9a8 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -160,13 +160,11 @@ def test_macro_members():
     assert_equal(r,
         '<div class="markdown_content">'
             '<h6>Project Members:</h6>'
-            '<div style="margin-left: 1.5em;">'
-                '<div style="margin-left: 0.5em; margin-bottom: 0.5em;">'
-                    '<a href="/u/test-admin/">Test Admin</a> (admin)<br />'
-                    '<a href="/u/test-user/">Test User</a><br />'
-                '</div>'
-                '<a href="/p/test/_members">All Members</a>'
-            '</div><div style="clear: both;"></div>\n'
+            '<ul class="md-users-list">'
+                '<li><a href="/u/test-admin/">Test Admin</a> (admin)</li>'
+                '<li><a href="/u/test-user/">Test User</a></li>'
+                '<li class="md-users-list-more"><a href="/p/test/_members">All Members</a></li>'
+            '</ul>\n'
         '</div>')
 
 @with_setup(teardown=setUp) # reset everything we changed
@@ -174,7 +172,7 @@ def test_macro_project_admins():
     user = M.User.by_username('test-admin')
     user.display_name = u'Test Ådmin'
     r = g.markdown_wiki.convert('[[project_admins]]')
-    assert_equal(r, u'<div class="markdown_content"><h6>Project Admins:</h6><div class="grid-10" style="margin-left: 2em;"><a href="/u/test-admin/">Test Ådmin</a><br /></div><div style="clear: both;"></div>\n</div>')
+    assert_equal(r, u'<div class="markdown_content"><h6>Project Admins:</h6><ul class="md-users-list"><li><a href="/u/test-admin/">Test Ådmin</a></li></ul>\n</div>')
 
 @with_setup(teardown=setUp) # reset everything we changed
 def test_macro_project_admins_one_br():
@@ -185,7 +183,7 @@ def test_macro_project_admins_one_br():
     r = g.markdown_wiki.convert('[[project_admins]]\n[[download_button]]')
 
     assert not '</a><br /><br /><a href=' in r, r
-    assert '</a><br /><a href=' in r, r
+    assert '</a></li><li><a href=' in r, r
 
 
 @td.with_wiki


[12/50] git commit: [#5453] Fix initialization of the stats object

Posted by ac...@apache.org.
[#5453] Fix initialization of the stats object


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/8eeb3ae0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/8eeb3ae0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/8eeb3ae0

Branch: refs/heads/acs2/5518
Commit: 8eeb3ae0db7dd9bfde2e8fb5cfdf0f5da6a384d8
Parents: faf7812
Author: Stefano Invernizzi <st...@apache.org>
Authored: Wed Mar 6 22:39:25 2013 +0100
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:37 2013 +0000

----------------------------------------------------------------------
 Allura/allura/model/contrib_stats.py |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/8eeb3ae0/Allura/allura/model/contrib_stats.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/contrib_stats.py b/Allura/allura/model/contrib_stats.py
index adc36db..51121ad 100644
--- a/Allura/allura/model/contrib_stats.py
+++ b/Allura/allura/model/contrib_stats.py
@@ -498,12 +498,12 @@ class Stats(MappedClass):
                     newstats = dict(
                         category=t,
                         commits=[],
-                        messages=dict(
+                        messages=[dict(
                             assigned=0,
                             solved=0,
                             revoked=0,
-                            totsolvingtime=0),
-                        tickets=[])   
+                            totsolvingtime=0)],
+                        tickets={})
                     stats.general.append(newstats)
                     i = getElementIndex(stats.general, category=t)
                 for lang in ll:


[23/50] git commit: [#6068] fix paged_diffs return value when no DiffInfoDoc found

Posted by ac...@apache.org.
[#6068] fix paged_diffs return value when no DiffInfoDoc found


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/2dfbcfb2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/2dfbcfb2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/2dfbcfb2

Branch: refs/heads/acs2/5518
Commit: 2dfbcfb25a24f844c332f7e3643fe0df5dc60eb0
Parents: b08571f
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Mon Apr 8 13:17:26 2013 -0400
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Mon Apr 8 17:22:11 2013 +0000

----------------------------------------------------------------------
 Allura/allura/model/repo.py                      |    2 +-
 ForgeSVN/forgesvn/tests/model/test_repository.py |    6 +++++-
 2 files changed, 6 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/2dfbcfb2/Allura/allura/model/repo.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/repo.py b/Allura/allura/model/repo.py
index 4d396b8..d8b06be 100644
--- a/Allura/allura/model/repo.py
+++ b/Allura/allura/model/repo.py
@@ -270,7 +270,7 @@ class Commit(RepoObject):
     def paged_diffs(self, start=0, end=None):
         di = DiffInfoDoc.m.get(_id=self._id)
         if di is None:
-            return Object(added=[], removed=[], changed=[], copied=[])
+            return Object(added=[], removed=[], changed=[], copied=[], total=0)
         added = []
         removed = []
         changed = []

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/2dfbcfb2/ForgeSVN/forgesvn/tests/model/test_repository.py
----------------------------------------------------------------------
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index 676a887..09745e7 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -209,7 +209,11 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
         expected =  dict(
                 copied=[], changed=[], removed=[],
                 added=['/a/b', '/a/b/c'], total=4)
-        self.assertEqual(expected, entry.paged_diffs(start=1, end=3))
+        actual = entry.paged_diffs(start=1, end=3)
+        self.assertEqual(expected, actual)
+
+        empty = M.repo.Commit().paged_diffs()
+        self.assertEqual(sorted(actual.keys()), sorted(empty.keys()))
 
     def test_diff_create_file(self):
         entry = self.repo.log(1, limit=1)[0]


[03/50] git commit: [5453] Fixed bug in code to hide stats

Posted by ac...@apache.org.
[5453] Fixed bug in code to hide stats


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/0cf61cb1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/0cf61cb1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/0cf61cb1

Branch: refs/heads/acs2/5518
Commit: 0cf61cb1563c8eb3cfc353edcb9a58434f806ada
Parents: 9ba8e4a
Author: Stefano Invernizzi <st...@apache.org>
Authored: Sat Feb 23 12:06:17 2013 +0100
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:36 2013 +0000

----------------------------------------------------------------------
 .../forgeuserstats/controllers/userstats.py        |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0cf61cb1/ForgeUserStats/forgeuserstats/controllers/userstats.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/controllers/userstats.py b/ForgeUserStats/forgeuserstats/controllers/userstats.py
index 3944557..c77dded 100644
--- a/ForgeUserStats/forgeuserstats/controllers/userstats.py
+++ b/ForgeUserStats/forgeuserstats/controllers/userstats.py
@@ -173,6 +173,7 @@ class ForgeUserStatsMetricController(BaseController):
     def artifacts(self, **kw):
         if not self.user:
             return dict(user=None)
+        stats = self.user.stats
         if (not stats.visible) and (c.user != self.user):
             return dict(user=self.user)
 
@@ -185,6 +186,7 @@ class ForgeUserStatsMetricController(BaseController):
     def tickets(self, **kw):
         if not self.user: 
             return dict(user=None)
+        stats = self.user.stats
         if (not stats.visible) and (c.user != self.user):
             return dict(user=self.user)
 


[31/50] git commit: [#5465] ticket:310 Test for label autocompletion data provider

Posted by ac...@apache.org.
[#5465] ticket:310 Test for label autocompletion data provider


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/828b29fc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/828b29fc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/828b29fc

Branch: refs/heads/acs2/5518
Commit: 828b29fc85aff2757cd088c333bcbfff24950603
Parents: b970ea6
Author: Igor Bondarenko <je...@gmail.com>
Authored: Wed Apr 10 14:24:25 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Wed Apr 10 22:00:17 2013 +0000

----------------------------------------------------------------------
 .../forgetracker/tests/functional/test_root.py     |   17 +++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/828b29fc/ForgeTracker/forgetracker/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index b2fd554..917b064 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -1435,6 +1435,23 @@ class TestFunctionalController(TrackerTestController):
         assert_equal(r.request.path, '/p/test/dummy/1/')
         assert_in('I am comment', r)
 
+    def test_tags(self):
+        p = M.Project.query.get(shortname='test')
+        tracker = p.app_instance('bugs')
+        self.new_ticket(summary='a', labels='tag1,tag2')
+        self.new_ticket(summary='b', labels='tag2')
+        self.new_ticket(summary='c', labels='42cc,test')
+        r = self.app.get('/p/test/bugs/tags?term=t')
+        assert_equal(json.loads(r.body), ['tag2', 'tag1', 'test'])
+        r = self.app.get('/p/test/bugs/tags?term=ta')
+        assert_equal(json.loads(r.body), ['tag2', 'tag1'])
+        r = self.app.get('/p/test/bugs/tags?term=te')
+        assert_equal(json.loads(r.body), ['test'])
+        r = self.app.get('/p/test/bugs/tags?term=nope')
+        assert_equal(json.loads(r.body), [])
+        r = self.app.get('/p/test/bugs/tags?term=')
+        assert_equal(json.loads(r.body), [])
+
 
 class TestMilestoneAdmin(TrackerTestController):
     def _post(self, params, **kw):


[04/50] git commit: [5453] Improved code

Posted by ac...@apache.org.
[5453] Improved code


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/9ba8e4a1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/9ba8e4a1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/9ba8e4a1

Branch: refs/heads/acs2/5518
Commit: 9ba8e4a1de3da18e3edf998829bd647774ec7393
Parents: 21b3465
Author: Stefano Invernizzi <st...@apache.org>
Authored: Sat Feb 16 14:33:22 2013 +0100
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:36 2013 +0000

----------------------------------------------------------------------
 Allura/allura/templates/user_preferences.html      |    1 +
 .../forgeuserstats/templates/artifacts.html        |    2 +-
 .../forgeuserstats/templates/commits.html          |    2 +-
 ForgeUserStats/forgeuserstats/templates/index.html |    2 +-
 .../forgeuserstats/templates/tickets.html          |    2 +-
 5 files changed, 5 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9ba8e4a1/Allura/allura/templates/user_preferences.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/user_preferences.html b/Allura/allura/templates/user_preferences.html
index 8159f52..bd4c71e 100644
--- a/Allura/allura/templates/user_preferences.html
+++ b/Allura/allura/templates/user_preferences.html
@@ -133,6 +133,7 @@
     <a name="Statistics"></a>
     <div class="grid-20">
       <h2>Contribution statistics</h2>
+      <ul><li><a href="/userstats/{{c.user.username}}">Click here to check your personal statistics</a></li></ul>
       {{g.theme.statistics_form.display(user=c.user)}}
     </div>
   {% endif %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9ba8e4a1/ForgeUserStats/forgeuserstats/templates/artifacts.html
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/templates/artifacts.html b/ForgeUserStats/forgeuserstats/templates/artifacts.html
index d6a01d6..013c108 100644
--- a/ForgeUserStats/forgeuserstats/templates/artifacts.html
+++ b/ForgeUserStats/forgeuserstats/templates/artifacts.html
@@ -48,7 +48,7 @@
     </div>
     {% endif %}
   {% else %}
-    {% if not user.stats.visible %}
+    {% if user %}
       <h2>Statistics not available</h2>
       <div class="grid-20"> 
         This user has set his or her preferences so that personal statistics are not visible

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9ba8e4a1/ForgeUserStats/forgeuserstats/templates/commits.html
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/templates/commits.html b/ForgeUserStats/forgeuserstats/templates/commits.html
index cec0ab7..10d1c67 100644
--- a/ForgeUserStats/forgeuserstats/templates/commits.html
+++ b/ForgeUserStats/forgeuserstats/templates/commits.html
@@ -38,7 +38,7 @@
     </div>
     {% endif %}
   {% else %}
-    {% if not user.stats.visible %}
+    {% if user %}
       <h2>Statistics not available</h2>
       <div class="grid-20"> 
         This user has set his or her preferences so that personal statistics are not visible

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9ba8e4a1/ForgeUserStats/forgeuserstats/templates/index.html
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/templates/index.html b/ForgeUserStats/forgeuserstats/templates/index.html
index 4a8f504..653cd31 100644
--- a/ForgeUserStats/forgeuserstats/templates/index.html
+++ b/ForgeUserStats/forgeuserstats/templates/index.html
@@ -418,7 +418,7 @@
       </p>
     {% endif %}
   {% else %}
-    {% if not user.stats.visible %}
+    {% if user %}
       <h2>Statistics not available</h2>
       <div class="grid-20"> 
         This user has set his or her preferences so that personal statistics are not visible

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/9ba8e4a1/ForgeUserStats/forgeuserstats/templates/tickets.html
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/templates/tickets.html b/ForgeUserStats/forgeuserstats/templates/tickets.html
index 6ee66d4..a713b25 100644
--- a/ForgeUserStats/forgeuserstats/templates/tickets.html
+++ b/ForgeUserStats/forgeuserstats/templates/tickets.html
@@ -48,7 +48,7 @@
     </div>
     {% endif %}
   {% else %}
-    {% if not user.stats.visible %}
+    {% if user %}
       <h2>Statistics not available</h2>
       <div class="grid-20"> 
         This user has set his or her preferences so that personal statistics are not visible


[06/50] git commit: [#5453] Moving userstats into a tool

Posted by ac...@apache.org.
[#5453] Moving userstats into a tool


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/c99abb4f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/c99abb4f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/c99abb4f

Branch: refs/heads/acs2/5518
Commit: c99abb4f36d091fd4449acd8164be99927df3d64
Parents: 86799b5
Author: Stefano Invernizzi <st...@apache.org>
Authored: Wed Feb 27 23:47:24 2013 +0100
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:36 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py                  |   10 -
 Allura/allura/controllers/root.py                  |    4 +-
 .../ext/user_profile/templates/user_index.html     |    4 +-
 Allura/allura/ext/user_profile/user_main.py        |    9 +-
 Allura/allura/lib/app_globals.py                   |    2 +-
 Allura/allura/lib/plugin.py                        |    8 -
 Allura/allura/lib/widgets/forms.py                 |   15 -
 Allura/allura/model/project.py                     |    2 +
 Allura/allura/nf/allura/css/allura.css             |   13 +
 Allura/allura/templates/user_preferences.html      |    9 -
 .../forgeuserstats/controllers/userstats.py        |  235 +++++++++------
 ForgeUserStats/forgeuserstats/main.py              |   90 +++++-
 .../forgeuserstats/templates/artifacts.html        |    2 +-
 .../forgeuserstats/templates/commits.html          |    2 +-
 ForgeUserStats/forgeuserstats/templates/index.html |   32 +-
 .../forgeuserstats/templates/settings.html         |   19 ++
 .../forgeuserstats/templates/tickets.html          |    2 +-
 ForgeUserStats/forgeuserstats/widgets/forms.py     |   22 ++
 ForgeUserStats/setup.py                            |    6 +-
 19 files changed, 311 insertions(+), 175 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 1118d86..1b9c74e 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -58,7 +58,6 @@ class F(object):
     remove_inactive_period_form = forms.RemoveInactivePeriodForm()
     save_skill_form = forms.AddUserSkillForm()
     remove_skill_form = forms.RemoveSkillForm()
-    set_statistics = forms.StatsPreferencesForm()
 
 class AuthController(BaseController):
 
@@ -727,15 +726,6 @@ class SubscriptionsController(BaseController):
     @h.vardec
     @expose()
     @require_post()
-    @validate(F.set_statistics, error_handler=index)
-    def set_statistics(self, **kw):
-        require_authenticated()
-        c.user.stats.visible = kw.get('visible', True)
-        flash('Your preferences about statistics were successfully updated!')
-        redirect('.#Statistics')
-
-    @expose()
-    @require_post()
     def upload_sshkey(self, key=None):
         ap = plugin.AuthenticationProvider.get(request)
         try:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/Allura/allura/controllers/root.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/root.py b/Allura/allura/controllers/root.py
index d23891c..c56e373 100644
--- a/Allura/allura/controllers/root.py
+++ b/Allura/allura/controllers/root.py
@@ -69,9 +69,7 @@ class RootController(WsgiDispatchController):
         if n and not n.url_prefix.startswith('//'):
             n.bind_controller(self)
         self.browse = ProjectBrowseController()
-        ep = g.entry_points["stats"].get('userstats')
-        if ep and g.show_userstats:
-            self.userstats = ep().root
+
         super(RootController, self).__init__()
 
     def _setup_request(self):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/Allura/allura/ext/user_profile/templates/user_index.html
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/templates/user_index.html b/Allura/allura/ext/user_profile/templates/user_index.html
index 7371eb6..2b17b79 100644
--- a/Allura/allura/ext/user_profile/templates/user_index.html
+++ b/Allura/allura/ext/user_profile/templates/user_index.html
@@ -236,11 +236,11 @@
     </div>
   </div>
 
-  {% if statslinkurl %}
+  {% if user.stats.visible %}
     <div class="grid-24">
       <div class="grid-24" style="margin:0;"><b>User statistics</b></div>
       <div class="grid-24" style="margin-top:5px;margin-bottom:5px;">
-        <div><a href="{{statslinkurl}}"/>{{statslinkdescription}}</a></div>
+        <div><a href="{{c.project.url()}}userstats"/>Go to the personal statistics of this user</a></div>
       </div>
     </div>
   {% endif %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/Allura/allura/ext/user_profile/user_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/user_main.py b/Allura/allura/ext/user_profile/user_main.py
index f3c3331..7754228 100644
--- a/Allura/allura/ext/user_profile/user_main.py
+++ b/Allura/allura/ext/user_profile/user_main.py
@@ -64,14 +64,7 @@ class UserProfileController(BaseController):
         user = c.project.user_project_of
         if not user:
             raise exc.HTTPNotFound()
-        if g.show_userstats and user.stats.visible:
-            from forgeuserstats.main import ForgeUserStatsApp
-            link, description = ForgeUserStatsApp.createlink(user)
-        else:
-            link, description = None, None
-        return dict(user=user,
-                    statslinkurl = link,
-                    statslinkdescription = description)
+        return dict(user=user)
     # This will be fully implemented in a future iteration
     # @expose('jinja:allura.ext.user_profile:templates/user_subscriptions.html')
     # def subscriptions(self):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/Allura/allura/lib/app_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py
index 632a29f..ee2c9b9 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -177,7 +177,7 @@ class Globals(object):
         statslisteners = []
         for name, ep in self.entry_points['stats'].iteritems():
             if config.get('%s.enable' % name,'false')=='true':
-                statslisteners.append(ep().listener)
+                statslisteners.append(ep())
         self.statsUpdater = PostEvent(statslisteners)
 
     @LazyProperty

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 59f03e5..ed704d4 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -736,14 +736,6 @@ class ThemeProvider(object):
         return RemoveInactivePeriodForm()
 
     @LazyProperty
-    def statistics_form(self):
-        '''
-        :return: None, or an easywidgets Form to render on the user preferences page
-        '''
-        from allura.lib.widgets.forms import StatsPreferencesForm
-        return StatsPreferencesForm(action='/auth/prefs/set_statistics')
-
-    @LazyProperty
     def add_trove_category(self):
         '''
         :return: None, or an easywidgets Form to render on the page to create a

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/Allura/allura/lib/widgets/forms.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/forms.py b/Allura/allura/lib/widgets/forms.py
index c1a1d75..96f832d 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -452,21 +452,6 @@ class RemoveTimeSlotForm(ForgeForm):
         return d
 
 
-class StatsPreferencesForm(ForgeForm):
-    defaults=dict(ForgeForm.defaults)
-
-    class fields(ew_core.NameList):
-        visible = ew.Checkbox(
-            label='Make my personal statistics visible to other users.')
-            
-    def display(self, **kw):
-        if kw.get('user').stats.visible:
-            self.fields['visible'].attrs = {'checked':'true'}      
-        else:
-            self.fields['visible'].attrs = {}    
-        return super(ForgeForm, self).display(**kw)
-                
-
 class RemoveTroveCategoryForm(ForgeForm):
     defaults=dict(ForgeForm.defaults, submit_text=None, show_errors=False)
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/Allura/allura/model/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 39509ff..0f46a11 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -715,6 +715,8 @@ class Project(MappedClass, ActivityNode, ActivityObject):
                 apps += [('Wiki', 'wiki', 'Wiki'),
                         ('profile', 'profile', 'Profile'),
                        ]
+                if g.show_userstats:
+                    apps = apps + [('userstats', 'userstats', 'Statistics')]
             apps += [
                 ('admin', 'admin', 'Admin'),
                 ('search', 'search', 'Search'),

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/Allura/allura/nf/allura/css/allura.css
----------------------------------------------------------------------
diff --git a/Allura/allura/nf/allura/css/allura.css b/Allura/allura/nf/allura/css/allura.css
index 1f32750..f3863b8 100644
--- a/Allura/allura/nf/allura/css/allura.css
+++ b/Allura/allura/nf/allura/css/allura.css
@@ -60,6 +60,11 @@ b.ico.ico-vote-down { background-image: url('../images/vote_down.png'); }
   background-repeat: no-repeat;
 }
 
+.ui-icon-tool-userstats {
+  background-image: url("../images/stats_24.png");
+  background-repeat: no-repeat;
+}
+
 .ui-icon-tool-admin, .ui-icon-admin {
   background-image: url("../images/admin_24.png");
   background-repeat: no-repeat;
@@ -118,6 +123,10 @@ b.ico.ico-vote-down { background-image: url('../images/vote_down.png'); }
 #top_nav .ui-icon-tool-stats {
   background-image: url("../images/stats_32.png");
 }
+#top_nav .ui-icon-tool-userstats {
+  background-image: url("../images/stats_32.png");
+}
+
 #top_nav .ui-icon-tool-admin, #top_nav .ui-icon-admin {
   background-image: url("../images/admin_32.png");
 }
@@ -152,6 +161,10 @@ b.ico.ico-vote-down { background-image: url('../images/vote_down.png'); }
 .big_icon.ui-icon-tool-stats {
   background-image: url("../images/stats_48.png");
 }
+.big_icon.ui-icon-tool-userstats {
+  background-image: url("../images/stats_48.png");
+}
+
 .big_icon.ui-icon-tool-admin, .big_icon.ui-icon-admin {
   background-image: url("../images/admin_48.png");
 }

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/Allura/allura/templates/user_preferences.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/user_preferences.html b/Allura/allura/templates/user_preferences.html
index bd4c71e..768cd2e 100644
--- a/Allura/allura/templates/user_preferences.html
+++ b/Allura/allura/templates/user_preferences.html
@@ -129,15 +129,6 @@
     <ul><li><a href="/auth/prefs/user_skills">Click here to check and change your skills list</a></li></ul>
   </div>
 
-  {% if g.show_userstats %}
-    <a name="Statistics"></a>
-    <div class="grid-20">
-      <h2>Contribution statistics</h2>
-      <ul><li><a href="/userstats/{{c.user.username}}">Click here to check your personal statistics</a></li></ul>
-      {{g.theme.statistics_form.display(user=c.user)}}
-    </div>
-  {% endif %}
-
   {% if g.theme.password_change_form %}
   <div class="grid-20">
     <h2>Change Password</h2>

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/ForgeUserStats/forgeuserstats/controllers/userstats.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/controllers/userstats.py b/ForgeUserStats/forgeuserstats/controllers/userstats.py
index 40ad92c..b93e77b 100644
--- a/ForgeUserStats/forgeuserstats/controllers/userstats.py
+++ b/ForgeUserStats/forgeuserstats/controllers/userstats.py
@@ -1,4 +1,4 @@
-from tg import expose
+from tg import expose, validate, redirect
 from tg.decorators import with_trailing_slash
 from datetime import datetime
 from allura.controllers import BaseController
@@ -6,33 +6,86 @@ import allura.model as M
 from allura.lib.graphics.graphic_methods import create_histogram, create_progress_bar
 from forgeuserstats.model.stats import UserStats
 from pylons import tmpl_context as c
+from allura.lib.security import require_access
+from forgeuserstats.widgets.forms import StatsPreferencesForm
+from allura.lib.decorators import require_post
+from allura.lib import validators as V
 
-class ForgeUserStatsController(BaseController):
+stats_preferences_form = StatsPreferencesForm()
+
+class ForgeUserStatsCatController(BaseController):
 
     @expose()
-    def _lookup(self, part, *remainder):
-        user = M.User.query.get(username=part)
+    def _lookup(self, category, *remainder):
+        cat = M.TroveCategory.query.get(shortname=category)
+        return ForgeUserStatsCatController(category = cat), remainder
 
-        if not self.user:
-            return ForgeUserStatsController(user=user), remainder
-        if part == "category":
-            return ForgeUserStatsCatController(self.user, None), remainder
-        if part == "metric":
-            return ForgeUserStatsMetricController(self.user), remainder
+    def __init__(self, category = None):
+        self.category = category
+        super(ForgeUserStatsCatController, self).__init__()
 
-    def __init__(self, user=None):
-        self.user = user
-        if self.user:
-            if not user.stats:
-                UserStats.create(self.user)
+    @expose('jinja:forgeuserstats:templates/index.html')
+    @with_trailing_slash
+    def index(self, **kw):
+        self.user = c.project.user_project_of
+        if not self.user: 
+            return None
+        stats = self.user.stats
+        if (not stats.visible) and (c.user != self.user):
+            return dict(user=self.user)
+        
+        cat_id = None
+        if self.category: 
+            cat_id = self.category._id
+        ret_dict = _getDataForCategory(cat_id, stats)
+        ret_dict['user'] = self.user
+        ret_dict['registration_date'] = stats.registration_date
+        ret_dict['category'] = self.category
+        return ret_dict
 
-        super(ForgeUserStatsController, self).__init__()
+class ForgeUserStatsController(BaseController):
+
+    category = ForgeUserStatsCatController()            
+    
+    @expose('jinja:forgeuserstats:templates/settings.html')
+    @with_trailing_slash
+    def settings(self, **kw):
+        require_access(c.project, 'admin')
+
+        self.user = c.project.user_project_of
+        if not self.user: 
+            return dict(user=None)
+        if not self.user.stats:
+            UserStats.create(self.user)
+        return dict(
+            user = self.user, 
+            form = StatsPreferencesForm(
+                action = c.project.url() + 'userstats/change_settings'))
+      
+    @expose()
+    @require_post()
+    @validate(stats_preferences_form, error_handler=settings)
+    def change_settings(self, **kw):
+        require_access(c.project, 'admin')
+
+        self.user = c.project.user_project_of
+        if not self.user: 
+            return dict(user=None)
+        if not self.user.stats:
+            UserStats.create(self.user)
+        visible = kw.get('visible')
+        self.user.stats.visible = visible
+        redirect(c.project.url() + 'userstats/settings')
 
     @expose('jinja:forgeuserstats:templates/index.html')
     @with_trailing_slash
     def index(self, **kw):
+        self.user = c.project.user_project_of
         if not self.user: 
             return dict(user=None)
+        if not self.user.stats:
+            UserStats.create(self.user)
+
         stats = self.user.stats
         if (not stats.visible) and (c.user != self.user):
             return dict(user=self.user)
@@ -79,11 +132,71 @@ class ForgeUserStatsController(BaseController):
             stats.getMaxAndAverageDiscussionContribution()
         ret_dict['maxticketcontrib'], ret_dict['averageticketcontrib'] =\
             stats.getMaxAndAverageTicketsSolvingPercentage()
-
+        
         return ret_dict
 
+
+    @expose('jinja:forgeuserstats:templates/commits.html')
+    @with_trailing_slash
+    def commits(self, **kw):
+        self.user = c.project.user_project_of
+        if not self.user: 
+            return dict(user=None)
+        if not self.user.stats:
+            UserStats.create(self.user)
+        stats = self.user.stats
+
+        if (not stats.visible) and (c.user != self.user):
+            return dict(user=self.user)
+        
+        commits = stats.getCommitsByCategory()
+        return dict(
+            user = self.user,
+            data = commits) 
+
+    @expose('jinja:forgeuserstats:templates/artifacts.html')
+    @with_trailing_slash
+    def artifacts(self, **kw):
+        self.user = c.project.user_project_of
+        if not self.user: 
+            return dict(user=None)
+        if not self.user.stats:
+            UserStats.create(self.user)
+        stats = self.user.stats
+
+        if (not stats.visible) and (c.user != self.user):
+            return dict(user=self.user)
+
+        stats = self.user.stats       
+        artifacts = stats.getArtifactsByCategory(detailed=True)
+        return dict(
+            user = self.user,
+            data = artifacts)
+
+    @expose('jinja:forgeuserstats:templates/tickets.html')
+    @with_trailing_slash
+    def tickets(self, **kw):
+        self.user = c.project.user_project_of
+        if not self.user: 
+            return dict(user=None)
+        if not self.user.stats:
+            UserStats.create(self.user)
+        stats = self.user.stats
+
+        if (not stats.visible) and (c.user != self.user):
+            return dict(user=self.user)
+
+        artifacts = self.user.stats.getTicketsByCategory()
+        return dict(
+            user=self.user,
+            data=artifacts)
+
     @expose()
     def categories_graph(self):
+        self.user = c.project.user_project_of
+        if not self.user: 
+            return None
+
         categories = {}
         for p in self.user.my_projects():
             for cat in p.trove_topic:
@@ -109,89 +222,27 @@ class ForgeUserStatsController(BaseController):
 
     @expose()
     def code_ranking_bar(self):
-        return create_progress_bar(self.user.stats.codeRanking())
+        self.user = c.project.user_project_of
+        if not self.user: 
+            return None
+        stats = self.user.stats
+        return create_progress_bar(stats.codeRanking())
 
     @expose()
     def discussion_ranking_bar(self):
-        return create_progress_bar(self.user.stats.discussionRanking())
+        self.user = c.project.user_project_of
+        if not self.user: 
+            return None
+        stats = self.user.stats
+        return create_progress_bar(stats.discussionRanking())
 
     @expose()
     def tickets_ranking_bar(self):
-        return create_progress_bar(self.user.stats.ticketsRanking())
-
-class ForgeUserStatsCatController(BaseController):
-    @expose()
-    def _lookup(self, category, *remainder):
-        cat = M.TroveCategory.query.get(shortname=category)
-        return ForgeUserStatsCatController(self.user, cat), remainder
-
-    def __init__(self, user, category):
-        self.user = user
-        self.category = category
-        super(ForgeUserStatsCatController, self).__init__()
-
-    @expose('jinja:forgeuserstats:templates/index.html')
-    @with_trailing_slash
-    def index(self, **kw):
-        if not self.user:
-            return dict(user=None)
-        stats = self.user.stats
-        if (not stats.visible) and (c.user != self.user):
-            return dict(user=self.user)
-        
-        cat_id = None
-        if self.category: 
-            cat_id = self.category._id
-        ret_dict = _getDataForCategory(cat_id, stats)
-        ret_dict['user'] = self.user
-        ret_dict['registration_date'] = stats.registration_date
-        ret_dict['category'] = self.category
-        
-        return ret_dict
-
-class ForgeUserStatsMetricController(BaseController):
-
-    def __init__(self, user):
-        self.user = user
-        super(ForgeUserStatsMetricController, self).__init__()
-
-    @expose('jinja:forgeuserstats:templates/commits.html')
-    @with_trailing_slash
-    def commits(self, **kw):
-        if not self.user:
-            return dict(user=None)
-        stats = self.user.stats
-        if (not stats.visible) and (c.user != self.user):
-            return dict(user=self.user)
-        
-        commits = stats.getCommitsByCategory()
-        return dict(user = self.user,
-                    data = commits) 
-
-    @expose('jinja:forgeuserstats:templates/artifacts.html')
-    @with_trailing_slash
-    def artifacts(self, **kw):
-        if not self.user:
-            return dict(user=None)
-        stats = self.user.stats
-        if (not stats.visible) and (c.user != self.user):
-            return dict(user=self.user)
-
-        stats = self.user.stats       
-        artifacts = stats.getArtifactsByCategory(detailed=True)
-        return dict(user = self.user, data = artifacts) 
-
-    @expose('jinja:forgeuserstats:templates/tickets.html')
-    @with_trailing_slash
-    def tickets(self, **kw):
+        self.user = c.project.user_project_of
         if not self.user: 
-            return dict(user=None)
+            return None
         stats = self.user.stats
-        if (not stats.visible) and (c.user != self.user):
-            return dict(user=self.user)
-
-        artifacts = self.user.stats.getTicketsByCategory()
-        return dict(user = self.user, data = artifacts) 
+        return create_progress_bar(stats.ticketsRanking())
 
 def _getDataForCategory(category, stats):
     totcommits = stats.getCommits(category)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/ForgeUserStats/forgeuserstats/main.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/main.py b/ForgeUserStats/forgeuserstats/main.py
index 8eeb113..dcecdb9 100644
--- a/ForgeUserStats/forgeuserstats/main.py
+++ b/ForgeUserStats/forgeuserstats/main.py
@@ -1,10 +1,24 @@
+#-*- python -*-
 import logging
+from pylons import tmpl_context as c
+import formencode
+from formencode import validators
+from webob import exc
 from datetime import datetime
 
+from allura.app import Application, SitemapEntry
+from allura.lib import helpers as h
+from allura.lib.security import has_access
+from allura import model as M
 from allura.eventslistener import EventsListener
 from model.stats import UserStats
 from controllers.userstats import ForgeUserStatsController
 
+from forgeuserstats import version
+from forgeuserstats.controllers.userstats import ForgeUserStatsController
+
+from ming.orm import session
+
 log = logging.getLogger(__name__)
 
 class UserStatsListener(EventsListener):
@@ -55,12 +69,74 @@ class UserStatsListener(EventsListener):
     def newOrganization(self, organization):
         pass
 
-class ForgeUserStatsApp:
+class ForgeUserStatsApp(Application):
+    __version__ = version.__version__
+    tool_label='Statistics'
+    default_mount_label='Statistics'
+    default_mount_point='stats'
+    permissions = ['configure', 'read', 'write',
+                    'unmoderated_post', 'post', 'moderate', 'admin']
+    ordinal=15
+    installable=False
+    config_options = Application.config_options
+    default_external_feeds = []
+    icons={
+        24:'images/stats_24.png',
+        32:'images/stats_32.png',
+        48:'images/stats_48.png'
+    }
     root = ForgeUserStatsController()
-    listener = UserStatsListener()
 
-    @classmethod
-    def createlink(cls, user):
-        return (
-            "/userstats/%s/" % user.username, 
-            "%s personal statistcs" % user.display_name)
+    def __init__(self, project, config):
+        Application.__init__(self, project, config)
+        role_admin = M.ProjectRole.by_name('Admin')._id
+        role_anon = M.ProjectRole.by_name('*anonymous')._id
+        self.config.acl = [
+            M.ACE.allow(role_anon, 'read'),
+            M.ACE.allow(role_admin, 'admin')]
+
+    def main_menu(self):
+        return [SitemapEntry(self.config.options.mount_label.title(), '.')]
+
+    @property
+    @h.exceptionless([], log)
+    def sitemap(self):
+        menu_id = self.config.options.mount_label.title()
+        with h.push_config(c, app=self):
+            return [
+                SitemapEntry(menu_id, '.')[self.sidebar_menu()] ]
+
+    @property
+    def show_discussion(self):
+        if 'show_discussion' in self.config.options:
+            return self.config.options['show_discussion']
+        else:
+            return True
+
+    @h.exceptionless([], log)
+    def sidebar_menu(self):
+        base = c.app.url
+        links = [SitemapEntry('Overview', base),
+                 SitemapEntry('Commits', base + 'commits'),
+                 SitemapEntry('Artifacts', base + 'artifacts'),
+                 SitemapEntry('Tickets', base + 'tickets')]
+        return links
+
+    def admin_menu(self):
+        links = [SitemapEntry(
+                     'Settings', c.project.url() + 'userstats/settings')]
+        return links
+
+    def install(self, project):
+        #It doesn't make any sense to install the tool twice on the same 
+        #project therefore, if it already exists, it doesn't install it
+        #a second time.
+        for tool in project.app_configs:
+            if tool.tool_name == 'userstats':
+                if self.config.options.mount_point!=tool.options.mount_point:
+                    project.uninstall_app(self.config.options.mount_point)
+                    return
+
+    def uninstall(self, project):
+        self.config.delete()
+        session(self.config).flush()

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/ForgeUserStats/forgeuserstats/templates/artifacts.html
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/templates/artifacts.html b/ForgeUserStats/forgeuserstats/templates/artifacts.html
index 013c108..ede6dde 100644
--- a/ForgeUserStats/forgeuserstats/templates/artifacts.html
+++ b/ForgeUserStats/forgeuserstats/templates/artifacts.html
@@ -11,7 +11,7 @@
 
   {% if user and (user.stats.visible or (c.user == user)) %}
     <div class="grid-20">
-      <ul><li><a href="/userstats/{{user.username}}">Go back to general statistics</a></li></ul>
+      <ul><li><a href="{{c.project.url()}}userstats">Go back to general statistics</a></li></ul>
     </div>
 
     {% if data %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/ForgeUserStats/forgeuserstats/templates/commits.html
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/templates/commits.html b/ForgeUserStats/forgeuserstats/templates/commits.html
index 10d1c67..f0aca6f 100644
--- a/ForgeUserStats/forgeuserstats/templates/commits.html
+++ b/ForgeUserStats/forgeuserstats/templates/commits.html
@@ -11,7 +11,7 @@
 
   {% if user and (user.stats.visible or (c.user == user)) %}
     <div class="grid-20">
-      <ul><li><a href="/userstats/{{user.username}}">Go back to general statistics</a></li></ul>
+      <ul><li><a href="{{c.project.url()}}userstats">Go back to general statistics</a></li></ul>
     </div>
 
     {% if data %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/ForgeUserStats/forgeuserstats/templates/index.html
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/templates/index.html b/ForgeUserStats/forgeuserstats/templates/index.html
index 653cd31..ae58cf8 100644
--- a/ForgeUserStats/forgeuserstats/templates/index.html
+++ b/ForgeUserStats/forgeuserstats/templates/index.html
@@ -15,7 +15,7 @@
 
     {% if category %}
        <ul>
-         <li><a href="/userstats/{{user.username}}">Go back to general statistics</a></li>
+         <li><a href="{{c.project.url()}}userstats">Go back to general statistics</a></li>
        </ul>
     {% endif %}
     <h2>General statistics</h2>
@@ -80,7 +80,7 @@
         <tr>
           <td>
             {% if totcommits.number > 0 %}
-              <a href="/userstats/{{user.username}}/metric/commits/">Commits number</a>
+              <a href="{{c.project.url()}}userstats/commits/">Commits number</a>
             {% else %}
               Commits number
             {% endif %}
@@ -103,7 +103,7 @@
         <tr>
           <td>
             {% if totcommits.lines > 0 %}
-              <a href="/userstats/{{user.username}}/metric/commits/">Added/modified LOCs</a>
+              <a href="{{c.project.url()}}userstats/commits/">Added/modified LOCs</a>
             {% else %}
               Added/modified LOCs
             {% endif %}
@@ -126,7 +126,7 @@
         <tr>
           <td>
             {% if totartifacts.created > 0 %}
-              <a href="/userstats/{{user.username}}/metric/artifacts/">Total number of created artifacts</a>
+              <a href="{{c.project.url()}}userstats/artifacts/">Total number of created artifacts</a>
             {% else %}
               Total number of created artifacts
             {% endif %}
@@ -149,7 +149,7 @@
         <tr>
           <td>
             {% if totartifacts.modified > 0 %}
-              <a href="/userstats/{{user.username}}/metric/artifacts/">Total number of edited artifacts</a>
+              <a href="{{c.project.url()}}userstats/artifacts/">Total number of edited artifacts</a>
             {% else %}
               Total number of edited artifacts
             {% endif %}
@@ -174,7 +174,7 @@
           <tr>
             <td>
               {% if value.created > 0 %}
-                <a href="/userstats/{{user.username}}/metric/artifacts/">Created {{key}} artifacts</a>
+                <a href="{{c.project.url()}}userstats/artifacts/">Created {{key}} artifacts</a>
               {% else %}
                 Created {{key}} artifacts
               {% endif %}
@@ -205,7 +205,7 @@
           <tr>
             <td>
               {% if value.modified > 0 %}
-                <a href="/userstats/{{user.username}}/metric/artifacts/">Edited {{key}} artifacts</a>
+                <a href="{{c.project.url()}}userstats/artifacts/">Edited {{key}} artifacts</a>
               {% else %}
                 Edited {{key}} artifacts
               {% endif %}
@@ -238,7 +238,7 @@
         <tr>
           <td>
             {% if tottickets.assigned > 0 %}
-              <a href="/userstats/{{user.username}}/metric/tickets/">Assigned tickets</a>
+              <a href="{{c.project.url()}}userstats/tickets/">Assigned tickets</a>
             {% else %}
               Assigned tickets
             {% endif %}
@@ -261,7 +261,7 @@
         <tr>
           <td>
             {% if tottickets.revoked > 0 %}
-              <a href="/userstats/{{user.username}}/metric/tickets/">Revoked tickets</a>
+              <a href="{{c.project.url()}}userstats/tickets/">Revoked tickets</a>
             {% else %}
               Revoked tickets
             {% endif %}
@@ -284,7 +284,7 @@
         <tr>
           <td>
             {% if tottickets.solved > 0 %}
-              <a href="/userstats/{{user.username}}/metric/tickets/">Solved tickets</a>
+              <a href="{{c.project.url()}}userstats/tickets/">Solved tickets</a>
             {% else %}
               Solved tickets
             {% endif %}
@@ -307,7 +307,7 @@
         <tr>
           <td>
             {% if tottickets.averagesolvingtime > 0 %}
-              <a href="/userstats/{{user.username}}/metric/tickets/">Average tickets solving time</a>
+              <a href="{{c.project.url()}}userstats/tickets/">Average tickets solving time</a>
             {% else %}
               Average tickets solving time
             {% endif %}
@@ -357,7 +357,7 @@
           <tbody>
             {% for cat, count in categories %}
               <tr>
-                <td><a href="/userstats/{{user.username}}/category/{{cat.shortname}}">{{cat.fullname}}</a></td>
+                <td><a href="{{c.project.url()}}userstats/category/{{cat.shortname}}">{{cat.fullname}}</a></td>
                 <td>{{count}}</td>
               </tr>
             {% endfor %}
@@ -369,7 +369,7 @@
             The same data listed in the previous table is graphically presented by the following histogram.
           </p>
           <p>
-            <img src="/userstats/{{user.username}}/categories_graph"/>
+            <img src="{{c.project.url()}}userstats/categories_graph"/>
           </p>
         {% endif %}
     {% endif %}
@@ -391,21 +391,21 @@
             <td>{{codecontribution}} LOC{% if codecontribution != 1 %}s{% endif %}/month</td>
             <td>{{averagecodecontrib}} LOC{% if averagecodecontrib != 1 %}s{% endif %}/month</td>
             <td>{{maxcodecontrib}} LOC{% if maxcodecontrib != 1 %}s{% endif %}/month</td>
-            <td><img src="/userstats/{{user.username}}/code_ranking_bar"/> {{codepercentage}} %</td>
+            <td><img src="{{c.project.url()}}userstats/code_ranking_bar"/> {{codepercentage}} %</td>
           </tr>
           <tr>
             <td>Discussion</td>
             <td>{{discussioncontribution}} contr./month</td>
             <td>{{averagedisccontrib}} contr./month</td>
             <td>{{maxdisccontrib}} contr./month</td>
-            <td><img src="/userstats/{{user.username}}/discussion_ranking_bar"/> {{discussionpercentage}} %</td>
+            <td><img src="{{c.project.url()}}userstats/discussion_ranking_bar"/> {{discussionpercentage}} %</td>
           </tr>
           <tr>
             <td>Solved issues</td>
             <td>{{ticketcontribution}} %</td>
             <td>{{averageticketcontrib}} %</td>
             <td>{{maxticketcontrib}} %</td>
-            <td><img src="/userstats/{{user.username}}/tickets_ranking_bar"/> {{ticketspercentage}} %</td>
+            <td><img src="{{c.project.url()}}userstats/tickets_ranking_bar"/> {{ticketspercentage}} %</td>
           </tr>
         </tbody>
       </table>

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/ForgeUserStats/forgeuserstats/templates/settings.html
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/templates/settings.html b/ForgeUserStats/forgeuserstats/templates/settings.html
new file mode 100644
index 0000000..c07301a
--- /dev/null
+++ b/ForgeUserStats/forgeuserstats/templates/settings.html
@@ -0,0 +1,19 @@
+{% set hide_left_bar = True %}
+{% extends g.theme.master %}
+
+{% block title %}User stats – Settings{% endblock %}
+
+{% block header %}
+    Statistics about {{user.display_name}}'s contribution – Settings
+{% endblock %}
+
+{% block content %}
+
+    <div class="grid-20">
+      In this page you can set the visibility of your personal statistics. If you decide to hide your personal statistics to 
+      other users, data collected about your contributions to projects hosted on this forge will be available only for your
+      personal use. 
+      {{form.display(user = user)}}
+    </div>
+
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/ForgeUserStats/forgeuserstats/templates/tickets.html
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/templates/tickets.html b/ForgeUserStats/forgeuserstats/templates/tickets.html
index a713b25..0252021 100644
--- a/ForgeUserStats/forgeuserstats/templates/tickets.html
+++ b/ForgeUserStats/forgeuserstats/templates/tickets.html
@@ -11,7 +11,7 @@
 
   {% if user and (user.stats.visible or (c.user == user)) %}
     <div class="grid-20">
-      <ul><li><a href="/userstats/{{user.username}}">Go back to general statistics</a></li></ul>
+      <ul><li><a href="{{c.project.url()}}userstats">Go back to general statistics</a></li></ul>
     </div>
 
     {% if data %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/ForgeUserStats/forgeuserstats/widgets/__init__.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/widgets/__init__.py b/ForgeUserStats/forgeuserstats/widgets/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/ForgeUserStats/forgeuserstats/widgets/forms.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/widgets/forms.py b/ForgeUserStats/forgeuserstats/widgets/forms.py
new file mode 100644
index 0000000..c4da4fb
--- /dev/null
+++ b/ForgeUserStats/forgeuserstats/widgets/forms.py
@@ -0,0 +1,22 @@
+from allura.lib import validators as V
+from allura.lib.widgets.forms import ForgeForm
+
+from formencode import validators as fev
+
+import ew as ew_core
+import ew.jinja2_ew as ew
+
+class StatsPreferencesForm(ForgeForm):
+    defaults=dict(ForgeForm.defaults)
+
+    class fields(ew_core.NameList):
+        visible = ew.Checkbox(
+            label='Make my personal statistics visible to other users.')
+            
+    def display(self, **kw):
+        if kw.get('user').stats.visible:
+            self.fields['visible'].attrs = {'checked':'true'}      
+        else:
+            self.fields['visible'].attrs = {}    
+        return super(ForgeForm, self).display(**kw)
+

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c99abb4f/ForgeUserStats/setup.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/setup.py b/ForgeUserStats/setup.py
index dc2f07b..733ebd8 100644
--- a/ForgeUserStats/setup.py
+++ b/ForgeUserStats/setup.py
@@ -23,7 +23,11 @@ setup(name='ForgeUserStats',
       ],
       entry_points="""
       # -*- Entry points: -*-
-      [allura.stats]
+      [allura]
       userstats=forgeuserstats.main:ForgeUserStatsApp
+
+      [allura.stats]
+      userstats=forgeuserstats.main:UserStatsListener
+
       """,
       )


[25/50] git commit: [#2643] update test for longer time window

Posted by ac...@apache.org.
[#2643] update test for longer time window


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/fa5d7e03
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/fa5d7e03
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/fa5d7e03

Branch: refs/heads/acs2/5518
Commit: fa5d7e03e3baa587129ec4f49738d598c9861a76
Parents: 7041d1a
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Tue Apr 9 11:15:45 2013 -0400
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Apr 9 11:15:45 2013 -0400

----------------------------------------------------------------------
 Allura/allura/tests/test_utils.py |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/fa5d7e03/Allura/allura/tests/test_utils.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_utils.py b/Allura/allura/tests/test_utils.py
index 2095179..c047028 100644
--- a/Allura/allura/tests/test_utils.py
+++ b/Allura/allura/tests/test_utils.py
@@ -77,7 +77,7 @@ class TestAntispam(unittest.TestCase):
         self.assertRaises(
             ValueError,
             utils.AntiSpam.validate_request,
-            r, now=time.time()+60*60+1)
+            r, now=time.time()+24*60*60+1)
 
     def test_invalid_future(self):
         form = dict(a='1', b='2')


[05/50] git commit: [#5453] Setting userstats tool as anchored for user projects

Posted by ac...@apache.org.
[#5453] Setting userstats tool as anchored for user projects


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/d2503902
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/d2503902
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/d2503902

Branch: refs/heads/acs2/5518
Commit: d2503902c8b346bc92f726c3ac7e24287778995f
Parents: c99abb4
Author: Stefano Invernizzi <st...@apache.org>
Authored: Sun Mar 3 10:30:05 2013 +0100
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:36 2013 +0000

----------------------------------------------------------------------
 Allura/allura/lib/app_globals.py    |    4 +---
 Allura/allura/model/auth.py         |    6 ++++--
 Allura/allura/model/project.py      |    2 --
 Allura/allura/websetup/bootstrap.py |    1 +
 Allura/development.ini              |    6 ------
 ForgeUserStats/test.ini             |    1 -
 6 files changed, 6 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/d2503902/Allura/allura/lib/app_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py
index ee2c9b9..1ab9b31 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -172,12 +172,10 @@ class Globals(object):
         # Zarkov logger
         self._zarkov = None
 
-        self.show_userstats = config.get('userstats.enable','false')=='true'
         # Set listeners to update stats
         statslisteners = []
         for name, ep in self.entry_points['stats'].iteritems():
-            if config.get('%s.enable' % name,'false')=='true':
-                statslisteners.append(ep())
+            statslisteners.append(ep())
         self.statsUpdater = PostEvent(statslisteners)
 
     @LazyProperty

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/d2503902/Allura/allura/model/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index b8240b9..a6904f2 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -342,9 +342,11 @@ class User(MappedClass, ActivityNode, ActivityObject):
 
     @property
     def stats(self):
-        if g.show_userstats:
+        if 'userstats' in g.entry_points['stats']:
             from forgeuserstats.model.stats import UserStats
-            return UserStats.query.get(_id=self.stats_id)
+            if self.stats_id:
+                return UserStats.query.get(_id=self.stats_id)
+            return UserStats.create(self)
         else: 
             return None
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/d2503902/Allura/allura/model/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 0f46a11..39509ff 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -715,8 +715,6 @@ class Project(MappedClass, ActivityNode, ActivityObject):
                 apps += [('Wiki', 'wiki', 'Wiki'),
                         ('profile', 'profile', 'Profile'),
                        ]
-                if g.show_userstats:
-                    apps = apps + [('userstats', 'userstats', 'Statistics')]
             apps += [
                 ('admin', 'admin', 'Admin'),
                 ('search', 'search', 'Search'),

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/d2503902/Allura/allura/websetup/bootstrap.py
----------------------------------------------------------------------
diff --git a/Allura/allura/websetup/bootstrap.py b/Allura/allura/websetup/bootstrap.py
index 9614b99..747504c 100644
--- a/Allura/allura/websetup/bootstrap.py
+++ b/Allura/allura/websetup/bootstrap.py
@@ -88,6 +88,7 @@ def bootstrap(command, conf, vars):
                                               google_analytics = False))
     n_users = M.Neighborhood(name='Users', url_prefix='/u/',
                              shortname_prefix='u/',
+                             anchored_tools='userstats:Statistics',
                              features=dict(private_projects = True,
                                            max_projects = None,
                                            css = 'none',

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/d2503902/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index 68821e4..3dc76d0 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -126,12 +126,6 @@ scm.repos.tarball.url_prefix = http://localhost/
 
 trovecategories.enableediting = true
 
-# If set to false, the stats of the user are not
-# updated and they are not shown to users.
-# Note: the name of the parameter has to be the same
-#       of the entry point, followed by .enable
-userstats.enable = true
-
 # ActivityStream
 activitystream.master = mongodb://127.0.0.1:27017
 activitystream.database = activitystream

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/d2503902/ForgeUserStats/test.ini
----------------------------------------------------------------------
diff --git a/ForgeUserStats/test.ini b/ForgeUserStats/test.ini
index 04c1c6e..6753aa4 100644
--- a/ForgeUserStats/test.ini
+++ b/ForgeUserStats/test.ini
@@ -5,7 +5,6 @@
 #
 [DEFAULT]
 debug = true
-userstats.enable = true
 
 [server:main]
 use = egg:Paste#http


[44/50] git commit: [#5481] ticket:313 fixed Project Admins

Posted by ac...@apache.org.
[#5481] ticket:313 fixed Project Admins


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/56531a33
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/56531a33
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/56531a33

Branch: refs/heads/acs2/5518
Commit: 56531a331aa80ed6a617ac9deac08c9a5c7fb83f
Parents: 57b3310
Author: Yuriy Arhipov <yu...@yandex.ru>
Authored: Tue Apr 9 19:07:34 2013 +0400
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Mon Apr 15 14:01:51 2013 +0000

----------------------------------------------------------------------
 Allura/allura/lib/macro.py          |    2 +-
 Allura/allura/tests/test_globals.py |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/56531a33/Allura/allura/lib/macro.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/macro.py b/Allura/allura/lib/macro.py
index 829897b..0f2c65f 100644
--- a/Allura/allura/lib/macro.py
+++ b/Allura/allura/lib/macro.py
@@ -345,7 +345,7 @@ def project_admins():
                 url=user_role.user.url(),
                 name=user_role.user.display_name))
             for user_role in admin_role.users_with_role())
-    return u'<h6>Project Admins:</h6><p>{}</p>'.format(output)
+    return u'<h6>Project Admins:</h6><div class="grid-10">{}</div><div style="clear: both;"></div>'.format(output)
 
 template_members = string.Template('<a href="$url">Members</a><br/>')
 @macro()

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/56531a33/Allura/allura/tests/test_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index e52c00c..44c6850 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -157,7 +157,7 @@ def test_macro_project_admins():
     user = M.User.by_username('test-admin')
     user.display_name = u'Test Ådmin'
     r = g.markdown_wiki.convert('[[project_admins]]')
-    assert_equal(r, u'<div class="markdown_content"><h6>Project Admins:</h6><p><a href="/u/test-admin/">Test Ådmin</a><br /></p>\n</div>')
+    assert_equal(r, u'<div class="markdown_content"><h6>Project Admins:</h6><div class="grid-10"><a href="/u/test-admin/">Test Ådmin</a><br /></div><div style="clear: both;"></div>\n</div>')
 
 def test_macro_project_admins_one_br():
     p_nbhd = M.Neighborhood.query.get(name='Projects')


[33/50] git commit: [#3699] Removed title casing of mount_label

Posted by ac...@apache.org.
[#3699] Removed title casing of mount_label

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/c794904c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/c794904c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/c794904c

Branch: refs/heads/acs2/5518
Commit: c794904c997e10ab5b9b205503f79323de64eba1
Parents: e62d190
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Mon Apr 8 21:10:49 2013 +0000
Committer: Tim Van Steenburgh <tv...@gmail.com>
Committed: Thu Apr 11 14:19:06 2013 +0000

----------------------------------------------------------------------
 Allura/allura/ext/project_home/project_main.py     |    2 +-
 Allura/allura/lib/repository.py                    |    4 ++--
 .../templates/jinja_master/sidebar_menu.html       |    2 +-
 ForgeBlog/forgeblog/main.py                        |    4 ++--
 ForgeChat/forgechat/main.py                        |    4 ++--
 ForgeDiscussion/forgediscussion/forum_main.py      |    4 ++--
 ForgeLink/forgelink/link_main.py                   |    2 +-
 ForgeShortUrl/forgeshorturl/main.py                |    2 +-
 ForgeTracker/forgetracker/tracker_main.py          |    4 ++--
 ForgeUserStats/forgeuserstats/main.py              |    4 ++--
 ForgeWiki/forgewiki/wiki_main.py                   |    4 ++--
 11 files changed, 18 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c794904c/Allura/allura/ext/project_home/project_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/project_home/project_main.py b/Allura/allura/ext/project_home/project_main.py
index 70c781d..ace0ddc 100644
--- a/Allura/allura/ext/project_home/project_main.py
+++ b/Allura/allura/ext/project_home/project_main.py
@@ -41,7 +41,7 @@ class ProjectHomeApp(Application):
         :return: a list of :class:`SitemapEntries <allura.app.SitemapEntry>`
         '''
         return [ SitemapEntry(
-                self.config.options.mount_label.title(),
+                self.config.options.mount_label,
                 '..')]
 
     @property

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c794904c/Allura/allura/lib/repository.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/repository.py b/Allura/allura/lib/repository.py
index 79a6b33..401c71d 100644
--- a/Allura/allura/lib/repository.py
+++ b/Allura/allura/lib/repository.py
@@ -55,13 +55,13 @@ class RepositoryApp(Application):
         :return: a list of :class:`SitemapEntries <allura.app.SitemapEntry>`
         '''
         return [ SitemapEntry(
-                self.config.options.mount_label.title(),
+                self.config.options.mount_label,
                 '.')]
 
     @property
     @h.exceptionless([], log)
     def sitemap(self):
-        menu_id = self.config.options.mount_label.title()
+        menu_id = self.config.options.mount_label
         with h.push_config(c, app=self):
             return [
                 SitemapEntry(menu_id, '.')[self.sidebar_menu()] ]

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c794904c/Allura/allura/templates/jinja_master/sidebar_menu.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/sidebar_menu.html b/Allura/allura/templates/jinja_master/sidebar_menu.html
index 651ed77..e7ffdd9 100644
--- a/Allura/allura/templates/jinja_master/sidebar_menu.html
+++ b/Allura/allura/templates/jinja_master/sidebar_menu.html
@@ -22,7 +22,7 @@
 <div id="sidebar">
   {% if c.app and c.app.searchable %}
     <form id="search" method="GET" action="{{c.app.url + 'search/'}}">
-      <input name="q" type="text" title="Search {{c.app.config.options.mount_point.title()}}" placeholder="Search {{c.app.config.options.mount_point.title()}}">
+      <input name="q" type="text" title="Search {{c.app.config.options.mount_label}}" placeholder="Search {{c.app.config.options.mount_label}}">
     </form>
   {% else %}
     <div>&nbsp;</div>

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c794904c/ForgeBlog/forgeblog/main.py
----------------------------------------------------------------------
diff --git a/ForgeBlog/forgeblog/main.py b/ForgeBlog/forgeblog/main.py
index 1cfd96a..14cf2c2 100644
--- a/ForgeBlog/forgeblog/main.py
+++ b/ForgeBlog/forgeblog/main.py
@@ -96,12 +96,12 @@ class ForgeBlogApp(Application):
                 session(globals).flush()
 
     def main_menu(self):
-        return [SitemapEntry(self.config.options.mount_label.title(), '.')]
+        return [SitemapEntry(self.config.options.mount_label, '.')]
 
     @property
     @h.exceptionless([], log)
     def sitemap(self):
-        menu_id = self.config.options.mount_label.title()
+        menu_id = self.config.options.mount_label
         with h.push_config(c, app=self):
             return [
                 SitemapEntry(menu_id, '.')[self.sidebar_menu()] ]

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c794904c/ForgeChat/forgechat/main.py
----------------------------------------------------------------------
diff --git a/ForgeChat/forgechat/main.py b/ForgeChat/forgechat/main.py
index 6d2eb9a..4b411d6 100644
--- a/ForgeChat/forgechat/main.py
+++ b/ForgeChat/forgechat/main.py
@@ -52,12 +52,12 @@ class ForgeChatApp(Application):
         self.admin = AdminController(self)
 
     def main_menu(self):
-        return [SitemapEntry(self.config.options.mount_label.title(), '.')]
+        return [SitemapEntry(self.config.options.mount_label, '.')]
 
     @property
     @h.exceptionless([], log)
     def sitemap(self):
-        menu_id = self.config.options.mount_label.title()
+        menu_id = self.config.options.mount_label
         with h.push_config(c, app=self):
             return [
                 SitemapEntry(menu_id, '.')[self.sidebar_menu()] ]

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c794904c/ForgeDiscussion/forgediscussion/forum_main.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/forum_main.py b/ForgeDiscussion/forgediscussion/forum_main.py
index c7f1361..85daf3c 100644
--- a/ForgeDiscussion/forgediscussion/forum_main.py
+++ b/ForgeDiscussion/forgediscussion/forum_main.py
@@ -88,13 +88,13 @@ class ForgeDiscussionApp(Application):
         :return: a list of :class:`SitemapEntries <allura.app.SitemapEntry>`
         '''
         return [ SitemapEntry(
-                self.config.options.mount_label.title(),
+                self.config.options.mount_label,
                 '.')]
 
     @property
     @h.exceptionless([], log)
     def sitemap(self):
-        menu_id = self.config.options.mount_label.title()
+        menu_id = self.config.options.mount_label
         with h.push_config(c, app=self):
             return [
                 SitemapEntry(menu_id, '.')[self.sidebar_menu()] ]

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c794904c/ForgeLink/forgelink/link_main.py
----------------------------------------------------------------------
diff --git a/ForgeLink/forgelink/link_main.py b/ForgeLink/forgelink/link_main.py
index a6128f5..1c7b7b9 100644
--- a/ForgeLink/forgelink/link_main.py
+++ b/ForgeLink/forgelink/link_main.py
@@ -47,7 +47,7 @@ class ForgeLinkApp(Application):
     @property
     @h.exceptionless([], log)
     def sitemap(self):
-        menu_id = self.config.options.mount_label.title()
+        menu_id = self.config.options.mount_label
         return [SitemapEntry(menu_id, '.')[self.sidebar_menu()] ]
 
     def sidebar_menu(self):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c794904c/ForgeShortUrl/forgeshorturl/main.py
----------------------------------------------------------------------
diff --git a/ForgeShortUrl/forgeshorturl/main.py b/ForgeShortUrl/forgeshorturl/main.py
index 53d96c8..7cad8a7 100644
--- a/ForgeShortUrl/forgeshorturl/main.py
+++ b/ForgeShortUrl/forgeshorturl/main.py
@@ -64,7 +64,7 @@ class ForgeShortUrlApp(Application):
     @property
     @h.exceptionless([], log)
     def sitemap(self):
-        menu_id = self.config.options.mount_label.title()
+        menu_id = self.config.options.mount_label
         return [SitemapEntry(menu_id, '.')[self.sidebar_menu()]]
 
     def sidebar_menu(self):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c794904c/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index f62ae03..4a7562e 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -198,13 +198,13 @@ class ForgeTrackerApp(Application):
         :return: a list of :class:`SitemapEntries <allura.app.SitemapEntry>`
         '''
         return [ SitemapEntry(
-                self.config.options.mount_label.title(),
+                self.config.options.mount_label,
                 '.')]
 
     @property
     @h.exceptionless([], log)
     def sitemap(self):
-        menu_id = self.config.options.mount_label.title()
+        menu_id = self.config.options.mount_label
         with h.push_config(c, app=self):
             return [
                 SitemapEntry(menu_id, '.')[self.sidebar_menu()] ]

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c794904c/ForgeUserStats/forgeuserstats/main.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/main.py b/ForgeUserStats/forgeuserstats/main.py
index 194c7d6..95bfbfa 100644
--- a/ForgeUserStats/forgeuserstats/main.py
+++ b/ForgeUserStats/forgeuserstats/main.py
@@ -96,12 +96,12 @@ class ForgeUserStatsApp(Application):
             M.ACE.allow(role_admin, 'admin')]
 
     def main_menu(self):
-        return [SitemapEntry(self.config.options.mount_label.title(), '.')]
+        return [SitemapEntry(self.config.options.mount_label, '.')]
 
     @property
     @h.exceptionless([], log)
     def sitemap(self):
-        menu_id = self.config.options.mount_label.title()
+        menu_id = self.config.options.mount_label
         with h.push_config(c, app=self):
             return [
                 SitemapEntry(menu_id, '.')[self.sidebar_menu()] ]

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c794904c/ForgeWiki/forgewiki/wiki_main.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index be11731..219fe00 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -141,13 +141,13 @@ class ForgeWikiApp(Application):
         :return: a list of :class:`SitemapEntries <allura.app.SitemapEntry>`
         '''
         return [ SitemapEntry(
-                self.config.options.mount_label.title(),
+                self.config.options.mount_label,
                 '.')]
 
     @property
     @h.exceptionless([], log)
     def sitemap(self):
-        menu_id = self.config.options.mount_label.title()
+        menu_id = self.config.options.mount_label
         with h.push_config(c, app=self):
             pages = [
                 SitemapEntry(p.title, p.url())


[11/50] git commit: [#5453] Correctly initialize user stats

Posted by ac...@apache.org.
[#5453] Correctly initialize user stats


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/cfb38058
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/cfb38058
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/cfb38058

Branch: refs/heads/acs2/5518
Commit: cfb38058afb37e14064d4b420e5c3f146e4979c7
Parents: 8eeb3ae
Author: Stefano Invernizzi <st...@apache.org>
Authored: Thu Mar 7 23:44:50 2013 +0100
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:37 2013 +0000

----------------------------------------------------------------------
 Allura/allura/model/contrib_stats.py |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/cfb38058/Allura/allura/model/contrib_stats.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/contrib_stats.py b/Allura/allura/model/contrib_stats.py
index 51121ad..5a4751a 100644
--- a/Allura/allura/model/contrib_stats.py
+++ b/Allura/allura/model/contrib_stats.py
@@ -498,12 +498,12 @@ class Stats(MappedClass):
                     newstats = dict(
                         category=t,
                         commits=[],
-                        messages=[dict(
+                        messages=[],
+                        tickets=dict(
                             assigned=0,
                             solved=0,
                             revoked=0,
-                            totsolvingtime=0)],
-                        tickets={})
+                            totsolvingtime=0))
                     stats.general.append(newstats)
                     i = getElementIndex(stats.general, category=t)
                 for lang in ll:


[40/50] git commit: [#5481] ticket:313 project members page

Posted by ac...@apache.org.
[#5481] ticket:313  project members page


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/18f106f7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/18f106f7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/18f106f7

Branch: refs/heads/acs2/5518
Commit: 18f106f7bc7e399e3209588c7385b087409f1b3b
Parents: 1dd8575
Author: Yuriy Arhipov <yu...@yandex.ru>
Authored: Fri Apr 5 12:56:22 2013 +0400
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Mon Apr 15 14:01:50 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/project.py |   19 +++++++++++++++++++
 Allura/allura/lib/macro.py           |    9 +++++++++
 Allura/allura/lib/plugin.py          |    2 +-
 Allura/allura/templates/members.html |   28 ++++++++++++++++++++++++++++
 Allura/allura/tests/test_globals.py  |    9 ++++++++-
 ForgeWiki/forgewiki/wiki_main.py     |    1 +
 6 files changed, 66 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/18f106f7/Allura/allura/controllers/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index 891e18f..f91c543 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -317,6 +317,25 @@ class ProjectController(object):
 
         return app.root, remainder
 
+    @expose('jinja:allura:templates/members.html')
+    @with_trailing_slash
+    def _members(self, **kw):
+        users = []
+        for user in c.project.users():
+            roles = []
+            for role in user.project_role().roles:
+                r = M.ProjectRole.query.get(_id=role)
+                if r.name not in roles:
+                    roles.append(r.name)
+            users.append(dict(
+                display_name = user.display_name,
+                username = user.username,
+                url = user.url(),
+                roles = roles,
+                email_addresses = user.email_addresses,
+                skills = user.get_skills()))
+        return dict(users=users)
+
     def _check_security(self):
         require_access(c.project, 'read')
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/18f106f7/Allura/allura/lib/macro.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/macro.py b/Allura/allura/lib/macro.py
index ff5a0d3..4615828 100644
--- a/Allura/allura/lib/macro.py
+++ b/Allura/allura/lib/macro.py
@@ -8,6 +8,7 @@ import traceback
 import pymongo
 from pylons import tmpl_context as c, app_globals as g
 from pylons import request
+from urlparse import urljoin
 
 from . import helpers as h
 from . import security
@@ -344,4 +345,12 @@ def project_admins():
                 url=user_role.user.url(),
                 name=user_role.user.display_name))
             for user_role in admin_role.users_with_role())
+    return u'<p>Project Admins:<br/>{}</p>'.format(output)
+
+template_members = string.Template('<a href="$url">Members</a><br/>')
+@macro()
+def members():
+    output = ''.join(
+            template_members.substitute(dict(
+                url=urljoin(c.project.url(),'_members'),)))
     return u'<p>{}</p>'.format(output)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/18f106f7/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index efc5d07..77207a2 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -521,7 +521,7 @@ class ProjectRegistrationProvider(object):
                     if tool == 'wiki':
                         from forgewiki import model as WM
                         text = tool_config.get('home_text',
-                            '[[project_admins]]\n[[download_button]]')
+                            '[[project_admins]]\n[[members]]\n[[download_button]]')
                         WM.Page.query.get(app_config_id=app.config._id).text = text
 
         if 'tool_order' in project_template:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/18f106f7/Allura/allura/templates/members.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/members.html b/Allura/allura/templates/members.html
new file mode 100644
index 0000000..06d353a
--- /dev/null
+++ b/Allura/allura/templates/members.html
@@ -0,0 +1,28 @@
+{% set hide_left_bar = True %}
+{% extends g.theme.master %}
+{% block title %}Members{% endblock %}
+{% block header %}Members{% endblock %}
+{% block content %}
+<div class="grid-23">
+<div style="overflow:auto">
+<table>
+    <thead>
+    <tr>
+        <th >Developer</th>
+        <th>Username</th>
+        <th>Role/Position</th>
+        <th>Email</th>
+    </tr>
+    </thead>
+    {%for user in users%}
+    <tr>
+        <td >{{ user.display_name }}</td>
+        <td ><a href="{{ user.url }}">{{ user.username }}</a></td>
+        <td >{% for role in user.roles%} {{ role }}</br> {%endfor%}</td>
+        <td >{% for email in user.email_addresses %}{{email}}{%endfor%}</td>
+    </tr>
+    {%endfor%}
+</table>
+</div>
+</div>
+{% endblock %}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/18f106f7/Allura/allura/tests/test_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index 7ad940e..4fa37cc 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -149,11 +149,17 @@ def test_macros():
     r = g.markdown_wiki.convert('[[neighborhood_blog_posts]]')
     assert 'test content' in r
 
+def test_macro_members():
+    user = M.User.by_username('test-admin')
+    user.display_name = u'Test Ådmin'
+    r = g.markdown_wiki.convert('[[members]]')
+    assert_equal(r, u'<div class="markdown_content"><p><a href="/p/test/_members">Members</a><br /></p>\n</div>')
+
 def test_macro_project_admins():
     user = M.User.by_username('test-admin')
     user.display_name = u'Test Ådmin'
     r = g.markdown_wiki.convert('[[project_admins]]')
-    assert_equal(r, u'<div class="markdown_content"><p><a href="/u/test-admin/">Test Ådmin</a><br /></p>\n</div>')
+    assert_equal(r, u'<div class="markdown_content"><p>Project Admins:<br /><a href="/u/test-admin/">Test Ådmin</a><br /></p>\n</div>')
 
 def test_macro_project_admins_one_br():
     p_nbhd = M.Neighborhood.query.get(name='Projects')
@@ -161,6 +167,7 @@ def test_macro_project_admins_one_br():
     p_test.add_user(M.User.by_username('test-user'), ['Admin'])
     ThreadLocalORMSession.flush_all()
     r = g.markdown_wiki.convert('[[project_admins]]\n[[download_button]]')
+
     assert not '</a><br /><br /><a href=' in r, r
     assert '</a><br /><a href=' in r, r
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/18f106f7/ForgeWiki/forgewiki/wiki_main.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index 219fe00..ce253fb 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -247,6 +247,7 @@ This is the default page, edit it as you see fit. To add a new page simply refer
 The wiki uses [Markdown](%s) syntax.
 
 [[project_admins]]
+[[members]]
 [[download_button]]
 """ % url
                 p.commit()


[30/50] git commit: [#5465] ticket:310 Add autocompletion for labels (placeholder data)

Posted by ac...@apache.org.
[#5465] ticket:310 Add autocompletion for labels (placeholder data)


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/b970ea62
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/b970ea62
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/b970ea62

Branch: refs/heads/acs2/5518
Commit: b970ea62edb287531b53b57f4fc126248d693f81
Parents: 06a70ab
Author: Igor Bondarenko <je...@gmail.com>
Authored: Wed Apr 10 12:49:13 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Wed Apr 10 22:00:17 2013 +0000

----------------------------------------------------------------------
 Allura/allura/lib/widgets/form_fields.py  |    7 ++++---
 ForgeTracker/forgetracker/tracker_main.py |    5 +++++
 2 files changed, 9 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b970ea62/Allura/allura/lib/widgets/form_fields.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/form_fields.py b/Allura/allura/lib/widgets/form_fields.py
index 67ea947..f8a4b06 100644
--- a/Allura/allura/lib/widgets/form_fields.py
+++ b/Allura/allura/lib/widgets/form_fields.py
@@ -51,10 +51,11 @@ class LabelEdit(ew.InputField):
         yield ew.CSSLink('css/jquery.tagsinput.css')
         yield onready('''
           $('input.label_edit').tagsInput({
-              'height':'100%',
-              'width':'100%'
+              'height':'100%%',
+              'width':'100%%',
+              'autocomplete_url':'%(url)stags'
           });
-        ''')
+        ''' % dict(url=c.app.url))
 
 class ProjectUserSelect(ew.InputField):
     template='jinja:allura:templates/widgets/project_user_select.html'

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b970ea62/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index dc14459..e615b17 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -481,6 +481,11 @@ class RootController(BaseController):
                 milestone_counts.append({'name': name, 'count': count})
         return {'milestone_counts': milestone_counts}
 
+    @expose('json:')
+    def tags(self, term, **kw):
+        tags = ['sad', 'happy']
+        return json.dumps(tags)
+
     @with_trailing_slash
     @h.vardec
     @expose('jinja:forgetracker:templates/tracker/index.html')


[08/50] git commit: Remove user_preferences.html

Posted by ac...@apache.org.
Remove user_preferences.html


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/2e6c61f8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/2e6c61f8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/2e6c61f8

Branch: refs/heads/acs2/5518
Commit: 2e6c61f8624f31165eb6ab6092b350918540eeab
Parents: 96f7e9a
Author: Stefano Invernizzi <st...@apache.org>
Authored: Sun Mar 24 11:36:25 2013 +0100
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:37 2013 +0000

----------------------------------------------------------------------
 Allura/allura/templates/user_preferences.html |  279 --------------------
 1 files changed, 0 insertions(+), 279 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/2e6c61f8/Allura/allura/templates/user_preferences.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/user_preferences.html b/Allura/allura/templates/user_preferences.html
deleted file mode 100644
index 768cd2e..0000000
--- a/Allura/allura/templates/user_preferences.html
+++ /dev/null
@@ -1,279 +0,0 @@
-{% set hide_left_bar = True %}
-{% extends g.theme.master %}
-
-{% block title %}{{c.user.username}} / Preferences{% endblock %}
-
-{% block header %}User Preferences for {{c.user.username}}{% endblock %}
-
-{% block content %}
-  <ul id="account-nav-menu" class="b-hornav droppy">
-      {% for item in menu -%}
-      <li id="{{ item.tabid }}">
-      <a href="{{ item.target }}">
-          {{ item.title }}
-          <div class="marker{% if item.target.rstrip('/') == request.path.rstrip('/') %} current{% endif %}"></div>
-      </a>
-      </li>
-      {%- endfor %}
-   </ul>
-
-  <div style="clear:both" class="grid-20">
-    <h2>Personal Settings</h2>
-    {{g.theme.personal_data_form.display(action="/auth/prefs/change_personal_data", user=c.user)}}
-  </div>
-
-  <div style="clear:both" class="grid-20">
-    <a name="Contacts"></a>
-    <h2>Personal Contacts</h2>
-    <h3>Skype account</h3>
-
-    {{g.theme.skype_account_form.display(action="/auth/prefs/skype_account",
-          initial_value=c.user.get_pref('skypeaccount'))}}
-
-    {%if c.user.get_pref('socialnetworks') or c.user.get_pref('telnumbers') or c.user.get_pref('webpages') %}
-      <h3>Other existing contacts</h3>
-        <table>
-          <tr>
-            <thead>
-              <th>Type</th>
-              <th>Contact</th>
-              <th>Actions</th>
-            </thead>
-          </tr>
-          {% for sn in c.user.get_pref('socialnetworks') %}
-             {{g.theme.remove_socialnetwork_form.display(account=sn.accounturl, socialnetwork=sn.socialnetwork)}}
-          {% endfor %}
-
-          {% for tn in c.user.get_pref('telnumbers') %}
-              {{g.theme.remove_textvalue_form.display(action="/auth/prefs/remove_telnumber", value=tn, label="Telephone number")}}
-          {%endfor%}
-
-          {% for ws in c.user.get_pref('webpages') %}
-              {{g.theme.remove_textvalue_form.display(action="/auth/prefs/remove_webpage", value=ws, label="Website url")}}
-          {%endfor%}
-        </table>
-    {% endif %}
-
-    <h3>Add a social network account</h3>
-    {{g.theme.add_socialnetwork_form.display(action="/auth/prefs/add_social_network")}}
-    <h3>Add a telephone number</h3>
-    {{g.theme.add_telnumber_form.display(action="/auth/prefs/add_telnumber")}}
-    <h3>Add a personal website</h3>
-    {{g.theme.add_website_form.display(action="/auth/prefs/add_webpage")}}
-  </div>
-
-  <a name="Availability"></a>
-  <div style="clear:both" class="grid-20">
-    <h2>Availability</h2>
-    <div class="grid-18">
-      If you want, you can set the weekly timeslot during which you are usually available to support other users of the forge.
-      Please, set your time intervals choosing a weekday and entering the time interval according to the timezone specified in your
-      personal data, using the format HH:MM. If you didn't set any timezone, your timeslots could be meaningless to other users,
-      therefore they will be ignored.
-    </div>
-    <div class="grid-18">
-      You can also specify periods of time during which you won't be able to work on the forge, in orther to communicate other users
-      that they can't contact you during those days. Please, do it specifying date intervals in format DD/MM/YYYY.
-    </div>
-  </div>
-  <div class="grid-20">
-    {%if c.user.get_availability_timeslots() %}
-      <h3>Existing availability timeslots</h3>
-      <table>
-        <tr>
-          <thead>
-            <th>Weekday</th>
-            <th>Start time</th>
-            <th>End time</th>
-            <th>Actions</th>
-          </thead>
-        </tr>
-        {% for ts in c.user.get_availability_timeslots() %}
-          {{g.theme.remove_timeslot_form.display(
-                action="/auth/prefs/remove_timeslot",
-                weekday=ts.week_day,
-                starttime=ts.start_time,
-                endtime=ts.end_time)}}
-        {%endfor%}
-      </table>
-    {% endif %}
-    <h3>Add a new availability timeslot</h3>
-    {{g.theme.add_timeslot_form.display(action="/auth/prefs/add_timeslot")}}
-  </div>
-
-  <div class="grid-20">
-    {%if c.user.get_inactive_periods() %}
-      <h3>Existing periods of inactivity on the forge</h3>
-      <table>
-        <tr>
-          <thead>
-            <th>Start date</th>
-            <th>End date</th>
-            <th>Actions</th>
-          </thead>
-        </tr>
-        {% for ip in c.user.get_inactive_periods() %}
-          {{g.theme.remove_inactive_period_form.display(
-                action="/auth/prefs/remove_inactive_period",
-                startdate=ip.start_date,
-                enddate=ip.end_date)}}
-        {%endfor%}
-      </table>
-    {% endif %}
-    <h3>Add a new period of inactivity on the forge</h3>
-    {{g.theme.add_inactive_period_form.display(action="/auth/prefs/add_inactive_period")}}
-  </div>
-
-  <div class="grid-20">
-    <h2>Skills list</h2>
-    <ul><li><a href="/auth/prefs/user_skills">Click here to check and change your skills list</a></li></ul>
-  </div>
-
-  {% if g.theme.password_change_form %}
-  <div class="grid-20">
-    <h2>Change Password</h2>
-    {{ g.theme.password_change_form.display() }}
-  </div>
-  {% endif %}
-  {% if g.theme.upload_key_form %}
-  <div class="grid-20">
-    <h2>Upload ssh public key</h2>
-    {{ g.theme.upload_key_form.display() }}
-  </div>
-  {% endif %}
-
-  {% if tg.config.get('auth.method', 'local') == 'local' %}
-      <br style="clear:both"/>
-      <h2>API Token</h2>
-      {% if api_token %}
-        <p>
-          <b>API Key:</b><br/>
-          {{api_token.api_key}}<br/>
-          <b>Secret Key:</b><br/>
-          {{api_token.secret_key}}<br/>
-        </p>
-        <form method="POST" action="del_api_token" class="grid-18">
-          <input type="submit" value="Delete API Token">
-        </form>
-      {% else %}
-        <p>No API token generated</p>
-      {% endif %}
-      <form method="POST" action="gen_api_token" class="grid-18">
-        <input type="submit" value="(Re)generate API Token">
-      </form>
-  {% endif %}
-
-  <div style="clear:both"></div>
-
-  <h2>Authorized Third-party Applications</h2>
-  {% for access_tok in authorized_applications %}
-    <div>
-      <h3>{{access_tok.consumer_token.name}}</h3>
-      {{access_tok.consumer_token.description_html}}
-      {{ c.revoke_access.display(value=access_tok) }}
-      <br style="clear:both"/>
-  </div>
- {% endfor %}
-    {% if not authorized_applications %}<p>No authorized third-party applications</p>{% endif %}
-
-
-  <h2>Subscriptions</h2>
-  {% if subscriptions %}
-    <p><em>Mark tools that you want to subscribe to. Unmark tools that you want to unsubscribe from. Press 'Save' button.</em></p>
-    {{c.form.display(action='update_subscriptions', value=dict(subscriptions=subscriptions))}}
-  {% else%}
-    <p>No subscriptions.</p>
-  {% endif %}
-  <hr/>
-  <div style="clear:both">&nbsp;</div>
-  <form action="update" method="post">
-        {% if tg.config.get('auth.method', 'local') == 'local' %}
-        <label class="grid-4">Display Name</label>
-        <div class="grid-18">
-          <input name="preferences.display_name" value="{{c.user.display_name}}" type="text">
-        </div>
-        {% endif %}
-        <label class="grid-4">Email Format</label>
-        <div class="grid-18">
-          <select name="preferences.email_format">
-            <option value="plain" {{'selected' if c.user.preferences.email_format == 'plain' else ''}}>Plain Text</option>
-            <option value="html" {{'selected' if c.user.preferences.email_format == 'html' else ''}}>HTML</option>
-            <option value="both" {{'selected' if c.user.preferences.email_format == 'both' else ''}}>Combined</option>
-          </select>
-        </div>
-        {% if tg.config.get('auth.method', 'local') == 'local' %}
-        <label class="grid-4">Page Size</label>
-        <div class="grid-18">
-          <select name="preferences.results_per_page">
-            {% for per_page in [25, 50, 100, 250] %}
-                <option {% if per_page == c.user.preferences.results_per_page %}selected="selected"{% endif %}
-                   value="{{per_page}}">{{per_page}}</option>
-            {% endfor %}
-          </select>
-        </div>
-        {% endif %}
-
-    {% if tg.config.get('auth.method', 'local') == 'local' %}
-      {% for a in c.user.email_addresses %}
-        <input name="addr-{{loop.index0}}.ord" value="{{loop.index0}}" type="hidden"/>
-      {% endfor %}
-      {% if c.user.email_addresses %}
-        <h3 class="grid-18">Email Addresses</h3>
-        <table class="grid-18">
-          <tr>
-            <th>Primary?</th>
-            <th>Address</th>
-            <th>Confirmed</th>
-            <th></th>
-          </tr>
-          {% for a in c.user.email_addresses %}
-          <tr>
-            {% set obj = c.user.address_object(a) %}
-            <td>{{lib.radio_button('primary_addr', None, a, c.user.preferences.email_address)}}</td>
-            <td>{{a}}</td>
-            {% if obj %}
-            <td>
-              {% if obj.confirmed %}
-                yes
-              {% else %}
-                no (<a href="{{g.url('/auth/send_verification_link', a=a)}}">verify</a>)
-              {% endif %}
-            </td>
-            {% else %}
-              <td>Unknown addr obj {{a}}</td>
-            {% endif %}
-            <td>{{lib.submit_button('Delete', 'addr-%s.delete' % i)}}</td>
-          </tr>
-          {% endfor %}
-        </table>
-        {% endif %}
-        <div class="grid-18">
-        {{lib.text_field('new_addr.addr', 'New Email Address')}}
-        {{lib.submit_button('Claim Address', name='new_addr.claim')}}
-        </div>
-
-        {% if c.user.open_ids %}
-        <h3 class="grid-18">OpenIDs Claimed</h3>
-        <table class="grid-18">
-          <tr>
-            <th>OpenID</th>
-            <th></th>
-          </tr>
-          {% for oid in c.user.open_ids %}
-            {% set obj = c.user.openid_object(oid) %}
-          <tr>
-            <td>{{oid}}</td>
-            <td>{{lib.submit_button('Delete', 'oid-%s.delete' % loop.index0)}}</td>
-          </tr>
-          {% endfor %}
-        </table>
-        {% endif %}
-        <div class="grid-18">
-        <a href="/auth/claim_oid">Claim New OpenID</a>
-        </div>
-    {% endif %}
-    <div class="grid-18">
-    {{lib.submit_button('Save Changes')}}
-    </div>
-  </form>
-{% endblock %}


[27/50] git commit: [#6006] Return empty string if path portion isn't latin1-encodable

Posted by ac...@apache.org.
[#6006] Return empty string if path portion isn't latin1-encodable

Signed-off-by: Tim Van Steenburgh <tv...@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/76800ef6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/76800ef6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/76800ef6

Branch: refs/heads/acs2/5518
Commit: 76800ef6445d53b5a4ffa4e56a7ce6077b465508
Parents: 960602a
Author: Tim Van Steenburgh <tv...@gmail.com>
Authored: Tue Apr 9 18:32:14 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Wed Apr 10 14:20:30 2013 +0000

----------------------------------------------------------------------
 Allura/allura/lib/helpers.py        |    7 ++++++-
 Allura/allura/tests/test_helpers.py |    6 ++++--
 2 files changed, 10 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/76800ef6/Allura/allura/lib/helpers.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index 583ab32..1035206 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -48,8 +48,13 @@ re_clean_vardec_key = re.compile(r'''\A
 \Z''', re.VERBOSE)
 
 def make_safe_path_portion(ustr):
+    """Return an ascii representation of `ustr`
+
+    Will return an empty string if no char in `ustr`
+    is latin1-encodable.
+    """
     ustr = really_unicode(ustr)
-    s = ustr.encode('utf8', 'ignore')
+    s = ustr.encode('latin1', 'ignore')
     s = AsciiDammit.asciiDammit(s)
     s = s.lower()
     s = '-'.join(re_path_portion_fragment.findall(s))

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/76800ef6/Allura/allura/tests/test_helpers.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index ac979e3..2e80b56 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -18,8 +18,10 @@ def setUp(self):
 def test_make_safe_path_portion():
     s = u'Задачи'
     new_s = h.make_safe_path_portion(s)
-    assert len(new_s), len(new_s)
-    assert new_s == new_s.encode('ascii')
+    assert len(new_s) == 0
+    s = 'åß∂ƒ'
+    new_s = h.make_safe_path_portion(s)
+    assert new_s == 'ab'
 
 def test_really_unicode():
     here_dir = path.dirname(__file__)


[41/50] git commit: [#5481] Removed email address from new members page

Posted by ac...@apache.org.
[#5481] Removed email address from new members page

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/4328a168
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/4328a168
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/4328a168

Branch: refs/heads/acs2/5518
Commit: 4328a168eb85b08e3bf28c84bcb225c521052eb5
Parents: 56531a3
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Fri Apr 12 17:51:49 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Mon Apr 15 14:01:51 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/project.py        |    2 +-
 Allura/allura/templates/members.html        |    6 ++----
 Allura/allura/tests/functional/test_home.py |    5 ++---
 3 files changed, 5 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/4328a168/Allura/allura/controllers/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index 6a05acf..9a72f4c 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -329,7 +329,7 @@ class ProjectController(object):
                 username=user.username,
                 url=user.url(),
                 roles=roles,
-                email_addresses=user.email_addresses))
+                ))
         return dict(users=users)
 
     def _check_security(self):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/4328a168/Allura/allura/templates/members.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/members.html b/Allura/allura/templates/members.html
index 468d14c..f709d78 100644
--- a/Allura/allura/templates/members.html
+++ b/Allura/allura/templates/members.html
@@ -11,18 +11,16 @@
         <th>Developer</th>
         <th>Username</th>
         <th>Role/Position</th>
-        <th>Email</th>
     </tr>
     </thead>
     {%for user in users%}
     <tr>
         <td>{{ user.display_name }}</td>
         <td><a href="{{ user.url }}">{{ user.username }}</a></td>
-        <td>{% for role in user.roles%} {{ role }}</br> {%endfor%}</td>
-        <td>{% for email in user.email_addresses %}{{email.replace('@', ' at ')}}{%endfor%}</td>
+        <td>{{user.roles|join(', ')}}</td>
     </tr>
     {%endfor%}
 </table>
 </div>
 </div>
-{% endblock %}
\ No newline at end of file
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/4328a168/Allura/allura/tests/functional/test_home.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_home.py b/Allura/allura/tests/functional/test_home.py
index b465808..252ad52 100644
--- a/Allura/allura/tests/functional/test_home.py
+++ b/Allura/allura/tests/functional/test_home.py
@@ -61,12 +61,11 @@ class TestProjectHome(TestController):
         r = self.app.get('/p/test/_members/')
         assert '<td>Test Admin</td>' in r
         assert '<td><a href="/u/test-admin/">test-admin</a></td>' in r
-        assert '<td> Admin</br> </td>' in r
-        assert '<td>test-admin at users.localhost</td>' in r
+        assert '<td>Admin</td>' in r
 
     def test_members_anonymous(self):
         r = self.app.get('/p/test/_members/', extra_environ=dict(username='*anonymous'))
         assert '<td>Test Admin</td>' in r
         assert '<td><a href="/u/test-admin/">test-admin</a></td>' in r
-        assert '<td> Admin</br> </td>' in r
+        assert '<td>Admin</td>' in r
 


[34/50] git commit: [#4504] ticket:311 Test for $USER variable in ticket searches

Posted by ac...@apache.org.
[#4504] ticket:311 Test for $USER variable in ticket searches


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/6f045479
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/6f045479
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/6f045479

Branch: refs/heads/acs2/5518
Commit: 6f045479527c2444193c43d1d7d6e583402413ee
Parents: c794904
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Apr 9 09:02:12 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Fri Apr 12 17:07:49 2013 +0000

----------------------------------------------------------------------
 .../forgetracker/tests/functional/test_root.py     |   21 +++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/6f045479/ForgeTracker/forgetracker/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index ed03410..cef0134 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -816,6 +816,27 @@ class TestFunctionalController(TrackerTestController):
         response = self.app.get('/p/test/bugs/search_feed.atom?q=test')
         assert '<title>test first ticket</title>' in response
 
+    def test_search_current_user(self):
+        self.new_ticket(summary='test first ticket')
+        self.new_ticket(summary='test second ticket')
+        p = M.Project.query.get(shortname='test')
+        tracker = p.app_instance('bugs')
+        t = tm.Ticket.query.get(summary='test first ticket')
+        t.reported_by_id = M.User.by_username('test-user-0')._id
+        t = tm.Ticket.query.get(summary='test second ticket')
+        t.reported_by_id = M.User.by_username('test-user-1')._id
+        ThreadLocalORMSession.flush_all()
+        M.MonQTask.run_ready()
+        ThreadLocalORMSession.flush_all()
+        response = self.app.get('/p/test/bugs/search/?q=reported_by_s:$USER',
+                                extra_environ={'username': 'test-user-0'})
+        assert '1 result' in response, response.showbrowser()
+        assert 'test first ticket' in response, response.showbrowser()
+        response = self.app.get('/p/test/bugs/search/?q=reported_by_s:$USER',
+                                extra_environ={'username': 'test-user-1'})
+        assert '1 result' in response, response.showbrowser()
+        assert 'test second ticket' in response, response.showbrowser()
+
     def test_feed(self):
         self.new_ticket(
             summary='test first ticket',


[16/50] git commit: [#5453] don't count svn imports either

Posted by ac...@apache.org.
[#5453] don't count svn imports either


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/17728a59
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/17728a59
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/17728a59

Branch: refs/heads/acs2/5518
Commit: 17728a59faa947c3a0a450b620781b00d595fc9b
Parents: 9d12670
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Thu Apr 4 18:36:39 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:38 2013 +0000

----------------------------------------------------------------------
 Allura/allura/model/repo_refresh.py |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/17728a59/Allura/allura/model/repo_refresh.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/repo_refresh.py b/Allura/allura/model/repo_refresh.py
index d06e879..20383e9 100644
--- a/Allura/allura/model/repo_refresh.py
+++ b/Allura/allura/model/repo_refresh.py
@@ -112,7 +112,7 @@ def refresh_repo(repo, all_commits=False, notify=True, new_clone=False):
             if (i+1) % 100 == 0:
                 log.info('Compute last commit info %d: %s', (i+1), ci._id)
 
-    if not all_commits:
+    if not all_commits and not new_clone:
         for commit in commit_ids:
             new = repo.commit(commit)
             user = User.by_email_address(new.committed.email)


[28/50] git commit: [#6006] Make safe path portion out of non-latin1 chars

Posted by ac...@apache.org.
[#6006] Make safe path portion out of non-latin1 chars

Signed-off-by: Tim Van Steenburgh <tv...@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/960602a9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/960602a9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/960602a9

Branch: refs/heads/acs2/5518
Commit: 960602a907db8439a40674b0d6ac7dd0fbd30c04
Parents: 5207de0
Author: Tim Van Steenburgh <tv...@gmail.com>
Authored: Tue Apr 9 13:17:41 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Wed Apr 10 14:20:30 2013 +0000

----------------------------------------------------------------------
 Allura/allura/lib/helpers.py        |    2 +-
 Allura/allura/tests/test_helpers.py |    7 +++++++
 2 files changed, 8 insertions(+), 1 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/960602a9/Allura/allura/lib/helpers.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index eeee7bc..583ab32 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -49,7 +49,7 @@ re_clean_vardec_key = re.compile(r'''\A
 
 def make_safe_path_portion(ustr):
     ustr = really_unicode(ustr)
-    s = ustr.encode('latin-1', 'ignore')
+    s = ustr.encode('utf8', 'ignore')
     s = AsciiDammit.asciiDammit(s)
     s = s.lower()
     s = '-'.join(re_path_portion_fragment.findall(s))

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/960602a9/Allura/allura/tests/test_helpers.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index 4829549..ac979e3 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 from os import path
 from mock import Mock, patch
 
@@ -14,6 +15,12 @@ def setUp(self):
     """Method called by nose before running each test"""
     setup_basic_test()
 
+def test_make_safe_path_portion():
+    s = u'Задачи'
+    new_s = h.make_safe_path_portion(s)
+    assert len(new_s), len(new_s)
+    assert new_s == new_s.encode('ascii')
+
 def test_really_unicode():
     here_dir = path.dirname(__file__)
     s = h.really_unicode('\xef\xbb\xbf<?xml version="1.0" encoding="utf-8" ?>')


[21/50] git commit: [#2716] Fix users_with_role() for subprojects.

Posted by ac...@apache.org.
[#2716] Fix users_with_role() for subprojects.

Signed-off-by: Tim Van Steenburgh <tv...@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/0ce64c7b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/0ce64c7b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/0ce64c7b

Branch: refs/heads/acs2/5518
Commit: 0ce64c7b392a1af9601e38b78bcee0afc20ffa59
Parents: 46780f8
Author: Tim Van Steenburgh <tv...@gmail.com>
Authored: Thu Apr 4 17:58:33 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Apr 4 19:32:59 2013 +0000

----------------------------------------------------------------------
 Allura/allura/model/project.py            |   12 ++++++------
 Allura/allura/tests/model/test_project.py |    8 +++++++-
 2 files changed, 13 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0ce64c7b/Allura/allura/model/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index b0b45df..279a122 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -666,15 +666,15 @@ class Project(MappedClass, ActivityNode, ActivityObject):
         e.g., project.users_with_role('Admin', 'Developer') -> returns all
           users in `project` having the Admin role or the Developer role, or both
         """
-        roles = ProjectRole.query.find(dict(name={'$in': role_names}, project_id=self._id))
-        return [project_role.user for r in roles for project_role in r.users_with_role(self)]
+        users = set()
+        for role_name in role_names:
+            for user in g.credentials.users_with_named_role(self.root_project._id, role_name):
+                users.add(user)
+        return list(users)
 
     def admins(self):
         """Find all the users who have 'Admin' role for this project"""
-        admin_role = ProjectRole.query.get(name='Admin', project_id=self._id)
-        if not admin_role:
-            return []
-        return [r.user.username for r in admin_role.users_with_role(self)]
+        return self.users_with_role('Admin')
 
     def user_in_project(self, username):
         from .auth import User

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0ce64c7b/Allura/allura/tests/model/test_project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/model/test_project.py b/Allura/allura/tests/model/test_project.py
index 5277d34..b084a3d 100644
--- a/Allura/allura/tests/model/test_project.py
+++ b/Allura/allura/tests/model/test_project.py
@@ -84,4 +84,10 @@ def test_set_ordinal_to_admin_tool():
     assert c.project.sitemap()
     assert c.project.app_config('admin').options.ordinal == 100
 
-
+def test_users_and_roles():
+    p = c.project
+    sub = c.project.direct_subprojects.next()
+    u = M.User.by_username('test-admin')
+    assert p.users_with_role('Admin') == [u]
+    assert p.users_with_role('Admin') == sub.users_with_role('Admin')
+    assert p.users_with_role('Admin') == p.admins()


[13/50] git commit: [#5453] Avoid conflict with mongo's built-in stats collection

Posted by ac...@apache.org.
[#5453] Avoid conflict with mongo's built-in stats collection


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/faf78125
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/faf78125
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/faf78125

Branch: refs/heads/acs2/5518
Commit: faf781252ed34639cd795eeffe615f0af0c60710
Parents: e5abf08
Author: Tim Van Steenburgh <tv...@gmail.com>
Authored: Tue Mar 5 21:45:38 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:37 2013 +0000

----------------------------------------------------------------------
 Allura/allura/model/contrib_stats.py |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/faf78125/Allura/allura/model/contrib_stats.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/contrib_stats.py b/Allura/allura/model/contrib_stats.py
index 4d9e1e9..adc36db 100644
--- a/Allura/allura/model/contrib_stats.py
+++ b/Allura/allura/model/contrib_stats.py
@@ -16,7 +16,7 @@ from allura.lib import helpers as h
 
 class Stats(MappedClass):
     class __mongometa__:
-        name='stats'
+        name='userstats'
         session = main_orm_session
         unique_indexes = [ '_id']
 


[47/50] git commit: [#6102] update repo_clone_task_failed event to match related changes in aff89824

Posted by ac...@apache.org.
[#6102] update repo_clone_task_failed event to match related changes in aff89824


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/11c9c489
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/11c9c489
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/11c9c489

Branch: refs/heads/acs2/5518
Commit: 11c9c489eefbd0a0bda423ecbc43bf391ee3dd56
Parents: 1958598
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Fri Apr 12 20:34:11 2013 +0000
Committer: Tim Van Steenburgh <tv...@gmail.com>
Committed: Mon Apr 15 23:48:05 2013 +0000

----------------------------------------------------------------------
 Allura/allura/tasks/repo_tasks.py |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/11c9c489/Allura/allura/tasks/repo_tasks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tasks/repo_tasks.py b/Allura/allura/tasks/repo_tasks.py
index 03ce1f2..505786f 100644
--- a/Allura/allura/tasks/repo_tasks.py
+++ b/Allura/allura/tasks/repo_tasks.py
@@ -100,8 +100,7 @@ def reclone_repo(*args, **kwargs):
             text='Repository %s/%s created' % (
                 c.project.shortname, c.app.config.options.mount_point))
     except Exception, e:
-        source_url = source_path or source_url
-        g.post_event('repo_clone_task_failed', source_url, traceback.format_exc())
+        g.post_event('repo_clone_task_failed', source_url, source_path, traceback.format_exc())
 
 @task
 def tarball(revision=None):


[32/50] git commit: [#5465] ticket:310 Ticket's labels autocompletion

Posted by ac...@apache.org.
[#5465] ticket:310 Ticket's labels autocompletion

Added query to retrieve labels for tracker sorted by usage frequency
and filtered by user input using mongo aggregation framework.

Needs further performance testing, second '$match' clause won't touch the index
(because it uses case insensitive regex match and takes place after '$unwind'),
but it's best I can do with such data layout.

Also simplified the test, because mim doesn't support aggregation queries.


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/e62d190b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/e62d190b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/e62d190b

Branch: refs/heads/acs2/5518
Commit: e62d190beca2cdfa213a4edd283fcbf016953b34
Parents: 828b29f
Author: Igor Bondarenko <je...@gmail.com>
Authored: Wed Apr 10 16:06:19 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Wed Apr 10 22:00:17 2013 +0000

----------------------------------------------------------------------
 .../forgetracker/tests/functional/test_root.py     |    9 +----
 ForgeTracker/forgetracker/tracker_main.py          |   28 ++++++++++++--
 2 files changed, 26 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/e62d190b/ForgeTracker/forgetracker/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index 917b064..ed03410 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -1441,13 +1441,8 @@ class TestFunctionalController(TrackerTestController):
         self.new_ticket(summary='a', labels='tag1,tag2')
         self.new_ticket(summary='b', labels='tag2')
         self.new_ticket(summary='c', labels='42cc,test')
-        r = self.app.get('/p/test/bugs/tags?term=t')
-        assert_equal(json.loads(r.body), ['tag2', 'tag1', 'test'])
-        r = self.app.get('/p/test/bugs/tags?term=ta')
-        assert_equal(json.loads(r.body), ['tag2', 'tag1'])
-        r = self.app.get('/p/test/bugs/tags?term=te')
-        assert_equal(json.loads(r.body), ['test'])
-        r = self.app.get('/p/test/bugs/tags?term=nope')
+        # Testing only empty 'term', because mim doesn't support aggregation calls
+        r = self.app.get('/p/test/bugs/tags')
         assert_equal(json.loads(r.body), [])
         r = self.app.get('/p/test/bugs/tags?term=')
         assert_equal(json.loads(r.body), [])

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/e62d190b/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index e615b17..f62ae03 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -6,7 +6,7 @@ from urllib import urlencode, unquote
 from urllib2 import urlopen
 from webob import exc
 import json
-from itertools import ifilter
+from itertools import ifilter, imap
 
 # Non-stdlib imports
 import pkg_resources
@@ -17,6 +17,7 @@ from pylons import tmpl_context as c, app_globals as g
 from pylons import request, response
 from formencode import validators
 from bson import ObjectId
+from bson.son import SON
 from bson.errors import InvalidId
 from webhelpers import feedgenerator as FG
 
@@ -482,9 +483,28 @@ class RootController(BaseController):
         return {'milestone_counts': milestone_counts}
 
     @expose('json:')
-    def tags(self, term, **kw):
-        tags = ['sad', 'happy']
-        return json.dumps(tags)
+    def tags(self, term=None, **kw):
+        if not term:
+            return json.dumps([])
+        db = M.session.project_doc_session.db
+        tickets = db[TM.Ticket.__mongometa__.name]
+        tags = tickets.aggregate([
+            {
+                '$match': {
+                    'app_config_id': c.app.config._id,
+                    'labels': {
+                        '$exists': True,
+                        '$ne': [],
+                    }
+                }
+            },
+            {'$project': {'labels': 1}},
+            {'$unwind': '$labels'},
+            {'$match': {'labels': {'$regex': '^%s' % term, '$options': 'i'}}},
+            {'$group': { '_id': '$labels', 'count': {'$sum': 1}}},
+            {'$sort': SON([('count', -1), ('_id', 1)])}
+        ])
+        return json.dumps([tag['_id'] for tag in tags.get('result', [])])
 
     @with_trailing_slash
     @h.vardec


[49/50] git commit: Merge branch 'master' into acs2/5518

Posted by ac...@apache.org.
Merge branch 'master' into acs2/5518


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/674348a2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/674348a2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/674348a2

Branch: refs/heads/acs2/5518
Commit: 674348a2bd1e17fc102ec5e6ad27d97950dd95fd
Parents: 9213be0 630309e
Author: Alvaro del Castillo <ac...@barrapunto.com>
Authored: Tue Apr 16 13:34:04 2013 +0200
Committer: Alvaro del Castillo <ac...@barrapunto.com>
Committed: Tue Apr 16 13:34:04 2013 +0200

----------------------------------------------------------------------
 .gitignore                                         |    1 +
 Allura/LICENSE                                     |  335 ++++++++
 Allura/NOTICE                                      |   18 +
 Allura/README.txt                                  |   24 -
 Allura/allura/app.py                               |   27 +-
 Allura/allura/command/base.py                      |   10 +-
 Allura/allura/command/reclone_repo.py              |    2 +-
 Allura/allura/command/script.py                    |    2 +-
 Allura/allura/command/show_models.py               |    2 +-
 Allura/allura/command/taskd.py                     |   10 +-
 Allura/allura/command/taskd_cleanup.py             |   12 +-
 Allura/allura/config/environment.py                |    3 -
 Allura/allura/config/middleware.py                 |   17 +-
 Allura/allura/controllers/auth.py                  |  429 ++++++----
 .../controllers/basetest_neighborhood_root.py      |    3 +-
 Allura/allura/controllers/basetest_project_root.py |    3 +-
 Allura/allura/controllers/discuss.py               |   26 +-
 Allura/allura/controllers/project.py               |   86 ++-
 Allura/allura/controllers/repository.py            |   69 ++-
 Allura/allura/controllers/rest.py                  |    3 +-
 Allura/allura/controllers/root.py                  |   19 +-
 Allura/allura/controllers/search.py                |    5 +-
 Allura/allura/controllers/site_admin.py            |  140 +++-
 Allura/allura/controllers/static.py                |    8 +-
 Allura/allura/controllers/trovecategories.py       |    3 +-
 Allura/allura/eventslistener.py                    |   63 ++
 Allura/allura/ext/admin/admin_main.py              |   23 +-
 .../templates/admin_widgets/metadata_admin.html    |    3 +
 .../allura/ext/admin/templates/project_admin.html  |    2 +-
 .../ext/admin/templates/project_overview.html      |    8 +-
 .../allura/ext/admin/templates/project_tools.html  |   28 +-
 Allura/allura/ext/admin/widgets.py                 |    3 +-
 Allura/allura/ext/project_home/project_main.py     |    4 +-
 Allura/allura/ext/search/search_main.py            |    4 +-
 Allura/allura/ext/user_profile/user_main.py        |   23 +-
 Allura/allura/i18n/ru/LC_MESSAGES/pyforge.po       |    5 +-
 Allura/allura/lib/app_globals.py                   |   43 +-
 Allura/allura/lib/base.py                          |    2 +-
 Allura/allura/lib/custom_middleware.py             |   62 ++-
 Allura/allura/lib/decorators.py                    |   10 +-
 Allura/allura/lib/graphics/graphic_methods.py      |   69 ++
 Allura/allura/lib/helpers.py                       |   39 +-
 Allura/allura/lib/import_api.py                    |    3 +
 Allura/allura/lib/macro.py                         |   65 ++-
 Allura/allura/lib/mail_util.py                     |    2 +-
 Allura/allura/lib/markdown_extensions.py           |   23 +-
 Allura/allura/lib/oid_helper.py                    |    3 +-
 Allura/allura/lib/plugin.py                        |   68 ++-
 Allura/allura/lib/repository.py                    |   22 +-
 Allura/allura/lib/search.py                        |   60 +-
 Allura/allura/lib/security.py                      |   68 ++-
 Allura/allura/lib/solr.py                          |    5 +-
 Allura/allura/lib/spam/__init__.py                 |   30 +-
 Allura/allura/lib/spam/akismetfilter.py            |   53 ++
 Allura/allura/lib/spam/akismetservice.py           |   28 -
 Allura/allura/lib/spam/mollomfilter.py             |   61 ++
 Allura/allura/lib/utils.py                         |   83 +--
 Allura/allura/lib/validators.py                    |   77 ++
 Allura/allura/lib/widgets/discuss.py               |   43 +-
 Allura/allura/lib/widgets/form_fields.py           |   87 ++-
 Allura/allura/lib/widgets/forms.py                 |  160 ++--
 Allura/allura/lib/widgets/oauth_widgets.py         |    2 +-
 Allura/allura/lib/widgets/project_list.py          |    2 +-
 .../allura/lib/widgets/resources/css/combobox.css  |   17 +
 .../lib/widgets/resources/css/jquery.tagsinput.css |    8 +
 Allura/allura/lib/widgets/resources/css/search.css |   12 +
 Allura/allura/lib/widgets/resources/js/combobox.js |  146 ++++
 .../lib/widgets/resources/js/jquery.lightbox_me.js |  198 +++--
 .../lib/widgets/resources/js/jquery.tag.editor.js  |  147 ----
 .../lib/widgets/resources/js/jquery.tagsinput.js   |  357 ++++++++
 .../resources/js/sortable_repeated_field.js        |    4 +-
 Allura/allura/lib/widgets/search.py                |    4 +-
 Allura/allura/lib/widgets/subscriptions.py         |   15 +-
 Allura/allura/model/artifact.py                    |   29 +-
 Allura/allura/model/attachments.py                 |    2 +-
 Allura/allura/model/auth.py                        |   30 +-
 Allura/allura/model/discuss.py                     |   15 +-
 Allura/allura/model/index.py                       |    2 +-
 Allura/allura/model/monq_model.py                  |   23 +-
 Allura/allura/model/neighborhood.py                |   26 +-
 Allura/allura/model/notification.py                |    9 +-
 Allura/allura/model/oauth.py                       |    2 +-
 Allura/allura/model/project.py                     |  149 +++-
 Allura/allura/model/repo.py                        |  527 +++++++++++-
 Allura/allura/model/repo_refresh.py                |  274 ++++---
 Allura/allura/model/repository.py                  |  128 +++-
 Allura/allura/model/session.py                     |    2 +-
 Allura/allura/model/stats.py                       |  643 ++++++++++++++-
 Allura/allura/nf/allura/css/allura.css             |   19 +-
 Allura/allura/nf/allura/css/site_style.css         |  124 +++-
 Allura/allura/public/nf/images/down.png            |  Bin 0 -> 2993 bytes
 Allura/allura/public/nf/images/equal.png           |  Bin 0 -> 343 bytes
 Allura/allura/public/nf/images/up.png              |  Bin 0 -> 2974 bytes
 Allura/allura/public/nf/js/allura-base.js          |   14 +-
 Allura/allura/public/nf/js/jquery.maxlength-min.js |    8 -
 Allura/allura/public/nf/js/jquery.maxlength.min.js |    7 +
 Allura/allura/public/nf/js/project_tools.js        |   11 +-
 Allura/allura/scripts/__init__.py                  |    1 +
 Allura/allura/scripts/refresh_last_commits.py      |  186 +++++
 Allura/allura/scripts/refreshrepo.py               |  155 ++++
 Allura/allura/scripts/scripttask.py                |   91 ++
 Allura/allura/tasks/index_tasks.py                 |    2 +-
 Allura/allura/tasks/mail_tasks.py                  |    2 +-
 Allura/allura/tasks/repo_tasks.py                  |   17 +-
 Allura/allura/templates/app_admin_options.html     |   10 +-
 Allura/allura/templates/jinja_master/lib.html      |   44 +-
 .../templates/jinja_master/sidebar_menu.html       |    2 +-
 .../templates/jinja_master/theme_macros.html       |    4 +-
 Allura/allura/templates/jinja_master/top_nav.html  |    8 +-
 Allura/allura/templates/mail/footer.txt            |    2 +-
 Allura/allura/templates/members.html               |   26 +
 Allura/allura/templates/neighborhood_list.html     |   31 +
 Allura/allura/templates/oauth_authorize_ok.html    |    4 +-
 Allura/allura/templates/repo/barediff.html         |    8 +-
 Allura/allura/templates/repo/commit.html           |    2 +-
 Allura/allura/templates/repo/diff.html             |    8 +-
 Allura/allura/templates/repo/file.html             |    2 +-
 Allura/allura/templates/repo/forks.html            |   13 +
 Allura/allura/templates/repo/log.html              |   54 ++-
 Allura/allura/templates/repo/tarball.html          |   77 ++
 Allura/allura/templates/repo/tree.html             |    6 +
 Allura/allura/templates/search_index.html          |    4 +-
 Allura/allura/templates/site_admin.html            |   12 +-
 .../allura/templates/site_admin_api_tickets.html   |    2 +-
 Allura/allura/templates/site_admin_task_list.html  |   93 +++
 Allura/allura/templates/site_admin_task_new.html   |  112 +++
 Allura/allura/templates/site_admin_task_view.html  |  153 ++++
 Allura/allura/templates/tool_list.html             |   21 +
 Allura/allura/templates/trovecategories.html       |    2 +-
 Allura/allura/templates/user_availability.html     |   83 ++
 Allura/allura/templates/user_contacts.html         |   58 ++
 Allura/allura/templates/user_info.html             |   47 ++
 Allura/allura/templates/user_preferences.html      |  279 -------
 Allura/allura/templates/user_prefs.html            |  140 ++++
 Allura/allura/templates/user_skills.html           |   33 +-
 Allura/allura/templates/user_subs.html             |   54 ++
 .../allura/templates/widgets/download_button.html  |    2 +-
 Allura/allura/templates/widgets/moderate_post.html |   16 +-
 .../allura/templates/widgets/moderate_posts.html   |   10 +-
 .../widgets/neighborhood_overview_form.html        |    6 +
 Allura/allura/templates/widgets/post_widget.html   |   60 +-
 .../templates/widgets/project_user_combo.html      |    5 +
 Allura/allura/templates/widgets/repo/log.html      |   13 +-
 .../allura/templates/widgets/search_results.html   |   58 +-
 Allura/allura/tests/decorators.py                  |    2 +-
 Allura/allura/tests/functional/test_admin.py       |   27 +-
 Allura/allura/tests/functional/test_auth.py        |  114 ++--
 Allura/allura/tests/functional/test_discuss.py     |   41 +-
 Allura/allura/tests/functional/test_home.py        |   26 +-
 .../allura/tests/functional/test_neighborhood.py   |   91 ++-
 Allura/allura/tests/functional/test_root.py        |    6 +-
 Allura/allura/tests/functional/test_site_admin.py  |   74 ++-
 Allura/allura/tests/functional/test_tool_list.py   |   13 +
 .../allura/tests/functional/test_user_profile.py   |    2 +-
 Allura/allura/tests/model/test_artifact.py         |    4 +-
 Allura/allura/tests/model/test_auth.py             |    9 +-
 Allura/allura/tests/model/test_discussion.py       |    6 +-
 Allura/allura/tests/model/test_neighborhood.py     |    6 +-
 Allura/allura/tests/model/test_notification.py     |    6 +-
 Allura/allura/tests/model/test_openid.py           |    3 +-
 Allura/allura/tests/model/test_project.py          |   24 +-
 Allura/allura/tests/model/test_repo.py             |  503 +++++++++++-
 Allura/allura/tests/test_app.py                    |    2 +-
 Allura/allura/tests/test_diff.py                   |  122 +++
 Allura/allura/tests/test_globals.py                |  187 +++--
 Allura/allura/tests/test_helpers.py                |   40 +-
 Allura/allura/tests/test_scripttask.py             |   24 +
 Allura/allura/tests/test_security.py               |   94 +++
 Allura/allura/tests/test_tasks.py                  |    5 +-
 Allura/allura/tests/test_utils.py                  |   64 ++-
 Allura/allura/tests/test_validators.py             |  107 +++
 Allura/allura/tests/tscript.py                     |    2 +-
 .../test_discussion_moderation_controller.py       |    5 +-
 Allura/allura/tests/unit/patches.py                |    2 +-
 Allura/allura/tests/unit/spam/test_akismet.py      |  103 +++
 Allura/allura/tests/unit/spam/test_mollom.py       |   77 ++
 Allura/allura/tests/unit/spam/test_spam_filter.py  |   40 +
 .../tests/unit/test_helpers/test_set_context.py    |    2 +-
 Allura/allura/tests/unit/test_project.py           |   59 ++
 Allura/allura/tests/unit/test_repo.py              |  252 ++++---
 Allura/allura/tests/unit/test_sitemapentry.py      |   16 +
 Allura/allura/tests/unit/test_spam.py              |   95 ---
 Allura/allura/tests/unit/test_utils.py             |  158 ----
 Allura/allura/websetup/bootstrap.py                |    3 +-
 Allura/allura/websetup/schema.py                   |    4 +-
 Allura/development.ini                             |    9 +
 Allura/docs/conf.py                                |    4 +-
 Allura/docs/tutorials/wiki-tool.rst                |    2 +-
 Allura/setup.py                                    |    4 +
 Allura/test-light.py                               |    2 +-
 Allura/test.ini                                    |    3 +
 AlluraTesting/LICENSE                              |  234 ++++++
 AlluraTesting/alluratest/controller.py             |    7 +-
 AlluraTesting/alluratest/test_syntax.py            |    5 +-
 AlluraTesting/alluratest/validation.py             |    3 +-
 CONTRIBUTING                                       |    2 +-
 ForgeActivity/forgeactivity/main.py                |    6 +-
 ForgeActivity/forgeactivity/widgets/follow.py      |    2 +-
 ForgeBlog/forgeblog/command/__init__.py            |    1 -
 ForgeBlog/forgeblog/command/rssfeeds.py            |   13 +-
 ForgeBlog/forgeblog/main.py                        |   41 +-
 ForgeBlog/forgeblog/model/blog.py                  |    9 +-
 ForgeBlog/forgeblog/templates/blog/search.html     |    6 +-
 .../templates/blog_widgets/preview_post.html       |    2 +-
 .../templates/blog_widgets/view_post.html          |    2 +-
 ForgeBlog/forgeblog/tests/test_commands.py         |   26 +-
 ForgeBlog/forgeblog/tests/test_roles.py            |    2 +-
 ForgeBlog/forgeblog/tests/unit/__init__.py         |    4 +-
 ForgeBlog/forgeblog/tests/unit/test_blog_post.py   |    2 +-
 ForgeChat/forgechat/command.py                     |    2 +-
 ForgeChat/forgechat/main.py                        |   29 +-
 ForgeChat/forgechat/templates/chat/search.html     |    6 +-
 ForgeDiscussion/NOTICE                             |    5 +
 .../forgediscussion/controllers/forum.py           |    2 +-
 .../forgediscussion/controllers/root.py            |   31 +-
 ForgeDiscussion/forgediscussion/forum_main.py      |    7 +-
 ForgeDiscussion/forgediscussion/import_support.py  |    2 +-
 ForgeDiscussion/forgediscussion/tasks.py           |    2 +-
 .../templates/discussionforums/search.html         |    4 +-
 .../forgediscussion/tests/functional/test_forum.py |   36 +-
 .../tests/functional/test_import.py                |    5 +-
 .../forgediscussion/tests/test_forum_roles.py      |    2 +-
 ForgeDiscussion/forgediscussion/widgets/admin.py   |    2 +-
 .../forgediscussion/widgets/forum_widgets.py       |   40 +-
 ForgeGit/NOTICE                                    |    5 +
 ForgeGit/forgegit/controllers.py                   |    4 +-
 ForgeGit/forgegit/git_main.py                      |    2 +-
 ForgeGit/forgegit/model/git_repo.py                |   61 ++-
 ForgeGit/forgegit/templates/git/index.html         |   16 +-
 .../5c/47243c8e424136fd5cdd18cd94d34c66d1955c      |    3 +
 .../5c/891311e2b402f3f86eabf1688b5496183d9f94      |  Bin 0 -> 24 bytes
 .../b1/42cbffd81acd7c57b47bf64fbb9e0920d82c55      |  Bin 0 -> 78 bytes
 .../forgegit/tests/data/testgit.git/refs/heads/zz  |    1 +
 .../2c/e83a24e52c21e8d2146b1a04a20717c0bb08d7      |    2 +
 .../4d/a92902b500ae6b74b8e6dea9639ebfde6a007f      |  Bin 0 -> 158 bytes
 .../82/ac89a3fa20831c99faa54331fdce563df45dc8      |  Bin 0 -> 794 bytes
 .../8d/27123659c0022b0a4a7b10f4d1fe03800a1c8c      |  Bin 0 -> 158 bytes
 .../d9/61abbbf10341ee18a668c975842c35cfc0bef2      |    1 +
 .../e1/db0418f7fe2c16e9a57b50196e6ff25c2089ca      |  Bin 0 -> 415 bytes
 .../tests/data/testmime.git/refs/heads/master      |    2 +-
 .../forgegit/tests/functional/test_controllers.py  |   81 ++-
 ForgeGit/forgegit/tests/model/test_repository.py   |  129 +++-
 ForgeGit/forgegit/tests/test_git_app.py            |    2 +-
 ForgeGit/forgegit/tests/test_tasks.py              |    2 +-
 ForgeLink/NOTICE                                   |    5 +
 ForgeLink/forgelink/link_main.py                   |    5 +-
 ForgeSVN/NOTICE                                    |    5 +
 ForgeSVN/forgesvn/controllers.py                   |    4 +-
 ForgeSVN/forgesvn/model/svn.py                     |  237 +++++--
 ForgeSVN/forgesvn/svn_main.py                      |    5 +-
 .../tests/data/testsvn/hooks/post-revprop-change   |    3 +-
 .../forgesvn/tests/functional/test_controllers.py  |   18 +-
 ForgeSVN/forgesvn/tests/model/test_repository.py   |  157 ++--
 .../forgesvn/tests/model/test_svnimplementation.py |   58 ++
 ForgeSVN/forgesvn/tests/test_svn_app.py            |    2 +-
 ForgeSVN/forgesvn/tests/test_tasks.py              |    2 +-
 ForgeSVN/setup.py                                  |    9 +
 ForgeShortUrl/forgeshorturl/command/base.py        |    5 -
 .../forgeshorturl/command/migrate_urls.py          |  106 ---
 ForgeShortUrl/forgeshorturl/main.py                |   18 +-
 ForgeShortUrl/forgeshorturl/model/shorturl.py      |    6 +-
 ForgeShortUrl/forgeshorturl/templates/search.html  |    2 +-
 .../forgeshorturl/tests/functional/test.py         |    4 +-
 ForgeShortUrl/forgeshorturl/tests/test_commands.py |   71 --
 ForgeShortUrl/setup.py                             |    2 -
 ForgeTracker/NOTICE                                |    5 +
 .../forgetracker/command/fix_discussion.py         |   84 ++
 ForgeTracker/forgetracker/import_support.py        |    9 +-
 ForgeTracker/forgetracker/model/ticket.py          |  203 ++++-
 ForgeTracker/forgetracker/tasks.py                 |   17 +
 .../forgetracker/templates/tracker/index.html      |   10 +
 .../forgetracker/templates/tracker/milestone.html  |   11 +-
 .../templates/tracker/move_ticket.html             |    9 +
 .../forgetracker/templates/tracker/search.html     |    9 +
 .../forgetracker/templates/tracker/ticket.html     |   22 +-
 .../templates/tracker_widgets/mass_edit.html       |    2 +-
 .../templates/tracker_widgets/mass_edit_form.html  |   10 +-
 .../tracker_widgets/ticket_search_results.html     |    8 +-
 .../tests/command/test_fix_discussion.py           |   65 ++
 .../forgetracker/tests/functional/test_import.py   |    5 +-
 .../forgetracker/tests/functional/test_rest.py     |    5 +-
 .../forgetracker/tests/functional/test_root.py     |  500 +++++++++++-
 .../forgetracker/tests/test_tracker_roles.py       |    2 +-
 ForgeTracker/forgetracker/tests/unit/__init__.py   |    5 +-
 .../forgetracker/tests/unit/test_globals_model.py  |   71 ++-
 .../tests/unit/test_milestone_controller.py        |    2 +-
 .../tests/unit/test_root_controller.py             |    2 +-
 .../tests/unit/test_ticket_custom_fields_form.py   |    2 +-
 .../forgetracker/tests/unit/test_ticket_form.py    |    2 +-
 .../forgetracker/tests/unit/test_ticket_model.py   |  130 +++-
 ForgeTracker/forgetracker/tracker_main.py          |  324 +++++---
 .../forgetracker/widgets/admin_custom_fields.py    |    2 +-
 .../forgetracker/widgets/resources/js/mass-edit.js |   16 +-
 ForgeTracker/forgetracker/widgets/ticket_form.py   |   93 ++-
 ForgeTracker/forgetracker/widgets/ticket_search.py |    2 +-
 ForgeTracker/setup.py                              |    3 +
 .../forgeuserstats/controllers/userstats.py        |  308 +++++++
 ForgeUserStats/forgeuserstats/main.py              |  146 ++++
 ForgeUserStats/forgeuserstats/model/stats.py       |   51 ++
 .../nf/userstats/images/stats_24.png               |  Bin 0 -> 654 bytes
 .../nf/userstats/images/stats_32.png               |  Bin 0 -> 715 bytes
 .../nf/userstats/images/stats_48.png               |  Bin 0 -> 925 bytes
 .../forgeuserstats/templates/artifacts.html        |   65 ++
 .../forgeuserstats/templates/commits.html          |   54 ++
 ForgeUserStats/forgeuserstats/templates/index.html |  435 ++++++++++
 .../forgeuserstats/templates/settings.html         |   19 +
 .../forgeuserstats/templates/tickets.html          |   64 ++
 .../forgeuserstats/tests/data/testgit.git/HEAD     |    1 +
 .../forgeuserstats/tests/data/testgit.git/config   |    4 +
 .../tests/data/testgit.git/description             |    1 +
 .../tests/data/testgit.git/info/exclude            |    6 +
 .../0d/666fc313e6f4829e8d4446d4529394f8e464a9      |  Bin 0 -> 29 bytes
 .../0f/419b54b956f4a849a689105216282f1a4c749a      |  Bin 0 -> 51 bytes
 .../1e/146e67985dcd71c74de79613719bef7bddca4a      |  Bin 0 -> 164 bytes
 .../43/80f66cf5cbd858b73156681d665593ec80a58d      |  Bin 0 -> 43 bytes
 .../4b/825dc642cb6eb9a060e54bf8d69288fbee4904      |  Bin 0 -> 15 bytes
 .../6a/45885ae7347f1cac5103b0050cc1be6a1496c8      |  Bin 0 -> 158 bytes
 .../6d/2ce67bdd55ae2c2ac72cbc879ed7c67ecc9786      |  Bin 0 -> 43 bytes
 .../8c/3c7fbcd903744b20fd7567a1fcefa99133b5bc      |  Bin 0 -> 53 bytes
 .../9a/7df788cf800241e3bb5a849c8870f2f8259d98      |  Bin 0 -> 129 bytes
 .../be/00c63250248c284b842deee5d8fb0b8132acab      |  Bin 0 -> 42 bytes
 .../d7/c40db3ffe2b87e96b94c280a67265c8de7a4ad      |  Bin 0 -> 51 bytes
 .../df/30427c488aeab84b2352bdf88a3b19223f9d7a      |    2 +
 .../e5/6a4d15295d3754310f114c86d93645308110ad      |  Bin 0 -> 43 bytes
 .../e9/65047ad7c57865823c7d992b1d046ea66edf78      |  Bin 0 -> 21 bytes
 .../tests/data/testgit.git/refs/heads/master       |    1 +
 ForgeUserStats/forgeuserstats/tests/test_model.py  |  374 +++++++++
 ForgeUserStats/forgeuserstats/tests/test_stats.py  |  185 +++++
 ForgeUserStats/forgeuserstats/version.py           |    2 +
 ForgeUserStats/forgeuserstats/widgets/forms.py     |   22 +
 ForgeUserStats/setup.py                            |   33 +
 ForgeUserStats/test.ini                            |   54 ++
 ForgeWiki/NOTICE                                   |    5 +
 ForgeWiki/forgewiki/command/__init__.py            |    1 -
 ForgeWiki/forgewiki/command/base.py                |    4 -
 .../forgewiki/command/wiki2markdown/__init__.py    |   94 ---
 .../forgewiki/command/wiki2markdown/extractors.py  |  178 ----
 .../forgewiki/command/wiki2markdown/loaders.py     |  191 -----
 ForgeWiki/forgewiki/converters.py                  |   13 +-
 ForgeWiki/forgewiki/model/wiki.py                  |   13 +-
 .../forgewiki/scripts/wiki2markdown/__init__.py    |    1 +
 .../forgewiki/scripts/wiki2markdown/extractors.py  |  171 ++++
 .../forgewiki/scripts/wiki2markdown/loaders.py     |  182 ++++
 .../scripts/wiki2markdown/wiki2markdown.py         |  109 +++
 ForgeWiki/forgewiki/templates/wiki/page_view.html  |    4 +-
 ForgeWiki/forgewiki/templates/wiki/search.html     |    2 +-
 ForgeWiki/forgewiki/tests/functional/test_root.py  |    6 +-
 ForgeWiki/forgewiki/tests/test_wiki2markdown.py    |    8 +-
 ForgeWiki/forgewiki/tests/test_wiki_roles.py       |    2 +-
 ForgeWiki/forgewiki/wiki_main.py                   |   67 ++-
 Makefile                                           |    8 +
 Makefile.def.buildbot                              |    8 +-
 NoWarnings/NOTICE                                  |    5 +
 NoWarnings/setup.py                                |    1 -
 README.markdown                                    |   92 +--
 rebuild-all.bash                                   |    9 +
 rebuild.bash                                       |    8 -
 requirements-common.txt                            |   16 +-
 requirements-optional.txt                          |    7 +
 requirements-sf.txt                                |   10 +-
 requirements.txt                                   |    8 +-
 run_clonedigger                                    |    3 +-
 run_tests                                          |    2 +-
 scripts/allura_import.py                           |   16 +-
 scripts/benchmark-scm.py                           |  125 +++
 scripts/create-allura-sitemap.py                   |    2 +-
 scripts/migrate_project_database.py                |    2 +-
 scripts/migrations/000-fix-tracker-fields.py       |    2 +-
 scripts/migrations/001-restore-labels.py           |    2 +-
 .../migrations/002-fix-tracker-thread-subjects.py  |    2 +-
 scripts/migrations/003-migrate_project_roles.py    |    2 +-
 .../migrations/004-make-attachments-polymorphic.py |    2 +-
 scripts/migrations/006-migrate-artifact-refs.py    |    2 +-
 scripts/migrations/007-update-acls.py              |    2 +-
 scripts/migrations/010-fix-home-permissions.py     |    2 +-
 scripts/migrations/012-uninstall-home.py           |    2 +-
 scripts/migrations/013-update-ordinals.py          |    2 +-
 scripts/migrations/014-add-trove-category-agpl.py  |    2 +-
 .../015-add-neighborhood_id-to-blog-posts.py       |    2 +-
 scripts/migrations/016-add-trove-category-lppl.py  |    2 +-
 scripts/migrations/017-sync-trove-categories.py    |    2 +-
 .../migrations/020-remove-wiki-title-slashes.py    |    2 +-
 .../migrations/024-migrate-custom-profile-text.py  |    2 +-
 scripts/migrations/025-add-is-nbhd-project.py      |    2 +-
 .../027-change-ticket-write-permissions.py         |    2 +-
 scripts/project-import.py                          |    2 +-
 scripts/publicize-neighborhood.py                  |    2 +-
 scripts/refresh-all-repos.py                       |  169 ----
 scripts/rethumb.py                                 |    2 +-
 scripts/scrub-allura-data.py                       |    2 +-
 scripts/teamforge-import.py                        |    2 +-
 update.sh                                          |    4 +-
 vagrant/README                                     |   14 +-
 vagrant/Vagrantfile                                |    6 +-
 vagrant/allura_setup.sh                            |   18 +-
 vagrant/manifests/ubuntu-1204-server-amd64.pp      |  134 +++
 vagrant/start_allura                               |    6 +-
 397 files changed, 13071 insertions(+), 3740 deletions(-)
----------------------------------------------------------------------



[37/50] git commit: [#4504] Fixed $USER search for *anonymous

Posted by ac...@apache.org.
[#4504] Fixed $USER search for *anonymous

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/96479410
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/96479410
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/96479410

Branch: refs/heads/acs2/5518
Commit: 964794109250beb17c0780b9cc2155c41783699f
Parents: f785c52
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Fri Apr 12 17:08:17 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Fri Apr 12 17:08:17 2013 +0000

----------------------------------------------------------------------
 Allura/allura/lib/search.py         |    2 +-
 Allura/allura/tests/test_helpers.py |    7 +++++--
 2 files changed, 6 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96479410/Allura/allura/lib/search.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/search.py b/Allura/allura/lib/search.py
index 89d1d6e..b4bbd2f 100644
--- a/Allura/allura/lib/search.py
+++ b/Allura/allura/lib/search.py
@@ -26,7 +26,7 @@ def inject_user(q, user=None):
     '''Replace $USER with current user's name.'''
     if user is None:
         user = c.user
-    return q.replace('$USER', user.username) if q else q
+    return q.replace('$USER', '"%s"' % user.username) if q else q
 
 def search(q,short_timeout=False,ignore_errors=True,**kw):
     q = inject_user(q)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/96479410/Allura/allura/tests/test_helpers.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index 8a7065f..ed919b0 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -194,7 +194,10 @@ def test_inject_user(context):
     assert_equals(inject_user('', user), '')
     assert_equals(inject_user('query', user), 'query')
     result = inject_user('reported_by_s:$USER OR assigned_to_s:$USER', user)
-    assert_equals(result, 'reported_by_s:user01 OR assigned_to_s:user01')
+    assert_equals(result, 'reported_by_s:"user01" OR assigned_to_s:"user01"')
     context.user = Mock(username='admin1')
     result = inject_user('reported_by_s:$USER OR assigned_to_s:$USER')
-    assert_equals(result, 'reported_by_s:admin1 OR assigned_to_s:admin1')
+    assert_equals(result, 'reported_by_s:"admin1" OR assigned_to_s:"admin1"')
+    context.user = Mock(username='*anonymous')
+    result = inject_user('reported_by_s:$USER OR assigned_to_s:$USER')
+    assert_equals(result, 'reported_by_s:"*anonymous" OR assigned_to_s:"*anonymous"')


[20/50] git commit: [#5673] Removed unused mass-edit views on Milestone controller

Posted by ac...@apache.org.
[#5673] Removed unused mass-edit views on Milestone controller

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/46780f88
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/46780f88
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/46780f88

Branch: refs/heads/acs2/5518
Commit: 46780f88bbbc4fd39b2c5b2a10529f436d987e6c
Parents: 17728a5
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Thu Apr 4 18:48:08 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Apr 4 18:48:23 2013 +0000

----------------------------------------------------------------------
 ForgeTracker/forgetracker/tracker_main.py |   59 ------------------------
 1 files changed, 0 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/46780f88/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index bec418e..7cde33e 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -1698,62 +1698,3 @@ class MilestoneController(BaseController):
         c.ticket_search_results = W.ticket_search_results
         c.auto_resize_textarea = W.auto_resize_textarea
         return result
-
-    @with_trailing_slash
-    @expose('jinja:forgetracker:templates/tracker/mass_edit.html')
-    @validate(dict(q=validators.UnicodeString(if_empty=None),
-                   limit=validators.Int(if_empty=10),
-                   page=validators.Int(if_empty=0),
-                   sort=validators.UnicodeString(if_empty='ticket_num_i asc')))
-    def edit(self, q=None, limit=None, page=None, sort=None, columns=None, **kw):
-        require_access(c.app, 'update')
-        result = TM.Ticket.paged_query(c.app.config, c.user,
-            self.mongo_query, page=page, sort=sort, **kw)
-        result['columns'] = columns or mongo_columns()
-        result['sortable_custom_fields'] = c.app.globals.sortable_custom_fields_shown_in_search()
-        # if c.app.globals.milestone_names is None:
-        #     c.app.globals.milestone_names = ''
-        result.pop('q')
-        result['globals'] = c.app.globals
-        result['cancel_href'] = '..'
-        c.user_select = ffw.ProjectUserCombo()
-        c.mass_edit = W.mass_edit
-        c.mass_edit_form = W.mass_edit_form
-        return result
-
-    @expose()
-    @require_post()
-    def update_tickets(self, **post_data):
-        tickets = TM.Ticket.query.find(dict(
-                _id={'$in':[ObjectId(id) for id in post_data['selected'].split(',')]},
-                app_config_id=c.app.config._id)).all()
-        for ticket in tickets:
-            require_access(ticket, 'update')
-
-        fields = set(['status'])
-        values = {}
-        for k in fields:
-            v = post_data.get(k)
-            if v: values[k] = v
-        assigned_to = post_data.get('assigned_to')
-        if assigned_to == '-':
-            values['assigned_to_id'] = None
-        elif assigned_to is not None:
-            user = c.project.user_in_project(assigned_to)
-            if user:
-                values['assigned_to_id'] = user._id
-
-        custom_fields = set([cf.name for cf in c.app.globals.custom_fields or[]])
-        custom_values = {}
-        for k in custom_fields:
-            v = post_data.get(k)
-            if v: custom_values[k] = v
-
-        for ticket in tickets:
-            for k, v in values.iteritems():
-                setattr(ticket, k, v)
-            for k, v in custom_values.iteritems():
-                ticket.custom_fields[k] = v
-
-        c.app.globals.invalidate_bin_counts()
-        ThreadLocalORMSession.flush_all()


[10/50] git commit: [#5453] Fixed bug in userstats model

Posted by ac...@apache.org.
[#5453] Fixed bug in userstats model


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/719ec685
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/719ec685
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/719ec685

Branch: refs/heads/acs2/5518
Commit: 719ec6859e47600913ad8f9e4ade4b2c9a2591a0
Parents: cfb3805
Author: Stefano Invernizzi <st...@apache.org>
Authored: Sat Mar 9 16:34:02 2013 +0100
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:37 2013 +0000

----------------------------------------------------------------------
 ForgeUserStats/forgeuserstats/model/stats.py |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/719ec685/ForgeUserStats/forgeuserstats/model/stats.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/model/stats.py b/ForgeUserStats/forgeuserstats/model/stats.py
index 8575e79..4171d52 100644
--- a/ForgeUserStats/forgeuserstats/model/stats.py
+++ b/ForgeUserStats/forgeuserstats/model/stats.py
@@ -25,8 +25,10 @@ class UserStats(Stats):
         stats = cls(user_id=user._id,
             registration_date = datetime.utcnow())
         user.stats_id = stats._id
-        session(stats).flush(stats)
-        session(user).flush(user)
+        if session(stats):
+            session(stats).flush(stats)
+        if session(user):
+            session(user).flush(user)
         return stats
 
     def getLastMonthLogins(self):


[35/50] git commit: [#4504] ticket:311 Replace $USER with actual username in a search query

Posted by ac...@apache.org.
[#4504] ticket:311 Replace $USER with actual username in a search query


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/f8c30d49
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/f8c30d49
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/f8c30d49

Branch: refs/heads/acs2/5518
Commit: f8c30d4909cbadd3c27c64867ae78d0888e8cd19
Parents: 6f04547
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Apr 9 14:45:13 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Fri Apr 12 17:07:49 2013 +0000

----------------------------------------------------------------------
 Allura/allura/lib/search.py         |    7 +++++++
 Allura/allura/tests/test_helpers.py |   13 +++++++++++++
 2 files changed, 20 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/f8c30d49/Allura/allura/lib/search.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/search.py b/Allura/allura/lib/search.py
index a428c53..89d1d6e 100644
--- a/Allura/allura/lib/search.py
+++ b/Allura/allura/lib/search.py
@@ -22,7 +22,14 @@ def solarize(obj):
 class SearchError(SolrError):
     pass
 
+def inject_user(q, user=None):
+    '''Replace $USER with current user's name.'''
+    if user is None:
+        user = c.user
+    return q.replace('$USER', user.username) if q else q
+
 def search(q,short_timeout=False,ignore_errors=True,**kw):
+    q = inject_user(q)
     try:
         if short_timeout:
             return g.solr_short_timeout.search(q, **kw)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/f8c30d49/Allura/allura/tests/test_helpers.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index 2e80b56..8a7065f 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -7,6 +7,7 @@ from nose.tools import eq_, assert_equals
 
 from allura import model as M
 from allura.lib import helpers as h
+from allura.lib.search import inject_user
 from allura.tests import decorators as td
 from alluratest.controller import setup_basic_test
 
@@ -185,3 +186,15 @@ def test_get_first():
     assert_equals(h.get_first({'title': ['Value']}, 'title'), 'Value')
     assert_equals(h.get_first({'title': []}, 'title'), None)
     assert_equals(h.get_first({'title': ['Value']}, 'title'), 'Value')
+
+@patch('allura.lib.search.c')
+def test_inject_user(context):
+    user = Mock(username='user01')
+    assert_equals(inject_user(None, user), None)
+    assert_equals(inject_user('', user), '')
+    assert_equals(inject_user('query', user), 'query')
+    result = inject_user('reported_by_s:$USER OR assigned_to_s:$USER', user)
+    assert_equals(result, 'reported_by_s:user01 OR assigned_to_s:user01')
+    context.user = Mock(username='admin1')
+    result = inject_user('reported_by_s:$USER OR assigned_to_s:$USER')
+    assert_equals(result, 'reported_by_s:admin1 OR assigned_to_s:admin1')


[19/50] git commit: [#5453] only count commits for incremental commits, not full refreshes

Posted by ac...@apache.org.
[#5453] only count commits for incremental commits, not full refreshes


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/e81542a2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/e81542a2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/e81542a2

Branch: refs/heads/acs2/5518
Commit: e81542a2cd132895e549019e1f517f7d0111b4ac
Parents: 2e6c61f
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Wed Mar 27 21:04:59 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Apr 4 18:37:38 2013 +0000

----------------------------------------------------------------------
 Allura/allura/model/repo_refresh.py |   15 ++++++++-------
 1 files changed, 8 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/e81542a2/Allura/allura/model/repo_refresh.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/repo_refresh.py b/Allura/allura/model/repo_refresh.py
index 799d3cc..d06e879 100644
--- a/Allura/allura/model/repo_refresh.py
+++ b/Allura/allura/model/repo_refresh.py
@@ -112,13 +112,14 @@ def refresh_repo(repo, all_commits=False, notify=True, new_clone=False):
             if (i+1) % 100 == 0:
                 log.info('Compute last commit info %d: %s', (i+1), ci._id)
 
-    for commit in commit_ids:
-        new = repo.commit(commit)
-        user = User.by_email_address(new.committed.email)
-        if user is None:
-            user = User.by_username(new.committed.name)
-        if user is not None:
-            g.statsUpdater.newCommit(new, repo.app_config.project, user)
+    if not all_commits:
+        for commit in commit_ids:
+            new = repo.commit(commit)
+            user = User.by_email_address(new.committed.email)
+            if user is None:
+                user = User.by_username(new.committed.name)
+            if user is not None:
+                g.statsUpdater.newCommit(new, repo.app_config.project, user)
 
     log.info('Refresh complete for %s', repo.full_fs_path)
     g.post_event('repo_refreshed', len(commit_ids), all_commits, new_clone)