code:
# paths and configuration variables for gitolite

# please read comments before editing

# this file is meant to be pulled into a perl program using "do" or "require".

# You do NOT need to know perl to edit the paths; it should be fairly
# self-explanatory and easy to maintain perl syntax :-)

# --------------------------------------
# Do not uncomment these values unless you know what you're doing
# $GL_PACKAGE_CONF = "";
# $GL_PACKAGE_HOOKS = "";

# --------------------------------------

# --------------------------------------

# this is where the repos go.  If you provide a relative path (not starting
# with "/"), it's relative to your $HOME.  You may want to put in something
# like "/bigdisk" or whatever if your $HOME is too small for the repos, for
# example

$REPO_BASE="/srv/git/repositories/";

# the default umask for repositories is 0077; change this if you run stuff
# like gitweb and find it can't read the repos.  Please note the syntax;  the
# leading 0 is required

$REPO_UMASK = 0002;
# $REPO_UMASK = 0027;       # gets you 'rwxr-x---'
# $REPO_UMASK = 0022;       # gets you 'rwxr-xr-x'

# part of the setup of gitweb is a variable called $projects_list (please see
# gitweb documentation for more on this).  Set this to the same value:

$PROJECTS_LIST = $ENV{HOME} . "/projects.list";

# --------------------------------------

# I see no reason anyone may want to change the gitolite admin directory, but
# feel free to do so.  However, please note that it *must* be an *absolute*
# path (i.e., starting with a "/" character)

# gitolite admin directory, files, etc

$GL_ADMINDIR="/etc/gitolite";

# --------------------------------------

# templates for location of the log files and format of their names

# I prefer this template (note the %y and %m placeholders)
# it produces files like `~/.gitolite/logs/gitolite-2009-09.log`

$GL_LOGT="/var/log/gitolite/gitolite-%y-%m.log";

# other choices are below, or you can make your own -- but PLEASE MAKE SURE
# the directory exists and is writable; gitolite won't do that for you (unless
# it is the default, which is "$GL_ADMINDIR/logs")

# $GL_LOGT="$GL_ADMINDIR/logs/gitolite-%y-%m-%d.log";
# $GL_LOGT="$GL_ADMINDIR/logs/gitolite-%y.log";

# --------------------------------------

# Please DO NOT change these three paths

$GL_CONF="$GL_ADMINDIR/conf/gitolite.conf";
$GL_KEYDIR="$GL_ADMINDIR/keydir";
$GL_CONF_COMPILED="$GL_ADMINDIR/conf/gitolite.conf-compiled.pm";

# --------------------------------------

# if git on your server is on a standard path (that is
#       ssh git@server git --version
# works), leave this setting as is.  Otherwise, choose one of the
# alternatives, or write your own

$GIT_PATH="";
# $GIT_PATH="/opt/bin/";

# --------------------------------------

# ----------------------------------------------------------------------
#                   BIG CONFIG SETTINGS

# Please read doc/big-config.mkd for details

$GL_BIG_CONFIG = 1;
$GL_NO_DAEMON_NO_GITWEB = 1;
$GL_NO_CREATE_REPOS = 1;
$GL_NO_SETUP_AUTHKEYS = 1;

# ----------------------------------------------------------------------
#                   SECURITY SENSITIVE SETTINGS
#
#       Settings below this point may have security implications.  That
#       usually means that I have not thought hard enough about all the
#       possible ways to crack security if these settings are enabled.

#       Please see details on each setting for specifics, if any.
# ----------------------------------------------------------------------

# --------------------------------------
# ALLOW REPO ADMIN TO SET GITCONFIG KEYS
#
# Gitolite allows you to set git repo options using the "config" keyword; see
# conf/example.conf for details and syntax.
#
# However, if you are in an installation where the repo admin does not (and
# should not) have shell access to the server, then allowing him to set
# arbitrary repo config options *may* be a security risk -- some config
# settings may allow executing arbitrary commands.
#
# You have 3 choices.  By default $GL_GITCONFIG_KEYS is left empty, which
# completely disables this feature (meaning you cannot set git configs from
# the repo config).

$GL_GITCONFIG_KEYS = "";

# The second choice is to give it a space separated list of settings you
# consider safe.  (These are actually treated as a set of regular expression
# patterns, and any one of them must match).  For example:
# $GL_GITCONFIG_KEYS = "core\.logAllRefUpdates core\..*compression";
# allows repo admins to set one of those 3 config keys (yes, that second
# pattern matches two settings from "man git-config", if you look)
#
# The third choice (which you may have guessed already if you're familiar with
# regular expressions) is to allow anything and everything:
# $GL_GITCONFIG_KEYS = ".*";

# --------------------------------------
# EXTERNAL COMMAND HELPER -- HTPASSWD

# security note: runs an external command (htpasswd) with specific arguments,
# including a user-chosen "password".

# if you want to enable the "htpasswd" command, give this the absolute path to
# whatever file apache (etc) expect to find the passwords in.

$HTPASSWD_FILE = "";

# Look in doc/3 ("easier to link gitweb authorisation with gitolite" section)
# for more details on using this feature.

# --------------------------------------
# EXTERNAL COMMAND HELPER -- RSYNC

# security note: runs an external command (rsync) with specific arguments, all
# presumably filled in correctly by the client-side rsync.

# base path of all the files that are accessible via rsync.  Must be an
# absolute path.  Leave it undefined or set to the empty string to disable the
# rsync helper.

$RSYNC_BASE = "";

# $RSYNC_BASE = "/home/git/up-down";
# $RSYNC_BASE = "/tmp/up-down";

# --------------------------------------
# EXTERNAL COMMAND HELPER -- SVNSERVE

# security note: runs an external command (svnserve) with specific arguments,
# as specified below. %u is substituted with the username.

# This setting allows launching svnserve when requested by the ssh client.
# This allows using the same SSH setup (hostname/username/public key) for both
# SVN and git access. Leave it undefined or set to the empty string to disable
# svnserve access.

$SVNSERVE = "";
# $SVNSERVE = "/usr/bin/svnserve -r /var/svn/ -t --tunnel-user=%u";

# --------------------------------------
# ALLOW REPO CONFIG TO USE WILDCARDS

# security note: this used to in a separate "wildrepos" branch.  You can
# create repositories based on wild cards, give "ownership" to the specific
# user who created it, allow him/her to hand out R and RW permissions to other
# users to collaborate, etc.  This is powerful stuff, and I've made it as
# secure as I can, but it hasn't had the kind of rigorous line-by-line
# analysis that the old "master" branch had.

# This has now been rolled into master, with all the functionality gated by
# this variable.  Set this to 1 if you want to enable the wildrepos features.
# Please see doc/4-wildcard-repositories.mkd for details.

$GL_WILDREPOS = 0;

# --------------------------------------
# DEFAULT WILDCARD PERMISSIONS

# If set, this value will be used as the default user-level permission rule of
# new wildcard repositories. The user can change this value with the setperms command
# as desired after repository creation; it is only a default. Note that @all can be
# used here but is special; no other groups can be used in user-level permissions.

# $GL_WILDREPOS_DEFPERMS = 'R = @all';

# --------------------------------------
# HOOK CHAINING

# by default, the update hook in every repo chains to "update.secondary".
# Similarly, the post-update hook in the admin repo chains to
# "post-update.secondary".  If you're fine with the defaults, there's no need
# to do anything here.  However, if you want to use different names or paths,
# change these variables

# $UPDATE_CHAINS_TO = "hooks/update.secondary";
# $ADMIN_POST_UPDATE_CHAINS_TO = "hooks/post-update.secondary";

# --------------------------------------
# ADMIN DEFINED COMMANDS

# WARNING: Use this feature only if (a) you really really know what you're
# doing or (b) you really don't care too much about security.  Please read
# doc/admin-defined-commands.mkd for details.

# $GL_ADC_PATH = "";

# --------------------------------------
# per perl rules, this should be the last line in such a file:
1;

# Local variables:
# mode: perl
# End:
# vim: set syn=perl:


code:
# configuration variables for gitolite

# This file is in perl syntax.  But you do NOT need to know perl to edit it --
# just mind the commas, use single quotes unless you know what you're doing,
# and make sure the brackets and braces stay matched up!

# (Tip: perl allows a comma after the last item in a list also!)

# HELP for commands can be had by running the command with "-h".

# HELP for all the other FEATURES can be found in the documentation (look for
# "list of non-core programs shipped with gitolite" in the master index) or
# directly in the corresponding source file.

