diff --git a/docs/changelog.rst b/docs/changelog.rst --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -17,13 +17,17 @@ fixes incompatible - setup-app will check for write permission in given path - cleaned up license info issue #149 -- fixes for issues #137 and #116 +- fixes for issues #137,#116 and #116, problems with unicode and + accented characters. - fixes crashes on gravatar, when passed in email as unicode - fixed tooltip flickering problems - fixed came_from redirection on windows - fixed logging modules,and sql formatters -- windows fixes for os.kill and path spliting, issues #148 and #133 +- windows fixes for os.kill #133 +- fixes path splitting for windows issues #148 +- fixed issue #143 wrong import on migration to 1.1.X + 1.1.7 (**2011-03-23**) ====================== diff --git a/rhodecode/lib/dbmigrate/versions/002_version_1_1_0.py b/rhodecode/lib/dbmigrate/versions/002_version_1_1_0.py --- a/rhodecode/lib/dbmigrate/versions/002_version_1_1_0.py +++ b/rhodecode/lib/dbmigrate/versions/002_version_1_1_0.py @@ -6,14 +6,14 @@ from sqlalchemy.exc import DatabaseError from sqlalchemy.orm import relation, backref, class_mapper from sqlalchemy.orm.session import Session from rhodecode.model.meta import Base -from rhodecode.model.db import BaseModel from rhodecode.lib.dbmigrate.migrate import * +from rhodecode.lib.dbmigrate.migrate.changeset import * log = logging.getLogger(__name__) def upgrade(migrate_engine): - """ Upgrade operations go here. + """ Upgrade operations go here. Don't create your own engine; bind migrate_engine to your metadata """ @@ -32,7 +32,7 @@ def upgrade(migrate_engine): #========================================================================== # Upgrade of `user_logs` table - #========================================================================== + #========================================================================== tblname = 'users' tbl = Table(tblname, MetaData(bind=migrate_engine), autoload=True, @@ -48,7 +48,7 @@ def upgrade(migrate_engine): #========================================================================== # Upgrade of `repositories` table - #========================================================================== + #========================================================================== tblname = 'repositories' tbl = Table(tblname, MetaData(bind=migrate_engine), autoload=True, autoload_with=migrate_engine) @@ -69,8 +69,6 @@ def upgrade(migrate_engine): #========================================================================== # Add table `user_followings` #========================================================================== - tblname = 'user_followings' - class UserFollowing(Base, BaseModel): __tablename__ = 'user_followings' __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'), @@ -87,13 +85,11 @@ def upgrade(migrate_engine): follows_user = relation('User', primaryjoin='User.user_id==UserFollowing.follows_user_id') follows_repository = relation('Repository') - Base.metadata.tables[tblname].create(migrate_engine) + UserFollowing().__table__.create() #========================================================================== # Add table `cache_invalidation` #========================================================================== - tblname = 'cache_invalidation' - class CacheInvalidation(Base, BaseModel): __tablename__ = 'cache_invalidation' __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True}) @@ -110,18 +106,10 @@ def upgrade(migrate_engine): def __repr__(self): return "" % (self.cache_id, self.cache_key) - - Base.metadata.tables[tblname].create(migrate_engine) + CacheInvalidation().__table__.create() return - - - - - def downgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine - - diff --git a/rhodecode/lib/helpers.py b/rhodecode/lib/helpers.py --- a/rhodecode/lib/helpers.py +++ b/rhodecode/lib/helpers.py @@ -402,8 +402,6 @@ HasRepoPermissionAny, HasRepoPermissionA #============================================================================== # GRAVATAR URL #============================================================================== -import hashlib -import urllib from pylons import request def gravatar_url(email_address, size=30): diff --git a/rhodecode/lib/hooks.py b/rhodecode/lib/hooks.py --- a/rhodecode/lib/hooks.py +++ b/rhodecode/lib/hooks.py @@ -4,10 +4,10 @@ ~~~~~~~~~~~~~~~~~~~ Hooks runned by rhodecode - + :created_on: Aug 6, 2010 :author: marcink - :copyright: (C) 2009-2011 Marcin Kuzminski + :copyright: (C) 2009-2011 Marcin Kuzminski :license: GPLv3, see COPYING for more details. """ # This program is free software: you can redistribute it and/or modify @@ -34,7 +34,7 @@ from rhodecode.lib.utils import action_l def repo_size(ui, repo, hooktype=None, **kwargs): """Presents size of repository after push - + :param ui: :param repo: :param hooktype: @@ -65,7 +65,7 @@ def repo_size(ui, repo, hooktype=None, * def log_pull_action(ui, repo, **kwargs): """Logs user last pull action - + :param ui: :param repo: """ @@ -81,7 +81,7 @@ def log_pull_action(ui, repo, **kwargs): def log_push_action(ui, repo, **kwargs): """Maps user last push action to new changeset id, from mercurial - + :param ui: :param repo: """ @@ -111,4 +111,3 @@ def log_push_action(ui, repo, **kwargs): action_logger(username, action, repository, extra_params['ip']) return 0 - diff --git a/rhodecode/lib/indexers/__init__.py b/rhodecode/lib/indexers/__init__.py --- a/rhodecode/lib/indexers/__init__.py +++ b/rhodecode/lib/indexers/__init__.py @@ -1,3 +1,27 @@ +# -*- coding: utf-8 -*- +""" + rhodecode.lib.indexers.__init__ + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Whoosh indexing module for RhodeCode + + :created_on: Aug 17, 2010 + :author: marcink + :copyright: (C) 2009-2010 Marcin Kuzminski + :license: GPLv3, see COPYING for more details. +""" +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . import os import sys import traceback @@ -6,6 +30,8 @@ from os.path import dirname as dn, join #to get the rhodecode import sys.path.append(dn(dn(dn(os.path.realpath(__file__))))) +from string import strip + from rhodecode.model import init_model from rhodecode.model.scm import ScmModel from rhodecode.config.environment import load_environment @@ -135,10 +161,12 @@ class ResultWrapper(object): for docid in self.doc_ids: yield self.get_full_content(docid) - def __getslice__(self, i, j): + def __getitem__(self, key): """ Slicing of resultWrapper """ + i, j = key.start, key.stop + slice = [] for docid in self.doc_ids[i:j]: slice.append(self.get_full_content(docid)) diff --git a/rhodecode/lib/middleware/simplehg.py b/rhodecode/lib/middleware/simplehg.py --- a/rhodecode/lib/middleware/simplehg.py +++ b/rhodecode/lib/middleware/simplehg.py @@ -1,8 +1,16 @@ -#!/usr/bin/env python -# encoding: utf-8 -# middleware to handle mercurial api calls -# Copyright (C) 2009-2010 Marcin Kuzminski -# +# -*- coding: utf-8 -*- +""" + rhodecode.lib.middleware.simplehg + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + SimpleHG middleware for handling mercurial protocol request + (push/clone etc.). It's implemented with basic auth function + + :created_on: Apr 28, 2010 + :author: marcink + :copyright: (C) 2009-2010 Marcin Kuzminski + :license: GPLv3, see COPYING for more details. +""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -15,13 +23,11 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -""" -Created on 2010-04-28 -@author: marcink -SimpleHG middleware for handling mercurial protocol request (push/clone etc.) -It's implemented with basic auth function -""" +import os +import logging +import traceback + from mercurial.error import RepoError from mercurial.hgweb import hgweb from mercurial.hgweb.request import wsgiapplication diff --git a/rhodecode/lib/profiler.py b/rhodecode/lib/profiler.py --- a/rhodecode/lib/profiler.py +++ b/rhodecode/lib/profiler.py @@ -12,8 +12,8 @@ class ProfilingMiddleware(object): def __init__(self, app): self.lock = threading.Lock() self.app = app - - + + def __call__(self, environ, start_response): with self.lock: profiler = cProfile.Profile() @@ -41,13 +41,11 @@ class ProfilingMiddleware(object): ## Browsers don't mind this. resp += '
'
                 resp += cgi.escape(out.getvalue(), True)
