#2255 Add the ability to watch issues and PRs, commits, or both on a project
Merged 6 years ago by pingou. Opened 6 years ago by mprahl.
Unknown source watch-granularity  into  master

@@ -0,0 +1,74 @@

+ """Add granularity to watching repos

+ 

+ Revision ID: d4d2c5aa8a0

+ Revises: 4255158a6913

+ Create Date: 2017-04-28 14:39:09.746953

+ 

+ """

+ 

+ # revision identifiers, used by Alembic.

+ revision = 'd4d2c5aa8a0'

+ down_revision = '4255158a6913'

+ 

+ from alembic import op

+ import sqlalchemy as sa

+ 

+ # A helper table that is a hybrid with both states. This is used for data

+ # migrations later on.

+ watcher_helper = sa.Table(

+     'watchers',

+     sa.MetaData(),

+     sa.Column('id', sa.Integer, primary_key=True),

+     sa.Column('watch_issues', sa.Boolean),

+     sa.Column('watch_commits', sa.Boolean),

+     sa.Column('watch', sa.Boolean),

+ )

+ 

+ 

+ def upgrade():

+     op.add_column('watchers', sa.Column('watch_commits', sa.Boolean(),

+                                         nullable=True))

+     op.add_column('watchers', sa.Column('watch_issues', sa.Boolean(),

+                                         nullable=True))

+     # This section is to update the `watch_issues` and `watch_commits` columns

+     # with the value of `watch`

+     connection = op.get_bind()

+     for watcher in connection.execute(watcher_helper.select()):

+         connection.execute(

+             watcher_helper.update().where(

+                 watcher_helper.c.id == watcher.id

+             ).values(

+                 watch_issues=watcher.watch,

+                 watch_commits=False

+             )

+         )

+ 

+     with op.batch_alter_table('watchers') as b:

+         # Set nullable to False now that we've set values

+         b.alter_column('watch_issues', nullable=False)

+         b.alter_column('watch_commits', nullable=False)

+         # Remove the watch column

+         b.drop_column('watch')

+ 

+ 

+ def downgrade():

+     op.add_column('watchers', sa.Column('watch', sa.BOOLEAN(), nullable=True))

+ 

+     # This section is to update the `watch` column with the value of

+     # `watch_issues`

+     connection = op.get_bind()

+     for watcher in connection.execute(watcher_helper.select()):

+         connection.execute(

+             watcher_helper.update().where(

+                 watcher_helper.c.id == watcher.id

+             ).values(

+                 watch=watcher.watch_issues

+             )

+         )

+ 

+     with op.batch_alter_table('watchers') as b:

+         # Set nullable to False now that we've set values

+         b.alter_column('watch', nullable=False)

+         # Drop the added columns

+         b.drop_column('watch_issues')

+         b.drop_column('watch_commits')

@@ -22,8 +22,7 @@

  import logging

  import os

  import traceback

- 

- import requests

+ import inspect

  import trollius

  import trollius_redis

  

@@ -20,6 +20,7 @@

  import json

  import logging

  import os

+ from sqlalchemy.exc import SQLAlchemyError

  

  import trollius

  import trollius_redis
@@ -41,7 +42,7 @@

  def handle_messages():

      ''' Handles connecting to redis and acting upon messages received.

      In this case, it means logging into the DB the commits specified in the

-     message for the specified repo.

+     message for the default repo or sending commit notification emails.

  

      The currently accepted message format looks like:

  
@@ -61,7 +62,9 @@

              "b7b4059c44d692d7df3227ce58ce01191e5407bd",

              "f8d0899bb6654590ffdef66b539fd3b8cf873b35",

              "9b6fdc48d3edab82d3de28953271ea52b0a96117"

-           ]

+           ],

+           "branch": "master",

+           "default_branch": "master"

          }

  

      '''
@@ -88,6 +91,8 @@

  

          commits = data['commits']

          abspath = data['abspath']

+         branch = ['data']['branch']

+         default_branch = ['data']['default_branch']

          repo = data['project']['name']

          username = data['project']['username']['name'] \

              if data['project']['parent'] else None
@@ -96,7 +101,7 @@

          session = pagure.lib.create_session(pagure.APP.config['DB_URL'])

  

          _log.info('Looking for project: %s%s of %s',

-                  '%s/' % namespacerepo if namespace else '',

+                  '%s/' % namespace if namespace else '',

                   repo, username)

          project = pagure.lib._get_project(

              pagure.SESSION, repo, user=username, namespace=namespace)
@@ -109,8 +114,14 @@

  

          _log.info('Processing %s commits in %s', len(commits), abspath)

  

-         pagure.lib.git.log_commits_to_db(

-             session, project, commits, abspath)

+         # Only log commits when the branch is the default branch

+         if branch == default_branch:

+             pagure.lib.git.log_commits_to_db(

+                 session, project, commits, abspath)

+ 

+         # Notify subscribed users that there are new commits

+         pagure.lib.notify.notify_new_commits(

+             abspath, project, branch, commits)

  

          try:

              session.commit()

file modified
+6 -11
@@ -426,16 +426,6 @@

      if justlogedout:

          flask.session['_justloggedout'] = None

  

-     def is_watching(reponame, username=None, namespace=None):

-         watch = False

-         if authenticated():

-             watch = pagure.lib.is_watching(

-                 SESSION, flask.g.fas_user,

-                 reponame,

-                 repouser=username,

-                 namespace=namespace)

-         return watch

- 

      new_user = False

      if flask.session.get('_new_user'):

          new_user = True
@@ -446,7 +436,6 @@

          admin=user_admin,

          authenticated=authenticated(),

          forkbuttonform=forkbuttonform,

-         is_watching=is_watching,

          new_user=new_user,

      )

  
@@ -502,6 +491,12 @@

          flask.g.repo_user = is_repo_user(flask.g.repo)

          flask.g.branches = sorted(flask.g.repo_obj.listall_branches())

  

+         repouser = flask.g.repo.user.user if flask.g.repo.is_fork else None

+         fas_user = flask.g.fas_user if authenticated() else None

+         flask.g.repo_watch_levels = pagure.lib.get_watch_level_on_repo(

+             SESSION, fas_user, flask.g.repo.name,

+             repouser=repouser, namespace=namespace)

+ 

      items_per_page = APP.config['ITEM_PER_PAGE']

      flask.g.offset = 0

      flask.g.page = 1

file modified
+78
@@ -66,10 +66,88 @@

      return jsonout

  

  

+ @API.route('/<repo>/watchers')

+ @API.route('/<namespace>/<repo>/watchers')

+ @API.route('/fork/<username>/<repo>/watchers')

+ @API.route('/fork/<username>/<namespace>/<repo>/watchers')

+ @api_method

+ def api_project_watchers(repo, username=None, namespace=None):