%RC = (

    # ------------------------------------------------------------------

    # default umask gives you perms of '0700'; see the rc file docs for
    # how/why you might change this
    UMASK                           =>  0077,

    # look for "git-config" in the documentation
    GIT_CONFIG_KEYS                 =>  '',

    # comment out if you don't need all the extra detail in the logfile
    LOG_EXTRA                       =>  1,
    # syslog options
    # 1. leave this section as is for normal gitolite logging
    # 2. uncomment this line to log only to syslog:
    # LOG_DEST                      => 'syslog',
    # 3. uncomment this line to log to syslog and the normal gitolite log:
    # LOG_DEST                      => 'syslog,normal',

    # roles.  add more roles (like MANAGER, TESTER, ...) here.
    #   WARNING: if you make changes to this hash, you MUST run 'gitolite
    #   compile' afterward, and possibly also 'gitolite trigger POST_COMPILE'
    ROLES => {
        READERS                     =>  1,
        WRITERS                     =>  1,
    },

    # enable caching (currently only Redis).  PLEASE RTFM BEFORE USING!!!
    # CACHE                         =>  'Redis',

    # ------------------------------------------------------------------

    # rc variables used by various features

    # the 'info' command prints this as additional info, if it is set
        # SITE_INFO                 =>  'Please see http://blahblah/gitolite for more help',

    # the CpuTime feature uses these
        # display user, system, and elapsed times to user after each git operation
        # DISPLAY_CPU_TIME          =>  1,
        # display a warning if total CPU times (u, s, cu, cs) crosses this limit
        # CPU_TIME_WARN_LIMIT       =>  0.1,

    # the Mirroring feature needs this
        # HOSTNAME                  =>  "foo",

    # TTL for redis cache; PLEASE SEE DOCUMENTATION BEFORE UNCOMMENTING!
        # CACHE_TTL                 =>  600,

    # ------------------------------------------------------------------

    # suggested locations for site-local gitolite code (see cust.html)

        # this one is managed directly on the server
        # LOCAL_CODE                =>  "$ENV{HOME}/local",

        # or you can use this, which lets you put everything in a subdirectory
        # called "local" in your gitolite-admin repo.  For a SECURITY WARNING
        # on this, see http://gitolite.com/gitolite/non-core.html#pushcode
        # LOCAL_CODE                =>  "$rc{GL_ADMIN_BASE}/local",

    # ------------------------------------------------------------------

    # List of commands and features to enable

    ENABLE => [

        # COMMANDS

            # These are the commands enabled by default
            'help',
            'desc',
            'info',
            'perms',
            'writable',

            # Uncomment or add new commands here.
            # 'create',
            # 'fork',
            # 'mirror',
            # 'readme',
            # 'sskm',
            # 'D',

        # These FEATURES are enabled by default.

            # essential (unless you're using smart-http mode)
            'ssh-authkeys',

            # creates git-config enties from gitolite.conf file entries like 'config foo.bar = baz'
            'git-config',

            # creates git-daemon-export-ok files; if you don't use git-daemon, comment this out
            'daemon',

            # creates projects.list file; if you don't use gitweb, comment this out
            #'gitweb',

        # These FEATURES are disabled by default; uncomment to enable.  If you
        # need to add new ones, ask on the mailing list :-)

        # user-visible behaviour

            # prevent wild repos auto-create on fetch/clone
            # 'no-create-on-read',
            # no auto-create at all (don't forget to enable the 'create' command!)
            # 'no-auto-create',

            # access a repo by another (possibly legacy) name
            # 'Alias',

            # give some users direct shell access.  See documentation in
            # sts.html for details on the following two choices.
            # "Shell $ENV{HOME}/.gitolite.shell-users",
            # 'Shell alice bob',

            # set default roles from lines like 'option default.roles-1 = ...', etc.
            # 'set-default-roles',

            # show more detailed messages on deny
            # 'expand-deny-messages',

            # show a message of the day
            # 'Motd',

        # system admin stuff

            # enable mirroring (don't forget to set the HOSTNAME too!)
            # 'Mirroring',

            # allow people to submit pub files with more than one key in them
            # 'ssh-authkeys-split',

            # selective read control hack
            # 'partial-copy',

            # manage local, gitolite-controlled, copies of read-only upstream repos
            # 'upstream',

            # updates 'description' file instead of 'gitweb.description' config item
            # 'cgit',

            # allow repo-specific hooks to be added
            # 'repo-specific-hooks',

        # performance, logging, monitoring...

            # be nice
            # 'renice 10',

            # log CPU times (user, system, cumulative user, cumulative system)
            # 'CpuTime',

        # syntactic_sugar for gitolite.conf and included files

            # allow backslash-escaped continuation lines in gitolite.conf
            # 'continuation-lines',

            # create implicit user groups from directory names in keydir/
            # 'keysubdirs-as-groups',

            # allow simple line-oriented macros
            # 'macros',

        # Kindergarten mode

            # disallow various things that sensible people shouldn't be doing anyway
            # 'Kindergarten',
    ],

);

# ------------------------------------------------------------------------------
# per perl rules, this should be the last line in such a file:
1;

# Local variables:
# mode: perl
# End:
# vim: set syn=perl:

repo_name: bill/auger

license: mit


code:
#!/usr/bin/env python

import argparse
import requests
import os

from sqlalchemy.exc import SQLAlchemyError

if 'PAGURE_CONFIG' not in os.environ \
        and os.path.exists('/etc/pagure/pagure.cfg'):
    print 'Using configuration file `/etc/pagure/pagure.cfg`'
    os.environ['PAGURE_CONFIG'] = '/etc/pagure/pagure.cfg'

import pagure
import pagure.lib
import pagure.lib.model

def get_poc_of_pkgs(debug=False):
    """ Retrieve a dictionary giving the point of contact of each package
    in pkgdb.
    """
    if debug:
        print 'Querying pkgdb'
    PKGDB_URL = 'https://admin.stg.fedoraproject.org/pkgdb/api/'
    req = requests.get(PKGDB_URL + 'bugzilla').text
    if debug:
        print 'Pkgdb data retrieved, getting POC'
    pkgs = {}
    for line in req.split('\n'):
        line = line.strip()
        if not line or line.startswith('#'):
            continue
        line = line.split('|')
        if len(line) < 4:
            continue
        pkgs[line[1]] = line[3]

    return pkgs

def main(folder, debug=False):
    """
    Logic:
    - Query the list of maintainer/PoC from pkgdb
    - Browse the directory
    - For each git in the directory, create the project with the correct POC
    """
    pocs = get_poc_of_pkgs(debug=debug)

    if debug:
        print 'Adding the user to the DB'
    for user in sorted(set(pocs.values())):
        if debug:
            print user
        try:
            pagure.lib.set_up_user(
                session=pagure.SESSION,
                username=user,
                fullname=user,
                default_email='%s@fedoraproject.org' % user,
                keydir=pagure.APP.config.get('GITOLITE_KEYDIR', None),
            )
            pagure.SESSION.commit()
        except SQLAlchemyError as err:
            pagure.SESSION.rollback()
            print 'ERROR with user %s' % user
            print err

    for project in sorted(os.listdir(folder)):
        if debug:
            print project

        if not project.endswith('.git'):
            if debug:
                print '  -skip: not a git repository'
            continue

        if project.split('.git')[0] not in pocs:
            if debug:
                print '  -skip: no pocs'
            continue

        try:
            name = project.split('.git')[0]
            orig_name = name
            name = 'rpms/%s' % name
            if name in pagure.APP.config['BLACKLISTED_PROJECTS']:
                raise pagure.exceptions.RepoExistsException(
                    'No project "%s" are allowed to be created due to potential '
                    'conflicts in URLs with pagure itself' % name
                )

            user_obj = pagure.lib.__get_user(pagure.SESSION, pocs[orig_name])
            allowed_prefix = pagure.APP.config[
                'ALLOWED_PREFIX'] + [grp for grp in user_obj.groups]

            first_part, _, second_part = name.partition('/')
            if second_part and first_part not in allowed_prefix:
                raise pagure.exceptions.PagureException(
                    'The prefix of you project must be in the list of allowed '
                    'prefix set by the admins of this pagure instance, or the name '
                    'of a group that you are part of.'
                )

            gitfolder = pagure.APP.config['GIT_FOLDER']
            docfolder = pagure.APP.config['DOCS_FOLDER']
            ticketfolder = pagure.APP.config['TICKETS_FOLDER']
            requestfolder = pagure.APP.config['REQUESTS_FOLDER']

            gitrepo = os.path.join(gitfolder, '%s.git' % name)

            project = pagure.lib.model.Project(
                name=name,
                description=None,
                url=None,
                avatar_email=None,
                user_id=user_obj.id,
                parent_id=None,
                hook_token=pagure.lib.login.id_generator(40)
            )
            pagure.SESSION.add(project)
            # Make sure we won't have SQLAlchemy error before we create the repo
            pagure.SESSION.flush()

            http_clone_file = os.path.join(gitrepo, 'git-daemon-export-ok')
            if not os.path.exists(http_clone_file):
                with open(http_clone_file, 'w') as stream:
                    pass

            docrepo = os.path.join(docfolder, project.path)
            if os.path.exists(docrepo):
                shutil.rmtree(gitrepo)
                raise pagure.exceptions.RepoExistsException(
                    'The docs repo "%s" already exists' % project.path
                )
            pygit2.init_repository(docrepo, bare=True)

            ticketrepo = os.path.join(ticketfolder, project.path)
            if os.path.exists(ticketrepo):
                shutil.rmtree(gitrepo)
                shutil.rmtree(docrepo)
                raise pagure.exceptions.RepoExistsException(
                    'The tickets repo "%s" already exists' % project.path
                )
            pygit2.init_repository(
                ticketrepo, bare=True,
                mode=pygit2.C.GIT_REPOSITORY_INIT_SHARED_GROUP)

            requestrepo = os.path.join(requestfolder, project.path)
            if os.path.exists(requestrepo):
                shutil.rmtree(gitrepo)
                shutil.rmtree(docrepo)
                shutil.rmtree(ticketrepo)
                raise pagure.exceptions.RepoExistsException(
                    'The requests repo "%s" already exists' % project.path
                )
            pygit2.init_repository(
                requestrepo, bare=True,
                mode=pygit2.C.GIT_REPOSITORY_INIT_SHARED_GROUP)

            pagure.SESSION.commit()
        except pagure.exceptions.PagureException as err:
            print 'ERROR with project %s' % project
            print err
        except SQLAlchemyError as err:  # pragma: no cover
            pagure.SESSION.rollback()
            print 'ERROR (DB) with project %s' % project
            print err

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description='Script creating projects on pagure based on the git '
        'repos present in the specified folder and the pkgdb information.'
    )
    parser.add_argument(
        'folder',
        help='Folder containing all the git repos of the projects to create')
    parser.add_argument(
        '--debug', dest='debug', action='store_true', default=False,
        help='Print the debugging output')

    args = parser.parse_args()

    main(args.folder, debug=args.debug)


code:
import os
from datetime import timedelta

### Set the time after which the admin session expires
# There are two sessions on pagure, login that holds for 31 days and
# the session defined here after which an user has to re-login.
# This session is used when accessing all administrative parts of pagure
# (ie: changing a project's or a user's settings)
ADMIN_SESSION_LIFETIME = timedelta(minutes=20)

### Secret key for the Flask application
SECRET_KEY='<The web application secret key>'

### url to the database server:
#DB_URL=mysql://user:pass@host/db_name
#DB_URL=postgres://user:pass@host/db_name
DB_URL = 'sqlite:////var/tmp/pagure_dev.sqlite'

### The FAS group in which the admin of pagure are
ADMIN_GROUP = ['sysadmin-main']

### Hard-coded list of global admins
PAGURE_ADMIN_USERS = []

### The email address to which the flask.log will send the errors (tracebacks)
EMAIL_ERROR = 'pingou@pingoured.fr'

### SMTP settings
SMTP_SERVER = 'localhost'
SMTP_PORT = 25
SMTP_SSL = False

#Specify both for enabling SMTP with auth
SMTP_USERNAME = None
SMTP_PASSWORD = None

### Information used to sent notifications
FROM_EMAIL = 'pagure@pagure.io'
DOMAIN_EMAIL_NOTIFICATIONS = 'pagure.io'
SALT_EMAIL = '<secret key to be changed>'

