changeset 671:bee56f209c40 rhodecode-0.0.1.0.1

fixes few bugs - fixed #53 python2.5 incompatible enumerate calls - fixed #52 disable mercurial extension for web - fixed #51 deleting repositories don't delete it's dependent objects - small css updated
author Marcin Kuzminski <marcin@python-works.com>
date Wed, 10 Nov 2010 01:14:44 +0100
parents fe8c3989ab0e
children 6f796f56a64c
files docs/changelog.rst docs/installation.rst docs/setup.rst rhodecode/__init__.py rhodecode/lib/helpers.py rhodecode/lib/utils.py rhodecode/model/db.py rhodecode/public/css/style.css rhodecode/templates/files/files_browser.html rhodecode/templates/summary/summary.html
diffstat 10 files changed, 113 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- a/docs/changelog.rst	Tue Nov 02 20:28:28 2010 +0100
+++ b/docs/changelog.rst	Wed Nov 10 01:14:44 2010 +0100
@@ -3,6 +3,16 @@
 Changelog
 =========
 
+
+1.0.1 (**2010-11-10**)
+----------------------
+
+- fixed #53 python2.5 incompatible enumerate calls
+- fixed #52 disable mercurial extension for web
+- fixed #51 deleting repositories don't delete it's dependent objects
+- small css updated
+
+
 1.0.0 (**2010-11-02**)
 ----------------------
 
--- a/docs/installation.rst	Tue Nov 02 20:28:28 2010 +0100
+++ b/docs/installation.rst	Wed Nov 10 01:14:44 2010 +0100
@@ -5,12 +5,12 @@
 
 ``RhodeCode`` is written entirely in Python, but in order to use it's full
 potential there are some third-party requirements. When RhodeCode is used 
-together with celery You have to install some kind of message broker,
+together with celery_ You have to install some kind of message broker,
 recommended one is rabbitmq_ to make the async tasks work.
 
 Of course RhodeCode works in sync mode also, then You don't have to install
 any third party apps. Celery_ will give You large speed improvement when using
-many big repositories. If You plan to use it for 2 or 3 small repositories, it
+many big repositories. If You plan to use it for 5 or 10 small repositories, it
 will work just fine without celery running.
    
 After You decide to Run it with celery make sure You run celeryd and
@@ -33,7 +33,7 @@
 
 Easiest way to install ``rhodecode`` is to run::
 
-   easy_install rhodecode
+ easy_install rhodecode
 
 Or::
 
@@ -42,15 +42,16 @@
 If you prefer to install manually simply grab latest release from
 http://pypi.python.org/pypi/rhodecode, decompres archive and run::
 
-   python setup.py install
+ python setup.py install
 
 
 Step by step installation example
 ---------------------------------
 
 
-- Assuming You have installed virtualenv_ create one using. The `--no-site-packages`
-  will make sure non of Your system libs are linked with this virtualenv_  
+- Assuming You have installed virtualenv_ create one using. 
+  The `--no-site-packages` will make sure non of Your system libs are linked 
+  with this virtualenv_  
 
 ::
 
--- a/docs/setup.rst	Tue Nov 02 20:28:28 2010 +0100
+++ b/docs/setup.rst	Wed Nov 10 01:14:44 2010 +0100
@@ -40,6 +40,18 @@
 - Default permissions on each repository is read, and owner is admin. So 
   remember to update these if needed.
   
+Note
+----
+
+RhodeCode when running without the celery it's running all it's task in sync
+mode, for first few times when visiting summary page You can notice few
+slow downs, this is due the statistics building it's cache. After all changesets
+are parsed it'll take the stats from cache and run much faster. Each summary
+page display parse at most 250 changesets in order to not stress the cpu, so
+the full stats are going to be loaded after total_number_of_changesets/250
+summary page visits.
+
+
     
 Setting up Whoosh
 -----------------
@@ -53,9 +65,9 @@
 When using incremental mode whoosh will check last modification date of each file
 and add it to reindex if newer file is available. Also indexing daemon checks
 for removed files and removes them from index. Sometime You might want to rebuild
-index from scrach, in admin pannel You can check `build from scratch` flag
+index from scratch, in admin panel You can check `build from scratch` flag
 and in standalone daemon You can pass `full` instead on incremental to build
-remove previos index and build new one.
+remove previous index and build new one.
 
 Nginx virtual host example
 --------------------------
