Skip to content

Instantly share code, notes, and snippets.

@BharatKalluri
Last active September 18, 2023 15:52
Show Gist options
  • Save BharatKalluri/f8a1cd2fc92439ea003acfadd5d3f32d to your computer and use it in GitHub Desktop.
Save BharatKalluri/f8a1cd2fc92439ea003acfadd5d3f32d to your computer and use it in GitHub Desktop.
Norns: A TODO wrangler for TODOs across git repositories

Build the database

build_todo_db . >> ~/tododb.json

this creates a file with all the TODOs along with its metadata at ~/tododb.json

cat ~/tododb.json | jq -r '["commit_id", "line_no", "author", "time_in_epoch", "file_name", "todo_contents", "git_dir"],
                       (.[] | [.todo_context.commit_id, .todo_context.line_no, .todo_context.author, .todo_context.time_in_epoch, .todo_context.file_name, .todo_context.todo_contents, (.project_metadata.git_dir | tostring)])
                       | @csv' >> ~/todos.csv

creates a file called todos.csv at home folder with all the metadata on TODOs

#!/usr/bin/env python3
import sys
import json
import os
import subprocess
import itertools
def get_details(data_block: str, project_metadata: dict):
lines_in_block = [l for l in data_block.splitlines() if len(l) > 0]
commit_id, _, line_no, __ = lines_in_block[0].split(" ")
author = lines_in_block[1].replace("author ", "")
time_in_epoch = lines_in_block[3].split(" ")[-1]
file_name = lines_in_block[-2].replace("filename ", "")
todo_contents = lines_in_block[-1].strip()
return {
"todo_context": {
"commit_id": commit_id,
"line_no": line_no,
"author": author,
"time_in_epoch": int(time_in_epoch),
"file_name": file_name,
"todo_contents": todo_contents,
},
"project_metadata": project_metadata,
}
def find_git_directories(base_path):
return [
os.path.join(root) for root, dirs, _ in os.walk(base_path) if ".git" in dirs
]
def run_bash_command(command):
result = subprocess.run(
command,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
if result.returncode == 0:
return result.stdout.strip()
raise Exception(result.stderr)
def get_todo_db_from_dir(git_dir: str) -> list:
# TODO: ties this setup to bash or bash based shells, does not work on windows
command_raw_text = (
'ggb() { git grep -ni $1 | while IFS=: read i j k; do git blame -L $j,$j --line-porcelain $i | cat; echo "<---->"; done }; cd '
+ git_dir
+ "; ggb todo;"
)
todo_raw_text = run_bash_command(command=command_raw_text)
data_blocks = "\n".join(
[line.strip() for line in todo_raw_text.splitlines() if len(line) > 0]
).split("<---->")
project_metadata = {"git_dir": git_dir}
todo_metadata = [
get_details(data_block=el, project_metadata=project_metadata)
for el in data_blocks
if len(el) > 0
]
return todo_metadata
def build_todo_db(base_dir: str):
git_dirs = find_git_directories(base_path=base_dir)
return list(
itertools.chain(
*[get_todo_db_from_dir(git_dir=git_dir) for git_dir in git_dirs]
)
)
if __name__ == "__main__":
base_dir = sys.argv[1]
todo_db = build_todo_db(base_dir=base_dir)
print(json.dumps(todo_db))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment