clapp-pm 1.0.9__py3-none-any.whl → 1.0.11__py3-none-any.whl

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.
Files changed (40) hide show
  1. backup_current/build_index.py +132 -0
  2. backup_current/check_env.py +133 -0
  3. backup_current/clapp_core.py +61 -0
  4. backup_current/clean_command.py +214 -0
  5. backup_current/cli_commands.py +404 -0
  6. backup_current/dependency_resolver.py +272 -0
  7. backup_current/doctor_command.py +239 -0
  8. backup_current/info_command.py +194 -0
  9. backup_current/install_command.py +236 -0
  10. backup_current/installer.py +323 -0
  11. backup_current/list_command.py +262 -0
  12. backup_current/main.py +294 -0
  13. backup_current/manifest_schema.py +84 -0
  14. backup_current/manifest_validator.py +245 -0
  15. backup_current/package_registry.py +127 -0
  16. backup_current/package_runner.py +85 -0
  17. backup_current/post_install_hint.py +144 -0
  18. backup_current/publish_command.py +253 -0
  19. backup_current/remote_registry.py +285 -0
  20. backup_current/setup.py +160 -0
  21. backup_current/system_test.py +477 -0
  22. backup_current/uninstall_command.py +215 -0
  23. backup_current/validate_command.py +225 -0
  24. backup_current/version.py +8 -0
  25. backup_current/version_command.py +145 -0
  26. backup_current/where_command.py +207 -0
  27. check_env.py +1 -8
  28. clapp-packages-repo/packages/hello-python/main.py +0 -49
  29. clapp-packages-repo/packages/hello-python/manifest.json +0 -8
  30. {clapp_pm-1.0.9.data → clapp_pm-1.0.11.data}/data/version.json +1 -1
  31. {clapp_pm-1.0.9.dist-info → clapp_pm-1.0.11.dist-info}/METADATA +1 -1
  32. clapp_pm-1.0.11.dist-info/RECORD +71 -0
  33. {clapp_pm-1.0.9.dist-info → clapp_pm-1.0.11.dist-info}/top_level.txt +2 -0
  34. doctor_command.py +0 -1
  35. install_command.py +3 -0
  36. version.py +8 -0
  37. clapp_pm-1.0.9.dist-info/RECORD +0 -44
  38. {clapp_pm-1.0.9.dist-info → clapp_pm-1.0.11.dist-info}/WHEEL +0 -0
  39. {clapp_pm-1.0.9.dist-info → clapp_pm-1.0.11.dist-info}/entry_points.txt +0 -0
  40. {clapp_pm-1.0.9.dist-info → clapp_pm-1.0.11.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,477 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Sistem Entegrasyon Testi
4
+ ========================
5
+
6
+ Bu script clapp sisteminin tüm bileşenlerinin doğru çalışıp çalışmadığını test eder.
7
+ """
8
+
9
+ import os
10
+ import sys
11
+ import json
12
+ import subprocess
13
+ import tempfile
14
+ import shutil
15
+ from pathlib import Path
16
+ from typing import Dict, List, Tuple, Any
17
+
18
+ class SystemTester:
19
+ def __init__(self):
20
+ self.test_results = []
21
+ self.errors = []
22
+ self.warnings = []
23
+
24
+ def log_test(self, test_name: str, success: bool, message: str = "", details: Any = None):
25
+ """Test sonucunu kaydet"""
26
+ result = {
27
+ "test": test_name,
28
+ "success": success,
29
+ "message": message,
30
+ "details": details
31
+ }
32
+ self.test_results.append(result)
33
+
34
+ if success:
35
+ print(f"✅ {test_name}: {message}")
36
+ else:
37
+ print(f"❌ {test_name}: {message}")
38
+ self.errors.append(result)
39
+
40
+ def log_warning(self, warning: str):
41
+ """Uyarı kaydet"""
42
+ self.warnings.append(warning)
43
+ print(f"⚠️ {warning}")
44
+
45
+ def test_imports(self) -> bool:
46
+ """Tüm modüllerin import edilebilirliğini test et"""
47
+ print("\n🔍 Modül Import Testleri")
48
+ print("=" * 50)
49
+
50
+ modules = [
51
+ "main", "clapp_core", "package_registry", "package_runner",
52
+ "manifest_schema", "manifest_validator", "install_command",
53
+ "list_command", "version_command", "info_command", "doctor_command",
54
+ "clean_command", "where_command", "validate_command", "uninstall_command",
55
+ "publish_command", "remote_registry", "dependency_resolver",
56
+ "installer", "cli_commands", "check_env", "post_install_hint"
57
+ ]
58
+
59
+ all_success = True
60
+ for module in modules:
61
+ try:
62
+ __import__(module)
63
+ self.log_test(f"Import {module}", True, "Başarılı")
64
+ except ImportError as e:
65
+ self.log_test(f"Import {module}", False, f"Import hatası: {e}")
66
+ all_success = False
67
+ except Exception as e:
68
+ self.log_test(f"Import {module}", False, f"Beklenmeyen hata: {e}")
69
+ all_success = False
70
+
71
+ return all_success
72
+
73
+ def test_version_system(self) -> bool:
74
+ """Sürüm sistemi testleri"""
75
+ print("\n🔍 Sürüm Sistemi Testleri")
76
+ print("=" * 50)
77
+
78
+ try:
79
+ from version import __version__, __author__, __email__
80
+
81
+ # Sürüm formatı kontrolü
82
+ if not __version__ or __version__ == "0.0.0":
83
+ self.log_test("Version Format", False, "Geçersiz sürüm numarası")
84
+ return False
85
+
86
+ self.log_test("Version Import", True, f"Sürüm: {__version__}")
87
+ self.log_test("Author Import", True, f"Yazar: {__author__}")
88
+ self.log_test("Email Import", True, f"Email: {__email__}")
89
+
90
+ # version_command.py testi
91
+ try:
92
+ from version_command import get_version_info
93
+ info = get_version_info()
94
+
95
+ if info["version"] == __version__:
96
+ self.log_test("Version Command Integration", True, "Sürüm bilgisi eşleşiyor")
97
+ else:
98
+ self.log_test("Version Command Integration", False,
99
+ f"Sürüm uyumsuzluğu: {info['version']} != {__version__}")
100
+ return False
101
+
102
+ except Exception as e:
103
+ self.log_test("Version Command Integration", False, f"Hata: {e}")
104
+ return False
105
+
106
+ return True
107
+
108
+ except Exception as e:
109
+ self.log_test("Version System", False, f"Sürüm sistemi hatası: {e}")
110
+ return False
111
+
112
+ def test_directory_structure(self) -> bool:
113
+ """Dizin yapısı testleri"""
114
+ print("\n🔍 Dizin Yapısı Testleri")
115
+ print("=" * 50)
116
+
117
+ # package_registry.py'deki get_apps_directory() testi
118
+ try:
119
+ from package_registry import get_apps_directory
120
+ apps_dir = get_apps_directory()
121
+
122
+ # Dizin oluşturulabilir mi?
123
+ Path(apps_dir).mkdir(parents=True, exist_ok=True)
124
+ self.log_test("Apps Directory Creation", True, f"Dizin: {apps_dir}")
125
+
126
+ # Dizin yazılabilir mi?
127
+ test_file = Path(apps_dir) / "test.txt"
128
+ test_file.write_text("test")
129
+ test_file.unlink()
130
+ self.log_test("Apps Directory Write", True, "Yazma testi başarılı")
131
+
132
+ return True
133
+
134
+ except Exception as e:
135
+ self.log_test("Directory Structure", False, f"Dizin yapısı hatası: {e}")
136
+ return False
137
+
138
+ def test_manifest_system(self) -> bool:
139
+ """Manifest sistemi testleri"""
140
+ print("\n🔍 Manifest Sistemi Testleri")
141
+ print("=" * 50)
142
+
143
+ # Geçerli manifest örneği
144
+ valid_manifest = {
145
+ "name": "test-app",
146
+ "version": "1.0.0",
147
+ "language": "python",
148
+ "entry": "main.py",
149
+ "description": "Test uygulaması"
150
+ }
151
+
152
+ # Geçersiz manifest örneği
153
+ invalid_manifest = {
154
+ "name": "test-app",
155
+ # version eksik
156
+ "language": "python"
157
+ # entry eksik
158
+ }
159
+
160
+ try:
161
+ from manifest_schema import validate_manifest
162
+ from manifest_validator import validate_manifest_verbose
163
+
164
+ # Geçerli manifest testi
165
+ is_valid = validate_manifest(valid_manifest)
166
+ if is_valid:
167
+ self.log_test("Valid Manifest Schema", True, "Geçerli manifest doğrulandı")
168
+ else:
169
+ self.log_test("Valid Manifest Schema", False, "Geçerli manifest reddedildi")
170
+ return False
171
+
172
+ # Geçersiz manifest testi
173
+ is_valid = validate_manifest(invalid_manifest)
174
+ if not is_valid:
175
+ self.log_test("Invalid Manifest Schema", True, "Geçersiz manifest reddedildi")
176
+ else:
177
+ self.log_test("Invalid Manifest Schema", False, "Geçersiz manifest kabul edildi")
178
+ return False
179
+
180
+ # Detaylı doğrulama testi
181
+ is_valid, errors = validate_manifest_verbose(valid_manifest)
182
+ if is_valid and not errors:
183
+ self.log_test("Detailed Validation", True, "Detaylı doğrulama başarılı")
184
+ else:
185
+ self.log_test("Detailed Validation", False, f"Doğrulama hataları: {errors}")
186
+ return False
187
+
188
+ return True
189
+
190
+ except Exception as e:
191
+ self.log_test("Manifest System", False, f"Manifest sistemi hatası: {e}")
192
+ return False
193
+
194
+ def test_package_registry(self) -> bool:
195
+ """Paket kayıt sistemi testleri"""
196
+ print("\n🔍 Paket Kayıt Sistemi Testleri")
197
+ print("=" * 50)
198
+
199
+ try:
200
+ from package_registry import list_packages, get_manifest, app_exists, get_apps_directory
201
+
202
+ apps_dir = get_apps_directory()
203
+
204
+ # Boş liste testi
205
+ packages = list_packages()
206
+ if isinstance(packages, list):
207
+ self.log_test("List Packages Type", True, f"{len(packages)} paket bulundu")
208
+ else:
209
+ self.log_test("List Packages Type", False, f"Yanlış tip: {type(packages)}")
210
+ return False
211
+
212
+ # Var olmayan uygulama testi
213
+ manifest = get_manifest("nonexistent-app")
214
+ if manifest is None:
215
+ self.log_test("Non-existent App", True, "Var olmayan uygulama None döndürdü")
216
+ else:
217
+ self.log_test("Non-existent App", False, "Var olmayan uygulama None döndürmedi")
218
+ return False
219
+
220
+ # app_exists testi
221
+ exists = app_exists("nonexistent-app")
222
+ if not exists:
223
+ self.log_test("App Exists Check", True, "Var olmayan uygulama False döndürdü")
224
+ else:
225
+ self.log_test("App Exists Check", False, "Var olmayan uygulama True döndürdü")
226
+ return False
227
+
228
+ return True
229
+
230
+ except Exception as e:
231
+ self.log_test("Package Registry", False, f"Paket kayıt sistemi hatası: {e}")
232
+ return False
233
+
234
+ def test_cli_commands(self) -> bool:
235
+ """CLI komutları testleri"""
236
+ print("\n🔍 CLI Komutları Testleri")
237
+ print("=" * 50)
238
+
239
+ try:
240
+ from cli_commands import handle_version_command, handle_list_command
241
+
242
+ # Version komutu testi
243
+ try:
244
+ # Mock args objesi oluştur
245
+ class MockArgs:
246
+ def __init__(self):
247
+ self.format = 'default'
248
+
249
+ args = MockArgs()
250
+ handle_version_command(args)
251
+ self.log_test("Version Command", True, "Version komutu çalıştı")
252
+ except Exception as e:
253
+ self.log_test("Version Command", False, f"Version komutu hatası: {e}")
254
+ return False
255
+
256
+ # List komutu testi
257
+ try:
258
+ # Mock args objesi oluştur
259
+ class MockArgs:
260
+ def __init__(self):
261
+ self.format = 'table'
262
+ self.language = None
263
+ self.search = None
264
+
265
+ args = MockArgs()
266
+ handle_list_command(args)
267
+ self.log_test("List Command", True, "List komutu çalıştı")
268
+ except Exception as e:
269
+ self.log_test("List Command", False, f"List komutu hatası: {e}")
270
+ return False
271
+
272
+ return True
273
+
274
+ except Exception as e:
275
+ self.log_test("CLI Commands", False, f"CLI komutları hatası: {e}")
276
+ return False
277
+
278
+ def test_integration(self) -> bool:
279
+ """Entegrasyon testleri"""
280
+ print("\n🔍 Entegrasyon Testleri")
281
+ print("=" * 50)
282
+
283
+ # Test uygulaması oluştur
284
+ with tempfile.TemporaryDirectory() as temp_dir:
285
+ try:
286
+ # Test uygulaması dizini
287
+ test_app_dir = Path(temp_dir) / "test-app"
288
+ test_app_dir.mkdir()
289
+
290
+ # Test manifest.json
291
+ manifest = {
292
+ "name": "test-app",
293
+ "version": "1.0.0",
294
+ "language": "python",
295
+ "entry": "main.py",
296
+ "description": "Test uygulaması"
297
+ }
298
+
299
+ manifest_file = test_app_dir / "manifest.json"
300
+ with open(manifest_file, 'w', encoding='utf-8') as f:
301
+ json.dump(manifest, f, indent=2, ensure_ascii=False)
302
+
303
+ # Test main.py
304
+ main_file = test_app_dir / "main.py"
305
+ main_file.write_text('print("Hello from test app!")')
306
+
307
+ # package_registry entegrasyonu
308
+ from package_registry import get_apps_directory
309
+ apps_dir = get_apps_directory()
310
+ target_dir = Path(apps_dir) / "test-app"
311
+
312
+ # Kopyala
313
+ if target_dir.exists():
314
+ shutil.rmtree(target_dir)
315
+ shutil.copytree(test_app_dir, target_dir)
316
+
317
+ # Manifest doğrulama
318
+ from manifest_validator import validate_manifest_verbose
319
+ with open(target_dir / "manifest.json", 'r', encoding='utf-8') as f:
320
+ loaded_manifest = json.load(f)
321
+
322
+ is_valid, errors = validate_manifest_verbose(loaded_manifest)
323
+ if is_valid:
324
+ self.log_test("Integration Manifest Validation", True, "Manifest doğrulandı")
325
+ else:
326
+ self.log_test("Integration Manifest Validation", False, f"Doğrulama hataları: {errors}")
327
+ return False
328
+
329
+ # package_registry entegrasyonu
330
+ from package_registry import get_manifest, app_exists
331
+ manifest = get_manifest("test-app")
332
+ if manifest and manifest["name"] == "test-app":
333
+ self.log_test("Integration Package Registry", True, "Paket kayıt sistemi çalışıyor")
334
+ else:
335
+ self.log_test("Integration Package Registry", False, "Paket kayıt sistemi hatası")
336
+ return False
337
+
338
+ # app_exists testi
339
+ if app_exists("test-app"):
340
+ self.log_test("Integration App Exists", True, "Uygulama varlık kontrolü çalışıyor")
341
+ else:
342
+ self.log_test("Integration App Exists", False, "Uygulama varlık kontrolü hatası")
343
+ return False
344
+
345
+ # Temizlik
346
+ if target_dir.exists():
347
+ shutil.rmtree(target_dir)
348
+
349
+ return True
350
+
351
+ except Exception as e:
352
+ self.log_test("Integration Test", False, f"Entegrasyon testi hatası: {e}")
353
+ return False
354
+
355
+ def test_cli_execution(self) -> bool:
356
+ """CLI çalıştırma testleri"""
357
+ print("\n🔍 CLI Çalıştırma Testleri")
358
+ print("=" * 50)
359
+
360
+ try:
361
+ # Version komutu
362
+ result = subprocess.run([sys.executable, "main.py", "version"],
363
+ capture_output=True, text=True, timeout=10)
364
+
365
+ if result.returncode == 0:
366
+ self.log_test("CLI Version Execution", True, "Version komutu başarıyla çalıştı")
367
+ else:
368
+ self.log_test("CLI Version Execution", False, f"Version komutu hatası: {result.stderr}")
369
+ return False
370
+
371
+ # List komutu
372
+ result = subprocess.run([sys.executable, "main.py", "list"],
373
+ capture_output=True, text=True, timeout=10)
374
+
375
+ if result.returncode == 0:
376
+ self.log_test("CLI List Execution", True, "List komutu başarıyla çalıştı")
377
+ else:
378
+ self.log_test("CLI List Execution", False, f"List komutu hatası: {result.stderr}")
379
+ return False
380
+
381
+ return True
382
+
383
+ except subprocess.TimeoutExpired:
384
+ self.log_test("CLI Execution", False, "CLI komutları zaman aşımı")
385
+ return False
386
+ except Exception as e:
387
+ self.log_test("CLI Execution", False, f"CLI çalıştırma hatası: {e}")
388
+ return False
389
+
390
+ def run_all_tests(self) -> Dict[str, Any]:
391
+ """Tüm testleri çalıştır"""
392
+ print("🚀 CLAPP Sistem Entegrasyon Testi Başlatılıyor")
393
+ print("=" * 60)
394
+
395
+ tests = [
396
+ ("Modül Importları", self.test_imports),
397
+ ("Sürüm Sistemi", self.test_version_system),
398
+ ("Dizin Yapısı", self.test_directory_structure),
399
+ ("Manifest Sistemi", self.test_manifest_system),
400
+ ("Paket Kayıt Sistemi", self.test_package_registry),
401
+ ("CLI Komutları", self.test_cli_commands),
402
+ ("Entegrasyon", self.test_integration),
403
+ ("CLI Çalıştırma", self.test_cli_execution)
404
+ ]
405
+
406
+ results = {}
407
+ for test_name, test_func in tests:
408
+ try:
409
+ success = test_func()
410
+ results[test_name] = success
411
+ except Exception as e:
412
+ self.log_test(test_name, False, f"Test hatası: {e}")
413
+ results[test_name] = False
414
+
415
+ return results
416
+
417
+ def generate_report(self) -> str:
418
+ """Test raporu oluştur"""
419
+ print("\n" + "=" * 60)
420
+ print("📊 TEST RAPORU")
421
+ print("=" * 60)
422
+
423
+ total_tests = len(self.test_results)
424
+ successful_tests = len([r for r in self.test_results if r["success"]])
425
+ failed_tests = len(self.errors)
426
+
427
+ print(f"Toplam Test: {total_tests}")
428
+ print(f"Başarılı: {successful_tests}")
429
+ print(f"Başarısız: {failed_tests}")
430
+ print(f"Başarı Oranı: {(successful_tests/total_tests*100):.1f}%")
431
+
432
+ if self.errors:
433
+ print(f"\n❌ BAŞARISIZ TESTLER:")
434
+ for error in self.errors:
435
+ print(f" - {error['test']}: {error['message']}")
436
+
437
+ if self.warnings:
438
+ print(f"\n⚠️ UYARILAR:")
439
+ for warning in self.warnings:
440
+ print(f" - {warning}")
441
+
442
+ if failed_tests == 0:
443
+ print(f"\n🎉 TÜM TESTLER BAŞARILI! Sistem tam entegre çalışıyor.")
444
+ else:
445
+ print(f"\n🔧 {failed_tests} test başarısız. Sistem entegrasyonunda sorunlar var.")
446
+
447
+ return f"Başarı Oranı: {(successful_tests/total_tests*100):.1f}%"
448
+
449
+ def main():
450
+ """Ana test fonksiyonu"""
451
+ tester = SystemTester()
452
+ results = tester.run_all_tests()
453
+ report = tester.generate_report()
454
+
455
+ # Sonuçları JSON olarak kaydet
456
+ with open("test_results.json", "w", encoding="utf-8") as f:
457
+ json.dump({
458
+ "results": results,
459
+ "test_details": tester.test_results,
460
+ "errors": tester.errors,
461
+ "warnings": tester.warnings,
462
+ "summary": report
463
+ }, f, indent=2, ensure_ascii=False)
464
+
465
+ print(f"\n📄 Detaylı rapor: test_results.json")
466
+
467
+ # Başarı oranına göre exit code
468
+ total_tests = len(tester.test_results)
469
+ successful_tests = len([r for r in tester.test_results if r["success"]])
470
+
471
+ if successful_tests == total_tests:
472
+ sys.exit(0) # Başarılı
473
+ else:
474
+ sys.exit(1) # Başarısız
475
+
476
+ if __name__ == "__main__":
477
+ main()
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ uninstall_command.py - clapp Uninstall Command
4
+
5
+ Bu modül 'clapp uninstall <app_name>' komutunu uygular.
6
+ Kurulu uygulamaları güvenli bir şekilde kaldırır.
7
+ """
8
+
9
+ import os
10
+ import shutil
11
+ import sys
12
+ from pathlib import Path
13
+ from typing import Tuple, List
14
+
15
+ def get_apps_directory() -> str:
16
+ """Uygulamaların kurulu olduğu dizini döndürür"""
17
+ # Kullanıcının home dizininde .clapp klasörü
18
+ home_dir = Path.home()
19
+ clapp_dir = home_dir / ".clapp"
20
+ apps_dir = clapp_dir / "apps"
21
+
22
+ return str(apps_dir)
23
+
24
+ def get_installed_apps() -> List[str]:
25
+ """Kurulu uygulamaların listesini döndürür"""
26
+ apps_dir = get_apps_directory()
27
+
28
+ if not os.path.exists(apps_dir):
29
+ return []
30
+
31
+ apps = []
32
+ for item in os.listdir(apps_dir):
33
+ item_path = os.path.join(apps_dir, item)
34
+ if os.path.isdir(item_path) and not item.startswith('.'):
35
+ # manifest.json varlığını kontrol et
36
+ manifest_path = os.path.join(item_path, "manifest.json")
37
+ if os.path.exists(manifest_path):
38
+ apps.append(item)
39
+
40
+ return apps
41
+
42
+ def is_app_installed(app_name: str) -> bool:
43
+ """Uygulamanın kurulu olup olmadığını kontrol eder"""
44
+ apps_dir = get_apps_directory()
45
+ app_path = os.path.join(apps_dir, app_name)
46
+
47
+ if not os.path.exists(app_path):
48
+ return False
49
+
50
+ if not os.path.isdir(app_path):
51
+ return False
52
+
53
+ # manifest.json varlığını kontrol et
54
+ manifest_path = os.path.join(app_path, "manifest.json")
55
+ return os.path.exists(manifest_path)
56
+
57
+ def get_app_info(app_name: str) -> Tuple[bool, str, dict]:
58
+ """Uygulamanın bilgilerini getirir"""
59
+ apps_dir = get_apps_directory()
60
+ app_path = os.path.join(apps_dir, app_name)
61
+ manifest_path = os.path.join(app_path, "manifest.json")
62
+
63
+ try:
64
+ import json
65
+ with open(manifest_path, 'r', encoding='utf-8') as f:
66
+ manifest = json.load(f)
67
+
68
+ return True, "Bilgiler alındı", manifest
69
+ except Exception as e:
70
+ return False, f"Manifest okunamadı: {e}", {}
71
+
72
+ def confirm_uninstall(app_name: str, app_info: dict, skip_confirmation: bool = False) -> bool:
73
+ """Kullanıcıdan kaldırma onayı alır"""
74
+ if skip_confirmation:
75
+ return True
76
+
77
+ print(f"\n📋 Kaldırılacak uygulama:")
78
+ print(f" Ad: {app_info.get('name', app_name)}")
79
+ print(f" Sürüm: {app_info.get('version', 'Bilinmiyor')}")
80
+ print(f" Dil: {app_info.get('language', 'Bilinmiyor')}")
81
+ print(f" Açıklama: {app_info.get('description', 'Yok')}")
82
+
83
+ while True:
84
+ response = input(f"\n❓ '{app_name}' uygulamasını kaldırmak istediğinizden emin misiniz? (e/h): ").lower().strip()
85
+ if response in ['e', 'evet', 'y', 'yes']:
86
+ return True
87
+ elif response in ['h', 'hayır', 'n', 'no']:
88
+ return False
89
+ else:
90
+ print("Lütfen 'e' (evet) veya 'h' (hayır) giriniz.")
91
+
92
+ def remove_app_directory(app_name: str) -> Tuple[bool, str]:
93
+ """Uygulama klasörünü güvenli şekilde kaldırır"""
94
+ try:
95
+ apps_dir = get_apps_directory()
96
+ app_path = os.path.join(apps_dir, app_name)
97
+
98
+ # Güvenlik kontrolü - sadece .clapp/apps altındaki klasörleri sil
99
+ if not app_path.startswith(apps_dir):
100
+ return False, "Güvenlik hatası: Geçersiz klasör yolu"
101
+
102
+ if not os.path.exists(app_path):
103
+ return False, "Uygulama klasörü bulunamadı"
104
+
105
+ # Klasörü sil
106
+ shutil.rmtree(app_path)
107
+
108
+ return True, f"Uygulama klasörü kaldırıldı: {app_path}"
109
+
110
+ except PermissionError:
111
+ return False, "İzin hatası: Klasör kaldırılamadı"
112
+ except Exception as e:
113
+ return False, f"Kaldırma hatası: {e}"
114
+
115
+ def uninstall_app(app_name: str, skip_confirmation: bool = False) -> Tuple[bool, str]:
116
+ """
117
+ Ana uninstall fonksiyonu
118
+
119
+ Args:
120
+ app_name: Kaldırılacak uygulamanın adı
121
+ skip_confirmation: Onay sorma (--yes flag için)
122
+
123
+ Returns:
124
+ (success, message)
125
+ """
126
+ print(f"🗑️ Kaldırma başlatılıyor: {app_name}")
127
+ print("=" * 50)
128
+
129
+ # 1. Uygulama kurulu mu kontrol et
130
+ print("1️⃣ Uygulama kontrol ediliyor...")
131
+
132
+ if not is_app_installed(app_name):
133
+ installed_apps = get_installed_apps()
134
+ if installed_apps:
135
+ return False, f"Uygulama kurulu değil: {app_name}\nKurulu uygulamalar: {', '.join(installed_apps)}"
136
+ else:
137
+ return False, f"Uygulama kurulu değil: {app_name}\nHiç uygulama kurulu değil."
138
+
139
+ print(f"✅ {app_name} kurulu")
140
+
141
+ # 2. Uygulama bilgilerini al
142
+ print("2️⃣ Uygulama bilgileri alınıyor...")
143
+ info_success, info_message, app_info = get_app_info(app_name)
144
+
145
+ if not info_success:
146
+ print(f"⚠️ {info_message}")
147
+ app_info = {'name': app_name}
148
+
149
+ # 3. Kullanıcı onayı
150
+ if not skip_confirmation:
151
+ print("3️⃣ Kullanıcı onayı bekleniyor...")
152
+ if not confirm_uninstall(app_name, app_info, skip_confirmation):
153
+ return False, "Kaldırma işlemi iptal edildi"
154
+
155
+ # 4. Uygulamayı kaldır
156
+ print("4️⃣ Uygulama kaldırılıyor...")
157
+ remove_success, remove_message = remove_app_directory(app_name)
158
+
159
+ if not remove_success:
160
+ return False, remove_message
161
+
162
+ return True, f"🎉 '{app_name}' başarıyla kaldırıldı!"
163
+
164
+ def list_installed_apps():
165
+ """Kurulu uygulamaları listeler"""
166
+ apps = get_installed_apps()
167
+
168
+ if not apps:
169
+ print("📭 Hiç uygulama kurulu değil.")
170
+ return
171
+
172
+ print(f"📦 Kurulu uygulamalar ({len(apps)}):")
173
+ print("-" * 30)
174
+
175
+ for app_name in sorted(apps):
176
+ info_success, _, app_info = get_app_info(app_name)
177
+ if info_success:
178
+ version = app_info.get('version', '?')
179
+ language = app_info.get('language', '?')
180
+ print(f" • {app_name} (v{version}) - {language}")
181
+ else:
182
+ print(f" • {app_name} - bilgi alınamadı")
183
+
184
+ def main():
185
+ """CLI entry point"""
186
+ if len(sys.argv) < 2:
187
+ print("Kullanım: python uninstall_command.py <app_name> [--yes]")
188
+ print(" python uninstall_command.py --list")
189
+ print()
190
+ print("Örnekler:")
191
+ print(" python uninstall_command.py hello-python")
192
+ print(" python uninstall_command.py hello-python --yes")
193
+ print(" python uninstall_command.py --list")
194
+ sys.exit(1)
195
+
196
+ # --list flag kontrolü
197
+ if sys.argv[1] == "--list":
198
+ list_installed_apps()
199
+ sys.exit(0)
200
+
201
+ app_name = sys.argv[1]
202
+ skip_confirmation = "--yes" in sys.argv
203
+
204
+ success, message = uninstall_app(app_name, skip_confirmation)
205
+
206
+ print("\n" + "=" * 50)
207
+ if success:
208
+ print(f"✅ {message}")
209
+ sys.exit(0)
210
+ else:
211
+ print(f"❌ {message}")
212
+ sys.exit(1)
213
+
214
+ if __name__ == "__main__":
215
+ main()