repositories: allow properly updating repository push url.

This commit is contained in:
Marcin Kuzminski 2018-02-12 14:14:33 +01:00
parent 803051c06b
commit 5f25ae601e
10 changed files with 165 additions and 39 deletions

View file

@ -563,6 +563,7 @@ def create_repo(
description=Optional(''),
private=Optional(False),
clone_uri=Optional(None),
push_uri=Optional(None),
landing_rev=Optional('rev:tip'),
enable_statistics=Optional(False),
enable_locking=Optional(False),
@ -596,6 +597,8 @@ def create_repo(
:type private: bool
:param clone_uri: set clone_uri
:type clone_uri: str
:param push_uri: set push_uri
:type push_uri: str
:param landing_rev: <rev_type>:<rev>
:type landing_rev: str
:param enable_locking:
@ -639,6 +642,7 @@ def create_repo(
description = Optional.extract(description)
copy_permissions = Optional.extract(copy_permissions)
clone_uri = Optional.extract(clone_uri)
push_uri = Optional.extract(push_uri)
landing_commit_ref = Optional.extract(landing_rev)
defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
@ -666,6 +670,7 @@ def create_repo(
repo_description=description,
repo_landing_commit_ref=landing_commit_ref,
repo_clone_uri=clone_uri,
repo_push_uri=push_uri,
repo_private=private,
repo_copy_permissions=copy_permissions,
repo_enable_statistics=enable_statistics,
@ -684,6 +689,7 @@ def create_repo(
'repo_description': schema_data['repo_description'],
'repo_private': schema_data['repo_private'],
'clone_uri': schema_data['repo_clone_uri'],
'push_uri': schema_data['repo_push_uri'],
'repo_landing_rev': schema_data['repo_landing_commit_ref'],
'enable_statistics': schema_data['repo_enable_statistics'],
'enable_locking': schema_data['repo_enable_locking'],
@ -907,6 +913,7 @@ def update_repo(
repo_owner=updates['user'],
repo_description=updates['repo_description'],
repo_clone_uri=updates['clone_uri'],
repo_push_uri=updates['push_uri'],
repo_fork_of=updates['fork_id'],
repo_private=updates['repo_private'],
repo_landing_commit_ref=updates['repo_landing_rev'],
@ -925,6 +932,7 @@ def update_repo(
repo_description=schema_data['repo_description'],
repo_private=schema_data['repo_private'],
clone_uri=schema_data['repo_clone_uri'],
push_uri=schema_data['repo_push_uri'],
repo_landing_rev=schema_data['repo_landing_commit_ref'],
repo_enable_statistics=schema_data['repo_enable_statistics'],
repo_enable_locking=schema_data['repo_enable_locking'],

View file

@ -373,6 +373,9 @@ def includeme(config):
config.add_route(
name='edit_repo_remote_pull',
pattern='/{repo_name:.*?[^/]}/settings/remote/pull', repo_route=True)
config.add_route(
name='edit_repo_remote_push',
pattern='/{repo_name:.*?[^/]}/settings/remote/push', repo_route=True)
# Statistics
config.add_route(

View file

@ -138,15 +138,19 @@ class RepoSettingsView(RepoAppView):
repo_description=schema_data['repo_description'],
repo_private=schema_data['repo_private'],
clone_uri=schema_data['repo_clone_uri'],
push_uri=schema_data['repo_push_uri'],
repo_landing_rev=schema_data['repo_landing_commit_ref'],
repo_enable_statistics=schema_data['repo_enable_statistics'],
repo_enable_locking=schema_data['repo_enable_locking'],
repo_enable_downloads=schema_data['repo_enable_downloads'],
)
# detect if CLONE URI changed, if we get OLD means we keep old values
# detect if SYNC URI changed, if we get OLD means we keep old values
if schema_data['repo_clone_uri_change'] == 'OLD':
validated_updates['clone_uri'] = self.db_repo.clone_uri
if schema_data['repo_push_uri_change'] == 'OLD':
validated_updates['push_uri'] = self.db_repo.push_uri
# use the new full name for redirect
new_repo_name = schema_data['repo_group']['repo_name_with_group']

View file

@ -35,8 +35,6 @@ log = logging.getLogger(__name__)
class RepoSettingsRemoteView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
return c
@LoginRequired()

View file

@ -304,6 +304,7 @@ class RepoModel(BaseModel):
{'k': 'repo_enable_locking', 'strip': True},
{'k': 'repo_landing_rev', 'strip': True},
{'k': 'clone_uri', 'strip': False},
{'k': 'push_uri', 'strip': False},
{'k': 'repo_private', 'strip': True},
{'k': 'repo_enable_statistics', 'strip': True}
)
@ -319,6 +320,8 @@ class RepoModel(BaseModel):
defaults[item['k']] = val
if item['k'] == 'clone_uri':
defaults['clone_uri_hidden'] = repo_info.clone_uri_hidden
if item['k'] == 'push_uri':
defaults['push_uri_hidden'] = repo_info.push_uri_hidden
# fill owner
if repo_info.user:
@ -348,6 +351,7 @@ class RepoModel(BaseModel):
(1, 'repo_enable_locking'),
(1, 'repo_enable_statistics'),
(0, 'clone_uri'),
(0, 'push_uri'),
(0, 'fork_id')
]
for strip, k in update_keys:

View file

@ -66,7 +66,7 @@ def deferred_landing_ref_validator(node, kw):
@colander.deferred
def deferred_clone_uri_validator(node, kw):
def deferred_sync_uri_validator(node, kw):
repo_type = kw.get('repo_type')
validator = validators.CloneUriValidator(repo_type)
return validator
@ -323,6 +323,12 @@ class RepoSchema(colander.MappingSchema):
preparers=[preparers.strip_preparer],
missing='')
repo_push_uri = colander.SchemaNode(
colander.String(),
validator=colander.All(colander.Length(min=1)),
preparers=[preparers.strip_preparer],
missing='')
repo_fork_of = colander.SchemaNode(
colander.String(),
validator=deferred_fork_of_validator,
@ -381,7 +387,17 @@ class RepoSettingsSchema(RepoSchema):
repo_clone_uri = colander.SchemaNode(
colander.String(),
preparers=[preparers.strip_preparer],
validator=deferred_clone_uri_validator,
validator=deferred_sync_uri_validator,
missing='')
repo_push_uri_change = colander.SchemaNode(
colander.String(),
missing='NEW')
repo_push_uri = colander.SchemaNode(
colander.String(),
preparers=[preparers.strip_preparer],
validator=deferred_sync_uri_validator,
missing='')
def deserialize(self, cstruct):

View file

@ -232,6 +232,7 @@ function registerRCRoutes() {
pyroutes.register('repo_edit_toggle_locking', '/%(repo_name)s/settings/toggle_locking', ['repo_name']);
pyroutes.register('edit_repo_remote', '/%(repo_name)s/settings/remote', ['repo_name']);
pyroutes.register('edit_repo_remote_pull', '/%(repo_name)s/settings/remote/pull', ['repo_name']);
pyroutes.register('edit_repo_remote_push', '/%(repo_name)s/settings/remote/push', ['repo_name']);
pyroutes.register('edit_repo_statistics', '/%(repo_name)s/settings/statistics', ['repo_name']);
pyroutes.register('edit_repo_statistics_reset', '/%(repo_name)s/settings/statistics/update', ['repo_name']);
pyroutes.register('edit_repo_issuetracker', '/%(repo_name)s/settings/issue_trackers', ['repo_name']);

View file

@ -65,7 +65,7 @@
</li>
%if c.rhodecode_db_repo.repo_type != 'svn':
<li class="${'active' if c.active=='remote' else ''}">
<a href="${h.route_path('edit_repo_remote', repo_name=c.repo_name)}">${_('Remote')}</a>
<a href="${h.route_path('edit_repo_remote', repo_name=c.repo_name)}">${_('Remote sync')}</a>
</li>
%endif
<li class="${'active' if c.active=='statistics' else ''}">

View file

@ -1,31 +1,60 @@
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">${_('Remote url')}</h3>
<h3 class="panel-title">${_('Remote Sync')}</h3>
</div>
<div class="panel-body">
<h4>${_('Manually pull changes from external repository.')}</h4>
<h4>${_('Manually pull/push changes from/to external URLs.')}</h4>
%if c.rhodecode_db_repo.clone_uri:
%if c.rhodecode_db_repo.clone_uri or c.rhodecode_db_repo.push_uri:
${_('Remote mirror url')}:
<a href="${c.rhodecode_db_repo.clone_uri}">${c.rhodecode_db_repo.clone_uri_hidden}</a>
<table>
% if c.rhodecode_db_repo.clone_uri:
<tr>
<td><div style="min-width: 80px"><strong>${_('Pull url')}</strong></div></td>
<td><a href="${c.rhodecode_db_repo.clone_uri}">${c.rhodecode_db_repo.clone_uri_hidden}</a></td>
</tr>
<tr>
<td></td>
<td>
<p>
${_('Pull can be automated by such api call. Can be called periodically in crontab etc.')}
<br/>
<code>
${h.api_call_example(method='pull', args={"repoid": c.rhodecode_db_repo.repo_name})}
</code>
</p>
</td>
</tr>
<tr>
<td></td>
<td>
${h.secure_form(h.route_path('edit_repo_remote_pull', repo_name=c.repo_name), request=request)}
<div class="form">
<div class="fields">
${h.submit('remote_pull_%s' % c.rhodecode_db_repo.repo_name,_('Pull changes from remote location'),class_="btn btn-small",onclick="return confirm('"+_('Confirm to pull changes from remote side')+"');")}
</div>
</div>
${h.end_form()}
</td>
</tr>
% endif
<p>
${_('Pull can be automated by such api call. Can be called periodically in crontab etc.')}
<br/>
<code>
${h.api_call_example(method='pull', args={"repoid": c.rhodecode_db_repo.repo_name})}
</code>
</p>
% if c.rhodecode_db_repo.push_uri:
<tr>
<td><div style="min-width: 80px"><strong>${_('Push url')}</strong></div></td>
<td><a href="${c.rhodecode_db_repo.push_uri_hidden}">${c.rhodecode_db_repo.push_uri_hidden}</a></td>
</tr>
<tr>
<td></td>
<td>
${_('This feature is available in RhodeCode EE edition only. Contact {sales_email} to obtain a trial license.').format(sales_email='<a href="mailto:sales@rhodecode.com">sales@rhodecode.com</a>')|n}
</td>
</tr>
% endif
</table>
${h.secure_form(h.route_path('edit_repo_remote_pull', repo_name=c.repo_name), request=request)}
<div class="form">
<div class="fields">
${h.submit('remote_pull_%s' % c.rhodecode_db_repo.repo_name,_('Pull changes from remote location'),class_="btn btn-small",onclick="return confirm('"+_('Confirm to pull changes from remote side')+"');")}
</div>
</div>
${h.end_form()}
%else:
${_('This repository does not have any remote mirror url set.')}

View file

@ -46,9 +46,10 @@
</div>
% if c.rhodecode_db_repo.repo_type != 'svn':
<% sync_link = h.literal(h.link_to('remote sync', h.route_path('edit_repo_remote', repo_name=c.repo_name))) %>
<div class="field">
<div class="label">
<label for="clone_uri">${_('Remote uri')}:</label>
<label for="clone_uri">${_('Remote pull uri')}:</label>
</div>
<div class="input">
%if c.rhodecode_db_repo.clone_uri:
@ -83,14 +84,56 @@
${h.hidden('repo_clone_uri_change', 'NEW')}
%endif
<p id="alter_clone_uri_help_block" class="help-block">
<% pull_link = h.literal(h.link_to('remote sync', h.route_path('edit_repo_remote', repo_name=c.repo_name))) %>
${_('http[s] url where from repository was imported, this field can used for doing {pull_link}.').format(pull_link=pull_link)|n} <br/>
${_('http[s] url where from repository was imported. This field can used for doing {sync_link}.').format(sync_link=sync_link)|n} <br/>
${_('This field is stored encrypted inside Database, a format of http://user:password@server.com/repo_name can be used and will be hidden from display.')}
</p>
</div>
</div>
<div class="field">
<div class="label">
<label for="push_uri">${_('Remote push uri')}:</label>
</div>
<div class="input">
%if c.rhodecode_db_repo.push_uri:
## display, if we don't have any errors
% if not c.form['repo_push_uri'].error:
<div id="push_uri_hidden" class='text-as-placeholder'>
<span id="push_uri_hidden_value">${c.rhodecode_db_repo.push_uri_hidden}</span>
<span class="link" id="edit_push_uri"><i class="icon-edit"></i>${_('edit')}</span>
</div>
% endif
## alter field
<div id="alter_push_uri" style="${'' if c.form['repo_push_uri'].error else 'display: none'}">
${c.form['repo_push_uri'].render(css_class='medium', oid='push_uri', placeholder=_('enter new value, or leave empty to remove'))|n}
${c.form.render_error(request, c.form['repo_push_uri'])|n}
% if c.form['repo_push_uri'].error:
## we got error from form subit, means we modify the url
${h.hidden('repo_push_uri_change', 'MOD')}
% else:
${h.hidden('repo_push_uri_change', 'OLD')}
% endif
% if not c.form['repo_push_uri'].error:
<span class="link" id="cancel_edit_push_uri">${_('cancel')}</span>
% endif
</div>
%else:
## not set yet, display form to set it
${c.form['repo_push_uri'].render(css_class='medium', oid='push_uri')|n}
${c.form.render_error(request, c.form['repo_push_uri'])|n}
${h.hidden('repo_push_uri_change', 'NEW')}
%endif
<p id="alter_push_uri_help_block" class="help-block">
${_('http[s] url to sync data back. This field can used for doing {sync_link}.').format(sync_link=sync_link)|n} <br/>
${_('This field is stored encrypted inside Database, a format of http://user:password@server.com/repo_name can be used and will be hidden from display.')}
</p>
</div>
</div>
% else:
${h.hidden('repo_clone_uri', '')}
${h.hidden('repo_push_uri', '')}
% endif
<div class="field">
@ -207,16 +250,11 @@
</div>
<script>
$(document).ready(function(){
var cloneUrl = function() {
var alterButton = $('#alter_clone_uri');
var editButton = $('#edit_clone_uri');
var cancelEditButton = $('#cancel_edit_clone_uri');
var hiddenUrl = $('#clone_uri_hidden');
var hiddenUrlValue = $('#clone_uri_hidden_value');
var input = $('#clone_uri');
var helpBlock = $('#alter_clone_uri_help_block');
var changedFlag = $('#repo_clone_uri_change');
$(document).ready(function () {
var cloneUrl = function (
alterButton, editButton, cancelEditButton,
hiddenUrl, hiddenUrlValue, input, helpBlock, changedFlag) {
var originalText = helpBlock.html();
var obfuscatedUrl = hiddenUrlValue.html();
@ -255,7 +293,32 @@
setInitialState();
initEvents();
}();
};
var alterButton = $('#alter_clone_uri');
var editButton = $('#edit_clone_uri');
var cancelEditButton = $('#cancel_edit_clone_uri');
var hiddenUrl = $('#clone_uri_hidden');
var hiddenUrlValue = $('#clone_uri_hidden_value');
var input = $('#clone_uri');
var helpBlock = $('#alter_clone_uri_help_block');
var changedFlag = $('#repo_clone_uri_change');
cloneUrl(
alterButton, editButton, cancelEditButton, hiddenUrl,
hiddenUrlValue, input, helpBlock, changedFlag);
var alterButton = $('#alter_push_uri');
var editButton = $('#edit_push_uri');
var cancelEditButton = $('#cancel_edit_push_uri');
var hiddenUrl = $('#push_uri_hidden');
var hiddenUrlValue = $('#push_uri_hidden_value');
var input = $('#push_uri');
var helpBlock = $('#alter_push_uri_help_block');
var changedFlag = $('#repo_push_uri_change');
cloneUrl(
alterButton, editButton, cancelEditButton, hiddenUrl,
hiddenUrlValue, input, helpBlock, changedFlag);
selectMyGroup = function(element) {
$("#repo_group").val($(element).data('personalGroupId')).trigger("change");