--- a/rhodecode/__init__.py	Tue Nov 02 20:28:28 2010 +0100
+++ b/rhodecode/__init__.py	Wed Nov 10 01:14:44 2010 +0100
@@ -24,7 +24,7 @@
 @author: marcink
 """
 
-VERSION = (1, 0, 0,)
+VERSION = (1, 0, 1,)
 
 __version__ = '.'.join((str(each) for each in VERSION[:4]))
 
--- a/rhodecode/lib/helpers.py	Tue Nov 02 20:28:28 2010 +0100
+++ b/rhodecode/lib/helpers.py	Wed Nov 10 01:14:44 2010 +0100
@@ -64,20 +64,20 @@
         return str
     else:
         str = str.replace(replace * 2, replace)
-        return recursive_replace(str, replace)  
+        return recursive_replace(str, replace)
 
 class _ToolTip(object):
-    
+
     def __call__(self, tooltip_title, trim_at=50):
         """
         Special function just to wrap our text into nice formatted autowrapped
         text
         :param tooltip_title:
         """
-        
+
         return wrap_paragraphs(escape(tooltip_title), trim_at)\
                        .replace('\n', '<br/>')
-    
+
     def activate(self):
         """
         Adds tooltip mechanism to the given Html all tooltips have to have 
@@ -85,7 +85,7 @@
         Then a tooltip will be generated based on that
         All with yui js tooltip
         """
-        
+
         js = '''
         YAHOO.util.Event.onDOMReady(function(){
             function toolTipsId(){
@@ -190,25 +190,25 @@
                     
                 });
         });
-        '''         
+        '''
         return literal(js)
 
 tooltip = _ToolTip()
 
 class _FilesBreadCrumbs(object):
-    
+
     def __call__(self, repo_name, rev, paths):
         url_l = [link_to(repo_name, url('files_home',
                                         repo_name=repo_name,
                                         revision=rev, f_path=''))]
         paths_l = paths.split('/')
-        
-        for cnt, p in enumerate(paths_l, 1):
+
+        for cnt, p in enumerate(paths_l):
             if p != '':
                 url_l.append(link_to(p, url('files_home',
                                             repo_name=repo_name,
                                             revision=rev,
-                                            f_path='/'.join(paths_l[:cnt]))))
+                                            f_path='/'.join(paths_l[:cnt + 1]))))
 
         return literal('/'.join(url_l))
 
@@ -219,9 +219,9 @@
         return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
 
     def _wrap_code(self, source):
-        for cnt, it in enumerate(source, 1):
+        for cnt, it in enumerate(source):
             i, t = it
-            t = '<div id="#S-%s">%s</div>' % (cnt, t)
+            t = '<div id="#S-%s">%s</div>' % (cnt + 1, t)
             yield i, t
 def pygmentize(filenode, **kwargs):
     """
@@ -236,12 +236,12 @@
     pygmentize function for annotation
     :param filenode:
     """
-    
+
     color_dict = {}
     def gen_color():
         """generator for getting 10k of evenly distibuted colors using hsv color
         and golden ratio.
-        """        
+        """
         import colorsys
         n = 10000
         golden_ratio = 0.618033988749895
@@ -252,21 +252,21 @@
             h %= 1
             HSV_tuple = [h, 0.95, 0.95]
             RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
-            yield map(lambda x:str(int(x * 256)), RGB_tuple)           
+            yield map(lambda x:str(int(x * 256)), RGB_tuple)
 
     cgenerator = gen_color()
-        
+
     def get_color_string(cs):
         if color_dict.has_key(cs):
             col = color_dict[cs]
         else:
             col = color_dict[cs] = cgenerator.next()
         return "color: rgb(%s)! important;" % (', '.join(col))
-        
+
     def url_func(changeset):
         tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
-        " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>" 
-        
+        " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
+
         tooltip_html = tooltip_html % (changeset.author,
                                                changeset.date,
                                                tooltip(changeset.message))
@@ -280,11 +280,11 @@
                 class_='tooltip',
                 tooltip_title=tooltip_html
               )
-        
+
         uri += '\n'
-        return uri   
+        return uri
     return literal(annotate_highlight(filenode, url_func, **kwargs))
-      
+
 def repo_name_slug(value):
     """Return slug of name of repository
     This function is called on each creation/modification
@@ -292,7 +292,7 @@
     """
     slug = remove_formatting(value)
     slug = strip_tags(slug)
-    
+
     for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
         slug = slug.replace(c, '-')
     slug = recursive_replace(slug, '-')
@@ -305,7 +305,7 @@
     if not isinstance(repo, BaseRepository):
         raise Exception('You must pass an Repository '
                         'object as first argument got %s', type(repo))
-        
+
     try:
         cs = repo.get_changeset(rev)
     except RepositoryError:
@@ -358,8 +358,8 @@
     baseurl_nossl = "http://www.gravatar.com/avatar/"
     baseurl_ssl = "https://secure.gravatar.com/avatar/"
     baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
-        
-    
+
+
     # construct the url
     gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
     gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
@@ -370,7 +370,7 @@
     """safe unicode function. In case of UnicodeDecode error we try to return
     unicode with errors replace, if this failes we return unicode with 
     string_escape decoding """
