##// END OF EJS Templates
landing-rev: fixes #4102, use branches instead of landing tip refs by default....
marcink -
r3881:95b6f937 default
parent child Browse files
Show More
@@ -20,11 +20,16 b''
20 20
21 21
22 22 import random
23 import pytest
23 24
24 25 from rhodecode.api.utils import get_origin
25 26 from rhodecode.lib.ext_json import json
26 27
27 28
29 def jsonify(obj):
30 return json.loads(json.dumps(obj))
31
32
28 33 API_URL = '/_admin/api'
29 34
30 35
@@ -42,12 +47,16 b' def assert_call_ok(id_, given):'
42 47
43 48
44 49 def assert_ok(id_, expected, given):
50 given = json.loads(given)
51 if given.get('error'):
52 pytest.fail("Unexpected ERROR in success response: {}".format(given['error']))
53
45 54 expected = jsonify({
46 55 'id': id_,
47 56 'error': None,
48 57 'result': expected
49 58 })
50 given = json.loads(given)
59
51 60 assert expected == given
52 61
53 62
@@ -61,10 +70,6 b' def assert_error(id_, expected, given):'
61 70 assert expected == given
62 71
63 72
64 def jsonify(obj):
65 return json.loads(json.dumps(obj))
66
67
68 73 def build_data(apikey, method, **kw):
69 74 """
70 75 Builds API data with given random ID
@@ -711,7 +711,7 b' def create_repo('
711 711 private=Optional(False),
712 712 clone_uri=Optional(None),
713 713 push_uri=Optional(None),
714 landing_rev=Optional('rev:tip'),
714 landing_rev=Optional(None),
715 715 enable_statistics=Optional(False),
716 716 enable_locking=Optional(False),
717 717 enable_downloads=Optional(False),
@@ -746,7 +746,7 b' def create_repo('
746 746 :type clone_uri: str
747 747 :param push_uri: set push_uri
748 748 :type push_uri: str
749 :param landing_rev: <rev_type>:<rev>
749 :param landing_rev: <rev_type>:<rev>, e.g branch:default, book:dev, rev:abcd
750 750 :type landing_rev: str
751 751 :param enable_locking:
752 752 :type enable_locking: bool
@@ -790,7 +790,6 b' def create_repo('
790 790 copy_permissions = Optional.extract(copy_permissions)
791 791 clone_uri = Optional.extract(clone_uri)
792 792 push_uri = Optional.extract(push_uri)
793 landing_commit_ref = Optional.extract(landing_rev)
794 793
795 794 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
796 795 if isinstance(private, Optional):
@@ -804,8 +803,15 b' def create_repo('
804 803 if isinstance(enable_downloads, Optional):
805 804 enable_downloads = defs.get('repo_enable_downloads')
806 805
806 landing_ref, _label = ScmModel.backend_landing_ref(repo_type)
807 ref_choices, _labels = ScmModel().get_repo_landing_revs(request.translate)
808 ref_choices = list(set(ref_choices + [landing_ref]))
809
810 landing_commit_ref = Optional.extract(landing_rev) or landing_ref
811
807 812 schema = repo_schema.RepoSchema().bind(
808 813 repo_type_options=rhodecode.BACKENDS.keys(),
814 repo_ref_options=ref_choices,
809 815 repo_type=repo_type,
810 816 # user caller
811 817 user=apiuser)
@@ -955,7 +961,7 b' def update_repo('
955 961 owner=Optional(OAttr('apiuser')), description=Optional(''),
956 962 private=Optional(False),
957 963 clone_uri=Optional(None), push_uri=Optional(None),
958 landing_rev=Optional('rev:tip'), fork_of=Optional(None),
964 landing_rev=Optional(None), fork_of=Optional(None),
959 965 enable_statistics=Optional(False),
960 966 enable_locking=Optional(False),
961 967 enable_downloads=Optional(False), fields=Optional('')):
@@ -990,7 +996,7 b' def update_repo('
990 996 :type private: bool
991 997 :param clone_uri: Update the |repo| clone URI.
992 998 :type clone_uri: str
993 :param landing_rev: Set the |repo| landing revision. Default is ``rev:tip``.
999 :param landing_rev: Set the |repo| landing revision. e.g branch:default, book:dev, rev:abcd
994 1000 :type landing_rev: str
995 1001 :param enable_statistics: Enable statistics on the |repo|, (True | False).
996 1002 :type enable_statistics: bool
@@ -1046,8 +1052,10 b' def update_repo('
1046 1052 repo_enable_downloads=enable_downloads
1047 1053 if not isinstance(enable_downloads, Optional) else repo.enable_downloads)
1048 1054
1055 landing_ref, _label = ScmModel.backend_landing_ref(repo.repo_type)
1049 1056 ref_choices, _labels = ScmModel().get_repo_landing_revs(
1050 1057 request.translate, repo=repo)
1058 ref_choices = list(set(ref_choices + [landing_ref]))
1051 1059
1052 1060 old_values = repo.get_api_data()
1053 1061 repo_type = repo.repo_type
@@ -1125,7 +1133,7 b' def fork_repo(request, apiuser, repoid, '
1125 1133 description=Optional(''),
1126 1134 private=Optional(False),
1127 1135 clone_uri=Optional(None),
1128 landing_rev=Optional('rev:tip'),
1136 landing_rev=Optional(None),
1129 1137 copy_permissions=Optional(False)):
1130 1138 """
1131 1139 Creates a fork of the specified |repo|.
@@ -1155,7 +1163,7 b' def fork_repo(request, apiuser, repoid, '
1155 1163 :type copy_permissions: bool
1156 1164 :param private: Make the fork private. The default is False.
1157 1165 :type private: bool
1158 :param landing_rev: Set the landing revision. The default is tip.
1166 :param landing_rev: Set the landing revision. E.g branch:default, book:dev, rev:abcd
1159 1167
1160 1168 Example output:
1161 1169
@@ -1207,11 +1215,17 b' def fork_repo(request, apiuser, repoid, '
1207 1215 description = Optional.extract(description)
1208 1216 copy_permissions = Optional.extract(copy_permissions)
1209 1217 clone_uri = Optional.extract(clone_uri)
1210 landing_commit_ref = Optional.extract(landing_rev)
1218
1219 landing_ref, _label = ScmModel.backend_landing_ref(repo.repo_type)
1220 ref_choices, _labels = ScmModel().get_repo_landing_revs(request.translate)
1221 ref_choices = list(set(ref_choices + [landing_ref]))
1222 landing_commit_ref = Optional.extract(landing_rev) or landing_ref
1223
1211 1224 private = Optional.extract(private)
1212 1225
1213 1226 schema = repo_schema.RepoSchema().bind(
1214 1227 repo_type_options=rhodecode.BACKENDS.keys(),
1228 repo_ref_options=ref_choices,
1215 1229 repo_type=repo.repo_type,
1216 1230 # user caller
1217 1231 user=apiuser)
@@ -59,8 +59,6 b' class AdminReposView(BaseAppView, DataGr'
59 59 perm_set=['group.write', 'group.admin'])
60 60 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
61 61 c.repo_groups_choices = map(lambda k: safe_unicode(k[0]), c.repo_groups)
62 c.landing_revs_choices, c.landing_revs = \
63 ScmModel().get_repo_landing_revs(self.request.translate)
64 62 c.personal_repo_group = self._rhodecode_user.personal_repo_group
65 63
66 64 @LoginRequired()
@@ -150,8 +148,7 b' class AdminReposView(BaseAppView, DataGr'
150 148 try:
151 149 # CanWriteToGroup validators checks permissions of this POST
152 150 form = RepoForm(
153 self.request.translate, repo_groups=c.repo_groups_choices,
154 landing_revs=c.landing_revs_choices)()
151 self.request.translate, repo_groups=c.repo_groups_choices)()
155 152 form_result = form.to_python(dict(self.request.POST))
156 153 copy_permissions = form_result.get('repo_copy_permissions')
157 154 # create is done sometimes async on celery, db transaction
@@ -55,9 +55,7 b' class RepoForksView(RepoAppView, DataGri'
55 55 perm_set=['group.write', 'group.admin'])
56 56 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
57 57 c.repo_groups_choices = map(lambda k: safe_unicode(k[0]), c.repo_groups)
58 choices, c.landing_revs = ScmModel().get_repo_landing_revs(
59 self.request.translate)
60 c.landing_revs_choices = choices
58
61 59 c.personal_repo_group = c.rhodecode_user.personal_repo_group
62 60
63 61 return c
@@ -212,9 +210,9 b' class RepoForksView(RepoAppView, DataGri'
212 210 _ = self.request.translate
213 211 c = self.load_default_context()
214 212
215 _form = RepoForkForm(self.request.translate, old_data={'repo_type': self.db_repo.repo_type},
216 repo_groups=c.repo_groups_choices,
217 landing_revs=c.landing_revs_choices)()
213 _form = RepoForkForm(self.request.translate,
214 old_data={'repo_type': self.db_repo.repo_type},
215 repo_groups=c.repo_groups_choices)()
218 216 post_data = dict(self.request.POST)
219 217
220 218 # forbid injecting other repo by forging a request
@@ -20,6 +20,8 b''
20 20
21 21 import logging
22 22 import string
23 import time
24
23 25 import rhodecode
24 26
25 27 from pyramid.view import view_config
@@ -53,24 +55,25 b' class RepoSummaryView(RepoAppView):'
53 55 return c
54 56
55 57 def _get_readme_data(self, db_repo, renderer_type):
56
57 58 log.debug('Looking for README file')
59 landing_commit = db_repo.get_landing_commit()
60 if isinstance(landing_commit, EmptyCommit):
61 return None, None
58 62
59 63 cache_namespace_uid = 'cache_repo_instance.{}_{}'.format(
60 64 db_repo.repo_id, CacheKey.CACHE_TYPE_README)
61 invalidation_namespace = CacheKey.REPO_INVALIDATION_NAMESPACE.format(
62 repo_id=self.db_repo.repo_id)
63 65 region = rc_cache.get_or_create_region('cache_repo_longterm', cache_namespace_uid)
66 start = time.time()
64 67
65 68 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid)
66 def generate_repo_readme(repo_id, _repo_name, _renderer_type):
69 def generate_repo_readme(repo_id, commit_id, _repo_name, _renderer_type):
67 70 readme_data = None
68 readme_node = None
69 71 readme_filename = None
70 commit = self._get_landing_commit_or_none(db_repo)
71 if commit:
72 log.debug("Searching for a README file.")
73 readme_node = ReadmeFinder(_renderer_type).search(commit)
72
73 commit = db_repo.get_commit(commit_id)
74 log.debug("Searching for a README file at commit %s.", commit_id)
75 readme_node = ReadmeFinder(_renderer_type).search(commit)
76
74 77 if readme_node:
75 78 log.debug('Found README node: %s', readme_node)
76 79 relative_urls = {
@@ -81,42 +84,19 b' class RepoSummaryView(RepoAppView):'
81 84 'repo_files', repo_name=_repo_name,
82 85 commit_id=commit.raw_id, f_path=readme_node.path),
83 86 }
84 readme_data = self._render_readme_or_none(
85 commit, readme_node, relative_urls)
87 readme_data = self._render_readme_or_none(commit, readme_node, relative_urls)
86 88 readme_filename = readme_node.unicode_path
87 89
88 90 return readme_data, readme_filename
89 91
90 inv_context_manager = rc_cache.InvalidationContext(
91 uid=cache_namespace_uid, invalidation_namespace=invalidation_namespace)
92 with inv_context_manager as invalidation_context:
93 args = (db_repo.repo_id, db_repo.repo_name, renderer_type,)
94 # re-compute and store cache if we get invalidate signal
95 if invalidation_context.should_invalidate():
96 instance = generate_repo_readme.refresh(*args)
97 else:
98 instance = generate_repo_readme(*args)
99
100 log.debug(
101 'Repo readme generated and computed in %.4fs',
102 inv_context_manager.compute_time)
103 return instance
104
105 def _get_landing_commit_or_none(self, db_repo):
106 log.debug("Getting the landing commit.")
107 try:
108 commit = db_repo.get_landing_commit()
109 if not isinstance(commit, EmptyCommit):
110 return commit
111 else:
112 log.debug("Repository is empty, no README to render.")
113 except CommitError:
114 log.exception(
115 "Problem getting commit when trying to render the README.")
92 readme_data, readme_filename = generate_repo_readme(
93 db_repo.repo_id, landing_commit.raw_id, db_repo.repo_name, renderer_type,)
94 compute_time = time.time() - start
95 log.debug('Repo readme generated and computed in %.4fs', compute_time)
96 return readme_data, readme_filename
116 97
117 98 def _render_readme_or_none(self, commit, readme_node, relative_urls):
118 log.debug(
119 'Found README file `%s` rendering...', readme_node.path)
99 log.debug('Found README file `%s` rendering...', readme_node.path)
120 100 renderer = MarkupRenderer()
121 101 try:
122 102 html_source = renderer.render(
@@ -125,6 +125,7 b' def send_email(recipients, subject, body'
125 125 def create_repo(form_data, cur_user):
126 126 from rhodecode.model.repo import RepoModel
127 127 from rhodecode.model.user import UserModel
128 from rhodecode.model.scm import ScmModel
128 129 from rhodecode.model.settings import SettingsModel
129 130
130 131 log = get_logger(create_repo)
@@ -139,7 +140,6 b' def create_repo(form_data, cur_user):'
139 140 private = form_data['repo_private']
140 141 clone_uri = form_data.get('clone_uri')
141 142 repo_group = safe_int(form_data['repo_group'])
142 landing_rev = form_data['repo_landing_rev']
143 143 copy_fork_permissions = form_data.get('copy_permissions')
144 144 copy_group_permissions = form_data.get('repo_copy_permissions')
145 145 fork_of = form_data.get('fork_parent_id')
@@ -154,6 +154,9 b' def create_repo(form_data, cur_user):'
154 154 enable_downloads = form_data.get(
155 155 'enable_downloads', defs.get('repo_enable_downloads'))
156 156
157 # set landing rev based on default branches for SCM
158 landing_ref, _label = ScmModel.backend_landing_ref(repo_type)
159
157 160 try:
158 161 RepoModel()._create_repo(
159 162 repo_name=repo_name_full,
@@ -163,7 +166,7 b' def create_repo(form_data, cur_user):'
163 166 private=private,
164 167 clone_uri=clone_uri,
165 168 repo_group=repo_group,
166 landing_rev=landing_rev,
169 landing_rev=landing_ref,
167 170 fork_of=fork_of,
168 171 copy_fork_permissions=copy_fork_permissions,
169 172 copy_group_permissions=copy_group_permissions,
@@ -244,12 +244,10 b' def PasswordResetForm(localizer):'
244 244 return _PasswordResetForm
245 245
246 246
247 def RepoForm(localizer, edit=False, old_data=None, repo_groups=None,
248 landing_revs=None, allow_disabled=False):
247 def RepoForm(localizer, edit=False, old_data=None, repo_groups=None, allow_disabled=False):
249 248 _ = localizer
250 249 old_data = old_data or {}
251 250 repo_groups = repo_groups or []
252 landing_revs = landing_revs or []
253 251 supported_backends = BACKENDS.keys()
254 252
255 253 class _RepoForm(formencode.Schema):
@@ -263,7 +261,6 b' def RepoForm(localizer, edit=False, old_'
263 261 if_missing=old_data.get('repo_type'))
264 262 repo_description = v.UnicodeString(strip=True, min=1, not_empty=False)
265 263 repo_private = v.StringBoolean(if_missing=False)
266 repo_landing_rev = v.OneOf(landing_revs, hideList=True)
267 264 repo_copy_permissions = v.StringBoolean(if_missing=False)
268 265 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
269 266
@@ -333,12 +330,10 b' def RepoFieldForm(localizer):'
333 330
334 331
335 332 def RepoForkForm(localizer, edit=False, old_data=None,
336 supported_backends=BACKENDS.keys(), repo_groups=None,
337 landing_revs=None):
333 supported_backends=BACKENDS.keys(), repo_groups=None):
338 334 _ = localizer
339 335 old_data = old_data or {}
340 336 repo_groups = repo_groups or []
341 landing_revs = landing_revs or []
342 337
343 338 class _RepoForkForm(formencode.Schema):
344 339 allow_extra_fields = True
@@ -353,7 +348,6 b' def RepoForkForm(localizer, edit=False, '
353 348 copy_permissions = v.StringBoolean(if_missing=False)
354 349 fork_parent_id = v.UnicodeString()
355 350 chained_validators = [v.ValidForkName(localizer, edit, old_data)]
356 landing_rev = v.OneOf(landing_revs, hideList=True)
357 351 return _RepoForkForm
358 352
359 353
@@ -891,6 +891,21 b' class ScmModel(BaseModel):'
891 891 def get_unread_journal(self):
892 892 return self.sa.query(UserLog).count()
893 893
894 @classmethod
895 def backend_landing_ref(cls, repo_type):
896 """
897 Return a default landing ref based on a repository type.
898 """
899
900 landing_ref = {
901 'hg': ('branch:default', 'default'),
902 'git': ('branch:master', 'master'),
903 'svn': ('rev:tip', 'latest tip'),
904 'default': ('rev:tip', 'latest tip'),
905 }
906
907 return landing_ref.get(repo_type) or landing_ref['default']
908
894 909 def get_repo_landing_revs(self, translator, repo=None):
895 910 """
896 911 Generates select option with tags branches and bookmarks (for hg only)
@@ -901,41 +916,56 b' class ScmModel(BaseModel):'
901 916 _ = translator
902 917 repo = self._get_repo(repo)
903 918
904 hist_l = [
905 ['rev:tip', _('latest tip')]
919 if repo:
920 repo_type = repo.repo_type
921 else:
922 repo_type = 'default'
923
924 default_landing_ref, landing_ref_lbl = self.backend_landing_ref(repo_type)
925
926 default_ref_options = [
927 [default_landing_ref, landing_ref_lbl]
906 928 ]
907 choices = [
908 'rev:tip'
929 default_choices = [
930 default_landing_ref
909 931 ]
910 932
911 933 if not repo:
912 return choices, hist_l
934 return default_choices, default_ref_options
913 935
914 936 repo = repo.scm_instance()
915 937
916 branches_group = (
917 [(u'branch:%s' % safe_unicode(b), safe_unicode(b))
918 for b in repo.branches],
919 _("Branches"))
920 hist_l.append(branches_group)
938 ref_options = [('rev:tip', 'latest tip')]
939 choices = ['rev:tip']
940
941 # branches
942 branch_group = [(u'branch:%s' % safe_unicode(b), safe_unicode(b)) for b in repo.branches]
943 if not branch_group:
944 # new repo, or without maybe a branch?
945 branch_group = default_ref_options
946
947 branches_group = (branch_group, _("Branches"))
948 ref_options.append(branches_group)
921 949 choices.extend([x[0] for x in branches_group[0]])
922 950
951 # bookmarks for HG
923 952 if repo.alias == 'hg':
924 953 bookmarks_group = (
925 954 [(u'book:%s' % safe_unicode(b), safe_unicode(b))
926 955 for b in repo.bookmarks],
927 956 _("Bookmarks"))
928 hist_l.append(bookmarks_group)
957 ref_options.append(bookmarks_group)
929 958 choices.extend([x[0] for x in bookmarks_group[0]])
930 959
960 # tags
931 961 tags_group = (
932 962 [(u'tag:%s' % safe_unicode(t), safe_unicode(t))
933 963 for t in repo.tags],
934 964 _("Tags"))
935 hist_l.append(tags_group)
965 ref_options.append(tags_group)
936 966 choices.extend([x[0] for x in tags_group[0]])
937 967
938 return choices, hist_l
968 return choices, ref_options
939 969
940 970 def get_server_info(self, environ=None):
941 971 server_info = get_system_info(environ)
@@ -26,6 +26,11 b' from rhodecode.model.validation_schema.u'
26 26 from rhodecode.model.validation_schema import validators, preparers, types
27 27
28 28 DEFAULT_LANDING_REF = 'rev:tip'
29 DEFAULT_BACKEND_LANDING_REF = {
30 'hg': 'branch:default',
31 'git': 'branch:master',
32 'svn': 'rev:tip',
33 }
29 34
30 35
31 36 def get_group_and_repo(repo_name):
@@ -74,8 +79,14 b' def deferred_sync_uri_validator(node, kw'
74 79
75 80 @colander.deferred
76 81 def deferred_landing_ref_widget(node, kw):
77 items = kw.get(
78 'repo_ref_items', [(DEFAULT_LANDING_REF, DEFAULT_LANDING_REF)])
82 repo_type = kw.get('repo_type')
83 default_opts = []
84 if repo_type:
85 default_opts.append(
86 (DEFAULT_BACKEND_LANDING_REF[repo_type],
87 DEFAULT_BACKEND_LANDING_REF[repo_type]))
88
89 items = kw.get('repo_ref_items', default_opts)
79 90 items = convert_to_optgroup(items)
80 91 return deform.widget.Select2Widget(values=items)
81 92
@@ -39,15 +39,6 b''
39 39 </div>
40 40 </div>
41 41 <div class="field">
42 <div class="label">
43 <label for="repo_type">${_('Type')}:</label>
44 </div>
45 <div class="select">
46 ${h.select('repo_type','hg',c.backends)}
47 <span class="help-block">${_('Set the type of repository to create.')}</span>
48 </div>
49 </div>
50 <div class="field">
51 42 <div class="label">
52 43 <label for="repo_group">${_('Repository group')}:</label>
53 44 </div>
@@ -63,6 +54,15 b''
63 54 </div>
64 55 <div class="field">
65 56 <div class="label">
57 <label for="repo_type">${_('Type')}:</label>
58 </div>
59 <div class="select">
60 ${h.select('repo_type','hg',c.backends)}
61 <span class="help-block">${_('Set the type of repository to create.')}</span>
62 </div>
63 </div>
64 <div class="field">
65 <div class="label">
66 66 <label for="repo_description">${_('Description')}:</label>
67 67 </div>
68 68 <div class="textarea editor">
@@ -75,15 +75,6 b''
75 75 </span>
76 76 </div>
77 77 </div>
78 <div class="field">
79 <div class="label">
80 <label for="repo_landing_rev">${_('Landing commit')}:</label>
81 </div>
82 <div class="select">
83 ${h.select('repo_landing_rev','',c.landing_revs,class_="medium")}
84 <span class="help-block">${_('The default commit for file pages, downloads, full text search index, and README generation.')}</span>
85 </div>
86 </div>
87 78 <div id="copy_perms" class="field">
88 79 <div class="label label-checkbox">
89 80 <label for="repo_copy_permissions">${_('Copy Parent Group Permissions')}:</label>
@@ -147,11 +138,7 b''
147 138 'dropdownCssClass': "drop-menu-dropdown",
148 139 'minimumResultsForSearch': -1,
149 140 });
150 $("#repo_landing_rev").select2({
151 'containerCssClass': "drop-menu",
152 'dropdownCssClass': "drop-menu-dropdown",
153 'minimumResultsForSearch': -1,
154 });
141
155 142 $('#repo_name').focus();
156 143
157 144 $('#select_my_group').on('click', function(e){
@@ -67,16 +67,6 b''
67 67 </div>
68 68
69 69 <div class="field">
70 <div class="label">
71 <label for="landing_rev">${_('Landing commit')}:</label>
72 </div>
73 <div class="select">
74 ${h.select('landing_rev','',c.landing_revs,class_="medium")}
75 <span class="help-block">${_('The default commit for file pages, downloads, full text search index, and README generation.')}</span>
76 </div>
77 </div>
78
79 <div class="field">
80 70 <div class="label label-checkbox">
81 71 <label for="private">${_('Copy permissions')}:</label>
82 72 </div>
General Comments 0
You need to be logged in to leave comments. Login now