from flask import Flask, send_file, request, render_template import io import zipfile import os app = Flask(__name__) import subprocess import re from urllib.parse import urlparse, urlunparse import shutil def sanitize_git_url(url): """Sanitizes a Git repository URL.""" # Validate URL structure using urllib.parse try: parsed_url = urlparse(url) if not all([parsed_url.scheme, parsed_url.netloc]): print(f"Error: Invalid URL structure: {url}") return None if parsed_url.scheme not in ("https", "http", "git", "ssh"): print(f"Error: Invalid URL scheme: {parsed_url.scheme}") return None except Exception: print(f"Error: Could not parse url: {url}") return None # check input for suspicious characters if re.search(r'[;&|]', url): print(f"Error: Suspicious character in url {url}") return None # Normalize the url. Remove trailing slashes and .git suffix normalized_url = url.rstrip("/").rstrip(".git") return normalized_url def git_clone(repo_url): """Clones a Git repository, using the repo name as the destination folder.""" sanitized_url = sanitize_git_url(repo_url) if not sanitized_url: return # If sanitize_git_url returned None, don't continue. try: # Extract the repository name from the URL repo_name = extract_repo_name(sanitized_url) if not repo_name: print(f"Error: Unable to extract repository name from URL: {repo_url}") return destination_dir = repo_name # Use the extracted name for the destination folder if os.path.isdir(destination_dir): return repo_name subprocess.run( ["git", "clone", sanitized_url, destination_dir], check=True, capture_output=True, text=True ) print(f"Successfully cloned {sanitized_url} to {destination_dir}") return repo_name except subprocess.CalledProcessError as e: print(f"Error cloning {sanitized_url}:") print(f" Return code: {e.returncode}") print(f" Stdout:\n{e.stdout}") print(f" Stderr:\n{e.stderr}") def extract_repo_name(repo_url): """Extracts the repository name from a Git URL.""" # Example formats: # https://github.com/user/repo.git # git@github.com:user/repo.git # https://gitlab.com/user/repo match = re.search(r"([^/:]+)\/?$", repo_url.rstrip(".git/")) if match: return match.group(1) else: return None def zip_folder_to_buffer(folder_path): """ Zips a folder and returns the zipped content in a BytesIO buffer. Args: folder_path: The path to the folder you want to zip. Returns: A io.BytesIO buffer containing the zipped folder data, or None if there is an error. """ try: buffer = io.BytesIO() with zipfile.ZipFile(buffer, 'w', zipfile.ZIP_DEFLATED) as zf: for root, _, files in os.walk(folder_path): for file in files: file_path = os.path.join(root, file) arcname = os.path.relpath(file_path, folder_path) zf.write(file_path, arcname=arcname) buffer.seek(0) # Reset buffer position to the beginning for reading return buffer except Exception as e: print(f"Error creating zip file: {e}") return None @app.route('/', methods=['GET', 'POST']) def index(): if request.method == 'POST': # folder_to_zip = "./my_folder" # Replace with the actual folder path # deltemp = remove_all_files_and_directories("temp_folder") #clean temp folder # # Create an example folder and files # os.makedirs(folder_to_zip, exist_ok=True) # with open(os.path.join(folder_to_zip, "file1.txt"), "w") as f: # f.write("This is file1") # with open(os.path.join(folder_to_zip, "file2.txt"), "w") as f: # f.write("This is file2") repo_url = request.form['giturl'] #"https://huggingface.co/spaces/stepenZEN/gitgud" # Example repo, can be very large folder_to_zip = git_clone(repo_url) # if not folder_to_zip: # return zipped_buffer = zip_folder_to_buffer(folder_to_zip) if zipped_buffer: # Send the zipped buffer as a file download response = send_file( zipped_buffer, mimetype="application/zip", # Important: Set the correct MIME type as_attachment=True, download_name=f"{folder_to_zip}.zip" # Optional: Sets the suggested file name ) # Clean up the example folder # os.remove(os.path.join(folder_to_zip, "file1.txt")) # os.remove(os.path.join(folder_to_zip, "file2.txt")) # os.rmdir(folder_to_zip) # shutil.rmtree(folder_to_zip) return response else: return "Failed to create zip file", 500 return render_template('form.html') # Render form template if __name__ == '__main__': # app = create_app() app.run(debug=True, port=5500)