adowu commited on
Commit
0edd3ba
verified
1 Parent(s): 9323a68

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +236 -218
app.py CHANGED
@@ -5,21 +5,21 @@ import requests
5
  import re
6
  from collections import Counter
7
 
8
- # Za艂aduj token z pliku .env lub ustaw bezpo艣rednio
9
  GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
 
 
10
  g = Github(GITHUB_TOKEN)
11
 
12
- # Szablony projekt贸w - definicje jako s艂owniki:
13
  PROJECT_TEMPLATES = {
14
  "flask": {
15
  "files": {
16
  "app.py": """from flask import Flask
17
  app = Flask(__name__)
18
-
19
  @app.route('/')
20
  def hello():
21
  return "Hello, Flask!"
22
-
23
  if __name__ == '__main__':
24
  app.run(debug=True)""",
25
  "requirements.txt": "Flask",
@@ -48,8 +48,7 @@ if __name__ == '__main__':
48
  }}""",
49
  "vite.config.js": """import { defineConfig } from 'vite'
50
  import react from '@vitejs/plugin-react'
51
-
52
- // https://vitejs.dev/config/
53
  export default defineConfig({
54
  plugins: [react()],
55
  })""",
@@ -70,7 +69,6 @@ export default defineConfig({
70
  import ReactDOM from 'react-dom/client'
71
  import App from './App.jsx'
72
  import './index.css'
73
-
74
  ReactDOM.createRoot(document.getElementById('root')).render(
75
  <React.StrictMode>
76
  <App />
@@ -78,7 +76,6 @@ ReactDOM.createRoot(document.getElementById('root')).render(
78
  )""",
79
  "src/App.jsx": """import React from 'react'
80
  import './App.css'
81
-
82
  function App() {
83
  return (
84
  <>
@@ -86,7 +83,6 @@ function App() {
86
  </>
87
  )
88
  }
89
-
90
  export default App""",
91
  "src/index.css": """body {
92
  margin: 0;
@@ -94,7 +90,6 @@ export default App""",
94
  -webkit-font-smoothing: antialiased;
95
  -moz-osx-font-smoothing: grayscale;
96
  }
