changeset 1815:985f1fb3999a beta

merge with bb
author Marcin Kuzminski <marcin@python-works.com>
date Thu, 29 Dec 2011 00:02:42 +0200
parents 9de452afbe01 (diff) 58df0b3ed377 (current diff)
children ee2817f2cb3d
files
diffstat 12 files changed, 170 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/docs/api/api.rst	Wed Dec 28 11:21:04 2011 -0700
+++ b/docs/api/api.rst	Thu Dec 29 00:02:42 2011 +0200
@@ -11,6 +11,13 @@
 <your_server>/_admin/api
 
 
+API access can also be turned on for each view decorated with `@LoginRequired`
+decorator. To enable API access simple change standard login decorator into
+`@LoginRequired(api_access=True)`. After such a change view can be accessed
+by adding a GET parameter to url `?api_key=<api_key>`. By default it's only
+enabled on RSS/ATOM feed views.
+
+
 All clients are required to send JSON-RPC spec JSON data::
 
     {   
--- a/docs/usage/general.rst	Wed Dec 28 11:21:04 2011 -0700
+++ b/docs/usage/general.rst	Thu Dec 29 00:02:42 2011 +0200
@@ -36,6 +36,31 @@
 one changeset
 
 
+Non changeable repository urls
+------------------------------
+
+Due to complicated nature of repository grouping, often urls of repositories
+can change.
+
+example::
+  
+  #before
+  http://server.com/repo_name
+  # after insertion to test_group group the url will be
+  http://server.com/test_group/repo_name
+  
+This can be an issue for build systems and any other hardcoded scripts, moving
+repository to a group leads to a need for changing external systems. To 
+overcome this RhodeCode introduces a non changable replacement url. It's 
+simply an repository ID prefixed with `_` above urls are also accessible as::
+
+  http://server.com/_<ID>
+  
+Since ID are always the same moving the repository will not affect such url.
+the _<ID> syntax can be used anywhere in the system so urls with repo_name 
+for changelogs, files and other can be exchanged with _<ID> syntax.
+
+
 
 Mailing
 -------
--- a/rhodecode/config/routing.py	Wed Dec 28 11:21:04 2011 -0700
+++ b/rhodecode/config/routing.py	Thu Dec 29 00:02:42 2011 +0200
@@ -8,7 +8,6 @@
 from __future__ import with_statement
 from routes import Mapper
 
-
 # prefix for non repository related links needs to be prefixed with `/`
 ADMIN_PREFIX = '/_admin'
 
@@ -30,8 +29,17 @@
         :param environ:
         :param match_dict:
         """
+        from rhodecode.model.db import Repository
+        repo_name = match_dict.get('repo_name')
 
-        repo_name = match_dict.get('repo_name')
+        try:
+            by_id = repo_name.split('_')
+            if len(by_id) == 2 and by_id[1].isdigit():
+                repo_name = Repository.get(by_id[1]).repo_name
+                match_dict['repo_name'] = repo_name
+        except:
+            pass
+
         return is_valid_repo(repo_name, config['base_path'])
 
     def check_group(environ, match_dict):
--- a/rhodecode/controllers/summary.py	Wed Dec 28 11:21:04 2011 -0700
+++ b/rhodecode/controllers/summary.py	Thu Dec 29 00:02:42 2011 +0200
@@ -92,13 +92,20 @@
         uri_tmpl = config.get('clone_uri', default_clone_uri)
         uri_tmpl = uri_tmpl.replace('{', '%(').replace('}', ')s')
 
-        uri = uri_tmpl % {'user': username,
-                           'pass': password,
-                           'scheme': parsed_url.scheme,
-                           'netloc': parsed_url.netloc,
-                           'path':parsed_url.path}
+        uri_dict = {
+           'user': username,
+           'pass': password,
+           'scheme': parsed_url.scheme,
+           'netloc': parsed_url.netloc,
+           'path': parsed_url.path
+        }
+        uri = uri_tmpl % uri_dict
+        # generate another clone url by id
+        uri_dict.update({'path': '/_%s' % c.dbrepo.repo_id})
+        uri_id = uri_tmpl % uri_dict
 
         c.clone_repo_url = uri
+        c.clone_repo_url_id = uri_id
         c.repo_tags = OrderedDict()
         for name, hash in c.rhodecode_repo.tags.items()[:10]:
             try:
--- a/rhodecode/lib/base.py	Wed Dec 28 11:21:04 2011 -0700
+++ b/rhodecode/lib/base.py	Thu Dec 29 00:02:42 2011 +0200
@@ -4,6 +4,7 @@
 """
 import logging
 import time
+import traceback
 
 from paste.auth.basic import AuthBasicAuthenticator
 
@@ -26,8 +27,9 @@
 
 log = logging.getLogger(__name__)
 
+
 class BaseVCSController(object):
-    
+
     def __init__(self, application, config):
         self.application = application
         self.config = config
@@ -36,15 +38,37 @@
         #authenticate this mercurial request using authfunc
         self.authenticate = AuthBasicAuthenticator('', authfunc)
         self.ipaddr = '0.0.0.0'
-    
+
+    def _get_by_id(self, repo_name):
+        """
+        Get's a special pattern _<ID> from clone url and tries to replace it
+        with a repository_name for support of _<ID> non changable urls
+
+        :param repo_name:
+        """
+        try:
+            data = repo_name.split('/')
+            if len(data) >= 2:
+                by_id = data[1].split('_')
+                if len(by_id) == 2 and by_id[1].isdigit():
+                    _repo_name = Repository.get(by_id[1]).repo_name
+                    data[1] = _repo_name
+        except:
+            log.debug('Failed to extract repo_name from id %s' % (
+                      traceback.format_exc()
+                      )
+            )
+
+        return '/'.join(data)
+
     def _invalidate_cache(self, repo_name):
         """
         Set's cache for this repository for invalidation on next access
-        
+
         :param repo_name: full repo name, also a cache key
         """
         invalidate_cache('get_repo_cached_%s' % repo_name)
-                
+
     def _check_permission(self, action, user, repo_name):
         """
         Checks permissions using action (push/pull) user and repository
@@ -68,8 +92,8 @@
                                                                   repo_name):
                 return False
 
-        return True        
-        
+        return True
+
     def __call__(self, environ, start_response):
         start = time.time()
         try:
--- a/rhodecode/lib/hooks.py	Wed Dec 28 11:21:04 2011 -0700
+++ b/rhodecode/lib/hooks.py	Thu Dec 29 00:02:42 2011 +0200
@@ -41,8 +41,6 @@
     :param hooktype:
     """
 
-    if hooktype != 'changegroup':
-        return False
     size_hg, size_root = 0, 0
     for path, dirs, files in os.walk(repo.root):
         if path.find('.hg') != -1:
@@ -61,8 +59,15 @@
     size_hg_f = h.format_byte_size(size_hg)
     size_root_f = h.format_byte_size(size_root)
     size_total_f = h.format_byte_size(size_root + size_hg)
-    sys.stdout.write('Repository size .hg:%s repo:%s total:%s\n' \
-                     % (size_hg_f, size_root_f, size_total_f))
+
+    last_cs = repo[len(repo) - 1]
+
+    msg = ('Repository size .hg:%s repo:%s total:%s\n'
+           'Last revision is now r%s:%s\n') % (
+        size_hg_f, size_root_f, size_total_f, last_cs.rev(), last_cs.hex()[:12]
+    )
+
+    sys.stdout.write(msg)
 
 
 def log_pull_action(ui, repo, **kwargs):
--- a/rhodecode/lib/middleware/simplegit.py	Wed Dec 28 11:21:04 2011 -0700
+++ b/rhodecode/lib/middleware/simplegit.py	Thu Dec 29 00:02:42 2011 +0200
@@ -217,6 +217,7 @@
         :param environ: environ where PATH_INFO is stored
         """
         try:
+            environ['PATH_INFO'] = self._get_by_id(environ['PATH_INFO'])
             repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:])
             if repo_name.endswith('/'):
                 repo_name = repo_name.rstrip('/')
--- a/rhodecode/lib/middleware/simplehg.py	Wed Dec 28 11:21:04 2011 -0700
+++ b/rhodecode/lib/middleware/simplehg.py	Thu Dec 29 00:02:42 2011 +0200
@@ -180,7 +180,6 @@
         """
         return hgweb_mod.hgweb(repo_name, name=repo_name, baseui=baseui)
 
-
     def __get_repository(self, environ):
         """
         Get's repository name out of PATH_INFO header
@@ -188,6 +187,7 @@
         :param environ: environ where PATH_INFO is stored
         """
         try:
+            environ['PATH_INFO'] = self._get_by_id(environ['PATH_INFO'])
             repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:])
             if repo_name.endswith('/'):
                 repo_name = repo_name.rstrip('/')
