File size: 5,845 Bytes
d13391d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8229763
 
d13391d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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()