Changeset - d2319cb2ba9b
[Not reviewed]
Merge default
0 5 0
Mads Kiilerich (mads) - 6 years ago 2019-12-19 20:50:33
mads@kiilerich.com
Merge stable
5 files changed with 12 insertions and 7 deletions:
0 comments (0 inline, 0 general)
kallithea/bin/ldap_sync.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
# 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 <http://www.gnu.org/licenses/>.
 
"""
 
kallithea.bin.ldap_sync
 
~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
LDAP sync script
 

	
 
This file was forked by the Kallithea project in July 2014.
 
Original author and date, and relevant copyright and licensing information is below:
 
:created_on: Mar 06, 2013
 
:author: marcink
 
:copyright: (c) 2013 RhodeCode GmbH, and others.
 
:license: GPLv3, see LICENSE.md for more details.
 
"""
 

	
 
from __future__ import print_function
 

	
 
import urllib2
 
import uuid
 
from ConfigParser import ConfigParser
 

	
 
import ldap
 

	
 
from kallithea.lib.compat import json
 

	
 

	
 
config = ConfigParser()
 
config.read('ldap_sync.conf')
 

	
 

	
 
class InvalidResponseIDError(Exception):
 
    """ Request and response don't have the same UUID. """
 

	
 

	
 
class ResponseError(Exception):
 
    """ Response has an error, something went wrong with request execution. """
 

	
 

	
 
class UserAlreadyInGroupError(Exception):
 
    """ User is already a member of the target group. """
 

	
 

	
 
class UserNotInGroupError(Exception):
 
    """ User is not a member of the target group. """
 

	
 

	
 
class API(object):
 

	
 
    def __init__(self, url, key):
 
        self.url = url
 
        self.key = key
 

	
 
    def get_api_data(self, uid, method, args):
 
        """Prepare dict for API post."""
 
        return {
 
            "id": uid,
 
            "api_key": self.key,
 
            "method": method,
 
            "args": args
 
        }
 

	
 
    def post(self, method, args):
 
        """Send a generic API post to Kallithea.
 

	
 
        This will generate the UUID for validation check after the
 
        response is returned. Handle errors and get the result back.
 
        """
 
        uid = str(uuid.uuid1())
 
        data = self.get_api_data(uid, method, args)
 

	
 
        data = json.dumps(data)
kallithea/i18n/ru/LC_MESSAGES/kallithea.po
Show inline comments
 
@@ -35,111 +35,111 @@ msgstr "Нет такой ревизии в этом репозитории"
 
msgid "Cannot compare repositories without using common ancestor"
 
msgstr "Невозможно сравнивать репозитории без общего предка"
 

	
 
msgid "No response"
 
msgstr "Нет ответа"
 

	
 
msgid "Unknown error"
 
msgstr "Неизвестная ошибка"
 

	
 
msgid ""
 
"The request could not be understood by the server due to malformed syntax."
 
msgstr "Запрос не распознан сервером из-за неправильного синтаксиса."
 

	
 
msgid "Unauthorized access to resource"
 
msgstr "Несанкционированный доступ к ресурсу"
 

	
 
msgid "You don't have permission to view this page"
 
msgstr "У вас нет прав для просмотра этой страницы"
 

	
 
msgid "The resource could not be found"
 
msgstr "Ресурс не найден"
 

	
 
msgid ""
 
"The server encountered an unexpected condition which prevented it from "
 
"fulfilling the request."
 
msgstr ""
 
"Сервер не может выполнить запрос из-за неправильного условия в запросе."
 

	
 
msgid "%s committed on %s"
 
msgstr "%s выполнил коммит в %s"
 

	
 
msgid "Changeset was too big and was cut off..."
 
msgstr "Изменения оказались слишком большими и были вырезаны..."
 

	
 
msgid "%s %s feed"
 
msgstr "Лента новостей %s %s"
 

	
 