+     '''

+     Project watchers

+     ----------------

+     List the watchers on the project.

+ 

+     ::

+ 

+         GET /api/0/<repo>/watchers

+         GET /api/0/<namespace>/<repo>/watchers

+ 

+     ::

+ 

+         GET /api/0/fork/<username>/<repo>/watchers

+         GET /api/0/fork/<username>/<namespace>/<repo>/watchers

+ 

+     Sample response

+     ^^^^^^^^^^^^^^^

+ 

+     ::

+ 

+         {

+             "total_watchers": 1,

+             "watchers": {

+                 "mprahl": [

+                     "issues",

+                     "commits"

+                 ]

+             }

+         }

+     '''

+     repo = pagure.get_authorized_project(

+         SESSION, repo, user=username, namespace=namespace)

+     if repo is None:

+         raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)

+ 

+     implicit_watch_users = {repo.user.username}

+     for access_type in repo.access_users.keys():

+         implicit_watch_users = \

+             implicit_watch_users | set(

+                 [user.username for user in repo.access_users[access_type]])

+     for access_type in repo.access_groups.keys():

+         group_names = [group.group_name

+                        for group in repo.access_groups[access_type]]

+         for group_name in group_names:

+             group = pagure.lib.search_groups(SESSION, group_name=group_name)

+             implicit_watch_users = \

+                 implicit_watch_users | set([

+                     user.username for user in group.users])

+ 

+     watching_users_to_watch_level = {}

+     for implicit_watch_user in implicit_watch_users:

+         user_watch_level = pagure.lib.get_watch_level_on_repo(

+             SESSION, implicit_watch_user, repo)

+         watching_users_to_watch_level[implicit_watch_user] = user_watch_level

+ 

+     # Get the explicit watch statuses

+     for watcher in repo.watchers:

+         if watcher.watch_issues or watcher.watch_commits:

+             watching_users_to_watch_level[watcher.user.username] = \

+                 pagure.lib.get_watch_level_on_repo(

+                     SESSION, watcher.user.username, repo)

+         else:

+             if watcher.user.username in watching_users_to_watch_level:

+                 watching_users_to_watch_level.pop(watcher.user.username, None)

+ 

+     return flask.jsonify({

+         'total_watchers': len(watching_users_to_watch_level),

+         'watchers': watching_users_to_watch_level

+     })

+ 

+ 

  @API.route('/<repo>/git/branches')

  @API.route('/<namespace>/<repo>/git/branches')

  @API.route('/fork/<username>/<repo>/git/branches')

  @API.route('/fork/<username>/<namespace>/<repo>/git/branches')

+ @api_method

  def api_git_branches(repo, username=None, namespace=None):

      '''

      List all the branches of a git repo

@@ -60,29 +60,37 @@

          if not repo_obj.is_empty and not repo_obj.head_is_unborn:

              default_branch = repo_obj.head.shorthand

  

-         # Skip all branch but the default one

-         refname = refname.replace('refs/heads/', '')

-         if refname != default_branch:

-             continue

- 

          if set(newrev) == set(['0']):

              print("Deleting a reference/branch, so we won't run the "

                    "pagure hook")

              return

  

+         refname = refname.replace('refs/heads/', '')

          commits = pagure.lib.git.get_revs_between(

              oldrev, newrev, abspath, refname)

  

          if REDIS:

-             print('Sending to redis to log activity')

+             if refname == default_branch:

+                 print('Sending to redis to log activity and send commit '

+                       'notification emails')

+             else:

+                 print('Sending to redis to send commit notification emails')

+             # If REDIS is enabled, notify subscribed users that there are new

+             # commits to this project

              REDIS.publish(

                  'pagure.logcom',

                  json.dumps({

                      'project': project.to_json(public=True),

                      'abspath': abspath,

+                     'branch': refname,

+                     'default_branch': default_branch,

                      'commits': commits,

                  })

              )

+         else:

+             print('Hook not configured to connect to pagure-logcom')

+             print('/!\ Commit notification emails will not be sent and '

+                   'commits won\'t be logged')

  

      try:

          # Reset the merge_status of all opened PR to refresh their cache

file modified
+101 -64
@@ -1982,14 +1982,14 @@

  

      if not private:

          projects = projects.filter(

-             model.Project.private == False

+             model.Project.private == False  # noqa: E712

          )

      # No filtering is done if private == username i.e  if the owner of the

      # project is viewing the project

      elif isinstance(private, basestring) and private != username:

          projects = projects.filter(

              sqlalchemy.or_(

-                 model.Project.private == False,

+                 model.Project.private == False,  # noqa: E712

                  sqlalchemy.and_(

                      model.User.user == private,

                      model.User.id == model.ProjectUser.user_id,
@@ -2002,11 +2002,11 @@

      if fork is not None:

          if fork is True:

              projects = projects.filter(

-                 model.Project.is_fork == True

+                 model.Project.is_fork == True  # noqa: E712

              )

          elif fork is False:

              projects = projects.filter(

-                 model.Project.is_fork == False

+                 model.Project.is_fork == False  # noqa: E712

              )

      if tags:

          if not isinstance(tags, (list, tuple)):
@@ -2087,11 +2087,11 @@

          ).filter(

              model.User.id == model.Project.user_id

          ).filter(

-             model.Project.is_fork == True

+             model.Project.is_fork == True  # noqa: E712

          )

      else:

          query = query.filter(

-             model.Project.is_fork == False

+             model.Project.is_fork == False  # noqa: E712

          )

  

      return query.first()
@@ -2286,15 +2286,15 @@

  

      if private is False:

          query = query.filter(

-             model.Issue.private == False

+             model.Issue.private == False  # noqa: E712

          )

      elif isinstance(private, basestring):

          user2 = aliased(model.User)

          query = query.filter(

              sqlalchemy.or_(

-                 model.Issue.private == False,

+                 model.Issue.private == False,  # noqa: E712

                  sqlalchemy.and_(

-                     model.Issue.private == True,

+                     model.Issue.private == True,  # noqa: E712

                      model.Issue.user_id == user2.id,

                      user2.user == private,

                  )
@@ -3555,6 +3555,10 @@

  def update_watch_status(session, project, user, watch):

      ''' Update the user status for watching a project.

      '''

+     if watch not in ['-1', '0', '1', '2', '3']:

+         raise pagure.exceptions.PagureException(

+             'The watch value of "%s" is invalid' % watch)

+ 

      user_obj = get_user(session, user)

  

      if not user_obj:
@@ -3578,33 +3582,72 @@

          session.flush()

          return 'Watch status reset'

  

+     should_watch_issues = False

+     should_watch_commits = False

+     if watch == '1':

+         should_watch_issues = True

+     elif watch == '2':

+         should_watch_commits = True

+     elif watch == '3':

+         should_watch_issues = True

+         should_watch_commits = True

+ 

      if not watcher:

          watcher = model.Watcher(

              project_id=project.id,

              user_id=user_obj.id,

-             watch=watch

+             watch_issues=should_watch_issues,

+             watch_commits=should_watch_commits

          )

      else:

-         watcher.watch = watch

+         watcher.watch_issues = should_watch_issues

+         watcher.watch_commits = should_watch_commits

  

      session.add(watcher)

      session.flush()

  

-     msg_success = 'You are now watching this repo.'

-     if not int(watch):

-         msg_success = 'You are no longer watching this repo.'

-     return msg_success

- 

+     if should_watch_issues and should_watch_commits:

+         return 'You are now watching issues, PRs, and commits on this project'

+     elif should_watch_issues:

+         return 'You are now watching issues and PRs on this project'

+     elif should_watch_commits:

+         return 'You are now watching commits on this project'

+     else:

+         return 'You are no longer watching this project'

  

- def is_watching(session, user, reponame, repouser=None, namespace=None):

-     ''' Check user watching the project. '''

  

+ def get_watch_level_on_repo(session, user, repo, repouser=None,

+                             namespace=None):

+     ''' Get a list representing the watch level of the user on the project.