### The URL at which the project is available.
APP_URL = 'https://pagure.io/'
### The URL at which the documentation of projects will be available
## This should be in a different domain to avoid XSS issues since we want
## to allow raw html to be displayed (different domain, ie not a sub-domain).
DOC_APP_URL = 'https://docs.pagure.org'

### The URL to use to clone git repositories.
GIT_URL_SSH = 'ssh://git@pagure.io/'
GIT_URL_GIT = 'git://pagure.io/'

### Folder containing to the git repos
GIT_FOLDER = os.path.join(
    os.path.abspath(os.path.dirname(__file__)),
    '..',
    'repos'
)

### Folder containing the forks repos
FORK_FOLDER = os.path.join(
    os.path.abspath(os.path.dirname(__file__)),
    '..',
    'forks'
)

### Folder containing the docs repos
DOCS_FOLDER = os.path.join(
    os.path.abspath(os.path.dirname(__file__)),
    '..',
    'docs'
)

### Folder containing the tickets repos
TICKETS_FOLDER = os.path.join(
    os.path.abspath(os.path.dirname(__file__)),
    '..',
    'tickets'
)

### Folder containing the pull-requests repos
REQUESTS_FOLDER = os.path.join(
    os.path.abspath(os.path.dirname(__file__)),
    '..',
    'requests'
)

### Folder containing the clones for the remote pull-requests
REMOTE_GIT_FOLDER = os.path.join(
    os.path.abspath(os.path.dirname(__file__)),
    '..',
    'remotes'
)

### Configuration file for gitolite
GITOLITE_CONFIG = os.path.join(
    os.path.abspath(os.path.dirname(__file__)),
    '..',
    'gitolite.conf'
)

### Home folder of the gitolite user
### Folder where to run gl-compile-conf from
GITOLITE_HOME = None

### Version of gitolite used: 2 or 3?
GITOLITE_VERSION = 3

### Folder containing all the public ssh keys for gitolite
GITOLITE_KEYDIR = None

### Path to the gitolite.rc file
GL_RC = None

### Path to the /bin directory where the gitolite tools can be found
GL_BINDIR = None

# SSH Information

### The ssh certificates of the git server to be provided to the user
### /!\ format is important
# SSH_KEYS = {'RSA': {'fingerprint': '<foo>', 'pubkey': '<bar>'}}

# Optional configuration

### Number of items displayed per page
# Used when listing items
ITEM_PER_PAGE = 50

### Maximum size of the uploaded content
# Used to limit the size of file attached to a ticket for example
MAX_CONTENT_LENGTH = 4 * 1024 * 1024  # 4 megabytes

### Lenght for short commits ids or file hex
SHORT_LENGTH = 6

### List of blacklisted project names that can conflicts for pagure's URLs
### or other
BLACKLISTED_PROJECTS = [
    'static', 'pv', 'releases', 'new', 'api', 'settings',
    'logout', 'login', 'users', 'groups', 'projects']

### IP addresses allowed to access the internal endpoints
### These endpoints are used by the milter and are security sensitive, thus
### the IP filter
IP_ALLOWED_INTERNAL = ['127.0.0.1', 'localhost', '::1']

### EventSource/Web-Hook/Redis configuration
# The eventsource integration is what allows pagure to refresh the content
# on your page when someone else comments on the ticket (and this without
# asking you to reload the page.
# By default it is off, ie: EVENTSOURCE_SOURCE is None, to turn it on, specify
# here what the URL of the eventsource server is, for example:
# https://ev.pagure.io or https://pagure.io:8080 or whatever you are using
# (Note: the urls sent to it start with a '/' so no need to add one yourself)
EVENTSOURCE_SOURCE = None
# Port where the event source server is running (maybe be the same port
# as the one specified in EVENTSOURCE_SOURCE or a different one if you
# have something running in front of the server such as apache or stunnel).
EVENTSOURCE_PORT = 8080
# If this port is specified, the event source server will run another server
# at this port and will provide information about the number of active
# connections running on the first (main) event source server
#EV_STATS_PORT = 8888
# Web-hook can be turned on or off allowing using them for notifications, or
# not.
WEBHOOK = False

### Redis configuration
# A redis server is required for both the Event-Source server or the web-hook
# server.
REDIS_HOST = '0.0.0.0'
REDIS_PORT = 6379
REDIS_DB = 0

# Authentication related configuration option

### Switch the authentication method
# Specify which authentication method to use, defaults to `fas` can be or
# `local`
# Default: ``fas``.
PAGURE_AUTH = 'fas'

# When this is set to True, the session cookie will only be returned to the
# server via ssl (https). If you connect to the server via plain http, the
# cookie will not be sent. This prevents sniffing of the cookie contents.
# This may be set to False when testing your application but should always
# be set to True in production.
# Default: ``True``.
SESSION_COOKIE_SECURE = False

# The name of the cookie used to store the session id.
# Default: ``.pagure``.
SESSION_COOKIE_NAME = 'pagure'

# Boolean specifying whether to check the user's IP address when retrieving
# its session. This make things more secure (thus is on by default) but
# under certain setup it might not work (for example is there are proxies
# in front of the application).
CHECK_SESSION_IP = True

# Used by SESSION_COOKIE_PATH
APPLICATION_ROOT = '/'

# Allow the backward compatiblity endpoints for the old URLs schema to
# see the commits of a repo. This is only interesting if you pagure instance
# was running since before version 1.3 and if you care about backward
# compatibility in your URLs.
OLD_VIEW_COMMIT_ENABLED = False


code:
#WSGISocketPrefix run/wsgi
##WSGIRestrictStdout On
#WSGIRestrictSignal Off
#WSGIPythonOptimize 1
#WSGIPassAuthorization On
#WSGIDaemonProcess pagure user=git group=git maximum-requests=1000 display-name=pagure processes=4 threads=4 inactivity-timeout=300
## It is important that the doc server runs in a different apache process
#WSGIDaemonProcess paguredocs user=git group=git maximum-requests=1000 display-name=pagure processes=4 threads=4 inactivity-timeout=300

#<VirtualHost *:80>
  #ServerName pagure.io
  #Redirect permanent / https://pagure.io/
#</VirtualHost>

#<VirtualHost *:80>
  #ServerName docs.pagure.org
  #Redirect permanent / https://docs.pagure.org/
#</VirtualHost>

#<VirtualHost *:443>
  #ServerName docs.pagure.org

  #WSGIScriptAlias / /usr/share/pagure/docs_pagure.wsgi

  #SSLEngine on
  #SSLProtocol all -SSLv2 -SSLv3
  ## Use secure TLSv1.1 and TLSv1.2 ciphers
  #Header always add Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"

  #SSLCertificateFile /etc/pki/tls/....crt
  #SSLCertificateChainFile /etc/pki/tls/....intermediate.crt
  #SSLCertificateKeyFile /etc/pki/tls/....key

  #Alias /static /usr/lib/python2.7/site-packages/pagure/static/

  #<Location />
    #WSGIProcessGroup paguredocs
    #<IfModule mod_authz_core.c>
      ## Apache 2.4
      #Require all granted
    #</IfModule>
    #<IfModule !mod_authz_core.c>
      ## Apache 2.2
      #Order deny,allow
      #Allow from all
    #</IfModule>
   #</Location>
#</VirtualHost>

#<VirtualHost *:443>
  #ServerName pagure.io

  #WSGIScriptAlias / /usr/share/pagure/pagure.wsgi

  #SSLEngine on
  #SSLProtocol all -SSLv2 -SSLv3
  ## Use secure TLSv1.1 and TLSv1.2 ciphers
  #Header always add Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"

  #SSLCertificateFile /etc/pki/tls/....crt
  #SSLCertificateChainFile /etc/pki/tls/....intermediate.crt
  #SSLCertificateKeyFile /etc/pki/tls/....key

  #Alias /static /usr/lib/python2.7/site-packages/pagure/static/
  #Alias /releases /var/www/releases

  ## Section used to support cloning git repo over http (https in this case)
  #SetEnv GIT_PROJECT_ROOT /srv/git/repositories

  #AliasMatch ^/(.*/objects/[0-9a-f]{2}/[0-9a-f]{38})$          /path/to/git/repositories/$1
  #AliasMatch ^/(.*/objects/pack/pack-[0-9a-f]{40}.(pack|idx))$ /path/to/git/repositories/$1
  #ScriptAliasMatch \
    #"(?x)^/(.*/(HEAD | \
    #info/refs | \
    #objects/info/[^/]+ | \
    #git-(upload|receive)-pack))$" \
    #/usr/libexec/git-core/git-http-backend/$1

  #<Location />
   #WSGIProcessGroup pagure
   #<IfModule mod_authz_core.c>
      ## Apache 2.4
      #Require all granted
   #</IfModule>
   #<IfModule !mod_authz_core.c>
      ## Apache 2.2
      #Order deny,allow
      #Allow from all
   #</IfModule>
  #</Location>

  ## Folder where are stored the tarball of the releases
  #<Location /releases>
   #WSGIProcessGroup pagure
   #<IfModule mod_authz_core.c>
      ## Apache 2.4
      #Require all granted
   #</IfModule>
   #<IfModule !mod_authz_core.c>
       ## Apache 2.2
      #Order deny,allow
      #Allow from all
   #</IfModule>
  #</Location>

  #<Directory /var/www/releases>
    #Options +Indexes
  #</Directory>

#</VirtualHost>


code:
%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from
%distutils.sysconfig import get_python_lib; print (get_python_lib())")}

Name:           pagure
Version:        2.3.3
Release:        1%{?dist}
Summary:        A git-centered forge

License:        GPLv2+
URL:            https://pagure.io/pagure
Source0:        https://pagure.io/releases/pagure/%{name}-%{version}.tar.gz

BuildArch:      noarch

BuildRequires:  python2-devel
BuildRequires:  python-setuptools
BuildRequires:  python-nose

BuildRequires:  py-bcrypt
BuildRequires:  python-alembic
BuildRequires:  python-arrow
BuildRequires:  python-binaryornot
BuildRequires:  python-bleach
BuildRequires:  python-blinker
BuildRequires:  python-chardet
BuildRequires:  python-cryptography
BuildRequires:  python-docutils
BuildRequires:  python-flask
BuildRequires:  python-flask-wtf
BuildRequires:  python-flask-multistatic
BuildRequires:  python-markdown
BuildRequires:  python-psutil
BuildRequires:  python-pygit2 >= 0.20.1
BuildRequires:  python-pygments
BuildRequires:  python-fedora
BuildRequires:  python-openid
BuildRequires:  python-openid-cla
BuildRequires:  python-openid-teams
BuildRequires:  python-straight-plugin
BuildRequires:  python-wtforms
BuildRequires:  python-munch
BuildRequires:  python-enum34
BuildRequires:  python-redis

