openfree commited on
Commit
9f5c15f
ยท
verified ยท
1 Parent(s): c2259b4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +221 -43
app.py CHANGED
@@ -747,6 +747,114 @@ Deployed from: {repo_git}
747
  shutil.rmtree(folder)
748
  yield f"โŒ Error: {str(e)}"
749
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
750
  css = """
751
  .container {
752
  max-width: 900px;
@@ -761,57 +869,127 @@ css = """
761
  font-size: 14px;
762
  line-height: 1.5;
763
  }
 
 
 
764
  """
765
 
766
- with gr.Blocks(css=css) as demo:
767
- gr.Markdown("# ๐Ÿš€ GitHub to Hugging Face Space Cloner")
768
 
769
- if not os.getenv("HF_TOKEN"):
770
- gr.Markdown("โŒ HF_TOKEN Required - Set it in Space settings")
771
- else:
772
- gr.Markdown("โœ… HF_TOKEN Found")
773
-
774
- with gr.Row():
775
- with gr.Column():
776
- repo_git = gr.Textbox(
777
- label="GitHub Repository URL",
778
- placeholder="https://github.com/username/repository"
779
- )
780
- repo_hf = gr.Textbox(
781
- label="Hugging Face Space Name",
782
- placeholder="my-awesome-space"
783
- )
784
- sdk_choices = gr.Radio(
785
- ["gradio", "streamlit", "docker", "static"],
786
- label="Space SDK",
787
- value="gradio"
788
- )
789
- skip_lfs = gr.Checkbox(
790
- label="Skip Git LFS files",
791
- value=True
792
- )
793
- enable_smart_generation = gr.Checkbox(
794
- label="๐Ÿค– Enable Smart app.py Generation",
795
- value=False,
796
- info="Requires FIREWORKS_API_KEY in environment variables"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
797
  )
 
 
 
 
798
 
799
- btn = gr.Button("๐ŸŽฏ Clone Repository", variant="primary")
 
800
 
801
- with gr.Column():
802
- output = gr.Textbox(
803
- label="Progress",
804
- lines=15,
805
- elem_classes=["output-box"],
806
- interactive=False,
807
- show_copy_button=True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
808
  )
809
 
810
- btn.click(
811
- fn=clone,
812
- inputs=[repo_git, repo_hf, sdk_choices, skip_lfs, enable_smart_generation],
813
- outputs=output
814
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
815
 
816
  if __name__ == "__main__":
817
  demo.launch()
 
747
  shutil.rmtree(folder)
748
  yield f"โŒ Error: {str(e)}"
749
 
750
+ def space_to_github(hf_username, hf_space_name, github_repo_name, github_token):
751
+ """Clone HuggingFace Space and push to GitHub"""
752
+ tmp_dir = None
753
+ try:
754
+ # HF Space URL ์ƒ์„ฑ
755
+ hf_repo_url = f"https://huggingface.co/spaces/{hf_username}/{hf_space_name}.git"
756
+
757
+ # ์ž„์‹œ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ ๋ฐ ํด๋ก 
758
+ tmp_dir = tempfile.mkdtemp()
759
+ yield f"๐Ÿ“ฅ Cloning HF Space: {hf_username}/{hf_space_name}..."
760
+
761
+ # Git ํด๋ก 
762
+ env = os.environ.copy()
763
+ env['GIT_LFS_SKIP_SMUDGE'] = '1' # LFS ํŒŒ์ผ ์Šคํ‚ต
764
+
765
+ clone_cmd = ['git', 'clone', hf_repo_url, tmp_dir]
766
+ result = subprocess.run(clone_cmd, env=env, capture_output=True, text=True)
767
+
768
+ if result.returncode != 0:
769
+ raise Exception(f"Clone failed: {result.stderr}")
770
+
771
+ yield "โœ… HF Space cloned successfully"
772
+
773
+ # GitHub ์ธ์ฆ ๋ฐ ๋ ˆํฌ ์ƒ์„ฑ
774
+ yield "๐Ÿ” Authenticating with GitHub..."
775
+
776
+ # GitHub API ํ˜ธ์ถœ๋กœ ๋ ˆํฌ ์ƒ์„ฑ
777
+ headers = {
778
+ "Authorization": f"token {github_token}",
779
+ "Accept": "application/vnd.github.v3+json"
780
+ }
781
+
782
+ # ์‚ฌ์šฉ์ž ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ
783
+ user_response = requests.get("https://api.github.com/user", headers=headers)
784
+ if user_response.status_code != 200:
785
+ raise Exception("GitHub authentication failed")
786
+
787
+ github_username = user_response.json()["login"]
788
+ yield f"โœ… Authenticated as GitHub user: {github_username}"
789
+
790
+ # ๋ ˆํฌ์ง€ํ† ๋ฆฌ ์ƒ์„ฑ
791
+ yield f"๐Ÿ“ฆ Creating GitHub repository: {github_repo_name}..."
792
+ create_data = {
793
+ "name": github_repo_name,
794
+ "private": False,
795
+ "auto_init": False
796
+ }
797
+
798
+ create_response = requests.post(
799
+ "https://api.github.com/user/repos",
800
+ headers=headers,
801
+ json=create_data
802
+ )
803
+
804
+ if create_response.status_code == 201:
805
+ repo_info = create_response.json()
806
+ yield f"โœ… GitHub repository created: {repo_info['html_url']}"
807
+ elif create_response.status_code == 422:
808
+ # ๋ ˆํฌ๊ฐ€ ์ด๋ฏธ ์กด์žฌํ•จ
809
+ repo_info = {"html_url": f"https://github.com/{github_username}/{github_repo_name}"}
810
+ yield f"โ„น๏ธ Repository already exists: {repo_info['html_url']}"
811
+ else:
812
+ raise Exception(f"Failed to create repository: {create_response.json().get('message', 'Unknown error')}")
813
+
814
+ # Git remote ๋ณ€๊ฒฝ ๋ฐ ํ‘ธ์‹œ
815
+ yield "๐Ÿ“ค Pushing to GitHub..."
816
+
817
+ # git ๋ช…๋ น์–ด๋กœ remote ๋ณ€๊ฒฝ ๋ฐ ํ‘ธ์‹œ
818
+ os.chdir(tmp_dir)
819
+
820
+ # ๊ธฐ์กด origin ์ œ๊ฑฐ
821
+ subprocess.run(['git', 'remote', 'remove', 'origin'], capture_output=True)
822
+
823
+ # GitHub remote ์ถ”๊ฐ€
824
+ github_remote_url = f"https://{github_username}:{github_token}@github.com/{github_username}/{github_repo_name}.git"
825
+ subprocess.run(['git', 'remote', 'add', 'origin', github_remote_url], check=True)
826
+
827
+ # main ๋ธŒ๋žœ์น˜๋กœ ํ‘ธ์‹œ
828
+ push_result = subprocess.run(
829
+ ['git', 'push', '-u', 'origin', 'HEAD:main'],
830
+ capture_output=True,
831
+ text=True
832
+ )
833
+
834
+ if push_result.returncode != 0:
835
+ # master ๋ธŒ๋žœ์น˜๋กœ ์žฌ์‹œ๋„
836
+ push_result = subprocess.run(
837
+ ['git', 'push', '-u', 'origin', 'HEAD:master'],
838
+ capture_output=True,
839
+ text=True
840
+ )
841
+
842
+ if push_result.returncode != 0:
843
+ raise Exception(f"Push failed: {push_result.stderr}")
844
+
845
+ yield "โœ… Successfully pushed to GitHub!"
846
+ yield f"\n๐Ÿ”— GitHub Repository: https://github.com/{github_username}/{github_repo_name}"
847
+ yield f"\nโœจ Clone command: `git clone https://github.com/{github_username}/{github_repo_name}.git`"
848
+
849
+ except Exception as e:
850
+ yield f"โŒ Error: {str(e)}"
851
+ finally:
852
+ # ์ž„์‹œ ๋””๋ ‰ํ† ๋ฆฌ ์ •๋ฆฌ
853
+ if tmp_dir and os.path.exists(tmp_dir):
854
+ os.chdir("/") # ๋””๋ ‰ํ† ๋ฆฌ ๋ฐ–์œผ๋กœ ์ด๋™
855
+ shutil.rmtree(tmp_dir)
856
+ yield "๐Ÿงน Cleaned up temporary files"
857
+
858
  css = """
