@@ -109,101 +109,99 @@ class SummaryController(BaseRepoControll
c.repo_tags = OrderedDict()
for name, hash in c.rhodecode_repo.tags.items()[:10]:
try:
c.repo_tags[name] = c.rhodecode_repo.get_changeset(hash)
except ChangesetError:
c.repo_tags[name] = EmptyChangeset(hash)
c.repo_branches = OrderedDict()
for name, hash in c.rhodecode_repo.branches.items()[:10]:
c.repo_branches[name] = c.rhodecode_repo.get_changeset(hash)
c.repo_branches[name] = EmptyChangeset(hash)
td = date.today() + timedelta(days=1)
td_1m = td - timedelta(days=calendar.mdays[td.month])
td_1y = td - timedelta(days=365)
ts_min_m = mktime(td_1m.timetuple())
ts_min_y = mktime(td_1y.timetuple())
ts_max_y = mktime(td.timetuple())
if dbrepo.enable_statistics:
c.show_stats = True
c.no_data_msg = _('No data loaded yet')
run_task(get_commits_stats, c.dbrepo.repo_name, ts_min_y, ts_max_y)
else:
c.show_stats = False
c.no_data_msg = _('Statistics are disabled for this repository')
c.ts_min = ts_min_m
c.ts_max = ts_max_y
stats = self.sa.query(Statistics)\
.filter(Statistics.repository == dbrepo)\
.scalar()
c.stats_percentage = 0
if stats and stats.languages:
c.no_data = False is dbrepo.enable_statistics
lang_stats_d = json.loads(stats.languages)
c.commit_data = stats.commit_activity
c.overview_data = stats.commit_activity_combined
lang_stats = ((x, {"count": y,
"desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
for x, y in lang_stats_d.items())
c.trending_languages = json.dumps(OrderedDict(
sorted(lang_stats, reverse=True,
key=lambda k: k[1])[:10]
)
c.trending_languages = json.dumps(
sorted(lang_stats, reverse=True, key=lambda k: k[1])[:10]
last_rev = stats.stat_on_revision + 1
c.repo_last_rev = c.rhodecode_repo.count()\
if c.rhodecode_repo.revisions else 0
if last_rev == 0 or c.repo_last_rev == 0:
pass
c.stats_percentage = '%.2f' % ((float((last_rev)) /
c.repo_last_rev) * 100)
c.commit_data = json.dumps({})
c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10]])
c.trending_languages = json.dumps({})
c.no_data = True
c.enable_downloads = dbrepo.enable_downloads
if c.enable_downloads:
c.download_options = self._get_download_links(c.rhodecode_repo)
c.readme_data, c.readme_file = self.__get_readme_data(c.rhodecode_repo)
return render('summary/summary.html')
def __get_readme_data(self, repo):
@cache_region('long_term')
def _get_readme_from_cache(key):
readme_data = None
readme_file = None
log.debug('Fetching readme file')
cs = repo.get_changeset('tip')
renderer = MarkupRenderer()
for f in README_FILES:
readme = cs.get_node(f)
readme_file = f
readme_data = renderer.render(readme.content, f)
log.debug('Found readme %s' % readme_file)
break
except NodeDoesNotExistError:
continue
except EmptyRepositoryError:
except Exception:
log.error(traceback.format_exc())
return readme_data, readme_file
@@ -42,168 +42,169 @@ except ImportError:
from itertools import izip_longest
except ImportError:
import itertools
def izip_longest(*args, **kwds): # noqa
fillvalue = kwds.get("fillvalue")
def sentinel(counter=([fillvalue] * (len(args) - 1)).pop):
yield counter() # yields the fillvalue, or raises IndexError
fillers = itertools.repeat(fillvalue)
iters = [itertools.chain(it, sentinel(), fillers)
for it in args]
for tup in itertools.izip(*iters):
yield tup
except IndexError:
#==============================================================================
# OrderedDict
# Python Software Foundation License
# XXX: it feels like using the class with "is" and "is not" instead of "==" and
# "!=" should be faster.
class _Nil(object):
def __repr__(self):
return "nil"
def __eq__(self, other):
if (isinstance(other, _Nil)):
return True
return NotImplemented
def __ne__(self, other):
return False
_nil = _Nil()
class _odict(object):
"""Ordered dict data structure, with O(1) complexity for dict operations
that modify one element.
Overwriting values doesn't change their original sequential order.
"""
def _dict_impl(self):
return None
def __init__(self, data=(), **kwds):
"""This doesn't accept keyword initialization as normal dicts to avoid
a trap - inside a function or method the keyword args are accessible
only as a dict, without a defined order, so their original order is
lost.
if kwds:
raise TypeError("__init__() of ordered dict takes no keyword "
"arguments to avoid an ordering trap.")
self._dict_impl().__init__(self)
# If you give a normal dict, then the order of elements is undefined
if hasattr(data, "iteritems"):
for key, val in data.iteritems():
self[key] = val
for key, val in data:
# Double-linked list header
def _get_lh(self):
dict_impl = self._dict_impl()
if not hasattr(self, '_lh'):
dict_impl.__setattr__(self, '_lh', _nil)
return dict_impl.__getattribute__(self, '_lh')
def _set_lh(self, val):
self._dict_impl().__setattr__(self, '_lh', val)
lh = property(_get_lh, _set_lh)
# Double-linked list tail
def _get_lt(self):
if not hasattr(self, '_lt'):
dict_impl.__setattr__(self, '_lt', _nil)
return dict_impl.__getattribute__(self, '_lt')
def _set_lt(self, val):
self._dict_impl().__setattr__(self, '_lt', val)
lt = property(_get_lt, _set_lt)
def __getitem__(self, key):
return self._dict_impl().__getitem__(self, key)[1]
def __setitem__(self, key, val):
dict_impl.__getitem__(self, key)[1] = val
except KeyError, e:
except KeyError:
new = [dict_impl.__getattribute__(self, 'lt'), val, _nil]
dict_impl.__setitem__(self, key, new)
if dict_impl.__getattribute__(self, 'lt') == _nil:
dict_impl.__setattr__(self, 'lh', key)
dict_impl.__getitem__(
self, dict_impl.__getattribute__(self, 'lt'))[2] = key
dict_impl.__setattr__(self, 'lt', key)
def __delitem__(self, key):
pred, _ , succ = self._dict_impl().__getitem__(self, key)
pred, _, succ = self._dict_impl().__getitem__(self, key)
if pred == _nil:
dict_impl.__setattr__(self, 'lh', succ)
dict_impl.__getitem__(self, pred)[2] = succ
if succ == _nil:
dict_impl.__setattr__(self, 'lt', pred)
dict_impl.__getitem__(self, succ)[0] = pred
dict_impl.__delitem__(self, key)
def __contains__(self, key):
return key in self.keys()
def __len__(self):
return len(self.keys())
def __str__(self):
pairs = ("%r: %r" % (k, v) for k, v in self.iteritems())
return "{%s}" % ", ".join(pairs)
if self:
pairs = ("(%r, %r)" % (k, v) for k, v in self.iteritems())
return "odict([%s])" % ", ".join(pairs)
return "odict()"
def get(self, k, x=None):
if k in self:
return self._dict_impl().__getitem__(self, k)[1]
return x
def __iter__(self):
curr_key = dict_impl.__getattribute__(self, 'lh')
while curr_key != _nil:
yield curr_key
curr_key = dict_impl.__getitem__(self, curr_key)[2]
iterkeys = __iter__
def keys(self):
return list(self.iterkeys())
def itervalues(self):
@@ -306,74 +307,75 @@ class _odict(object):
curr_key, val, _ = dict_impl.__getitem__(self, curr_key)
yield val
def rvalues(self):
"""List of the values in reversed order.
return list(self.ritervalues())
def riteritems(self):
"""To iterate on (key, value) in reversed order.
curr_key = dict_impl.__getattribute__(self, 'lt')
pred_key, val, _ = dict_impl.__getitem__(self, curr_key)
yield curr_key, val
curr_key = pred_key
def ritems(self):
"""List of the (key, value) in reversed order.
return list(self.riteritems())
def firstkey(self):
return self._dict_impl().__getattribute__(self, 'lh')
raise KeyError("'firstkey(): ordered dictionary is empty'")
def lastkey(self):
return self._dict_impl().__getattribute__(self, 'lt')
raise KeyError("'lastkey(): ordered dictionary is empty'")
def as_dict(self):
return self._dict_impl()(self.items())
def _repr(self):
"""_repr(): low level repr of the whole data contained in the odict.
Useful for debugging.
form = "odict low level repr lh,lt,data: %r, %r, %s"
return form % (dict_impl.__getattribute__(self, 'lh'),
dict_impl.__getattribute__(self, 'lt'),
dict_impl.__repr__(self))
class OrderedDict(_odict, dict):
return dict
# OrderedSet
from sqlalchemy.util import OrderedSet
# kill FUNCTIONS
if __platform__ in PLATFORM_WIN:
import ctypes
def kill(pid, sig):
"""kill function for Win32"""
kernel32 = ctypes.windll.kernel32
handle = kernel32.OpenProcess(1, 0, pid)
return (0 != kernel32.TerminateProcess(handle, 0))
kill = os.kill
@@ -250,123 +250,125 @@ YUE.on('clone_by_name','click',function(
// hide url by id and show name button
YUD.setStyle('clone_by_id','display','');
YUD.setStyle('clone_url_id','display','none');
})
YUE.on('clone_by_id','click',function(e){
// show url by id and hide id button
YUD.setStyle('clone_by_id','display','none');
YUD.setStyle('clone_url_id','display','');
// hide url by name and show id button
YUD.setStyle('clone_by_name','display','');
YUD.setStyle('clone_url','display','none');
var tmpl_links = {};
%for cnt,archive in enumerate(c.rhodecode_repo._get_archives()):
tmpl_links["${archive['type']}"] = '${h.link_to('__NAME__', h.url('files_archive_home',repo_name=c.dbrepo.repo_name, fname='__CS__'+archive['extension'],subrepos='__SUB__'),class_='archive_icon ui-btn')}';
%endfor
YUE.on(['download_options','archive_subrepos'],'change',function(e){
var sm = YUD.get('download_options');
var new_cs = sm.options[sm.selectedIndex];
for(k in tmpl_links){
var s = YUD.get(k+'_link');
if(s){
var title_tmpl = "${_('Download %s as %s') % ('__CS_NAME__','__CS_EXT__')}";
title_tmpl= title_tmpl.replace('__CS_NAME__',new_cs.text);
title_tmpl = title_tmpl.replace('__CS_EXT__',k);
var url = tmpl_links[k].replace('__CS__',new_cs.value);
var subrepos = YUD.get('archive_subrepos').checked;
url = url.replace('__SUB__',subrepos);
url = url.replace('__NAME__',title_tmpl);
s.innerHTML = url
}
});
</script>
%if c.show_stats:
<script type="text/javascript">
var data = ${c.trending_languages|n};
var total = 0;
var no_data = true;
for (k in data){
total += data[k].count;
no_data = false;
var tbl = document.createElement('table');
tbl.setAttribute('class','trending_language_tbl');
var cnt = 0;
for (var i=0;i<data.length;i++){
total += data[i][1].count;
cnt += 1;
var hide = cnt>2;
var tr = document.createElement('tr');
if (hide){
tr.setAttribute('style','display:none');
tr.setAttribute('class','stats_hidden');
var percentage = Math.round((data[k].count/total*100),2);
var value = data[k].count;
var k = data[i][0];
var obj = data[i][1];
var percentage = Math.round((obj.count/total*100),2);
var td1 = document.createElement('td');
td1.width = 150;
var trending_language_label = document.createElement('div');
trending_language_label.innerHTML = data[k].desc+" ("+k+")";
trending_language_label.innerHTML = obj.desc+" ("+k+")";
td1.appendChild(trending_language_label);
var td2 = document.createElement('td');
td2.setAttribute('style','padding-right:14px !important');
var trending_language = document.createElement('div');
var nr_files = value+" ${_('files')}";
var nr_files = obj.count+" ${_('files')}";
trending_language.title = k+" "+nr_files;
if (percentage>22){
trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";
else{
trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
trending_language.style.width=percentage+"%";
td2.appendChild(trending_language);
tr.appendChild(td1);
tr.appendChild(td2);
tbl.appendChild(tr);
if(cnt == 3){
var show_more = document.createElement('tr');
var td = document.createElement('td');
lnk = document.createElement('a');
lnk.href='#';
lnk.innerHTML = "${_('show more')}";
lnk.id='code_stats_show_more';
td.appendChild(lnk);
show_more.appendChild(td);
show_more.appendChild(document.createElement('td'));
tbl.appendChild(show_more);
YUD.get('lang_stats').appendChild(tbl);
YUE.on('code_stats_show_more','click',function(){
l = YUD.getElementsByClassName('stats_hidden')
for (e in l){
YUD.setStyle(l[e],'display','');
};
YUD.setStyle(YUD.get('code_stats_show_more'),
'display','none');
/**
* Plots summary graph
*
Status change: