# HG changeset patch # User Marcin Kuzminski # Date 2010-10-18 01:04:58 # Node ID 5cc96df705b9fef9832b01af56c2f37a5ef0e856 # Parent 95a502d9486073a559ee23825f0b234bb185140c fixed @repo into :repo for docs fixed routes descriptions diff --git a/rhodecode/config/routing.py b/rhodecode/config/routing.py --- a/rhodecode/config/routing.py +++ b/rhodecode/config/routing.py @@ -1,4 +1,5 @@ -"""Routes configuration +""" +Routes configuration The more specific and detailed routes should be defined first so they may take precedent over the more generic routes. For more information @@ -15,24 +16,28 @@ def make_map(config): map.minimization = False map.explicit = False + def check_repo(environ, match_dict): + """ + check for valid repository for proper 404 handling + :param environ: + :param match_dict: + """ + repo_name = match_dict.get('repo_name') + return not cr(repo_name, config['base_path']) + # The ErrorController route (handles 404/500 error pages); it should # likely stay at the top, ensuring it can always be resolved map.connect('/error/{action}', controller='error') map.connect('/error/{action}/{id}', controller='error') + #========================================================================== # CUSTOM ROUTES HERE + #========================================================================== + + #MAIN PAGE map.connect('hg_home', '/', controller='hg', action='index') - - def check_repo(environ, match_dict): - """ - check for valid repository for proper 404 handling - @param environ: - @param match_dict: - """ - repo_name = match_dict.get('repo_name') - return not cr(repo_name, config['base_path']) - - #REST REPO MAP + + #ADMIN REPOSITORY REST ROUTES with map.submapper(path_prefix='/_admin', controller='admin/repos') as m: m.connect("repos", "/repos", action="create", conditions=dict(method=["POST"])) @@ -67,11 +72,14 @@ def make_map(config): m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}", action="delete_perm_user", conditions=dict(method=["DELETE"], function=check_repo)) - + + #ADMIN USER REST ROUTES map.resource('user', 'users', controller='admin/users', path_prefix='/_admin') + + #ADMIN PERMISSIONS REST ROUTES map.resource('permission', 'permissions', controller='admin/permissions', path_prefix='/_admin') - - #REST SETTINGS MAP + + #ADMIN SETTINGS REST ROUTES with map.submapper(path_prefix='/_admin', controller='admin/settings') as m: m.connect("admin_settings", "/settings", action="create", conditions=dict(method=["POST"])) @@ -101,8 +109,8 @@ def make_map(config): action="my_account_update", conditions=dict(method=["PUT"])) m.connect("admin_settings_create_repository", "/create_repository", action="create_repository", conditions=dict(method=["GET"])) - - #ADMIN + + #ADMIN MAIN PAGES with map.submapper(path_prefix='/_admin', controller='admin/admin') as m: m.connect('admin_home', '', action='index')#main page m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}', @@ -110,13 +118,13 @@ def make_map(config): #SEARCH map.connect('search', '/_admin/search', controller='search',) map.connect('search_repo', '/_admin/search/{search_repo:.*}', controller='search') - + #LOGIN/LOGOUT/REGISTER/SIGN IN map.connect('login_home', '/_admin/login', controller='login') map.connect('logout_home', '/_admin/logout', controller='login', action='logout') map.connect('register', '/_admin/register', controller='login', action='register') map.connect('reset_password', '/_admin/password_reset', controller='login', action='password_reset') - + #FEEDS map.connect('rss_feed_home', '/{repo_name:.*}/feed/rss', controller='feed', action='rss', @@ -124,9 +132,9 @@ def make_map(config): map.connect('atom_feed_home', '/{repo_name:.*}/feed/atom', controller='feed', action='atom', conditions=dict(function=check_repo)) - - - #OTHERS + + + #REPOSITORY ROUTES map.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}', controller='changeset', revision='tip', conditions=dict(function=check_repo)) @@ -142,7 +150,7 @@ def make_map(config): map.connect('tags_home', '/{repo_name:.*}/tags', controller='tags', conditions=dict(function=check_repo)) map.connect('changelog_home', '/{repo_name:.*}/changelog', - controller='changelog', conditions=dict(function=check_repo)) + controller='changelog', conditions=dict(function=check_repo)) map.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}', controller='files', revision='tip', f_path='', conditions=dict(function=check_repo)) @@ -157,10 +165,10 @@ def make_map(config): conditions=dict(function=check_repo)) map.connect('files_annotate_home', '/{repo_name:.*}/annotate/{revision}/{f_path:.*}', controller='files', action='annotate', revision='tip', f_path='', - conditions=dict(function=check_repo)) + conditions=dict(function=check_repo)) map.connect('files_archive_home', '/{repo_name:.*}/archive/{revision}/{fileformat}', controller='files', action='archivefile', revision='tip', - conditions=dict(function=check_repo)) + conditions=dict(function=check_repo)) map.connect('repo_settings_delete', '/{repo_name:.*}/settings', controller='settings', action="delete", conditions=dict(method=["DELETE"], function=check_repo)) @@ -177,5 +185,5 @@ def make_map(config): map.connect('repo_fork_home', '/{repo_name:.*}/fork', controller='settings', action='fork', conditions=dict(function=check_repo)) - + return map diff --git a/rhodecode/controllers/admin/repos.py b/rhodecode/controllers/admin/repos.py --- a/rhodecode/controllers/admin/repos.py +++ b/rhodecode/controllers/admin/repos.py @@ -193,7 +193,7 @@ class ReposController(BaseController): def delete_perm_user(self, repo_name): """ DELETE an existing repository permission user - @param repo_name: + :param repo_name: """ try: diff --git a/rhodecode/lib/auth.py b/rhodecode/lib/auth.py --- a/rhodecode/lib/auth.py +++ b/rhodecode/lib/auth.py @@ -66,7 +66,7 @@ class PasswordGenerator(object): def get_crypt_password(password): """Cryptographic function used for password hashing based on sha1 - @param password: password to hash + :param password: password to hash """ return bcrypt.hashpw(password, bcrypt.gensalt(10)) @@ -120,7 +120,7 @@ def set_available_permissions(config): permission given in db. We don't wannt to check each time from db for new permissions since adding a new permission also requires application restart ie. to decorate new views with the newly created permission - @param config: + :param config: """ log.info('getting information about all available permissions') try: @@ -138,7 +138,7 @@ def fill_data(user): """ Fills user data with those from database and log out user if not present in database - @param user: + :param user: """ sa = meta.Session dbuser = sa.query(User).get(user.user_id) @@ -156,7 +156,7 @@ def fill_data(user): def fill_perms(user): """ Fills user permission attribute with permissions taken from database - @param user: + :param user: """ sa = meta.Session @@ -228,7 +228,7 @@ def fill_perms(user): def get_user(session): """ Gets user from session, and wraps permissions into user - @param session: + :param session: """ user = session.get('rhodecode_user', AuthUser()) if user.is_authenticated: diff --git a/rhodecode/lib/helpers.py b/rhodecode/lib/helpers.py --- a/rhodecode/lib/helpers.py +++ b/rhodecode/lib/helpers.py @@ -28,8 +28,8 @@ from webhelpers.text import chop_at, col class _Link(object): ''' Make a url based on label and url with help of url_for - @param label:name of link if not defined url is used - @param url: the url for link + :param label:name of link if not defined url is used + :param url: the url for link ''' def __call__(self, label='', *url_, **urlargs): @@ -52,8 +52,8 @@ get_error = _GetError() def recursive_replace(str, replace=' '): """ Recursive replace of given sign to just one instance - @param str: given string - @param replace:char to find and replace multiple instances + :param str: given string + :param replace:char to find and replace multiple instances Examples:: >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-') @@ -72,7 +72,7 @@ class _ToolTip(object): """ Special function just to wrap our text into nice formatted autowrapped text - @param tooltip_title: + :param tooltip_title: """ return wrap_paragraphs(escape(tooltip_title), trim_at)\ @@ -226,7 +226,7 @@ class CodeHtmlFormatter(HtmlFormatter): def pygmentize(filenode, **kwargs): """ pygmentize function using pygments - @param filenode: + :param filenode: """ return literal(code_highlight(filenode.content, filenode.lexer, CodeHtmlFormatter(**kwargs))) @@ -234,7 +234,7 @@ def pygmentize(filenode, **kwargs): def pygmentize_annotation(filenode, **kwargs): """ pygmentize function for annotation - @param filenode: + :param filenode: """ color_dict = {} diff --git a/rhodecode/lib/hooks.py b/rhodecode/lib/hooks.py --- a/rhodecode/lib/hooks.py +++ b/rhodecode/lib/hooks.py @@ -53,9 +53,9 @@ def repo_size(ui, repo, hooktype=None, * def user_action_mapper(ui, repo, hooktype=None, **kwargs): """ Maps user last push action to new changeset id, from mercurial - @param ui: - @param repo: - @param hooktype: + :param ui: + :param repo: + :param hooktype: """ try: 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 @@ -115,8 +115,8 @@ class ResultWrapper(object): Smart function that implements chunking the content but not overlap chunks so it doesn't highlight the same close occurrences twice. - @param matcher: - @param size: + :param matcher: + :param size: """ memory = [(0, 0)] for span in self.matcher.spans(): diff --git a/rhodecode/lib/pidlock.py b/rhodecode/lib/pidlock.py --- a/rhodecode/lib/pidlock.py +++ b/rhodecode/lib/pidlock.py @@ -109,8 +109,8 @@ class DaemonLock(object): def makelock(self, lockname, pidfile): """ this function will make an actual lock - @param lockname: acctual pid of file - @param pidfile: the file to write the pid in + :param lockname: acctual pid of file + :param pidfile: the file to write the pid in """ if self.debug: print 'creating a file %s and pid: %s' % (pidfile, lockname) 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 @@ -108,7 +108,7 @@ class SmtpMailer(object): ''' 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: + :param msg_file: ''' if isinstance(msg_file, str): return open(msg_file, "rb").read() diff --git a/rhodecode/lib/utils.py b/rhodecode/lib/utils.py --- a/rhodecode/lib/utils.py +++ b/rhodecode/lib/utils.py @@ -36,7 +36,7 @@ import os log = logging.getLogger(__name__) -def get_repo_slug(request): +def get_repo_slug(request): return request.environ['pylons.routes_dict'].get('repo_name') def is_mercurial(environ): @@ -49,14 +49,26 @@ def is_mercurial(environ): return True return False +def is_git(environ): + """ + Returns True if request's target is git server. ``HTTP_USER_AGENT`` would + then have git client version given. + + :param environ: + """ + http_user_agent = environ.get('HTTP_USER_AGENT') + if http_user_agent.startswith('git'): + return True + return False + def action_logger(user, action, repo, ipaddr, sa=None): """ Action logger for various action made by users """ - + if not sa: - sa = meta.Session - + sa = meta.Session + try: if hasattr(user, 'user_id'): user_id = user.user_id @@ -64,7 +76,7 @@ def action_logger(user, action, repo, ip user_id = sa.query(User).filter(User.username == user).one() else: raise Exception('You have to provide user object or username') - + repo_name = repo.lstrip('/') user_log = UserLog() user_log.user_id = user_id @@ -82,7 +94,7 @@ def action_logger(user, action, repo, ip raise sa.rollback() log.error('could not log user action:%s', str(e)) - + def check_repo_dir(paths): repos_path = paths[0][1].split('/') if repos_path[-1] in ['*', '**']: @@ -122,7 +134,7 @@ def ask_ok(prompt, retries=4, complaint= retries = retries - 1 if retries < 0: raise IOError print complaint - + @cache_region('super_short_term', 'cached_hg_ui') def get_hg_ui_cached(): try: @@ -139,13 +151,13 @@ def get_hg_settings(): ret = sa.query(RhodeCodeSettings).all() finally: meta.Session.remove() - + if not ret: raise Exception('Could not get application settings !') settings = {} for each in ret: - settings['rhodecode_' + each.app_settings_name] = each.app_settings_value - + settings['rhodecode_' + each.app_settings_name] = each.app_settings_value + return settings def get_hg_ui_settings(): @@ -154,7 +166,7 @@ def get_hg_ui_settings(): ret = sa.query(RhodeCodeUi).all() finally: meta.Session.remove() - + if not ret: raise Exception('Could not get application ui settings !') settings = {} @@ -163,15 +175,15 @@ def get_hg_ui_settings(): v = each.ui_value if k == '/': k = 'root_path' - + if k.find('.') != -1: k = k.replace('.', '_') - + if each.ui_section == 'hooks': v = each.ui_active - - settings[each.ui_section + '_' + k] = v - + + settings[each.ui_section + '_' + k] = v + return settings #propagated from mercurial documentation @@ -185,15 +197,15 @@ ui_sections = ['alias', 'auth', 'paths', 'profiling', 'server', 'trusted', 'ui', 'web', ] - -def make_ui(read_from='file', path=None, checkpaths=True): + +def make_ui(read_from='file', path=None, checkpaths=True): """ 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' + :param path: path to mercurial config file + :param checkpaths: check the path + :param read_from: read from 'file' or 'db' """ baseui = ui.ui() @@ -209,52 +221,52 @@ def make_ui(read_from='file', path=None, for k, v in cfg.items(section): baseui.setconfig(section, k, v) log.debug('settings ui from file[%s]%s:%s', section, k, v) - if checkpaths:check_repo_dir(cfg.items('paths')) - - + if checkpaths:check_repo_dir(cfg.items('paths')) + + elif read_from == 'db': hg_ui = get_hg_ui_cached() for ui_ in hg_ui: if ui_.ui_active: log.debug('settings ui from db[%s]%s:%s', ui_.ui_section, ui_.ui_key, ui_.ui_value) baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value) - - + + return baseui def set_rhodecode_config(config): hgsettings = get_hg_settings() - + for k, v in hgsettings.items(): config[k] = v def invalidate_cache(name, *args): """Invalidates given name cache""" - + from beaker.cache import region_invalidate log.info('INVALIDATING CACHE FOR %s', name) - + """propagate our arguments to make sure invalidation works. First argument has to be the name of cached func name give to cache decorator without that the invalidation would not work""" tmp = [name] tmp.extend(args) args = tuple(tmp) - + if name == 'cached_repo_list': from rhodecode.model.hg_model import _get_repos_cached region_invalidate(_get_repos_cached, None, *args) - + if name == 'full_changelog': from rhodecode.model.hg_model import _full_changelog_cached region_invalidate(_full_changelog_cached, None, *args) - + class EmptyChangeset(BaseChangeset): """ An dummy empty changeset. """ - + revision = -1 message = '' author = '' @@ -266,35 +278,35 @@ class EmptyChangeset(BaseChangeset): representation. """ return '0' * 40 - + @LazyProperty def short_id(self): return self.raw_id[:12] def get_file_changeset(self, path): return self - + def get_file_content(self, path): return u'' - + def get_file_size(self, path): return 0 - + def repo2db_mapper(initial_repo_list, remove_obsolete=False): """ maps all found repositories into db """ from rhodecode.model.repo_model import RepoModel - + sa = meta.Session user = sa.query(User).filter(User.admin == True).first() - + rm = RepoModel() - + for name, repo in initial_repo_list.items(): if not sa.query(Repository).filter(Repository.repo_name == name).scalar(): log.info('repository %s not found creating default', name) - + form_data = { 'repo_name':name, 'description':repo.description if repo.description != 'unknown' else \ @@ -311,7 +323,7 @@ def repo2db_mapper(initial_repo_list, re sa.delete(repo) sa.commit() - + meta.Session.remove() from UserDict import DictMixin @@ -421,25 +433,25 @@ class OrderedDict(dict, DictMixin): #=============================================================================== def create_test_index(repo_location, full_index): """Makes default test index - @param repo_location: - @param full_index: + :param repo_location: + :param full_index: """ from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon from rhodecode.lib.pidlock import DaemonLock, LockHeld from rhodecode.lib.indexers import IDX_LOCATION import shutil - + if os.path.exists(IDX_LOCATION): shutil.rmtree(IDX_LOCATION) - + try: l = DaemonLock() WhooshIndexingDaemon(repo_location=repo_location)\ .run(full_index=full_index) l.release() except LockHeld: - pass - + pass + def create_test_env(repos_test_path, config): """Makes a fresh database and install test repository into tmp dir @@ -448,7 +460,7 @@ def create_test_env(repos_test_path, con import tarfile import shutil from os.path import dirname as dn, join as jn, abspath - + log = logging.getLogger('TestEnvCreator') # create logger log.setLevel(logging.DEBUG) @@ -456,20 +468,20 @@ def create_test_env(repos_test_path, con # create console handler and set level to debug ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) - + # create formatter formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") - + # add formatter to ch ch.setFormatter(formatter) - + # add ch to logger log.addHandler(ch) - + #PART ONE create db dbname = config['sqlalchemy.db1.url'].split('/')[-1] log.debug('making test db %s', dbname) - + dbmanage = DbManage(log_sql=True, dbname=dbname, root=config['here'], tests=True) dbmanage.create_tables(override=True) @@ -478,12 +490,12 @@ def create_test_env(repos_test_path, con dbmanage.admin_prompt() dbmanage.create_permissions() dbmanage.populate_default_permissions() - + #PART TWO make test repo log.debug('making test vcs repo') if os.path.isdir('/tmp/vcs_test'): shutil.rmtree('/tmp/vcs_test') - + cur_dir = dn(dn(abspath(__file__))) tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test.tar.gz")) tar.extractall('/tmp')