+     '''

+     # If a user wasn't passed in, we can't determine their watch level

      if user is None:

-         return False

- 

-     user_obj = search_user(session, username=user.username)

+         return []

+     elif isinstance(user, six.string_types):

+         user_obj = search_user(session, username=user)

+     else:

+         user_obj = search_user(session, username=user.username)

+     # If we can't find the user in the database, we can't determine their watch

+     # level

      if not user_obj:

-         return False

+         return []

+ 

+     # If the user passed in a Project for the repo parameter, then we don't

+     # need to query for it

+     if isinstance(repo, model.Project):

+         project = repo

+     # If the user passed in a string, then assume it is a project name

+     elif isinstance(repo, six.string_types):

+         project = pagure.get_authorized_project(

+             session, repo, user=repouser, namespace=namespace)

+     else:

+         raise RuntimeError('The passed in repo is an invalid type of "{0}"'

+                            .format(type(repo).__name__))

+ 

+     # If the project is not found, we can't determine the involvement of the

+     # user in the project

+     if not project:

+         return []

  

      query = session.query(

          model.Watcher
@@ -3612,52 +3655,42 @@

          model.Watcher.user_id == user_obj.id

      ).filter(

          model.Watcher.project_id == model.Project.id

-     ).filter(

-         model.Project.name == reponame

      )

  

-     if repouser is not None:

-         query = query.filter(

-             model.User.user == repouser

-         ).filter(

-             model.User.id == model.Project.user_id

-         ).filter(

-             model.Project.is_fork == True

-         )

-     else:

-         query = query.filter(

-             model.Project.is_fork == False

-         )

- 

-     if namespace is not None:

-         query = query.filter(

-             model.Project.namespace == namespace

-         )

- 

      watcher = query.first()

- 

+     # If there is a watcher issue, that means the user explicitly set a watch

+     # level on the project

      if watcher:

-         return watcher.watch

- 

-     project = pagure.get_authorized_project(

-         session, reponame, user=repouser, namespace=namespace)

- 

-     if not project:

-         return False

- 

-     if user.username == project.user.username:

-         return True

- 

+         if watcher.watch_issues and watcher.watch_commits:

+             return ['issues', 'commits']

+         elif watcher.watch_issues:

+             return ['issues']

+         elif watcher.watch_commits:

+             return ['commits']

+         else:

+             # If a watcher entry is set and both are set to False, that means

+             # the user explicitly asked to not be notified

+             return []

+ 

+     # If the user is the project owner, by default they will be watching

+     # issues and PRs

+     if user_obj.username == project.user.username:

+         return ['issues']

+     # If the user is a contributor, by default they will be watching issues

+     # and PRs

      for contributor in project.users:

-         if user.username == contributor.username:

-             return True

- 

+         if user_obj.username == contributor.username:

+             return ['issues']

+     # If the user is in a project group, by default they will be watching

+     # issues and PRs

      for group in project.groups:

          for guser in group.users:

-             if user.username == guser.username:

-                 return True

- 

-     return False

+             if user_obj.username == guser.username:

+                 return ['issues']

+     # If no other condition is true, then they are not explicitly watching the

+     # project or are not involved in the project to the point that comes with a

+     # default watch level

+     return []

  

  

  def user_watch_list(session, user, exclude_groups=None):
@@ -3672,7 +3705,9 @@

      ).filter(

          model.Watcher.user_id == user_obj.id

      ).filter(

-         model.Watcher.watch == False

+         model.Watcher.watch_issues == False  # noqa: E712

+     ).filter(

+         model.Watcher.watch_commits == False  # noqa: E712

      )

  

      unwatched_list = []
@@ -3684,7 +3719,9 @@

      ).filter(

          model.Watcher.user_id == user_obj.id

      ).filter(

-         model.Watcher.watch == True

+         model.Watcher.watch_issues == True  # noqa: E712

+     ).filter(

+         model.Watcher.watch_commits == True  # noqa: E712

      )

  

      watched_list = []
@@ -3810,7 +3847,7 @@

      if not private:

          # Add all the people watching the repo, remove those who opted-out

          for watcher in project_watchers_query.all():

-             if watcher.watch:

+             if watcher.watch_issues:

                  users.add(watcher.user.username)

              else:

                  if watcher.user.username in users:

file modified
+10 -2
@@ -1148,6 +1148,14 @@

      return user

  

  

+ def get_commit_subject(commit, abspath):

+     ''' Return the subject of the commit. '''

+     subject = pagure.lib.git.read_git_lines(

+         ['log', '-1', '--pretty=format:"%s"', commit],

+         abspath)[0].replace('"', '')

+     return subject

+ 

+ 

  def get_repo_name(abspath):

      ''' Return the name of the git repo based on its path.

      '''
@@ -1163,8 +1171,8 @@

      if not gitfolder:

          gitfolder = pagure.APP.config['GIT_FOLDER']

  

-     short_path = os.path.abspath(abspath).replace(

-         os.path.abspath(gitfolder), '').strip('/')

+     short_path = os.path.realpath(abspath).replace(

+         os.path.realpath(gitfolder), '').strip('/')

  

      if short_path.startswith('forks/'):

          username, projectname = short_path.split('forks/', 1)[1].split('/', 1)

file modified
+3 -10
@@ -442,12 +442,6 @@

          viewonly=True

      )

  

-     unwatchers = relation(

-         "Watcher",

-         primaryjoin="and_(Project.id==Watcher.project_id, "

-         "Watcher.watch=='0')"

-     )

- 

      @property

      def isa(self):

          ''' A string to allow finding out that this is a project. '''
@@ -647,7 +641,7 @@

          ).filter(

              Issue.status == 'Open'

          ).filter(

-             Issue.private == False

+             Issue.private == False  # noqa: E712

          ).count()

  

      @property
@@ -2055,9 +2049,8 @@

          sa.ForeignKey('users.id', onupdate='CASCADE'),

          nullable=False,

          index=True)

-     watch = sa.Column(

-         sa.Boolean,

-         nullable=False)

+     watch_issues = sa.Column(sa.Boolean, nullable=False, default=False)

+     watch_commits = sa.Column(sa.Boolean, nullable=False, default=False)

  

      user = relation(

          'User', foreign_keys=[user_id], remote_side=[User.id],

file modified
+71 -12
@@ -135,14 +135,6 @@

      if obj.assignee and obj.assignee.default_email:

          emails.add(obj.assignee.default_email)

  

-     # Add the person watching this project, if the issue is public

-     if obj.isa == 'issue' and not obj.private:

-         for watcher in obj.project.watchers:

-             emails.add(watcher.user.default_email)

-     elif obj.isa == 'pull-request':

-         for watcher in obj.project.watchers:

-             emails.add(watcher.user.default_email)

- 

      # Add public notifications to lists/users set project-wide

      if obj.isa == 'issue' and not obj.private:

          for notifs in obj.project.notifications.get('issues', []):
@@ -151,10 +143,17 @@

          for notifs in obj.project.notifications.get('requests', []):

              emails.add(notifs)

  

-     # Remove the person list in unwatch

-     for unwatcher in obj.project.unwatchers:

-         if unwatcher.user.default_email in emails:

-             emails.remove(unwatcher.user.default_email)

+     # Add the person watching this project, if it's a public issue or a

+     # pull-request

+     if (obj.isa == 'issue' and not obj.private) or obj.isa == 'pull-request':

+         for watcher in obj.project.watchers:

+             if watcher.watch_issues:

+                 emails.add(watcher.user.default_email)

+             else:

+                 # If there is a watch entry and it is false, it means the user

+                 # explicitly requested to not watch the issue

+                 if watcher.user.default_email in emails:

+                     emails.remove(watcher.user.default_email)

  

      # Add/Remove people who explicitly asked to be added/removed

      for watcher in obj.watchers:
@@ -172,6 +171,21 @@

      return emails

  

  

+ def _get_emails_for_commit_notification(project):

+     emails = set()

+     for watcher in project.watchers:

+         if watcher.watch_commits:

+             emails.add(watcher.user.default_email)

+ 

+     # Drop the email used by pagure when sending

+     emails = _clean_emails(

+         emails, pagure.APP.config.get(pagure.APP.config.get(

+             'FROM_EMAIL', 'pagure@fedoraproject.org'))

+     )

+ 

+     return emails

+ 

+ 

  def _build_url(*args):

      ''' Build a URL from a given list of arguments. '''

      items = []
@@ -678,3 +692,48 @@

          email.email,

          user_from=user.fullname or user.user,

      )

+ 

+ 

+ def notify_new_commits(abspath, project, branch, commits):

+     ''' Notify the people following a project's commits that new commits have

