import gradio as gr from huggingface_hub import HfApi from git import Repo from slugify import slugify import uuid import os import re import subprocess # Function to extract metadata from README.md file def extract_from_readme(readme_path): title = None description = None port = None if os.path.exists(readme_path): with open(readme_path, encoding="utf-8") as f: content = f.read() match_title = re.search(r'title:\s*(.*)', content) match_desc = re.search(r'short_description:\s*(.*)', content) match_port = re.search(r'app_port:\s*(\d+)', content) if match_title: title = match_title.group(1).strip() if match_desc: description = match_desc.group(1).strip() if match_port: port = match_port.group(1).strip() return title, description, port # Main function to clone a Git repo and create a Hugging Face repo def clone_and_create(profile: gr.OAuthProfile, token: gr.OAuthToken, repo_url, repo_type, private, space_sdk, sdk_version, space_id, space_title, space_description, include_submodules): folder = str(uuid.uuid4()) # ユニークなフォルダ名作成 Repo.clone_from(repo_url, folder) # Gitリポジトリをクローン # サブモジュールを含める場合 if include_submodules: subprocess.run(["git", "submodule", "update", "--init", "--recursive"], cwd=folder, check=True) hf_api = HfApi(token=token.token) # README.md から自動情報取得 title_from_readme, desc_from_readme, port_from_readme = extract_from_readme(os.path.join(folder, "README.md")) # 最終的なID, タイトル, 説明を決定 final_id = slugify(space_id) if space_id else slugify(repo_url.split("/")[-1]) final_title = space_title or title_from_readme or final_id final_description = space_description or desc_from_readme repo_visibility = "private" if private else "public" # リポジトリ作成時の引数設定 if repo_type == "space": create_kwargs = dict( repo_id=f"{profile.username}/{final_id}", repo_type="space", space_sdk=space_sdk, private=private, ) # gradio, streamlit の場合のみバージョンを渡す if space_sdk in ["gradio", "streamlit"] and sdk_version: create_kwargs["space_sdk_version"] = sdk_version hf_api.create_repo(**create_kwargs) else: hf_api.create_repo( repo_id=f"{profile.username}/{final_id}", repo_type=repo_type, private=private ) # README.md に不足情報を追記 readme_path = os.path.join(folder, "README.md") with open(readme_path, "a", encoding="utf-8") as f: if space_title and not title_from_readme: f.write(f"\ntitle: {space_title}") if space_description and not desc_from_readme: f.write(f"\nshort_description: {space_description}") if port_from_readme: f.write(f"\napp_port: {port_from_readme}") # フォルダ内容をHugging Faceにアップロード hf_api.upload_folder( folder_path=folder, repo_id=f"{profile.username}/{final_id}", repo_type=repo_type ) # 作成したURLを返す base_url = "spaces" if repo_type == "space" else (repo_type + "s" if repo_type != "model" else "models") return f"https://huggingface.co/{base_url}/{profile.username}/{final_id}" # Define Gradio UI with gr.Blocks() as demo: gr.Markdown("# 🚀 Git Repository → Hugging Face Clone Tool") gr.LoginButton() with gr.Row(): with gr.Column(): repo_url = gr.Textbox(label="Git Repository URL (e.g., GitHub)") repo_type = gr.Dropdown(choices=["space", "dataset", "model"], value="space", label="Hugging Face repo type") private = gr.Checkbox(label="Make Private", value=False) include_submodules = gr.Checkbox(label="Include submodules", value=False) # 追加 space_sdk = gr.Dropdown(choices=["gradio", "streamlit", "docker", "static"], label="Space SDK", visible=True) sdk_version = gr.Textbox(label="SDK Version (optional)", visible=True) space_id = gr.Textbox(label="Hugging Face ID (auto if blank)") space_title = gr.Textbox(label="Space Title (from README or ID if blank)") space_description = gr.Textbox(label="Space Description (from README if blank)") with gr.Column(): output = gr.Textbox(label="Created Hugging Face URL") # Show/hide some inputs depending on repo_type def toggle_space_fields(repo_type_val): visible = repo_type_val == "space" return { space_sdk: gr.update(visible=visible), sdk_version: gr.update(visible=visible), space_id: gr.update(visible=True), space_title: gr.update(visible=True), space_description: gr.update(visible=True), } repo_type.change(fn=toggle_space_fields, inputs=repo_type, outputs=[space_sdk, sdk_version, space_id, space_title, space_description]) btn = gr.Button("Clone and Create!") btn.click( fn=clone_and_create, inputs=[repo_url, repo_type, private, space_sdk, sdk_version, space_id, space_title, space_description, include_submodules], outputs=output ) if __name__ == "__main__": demo.launch()