# EPEL6
%if ( 0%{?rhel} && 0%{?rhel} == 6 )
BuildRequires:  python-sqlalchemy0.8
Requires:  python-sqlalchemy0.8
%else
BuildRequires:  python-sqlalchemy > 0.8
Requires:  python-sqlalchemy > 0.8
BuildRequires:  systemd
%endif

Requires:  py-bcrypt
Requires:  python-alembic
Requires:  python-arrow
Requires:  python-binaryornot
Requires:  python-bleach
Requires:  python-blinker
Requires:  python-chardet
Requires:  python-cryptography
Requires:  python-docutils
Requires:  python-enum34
Requires:  python-flask
Requires:  python-flask-wtf
Requires:  python-flask-multistatic
Requires:  python-markdown
Requires:  python-psutil
Requires:  python-pygit2 >= 0.20.1
Requires:  python-pygments
Requires:  python-fedora
Requires:  python-openid
Requires:  python-openid-cla
Requires:  python-openid-teams
Requires:  python-straight-plugin
Requires:  python-wtforms
Requires:  python-munch
Requires:  python-redis
Requires:  mod_wsgi

# No dependency of the app per se, but required to make it working.
Requires:  gitolite3

%description
Pagure is a light-weight git-centered forge based on pygit2.

Currently, Pagure offers a web-interface for git repositories, a ticket
system and possibilities to create new projects, fork existing ones and
create/merge pull-requests across or within projects.

%package milters
Summary:            Milter to integrate pagure with emails
BuildArch:          noarch
BuildRequires:      systemd-devel
Requires:           python-pymilter
Requires(post):     systemd
Requires(preun):    systemd
Requires(postun):   systemd
# It would work with sendmail but we configure things (like the tempfile)
# to work with postfix
Requires:           postfix
%description milters
Milters (Mail filters) allowing the integration of pagure and emails.
This is useful for example to allow commenting on a ticket by email.

%package ev
Summary:   EventSource server for pagure
BuildArch: noarch

BuildRequires:      systemd-devel
Requires:  python-redis
Requires:  python-trollius
Requires:  python-trollius-redis
Requires(post): systemd
Requires(preun): systemd
Requires(postun): systemd
%description ev
Pagure comes with an eventsource server allowing live update of the pages
supporting it. This package provides it.

%package webhook
Summary:   Web-Hook server for pagure
BuildArch: noarch

BuildRequires:      systemd-devel
Requires:  python-redis
Requires:  python-trollius
Requires:  python-trollius-redis
Requires(post): systemd
Requires(preun): systemd
Requires(postun): systemd
%description webhook
Pagure comes with an webhook server allowing http callbacks for any action
done on a project. This package provides it.

%prep
%setup -q

%build
%{__python2} setup.py build

%install
%{__python2} setup.py install -O1 --skip-build --root $RPM_BUILD_ROOT

# Install apache configuration file
mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/httpd/conf.d/
install -m 644 files/pagure.conf $RPM_BUILD_ROOT/%{_sysconfdir}/httpd/conf.d/pagure.conf

# Install configuration file
mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/pagure
install -m 644 files/pagure.cfg.sample $RPM_BUILD_ROOT/%{_sysconfdir}/pagure/pagure.cfg

# Install WSGI file
mkdir -p $RPM_BUILD_ROOT/%{_datadir}/pagure
install -m 644 files/pagure.wsgi $RPM_BUILD_ROOT/%{_datadir}/pagure/pagure.wsgi
install -m 644 files/doc_pagure.wsgi $RPM_BUILD_ROOT/%{_datadir}/pagure/doc_pagure.wsgi

# Install the createdb script
install -m 644 createdb.py $RPM_BUILD_ROOT/%{_datadir}/pagure/pagure_createdb.py

# Install the api_key_expire_mail.py script
install -m 644 createdb.py $RPM_BUILD_ROOT/%{_datadir}/pagure/api_key_expire_mail.py

# Install the alembic configuration file
install -m 644 files/alembic.ini $RPM_BUILD_ROOT/%{_sysconfdir}/pagure/alembic.ini

# Install the alembic revisions
cp -r alembic $RPM_BUILD_ROOT/%{_datadir}/pagure

# Install the milter files
mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/run/pagure
mkdir -p $RPM_BUILD_ROOT/%{_tmpfilesdir}
mkdir -p $RPM_BUILD_ROOT/%{_unitdir}
install -m 0644 milters/milter_tempfile.conf \
    $RPM_BUILD_ROOT/%{_tmpfilesdir}/%{name}-milter.conf
install -m 644 milters/pagure_milter.service \
    $RPM_BUILD_ROOT/%{_unitdir}/pagure_milter.service
install -m 644 milters/comment_email_milter.py \
    $RPM_BUILD_ROOT/%{_datadir}/pagure/comment_email_milter.py

# Install the eventsource
mkdir -p $RPM_BUILD_ROOT/%{_libexecdir}/pagure-ev
install -m 755 ev-server/pagure-stream-server.py \
    $RPM_BUILD_ROOT/%{_libexecdir}/pagure-ev/pagure-stream-server.py
install -m 644 ev-server/pagure_ev.service \
    $RPM_BUILD_ROOT/%{_unitdir}/pagure_ev.service

# Install the web-hook
mkdir -p $RPM_BUILD_ROOT/%{_libexecdir}/pagure-webhook
install -m 755 webhook-server/pagure-webhook-server.py \
    $RPM_BUILD_ROOT/%{_libexecdir}/pagure-webhook/pagure-webhook-server.py
install -m 644 webhook-server/pagure_webhook.service \
    $RPM_BUILD_ROOT/%{_unitdir}/pagure_webhook.service

%post milters
%systemd_post pagure_milter.service
%post ev
%systemd_post pagure_ev.service
%post webhook
%systemd_post pagure_webhook.service

%preun milters
%systemd_preun pagure_milter.service
%preun ev
%systemd_preun pagure_ev.service
%preun webhook
%systemd_preun pagure_webhook.service

%postun milters
%systemd_postun_with_restart pagure_milter.service
%postun ev
%systemd_postun_with_restart pagure_ev.service
%postun webhook
%systemd_postun_with_restart pagure_webhook.service

