|
|
|
|
|
import streamlit as st |
|
import tempfile |
|
import shutil |
|
from pathlib import Path |
|
import git |
|
from core.file_scanner import FileScanner, FileInfo |
|
|
|
|
|
|
|
if 'scanned_files' not in st.session_state: |
|
st.session_state.scanned_files = [] |
|
if 'selected_files' not in st.session_state: |
|
st.session_state.selected_files = set() |
|
if 'cloned_repo_dir' not in st.session_state: |
|
st.session_state.cloned_repo_dir = None |
|
|
|
st.title("Gitリポジトリ スキャナー (削除ボタン付き)") |
|
|
|
|
|
repo_url = st.text_input("GitリポジトリURLを入力 (例: https://github.com/username/repo.git)") |
|
|
|
|
|
st.subheader("スキャン対象拡張子") |
|
available_exts = [".py", ".js", ".ts", ".md", ".txt", ".java", ".cpp",".sh"] |
|
chosen_exts = [] |
|
for ext in available_exts: |
|
default_checked = (ext in [".py", ".md"]) |
|
if st.checkbox(ext, key=f"ext_{ext}", value=default_checked): |
|
chosen_exts.append(ext) |
|
|
|
|
|
if st.button("スキャン開始"): |
|
if not repo_url.strip(): |
|
st.error("リポジトリURLを入力してください") |
|
else: |
|
|
|
if st.session_state.cloned_repo_dir and Path(st.session_state.cloned_repo_dir).exists(): |
|
shutil.rmtree(st.session_state.cloned_repo_dir, ignore_errors=True) |
|
|
|
|
|
tmp_dir = tempfile.mkdtemp() |
|
clone_path = Path(tmp_dir) / "cloned_repo" |
|
|
|
st.write(f"リポジトリを一時ディレクトリへクローン中: {clone_path}") |
|
try: |
|
git.Repo.clone_from(repo_url, clone_path) |
|
st.session_state.cloned_repo_dir = str(clone_path) |
|
except Exception as e: |
|
st.error(f"クローン失敗: {e}") |
|
st.stop() |
|
|
|
|
|
scanner = FileScanner(base_dir=clone_path, target_extensions=set(chosen_exts)) |
|
found_files = scanner.scan_files() |
|
|
|
|
|
st.session_state.scanned_files = found_files |
|
st.session_state.selected_files = set() |
|
|
|
st.success(f"スキャン完了: {len(found_files)}個のファイルを検出") |
|
|
|
|
|
if st.session_state.cloned_repo_dir: |
|
|
|
if st.button("クローン済みリポジトリを削除"): |
|
|
|
shutil.rmtree(st.session_state.cloned_repo_dir, ignore_errors=True) |
|
st.session_state.cloned_repo_dir = None |
|
st.session_state.scanned_files = [] |
|
st.session_state.selected_files = set() |
|
st.success("クローンしたデータを削除しました") |
|
|
|
|
|
|
|
if st.session_state.scanned_files: |
|
st.write("## スキャン結果 (指定拡張子のみ)") |
|
|
|
col1, col2 = st.columns(2) |
|
with col1: |
|
if st.button("すべて選択"): |
|
base_path = Path(st.session_state.cloned_repo_dir) |
|
st.session_state.selected_files = { |
|
f.path.relative_to(base_path) for f in st.session_state.scanned_files |
|
} |
|
with col2: |
|
if st.button("すべて解除"): |
|
st.session_state.selected_files = set() |
|
|
|
base_path = Path(st.session_state.cloned_repo_dir) |
|
for file_info in st.session_state.scanned_files: |
|
rel_path = file_info.path.relative_to(base_path) |
|
checked = (rel_path in st.session_state.selected_files) |
|
|
|
|
|
new_checked = st.checkbox( |
|
f"{rel_path} ({file_info.formatted_size})", |
|
value=checked, |
|
key=str(rel_path) |
|
) |
|
if new_checked: |
|
st.session_state.selected_files.add(rel_path) |
|
else: |
|
st.session_state.selected_files.discard(rel_path) |
|
|
|
|
|
|
|
def create_markdown_for_selected(files, selected_paths, base_dir: Path) -> str: |
|
""" |
|
選択されたファイルを1つのMarkdownとして連結。 |
|
""" |
|
output = [] |
|
for f in files: |
|
rel_path = f.path.relative_to(base_dir) |
|
if rel_path in selected_paths: |
|
output.append(f"## {rel_path}") |
|
output.append("------------") |
|
if f.content is not None: |
|
output.append(f.content) |
|
else: |
|
output.append("# Failed to read content") |
|
output.append("") |
|
|
|
return "\n".join(output) |
|
|
|
if st.session_state.scanned_files: |
|
st.write("## 選択ファイルをMarkdownとしてダウンロード") |
|
if st.button("選択ファイルをダウンロード"): |
|
base_path = Path(st.session_state.cloned_repo_dir) |
|
markdown_text = create_markdown_for_selected( |
|
st.session_state.scanned_files, |
|
st.session_state.selected_files, |
|
base_path |
|
) |
|
|
|
st.download_button( |
|
label="Markdownダウンロード", |
|
data=markdown_text, |
|
file_name="selected_files.md", |
|
mime="text/markdown" |
|
) |
|
|