-    
+
     try:
         u_str = unicode(str)
     except UnicodeDecodeError:
@@ -379,5 +379,5 @@
         except UnicodeDecodeError:
             #incase we have a decode error just represent as byte string
             u_str = unicode(str(str).encode('string_escape'))
-        
+
     return u_str
--- a/rhodecode/lib/utils.py	Tue Nov 02 20:28:28 2010 +0100
+++ b/rhodecode/lib/utils.py	Wed Nov 10 01:14:44 2010 +0100
@@ -221,6 +221,11 @@
             for k, v in cfg.items(section):
                 baseui.setconfig(section, k, v)
                 log.debug('settings ui from file[%s]%s:%s', section, k, v)
+
+        for k, v in baseui.configitems('extensions'):
+            baseui.setconfig('extensions', k, '0')
+        #just enable mq
+        baseui.setconfig('extensions', 'mq', '1')
         if checkpaths:check_repo_dir(cfg.items('paths'))
 
 
--- a/rhodecode/model/db.py	Tue Nov 02 20:28:28 2010 +0100
+++ b/rhodecode/model/db.py	Wed Nov 10 01:14:44 2010 +0100
@@ -22,9 +22,9 @@
     ui_key = Column("ui_key", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     ui_value = Column("ui_value", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     ui_active = Column("ui_active", BOOLEAN(), nullable=True, unique=None, default=True)
-    
-    
-class User(Base): 
+
+
+class User(Base):
     __tablename__ = 'users'
     __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
     user_id = Column("user_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
@@ -36,21 +36,21 @@
     lastname = Column("lastname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     email = Column("email", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     last_login = Column("last_login", DATETIME(timezone=False), nullable=True, unique=None, default=None)
-    
+
     user_log = relation('UserLog')
     user_perms = relation('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id")
-    
+
     @LazyProperty
     def full_contact(self):
         return '%s %s <%s>' % (self.name, self.lastname, self.email)
-        
+
     def __repr__(self):
         return "<User('id:%s:%s')>" % (self.user_id, self.username)
-    
+
     def update_lastlogin(self):
         """Update user lastlogin"""
         import datetime
-        
+
         try:
             session = Session.object_session(self)
             self.last_login = datetime.datetime.now()
@@ -58,24 +58,24 @@
             session.commit()
             log.debug('updated user %s lastlogin', self.username)
         except Exception:
-            session.rollback()        
-    
-      
-class UserLog(Base): 
+            session.rollback()
+
+
+class UserLog(Base):
     __tablename__ = 'user_logs'
     __table_args__ = {'useexisting':True}
     user_log_id = Column("user_log_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
     user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
     repository_id = Column("repository_id", INTEGER(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
     repository_name = Column("repository_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
-    user_ip = Column("user_ip", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 
+    user_ip = Column("user_ip", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     action = Column("action", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     action_date = Column("action_date", DATETIME(timezone=False), nullable=True, unique=None, default=None)
     revision = Column('revision', TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
-    
+
     user = relation('User')
     repository = relation('Repository')
-    
+
 class Repository(Base):
     __tablename__ = 'repositories'
     __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
@@ -85,21 +85,23 @@
     private = Column("private", BOOLEAN(), nullable=True, unique=None, default=None)
     description = Column("description", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     fork_id = Column("fork_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=True, unique=False, default=None)
-    
+
     user = relation('User')
     fork = relation('Repository', remote_side=repo_id)
     repo_to_perm = relation('RepoToPerm', cascade='all')
-    
+    stats = relation('Statistics', cascade='all')
+
+
     def __repr__(self):
         return "<Repository('id:%s:%s')>" % (self.repo_id, self.repo_name)
-        
+
 class Permission(Base):
     __tablename__ = 'permissions'
     __table_args__ = {'useexisting':True}
     permission_id = Column("permission_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
     permission_name = Column("permission_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     permission_longname = Column("permission_longname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
-    
+
     def __repr__(self):
         return "<Permission('%s:%s')>" % (self.permission_id, self.permission_name)
 
@@ -109,8 +111,8 @@
     repo_to_perm_id = Column("repo_to_perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
     user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
     permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
-    repository_id = Column("repository_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None) 
-    
+    repository_id = Column("repository_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
+
     user = relation('User')
     permission = relation('Permission')
     repository = relation('Repository')
@@ -121,7 +123,7 @@
     user_to_perm_id = Column("user_to_perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
     user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
     permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
-    
+
     user = relation('User')
     permission = relation('Permission')
 
@@ -134,6 +136,6 @@
     commit_activity = Column("commit_activity", BLOB(), nullable=False)#JSON data
     commit_activity_combined = Column("commit_activity_combined", BLOB(), nullable=False)#JSON data
     languages = Column("languages", BLOB(), nullable=False)#JSON data
-    
-    repository = relation('Repository')
 
+    repository = relation('Repository', single_parent=True)
+
--- a/rhodecode/public/css/style.css	Tue Nov 02 20:28:28 2010 +0100
+++ b/rhodecode/public/css/style.css	Wed Nov 10 01:14:44 2010 +0100
@@ -270,7 +270,7 @@
 }
 
 #header #header-inner #logo a:hover {
-color:#dabf29;
+color:#bfe3ff;
 }
 
 #header #header-inner #quick,#header #header-inner #quick ul {
@@ -419,7 +419,7 @@
 }
 
 #header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover {
-background:url("../images/icons/folder_edit.png") no-repeat scroll 4px 9px #FFF;
+background:url("../images/icons/database_edit.png") no-repeat scroll 4px 9px #FFF;
 width:167px;
 margin:0;
 padding:12px 9px 7px 24px;
@@ -1010,7 +1010,7 @@
 #content div.box table th {
 background:#eee;
 border-bottom:1px solid #ddd;
-padding:10px;
+padding:5px 0px 5px 5px;
 }
 
 #content div.box table th.left {
@@ -1393,7 +1393,6 @@
 color:#FFF;
 display:block;
 min-width:20px;
-max-width:400px;
 text-decoration:none;
 height:12px;
 margin-bottom:4px;
@@ -1542,7 +1541,7 @@
 
 .right .merge {
 vertical-align:top;
-font-size:60%;
+font-size:0.75em;
 font-weight:700;
 }
 
@@ -1554,13 +1553,15 @@
 .right .logtags .branchtag {
 background:#FFF url("../images/icons/arrow_branch.png") no-repeat right 6px;
 display:block;
-padding:8px 16px 0 0;
+font-size:0.8em;
+padding:11px 16px 0 0;
 }
 
 .right .logtags .tagtag {
 background:#FFF url("../images/icons/tag_blue.png") no-repeat right 6px;
 display:block;
-padding:6px 18px 0 0;
+font-size:0.8em;
+padding:11px 16px 0 0;
 }
 
 div.browserblock {
@@ -1701,6 +1702,7 @@
 width:auto;
 opacity:1px;
 padding:8px;
+white-space: pre;
 }
 
 .ac {
@@ -2024,7 +2026,6 @@
 }
 
 #content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a {
-background:url("../../images/title_tab_selected.png") no-repeat bottom center;
 color:#bfe3ff;
 }
 
--- a/rhodecode/templates/files/files_browser.html	Tue Nov 02 20:28:28 2010 +0100
+++ b/rhodecode/templates/files/files_browser.html	Wed Nov 10 01:14:44 2010 +0100
@@ -43,8 +43,8 @@
 				</tr>	          		
           		%endif
 		         	
-		    %for cnt,node in enumerate(c.files_list,1):
-				<tr class="parity${cnt%2}">
+		    %for cnt,node in enumerate(c.files_list):
+				<tr class="parity${(cnt+1)%2}">
 		             <td>
 						${h.link_to(node.name,h.url('files_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=node.path),class_=file_class(node))}
 		             </td>
@@ -59,19 +59,19 @@
 		              %endif
 		             </td>
 		             <td>
-		             	%if node.is_file():
-		             		${node.last_changeset.revision}
-		             	%endif
+	             	  %if node.is_file():
+	             		  ${node.last_changeset.revision}
+	             	  %endif
 		             </td>
 		             <td>
-		             	%if node.is_file():
-		             		${h.age(node.last_changeset._ctx.date())} - ${node.last_changeset.date}
-		             	%endif
+		              %if node.is_file():
+		                  ${h.age(node.last_changeset._ctx.date())} - ${node.last_changeset.date}
+		              %endif
 		             </td>
 		             <td>
-		             	%if node.is_file():
-		             		${node.last_changeset.author}
-		             	%endif                    
+		              %if node.is_file():
+		                  ${node.last_changeset.author}
+		              %endif                    
 		             </td>
 				</tr>
 			%endfor
--- a/rhodecode/templates/summary/summary.html	Tue Nov 02 20:28:28 2010 +0100
+++ b/rhodecode/templates/summary/summary.html	Wed Nov 10 01:14:44 2010 +0100
@@ -131,11 +131,13 @@
 						var value = data[k];
 				  		var td1 = document.createElement('td');
 				  		td1.width=150;
+                        
 				  		var trending_language_label = document.createElement('div');
 				  		trending_language_label.innerHTML = k;
 				  		td1.appendChild(trending_language_label);
 
 				  		var td2 = document.createElement('td');
+				  		td2.setAttribute('style','padding-right: 12px ! important;');
 			  		    var trending_language = document.createElement('div');
 			  		    trending_language.title = k;
 			  		    trending_language.innerHTML = "<b>"+percentage+"% "+value+" ${_('files')}</b>";