From bba07e7f6fd4c1b8fff97e4330347d9f3908a9a5 Mon Sep 17 00:00:00 2001 From: Matt Prahl Date: May 09 2017 20:24:31 +0000 Subject: [PATCH 1/9] Use 'os.path.realpath' in 'get_repo_namespace' to resolve an issue when a symbolic link was being used for APP.config['GIT_FOLDER'] --- diff --git a/pagure/lib/git.py b/pagure/lib/git.py index 8d4f8ae..90910f3 100644 --- a/pagure/lib/git.py +++ b/pagure/lib/git.py @@ -1163,8 +1163,8 @@ def get_repo_namespace(abspath, gitfolder=None): 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) From 9144f340625ae2c5a9059598c82016e2344d0384 Mon Sep 17 00:00:00 2001 From: Matt Prahl Date: May 09 2017 20:24:31 +0000 Subject: [PATCH 2/9] Correct variable name in pagure_logcom_server --- diff --git a/pagure-logcom/pagure_logcom_server.py b/pagure-logcom/pagure_logcom_server.py index fdb4cb1..e015be0 100644 --- a/pagure-logcom/pagure_logcom_server.py +++ b/pagure-logcom/pagure_logcom_server.py @@ -96,7 +96,7 @@ def handle_messages(): 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) From 11e5cfdf00984b822939648fca0da841dd4f470f Mon Sep 17 00:00:00 2001 From: Matt Prahl Date: May 09 2017 20:24:31 +0000 Subject: [PATCH 3/9] Add missing import in pagure_logcom_server --- diff --git a/pagure-logcom/pagure_logcom_server.py b/pagure-logcom/pagure_logcom_server.py index e015be0..29bf9d4 100644 --- a/pagure-logcom/pagure_logcom_server.py +++ b/pagure-logcom/pagure_logcom_server.py @@ -20,6 +20,7 @@ time can be really time-consuming). import json import logging import os +from sqlalchemy.exc import SQLAlchemyError import trollius import trollius_redis From c9a58392409c03c72a228620f2309be55dca3a38 Mon Sep 17 00:00:00 2001 From: Matt Prahl Date: May 09 2017 20:24:31 +0000 Subject: [PATCH 4/9] Fix imports in pagure_loadjson_server.py --- diff --git a/pagure-loadjson/pagure_loadjson_server.py b/pagure-loadjson/pagure_loadjson_server.py index d00f4cd..bfaa362 100644 --- a/pagure-loadjson/pagure_loadjson_server.py +++ b/pagure-loadjson/pagure_loadjson_server.py @@ -22,8 +22,7 @@ import json import logging import os import traceback - -import requests +import inspect import trollius import trollius_redis From 3114c123ea7b5eac4fe42ea13aca1e69948eddd6 Mon Sep 17 00:00:00 2001 From: Matt Prahl Date: May 09 2017 20:24:31 +0000 Subject: [PATCH 5/9] Add missing decorator for api_git_branches --- diff --git a/pagure/api/project.py b/pagure/api/project.py index 9c8fef0..f51684c 100644 --- a/pagure/api/project.py +++ b/pagure/api/project.py @@ -70,6 +70,7 @@ def api_git_tags(repo, username=None, namespace=None): @API.route('///git/branches') @API.route('/fork///git/branches') @API.route('/fork////git/branches') +@api_method def api_git_branches(repo, username=None, namespace=None): ''' List all the branches of a git repo From b49f937130f46c238e8341a3a9fbe00e2e38ee07 Mon Sep 17 00:00:00 2001 From: Matt Prahl Date: May 09 2017 20:24:31 +0000 Subject: [PATCH 6/9] Add different levels of granularity for watching a project and fix flake8 errors for tests to pass --- diff --git a/alembic/versions/d4d2c5aa8a0_add_granularity_to_watching_repos.py b/alembic/versions/d4d2c5aa8a0_add_granularity_to_watching_repos.py new file mode 100644 index 0000000..6802807 --- /dev/null +++ b/alembic/versions/d4d2c5aa8a0_add_granularity_to_watching_repos.py @@ -0,0 +1,75 @@ +"""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=False, server_default='false')) + op.add_column('watchers', sa.Column('watch_issues', sa.Boolean(), + nullable=False, server_default='false')) + # 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: + # Remove the server_default now that we've set values + b.alter_column('watch_issues', server_default=None) + b.alter_column('watch_commits', server_default=None) + # Remove the watch column + b.drop_column('watch') + + +def downgrade(): + op.add_column('watchers', sa.Column('watch', sa.BOOLEAN(), nullable=False, + server_default='false')) + + # 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: + # Remove the server_default now that we've set values + b.alter_column('watch', server_default=None) + # Drop the added columns + b.drop_column('watch_issues') + b.drop_column('watch_commits') diff --git a/pagure-logcom/pagure_logcom_server.py b/pagure-logcom/pagure_logcom_server.py index 29bf9d4..bc48382 100644 --- a/pagure-logcom/pagure_logcom_server.py +++ b/pagure-logcom/pagure_logcom_server.py @@ -42,7 +42,7 @@ import pagure.lib 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: @@ -62,7 +62,9 @@ def handle_messages(): "b7b4059c44d692d7df3227ce58ce01191e5407bd", "f8d0899bb6654590ffdef66b539fd3b8cf873b35", "9b6fdc48d3edab82d3de28953271ea52b0a96117" - ] + ], + "branch": "master", + "default_branch": "master" } ''' @@ -89,6 +91,8 @@ def handle_messages(): 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 @@ -110,8 +114,14 @@ def handle_messages(): _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() diff --git a/pagure/__init__.py b/pagure/__init__.py index f1ee87d..7f14cb9 100644 --- a/pagure/__init__.py +++ b/pagure/__init__.py @@ -426,16 +426,6 @@ def inject_variables(): 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 @@ def inject_variables(): admin=user_admin, authenticated=authenticated(), forkbuttonform=forkbuttonform, - is_watching=is_watching, new_user=new_user, ) @@ -502,6 +491,12 @@ def set_variables(): 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 diff --git a/pagure/hooks/files/default_hook.py b/pagure/hooks/files/default_hook.py index 790d8d6..ef000b2 100755 --- a/pagure/hooks/files/default_hook.py +++ b/pagure/hooks/files/default_hook.py @@ -60,29 +60,37 @@ def run_as_post_receive_hook(): 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 diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py index 4ed0312..0890b19 100644 --- a/pagure/lib/__init__.py +++ b/pagure/lib/__init__.py @@ -1982,14 +1982,14 @@ def search_projects( 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 @@ def search_projects( 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 @@ def _get_project(session, name, user=None, namespace=None): ).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 @@ def search_issues( 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 get_pull_request_of_user(session, username): 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,52 @@ def update_watch_status(session, project, user, watch): 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 just watching issues and PRs on this project' + elif should_watch_commits: + return 'You are now just 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, reponame, 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 - + return [] + # If we can't find the user in the database, we can't determine their watch + # level user_obj = search_user(session, username=user.username) if not user_obj: - return False + return [] query = session.query( model.Watcher @@ -3622,11 +3645,11 @@ def is_watching(session, user, reponame, repouser=None, namespace=None): ).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 ) if namespace is not None: @@ -3635,29 +3658,46 @@ def is_watching(session, user, reponame, repouser=None, namespace=None): ) 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 + 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 [] project = pagure.get_authorized_project( session, reponame, user=repouser, namespace=namespace) + # If the project is not found, we can't determine the involvement of the + # user in the project if not project: - return False - + return [] + # If the user is the project owner, by default they will be watching + # issues and PRs if user.username == project.user.username: - return True - + 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 - + 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 + 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 +3712,9 @@ def user_watch_list(session, user, exclude_groups=None): ).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 +3726,9 @@ def user_watch_list(session, user, exclude_groups=None): ).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 +3854,7 @@ def get_watch_list(session, obj): 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: diff --git a/pagure/lib/git.py b/pagure/lib/git.py index 90910f3..ccb1f25 100644 --- a/pagure/lib/git.py +++ b/pagure/lib/git.py @@ -1148,6 +1148,14 @@ def get_author_email(commit, abspath): 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. ''' diff --git a/pagure/lib/model.py b/pagure/lib/model.py index d7b1e1a..011a6e3 100644 --- a/pagure/lib/model.py +++ b/pagure/lib/model.py @@ -442,12 +442,6 @@ class Project(BASE): 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 @@ class Project(BASE): ).filter( Issue.status == 'Open' ).filter( - Issue.private == False + Issue.private == False # noqa: E712 ).count() @property @@ -2055,9 +2049,8 @@ class Watcher(BASE): 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], diff --git a/pagure/lib/notify.py b/pagure/lib/notify.py index c6a2777..6435ed3 100644 --- a/pagure/lib/notify.py +++ b/pagure/lib/notify.py @@ -135,14 +135,6 @@ def _get_emails_for_obj(obj): 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 @@ def _get_emails_for_obj(obj): 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 @@ def _get_emails_for_obj(obj): 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 @@ Your pagure admin. 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 + ) diff --git a/pagure/templates/repo_master.html b/pagure/templates/repo_master.html index 734dc0b..25c68fe 100644 --- a/pagure/templates/repo_master.html +++ b/pagure/templates/repo_master.html @@ -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 %}
@@ -62,24 +74,9 @@ Fork {% endif %} {% endif %} - @@ -307,20 +306,32 @@ {{ super() }} {% endblock %} diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py index 422b4a8..5e4acd5 100644 --- a/pagure/ui/repo.py +++ b/pagure/ui/repo.py @@ -2261,7 +2261,7 @@ def view_project_activity(repo, namespace=None): 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 @@ def watch_repo(repo, watch, username=None, namespace=None): 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: diff --git a/tests/test_pagure_flask_ui_repo.py b/tests/test_pagure_flask_ui_repo.py index 642b227..5c92b83 100644 --- a/tests/test_pagure_flask_ui_repo.py +++ b/tests/test_pagure_flask_ui_repo.py @@ -4123,20 +4123,33 @@ index 0000000..fb7093d 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( '\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( '\n You are now' - ' watching this repo.', output.data) + ' just watching issues and PRs on this project', output.data) + + output = self.app.post( + '/test/watch/settings/2', data=data, follow_redirects=True) + self.assertIn( + '\n You are now' + ' just watching commits on this project', output.data) + + output = self.app.post( + '/test/watch/settings/3', data=data, follow_redirects=True) + self.assertIn( + ('\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 @@ index 0000000..fb7093d follow_redirects=True) self.assertIn( '\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( '\n You are now' - ' watching this repo.', output.data) + ' just 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( + '\n You are now' + ' just watching commits on this project', output.data) + + output = self.app.post( + '/fork/foo/test/watch/settings/3', data=data, + follow_redirects=True) + self.assertIn( + ('\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 @@ index 0000000..fb7093d '\n Watch status reset', output.data) - def test_delete_report(self): """ Test the delete_report endpoint. """ diff --git a/tests/test_pagure_lib.py b/tests/test_pagure_lib.py index a3cd9ff..58e6363 100644 --- a/tests/test_pagure_lib.py +++ b/tests/test_pagure_lib.py @@ -3143,10 +3143,20 @@ class PagureLibtests(tests.Modeltests): 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 @@ class PagureLibtests(tests.Modeltests): 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 just 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 @@ class PagureLibtests(tests.Modeltests): 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', ) - 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', ) - self.assertFalse(watch) + self.assertEqual(watch_level, []) pagure.lib.add_group_to_project( session=self.session, @@ -3232,56 +3243,97 @@ class PagureLibtests(tests.Modeltests): # 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', ) - 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', ) - 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, + reponame='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 just watching commits on this project') + + # From watchers table + watch_level = pagure.lib.get_watch_level_on_repo( + session=self.session, + user=user, + reponame='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 just 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', ) - 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', ) - self.assertFalse(watch) + self.assertEqual(watch_level, []) # Add a contributor to the project item = pagure.lib.model.User( @@ -3306,12 +3358,12 @@ class PagureLibtests(tests.Modeltests): # 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', ) - self.assertTrue(watch) + self.assertEqual(watch_level, ['issues']) def test_user_watch_list(self): ''' test user watch list method of pagure.lib ''' diff --git a/tests/test_pagure_lib_notify.py b/tests/test_pagure_lib_notify.py index 1f6e891..2c4074e 100644 --- a/tests/test_pagure_lib_notify.py +++ b/tests/test_pagure_lib_notify.py @@ -162,8 +162,9 @@ class PagureLibNotifytests(tests.Modeltests): # 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 just 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 @@ class PagureLibNotifytests(tests.Modeltests): # 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 just 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) diff --git a/tests/test_pagure_lib_watch_list.py b/tests/test_pagure_lib_watch_list.py index c2b075d..cb0d5ed 100644 --- a/tests/test_pagure_lib_watch_list.py +++ b/tests/test_pagure_lib_watch_list.py @@ -309,10 +309,10 @@ class PagureLibGetWatchListtests(tests.Modeltests): 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 @@ class PagureLibGetWatchListtests(tests.Modeltests): 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 just watching issues and PRs on this project') # Create the pull-request req = pagure.lib.new_pull_request( @@ -492,10 +493,11 @@ class PagureLibGetWatchListtests(tests.Modeltests): 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 just watching issues and PRs on this project') # Create the ticket iss = pagure.lib.new_issue( From a47c0d60af8f6f7ad3718cba5ecad5ff681e9d2f Mon Sep 17 00:00:00 2001 From: Matt Prahl Date: May 09 2017 20:24:31 +0000 Subject: [PATCH 7/9] Remove server_default in the add_granularity_to_watching_repos migration --- diff --git a/alembic/versions/d4d2c5aa8a0_add_granularity_to_watching_repos.py b/alembic/versions/d4d2c5aa8a0_add_granularity_to_watching_repos.py index 6802807..fca2de2 100644 --- a/alembic/versions/d4d2c5aa8a0_add_granularity_to_watching_repos.py +++ b/alembic/versions/d4d2c5aa8a0_add_granularity_to_watching_repos.py @@ -27,9 +27,9 @@ watcher_helper = sa.Table( def upgrade(): op.add_column('watchers', sa.Column('watch_commits', sa.Boolean(), - nullable=False, server_default='false')) + nullable=True)) op.add_column('watchers', sa.Column('watch_issues', sa.Boolean(), - nullable=False, server_default='false')) + nullable=True)) # This section is to update the `watch_issues` and `watch_commits` columns # with the value of `watch` connection = op.get_bind() @@ -44,16 +44,15 @@ def upgrade(): ) with op.batch_alter_table('watchers') as b: - # Remove the server_default now that we've set values - b.alter_column('watch_issues', server_default=None) - b.alter_column('watch_commits', server_default=None) + # 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=False, - server_default='false')) + 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` @@ -68,8 +67,8 @@ def downgrade(): ) with op.batch_alter_table('watchers') as b: - # Remove the server_default now that we've set values - b.alter_column('watch', server_default=None) + # 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') From 733eaa20e051fb53943a69d4595c256bdfc712ec Mon Sep 17 00:00:00 2001 From: Matt Prahl Date: May 09 2017 20:24:31 +0000 Subject: [PATCH 8/9] Add a project watchers API endpoint --- diff --git a/pagure/api/project.py b/pagure/api/project.py index f51684c..1839828 100644 --- a/pagure/api/project.py +++ b/pagure/api/project.py @@ -66,6 +66,83 @@ def api_git_tags(repo, username=None, namespace=None): return jsonout +@API.route('//watchers') +@API.route('///watchers') +@API.route('/fork///watchers') +@API.route('/fork////watchers') +@api_method +def api_project_watchers(repo, username=None, namespace=None): + ''' + Project watchers + ---------------- + List the watchers on the project. + + :: + + GET /api/0//watchers + GET /api/0///watchers + + :: + + GET /api/0/fork///watchers + GET /api/0/fork////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('//git/branches') @API.route('///git/branches') @API.route('/fork///git/branches') diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py index 0890b19..bfcb038 100644 --- a/pagure/lib/__init__.py +++ b/pagure/lib/__init__.py @@ -3616,47 +3616,47 @@ def update_watch_status(session, project, user, watch): return 'You are no longer watching this project' -def get_watch_level_on_repo(session, user, reponame, repouser=None, +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 [] + 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 - user_obj = search_user(session, username=user.username) if not user_obj: 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 ).filter( 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 # noqa: E712 - ) - else: - query = query.filter( - model.Project.is_fork == False # noqa: E712 - ) - - 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 @@ -3672,27 +3672,20 @@ def get_watch_level_on_repo(session, user, reponame, repouser=None, # the user explicitly asked to not be notified return [] - project = pagure.get_authorized_project( - session, reponame, user=repouser, namespace=namespace) - - # If the project is not found, we can't determine the involvement of the - # user in the project - if not project: - return [] # If the user is the project owner, by default they will be watching # issues and PRs - if user.username == project.user.username: + 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: + 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: + 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 diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py index 46e5b40..baa179d 100644 --- a/tests/test_pagure_flask_api_project.py +++ b/tests/test_pagure_flask_api_project.py @@ -532,6 +532,194 @@ class PagureFlaskApiProjecttests(tests.Modeltests): } 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. """ diff --git a/tests/test_pagure_lib.py b/tests/test_pagure_lib.py index 58e6363..a0d648c 100644 --- a/tests/test_pagure_lib.py +++ b/tests/test_pagure_lib.py @@ -3208,7 +3208,7 @@ class PagureLibtests(tests.Modeltests): watch_level = pagure.lib.get_watch_level_on_repo( session=self.session, user=None, - reponame='test', + repo='test', ) self.assertEqual(watch_level, []) @@ -3218,7 +3218,7 @@ class PagureLibtests(tests.Modeltests): watch_level = pagure.lib.get_watch_level_on_repo( session=self.session, user=user, - reponame='test', + repo='test', ) self.assertEqual(watch_level, []) @@ -3246,7 +3246,7 @@ class PagureLibtests(tests.Modeltests): msg = watch_level = pagure.lib.get_watch_level_on_repo( session=self.session, user=user, - reponame='test', + repo='test', ) self.assertEqual(watch_level, ['issues']) @@ -3255,7 +3255,7 @@ class PagureLibtests(tests.Modeltests): watch_level = pagure.lib.get_watch_level_on_repo( session=self.session, user=user, - reponame='test', + repo='test', ) self.assertEqual(watch_level, ['issues']) @@ -3275,7 +3275,7 @@ class PagureLibtests(tests.Modeltests): watch_level = pagure.lib.get_watch_level_on_repo( session=self.session, user=user, - reponame='test', + repo='test', ) self.assertEqual(['issues', 'commits'], watch_level) @@ -3294,7 +3294,7 @@ class PagureLibtests(tests.Modeltests): watch_level = pagure.lib.get_watch_level_on_repo( session=self.session, user=user, - reponame='test', + repo='test', ) self.assertEqual(['commits'], watch_level) @@ -3313,7 +3313,7 @@ class PagureLibtests(tests.Modeltests): watch_level = pagure.lib.get_watch_level_on_repo( session=self.session, user=user, - reponame='test', + repo='test', ) self.assertEqual(['issues'], watch_level) @@ -3331,7 +3331,7 @@ class PagureLibtests(tests.Modeltests): watch_level = pagure.lib.get_watch_level_on_repo( session=self.session, user=user, - reponame='test', + repo='test', ) self.assertEqual(watch_level, []) @@ -3361,7 +3361,7 @@ class PagureLibtests(tests.Modeltests): watch_level = pagure.lib.get_watch_level_on_repo( session=self.session, user=user, - reponame='test', + repo='test', ) self.assertEqual(watch_level, ['issues']) From d7ac6648359ad36ec5b53bd4d67e528f8bf46c72 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: May 12 2017 20:13:37 +0000 Subject: [PATCH 9/9] Small wording adjustment Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py index bfcb038..5f52795 100644 --- a/pagure/lib/__init__.py +++ b/pagure/lib/__init__.py @@ -3609,9 +3609,9 @@ def update_watch_status(session, project, user, watch): 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 just watching issues and PRs on this project' + return 'You are now watching issues and PRs on this project' elif should_watch_commits: - return 'You are now just watching commits on this project' + return 'You are now watching commits on this project' else: return 'You are no longer watching this project' diff --git a/tests/test_pagure_flask_ui_repo.py b/tests/test_pagure_flask_ui_repo.py index 5c92b83..34d14ee 100644 --- a/tests/test_pagure_flask_ui_repo.py +++ b/tests/test_pagure_flask_ui_repo.py @@ -4136,13 +4136,13 @@ index 0000000..fb7093d '/test/watch/settings/1', data=data, follow_redirects=True) self.assertIn( '\n You are now' - ' just watching issues and PRs on this project', 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( '\n You are now' - ' just watching commits on this project', output.data) + ' watching commits on this project', output.data) output = self.app.post( '/test/watch/settings/3', data=data, follow_redirects=True) @@ -4183,14 +4183,14 @@ index 0000000..fb7093d follow_redirects=True) self.assertIn( '\n You are now' - ' just watching issues and PRs on this project', 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( '\n You are now' - ' just watching commits on this project', output.data) + ' watching commits on this project', output.data) output = self.app.post( '/fork/foo/test/watch/settings/3', data=data, diff --git a/tests/test_pagure_lib.py b/tests/test_pagure_lib.py index a0d648c..3d93f52 100644 --- a/tests/test_pagure_lib.py +++ b/tests/test_pagure_lib.py @@ -3175,7 +3175,7 @@ class PagureLibtests(tests.Modeltests): ) self.session.commit() self.assertEqual( - msg, 'You are now just watching issues and PRs on this project') + 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( @@ -3288,7 +3288,7 @@ class PagureLibtests(tests.Modeltests): ) self.session.commit() self.assertEqual( - msg, 'You are now just watching commits on this project') + msg, 'You are now watching commits on this project') # From watchers table watch_level = pagure.lib.get_watch_level_on_repo( @@ -3307,7 +3307,7 @@ class PagureLibtests(tests.Modeltests): ) self.session.commit() self.assertEqual( - msg, 'You are now just watching issues and PRs on this project') + msg, 'You are now watching issues and PRs on this project') # From watchers table watch_level = pagure.lib.get_watch_level_on_repo( diff --git a/tests/test_pagure_lib_notify.py b/tests/test_pagure_lib_notify.py index 2c4074e..9463f84 100644 --- a/tests/test_pagure_lib_notify.py +++ b/tests/test_pagure_lib_notify.py @@ -164,7 +164,7 @@ class PagureLibNotifytests(tests.Modeltests): repo = pagure.get_authorized_project(self.session, 'test3', namespace='ns') out = pagure.lib.update_watch_status(self.session, repo, 'bar', '1') self.assertEqual( - out, 'You are now just watching issues and PRs on this project') + 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) @@ -326,7 +326,7 @@ class PagureLibNotifytests(tests.Modeltests): repo = pagure.get_authorized_project(self.session, 'test') out = pagure.lib.update_watch_status(self.session, repo, 'bar', '1') self.assertEqual( - out, 'You are now just watching issues and PRs on this project') + 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) diff --git a/tests/test_pagure_lib_watch_list.py b/tests/test_pagure_lib_watch_list.py index cb0d5ed..0cf88df 100644 --- a/tests/test_pagure_lib_watch_list.py +++ b/tests/test_pagure_lib_watch_list.py @@ -436,7 +436,7 @@ class PagureLibGetWatchListtests(tests.Modeltests): ) self.session.commit() self.assertEqual( - msg, 'You are now just watching issues and PRs on this project') + msg, 'You are now watching issues and PRs on this project') # Create the pull-request req = pagure.lib.new_pull_request( @@ -497,7 +497,7 @@ class PagureLibGetWatchListtests(tests.Modeltests): ) self.session.commit() self.assertEqual( - msg, 'You are now just watching issues and PRs on this project') + msg, 'You are now watching issues and PRs on this project') # Create the ticket iss = pagure.lib.new_issue(