Spaces:
Sleeping
Sleeping
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() |