859
  .container {
860
  max-width: 900px;
 
869
  font-size: 14px;
870
  line-height: 1.5;
871
  }
872
+ .tab-content {
873
+ margin-top: 20px;
874
+ }
875
  """
876
 
877
+ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
878
+ gr.Markdown("# ๐Ÿ”„ GitHub โ†” HuggingFace Space Converter")
879
 
880
+ with gr.Tabs():
881
+ with gr.Tab("GitHub โ†’ HF Space"):
882
+ if not os.getenv("HF_TOKEN"):
883
+ gr.Markdown("โŒ HF_TOKEN Required - Set it in Space settings")
884
+ else:
885
+ gr.Markdown("โœ… HF_TOKEN Found")
886
+
887
+ with gr.Row():
888
+ with gr.Column():
889
+ repo_git = gr.Textbox(
890
+ label="GitHub Repository URL",
891
+ placeholder="https://github.com/username/repository"
892
+ )
893
+ repo_hf = gr.Textbox(
894
+ label="Hugging Face Space Name",
895
+ placeholder="my-awesome-space"
896
+ )
897
+ sdk_choices = gr.Radio(
898
+ ["gradio", "streamlit", "docker", "static"],
899
+ label="Space SDK",
900
+ value="gradio"
901
+ )
902
+ skip_lfs = gr.Checkbox(
903
+ label="Skip Git LFS files",
904
+ value=True
905
+ )
906
+ enable_smart_generation = gr.Checkbox(
907
+ label="๐Ÿค– Enable Smart app.py Generation",
908
+ value=False,
909
+ info="Requires FIREWORKS_API_KEY in environment variables"
910
+ )
911
+
912
+ btn_to_hf = gr.Button("๐Ÿš€ Deploy to HF Space", variant="primary")
913
+
914
+ with gr.Column():
915
+ output_to_hf = gr.Textbox(
916
+ label="Progress",
917
+ lines=15,
918
+ elem_classes=["output-box"],
919
+ interactive=False,
920
+ show_copy_button=True
921
+ )
922
+
923
+ btn_to_hf.click(
924
+ fn=clone,
925
+ inputs=[repo_git, repo_hf, sdk_choices, skip_lfs, enable_smart_generation],
926
+ outputs=output_to_hf
927
  )
928
+
929
+ with gr.Tab("HF Space โ†’ GitHub"):
930
+ gr.Markdown("""
931
+ ๐Ÿ“Œ **Export your HuggingFace Space to GitHub**
932
 
