From 241908b27c76bb605c39c787cd39e7cc394d0722 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 1/16] Issue 1747 - Adda notification comment after updating metadata


Whne editing an Issue's metadata start building a string of comments for each field updated.  Then add a single notification comment that describes who changed what field and to what value.  This requires returning a "edit comment", along withthe orignal message, for each type of metadata field we update.

---

diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py
index 377bcfe..c78554b 100644
--- a/pagure/lib/__init__.py
+++ b/pagure/lib/__init__.py
@@ -396,6 +396,10 @@ def add_issue_assignee(session, issue, assignee, user, ticketfolder,
                        notify=True):
     ''' Add an assignee to an issue, in other words, assigned an issue. '''
     user_obj = get_user(session, user)
+    if issue.assignee is None or issue.assignee == "":
+        old_assignee = '\"\"'
+    else:
+        old_assignee = issue.assignee
 
     if not assignee and issue.assignee is not None:
         issue.assignee_id = None
@@ -404,7 +408,7 @@ def add_issue_assignee(session, issue, assignee, user, ticketfolder,
         session.commit()
         pagure.lib.git.update_git(
             issue, repo=issue.project, repofolder=ticketfolder)
-
+        comment = '**Assignee** removed ``%s``' % (old_assignee.user)
         if notify:
             pagure.lib.notify.notify_assigned_issue(issue, None, user_obj)
 
@@ -425,19 +429,26 @@ def add_issue_assignee(session, issue, assignee, user, ticketfolder,
             REDIS.publish('pagure.%s' % issue.uid, json.dumps(
                 {'unassigned': '-'}))
 
-        return 'Assignee reset'
+        return 'Assignee reset', comment
     elif not assignee and issue.assignee is None:
-        return 'Nothing to change'
+        return 'Nothing to change', ""
 
     # Validate the assignee
     assignee_obj = get_user(session, assignee)
 
     if issue.assignee_id != assignee_obj.id:
+        if issue.assignee_id is None:
+            comment = '**Assignee** set to ``%s``' % (assignee_obj.user)
+        else:
+            comment = '**Assignee** changed from ``%s`` to ``%s``' % (
+                old_assignee, assignee_obj.user)
+
         issue.assignee_id = assignee_obj.id
         session.add(issue)
         session.flush()
         pagure.lib.git.update_git(
             issue, repo=issue.project, repofolder=ticketfolder)
+
         if notify:
             pagure.lib.notify.notify_assigned_issue(
                 issue, assignee_obj, user_obj)
@@ -460,7 +471,9 @@ def add_issue_assignee(session, issue, assignee, user, ticketfolder,
             REDIS.publish('pagure.%s' % issue.uid, json.dumps(
                 {'assigned': assignee_obj.to_json(public=True)}))
 
-        return 'Issue assigned'
+        return 'Issue assigned', comment
+    else:
+        return "", ""
 
 
 def add_pull_request_assignee(
@@ -1395,9 +1408,21 @@ def new_tag(session, tag_name, tag_description, tag_color, project_id):
     return tagobj
 
 
+def build_meta_comment(comment, field, old_value, new_value):
+    ''' Format a new comment for metadata changes and add it to the existing
+    comment.  Convert 'None' and empty values to something more friendly.
+    '''
+    if old_value is None or old_value == "":
+        old_value = '\"\"'
+    if new_value is None or new_value == "":
+        new_value = '\"\"'
+    return ("**%s** changed from ``%s`` to ``%s``\n%s" %
+            (field, old_value, new_value, comment))
+
+
 def edit_issue(session, issue, ticketfolder, user,
                title=None, content=None, status=None, close_status=-1,
-               priority=None, milestone=None, private=False):
+               priority=None, milestone=-1, private=False):
     ''' Edit the specified issue.
     '''
     user_obj = get_user(session, user)
@@ -1410,13 +1435,18 @@ def edit_issue(session, issue, ticketfolder, user,
                     'depending that are still open.')
 
     edit = []
+    edit_comment = ""
     if title and title != issue.title:
+        edit_comment = build_meta_comment(
+            edit_comment, "Title", issue.title, title)
         issue.title = title
         edit.append('title')
     if content and content != issue.content:
         issue.content = content
         edit.append('content')
     if status and status != issue.status:
+        edit_comment = build_meta_comment(
+            edit_comment, "Status", issue.status, status)
         issue.status = status
         if status.lower() != 'open':
             issue.closed_at = datetime.datetime.utcnow()
@@ -1425,6 +1455,8 @@ def edit_issue(session, issue, ticketfolder, user,
             edit.append('close_status')
         edit.append('status')
     if close_status != -1 and close_status != issue.close_status:
+        edit_comment = build_meta_comment(
+            edit_comment, "Closed as", issue.close_status, close_status)
         issue.close_status = close_status
         edit.append('close_status')
     if priority:
@@ -1433,12 +1465,18 @@ def edit_issue(session, issue, ticketfolder, user,
         except:
             priority = None
         if priority != issue.priority:
+            edit_comment = build_meta_comment(
+                edit_comment, "Priority", issue.priority, priority)
             issue.priority = priority
             edit.append('priority')
     if private in [True, False] and private != issue.private:
+        edit_comment = build_meta_comment(
+            edit_comment, "Private", str(issue.private), str(private))
         issue.private = private
         edit.append('private')
-    if milestone != issue.milestone:
+    if milestone != -1 and milestone != issue.milestone:
+        edit_comment = build_meta_comment(
+            edit_comment, "Milestone", issue.milestone, milestone)
         issue.milestone = milestone
         edit.append('milestone')
     issue.last_updated = datetime.datetime.utcnow()
@@ -1449,16 +1487,6 @@ def edit_issue(session, issue, ticketfolder, user,
         issue, repo=issue.project, repofolder=ticketfolder)
 
     if 'status' in edit:
-        add_issue_comment(
-            session,
-            issue,
-            comment='@%s changed the status to ``%s``' % (
-                user_obj.username, status),
-            user=user,
-            ticketfolder=ticketfolder,
-            notify=False,
-            notification=True,
-        )
         log_action(session, status.lower(), issue, user_obj)
         pagure.lib.notify.notify_status_change_issue(issue, user_obj)
 
@@ -1490,7 +1518,9 @@ def edit_issue(session, issue, ticketfolder, user,
     if edit:
         session.add(issue)
         session.flush()
-        return 'Successfully edited issue #%s' % issue.id
+        return 'Successfully edited issue #%s' % issue.id, edit_comment
+    else:
+        return "", ""
 
 
 def update_project_settings(session, repo, settings, user):
@@ -2486,6 +2516,7 @@ def update_tags(session, obj, tags, username, ticketfolder):
     toadd = set(tags) - set(obj.tags_text)
     torm = set(obj.tags_text) - set(tags)
     messages = []
+    comment = ""
     if toadd:
         messages.append(
             add_tag_obj(
@@ -2496,6 +2527,10 @@ def update_tags(session, obj, tags, username, ticketfolder):
                 ticketfolder=ticketfolder,
             )
         )
+        if len(toadd) == 1:
+            comment += "**Tags** added tag: ``%s``\n" % list(toadd)[0]
+        else:
+            comment += "**Tags** added tags: ``" + ', '.join(toadd) + "``\n"
 
     if torm:
         messages.append(
@@ -2507,9 +2542,14 @@ def update_tags(session, obj, tags, username, ticketfolder):
                 ticketfolder=ticketfolder,
             )
         )
+        if len(torm) == 1:
+            comment += "**Tags** removed tag: ``%s\n``" % list(torm)[0]
+        else:
+            comment += "**Tags** removed tags: ``" + ', '.join(torm) + "``\n"
+
     session.commit()
 
-    return messages
+    return messages, comment
 
 
 def update_dependency_issue(
@@ -2523,8 +2563,11 @@ def update_dependency_issue(
     toadd = set(depends) - set(issue.depends_text)
     torm = set(issue.depends_text) - set(depends)
     messages = []
+    comment = ""
 
     # Add issue depending
+    if toadd:
+        comment += "**Depends on** added dependencies: ``"
     for depend in toadd:
         issue_depend = search_issues(session, repo, issueid=depend)
         if issue_depend is None:
@@ -2542,8 +2585,14 @@ def update_dependency_issue(
                 ticketfolder=ticketfolder,
             )
         )
+        comment += "%s " % (depend)
+
+    if toadd:
+        comment += "``\n"
 
     # Remove issue depending
+    if torm:
+        comment += "**Depends on** removed issue dependencies: ``"
     for depend in torm:
         issue_depend = search_issues(session, repo, issueid=depend)
         if issue_depend is None:  # pragma: no cover
@@ -2563,9 +2612,13 @@ def update_dependency_issue(
                 ticketfolder=ticketfolder,
             )
         )
+        comment += "%s " % (depend)
+
+    if torm:
+        comment += "``\n"
 
     session.commit()
-    return messages
+    return messages, comment
 
 
 def update_blocked_issue(
@@ -2580,8 +2633,11 @@ def update_blocked_issue(
     toadd = set(blocks) - set(issue.blocks_text)
     torm = set(issue.blocks_text) - set(blocks)
     messages = []
+    comment = ""
 
     # Add issue blocked
+    if toadd:
+        comment += "**Blocked** added blocking issue dependencies: ``"
     for block in toadd:
         issue_block = search_issues(session, repo, issueid=block)
         if issue_block is None:
@@ -2600,8 +2656,14 @@ def update_blocked_issue(
             )
         )
         session.commit()
+        comment += "%s " % (block)
+
+    if toadd:
+        comment += "``\n"
 
     # Remove issue blocked
+    if torm:
+        comment += "**Blocked** remove blocking issue dependencies: ``"
     for block in torm:
         issue_block = search_issues(session, repo, issueid=block)
         if issue_block is None:  # pragma: no cover
@@ -2622,9 +2684,12 @@ def update_blocked_issue(
                 ticketfolder=ticketfolder,
             )
         )
+        comment += "%s " % (block)
 
+        if torm:
+            comment += "``\n"
     session.commit()
-    return messages
+    return messages, comment
 
 
 def add_user_pending_email(session, userobj, email):
@@ -3523,7 +3588,10 @@ def set_custom_key_value(session, issue, key, value):
     current_field = query.first()
     updated = False
     delete = False
+    old_value = None
+    comment = ""
     if current_field:
+        old_value = current_field.value
         if current_field.key.key_type == 'boolean':
             value = value or False
         if value is None or value == '':
@@ -3534,18 +3602,20 @@ def set_custom_key_value(session, issue, key, value):
             current_field.value = value
             updated = True
     else:
-        if value is None or value == '':
-            delete = True
-        else:
-            current_field = model.IssueValues(
-                issue_uid=issue.uid,
-                key_id=key.id,
-                value=value,
-            )
+        current_field = model.IssueValues(
+            issue_uid=issue.uid,
+            key_id=key.id,
+            value=value,
+        )
+        if value:
             updated = True
+
     if not delete:
         session.add(current_field)
 
+    if updated:
+        comment = build_meta_comment("", key.name, old_value, value)
+
     if REDIS and updated:
         if issue.private:
             REDIS.publish('pagure.%s' % issue.uid, json.dumps({
@@ -3558,14 +3628,14 @@ def set_custom_key_value(session, issue, key, value):
                 'issue': issue.to_json(public=True, with_comments=False),
             }))
 
-    return 'Custom field adjusted'
+    return comment
 
 
 def get_yearly_stats_user(session, user, date):
     """ Return the activity of the specified user in the year preceding the
     specified date.
     """
-    start_date = datetime.datetime(date.year -1, date.month, date.day)
+    start_date = datetime.datetime(date.year - 1, date.month, date.day)
 
     query = session.query(
         model.PagureLog.date, func.count(model.PagureLog.id)
@@ -3622,7 +3692,6 @@ def log_action(session, action, obj, user_obj):
     elif obj.isa == 'pull-request':
         setattr(log, 'pull_request_uid', obj.uid)
 
-
     session.add(log)
     session.commit()
 
diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py
index 09747b0..8463d79 100644
--- a/pagure/ui/issues.py
+++ b/pagure/ui/issues.py
@@ -194,6 +194,7 @@ def update_issue(repo, issueid, username=None, namespace=None):
 
         try:
             messages = set()
+            field_comments = ""
 
             # New comment
             if comment:
@@ -213,36 +214,43 @@ def update_issue(repo, issueid, username=None, namespace=None):
             # Update status
             if repo_admin or flask.g.fas_user.username == issue.user.user:
                 if new_status in status:
-                    message = pagure.lib.edit_issue(
+                    message, new_comment = pagure.lib.edit_issue(
                         SESSION,
                         issue=issue,
                         status=new_status,
                         close_status=close_status,
                         private=issue.private,
                         user=flask.g.fas_user.username,
-                        ticketfolder=APP.config['TICKETS_FOLDER'],
+                        ticketfolder=APP.config['TICKETS_FOLDER']
                     )
                     SESSION.commit()
                     if message:
                         messages.add(message)
+                    if new_comment != "":
+                        field_comments = ("%s\n%s" %
+                                          (field_comments, new_comment))
 
             # All the other meta-data can be changed only by admins
             # while other field will be missing for non-admin and thus
             # reset if we let them
             if repo_admin:
                 # Adjust (add/remove) tags
-                messages.union(set(pagure.lib.update_tags(
+                msgs, new_comment = pagure.lib.update_tags(
                     SESSION, issue, tags,
                     username=flask.g.fas_user.username,
                     ticketfolder=APP.config['TICKETS_FOLDER']
-                )))
+                )
+                messages.union(set(msgs))
+                if new_comment != "":
+                    field_comments = ("%s\n%s" %
+                                      (field_comments, new_comment))
 
             # The meta-data can be changed by admins and issue creator,
             # where issue creators can only change status of their issue while
             # other fields will be missing for non-admin and thus reset if we let them
             if repo_admin:
                 # Assign or update assignee of the ticket
-                message = pagure.lib.add_issue_assignee(
+                message, new_comment = pagure.lib.add_issue_assignee(
                     SESSION,
                     issue=issue,
                     assignee=assignee or None,
@@ -252,26 +260,19 @@ def update_issue(repo, issueid, username=None, namespace=None):
                 SESSION.commit()
                 if message and message != 'Nothing to change':
                     messages.add(message)
-
-                # Update priority
-                if str(new_priority) in repo.priorities:
-                    message = pagure.lib.edit_issue(
-                        SESSION,
-                        issue=issue,
-                        priority=new_priority,
-                        private=issue.private,
-                        user=flask.g.fas_user.username,
-                        ticketfolder=APP.config['TICKETS_FOLDER'],
-                    )
-                    SESSION.commit()
-                    if message:
-                        messages.add(message)
-
-                # Update milestone and privacy setting
-                message = pagure.lib.edit_issue(
+                if new_comment != "":
+                    field_comments = ("%s\n%s" %
+                                      (field_comments, new_comment))
+                # Adjust priority if needed
+                if str(new_priority) not in repo.priorities:
+                    new_priority = None
+
+                # Update core metadata
+                message, new_comment = pagure.lib.edit_issue(
                     SESSION,
                     issue=issue,
                     milestone=new_milestone,
+                    priority=new_priority,
                     private=form.private.data,
                     user=flask.g.fas_user.username,
                     ticketfolder=APP.config['TICKETS_FOLDER'],
@@ -279,38 +280,67 @@ def update_issue(repo, issueid, username=None, namespace=None):
                 SESSION.commit()
                 if message:
                     messages.add(message)
+                if new_comment != "":
+                    field_comments = ("%s\n%s" %
+                                      (field_comments, new_comment))
 
                 # Update the custom keys/fields
+                edit_comment = ""
                 for key in repo.issue_keys:
                     value = flask.request.form.get(key.name)
-                    if key.key_type == 'link':
-                        links = value.split(',')
-                        for link in links:
-                            link = link.replace(' ', '')
-                            if not urlpattern.match(link):
-                                flask.abort(
-                                    400,
-                                    'Meta-data "link" field '
-                                    '(%s) has invalid url (%s) ' %
-                                    (key.name, link))
-                    messages.add(
-                        pagure.lib.set_custom_key_value(
-                            SESSION, issue, key, value)
-                    )
+                    if value:
+                        if key.key_type == 'link':
+                            links = value.split(',')
+                            for link in links:
+                                link = link.replace(' ', '')
+                                if not urlpattern.match(link):
+                                    flask.abort(
+                                        400,
+                                        'Meta-data "link" field '
+                                        '(%s) has invalid url (%s) ' %
+                                        (key.name, link))
+
+                    new_comment = pagure.lib.set_custom_key_value(
+                        SESSION, issue, key, value)
+                    if new_comment is not "":
+                        edit_comment = "%s%s" % (new_comment, edit_comment)
+
+                if edit_comment is not "":
+                    field_comments = ("%s%s" %
+                                      (field_comments, edit_comment))
 
                 # Update ticket this one depends on
-                messages.union(set(pagure.lib.update_dependency_issue(
+                msgs, new_comment = pagure.lib.update_dependency_issue(
                     SESSION, repo, issue, depends,
                     username=flask.g.fas_user.username,
-                    ticketfolder=APP.config['TICKETS_FOLDER'],
-                )))
+                    ticketfolder=APP.config['TICKETS_FOLDER'])
+                messages.union(set(msgs))
+                if new_comment != "":
+                    field_comments = ("%s%s" %
+                                      (field_comments, new_comment))
 
                 # Update ticket(s) depending on this one
-                messages.union(set(pagure.lib.update_blocked_issue(
+                msgs, new_comment = pagure.lib.update_blocked_issue(
                     SESSION, repo, issue, blocks,
                     username=flask.g.fas_user.username,
-                    ticketfolder=APP.config['TICKETS_FOLDER'],
-                )))
+                    ticketfolder=APP.config['TICKETS_FOLDER'],)
+                messages.union(set(msgs))
+                if new_comment != "":
+                    field_comments = ("%s%s" %
+                                      (field_comments, new_comment))
+
+                # Add the comment for field updates:
+                if field_comments != "":
+                    pagure.lib.add_issue_comment(
+                        SESSION,
+                        issue,
+                        comment='@%s updated metadata\n%s' % (
+                            flask.g.fas_user.username, field_comments),
+                        user=flask.g.fas_user.username,
+                        ticketfolder=APP.config['TICKETS_FOLDER'],
+                        notify=False,
+                        notification=True)
+                    messages.add('Metadata fields updated')
 
             if not is_js:
                 for message in messages:
@@ -1080,7 +1110,7 @@ def edit_issue(repo, issueid, username=None, namespace=None):
                     flask.g.fas_user.username))
 
         try:
-            message = pagure.lib.edit_issue(
+            message, comment = pagure.lib.edit_issue(
                 SESSION,
                 issue=issue,
                 title=title,
@@ -1091,6 +1121,15 @@ def edit_issue(repo, issueid, username=None, namespace=None):
                 private=private,
             )
             SESSION.commit()
+            if comment != "":
+                pagure.lib.add_issue_comment(
+                    SESSION,
+                    issue,
+                    comment=comment,
+                    user=flask.g.fas_user.username,
+                    ticketfolder=APP.config['TICKETS_FOLDER'],
+                    notify=False,
+                    notification=True)
 
             # If there is a file attached, attach it.
             filestream = flask.request.files.get('filestream')
diff --git a/tests/test_pagure_flask_api_issue.py b/tests/test_pagure_flask_api_issue.py
index 33c99bc..1616fb6 100644
--- a/tests/test_pagure_flask_api_issue.py
+++ b/tests/test_pagure_flask_api_issue.py
@@ -1075,7 +1075,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': 'No changes'}
+            {'message': ['', '']}
         )
 
         # No change
@@ -1092,9 +1092,12 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
             '/api/0/test/issue/1/status', data=data, headers=headers)
         self.assertEqual(output.status_code, 200)
         data = json.loads(output.data)
+        print "MARK2\n\n" + str(data)
         self.assertDictEqual(
             data,
-            {'message': 'Successfully edited issue #1'}
+            {'message': ['Successfully edited issue #1',
+                         '**Closed as** changed from ``""`` to ``Fixed``\n'
+                         '**Status** changed from ``Open`` to ``Closed``\n']}
         )
 
         headers = {'Authorization': 'token pingou_foo'}
@@ -1506,7 +1509,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': 'Issue assigned'}
+            {'message': ['Issue assigned', '**Assignee** set to ``pingou``']}
         )
 
         # Un-assign
@@ -1516,7 +1519,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': 'Assignee reset'}
+            {'message': ['Assignee reset', '**Assignee** removed ``pingou``']}
         )
         repo = pagure.lib.get_project(self.session, 'test')
         issue = pagure.lib.search_issues(self.session, repo, issueid=1)
@@ -1530,7 +1533,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': 'Nothing to change'}
+            {'message': ['Nothing to change', '']}
         )
         repo = pagure.lib.get_project(self.session, 'test')
         issue = pagure.lib.search_issues(self.session, repo, issueid=1)
@@ -1544,7 +1547,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': 'Issue assigned'}
+            {'message': ['Issue assigned', '**Assignee** set to ``pingou``']}
         )
 
         # Un-assign
@@ -1555,7 +1558,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': 'Assignee reset'}
+            {'message': ['Assignee reset', '**Assignee** removed ``pingou``']}
         )
 
         # Re-assign for the rest of the tests
@@ -1566,7 +1569,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': 'Issue assigned'}
+            {'message': ['Issue assigned', '**Assignee** set to ``pingou``']}
         )
 
         # One comment added
@@ -1666,7 +1669,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': 'Issue assigned'}
+            {'message': ['Issue assigned', '**Assignee** set to ``pingou``']}
         )
 
     @patch('pagure.lib.git.update_git')
@@ -1964,7 +1967,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
                 self.assertEqual(
                     sorted(key.data), ['ack', 'nack', 'needs review'])
 
-        # Reset the value of the field to None
+        # Delete a value from a custom filed that does not exist in the entry
         output = self.app.post(
             '/api/0/test/issue/1/custom/bugzilla', headers=headers)
         self.assertEqual(output.status_code, 200)
@@ -1972,7 +1975,9 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         self.assertDictEqual(
             data,
             {
-              'message': 'Custom field adjusted'
+              "error": "An error occured at the database level and prevent "
+                       "the action from reaching completion",
+              "error_code": "EDBERROR",
             }
         )
 
@@ -2010,7 +2015,8 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         self.assertDictEqual(
             data,
             {
-              "message": "Custom field adjusted"
+              "message": '**bugzilla** changed from ``""`` to'
+                         ' ``https://bugzilla.redhat.com/1234``\n'
             }
         )
 
@@ -2024,7 +2030,8 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
 
         # Reset the value
         output = self.app.post(
-            '/api/0/test/issue/1/custom/bugzilla', headers=headers)
+            '/api/0/test/issue/1/custom/bugzilla', headers=headers,
+            data={'value': ''})
         self.assertEqual(output.status_code, 200)
         data = json.loads(output.data)
         self.assertDictEqual(
diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py
index 09b19b8..b93ee80 100644
--- a/tests/test_pagure_flask_api_project.py
+++ b/tests/test_pagure_flask_api_project.py
@@ -119,7 +119,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests):
         self.assertEqual(repo.tags, [])
 
         # Adding a tag