--- a/rhodecode/public/css/style.css	Wed Dec 28 11:21:04 2011 -0700
+++ b/rhodecode/public/css/style.css	Thu Dec 29 00:02:42 2011 +0200
@@ -1350,9 +1350,11 @@
 	padding: 7px 7px 6px;
 }
 
-#content div.box div.form div.fields div.field div.input input#clone_url{
+#content div.box div.form div.fields div.field div.input input#clone_url,
+#content div.box div.form div.fields div.field div.input input#clone_url_id
+{
     font-size: 16px;
-    padding: 2px 7px 2px;	
+    padding: 2px;	
 }
 
 #content div.box div.form div.fields div.field div.file input {
@@ -3034,7 +3036,18 @@
 .ui-btn.xsmall{
     padding: 1px 2px 1px 1px;
 }
-
+.ui-btn.clone{
+	padding: 5px 2px 6px 1px;
+	margin: 0px -4px 3px 0px;
+    -webkit-border-radius: 4px 0px 0px 4px !important;
+    -khtml-border-radius: 4px 0px 0px 4px !important;
+    -moz-border-radius: 4px 0px 0px 4px !important;
+    border-radius: 4px 0px 0px 4px !important;
+    width: 100px;
+    text-align: center;
+    float: left;
+    position: absolute;
+}
 .ui-btn:focus {
   outline: none;
 }