msgid "Changes on %s repository"
 
msgstr "Изменения в репозитории %s"
 

	
 
msgid "Click here to add new file"
 
msgstr "Нажмите чтобы добавить новый файл"
 

	
 
msgid "%s at %s"
 
msgstr "%s (%s)"
 

	
 
msgid "You can only delete files with revision being a valid branch"
 
msgstr ""
 
"Вы можете удалять файлы только в ревизии, связанной с существующей веткой "
 
"Вы можете удалять файлы только в ревизии, являющейся корректной веткой"
 

	
 
msgid "Deleted file %s via Kallithea"
 
msgstr "Файл %s удалён с помощью Kallithea"
 

	
 
msgid "Successfully deleted file %s"
 
msgstr "Файл %s удалён"
 

	
 
msgid "Error occurred during commit"
 
msgstr "Во время коммита произошла ошибка"
 

	
 
msgid "You can only edit files with revision being a valid branch"
 
msgstr ""
 
"Вы можете редактировать файлы только в ревизии, связанной с существующей "
 
"веткой "
 
"веткой"
 

	
 
msgid "Edited file %s via Kallithea"
 
msgstr "Файл %s отредактирован с помощью Kallithea"
 

	
 
msgid "No changes"
 
msgstr "Без изменений"
 

	
 
msgid "Successfully committed to %s"
 
msgstr "Изменения применены в %s"
 

	
 
msgid "Added file via Kallithea"
 
msgstr "Файл добавлен с помощью Kallithea"
 

	
 
msgid "No content"
 
msgstr "Пусто"
 

	
 
msgid "No filename"
 
msgstr "Безымянный"
 

	
 
msgid "Location must be relative path and must not contain .. in path"
 
msgstr ""
 
"Расположение должно быть относительным путем, и не должно содержать \".."
 
"\" в пути"
 

	
 
msgid "Downloads disabled"
 
msgstr "Возможность скачивать отключена"
 

	
 
msgid "Unknown revision %s"
 
msgstr "Неизвестная ревизия %s"
 

	
 
msgid "Empty repository"
 
msgstr "Пустой репозиторий"
 

	
 
msgid "Unknown archive type"
 
msgstr "Неизвестный тип архива"
 

	
 
msgid "Changesets"
 
msgstr "Набор изменений"
 

	
 
msgid "Branches"
 
msgstr "Ветки"
 

	
 
msgid "Tags"
 
msgstr "Метки"
 

	
 
msgid "An error occurred during repository forking %s"
 
msgstr "Произошла ошибка во время создания форка репозитория %s"
 

	
 
@@ -666,99 +666,99 @@ msgstr "удалён"
 

	
 
msgid "rename"
 
msgstr "переименован"
 

	
 
msgid "chmod"
 
msgstr "chmod"
 

	
 
msgid ""
 
"%s repository is not mapped to db perhaps it was created or renamed from "
 
"the filesystem please run the application again in order to rescan "
 
"repositories"
 
msgstr ""
 
"Репозиторий %s отсутствует в базе данных; возможно, он был создан или "
 
"переименован из файловой системы. Пожалуйста, перезапустите приложение "
 
"для сканирования репозиториев"
 

	
 
msgid "%d year"
 
msgid_plural "%d years"
 
msgstr[0] "%d год"
 
msgstr[1] "%d лет"
 
msgstr[2] "%d года"
 

	
 
msgid "%d month"
 
msgid_plural "%d months"
 
msgstr[0] "%d месяц"
 
msgstr[1] "%d месяца"
 
msgstr[2] "%d месяцев"
 

	
 
msgid "%d day"
 
msgid_plural "%d days"
 
msgstr[0] "%d день"
 
msgstr[1] "%d дня"
 
msgstr[2] "%d дней"
 

	
 
msgid "%d hour"
 
msgid_plural "%d hours"
 
msgstr[0] "%d час"
 
