Spaces:
Running
Running
import gradio as gr | |
from huggingface_hub import HfApi | |
from git import Repo | |
from slugify import slugify | |
import uuid | |
import os | |
import re | |
# 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): | |
folder = str(uuid.uuid4()) # Create a unique folder name | |
Repo.clone_from(repo_url, folder) # Clone the git repository | |
hf_api = HfApi(token=token.token) | |
# Auto-fill info by extracting from README.md | |
title_from_readme, desc_from_readme, port_from_readme = extract_from_readme(os.path.join(folder, "README.md")) | |
# Determine final repo ID, title, description | |
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" | |
# Create Hugging Face repo | |
if repo_type == "space": | |
hf_api.create_repo( | |
repo_id=f"{profile.username}/{final_id}", | |
repo_type="space", | |
space_sdk=space_sdk, | |
space_sdk_version=sdk_version if sdk_version else None, | |
private=private | |
) | |
else: | |
hf_api.create_repo( | |
repo_id=f"{profile.username}/{final_id}", | |
repo_type=repo_type, | |
private=private | |
) | |
# Append missing info to README.md if needed | |
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}") | |
# Upload folder contents to the Hugging Face repo | |
hf_api.upload_folder( | |
folder_path=folder, | |
repo_id=f"{profile.username}/{final_id}", | |
repo_type=repo_type | |
) | |
# Return URL to created Hugging Face repo | |
return f"https://huggingface.co/{repo_type + 's' if repo_type != 'model' else 'models'}/{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) | |
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], | |
outputs=output | |
) | |
if __name__ == "__main__": | |
demo.launch() | |