0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GitHubのPull RequestのURLを入力するとMarkdown形式Diffに整形するPythonコード

Posted at

今回のコードでできること

GitHubのPull RequestのURL(Load diffがあってもOK)を今回のコードを実行して張り付けると
image.png

このようなMarkdown形式Diffに整形
image.png

動機

  • GitHubAPIを使うことでLoad diffを展開した状態のdiffが取れるのでGitHubAPIのレスポンスに対応した整形コードを作成

  • URLを指定するだけでdiffを取得したい。前回よりも手順を省略したい

使い方

  • Pull Request画面でURL(とにかくowner, repo, PR番号が取れればOK)を取得する
  • "GitDiffURLToMd.py"ファイルを作成してエディタでソースコードを張り付ける
  • "GitDiffURLToMd.py"をクリックして、指示に従ってURLを指定する
  • "diff.md"にテキスト化した結果が入っているので、生成AIへの質問等で活用する

ソースコード(Pythonファイル)

import requests
import re

# GitHub APIからプルリクエストのdiffを取得する
def getDiffRes(url):
    # URLからowner, repo, PR番号を抽出

    m = re.match(r"https://github.com/([^/]+)/([^/]+)/pull/(\d+)", url)
    if not m:
        print("無効なURLです")
        exit()
    owner, repo, pr_number = m.groups()
    
    api_url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{pr_number}"
    headers = {"Accept": "application/vnd.github.v3.diff"}

    try:
        res = requests.get(api_url, headers=headers)
        res.raise_for_status()
        return res.text
    except requests.exceptions.RequestException as e:
        print(f"Error fetching diff: {e}")
        exit()

def getCleanedDiffMd(diff_text):
    # ファイルごとにdiffを分割
    parts = diff_text.split("diff --git ")
    formatted = []

    for part in parts:
        if not part.strip():
            continue

        lines = part.strip().splitlines()

        # diff --git a/xxx b/xxx からファイル名を取得
        first_line = lines[0] if lines else ""
        # b/以下のパスを抽出(通常は2つ目のファイルパス)
        if first_line.startswith("a/") or first_line.startswith("b/"):
            # splitすると ['a/filepath', 'b/filepath'] になる
            file_paths = first_line.split()
            if len(file_paths) == 2:
                filename = file_paths[1][2:]  # b/ を除去
            else:
                filename = "unknown_file"
        else:
            filename = "unknown_file"

        # "@@"で始まる行を探す
        at_at_index = -1
        for i, line in enumerate(lines):
            if line.startswith('@@'):
                at_at_index = i
                break

        # "@@"行が見つかった場合、その行から最後までを取得
        if at_at_index != -1:
            cleaned_diff_lines = lines[at_at_index:]
            cleaned_diff = "\n".join(cleaned_diff_lines)
        else:
            cleaned_diff = "\n".join(lines)

        # Markdown形式に整形(ファイル名も追加)
        formatted.append(f"## {filename}\n```diff\n{cleaned_diff}\n```")

    # 全ての整形済みdiffを結合
    md_diff = "\n\n".join(formatted)
    return md_diff

def main():
    url = input("GitHub Pull Request のURLを入力してください: ").strip()

    # URLからdiff取得
    diff_text = getDiffRes(url)

    # diffを整形
    md_diff = getCleanedDiffMd(diff_text)

    # Markdownファイルとして保存
    output_filename = "diff.md"
    try:
        with open(output_filename, "w", encoding="utf-8") as f:
            f.write(md_diff)
        print(f"PR diff has been saved to {output_filename}")
    except IOError as e:
        print(f"Error saving file: {e}")
    
    # 入力待ち
    input("続行するには何かキーを押してください...")


if __name__ == "__main__":
    main()
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?