msgstr[1] "%d часов"
 
msgstr[2] "%d часа"
 

	
 
msgid "%d minute"
 
msgid_plural "%d minutes"
 
msgstr[0] "%d минута"
 
msgstr[1] "%d минут"
 
msgstr[2] "%d минуты"
 

	
 
msgid "%d second"
 
msgid_plural "%d seconds"
 
msgstr[0] "%d секунды"
 
msgstr[0] "%d секунда"
 
msgstr[1] "%d секунды"
 
msgstr[2] "%d секунды"
 
msgstr[2] "%d секунд"
 

	
 
msgid "in %s"
 
msgstr "в %s"
 

	
 
msgid "%s ago"
 
msgstr "%s назад"
 

	
 
msgid "in %s and %s"
 
msgstr "в %s и %s"
 

	
 
msgid "%s and %s ago"
 
msgstr "%s и %s назад"
 

	
 
msgid "just now"
 
msgstr "прямо сейчас"
 

	
 
msgid "on line %s"
 
msgstr "на строке %s"
 

	
 
msgid "[Mention]"
 
msgstr "[Упоминание]"
 

	
 
msgid "top level"
 
msgstr "верхний уровень"
 

	
 
msgid "Kallithea Administrator"
 
msgstr "Администратор Kallithea"
 

	
 
msgid "Default user has read access to new repositories"
 
msgstr "Неавторизованные пользователи имеют право чтения новых репозиториев"
 

	
 
msgid "Default user has write access to new repositories"
 
msgstr ""
 
"Неавторизованные пользователи имеют право записи в новые репозитории"
 

	
 
msgid "Only admins can create repository groups"
 
msgstr "Только администраторы могут создавать группы"
 

	
 
msgid "Registration disabled"
 
msgstr "Регистрация отключена"
 

	
 
msgid "Approved"
 
msgstr "Одобрено"
 

	
 
msgid "Please enter a login"
 
msgstr "Пожалуйста, введите логин"
 

	
 
msgid "Enter a value %(min)i characters long or more"
 
@@ -792,97 +792,97 @@ msgstr ""
 
msgid ""
 
"User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 
"owners or remove those repository groups: %s"
 
msgstr ""
 
"Пользователь \"%s\" всё ещё является владельцем %s групп репозиториев и "
 
"поэтому не может быть удалён. Смените владельца или удалите данные "
 
"группы: %s"
 

	
 
msgid ""
 
"User \"%s\" still owns %s user groups and cannot be removed. Switch "
 
"owners or remove those user groups: %s"
 
msgstr ""
 
"Пользователь \"%s\" всё ещё является владельцем %s групп пользователей и "
 
"поэтому не может быть удалён. Смените владельца или удалите данные "
 
"группы: %s"
 

	
 
msgid "Password reset link"
 
msgstr "Ссылка сброса пароля"
 

	
 
msgid "Value cannot be an empty list"
 
msgstr "Значение не может быть пустым списком"
 

	
 
msgid "Username \"%(username)s\" already exists"
 
msgstr "Пользователь с именем \"%(username)s\" уже существует"
 

	
 
msgid "Username %(username)s is not valid"
 
msgstr "Имя \"%(username)s\" недопустимо"
 

	
 
msgid "Invalid user group name"
 
msgstr "Неверное имя группы пользователей"
 

	
 
msgid "User group \"%(usergroup)s\" already exists"
 
msgstr "Группа пользователей \"%(usergroup)s\" уже существует"
 

	
 
msgid ""
 
"user group name may only contain alphanumeric characters underscores, "
 
"periods or dashes and must begin with alphanumeric character"
 
msgstr ""
 
"имя группы пользователей может содержать только буквы, цифры, символы "
 
"подчеркивания, точки и тире; а так же должно начинаться с буквы или цифры"
 

	
 
msgid "Cannot assign this group as parent"
 