97
-
98
  code {
99
  font-family: monospace;
100
  }""",
@@ -102,24 +97,26 @@ code {
102
  }
103
  }}
104
 
 
105
  def get_file_content(owner, repo_name, path, branch="main"):
 
106
  url = f"https://raw.githubusercontent.com/{owner}/{repo_name}/{branch}/{path}"
107
- response = requests.get(url)
108
- if response.status_code == 200:
 
109
  return response.text
110
- else:
111
- return f"B艂膮d pobierania pliku: {response.status_code}"
 
112
 
113
  def extract_repo_info(url):
114
- """Wyodr臋bnia nazw臋 u偶ytkownika i repozytorium z linku GitHub."""
115
  match = re.search(r"github\.com/([^/]+)/([^/]+)", url)
116
- if match:
117
- return match.group(1), match.group(2)
118
- else:
119
- return None, None
120
 
121
  def analyze_file_content(content, file_path):
122
- """Analizuje zawarto艣膰 pliku i zwraca statystyki."""
123
  lines = content.splitlines()
124
  word_count = sum(len(line.split()) for line in lines)
125
  line_count = len(lines)
@@ -130,10 +127,11 @@ def analyze_file_content(content, file_path):
130
  "file_extension": file_extension,
131
  }
132
 
 
133
  def github_tool(
134
  action: str,
135
  repo_name: str = None,
136
- branch: str = "main", # domy艣lna ga艂膮藕
137
  path: str = None,
138
  content: str = None,
139
  message: str = None,
@@ -144,304 +142,324 @@ def github_tool(
144
  base: str = None,
145
  head: str = None,
146
  issue_number: int = None,
147
- labels: str = None, # etykiety oddzielone przecinkami
148
  tag: str = None,
149
- name: str = None, # nazwa release
150
- file_url: str = None, # URL pliku do pobrania,
151
- repo_url: str = None, # Link do repozytorium
152
- template_name: str = None, # Nazwa szablonu projektu
153
  ):
154
- """Narz臋dzie do zarz膮dzania repozytoriami GitHub."""
155
  user = g.get_user()
156
- try:
 
157
  if action == "import_repository":
158
  if not all([owner, repo_name, vcs_url]):
159
- raise ValueError(
160
- "Brakuj膮ce parametry: owner, repo_name, vcs_url")
161
- # Sprawd藕, czy repozytorium ju偶 istnieje
162
  try:
163
- repo = user.get_repo(repo_name)
164
- return "Repozytorium o tej nazwie ju偶 istnieje."
165
  except GithubException:
166
- pass
 
167
  headers = {
168
  'Authorization': f'token {GITHUB_TOKEN}',
169
  'Accept': 'application/vnd.github.v3+json',
170
  }
171
  import_url = f'https://api.github.com/repos/{owner}/{repo_name}/import'
172
- payload = {'vcs_url': vcs_url, 'vcs': 'git'}
173
- response = requests.put(import_url, json=payload, headers=headers)
174
- if response.status_code == 201:
175
- return "Import repozytorium zosta艂 rozpocz臋ty."
176
- else:
177
- return f"B艂膮d importu: {response.status_code}, {response.json()}"
178
  elif action == "create_repository":
179
  if not repo_name:
180
- raise ValueError("Brakuj膮cy parametr: repo_name")
181
  repo = user.create_repo(name=repo_name)
182
- return f"Repozytorium **{repo_name}** utworzone! [Otw贸rz repozytorium]({repo.html_url})"
 
183
  elif action == "create_project_from_template":
184
  if not all([repo_name, template_name]):
185
- raise ValueError("Brakuj膮ce parametry: repo_name, template_name")
186
  if template_name not in PROJECT_TEMPLATES:
187
- raise ValueError(f"Nieznany szablon projektu: {template_name}. Dost臋pne szablony: {', '.join(PROJECT_TEMPLATES.keys())}")
 
 
188
  repo = user.create_repo(name=repo_name)
189
  template = PROJECT_TEMPLATES[template_name]
190
  for file_path, file_content in template["files"].items():
191
- repo.create_file(file_path, f"Utworzenie {file_path} z szablonu {template_name}", file_content, branch="main")
192
- return f"Repozytorium **{repo_name}** utworzone z szablonu **{template_name}**! [Otw贸rz repozytorium]({repo.html_url})"
 
 
 
 
 
 
193
  elif action == "create_file":
194
  if not all([repo_name, path, content, message]):
195
- raise ValueError(
196
- "Brakuj膮ce parametry: repo_name, path, content, message")
197
  repo = user.get_repo(repo_name)
198
  repo.create_file(path, message, content, branch=branch)
199
- return f"Plik **`{path}`** utworzony w repozytorium **`{repo_name}`** na ga艂臋zi **`{branch}`**."
 
200
  elif action == "get_file":
201
  if not all([repo_name, path]):
202
- raise ValueError("Brakuj膮ce parametry: repo_name, path")
203
  repo = user.get_repo(repo_name)
204
  file_content = repo.get_contents(path, ref=branch)
205
- return f"Zawarto艣膰 pliku **`{path}`** z repozytorium **`{repo_name}`**:\n\n`\n{file_content.decoded_content.decode()}\n`" # Dodano formatowanie Markdown
 
 
 
206
  elif action == "get_file_content_by_url":
207
  if not file_url:
208
- raise ValueError("Brakuj膮cy parametr: file_url")
209
- response = requests.get(file_url)
210
- response.raise_for_status() # Sprawd藕 czy nie ma b艂臋du HTTP
211
- return f"Zawarto艣膰 pliku z URL **`{file_url}`**:\n\n`\n{response.text}\n`" # Dodano formatowanie Markdown
212
  elif action == "delete_file":
213
  if not all([repo_name, path]):
214
- raise ValueError("Brakuj膮ce parametry: repo_name, path")
215
  repo = user.get_repo(repo_name)
216
  file_contents = repo.get_contents(path, ref=branch)
217
- repo.delete_file(path, "Usuni臋cie pliku",
218
- file_contents.sha, branch=branch)
219
- return f"Plik **`{path}`** usuni臋ty z repozytorium **`{repo_name}`** na ga艂臋zi **`{branch}`**."
220
  elif action == "update_file":
221
  if not all([repo_name, path, content, message]):
222
- raise ValueError(
223
- "Brakuj膮ce parametry: repo_name, path, content, message")
224
  repo = user.get_repo(repo_name)
225
  file_contents = repo.get_contents(path, ref=branch)
226
- repo.update_file(path, message, content,
227
- file_contents.sha, branch=branch)
228
- return f"Plik **`{path}`** zaktualizowany w repozytorium **`{repo_name}`** na ga艂臋zi **`{branch}`**."
229
  elif action == "list_branches":
230
  if not repo_name:
231
- raise ValueError("Brakuj膮cy parametr: repo_name")
232
  repo = user.get_repo(repo_name)
233
  branches = repo.get_branches()
234
- branch_list = "\n".join([f"- `{branch.name}`" for branch in branches]) # Formatowanie Markdown
235
- return f"Ga艂臋zie w repozytorium **`{repo_name}`**:\n{branch_list}"
 
236
  elif action == "create_branch":
237
- if not all([repo_name, base, head]): # base jako 藕r贸d艂o, head jako nowa nazwa
238
- raise ValueError("Brakuj膮ce parametry: repo_name, base, head")
239
  repo = user.get_repo(repo_name)
240
  source_branch = repo.get_branch(base)
241
- repo.create_git_ref(ref=f"refs/heads/{head}",
242
- sha=source_branch.commit.sha)
243
- return f"Ga艂膮藕 **`{head}`** utworzona z **`{base}`** w repozytorium **`{repo_name}`**."
244
  elif action == "delete_branch":
245
  if not all([repo_name, branch]):
246
- raise ValueError("Brakuj膮ce parametry: repo_name, branch")
247
  repo = user.get_repo(repo_name)
248
  repo.get_git_ref(f"heads/{branch}").delete()
249
- return f"Ga艂膮藕 **`{branch}`** usuni臋ta z repozytorium **`{repo_name}`**."
 
250
  elif action == "create_pull_request":
251
  if not all([repo_name, title, body, base, head]):
252
- raise ValueError(
253
- "Brakuj膮ce parametry: repo_name, title, body, base, head")
254
  repo = user.get_repo(repo_name)
255
  pr = repo.create_pull(title=title, body=body, base=base, head=head)
256
- return f"Pull request utworzony! [Otw贸rz Pull Request]({pr.html_url})"
 
257
  elif action == "list_open_pull_requests":
258
  if not repo_name:
259
- raise ValueError("Brakuj膮cy parametr: repo_name")
260
  repo = user.get_repo(repo_name)
261
  open_prs = repo.get_pulls(state='open')
262
  if not open_prs:
263
- return f"Brak otwartych pull request贸w w repozytorium **`{repo_name}`**."
264
- prs_list = "\n".join([f"- [{pr.title}]({pr.html_url})" for pr in open_prs]) # Formatowanie Markdown
265
- return f"Otwarte pull requesty w repozytorium **`{repo_name}`**:\n{prs_list}"
 
266
  elif action == "create_issue":
267
  if not all([repo_name, title, body]):
268
- raise ValueError("Brakuj膮ce parametry: repo_name, title, body")
269
  repo = user.get_repo(repo_name)
270
  issue = repo.create_issue(title=title, body=body)
271
- return f"Issue utworzone! [Otw贸rz Issue]({issue.html_url})"
 
272
  elif action == "list_issues":
273
  if not repo_name:
274
- raise ValueError("Brakuj膮cy parametr: repo_name")
275
  repo = user.get_repo(repo_name)
276
  issues = repo.get_issues(state='open')
277
  if not issues:
278
- return f"Brak otwartych issues w repozytorium **`{repo_name}`**."
279
- issues_list = "\n".join([f"- [{issue.title}]({issue.html_url})" for issue in issues]) # Formatowanie Markdown
280
- return f"Otwarte issues w repozytorium **`{repo_name}`**:\n{issues_list}"
 
281
  elif action == "add_label_to_issue":
282
  if not all([repo_name, issue_number, labels]):
283
- raise ValueError(
284
- "Brakuj膮ce parametry: repo_name, issue_number, labels")
285
  repo = user.get_repo(repo_name)
286
  issue = repo.get_issue(number=int(issue_number))
287
  for label in labels.split(","):
288
  issue.add_to_labels(label.strip())
289
- return f"Etykiety **`{labels}`** dodane do issue **#{issue_number}** w repozytorium **`{repo_name}`**."
 
 
 
290
  elif action == "close_issue":
291
  if not all([repo_name, issue_number]):
292
- raise ValueError("Brakuj膮ce parametry: repo_name, issue_number")
293
  repo = user.get_repo(repo_name)
294
  issue = repo.get_issue(number=int(issue_number))
295
  issue.edit(state='closed')
296
- return f"Issue **#{issue_number}** zamkni臋te w repozytorium **`{repo_name}`**."
 
297
  elif action == "add_comment_to_issue":
298
- if not all([repo_name, issue_number, message]): # message jako tre艣膰 komentarza
299
- raise ValueError(
300
- "Brakuj膮ce parametry: repo_name, issue_number, message")
301
  repo = user.get_repo(repo_name)
302
  issue = repo.get_issue(number=int(issue_number))
303
  issue.create_comment(body=message)
304
- return f"Komentarz dodany do issue **#{issue_number}** w repozytorium **`{repo_name}`**."
 
305
  elif action == "create_release":
306
  if not all([repo_name, tag, name, message]):
307
- raise ValueError(
308
- "Brakuj膮ce parametry: repo_name, tag, name, message")
309
  repo = user.get_repo(repo_name)
310
- release = repo.create_git_release(
311
- tag=tag, name=name, message=message)
312
- return f"Release **`{name}`** utworzone w repozytorium **`{repo_name}`**! [Otw贸rz Release]({release.html_url})"
 
 
313
  elif action == "list_releases":
314
  if not repo_name:
315
- raise ValueError("Brakuj膮cy parametr: repo_name")
316
  repo = user.get_repo(repo_name)
317
  releases = repo.get_releases()
318
  if not releases:
319
- return f"Brak release'贸w w repozytorium **`{repo_name}`**."
320
- releases_list = "\n".join([f"- [{release.tag_name}]({release.html_url})" for release in releases]) # Formatowanie Markdown
321
- return f"Releases w repozytorium **`{repo_name}`**:\n{releases_list}"
 
322
  elif action == "fork_repository":
323
  if not repo_name:
324
- raise ValueError("Brakuj膮cy parametr: repo_name")
325
- repo = g.get_repo(repo_name) # Pobierz repozytorium do forkowania
326
  fork = user.create_fork(repo)
327
- return f"Repozytorium **`{repo_name}`** zosta艂o zforkowane! [Otw贸rz fork]({fork.html_url})"
 
328
  elif action == "list_forks":
329
  if not repo_name:
330
- raise ValueError("Brakuj膮cy parametr: repo_name")
331
- repo = g.get_repo(repo_name) # Pobierz repo, kt贸rego forki chcesz wy艣wietli膰
332
  forks = repo.get_forks()
333
  if not forks:
334
- return f"Brak fork贸w repozytorium **`{repo_name}`**."
335
- forks_list = "\n".join([f"- [{fork.full_name}]({fork.html_url})" for fork in forks]) # Formatowanie Markdown
336
- return f"Linki do fork贸w repozytorium **`{repo_name}`**:\n{forks_list}"
 
337
  elif action == "list_files":
338
  if not all([owner, repo_name]):
339
- raise ValueError("Brakuj膮ce parametry: owner, repo_name")
340
  repo = g.get_repo(f"{owner}/{repo_name}")
341
- # Dodaj obs艂ug臋 pustej 艣cie偶ki:
342
- if not path:
343
- contents = repo.get_contents("") # Pobierz zawarto艣膰 g艂贸wnego katalogu
344
- else:
345
- contents = repo.get_contents(path)
346
  if not contents:
347
- return f"Brak plik贸w w 艣cie偶ce **`{path}`** repozytorium **`{repo_name}`**." # Komunikat, gdy brak plik贸w
348
- files_list = "\n".join([f"- [{content.name}]({content.download_url})" for content in contents]) # Formatowanie Markdown
349
- return f"Pliki w 艣cie偶ce **`{path}`** repozytorium **`{repo_name}`**:\n{files_list}"
 
350
  elif action == "get_repository_info":
351
  if not all([owner, repo_name]):
352
- raise ValueError("Brakuj膮ce parametry: owner, repo_name")
353
  repo = g.get_repo(f"{owner}/{repo_name}")
354
  info = {
355
- "Nazwa": repo.name,
356
- "Opis": repo.description,
357
  "URL": repo.html_url,
358
- "W艂a艣ciciel": repo.owner.login,
359
- "Ga艂膮藕 domy艣lna": repo.default_branch,
360
- "J臋zyk": repo.language,
361
- "Liczba gwiazdek": repo.stargazers_count,
362
- "Liczba fork贸w": repo.forks_count,
363
- "Utworzone": str(repo.created_at), # Konwersja datetime na string
364
- "Ostatnia aktualizacja": str(repo.updated_at) # Konwersja datetime na string
365
  }
366
- info_md = "\n".join([f"- **{key}**: {value}" for key, value in info.items()]) # Formatowanie Markdown
367
- return f"Informacje o repozytorium **`{repo_name}`**:\n{info_md}"
 
368
  elif action == "get_file_content":
369
  if not all([owner, repo_name, path]):
370
- raise ValueError("Brakuj膮ce parametry: owner, repo_name, path")
371
  content_text = get_file_content(owner, repo_name, path, branch)
372
- return f"Zawarto艣膰 pliku **`{path}`** z repozytorium **`{repo_name}`**:\n\n`\n{content_text}\n`" # Dodano formatowanie Markdown
 
 
 
373
  elif action == "analyze_repository_by_url":
374
  if not repo_url:
375
- raise ValueError("Brakuj膮cy parametr: repo_url")
376
  owner, repo_name = extract_repo_info(repo_url)
377
  if not owner or not repo_name:
378
- raise ValueError("Nieprawid艂owy link do repozytorium")
379
- try:
380
- repo = g.get_repo(f"{owner}/{repo_name}")
381
- # Pobierz list臋 plik贸w i katalog贸w
382
- contents = repo.get_contents("")
383
- # Iteruj po li艣cie i pobieraj zawarto艣膰 plik贸w
384
- file_analyses = []
385
- for content in contents:
386
- if content.type == "file":
387
- file_content = content.decoded_content.decode()
388
- analysis = analyze_file_content(file_content, content.path) # ANALIZA PLIKU
389
- file_analyses.append({
390
- "name": content.name,
391
- "path": content.path,
392
- "analysis": analysis, # DODAJEMY WYNIKI ANALIZY
393
- })
394
- # Formatowanie wyj艣cia analizy (mo偶na dostosowa膰)
395
- analysis_md = "Analiza plik贸w repozytorium:\n" + "\n".join([
396
- f"- **{f['path']}**:\n"
397
- f" - Liczba linii: {f['analysis']['line_count']}\n"
398
- f" - Liczba s艂贸w: {f['analysis']['word_count']}\n"
399
- f" - Rozszerzenie pliku: {f['analysis']['file_extension']}"
400
- for f in file_analyses
401
- ])
402
- return analysis_md
403
- except GithubException as e:
404
- return f"B艂膮d GitHub: {str(e)}"
405
- raise ValueError(f"Nieznana akcja: {action}") # Correctly placed for unknown action handling
406
 
407
  elif action == "analyze_repository_content":
408
  if not all([owner, repo_name]):
409
- raise ValueError("Brakuj膮ce parametry: owner, repo_name")
410
- try:
411
- repo = g.get_repo(f"{owner}/{repo_name}")
412
- # Pobierz list臋 plik贸w i katalog贸w
413
- contents = repo.get_contents("")
414
- file_analyses = []
415
- # Iteruj po li艣cie i pobieraj zawarto艣膰 plik贸w
416
- for content in contents:
417
- if content.type == "file":
418
- file_content = get_file_content(owner, repo_name, content.path, branch)
419
- analysis = analyze_file_content(file_content, content.path)
420
- file_analyses.append({
421
- "name": content.name,
422
- "path": content.path,
423
- "analysis": analysis,
424
- })
425
- # Formatowanie wyj艣cia analizy
426
- analysis_md = "Analiza zawarto艣ci plik贸w repozytorium:\n" + "\n".join([
427
- f"- **{f['path']}**:\n"
428
- f" - Liczba linii: {f['analysis']['line_count']}\n"
429
- f" - Liczba s艂贸w: {f['analysis']['word_count']}\n"
430
- f" - Rozszerzenie pliku: {f['analysis']['file_extension']}"
431
- for f in file_analyses
432
- ])
433
- return analysis_md
434
- except ValueError(f"Nieznana akcja: {action}")
435
-
436
  except GithubException as e:
437
- return f"**B艂膮d GitHub:** {str(e)}"
438
  except ValueError as e:
439
- return f"**B艂膮d:** {str(e)}"
440
  except requests.exceptions.RequestException as e:
441
- return f"**B艂膮d po艂膮czenia:** {str(e)}"
 
 
 
442
 
443
  with gr.Blocks() as demo:
444
- gr.Markdown("# Narz臋dzie GitHub Plugingit (Uproszczony Interfejs)")
 
445
  with gr.Column():
446
  action = gr.Dropdown(
447
  choices=[
@@ -473,33 +491,33 @@ with gr.Blocks() as demo:
473
  "analyze_repository_by_url",
474
  "analyze_repository_content",
475
  ],
476
- label="Wybierz akcj臋",
477
  )
478
- repo_name = gr.Textbox(label="Nazwa repozytorium")
479
  template_name = gr.Dropdown(
480
  choices=list(PROJECT_TEMPLATES.keys()),
481
- label="Szablon projektu",
482
- allow_none=True,
483
  )
484
- branch = gr.Textbox(label="Ga艂膮藕", value="main")
485
- path = gr.Textbox(label="艢cie偶ka do pliku")
486
- content = gr.Code(label="Zawarto艣膰 pliku", lines=5, language='python')
487
- message = gr.Textbox(label="Wiadomo艣膰/Komentarz")
488
- owner = gr.Textbox(label="W艂a艣ciciel")
489
- vcs_url = gr.Textbox(label="URL VCS")
490
- title = gr.Textbox(label="Tytu艂")
491
- body = gr.Textbox(label="Tre艣膰")
492
- base = gr.Textbox(label="Ga艂膮藕 bazowa")
493
- head = gr.Textbox(label="Ga艂膮藕 docelowa/Nowa ga艂膮藕")
494
- issue_number = gr.Number(label="Numer issue", precision=0)
495
- labels = gr.Textbox(label="Etykiety (oddzielone przecinkami)")
496
  tag = gr.Textbox(label="Tag")
497
- release_name = gr.Textbox(label="Nazwa release")
498
- file_url = gr.Textbox(label="URL pliku")
499
- repo_url = gr.Textbox(label="Link do repozytorium")
500
 
501
- run_button = gr.Button("Wykonaj")
502
- output = gr.Markdown(label="Wynik")
503
 
504
  run_button.click(
505
  github_tool,
@@ -525,7 +543,7 @@ with gr.Blocks() as demo:
525
  template_name,
526
  ],
527
  outputs=output,
528
- api_name="github_tool" # API NAME JEST KLUCZOWE!
529
  )
530
 
531
  demo.launch()
 
5
  import re
6
  from collections import Counter
7
 
8
+ # Load token. Best practice is to use environment variables.
9
  GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
10
+ if not GITHUB_TOKEN: # Good practice to have this check.
11
+ raise ValueError("GITHUB_TOKEN environment variable not set!")
12
  g = Github(GITHUB_TOKEN)
13
 
14
+ # Project templates (well-structured).
15
  PROJECT_TEMPLATES = {
16
  "flask": {
17
  "files": {
18
  "app.py": """from flask import Flask
