gitarsenal-cli 1.3.8 ā 1.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -119,12 +119,12 @@ except Exception as e:
|
|
119
119
|
# print(f"š Token ID exists: {'Yes' if os.environ.get('MODAL_TOKEN_ID') else 'No'}")
|
120
120
|
# print(f"š Token secret exists: {'Yes' if os.environ.get('MODAL_TOKEN_SECRET') else 'No'}")
|
121
121
|
# print(f"š Token exists: {'Yes' if os.environ.get('MODAL_TOKEN') else 'No'}")
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
122
|
+
if os.environ.get('MODAL_TOKEN_ID'):
|
123
|
+
print(f"š Token ID length: {len(os.environ.get('MODAL_TOKEN_ID'))}")
|
124
|
+
if os.environ.get('MODAL_TOKEN_SECRET'):
|
125
|
+
print(f"š Token secret length: {len(os.environ.get('MODAL_TOKEN_SECRET'))}")
|
126
|
+
if os.environ.get('MODAL_TOKEN'):
|
127
|
+
print(f"š Token length: {len(os.environ.get('MODAL_TOKEN'))}")
|
128
128
|
# print(f"ā
Token setup completed")
|
129
129
|
|
130
130
|
# Import modal after token setup
|
@@ -2025,7 +2025,7 @@ cd "{current_dir}"
|
|
2025
2025
|
print("ā³ Sandbox will remain running until you terminate it with:")
|
2026
2026
|
print(f"modal sandbox terminate {sandbox_id}")
|
2027
2027
|
|
2028
|
-
# Try to open a new terminal window and connect to the
|
2028
|
+
# Try to open a new terminal window and connect to the container
|
2029
2029
|
if container_id:
|
2030
2030
|
print("š„ļø Attempting to open new terminal window...")
|
2031
2031
|
# Use osascript to open a new terminal with the modal shell command
|
@@ -2558,129 +2558,301 @@ def create_modal_ssh_container(gpu_type, repo_url=None, repo_name=None, setup_co
|
|
2558
2558
|
print(f"ā Error running container: {e}")
|
2559
2559
|
return None
|
2560
2560
|
|
2561
|
+
def is_local_server_running(url, timeout=2):
|
2562
|
+
"""Check if a local server is running by attempting a connection."""
|
2563
|
+
import requests
|
2564
|
+
try:
|
2565
|
+
response = requests.get(url, timeout=timeout)
|
2566
|
+
return True
|
2567
|
+
except requests.exceptions.RequestException:
|
2568
|
+
return False
|
2569
|
+
|
2561
2570
|
def fetch_setup_commands_from_api(repo_url):
|
2562
|
-
"""
|
2571
|
+
"""Fetch setup commands from the GitIngest API using real repository analysis."""
|
2563
2572
|
import tempfile
|
2564
2573
|
import subprocess
|
2565
2574
|
import os
|
2566
2575
|
import shutil
|
2567
2576
|
import json
|
2577
|
+
import time
|
2578
|
+
import requests
|
2579
|
+
|
2580
|
+
# Define API endpoints to try in order - using only online endpoints
|
2581
|
+
api_endpoints = [
|
2582
|
+
"https://www.gitarsenal.dev/api/analyze-with-gitingest" # Working endpoint with www prefix
|
2583
|
+
]
|
2584
|
+
|
2585
|
+
print(f"š Fetching setup commands from API for repository: {repo_url}")
|
2568
2586
|
|
2569
|
-
|
2587
|
+
# Check if gitingest command line tool is available - try multiple possible command names
|
2588
|
+
has_gitingest_cli = False
|
2589
|
+
gitingest_cmd_name = None
|
2570
2590
|
|
2571
|
-
#
|
2591
|
+
# Try the standard command name first
|
2572
2592
|
try:
|
2573
2593
|
print(f"š Checking for GitIngest CLI tool...")
|
2574
2594
|
result = subprocess.run(["gitingest", "--help"], check=True, capture_output=True, text=True)
|
2595
|
+
has_gitingest_cli = True
|
2596
|
+
gitingest_cmd_name = "gitingest"
|
2575
2597
|
print(f"ā
GitIngest CLI tool found")
|
2576
2598
|
except (subprocess.SubprocessError, FileNotFoundError) as e:
|
2577
|
-
print(f"
|
2578
|
-
return generate_fallback_commands(None)
|
2599
|
+
print(f" - GitIngest command not found: {str(e)}")
|
2579
2600
|
|
2580
2601
|
# Create a temporary directory for output
|
2581
2602
|
temp_dir = tempfile.mkdtemp(prefix="repo_analysis_")
|
2582
2603
|
output_file = os.path.join(temp_dir, "digest.json")
|
2583
2604
|
|
2605
|
+
# Create a directory to save GitIngest results
|
2606
|
+
save_dir = os.path.join(os.path.expanduser("~"), "gitarsenal_results")
|
2607
|
+
os.makedirs(save_dir, exist_ok=True)
|
2608
|
+
timestamp = time.strftime("%Y%m%d_%H%M%S")
|
2609
|
+
repo_name = repo_url.split("/")[-1].replace(".git", "")
|
2610
|
+
save_file = os.path.join(save_dir, f"gitingest_{repo_name}_{timestamp}.txt")
|
2611
|
+
|
2584
2612
|
try:
|
2585
|
-
|
2586
|
-
|
2587
|
-
|
2588
|
-
|
2589
|
-
|
2590
|
-
|
2591
|
-
|
2592
|
-
|
2593
|
-
|
2594
|
-
|
2595
|
-
|
2596
|
-
|
2597
|
-
|
2598
|
-
|
2599
|
-
|
2600
|
-
|
2601
|
-
print(f"ā ļø Error output: {result.stderr}")
|
2602
|
-
print("Falling back to basic analysis")
|
2603
|
-
return generate_fallback_commands(None)
|
2604
|
-
|
2605
|
-
print(f"ā
GitIngest analysis completed successfully")
|
2606
|
-
|
2607
|
-
# Read the output file - GitIngest outputs structured text, not JSON
|
2608
|
-
try:
|
2609
|
-
with open(output_file, 'r', encoding='utf-8') as f:
|
2610
|
-
content = f.read()
|
2611
|
-
|
2612
|
-
# Process the text output into a structured format
|
2613
|
-
print(f"š Processing GitIngest text output")
|
2614
|
-
|
2615
|
-
# Extract key information from the text output
|
2616
|
-
import re
|
2617
|
-
|
2618
|
-
# Try to identify language
|
2619
|
-
language_match = re.search(r"(?i)language[s]?:?\s*(\w+)", content)
|
2620
|
-
detected_language = language_match.group(1) if language_match else "Unknown"
|
2621
|
-
|
2622
|
-
# Try to identify technologies
|
2623
|
-
tech_patterns = {
|
2624
|
-
"python": r"(?i)(python|\.py\b|pip\b|requirements\.txt|setup\.py)",
|
2625
|
-
"javascript": r"(?i)(javascript|\.js\b|node|npm|yarn|package\.json)",
|
2626
|
-
"typescript": r"(?i)(typescript|\.ts\b|tsc\b|tsconfig\.json)",
|
2627
|
-
"go": r"(?i)(\bgo\b|golang|\.go\b|go\.mod|go\.sum)",
|
2628
|
-
"rust": r"(?i)(rust|\.rs\b|cargo|Cargo\.toml)",
|
2629
|
-
"java": r"(?i)(java\b|\.java\b|maven|gradle|pom\.xml)",
|
2630
|
-
"c++": r"(?i)(c\+\+|\.cpp\b|\.hpp\b|cmake\b|CMakeLists\.txt)",
|
2631
|
-
"pytorch": r"(?i)(pytorch|torch\b|nn\.Module)",
|
2632
|
-
"tensorflow": r"(?i)(tensorflow|tf\.|keras\b)",
|
2633
|
-
}
|
2613
|
+
if has_gitingest_cli:
|
2614
|
+
# Use gitingest CLI tool to analyze the repository directly from URL
|
2615
|
+
print(f"š Running GitIngest analysis on {repo_url}...")
|
2616
|
+
|
2617
|
+
# Based on the help output, the correct format is:
|
2618
|
+
# gitingest [OPTIONS] [SOURCE]
|
2619
|
+
# With options:
|
2620
|
+
# -o, --output TEXT Output file path
|
2621
|
+
# --format TEXT Output format (json)
|
2622
|
+
|
2623
|
+
# Run gitingest command with proper parameters
|
2624
|
+
gitingest_run_cmd = [
|
2625
|
+
gitingest_cmd_name,
|
2626
|
+
repo_url,
|
2627
|
+
"-o", output_file, # Use -o for output file
|
2628
|
+
]
|
2634
2629
|
|
2635
|
-
|
2636
|
-
for tech, pattern in tech_patterns.items():
|
2637
|
-
if re.search(pattern, content):
|
2638
|
-
detected_technologies.append(tech)
|
2630
|
+
print(f"š Executing: {' '.join(gitingest_run_cmd)}")
|
2639
2631
|
|
2640
|
-
|
2641
|
-
|
2642
|
-
|
2643
|
-
|
2644
|
-
|
2645
|
-
|
2646
|
-
|
2647
|
-
|
2648
|
-
|
2649
|
-
|
2650
|
-
|
2651
|
-
|
2652
|
-
|
2632
|
+
result = subprocess.run(gitingest_run_cmd, capture_output=True, text=True)
|
2633
|
+
|
2634
|
+
if result.returncode != 0:
|
2635
|
+
print(f"ā ļø GitIngest CLI failed with exit code {result.returncode}")
|
2636
|
+
print(f"ā ļø Error output: {result.stderr}")
|
2637
|
+
print("Falling back to basic analysis")
|
2638
|
+
gitingest_data = generate_basic_repo_analysis_from_url(repo_url)
|
2639
|
+
else:
|
2640
|
+
print(f"ā
GitIngest analysis completed successfully")
|
2641
|
+
|
2642
|
+
# Read the output file - note that the default format might not be JSON
|
2643
|
+
try:
|
2644
|
+
# First try to parse as JSON
|
2645
|
+
try:
|
2646
|
+
with open(output_file, 'r', encoding='utf-8') as f:
|
2647
|
+
content = f.read()
|
2648
|
+
|
2649
|
+
# Save the GitIngest output to the results directory
|
2650
|
+
with open(save_file, 'w', encoding='utf-8') as save_f:
|
2651
|
+
save_f.write(content)
|
2652
|
+
print(f"š GitIngest output saved to: {save_file}")
|
2653
|
+
|
2654
|
+
try:
|
2655
|
+
gitingest_data = json.loads(content)
|
2656
|
+
print(f"ā
GitIngest data loaded as JSON from {output_file}")
|
2657
|
+
except json.JSONDecodeError:
|
2658
|
+
# If not JSON, convert the text output to a basic structure
|
2659
|
+
print(f"ā ļø GitIngest output is not in JSON format, converting text to structure")
|
2660
|
+
|
2661
|
+
# Process the text to extract useful information
|
2662
|
+
import re
|
2663
|
+
|
2664
|
+
# Try to identify language
|
2665
|
+
language_match = re.search(r"(?i)language[s]?:?\s*(\w+)", content)
|
2666
|
+
detected_language = language_match.group(1) if language_match else "Unknown"
|
2667
|
+
|
2668
|
+
# Try to identify technologies with stronger evidence requirements
|
2669
|
+
tech_patterns = {
|
2670
|
+
"python": r"(?i)(python|\.py\b|pip\b|requirements\.txt|setup\.py)",
|
2671
|
+
"javascript": r"(?i)(javascript|\.js\b|node|npm|yarn|package\.json)",
|
2672
|
+
"typescript": r"(?i)(typescript|\.ts\b|tsc\b|tsconfig\.json)",
|
2673
|
+
"go": r"(?i)(\bgo\b|golang|\.go\b|go\.mod|go\.sum)",
|
2674
|
+
"rust": r"(?i)(rust|\.rs\b|cargo|Cargo\.toml)",
|
2675
|
+
"java": r"(?i)(java\b|\.java\b|maven|gradle|pom\.xml)",
|
2676
|
+
"c++": r"(?i)(c\+\+|\.cpp\b|\.hpp\b|cmake\b|CMakeLists\.txt)",
|
2677
|
+
"pytorch": r"(?i)(pytorch|torch\b|nn\.Module)",
|
2678
|
+
"tensorflow": r"(?i)(tensorflow|tf\.|keras\b)",
|
2679
|
+
}
|
2680
|
+
|
2681
|
+
# Count occurrences to filter out false positives
|
2682
|
+
tech_counts = {}
|
2683
|
+
for tech, pattern in tech_patterns.items():
|
2684
|
+
matches = re.findall(pattern, content)
|
2685
|
+
if matches:
|
2686
|
+
tech_counts[tech] = len(matches)
|
2687
|
+
|
2688
|
+
# Filter technologies based on threshold
|
2689
|
+
thresholds = {
|
2690
|
+
"javascript": 3, # Higher threshold for JavaScript
|
2691
|
+
"go": 3, # Higher threshold for Go
|
2692
|
+
"default": 2 # Default threshold
|
2693
|
+
}
|
2694
|
+
|
2695
|
+
detected_technologies = []
|
2696
|
+
for tech, count in tech_counts.items():
|
2697
|
+
threshold = thresholds.get(tech, thresholds["default"])
|
2698
|
+
if count >= threshold:
|
2699
|
+
detected_technologies.append(tech)
|
2700
|
+
print(f"š Detected {tech} with confidence score {count}")
|
2701
|
+
|
2702
|
+
# Create a structured representation
|
2703
|
+
gitingest_data = {
|
2704
|
+
"system_info": {
|
2705
|
+
"detected_language": detected_language,
|
2706
|
+
"detected_technologies": detected_technologies,
|
2707
|
+
},
|
2708
|
+
"repository_analysis": {
|
2709
|
+
"summary": content[:5000], # First 5000 chars as summary
|
2710
|
+
"content_preview": content[:10000] # First 10000 chars as preview
|
2711
|
+
},
|
2712
|
+
"success": True
|
2713
|
+
}
|
2714
|
+
|
2715
|
+
# Save the processed data
|
2716
|
+
processed_file = os.path.join(save_dir, f"gitingest_processed_{repo_name}_{timestamp}.json")
|
2717
|
+
with open(processed_file, 'w', encoding='utf-8') as proc_f:
|
2718
|
+
json.dump(gitingest_data, proc_f, indent=2)
|
2719
|
+
print(f"š Processed GitIngest data saved to: {processed_file}")
|
2720
|
+
except FileNotFoundError:
|
2721
|
+
print(f"ā ļø Output file not found at {output_file}")
|
2722
|
+
gitingest_data = generate_basic_repo_analysis_from_url(repo_url)
|
2723
|
+
except Exception as e:
|
2724
|
+
print(f"ā ļø Error reading GitIngest output: {e}")
|
2725
|
+
gitingest_data = generate_basic_repo_analysis_from_url(repo_url)
|
2726
|
+
else:
|
2727
|
+
# Fall back to basic analysis if gitingest CLI is not available
|
2728
|
+
gitingest_data = generate_basic_repo_analysis_from_url(repo_url)
|
2729
|
+
|
2730
|
+
# Prepare the request payload with GitIngest data
|
2731
|
+
payload = {
|
2732
|
+
"repoUrl": repo_url,
|
2733
|
+
"gitingestData": gitingest_data,
|
2734
|
+
"userRequest": "Setup and run the repository"
|
2735
|
+
}
|
2736
|
+
|
2737
|
+
print(f"š¤ API Request payload prepared (GitIngest data size: {len(json.dumps(gitingest_data))} bytes)")
|
2738
|
+
|
2739
|
+
# Try each endpoint in sequence until one succeeds
|
2740
|
+
response = None
|
2741
|
+
for api_url in api_endpoints:
|
2742
|
+
# Use the retry mechanism for more reliable requests
|
2743
|
+
response = make_api_request_with_retry(
|
2744
|
+
url=api_url,
|
2745
|
+
payload=payload,
|
2746
|
+
max_retries=2,
|
2747
|
+
timeout=180 # 3 minute timeout
|
2748
|
+
)
|
2749
|
+
|
2750
|
+
# If we got a response and it's successful, break out of the loop
|
2751
|
+
if response and response.status_code == 200:
|
2752
|
+
print(f"ā
Successful response from {api_url}")
|
2753
|
+
break
|
2754
|
+
|
2755
|
+
if response:
|
2756
|
+
print(f"ā ļø Endpoint {api_url} returned status code {response.status_code}, trying next endpoint...")
|
2757
|
+
else:
|
2758
|
+
print(f"ā ļø Failed to connect to {api_url}, trying next endpoint...")
|
2759
|
+
|
2760
|
+
# If we've tried all endpoints and still don't have a response, use fallback
|
2761
|
+
if response is None:
|
2762
|
+
print("ā All API endpoints failed")
|
2763
|
+
return generate_fallback_commands(gitingest_data)
|
2653
2764
|
|
2654
|
-
|
2765
|
+
# Continue with the response we got from the successful endpoint
|
2766
|
+
if not response:
|
2767
|
+
print("ā No valid response received from any endpoint")
|
2768
|
+
return generate_fallback_commands(gitingest_data)
|
2655
2769
|
|
2656
|
-
|
2657
|
-
print(f"
|
2658
|
-
setup_commands = generate_fallback_commands(gitingest_data)
|
2659
|
-
return setup_commands
|
2770
|
+
try:
|
2771
|
+
print(f"š„ API Response status code: {response.status_code}")
|
2660
2772
|
|
2661
|
-
|
2662
|
-
|
2663
|
-
|
2773
|
+
if response.status_code == 200:
|
2774
|
+
try:
|
2775
|
+
data = response.json()
|
2776
|
+
print(f"š API Response data received")
|
2777
|
+
print(f"š Response size: {len(response.text)} bytes")
|
2778
|
+
print(f"š Response URL: {response.url}")
|
2779
|
+
|
2780
|
+
# Extract setup commands from the response
|
2781
|
+
if "setupInstructions" in data and "commands" in data["setupInstructions"]:
|
2782
|
+
commands = data["setupInstructions"]["commands"]
|
2783
|
+
print(f"ā
Successfully fetched {len(commands)} setup commands from API")
|
2784
|
+
|
2785
|
+
# Print the original commands for reference
|
2786
|
+
print("š Original commands from API:")
|
2787
|
+
for i, cmd in enumerate(commands, 1):
|
2788
|
+
print(f" {i}. {cmd}")
|
2789
|
+
|
2790
|
+
# Fix the commands by removing placeholders and comments
|
2791
|
+
fixed_commands = fix_setup_commands(commands)
|
2792
|
+
|
2793
|
+
# If we have a temp_dir with the cloned repo, try to find the entry point
|
2794
|
+
# and replace any placeholder entry points
|
2795
|
+
for i, cmd in enumerate(fixed_commands):
|
2796
|
+
if "python main.py" in cmd or "python3 main.py" in cmd:
|
2797
|
+
try:
|
2798
|
+
entry_point = find_entry_point(temp_dir)
|
2799
|
+
if entry_point and entry_point != "main.py":
|
2800
|
+
fixed_commands[i] = cmd.replace("main.py", entry_point)
|
2801
|
+
print(f"š Replaced main.py with detected entry point: {entry_point}")
|
2802
|
+
except Exception as e:
|
2803
|
+
print(f"ā ļø Error finding entry point: {e}")
|
2804
|
+
|
2805
|
+
# Print the fixed commands
|
2806
|
+
print("\nš Fixed commands:")
|
2807
|
+
for i, cmd in enumerate(fixed_commands, 1):
|
2808
|
+
print(f" {i}. {cmd}")
|
2809
|
+
|
2810
|
+
return fixed_commands
|
2811
|
+
else:
|
2812
|
+
print("ā ļø API response did not contain setupInstructions.commands field")
|
2813
|
+
print("š Available fields in response:")
|
2814
|
+
for key in data.keys():
|
2815
|
+
print(f" - {key}")
|
2816
|
+
# Return fallback commands
|
2817
|
+
return generate_fallback_commands(gitingest_data)
|
2818
|
+
except json.JSONDecodeError as e:
|
2819
|
+
print(f"ā Failed to parse API response as JSON: {e}")
|
2820
|
+
print(f"Raw response: {response.text[:500]}...")
|
2821
|
+
# Return fallback commands
|
2822
|
+
return generate_fallback_commands(gitingest_data)
|
2823
|
+
elif response.status_code == 504:
|
2824
|
+
print(f"ā API request timed out (504 Gateway Timeout)")
|
2825
|
+
print("ā ļø The server took too long to respond. Using fallback commands instead.")
|
2826
|
+
# Return fallback commands
|
2827
|
+
return generate_fallback_commands(gitingest_data)
|
2828
|
+
else:
|
2829
|
+
print(f"ā API request failed with status code: {response.status_code}")
|
2830
|
+
print(f"ā Response URL: {response.url}")
|
2831
|
+
print(f"ā Response headers: {dict(response.headers)}")
|
2832
|
+
print(f"ā Error response: {response.text[:500]}...")
|
2833
|
+
# Return fallback commands
|
2834
|
+
return generate_fallback_commands(gitingest_data)
|
2664
2835
|
except Exception as e:
|
2665
|
-
print(f"
|
2666
|
-
|
2836
|
+
print(f"ā Error processing API response: {str(e)}")
|
2837
|
+
print("ā ļø Using fallback commands instead")
|
2838
|
+
# Return fallback commands
|
2839
|
+
return generate_fallback_commands(gitingest_data)
|
2840
|
+
except Exception as e:
|
2841
|
+
print(f"ā Error fetching setup commands from API: {e}")
|
2842
|
+
import traceback
|
2843
|
+
traceback.print_exc()
|
2844
|
+
# Return fallback commands
|
2845
|
+
return generate_fallback_commands(None)
|
2667
2846
|
finally:
|
2668
|
-
# Clean up temporary directory
|
2847
|
+
# Clean up the temporary directory
|
2669
2848
|
print(f"š§¹ Cleaning up temporary directory...")
|
2670
|
-
|
2671
|
-
shutil.rmtree(temp_dir)
|
2672
|
-
except Exception as e:
|
2673
|
-
print(f"ā ļø Error cleaning up temporary directory: {e}")
|
2674
|
-
|
2675
|
-
# If all else fails, return basic setup commands
|
2676
|
-
return [
|
2677
|
-
"apt-get update -y",
|
2678
|
-
"apt-get install -y git curl wget",
|
2679
|
-
"pip install --upgrade pip setuptools wheel"
|
2680
|
-
]
|
2849
|
+
shutil.rmtree(temp_dir, ignore_errors=True)
|
2681
2850
|
|
2682
2851
|
def generate_fallback_commands(gitingest_data):
|
2683
2852
|
"""Generate fallback setup commands based on repository analysis"""
|
2853
|
+
print("\n" + "="*80)
|
2854
|
+
print("š GENERATING FALLBACK SETUP COMMANDS")
|
2855
|
+
print("="*80)
|
2684
2856
|
print("Using basic repository analysis to generate setup commands")
|
2685
2857
|
|
2686
2858
|
# Default commands that work for most repositories
|
@@ -2700,28 +2872,6 @@ def generate_fallback_commands(gitingest_data):
|
|
2700
2872
|
detected_technologies = gitingest_data.get("system_info", {}).get("detected_technologies", [])
|
2701
2873
|
primary_package_manager = gitingest_data.get("system_info", {}).get("primary_package_manager", "Unknown")
|
2702
2874
|
|
2703
|
-
# Extract more information from raw text if available
|
2704
|
-
if "raw_text" in gitingest_data and gitingest_data["raw_text"]:
|
2705
|
-
raw_text = gitingest_data["raw_text"]
|
2706
|
-
|
2707
|
-
# Look for additional technologies in raw text
|
2708
|
-
import re
|
2709
|
-
tech_patterns = {
|
2710
|
-
"python": r"(?i)(python|\.py\b|pip\b|requirements\.txt|setup\.py)",
|
2711
|
-
"javascript": r"(?i)(javascript|\.js\b|node|npm|yarn|package\.json)",
|
2712
|
-
"typescript": r"(?i)(typescript|\.ts\b|tsc\b|tsconfig\.json)",
|
2713
|
-
"go": r"(?i)(\bgo\b|golang|\.go\b|go\.mod|go\.sum)",
|
2714
|
-
"rust": r"(?i)(rust|\.rs\b|cargo|Cargo\.toml)",
|
2715
|
-
"java": r"(?i)(java\b|\.java\b|maven|gradle|pom\.xml)",
|
2716
|
-
"c++": r"(?i)(c\+\+|\.cpp\b|\.hpp\b|cmake\b|CMakeLists\.txt)",
|
2717
|
-
"pytorch": r"(?i)(pytorch|torch\b|nn\.Module)",
|
2718
|
-
"tensorflow": r"(?i)(tensorflow|tf\.|keras\b)",
|
2719
|
-
}
|
2720
|
-
|
2721
|
-
for tech, pattern in tech_patterns.items():
|
2722
|
-
if re.search(pattern, raw_text) and tech.lower() not in [t.lower() for t in detected_technologies]:
|
2723
|
-
detected_technologies.append(tech)
|
2724
|
-
|
2725
2875
|
# Add language-specific commands
|
2726
2876
|
language_commands = []
|
2727
2877
|
|
@@ -2729,21 +2879,12 @@ def generate_fallback_commands(gitingest_data):
|
|
2729
2879
|
print(f"š Detected technologies: {', '.join(detected_technologies) if detected_technologies else 'None'}")
|
2730
2880
|
print(f"š Detected package manager: {primary_package_manager}")
|
2731
2881
|
|
2732
|
-
# Check for specific technologies and add appropriate commands
|
2733
|
-
has_python = any(tech.lower() == "python" for tech in detected_technologies) or detected_language.lower() == "python"
|
2734
|
-
has_js = any(tech.lower() in ["javascript", "node", "nodejs"] for tech in detected_technologies)
|
2735
|
-
has_ts = any(tech.lower() == "typescript" for tech in detected_technologies)
|
2736
|
-
has_go = any(tech.lower() in ["go", "golang"] for tech in detected_technologies)
|
2737
|
-
has_pytorch = any(tech.lower() in ["pytorch", "torch"] for tech in detected_technologies)
|
2738
|
-
has_tensorflow = any(tech.lower() == "tensorflow" for tech in detected_technologies)
|
2739
|
-
|
2740
2882
|
# Python-specific commands
|
2741
|
-
if
|
2883
|
+
if detected_language == "Python" or primary_package_manager == "pip":
|
2742
2884
|
print("š¦ Adding Python-specific setup commands")
|
2743
|
-
language_commands.append("apt-get install -y python3 python3-pip python3-dev")
|
2744
2885
|
|
2745
2886
|
# Check for requirements.txt
|
2746
|
-
|
2887
|
+
requirements_check = [
|
2747
2888
|
"if [ -f requirements.txt ]; then",
|
2748
2889
|
" echo 'Installing from requirements.txt'",
|
2749
2890
|
" pip install -r requirements.txt",
|
@@ -2751,56 +2892,72 @@ def generate_fallback_commands(gitingest_data):
|
|
2751
2892
|
" echo 'Installing from setup.py'",
|
2752
2893
|
" pip install -e .",
|
2753
2894
|
"fi"
|
2754
|
-
]
|
2895
|
+
]
|
2896
|
+
language_commands.extend(requirements_check)
|
2897
|
+
|
2898
|
+
# Add common Python packages
|
2899
|
+
language_commands.append("pip install pytest numpy pandas matplotlib")
|
2755
2900
|
|
2756
2901
|
# JavaScript/Node.js specific commands
|
2757
|
-
|
2902
|
+
elif detected_language in ["JavaScript", "TypeScript"] or primary_package_manager in ["npm", "yarn", "pnpm"]:
|
2758
2903
|
print("š¦ Adding JavaScript/Node.js-specific setup commands")
|
2759
|
-
language_commands.append("curl -fsSL https://deb.nodesource.com/setup_18.x | bash -")
|
2760
|
-
language_commands.append("apt-get install -y nodejs")
|
2761
2904
|
|
2762
|
-
# Install
|
2763
|
-
|
2764
|
-
language_commands.append("npm install -g typescript ts-node")
|
2905
|
+
# Install Node.js if not available
|
2906
|
+
language_commands.append("apt-get install -y nodejs npm")
|
2765
2907
|
|
2766
2908
|
# Check for package.json
|
2767
|
-
|
2909
|
+
package_json_check = [
|
2768
2910
|
"if [ -f package.json ]; then",
|
2769
|
-
" echo 'Installing
|
2911
|
+
" echo 'Installing from package.json'",
|
2770
2912
|
" npm install",
|
2771
2913
|
"fi"
|
2772
|
-
]
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
2778
|
-
|
2779
|
-
|
2780
|
-
|
2781
|
-
|
2914
|
+
]
|
2915
|
+
language_commands.extend(package_json_check)
|
2916
|
+
|
2917
|
+
# Java specific commands
|
2918
|
+
elif detected_language == "Java" or primary_package_manager in ["maven", "gradle"]:
|
2919
|
+
print("š¦ Adding Java-specific setup commands")
|
2920
|
+
|
2921
|
+
language_commands.append("apt-get install -y openjdk-11-jdk maven gradle")
|
2922
|
+
|
2923
|
+
# Check for Maven or Gradle
|
2924
|
+
build_check = [
|
2925
|
+
"if [ -f pom.xml ]; then",
|
2926
|
+
" echo 'Building with Maven'",
|
2927
|
+
" mvn clean install -DskipTests",
|
2928
|
+
"elif [ -f build.gradle ]; then",
|
2929
|
+
" echo 'Building with Gradle'",
|
2930
|
+
" gradle build --no-daemon",
|
2782
2931
|
"fi"
|
2783
|
-
]
|
2932
|
+
]
|
2933
|
+
language_commands.extend(build_check)
|
2784
2934
|
|
2785
|
-
#
|
2786
|
-
|
2787
|
-
print("š¦ Adding
|
2788
|
-
|
2935
|
+
# Go specific commands
|
2936
|
+
elif detected_language == "Go" or primary_package_manager == "go":
|
2937
|
+
print("š¦ Adding Go-specific setup commands")
|
2938
|
+
|
2939
|
+
language_commands.append("apt-get install -y golang-go")
|
2940
|
+
language_commands.append("go mod tidy")
|
2789
2941
|
|
2790
|
-
#
|
2791
|
-
|
2792
|
-
print("š¦ Adding
|
2793
|
-
|
2942
|
+
# Rust specific commands
|
2943
|
+
elif detected_language == "Rust" or primary_package_manager == "cargo":
|
2944
|
+
print("š¦ Adding Rust-specific setup commands")
|
2945
|
+
|
2946
|
+
language_commands.append("curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y")
|
2947
|
+
language_commands.append("source $HOME/.cargo/env")
|
2948
|
+
language_commands.append("cargo build")
|
2794
2949
|
|
2795
|
-
# Combine
|
2950
|
+
# Combine all commands
|
2796
2951
|
all_commands = default_commands + language_commands
|
2797
2952
|
|
2798
|
-
#
|
2953
|
+
# Fix the commands
|
2954
|
+
fixed_commands = fix_setup_commands(all_commands)
|
2955
|
+
|
2799
2956
|
print("\nš Generated fallback setup commands:")
|
2800
|
-
for i, cmd in enumerate(
|
2957
|
+
for i, cmd in enumerate(fixed_commands, 1):
|
2801
2958
|
print(f" {i}. {cmd}")
|
2802
2959
|
|
2803
|
-
return
|
2960
|
+
return fixed_commands
|
2804
2961
|
|
2805
2962
|
def generate_basic_repo_analysis_from_url(repo_url):
|
2806
2963
|
"""Generate basic repository analysis data from a repository URL."""
|
@@ -2968,8 +3125,11 @@ def generate_basic_repo_analysis(repo_dir):
|
|
2968
3125
|
}
|
2969
3126
|
|
2970
3127
|
def get_setup_commands_from_local_api(repo_url, gitingest_data):
|
2971
|
-
"""Try to get setup commands from the
|
2972
|
-
|
3128
|
+
"""Try to get setup commands from the API."""
|
3129
|
+
# Use only online endpoints
|
3130
|
+
api_endpoints = [
|
3131
|
+
"https://www.gitarsenal.dev/api/analyze-with-gitingest" # Working endpoint with www prefix
|
3132
|
+
]
|
2973
3133
|
|
2974
3134
|
# Prepare the request payload
|
2975
3135
|
payload = {
|
@@ -2978,34 +3138,49 @@ def get_setup_commands_from_local_api(repo_url, gitingest_data):
|
|
2978
3138
|
"userRequest": "Setup and run the repository"
|
2979
3139
|
}
|
2980
3140
|
|
2981
|
-
|
2982
|
-
|
2983
|
-
|
2984
|
-
response =
|
3141
|
+
# Try each API endpoint
|
3142
|
+
for api_url in api_endpoints:
|
3143
|
+
# Use the retry mechanism for more reliable requests
|
3144
|
+
response = make_api_request_with_retry(
|
3145
|
+
url=api_url,
|
3146
|
+
payload=payload,
|
3147
|
+
max_retries=2,
|
3148
|
+
timeout=180 # 3 minute timeout
|
3149
|
+
)
|
2985
3150
|
|
2986
|
-
if response.status_code == 200:
|
2987
|
-
|
2988
|
-
|
2989
|
-
|
2990
|
-
print(f"
|
2991
|
-
|
2992
|
-
|
2993
|
-
|
2994
|
-
|
2995
|
-
|
2996
|
-
|
2997
|
-
|
2998
|
-
|
2999
|
-
|
3000
|
-
|
3001
|
-
|
3002
|
-
|
3003
|
-
|
3004
|
-
|
3005
|
-
|
3006
|
-
|
3007
|
-
|
3151
|
+
if response and response.status_code == 200:
|
3152
|
+
try:
|
3153
|
+
data = response.json()
|
3154
|
+
print(f"š Response size: {len(response.text)} bytes")
|
3155
|
+
print(f"š Response URL: {response.url}")
|
3156
|
+
if "setupInstructions" in data and "commands" in data["setupInstructions"]:
|
3157
|
+
commands = data["setupInstructions"]["commands"]
|
3158
|
+
print(f"ā
Successfully fetched {len(commands)} setup commands from API at {api_url}")
|
3159
|
+
|
3160
|
+
# Print the original commands
|
3161
|
+
print("š Original commands from API:")
|
3162
|
+
for i, cmd in enumerate(commands, 1):
|
3163
|
+
print(f" {i}. {cmd}")
|
3164
|
+
|
3165
|
+
# Fix the commands
|
3166
|
+
fixed_commands = fix_setup_commands(commands)
|
3167
|
+
|
3168
|
+
# Print the fixed commands
|
3169
|
+
print("\nš Fixed commands:")
|
3170
|
+
for i, cmd in enumerate(fixed_commands, 1):
|
3171
|
+
print(f" {i}. {cmd}")
|
3172
|
+
|
3173
|
+
return fixed_commands
|
3174
|
+
else:
|
3175
|
+
print("ā ļø API response did not contain setupInstructions.commands field")
|
3176
|
+
except json.JSONDecodeError:
|
3177
|
+
print(f"ā Failed to parse API response as JSON")
|
3178
|
+
elif response:
|
3179
|
+
print(f"ā API request failed with status code: {response.status_code}")
|
3180
|
+
else:
|
3181
|
+
print(f"ā Failed to connect to {api_url}")
|
3008
3182
|
|
3183
|
+
print("ā All API endpoints failed")
|
3009
3184
|
return None
|
3010
3185
|
|
3011
3186
|
# Define a function to create and return a properly configured ssh container function
|
@@ -3296,9 +3471,253 @@ def show_usage_examples():
|
|
3296
3471
|
print("ā --volume-name my-persistent-volume ā")
|
3297
3472
|
print("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n")
|
3298
3473
|
|
3474
|
+
print("With GitIngest API (default)")
|
3475
|
+
print("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā")
|
3476
|
+
print("ā gitarsenal --gpu A10G --repo-url https://github.com/username/repo.git ā")
|
3477
|
+
print("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n")
|
3478
|
+
|
3479
|
+
print("Without GitIngest API")
|
3480
|
+
print("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā")
|
3481
|
+
print("ā gitarsenal --gpu A10G --repo-url https://github.com/username/repo.git \\ ā")
|
3482
|
+
print("ā --no-gitingest ā")
|
3483
|
+
print("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n")
|
3484
|
+
|
3485
|
+
print("With Original API")
|
3486
|
+
print("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā")
|
3487
|
+
print("ā gitarsenal --gpu A10G --repo-url https://github.com/username/repo.git \\ ā")
|
3488
|
+
print("ā --use-api ā")
|
3489
|
+
print("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n")
|
3490
|
+
|
3299
3491
|
print("Available GPU Options:")
|
3300
3492
|
print(" T4, L4, A10G, A100-40GB, A100-80GB, L40S, H100, H200, B200")
|
3301
3493
|
|
3494
|
+
def make_api_request_with_retry(url, payload, max_retries=2, timeout=180):
|
3495
|
+
"""Make an API request with retry mechanism."""
|
3496
|
+
import requests
|
3497
|
+
import time
|
3498
|
+
|
3499
|
+
for attempt in range(max_retries + 1):
|
3500
|
+
try:
|
3501
|
+
if attempt > 0:
|
3502
|
+
print(f"š Retry attempt {attempt}/{max_retries}...")
|
3503
|
+
|
3504
|
+
print(f"š Making POST request to: {url}")
|
3505
|
+
print(f"ā³ Waiting up to {timeout//60} minutes for response...")
|
3506
|
+
|
3507
|
+
# Set allow_redirects=True to follow redirects automatically
|
3508
|
+
response = requests.post(
|
3509
|
+
url,
|
3510
|
+
json=payload,
|
3511
|
+
timeout=timeout,
|
3512
|
+
allow_redirects=True,
|
3513
|
+
headers={
|
3514
|
+
'Content-Type': 'application/json',
|
3515
|
+
'User-Agent': 'GitArsenal-CLI/1.0'
|
3516
|
+
}
|
3517
|
+
)
|
3518
|
+
|
3519
|
+
# Print redirect info if any
|
3520
|
+
if response.history:
|
3521
|
+
print(f"ā
Request was redirected {len(response.history)} times")
|
3522
|
+
for resp in response.history:
|
3523
|
+
print(f" - Redirect: {resp.status_code} from {resp.url}")
|
3524
|
+
print(f"ā
Final URL: {response.url}")
|
3525
|
+
|
3526
|
+
return response
|
3527
|
+
except requests.exceptions.RequestException as e:
|
3528
|
+
if attempt < max_retries:
|
3529
|
+
retry_delay = 2 ** attempt # Exponential backoff
|
3530
|
+
print(f"ā ļø Request failed: {str(e)}")
|
3531
|
+
print(f"ā³ Waiting {retry_delay} seconds before retrying...")
|
3532
|
+
time.sleep(retry_delay)
|
3533
|
+
else:
|
3534
|
+
print(f"ā All retry attempts failed: {str(e)}")
|
3535
|
+
return None
|
3536
|
+
|
3537
|
+
return None
|
3538
|
+
|
3539
|
+
def get_setup_commands_from_gitingest(repo_url):
|
3540
|
+
"""
|
3541
|
+
Get repository setup commands using the gitingest approach.
|
3542
|
+
|
3543
|
+
This function is inspired by gitingest_setup_client.py and provides a more
|
3544
|
+
robust way to get setup commands for a repository.
|
3545
|
+
|
3546
|
+
Args:
|
3547
|
+
repo_url: URL of the repository to set up
|
3548
|
+
|
3549
|
+
Returns:
|
3550
|
+
List of setup commands or None if failed
|
3551
|
+
"""
|
3552
|
+
import requests
|
3553
|
+
import json
|
3554
|
+
import os
|
3555
|
+
import sys
|
3556
|
+
import tempfile
|
3557
|
+
import subprocess
|
3558
|
+
|
3559
|
+
print(f"š Getting setup commands for repository: {repo_url}")
|
3560
|
+
|
3561
|
+
# Define API endpoints to try in order
|
3562
|
+
api_endpoints = [
|
3563
|
+
"https://www.gitarsenal.dev/api/gitingest-setup-commands",
|
3564
|
+
"https://gitarsenal.dev/api/gitingest-setup-commands",
|
3565
|
+
"https://www.gitarsenal.dev/api/analyze-with-gitingest",
|
3566
|
+
"http://localhost:3000/api/gitingest-setup-commands"
|
3567
|
+
]
|
3568
|
+
|
3569
|
+
# Generate basic gitingest data
|
3570
|
+
def generate_basic_gitingest_data():
|
3571
|
+
# Extract repo name from URL
|
3572
|
+
repo_name = repo_url.split('/')[-1].replace('.git', '')
|
3573
|
+
|
3574
|
+
return {
|
3575
|
+
"system_info": {
|
3576
|
+
"platform": "Unknown",
|
3577
|
+
"python_version": "Unknown",
|
3578
|
+
"detected_language": "Unknown",
|
3579
|
+
"detected_technologies": [],
|
3580
|
+
"file_count": 0,
|
3581
|
+
"repo_stars": 0,
|
3582
|
+
"repo_forks": 0,
|
3583
|
+
"primary_package_manager": "Unknown",
|
3584
|
+
"complexity_level": "Unknown"
|
3585
|
+
},
|
3586
|
+
"repository_analysis": {
|
3587
|
+
"summary": f"Repository: {repo_name}",
|
3588
|
+
"tree": "",
|
3589
|
+
"content_preview": ""
|
3590
|
+
},
|
3591
|
+
"success": True
|
3592
|
+
}
|
3593
|
+
|
3594
|
+
# Try to generate gitingest data using CLI if available
|
3595
|
+
def generate_gitingest_data_from_cli():
|
3596
|
+
try:
|
3597
|
+
# Check if gitingest CLI is available
|
3598
|
+
subprocess.run(["gitingest", "--help"], check=True, capture_output=True, text=True)
|
3599
|
+
|
3600
|
+
# Create a temporary file for the output
|
3601
|
+
with tempfile.NamedTemporaryFile(suffix='.json', delete=False) as tmp:
|
3602
|
+
output_file = tmp.name
|
3603
|
+
|
3604
|
+
# Run gitingest command
|
3605
|
+
print(f"Running gitingest analysis on {repo_url}...")
|
3606
|
+
gitingest_cmd = ["gitingest", repo_url, "-o", output_file]
|
3607
|
+
result = subprocess.run(gitingest_cmd, capture_output=True, text=True)
|
3608
|
+
|
3609
|
+
if result.returncode != 0:
|
3610
|
+
print(f"GitIngest CLI failed: {result.stderr}")
|
3611
|
+
return None
|
3612
|
+
|
3613
|
+
# Read the output file
|
3614
|
+
try:
|
3615
|
+
with open(output_file, 'r', encoding='utf-8') as f:
|
3616
|
+
content = f.read()
|
3617
|
+
try:
|
3618
|
+
data = json.loads(content)
|
3619
|
+
return data
|
3620
|
+
except json.JSONDecodeError:
|
3621
|
+
# If not JSON, convert the text output to a basic structure
|
3622
|
+
return {
|
3623
|
+
"system_info": {
|
3624
|
+
"platform": "Unknown",
|
3625
|
+
"python_version": "Unknown",
|
3626
|
+
"detected_language": "Unknown",
|
3627
|
+
"detected_technologies": []
|
3628
|
+
},
|
3629
|
+
"repository_analysis": {
|
3630
|
+
"summary": content[:5000], # First 5000 chars as summary
|
3631
|
+
"tree": "",
|
3632
|
+
"content_preview": content[:10000] # First 10000 chars as preview
|
3633
|
+
},
|
3634
|
+
"success": True
|
3635
|
+
}
|
3636
|
+
except Exception as e:
|
3637
|
+
print(f"Error reading gitingest output: {e}")
|
3638
|
+
return None
|
3639
|
+
finally:
|
3640
|
+
# Clean up the temporary file
|
3641
|
+
if os.path.exists(output_file):
|
3642
|
+
os.unlink(output_file)
|
3643
|
+
|
3644
|
+
except (subprocess.SubprocessError, FileNotFoundError):
|
3645
|
+
print("GitIngest CLI not found")
|
3646
|
+
return None
|
3647
|
+
|
3648
|
+
# First try to get data from CLI
|
3649
|
+
gitingest_data = generate_gitingest_data_from_cli()
|
3650
|
+
|
3651
|
+
# If CLI failed, use basic data
|
3652
|
+
if not gitingest_data:
|
3653
|
+
print("Using basic gitingest data")
|
3654
|
+
gitingest_data = generate_basic_gitingest_data()
|
3655
|
+
|
3656
|
+
# Try each API endpoint
|
3657
|
+
for api_url in api_endpoints:
|
3658
|
+
try:
|
3659
|
+
print(f"Trying API endpoint: {api_url}")
|
3660
|
+
|
3661
|
+
payload = {
|
3662
|
+
"repoUrl": repo_url,
|
3663
|
+
"gitingestData": gitingest_data
|
3664
|
+
}
|
3665
|
+
|
3666
|
+
# Use the retry mechanism for more reliable requests
|
3667
|
+
response = make_api_request_with_retry(
|
3668
|
+
url=api_url,
|
3669
|
+
payload=payload,
|
3670
|
+
max_retries=2,
|
3671
|
+
timeout=180 # 3 minute timeout
|
3672
|
+
)
|
3673
|
+
|
3674
|
+
if not response:
|
3675
|
+
print(f"Failed to connect to {api_url}")
|
3676
|
+
continue
|
3677
|
+
|
3678
|
+
if response.status_code != 200:
|
3679
|
+
print(f"API request failed with status code: {response.status_code}")
|
3680
|
+
continue
|
3681
|
+
|
3682
|
+
try:
|
3683
|
+
result = response.json()
|
3684
|
+
|
3685
|
+
# Check if we have commands in the response
|
3686
|
+
commands = None
|
3687
|
+
|
3688
|
+
# Check for different response formats
|
3689
|
+
if "commands" in result:
|
3690
|
+
commands = result["commands"]
|
3691
|
+
elif "setupInstructions" in result and "commands" in result["setupInstructions"]:
|
3692
|
+
commands = result["setupInstructions"]["commands"]
|
3693
|
+
|
3694
|
+
if commands:
|
3695
|
+
print(f"ā
Successfully fetched {len(commands)} setup commands from API at {api_url}")
|
3696
|
+
|
3697
|
+
# Print the commands
|
3698
|
+
print("\nš Setup Commands:")
|
3699
|
+
for i, cmd in enumerate(commands, 1):
|
3700
|
+
print(f" {i}. {cmd}")
|
3701
|
+
|
3702
|
+
# Fix the commands
|
3703
|
+
fixed_commands = fix_setup_commands(commands)
|
3704
|
+
|
3705
|
+
# Print the fixed commands
|
3706
|
+
print("\nš Fixed commands:")
|
3707
|
+
for i, cmd in enumerate(fixed_commands, 1):
|
3708
|
+
print(f" {i}. {cmd}")
|
3709
|
+
|
3710
|
+
return fixed_commands
|
3711
|
+
else:
|
3712
|
+
print("No commands found in API response")
|
3713
|
+
except json.JSONDecodeError:
|
3714
|
+
print(f"Failed to parse API response as JSON")
|
3715
|
+
except Exception as e:
|
3716
|
+
print(f"Error with API endpoint {api_url}: {e}")
|
3717
|
+
|
3718
|
+
print("ā All API endpoints failed")
|
3719
|
+
return generate_fallback_commands(gitingest_data)
|
3720
|
+
|
3302
3721
|
if __name__ == "__main__":
|
3303
3722
|
# Parse command line arguments when script is run directly
|
3304
3723
|
import argparse
|
@@ -3316,7 +3735,9 @@ if __name__ == "__main__":
|
|
3316
3735
|
parser.add_argument('--volume-name', type=str, help='Name of the Modal volume for persistent storage')
|
3317
3736
|
parser.add_argument('--timeout', type=int, default=60, help='Container timeout in minutes (default: 60)')
|
3318
3737
|
parser.add_argument('--ssh-password', type=str, help='SSH password (random if not provided)')
|
3319
|
-
parser.add_argument('--use-api', action='store_true', help='Fetch setup commands from API')
|
3738
|
+
parser.add_argument('--use-api', action='store_true', help='Fetch setup commands from original API')
|
3739
|
+
parser.add_argument('--use-gitingest', action='store_true', default=True, help='Use gitingest approach to fetch setup commands (default)')
|
3740
|
+
parser.add_argument('--no-gitingest', action='store_true', help='Disable gitingest approach for setup commands')
|
3320
3741
|
parser.add_argument('--show-examples', action='store_true', help='Show usage examples')
|
3321
3742
|
|
3322
3743
|
args = parser.parse_args()
|
@@ -3332,13 +3753,27 @@ if __name__ == "__main__":
|
|
3332
3753
|
|
3333
3754
|
# If --use-api flag is set and repo_url is provided, fetch setup commands from API
|
3334
3755
|
|
3756
|
+
# Use gitingest by default unless --no-gitingest is set
|
3757
|
+
if args.repo_url and (args.use_gitingest and not args.no_gitingest):
|
3758
|
+
print("š Using gitingest approach to fetch setup commands (default)")
|
3759
|
+
api_commands = get_setup_commands_from_gitingest(args.repo_url)
|
3760
|
+
if api_commands:
|
3761
|
+
setup_commands = api_commands
|
3762
|
+
print(f"š Using {len(setup_commands)} commands from gitingest API")
|
3763
|
+
else:
|
3764
|
+
print("ā ļø Failed to get commands from gitingest API")
|
3765
|
+
if not args.use_api:
|
3766
|
+
print("ā ļø Falling back to basic setup commands")
|
3767
|
+
setup_commands = generate_fallback_commands(None)
|
3768
|
+
else:
|
3769
|
+
setup_commands = []
|
3335
3770
|
# If --use-api flag is set and repo_url is provided, fetch setup commands from API
|
3336
|
-
|
3337
|
-
print("š Using API to fetch setup commands")
|
3771
|
+
elif args.use_api and args.repo_url:
|
3772
|
+
print("š Using original API to fetch setup commands")
|
3338
3773
|
api_commands = fetch_setup_commands_from_api(args.repo_url)
|
3339
3774
|
if api_commands:
|
3340
3775
|
setup_commands = api_commands
|
3341
|
-
print(f"š Using {len(setup_commands)} commands from API")
|
3776
|
+
print(f"š Using {len(setup_commands)} commands from original API")
|
3342
3777
|
else:
|
3343
3778
|
print("ā ļø Failed to get commands from API, no fallback commands will be used")
|
3344
3779
|
# Do not fall back to basic setup commands
|