# HG changeset patch # User Marcin Kuzminski # Date 2011-09-22 01:33:29 # Node ID 7b67b0dcad6d136c1ecea8376de92ad8b29b941c # Parent a39c0e5fca898a1eecf0c3f66f412db82d3f5fbd Added initial support for creating new nodes in repos diff --git a/rhodecode/config/routing.py b/rhodecode/config/routing.py --- a/rhodecode/config/routing.py +++ b/rhodecode/config/routing.py @@ -378,6 +378,11 @@ def make_map(config): controller='files', action='edit', revision='tip', f_path='', conditions=dict(function=check_repo)) + rmap.connect('files_add_home', + '/{repo_name:.*}/add/{revision}/{f_path:.*}', + controller='files', action='add', revision='tip', + f_path='', conditions=dict(function=check_repo)) + rmap.connect('files_archive_home', '/{repo_name:.*}/archive/{fname}', controller='files', action='archivefile', conditions=dict(function=check_repo)) diff --git a/rhodecode/controllers/files.py b/rhodecode/controllers/files.py --- a/rhodecode/controllers/files.py +++ b/rhodecode/controllers/files.py @@ -57,7 +57,7 @@ class FilesController(BaseRepoController super(FilesController, self).__before__() c.cut_off_limit = self.cut_off_limit - def __get_cs_or_redirect(self, rev, repo_name): + def __get_cs_or_redirect(self, rev, repo_name, redirect_after=True): """ Safe way to get changeset if error occur it redirects to tip with proper message @@ -69,7 +69,14 @@ class FilesController(BaseRepoController try: return c.rhodecode_repo.get_changeset(rev) except EmptyRepositoryError, e: - h.flash(_('There are no files yet'), category='warning') + if not redirect_after: + return None + url_ = url('files_add_home', + repo_name=c.repo_name, + revision=0,f_path='') + add_new = '[%s]' % (url_,_('add new')) + h.flash(h.literal(_('There are no files yet %s' % add_new)), + category='warning') redirect(h.url('summary_home', repo_name=repo_name)) except RepositoryError, e: @@ -247,7 +254,6 @@ class FilesController(BaseRepoController return redirect(url('files_home', repo_name=c.repo_name, revision=c.cs.raw_id, f_path=f_path)) - c.file_history = self._get_node_history(c.cs, f_path) c.f_path = f_path if r_post: @@ -286,6 +292,49 @@ class FilesController(BaseRepoController return render('files/files_edit.html') + @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin') + def add(self, repo_name, revision, f_path): + r_post = request.POST + c.cs = self.__get_cs_or_redirect(revision, repo_name, + redirect_after=False) + if c.cs is None: + c.cs = EmptyChangeset(alias=c.rhodecode_repo.alias) + + c.f_path = f_path + + if r_post: + unix_mode = 0 + content = convert_line_endings(r_post.get('content'), unix_mode) + + message = r_post.get('message') or (_('Added %s via RhodeCode') + % (f_path)) + location = r_post.get('location') + filename = r_post.get('filename') + node_path = os.path.join(location, filename) + author = self.rhodecode_user.full_contact + + if not content: + h.flash(_('No content'), category='warning') + return redirect(url('changeset_home', repo_name=c.repo_name, + revision='tip')) + + try: + self.scm_model.create_node(repo=c.rhodecode_repo, + repo_name=repo_name, cs=c.cs, + user=self.rhodecode_user, + author=author, message=message, + content=content, f_path=node_path) + h.flash(_('Successfully committed to %s' % node_path), + category='success') + + except Exception: + log.error(traceback.format_exc()) + h.flash(_('Error occurred during commit'), category='error') + return redirect(url('changeset_home', + repo_name=c.repo_name, revision='tip')) + + return render('files/files_add.html') + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') def archivefile(self, repo_name, fname): diff --git a/rhodecode/lib/utils.py b/rhodecode/lib/utils.py --- a/rhodecode/lib/utils.py +++ b/rhodecode/lib/utils.py @@ -42,6 +42,7 @@ from webhelpers.text import collapse, re from vcs.backends.base import BaseChangeset from vcs.utils.lazy import LazyProperty +from vcs import get_backend from rhodecode.model import meta from rhodecode.model.caching_query import FromCache @@ -313,7 +314,7 @@ class EmptyChangeset(BaseChangeset): an EmptyChangeset """ - def __init__(self, cs='0' * 40, repo=None,requested_revision=None): + def __init__(self, cs='0' * 40, repo=None, requested_revision=None, alias=None): self._empty_cs = cs self.revision = -1 self.message = '' @@ -321,7 +322,8 @@ class EmptyChangeset(BaseChangeset): self.date = '' self.repository = repo self.requested_revision = requested_revision - + self.alias = alias + @LazyProperty def raw_id(self): """Returns raw string identifying this changeset, useful for web @@ -331,6 +333,10 @@ class EmptyChangeset(BaseChangeset): return self._empty_cs @LazyProperty + def branch(self): + return get_backend(self.alias).DEFAULT_BRANCH_NAME + + @LazyProperty def short_id(self): return self.raw_id[:12] @@ -602,3 +608,4 @@ class BasePasterCommand(Command): path_to_ini_file = os.path.realpath(conf) conf = paste.deploy.appconfig('config:' + path_to_ini_file) pylonsconfig.init_app(conf.global_conf, conf.local_conf) + diff --git a/rhodecode/model/scm.py b/rhodecode/model/scm.py --- a/rhodecode/model/scm.py +++ b/rhodecode/model/scm.py @@ -39,7 +39,7 @@ from rhodecode.lib import helpers as h from rhodecode.lib import safe_str from rhodecode.lib.auth import HasRepoPermissionAny from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \ - action_logger + action_logger, EmptyChangeset from rhodecode.model import BaseModel from rhodecode.model.user import UserModel from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \ @@ -352,6 +352,37 @@ class ScmModel(BaseModel): self.mark_for_invalidation(repo_name) + def create_node(self, repo, repo_name, cs, user, author, message, content, + f_path): + if repo.alias == 'hg': + from vcs.backends.hg import MercurialInMemoryChangeset as IMC + elif repo.alias == 'git': + from vcs.backends.git import GitInMemoryChangeset as IMC + # decoding here will force that we have proper encoded values + # in any other case this will throw exceptions and deny commit + content = safe_str(content) + message = safe_str(message) + path = safe_str(f_path) + author = safe_str(author) + m = IMC(repo) + + if isinstance(cs, EmptyChangeset): + # Emptychangeset means we we're editing empty repository + parents = None + else: + parents = [cs] + + m.add(FileNode(path, content=content)) + tip = m.commit(message=message, + author=author, + parents=parents, branch=cs.branch) + new_cs = tip.short_id + action = 'push_local:%s' % new_cs + + action_logger(user, action, repo_name) + + self.mark_for_invalidation(repo_name) + def get_unread_journal(self): return self.sa.query(UserLog).count() @@ -368,3 +399,4 @@ class ScmModel(BaseModel): .scalar() return ret + diff --git a/rhodecode/public/css/style.css b/rhodecode/public/css/style.css --- a/rhodecode/public/css/style.css +++ b/rhodecode/public/css/style.css @@ -1867,9 +1867,21 @@ font-weight:700; div.browserblock .browser-search{ clear:both; padding:8px 8px 0px 5px; -} - -div.browserblock .search_activate #filter_activate{ + height: 20px; +} +div.browserblock #node_filter_box { +} + +div.browserblock .search_activate{ + float: left +} + +div.browserblock .add_node{ + float: left; + padding-left: 5px; +} + +div.browserblock .search_activate #filter_activate,div.browserblock .add_node a{ vertical-align: sub; border: 1px solid; padding:2px; @@ -1882,7 +1894,7 @@ div.browserblock .search_activate #filte color: #515151; } -div.browserblock .search_activate a:hover{ +div.browserblock .search_activate a:hover,div.browserblock .add_node a:hover{ text-decoration: none !important; } diff --git a/rhodecode/templates/files/files_add.html b/rhodecode/templates/files/files_add.html new file mode 100644 --- /dev/null +++ b/rhodecode/templates/files/files_add.html @@ -0,0 +1,85 @@ +<%inherit file="/base/base.html"/> + +<%def name="title()"> + ${c.repo_name} ${_('Edit file')} - ${c.rhodecode_name} + + +<%def name="js_extra()"> + + +<%def name="css_extra()"> + + + +<%def name="breadcrumbs_links()"> + ${h.link_to(u'Home',h.url('/'))} + » + ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))} + » + ${_('add file')} @ R${c.cs.revision}:${h.short_id(c.cs.raw_id)} + + +<%def name="page_nav()"> + ${self.menu('files')} + +<%def name="main()"> +
+ +
+ ${self.breadcrumbs()} + +
+
+
+ ${h.form(h.url.current(),method='post',id='eform')} +

${_('Add new file')}

+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+

+				
+				
${_('commit message')}
+ +
+
+ + ${h.submit('commit',_('Commit changes'),class_="ui-button-small-blue")} +
+ ${h.end_form()} + +
+
+
+ \ No newline at end of file diff --git a/rhodecode/templates/files/files_browser.html b/rhodecode/templates/files/files_browser.html --- a/rhodecode/templates/files/files_browser.html +++ b/rhodecode/templates/files/files_browser.html @@ -23,11 +23,12 @@