Phabricator: a script to find TODO lines in a code base and generate bug reports.

Sometimes, a code base is haunted with dozens of lines like this one:

//TODO: handle relative moves

This line doesn’t explain the current state of code as much as it offers a feature request. But this feature request isn’t really visible, you have to browse the relevant code file to see it.

So, what about transform all these todo lines into actual Phabricator tasks?

At best, you have identified an actual bug or feature request. At worst, you can identify already solved issues and clean your code files of extraneous TODO lines.

This Python script will find todo lines, and fill draft tasks with the content of the line, the name and line where it has been found. We also add a visible message to identify it as draft: here I’ve chosen “Please edit this description to describe correctly the bug or the task.”.

It calls arc call-conduit to use Phabricator conduit API to publish tasks.

That gives this result:



Here the script used for this migration. To reuse it, change the description and the projectPHIDs to match the project you want to attach the task to.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Name:
# Author: Sébastien Santoro aka Dereckson
# Created: 2012-07-05
# Purpose: Reads @todo & co notes in the code
# Outputs Phabicator json stubs for Conduit
# Licence: BSD
# Suggested use:
# cd /path/to/repo
# grep -rin todo . > tasks.txt
# tasks.txt
# We generate an hash based on file + comment. This hash should
# be looked in the bugtracker (here Maniphest) to try to detect
# already reported entries.
# Scripts / Development
# Zed

import sys
import os
import json
from subprocess import Popen, PIPE, STDOUT

# Parameter from command lines
# taskFile should be generated by the following command:
# cd /path/to/repo ; grep -rin todo .
if sys.argv.__len__() > 1:
taskFile = sys.argv[1]
print "Usage: " + sys.argv[0] + " <file>"

# Other parameters
todoExpr = ["* @todo", "* @TODO", "//TODO:", "#TODO", "TODO:"]

# Reads the todo file
if not os.path.exists(taskFile):
print "Can’t open " + taskFile

f = open(taskFile, ‘r’);
for row in f:
#Format is <file>:<task>:<message>
pos = row.find(":", (row.find(":") + 1))
if pos > 2:
#Minimal position should be 3 (a:1:…TODO…)

#Prepares JSON message
data = row[0:pos].partition(":")
file = data[0]
line = data[2]
task = row[pos+1:]
for expr in todoExpr:
task = task.replace(expr, ”)
task = task.strip()
description = "=======================================================================\nAutomatic 2012-07-06 TODO bug report\nIn " + file + "\nAt line " + line + "\n\nPlease edit this description to describe correctly the bug or the task.\n=======================================================================\n\n" + task
apiMessage = json.dumps({
"title": task,
"projectPHIDs": ["PHID-PROJ-miznpx5ylznju5cys4an"],
"description": description
}, indent=4)

#Calls Phabricator API
process = Popen(["arc", "call-conduit", "maniphest.createtask"], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
replyMessage = process.communicate(input=apiMessage)[0]
reply = json.loads(replyMessage)
if reply[‘error’] == None:
print reply[‘response’][‘uri’] + "\n" + reply[‘response’][‘title’] + "\n"
print reply[‘errorMessage’]

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.