%files
%doc README.rst UPGRADING.rst
%license LICENSE
%config(noreplace) %{_sysconfdir}/httpd/conf.d/pagure.conf
%config(noreplace) %{_sysconfdir}/pagure/pagure.cfg
%config(noreplace) %{_sysconfdir}/pagure/alembic.ini
%dir %{_sysconfdir}/pagure/
%dir %{_datadir}/pagure/
%config(noreplace) %{_datadir}/pagure/*.wsgi
%{_datadir}/pagure/*.py*
%{_datadir}/pagure/alembic/
%{python_sitelib}/pagure/
%{python_sitelib}/pagure*.egg-info

%files milters
%license LICENSE
%attr(755,postfix,postfix) %dir %{_localstatedir}/run/pagure
%dir %{_datadir}/pagure/
%{_tmpfilesdir}/%{name}-milter.conf
%{_unitdir}/pagure_milter.service
%{_datadir}/pagure/comment_email_milter.py*

%files ev
%license LICENSE
%{_libexecdir}/pagure-ev/
%{_unitdir}/pagure_ev.service

%files webhook
%license LICENSE
%{_libexecdir}/pagure-webhook/
%{_unitdir}/pagure_webhook.service

%changelog
* Fri Jul 15 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.3.3-1
- Update to 2.3.3
- Fix redering the release page when the tag message contain only spaces (Vivek
  Anand)
- Fix the search in @<username> (Eric Barbour)
- Displays link and git sub-modules in the tree with a dedicated icon

* Tue Jul 12 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.3.2-1
- Update to 2.3.2
- Do not mark as local only some of the internal API endpoints since they are
  called via ajax and thus with the user's IP

* Mon Jul 11 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.3.1-1
- Update to 2.3.1
- Fix sending notifications to users watching a project
- Fix displaying if you are watching the project or not

* Mon Jul 11 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.3-1
- Update to 2.3
- Fix typos in pr_custom_page.rst (Lubomír Sedlář)
- Improve the unit-test suite (Vivek Anand)
- Remove the branch chooser from the repoheader and rework the fork button (Ryan
  Lerch)
- Add support for non utf-8 file names (Ryan Lerch)
- Add a 'Duplicate' status for issues (Vivek Anand)
- Add title attribute for replying to comment and editing the comment in issues
  and PRs (Vivek Anand)
- Include the user when reporting error by email
- Add an API endpoint to create projects
- Add an API endpoint to assign someone to a ticket
- Add small script to be ran as cron to send reminder of expiring tokens (Vivek
  Anand)
- Do not show the PR button on branches for which a PR is already opened
- Add an API endpoint to fork projects
- Add the possibility to watch/unwatch a project (Gaurav Kumar)
- Add a 'Take' button on the issue page (Ryan Lerch and I)
- Add a dev-data script to input some test data in the DB for testing/dev
  purposes (skrzepto)
- Fix links to ticket/pull-request in the preview of a new ticket
- Add the possibility to diff two or more commits (Oliver Gutierrez)
- Fix viewing a file having a non-ascii name
- Fix viewing the diff between two commits having a file with a non-ascii name
- On the commit detail page, specify on which branch(es) the commit is
- Add the possibility to have instance-wide admins will full access to every
  projects (set in the configuration file)
- Drop the hash to the blob of the file when listing the files in the repo
- Add autocomple/suggestion on typing @<username> on a ticket or a pull-request
  (Eric Barbour)
- Fix the edit link when adding a comment to a ticket via SSE
- Add notifications to issues as we have for pull-requests
- Record in the db the date at which a ticket was closed (Vivek Anand)
- Add the possibility for pagure to rely on external groups provided by the auth
  service
- Add the possibility for pagure to use an SMTP server requiring auth
  (Vyacheslav Anzhiganov)
- Add autocomple/suggestion on typing #<id> for tickets and pull-requests (Eric
  Barbour)
- With creating a README when project's description has non-ascii characters
  (vanzhiganov)
- Add colored label for duplicate status of issues (Vivek Anand)
- Ship working wsgi files so that they can be used directly from the RPM
- Mark the wsgi files provided with the RPM as %%config(noreplace)
- Install the api_key_expire_mail.py script next to the createdb one

* Wed Jun 01 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.2.1-1
- Update to 2.2.1
- Fix showing the inital comment on PR having only one commit (Ryan Lerch)
- Fix diffs not showing for additions/deletions for files under 1000 lines (Ryan
  Lerch)
- Split out the commits page to a template of its own (Ryan Lerch)
- Fix hightlighting the commits tab on commit view
- Fix the fact that the no readme box show on empty repo (Ryan Lerch)

* Tue May 31 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.2-1
- Update to 2.2
- Fix retrieving the log level from the configuration file (Nuno Maltez)
- Rework the labels used when sorting projects (Ankush Behl)
- Fix spelling error in sample config (Bruno)
- Hide the URL to the git repo for issues if these are disabled
- Do not notify about tickets being assigned when loaded from the issue git repo
  (Clément Verna)
- Adjust get_revs_between so that if the push is in the main branch we still get
  the list of changes (Clément Verna)
- Fix display of files moved on both old and new pygit2 (Ryan Lerch)
- Fix changes summary sidebar for older versions of pygit (Ryan Lerch)
- Fix the label on the button to add a new milestone to a project (Lubomír
  Sedlář)
- Allow the roadmap feature to have multiple milestone without dates (Lubomír
  Sedlář)
- Fix the link to switch the roadmap/list views (Lubomír Sedlář)
- Render the emoji when adding a comment to a ticket or PR via SSE (Clément
  Verna)
- Always allow adming to edit/delete comments on issues
- Build Require systemd to get macros defined in the spec file (Bruno)
- Upon creating a ticket if the form already has data, show that data
- Add a readme placeholder for projects without a readme (Ryan Lerch)
- Enable markdown preview on create pull request (Ryan Lerch)
- Make bottom pagination links on project list respect the sorting filter (Ryan
  Lerch)
- Add the ability to create a README when creating a project (Ryan Lerch)
- Try to prevent pushing commits without a parent when there should be one
- Fix the configuration keys to turn off ticket or user/group management for an
  entire instance (Vivek Anand)
- Fix deleting project (propagate the deletion to the plugins tables)
- Do not render the diffs of large added and removed files (more than 1000
  lines) (Ryan Lerch)
- Adjust the UI on the template to add/remove a group or an user to a project in
  the settings page (Ryan Lerch)
- Check if a tag exists on a project before allowing to edit it (skrzepto)

* Fri May 13 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.1.1-1
- Update to 2.1.1
- Do not render the comment as markdown when importing tickets via the ticket
  git repo
- Revert get_revs_between changes made in
  https://pagure.io/pagure/pull-request/941 (Clement Verna)

* Fri May 13 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.1-1
- Update to 2.1
- Fix the milter to get it working (hotfixed in prod)
- Fix the fedmsg hook so that it works fine (hotfixed in prod)
- Fix the path of one of the internal API endpoint
- Pass client_encoding utf8 when connecting to the DB (Richard Marko)
- Do not use client_encoding if using sqlite (Ryan Lerch)
- Allow project names up to 255 characters (Richard Marko)
- Add a spinner showing we're working on retrieve the PR status on the PR page
  (farhaanbukhsh)
- Rework installing and removing git hooks (Clement Verna)
- Rework the summary of the changes on the PR page (Ryan Lerch)
- Improve the description of the priority system (Lubomír Sedlář)
- Fix commit url in the pagure hook (Mike McLean)
- Improve the regex when fixing/relating a commit to a ticket or a PR (Mike
  McLean)
- Improve the description of the pagure hook (Mike McLean)
- Fix the priority system to support tickets without priority
- Fix the ordering of the priority in the drop-down list of priorities
- Ensure the drop-down list of priorities defaults to the current priority
- Adjust the runserver.py script to setup PAGURE_CONFIG before importing pagure
- Remove flashed message when creating a new project
- Add markdown support for making of PR# a link to the corresponding PR
- Include the priority in the JSON representation of a ticket
- Include the priorities in the JSON representation of a project
- Do not update the assignee if the person who commented isn't an admin
- When adding a comment fails, include the comment text in the form if there was
  one
- Add support to remove a group from a project
- Add a roadmap feature with corresponding documentation
- Allow 'kbd' and 'var' html tags to render properly
- Fix deleting a project on disk as well as in the DB
- Allow setting the date_created field when importing ticket from git (Clement
  Verna)
- Strip GPG signature from the release message on the release page (Jan Pokorný)
- Make comment on PR diffs fit the parent, and not overflow horiz (Ryan Lerch)

* Sun Apr 24 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.0.1-1
- Update to 2.0.1
- Fixes to the UPGRADING documentation
- Fix URLs to the git repos shown in the overview page for forks
- Fix the project titles in the html to not start with `forks/`

* Fri Apr 22 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.0-1
- Update to 2.0
- Rework the initial comment of a PR, making it less a comment and more
  something that belong to the PR itself
- Fix showing or not the fork button when editing a comment on an issue or a PR
  and fix the highlighted tab when editing comment of an issue (Oliver
  Gutierrez)
- Fix the count of comments shown on the page listing all the PRs to include
  only the comments and not the notifications (farhaanbukhsh)
- In the settings page explain that API keys are personal (Lubomír Sedlář)
- Rework the fedmsg message sent upon pushing commits, one message per push
  instead of one message per commit
- Mark the page next/previous as disabled when they are (on browse pages)
- Avoid the logout/login loop when logging out
- Support rendering file with a `.markdown` extension
- Fix the layout of the password change branch
- Improve the documentation, add overview graphs, expand the usage section,
  improve the overview description
- Fix checking if the user is an admin of a project or not (which was making the
  user experience confusing as they sometime had the fork button and sometime
  not)
- Fix the pagination on the browse pages when the results are sorted
- Disable the Commit and Files tabs if a repo is new
- Update the pagure logo to look better (Ryan Lerch)
- Allow anyone to fork any project (Ryan Lerch)
- Fix searching on the browse pages by preventing submission of the 'enter' key
  (Ryan Lerch)
- Rework the issue page to be a single, large form allowing to update the
  meta-data and comment in one action and fixing updating the page via SSE
- Turn off the project's documentation by default to empty `Docs` tab leading to
  nothing
- Fill the initial comment with the body of the commit message if the PR only
  has one commit (Ryan Lerch)
- Add a plugin/git hook allowing to disable non fast-forward pushes on a branch
  basis
- Fix asynchronous inline comments in PR by fixing the URL to which the form is
  submitted
- Add a plugin/git hook allowing to trigger build on readthedocs.org upon git
  push, with the possibility to restrict the trigger to only certain branches
- Automatically scroll to the highlighted range when viewing a file with a
  selection (Lubomír Sedlář)
- Indicate the project's creation date in the overview page (Anthony Lackey)
- Clear the `preview` field after adding a comment via SSE
- Adjust the unit-tests for the change in behavior in pygments 2.1.3
- Fix listing all the request when the status is True and do not convert to text
  request.closed_at if it is in fact None
- Improved documentation
- Attempt to fix the error `too many open files` on the EventSource Server
- Add a new param to runserver.py to set the host (Ryan Lerch)
- Fix the of the Docs tab and the Fork button with rounded corners (Pedro Lima)
- Expand the information in the notifications message when a PR is updated (Ryan
  Lerch)
- Fix hidding the reply buttons when users are not authenticated (Paul W. Frields)
- Improve the description of the git hooks (Lubomír Sedlář)
- Allow reply to a notification of pagure and setting the reply email address as
  Cc
- In the fedmsg git hook, publish the username of all the users who authored the
  commits pushed
- Add an activity page/feed for each project using the information retrieved
  from datagrepper (Ryan Lerch)
- Fix showing lightweight tags in the releases page (Ryan Lerch)
- Fix showing the list of branches when viewing a file
- Add priorities to issues, with the possibility to filter or sort them by it in
  the page listing them.
- Add support for pseudo-namespace to pagure (ie: allow one '/' in project name
  with a limited set of prefix allowed)
- Add a new plugin/hook to block push containing commits missing the
  'Signed-off-by' line
- Ensure we always use the default email address when sending notification to
  avoid potentially sending twice a notification
- Add support for using the keyword Merge(s|d) to close a ticket or pull-request
  via a commit message (Patrick Uiterwijk)
- Add an UPGRADING.rst documentation file explaining how to upgrade between
  pagure releases

* Tue Mar 01 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 1.2-1
- Update to 1.2
- Add the possibility to create a comment when opening a pull-request (Clement
  Verna)
- Fix creating PR from a fork directly from the page listing all the PR on the
  main project (Ryan Lerch)
- Color the label showing the issues' status on the issue page and the page
  listing them (Ryan Lerch)
- Add a small padding at the bottom of the blockquote (Ryan Lerch)
- In the list of closed PR, replace the column of the assignee with the date of
  closing (Ryan Lerch)
- Drop font awesome since we no longer use it and compress the png of the
  current logo (Ryan Lerch)
- Drop the svg of the old logo from the source (Ryan Lerch)
- Add descriptions to the git hooks in the settings page (farhaanbukhsh)
- Fix the pagure git hook

* Wed Feb 24 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 1.1.1-1
- Update to 1.1.1
- Fix showing some files where decoding to UTF-8 was failing
- Avoid adding a notification to a PR for nothing
- Show notifications correctly on the PR page when received via SSE

* Tue Feb 23 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 1.1-1
- Update to 1.1
- Sort the release by commit time rather than name (Clerment Verna)
- Add a link to the markdown syntax we support
- Add the possibility to display custom info when creating a new PR
- Improve the title of the issue page
- Make the ssh_info page more flexible so that we can add new info more easily
- Add the possibility to resend a confirmation email when adding a new email
  address
- Encode the email in UTF-8 for domain name supporting it
- Add a button to easily change your avatar in your settings' page (Clement
  Verna)
- Expand our markdown processor to support implicit linking to both PR and
  issues
- Fix running the unit-tests on F23
- Fix deleting in the UI branches containing a slash ('/') in their name
- Add the possibility to always have a merge commit when merging a PR
- Add the project's avatar to the list in front page when authenticated
- Make the dependency on flask-fas-openid (part of python-fedora) optional
- Prevent our customized markdown to create link on foo.com if it doesn't start
  with {f,ht}tp(s) (Clement Verna)
- Bring back the delete ticket button (Ryan Lerch)
- Add the possibility to notify someone when it is mentioned in a comment via
  @username
- Fix setting the default value of the web-hook setting and its display in the
  settings page
- Add the possibility to have templates for the issues
- Add a button on the doc page to open it in a new tab
- Add the concept of notifications on PR allowing to indicate when a PR is
  updated or rebased
- Fix allowing people with non-ascii username to merge PR with a merge commit
- Add the possibility to theme your pagure instance and customized its layout at
  will
- Add the possibility to always see inline-comments even if the file was changed
  since
- Improve the error message given to the user upon error 500 (Patrick Uiterwijk)
- Stop relying on pygit2 to determine if a file is a binary file or not and
  instead use the python library binaryornot
- Store in the DB the identifier of the tree when an inline comment is made to a
  PR, this way it will be simpler to figure out a way to add the context of this
  comment either by email on in the UI
- Add styling to blockquotes so that we see what is the quote and what is the
  answer when replying to someone
- Prevent users from adding again an email pending confirmation
- Fix the preview box for long comment (Ryan Lerch)
- Add the possibility to sort the projects when browsing them (Ryan Lerch)

* Thu Feb 04 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 1.0.2-1
- Update to 1.0.2
- Rework the PR page (Ryan Lerch)
- Add ssh_info to blacklist in default config (Ryan Lerch)
- Restyle the ssh_info page (Ryan Lerch)
- Fix hiding the preview pane when creating an issue (Ryan Lerch)
- Indicate the number of comments on the PR when listing them (Ryan Lerch)
- Fix showing the links to issues when previewing a comment
- Ensure some more that the page number isn't below 1
- Do not show the edit and delete buttons to everyone when adding a comment via
  SSE
- Update the requirements.txt for a missing dependency on Ubuntu (vanzhiganov)
- Improving sorting the release tags in the release page (Clement Verna)

* Mon Feb 01 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 1.0.1-1
- Update to 1.0.1
- Improve the fork list (Ryan Lerch)
- Make sure the images on comments do not exceed the size of the comment
  box/area (Ryan Lerch)
- Improve the page listing all issues (Ryan Lerch)
- Include the project information when sending a fedmsg message about editing a
  comment
- Allow <span> tags in rst files so that the README shows fine
- Fix linking directly to a specific comment in a PR
- Fix adding comment in a PR via SSE
- Fix updating issue information via SSE
- Fix the reply buttons on the issue page
- Remove the choice for a status when creating a new ticket (Farhaandukhsh)
- Fix deleting a branch from the UI
- Make the cards have rounded corners (Sayan Chowdhury)
- Fix showing the description of form field (Vivek Anand)
- Fix checking if the passwords added are the same (for local accounts)
  (Vivek Anand)
- Fix displaying emojis when previewing a comment on a ticket (Clement Verna)
- Add support for emojis when creating a new ticket (Clement Verna)

* Wed Jan 27 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 1.0-1
- Update to 1.0
- Entirely new UI thanks to the hard work on Ryan Lerch
- Add the possibility to edit comments on PR/Tickets (and the option to disable
  this) (farhaanbukhsh)
- Add the number of open Tickets/PR on the project's menu
- Also allow PRs to be closed via a git commit message (Patrick Uiterwijk)
- Disable issues and PR on forks by default (Vivek Anand)
- Fix deleting the temporary folders we create
- Un-bundle flask_fas_openid (requires python-fedora 0.7.0 or higher
- Add support for an openid backend (ie same thing as FAS but w/o the FPCA
  enforcing)
- Add support to view rst/markdown files as html directly inline (default) or as
  text (Yves Martin)
- Change the encryption system when using pagure with local auth to not be
  time-sensitive and be stronger in general (farhaanbukhsh)
- Change the size of the varchar from 256 to 255 for a better MySQL support
- Add support for pagure to work behind a reverse proxy
- Rename the cla_required decorator to a more appropriate login_required
- Show the in the front page and the page listing all the pull-requests the
  branch for which a PR can be opened
- Rework the avatar to not rely on the ones associated with id.fedoraproject.org
- Add support to high-light a section of code in a PR and show the diff
  automatically if there is such selection

* Mon Dec 14 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.36-1
- Update to 0.1.36
- Add the ssh info on the front page if the repo is empty
- Make the code handling exception be python3 compatible
- Make pagure compatible with F23 (ie: pygit2 0.23.0)
- Fix pagination when rendering the repo blocks (Gaurav Kumar)
- Make the SHOW_PROJECTS_INDEX list what should be showing in the index page
- Adjust pagure to work on recent version of psutils as well as the old one
- Added 'projects' to the blacklisted list of projects (Gaurav Kumar)
- Removed delete icons for non group members on the group info page (Gaurav
  Kumar)
- Fixed forbidden error for PR title editing (Gaurav Kumar)

* Mon Nov 30 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.35-1
- Update to 0.1.35
- Fix the web-hook server by preventing it to raise any exception (rather log
  the errors)

* Mon Nov 30 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.34-1
- Update to 0.1.34
- Fix the encoding of the files we're displaying on the UI
- Fix commenting on the last line of a diff
- Fix returning error message from the internal API (shows the PR as conflicting
  then)
- Fix stacktrace encountered in some repo if the content of a folder is empty
  (or is a git submodule)
- Split the web-hooks into their own server
- If you try to fork a forked project, redirect the user to the fork
- Show the repo from and repo to when opening a new PR
- Add the pagination links at the bottom of the repo list as well
- Add the groups to the pool of users to notify upon changes to a project
- Hide private repo from user who do not have commit access

* Fri Nov 20 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.33-1
- Update to 0.1.33
- Prevent project with a name starting with a non-alphanumerical character
  (Farhaanbukhsh)
- Ensure we appropriately set the private flag when creating an issue
- Add an activity graph on the user profile using datagrepper
- Sometime the identified we get is a Tag, not a commit (fixes traceback
  received by email)
- Order the PR from the most recent to the oldest
- Fix the patch view of a PR when we cannot find one of the commit (fixes
  traceback received by email)
- Allow user that are not admin to create a remote pull-request
- Fix closing the EV server by calling the appropriate variable
- Fix generating the diff of remote pull-request

* Fri Nov 13 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.32-1
- Update to 0.1.32
- Fix the example configuration file
- Make pagure work on MySQL
- Hide sections on the front page only if the user is logged out
- Fix the release page where sometime tags are commits
- Escape the raw html in markdown
- Decode the bytes returned by pygit2 to try to guess if the content is a text
  or not
- Fix the 'Clear' button on the pull-request page (farhaanbukhsh)
- Fix installing pagure in a venv
- Fix uploading images when editing the first comment of a ticket
- Let the author of the merge commit be the user doing the merge
- Suggest the title of the PR only if it has one and only one commit in
- Do not hide sections on the user page if we set some to be hidden on the front
  page
- Forward the head to the commits page to fix the pull-request button
- Ensure we create the git-daemon-export-ok when forking a repo (fixes cloning
  over https)
- Add instructions on how to get pagure working in a venv (Daniel Mach)
- Improve the way we retrieve and check pygit2's version (Daniel Mach)

* Tue Oct 13 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.31-1
- Forward the bail_on_tree boolean when iterating so that we know how to behave
  when we run into a git tree (where we expected a git blob)
  -> fixes error received by email

* Tue Oct 13 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.30-1
- Fix error received by email by checking the right variable if it is a git tree
  or a git blob
- Unless we explicitly accept all images tag, always filter them (fixes
  attaching images to a ticket)

* Tue Oct 13 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.29-1
- Use monospace fonts for online editing as well as comment on tickets and
  pull-requests
- Fix online editing of symlinked files (such as the README)
- Handle potential error when converting from rst to html

* Mon Oct 12 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.28-1
- Update to 0.1.28
- Fix the call to noJS() in the pull-request template to avoid crashing
- Improve the runserver script in the sources
- Fix the projects pagination on the index page
- Create the git-daemon-export-ok file upon creating a new project/git
- Use first line of commit message for PR title when only one commit (Maciej
  Lasyk)
- Show the tag message near the tag in the release page
- Set the default_email when creating a local user account

* Mon Oct 05 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.27-1
- Update to 0.1.27
- Skip writing empty ssh keys on disc
- Regenerate authorized_keys file on ssh key change (Patrick Uiterwijk)

* Mon Oct 05 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.26-1
- Update to 0.1.26
- Let admins close PRs as well

* Mon Oct 05 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.25-1
- Update to 0.1.25
- Improve the documentation (especially the part about configuring pagure and
  all the options the configuration file supports)
- Remove the two trailing empty lines when showing a file online
- Add a link on the issue list to be able to filter all the unassigned issues
- Rework the layout of the pull-request page
- Rework the commit list in the PR page to allow showing the entire commit
  message
- Let any user create remote pull-request otherwise what's the point?
- Add the possibility to edit the title of a pull-request
- Add a page listing all the pull-requests of an user (opened by or against)
- Add support for multiple ssh-keys (Patrick Uiterwijk)
- Ensure the authorized_keys file is generated by gitolite (Patrick Uiterwijk)
- Fix the regex for @<username>
- Improve the display of renamed files in PR
- Add option to disable entirely the user/group management from the UI
- Add an updated_on field to Pull-Request
- Add an closed_at field to Pull-Request
- Allow the submitter of a PR to close it (w/o merging it)
- Disable editing a pull-request when that one is closed/merged
- Add option to hide by default a part of the index page (ie: all the repos, the
  user's repos or the user's forks)
- Drop the csrf_token from the error emails sent to the admins

* Tue Sep 08 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.24-1
- Update to 0.1.24
- Fix changelog to add the -release
- Block the <img> tag on titles
- Better fedmsg notifications (for example for new branches or rebase)
- Support uploading multiple files at once
- Add a load_from_disk utility script to the sources
- Fix indentation to the right on very long pull-request

* Sun Aug 30 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.23-1
- Update to 0.1.23
- Return a 404 error if we can't find the doc repo asked
- Fix for #106 Allow setting the default branch of the git repo and in the UI
  (Ghost-script)
- Improve unit-tests suite
- Add a global boolean to disable entirely tickets on all projects of a pagure
  instance (with no way to re-set them per project)
- Do display uploading a tarball if it is not entirely configured
- Ensure we do not offer to reply by email if the milter is not set up
- Ensure there is no new line character on the msg-id and improve logging in the
  milter
- Add a configuration key to globally disable creating projects
- Add a configuration key to globally disable deleting projects
- Add the possibility to search projects/users
- Drop links to the individual commits in a remote pull-request
- Input that are cleaned via the noJS filter are safe to be displayed (avoid
  double HTML escaping)
- When writing the authorized_key file, encode the data in UTF-8
- Makes page title easier to find in multi-tab cases (dhrish20)
- Fix authorized_keys file creation (Patrick Uiterwijk)
- Honor also symlinked README's in repo overview (Jan Pakorný)
- Fix the patch generation for remote PR
- Fix showing the comment's preview on the pull-request page
- Fix bug in checking if a PR can be merged

* Fri Aug 07 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.22-1
- Update to 0.1.22
- Adjust the README to the current state of pagure
- Rework how we integrate our custom tags into markdown to avoid the infinite
  loop we run into once in a while

* Wed Aug 05 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.21-1
- Update to 0.1.21
- Make SSH protocol explicit for SSH URLs (Till Maas)
- Adjust the documentation (layout and content)
- Rework the doc server to allow showing html files directly
- Fix installing the pagure hook correctly (tickets and requests)
- Give proper attribution to the pagure logo to Micah Deen in the documentation
- Increase pull request text field lengths to 80 (Till Maas)
- Fix who can open a remote PR and the check that the repo allows PR
- If there is no commit and no content, it means we didn't find the file: 404

* Wed Jul 29 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.20-1
- Update to 0.1.20
- Include the tags in the JSON representation of a project
- Add the ability to open a pull-request from a git repo not hosted on pagure
- Fix pagination when browsing the list of commits
- Fix the fork button when viewing the Settings of a project
- Adjust the example apache configuration file
- Add a favicon with pagure's logo
- Fix asynchronous commentting on pull-requests
- Start working on some documentation on how to install pagure
- Do no flash messages when a comment is submitted via javascript (ie: async)
- Do not blink the tittle of the page if the page is already on focus
- Retrieve ssh key from FAS and set it up in pagure if none is currently set-up
- Fix anchors for comments on the pull-request pages
- Fix checking the merge status of a PR when user is not logged in

* Mon Jul 20 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.19-1
- Update to 0.1.19
- Prettify the JSON stored in the git for tickets/requests... (Simo Sorce)
- Use the project name as subject tag in the notifications sent (Simo Sorce)
- Add an X-pagure header with either the pagure instance or the project name
- Reset the merge status of all the open PR when one is merged
- Add a second server listing the number of connections opened on the first
  eventsource server
- Log the info instead of printing them in the eventsource server
- Split the documentation to a different wsgi application to avoid any risk of
  cross-site forgery
- Fix the JS logic when adding a tag or a dependency to avoid having duplicates
  in the input field
- Allow deleting a git branch of a project via the UI
- Include the font-awesome in the source rather than relying on an external cdn
- Do not try to connect to the eventsource server if we're not viewing a
  pull-request
- Fix showing the first comment made on a PR via the eventsource server
- Fix showing the git URLs in the doc server
- Much better API documentation (Lei Yang)
- Handle showing closed PR that were not merged
- Fix refreshing the UI of private tickets via the eventsource (making calls to
  the API to get the info while only getting what changed via the SSE)
- Fix the anchor links in the API documentation
- Blink the tab upon changes in the page
- Ensure we close both SSE server when stopping pagure_ev
- Let the HTML form trigger if we did not connect to the EV server successfully
- The admins of a repo are anyone with commit access to the repo, directly or
  via a group
- Order the project by names in the front page (instead of creation date)
- Add the ability to tag a project
- Fix the fedmsg_hook when there are only deletions or only additions
- Add a new API endpoint allowing to search projects (by name, author, tag ...)
- Make pagure compatible with pygit 0.22.0
- Adjust unit-tests for all these changes

* Mon Jun 22 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.18-1
- Update to 0.1.18
- Fix the eventsource server for CORS
- Fix showing/checking the merge status of a PR

* Mon Jun 22 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.17-1
- Update to 0.1.17
- Fix for missing docs of API issue add comment (Kunaal Jain)
- Fix the systemd init file
- Be more careful about the URL specified, it may be of the wrong format in the
  eventsource server
- Allow configuring the port where the event source server runs in the
  configuration
- Fix bug in filter_img_src introduced with its moved to the backend library

* Thu Jun 18 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.16-1
- Update to 0.1.16
- Clone all the remote branches when cloning a project
- Allow online editing to a new branch or any of the existing ones
- Allow the <hr /> html tags in markdown
- Add eventsource support in the ticket and pull-request pages

* Tue Jun 16 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.15-1
- Update 0.1.15
- Use a monospace font for the commit hash
- Remove duplicated "commit" id in the HTML (causing a graphical bug in the
  commit page)
- Secure the input using the no_js filter instead of relying on a restrictive
  regex for PR and issue titles
- Support ',' in the tags field since it's required to specify multiple tags

* Fri Jun 12 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.14-1
- Update to 0.1.14
- Remove all new lines characters from the ssh key uploaded
- Adjust the URL in the footer to point to https://pagure.io/pagure
- Fix displaying the time of a comment
- Forbid the use of spaces in group name
- Do not get the list of not-merged commits if there is only 1 branch in the
  repo
- Display the error message if pagure.lib.add_group raises an exception
- Add a new setting enforcing that all commits in a PR are signed-off by their
  author
- Enforce that all commits are signed-off by the author if the repo is
  configured for this
- Also check for the signed-off status before merging a pull-request
- Adjust online-editing to allow specifying which email address to use in the
  commit
- Add an avatar_email field to projects
- Change the PullRequest's status from a Boolean to a Text restricted at the DB
  level (Allows to distinguish Open/Merged/Closed)
- Show in the pull-request view who merged the pull-request
- Specify who closed the pull-request in the API output
- Catch GitError when merging and checking merge status of a PR
- Hide the form to create pull-requests if the user is not an admin of the repo
- Replace the Pull-Request button by a Compare button if the user it not a repo
  admin
- Set the title of the tab as URL hash to allow directly linking to it
- Adjust the API to be able to distinguish API authentication and UI
  authentication
- Fix API documentation to create new issues
- Drop the status from the requirements to open a new issue via the API
- Expand the list of blacklisted project names
- Have the code tags behave like pre tags (html tags)
- Allow project to specify an URL and display it on their page
- Strip the ssh keys when writing them to the authorized_keys file
- Disable javascript in all the markdown fields
- Validate early the input submitted in the forms (using more or less strict
  regex)
- If the session timed-out, redirect to the setting page after authentication
  and inform the user that the action was canceled
- Catch PagureException when adjusting the project's settings
- Redirect the /api endpoint to the api documentation place
- Fix how is retrieved the list of emails to send the notification to
- Sanitize the html using bleach to avoid potential XSS exploit
- Do not give READ access to everyone on the tickets and pull-requests repos to
  avoid leaking private tickets
- Adjust the unit-tests for all these changes

* Fri Jun 05 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.13-1
- Update to 0.1.13
- Do not show the edit button if the user cannot edit the file
- Fix who is allowed to drop comments
- Fix showing the drop comment button on issue comments
- Fix creating the pull-request for fast people like @lmacken
- Display the target of the PR as well as the origin in the PR page
- Limit the size of the lists on the front page

* Fri Jun 05 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.12-1
- Update to 0.1.12
- Fix the URL where the sources upload are done
- Upload the new sources under the project's name (be it project or
  user/project)

* Fri Jun 05 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.11-1
- Update to 0.1.11
- Another fix for the fedmsg_hook git hook
- Adjust how we display the README page to avoid XSS there as well
- Add the possibility to disable plugins via the configuration file
- Present the git tags in the UI
- As soon as the API user present a token, validate it or not, even if the
  endpoint would work without token
- Integrate alembic for DB scheme migration
- Cache the PR's merge status into the DB
- Only people with access to the project can add/remove API token
- Make the unit-tests run on bare repos as in prod
- First stab at online editing
- Simplify the API output to drop the project's settings where it doesn't
  make sense
- First stag at allowing upstream to upload their release to pagure
- Fix merging a PR into another branch than master
- Reduce code duplication when checking if a PR can be merged or merging it
- Code style clean-up

* Tue Jun 02 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.10-1
- Update to 0.1.10
- Add support for URL ending with a trailing slash where it makes sense (so
  we support both with and without trailing slash)
- Fix XSS issue by disabling <script> tags in the documentation pages
- Expend the unit-test suite for the api.project controller
- Add the possibility for 3rd party apps to 'flag' a pull-request with for
  example the result of a build
- Handle the situation where there are multiple branch of the same name in
  the same repo
- Fix the color of the link on hover when displayed within a tab view
  (for example in the PR pages)
- Redirect the user to the pull-request created after its the creation
- Do not leak emails over fedmsg
- Fix the fedmsg_hook plugin

* Fri May 29 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.9-1
- Update to 0.1.9
- Initial API work
- Document the initial API
- Fix the CSS to present the links correctly
- Add new API endpoint to list the git tags of a project
- Ensure the DB is updated regarding the start and stop commits before merging

* Wed May 27 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.8-1
- Update 0.1.8
- Add the possibility to do Asynchronous in-line comment posting
  (Patrick Uiterwijk)
- Handle the situation where the branch asked is not found in the git repo
- Handle the situation where we cannot find a desired commit
- Do not display a value in the settings page if there are none
- Rework the pull-request view to move the list of commits into a tab
- Make email sending optional (Patrick Uiterwijk)

* Fri May 22 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.7-1
- Update to 0.1.7
- Drop debugging code on the milter and the hooks
- Adjust the search_issues method to support filter for some tags, excluding
  some others (for example ?tags=easfix&tags=!0.2)
- Support groups when searching an user's projects (ie: finding the projects an
  user has access to via the group their are in)
- Do not load the git repo from the FS when loading an user's page
- Present and document the SSH keys in a dedicated documentation page

* Wed May 20 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.6-1
- Update to 0.1.6
- Fix sending notification emails to multiple users, avoid sending private into
  to all of them

* Tue May 19 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.5-1
- Update to 0.1.5
- Bug fix on the milter and the internal API endpoint

* Tue May 19 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.4-1
- Update to 0.1.4
- Fix loading requests and tickets from git (allows syncing projects between
  pagure instances)
- Add to the template .wsgi file a way to re-locate the tmp folder to work
  around a bug in libgit2
- Fix unit-tests suite
- Adjust the spec file to install all the files required for the milters
- Fix the `View` button on the pull-request pages

* Wed May 13 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.3-1
- Update to 0.1.3
- Add support for gitolite3
- Fix unit-tests suite to work on jenkins

* Sat May 09 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.2-2
- Fix the Requires on the milter subpackage (adding: post, preun and postun)
- Add systemd scriptlet to restart the service gracefully
- Use versioned python macro (py2)
- Ship the license in the milter subpackage as well
- Use the %%license macro

* Thu May 07 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.2-1
- Update to 0.1.2
- Fix bug in the fedmsg hook file (Thanks Zbigniew Jędrzejewski-Szmek)

* Wed May 06 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1.1-1
- Update to 0.1.1
- Port to python-munch and list it in the dependencies
- Fix exporting patch when they contain unicode characters or accent
- After creating an issue, user is brought back to the new issue page
- Fix unit-tests
- Stop the pagure hook if the user is deleting a branch (no need to run through
  all the commits of that branch)
- Fix the requirements.txt file (Sayan Chowdhury)
- Fix the tree page to show the commit sha on its proper line (Sayan Chowdhury)
- Fix typo in the form of some of the plugin (Sayan Chowdhury)
- Improve the README (Sayan Chowdhury)
- Fix highlighting the commits tab when accessing it (Sayan Chowdhury)

* Mon May 04 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.1-1
- First official release: 0.1

* Thu Apr 02 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.0-1.20150402
- Cut a RPM for testing on Thu Apr 2nd 2015

* Wed Oct 08 2014 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.0-1.20141008
- Initial packaging work for Fedora


code:
#-*- coding: utf-8 -*-

# The three lines below are required to run on EL6 as EL6 has
# two possible version of python-sqlalchemy and python-jinja2
# These lines make sure the application uses the correct version.
import __main__
__main__.__requires__ = ['SQLAlchemy >= 0.8', 'jinja2 >= 2.4']
import pkg_resources

# Set the environment variable pointing to the configuration file
import os
os.environ['PAGURE_CONFIG'] = '/etc/pagure/pagure.cfg'

# Set the environment variable if the tmp folder needs to be moved
# Might be necessary to work around bug in libgit2:
# refs: https://github.com/libgit2/libgit2/issues/2965
# and   https://github.com/libgit2/libgit2/issues/2797
os.environ['TEMP'] = '/var/tmp/'

# The following is only needed if you did not install pagure
# as a python module (for example if you run it from a git clone).
#import sys
#sys.path.insert(0, '/path/to/pagure/')

# The most import line to make the wsgi working
from pagure import APP as application
#application.debug = True


code:
#!/usr/bin/env python2
# -*- coding: utf-8 -*-

# Milter calls methods of your class at milter events.
# Return REJECT,TEMPFAIL,ACCEPT to short circuit processing for a message.
# You can also add/del recipients, replacebody, add/del headers, etc.

import base64
import email
import hashlib
import os
import urlparse
import StringIO
import sys
import time
from socket import AF_INET, AF_INET6
from multiprocessing import Process as Thread, Queue

import Milter
import requests

from Milter.utils import parse_addr

logq = Queue(maxsize=4)

if 'PAGURE_CONFIG' not in os.environ \
        and os.path.exists('/etc/pagure/pagure.cfg'):
    os.environ['PAGURE_CONFIG'] = '/etc/pagure/pagure.cfg'

import pagure

def get_email_body(emailobj):
    ''' Return the body of the email, preferably in text.
    '''
    body = None
    if emailobj.is_multipart():
        for payload in emailobj.get_payload():
            body = payload.get_payload()
            if payload.get_content_type() == 'text/plain':
                break
    else:
        body = emailobj.get_payload()

    enc = emailobj['Content-Transfer-Encoding']
    if enc == 'base64':
        body = base64.decodestring(body)

    return body

def clean_item(item):
    ''' For an item provided as <item> return the content, if there are no
    <> then return the string.
    '''
    if '<' in item:
        item = item.split('<')[1]
    if '>' in item:
        item = item.split('>')[0]

    return item

class PagureMilter(Milter.Base):

    def __init__(self):  # A new instance with each new connection.
        self.id = Milter.uniqueID()  # Integer incremented with each call.
        self.fp = None

    def log(self, message):
        print(message)
        sys.stdout.flush()

    def envfrom(self, mailfrom, *str):
        self.log("mail from: %s  -  %s" % (mailfrom, str))
        self.fromparms = Milter.dictfromlist(str)
        # NOTE: self.fp is only an *internal* copy of message data.  You
        # must use addheader, chgheader, replacebody to change the message
        # on the MTA.
        self.fp = StringIO.StringIO()
        self.canon_from = '@'.join(parse_addr(mailfrom))
        self.fp.write('From %s %s\n' % (self.canon_from, time.ctime()))
        return Milter.CONTINUE

    @Milter.noreply
    def header(self, name, hval):
        ''' Headers '''
        # add header to buffer
        self.fp.write("%s: %s\n" % (name, hval))
        return Milter.CONTINUE

    @Milter.noreply
    def eoh(self):
        ''' End of Headers '''
        self.fp.write("\n")
        return Milter.CONTINUE

    @Milter.noreply
    def body(self, chunk):
        ''' Body '''
        self.fp.write(chunk)
        return Milter.CONTINUE

    @Milter.noreply
    def envrcpt(self, to, *str):
        rcptinfo = to, Milter.dictfromlist(str)
        print rcptinfo

        return Milter.CONTINUE

    def eom(self):
        ''' End of Message '''
        self.fp.seek(0)
        msg = email.message_from_file(self.fp)

        msg_id = msg.get('In-Reply-To', None)
        if msg_id is None:
            self.log('No In-Reply-To, keep going')
            return Milter.CONTINUE

        # Ensure we don't get extra lines in the message-id
        msg_id = msg_id.split('\n')[0].strip()

        self.log('msg-ig %s' % msg_id)
        self.log('To %s' % msg['to'])
        self.log('Cc %s' % msg.get('cc'))
        self.log('From %s' % msg['From'])

        # Ensure the user replied to his/her own notification, not that
        # they are trying to forge their ID into someone else's
        salt = pagure.APP.config.get('SALT_EMAIL')
        m = hashlib.sha512('%s%s%s' % (msg_id, salt, clean_item(msg['From'])))
        email_address = msg['to']
        if 'reply+' in msg.get('cc', ''):
            email_address = msg['cc']
        if not 'reply+' in email_address:
            self.log(
                'No valid recipient email found in To/Cc: %s'
                % email_address)
        tohash = email_address.split('@')[0].split('+')[-1]
        if m.hexdigest() != tohash:
            self.log('hash: %s' % m.hexdigest())
            self.log('tohash:   %s' % tohash)
            self.log('Hash does not correspond to the destination')
            return Milter.CONTINUE

        if msg['From'] and msg['From'] == pagure.APP.config.get('FROM_EMAIL'):
            self.log("Let's not process the email we send")
            return Milter.CONTINUE

        msg_id = clean_item(msg_id)

        if msg_id and '-ticket-' in msg_id:
            self.log('Processing issue')
            return self.handle_ticket_email(msg, msg_id)
        elif msg_id and '-pull-request-' in msg_id:
            self.log('Processing pull-request')
            return self.handle_request_email(msg, msg_id)
        else:
            self.log('Not a pagure ticket or pull-request email, let it go')
            return Milter.CONTINUE

    def handle_ticket_email(self, emailobj, msg_id):
        ''' Add the email as a comment on a ticket. '''
        uid  = msg_id.split('-ticket-')[-1].split('@')[0]
        parent_id = None
        if '-' in uid:
            uid, parent_id = uid.rsplit('-', 1)
        if '/' in uid:
            uid = uid.split('/')[0]
        self.log('uid %s' % uid)
        self.log('parent_id %s' % parent_id)

        data = {
            'objid': uid,
            'comment': get_email_body(emailobj),
            'useremail': clean_item(emailobj['From']),
        }
        url = pagure.APP.config.get('APP_URL')

        if url.endswith('/'):
            url = url[:-1]
        url = '%s/pv/ticket/comment/' % url
        req = requests.put(url, data=data)
        if req.status_code == 200:
            self.log('Comment added')
            return Milter.ACCEPT
        self.log('Could not add the comment to pagure')
        return Milter.CONTINUE

    def handle_request_email(self, emailobj, msg_id):
        ''' Add the email as a comment on a request. '''
        uid  = msg_id.split('-pull-request-')[-1].split('@')[0]
        parent_id = None
        if '-' in uid:
            uid, parent_id = uid.rsplit('-', 1)
        if '/' in uid:
            uid = uid.split('/')[0]
        self.log('uid %s' % uid)
        self.log('parent_id %s' % parent_id)

        data = {
            'objid': uid,
            'comment': get_email_body(emailobj),
            'useremail': clean_item(emailobj['From']),
        }
        url = pagure.APP.config.get('APP_URL')

        if url.endswith('/'):
            url = url[:-1]
        url = '%s/pv/pull-request/comment/' % url
        req = requests.put(url, data=data)

        return Milter.ACCEPT

def background():
    while True:
        t = logq.get()
        if not t: break
        msg,id,ts = t
        print "%s [%d]" % (time.strftime('%Y%b%d %H:%M:%S',time.localtime(ts)),id),
        # 2005Oct13 02:34:11 [1] msg1 msg2 msg3 ...
        for i in msg: print i,
        print

def main():
    bt = Thread(target=background)
    bt.start()
    socketname = "/var/run/pagure/paguresock"
    timeout = 600
    # Register to have the Milter factory create instances of your class:
    Milter.factory = PagureMilter
    print "%s pagure milter startup" % time.strftime('%Y%b%d %H:%M:%S')
    sys.stdout.flush()
    Milter.runmilter("paguremilter", socketname, timeout)
    logq.put(None)
    bt.join()
    print "%s pagure milter shutdown" % time.strftime('%Y%b%d %H:%M:%S')

if __name__ == "__main__":
    main()


code: d /var/run/pagure 0755 postfix postfix


code:
[Unit]
Description=Pagure SMTP filter (Milter) Daemon (talk to postfix over a socket)
After=postfix.target
Documentation=https://github.com/pypingou/pagure

[Service]
ExecStart=/usr/bin/python2 /usr/share/pagure/comment_email_milter.py
Type=simple
User=postfix
Group=postfix
Restart=on-failure

[Install]
WantedBy=multi-user.target


code:
#!/usr/bin/env python
# EASY-INSTALL-ENTRY-SCRIPT: 'nose==0.10.4','console_scripts','nosetests'
__requires__ = ['nose>=0.10.4', 'SQLAlchemy >= 0.7', 'jinja2 >= 2.4']
import sys
from pkg_resources import load_entry_point

sys.exit(
   load_entry_point('nose>=0.10.4', 'console_scripts', 'nosetests')()
)

path: nosetests