@@ -3100,7 +3113,8 @@
 #header #header-inner #quick li a:hover span.normal,
 #header #header-inner #quick li ul li.last,
 #content div.box div.form div.fields div.field div.textarea table td table td a,
-#clone_url
+#clone_url,
+#clone_url_id
 {
 	border: none;
 }
--- a/rhodecode/templates/summary/summary.html	Wed Dec 28 11:21:04 2011 -0700
+++ b/rhodecode/templates/summary/summary.html	Thu Dec 29 00:02:42 2011 +0200
@@ -74,7 +74,7 @@
 	             %endif
 	             
 	              ##REPO NAME
-			      <span class="repo_name">${h.repo_link(c.dbrepo.groups_and_repo)}</span>
+			      <span class="repo_name" title="${_('Non changable ID %s') % c.dbrepo.repo_id}">${h.repo_link(c.dbrepo.groups_and_repo)}</span>
                   
                   ##FORK
 		          %if c.dbrepo.fork:
@@ -121,7 +121,10 @@
 			      <label>${_('Clone url')}:</label>
 			  </div>
 			  <div class="input ${summary(c.show_stats)}">
-			      <input type="text" id="clone_url" readonly="readonly" value="${c.clone_repo_url}" size="70"/>
+                  <div  style="display:none" id="clone_by_name" class="ui-btn clone">${_('Show by Name')}</div>
+                  <div id="clone_by_id" class="ui-btn clone">${_('Show by ID')}</div>
+			      <input style="width:80%;margin-left:105px" type="text" id="clone_url" readonly="readonly" value="${c.clone_repo_url}"/>
+                  <input style="display:none;width:80%;margin-left:105px" type="text" id="clone_url_id" readonly="readonly" value="${c.clone_repo_url_id}"/>
 			  </div>
 			 </div>
 			 
@@ -240,6 +243,28 @@
     }
 })
 
+YUE.on('clone_by_name','click',function(e){
+    // show url by name and hide name button
+    YUD.setStyle('clone_url','display','');
+    YUD.setStyle('clone_by_name','display','none');
+    
+    // hide url by id and show name button
+    YUD.setStyle('clone_by_id','display','');
+    YUD.setStyle('clone_url_id','display','none');    
+    
+})
+YUE.on('clone_by_id','click',function(e){
+	
+	// show url by id and hide id button
+	YUD.setStyle('clone_by_id','display','none');
+    YUD.setStyle('clone_url_id','display','');
+	   
+    // hide url by name and show id button
+	YUD.setStyle('clone_by_name','display','');
+	YUD.setStyle('clone_url','display','none');
+})
+
+
 var tmpl_links = {};
 %for cnt,archive in enumerate(c.rhodecode_repo._get_archives()):
   tmpl_links["${archive['type']}"] = '${h.link_to('__NAME__', h.url('files_archive_home',repo_name=c.dbrepo.repo_name, fname='__CS__'+archive['extension'],subrepos='__SUB__'),class_='archive_icon ui-btn')}';