msgstr "Невозможно использовать эту группу как родителя"
 

	
 
msgid "Group \"%(group_name)s\" already exists"
 
msgstr "Группа \"%(group_name)s\" уже существует"
 

	
 
msgid "Repository with name \"%(group_name)s\" already exists"
 
msgstr "Репозитарий с  именем \"%(group_name)s\" уже существует"
 
msgstr "Репозиторий с именем «%(group_name)s» уже существует"
 

	
 
msgid "Invalid characters (non-ascii) in password"
 
msgstr "Недопустимые символы (не ascii) в пароле"
 

	
 
msgid "Invalid old password"
 
msgstr "Неверно задан старый пароль"
 

	
 
msgid "Passwords do not match"
 
msgstr "Пароли не совпадают"
 

	
 
msgid "Repository named %(repo)s already exists"
 
msgstr "Репозитарий %(repo)s уже существует"
 

	
 
msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 
msgstr "Репозитарий \"%(repo)s\" уже существует в группе \"%(group)s\""
 

	
 
msgid "Repository group with name \"%(repo)s\" already exists"
 
msgstr "Группа репозиториев \"%(repo)s\" уже существует"
 

	
 
msgid "Fork has to be the same type as parent"
 
msgstr "Тип форка будет совпадать с родительским"
 

	
 
msgid "You don't have permissions to create repository in this group"
 
msgstr "У вас недостаточно прав для создания репозиториев в этой группе"
 

	
 
msgid "no permission to create repository in root location"
 
msgstr "недостаточно прав для создания репозитория в корневом каталоге"
 

	
 
msgid "You don't have permissions to create a group in this location"
 
msgstr "У Вас недостаточно привилегий для создания группы в этом месте"
 

	
 
msgid "This username or user group name is not valid"
 
msgstr "Данное имя пользователя или группы пользователей недопустимо"
 

	
 
msgid "This is not a valid path"
 
msgstr "Этот путь ошибочен"
 

	
 
msgid ""
 
"The LDAP Login attribute of the CN must be specified - this is the name "
 
"of the attribute that is equivalent to \"username\""
 
msgstr ""
 
"Для входа по LDAP должно быть указано значение аттрибута CN - это "
 
"эквивалент имени пользователя"
 

	
 
msgid "Please enter a valid IPv4 or IPv6 address"
 
msgstr "Пожалуйста, введите существующий IPv4 или IPv6 адре"
 

	
 
msgid ""
kallithea/lib/ssh.py
Show inline comments
 
@@ -21,97 +21,99 @@
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 

	
 
import binascii
 
import logging
 
import re
 

	
 
from tg.i18n import ugettext as _
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class SshKeyParseError(Exception):
 
    """Exception raised by parse_pub_key"""
 

	
 

	
 
