Spaces:
Sleeping
Sleeping
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import os
|
3 |
+
import subprocess
|
4 |
+
import shutil
|
5 |
+
from huggingface_hub import HfApi, HfFolder, whoami, create_repo, upload_folder
|
6 |
+
from huggingface_hub.utils import HfHubHTTPError
|
7 |
+
|
8 |
+
# --- Core Logic ---
|
9 |
+
|
10 |
+
def create_space_from_github(github_url, new_space_name, hf_token, space_sdk):
|
11 |
+
if not github_url or not new_space_name or not hf_token:
|
12 |
+
raise gr.Error("All fields are required. Please provide a GitHub URL, a new Space name, and your HF Token.")
|
13 |
+
|
14 |
+
# Sanitize the space name
|
15 |
+
new_space_name = new_space_name.strip().replace(" ", "-")
|
16 |
+
if not new_space_name:
|
17 |
+
raise gr.Error("New Space name cannot be empty.")
|
18 |
+
|
19 |
+
# Temporary directory for cloning
|
20 |
+
temp_clone_dir = f"/tmp/{new_space_name}"
|
21 |
+
|
22 |
+
try:
|
23 |
+
# 1. Authenticate with Hugging Face Hub
|
24 |
+
yield "Step 1/5: Authenticating with Hugging Face..."
|
25 |
+
api = HfApi(token=hf_token)
|
26 |
+
user = whoami(token=hf_token)
|
27 |
+
username = user['name']
|
28 |
+
repo_id = f"{username}/{new_space_name}"
|
29 |
+
|
30 |
+
# 2. Create the new, empty Hugging Face Space
|
31 |
+
yield f"Step 2/5: Creating new Space repository: {repo_id}..."
|
32 |
+
try:
|
33 |
+
space_url = create_repo(
|
34 |
+
repo_id=repo_id,
|
35 |
+
repo_type="space",
|
36 |
+
space_sdk=space_sdk.lower(),
|
37 |
+
token=hf_token,
|
38 |
+
exist_ok=False # Fail if it already exists
|
39 |
+
).url
|
40 |
+
except HfHubHTTPError as e:
|
41 |
+
if "exists" in str(e):
|
42 |
+
raise gr.Error(f"Space '{repo_id}' already exists on the Hub. Please choose a different name.")
|
43 |
+
else:
|
44 |
+
raise gr.Error(f"Error creating repository: {e}")
|
45 |
+
|
46 |
+
# 3. Clone the GitHub repository
|
47 |
+
yield f"Step 3/5: Cloning GitHub repo from {github_url}..."
|
48 |
+
if os.path.exists(temp_clone_dir):
|
49 |
+
shutil.rmtree(temp_clone_dir)
|
50 |
+
|
51 |
+
# Use subprocess to run git clone
|
52 |
+
subprocess.run(
|
53 |
+
["git", "clone", github_url, temp_clone_dir],
|
54 |
+
check=True,
|
55 |
+
capture_output=True # Capture stdout/stderr
|
56 |
+
)
|
57 |
+
|
58 |
+
# Remove the .git directory from the clone to avoid nested repos
|
59 |
+
git_dir = os.path.join(temp_clone_dir, ".git")
|
60 |
+
if os.path.exists(git_dir):
|
61 |
+
shutil.rmtree(git_dir)
|
62 |
+
|
63 |
+
# 4. Upload the contents to the new Space
|
64 |
+
yield f"Step 4/5: Uploading files to {repo_id}..."
|
65 |
+
upload_folder(
|
66 |
+
folder_path=temp_clone_dir,
|
67 |
+
repo_id=repo_id,
|
68 |
+
repo_type="space",
|
69 |
+
token=hf_token,
|
70 |
+
commit_message="Initial import from GitHub"
|
71 |
+
)
|
72 |
+
|
73 |
+
# 5. Cleanup
|
74 |
+
yield "Step 5/5: Cleaning up temporary files..."
|
75 |
+
shutil.rmtree(temp_clone_dir)
|
76 |
+
|
77 |
+
success_message = f"""
|
78 |
+
## β
Success!
|
79 |
+
|
80 |
+
Your new Space has been created.
|
81 |
+
|
82 |
+
**[Click here to visit your new Space]({space_url})**
|
83 |
+
|
84 |
+
Please note that it might take a few minutes for the Space to build and become fully operational.
|
85 |
+
"""
|
86 |
+
yield success_message
|
87 |
+
|
88 |
+
except subprocess.CalledProcessError as e:
|
89 |
+
error_msg = f"Error cloning GitHub repo. Is the URL correct and the repository public?\nDetails: {e.stderr.decode()}"
|
90 |
+
raise gr.Error(error_msg)
|
91 |
+
except Exception as e:
|
92 |
+
# Cleanup on failure
|
93 |
+
if os.path.exists(temp_clone_dir):
|
94 |
+
shutil.rmtree(temp_clone_dir)
|
95 |
+
raise gr.Error(f"An unexpected error occurred: {str(e)}")
|
96 |
+
|
97 |
+
|
98 |
+
# --- Gradio UI ---
|
99 |
+
|
100 |
+
with gr.Blocks(theme=gr.themes.Soft(), css="footer {display: none !important;}") as demo:
|
101 |
+
gr.Markdown(
|
102 |
+
"""
|
103 |
+
# GitHub Repo to Hugging Face Space Creator π
|
104 |
+
Turn any public GitHub repository into a Hugging Face Space with just a few clicks.
|
105 |
+
"""
|
106 |
+
)
|
107 |
+
with gr.Row():
|
108 |
+
with gr.Column(scale=2):
|
109 |
+
gr.Markdown(
|
110 |
+
"""
|
111 |
+
### **Step 1: Get a Hugging Face Token**
|
112 |
+
You need a token with **`write`** permission to create a Space on your behalf.
|
113 |
+
1. Go to **[Settings β Access Tokens](https://huggingface.co/settings/tokens)**.
|
114 |
+
2. Create a `New token` with the `write` role.
|
115 |
+
3. Copy the token and paste it below. **Treat this token like a password!**
|
116 |
+
"""
|
117 |
+
)
|
118 |
+
with gr.Column(scale=1):
|
119 |
+
gr.Image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/hub/security-tokens-write.png", show_label=False, interactive=False)
|
120 |
+
|
121 |
+
with gr.Group():
|
122 |
+
github_url = gr.Textbox(
|
123 |
+
label="GitHub Repository URL",
|
124 |
+
placeholder="e.g., https://github.com/gradio-app/gradio"
|
125 |
+
)
|
126 |
+
new_space_name = gr.Textbox(
|
127 |
+
label="New Hugging Face Space Name",
|
128 |
+
placeholder="e.g., my-cool-gradio-app"
|
129 |
+
)
|
130 |
+
hf_token = gr.Textbox(
|
131 |
+
label="Hugging Face Write Token",
|
132 |
+
placeholder="hf_...",
|
133 |
+
type="password"
|
134 |
+
)
|
135 |
+
space_sdk = gr.Radio(
|
136 |
+
["Gradio", "Streamlit", "Static", "Docker"],
|
137 |
+
label="Select the Space SDK",
|
138 |
+
value="Gradio",
|
139 |
+
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."
|
140 |
+
)
|
141 |
+
|
142 |
+
create_button = gr.Button("Create Space β¨", variant="primary")
|
143 |
+
|
144 |
+
output_status = gr.Markdown(value="Awaiting input...")
|
145 |
+
|
146 |
+
create_button.click(
|
147 |
+
fn=create_space_from_github,
|
148 |
+
inputs=[github_url, new_space_name, hf_token, space_sdk],
|
149 |
+
outputs=[output_status]
|
150 |
+
)
|
151 |
+
|
152 |
+
gr.Markdown("Created by [Your Name/Handle](https://huggingface.co/Your-Handle) | This Space is stateless and does not store your token.")
|
153 |
+
|
154 |
+
# Launch the app
|
155 |
+
demo.launch()
|