You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by st...@apache.org on 2013/03/24 11:24:48 UTC
git commit: [#5453] Remove old stats.py file, improve userstats code
Updated Branches:
refs/heads/si/5453 2e6455f0a -> 1f65da837
[#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/1f65da83
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/1f65da83
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/1f65da83
Branch: refs/heads/si/5453
Commit: 1f65da8372ea7c591612587c39e808a3d59c0c3f
Parents: 2e6455f
Author: Stefano Invernizzi <st...@apache.org>
Authored: Sun Mar 24 11:00:39 2013 +0100
Committer: Stefano Invernizzi <st...@apache.org>
Committed: Sun Mar 24 11:00:39 2013 +0100
----------------------------------------------------------------------
Allura/allura/controllers/auth.py | 12 -
Allura/allura/controllers/site_admin.py | 8 +-
.../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, 656 insertions(+), 1154 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/1f65da83/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index f993ec4..2914799 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/1f65da83/Allura/allura/controllers/site_admin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index 096aba7..0457a9b 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -53,9 +53,9 @@ 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):
+ '''@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():
@@ -75,7 +75,7 @@ class SiteAdminController(object):
stats = sorted(stats.iteritems(), key=lambda x:-x[1]['total'])
return dict(
agg_timings=agg_timings,
- stats=stats[:int(limit)])
+ stats=stats[:int(limit)])'''
@expose('jinja:allura:templates/site_admin_api_tickets.html')
@without_trailing_slash
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/1f65da83/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/1f65da83/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 2c8038f..1e1df69 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/1f65da83/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/1f65da83/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/1f65da83/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> </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/1f65da83/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/1f65da83/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/1f65da83/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/1f65da83/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/1f65da83/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/1f65da83/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/1f65da83/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/1f65da83/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/1f65da83/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/1f65da83/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/1f65da83/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/1f65da83/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/1f65da83/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/1f65da83/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