-        output = pagure.lib.update_tags(
+        output, comment = pagure.lib.update_tags(
             self.session, repo, 'infra', 'pingou',
             ticketfolder=None)
         self.assertEqual(output, ['Tag added: infra'])
@@ -317,7 +317,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests):
         self.assertEqual(repo.tags, [])
 
         # Adding a tag
-        output = pagure.lib.update_tags(
+        output, comment = pagure.lib.update_tags(
             self.session, repo, 'infra', 'pingou',
             ticketfolder=None)
         self.assertEqual(output, ['Tag added: infra'])
diff --git a/tests/test_pagure_flask_dump_load_ticket.py b/tests/test_pagure_flask_dump_load_ticket.py
index 3db09c5..1339a6b 100644
--- a/tests/test_pagure_flask_dump_load_ticket.py
+++ b/tests/test_pagure_flask_dump_load_ticket.py
@@ -123,7 +123,7 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
         self.session.commit()
         self.assertEqual(msg, 'Comment added')
         # Assign the ticket to someone
-        msg = pagure.lib.add_issue_assignee(
+        msg, comment = pagure.lib.add_issue_assignee(
             session=self.session,
             issue=issue,
             assignee='pingou',
diff --git a/tests/test_pagure_flask_ui_app.py b/tests/test_pagure_flask_ui_app.py
index 581c4a0..e3b3461 100644
--- a/tests/test_pagure_flask_ui_app.py
+++ b/tests/test_pagure_flask_ui_app.py
@@ -1145,7 +1145,7 @@ class PagureFlaskApptests(tests.Modeltests):
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue #3')
 
-        msg = pagure.lib.add_issue_assignee(
+        msg, comment = pagure.lib.add_issue_assignee(
             session=self.session,
             issue=msg,
             assignee='pingou',
diff --git a/tests/test_pagure_flask_ui_issues.py b/tests/test_pagure_flask_ui_issues.py
index f8c3c77..d992119 100644
--- a/tests/test_pagure_flask_ui_issues.py
+++ b/tests/test_pagure_flask_ui_issues.py
@@ -541,7 +541,7 @@ class PagureFlaskIssuestests(tests.Modeltests):
 
         # Add a non-ascii milestone to the issue but project has no milestone
         issue = pagure.lib.search_issues(self.session, repo, issueid=1)
-        message = pagure.lib.edit_issue(
+        message, comment = pagure.lib.edit_issue(
             self.session,
             issue=issue,
             milestone=b'käpy'.decode('utf-8'),
@@ -682,9 +682,9 @@ class PagureFlaskIssuestests(tests.Modeltests):
                 '<option selected value="Fixed">Fixed</option>'
                 in output.data)
             self.assertIn(
-                '<small><p><a href="{app_url}/user/pingou"> '
-                '@pingou</a> changed the status to <code>Closed</code>'
-                '</p></small>'.format(
+                '@pingou</a> updated metadata</p>\n<p><strong>Closed '
+                'as</strong> changed from <code>""</code> to <code>Fixed'
+                .format(
                     app_url=pagure.APP.config['APP_URL'].rstrip('/')),
                 output.data)
 
@@ -1953,8 +1953,8 @@ class PagureFlaskIssuestests(tests.Modeltests):
         user = tests.FakeUser(username='foo')
         with tests.user_set(pagure.APP, user):
             data = {
-                'csrf_token' : csrf_token,
-                'comment' : 'Nevermind figured it out',
+                'csrf_token': csrf_token,
+                'comment': 'Nevermind figured it out',
                 'status': 'Closed',
                 'close_status': 'Invalid'
             }
@@ -1978,8 +1978,8 @@ class PagureFlaskIssuestests(tests.Modeltests):
             )
 
             data = {
-                'csrf_token' : csrf_token,
-                'comment' : 'Nevermind figured it out',
+                'csrf_token': csrf_token,
+                'comment': 'Nevermind figured it out',
                 'status': 'Closed',
                 'close_status': 'Invalid'
             }
@@ -2007,14 +2007,14 @@ class PagureFlaskIssuestests(tests.Modeltests):
         self.assertEqual(len(issue.comments), 2)
         self.assertEqual(issue.status, 'Open')
 
-        # Ticket #2 has one more comment and is closed
+        # Ticket #2 has one less comment and is closed
         issue = pagure.lib.search_issues(self.session, repo, issueid=2)
-        self.assertEqual(len(issue.comments), 2)
+        self.assertEqual(len(issue.comments), 1)
         self.assertEqual(issue.status, 'Closed')
 
     @patch('pagure.lib.git.update_git')
     @patch('pagure.lib.notify.send_email')
-    def test_git_urls(self,  p_send_email, p_ugt):
+    def test_git_urls(self, p_send_email, p_ugt):
         """ Check that the url to the git repo for issues is present/absent when
         it should.
         """
diff --git a/tests/test_pagure_lib.py b/tests/test_pagure_lib.py
index 9bfb92e..aeee490 100644
--- a/tests/test_pagure_lib.py
+++ b/tests/test_pagure_lib.py
@@ -232,15 +232,15 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(repo.open_tickets_public, 2)
 
         # Edit the issue
-        msg = pagure.lib.edit_issue(
+        msg, comment = pagure.lib.edit_issue(
             session=self.session,
             issue=issue,
             user='pingou',
             ticketfolder=None)
         self.session.commit()
-        self.assertEqual(msg, None)
+        self.assertEqual(msg, None or '')
 
-        msg = pagure.lib.edit_issue(
+        msg, comment = pagure.lib.edit_issue(
             session=self.session,
             issue=issue,
             user='pingou',
@@ -250,9 +250,9 @@ class PagureLibtests(tests.Modeltests):
             status='Open',
         )
         self.session.commit()
-        self.assertEqual(msg, None)
+        self.assertEqual(msg, None or '')
 
-        msg = pagure.lib.edit_issue(
+        msg, comment = pagure.lib.edit_issue(
             session=self.session,
             issue=issue,
             user='pingou',
@@ -273,7 +273,7 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(repo.issues[1].close_status, 'Invalid')
 
         # Edit the status: re-open the ticket
-        msg = pagure.lib.edit_issue(
+        msg, comment = pagure.lib.edit_issue(
             session=self.session,
             issue=issue,
             user='pingou',
@@ -293,7 +293,7 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(repo.open_tickets_public, 1)
 
         # Edit the status: re-close the ticket
-        msg = pagure.lib.edit_issue(
+        msg, comment = pagure.lib.edit_issue(
             session=self.session,
             issue=issue,
             user='pingou',
@@ -685,7 +685,7 @@ class PagureLibtests(tests.Modeltests):
         )
 
         # Set the assignee by its email
-        msg = pagure.lib.add_issue_assignee(
+        msg, comment = pagure.lib.add_issue_assignee(
             session=self.session,
             issue=issue,
             assignee='foo@bar.com',
@@ -695,7 +695,7 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(msg, 'Issue assigned')
 
         # Change the assignee to someone else by its username
-        msg = pagure.lib.add_issue_assignee(
+        msg, comment = pagure.lib.add_issue_assignee(
             session=self.session,
             issue=issue,
             assignee='pingou',
@@ -732,7 +732,7 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(issues[0].tags, [])
 
         # Reset the assignee to no-one
-        msg = pagure.lib.add_issue_assignee(
+        msg, comment = pagure.lib.add_issue_assignee(
             session=self.session,
             issue=issue,
             assignee=None,
@@ -766,7 +766,7 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(len(issue.comments), 0)
 
         # Set the assignee by its email
-        msg = pagure.lib.add_issue_assignee(
+        msg, comment = pagure.lib.add_issue_assignee(
             session=self.session,
             issue=issue,
             assignee='foo@bar.com',
@@ -1979,7 +1979,7 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(repo.tags_colored, [])
         self.assertEqual(issue.tags_text, [])
 
-        messages = pagure.lib.update_tags(
+        messages, comment = pagure.lib.update_tags(
             self.session, issue, 'tag', 'pingou', ticketfolder=None)
         self.assertEqual(messages, ['Tag added: tag'])
 
@@ -1992,7 +1992,7 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(issue.tags_text, ['tag'])
 
         # Replace the tag by two others
-        messages = pagure.lib.update_tags(
+        messages, comment = pagure.lib.update_tags(
             self.session, issue, ['tag2', 'tag3'], 'pingou',
             ticketfolder=None)
         self.assertEqual(
@@ -2043,10 +2043,10 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(issue.depends_text, [])
         self.assertEqual(issue.blocks_text, [])
 
-        messages = pagure.lib.update_dependency_issue(
+        messages, comment = pagure.lib.update_dependency_issue(
             self.session, repo, issue, '2', 'pingou', ticketfolder=None)
         self.assertEqual(messages, ['Dependency added'])
-        messages = pagure.lib.update_dependency_issue(
+        messages, comment = pagure.lib.update_dependency_issue(
             self.session, repo, issue, ['3', '4', 5], 'pingou',
             ticketfolder=None)
         self.assertEqual(
@@ -2086,10 +2086,10 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(issue.depends_text, [])
         self.assertEqual(issue.blocks_text, [])
 
-        messages = pagure.lib.update_blocked_issue(
+        messages, comment = pagure.lib.update_blocked_issue(
             self.session, repo, issue, '2', 'pingou', ticketfolder=None)
         self.assertEqual(messages, ['Dependency added'])
-        messages = pagure.lib.update_blocked_issue(
+        messages, comment = pagure.lib.update_blocked_issue(
             self.session, repo, issue, ['3', '4', 5], 'pingou',
             ticketfolder=None)
         self.assertEqual(

From 540397aa29271c678652c140ea490a4182bbb64e Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 2/16] Remove duplicate new lines from update_tags function


---

diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py
index c78554b..c5a3d81 100644
--- a/pagure/lib/__init__.py
+++ b/pagure/lib/__init__.py
@@ -2528,9 +2528,9 @@ def update_tags(session, obj, tags, username, ticketfolder):
             )
         )
         if len(toadd) == 1:
-            comment += "**Tags** added tag: ``%s``\n" % list(toadd)[0]
+            comment += "**Tags** added tag: ``%s``" % list(toadd)[0]
         else:
-            comment += "**Tags** added tags: ``" + ', '.join(toadd) + "``\n"
+            comment += "**Tags** added tags: ``" + ', '.join(toadd) + "``"
 
     if torm:
         messages.append(
@@ -2542,10 +2542,12 @@ def update_tags(session, obj, tags, username, ticketfolder):
                 ticketfolder=ticketfolder,
             )
         )
+        if toadd:
+            comment += '\n'
         if len(torm) == 1:
-            comment += "**Tags** removed tag: ``%s\n``" % list(torm)[0]
+            comment += "**Tags** removed tag: ``%s``" % list(torm)[0]
         else:
-            comment += "**Tags** removed tags: ``" + ', '.join(torm) + "``\n"
+            comment += "**Tags** removed tags: ``" + ', '.join(torm) + "``"
 
     session.commit()
 

From b154f133c31f2fb6592a6ee0c0c182af0138da14 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 3/16] Convert the priority number to its string name


---

diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py
index c5a3d81..67b3453 100644
--- a/pagure/lib/__init__.py
+++ b/pagure/lib/__init__.py
@@ -1420,13 +1420,12 @@ def build_meta_comment(comment, field, old_value, new_value):
             (field, old_value, new_value, comment))
 
 
-def edit_issue(session, issue, ticketfolder, user,
+def edit_issue(session, issue, ticketfolder, user, repo=None,
                title=None, content=None, status=None, close_status=-1,
                priority=None, milestone=-1, private=False):
     ''' Edit the specified issue.
     '''
     user_obj = get_user(session, user)
-
     if status != 'Open' and issue.parents:
         for parent in issue.parents:
             if parent.status == 'Open':
@@ -1466,7 +1465,8 @@ def edit_issue(session, issue, ticketfolder, user,
             priority = None
         if priority != issue.priority:
             edit_comment = build_meta_comment(
-                edit_comment, "Priority", issue.priority, priority)
+                edit_comment, "Priority", repo.priorities[str(issue.priority)],
+                repo.priorities[str(priority)])
             issue.priority = priority
             edit.append('priority')
     if private in [True, False] and private != issue.private:
diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py
index 8463d79..dff8e4c 100644
--- a/pagure/ui/issues.py
+++ b/pagure/ui/issues.py
@@ -270,6 +270,7 @@ def update_issue(repo, issueid, username=None, namespace=None):
                 # Update core metadata
                 message, new_comment = pagure.lib.edit_issue(
                     SESSION,
+                    repo=repo,
                     issue=issue,
                     milestone=new_milestone,
                     priority=new_priority,

From 799d32760a9fa8ce6b84b2e5caa143d482b5ad88 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 4/16] Changed how old_assignee is determined


---

diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py
index 67b3453..53e54ef 100644
--- a/pagure/lib/__init__.py
+++ b/pagure/lib/__init__.py
@@ -396,10 +396,8 @@ def add_issue_assignee(session, issue, assignee, user, ticketfolder,
                        notify=True):
     ''' Add an assignee to an issue, in other words, assigned an issue. '''
     user_obj = get_user(session, user)
-    if issue.assignee is None or issue.assignee == "":
-        old_assignee = '\"\"'
-    else:
-        old_assignee = issue.assignee
+
+    old_assignee = issue.assignee if issue.assignee else '\"\"'
 
     if not assignee and issue.assignee is not None:
         issue.assignee_id = None

From eabdc83d4643765cb29531c34258383ec88be813 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 5/16] Added a metadata comment class for building the comment notification


---

diff --git a/pagure/api/issue.py b/pagure/api/issue.py
index 902ffaa..31c628a 100644
--- a/pagure/api/issue.py
+++ b/pagure/api/issue.py
@@ -16,6 +16,7 @@ from sqlalchemy.exc import SQLAlchemyError
 import pagure
 import pagure.exceptions
 import pagure.lib
+from pagure.lib import MetaComment
 from pagure import (
     APP, SESSION, is_repo_admin, api_authenticated, urlpattern
 )
@@ -569,7 +570,7 @@ def api_change_status_issue(repo, issueid, username=None, namespace=None):
     +----------------- +---------+--------------+------------------------+
     | ``status``       | string  | Mandatory    | The new status of the  |
     |                  |         |              | issue, can be 'Open' or|
-    |                  |         |              | 'Closed'               |                 |
+    |                  |         |              | 'Closed'               |
     +----------------- +---------+--------------+------------------------+
 
     Sample response
@@ -626,6 +627,7 @@ def api_change_status_issue(repo, issueid, username=None, namespace=None):
         form.status.data = new_status
 
     if form.validate_on_submit():
+        mcomment = MetaComment()
         try:
             # Update status
             message = pagure.lib.edit_issue(
@@ -635,12 +637,24 @@ def api_change_status_issue(repo, issueid, username=None, namespace=None):
                 close_status=close_status,
                 user=flask.g.fas_user.username,
                 ticketfolder=APP.config['TICKETS_FOLDER'],
+                mcomment=mcomment,
             )
             SESSION.commit()
             if message:
                 output['message'] = message
             else:
                 output['message'] = 'No changes'
+
+            if mcomment.is_set():
+                pagure.lib.add_issue_comment(
+                    SESSION,
+                    issue,
+                    comment='@%s updated metadata\n%s' % (
+                        flask.g.fas_user.username, mcomment.get()),
+                    user=flask.g.fas_user.username,
+                    ticketfolder=APP.config['TICKETS_FOLDER'],
+                    notify=False,
+                    notification=True)
         except pagure.exceptions.PagureException as err:
             raise pagure.exceptions.APIError(
                 400, error_code=APIERROR.ENOCODE, error=str(err))
@@ -830,6 +844,8 @@ def api_assign_issue(repo, issueid, username=None, namespace=None):
     form = pagure.forms.AssignIssueForm(csrf_enabled=False)
     if form.validate_on_submit():
         assignee = form.assignee.data or None
+        # Create our metadata comment object
+        mcomment = MetaComment()
         try:
             # New comment
             message = pagure.lib.add_issue_assignee(
@@ -838,8 +854,19 @@ def api_assign_issue(repo, issueid, username=None, namespace=None):
                 assignee=assignee,
                 user=flask.g.fas_user.username,
                 ticketfolder=APP.config['TICKETS_FOLDER'],
+                mcomment=mcomment
             )
             SESSION.commit()
+            if mcomment.is_set():
+                pagure.lib.add_issue_comment(
+                    SESSION,
+                    issue,
+                    comment='@%s updated metadata\n%s' % (
+                        flask.g.fas_user.username, mcomment.get()),
+                    user=flask.g.fas_user.username,
+                    ticketfolder=APP.config['TICKETS_FOLDER'],
+                    notify=False,
+                    notification=True)
             output['message'] = message
         except pagure.exceptions.PagureException as err:  # pragma: no cover
             raise pagure.exceptions.APIError(
@@ -1051,8 +1078,9 @@ def api_update_custom_field(
                     raise pagure.exceptions.APIError(
                         400, error_code=APIERROR.EINVALIDISSUEFIELD_LINK)
     try:
+        mcomment = MetaComment()
         message = pagure.lib.set_custom_key_value(
-            SESSION, issue, key, value)
+            SESSION, issue, key, value, mcomment=mcomment)
 
         SESSION.commit()
         if message:
@@ -1067,5 +1095,16 @@ def api_update_custom_field(
         SESSION.rollback()
         raise pagure.exceptions.APIError(400, error_code=APIERROR.EDBERROR)
 
+    if mcomment.is_set():
+        pagure.lib.add_issue_comment(
+            SESSION,
+            issue,
+            comment='@%s updated metadata\n%s' % (
+                            flask.g.fas_user.username, mcomment.get()),
+            user=flask.g.fas_user.username,
+            ticketfolder=None,
+            notify=False,
+            notification=True)
+
     jsonout = flask.jsonify(output)
     return jsonout
diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py
index 53e54ef..5e099c2 100644
--- a/pagure/lib/__init__.py
+++ b/pagure/lib/__init__.py
@@ -56,6 +56,41 @@ PAGURE_CI = None
 LOG = None
 
 
+class MetaComment():
+    ''' This class store/builds comments about metadata updates that can be
+    displayed in a single notification comment in the UI. '''
+    def __init__(self):
+        ''' Initialize the comment '''
+        self.comment = ""
+
+    def add(self, field, old_value=None, new_value=None):
+        ''' Add a new comment about the changes to this field.  If the value is
+        not set/empty we still need to pass a string to markdown or else the
+        formatting is wrong.  So in this case we use ""
+        '''
+        if not old_value:
+            old_value = '""'
+        if not new_value:
+            new_value = '""'
+
+        self.comment += ("**%s** changed from ``%s`` to ``%s``\n" %
+            (field, old_value, new_value))
+
+    def add_as_is(self, comment):
+        ''' Add a comment as is '''
+        self.comment += "%s\n" % (comment)
+
+    def is_set(self):
+        if self.comment != "":
+            return True
+        else:
+            return False
+
+    def get(self):
+        ''' Return the full comment list '''
+        return self.comment
+
+
 def set_redis(host, port, dbname):
     """ Set the redis connection with the specified information. """
     global REDIS
@@ -392,12 +427,12 @@ def add_tag_obj(session, obj, tags, user, ticketfolder):
         return 'Nothing to add'
 
 
-def add_issue_assignee(session, issue, assignee, user, ticketfolder,
+def add_issue_assignee(session, issue, assignee, user, ticketfolder, mcomment,
                        notify=True):
     ''' Add an assignee to an issue, in other words, assigned an issue. '''
     user_obj = get_user(session, user)
 
-    old_assignee = issue.assignee if issue.assignee else '\"\"'
+    old_assignee = issue.assignee
 
     if not assignee and issue.assignee is not None:
         issue.assignee_id = None
@@ -406,7 +441,7 @@ def add_issue_assignee(session, issue, assignee, user, ticketfolder,
         session.commit()
         pagure.lib.git.update_git(
             issue, repo=issue.project, repofolder=ticketfolder)
-        comment = '**Assignee** removed ``%s``' % (old_assignee.user)
+        mcomment.add("Assignee", old_assignee.user, None)
         if notify:
             pagure.lib.notify.notify_assigned_issue(issue, None, user_obj)
 
@@ -427,20 +462,15 @@ def add_issue_assignee(session, issue, assignee, user, ticketfolder,
             REDIS.publish('pagure.%s' % issue.uid, json.dumps(
                 {'unassigned': '-'}))
 
-        return 'Assignee reset', comment
+        return 'Assignee reset'
     elif not assignee and issue.assignee is None:
-        return 'Nothing to change', ""
+        return 'Nothing to change'
 
     # Validate the assignee
     assignee_obj = get_user(session, assignee)
 
     if issue.assignee_id != assignee_obj.id:
-        if issue.assignee_id is None:
-            comment = '**Assignee** set to ``%s``' % (assignee_obj.user)
-        else:
-            comment = '**Assignee** changed from ``%s`` to ``%s``' % (
-                old_assignee, assignee_obj.user)
-
+        mcomment.add("Assignee", old_assignee, assignee_obj.user)
         issue.assignee_id = assignee_obj.id
         session.add(issue)
         session.flush()
@@ -469,9 +499,9 @@ def add_issue_assignee(session, issue, assignee, user, ticketfolder,
             REDIS.publish('pagure.%s' % issue.uid, json.dumps(
                 {'assigned': assignee_obj.to_json(public=True)}))
 
-        return 'Issue assigned', comment
+        return 'Issue assigned'
     else:
-        return "", ""
+        return ""
 
 
 def add_pull_request_assignee(
@@ -1406,19 +1436,7 @@ def new_tag(session, tag_name, tag_description, tag_color, project_id):
     return tagobj
 
 
-def build_meta_comment(comment, field, old_value, new_value):
-    ''' Format a new comment for metadata changes and add it to the existing
-    comment.  Convert 'None' and empty values to something more friendly.
-    '''
-    if old_value is None or old_value == "":
-        old_value = '\"\"'
-    if new_value is None or new_value == "":
-        new_value = '\"\"'
-    return ("**%s** changed from ``%s`` to ``%s``\n%s" %
-            (field, old_value, new_value, comment))
-
-
-def edit_issue(session, issue, ticketfolder, user, repo=None,
+def edit_issue(session, issue, ticketfolder, user, mcomment, repo=None,
                title=None, content=None, status=None, close_status=-1,
                priority=None, milestone=-1, private=False):
     ''' Edit the specified issue.
@@ -1432,18 +1450,15 @@ def edit_issue(session, issue, ticketfolder, user, repo=None,
                     'depending that are still open.')
 
     edit = []
-    edit_comment = ""
     if title and title != issue.title:
-        edit_comment = build_meta_comment(
-            edit_comment, "Title", issue.title, title)
+        mcomment.add("Title", issue.title, title)
         issue.title = title
         edit.append('title')
     if content and content != issue.content:
         issue.content = content
         edit.append('content')
     if status and status != issue.status:
-        edit_comment = build_meta_comment(
-            edit_comment, "Status", issue.status, status)
+        mcomment.add("Status", issue.status, status)
         issue.status = status
         if status.lower() != 'open':
             issue.closed_at = datetime.datetime.utcnow()
@@ -1452,8 +1467,7 @@ def edit_issue(session, issue, ticketfolder, user, repo=None,
             edit.append('close_status')
         edit.append('status')
     if close_status != -1 and close_status != issue.close_status:
-        edit_comment = build_meta_comment(
-            edit_comment, "Closed as", issue.close_status, close_status)
+        mcomment.add("Closed as", issue.close_status, close_status)
         issue.close_status = close_status
         edit.append('close_status')
     if priority:
@@ -1462,19 +1476,16 @@ def edit_issue(session, issue, ticketfolder, user, repo=None,
         except:
             priority = None
         if priority != issue.priority:
-            edit_comment = build_meta_comment(
-                edit_comment, "Priority", repo.priorities[str(issue.priority)],
+            mcomment.add("Priority", repo.priorities[str(issue.priority)],
                 repo.priorities[str(priority)])
             issue.priority = priority
             edit.append('priority')
     if private in [True, False] and private != issue.private:
-        edit_comment = build_meta_comment(
-            edit_comment, "Private", str(issue.private), str(private))
+        mcomment.add("Private", str(issue.private), str(private))
         issue.private = private
         edit.append('private')
     if milestone != -1 and milestone != issue.milestone:
-        edit_comment = build_meta_comment(
-            edit_comment, "Milestone", issue.milestone, milestone)
+        mcomment.add("Milestone", issue.milestone, milestone)
         issue.milestone = milestone
         edit.append('milestone')
     issue.last_updated = datetime.datetime.utcnow()
@@ -1516,9 +1527,9 @@ def edit_issue(session, issue, ticketfolder, user, repo=None,
     if edit:
         session.add(issue)
         session.flush()
-        return 'Successfully edited issue #%s' % issue.id, edit_comment
+        return 'Successfully edited issue #%s' % issue.id
     else:
-        return "", ""
+        return ""
 
 
 def update_project_settings(session, repo, settings, user):
@@ -2503,7 +2514,7 @@ def avatar_url_from_email(email, size=64, default='retro', dns=False):
             hashhex, query)
 
 
-def update_tags(session, obj, tags, username, ticketfolder):
+def update_tags(session, obj, tags, username, ticketfolder, mcomment):
     """ Update the tags of a specified object (adding or removing them).
     This object can be either an issue or a project.
 
@@ -2514,7 +2525,6 @@ def update_tags(session, obj, tags, username, ticketfolder):
     toadd = set(tags) - set(obj.tags_text)
     torm = set(obj.tags_text) - set(tags)
     messages = []
-    comment = ""
     if toadd:
         messages.append(
             add_tag_obj(
@@ -2526,9 +2536,10 @@ def update_tags(session, obj, tags, username, ticketfolder):
             )
         )
         if len(toadd) == 1:
-            comment += "**Tags** added tag: ``%s``" % list(toadd)[0]
+            mcomment.add_as_is("**Tags** added tag: ``%s``" % list(toadd)[0])
         else:
-            comment += "**Tags** added tags: ``" + ', '.join(toadd) + "``"
+            mcomment.add_as_is("**Tags** added tags: ``" + ', '.join(toadd) +
+                               "``")
 
     if torm:
         messages.append(
@@ -2540,20 +2551,19 @@ def update_tags(session, obj, tags, username, ticketfolder):
                 ticketfolder=ticketfolder,
             )
         )
-        if toadd:
-            comment += '\n'
         if len(torm) == 1:
-            comment += "**Tags** removed tag: ``%s``" % list(torm)[0]
+            mcomment.add_as_is("**Tags** removed tag: ``%s``" % list(torm)[0])
         else:
-            comment += "**Tags** removed tags: ``" + ', '.join(torm) + "``"
+            mcomment.add_as_is("**Tags** removed tags: ``" +
+                               ", ".join(torm) + "``")
 
     session.commit()
 
-    return messages, comment
+    return messages
 
 
 def update_dependency_issue(
-        session, repo, issue, depends, username, ticketfolder):
+        session, repo, issue, depends, username, ticketfolder, mcomment):
     """ Update the dependency of a specified issue (adding or removing them)
 
     """
@@ -2587,8 +2597,10 @@ def update_dependency_issue(
         )
         comment += "%s " % (depend)
 
-    if toadd:
-        comment += "``\n"
+    if comment:
+        comment += "``"
+        mcomment.add_as_is(comment)
+        comment = ""
 
     # Remove issue depending
     if torm:
@@ -2614,15 +2626,16 @@ def update_dependency_issue(
         )
         comment += "%s " % (depend)
 
-    if torm:
-        comment += "``\n"
+    if comment:
+        comment += "``"
+        mcomment.add_as_is(comment)
 
     session.commit()
-    return messages, comment
+    return messages
 
 
 def update_blocked_issue(
-        session, repo, issue, blocks, username, ticketfolder):
+        session, repo, issue, blocks, username, ticketfolder, mcomment):
     """ Update the upstream dependency of a specified issue (adding or
     removing them)
 
@@ -2658,8 +2671,10 @@ def update_blocked_issue(
         session.commit()
         comment += "%s " % (block)
 
-    if toadd:
-        comment += "``\n"
+    if comment:
+        comment += "``"
+        mcomment.add_as_is(comment)
+        comment = ""
 
     # Remove issue blocked
     if torm:
@@ -2686,10 +2701,12 @@ def update_blocked_issue(
         )
         comment += "%s " % (block)
 
-        if torm:
-            comment += "``\n"
+    if comment:
+        comment += "``"
+        mcomment.add_as_is(comment)
+
     session.commit()
-    return messages, comment
+    return messages
 
 
 def add_user_pending_email(session, userobj, email):
@@ -2802,7 +2819,8 @@ def get_group_types(session, group_type=None):
     return query.all()
 
 
-def search_groups(session, pattern=None, group_name=None, group_type=None, display_name=None):
+def search_groups(session, pattern=None, group_name=None, group_type=None,
+                  display_name=None):
     ''' Return the groups based on the criteria specified.
 
     '''
@@ -3002,7 +3020,8 @@ def add_group(
     display = search_groups(session, display_name=display_name)
     if display:
         raise pagure.exceptions.PagureException(
-            'There is already a group with display name `%s` created.' % display_name)
+            'There is already a group with display name `%s` created.' %
+            display_name)
 
     grp = pagure.lib.model.PagureGroup(
         group_name=group_name,
@@ -3573,7 +3592,7 @@ def set_custom_key_fields(session, project, fields, types, data):
     return 'List of custom fields updated'
 
 
-def set_custom_key_value(session, issue, key, value):
+def set_custom_key_value(session, issue, key, value, mcomment):
     """ Set or update the value of the specified custom key.
     """
 
@@ -3589,7 +3608,6 @@ def set_custom_key_value(session, issue, key, value):
     updated = False
     delete = False
     old_value = None
-    comment = ""
     if current_field:
         old_value = current_field.value
         if current_field.key.key_type == 'boolean':
@@ -3614,7 +3632,7 @@ def set_custom_key_value(session, issue, key, value):
         session.add(current_field)
 
     if updated:
-        comment = build_meta_comment("", key.name, old_value, value)
+        mcomment.add(key.name, old_value, value)
 
     if REDIS and updated:
         if issue.private:
@@ -3628,7 +3646,7 @@ def set_custom_key_value(session, issue, key, value):
                 'issue': issue.to_json(public=True, with_comments=False),
             }))
 
-    return comment
+    return 'Custom field adjusted'
 
 
 def get_yearly_stats_user(session, user, date):
diff --git a/pagure/lib/git.py b/pagure/lib/git.py
index d55be94..21edd2b 100644
--- a/pagure/lib/git.py
+++ b/pagure/lib/git.py
@@ -14,7 +14,6 @@
 # pylint: disable=too-many-statements
 # pylint: disable=too-many-lines
 
-
 import datetime
 import hashlib
 import json
@@ -29,7 +28,7 @@ import pygit2
 import werkzeug
 
 from sqlalchemy.exc import SQLAlchemyError
-
+from .__init__ import MetaComment
 import pagure
 import pagure.exceptions
 import pagure.lib
@@ -427,7 +426,7 @@ def get_project_from_json(
     return project
 
 
-def update_custom_field_from_json(session, repo, issue, json_data):
+def update_custom_field_from_json(session, repo, issue, json_data, mcomment):
     ''' Update the custom fields according to the custom fields of
     the issue. If the custom field is not present for the repo in
     it's settings, this will create them.
@@ -473,6 +472,7 @@ def update_custom_field_from_json(session, repo, issue, json_data):
             issue=issue,
             key=key_obj,
             value=value,
+            mcomment=mcomment
         )
         try:
             session.commit()
@@ -501,6 +501,7 @@ def update_ticket_from_git(
                 reponame, username, namespace))
 
     user = get_user_from_json(session, json_data)
+    mcomment = MetaComment()
 
     issue = pagure.lib.get_issue_by_uid(session, issue_uid=issue_uid)
     if not issue:
@@ -534,6 +535,7 @@ def update_ticket_from_git(
             status=json_data.get('status'),
             close_status=json_data.get('close_status'),
             private=json_data.get('private'),
+            mcomment=mcomment
         )
     session.commit()
 
@@ -544,6 +546,7 @@ def update_ticket_from_git(
         repo=repo,
         issue=issue,
         json_data=json_data,
+        mcomment=mcomment
     )
 
     # Update milestone
@@ -567,6 +570,7 @@ def update_ticket_from_git(
             ticketfolder=None,
             user=user.username,
             milestone=milestone,
+            mcomment=mcomment
         )
     except SQLAlchemyError:
         session.rollback()
@@ -586,26 +590,27 @@ def update_ticket_from_git(
     # Update tags
     tags = json_data.get('tags', [])
     pagure.lib.update_tags(
-        session, issue, tags, username=user.user, ticketfolder=None)
+        session, issue, tags, username=user.user, ticketfolder=None,
+        mcomment=mcomment)
 
     # Update assignee
     assignee = get_user_from_json(session, json_data, key='assignee')
     if assignee:
         pagure.lib.add_issue_assignee(
-            session, issue, assignee.username,
+            session, issue, assignee.username, mcomment=mcomment,
             user=user.user, ticketfolder=None, notify=False)
 
     # Update depends
     depends = json_data.get('depends', [])
     pagure.lib.update_dependency_issue(
         session, issue.project, issue, depends,
-        username=user.user, ticketfolder=None)
+        username=user.user, ticketfolder=None, mcomment=mcomment)
 
     # Update blocks
     blocks = json_data.get('blocks', [])
     pagure.lib.update_blocked_issue(
         session, issue.project, issue, blocks,
-        username=user.user, ticketfolder=None)
+        username=user.user, ticketfolder=None, mcomment=mcomment)
 
     for comment in json_data['comments']:
         user = get_user_from_json(session, comment)
@@ -622,6 +627,17 @@ def update_ticket_from_git(
                 date_created=datetime.datetime.utcfromtimestamp(
                     float(comment['date_created'])),
             )
+    if mcomment.is_set():
+        pagure.lib.add_issue_comment(
+            session,
+            issue,
+            comment='@%s updated metadata\n%s' % (
+                            user.username, mcomment.get()),
+            user=user.username,
+            ticketfolder=None,
+            notify=False,
+            notification=True)
+
     session.commit()
 
 
diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py
index dff8e4c..599f785 100644
--- a/pagure/ui/issues.py
+++ b/pagure/ui/issues.py
@@ -34,6 +34,7 @@ import pagure.doc_utils
 import pagure.exceptions
 import pagure.lib
 import pagure.lib.encoding_utils
+from pagure.lib import MetaComment
 import pagure.forms
 from pagure import (APP, SESSION, LOG, __get_file_in_tree,
                     login_required, authenticated, urlpattern)
@@ -194,7 +195,6 @@ def update_issue(repo, issueid, username=None, namespace=None):
 
         try:
             messages = set()
-            field_comments = ""
 
             # New comment
             if comment:
@@ -209,66 +209,67 @@ def update_issue(repo, issueid, username=None, namespace=None):
                 if message and not is_js:
                     messages.add(message)
 
+            # Create our metadata comment object which is used to track and
+            # report of what metadata fields were updated.  This is then turned
+            # into a notificaion comment in the Issue.
+            mcomment = MetaComment()
+
             # The status field can be updated by both the admin and the
             # person who opened the ticket.
             # Update status
             if repo_admin or flask.g.fas_user.username == issue.user.user:
                 if new_status in status:
-                    message, new_comment = pagure.lib.edit_issue(
+                    message = pagure.lib.edit_issue(
                         SESSION,
                         issue=issue,
                         status=new_status,
                         close_status=close_status,
                         private=issue.private,
                         user=flask.g.fas_user.username,
+                        mcomment=mcomment,
                         ticketfolder=APP.config['TICKETS_FOLDER']
                     )
                     SESSION.commit()
                     if message:
                         messages.add(message)
-                    if new_comment != "":
-                        field_comments = ("%s\n%s" %
-                                          (field_comments, new_comment))
 
             # All the other meta-data can be changed only by admins
             # while other field will be missing for non-admin and thus
             # reset if we let them
             if repo_admin:
                 # Adjust (add/remove) tags
-                msgs, new_comment = pagure.lib.update_tags(
+                msgs = pagure.lib.update_tags(
                     SESSION, issue, tags,
                     username=flask.g.fas_user.username,
-                    ticketfolder=APP.config['TICKETS_FOLDER']
+                    ticketfolder=APP.config['TICKETS_FOLDER'],
+                    mcomment=mcomment
                 )
                 messages.union(set(msgs))
-                if new_comment != "":
-                    field_comments = ("%s\n%s" %
-                                      (field_comments, new_comment))
 
             # The meta-data can be changed by admins and issue creator,
             # where issue creators can only change status of their issue while
-            # other fields will be missing for non-admin and thus reset if we let them
+            # other fields will be missing for non-admin and thus reset if we
+            # let them
             if repo_admin:
                 # Assign or update assignee of the ticket
-                message, new_comment = pagure.lib.add_issue_assignee(
+                message = pagure.lib.add_issue_assignee(
                     SESSION,
                     issue=issue,
                     assignee=assignee or None,
                     user=flask.g.fas_user.username,
                     ticketfolder=APP.config['TICKETS_FOLDER'],
+                    mcomment=mcomment
                 )
                 SESSION.commit()
                 if message and message != 'Nothing to change':
                     messages.add(message)
-                if new_comment != "":
-                    field_comments = ("%s\n%s" %
-                                      (field_comments, new_comment))
+
                 # Adjust priority if needed
                 if str(new_priority) not in repo.priorities:
                     new_priority = None
 
                 # Update core metadata
-                message, new_comment = pagure.lib.edit_issue(
+                message = pagure.lib.edit_issue(
                     SESSION,
                     repo=repo,
                     issue=issue,
@@ -277,16 +278,13 @@ def update_issue(repo, issueid, username=None, namespace=None):
                     private=form.private.data,
                     user=flask.g.fas_user.username,
                     ticketfolder=APP.config['TICKETS_FOLDER'],
+                    mcomment=mcomment
                 )
                 SESSION.commit()
                 if message:
                     messages.add(message)
-                if new_comment != "":
-                    field_comments = ("%s\n%s" %
-                                      (field_comments, new_comment))
 
                 # Update the custom keys/fields
-                edit_comment = ""
                 for key in repo.issue_keys:
                     value = flask.request.form.get(key.name)
                     if value:
@@ -301,42 +299,32 @@ def update_issue(repo, issueid, username=None, namespace=None):
                                         '(%s) has invalid url (%s) ' %
                                         (key.name, link))
 
-                    new_comment = pagure.lib.set_custom_key_value(
-                        SESSION, issue, key, value)
-                    if new_comment is not "":
-                        edit_comment = "%s%s" % (new_comment, edit_comment)
-
-                if edit_comment is not "":
-                    field_comments = ("%s%s" %
-                                      (field_comments, edit_comment))
+                    pagure.lib.set_custom_key_value(
+                        SESSION, issue, key, value, mcomment=mcomment)
 
                 # Update ticket this one depends on
-                msgs, new_comment = pagure.lib.update_dependency_issue(
+                msgs = pagure.lib.update_dependency_issue(
                     SESSION, repo, issue, depends,
                     username=flask.g.fas_user.username,
-                    ticketfolder=APP.config['TICKETS_FOLDER'])
+                    ticketfolder=APP.config['TICKETS_FOLDER'],
+                    mcomment=mcomment)
                 messages.union(set(msgs))
-                if new_comment != "":
-                    field_comments = ("%s%s" %
-                                      (field_comments, new_comment))
 
                 # Update ticket(s) depending on this one
-                msgs, new_comment = pagure.lib.update_blocked_issue(
+                msgs = pagure.lib.update_blocked_issue(
                     SESSION, repo, issue, blocks,
                     username=flask.g.fas_user.username,
-                    ticketfolder=APP.config['TICKETS_FOLDER'],)
+                    ticketfolder=APP.config['TICKETS_FOLDER'],
+                    mcomment=mcomment)
                 messages.union(set(msgs))
-                if new_comment != "":
-                    field_comments = ("%s%s" %
-                                      (field_comments, new_comment))
 
                 # Add the comment for field updates:
-                if field_comments != "":
+                if mcomment.is_set():
                     pagure.lib.add_issue_comment(
                         SESSION,
                         issue,
                         comment='@%s updated metadata\n%s' % (
-                            flask.g.fas_user.username, field_comments),
+                            flask.g.fas_user.username, mcomment.get()),
                         user=flask.g.fas_user.username,
                         ticketfolder=APP.config['TICKETS_FOLDER'],
                         notify=False,
@@ -1110,8 +1098,13 @@ def edit_issue(repo, issueid, username=None, namespace=None):
                 404, 'No such user found in the database: %s' % (
                     flask.g.fas_user.username))
 
+        # Create our metadata comment object which is used to track and
+        # report of what metadata fields were updated.  This is then turned
+        # into a notificaion comment in the Issue.
+        mcomment = MetaComment()
+
         try:
-            message, comment = pagure.lib.edit_issue(
+            message = pagure.lib.edit_issue(
                 SESSION,
                 issue=issue,
                 title=title,
@@ -1120,13 +1113,15 @@ def edit_issue(repo, issueid, username=None, namespace=None):
                 user=flask.g.fas_user.username,
                 ticketfolder=APP.config['TICKETS_FOLDER'],
                 private=private,
+                mcomment=mcomment
             )
             SESSION.commit()
-            if comment != "":
+            if mcomment.is_set():
                 pagure.lib.add_issue_comment(
                     SESSION,
                     issue,
-                    comment=comment,
+                    comment='@%s updated metadata\n%s' % (
+                            flask.g.fas_user.username, mcomment.get()),
                     user=flask.g.fas_user.username,
                     ticketfolder=APP.config['TICKETS_FOLDER'],
                     notify=False,
diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py
index aca1db1..b6148bf 100644
--- a/pagure/ui/repo.py
+++ b/pagure/ui/repo.py
@@ -50,6 +50,7 @@ import pagure.ui.plugins
 from pagure import (APP, SESSION, LOG, __get_file_in_tree, login_required,
                     admin_session_timedout)
 from pagure.lib import encoding_utils
+from pagure.lib import MetaComment
 
 
 @APP.route('/<repo>.git')
@@ -1116,6 +1117,7 @@ def update_project(repo, username=None, namespace=None):
     form = pagure.forms.ProjectFormSimplified()
 
     if form.validate_on_submit():
+        mcomment = MetaComment()
         try:
             repo.description = form.description.data
             repo.avatar_email = form.avatar_email.data.strip()
@@ -1124,7 +1126,7 @@ def update_project(repo, username=None, namespace=None):
                 SESSION, repo,
                 tags=[t.strip() for t in form.tags.data.split(',')],
                 username=flask.g.fas_user.username,
-                ticketfolder=None,
+                ticketfolder=None, mcomment=mcomment
             )
             SESSION.add(repo)
             SESSION.commit()
diff --git a/tests/test_pagure_flask_api_issue.py b/tests/test_pagure_flask_api_issue.py
index 1616fb6..92e0a07 100644
--- a/tests/test_pagure_flask_api_issue.py
+++ b/tests/test_pagure_flask_api_issue.py
@@ -1075,7 +1075,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': ['', '']}
+            {'message': 'No changes'}
         )
 
         # No change
@@ -1092,12 +1092,9 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
             '/api/0/test/issue/1/status', data=data, headers=headers)
         self.assertEqual(output.status_code, 200)
         data = json.loads(output.data)
-        print "MARK2\n\n" + str(data)
         self.assertDictEqual(
             data,
-            {'message': ['Successfully edited issue #1',
-                         '**Closed as** changed from ``""`` to ``Fixed``\n'
-                         '**Status** changed from ``Open`` to ``Closed``\n']}
+            {'message': 'Successfully edited issue #1'}
         )
 
         headers = {'Authorization': 'token pingou_foo'}
@@ -1509,7 +1506,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': ['Issue assigned', '**Assignee** set to ``pingou``']}
+            {'message': 'Issue assigned'}
         )
 
         # Un-assign
@@ -1519,7 +1516,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': ['Assignee reset', '**Assignee** removed ``pingou``']}
+            {'message': 'Assignee reset'}
         )
         repo = pagure.lib.get_project(self.session, 'test')
         issue = pagure.lib.search_issues(self.session, repo, issueid=1)
@@ -1533,7 +1530,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': ['Nothing to change', '']}
+            {'message': 'Nothing to change'}
         )
         repo = pagure.lib.get_project(self.session, 'test')
         issue = pagure.lib.search_issues(self.session, repo, issueid=1)
@@ -1547,7 +1544,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': ['Issue assigned', '**Assignee** set to ``pingou``']}
+            {'message': 'Issue assigned'}
         )
 
         # Un-assign
@@ -1558,7 +1555,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': ['Assignee reset', '**Assignee** removed ``pingou``']}
+            {'message': 'Assignee reset'}
         )
 
         # Re-assign for the rest of the tests
@@ -1569,7 +1566,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': ['Issue assigned', '**Assignee** set to ``pingou``']}
+            {'message': 'Issue assigned'}
         )
 
         # One comment added
@@ -1669,7 +1666,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': ['Issue assigned', '**Assignee** set to ``pingou``']}
+            {'message': 'Issue assigned'}
         )
 
     @patch('pagure.lib.git.update_git')
@@ -1967,25 +1964,6 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
                 self.assertEqual(
                     sorted(key.data), ['ack', 'nack', 'needs review'])
 
-        # Delete a value from a custom filed that does not exist in the entry
-        output = self.app.post(
-            '/api/0/test/issue/1/custom/bugzilla', headers=headers)
-        self.assertEqual(output.status_code, 200)
-        data = json.loads(output.data)
-        self.assertDictEqual(
-            data,
-            {
-              "error": "An error occured at the database level and prevent "
-                       "the action from reaching completion",
-              "error_code": "EDBERROR",
-            }
-        )
-
-        repo = pagure.lib.get_project(self.session, 'test')
-        issue = pagure.lib.search_issues(self.session, repo, issueid=1)
-        self.assertEqual(issue.other_fields, [])
-        self.assertEqual(len(issue.other_fields), 0)
-
         # Invalid value
         output = self.app.post(
             '/api/0/test/issue/1/custom/bugzilla', headers=headers,
@@ -2015,8 +1993,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         self.assertDictEqual(
             data,
             {
-              "message": '**bugzilla** changed from ``""`` to'
-                         ' ``https://bugzilla.redhat.com/1234``\n'
+              "message": "Custom field adjusted"
             }
         )
 
@@ -2043,8 +2020,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
 
         repo = pagure.lib.get_project(self.session, 'test')
         issue = pagure.lib.search_issues(self.session, repo, issueid=1)
-        self.assertEqual(issue.other_fields, [])
-        self.assertEqual(len(issue.other_fields), 0)
+        self.assertEqual(len(issue.other_fields), 1)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py
index b93ee80..8e37209 100644
--- a/tests/test_pagure_flask_api_project.py
+++ b/tests/test_pagure_flask_api_project.py
@@ -29,6 +29,9 @@ sys.path.insert(0, os.path.join(os.path.dirname(
 import pagure.lib
 import tests
 from pagure.lib.repo import PagureRepo
+from pagure.lib import MetaComment
+
+mcomment = MetaComment()
 
 
 class PagureFlaskApiProjecttests(tests.Modeltests):
@@ -119,9 +122,9 @@ class PagureFlaskApiProjecttests(tests.Modeltests):
         self.assertEqual(repo.tags, [])
 
         # Adding a tag
-        output, comment = pagure.lib.update_tags(
+        output = pagure.lib.update_tags(
             self.session, repo, 'infra', 'pingou',
-            ticketfolder=None)
+            None, mcomment)
         self.assertEqual(output, ['Tag added: infra'])
 
         # Check after adding
@@ -317,9 +320,9 @@ class PagureFlaskApiProjecttests(tests.Modeltests):
         self.assertEqual(repo.tags, [])
 
         # Adding a tag
-        output, comment = pagure.lib.update_tags(
+        output = pagure.lib.update_tags(
             self.session, repo, 'infra', 'pingou',
-            ticketfolder=None)
+            ticketfolder=None, mcomment=mcomment)
         self.assertEqual(output, ['Tag added: infra'])
 
         # Check after adding
diff --git a/tests/test_pagure_flask_dump_load_ticket.py b/tests/test_pagure_flask_dump_load_ticket.py
index 1339a6b..0e00519 100644
--- a/tests/test_pagure_flask_dump_load_ticket.py
+++ b/tests/test_pagure_flask_dump_load_ticket.py
@@ -26,6 +26,9 @@ sys.path.insert(0, os.path.join(os.path.dirname(
 
 import pagure.lib
 import tests
+from pagure.lib import MetaComment
+
+mcomment = MetaComment()
 
 
 class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
@@ -123,12 +126,13 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
         self.session.commit()
         self.assertEqual(msg, 'Comment added')
         # Assign the ticket to someone
-        msg, comment = pagure.lib.add_issue_assignee(
+        msg = pagure.lib.add_issue_assignee(
             session=self.session,
             issue=issue,
             assignee='pingou',
             user='pingou',
             ticketfolder=repopath,
+            mcomment=mcomment
         )
         self.session.commit()
         self.assertEqual(msg, 'Issue assigned')
@@ -213,7 +217,7 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
         issue = pagure.lib.search_issues(self.session, repo, issueid=1)
 
         # Check after re-loading
-        self.assertEqual(len(issue.comments), 2)
+        self.assertEqual(len(issue.comments), 3)
         self.assertEqual(len(issue.tags), 2)
         self.assertEqual(issue.tags_text, ['future', 'feature'])
         self.assertEqual(issue.assignee.username, 'pingou')
diff --git a/tests/test_pagure_flask_ui_app.py b/tests/test_pagure_flask_ui_app.py
index e3b3461..1ab4c5f 100644
--- a/tests/test_pagure_flask_ui_app.py
+++ b/tests/test_pagure_flask_ui_app.py
@@ -25,6 +25,9 @@ sys.path.insert(0, os.path.join(os.path.dirname(
 
 import pagure.lib
 import tests
+from pagure.lib import MetaComment
+
+mcomment = MetaComment()
 
 
 class PagureFlaskApptests(tests.Modeltests):
@@ -1145,12 +1148,13 @@ class PagureFlaskApptests(tests.Modeltests):
         self.session.commit()
         self.assertEqual(msg.title, 'Test issue #3')
 
-        msg, comment = pagure.lib.add_issue_assignee(
+        msg = pagure.lib.add_issue_assignee(
             session=self.session,
             issue=msg,
             assignee='pingou',
             user='foo',
-            ticketfolder=None)
+            ticketfolder=None,
+            mcomment=mcomment)
         self.session.commit()
         self.assertEqual(msg, 'Issue assigned')
 
diff --git a/tests/test_pagure_flask_ui_issues.py b/tests/test_pagure_flask_ui_issues.py
index d992119..20a6f9b 100644
--- a/tests/test_pagure_flask_ui_issues.py
+++ b/tests/test_pagure_flask_ui_issues.py
@@ -31,6 +31,9 @@ sys.path.insert(0, os.path.join(os.path.dirname(
 
 import pagure.lib
 import tests
+from pagure.lib import MetaComment
+
+mcomment = MetaComment()
 
 
 class PagureFlaskIssuestests(tests.Modeltests):
@@ -541,14 +544,16 @@ class PagureFlaskIssuestests(tests.Modeltests):
 
         # Add a non-ascii milestone to the issue but project has no milestone
         issue = pagure.lib.search_issues(self.session, repo, issueid=1)
-        message, comment = pagure.lib.edit_issue(
+        message = pagure.lib.edit_issue(
             self.session,
             issue=issue,
             milestone=b'käpy'.decode('utf-8'),
             private=False,
             user='pingou',
             ticketfolder=None,
+            mcomment=mcomment
         )
+        print "MARK2 " + message
         self.assertEqual(message, 'Successfully edited issue #1')
         self.session.commit()
 
@@ -682,8 +687,8 @@ class PagureFlaskIssuestests(tests.Modeltests):
                 '<option selected value="Fixed">Fixed</option>'
                 in output.data)
             self.assertIn(
-                '@pingou</a> updated metadata</p>\n<p><strong>Closed '
-                'as</strong> changed from <code>""</code> to <code>Fixed'
+                '<small><p><a href="https://pagure.org/user/pingou"> '
+                '@pingou</a> updated metadata'
                 .format(
                     app_url=pagure.APP.config['APP_URL'].rstrip('/')),
                 output.data)
diff --git a/tests/test_pagure_lib.py b/tests/test_pagure_lib.py
index aeee490..b4120a7 100644
--- a/tests/test_pagure_lib.py
+++ b/tests/test_pagure_lib.py
@@ -24,6 +24,9 @@ sys.path.insert(0, os.path.join(os.path.dirname(
 import pagure.lib
 import pagure.lib.model
 import tests
+from pagure.lib import MetaComment
+
+mcomment = MetaComment()
 
 
 class PagureLibtests(tests.Modeltests):
@@ -232,19 +235,21 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(repo.open_tickets_public, 2)
 
         # Edit the issue
-        msg, comment = pagure.lib.edit_issue(
+        msg = pagure.lib.edit_issue(
             session=self.session,
             issue=issue,
             user='pingou',
-            ticketfolder=None)
+            ticketfolder=None,
+            mcomment=mcomment)
         self.session.commit()
         self.assertEqual(msg, None or '')
 
-        msg, comment = pagure.lib.edit_issue(
+        msg = pagure.lib.edit_issue(
             session=self.session,
             issue=issue,
             user='pingou',
             ticketfolder=None,
+            mcomment=mcomment,
             title='Test issue #2',
             content='We should work on this for the second time',
             status='Open',
@@ -252,11 +257,12 @@ class PagureLibtests(tests.Modeltests):
         self.session.commit()
         self.assertEqual(msg, None or '')
 
-        msg, comment = pagure.lib.edit_issue(
+        msg = pagure.lib.edit_issue(
             session=self.session,
             issue=issue,
             user='pingou',
             ticketfolder=None,
+            mcomment=mcomment,
             title='Foo issue #2',
             content='We should work on this period',
             status='Closed',
@@ -273,11 +279,12 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(repo.issues[1].close_status, 'Invalid')
 
         # Edit the status: re-open the ticket
-        msg, comment = pagure.lib.edit_issue(
+        msg = pagure.lib.edit_issue(
             session=self.session,
             issue=issue,
             user='pingou',
             status='Open',
+            mcomment=mcomment,
             ticketfolder=None,
             private=True,
         )
@@ -293,7 +300,7 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(repo.open_tickets_public, 1)
 
         # Edit the status: re-close the ticket
-        msg, comment = pagure.lib.edit_issue(
+        msg = pagure.lib.edit_issue(
             session=self.session,
             issue=issue,
             user='pingou',
@@ -301,6 +308,7 @@ class PagureLibtests(tests.Modeltests):
             close_status='Invalid',
             ticketfolder=None,
             private=True,
+            mcomment=mcomment
         )
         self.session.commit()
         self.assertEqual(msg, 'Successfully edited issue #2')
@@ -442,7 +450,6 @@ class PagureLibtests(tests.Modeltests):
             tags='tag1',
             user='pingou',
             ticketfolder=None)
-
         self.assertEqual(msgs, 'Removed tag: tag1')
 
     @patch('pagure.lib.git.update_git')
@@ -671,7 +678,8 @@ class PagureLibtests(tests.Modeltests):
             issue=issue,
             assignee='foo@foobar.com',
             user='foo@pingou.com',
-            ticketfolder=None
+            ticketfolder=None,
+            mcomment=mcomment
         )
 
         self.assertRaises(
@@ -681,26 +689,29 @@ class PagureLibtests(tests.Modeltests):
             issue=issue,
             assignee='foo@bar.com',
             user='foo@foopingou.com',
-            ticketfolder=None
+            ticketfolder=None,
+            mcomment=mcomment
         )
 
         # Set the assignee by its email
-        msg, comment = pagure.lib.add_issue_assignee(
+        msg = pagure.lib.add_issue_assignee(
             session=self.session,
             issue=issue,
             assignee='foo@bar.com',
             user='foo@pingou.com',
-            ticketfolder=None)
+            ticketfolder=None,
+            mcomment=mcomment)
         self.session.commit()
         self.assertEqual(msg, 'Issue assigned')
 
         # Change the assignee to someone else by its username
-        msg, comment = pagure.lib.add_issue_assignee(
+        msg = pagure.lib.add_issue_assignee(
             session=self.session,
             issue=issue,
             assignee='pingou',
             user='pingou',
-            ticketfolder=None)
+            ticketfolder=None,
+            mcomment=mcomment)
         self.session.commit()
         self.assertEqual(msg, 'Issue assigned')
 
@@ -732,12 +743,13 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(issues[0].tags, [])
 
         # Reset the assignee to no-one
-        msg, comment = pagure.lib.add_issue_assignee(
+        msg = pagure.lib.add_issue_assignee(
             session=self.session,
             issue=issue,
             assignee=None,
             user='pingou',
-            ticketfolder=None)
+            ticketfolder=None,
+            mcomment=mcomment)
         self.session.commit()
         self.assertEqual(msg, 'Assignee reset')
 
@@ -766,12 +778,13 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(len(issue.comments), 0)
 
         # Set the assignee by its email
-        msg, comment = pagure.lib.add_issue_assignee(
+        msg = pagure.lib.add_issue_assignee(
             session=self.session,
             issue=issue,
             assignee='foo@bar.com',
             user='foo@pingou.com',
-            ticketfolder=None)
+            ticketfolder=None,
+            mcomment=mcomment)
         self.session.commit()
         self.assertEqual(msg, 'Issue assigned')
 
@@ -1979,8 +1992,9 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(repo.tags_colored, [])
         self.assertEqual(issue.tags_text, [])
 
-        messages, comment = pagure.lib.update_tags(
-            self.session, issue, 'tag', 'pingou', ticketfolder=None)
+        messages = pagure.lib.update_tags(
+            self.session, issue, 'tag', 'pingou', ticketfolder=None,
+            mcomment=mcomment)
         self.assertEqual(messages, ['Tag added: tag'])
 
         # after
@@ -1992,9 +2006,9 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(issue.tags_text, ['tag'])
 
         # Replace the tag by two others
-        messages, comment = pagure.lib.update_tags(
+        messages = pagure.lib.update_tags(
             self.session, issue, ['tag2', 'tag3'], 'pingou',
-            ticketfolder=None)
+            ticketfolder=None, mcomment=mcomment)
         self.assertEqual(
             messages, ['Tag added: tag2, tag3', 'Removed tag: tag'])
 
@@ -2043,12 +2057,13 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(issue.depends_text, [])
         self.assertEqual(issue.blocks_text, [])
 
-        messages, comment = pagure.lib.update_dependency_issue(
-            self.session, repo, issue, '2', 'pingou', ticketfolder=None)
+        messages = pagure.lib.update_dependency_issue(
+            self.session, repo, issue, '2', 'pingou', ticketfolder=None,
+            mcomment=mcomment)
         self.assertEqual(messages, ['Dependency added'])
-        messages, comment = pagure.lib.update_dependency_issue(
+        messages = pagure.lib.update_dependency_issue(
             self.session, repo, issue, ['3', '4', 5], 'pingou',
-            ticketfolder=None)
+            ticketfolder=None, mcomment=mcomment)
         self.assertEqual(
             messages, ['Dependency added', 'Dependency removed'])
 
@@ -2086,12 +2101,13 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(issue.depends_text, [])
         self.assertEqual(issue.blocks_text, [])
 
-        messages, comment = pagure.lib.update_blocked_issue(
-            self.session, repo, issue, '2', 'pingou', ticketfolder=None)
+        messages = pagure.lib.update_blocked_issue(
+            self.session, repo, issue, '2', 'pingou', ticketfolder=None,
+            mcomment=mcomment)
         self.assertEqual(messages, ['Dependency added'])
-        messages, comment = pagure.lib.update_blocked_issue(
+        messages = pagure.lib.update_blocked_issue(
             self.session, repo, issue, ['3', '4', 5], 'pingou',
-            ticketfolder=None)
+            ticketfolder=None, mcomment=mcomment)
         self.assertEqual(
             messages, ['Dependency added', 'Dependency removed'])
 
diff --git a/tests/test_pagure_lib_git.py b/tests/test_pagure_lib_git.py
index bb1d0d7..7fc9146 100644
--- a/tests/test_pagure_lib_git.py
+++ b/tests/test_pagure_lib_git.py
@@ -27,7 +27,9 @@ import pagure.lib.git
 import tests
 
 from pagure.lib.repo import PagureRepo
+from pagure.lib import MetaComment
 
+mcomment = MetaComment()
 
 class PagureLibGittests(tests.Modeltests):
     """ Tests for pagure.lib.git """
@@ -1641,7 +1643,7 @@ index 0000000..60f7480
         }
 
         pagure.lib.git.update_custom_field_from_json(
-            self.session, repo, issue, json_data)
+            self.session, repo, issue, json_data, mcomment=mcomment)
 
         updated_issue = pagure.lib.get_issue_by_uid(self.session, 'someuid')
 
@@ -1684,7 +1686,7 @@ index 0000000..60f7480
         }
 
         pagure.lib.git.update_custom_field_from_json(
-            self.session, repo, issue, json_data)
+            self.session, repo, issue, json_data, mcomment=mcomment)
 
         updated_issue = pagure.lib.get_issue_by_uid(self.session, 'someuid')
 

From 1878ce5dfaea03b1af211759debdb8f2cf7f7c31 Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 6/16] Propose another way to log via notification meta-data changes made to a ticket


---

diff --git a/pagure/api/issue.py b/pagure/api/issue.py
index 31c628a..afc3b18 100644
--- a/pagure/api/issue.py
+++ b/pagure/api/issue.py
@@ -16,7 +16,6 @@ from sqlalchemy.exc import SQLAlchemyError
 import pagure
 import pagure.exceptions
 import pagure.lib
-from pagure.lib import MetaComment
 from pagure import (
     APP, SESSION, is_repo_admin, api_authenticated, urlpattern
 )
@@ -627,7 +626,6 @@ def api_change_status_issue(repo, issueid, username=None, namespace=None):
         form.status.data = new_status
 
     if form.validate_on_submit():
-        mcomment = MetaComment()
         try:
             # Update status
             message = pagure.lib.edit_issue(
@@ -637,7 +635,6 @@ def api_change_status_issue(repo, issueid, username=None, namespace=None):
                 close_status=close_status,
                 user=flask.g.fas_user.username,
                 ticketfolder=APP.config['TICKETS_FOLDER'],
-                mcomment=mcomment,
             )
             SESSION.commit()
             if message:
@@ -645,16 +642,14 @@ def api_change_status_issue(repo, issueid, username=None, namespace=None):
             else:
                 output['message'] = 'No changes'
 
-            if mcomment.is_set():
-                pagure.lib.add_issue_comment(
-                    SESSION,
-                    issue,
-                    comment='@%s updated metadata\n%s' % (
-                        flask.g.fas_user.username, mcomment.get()),
+            if message:
+                pagure.lib.add_metadata_update_notif(
+                    session=SESSION,
+                    issue=issue,
+                    messages=message,
                     user=flask.g.fas_user.username,
-                    ticketfolder=APP.config['TICKETS_FOLDER'],
-                    notify=False,
-                    notification=True)
+                    ticketfolder=APP.config['TICKETS_FOLDER']
+                )
         except pagure.exceptions.PagureException as err:
             raise pagure.exceptions.APIError(
                 400, error_code=APIERROR.ENOCODE, error=str(err))
@@ -845,7 +840,6 @@ def api_assign_issue(repo, issueid, username=None, namespace=None):
     if form.validate_on_submit():
         assignee = form.assignee.data or None
         # Create our metadata comment object
-        mcomment = MetaComment()
         try:
             # New comment
             message = pagure.lib.add_issue_assignee(
@@ -854,20 +848,19 @@ def api_assign_issue(repo, issueid, username=None, namespace=None):
                 assignee=assignee,
                 user=flask.g.fas_user.username,
                 ticketfolder=APP.config['TICKETS_FOLDER'],
-                mcomment=mcomment
             )
             SESSION.commit()
-            if mcomment.is_set():
-                pagure.lib.add_issue_comment(
-                    SESSION,
-                    issue,
-                    comment='@%s updated metadata\n%s' % (
-                        flask.g.fas_user.username, mcomment.get()),
+            if message:
+                pagure.lib.add_metadata_update_notif(
+                    session=SESSION,
+                    issue=issue,
+                    messages=message,
                     user=flask.g.fas_user.username,
-                    ticketfolder=APP.config['TICKETS_FOLDER'],
-                    notify=False,
-                    notification=True)
-            output['message'] = message
+                    ticketfolder=APP.config['TICKETS_FOLDER']
+                )
+                output['message'] = message
+            else:
+                output['message'] = 'Nothing to change'
         except pagure.exceptions.PagureException as err:  # pragma: no cover
             raise pagure.exceptions.APIError(
                 400, error_code=APIERROR.ENOCODE, error=str(err))
@@ -1078,13 +1071,19 @@ def api_update_custom_field(
                     raise pagure.exceptions.APIError(
                         400, error_code=APIERROR.EINVALIDISSUEFIELD_LINK)
     try:
-        mcomment = MetaComment()
         message = pagure.lib.set_custom_key_value(
-            SESSION, issue, key, value, mcomment=mcomment)
+            SESSION, issue, key, value)
 
         SESSION.commit()
         if message:
             output['message'] = message
+            pagure.lib.add_metadata_update_notif(
+                session=SESSION,
+                issue=issue,
+                messages=message,
+                user=flask.g.fas_user.username,
+                ticketfolder=APP.config['TICKETS_FOLDER']
+            )
         else:
             output['message'] = 'No changes'
     except pagure.exceptions.PagureException as err:
@@ -1095,16 +1094,15 @@ def api_update_custom_field(
         SESSION.rollback()
         raise pagure.exceptions.APIError(400, error_code=APIERROR.EDBERROR)
 
-    if mcomment.is_set():
-        pagure.lib.add_issue_comment(
-            SESSION,
-            issue,
-            comment='@%s updated metadata\n%s' % (
-                            flask.g.fas_user.username, mcomment.get()),
+
+    if message:
+        pagure.lib.add_metadata_update_notif(
+            session=SESSION,
+            issue=issue,
+            messages=message,
             user=flask.g.fas_user.username,
-            ticketfolder=None,
-            notify=False,
-            notification=True)
+            ticketfolder=APP.config['TICKETS_FOLDER']
+        )
 
     jsonout = flask.jsonify(output)
     return jsonout
diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py
index 5e099c2..56959fb 100644
--- a/pagure/lib/__init__.py
+++ b/pagure/lib/__init__.py
@@ -56,41 +56,6 @@ PAGURE_CI = None
 LOG = None
 
 
-class MetaComment():
-    ''' This class store/builds comments about metadata updates that can be
-    displayed in a single notification comment in the UI. '''
-    def __init__(self):
-        ''' Initialize the comment '''
-        self.comment = ""
-
-    def add(self, field, old_value=None, new_value=None):
-        ''' Add a new comment about the changes to this field.  If the value is
-        not set/empty we still need to pass a string to markdown or else the
-        formatting is wrong.  So in this case we use ""
-        '''
-        if not old_value:
-            old_value = '""'
-        if not new_value:
-            new_value = '""'
-
-        self.comment += ("**%s** changed from ``%s`` to ``%s``\n" %
-            (field, old_value, new_value))
-
-    def add_as_is(self, comment):
-        ''' Add a comment as is '''
-        self.comment += "%s\n" % (comment)
-
-    def is_set(self):
-        if self.comment != "":
-            return True
-        else:
-            return False
-
-    def get(self):
-        ''' Return the full comment list '''
-        return self.comment
-
-
 def set_redis(host, port, dbname):
     """ Set the redis connection with the specified information. """
     global REDIS
@@ -422,12 +387,12 @@ def add_tag_obj(session, obj, tags, user, ticketfolder):
                 {'added_tags': added_tags}))
 
     if added_tags:
-        return 'Tag added: %s' % ', '.join(added_tags)
+        return 'Issue tagged with: %s' % ', '.join(added_tags)
     else:
         return 'Nothing to add'
 
 
-def add_issue_assignee(session, issue, assignee, user, ticketfolder, mcomment,
+def add_issue_assignee(session, issue, assignee, user, ticketfolder,
                        notify=True):
     ''' Add an assignee to an issue, in other words, assigned an issue. '''
     user_obj = get_user(session, user)
@@ -441,7 +406,7 @@ def add_issue_assignee(session, issue, assignee, user, ticketfolder, mcomment,
         session.commit()
         pagure.lib.git.update_git(
             issue, repo=issue.project, repofolder=ticketfolder)
-        mcomment.add("Assignee", old_assignee.user, None)
+
         if notify:
             pagure.lib.notify.notify_assigned_issue(issue, None, user_obj)
 
@@ -464,13 +429,12 @@ def add_issue_assignee(session, issue, assignee, user, ticketfolder, mcomment,
 
         return 'Assignee reset'
     elif not assignee and issue.assignee is None:
-        return 'Nothing to change'
+        return
 
     # Validate the assignee
     assignee_obj = get_user(session, assignee)
 
     if issue.assignee_id != assignee_obj.id:
-        mcomment.add("Assignee", old_assignee, assignee_obj.user)
         issue.assignee_id = assignee_obj.id
         session.add(issue)
         session.flush()
@@ -499,9 +463,7 @@ def add_issue_assignee(session, issue, assignee, user, ticketfolder, mcomment,
             REDIS.publish('pagure.%s' % issue.uid, json.dumps(
                 {'assigned': assignee_obj.to_json(public=True)}))
 
-        return 'Issue assigned'
-    else:
-        return ""
+        return 'Issue assigned to %s' % assignee
 
 
 def add_pull_request_assignee(
@@ -618,7 +580,7 @@ def add_issue_dependency(
                 'type': 'parent',
             }))
 
-        return 'Dependency added'
+        return 'Issue marked as depending on: #%s' % issue_blocked.id
 
 
 def remove_issue_dependency(
@@ -678,7 +640,8 @@ def remove_issue_dependency(
                 'type': 'parent',
             }))
 
-        return 'Dependency removed'
+        return 'Issue **un**marked as depending on: #%s' % ' #'.join(
+            [str(id) for id in child_del])
 
 
 def remove_tags(session, project, tags, ticketfolder, user):
@@ -699,7 +662,7 @@ def remove_tags(session, project, tags, ticketfolder, user):
         if tagobj:
             tag_found = True
             removed_tags.append(tag)
-            msgs.append('Removed tag: %s' % tag)
+            msgs.append('Issue **un**tagged with: %s' % tag)
             session.delete(tagobj)
 
     if not tag_found:
@@ -770,7 +733,7 @@ def remove_tags_obj(session, obj, tags, ticketfolder, user):
             REDIS.publish('pagure.%s' % obj.uid, json.dumps(
                 {'removed_tags': removed_tags}))
 
-    return 'Removed tag: %s' % ', '.join(removed_tags)
+    return 'Issue **un**tagged with: %s' % ', '.join(removed_tags)
 
 
 def edit_issue_tags(
@@ -1436,7 +1399,7 @@ def new_tag(session, tag_name, tag_description, tag_color, project_id):
     return tagobj
 
 
-def edit_issue(session, issue, ticketfolder, user, mcomment, repo=None,
+def edit_issue(session, issue, ticketfolder, user, repo=None,
                title=None, content=None, status=None, close_status=-1,
                priority=None, milestone=-1, private=False):
     ''' Edit the specified issue.
@@ -1450,15 +1413,16 @@ def edit_issue(session, issue, ticketfolder, user, mcomment, repo=None,
                     'depending that are still open.')
 
     edit = []
+    messages = []
     if title and title != issue.title:
-        mcomment.add("Title", issue.title, title)
         issue.title = title
         edit.append('title')
+        messages.append('Issue title edited')
     if content and content != issue.content:
         issue.content = content
         edit.append('content')
+        messages.append('Issue description edited')
     if status and status != issue.status:
-        mcomment.add("Status", issue.status, status)
         issue.status = status
         if status.lower() != 'open':
             issue.closed_at = datetime.datetime.utcnow()
@@ -1466,28 +1430,28 @@ def edit_issue(session, issue, ticketfolder, user, mcomment, repo=None,
             issue.close_status = None
             edit.append('close_status')
         edit.append('status')
+        messages.append('Issue status updated to: %s' % status)
     if close_status != -1 and close_status != issue.close_status:
-        mcomment.add("Closed as", issue.close_status, close_status)
         issue.close_status = close_status
         edit.append('close_status')
+        messages.append('Issue close_status updated to: %s' % close_status)
     if priority:
         try:
             priority = int(priority)
         except:
             priority = None
         if priority != issue.priority:
-            mcomment.add("Priority", repo.priorities[str(issue.priority)],
-                repo.priorities[str(priority)])
             issue.priority = priority
             edit.append('priority')
+            messages.append('Issue priority set to: %s' % priority)
     if private in [True, False] and private != issue.private:
-        mcomment.add("Private", str(issue.private), str(private))
         issue.private = private
         edit.append('private')
+        messages.append('Issue private status set to: %s' % private)
     if milestone != -1 and milestone != issue.milestone:
-        mcomment.add("Milestone", issue.milestone, milestone)
         issue.milestone = milestone
         edit.append('milestone')
+        messages.append('Issue set to the milestone: %s' % milestone)
     issue.last_updated = datetime.datetime.utcnow()
     # uniquify the list of edited fields
     edit = list(set(edit))
@@ -1527,9 +1491,7 @@ def edit_issue(session, issue, ticketfolder, user, mcomment, repo=None,
     if edit:
         session.add(issue)
         session.flush()
-        return 'Successfully edited issue #%s' % issue.id
-    else:
-        return ""
+        return messages
 
 
 def update_project_settings(session, repo, settings, user):
@@ -2514,7 +2476,7 @@ def avatar_url_from_email(email, size=64, default='retro', dns=False):
             hashhex, query)
 
 
-def update_tags(session, obj, tags, username, ticketfolder, mcomment):
+def update_tags(session, obj, tags, username, ticketfolder):
     """ Update the tags of a specified object (adding or removing them).
     This object can be either an issue or a project.
 
@@ -2526,36 +2488,24 @@ def update_tags(session, obj, tags, username, ticketfolder, mcomment):
     torm = set(obj.tags_text) - set(tags)
     messages = []
     if toadd:
-        messages.append(
-            add_tag_obj(
-                session,
-                obj=obj,
-                tags=toadd,
-                user=username,
-                ticketfolder=ticketfolder,
-            )
+        add_tag_obj(
+            session,
+            obj=obj,
+            tags=toadd,
+            user=username,
+            ticketfolder=ticketfolder,
         )
-        if len(toadd) == 1:
-            mcomment.add_as_is("**Tags** added tag: ``%s``" % list(toadd)[0])
-        else:
-            mcomment.add_as_is("**Tags** added tags: ``" + ', '.join(toadd) +
-                               "``")
+        messages.append('Issue tagged with: %s' % ', '.join(toadd))
 
     if torm:
-        messages.append(
-            remove_tags_obj(
-                session,
-                obj=obj,
-                tags=torm,
-                user=username,
-                ticketfolder=ticketfolder,
-            )
+        remove_tags_obj(
+            session,
+            obj=obj,
+            tags=torm,
+            user=username,
+            ticketfolder=ticketfolder,
         )
-        if len(torm) == 1:
-            mcomment.add_as_is("**Tags** removed tag: ``%s``" % list(torm)[0])
-        else:
-            mcomment.add_as_is("**Tags** removed tags: ``" +
-                               ", ".join(torm) + "``")
+        messages.append('Issue **un**tagged with: %s' % ', '.join(torm))
 
     session.commit()
 
@@ -2563,7 +2513,7 @@ def update_tags(session, obj, tags, username, ticketfolder, mcomment):
 
 
 def update_dependency_issue(
-        session, repo, issue, depends, username, ticketfolder, mcomment):
+        session, repo, issue, depends, username, ticketfolder):
     """ Update the dependency of a specified issue (adding or removing them)
 
     """
@@ -2576,9 +2526,8 @@ def update_dependency_issue(
     comment = ""
 
     # Add issue depending
-    if toadd:
-        comment += "**Depends on** added dependencies: ``"
     for depend in toadd:
+        messages.append("Issue marked as depending on: #%s" % depend)
         issue_depend = search_issues(session, repo, issueid=depend)
         if issue_depend is None:
             continue
@@ -2586,26 +2535,17 @@ def update_dependency_issue(
             # we should never be in this case but better safe than sorry...
             continue
 
-        messages.append(
-            add_issue_dependency(
-                session,
-                issue=issue_depend,
-                issue_blocked=issue,
-                user=username,
-                ticketfolder=ticketfolder,
-            )
+        add_issue_dependency(
+            session,
+            issue=issue_depend,
+            issue_blocked=issue,
+            user=username,
+            ticketfolder=ticketfolder,
         )
-        comment += "%s " % (depend)
-
-    if comment:
-        comment += "``"
-        mcomment.add_as_is(comment)
-        comment = ""
 
     # Remove issue depending
-    if torm:
-        comment += "**Depends on** removed issue dependencies: ``"
     for depend in torm:
+        messages.append("Issue **un**marked as depending on: #%s" % depend)
         issue_depend = search_issues(session, repo, issueid=depend)
         if issue_depend is None:  # pragma: no cover
             # We cannot test this as it would mean we managed to put in an
@@ -2615,27 +2555,20 @@ def update_dependency_issue(
             # we should never be in this case but better safe than sorry...
             continue
 
-        messages.append(
-            remove_issue_dependency(
-                session,
-                issue=issue,
-                issue_blocked=issue_depend,
-                user=username,
-                ticketfolder=ticketfolder,
-            )
+        remove_issue_dependency(
+            session,
+            issue=issue,
+            issue_blocked=issue_depend,
+            user=username,
+            ticketfolder=ticketfolder,
         )
-        comment += "%s " % (depend)
-
-    if comment:
-        comment += "``"
-        mcomment.add_as_is(comment)
 
     session.commit()
     return messages
 
 
 def update_blocked_issue(
-        session, repo, issue, blocks, username, ticketfolder, mcomment):
+        session, repo, issue, blocks, username, ticketfolder):
     """ Update the upstream dependency of a specified issue (adding or
     removing them)
 
@@ -2646,12 +2579,10 @@ def update_blocked_issue(
     toadd = set(blocks) - set(issue.blocks_text)
     torm = set(issue.blocks_text) - set(blocks)
     messages = []
-    comment = ""
 
     # Add issue blocked
-    if toadd:
-        comment += "**Blocked** added blocking issue dependencies: ``"
     for block in toadd:
+        messages.append("Issue marked as blocked by: #%s" % block)
         issue_block = search_issues(session, repo, issueid=block)
         if issue_block is None:
             continue
@@ -2659,27 +2590,19 @@ def update_blocked_issue(
             # we should never be in this case but better safe than sorry...
             continue
 
-        messages.append(
-            add_issue_dependency(
-                session,
-                issue=issue,
-                issue_blocked=issue_block,
-                user=username,
-                ticketfolder=ticketfolder,
-            )
+
+        add_issue_dependency(
+            session,
+            issue=issue,
+            issue_blocked=issue_block,
+            user=username,
+            ticketfolder=ticketfolder,
         )
         session.commit()
-        comment += "%s " % (block)
-
-    if comment:
-        comment += "``"
-        mcomment.add_as_is(comment)
-        comment = ""
 
     # Remove issue blocked
-    if torm:
-        comment += "**Blocked** remove blocking issue dependencies: ``"
     for block in torm:
+        messages.append("Issue **un**marked as blocked by: #%s" % block)
         issue_block = search_issues(session, repo, issueid=block)
         if issue_block is None:  # pragma: no cover
             # We cannot test this as it would mean we managed to put in an
@@ -2690,20 +2613,13 @@ def update_blocked_issue(
             # we should never be in this case but better safe than sorry...
             continue
 
-        messages.append(
-            remove_issue_dependency(
-                session,
-                issue=issue_block,
-                issue_blocked=issue,
-                user=username,
-                ticketfolder=ticketfolder,
-            )
+        remove_issue_dependency(
+            session,
+            issue=issue_block,
+            issue_blocked=issue,
+            user=username,
+            ticketfolder=ticketfolder,
         )
-        comment += "%s " % (block)
-
-    if comment:
-        comment += "``"
-        mcomment.add_as_is(comment)
 
     session.commit()
     return messages
@@ -3592,7 +3508,7 @@ def set_custom_key_fields(session, project, fields, types, data):
     return 'List of custom fields updated'
 
 
-def set_custom_key_value(session, issue, key, value, mcomment):
+def set_custom_key_value(session, issue, key, value):
     """ Set or update the value of the specified custom key.
     """
 
@@ -3631,9 +3547,6 @@ def set_custom_key_value(session, issue, key, value, mcomment):
     if not delete:
         session.add(current_field)
 
-    if updated:
-        mcomment.add(key.name, old_value, value)
-
     if REDIS and updated:
         if issue.private:
             REDIS.publish('pagure.%s' % issue.uid, json.dumps({
@@ -3646,7 +3559,10 @@ def set_custom_key_value(session, issue, key, value, mcomment):
                 'issue': issue.to_json(public=True, with_comments=False),
             }))
 
-    return 'Custom field adjusted'
+    if value:
+        return 'Custom field %s adjusted to %s' % (key.name, value)
+    else:
+        return 'Custom field %s reset' % key.name
 
 
 def get_yearly_stats_user(session, user, date):
@@ -3768,3 +3684,31 @@ def get_active_milestones(session, project):
     )
 
     return sorted([item[0] for item in query.distinct()])
+
+
+def add_metadata_update_notif(session, issue, messages, user, ticketfolder):
+    ''' Add a notification to the specified issue with the given messages
+    which should reflect changes made to the meta-data of the issue.
+    '''
+    if not messages:
+        return
+
+    if not isinstance(messages, (list, set)):
+        messages = [messages]
+
+    user_id = None
+    if user:
+        user_obj = get_user(session, user)
+        user_id = user_obj.id
+
+    issue_comment = model.IssueComment(
+        issue_uid=issue.uid,
+        comment='Metadata Update:\n- %s' % ('\n- '.join(messages)),
+        user_id=user_id,
+        notification=True,
+    )
+    issue.last_updated = datetime.datetime.utcnow()
+    session.add(issue)
+    session.add(issue_comment)
+    # Make sure we won't have SQLAlchemy error before we continue
+    session.commit()
diff --git a/pagure/lib/git.py b/pagure/lib/git.py
index 21edd2b..53c548b 100644
--- a/pagure/lib/git.py
+++ b/pagure/lib/git.py
@@ -28,7 +28,6 @@ import pygit2
 import werkzeug
 
 from sqlalchemy.exc import SQLAlchemyError
-from .__init__ import MetaComment
 import pagure
 import pagure.exceptions
 import pagure.lib
@@ -426,7 +425,7 @@ def get_project_from_json(
     return project
 
 
-def update_custom_field_from_json(session, repo, issue, json_data, mcomment):
+def update_custom_field_from_json(session, repo, issue, json_data):
     ''' Update the custom fields according to the custom fields of
     the issue. If the custom field is not present for the repo in
     it's settings, this will create them.
@@ -467,13 +466,20 @@ def update_custom_field_from_json(session, repo, issue, json_data, mcomment):
         value = new_key.get('value')
         if value:
             value = value.strip()
-        pagure.lib.set_custom_key_value(
+        messages = pagure.lib.set_custom_key_value(
             session,
             issue=issue,
             key=key_obj,
             value=value,
-            mcomment=mcomment
         )
+        if messages:
+            pagure.lib.add_metadata_update_notif(
+                session=session,
+                issue=issue,
+                messages=messages,
+                user=None,
+                ticketfolder=None
+            )
         try:
             session.commit()
         except SQLAlchemyError:
@@ -501,9 +507,9 @@ def update_ticket_from_git(
                 reponame, username, namespace))
 
     user = get_user_from_json(session, json_data)
-    mcomment = MetaComment()
 
     issue = pagure.lib.get_issue_by_uid(session, issue_uid=issue_uid)
+    messages = []
     if not issue:
         # Create new issue
         pagure.lib.new_issue(
@@ -525,7 +531,7 @@ def update_ticket_from_git(
 
     else:
         # Edit existing issue
-        pagure.lib.edit_issue(
+        messages.extend(pagure.lib.edit_issue(
             session,
             issue=issue,
             ticketfolder=None,
@@ -535,8 +541,8 @@ def update_ticket_from_git(
             status=json_data.get('status'),
             close_status=json_data.get('close_status'),
             private=json_data.get('private'),
-            mcomment=mcomment
-        )
+        ))
+
     session.commit()
 
     issue = pagure.lib.get_issue_by_uid(session, issue_uid=issue_uid)
@@ -546,7 +552,6 @@ def update_ticket_from_git(
         repo=repo,
         issue=issue,
         json_data=json_data,
-        mcomment=mcomment
     )
 
     # Update milestone
@@ -564,14 +569,15 @@ def update_ticket_from_git(
             except SQLAlchemyError:
                 session.rollback()
     try:
-        msg = pagure.lib.edit_issue(
+        msgs = pagure.lib.edit_issue(
             session,
             issue=issue,
             ticketfolder=None,
             user=user.username,
             milestone=milestone,
-            mcomment=mcomment
         )
+        if msgs:
+            messages.extend(msgs)
     except SQLAlchemyError:
         session.rollback()
 
@@ -589,28 +595,27 @@ def update_ticket_from_git(
 
     # Update tags
     tags = json_data.get('tags', [])
-    pagure.lib.update_tags(
-        session, issue, tags, username=user.user, ticketfolder=None,
-        mcomment=mcomment)
+    messages.extend(pagure.lib.update_tags(
+        session, issue, tags, username=user.user, ticketfolder=None))
 
     # Update assignee
     assignee = get_user_from_json(session, json_data, key='assignee')
     if assignee:
-        pagure.lib.add_issue_assignee(
-            session, issue, assignee.username, mcomment=mcomment,
-            user=user.user, ticketfolder=None, notify=False)
+        messages.append(pagure.lib.add_issue_assignee(
+            session, issue, assignee.username,
+            user=user.user, ticketfolder=None, notify=False))
 
     # Update depends
     depends = json_data.get('depends', [])
-    pagure.lib.update_dependency_issue(
+    messages.extend(pagure.lib.update_dependency_issue(
         session, issue.project, issue, depends,
-        username=user.user, ticketfolder=None, mcomment=mcomment)
+        username=user.user, ticketfolder=None))
 
     # Update blocks
     blocks = json_data.get('blocks', [])
-    pagure.lib.update_blocked_issue(
+    messages.extend(pagure.lib.update_blocked_issue(
         session, issue.project, issue, blocks,
-        username=user.user, ticketfolder=None, mcomment=mcomment)
+        username=user.user, ticketfolder=None))
 
     for comment in json_data['comments']:
         user = get_user_from_json(session, comment)
@@ -627,17 +632,14 @@ def update_ticket_from_git(
                 date_created=datetime.datetime.utcfromtimestamp(
                     float(comment['date_created'])),
             )
-    if mcomment.is_set():
-        pagure.lib.add_issue_comment(
-            session,
-            issue,
-            comment='@%s updated metadata\n%s' % (
-                            user.username, mcomment.get()),
+    if messages:
+        pagure.lib.add_metadata_update_notif(
+            session=session,
+            issue=issue,
+            messages=messages,
             user=user.username,
-            ticketfolder=None,
-            notify=False,
-            notification=True)
-
+            ticketfolder=None
+        )
     session.commit()
 
 
diff --git a/pagure/templates/issue.html b/pagure/templates/issue.html
index d0933d9..fea354b 100644
--- a/pagure/templates/issue.html
+++ b/pagure/templates/issue.html
@@ -719,7 +719,9 @@ function try_async_comment(form) {
 
 {% if authenticated and g.repo_admin %}
 function take_issue(){
-  var _url = "{{ url_for('api_ns.api_assign_issue', repo=repo.name, username=username, issueid=issueid) }}";
+  var _url = "{{ url_for('api_ns.api_assign_issue',
+            repo=repo.name, namespace=repo.namespace, username=username,
+            issueid=issueid) }}";
   var _data = {assignee: "{{ g.fas_user.username }}"};
   $.post (_url, _data ).done(
     function(data) {
@@ -741,9 +743,9 @@ function take_issue(){
     or issue.user.user == g.fas_user.username
     or issue.assignee.user == g.fas_user.username) %}
 function drop_issue(){
-  var _url = "{{ url_for(
-      'api_ns.api_assign_issue', repo=repo.name, username=username, issueid=issueid
-      ) }}";
+  var _url = "{{ url_for('api_ns.api_assign_issue',
+            repo=repo.name, namespace=repo.namespace, username=username,
+            issueid=issueid) }}";
   var _data = {assignee: ""};
   $.post( _url, _data ).done(
     function(data) {
diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py
index 599f785..b436ff4 100644
--- a/pagure/ui/issues.py
+++ b/pagure/ui/issues.py
@@ -34,7 +34,6 @@ import pagure.doc_utils
 import pagure.exceptions
 import pagure.lib
 import pagure.lib.encoding_utils
-from pagure.lib import MetaComment
 import pagure.forms
 from pagure import (APP, SESSION, LOG, __get_file_in_tree,
                     login_required, authenticated, urlpattern)
@@ -206,32 +205,27 @@ def update_issue(repo, issueid, username=None, namespace=None):
                     ticketfolder=APP.config['TICKETS_FOLDER'],
                 )
                 SESSION.commit()
-                if message and not is_js:
-                    messages.add(message)
-
-            # Create our metadata comment object which is used to track and
-            # report of what metadata fields were updated.  This is then turned
-            # into a notificaion comment in the Issue.
-            mcomment = MetaComment()
+                if not is_js:
+                    if message:
+                        messages.add(message)
 
             # The status field can be updated by both the admin and the
             # person who opened the ticket.
             # Update status
             if repo_admin or flask.g.fas_user.username == issue.user.user:
                 if new_status in status:
-                    message = pagure.lib.edit_issue(
+                    msgs = pagure.lib.edit_issue(
                         SESSION,
                         issue=issue,
                         status=new_status,
                         close_status=close_status,
                         private=issue.private,
                         user=flask.g.fas_user.username,
-                        mcomment=mcomment,
                         ticketfolder=APP.config['TICKETS_FOLDER']
                     )
                     SESSION.commit()
-                    if message:
-                        messages.add(message)
+                    if msgs:
+                        messages = messages.union(set(msgs))
 
             # All the other meta-data can be changed only by admins
             # while other field will be missing for non-admin and thus
@@ -242,9 +236,8 @@ def update_issue(repo, issueid, username=None, namespace=None):
                     SESSION, issue, tags,
                     username=flask.g.fas_user.username,
                     ticketfolder=APP.config['TICKETS_FOLDER'],
-                    mcomment=mcomment
                 )
-                messages.union(set(msgs))
+                messages = messages.union(set(msgs))
 
             # The meta-data can be changed by admins and issue creator,
             # where issue creators can only change status of their issue while
@@ -258,7 +251,6 @@ def update_issue(repo, issueid, username=None, namespace=None):
                     assignee=assignee or None,
                     user=flask.g.fas_user.username,
                     ticketfolder=APP.config['TICKETS_FOLDER'],
-                    mcomment=mcomment
                 )
                 SESSION.commit()
                 if message and message != 'Nothing to change':
@@ -269,7 +261,7 @@ def update_issue(repo, issueid, username=None, namespace=None):
                     new_priority = None
 
                 # Update core metadata
-                message = pagure.lib.edit_issue(
+                msgs = pagure.lib.edit_issue(
                     SESSION,
                     repo=repo,
                     issue=issue,
@@ -278,11 +270,10 @@ def update_issue(repo, issueid, username=None, namespace=None):
                     private=form.private.data,
                     user=flask.g.fas_user.username,
                     ticketfolder=APP.config['TICKETS_FOLDER'],
-                    mcomment=mcomment
                 )
                 SESSION.commit()
-                if message:
-                    messages.add(message)
+                if msgs:
+                    messages = messages.union(set(msgs))
 
                 # Update the custom keys/fields
                 for key in repo.issue_keys:
@@ -299,15 +290,17 @@ def update_issue(repo, issueid, username=None, namespace=None):
                                         '(%s) has invalid url (%s) ' %
                                         (key.name, link))
 
-                    pagure.lib.set_custom_key_value(
-                        SESSION, issue, key, value, mcomment=mcomment)
+                    msg = pagure.lib.set_custom_key_value(
+                        SESSION, issue, key, value)
+                    if msg:
+                        messages.add(msg)
 
                 # Update ticket this one depends on
                 msgs = pagure.lib.update_dependency_issue(
                     SESSION, repo, issue, depends,
                     username=flask.g.fas_user.username,
                     ticketfolder=APP.config['TICKETS_FOLDER'],
-                    mcomment=mcomment)
+                )
                 messages.union(set(msgs))
 
                 # Update ticket(s) depending on this one
@@ -315,26 +308,25 @@ def update_issue(repo, issueid, username=None, namespace=None):
                     SESSION, repo, issue, blocks,
                     username=flask.g.fas_user.username,
                     ticketfolder=APP.config['TICKETS_FOLDER'],
-                    mcomment=mcomment)
+                )
                 messages.union(set(msgs))
 
-                # Add the comment for field updates:
-                if mcomment.is_set():
-                    pagure.lib.add_issue_comment(
-                        SESSION,
-                        issue,
-                        comment='@%s updated metadata\n%s' % (
-                            flask.g.fas_user.username, mcomment.get()),
-                        user=flask.g.fas_user.username,
-                        ticketfolder=APP.config['TICKETS_FOLDER'],
-                        notify=False,
-                        notification=True)
-                    messages.add('Metadata fields updated')
-
             if not is_js:
                 for message in messages:
                     flask.flash(message)
 
+            # Add the comment for field updates:
+            if messages:
+                not_needed = set(['Comment added', 'Updated comment'])
+                pagure.lib.add_metadata_update_notif(
+                    session=SESSION,
+                    issue=issue,
+                    messages=messages - not_needed,
+                    user=flask.g.fas_user.username,
+                    ticketfolder=APP.config['TICKETS_FOLDER']
+                )
+                messages.add('Metadata fields updated')
+
         except pagure.exceptions.PagureException as err:
             is_js = False
             SESSION.rollback()
@@ -1098,13 +1090,8 @@ def edit_issue(repo, issueid, username=None, namespace=None):
                 404, 'No such user found in the database: %s' % (
                     flask.g.fas_user.username))
 
-        # Create our metadata comment object which is used to track and
-        # report of what metadata fields were updated.  This is then turned
-        # into a notificaion comment in the Issue.
-        mcomment = MetaComment()
-
         try:
-            message = pagure.lib.edit_issue(
+            messages = pagure.lib.edit_issue(
                 SESSION,
                 issue=issue,
                 title=title,
@@ -1113,19 +1100,16 @@ def edit_issue(repo, issueid, username=None, namespace=None):
                 user=flask.g.fas_user.username,
                 ticketfolder=APP.config['TICKETS_FOLDER'],
                 private=private,
-                mcomment=mcomment
             )
             SESSION.commit()
-            if mcomment.is_set():
-                pagure.lib.add_issue_comment(
-                    SESSION,
-                    issue,
-                    comment='@%s updated metadata\n%s' % (
-                            flask.g.fas_user.username, mcomment.get()),
+            if messages:
+                pagure.lib.add_metadata_update_notif(
+                    session=SESSION,
+                    issue=issue,
+                    messages=messages,
                     user=flask.g.fas_user.username,
-                    ticketfolder=APP.config['TICKETS_FOLDER'],
-                    notify=False,
-                    notification=True)
+                    ticketfolder=APP.config['TICKETS_FOLDER']
+                )
 
             # If there is a file attached, attach it.
             filestream = flask.request.files.get('filestream')
@@ -1153,7 +1137,8 @@ def edit_issue(repo, issueid, username=None, namespace=None):
                 issue.content = issue.content.replace('<!!image>', url)
                 SESSION.add(issue)
                 SESSION.commit()
-            flask.flash(message)
+            for message in messages:
+                flask.flash(message)
             url = flask.url_for(
                 'view_issue', username=username, namespace=namespace,
                 repo=repo.name, issueid=issueid)
diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py
index b6148bf..9684ce7 100644
--- a/pagure/ui/repo.py
+++ b/pagure/ui/repo.py
@@ -50,7 +50,6 @@ import pagure.ui.plugins
 from pagure import (APP, SESSION, LOG, __get_file_in_tree, login_required,
                     admin_session_timedout)
 from pagure.lib import encoding_utils
-from pagure.lib import MetaComment
 
 
 @APP.route('/<repo>.git')
@@ -1117,16 +1116,16 @@ def update_project(repo, username=None, namespace=None):
     form = pagure.forms.ProjectFormSimplified()
 
     if form.validate_on_submit():
-        mcomment = MetaComment()
+
         try:
             repo.description = form.description.data
             repo.avatar_email = form.avatar_email.data.strip()
             repo.url = form.url.data.strip()
-            pagure.lib.update_tags(
+            messages = pagure.lib.update_tags(
                 SESSION, repo,
                 tags=[t.strip() for t in form.tags.data.split(',')],
                 username=flask.g.fas_user.username,
-                ticketfolder=None, mcomment=mcomment
+                ticketfolder=None,
             )
             SESSION.add(repo)
             SESSION.commit()

From a185478998bb3374bdf61417832867d3a31cb429 Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 7/16] Adjust the unit-tests for the other proposal around logging meta-data update


---

diff --git a/tests/test_pagure_flask_api_issue.py b/tests/test_pagure_flask_api_issue.py
index 92e0a07..01ce59f 100644
--- a/tests/test_pagure_flask_api_issue.py
+++ b/tests/test_pagure_flask_api_issue.py
@@ -1094,7 +1094,10 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': 'Successfully edited issue #1'}
+            {'message':[
+                'Issue status updated to: Closed',
+                'Issue close_status updated to: Fixed'
+            ]}
         )
 
         headers = {'Authorization': 'token pingou_foo'}
@@ -1506,7 +1509,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': 'Issue assigned'}
+            {'message': 'Issue assigned to pingou'}
         )
 
         # Un-assign
@@ -1544,7 +1547,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': 'Issue assigned'}
+            {'message': 'Issue assigned to pingou'}
         )
 
         # Un-assign
@@ -1566,7 +1569,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': 'Issue assigned'}
+            {'message': 'Issue assigned to pingou'}
         )
 
         # One comment added
@@ -1666,7 +1669,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         data = json.loads(output.data)
         self.assertDictEqual(
             data,
-            {'message': 'Issue assigned'}
+            {'message': 'Issue assigned to pingou'}
         )
 
     @patch('pagure.lib.git.update_git')
@@ -1993,7 +1996,8 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         self.assertDictEqual(
             data,
             {
-              "message": "Custom field adjusted"
+              "message": "Custom field bugzilla adjusted to "
+                "https://bugzilla.redhat.com/1234"
             }
         )
 
@@ -2014,7 +2018,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         self.assertDictEqual(
             data,
             {
-              "message": "Custom field adjusted"
+              "message": "Custom field bugzilla reset"
             }
         )
 
diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py
index 8e37209..27de057 100644
--- a/tests/test_pagure_flask_api_project.py
+++ b/tests/test_pagure_flask_api_project.py
@@ -29,9 +29,6 @@ sys.path.insert(0, os.path.join(os.path.dirname(
 import pagure.lib
 import tests
 from pagure.lib.repo import PagureRepo
-from pagure.lib import MetaComment
-
-mcomment = MetaComment()
 
 
 class PagureFlaskApiProjecttests(tests.Modeltests):
@@ -124,8 +121,8 @@ class PagureFlaskApiProjecttests(tests.Modeltests):
         # Adding a tag
         output = pagure.lib.update_tags(
             self.session, repo, 'infra', 'pingou',
-            None, mcomment)
-        self.assertEqual(output, ['Tag added: infra'])
+            None)
+        self.assertEqual(output, ['Issue tagged with: infra'])
 
         # Check after adding
         repo = pagure.lib.get_project(self.session, 'test')
@@ -322,8 +319,8 @@ class PagureFlaskApiProjecttests(tests.Modeltests):
         # Adding a tag
         output = pagure.lib.update_tags(
             self.session, repo, 'infra', 'pingou',
-            ticketfolder=None, mcomment=mcomment)
-        self.assertEqual(output, ['Tag added: infra'])
+            ticketfolder=None)
+        self.assertEqual(output, ['Issue tagged with: infra'])
 
         # Check after adding
         repo = pagure.lib.get_project(self.session, 'test')
diff --git a/tests/test_pagure_flask_dump_load_ticket.py b/tests/test_pagure_flask_dump_load_ticket.py
index 0e00519..b88c0ff 100644
--- a/tests/test_pagure_flask_dump_load_ticket.py
+++ b/tests/test_pagure_flask_dump_load_ticket.py
@@ -26,9 +26,6 @@ sys.path.insert(0, os.path.join(os.path.dirname(
 
 import pagure.lib
 import tests
-from pagure.lib import MetaComment
-
-mcomment = MetaComment()
 
 
 class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
@@ -132,10 +129,9 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
             assignee='pingou',
             user='pingou',
             ticketfolder=repopath,
-            mcomment=mcomment
         )
         self.session.commit()
-        self.assertEqual(msg, 'Issue assigned')
+        self.assertEqual(msg, 'Issue assigned to pingou')
         # Add a couple of tags on the ticket
         msg = pagure.lib.add_tag_obj(
             session=self.session,
@@ -145,7 +141,7 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
             ticketfolder=repopath,
         )
         self.session.commit()
-        self.assertEqual(msg, 'Tag added: feature, future')
+        self.assertEqual(msg, 'Issue tagged with: feature, future')
         # Add dependencies
         msg = pagure.lib.add_issue_dependency(
             session=self.session,
@@ -155,7 +151,7 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
             ticketfolder=repopath,
         )
         self.session.commit()
-        self.assertEqual(msg, 'Dependency added')
+        self.assertEqual(msg, 'Issue marked as depending on: #2')
         msg = pagure.lib.add_issue_dependency(
             session=self.session,
             issue=issue3,
@@ -164,7 +160,7 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests):
             ticketfolder=repopath,
         )
         self.session.commit()
-        self.assertEqual(msg, 'Dependency added')
+        self.assertEqual(msg, 'Issue marked as depending on: #1')
 
         # Dump the JSON
         pagure.lib.git.update_git(issue, repo, repopath)
diff --git a/tests/test_pagure_flask_ui_issues.py b/tests/test_pagure_flask_ui_issues.py
index 20a6f9b..8213d8f 100644
--- a/tests/test_pagure_flask_ui_issues.py
+++ b/tests/test_pagure_flask_ui_issues.py
@@ -31,9 +31,6 @@ sys.path.insert(0, os.path.join(os.path.dirname(
 
 import pagure.lib
 import tests
-from pagure.lib import MetaComment
-
-mcomment = MetaComment()
 
 
 class PagureFlaskIssuestests(tests.Modeltests):
@@ -550,11 +547,14 @@ class PagureFlaskIssuestests(tests.Modeltests):
             milestone=b'käpy'.decode('utf-8'),
             private=False,
             user='pingou',
-            ticketfolder=None,
-            mcomment=mcomment
+            ticketfolder=None
+        )
+        self.assertEqual(
+            message,
+            [
+                u'Issue set to the milestone: k\xe4py'
+            ]
         )
-        print "MARK2 " + message
-        self.assertEqual(message, 'Successfully edited issue #1')
         self.session.commit()
 
         output = self.app.get('/test/issue/1')
@@ -681,16 +681,20 @@ class PagureFlaskIssuestests(tests.Modeltests):
                 'href="/test/issue/1/edit" title="Edit this issue">',
                 output.data)
             self.assertIn(
-                '</button>\n                      Successfully edited issue #1',
+                '</button>\n                      '
+                'Issue close_status updated to: Fixed\n',
+                output.data)
+            self.assertIn(
+                '</button>\n                      '
+                'Issue status updated to: Closed\n',
                 output.data)
             self.assertTrue(
                 '<option selected value="Fixed">Fixed</option>'
                 in output.data)
             self.assertIn(
-                '<small><p><a href="https://pagure.org/user/pingou"> '
-                '@pingou</a> updated metadata'
-                .format(
-                    app_url=pagure.APP.config['APP_URL'].rstrip('/')),
+                '''<small><p>Metadata Update:<br>
+- Issue status updated to: Closed<br>
+- Issue close_status updated to: Fixed</p></small>''',
                 output.data)
 
             # Add new comment
@@ -792,7 +796,7 @@ class PagureFlaskIssuestests(tests.Modeltests):
                 'href="/test/issue/1/edit" title="Edit this issue">',
                 output.data)
             self.assertIn(
-                '</button>\n                      Issue assigned',
+                '</button>\n                      Issue assigned to pingou\n',
                 output.data)
             self.assertTrue(
                 '<a href="/test/issues?assignee=pingou">' in output.data)
@@ -1495,7 +1499,12 @@ class PagureFlaskIssuestests(tests.Modeltests):
                 '/test/issue/1/edit', data=data, follow_redirects=True)
             self.assertEqual(output.status_code, 200)
             self.assertIn(
-                '</button>\n                      Successfully edited issue #1',
+                '</button>\n                      '
+                'Issue title edited\n',
+                output.data)
+            self.assertIn(
+                '</button>\n                      '
+                'Issue description edited\n',
                 output.data)
             self.assertIn(
                 '<span class="issueid label label-default">#1</span>\n'
@@ -1566,7 +1575,7 @@ class PagureFlaskIssuestests(tests.Modeltests):
             user='pingou',
             ticketfolder=None)
         self.session.commit()
-        self.assertEqual(msg, 'Tag added: tag1')
+        self.assertEqual(msg, 'Issue tagged with: tag1')
 
         # Before edit, list tags
         tags = pagure.lib.get_tags_of_project(self.session, repo)
@@ -1669,7 +1678,7 @@ class PagureFlaskIssuestests(tests.Modeltests):
             user='pingou',
             ticketfolder=None)
         self.session.commit()
-        self.assertEqual(msg, 'Tag added: tag1')
+        self.assertEqual(msg, 'Issue tagged with: tag1')
 
         # Before edit, list tags
         tags = pagure.lib.get_tags_of_project(self.session, repo)
@@ -1701,8 +1710,8 @@ class PagureFlaskIssuestests(tests.Modeltests):
             self.assertEqual(output.status_code, 200)
             self.assertTrue("<h3>Settings for test</h3>" in output.data)
             self.assertIn(
-                '</button>\n                      Removed tag: tag1',
-                output.data)
+                '</button>\n                      '
+                'Issue **un**tagged with: tag1', output.data)
 
     @patch('pagure.lib.git.update_git')
     @patch('pagure.lib.notify.send_email')
@@ -1995,7 +2004,7 @@ class PagureFlaskIssuestests(tests.Modeltests):
             self.assertEqual(output.status_code, 200)
             self.assertIn(
                 '</button>\n                      '
-                'Successfully edited issue #2\n',
+                'Issue close_status updated to: Invalid\n',
                 output.data
             )
             self.assertIn(
@@ -2003,6 +2012,11 @@ class PagureFlaskIssuestests(tests.Modeltests):
                 output.data
             )
             self.assertIn(
+                '</button>\n                      '
+                'Issue status updated to: Closed\n',
+                output.data
+            )
+            self.assertIn(
                 'editmetadatatoggle">\n              Edit Metadata',
                 output.data
             )
@@ -2014,7 +2028,15 @@ class PagureFlaskIssuestests(tests.Modeltests):
 
         # Ticket #2 has one less comment and is closed
         issue = pagure.lib.search_issues(self.session, repo, issueid=2)
-        self.assertEqual(len(issue.comments), 1)
+        self.assertEqual(len(issue.comments), 2)
+        self.assertEqual(
+            issue.comments[0].comment,
+            'Nevermind figured it out')
+        self.assertEqual(
+            issue.comments[1].comment,
+            'Metadata Update:\n'
+            '- Issue close_status updated to: Invalid\n'
+            '- Issue status updated to: Closed')
         self.assertEqual(issue.status, 'Closed')
 
     @patch('pagure.lib.git.update_git')
diff --git a/tests/test_pagure_flask_ui_roadmap.py b/tests/test_pagure_flask_ui_roadmap.py
index 64755e8..503382b 100644
--- a/tests/test_pagure_flask_ui_roadmap.py
+++ b/tests/test_pagure_flask_ui_roadmap.py
@@ -461,7 +461,7 @@ class PagureFlaskRoadmaptests(tests.Modeltests):
                     output.data)
                 self.assertIn(
                     u'</button>\n                      '
-                    u'Successfully edited issue #%s' % cnt,
+                    u'Issue set to the milestone: %s\n' % mstone,
                     output.data)
 
         repo = pagure.lib.get_project(self.session, 'test')
diff --git a/tests/test_pagure_lib.py b/tests/test_pagure_lib.py
index b4120a7..903adbe 100644
--- a/tests/test_pagure_lib.py
+++ b/tests/test_pagure_lib.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 
 """
- (c) 2015-2016 - Copyright Red Hat Inc
+ (c) 2015-2017 - Copyright Red Hat Inc
 
  Authors:
    Pierre-Yves Chibon <pingou@pingoured.fr>
@@ -24,9 +24,6 @@ sys.path.insert(0, os.path.join(os.path.dirname(
 import pagure.lib
 import pagure.lib.model
 import tests
-from pagure.lib import MetaComment
-
-mcomment = MetaComment()
 
 
 class PagureLibtests(tests.Modeltests):
@@ -239,30 +236,27 @@ class PagureLibtests(tests.Modeltests):
             session=self.session,
             issue=issue,
             user='pingou',
-            ticketfolder=None,
-            mcomment=mcomment)
+            ticketfolder=None)
         self.session.commit()
-        self.assertEqual(msg, None or '')
+        self.assertEqual(msg, None)
 
         msg = pagure.lib.edit_issue(
             session=self.session,
             issue=issue,
             user='pingou',
             ticketfolder=None,
-            mcomment=mcomment,
             title='Test issue #2',
             content='We should work on this for the second time',
             status='Open',
         )
         self.session.commit()
-        self.assertEqual(msg, None or '')
+        self.assertEqual(msg, None)
 
         msg = pagure.lib.edit_issue(
             session=self.session,
             issue=issue,
             user='pingou',
             ticketfolder=None,
-            mcomment=mcomment,
             title='Foo issue #2',
             content='We should work on this period',
             status='Closed',
@@ -270,7 +264,16 @@ class PagureLibtests(tests.Modeltests):
             private=True,
         )
         self.session.commit()
-        self.assertEqual(msg, 'Successfully edited issue #2')
+        self.assertEqual(
+            msg,
+            [
+                'Issue title edited',
+                'Issue description edited',
+                'Issue status updated to: Closed',
+                'Issue close_status updated to: Invalid',
+                'Issue private status set to: True'
+            ]
+        )
 
         repo = pagure.lib.get_project(self.session, 'test')
         self.assertEqual(repo.open_tickets, 1)
@@ -284,12 +287,11 @@ class PagureLibtests(tests.Modeltests):
             issue=issue,
             user='pingou',
             status='Open',
-            mcomment=mcomment,
             ticketfolder=None,
             private=True,
         )
         self.session.commit()
-        self.assertEqual(msg, 'Successfully edited issue #2')
+        self.assertEqual(msg, ['Issue status updated to: Open'])
 
         repo = pagure.lib.get_project(self.session, 'test')
         for issue in repo.issues:
@@ -308,10 +310,15 @@ class PagureLibtests(tests.Modeltests):
             close_status='Invalid',
             ticketfolder=None,
             private=True,
-            mcomment=mcomment
         )
         self.session.commit()
-        self.assertEqual(msg, 'Successfully edited issue #2')
+        self.assertEqual(
+            msg,
+            [
+                'Issue status updated to: Closed',
+                'Issue close_status updated to: Invalid'
+            ]
+        )
 
         repo = pagure.lib.get_project(self.session, 'test')
         self.assertEqual(repo.open_tickets, 1)
@@ -354,7 +361,7 @@ class PagureLibtests(tests.Modeltests):
             user='pingou',
             ticketfolder=None)
         self.session.commit()
-        self.assertEqual(msg, 'Dependency added')
+        self.assertEqual(msg, 'Issue marked as depending on: #2')
 
         # After
         self.assertEqual(len(issue.parents), 1)
@@ -386,7 +393,7 @@ class PagureLibtests(tests.Modeltests):
             user='pingou',
             ticketfolder=None)
         self.session.commit()
-        self.assertEqual(msg, 'Tag added: tag1')
+        self.assertEqual(msg, 'Issue tagged with: tag1')
 
         # Try a second time
         msg = pagure.lib.add_tag_obj(
@@ -431,7 +438,7 @@ class PagureLibtests(tests.Modeltests):
             user='pingou',
             ticketfolder=None)
 
-        self.assertEqual(msgs, [u'Removed tag: tag1'])
+        self.assertEqual(msgs, ['Issue **un**tagged with: tag1'])
 
     @patch('pagure.lib.git.update_git')
     @patch('pagure.lib.notify.send_email')
@@ -450,7 +457,7 @@ class PagureLibtests(tests.Modeltests):
             tags='tag1',
             user='pingou',
             ticketfolder=None)
-        self.assertEqual(msgs, 'Removed tag: tag1')
+        self.assertEqual(msgs, 'Issue **un**tagged with: tag1')
 
     @patch('pagure.lib.git.update_git')
     @patch('pagure.lib.notify.send_email')
@@ -468,7 +475,7 @@ class PagureLibtests(tests.Modeltests):
             tags=['pagure', 'test'],
             user='pingou',
             ticketfolder=None)
-        self.assertEqual(msg, 'Tag added: pagure, test')
+        self.assertEqual(msg, 'Issue tagged with: pagure, test')
         self.session.commit()
 
         # Check the tags
@@ -482,7 +489,7 @@ class PagureLibtests(tests.Modeltests):
             tags='test',
             user='pingou',
             ticketfolder=None)
-        self.assertEqual(msgs, 'Removed tag: test')
+        self.assertEqual(msgs, 'Issue **un**tagged with: test')
         self.session.commit()
 
         # Check the tags
@@ -550,7 +557,7 @@ class PagureLibtests(tests.Modeltests):
             user='pingou',
             ticketfolder=None)
         self.session.commit()
-        self.assertEqual(msg, 'Tag added: tag3')
+        self.assertEqual(msg, 'Issue tagged with: tag3')
         self.assertEqual([tag.tag for tag in issue.tags], ['tag2', 'tag3'])
 
         # Attempt to rename an existing tag into another existing one
@@ -679,7 +686,6 @@ class PagureLibtests(tests.Modeltests):
             assignee='foo@foobar.com',
             user='foo@pingou.com',
             ticketfolder=None,
-            mcomment=mcomment
         )
 
         self.assertRaises(
@@ -690,7 +696,6 @@ class PagureLibtests(tests.Modeltests):
             assignee='foo@bar.com',
             user='foo@foopingou.com',
             ticketfolder=None,
-            mcomment=mcomment
         )
 
         # Set the assignee by its email
@@ -699,10 +704,9 @@ class PagureLibtests(tests.Modeltests):
             issue=issue,
             assignee='foo@bar.com',
             user='foo@pingou.com',
-            ticketfolder=None,
-            mcomment=mcomment)
+            ticketfolder=None)
         self.session.commit()
-        self.assertEqual(msg, 'Issue assigned')
+        self.assertEqual(msg, 'Issue assigned to foo@bar.com')
 
         # Change the assignee to someone else by its username
         msg = pagure.lib.add_issue_assignee(
@@ -710,10 +714,9 @@ class PagureLibtests(tests.Modeltests):
             issue=issue,
             assignee='pingou',
             user='pingou',
-            ticketfolder=None,
-            mcomment=mcomment)
+            ticketfolder=None)
         self.session.commit()
-        self.assertEqual(msg, 'Issue assigned')
+        self.assertEqual(msg, 'Issue assigned to pingou')
 
         # After  -- Searches by assignee
         issues = pagure.lib.search_issues(
@@ -748,8 +751,7 @@ class PagureLibtests(tests.Modeltests):
             issue=issue,
             assignee=None,
             user='pingou',
-            ticketfolder=None,
-            mcomment=mcomment)
+            ticketfolder=None)
         self.session.commit()
         self.assertEqual(msg, 'Assignee reset')
 
@@ -783,10 +785,9 @@ class PagureLibtests(tests.Modeltests):
             issue=issue,
             assignee='foo@bar.com',
             user='foo@pingou.com',
-            ticketfolder=None,
-            mcomment=mcomment)
+            ticketfolder=None)
         self.session.commit()
-        self.assertEqual(msg, 'Issue assigned')
+        self.assertEqual(msg, 'Issue assigned to foo@bar.com')
 
         # Add a comment to that issue
         msg = pagure.lib.add_issue_comment(
@@ -1929,7 +1930,7 @@ class PagureLibtests(tests.Modeltests):
             user='pingou',
             ticketfolder=None)
         self.session.commit()
-        self.assertEqual(msg, 'Dependency removed')
+        self.assertEqual(msg, 'Issue **un**marked as depending on: #1')
 
         # After
         self.assertEqual(issue.parents, [])
@@ -1993,9 +1994,8 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(issue.tags_text, [])
 
         messages = pagure.lib.update_tags(
-            self.session, issue, 'tag', 'pingou', ticketfolder=None,
-            mcomment=mcomment)
-        self.assertEqual(messages, ['Tag added: tag'])
+            self.session, issue, 'tag', 'pingou', ticketfolder=None)
+        self.assertEqual(messages, ['Issue tagged with: tag'])
 
         # after
         repo = pagure.lib.get_project(self.session, 'test')
@@ -2008,9 +2008,13 @@ class PagureLibtests(tests.Modeltests):
         # Replace the tag by two others
         messages = pagure.lib.update_tags(
             self.session, issue, ['tag2', 'tag3'], 'pingou',
-            ticketfolder=None, mcomment=mcomment)
+            ticketfolder=None)
         self.assertEqual(
-            messages, ['Tag added: tag2, tag3', 'Removed tag: tag'])
+            messages, [
+                'Issue tagged with: tag2, tag3',
+                'Issue **un**tagged with: tag'
+            ]
+        )
 
         # after
         repo = pagure.lib.get_project(self.session, 'test')
@@ -2058,14 +2062,20 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(issue.blocks_text, [])
 
         messages = pagure.lib.update_dependency_issue(
-            self.session, repo, issue, '2', 'pingou', ticketfolder=None,
-            mcomment=mcomment)
-        self.assertEqual(messages, ['Dependency added'])
+            self.session, repo, issue, '2', 'pingou', ticketfolder=None)
+        self.assertEqual(messages, ['Issue marked as depending on: #2'])
         messages = pagure.lib.update_dependency_issue(
             self.session, repo, issue, ['3', '4', 5], 'pingou',
-            ticketfolder=None, mcomment=mcomment)
+            ticketfolder=None)
         self.assertEqual(
-            messages, ['Dependency added', 'Dependency removed'])
+            messages,
+            [
+                'Issue marked as depending on: #3',
+                'Issue marked as depending on: #4',
+                'Issue marked as depending on: #5',
+                'Issue **un**marked as depending on: #2'
+            ]
+        )
 
         # after
         self.assertEqual(issue.tags_text, [])
@@ -2102,14 +2112,17 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(issue.blocks_text, [])
 
         messages = pagure.lib.update_blocked_issue(
-            self.session, repo, issue, '2', 'pingou', ticketfolder=None,
-            mcomment=mcomment)
-        self.assertEqual(messages, ['Dependency added'])
+            self.session, repo, issue, '2', 'pingou', ticketfolder=None)
+        self.assertEqual(messages, ['Issue marked as blocked by: #2'])
         messages = pagure.lib.update_blocked_issue(
             self.session, repo, issue, ['3', '4', 5], 'pingou',
-            ticketfolder=None, mcomment=mcomment)
+            ticketfolder=None)
         self.assertEqual(
-            messages, ['Dependency added', 'Dependency removed'])
+            messages, [
+                'Issue marked as blocked by: #3',
+                'Issue marked as blocked by: #4',
+                'Issue marked as blocked by: #5',
+                'Issue **un**marked as blocked by: #2'])
 
         # after
         self.assertEqual(issue.tags_text, [])
diff --git a/tests/test_pagure_lib_git.py b/tests/test_pagure_lib_git.py
index 7fc9146..bb1d0d7 100644
--- a/tests/test_pagure_lib_git.py
+++ b/tests/test_pagure_lib_git.py
@@ -27,9 +27,7 @@ import pagure.lib.git
 import tests
 
 from pagure.lib.repo import PagureRepo
-from pagure.lib import MetaComment
 
-mcomment = MetaComment()
 
 class PagureLibGittests(tests.Modeltests):
     """ Tests for pagure.lib.git """
@@ -1643,7 +1641,7 @@ index 0000000..60f7480
         }
 
         pagure.lib.git.update_custom_field_from_json(
-            self.session, repo, issue, json_data, mcomment=mcomment)
+            self.session, repo, issue, json_data)
 
         updated_issue = pagure.lib.get_issue_by_uid(self.session, 'someuid')
 
@@ -1686,7 +1684,7 @@ index 0000000..60f7480
         }
 
         pagure.lib.git.update_custom_field_from_json(
-            self.session, repo, issue, json_data, mcomment=mcomment)
+            self.session, repo, issue, json_data)
 
         updated_issue = pagure.lib.get_issue_by_uid(self.session, 'someuid')
 

From be6d3f06bbbbd9747e4675c67c99ddca67b751ea Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 8/16] Mention who was updating the metadata in the notification


---

diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py
index 56959fb..0518eab 100644
--- a/pagure/lib/__init__.py
+++ b/pagure/lib/__init__.py
@@ -3703,7 +3703,8 @@ def add_metadata_update_notif(session, issue, messages, user, ticketfolder):
 
     issue_comment = model.IssueComment(
         issue_uid=issue.uid,
-        comment='Metadata Update:\n- %s' % ('\n- '.join(messages)),
+        comment='**Metadata Update from @%s**:\n- %s' % (
+            user, '\n- '.join(messages)),
         user_id=user_id,
         notification=True,
     )

From 9746f564685a3e00d318798a006edc39b434bd75 Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 9/16] Report the old values of: assignee, status, close_status, priority and milestone


---

diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py
index 0518eab..20f84db 100644
--- a/pagure/lib/__init__.py
+++ b/pagure/lib/__init__.py
@@ -431,6 +431,7 @@ def add_issue_assignee(session, issue, assignee, user, ticketfolder,
     elif not assignee and issue.assignee is None:
         return
 
+    old_assignee = issue.assignee
     # Validate the assignee
     assignee_obj = get_user(session, assignee)
 
@@ -463,7 +464,10 @@ def add_issue_assignee(session, issue, assignee, user, ticketfolder,
             REDIS.publish('pagure.%s' % issue.uid, json.dumps(
                 {'assigned': assignee_obj.to_json(public=True)}))
 
-        return 'Issue assigned to %s' % assignee
+        output = 'Issue assigned to %s' % assignee
+        if old_assignee:
+            output += ' (was: %s)' % old_assignee.username
+        return output
 
 
 def add_pull_request_assignee(
@@ -1423,6 +1427,7 @@ def edit_issue(session, issue, ticketfolder, user, repo=None,
         edit.append('content')
         messages.append('Issue description edited')
     if status and status != issue.status:
+        old_status = issue.status
         issue.status = status
         if status.lower() != 'open':
             issue.closed_at = datetime.datetime.utcnow()
@@ -1430,28 +1435,45 @@ def edit_issue(session, issue, ticketfolder, user, repo=None,
             issue.close_status = None
             edit.append('close_status')
         edit.append('status')
-        messages.append('Issue status updated to: %s' % status)
+        messages.append(
+            'Issue status updated to: %s (was: %s)' % (status, old_status))
     if close_status != -1 and close_status != issue.close_status:
+        old_status = issue.close_status
         issue.close_status = close_status
         edit.append('close_status')
-        messages.append('Issue close_status updated to: %s' % close_status)
+        msg = 'Issue close_status updated to: %s' % close_status
+        if old_status:
+            msg += ' (was: %s)' % old_status
+        messages.append(msg)
     if priority:
         try:
             priority = int(priority)
         except:
             priority = None
         if priority != issue.priority:
+            old_priority = issue.priority
             issue.priority = priority
             edit.append('priority')
-            messages.append('Issue priority set to: %s' % priority)
+            msg = 'Issue priority set to: %s' % priority
+            if old_priority:
+                msg += ' (was: %s)' % old_priority
+            messages.append(msg)
     if private in [True, False] and private != issue.private:
+        old_private = issue.private
         issue.private = private
         edit.append('private')
-        messages.append('Issue private status set to: %s' % private)
+        msg = 'Issue private status set to: %s' % priority
+        if old_private:
+            msg += ' (was: %s)' % old_private
+        messages.append(msg)
     if milestone != -1 and milestone != issue.milestone:
+        old_milestone = issue.milestone
         issue.milestone = milestone
         edit.append('milestone')
-        messages.append('Issue set to the milestone: %s' % milestone)
+        msg = 'Issue set to the milestone: %s' % milestone
+        if old_private:
+            msg += ' (was: %s)' % old_milestone
+        messages.append(msg)
     issue.last_updated = datetime.datetime.utcnow()
     # uniquify the list of edited fields
     edit = list(set(edit))

From f1467c69c1f50e395f49f7cd4396caf15461b479 Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 10/16] Report the old values of the custom fields that have been updated


---

diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py
index 20f84db..a53c5a5 100644
--- a/pagure/lib/__init__.py
+++ b/pagure/lib/__init__.py
@@ -3582,7 +3582,10 @@ def set_custom_key_value(session, issue, key, value):
             }))
 
     if value:
-        return 'Custom field %s adjusted to %s' % (key.name, value)
+        output = 'Custom field %s adjusted to %s' % (key.name, value)
+        if old_value:
+            output += ' (was: %s)' % old_value
+        return output
     else:
         return 'Custom field %s reset' % key.name
 

From cf28273b3b16357a26b0d7598ba119d5c2cd961f Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 11/16] Drop reporting changes made to the title or the description of the issue


---

diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py
index a53c5a5..ef6119e 100644
--- a/pagure/lib/__init__.py
+++ b/pagure/lib/__init__.py
@@ -1421,11 +1421,9 @@ def edit_issue(session, issue, ticketfolder, user, repo=None,
     if title and title != issue.title:
         issue.title = title
         edit.append('title')
-        messages.append('Issue title edited')
     if content and content != issue.content:
         issue.content = content
         edit.append('content')
-        messages.append('Issue description edited')
     if status and status != issue.status:
         old_status = issue.status
         issue.status = status

From 78814efe9e4d1bf92c55f51a134a70edcb800375 Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 12/16] Typi typo


---

diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py
index ef6119e..a896428 100644
--- a/pagure/lib/__init__.py
+++ b/pagure/lib/__init__.py
@@ -1469,7 +1469,7 @@ def edit_issue(session, issue, ticketfolder, user, repo=None,
         issue.milestone = milestone
         edit.append('milestone')
         msg = 'Issue set to the milestone: %s' % milestone
-        if old_private:
+        if old_milestone:
             msg += ' (was: %s)' % old_milestone
         messages.append(msg)
     issue.last_updated = datetime.datetime.utcnow()

From 07fbe54c1a5410540d35518c24e1dc6569ea06e6 Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 13/16] Only report custom field changes when they are some


---

diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py
index a896428..923761a 100644
--- a/pagure/lib/__init__.py
+++ b/pagure/lib/__init__.py
@@ -3579,12 +3579,12 @@ def set_custom_key_value(session, issue, key, value):
                 'issue': issue.to_json(public=True, with_comments=False),
             }))
 
-    if value:
+    if updated and value:
         output = 'Custom field %s adjusted to %s' % (key.name, value)
         if old_value:
             output += ' (was: %s)' % old_value
         return output
-    else:
+    elif updated and old_value:
         return 'Custom field %s reset' % key.name
 
 

From aaece74531d15abc4c363359f25bed33562ed953 Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 14/16] Fix typo


---

diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py
index 923761a..dd0c511 100644
--- a/pagure/lib/__init__.py
+++ b/pagure/lib/__init__.py
@@ -1460,7 +1460,7 @@ def edit_issue(session, issue, ticketfolder, user, repo=None,
         old_private = issue.private
         issue.private = private
         edit.append('private')
-        msg = 'Issue private status set to: %s' % priority
+        msg = 'Issue private status set to: %s' % private
         if old_private:
             msg += ' (was: %s)' % old_private
         messages.append(msg)

From c8550e4e0cef2d18e7e0061c80ab1e6d59fb17d2 Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 15/16] Drop trying to add a notification when updating custom fields via JSON


When we load the content of a JSON file we have the status of a ticket at
a time T, but we do not know what were the changed made to it, so we
do not know who performed the action and therefore we cannot really
log a notification about someone changing the custom fields.

---

diff --git a/pagure/lib/git.py b/pagure/lib/git.py
index 53c548b..d52a9eb 100644
--- a/pagure/lib/git.py
+++ b/pagure/lib/git.py
@@ -466,20 +466,12 @@ def update_custom_field_from_json(session, repo, issue, json_data):
         value = new_key.get('value')
         if value:
             value = value.strip()
-        messages = pagure.lib.set_custom_key_value(
+        pagure.lib.set_custom_key_value(
             session,
             issue=issue,
             key=key_obj,
             value=value,
         )
-        if messages:
-            pagure.lib.add_metadata_update_notif(
-                session=session,
-                issue=issue,
-                messages=messages,
-                user=None,
-                ticketfolder=None
-            )
         try:
             session.commit()
         except SQLAlchemyError:

From 5b805205f21a350d350e313546d11818f5b3e41b Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Feb 06 2017 14:15:12 +0000
Subject: [PATCH 16/16] Adjust the unit-tests for the new behavior around notifications


---

diff --git a/tests/test_pagure_flask_api_issue.py b/tests/test_pagure_flask_api_issue.py
index 01ce59f..28b31e1 100644
--- a/tests/test_pagure_flask_api_issue.py
+++ b/tests/test_pagure_flask_api_issue.py
@@ -1095,7 +1095,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
         self.assertDictEqual(
             data,
             {'message':[
-                'Issue status updated to: Closed',
+                'Issue status updated to: Closed (was: Open)',
                 'Issue close_status updated to: Fixed'
             ]}
         )
@@ -2024,7 +2024,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests):
 
         repo = pagure.lib.get_project(self.session, 'test')
         issue = pagure.lib.search_issues(self.session, repo, issueid=1)
-        self.assertEqual(len(issue.other_fields), 1)
+        self.assertEqual(len(issue.other_fields), 0)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_pagure_flask_ui_app.py b/tests/test_pagure_flask_ui_app.py
index 1ab4c5f..e4bd60a 100644
--- a/tests/test_pagure_flask_ui_app.py
+++ b/tests/test_pagure_flask_ui_app.py
@@ -25,9 +25,6 @@ sys.path.insert(0, os.path.join(os.path.dirname(
 
 import pagure.lib
 import tests
-from pagure.lib import MetaComment
-
-mcomment = MetaComment()
 
 
 class PagureFlaskApptests(tests.Modeltests):
@@ -1153,10 +1150,9 @@ class PagureFlaskApptests(tests.Modeltests):
             issue=msg,
             assignee='pingou',
             user='foo',
-            ticketfolder=None,
-            mcomment=mcomment)
+            ticketfolder=None)
         self.session.commit()
-        self.assertEqual(msg, 'Issue assigned')
+        self.assertEqual(msg, 'Issue assigned to pingou')
 
         output = self.app.get('/user/pingou/issues')
         self.assertEqual(output.status_code, 200)
diff --git a/tests/test_pagure_flask_ui_issues.py b/tests/test_pagure_flask_ui_issues.py
index 8213d8f..afc6d27 100644
--- a/tests/test_pagure_flask_ui_issues.py
+++ b/tests/test_pagure_flask_ui_issues.py
@@ -686,14 +686,18 @@ class PagureFlaskIssuestests(tests.Modeltests):
                 output.data)
             self.assertIn(
                 '</button>\n                      '
-                'Issue status updated to: Closed\n',
+                'Issue status updated to: Closed (was: Open)\n',
                 output.data)
             self.assertTrue(
                 '<option selected value="Fixed">Fixed</option>'
                 in output.data)
+            # FIXME: There is likely something going wrong in the html
+            # below
             self.assertIn(
-                '''<small><p>Metadata Update:<br>
-- Issue status updated to: Closed<br>
+                '<small><p><strong>Metadata Update from '\
+'<a href="https://pagure.org/user/pingou"> </a>'\
+'''<a href="https://pagure.org/user/pingou"> @pingou</a></strong>:<br>
+- Issue status updated to: Closed (was: Open)<br>
 - Issue close_status updated to: Fixed</p></small>''',
                 output.data)
 
@@ -1499,14 +1503,6 @@ class PagureFlaskIssuestests(tests.Modeltests):
                 '/test/issue/1/edit', data=data, follow_redirects=True)
             self.assertEqual(output.status_code, 200)
             self.assertIn(
-                '</button>\n                      '
-                'Issue title edited\n',
-                output.data)
-            self.assertIn(
-                '</button>\n                      '
-                'Issue description edited\n',
-                output.data)
-            self.assertIn(
                 '<span class="issueid label label-default">#1</span>\n'
                 '    <span id="issuetitle">Test issue #1</span>',
                 output.data)
@@ -2013,7 +2009,7 @@ class PagureFlaskIssuestests(tests.Modeltests):
             )
             self.assertIn(
                 '</button>\n                      '
-                'Issue status updated to: Closed\n',
+                'Issue status updated to: Closed (was: Open)\n',
                 output.data
             )
             self.assertIn(
@@ -2034,9 +2030,9 @@ class PagureFlaskIssuestests(tests.Modeltests):
             'Nevermind figured it out')
         self.assertEqual(
             issue.comments[1].comment,
-            'Metadata Update:\n'
+            '**Metadata Update from @foo**:\n'
             '- Issue close_status updated to: Invalid\n'
-            '- Issue status updated to: Closed')
+            '- Issue status updated to: Closed (was: Open)')
         self.assertEqual(issue.status, 'Closed')
 
     @patch('pagure.lib.git.update_git')
diff --git a/tests/test_pagure_lib.py b/tests/test_pagure_lib.py
index 903adbe..33e40d8 100644
--- a/tests/test_pagure_lib.py
+++ b/tests/test_pagure_lib.py
@@ -267,9 +267,7 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(
             msg,
             [
-                'Issue title edited',
-                'Issue description edited',
-                'Issue status updated to: Closed',
+                'Issue status updated to: Closed (was: Open)',
                 'Issue close_status updated to: Invalid',
                 'Issue private status set to: True'
             ]
@@ -291,7 +289,8 @@ class PagureLibtests(tests.Modeltests):
             private=True,
         )
         self.session.commit()
-        self.assertEqual(msg, ['Issue status updated to: Open'])
+        self.assertEqual(
+            msg, ['Issue status updated to: Open (was: Closed)'])
 
         repo = pagure.lib.get_project(self.session, 'test')
         for issue in repo.issues:
@@ -315,7 +314,7 @@ class PagureLibtests(tests.Modeltests):
         self.assertEqual(
             msg,
             [
-                'Issue status updated to: Closed',
+                'Issue status updated to: Closed (was: Open)',
                 'Issue close_status updated to: Invalid'
             ]
         )
@@ -716,7 +715,7 @@ class PagureLibtests(tests.Modeltests):
             user='pingou',
             ticketfolder=None)
         self.session.commit()
-        self.assertEqual(msg, 'Issue assigned to pingou')
+        self.assertEqual(msg, 'Issue assigned to pingou (was: foo)')
 
         # After  -- Searches by assignee
         issues = pagure.lib.search_issues(

