Show More
@@ -0,0 +1,85 b'' | |||||
|
1 | <%inherit file="/base/base.html"/> | |||
|
2 | ||||
|
3 | <%def name="title()"> | |||
|
4 | ${c.repo_name} ${_('Edit file')} - ${c.rhodecode_name} | |||
|
5 | </%def> | |||
|
6 | ||||
|
7 | <%def name="js_extra()"> | |||
|
8 | <script type="text/javascript" src="${h.url('/js/codemirror.js')}"></script> | |||
|
9 | </%def> | |||
|
10 | <%def name="css_extra()"> | |||
|
11 | <link rel="stylesheet" type="text/css" href="${h.url('/css/codemirror.css')}"/> | |||
|
12 | </%def> | |||
|
13 | ||||
|
14 | <%def name="breadcrumbs_links()"> | |||
|
15 | ${h.link_to(u'Home',h.url('/'))} | |||
|
16 | » | |||
|
17 | ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))} | |||
|
18 | » | |||
|
19 | ${_('add file')} @ R${c.cs.revision}:${h.short_id(c.cs.raw_id)} | |||
|
20 | </%def> | |||
|
21 | ||||
|
22 | <%def name="page_nav()"> | |||
|
23 | ${self.menu('files')} | |||
|
24 | </%def> | |||
|
25 | <%def name="main()"> | |||
|
26 | <div class="box"> | |||
|
27 | <!-- box / title --> | |||
|
28 | <div class="title"> | |||
|
29 | ${self.breadcrumbs()} | |||
|
30 | <ul class="links"> | |||
|
31 | <li> | |||
|
32 | <span style="text-transform: uppercase;"> | |||
|
33 | <a href="#">${_('branch')}: ${c.cs.branch}</a></span> | |||
|
34 | </li> | |||
|
35 | </ul> | |||
|
36 | </div> | |||
|
37 | <div class="table"> | |||
|
38 | <div id="files_data"> | |||
|
39 | ${h.form(h.url.current(),method='post',id='eform')} | |||
|
40 | <h3>${_('Add new file')}</h3> | |||
|
41 | <div class="form"> | |||
|
42 | <div class="fields"> | |||
|
43 | <div class="field"> | |||
|
44 | <div class="label"> | |||
|
45 | <label for="location">${_('Location')}</label> | |||
|
46 | </div> | |||
|
47 | <div class="input"> | |||
|
48 | <input type="text" value="${c.f_path}" size="30" name="location" id="location"> | |||
|
49 | </div> | |||
|
50 | </div> | |||
|
51 | ||||
|
52 | <div class="field"> | |||
|
53 | <div class="label"> | |||
|
54 | <label for="filename">${_('File Name')}:</label> | |||
|
55 | </div> | |||
|
56 | <div class="input"> | |||
|
57 | <input type="text" value="" size="30" name="filename" id="filename"> | |||
|
58 | </div> | |||
|
59 | </div> | |||
|
60 | </div> | |||
|
61 | </div> | |||
|
62 | <div id="body" class="codeblock"> | |||
|
63 | <pre id="editor_pre"></pre> | |||
|
64 | <textarea id="editor" name="content" style="display:none"></textarea> | |||
|
65 | <div style="padding-top: 10px;">${_('commit message')}</div> | |||
|
66 | <textarea id="commit" name="message" style="height: 100px;width: 99%"></textarea> | |||
|
67 | </div> | |||
|
68 | <div style="text-align: right;padding-top: 5px"> | |||
|
69 | <input id="reset" type="button" value="${_('Reset')}" class="ui-button-small" /> | |||
|
70 | ${h.submit('commit',_('Commit changes'),class_="ui-button-small-blue")} | |||
|
71 | </div> | |||
|
72 | ${h.end_form()} | |||
|
73 | <script type="text/javascript"> | |||
|
74 | var myCodeMirror = CodeMirror.fromTextArea(YUD.get('editor'),{ | |||
|
75 | mode: "null", | |||
|
76 | lineNumbers:true | |||
|
77 | }); | |||
|
78 | YUE.on('reset','click',function(){ | |||
|
79 | window.location="${h.url('files_home',repo_name=c.repo_name,revision=c.cs.revision,f_path=c.f_path)}"; | |||
|
80 | }) | |||
|
81 | </script> | |||
|
82 | </div> | |||
|
83 | </div> | |||
|
84 | </div> | |||
|
85 | </%def> No newline at end of file |
@@ -378,6 +378,11 b' def make_map(config):' | |||||
378 | controller='files', action='edit', revision='tip', |
|
378 | controller='files', action='edit', revision='tip', | |
379 | f_path='', conditions=dict(function=check_repo)) |
|
379 | f_path='', conditions=dict(function=check_repo)) | |
380 |
|
380 | |||
|
381 | rmap.connect('files_add_home', | |||
|
382 | '/{repo_name:.*}/add/{revision}/{f_path:.*}', | |||
|
383 | controller='files', action='add', revision='tip', | |||
|
384 | f_path='', conditions=dict(function=check_repo)) | |||
|
385 | ||||
381 | rmap.connect('files_archive_home', '/{repo_name:.*}/archive/{fname}', |
|
386 | rmap.connect('files_archive_home', '/{repo_name:.*}/archive/{fname}', | |
382 | controller='files', action='archivefile', |
|
387 | controller='files', action='archivefile', | |
383 | conditions=dict(function=check_repo)) |
|
388 | conditions=dict(function=check_repo)) |
@@ -57,7 +57,7 b' class FilesController(BaseRepoController' | |||||
57 | super(FilesController, self).__before__() |
|
57 | super(FilesController, self).__before__() | |
58 | c.cut_off_limit = self.cut_off_limit |
|
58 | c.cut_off_limit = self.cut_off_limit | |
59 |
|
59 | |||
60 | def __get_cs_or_redirect(self, rev, repo_name): |
|
60 | def __get_cs_or_redirect(self, rev, repo_name, redirect_after=True): | |
61 | """ |
|
61 | """ | |
62 | Safe way to get changeset if error occur it redirects to tip with |
|
62 | Safe way to get changeset if error occur it redirects to tip with | |
63 | proper message |
|
63 | proper message | |
@@ -69,7 +69,14 b' class FilesController(BaseRepoController' | |||||
69 | try: |
|
69 | try: | |
70 | return c.rhodecode_repo.get_changeset(rev) |
|
70 | return c.rhodecode_repo.get_changeset(rev) | |
71 | except EmptyRepositoryError, e: |
|
71 | except EmptyRepositoryError, e: | |
72 | h.flash(_('There are no files yet'), category='warning') |
|
72 | if not redirect_after: | |
|
73 | return None | |||
|
74 | url_ = url('files_add_home', | |||
|
75 | repo_name=c.repo_name, | |||
|
76 | revision=0,f_path='') | |||
|
77 | add_new = '<a href="%s">[%s]</a>' % (url_,_('add new')) | |||
|
78 | h.flash(h.literal(_('There are no files yet %s' % add_new)), | |||
|
79 | category='warning') | |||
73 | redirect(h.url('summary_home', repo_name=repo_name)) |
|
80 | redirect(h.url('summary_home', repo_name=repo_name)) | |
74 |
|
81 | |||
75 | except RepositoryError, e: |
|
82 | except RepositoryError, e: | |
@@ -247,7 +254,6 b' class FilesController(BaseRepoController' | |||||
247 | return redirect(url('files_home', repo_name=c.repo_name, |
|
254 | return redirect(url('files_home', repo_name=c.repo_name, | |
248 | revision=c.cs.raw_id, f_path=f_path)) |
|
255 | revision=c.cs.raw_id, f_path=f_path)) | |
249 |
|
256 | |||
250 | c.file_history = self._get_node_history(c.cs, f_path) |
|
|||
251 | c.f_path = f_path |
|
257 | c.f_path = f_path | |
252 |
|
258 | |||
253 | if r_post: |
|
259 | if r_post: | |
@@ -286,6 +292,49 b' class FilesController(BaseRepoController' | |||||
286 |
|
292 | |||
287 | return render('files/files_edit.html') |
|
293 | return render('files/files_edit.html') | |
288 |
|
294 | |||
|
295 | @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin') | |||
|
296 | def add(self, repo_name, revision, f_path): | |||
|
297 | r_post = request.POST | |||
|
298 | c.cs = self.__get_cs_or_redirect(revision, repo_name, | |||
|
299 | redirect_after=False) | |||
|
300 | if c.cs is None: | |||
|
301 | c.cs = EmptyChangeset(alias=c.rhodecode_repo.alias) | |||
|
302 | ||||
|
303 | c.f_path = f_path | |||
|
304 | ||||
|
305 | if r_post: | |||
|
306 | unix_mode = 0 | |||
|
307 | content = convert_line_endings(r_post.get('content'), unix_mode) | |||
|
308 | ||||
|
309 | message = r_post.get('message') or (_('Added %s via RhodeCode') | |||
|
310 | % (f_path)) | |||
|
311 | location = r_post.get('location') | |||
|
312 | filename = r_post.get('filename') | |||
|
313 | node_path = os.path.join(location, filename) | |||
|
314 | author = self.rhodecode_user.full_contact | |||
|
315 | ||||
|
316 | if not content: | |||
|
317 | h.flash(_('No content'), category='warning') | |||
|
318 | return redirect(url('changeset_home', repo_name=c.repo_name, | |||
|
319 | revision='tip')) | |||
|
320 | ||||
|
321 | try: | |||
|
322 | self.scm_model.create_node(repo=c.rhodecode_repo, | |||
|
323 | repo_name=repo_name, cs=c.cs, | |||
|
324 | user=self.rhodecode_user, | |||
|
325 | author=author, message=message, | |||
|
326 | content=content, f_path=node_path) | |||
|
327 | h.flash(_('Successfully committed to %s' % node_path), | |||
|
328 | category='success') | |||
|
329 | ||||
|
330 | except Exception: | |||
|
331 | log.error(traceback.format_exc()) | |||
|
332 | h.flash(_('Error occurred during commit'), category='error') | |||
|
333 | return redirect(url('changeset_home', | |||
|
334 | repo_name=c.repo_name, revision='tip')) | |||
|
335 | ||||
|
336 | return render('files/files_add.html') | |||
|
337 | ||||
289 | @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', |
|
338 | @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', | |
290 | 'repository.admin') |
|
339 | 'repository.admin') | |
291 | def archivefile(self, repo_name, fname): |
|
340 | def archivefile(self, repo_name, fname): |
@@ -42,6 +42,7 b' from webhelpers.text import collapse, re' | |||||
42 |
|
42 | |||
43 | from vcs.backends.base import BaseChangeset |
|
43 | from vcs.backends.base import BaseChangeset | |
44 | from vcs.utils.lazy import LazyProperty |
|
44 | from vcs.utils.lazy import LazyProperty | |
|
45 | from vcs import get_backend | |||
45 |
|
46 | |||
46 | from rhodecode.model import meta |
|
47 | from rhodecode.model import meta | |
47 | from rhodecode.model.caching_query import FromCache |
|
48 | from rhodecode.model.caching_query import FromCache | |
@@ -313,7 +314,7 b' class EmptyChangeset(BaseChangeset):' | |||||
313 | an EmptyChangeset |
|
314 | an EmptyChangeset | |
314 | """ |
|
315 | """ | |
315 |
|
316 | |||
316 | def __init__(self, cs='0' * 40, repo=None,requested_revision=None): |
|
317 | def __init__(self, cs='0' * 40, repo=None, requested_revision=None, alias=None): | |
317 | self._empty_cs = cs |
|
318 | self._empty_cs = cs | |
318 | self.revision = -1 |
|
319 | self.revision = -1 | |
319 | self.message = '' |
|
320 | self.message = '' | |
@@ -321,6 +322,7 b' class EmptyChangeset(BaseChangeset):' | |||||
321 | self.date = '' |
|
322 | self.date = '' | |
322 | self.repository = repo |
|
323 | self.repository = repo | |
323 | self.requested_revision = requested_revision |
|
324 | self.requested_revision = requested_revision | |
|
325 | self.alias = alias | |||
324 |
|
326 | |||
325 | @LazyProperty |
|
327 | @LazyProperty | |
326 | def raw_id(self): |
|
328 | def raw_id(self): | |
@@ -331,6 +333,10 b' class EmptyChangeset(BaseChangeset):' | |||||
331 | return self._empty_cs |
|
333 | return self._empty_cs | |
332 |
|
334 | |||
333 | @LazyProperty |
|
335 | @LazyProperty | |
|
336 | def branch(self): | |||
|
337 | return get_backend(self.alias).DEFAULT_BRANCH_NAME | |||
|
338 | ||||
|
339 | @LazyProperty | |||
334 | def short_id(self): |
|
340 | def short_id(self): | |
335 | return self.raw_id[:12] |
|
341 | return self.raw_id[:12] | |
336 |
|
342 | |||
@@ -602,3 +608,4 b' class BasePasterCommand(Command):' | |||||
602 | path_to_ini_file = os.path.realpath(conf) |
|
608 | path_to_ini_file = os.path.realpath(conf) | |
603 | conf = paste.deploy.appconfig('config:' + path_to_ini_file) |
|
609 | conf = paste.deploy.appconfig('config:' + path_to_ini_file) | |
604 | pylonsconfig.init_app(conf.global_conf, conf.local_conf) |
|
610 | pylonsconfig.init_app(conf.global_conf, conf.local_conf) | |
|
611 |
@@ -39,7 +39,7 b' from rhodecode.lib import helpers as h' | |||||
39 | from rhodecode.lib import safe_str |
|
39 | from rhodecode.lib import safe_str | |
40 | from rhodecode.lib.auth import HasRepoPermissionAny |
|
40 | from rhodecode.lib.auth import HasRepoPermissionAny | |
41 | from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \ |
|
41 | from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \ | |
42 | action_logger |
|
42 | action_logger, EmptyChangeset | |
43 | from rhodecode.model import BaseModel |
|
43 | from rhodecode.model import BaseModel | |
44 | from rhodecode.model.user import UserModel |
|
44 | from rhodecode.model.user import UserModel | |
45 | from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \ |
|
45 | from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \ | |
@@ -352,6 +352,37 b' class ScmModel(BaseModel):' | |||||
352 |
|
352 | |||
353 | self.mark_for_invalidation(repo_name) |
|
353 | self.mark_for_invalidation(repo_name) | |
354 |
|
354 | |||
|
355 | def create_node(self, repo, repo_name, cs, user, author, message, content, | |||
|
356 | f_path): | |||
|
357 | if repo.alias == 'hg': | |||
|
358 | from vcs.backends.hg import MercurialInMemoryChangeset as IMC | |||
|
359 | elif repo.alias == 'git': | |||
|
360 | from vcs.backends.git import GitInMemoryChangeset as IMC | |||
|
361 | # decoding here will force that we have proper encoded values | |||
|
362 | # in any other case this will throw exceptions and deny commit | |||
|
363 | content = safe_str(content) | |||
|
364 | message = safe_str(message) | |||
|
365 | path = safe_str(f_path) | |||
|
366 | author = safe_str(author) | |||
|
367 | m = IMC(repo) | |||
|
368 | ||||
|
369 | if isinstance(cs, EmptyChangeset): | |||
|
370 | # Emptychangeset means we we're editing empty repository | |||
|
371 | parents = None | |||
|
372 | else: | |||
|
373 | parents = [cs] | |||
|
374 | ||||
|
375 | m.add(FileNode(path, content=content)) | |||
|
376 | tip = m.commit(message=message, | |||
|
377 | author=author, | |||
|
378 | parents=parents, branch=cs.branch) | |||
|
379 | new_cs = tip.short_id | |||
|
380 | action = 'push_local:%s' % new_cs | |||
|
381 | ||||
|
382 | action_logger(user, action, repo_name) | |||
|
383 | ||||
|
384 | self.mark_for_invalidation(repo_name) | |||
|
385 | ||||
355 |
|
386 | |||
356 | def get_unread_journal(self): |
|
387 | def get_unread_journal(self): | |
357 | return self.sa.query(UserLog).count() |
|
388 | return self.sa.query(UserLog).count() | |
@@ -368,3 +399,4 b' class ScmModel(BaseModel):' | |||||
368 | .scalar() |
|
399 | .scalar() | |
369 |
|
400 | |||
370 | return ret |
|
401 | return ret | |
|
402 |
@@ -1867,9 +1867,21 b' font-weight:700;' | |||||
1867 | div.browserblock .browser-search{ |
|
1867 | div.browserblock .browser-search{ | |
1868 | clear:both; |
|
1868 | clear:both; | |
1869 | padding:8px 8px 0px 5px; |
|
1869 | padding:8px 8px 0px 5px; | |
1870 | } |
|
1870 | height: 20px; | |
1871 |
|
1871 | } | ||
1872 |
div.browserblock |
|
1872 | div.browserblock #node_filter_box { | |
|
1873 | } | |||
|
1874 | ||||
|
1875 | div.browserblock .search_activate{ | |||
|
1876 | float: left | |||
|
1877 | } | |||
|
1878 | ||||
|
1879 | div.browserblock .add_node{ | |||
|
1880 | float: left; | |||
|
1881 | padding-left: 5px; | |||
|
1882 | } | |||
|
1883 | ||||
|
1884 | div.browserblock .search_activate #filter_activate,div.browserblock .add_node a{ | |||
1873 | vertical-align: sub; |
|
1885 | vertical-align: sub; | |
1874 | border: 1px solid; |
|
1886 | border: 1px solid; | |
1875 | padding:2px; |
|
1887 | padding:2px; | |
@@ -1882,7 +1894,7 b' div.browserblock .search_activate #filte' | |||||
1882 | color: #515151; |
|
1894 | color: #515151; | |
1883 | } |
|
1895 | } | |
1884 |
|
1896 | |||
1885 | div.browserblock .search_activate a:hover{ |
|
1897 | div.browserblock .search_activate a:hover,div.browserblock .add_node a:hover{ | |
1886 | text-decoration: none !important; |
|
1898 | text-decoration: none !important; | |
1887 | } |
|
1899 | } | |
1888 |
|
1900 |
@@ -23,11 +23,12 b'' | |||||
23 | <label>${_('follow current branch')}</label> |
|
23 | <label>${_('follow current branch')}</label> | |
24 | </div> |
|
24 | </div> | |
25 | <div class="browser-search"> |
|
25 | <div class="browser-search"> | |
26 | <div class="search_activate"> |
|
26 | <div id="search_activate_id" class="search_activate"> | |
27 | <a id="filter_activate" href="#">${_('search file list')}</a> |
|
27 | <a id="filter_activate" href="#">${_('search file list')}</a> | |
28 | </div> |
|
28 | </div> | |
29 |
|
29 | <div id="add_node_id" class="add_node"> | ||
30 |
|
30 | <a href="${h.url('files_add_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path)}">${_('add new file')}</a> | ||
|
31 | </div> | |||
31 | <div> |
|
32 | <div> | |
32 | <div id="node_filter_box_loading" style="display:none">${_('Loading file list...')}</div> |
|
33 | <div id="node_filter_box_loading" style="display:none">${_('Loading file list...')}</div> | |
33 | <div id="node_filter_box" style="display:none"> |
|
34 | <div id="node_filter_box" style="display:none"> | |
@@ -67,7 +68,8 b'' | |||||
67 |
|
68 | |||
68 | F.initFilter = function(){ |
|
69 | F.initFilter = function(){ | |
69 | YUD.setStyle('node_filter_box_loading','display',''); |
|
70 | YUD.setStyle('node_filter_box_loading','display',''); | |
70 |
YUD.setStyle(' |
|
71 | YUD.setStyle('search_activate_id','display','none'); | |
|
72 | YUD.setStyle('add_node_id','display','none'); | |||
71 | YUC.initHeader('X-PARTIAL-XHR',true); |
|
73 | YUC.initHeader('X-PARTIAL-XHR',true); | |
72 | YUC.asyncRequest('GET',url,{ |
|
74 | YUC.asyncRequest('GET',url,{ | |
73 | success:function(o){ |
|
75 | success:function(o){ |
General Comments 0
You need to be logged in to leave comments.
Login now