def parse_pub_key(ssh_key):
 
    r"""Parse SSH public key string, raise SshKeyParseError or return decoded keytype, data and comment
 

	
 
    >>> getfixture('doctest_mock_ugettext')
 
    >>> parse_pub_key('')
 
    Traceback (most recent call last):
 
    ...
 
    SshKeyParseError: SSH key is missing
 
    >>> parse_pub_key('''AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ''')
 
    Traceback (most recent call last):
 
    ...
 
    SshKeyParseError: Incorrect SSH key - it must have both a key type and a base64 part
 
    >>> parse_pub_key('''abc AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ''')
 
    Traceback (most recent call last):
 
    ...
 
    SshKeyParseError: Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'
 
    >>> parse_pub_key('''ssh-rsa  AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ''')
 
    Traceback (most recent call last):
 
    ...
 
    SshKeyParseError: Incorrect SSH key - failed to decode base64 part 'AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ'
 
    >>> parse_pub_key('''ssh-rsa  AAAAB2NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ==''')
 
    Traceback (most recent call last):
 
    ...
 
    SshKeyParseError: Incorrect SSH key - base64 part is not 'ssh-rsa' as claimed but 'csh-rsa'
 
    >>> parse_pub_key('''ssh-rsa  AAAAB3NzaC1yc2EAAAA'LVGhpcyBpcyBmYWtlIQ''')
 
    Traceback (most recent call last):
 
    ...
 
    SshKeyParseError: Incorrect SSH key - unexpected characters in base64 part "AAAAB3NzaC1yc2EAAAA'LVGhpcyBpcyBmYWtlIQ"
 
    >>> parse_pub_key(''' ssh-rsa  AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ== and a comment
 
    ... ''')
 
    ('ssh-rsa', '\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x0bThis is fake!', 'and a comment\n')
 
    >>> parse_pub_key('''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP1NA2kBQIKe74afUXmIWD9ByDYQJqUwW44Y4gJOBRuo''')
 
    ('ssh-ed25519', '\x00\x00\x00\x0bssh-ed25519\x00\x00\x00 \xfdM\x03i\x01@\x82\x9e\xef\x86\x9fQy\x88X?A\xc86\x10&\xa50[\x8e\x18\xe2\x02N\x05\x1b\xa8', '')
 
    """
 
    if not ssh_key:
 
        raise SshKeyParseError(_("SSH key is missing"))
 

	
 
    parts = ssh_key.split(None, 2)
 
    if len(parts) < 2:
 
        raise SshKeyParseError(_("Incorrect SSH key - it must have both a key type and a base64 part"))
 

	
 
    keytype, keyvalue, comment = (parts + [''])[:3]
 
    if keytype not in ('ssh-rsa', 'ssh-dss', 'ssh-ed25519'):
 
        raise SshKeyParseError(_("Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"))
 

	
 
    if re.search(r'[^a-zA-Z0-9+/=]', keyvalue):
 
        raise SshKeyParseError(_("Incorrect SSH key - unexpected characters in base64 part %r") % keyvalue)
 

	
 
    try:
 
        decoded = keyvalue.decode('base64')
 
    except binascii.Error:
 
        raise SshKeyParseError(_("Incorrect SSH key - failed to decode base64 part %r") % keyvalue)
 

	
 
    if not decoded.startswith('\x00\x00\x00\x07' + str(keytype) + '\x00'):
 
    if not decoded.startswith('\x00\x00\x00' + chr(len(keytype)) + str(keytype) + '\x00'):
 
        raise SshKeyParseError(_("Incorrect SSH key - base64 part is not %r as claimed but %r") % (str(keytype), str(decoded[4:].split('\0', 1)[0])))
 

	
 
    return keytype, decoded, comment
 

	
 

	
 
SSH_OPTIONS = 'no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding'
 

	
 

	
 
def authorized_keys_line(kallithea_cli_path, config_file, key):
 
    """
 
    Return a line as it would appear in .authorized_keys
 

	
 
    >>> from kallithea.model.db import UserSshKeys, User
 
    >>> user = User(user_id=7, username='uu')
 
    >>> key = UserSshKeys(user_ssh_key_id=17, user=user, description='test key')
 
    >>> key.public_key='''ssh-rsa  AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ== and a comment'''
 
    >>> authorized_keys_line('/srv/kallithea/venv/bin/kallithea-cli', '/srv/kallithea/my.ini', key)
 
    'no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command="/srv/kallithea/venv/bin/kallithea-cli ssh-serve -c /srv/kallithea/my.ini 7 17" ssh-rsa AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ==\\n'
 
    """
 
    try:
 
        keytype, decoded, comment = parse_pub_key(key.public_key)
 
    except SshKeyParseError:
 
        return '# Invalid Kallithea SSH key: %s %s\n' % (key.user.user_id, key.user_ssh_key_id)
 
    mimekey = decoded.encode('base64').replace('\n', '')
 
    return '%s,command="%s ssh-serve -c %s %s %s" %s %s\n' % (
 
        SSH_OPTIONS, kallithea_cli_path, config_file,
 
        key.user.user_id, key.user_ssh_key_id,
 
        keytype, mimekey)
