Add a tool to delete (redact) gerrit comments
This adds a CLI tool that allows a gerrit admin to list and delete change messages and comments. Change-Id: I3600a59520c1f13a24f99f04eaf9ceb17af67fff
This commit is contained in:
parent
af14ca1aba
commit
9d62c9abf9
172
tools/gerrit-delete-comment.py
Executable file
172
tools/gerrit-delete-comment.py
Executable file
@ -0,0 +1,172 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# Copyright 2024 Acme Gating, LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
BREAK = '------------------------------------------------------------'
|
||||||
|
|
||||||
|
|
||||||
|
class Gerrit:
|
||||||
|
def __init__(self, url, username, password):
|
||||||
|
if url.endswith('/'):
|
||||||
|
url = url[:-1]
|
||||||
|
self.url = url
|
||||||
|
self.session = requests.Session()
|
||||||
|
self.session.auth = requests.auth.HTTPBasicAuth(username, password)
|
||||||
|
|
||||||
|
def get(self, path):
|
||||||
|
url = f'{self.url}{path}'
|
||||||
|
r = self.session.get(url,
|
||||||
|
headers={'Accept': 'application/json',
|
||||||
|
'Accept-Encoding': 'gzip'})
|
||||||
|
if r.status_code == 200:
|
||||||
|
ret = json.loads(r.text[4:])
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def post(self, path, data):
|
||||||
|
url = f'{self.url}{path}'
|
||||||
|
r = self.session.post(
|
||||||
|
url,
|
||||||
|
data=json.dumps(data).encode('utf8'),
|
||||||
|
headers={'Content-Type': 'application/json;charset=UTF-8'})
|
||||||
|
if r.status_code > 400:
|
||||||
|
raise Exception("POST to %s failed with http code %s (%s)",
|
||||||
|
path, r.status_code, r.text)
|
||||||
|
if r.text and len(r.text) > 4:
|
||||||
|
return json.loads(r.text[4:])
|
||||||
|
|
||||||
|
def list_messages(self, change):
|
||||||
|
data = self.get(f'/a/changes/{change}/messages')
|
||||||
|
for msg in data:
|
||||||
|
name = msg['real_author'].get('name')
|
||||||
|
username = msg['real_author'].get('username')
|
||||||
|
email = msg['real_author'].get('email')
|
||||||
|
date = msg['date']
|
||||||
|
msgid = msg['id']
|
||||||
|
print(BREAK)
|
||||||
|
print(f'Id : {msgid}')
|
||||||
|
print(f'Author: {name} ({username}) <{email}>')
|
||||||
|
print(f'Date : {date}')
|
||||||
|
print(msg['message'])
|
||||||
|
|
||||||
|
def delete_message(self, change, message_id, reason):
|
||||||
|
self.post(
|
||||||
|
f'/a/changes/{change}/messages/{message_id}/delete',
|
||||||
|
{'reason': reason})
|
||||||
|
print("Deleted")
|
||||||
|
|
||||||
|
def list_comments(self, change, revision):
|
||||||
|
data = self.get(f'/a/changes/{change}/revisions/{revision}/comments')
|
||||||
|
for path, comments in data.items():
|
||||||
|
for msg in comments:
|
||||||
|
name = msg['author'].get('name')
|
||||||
|
username = msg['author'].get('username')
|
||||||
|
email = msg['author'].get('email')
|
||||||
|
line = msg.get('line')
|
||||||
|
msgid = msg['id']
|
||||||
|
print(BREAK)
|
||||||
|
print(f'Id : {msgid}')
|
||||||
|
print(f'Author: {name} ({username}) <{email}>')
|
||||||
|
print(f'File : {path} line {line}')
|
||||||
|
print(msg['message'])
|
||||||
|
|
||||||
|
def delete_comment(self, change, revision, comment_id, reason):
|
||||||
|
self.post(
|
||||||
|
f'/a/changes/{change}/revisions/{revision}/'
|
||||||
|
f'comments/{comment_id}/delete',
|
||||||
|
{'reason': reason})
|
||||||
|
print("Deleted")
|
||||||
|
|
||||||
|
|
||||||
|
class App:
|
||||||
|
def __init__(self):
|
||||||
|
self.parser = argparse.ArgumentParser()
|
||||||
|
p = self.parser
|
||||||
|
p.add_argument('url',
|
||||||
|
help='Gerrit HTTP url')
|
||||||
|
p.add_argument('username',
|
||||||
|
help='Username of Gerrit administrator')
|
||||||
|
p.add_argument('password',
|
||||||
|
help='Password of Gerrit administrator')
|
||||||
|
subparsers = p.add_subparsers(title='commands',
|
||||||
|
help='valid commands')
|
||||||
|
|
||||||
|
cmd_list_messages = subparsers.add_parser(
|
||||||
|
'list-messages', help='List change messages')
|
||||||
|
cmd_list_messages.add_argument('change',
|
||||||
|
help='Change number')
|
||||||
|
cmd_list_messages.set_defaults(func=self.list_messages)
|
||||||
|
|
||||||
|
cmd_delete_message = subparsers.add_parser(
|
||||||
|
'delete-message', help='Delete change message')
|
||||||
|
cmd_delete_message.add_argument('change',
|
||||||
|
help='Change number')
|
||||||
|
cmd_delete_message.add_argument('message_id',
|
||||||
|
help='Message ID')
|
||||||
|
cmd_delete_message.add_argument(
|
||||||
|
'reason',
|
||||||
|
help='Reason for removal (will replace message)')
|
||||||
|
cmd_delete_message.set_defaults(func=self.delete_message)
|
||||||
|
|
||||||
|
cmd_list_comments = subparsers.add_parser(
|
||||||
|
'list-comments', help='List change comments')
|
||||||
|
cmd_list_comments.add_argument('change',
|
||||||
|
help='Change number')
|
||||||
|
cmd_list_comments.add_argument('revision',
|
||||||
|
help='Change revision')
|
||||||
|
cmd_list_comments.set_defaults(func=self.list_comments)
|
||||||
|
|
||||||
|
cmd_delete_comment = subparsers.add_parser(
|
||||||
|
'delete-comment', help='Delete change comment')
|
||||||
|
cmd_delete_comment.add_argument('change',
|
||||||
|
help='Change number')
|
||||||
|
cmd_delete_comment.add_argument('revision',
|
||||||
|
help='Change revision')
|
||||||
|
cmd_delete_comment.add_argument('comment_id',
|
||||||
|
help='Comment ID')
|
||||||
|
cmd_delete_comment.add_argument(
|
||||||
|
'reason',
|
||||||
|
help='Reason for removal (will replace comment)')
|
||||||
|
cmd_delete_comment.set_defaults(func=self.delete_comment)
|
||||||
|
|
||||||
|
args = p.parse_args()
|
||||||
|
self.args = args
|
||||||
|
self.gerrit = Gerrit(args.url, args.username, args.password)
|
||||||
|
if 'func' not in args:
|
||||||
|
p.print_help()
|
||||||
|
sys.exit(1)
|
||||||
|
args.func()
|
||||||
|
|
||||||
|
def list_messages(self):
|
||||||
|
self.gerrit.list_messages(self.args.change)
|
||||||
|
|
||||||
|
def delete_message(self):
|
||||||
|
self.gerrit.delete_message(self.args.change,
|
||||||
|
self.args.message_id, self.args.reason)
|
||||||
|
|
||||||
|
def list_comments(self):
|
||||||
|
self.gerrit.list_comments(self.args.change, self.args.revision)
|
||||||
|
|
||||||
|
def delete_comment(self):
|
||||||
|
self.gerrit.delete_comment(self.args.change, self.args.revision,
|
||||||
|
self.args.comment_id, self.args.reason)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
App()
|
Loading…
Reference in New Issue
Block a user