+     been added.

+     '''

+     commits_info = []

+     for commit in commits:

+         commits_info.append({

+             'commit': commit,

+             'author': pagure.lib.git.get_author(commit, abspath),

+             'subject': pagure.lib.git.get_commit_subject(commit, abspath)

+         })

+ 

+     commits_string = '\n'.join('{0}    {1}    {2}'.format(

+         commit_info['commit'], commit_info['author'], commit_info['subject'])

+         for commit_info in commits_info)

+     commit_url = _build_url(

+         pagure.APP.config['APP_URL'], _fullname_to_url(project.fullname),

+         'commits', branch)

+ 

+     email_body = '''

+ The following commits were pushed to the repo "{repo}" on branch

+ "{branch}", which you are following:

+ {commits}

+ 

+ 

+ 

+ To view more about the commits, visit:

+ {commit_url}

+ '''

+     email_body = email_body.format(

+         repo=project.fullname,

+         branch=branch,

+         commits=commits_string,

+         commit_url=commit_url

+     )

+     mail_to = _get_emails_for_commit_notification(project)

+ 

+     send_email(

+         email_body,

+         'New Commits To "{0}" ({1})'.format(project.fullname, branch),

+         ','.join(mail_to),

+         project_name=project.fullname

+     )

@@ -3,7 +3,19 @@

  {% block title %}{{

      repo.namespace + '/' if repo.namespace }}{{ repo.name }}{% endblock %}

  {% set tag = "home" %}

- 

+ {% if g.repo_watch_levels == ['issues', 'commits'] %}

+     {% set watch_button_title = 'You are watching issues, PRs, and commits on this project' %}

+     {% set watch_button_class = 'btn-primary' %}

+ {% elif g.repo_watch_levels == ['issues'] %}

+     {% set watch_button_title = 'You are watching issues on this project' %}

+     {% set watch_button_class = 'btn-info' %}

+ {% elif g.repo_watch_levels == ['commits'] %}

+     {% set watch_button_title = 'You are watching commits on this project' %}

+     {% set watch_button_class = 'btn-info' %}

+ {% else %}

+     {% set watch_button_title = 'You are not watching this project' %}

+     {% set watch_button_class = 'btn-secondary' %}

+ {% endif %}

  

  {% block content %}

  <div class="repo-header p-t-1">
@@ -62,24 +74,9 @@

                <span class="oi" data-glyph="fork"></span>Fork</button>

              {% endif %}

            {% endif %}

-             <button title="{%-

-             if is_watching(

-               repo.name,

-               repo.user.user if repo.is_fork else None,

-               repo.namespace

-             )%}You are watching this project{%

-             else %}You are not watching this project{%

-             endif -%}"

-             type="button" class="btn btn-sm dropdown-toggle

-             {%-

-             if is_watching(

-               repo.name,

-               repo.user.user if repo.is_fork else None,

-               repo.namespace

-             )%} btn-primary{%

-             else %} btn-secondary{%

-             endif -%}"

-             data-toggle="dropdown" id="watch-button">

+             <button title="{{ watch_button_title }}" type="button"

+                     class="btn btn-sm dropdown-toggle {{ watch_button_class }}"

+                     data-toggle="dropdown" id="watch-button">

                <span class="oi" data-glyph="eye"></span>

              </button>

              <div class="dropdown-menu dropdown-menu-right watch-menu">
@@ -89,19 +86,21 @@

                    user=repo.user.user if repo.is_fork else None,

                    namespace=repo.namespace,

                    watch=0) }}">

-                {%- if is_watching(

-                   repo.name,

-                   repo.user.user if repo.is_fork else None,

-                   repo.namespace)

-                %}

-                <a class="dropdown-item" id="unwatch_button">Unwatch {{

-                   repo.name }}</a>

-                {% else %}

-                <a class="dropdown-item" id="watch_button">Watch {{

-                   repo.name }}</a>

-                {% endif -%}

-                <a class="dropdown-item" id="reset_button">Reset Watch Status {{

-                   repo.name }}</a>

+                 <a class="dropdown-item" id="watch_issues_button">

+                     Watch issues and PRs on "{{ repo.name  }}"

+                 </a>

+                 <a class="dropdown-item" id="watch_commits_button">

+                     Watch commits on "{{ repo.name }}"

+                 </a>

+                 <a class="dropdown-item" id="watch_issues_commits_button">

+                     Watch issues, PRs, and commits on "{{ repo.name }}"

+                 </a>

+                 <a class="dropdown-item" id="unwatch_button">

+                     Unwatch "{{ repo.name }}"

+                 </a>

+                 <a class="dropdown-item" id="reset_button">

+                     Reset watch status on "{{ repo.name }}"

+                 </a>

                  {{ forkbuttonform.csrf_token }}

                </form>

              </div>
@@ -307,20 +306,32 @@

  {{ super() }}

  <script type="text/javascript">

  $(document).ready(function() {

-   $(".watch-menu a").click(function(){

-     var selectedValue = $(this).attr('id');

-     var action = $("#watch_project").attr('action');

-       if (selectedValue === "watch_button") {

-         action = action.replace('/settings/0', '/settings/1');

-         $('#watch_project').attr('action', action);

-       } else if (selectedValue === "reset_button") {

-         action = action.replace('/settings/0', '/settings/-1');

-         $('#watch_project').attr('action', action);

-       }

+     {% if g.repo_watch_levels %}

+         var currentWatchStatusButton = $('#watch_{{ g.repo_watch_levels | join('_') }}_button');

+     {% else %}

+         var currentWatchStatusButton = $('#unwatch_button');

+     {% endif %}

+     currentWatchStatusButton.prepend('<span class="oi" data-glyph="circle-check" style="padding-right:0.5em"></span>');

+     $('.watch-menu a').not(currentWatchStatusButton).css('padding-left', '2.85em');

+ 

+     $(".watch-menu a").click(function(){

+         var selectedValue = $(this).attr('id');

+         var watchProjectForm = $("#watch_project");

+         var action = watchProjectForm.attr('action');

  

-       $('#watch_project').submit();

+         if (selectedValue === "watch_issues_button") {

+             action = action.replace('/settings/0', '/settings/1');

+         } else if (selectedValue === "watch_commits_button") {

+             action = action.replace('/settings/0', '/settings/2');

+         } else if (selectedValue === "watch_issues_commits_button") {

+             action = action.replace('/settings/0', '/settings/3');

+         } else if (selectedValue === "reset_button") {

+             action = action.replace('/settings/0', '/settings/-1');

+         }

  

-   });

+         watchProjectForm.attr('action', action);

+         watchProjectForm.submit();

+     });

  });

  </script>

  {% endblock %}

file modified
+2 -2
@@ -2261,7 +2261,7 @@

      methods=['POST'])

  @login_required

  def watch_repo(repo, watch, username=None, namespace=None):

-     """ Marked for watching or Unwatching

+     """ Marked for watching or unwatching

      """

  

      return_point = flask.url_for('index')
@@ -2272,7 +2272,7 @@

      if not form.validate_on_submit():

          flask.abort(400)

  

-     if str(watch) not in ['0', '1', '-1']:

+     if str(watch) not in ['0', '1', '2', '3', '-1']:

          flask.abort(400)

  

      try:

@@ -532,6 +532,194 @@

          }

          self.assertDictEqual(data, expected_data)

  

+     def test_api_project_watchers(self):

+         """ Test the api_project_watchers method of the flask api. """

+         tests.create_projects(self.session)

+         # The user is not logged in and the owner is watching issues implicitly

+         output = self.app.get('/api/0/test/watchers')

+         self.assertEqual(output.status_code, 200)

+         expected_data = {

+             "total_watchers": 1,

+             "watchers": {

+                 "pingou": [

+                     "issues"

+                 ]

+             }

+         }

+         self.assertDictEqual(json.loads(output.data), expected_data)

+ 

+         user = pagure.SESSION.query(pagure.lib.model.User).filter_by(

+             user='pingou')

+         with tests.user_set(pagure.APP, user):

+             # Non-existing project

+             output = self.app.get('/api/0/random/watchers')

+             self.assertEqual(output.status_code, 404)

+             data = json.loads(output.data)

+             self.assertDictEqual(

+                 data,

+                 {'error_code': 'ENOPROJECT', 'error': 'Project not found'}

+             )

+ 

+             # The owner is watching issues implicitly

+             output = self.app.get('/api/0/test/watchers')

+             self.assertEqual(output.status_code, 200)

+             expected_data = {

+                 "total_watchers": 1,

+                 "watchers": {

+                     "pingou": [

+                         "issues"

+                     ]

+                 }

+             }

+             self.assertDictEqual(json.loads(output.data), expected_data)

+ 

+             project = pagure.get_authorized_project(self.session, 'test')

+ 

+             # The owner is watching issues and commits explicitly

+             pagure.lib.update_watch_status(

+                 pagure.SESSION, project, 'pingou', '3')

+             output = self.app.get('/api/0/test/watchers')

+             self.assertEqual(output.status_code, 200)

+             expected_data = {

+                 "total_watchers": 1,

+                 "watchers": {

+                     "pingou": [

+                         "issues",

+                         "commits"

+                     ]

+                 }

+             }

+             self.assertDictEqual(json.loads(output.data), expected_data)

+ 

+             # The owner is watching issues explicitly

+             pagure.lib.update_watch_status(

+                 pagure.SESSION, project, 'pingou', '1')

+             output = self.app.get('/api/0/test/watchers')

+             self.assertEqual(output.status_code, 200)

+             expected_data = {

+                 "total_watchers": 1,

+                 "watchers": {

+                     "pingou": [

+                         "issues"

+                     ]

+                 }

+             }

+             self.assertDictEqual(json.loads(output.data), expected_data)

+ 

+             # The owner is watching commits explicitly

+             pagure.lib.update_watch_status(

+                 pagure.SESSION, project, 'pingou', '2')

+             output = self.app.get('/api/0/test/watchers')

+             self.assertEqual(output.status_code, 200)

+             expected_data = {

+                 "total_watchers": 1,

+                 "watchers": {

+                     "pingou": [

+                         "commits"

+                     ]

+                 }

+             }

+             self.assertDictEqual(json.loads(output.data), expected_data)

+ 

+             # The owner is watching commits explicitly and foo is watching

+             # issues implicitly

+             project_user = pagure.lib.model.ProjectUser(

+                 project_id=project.id,

+                 user_id=2,

+                 access='commit',

+             )

+             pagure.lib.update_watch_status(

+                 pagure.SESSION, project, 'pingou', '2')

+             pagure.SESSION.add(project_user)

+             pagure.SESSION.commit()

+ 

+             output = self.app.get('/api/0/test/watchers')

+             self.assertEqual(output.status_code, 200)

+             expected_data = {

+                 "total_watchers": 2,

+                 "watchers": {

+                     "foo": ["issues"],

+                     "pingou": ["commits"]

+                 }

+             }

+             self.assertDictEqual(json.loads(output.data), expected_data)

+ 

+             # The owner and foo are watching issues implicitly

+             pagure.lib.update_watch_status(

+                 pagure.SESSION, project, 'pingou', '-1')

+ 

+             output = self.app.get('/api/0/test/watchers')

+             self.assertEqual(output.status_code, 200)

+             expected_data = {

+                 "total_watchers": 2,

+                 "watchers": {

+                     "foo": ["issues"],

+                     "pingou": ["issues"]

+                 }

+             }

+             self.assertDictEqual(json.loads(output.data), expected_data)

+ 

+             # The owner and foo through group membership are watching issues

+             # implicitly

+             pagure.lib.update_watch_status(

+                 pagure.SESSION, project, 'pingou', '-1')

+             project_membership = pagure.SESSION.query(

+                 pagure.lib.model.ProjectUser).filter_by(

+                     user_id=2, project_id=project.id).one()

+             pagure.SESSION.delete(project_membership)

+             pagure.SESSION.commit()

+             msg = pagure.lib.add_group(

+                 self.session,

+                 group_name='some_group',

+                 display_name='Some Group',

+                 description=None,

+                 group_type='bar',

+                 user='pingou',

+                 is_admin=False,

+                 blacklist=[],

+             )

+             pagure.SESSION.commit()

+             group = pagure.SESSION.query(pagure.lib.model.PagureGroup)\

+                 .filter_by(group_name='some_group').one()

+             pagure.lib.add_user_to_group(

+                 pagure.SESSION, 'foo', group, 'pingou', False)

+             project_group = pagure.lib.model.ProjectGroup(

+                 project_id=project.id,

+                 group_id=group.id,

+                 access='commit',

+             )

+             pagure.SESSION.add(project_group)

+             pagure.SESSION.commit()

+ 

+             output = self.app.get('/api/0/test/watchers')

+             self.assertEqual(output.status_code, 200)

+             expected_data = {

+                 "total_watchers": 2,

+                 "watchers": {

+                     "foo": ["issues"],

+                     "pingou": ["issues"]

+                 }

+             }

+             self.assertDictEqual(json.loads(output.data), expected_data)

+ 

+             # The owner is watching issues implicitly and foo will be watching

+             # commits explicitly but is in a group with commit access

+             pagure.lib.update_watch_status(

+                 pagure.SESSION, project, 'pingou', '-1')

+             pagure.lib.update_watch_status(

+                 pagure.SESSION, project, 'foo', '2')

+ 

+             output = self.app.get('/api/0/test/watchers')

+             self.assertEqual(output.status_code, 200)

+             expected_data = {

+                 "total_watchers": 2,

+                 "watchers": {

+                     "foo": ["commits"],

+                     "pingou": ["issues"]

+                 }

+             }

+             self.assertDictEqual(json.loads(output.data), expected_data)

+ 

      @patch('pagure.lib.git.generate_gitolite_acls')

      def test_api_new_project(self, p_gga):

          """ Test the api_new_project method of the flask api. """

@@ -4123,20 +4123,33 @@

              self.assertEqual(output.status_code, 404)

  

              output = self.app.post(

-                 '/test/watch/settings/2', data=data, follow_redirects=True)

+                 '/test/watch/settings/8', data=data, follow_redirects=True)

              self.assertEqual(output.status_code, 400)

  

              output = self.app.post(

                  '/test/watch/settings/0', data=data, follow_redirects=True)

              self.assertIn(

                  '</button>\n                      You are no longer'

-                 ' watching this repo.', output.data)

+                 ' watching this project', output.data)

  

              output = self.app.post(

                  '/test/watch/settings/1', data=data, follow_redirects=True)

              self.assertIn(

                  '</button>\n                      You are now'

-                 ' watching this repo.', output.data)

+                 ' watching issues and PRs on this project', output.data)

+ 

+             output = self.app.post(

+                 '/test/watch/settings/2', data=data, follow_redirects=True)

+             self.assertIn(

+                 '</button>\n                      You are now'

+                 ' watching commits on this project', output.data)

+ 

+             output = self.app.post(

+                 '/test/watch/settings/3', data=data, follow_redirects=True)

+             self.assertIn(

+                 ('</button>\n                      You are now'

+                  ' watching issues, PRs, and commits on this project'),

+                 output.data)

  

              item = pagure.lib.model.Project(

                  user_id=2,  # foo
@@ -4163,14 +4176,29 @@

                  follow_redirects=True)

              self.assertIn(

                  '</button>\n                      You are no longer'

-                 ' watching this repo.', output.data)

+                 ' watching this project', output.data)

  

              output = self.app.post(

                  '/fork/foo/test/watch/settings/1', data=data,

                  follow_redirects=True)

              self.assertIn(

                  '</button>\n                      You are now'

-                 ' watching this repo.', output.data)

+                 ' watching issues and PRs on this project', output.data)

+ 

+             output = self.app.post(

+                 '/fork/foo/test/watch/settings/2', data=data,

+                 follow_redirects=True)

+             self.assertIn(

+                 '</button>\n                      You are now'

+                 ' watching commits on this project', output.data)

+ 

+             output = self.app.post(

+                 '/fork/foo/test/watch/settings/3', data=data,

+                 follow_redirects=True)

+             self.assertIn(

+                 ('</button>\n                      You are now'

+                  ' watching issues, PRs, and commits on this project'),

+                 output.data)

  

              output = self.app.post(

                  '/fork/foo/test/watch/settings/-1', data=data,
@@ -4179,7 +4207,6 @@

                  '</button>\n                      Watch status reset',

                  output.data)

  

- 

      def test_delete_report(self):

          """ Test the  delete_report endpoint. """

  

file modified
+88 -36
@@ -3143,10 +3143,20 @@

              session=self.session,

              project=project,

              user='aavrug',

-             watch=True,

+             watch='1',

          )

  

-         # All good and when user seleted reset watch option.

+         # Invalid watch status

+         self.assertRaises(

+             pagure.exceptions.PagureException,

+             pagure.lib.update_watch_status,

+             session=self.session,

+             project=project,

+             user='pingou',

+             watch='me fail',

+         )

+ 

+         # All good and when user selected reset watch option.

          msg = pagure.lib.update_watch_status(

              session=self.session,

              project=project,
@@ -3156,25 +3166,26 @@

          self.session.commit()

          self.assertEqual(msg, 'Watch status is already reset')

  

-         # All good and when user seleted watch option.

+         # All good and when user selected watch issues option.

          msg = pagure.lib.update_watch_status(

              session=self.session,

              project=project,

              user='pingou',

-             watch=True,

+             watch='1',

          )

          self.session.commit()

-         self.assertEqual(msg, 'You are now watching this repo.')

+         self.assertEqual(

+             msg, 'You are now watching issues and PRs on this project')

  

          # All good and when user selected unwatch option.

          msg = pagure.lib.update_watch_status(

              session=self.session,

              project=project,

              user='pingou',

-             watch=False,

+             watch='0',

          )

          self.session.commit()

-         self.assertEqual(msg, 'You are no longer watching this repo.')

+         self.assertEqual(msg, 'You are no longer watching this project')

  

          # All good and when user seleted reset watch option.

          msg = pagure.lib.update_watch_status(
@@ -3186,30 +3197,30 @@

          self.session.commit()

          self.assertEqual(msg, 'Watch status reset')

  

-     def test_is_watching(self):

-         """ Test the is_watching method of pagure.lib. """

+     def test_get_watch_level_on_repo(self):

+         """ Test the get_watch_level_on_repo method of pagure.lib. """

          tests.create_projects(self.session)

          self.test_add_group()

  

          project = pagure.lib._get_project(self.session, 'test')

  

          # If user not logged in

-         watch = pagure.lib.is_watching(

+         watch_level = pagure.lib.get_watch_level_on_repo(

              session=self.session,

              user=None,

-             reponame='test',

+             repo='test',

          )

-         self.assertFalse(watch)

+         self.assertEqual(watch_level, [])

  

          # User does not exist

          user = tests.FakeUser()

          user.username = 'aavrug'

-         watch = pagure.lib.is_watching(

+         watch_level = pagure.lib.get_watch_level_on_repo(

              session=self.session,

              user=user,

-             reponame='test',

+             repo='test',

          )

-         self.assertFalse(watch)

+         self.assertEqual(watch_level, [])

  

          pagure.lib.add_group_to_project(

              session=self.session,
@@ -3232,56 +3243,97 @@

  

          # If user belongs to any group of that project

          user.username = 'foo'

-         watch = pagure.lib.is_watching(

+         msg = watch_level = pagure.lib.get_watch_level_on_repo(

              session=self.session,

              user=user,

-             reponame='test',

+             repo='test',

          )

-         self.assertTrue(watch)

+         self.assertEqual(watch_level, ['issues'])

  

          # If user is the creator

          user.username = 'pingou'

-         watch = pagure.lib.is_watching(

+         watch_level = pagure.lib.get_watch_level_on_repo(

              session=self.session,

              user=user,

-             reponame='test',

+             repo='test',

          )

-         self.assertTrue(watch)

+         self.assertEqual(watch_level, ['issues'])

  

-         # Entry into watchers table

-         pagure.lib.update_watch_status(

+         # Entry into watchers table for issues and commits

+         msg = pagure.lib.update_watch_status(

              session=self.session,

              project=project,

              user='pingou',

-             watch=True,

+             watch='3',

          )

          self.session.commit()

+         self.assertEqual(

+             msg,

+             'You are now watching issues, PRs, and commits on this project')

+ 

+         # From watchers table

+         watch_level = pagure.lib.get_watch_level_on_repo(

+             session=self.session,

+             user=user,

+             repo='test',

+         )

+         self.assertEqual(['issues', 'commits'], watch_level)

+ 

+         # Entry into watchers table for just commits

+         msg = pagure.lib.update_watch_status(

+             session=self.session,

+             project=project,

+             user='pingou',

+             watch='2',

+         )

+         self.session.commit()

+         self.assertEqual(

+             msg, 'You are now watching commits on this project')

+ 

+         # From watchers table

+         watch_level = pagure.lib.get_watch_level_on_repo(

+             session=self.session,

+             user=user,

+             repo='test',

+         )

+         self.assertEqual(['commits'], watch_level)

+ 

+         # Entry into watchers table for issues

+         msg = pagure.lib.update_watch_status(

+             session=self.session,

+             project=project,

+             user='pingou',

+             watch='1',

+         )

+         self.session.commit()

+         self.assertEqual(

+             msg, 'You are now watching issues and PRs on this project')

  

          # From watchers table

-         watch = pagure.lib.is_watching(

+         watch_level = pagure.lib.get_watch_level_on_repo(

              session=self.session,

              user=user,

-             reponame='test',

+             repo='test',

          )

-         self.assertTrue(watch)

+         self.assertEqual(['issues'], watch_level)

  

-         # Entry into watchers table

+         # Entry into watchers table for no watching

          msg = pagure.lib.update_watch_status(

              session=self.session,

              project=project,

              user='pingou',

-             watch=False,

+             watch='0',

          )

          self.session.commit()

-         self.assertEqual(msg, 'You are no longer watching this repo.')

+         self.assertEqual(msg, 'You are no longer watching this project')

  

          # From watchers table

-         watch = pagure.lib.is_watching(

+         watch_level = pagure.lib.get_watch_level_on_repo(

              session=self.session,

              user=user,

-             reponame='test',

+             repo='test',

          )

-         self.assertFalse(watch)

+         self.assertEqual(watch_level, [])

  

          # Add a contributor to the project

          item = pagure.lib.model.User(
@@ -3306,12 +3358,12 @@

  

          # Check if the new contributor is watching

          user.username = 'bar'

-         watch = pagure.lib.is_watching(

+         watch_level = pagure.lib.get_watch_level_on_repo(

              session=self.session,

              user=user,

-             reponame='test',

+             repo='test',

          )

-         self.assertTrue(watch)

+         self.assertEqual(watch_level, ['issues'])

  

      def test_user_watch_list(self):

          ''' test user watch list method of pagure.lib '''

@@ -162,8 +162,9 @@

  

          # Watch the project

          repo = pagure.get_authorized_project(self.session, 'test3', namespace='ns')

-         out = pagure.lib.update_watch_status(self.session, repo, 'bar', True)

-         self.assertEqual(out, 'You are now watching this repo.')

+         out = pagure.lib.update_watch_status(self.session, repo, 'bar', '1')

+         self.assertEqual(

+             out, 'You are now watching issues and PRs on this project')

  

          exp = set(['bar@pingou.com', 'foo@bar.com', 'bar@bar.com'])

          out = pagure.lib.notify._get_emails_for_obj(iss)
@@ -323,8 +324,9 @@

  

          # Watch the project

          repo = pagure.get_authorized_project(self.session, 'test')

-         out = pagure.lib.update_watch_status(self.session, repo, 'bar', True)

-         self.assertEqual(out, 'You are now watching this repo.')

+         out = pagure.lib.update_watch_status(self.session, repo, 'bar', '1')

+         self.assertEqual(

+             out, 'You are now watching issues and PRs on this project')

  

          exp = set(['bar@pingou.com', 'foo@bar.com', 'bar@bar.com'])

          out = pagure.lib.notify._get_emails_for_obj(req)

@@ -309,10 +309,10 @@

              session=self.session,

              project=project,

              user='pingou',

-             watch=False,

+             watch='0',

          )

          self.session.commit()

-         self.assertEqual(msg, 'You are no longer watching this repo.')

+         self.assertEqual(msg, 'You are no longer watching this project')

  

          # Create the ticket

          iss = pagure.lib.new_issue(
@@ -432,10 +432,11 @@

              session=self.session,

              project=project,

              user='bar',

-             watch=True,

+             watch='1',

          )

          self.session.commit()

-         self.assertEqual(msg, 'You are now watching this repo.')

+         self.assertEqual(

+             msg, 'You are now watching issues and PRs on this project')

  

          # Create the pull-request

          req = pagure.lib.new_pull_request(
@@ -492,10 +493,11 @@

              session=self.session,

              project=project,

              user='bar',

-             watch=True,

+             watch='1',

          )

          self.session.commit()

-         self.assertEqual(msg, 'You are now watching this repo.')

+         self.assertEqual(

+             msg, 'You are now watching issues and PRs on this project')

  

          # Create the ticket

          iss = pagure.lib.new_issue(

As a heads up, the first few commits were a couple of bug fixes.

Additionally, I'm not sure how to test the email notification in the git hook practically and through unit tests. It seems to call the send_email function as I'd expect but I don't know for sure since I don't have a mail server configured. If you have any ideas, I'd appreciate it.

doesn't this duplicate the email hook?

looks like you fixed the typo above but missed it here (selected)

4 new commits added

  • Add different levels of granularity for watching a project and fix flake8 errors for tests to pass
  • Add missing import in pagure_logcom_server
  • Correct variable name in pagure_logcom_server
  • Use 'os.path.realpath' in 'get_repo_namespace' to resolve an issue when a symbolic link was being used for APP.config['GIT_FOLDER']
6 years ago

1 new commit added

  • Transition commit notification emails to use Redis
6 years ago

5 new commits added

  • Add different levels of granularity for watching a project and fix flake8 errors for tests to pass
  • Fix imports in pagure_loadjson_server.py
  • Add missing import in pagure_logcom_server
  • Correct variable name in pagure_logcom_server
  • Use 'os.path.realpath' in 'get_repo_namespace' to resolve an issue when a symbolic link was being used for APP.config['GIT_FOLDER']
6 years ago

Pretty please pagure-ci rebuild

We can't create a column nullable=False directly since there will be data in the table and that column will thus be null upon creation. So we need to create it as nullable=True, set some data in it and then alter it to nullable=False

EDIT: I think I tried it with server_default but I'm not sure anymore suddenly, so I'll give this a try first

This is not actually the right service, this one is triggered by pushes made to the ticket or request repo. We should adjust the logcom (log commit) service for this (it's the one that updates the calendar heatmap to reflect the commits in the activity of the users).

Should we check that watch is in ['1', '2', '3'] first and warn if it is not?

5 new commits added

  • Add different levels of granularity for watching a project and fix flake8 errors for tests to pass
  • Fix imports in pagure_loadjson_server.py
  • Add missing import in pagure_logcom_server
  • Correct variable name in pagure_logcom_server
  • Use 'os.path.realpath' in 'get_repo_namespace' to resolve an issue when a symbolic link was being used for APP.config['GIT_FOLDER']
6 years ago

5 new commits added

  • Add different levels of granularity for watching a project and fix flake8 errors for tests to pass
  • Fix imports in pagure_loadjson_server.py
  • Add missing import in pagure_logcom_server
  • Correct variable name in pagure_logcom_server
  • Use 'os.path.realpath' in 'get_repo_namespace' to resolve an issue when a symbolic link was being used for APP.config['GIT_FOLDER']
6 years ago

rebased

6 years ago

I wonder if instead of calling the function in the template we shouldn't do that in the controller and just pass the output to the template, what do you think?

5 new commits added

  • Add different levels of granularity for watching a project and fix flake8 errors for tests to pass
  • Fix imports in pagure_loadjson_server.py
  • Add missing import in pagure_logcom_server
  • Correct variable name in pagure_logcom_server
  • Use 'os.path.realpath' in 'get_repo_namespace' to resolve an issue when a symbolic link was being used for APP.config['GIT_FOLDER']
6 years ago

I like that idea. I was trying to keep it more or less like you had it before when you were calling is_watching. If there's no reason to keep it like that, I will try to change it.

6 new commits added

  • Move pagure.lib.get_watch_level_on_repo function call to
  • Add different levels of granularity for watching a project and fix flake8 errors for tests to pass
  • Fix imports in pagure_loadjson_server.py
  • Add missing import in pagure_logcom_server
  • Correct variable name in pagure_logcom_server
  • Use 'os.path.realpath' in 'get_repo_namespace' to resolve an issue when a symbolic link was being used for APP.config['GIT_FOLDER']
6 years ago

I'm thinking we may want this section to be before the one for # Add/Remove people who explicitly asked to be added/removed

Yes, you're right. Let me fix that.

5 new commits added

  • Add different levels of granularity for watching a project and fix flake8 errors for tests to pass
  • Fix imports in pagure_loadjson_server.py
  • Add missing import in pagure_logcom_server
  • Correct variable name in pagure_logcom_server
  • Use 'os.path.realpath' in 'get_repo_namespace' to resolve an issue when a symbolic link was being used for APP.config['GIT_FOLDER']
6 years ago

The tests are failing now. I'll look into it later.

Edit:
This is ready for review again.

5 new commits added

  • Add different levels of granularity for watching a project and fix flake8 errors for tests to pass
  • Fix imports in pagure_loadjson_server.py
  • Add missing import in pagure_logcom_server
  • Correct variable name in pagure_logcom_server
  • Use 'os.path.realpath' in 'get_repo_namespace' to resolve an issue when a symbolic link was being used for APP.config['GIT_FOLDER']
6 years ago

As per our conversation, we will replace server_default.

Edit: This is now replaced in a new commit

8 new commits added

  • Add a project watchers API endpoint
  • Remove server_default in the add_granularity_to_watching_repos migration
  • Add different levels of granularity for watching a project and fix flake8 errors for tests to pass
  • Add missing decorator for api_git_branches
  • Fix imports in pagure_loadjson_server.py
  • Add missing import in pagure_logcom_server
  • Correct variable name in pagure_logcom_server
  • Use 'os.path.realpath' in 'get_repo_namespace' to resolve an issue when a symbolic link was being used for APP.config['GIT_FOLDER']
6 years ago

8 new commits added

  • Add a project watchers API endpoint
  • Remove server_default in the add_granularity_to_watching_repos migration
  • Add different levels of granularity for watching a project and fix flake8 errors for tests to pass
  • Add missing decorator for api_git_branches
  • Fix imports in pagure_loadjson_server.py
  • Add missing import in pagure_logcom_server
  • Correct variable name in pagure_logcom_server
  • Use 'os.path.realpath' in 'get_repo_namespace' to resolve an issue when a symbolic link was being used for APP.config['GIT_FOLDER']
6 years ago

rebased

6 years ago

Pretty please pagure-ci rebuild

Pretty please pagure-ci rebuild

Pretty please pagure-ci rebuild

Pretty please pagure-ci rebuild

Pretty please pagure-ci rebuild

@pingou I can't get the unit tests to actually run in Jenkins. Can you check the Jenkins setup when you can please?

Pull-Request has been merged by pingou

6 years ago
Metadata