.. _changelog:
Changelog
=========
1.1.0 (**2010-XX-XX**)
1.2.0 (**2010-12-18**)
----------------------
:status: in-progress
:branch: beta
news
++++
- implemented #91 added nicer looking archive urls
fixes
1.1.0 (**2010-12-18**)
- rewrite of internals for vcs >=0.1.10
- uses mercurial 1.7 with dotencode disabled for maintaining compatibility
with older clients
- anonymous access, authentication via ldap
- performance upgrade for cached repos list - each repository has it's own
cache that's invalidated when needed.
- performance upgrades on repositories with large amount of commits (20K+)
- main page quick filter for filtering repositories
- user dashboards with ability to follow chosen repositories actions
- sends email to admin on new user registration
- added cache/statistics reset options into repository settings
- more detailed action logger (based on hooks) with pushed changesets lists
@@ -108,14 +120,13 @@ fixes
1.0.0rc3 (**2010-10-11**)
-------------------------
- fixed i18n during installation.
1.0.0rc2 (**2010-10-11**)
- Disabled dirsize in file browser, it's causing nasty bug when dir renames
occure. After vcs is fixed it'll be put back again.
- templating/css rewrites, optimized css.
\ No newline at end of file
@@ -180,26 +180,26 @@ def make_map(config):
map.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
controller='files', action='diff', revision='tip', f_path='',
conditions=dict(function=check_repo))
map.connect('files_rawfile_home', '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
controller='files', action='rawfile', revision='tip', f_path='',
map.connect('files_raw_home', '/{repo_name:.*}/raw/{revision}/{f_path:.*}',
controller='files', action='raw', revision='tip', f_path='',
map.connect('files_annotate_home', '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
controller='files', action='annotate', revision='tip', f_path='',
map.connect('files_archive_home', '/{repo_name:.*}/archive/{revision}/{fileformat}',
controller='files', action='archivefile', revision='tip',
map.connect('files_archive_home', '/{repo_name:.*}/archive/{fname}',
controller='files', action='archivefile',
map.connect('repo_settings_delete', '/{repo_name:.*}/settings',
controller='settings', action="delete",
conditions=dict(method=["DELETE"], function=check_repo))
map.connect('repo_settings_update', '/{repo_name:.*}/settings',
controller='settings', action="update",
conditions=dict(method=["PUT"], function=check_repo))
map.connect('repo_settings_home', '/{repo_name:.*}/settings',
controller='settings', action='index',
map.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
@@ -30,25 +30,25 @@ import rhodecode.lib.helpers as h
from mercurial import archival
from pylons import request, response, session, tmpl_context as c, url
from pylons.i18n.translation import _
from pylons.controllers.util import redirect
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
from rhodecode.lib.base import BaseController, render
from rhodecode.lib.utils import EmptyChangeset
from rhodecode.model.scm import ScmModel
from vcs.exceptions import RepositoryError, ChangesetError
from vcs.exceptions import RepositoryError, ChangesetError, ChangesetDoesNotExistError
from vcs.nodes import FileNode
from vcs.utils import diffs as differ
log = logging.getLogger(__name__)
class FilesController(BaseController):
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
def __before__(self):
super(FilesController, self).__before__()
@@ -124,50 +124,60 @@ class FilesController(BaseController):
c.cs = c.repo.get_changeset(revision)
c.file = c.cs.get_node(f_path)
except RepositoryError, e:
h.flash(str(e), category='warning')
redirect(h.url('files_home', repo_name=repo_name, revision=revision))
c.file_history = self._get_history(c.repo, c.file, f_path)
c.f_path = f_path
return render('files/files_annotate.html')
def archivefile(self, repo_name, revision, fileformat):
def archivefile(self, repo_name, fname):
info = fname.split('.')
revision, fileformat = info[0], '.' + '.'.join(info[1:])
archive_specs = {
'.tar.bz2': ('application/x-tar', 'tbz2'),
'.tar.gz': ('application/x-tar', 'tgz'),
'.zip': ('application/zip', 'zip'),
}
if not archive_specs.has_key(fileformat):
return 'Unknown archive type %s' % fileformat
return _('Unknown archive type %s') % fileformat
repo = ScmModel().get_repo(repo_name)
try:
repo.get_changeset(revision)
except ChangesetDoesNotExistError:
return _('Unknown revision %s') % revision
archive = tempfile.TemporaryFile()
localrepo = repo.repo
fname = '%s-%s%s' % (repo_name, revision, fileformat)
archival.archive(localrepo, archive, revision, archive_specs[fileformat][1],
prefix='%s-%s' % (repo_name, revision))
response.content_type = archive_specs[fileformat][0]
response.content_disposition = 'attachment; filename=%s' % fname
archive.seek(0)
def read_in_chunks(file_object, chunk_size=1024 * 40):
"""Lazy function (generator) to read a file piece by piece.
Default chunk size: 40k."""
while True:
data = file_object.read(chunk_size)
if not data:
break
yield data
repo = ScmModel().get_repo(repo_name).repo
archival.archive(repo, archive, revision, archive_specs[fileformat][1],
return read_in_chunks(archive)
def diff(self, repo_name, f_path):
hg_model = ScmModel()
diff1 = request.GET.get('diff1')
diff2 = request.GET.get('diff2')
c.action = request.GET.get('diff')
c.no_changes = diff1 == diff2
c.repo = hg_model.get_repo(c.repo_name)
@@ -214,25 +214,25 @@
<div class="field">
<div class="label">
<label>${_('Download')}:</label>
</div>
<div class="input-short">
%for cnt,archive in enumerate(c.repo_info._get_archives()):
%if cnt >=1:
|
%endif
${h.link_to(c.repo_info.name+'.'+archive['type'],
h.url('files_archive_home',repo_name=c.repo_info.name,
revision='tip',fileformat=archive['extension']),class_="archive_icon")}
fname='tip'+archive['extension']),class_="archive_icon")}
%endfor
<label>${_('Feeds')}:</label>
${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.repo_info.name),class_='rss_icon')}
${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.repo_info.name),class_='atom_icon')}
import sys
py_version = sys.version_info
from rhodecode import get_version
requirements = [
"Pylons==1.0.0",
"SQLAlchemy==0.6.5",
"SQLAlchemy>=0.6.5",
"Mako==0.3.6",
"vcs==0.1.10",
"pygments==1.3.1",
"mercurial==1.7.2",
"whoosh==1.3.4",
"celery==2.1.4",
"vcs=>0.1.10",
"pygments>=1.3.1",
"mercurial>=1.7.2",
"whoosh>=1.3.4",
"celery>=2.1.4",
"py-bcrypt",
"babel",
]
classifiers = ['Development Status :: 4 - Beta',
'Environment :: Web Environment',
'Framework :: Pylons',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Programming Language :: Python', ]
Status change: