File size: 4,145 Bytes
f0b7f76
 
 
0a5d37a
 
f0b7f76
 
 
 
 
 
 
0a5d37a
f0b7f76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8790563
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f0b7f76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0a5d37a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f0b7f76
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
import gradio as gr
import requests
import git
import os
import subprocess
import zipfile
import io
from getpass import getpass
import radon.complexity as radon_complexity
import pylint.lint
from pylint.reporters.text import TextReporter

# Function to download repo as a zip file from GitHub API
def download_repo(github_url):
    repo_name = github_url.split('/')[-1]
    repo_owner = github_url.split('/')[-2]
    api_url = f"https://github.com/{repo_owner}/{repo_name}/archive/refs/heads/main.zip"
    
    # Download the zip file
    response = requests.get(api_url)
    
    # Extract the zip file
    zip_file = zipfile.ZipFile(io.BytesIO(response.content))
    zip_file.extractall(f"/content/repos/{repo_name}")
    
    return f"/content/repos/{repo_name}"

# Function to fetch the GitHub repo using SSH or token for private repos
def fetch_repo(github_url, token=None):
    try:
        # Check if the repository is private or public
        if token:
            repo_name = github_url.split('/')[-1]
            repo_owner = github_url.split('/')[-2]
            clone_url = f"https://{token}@github.com/{repo_owner}/{repo_name}.git"
        else:
            repo_name = github_url.split('/')[-1]
            repo_owner = github_url.split('/')[-2]
            clone_url = f"git@github.com:{repo_owner}/{repo_name}.git"
        
        # Create a temporary directory to clone the repo
        temp_dir = f"/content/repos/{repo_name}"
        
        # Check if repo already exists
        if not os.path.exists(temp_dir):
            # If SSH method fails, fallback to downloading as a zip
            try:
                git.Repo.clone_from(clone_url, temp_dir)
            except Exception as e:
                return download_repo(github_url)
        
        return temp_dir
    except Exception as e:
        return f"Error: {str(e)}"

# Function to calculate cyclomatic complexity using Radon
def analyze_complexity(repo_path):
    result = subprocess.run(['radon', 'cc', repo_path, '--json'], stdout=subprocess.PIPE)
    complexity_data = result.stdout.decode('utf-8')
    return complexity_data

# Function to run pylint for linting
def analyze_linting(repo_path):
    pylint_output = []
    pylint_runner = pylint.lint.Run([repo_path], reporter=TextReporter(pylint_output))
    return "\n".join(pylint_output)

# Function to check test coverage
def analyze_coverage(repo_path):
    result = subprocess.run(['pytest', '--cov', repo_path], stdout=subprocess.PIPE)
    coverage_data = result.stdout.decode('utf-8')
    return coverage_data

# Function to check for code duplication with jscpd
def analyze_duplication(repo_path):
    result = subprocess.run(['jscpd', repo_path, '--reporters', 'text'], stdout=subprocess.PIPE)
    duplication_data = result.stdout.decode('utf-8')
    return duplication_data

# Main function to analyze the repository
def analyze_code(github_url, token=None):
    try:
        repo_path = fetch_repo(github_url, token)
        
        # Perform analysis
        complexity = analyze_complexity(repo_path)
        linting = analyze_linting(repo_path)
        coverage = analyze_coverage(repo_path)
        duplication = analyze_duplication(repo_path)
        
        # Combine results
        results = f"### Cyclomatic Complexity Analysis\n{complexity}\n\n"
        results += f"### Linting Results\n{linting}\n\n"
        results += f"### Test Coverage\n{coverage}\n\n"
        results += f"### Code Duplication\n{duplication}\n"
        
        return results
    except Exception as e:
        return f"Error: {str(e)}"

# Create Gradio Interface
def gradio_interface():
    gr.Interface(
        fn=analyze_code, 
        inputs=[
            gr.Textbox(label="GitHub Repository URL", placeholder="Enter the URL of the GitHub repo"),
            gr.Textbox(label="GitHub Token (Optional)", type="password")
        ], 
        outputs="text", 
        live=True, 
        title="GitHub Code Quality Analyzer", 
        description="Enter a GitHub repository URL to analyze its code quality (complexity, linting, coverage, duplication)."
    ).launch(share=True)

gradio_interface()