kallithea/templates/admin/settings/settings_visual.html
Show inline comments
 
@@ -13,96 +13,98 @@ ${h.form(url('admin_settings_visual'), m
 

	
 
                    <div class="checkbox">
 
                        <label>
 
                            ${h.checkbox('show_version','True')}
 
                            ${_('Show Kallithea version')}
 
                        </label>
 
                    </div>
 
                    <span class="help-block">${_('Shows or hides a version number of Kallithea displayed in the footer.')}</span>
 

	
 
                    <div class="checkbox">
 
                        <label>
 
                            ${h.checkbox('use_gravatar','True')}
 
                            ${_('Show user Gravatars')}
 
                        </label>
 
                    </div>
 
                    ${h.text('gravatar_url', size=80, class_='form-control')}
 
                    <span class="help-block">${_('''Gravatar URL allows you to use another avatar server application.
 
                                                        The following variables of the URL will be replaced accordingly.
 
                                                        {scheme}    'http' or 'https' sent from running Kallithea server,
 
                                                        {email}     user email,
 
                                                        {md5email}  md5 hash of the user email (like at gravatar.com),
 
                                                        {size}      size of the image that is expected from the server application,
 
                                                        {netloc}    network location/server host of running Kallithea server''')}</span>
 
                </div>
 
            </div>
 

	
 
            <div class="form-group">
 
                <label class="control-label">${_('HTTP Clone URL')}:</label>
 
                <div>
 
                    ${h.text('clone_uri_tmpl', size=80, class_='form-control')}
 
                    <span class="help-block">${_('''Schema of clone URL construction eg. '{scheme}://{user}@{netloc}/{repo}'.
 
                                                    The following variables are available:
 
                                                    {scheme} 'http' or 'https' sent from running Kallithea server,
 
                                                    {user}   current user username,
 
                                                    {netloc} network location/server host of running Kallithea server,
 
                                                    {repo}   full repository name,
 
                                                    {repoid} ID of repository, can be used to construct clone-by-id,
 
                                                    {system_user}  name of the Kallithea system user,
 
                                                    {hostname}  server hostname
 
                                                    ''')}
 
                    </span>
 
                </div>
 
                %if c.ssh_enabled:
 
                <label class="control-label">${_('SSH Clone URL')}:</label>
 
                <div>
 
                    ${h.text('clone_ssh_tmpl', size=80, class_='form-control')}
 
                    <span class="help-block">${_('''Schema for constructing SSH clone URL, eg. 'ssh://{system_user}@{hostname}/{repo}'.''')}</span>
 
                </div>
 
                %else:
 
                ${h.hidden('clone_ssh_tmpl', size=80, class_='form-control')}
 
                %endif
 
            </div>
 

	
 
            <div class="form-group">
 
                <label class="control-label" for="dashboard_items">${_('Repository page size')}:</label>
 
                <div>
 
                    ${h.text('dashboard_items',size=5,class_='form-control')}
 
                    <span class="help-block">${_('Number of items displayed in the repository pages before pagination is shown.')}</span>
 
                </div>
 
            </div>
 

	
 
            <div class="form-group">
 
                <label class="control-label" for="admin_grid_items">${_('Admin page size')}:</label>
 
                <div>
 
                    ${h.text('admin_grid_items',size=5,class_='form-control')}
 
                    <span class="help-block">${_('Number of items displayed in the admin pages grids before pagination is shown.')}</span>
 
                </div>
 
            </div>
 

	
 
            <div class="form-group">
 
                <label class="control-label">${_('Icons')}:</label>
 
                <div>
 
                    <div class="checkbox">
 
                        <label>
 
                            ${h.checkbox('show_public_icon','True')}
 
                            ${_('Show public repository icon on repositories')}
 
                        </label>
 
                    </div>
 
                    <div class="checkbox">
 
                        <label>
 
                            ${h.checkbox('show_private_icon','True')}
 
                            ${_('Show private repository icon on repositories')}
 
                        </label>
 
                    </div>
 
                    <span class="help-block">${_('Show public/private icons next to repository names.')}</span>
 
                 </div>
 
            </div>
 

	
 
            <div class="form-group">
 
                <label class="control-label" for="stylify_metalabels">${_('Meta Tagging')}:</label>
 
                <div>
 
                    <div class="checkbox">
 
                        <label>
 
                            ${h.checkbox('stylify_metalabels','True')}
 
                            ${_('Parses meta tags from the repository description field and turns them into colored tags.')}
 
                        </label>
 
                    </div>
 
                    <div class="help-block">
scripts/make-release
Show inline comments
 
#!/bin/bash
 
set -e
 
set -x
 

	
 
cleanup()
 
{
 
  echo "Removing venv $venv"
 
  rm  -rf "$venv"
 
}
 

	
 
echo "Checking that you are NOT inside a virtualenv"
 
[ -z "$VIRTUAL_ENV" ]
 

	
 
venv=$(mktemp -d --tmpdir kallithea-release-XXXXX)
 
trap cleanup EXIT
 

	
 
echo "Setting up a fresh virtualenv in $venv"
 
virtualenv -p python2 "$venv"
 
. "$venv/bin/activate"
 

	
 
echo "Install/verify tools needed for building and uploading stuff"
 
pip install --upgrade -e . -r dev_requirements.txt twine
 
pip install --upgrade -e . -r dev_requirements.txt twine python-ldap python-pam
 

	
 
echo "Cleanup and update copyrights ... and clean checkout"
 
scripts/run-all-cleanup
 
scripts/update-copyrights.py
 
hg up -cr .
 

	
 
echo "Make release build from clean checkout in build/"
 
rm -rf build dist
 
hg archive build
 
cd build
 

	
 
echo "Check that each entry in MANIFEST.in match something"
 
sed -e 's/[^ ]*[ ]*\([^ ]*\).*/\1/g' MANIFEST.in | xargs ls -lad
 

	
 
echo "Build dist"
 
python2 setup.py compile_catalog
 
python2 setup.py sdist
 

	
 
echo "Verify VERSION from kallithea/__init__.py"
 
namerel=$(cd dist && echo Kallithea-*.tar.gz)
 
namerel=${namerel%.tar.gz}
 
version=${namerel#Kallithea-}
 
ls -l $(pwd)/dist/$namerel.tar.gz
 
echo "Releasing Kallithea $version in directory $namerel"
 

	
 
echo "Verify dist file content"
 
diff -u <((hg mani | grep -v '^\.hg') | LANG=C sort) <(tar tf dist/Kallithea-$version.tar.gz | sed "s|^$namerel/||" | grep . | grep -v '^kallithea/i18n/.*/LC_MESSAGES/kallithea.mo$\|^Kallithea.egg-info/\|^PKG-INFO$\|/$' | LANG=C sort)
 

	
 
echo "Verify docs build"
 
python2 setup.py build_sphinx # the results are not actually used, but we want to make sure it builds
 

	
 
echo "Shortlog for inclusion in the release announcement"
 
scripts/shortlog.py "only('.', branch('stable') & tagged() & public() & not '.')"
 

	
 
cat - << EOT
 

	
 
Now, make sure
 
* all tests are passing
 
* release note is ready
 
* announcement is ready
 
* source has been pushed to https://kallithea-scm.org/repos/kallithea
 

	
 
EOT
 

	
 
echo "Verify current revision is tagged for $version"
 
hg log -r "'$version'&." | grep .
 

	
 
echo -n "Enter \"pypi\" to upload Kallithea $version to pypi: "
0 comments (0 inline, 0 general)