import gradio as gr import os import subprocess import shutil from huggingface_hub import HfApi, HfFolder, whoami, create_repo, upload_folder from huggingface_hub.utils import HfHubHTTPError # --- Core Logic --- def create_space_from_github(github_url, new_space_name, hf_token, space_sdk): if not github_url or not new_space_name or not hf_token: raise gr.Error("All fields are required. Please provide a GitHub URL, a new Space name, and your HF Token.") # Sanitize the space name new_space_name = new_space_name.strip().replace(" ", "-") if not new_space_name: raise gr.Error("New Space name cannot be empty.") # Temporary directory for cloning temp_clone_dir = f"/tmp/{new_space_name}" try: # 1. Authenticate with Hugging Face Hub yield "Step 1/5: Authenticating with Hugging Face..." api = HfApi(token=hf_token) user = whoami(token=hf_token) username = user['name'] repo_id = f"{username}/{new_space_name}" # 2. Create the new, empty Hugging Face Space yield f"Step 2/5: Creating new Space repository: {repo_id}..." try: space_url = create_repo( repo_id=repo_id, repo_type="space", space_sdk=space_sdk.lower(), token=hf_token, exist_ok=False # Fail if it already exists ).url except HfHubHTTPError as e: if "exists" in str(e): raise gr.Error(f"Space '{repo_id}' already exists on the Hub. Please choose a different name.") else: raise gr.Error(f"Error creating repository: {e}") # 3. Clone the GitHub repository yield f"Step 3/5: Cloning GitHub repo from {github_url}..." if os.path.exists(temp_clone_dir): shutil.rmtree(temp_clone_dir) # Use subprocess to run git clone subprocess.run( ["git", "clone", github_url, temp_clone_dir], check=True, capture_output=True # Capture stdout/stderr ) # Remove the .git directory from the clone to avoid nested repos git_dir = os.path.join(temp_clone_dir, ".git") if os.path.exists(git_dir): shutil.rmtree(git_dir) # 4. Upload the contents to the new Space yield f"Step 4/5: Uploading files to {repo_id}..." upload_folder( folder_path=temp_clone_dir, repo_id=repo_id, repo_type="space", token=hf_token, commit_message="Initial import from GitHub" ) # 5. Cleanup yield "Step 5/5: Cleaning up temporary files..." shutil.rmtree(temp_clone_dir) success_message = f""" ## ✅ Success! Your new Space has been created. **[Click here to visit your new Space]({space_url})** Please note that it might take a few minutes for the Space to build and become fully operational. """ yield success_message except subprocess.CalledProcessError as e: error_msg = f"Error cloning GitHub repo. Is the URL correct and the repository public?\nDetails: {e.stderr.decode()}" raise gr.Error(error_msg) except Exception as e: # Cleanup on failure if os.path.exists(temp_clone_dir): shutil.rmtree(temp_clone_dir) raise gr.Error(f"An unexpected error occurred: {str(e)}") # --- Gradio UI --- with gr.Blocks(theme=gr.themes.Soft(), css="footer {display: none !important;}") as demo: gr.Markdown( """ # GitHub Repo to Hugging Face Space Creator 🚀 Turn any public GitHub repository into a Hugging Face Space with just a few clicks. """ ) with gr.Row(): with gr.Column(scale=2): gr.Markdown( """ ### **Step 1: Get a Hugging Face Token** You need a token with **`write`** permission to create a Space on your behalf. 1. Go to **[Settings → Access Tokens](https://huggingface.co/settings/tokens)**. 2. Create a `New token` with the `write` role. 3. Copy the token and paste it below. **Treat this token like a password!** """ ) #with gr.Column(scale=1): # gr.Image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/hub/security-tokens-write.png", show_label=False, interactive=False) with gr.Group(): github_url = gr.Textbox( label="GitHub Repository URL", placeholder="e.g., https://github.com/gradio-app/gradio" ) new_space_name = gr.Textbox( label="New Hugging Face Space Name", placeholder="e.g., my-cool-gradio-app" ) hf_token = gr.Textbox( label="Hugging Face Write Token", placeholder="hf_...", type="password" ) space_sdk = gr.Radio( ["Gradio", "Streamlit", "Static", "Docker"], label="Select the Space SDK", value="Gradio", info="Choose the SDK that matches the repo. If you're unsure, check the repo for app.py (Gradio/Streamlit), index.html (Static), or a Dockerfile." ) create_button = gr.Button("Create Space ✨", variant="primary") output_status = gr.Markdown(value="Awaiting input...") create_button.click( fn=create_space_from_github, inputs=[github_url, new_space_name, hf_token, space_sdk], outputs=[output_status] ) gr.Markdown("Created by [Your Name/Handle](https://huggingface.co/Your-Handle) | This Space is stateless and does not store your token.") # Launch the app demo.launch()