🤖

ChatGPTにgitのリポジトリ渡すと全ソースコード.txtをダウンロードさせてくれるやつ〜〜〜〜(AIに食わせるコード一覧が欲しい時用)

2024/06/15に公開
1

ChatGPTに渡すプロンプト

以下をコピペしてください。

以下はソースコードのプロジェクトルートで実行することで、ソースコードのダンプを.txt形式でダンプするシェルスクリプトです。

\`\`\`
#!/bin/bash

# バイナリファイルかどうかを判定する関数
is_binary_file() {
  local file="$1"
  local file_output
  file_output=$(file "$file")
  
  if [[ "$file_output" == *"text"* ]]; then
    return 1  # テキストファイルの場合
  else
    return 0  # バイナリファイルの場合
  fi
}

# フォルダ名の取得
folder_name=$(basename "$PWD")

# 出力ファイル名を設定
output_file="${folder_name}.txt"

# 出力ファイルを新規作成または上書き
> "$output_file"

# find コマンドの出力を取得し、ファイルに保存
echo "## Find Output" | tee -a "$output_file"
find . -type f -exec ls -lh {} \; | tee -a "$output_file"

# ソースコードセクションの開始
echo "## Source Code" | tee -a "$output_file"

# find コマンドを使用してすべてのファイルを取得
find_output=$(find . -type f)

while IFS= read -r line; do
  if [[ $line != "./$output_file" ]] && ! is_binary_file "$line"; then
    file_size=$(stat -c%s "$line")
    if (( file_size <= 10240 )); then
      {
        echo "\`\`\`file:$line"
        cat "$line"
        echo "\`\`\`"
        echo
      } | tee -a "$output_file"
      echo "Processed: $line"
    else
      echo "Ignored (file too large): $line"
    fi
  else
    [[ $line == "./$output_file" ]] && echo "Ignored (output file): $line" || echo "Ignored (binary file): $line"
  fi
done <<< "$find_output"

# 出力ファイルサイズのセクション
output_file_size=$(stat -c%s "$output_file")
echo "## Output File Size" | tee -a "$output_file"
echo "Output file size: $output_file_size bytes" | tee -a "$output_file"
\`\`\`


今からgithubのソースコードをまとめたzipを渡すので、上記のShellを実行し.txtファイルをダウンロードさせてください。標準出力についてはChat上に表示する必要はありません。

試してみる

以下のRemixのStackで試してみます。
ソースコードをzip形式でダウンロードしておきます。

https://github.com/dev-xo/remix-saas

まず冒頭のプロンプトをChatGPTにコピペします。

いつでもこいやって感じになったので、リポジトリからダウンロードしたzipをそのままChatGPTに渡します。

成功したみたいです。

ChatGPTにgitのリポジトリの質問をする

新規にChatを開いて、さきほどのtxtファイルをアップロードします。

例えば以下の質問をしてみます。

- このリポジトリの概要・モチベーションを説明して
- 使われている技術スタックを箇条書きで列挙して
- 対応している認証方式を出力して
- DBの種類を教えて
- データを参照しているコードがある場合、参照から表示までをソースコード付きで教えて
- データを更新しているコードがある場合、参照から表示までをソースコード付きで教えて
- ユーザーがログイン済みかを確認している箇所のソースコードを説明して
- 画面遷移を図示して
- DBのER図を表示
- デプロイ先のクラウドは何を想定してますか?
- ...

出力は以下です。長いのでトグルにしてます。

ChatGPTの出力

リポジトリの概要・モチベーション

このリポジトリ「Remix SaaS」は、次世代のSaaSアプリケーションのための軽量で機能豊富かつプロダクションレディなRemixスタックを提供することを目的としています。このテンプレートは、開発者が迅速にSaaSアプリケーションを構築し、スケーラブルで保守しやすいコードベースを実現するためのベストプラクティスを取り入れています。

技術スタック

  • Remix
  • TypeScript
  • Prisma
  • SQLite
  • Docker
  • TailwindCSS
  • i18next
  • GitHub Actions
  • Node.js

対応している認証方式

  • GitHub認証
  • TOTP (Time-based One-Time Password) 認証

データベースの種類

  • SQLite

データを参照しているコード例

以下のコードは、ユーザーのデータを取得し、画面に表示する例です。

// app/routes/dashboard+/_index.tsx
import { json, LoaderFunction } from '@remix-run/node'
import { useLoaderData } from '@remix-run/react'
import { prisma } from '#app/utils/db.server'

export const loader: LoaderFunction = async () => {
  const users = await prisma.user.findMany()
  return json({ users })
}

export default function Dashboard() {
  const { users } = useLoaderData()
  return (
    <div>
      <h1>Dashboard</h1>
      <ul>
        {users.map((user) => (
          <li key={user.id}>{user.email}</li>
        ))}
      </ul>
    </div>
  )
}

データを更新しているコード例

以下のコードは、ユーザーのデータを更新する例です。

// app/routes/dashboard+/update-user.tsx
import { json, ActionFunction, redirect } from '@remix-run/node'
import { prisma } from '#app/utils/db.server'
import { useActionData, Form, useTransition } from '@remix-run/react'

export const action: ActionFunction = async ({ request }) => {
  const formData = await request.formData()
  const userId = formData.get('userId')
  const email = formData.get('email')

  if (typeof userId !== 'string' || typeof email !== 'string') {
    return json({ error: 'Invalid form submission' }, { status: 400 })
  }

  await prisma.user.update({
    where: { id: userId },
    data: { email },
  })

  return redirect('/dashboard')
}

export default function UpdateUser() {
  const actionData = useActionData()
  const transition = useTransition()

  return (
    <Form method="post">
      <input type="hidden" name="userId" value="123" />
      <label>
        Email: <input type="email" name="email" />
      </label>
      {actionData?.error && <p>{actionData.error}</p>}
      <button type="submit" disabled={transition.state === 'submitting'}>
        {transition.state === 'submitting' ? 'Updating...' : 'Update'}
      </button>
    </Form>
  )
}

ユーザーがログイン済みかを確認している箇所のソースコード

以下のコードは、ユーザーがログイン済みかどうかを確認する例です。

// app/modules/auth/auth.server.ts
import { authenticator } from '#app/modules/auth/auth.server'

export const requireUser = async (request: Request) => {
  const user = await authenticator.isAuthenticated(request)
  if (!user) {
    throw redirect('/login')
  }
  return user
}

画面遷移の図

データベースのER図

デプロイ先のクラウド

  • Fly.io

このリポジトリでは、Fly.ioをデプロイ先として想定しています。

たまたまですが、zennがmarmeid記法に対応しているので、図が展開されているのいいですね。
質問に対して適切に回答してくれてそうです。

遊んでみる

ここからはおまけですが、すべてのファイルを飲み込んでいる状態なのでこんなこともできます。

あなたはLinux OSです。先程のソースコードに対して以下のコマンドを実行した場合の出力をシミュレーションしてください。
$ tree ./app -L1

L2にするとちゃんと対応してます。

cat app/components/header.tsx

$ ag -l auth

※agはgrep相当のコマンドで -l オプションを使うとファイル名だけ出力します。

おわりに

Claude 3の登場以降、超長文を読み込んでの回答を月額課金するだけで利用できるようになりました。
今回はGPT4oを使ってますが、txtファイルを生成したあとは他のClaude 3 OpusやGemini 1.5 Proでも同様に利用できるはずです。

便利なので利用してみてください。

Discussion

kazuphkazuph

ローカルでシェルスクリプト使うなというのは一緒なのですが、自己責任の上で自分がいつも使っているやつを上げておきます。git ls-files を使っているので変なファイルは展開されないとは思います。

以下をpathが通っている場所(例えば ~/bin/catall)に保存して chmod +x ~/bin/catall とすればどこでも叩けて、叩いたカレントディレクトリに .txt として保存されます。

#!/bin/bash

# バイナリファイルかどうかを判定する関数
is_binary_file() {
  local file="$1"
  local file_output
  file_output=$(file "$file")

  if [[ "$file_output" == *"text"* ]]; then
    return 1  # テキストファイルの場合
  else
    return 0  # バイナリファイルの場合
  fi
}

# フォルダ名の取得
folder_name=$(basename "$PWD")

# 出力ファイル名を設定
output_file="${folder_name}.txt"

# 出力ファイルを新規作成または上書き
> "$output_file"

# tree コマンドの出力を取得し、ファイルに保存
echo "## Tree Output" | tee -a "$output_file"
git ls-files | tee -a "$output_file"

# git ls-files を使って .gitignore を考慮したファイル一覧を取得
find_output=$(git ls-files)

# ソースコードセクションの開始
echo "## Source Code" | tee -a "$output_file"

while IFS= read -r line; do
  if [[ $line != "./$output_file" ]] && ! is_binary_file "$line"; then
    file_size=$(stat -c%s "$line")
    if (( file_size <= 10240 )); then
      {
        echo "\`\`\`file:$line"
        cat "$line"
        echo "\`\`\`"
        echo
      } | tee -a "$output_file"
      echo "Processed: $line"
    else
      echo "Ignored (file too large): $line"
    fi
  else
    [[ $line == "./$output_file" ]] && echo "Ignored (output file): $line" || echo "Ignored (binary file): $line"
  fi
done <<< "$find_output"

# 出力ファイルサイズのセクション
output_file_size=$(stat -c%s "$output_file")
echo "## Output File Size" | tee -a "$output_file"
echo "Output file size: $output_file_size bytes" | tee -a "$output_file"