{"id":506,"date":"2012-07-07T13:06:47","date_gmt":"2012-07-07T11:06:47","guid":{"rendered":"http:\/\/www.dereckson.be\/blog\/?p=506"},"modified":"2015-03-27T14:24:54","modified_gmt":"2015-03-27T13:24:54","slug":"phabricator-a-script-to-find-todo-lines-in-a-code-base-and-generate-bug-reports","status":"publish","type":"post","link":"https:\/\/www.dereckson.be\/blog\/2012\/07\/07\/phabricator-a-script-to-find-todo-lines-in-a-code-base-and-generate-bug-reports\/","title":{"rendered":"Phabricator: a script to find TODO lines in a code base and generate bug reports."},"content":{"rendered":"<p>Sometimes, a code base is haunted with dozens of lines like this one:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n\/\/TODO:\u00a0handle relative moves\r\n<\/pre>\n<p>This line doesn&#8217;t explain the current state of code\u00a0as much as it offers a feature request. But this feature request isn&#8217;t really visible, you have to browse the relevant code file to see it.<\/p>\n<p>So, what about transform all these todo lines into actual Phabricator tasks?<\/p>\n<p>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.<\/p>\n<p>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&#8217;ve chosen &#8220;Please edit this description to describe correctly the bug or the task.&#8221;.<\/p>\n<p><!--more--><\/p>\n<p>It calls arc call-conduit to use Phabricator conduit API to publish tasks.<\/p>\n<p>That gives this result:<\/p>\n<p><a href=\"https:\/\/www.dereckson.be\/blog\/wp-content\/uploads\/2015\/03\/TodoToPhabricatorTask.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-507\" src=\"https:\/\/www.dereckson.be\/blog\/wp-content\/uploads\/2015\/03\/TodoToPhabricatorTask.png\" alt=\"TodoToPhabricatorTask\" width=\"890\" height=\"569\" srcset=\"https:\/\/www.dereckson.be\/blog\/wp-content\/uploads\/2015\/03\/TodoToPhabricatorTask.png 890w, https:\/\/www.dereckson.be\/blog\/wp-content\/uploads\/2015\/03\/TodoToPhabricatorTask-300x192.png 300w\" sizes=\"auto, (max-width: 890px) 100vw, 890px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>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.<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\n#!\/usr\/bin\/env python\r\n# -*- coding: utf-8 -*-\r\n#----------------------------------------------------------------------\r\n# Name:             create_todo_bugs.py\r\n# Author:           S\u00e9bastien Santoro aka Dereckson\r\n# Created:          2012-07-05\r\n# Purpose:          Reads @todo &amp; co notes in the code\r\n#                   Outputs Phabicator json stubs for Conduit\r\n# Licence:          BSD\r\n#\r\n# Suggested use:\r\n#     cd \/path\/to\/repo\r\n#     grep -rin todo . &gt; tasks.txt\r\n#     create_todo_bugs.py tasks.txt\r\n#\r\n# TODO:\r\n#     We generate an hash based on file + comment. This hash should\r\n#     be looked in the bugtracker (here Maniphest) to try to detect\r\n#     already reported entries.\r\n#\r\n#                                                Scripts \/ Development\r\n#                                                                  Zed\r\n#----------------------------------------------------------------------\r\n\r\nimport sys\r\nimport os\r\nimport json\r\nfrom subprocess import Popen, PIPE, STDOUT\r\n\r\n# Parameter from command lines\r\n# taskFile should be generated by the following command:\r\n# cd \/path\/to\/repo ; grep -rin todo .\r\nif sys.argv.__len__() &gt; 1:\r\n\ttaskFile = sys.argv&#x5B;1]\r\nelse:\r\n\tprint &quot;Usage: &quot;\t +  sys.argv&#x5B;0] + &quot; &lt;file&gt;&quot;\r\n\tsys.exit(2)\r\n\r\n# Other parameters\r\ntodoExpr = &#x5B;&quot;* @todo&quot;, &quot;* @TODO&quot;, &quot;\/\/TODO:&quot;, &quot;#TODO&quot;, &quot;TODO:&quot;]\r\n\r\n# Reads the todo file\r\nif not os.path.exists(taskFile):\r\n\tprint &quot;Can't open &quot; + taskFile\r\n\tsys.exit(1)\r\n\r\nf = open(taskFile, 'r');\r\nfor row in f:\r\n\t#Format is &lt;file&gt;:&lt;task&gt;:&lt;message&gt;\r\n\tpos = row.find(&quot;:&quot;, (row.find(&quot;:&quot;) + 1))\r\n\tif pos &gt; 2:\r\n\t\t#Minimal position should be 3 (a:1:...TODO...)\r\n\r\n\t\t#Prepares JSON message\r\n\t\tdata = row&#x5B;0:pos].partition(&quot;:&quot;)\r\n\t\tfile = data&#x5B;0]\r\n\t\tline = data&#x5B;2]\r\n\t\ttask = row&#x5B;pos+1:]\r\n\t\tfor expr in todoExpr:\r\n\t\t\ttask = task.replace(expr, '')\r\n\t\ttask = task.strip()\r\n\t\tdescription = &quot;=======================================================================\\nAutomatic 2012-07-06 TODO bug report\\nIn &quot; + file + &quot;\\nAt line &quot; + line + &quot;\\n\\nPlease edit this description to describe correctly the bug or the task.\\n=======================================================================\\n\\n&quot; + task\r\n\t\tapiMessage = json.dumps({\r\n\t\t\t&quot;title&quot;: task,\r\n\t\t\t&quot;projectPHIDs&quot;: &#x5B;&quot;PHID-PROJ-miznpx5ylznju5cys4an&quot;],\r\n\t\t\t&quot;description&quot;: description\r\n\t\t}, indent=4)\r\n\r\n\t\t#Calls Phabricator API\r\n\t\tprocess = Popen(&#x5B;&quot;arc&quot;, &quot;call-conduit&quot;, &quot;maniphest.createtask&quot;], stdout=PIPE, stdin=PIPE, stderr=STDOUT)\r\n\t\treplyMessage = process.communicate(input=apiMessage)&#x5B;0]\r\n\t\treply = json.loads(replyMessage)\r\n\t\tif reply&#x5B;'error'] == None:\r\n\t\t\tprint reply&#x5B;'response']&#x5B;'uri'] + &quot;\\n&quot; + reply&#x5B;'response']&#x5B;'title'] + &quot;\\n&quot;\r\n\t\telse:\r\n\t\t\tprint reply&#x5B;'errorMessage']\r\n\t\t\tbreak\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Sometimes, a code base is haunted with dozens of lines like this one: \/\/TODO:\u00a0handle relative moves This line doesn&#8217;t explain the current state of code\u00a0as much as it offers a feature request. But this feature request isn&#8217;t really visible, you have to browse the relevant code file to see it. So, what about transform all [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[49],"tags":[206,268,250],"class_list":["post-506","post","type-post","status-publish","format-standard","hentry","category-dev","tag-phabricator","tag-python","tag-zed"],"_links":{"self":[{"href":"https:\/\/www.dereckson.be\/blog\/wp-json\/wp\/v2\/posts\/506","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dereckson.be\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dereckson.be\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dereckson.be\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dereckson.be\/blog\/wp-json\/wp\/v2\/comments?post=506"}],"version-history":[{"count":4,"href":"https:\/\/www.dereckson.be\/blog\/wp-json\/wp\/v2\/posts\/506\/revisions"}],"predecessor-version":[{"id":511,"href":"https:\/\/www.dereckson.be\/blog\/wp-json\/wp\/v2\/posts\/506\/revisions\/511"}],"wp:attachment":[{"href":"https:\/\/www.dereckson.be\/blog\/wp-json\/wp\/v2\/media?parent=506"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dereckson.be\/blog\/wp-json\/wp\/v2\/categories?post=506"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dereckson.be\/blog\/wp-json\/wp\/v2\/tags?post=506"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}