-                
+
                 output = StringIO()
                 pprint.pprint(environ, output, depth=3)
-                
+
                 resp += cgi.escape(output.getvalue(), True)
                 resp += '
' - + return resp - - diff --git a/rhodecode/lib/smtp_mailer.py b/rhodecode/lib/smtp_mailer.py --- a/rhodecode/lib/smtp_mailer.py +++ b/rhodecode/lib/smtp_mailer.py @@ -2,9 +2,9 @@ """ rhodecode.lib.smtp_mailer ~~~~~~~~~~~~~~~~~~~~~~~~~ - + Simple smtp mailer used in RhodeCode - + :created_on: Sep 13, 2010 :copyright: (c) 2011 by marcink. :license: LICENSE_NAME, see LICENSE_FILE for more details. @@ -25,18 +25,18 @@ from email import encoders class SmtpMailer(object): """SMTP mailer class - + mailer = SmtpMailer(mail_from, user, passwd, mail_server, mail_port, ssl, tls) - mailer.send(recipients, subject, body, attachment_files) - + mailer.send(recipients, subject, body, attachment_files) + :param recipients might be a list of string or single string - :param attachment_files is a dict of {filename:location} - it tries to guess the mimetype and attach the file - + :param attachment_files is a dict of {filename:location} + it tries to guess the mimetype and attach the file + """ def __init__(self, mail_from, user, passwd, mail_server, - mail_port=None, ssl=False, tls=False): + mail_port=None, ssl=False, tls=False, debug=False): self.mail_from = mail_from self.mail_server = mail_server @@ -45,7 +45,7 @@ class SmtpMailer(object): self.passwd = passwd self.ssl = ssl self.tls = tls - self.debug = False + self.debug = debug def send(self, recipients=[], subject='', body='', attachment_files=None): @@ -132,7 +132,7 @@ class SmtpMailer(object): def get_content(self, msg_file): """Get content based on type, if content is a string do open first else just read because it's a probably open file object - + :param msg_file: """ if isinstance(msg_file, str): diff --git a/rhodecode/lib/utils.py b/rhodecode/lib/utils.py --- a/rhodecode/lib/utils.py +++ b/rhodecode/lib/utils.py @@ -50,6 +50,7 @@ from rhodecode.model.user import UserMod log = logging.getLogger(__name__) + def recursive_replace(str, replace=' '): """Recursive replace of given sign to just one instance @@ -67,6 +68,7 @@ def recursive_replace(str, replace=' '): str = str.replace(replace * 2, replace) return recursive_replace(str, replace) + def repo_name_slug(value): """Return slug of name of repository This function is called on each creation/modification @@ -86,10 +88,11 @@ def repo_name_slug(value): def get_repo_slug(request): return request.environ['pylons.routes_dict'].get('repo_name') + def action_logger(user, action, repo, ipaddr='', sa=None): """ Action logger for various actions made by users - + :param user: user that made this action, can be a unique username string or object containing user_id attribute :param action: action to log, should be on of predefined unique actions for @@ -98,7 +101,7 @@ def action_logger(user, action, repo, ip that action was made on :param ipaddr: optional ip address from what the action was made :param sa: optional sqlalchemy session - + """ if not sa: @@ -113,7 +116,6 @@ def action_logger(user, action, repo, ip else: raise Exception('You have to provide user object or username') - rm = RepoModel() if hasattr(repo, 'repo_id'): repo_obj = rm.get(repo.repo_id, cache=False) @@ -124,7 +126,6 @@ def action_logger(user, action, repo, ip else: raise Exception('You have to provide repository to action logger') - user_log = UserLog() user_log.user_id = user_obj.user_id user_log.action = action @@ -142,6 +143,7 @@ def action_logger(user, action, repo, ip log.error(traceback.format_exc()) sa.rollback() + def get_repos(path, recursive=False, initial=False): """ Scans given path for repos and return (name,(type,path)) tuple @@ -173,12 +175,14 @@ def check_repo_fast(repo_name, base_path Check given path for existence of directory :param repo_name: :param base_path: - + :return False: if this directory is present """ - if os.path.isdir(os.path.join(base_path, repo_name)):return False + if os.path.isdir(os.path.join(base_path, repo_name)): + return False return True + def check_repo(repo_name, base_path, verify=True): repo_path = os.path.join(base_path, repo_name) @@ -197,13 +201,17 @@ def check_repo(repo_name, base_path, ver log.info('%s repo is free for creation', repo_name) return True + def ask_ok(prompt, retries=4, complaint='Yes or no, please!'): while True: ok = raw_input(prompt) - if ok in ('y', 'ye', 'yes'): return True - if ok in ('n', 'no', 'nop', 'nope'): return False + if ok in ('y', 'ye', 'yes'): + return True + if ok in ('n', 'no', 'nop', 'nope'): + return False retries = retries - 1 - if retries < 0: raise IOError + if retries < 0: + raise IOError print complaint #propagated from mercurial documentation @@ -218,11 +226,11 @@ ui_sections = ['alias', 'auth', 'server', 'trusted', 'ui', 'web', ] + def make_ui(read_from='file', path=None, checkpaths=True): - """ - A function that will read python rc files or database + """A function that will read python rc files or database and make an mercurial ui object from read options - + :param path: path to mercurial config file :param checkpaths: check the path :param read_from: read from 'file' or 'db' @@ -247,7 +255,6 @@ def make_ui(read_from='file', path=None, log.debug('settings ui from file[%s]%s:%s', section, k, v) baseui.setconfig(section, k, v) - elif read_from == 'db': sa = meta.Session() ret = sa.query(RhodeCodeUi)\ @@ -276,6 +283,7 @@ def set_rhodecode_config(config): for k, v in hgsettings.items(): config[k] = v + def invalidate_cache(cache_key, *args): """Puts cache invalidation task into db for further global cache invalidation @@ -287,18 +295,20 @@ def invalidate_cache(cache_key, *args): name = cache_key.split('get_repo_cached_')[-1] ScmModel().mark_for_invalidation(name) + class EmptyChangeset(BaseChangeset): """ An dummy empty changeset. It's possible to pass hash when creating an EmptyChangeset """ - def __init__(self, cs='0' * 40): + def __init__(self, cs='0' * 40, repo=None): self._empty_cs = cs self.revision = -1 self.message = '' self.author = '' self.date = '' + self.repository = repo @LazyProperty def raw_id(self): @@ -350,6 +360,7 @@ def repo2db_mapper(initial_repo_list, re sa.delete(repo) sa.commit() + class OrderedDict(dict, DictMixin): def __init__(self, *args, **kwds): @@ -452,7 +463,7 @@ class OrderedDict(dict, DictMixin): #set cache regions for beaker so celery can utilise it def add_cache(settings): - cache_settings = {'regions':None} + cache_settings = {'regions': None} for key in settings.keys(): for prefix in ['beaker.cache.', 'cache.']: if key.startswith(prefix): @@ -477,6 +488,7 @@ def add_cache(settings): 'memory') beaker.cache.cache_regions[region] = region_settings + def get_current_revision(): """Returns tuple of (number, id) from repository containing this package or None if repository could not be found. @@ -496,9 +508,10 @@ def get_current_revision(): "was: %s" % err) return None -#=============================================================================== + +#============================================================================== # TEST FUNCTIONS AND CREATORS -#=============================================================================== +#============================================================================== def create_test_index(repo_location, full_index): """Makes default test index :param repo_location: @@ -521,6 +534,7 @@ def create_test_index(repo_location, ful except LockHeld: pass + def create_test_env(repos_test_path, config): """Makes a fresh database and install test repository into tmp dir @@ -541,7 +555,8 @@ def create_test_env(repos_test_path, con ch.setLevel(logging.DEBUG) # create formatter - formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") + formatter = logging.Formatter("%(asctime)s - %(name)s -" + " %(levelname)s - %(message)s") # add formatter to ch ch.setFormatter(formatter) @@ -582,7 +597,6 @@ def create_test_env(repos_test_path, con #============================================================================== # PASTER COMMANDS #============================================================================== - class BasePasterCommand(Command): """ Abstract Base Class for paster commands. @@ -609,7 +623,6 @@ class BasePasterCommand(Command): if log and isinstance(log, logging): log(msg) - def run(self, args): """ Overrides Command.run diff --git a/test.ini b/test.ini --- a/test.ini +++ b/test.ini @@ -1,6 +1,6 @@ ################################################################################ ################################################################################ -# rhodecode - Pylons environment configuration # +# RhodeCode - Pylons environment configuration # # # # The %(here)s variable will be replaced with the parent directory of this file# ################################################################################ @@ -10,7 +10,7 @@ debug = true ################################################################################ ## Uncomment and replace with the address which should receive ## ## any error reports after application crash ## -## Additionally those settings will be used by rhodecode mailing system ## +## Additionally those settings will be used by RhodeCode mailing system ## ################################################################################ #email_to = admin@localhost #error_email_from = paste_error@localhost @@ -42,7 +42,7 @@ use = egg:rhodecode full_stack = true static_files = true lang=en -cache_dir = %(here)s/data +cache_dir = /tmp/data index_dir = /tmp/index cut_off_limit = 256000 force_https = false @@ -69,7 +69,7 @@ celery.result.serialier = json celeryd.concurrency = 2 #celeryd.log.file = celeryd.log celeryd.log.level = debug -celeryd.max.tasks.per.child = 3 +celeryd.max.tasks.per.child = 1 #tasks will never be sent to the queue, but executed locally instead. celery.always.eager = false @@ -77,8 +77,8 @@ celery.always.eager = false #################################### ### BEAKER CACHE #### #################################### -beaker.cache.data_dir=/%(here)s/data/cache/data -beaker.cache.lock_dir=/%(here)s/data/cache/lock +beaker.cache.data_dir=/tmp/data/cache/data +beaker.cache.lock_dir=/tmp/data/cache/lock beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long beaker.cache.super_short_term.type=memory @@ -147,7 +147,7 @@ sqlalchemy.convert_unicode = true ### LOGGING CONFIGURATION #### ################################ [loggers] -keys = root, routes, rhodecode, sqlalchemy +keys = root, routes, rhodecode, sqlalchemy,beaker,templates [handlers] keys = console