933
+ Create a GitHub repository from your existing HuggingFace Space.
934
+ """)
935
 
936
+ with gr.Row():
937
+ with gr.Column():
938
+ hf_username = gr.Textbox(
939
+ label="HuggingFace Username",
940
+ placeholder="e.g., john_doe"
941
+ )
942
+ hf_space_name = gr.Textbox(
943
+ label="HuggingFace Space Name",
944
+ placeholder="e.g., my-space"
945
+ )
946
+ github_repo_name = gr.Textbox(
947
+ label="GitHub Repository Name",
948
+ placeholder="e.g., my-new-repo"
949
+ )
950
+ github_token = gr.Textbox(
951
+ label="GitHub Personal Access Token",
952
+ type="password",
953
+ placeholder="ghp_xxxxxxxxxxxx",
954
+ info="Token needs 'repo' scope. Get it from: https://github.com/settings/tokens"
955
+ )
956
+
957
+ btn_to_github = gr.Button("๐Ÿ“ค Export to GitHub", variant="primary")
958
+
959
+ with gr.Column():
960
+ output_to_github = gr.Textbox(
961
+ label="Progress",
962
+ lines=15,
963
+ elem_classes=["output-box"],
964
+ interactive=False,
965
+ show_copy_button=True
966
+ )
967
+
968
+ btn_to_github.click(
969
+ fn=space_to_github,
970
+ inputs=[hf_username, hf_space_name, github_repo_name, github_token],
971
+ outputs=output_to_github
972
  )
973
 
974
+ gr.Markdown("""
975
+ ---
976
+ ### ๐Ÿ“– Instructions
977
+
978
+ **GitHub โ†’ HF Space:**
979
+ - Clone any public GitHub repository to your HuggingFace account
980
+ - Automatically handles LFS issues
981
+ - Optional AI-powered app.py generation
982
+
983
+ **HF Space โ†’ GitHub:**
984
+ - Export your HuggingFace Space to a new GitHub repository
985
+ - Requires GitHub Personal Access Token with 'repo' scope
986
+ - Preserves all files and structure
987
+
988
+ ### ๐Ÿ”‘ Required Tokens
989
+ - **HF_TOKEN**: Set in Space settings for GitHub โ†’ HF
990
+ - **GitHub Token**: Required for HF โ†’ GitHub (create at [GitHub Settings](https://github.com/settings/tokens))
991
+ - **FIREWORKS_API_KEY**: Optional, for smart app generation
992
+ """)
993
 
994
  if __name__ == "__main__":
995
  demo.launch()