--- a/rhodecode/tests/_test_concurency.py	Wed Dec 28 11:21:04 2011 -0700
+++ b/rhodecode/tests/_test_concurency.py	Thu Dec 29 00:02:42 2011 +0200
@@ -168,7 +168,6 @@
     except OSError:
         raise
 
-
     clone_url = 'http://%(user)s:%(pass)s@%(host)s/%(cloned_repo)s' % \
                   {'user':USER,
                    'pass':PASS,
@@ -191,12 +190,17 @@
         seq = None
         import time
 
+        try:
+            METHOD = sys.argv[3]
+        except:
+            pass
+
         if METHOD == 'pull':
             seq = _RandomNameSequence().next()
             test_clone_with_credentials(repo=sys.argv[1], method='clone',
                                         seq=seq)
         s = time.time()
-        for i in range(int(sys.argv[2])):
+        for i in range(1, int(sys.argv[2]) + 1):
             print 'take', i
             test_clone_with_credentials(repo=sys.argv[1], method=METHOD,
                                         seq=seq)
--- a/rhodecode/tests/functional/test_summary.py	Wed Dec 28 11:21:04 2011 -0700
+++ b/rhodecode/tests/functional/test_summary.py	Thu Dec 29 00:02:42 2011 +0200
@@ -2,27 +2,27 @@
 from rhodecode.model.db import Repository
 from rhodecode.lib.utils import invalidate_cache
 
+
 class TestSummaryController(TestController):
 
     def test_index(self):
         self.log_user()
+        ID = Repository.get_by_repo_name(HG_REPO).repo_id
         response = self.app.get(url(controller='summary',
-                                    action='index', repo_name=HG_REPO))
+                                    action='index', 
+                                    repo_name=HG_REPO))
 
         #repo type
-        self.assertTrue("""<img style="margin-bottom:2px" class="icon" """
+        response.mustcontain("""<img style="margin-bottom:2px" class="icon" """
                         """title="Mercurial repository" alt="Mercurial """
-                        """repository" src="/images/icons/hgicon.png"/>"""
-                        in response.body)
-        self.assertTrue("""<img style="margin-bottom:2px" class="icon" """
+                        """repository" src="/images/icons/hgicon.png"/>""")
+        response.mustcontain("""<img style="margin-bottom:2px" class="icon" """
                         """title="public repository" alt="public """
-                        """repository" src="/images/icons/lock_open.png"/>"""
-                        in response.body)
+                        """repository" src="/images/icons/lock_open.png"/>""")
 
         #codes stats
         self._enable_stats()
 
-
         invalidate_cache('get_repo_cached_%s' % HG_REPO)
         response = self.app.get(url(controller='summary', action='index',
                                     repo_name=HG_REPO))
@@ -37,8 +37,23 @@
                         in response.body)
 
         # clone url...
-        self.assertTrue("""<input type="text" id="clone_url" readonly="readonly" value="http://test_admin@localhost:80/%s" size="70"/>""" % HG_REPO in response.body)
+        response.mustcontain("""<input style="width:80%;margin-left:105px" type="text" id="clone_url" readonly="readonly" value="http://test_admin@localhost:80/vcs_test_hg"/>""")
+        response.mustcontain("""<input style="display:none;width:80%;margin-left:105px" type="text" id="clone_url_id" readonly="readonly" value="http://test_admin@localhost:80/_1"/>""")
 
+    def test_index_by_id(self):
+        self.log_user()
+        ID = Repository.get_by_repo_name(HG_REPO).repo_id
+        response = self.app.get(url(controller='summary',
+                                    action='index', 
+                                    repo_name='_%s' % ID))
+
+        #repo type
+        response.mustcontain("""<img style="margin-bottom:2px" class="icon" """
+                        """title="Mercurial repository" alt="Mercurial """
+                        """repository" src="/images/icons/hgicon.png"/>""")
+        response.mustcontain("""<img style="margin-bottom:2px" class="icon" """
+                        """title="public repository" alt="public """
+                        """repository" src="/images/icons/lock_open.png"/>""")
 
     def _enable_stats(self):
         r = Repository.get_by_repo_name(HG_REPO)