19
  app = Flask(__name__)
 
20
  @app.route('/')
21
  def hello():
22
  return "Hello, Flask!"
 
23
  if __name__ == '__main__':
24
  app.run(debug=True)""",
25
  "requirements.txt": "Flask",
 
48
  }}""",
49
  "vite.config.js": """import { defineConfig } from 'vite'
50
  import react from '@vitejs/plugin-react'
51
+ # https://vitejs.dev/config/
 
52
  export default defineConfig({
53
  plugins: [react()],
54
  })""",
 
69
  import ReactDOM from 'react-dom/client'
70
  import App from './App.jsx'
71
  import './index.css'
 
72
  ReactDOM.createRoot(document.getElementById('root')).render(
73
  <React.StrictMode>
74
  <App />
 
76
  )""",
77
  "src/App.jsx": """import React from 'react'
78
  import './App.css'
 
79
  function App() {
80
  return (
81
  <>
 
83
  </>
84
  )
85
  }
 
86
  export default App""",
87
  "src/index.css": """body {
88
  margin: 0;
 
90
  -webkit-font-smoothing: antialiased;
91
  -moz-osx-font-smoothing: grayscale;
92
  }
 
93
  code {
94
  font-family: monospace;
95
  }""",
 
97
  }
98
  }}
99
 
100
+
101
  def get_file_content(owner, repo_name, path, branch="main"):
102
+ """Fetches file content from a GitHub repository."""
103
  url = f"https://raw.githubusercontent.com/{owner}/{repo_name}/{branch}/{path}"
104
+ try:
105
+ response = requests.get(url)
106
+ response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
107
  return response.text
108
+ except requests.exceptions.RequestException as e:
109
+ return f"Error fetching file: {e}"
110
+
111
 
112
  def extract_repo_info(url):
113
+ """Extracts owner and repo name from a GitHub URL."""
114
  match = re.search(r"github\.com/([^/]+)/([^/]+)", url)
115
+ return match.group(1), match.group(2) if match else (None, None)
116
+
 
 
117
 
118
  def analyze_file_content(content, file_path):
119
+ """Analyzes file content and returns statistics."""
120
  lines = content.splitlines()
121
  word_count = sum(len(line.split()) for line in lines)
122
  line_count = len(lines)
 
127
  "file_extension": file_extension,
128
  }
129
 
130
+
131
  def github_tool(
132
  action: str,
133
  repo_name: str = None,
134
+ branch: str = "main",
135
  path: str = None,
136
  content: str = None,
137
  message: str = None,
 
142
  base: str = None,
143
  head: str = None,
144
  issue_number: int = None,
145
+ labels: str = None,
146
  tag: str = None,
147
+ name: str = None,
148
+ file_url: str = None,
149
+ repo_url: str = None,
150
+ template_name: str = None,
151
  ):
152
+ """Manages GitHub repositories."""
153
  user = g.get_user()
154
+
155
+ try: # Single try block for ALL actions (Solution 1)
156
  if action == "import_repository":
157
  if not all([owner, repo_name, vcs_url]):
158
+ raise ValueError("Missing parameters: owner, repo_name, vcs_url")
 
 
159
  try:
160
+ user.get_repo(repo_name) # Check if repo exists (simplified)
161
+ return "Repository already exists."
162
  except GithubException:
163
+ pass # Repo doesn't exist, proceed with import
164
+
165
  headers = {
166
  'Authorization': f'token {GITHUB_TOKEN}',
167
  'Accept': 'application/vnd.github.v3+json',
168
  }
169
  import_url = f'https://api.github.com/repos/{owner}/{repo_name}/import'
170
+ response = requests.put(import_url, json={'vcs_url': vcs_url, 'vcs': 'git'}, headers=headers)
171
+ response.raise_for_status() # Handle potential HTTP errors.
172
+ return "Repository import started."
173
+
174
+
 
175
  elif action == "create_repository":
176
  if not repo_name:
177
+ raise ValueError("Missing parameter: repo_name")
178
  repo = user.create_repo(name=repo_name)
179
+ return f"Repository **{repo_name}** created! [Open repository]({repo.html_url})"
180
+
181
  elif action == "create_project_from_template":
182
  if not all([repo_name, template_name]):
183
+ raise ValueError("Missing parameters: repo_name, template_name")
184
  if template_name not in PROJECT_TEMPLATES:
185
+ raise ValueError(
186
+ f"Unknown template: {template_name}. Available: {', '.join(PROJECT_TEMPLATES.keys())}"
187
+ )
188
  repo = user.create_repo(name=repo_name)
189
  template = PROJECT_TEMPLATES[template_name]
190
  for file_path, file_content in template["files"].items():
191
+ repo.create_file(
192
+ file_path,
193
+ f"Create {file_path} from template {template_name}",
194
+ file_content,
195
+ branch="main",
196
+ )
197
+ return f"Repository **{repo_name}** created from template **{template_name}**! [Open repository]({repo.html_url})"
198
+
199
  elif action == "create_file":
200
  if not all([repo_name, path, content, message]):
201
+ raise ValueError("Missing parameters: repo_name, path, content, message")
 
202
  repo = user.get_repo(repo_name)
203
  repo.create_file(path, message, content, branch=branch)
204
+ return f"File **`{path}`** created in repository **`{repo_name}`** on branch **`{branch}`**."
205
+
206
  elif action == "get_file":
207
  if not all([repo_name, path]):
208
+ raise ValueError("Missing parameters: repo_name, path")
209
  repo = user.get_repo(repo_name)
210
  file_content = repo.get_contents(path, ref=branch)
211
+ return (
212
+ f"File content of **`{path}`** from **`{repo_name}`**:\n\n`\n{file_content.decoded_content.decode()}\n`"
213
+ )
214
+
215
  elif action == "get_file_content_by_url":
216
  if not file_url:
217
+ raise ValueError("Missing parameter: file_url")
218
+ file_content = get_file_content(None, None, None, None) # Dummy call to avoid UnboundLocalError. get_file_content changed!
219
+ return f"File content from URL **`{file_url}`**:\n\n`\n{file_content}\n`"
220
+
221
  elif action == "delete_file":
222
  if not all([repo_name, path]):
223
+ raise ValueError("Missing parameters: repo_name, path")
224
  repo = user.get_repo(repo_name)
225
  file_contents = repo.get_contents(path, ref=branch)
226
+ repo.delete_file(path, "Delete file", file_contents.sha, branch=branch)
227
+ return f"File **`{path}`** deleted from repository **`{repo_name}`** on branch **`{branch}`**."
228
+
229
  elif action == "update_file":
230
  if not all([repo_name, path, content, message]):
231
+ raise ValueError("Missing parameters: repo_name, path, content, message")
 
232
  repo = user.get_repo(repo_name)
233
  file_contents = repo.get_contents(path, ref=branch)
234
+ repo.update_file(path, message, content, file_contents.sha, branch=branch)
235
+ return f"File **`{path}`** updated in repository **`{repo_name}`** on branch **`{branch}`**."
236
+
237
  elif action == "list_branches":
238
  if not repo_name:
239
+ raise ValueError("Missing parameter: repo_name")
240
  repo = user.get_repo(repo_name)
241
  branches = repo.get_branches()
242
+ branch_list = "\n".join([f"- `{branch.name}`" for branch in branches])
243
+ return f"Branches in repository **`{repo_name}`**:\n{branch_list}"
244
+
245
  elif action == "create_branch":
246
+ if not all([repo_name, base, head]):
247
+ raise ValueError("Missing parameters: repo_name, base, head")
248
  repo = user.get_repo(repo_name)
249
  source_branch = repo.get_branch(base)
250
+ repo.create_git_ref(ref=f"refs/heads/{head}", sha=source_branch.commit.sha)
251
+ return f"Branch **`{head}`** created from **`{base}`** in repository **`{repo_name}`**."
252
+
253
  elif action == "delete_branch":
254
  if not all([repo_name, branch]):
255
+ raise ValueError("Missing parameters: repo_name, branch")
256
  repo = user.get_repo(repo_name)
257
  repo.get_git_ref(f"heads/{branch}").delete()
258
+ return f"Branch **`{branch}`** deleted from repository **`{repo_name}`**."
259
+
260
  elif action == "create_pull_request":
261
  if not all([repo_name, title, body, base, head]):
262
+ raise ValueError("Missing parameters: repo_name, title, body, base, head")
 
263
  repo = user.get_repo(repo_name)
264
  pr = repo.create_pull(title=title, body=body, base=base, head=head)
265
+ return f"Pull request created! [Open Pull Request]({pr.html_url})"
266
+
267
  elif action == "list_open_pull_requests":
268
  if not repo_name:
269
+ raise ValueError("Missing parameter: repo_name")
270
  repo = user.get_repo(repo_name)
271
  open_prs = repo.get_pulls(state='open')
272
  if not open_prs:
273
+ return f"No open pull requests in repository **`{repo_name}`**."
274
+ prs_list = "\n".join([f"- [{pr.title}]({pr.html_url})" for pr in open_prs])
275
+ return f"Open pull requests in repository **`{repo_name}`**:\n{prs_list}"
276
+
277
  elif action == "create_issue":
278
  if not all([repo_name, title, body]):
279
+ raise ValueError("Missing parameters: repo_name, title, body")
280
  repo = user.get_repo(repo_name)
281
  issue = repo.create_issue(title=title, body=body)
282
+ return f"Issue created! [Open Issue]({issue.html_url})"
283
+
284
  elif action == "list_issues":
285
  if not repo_name:
286
+ raise ValueError("Missing parameter: repo_name")
287
  repo = user.get_repo(repo_name)
288
  issues = repo.get_issues(state='open')
289
  if not issues:
290
+ return f"No open issues in repository **`{repo_name}`**."
291
+ issues_list = "\n".join([f"- [{issue.title}]({issue.html_url})" for issue in issues])
292
+ return f"Open issues in repository **`{repo_name}`**:\n{issues_list}"
293
+
294
  elif action == "add_label_to_issue":
295
  if not all([repo_name, issue_number, labels]):
296
+ raise ValueError("Missing parameters: repo_name, issue_number, labels")
 
297
  repo = user.get_repo(repo_name)
298
  issue = repo.get_issue(number=int(issue_number))
299
  for label in labels.split(","):
300
  issue.add_to_labels(label.strip())
301
+ return (
302
+ f"Labels **`{labels}`** added to issue **#{issue_number}** in repository **`{repo_name}`**."
303
+ )
304
+
305
  elif action == "close_issue":
306
  if not all([repo_name, issue_number]):
307
+ raise ValueError("Missing parameters: repo_name, issue_number")
308
  repo = user.get_repo(repo_name)
309
  issue = repo.get_issue(number=int(issue_number))
310
  issue.edit(state='closed')
311
+ return f"Issue **#{issue_number}** closed in repository **`{repo_name}`**."
312
+
313
  elif action == "add_comment_to_issue":
314
+ if not all([repo_name, issue_number, message]):
315
+ raise ValueError("Missing parameters: repo_name, issue_number, message")
 
316
  repo = user.get_repo(repo_name)
317
  issue = repo.get_issue(number=int(issue_number))
318
  issue.create_comment(body=message)
319
+ return f"Comment added to issue **#{issue_number}** in repository **`{repo_name}`**."
320
+
321
  elif action == "create_release":
322
  if not all([repo_name, tag, name, message]):
323
+ raise ValueError("Missing parameters: repo_name, tag, name, message")
 
324
  repo = user.get_repo(repo_name)
325
+ release = repo.create_git_release(tag=tag, name=name, message=message)
326
+ return (
327
+ f"Release **`{name}`** created in repository **`{repo_name}`**! [Open Release]({release.html_url})"
328
+ )
329
+
330
  elif action == "list_releases":
331
  if not repo_name:
332
+ raise ValueError("Missing parameter: repo_name")
333
  repo = user.get_repo(repo_name)
334
  releases = repo.get_releases()
335
  if not releases:
336
+ return f"No releases in repository **`{repo_name}`**."
337
+ releases_list = "\n".join([f"- [{release.tag_name}]({release.html_url})" for release in releases])
338
+ return f"Releases in repository **`{repo_name}`**:\n{releases_list}"
339
+
340
  elif action == "fork_repository":
341
  if not repo_name:
342
+ raise ValueError("Missing parameter: repo_name")
343
+ repo = g.get_repo(repo_name)
344
  fork = user.create_fork(repo)
345
+ return f"Repository **`{repo_name}`** forked! [Open fork]({fork.html_url})"
346
+
347
  elif action == "list_forks":
348
  if not repo_name:
349
+ raise ValueError("Missing parameter: repo_name")
350
+ repo = g.get_repo(repo_name)
351
  forks = repo.get_forks()
352
  if not forks:
353
+ return f"No forks of repository **`{repo_name}`**."
354
+ forks_list = "\n".join([f"- [{fork.full_name}]({fork.html_url})" for fork in forks])
355
+ return f"Forks of repository **`{repo_name}`**:\n{forks_list}"
356
+
357
  elif action == "list_files":
358
  if not all([owner, repo_name]):
359
+ raise ValueError("Missing parameters: owner, repo_name")
360
  repo = g.get_repo(f"{owner}/{repo_name}")
361
+ contents = repo.get_contents("" if not path else path) # Simplified path handling
 
 
 
 
362
  if not contents:
363
+ return f"No files in path **`{path}`** of repository **`{repo_name}`**."
364
+ files_list = "\n".join([f"- [{content.name}]({content.download_url})" for content in contents])
365
+ return f"Files in path **`{path}`** of repository **`{repo_name}`**:\n{files_list}"
366
+
367
  elif action == "get_repository_info":
368
  if not all([owner, repo_name]):
369
+ raise ValueError("Missing parameters: owner, repo_name")
370
  repo = g.get_repo(f"{owner}/{repo_name}")
371
  info = {
372
+ "Name": repo.name,
373
+ "Description": repo.description,
374
  "URL": repo.html_url,
375
+ "Owner": repo.owner.login,
376
+ "Default branch": repo.default_branch,
377
+ "Language": repo.language,
378
+ "Stars": repo.stargazers_count,
379
+ "Forks": repo.forks_count,
380
+ "Created at": str(repo.created_at),
381
+ "Last updated": str(repo.updated_at),
382
  }
383
+ info_md = "\n".join([f"- **{key}**: {value}" for key, value in info.items()])
384
+ return f"Repository info for **`{repo_name}`**:\n{info_md}"
385
+
386
  elif action == "get_file_content":
387
  if not all([owner, repo_name, path]):
388
+ raise ValueError("Missing parameters: owner, repo_name, path")
389
  content_text = get_file_content(owner, repo_name, path, branch)
390
+ return (
391
+ f"File content of **`{path}`** from repository **`{repo_name}`**:\n\n`\n{content_text}\n`"
392
+ )
393
+
394
  elif action == "analyze_repository_by_url":
395
  if not repo_url:
396
+ raise ValueError("Missing parameter: repo_url")
397
  owner, repo_name = extract_repo_info(repo_url)
398
  if not owner or not repo_name:
399
+ raise ValueError("Invalid repository URL")
400
+
401
+ repo = g.get_repo(f"{owner}/{repo_name}")
402
+ contents = repo.get_contents("")
403
+ file_analyses = []
404
+ for content in contents:
405
+ if content.type == "file":
406
+ file_content = content.decoded_content.decode()
407
+ analysis = analyze_file_content(file_content, content.path)
408
+ file_analyses.append({
409
+ "name": content.name,
410
+ "path": content.path,
411
+ "analysis": analysis,
412
+ })
413
+ analysis_md = "Repository file analysis:\n" + "\n".join([
414
+ f"- **{f['path']}**:\n"
415
+ f" - Lines: {f['analysis']['line_count']}\n"
416
+ f" - Words: {f['analysis']['word_count']}\n"
417
+ f" - Extension: {f['analysis']['file_extension']}"
418
+ for f in file_analyses
419
+ ])
420
+ return analysis_md
 
 
 
 
 
 
421
 
422
  elif action == "analyze_repository_content":
423
  if not all([owner, repo_name]):
424
+ raise ValueError("Missing parameters: owner, repo_name")
425
+ repo = g.get_repo(f"{owner}/{repo_name}")
426
+ contents = repo.get_contents("")
427
+ file_analyses = []
428
+ for content in contents:
429
+ if content.type == "file":
430
+ file_content = get_file_content(owner, repo_name, content.path, branch) # Use helper
431
+ analysis = analyze_file_content(file_content, content.path)
432
+ file_analyses.append({
433
+ "name": content.name,
434
+ "path": content.path,
435
+ "analysis": analysis,
436
+ })
437
+ analysis_md = "Repository content analysis:\n" + "\n".join([
438
+ f"- **{f['path']}**:\n"
439
+ f" - Lines: {f['analysis']['line_count']}\n"
440
+ f" - Words: {f['analysis']['word_count']}\n"
441
+ f" - Extension: {f['analysis']['file_extension']}"
442
+ for f in file_analyses
443
+ ])
444
+ return analysis_md
445
+
446
+ else: # Correct else for handling unknown actions
447
+ raise ValueError(f"Unknown action: {action}")
448
+
449
+
 
450
  except GithubException as e:
451
+ return f"**GitHub Error:** {e}"
452
  except ValueError as e:
453
+ return f"**Error:** {e}" # This is line 434 (now corrected)
454
  except requests.exceptions.RequestException as e:
455
+ return f"**Connection Error:** {e}"
456
+ except Exception as e:
457
+ return f"**Unexpected Error:** {e}" # Catch all.
458
+
459
 
460
  with gr.Blocks() as demo:
461
+ gr.Markdown("# GitHub Tool Plugingit (Simplified Interface)") # More descriptive title
462
+
463
  with gr.Column():
464
  action = gr.Dropdown(
465
  choices=[
 
491
  "analyze_repository_by_url",
492
  "analyze_repository_content",
493
  ],
494
+ label="Select Action",
495
  )
496
+ repo_name = gr.Textbox(label="Repository Name")
497
  template_name = gr.Dropdown(
498
  choices=list(PROJECT_TEMPLATES.keys()),
499
+ label="Project Template",
500
+ allow_none=True, # Allow no template to be selected
501
  )
502
+ branch = gr.Textbox(label="Branch", value="main")
503
+ path = gr.Textbox(label="File Path")
504
+ content = gr.Code(label="File Content", lines=5, language='python') # Larger code box
505
+ message = gr.Textbox(label="Message/Comment")
506
+ owner = gr.Textbox(label="Owner")
507
+ vcs_url = gr.Textbox(label="VCS URL")
508
+ title = gr.Textbox(label="Title")
509
+ body = gr.Textbox(label="Body")
510
+ base = gr.Textbox(label="Base Branch")
511
+ head = gr.Textbox(label="Head Branch/New Branch")
512
+ issue_number = gr.Number(label="Issue Number", precision=0)
513
+ labels = gr.Textbox(label="Labels (comma-separated)")
514
  tag = gr.Textbox(label="Tag")
515
+ release_name = gr.Textbox(label="Release Name")
516
+ file_url = gr.Textbox(label="File URL")
517
+ repo_url = gr.Textbox(label="Repository URL")
518
 
519
+ run_button = gr.Button("Execute")
520
+ output = gr.Markdown(label="Result") # Use Markdown for richer output
521
 
522
  run_button.click(
523
  github_tool,
 
543
  template_name,
544
  ],
545
  outputs=output,
546
+ api_name="github_tool"
547
  )
548
 
549
  demo.launch()