clapp-pm 1.0.10__py3-none-any.whl → 1.0.13__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.
- backup_current/build_index.py +132 -0
- backup_current/check_env.py +133 -0
- backup_current/clapp_core.py +61 -0
- backup_current/clean_command.py +214 -0
- backup_current/cli_commands.py +404 -0
- backup_current/dependency_resolver.py +272 -0
- backup_current/doctor_command.py +239 -0
- backup_current/info_command.py +194 -0
- backup_current/install_command.py +236 -0
- backup_current/installer.py +323 -0
- backup_current/list_command.py +262 -0
- backup_current/main.py +294 -0
- backup_current/manifest_schema.py +84 -0
- backup_current/manifest_validator.py +245 -0
- backup_current/package_registry.py +127 -0
- backup_current/package_runner.py +85 -0
- backup_current/post_install_hint.py +144 -0
- backup_current/publish_command.py +253 -0
- backup_current/remote_registry.py +285 -0
- backup_current/setup.py +160 -0
- backup_current/system_test.py +477 -0
- backup_current/uninstall_command.py +215 -0
- backup_current/validate_command.py +225 -0
- backup_current/version.py +8 -0
- backup_current/version_command.py +145 -0
- backup_current/where_command.py +207 -0
- check_env.py +1 -8
- clapp-packages-repo/packages/hello-python/main.py +0 -49
- clapp-packages-repo/packages/hello-python/manifest.json +0 -8
- {clapp_pm-1.0.10.data → clapp_pm-1.0.13.data}/data/version.json +1 -1
- {clapp_pm-1.0.10.dist-info → clapp_pm-1.0.13.dist-info}/METADATA +1 -1
- clapp_pm-1.0.13.dist-info/RECORD +71 -0
- {clapp_pm-1.0.10.dist-info → clapp_pm-1.0.13.dist-info}/top_level.txt +1 -0
- doctor_command.py +0 -1
- install_command.py +3 -0
- version.py +1 -1
- clapp_pm-1.0.10.dist-info/RECORD +0 -45
- {clapp_pm-1.0.10.dist-info → clapp_pm-1.0.13.dist-info}/WHEEL +0 -0
- {clapp_pm-1.0.10.dist-info → clapp_pm-1.0.13.dist-info}/entry_points.txt +0 -0
- {clapp_pm-1.0.10.dist-info → clapp_pm-1.0.13.dist-info}/licenses/LICENSE +0 -0
backup_current/main.py
ADDED
@@ -0,0 +1,294 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
main.py - clapp Ana CLI Giriş Noktası
|
4
|
+
|
5
|
+
Bu dosya clapp'in ana komut satırı arayüzüdür.
|
6
|
+
Tüm komutları yönlendirir ve kullanıcı deneyimini yönetir.
|
7
|
+
"""
|
8
|
+
|
9
|
+
import argparse
|
10
|
+
import sys
|
11
|
+
import os
|
12
|
+
from pathlib import Path
|
13
|
+
|
14
|
+
# Mevcut modülleri import et
|
15
|
+
from clapp_core import list_apps, run_app
|
16
|
+
from cli_commands import (
|
17
|
+
install_from_remote, upgrade_package, publish_package,
|
18
|
+
search_remote_packages, show_package_info, list_all_packages,
|
19
|
+
check_system_health, handle_publish_command, handle_install_command,
|
20
|
+
handle_uninstall_command, handle_list_command, publish_to_repository
|
21
|
+
)
|
22
|
+
from installer import install_package, uninstall_package, install_from_directory
|
23
|
+
from remote_registry import list_remote_packages
|
24
|
+
|
25
|
+
# Yeni komut modüllerini import et
|
26
|
+
from post_install_hint import check_first_run, show_post_install_hint
|
27
|
+
from check_env import run_environment_check
|
28
|
+
from info_command import show_app_info
|
29
|
+
from validate_command import validate_app_folder
|
30
|
+
from doctor_command import run_doctor
|
31
|
+
from clean_command import run_clean
|
32
|
+
from where_command import locate_app_path, list_all_app_locations
|
33
|
+
from version_command import print_version, print_detailed_version
|
34
|
+
|
35
|
+
# Yeni publish.cursorrules komutları
|
36
|
+
from publish_command import publish_app
|
37
|
+
from install_command import install_app
|
38
|
+
from uninstall_command import uninstall_app
|
39
|
+
from list_command import list_apps as list_apps_new
|
40
|
+
|
41
|
+
def main():
|
42
|
+
"""Ana CLI fonksiyonu"""
|
43
|
+
|
44
|
+
# İlk çalıştırma kontrolü
|
45
|
+
first_run = check_first_run()
|
46
|
+
if first_run:
|
47
|
+
print() # Boş satır ekle
|
48
|
+
|
49
|
+
parser = argparse.ArgumentParser(
|
50
|
+
prog='clapp',
|
51
|
+
description='🚀 clapp - Hafif Çoklu Dil Uygulama Yöneticisi',
|
52
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
53
|
+
epilog="""
|
54
|
+
📚 Temel Komutlar:
|
55
|
+
clapp list # Yüklü uygulamaları listele
|
56
|
+
clapp run hello-python # hello-python uygulamasını çalıştır
|
57
|
+
clapp info hello-python # Uygulama bilgilerini göster
|
58
|
+
|
59
|
+
🔧 Yönetim Komutları:
|
60
|
+
clapp install app.zip # ZIP dosyasından uygulama yükle
|
61
|
+
clapp uninstall hello-python # Uygulamayı kaldır
|
62
|
+
clapp upgrade hello-python # Uygulamayı güncelle
|
63
|
+
clapp validate ./my-app # Uygulama klasörünü doğrula
|
64
|
+
clapp publish ./my-app # Uygulama yayınla
|
65
|
+
|
66
|
+
🛠️ Sistem Komutları:
|
67
|
+
clapp check-env # Ortam kontrolü
|
68
|
+
clapp doctor # Kapsamlı sistem tanılaması
|
69
|
+
clapp clean # Geçici dosyaları temizle
|
70
|
+
clapp where hello-python # Uygulama konumunu göster
|
71
|
+
clapp version # Sürüm bilgilerini göster
|
72
|
+
|
73
|
+
🌐 Uzak Komutlar:
|
74
|
+
clapp search calculator # Uzak depoda ara
|
75
|
+
clapp remote list # Uzak depo listesi
|
76
|
+
clapp health # Sistem sağlık kontrolü
|
77
|
+
|
78
|
+
📖 Daha fazla bilgi için: https://github.com/mburakmmm/clapp
|
79
|
+
"""
|
80
|
+
)
|
81
|
+
|
82
|
+
# Alt komutlar
|
83
|
+
subparsers = parser.add_subparsers(dest='command', help='Mevcut komutlar')
|
84
|
+
|
85
|
+
# run komutu
|
86
|
+
run_parser = subparsers.add_parser('run', help='Yüklü bir uygulamayı çalıştır')
|
87
|
+
run_parser.add_argument('app_name', help='Çalıştırılacak uygulamanın adı')
|
88
|
+
|
89
|
+
# list komutu
|
90
|
+
list_parser = subparsers.add_parser('list', help='Yüklü uygulamaları listele')
|
91
|
+
list_parser.add_argument('--all', action='store_true', help='Hem yerel hem uzak paketleri listele')
|
92
|
+
list_parser.add_argument('--format', choices=['table', 'simple', 'json', 'detailed'],
|
93
|
+
default='table', help='Çıktı formatı')
|
94
|
+
list_parser.add_argument('--language', help='Dil filtresi (python, lua, vb.)')
|
95
|
+
list_parser.add_argument('--search', help='Arama terimi (ad veya açıklamada)')
|
96
|
+
|
97
|
+
# install komutu
|
98
|
+
install_parser = subparsers.add_parser('install', help='Uygulama yükle')
|
99
|
+
install_parser.add_argument('source', help='Uygulama adı, zip dosyası veya URL')
|
100
|
+
install_parser.add_argument('--force', action='store_true', help='Mevcut uygulamanın üzerine yaz')
|
101
|
+
install_parser.add_argument('--local', action='store_true', help='Yerel dizinden yükle')
|
102
|
+
|
103
|
+
# uninstall komutu
|
104
|
+
uninstall_parser = subparsers.add_parser('uninstall', help='Uygulama kaldır')
|
105
|
+
uninstall_parser.add_argument('app_name', help='Kaldırılacak uygulamanın adı')
|
106
|
+
uninstall_parser.add_argument('--yes', action='store_true', help='Onay sorma')
|
107
|
+
|
108
|
+
# upgrade komutu
|
109
|
+
upgrade_parser = subparsers.add_parser('upgrade', help='Uygulamayı güncelle')
|
110
|
+
upgrade_parser.add_argument('app_name', help='Güncellenecek uygulamanın adı')
|
111
|
+
|
112
|
+
# search komutu
|
113
|
+
search_parser = subparsers.add_parser('search', help='Paket ara')
|
114
|
+
search_parser.add_argument('query', help='Arama terimi')
|
115
|
+
|
116
|
+
# info komutu (yeni)
|
117
|
+
info_parser = subparsers.add_parser('info', help='Uygulama bilgilerini detaylı göster')
|
118
|
+
info_parser.add_argument('app_name', help='Bilgisi gösterilecek uygulamanın adı')
|
119
|
+
info_parser.add_argument('--remote', action='store_true', help='Uzak paket bilgisini göster')
|
120
|
+
|
121
|
+
# validate komutu (yeni)
|
122
|
+
validate_parser = subparsers.add_parser('validate', help='Uygulama klasörünü doğrula')
|
123
|
+
validate_parser.add_argument('folder', help='Doğrulanacak klasör yolu')
|
124
|
+
|
125
|
+
# publish komutu
|
126
|
+
publish_parser = subparsers.add_parser('publish', help='Paket yayınla')
|
127
|
+
publish_parser.add_argument('app_path', help='Yayınlanacak uygulama dizini')
|
128
|
+
publish_parser.add_argument('--push', action='store_true', help='clapp-packages reposuna otomatik push et')
|
129
|
+
|
130
|
+
# remote komutu
|
131
|
+
remote_parser = subparsers.add_parser('remote', help='Uzak paket deposunu listele')
|
132
|
+
remote_parser.add_argument('--details', action='store_true', help='Detayları göster')
|
133
|
+
|
134
|
+
# health komutu
|
135
|
+
health_parser = subparsers.add_parser('health', help='Sistem sağlığını kontrol et')
|
136
|
+
|
137
|
+
# check-env komutu (yeni)
|
138
|
+
check_env_parser = subparsers.add_parser('check-env', help='Ortam kontrolü yap')
|
139
|
+
|
140
|
+
# doctor komutu (yeni)
|
141
|
+
doctor_parser = subparsers.add_parser('doctor', help='Kapsamlı sistem tanılaması')
|
142
|
+
|
143
|
+
# clean komutu (yeni)
|
144
|
+
clean_parser = subparsers.add_parser('clean', help='Geçici dosyaları temizle')
|
145
|
+
clean_parser.add_argument('--dry-run', action='store_true', help='Sadece göster, silme')
|
146
|
+
|
147
|
+
# where komutu (yeni)
|
148
|
+
where_parser = subparsers.add_parser('where', help='Uygulama konumunu göster')
|
149
|
+
where_parser.add_argument('app_name', nargs='?', help='Konumu gösterilecek uygulamanın adı')
|
150
|
+
where_parser.add_argument('--check-entry', action='store_true', help='Giriş dosyasını da kontrol et')
|
151
|
+
where_parser.add_argument('--open', action='store_true', help='Dosya yöneticisinde aç')
|
152
|
+
|
153
|
+
|
154
|
+
|
155
|
+
# version komutu (yeni)
|
156
|
+
version_parser = subparsers.add_parser('version', help='Sürüm bilgisini göster')
|
157
|
+
version_parser.add_argument('--short', action='store_true', help='Sadece sürüm numarası')
|
158
|
+
version_parser.add_argument('--json', action='store_true', help='JSON formatında')
|
159
|
+
version_parser.add_argument('--detailed', action='store_true', help='Detaylı bilgi')
|
160
|
+
|
161
|
+
# Argümanları parse et
|
162
|
+
args = parser.parse_args()
|
163
|
+
|
164
|
+
# Komut yoksa help göster
|
165
|
+
if not args.command:
|
166
|
+
parser.print_help()
|
167
|
+
return
|
168
|
+
|
169
|
+
try:
|
170
|
+
# Komutları işle
|
171
|
+
if args.command == 'run':
|
172
|
+
success = run_app(args.app_name)
|
173
|
+
sys.exit(0 if success else 1)
|
174
|
+
|
175
|
+
elif args.command == 'list':
|
176
|
+
if args.all:
|
177
|
+
list_all_packages()
|
178
|
+
else:
|
179
|
+
# Yeni gelişmiş list komutu
|
180
|
+
try:
|
181
|
+
output = list_apps_new(args.format, args.language, args.search)
|
182
|
+
print(output)
|
183
|
+
except Exception as e:
|
184
|
+
print(f"❌ Liste hatası: {e}")
|
185
|
+
sys.exit(1)
|
186
|
+
|
187
|
+
elif args.command == 'install':
|
188
|
+
if args.local:
|
189
|
+
# Yerel dizinden yükle
|
190
|
+
success, message = install_from_directory(args.source, args.force)
|
191
|
+
elif args.source.endswith('.zip') or '/' in args.source:
|
192
|
+
# Zip dosyası veya URL
|
193
|
+
success, message = install_package(args.source, args.force)
|
194
|
+
else:
|
195
|
+
# Yeni install komutu (GitHub'dan index.json ile)
|
196
|
+
success, message = install_app(args.source)
|
197
|
+
|
198
|
+
if not success:
|
199
|
+
print(f"❌ {message}")
|
200
|
+
sys.exit(1)
|
201
|
+
|
202
|
+
elif args.command == 'uninstall':
|
203
|
+
# Yeni uninstall komutu
|
204
|
+
success, message = uninstall_app(args.app_name, args.yes)
|
205
|
+
print(message)
|
206
|
+
sys.exit(0 if success else 1)
|
207
|
+
|
208
|
+
elif args.command == 'upgrade':
|
209
|
+
success, message = upgrade_package(args.app_name)
|
210
|
+
if not success:
|
211
|
+
print(f"❌ {message}")
|
212
|
+
sys.exit(1)
|
213
|
+
|
214
|
+
elif args.command == 'search':
|
215
|
+
success, message = search_remote_packages(args.query)
|
216
|
+
if not success:
|
217
|
+
print(f"❌ {message}")
|
218
|
+
sys.exit(1)
|
219
|
+
|
220
|
+
elif args.command == 'info':
|
221
|
+
if args.remote:
|
222
|
+
# Eski remote info fonksiyonu
|
223
|
+
success, message = show_package_info(args.app_name, args.remote)
|
224
|
+
if not success:
|
225
|
+
print(f"❌ {message}")
|
226
|
+
sys.exit(1)
|
227
|
+
else:
|
228
|
+
# Yeni detaylı info komutu
|
229
|
+
success = show_app_info(args.app_name)
|
230
|
+
sys.exit(0 if success else 1)
|
231
|
+
|
232
|
+
elif args.command == 'validate':
|
233
|
+
success = validate_app_folder(args.folder)
|
234
|
+
sys.exit(0 if success else 1)
|
235
|
+
|
236
|
+
elif args.command == 'publish':
|
237
|
+
# Yeni publish komutu
|
238
|
+
success, message = publish_app(args.app_path, push_to_github=args.push)
|
239
|
+
if not success:
|
240
|
+
print(f"❌ {message}")
|
241
|
+
sys.exit(1)
|
242
|
+
|
243
|
+
elif args.command == 'remote':
|
244
|
+
output = list_remote_packages(args.details)
|
245
|
+
print(output)
|
246
|
+
|
247
|
+
elif args.command == 'health':
|
248
|
+
check_system_health()
|
249
|
+
|
250
|
+
elif args.command == 'check-env':
|
251
|
+
success = run_environment_check()
|
252
|
+
sys.exit(0 if success else 1)
|
253
|
+
|
254
|
+
elif args.command == 'doctor':
|
255
|
+
success = run_doctor()
|
256
|
+
sys.exit(0 if success else 1)
|
257
|
+
|
258
|
+
elif args.command == 'clean':
|
259
|
+
success = run_clean(args.dry_run)
|
260
|
+
sys.exit(0 if success else 1)
|
261
|
+
|
262
|
+
elif args.command == 'where':
|
263
|
+
if args.app_name:
|
264
|
+
if args.open:
|
265
|
+
from where_command import open_app_location
|
266
|
+
success = open_app_location(args.app_name)
|
267
|
+
else:
|
268
|
+
success = locate_app_path(args.app_name, args.check_entry)
|
269
|
+
sys.exit(0 if success else 1)
|
270
|
+
else:
|
271
|
+
success = list_all_app_locations()
|
272
|
+
sys.exit(0 if success else 1)
|
273
|
+
|
274
|
+
|
275
|
+
|
276
|
+
elif args.command == 'version':
|
277
|
+
if args.short:
|
278
|
+
print_version("short")
|
279
|
+
elif args.json:
|
280
|
+
print_version("json")
|
281
|
+
elif args.detailed:
|
282
|
+
print_detailed_version()
|
283
|
+
else:
|
284
|
+
print_version("default")
|
285
|
+
|
286
|
+
except KeyboardInterrupt:
|
287
|
+
print("\n❌ İşlem iptal edildi")
|
288
|
+
sys.exit(1)
|
289
|
+
except Exception as e:
|
290
|
+
print(f"❌ Beklenmeyen hata: {e}")
|
291
|
+
sys.exit(1)
|
292
|
+
|
293
|
+
if __name__ == '__main__':
|
294
|
+
main()
|
@@ -0,0 +1,84 @@
|
|
1
|
+
import json
|
2
|
+
import os
|
3
|
+
|
4
|
+
def load_manifest(manifest_path):
|
5
|
+
"""
|
6
|
+
Manifest dosyasını yükler ve parse eder.
|
7
|
+
|
8
|
+
Args:
|
9
|
+
manifest_path (str): Manifest dosyasının yolu
|
10
|
+
|
11
|
+
Returns:
|
12
|
+
dict: Parse edilmiş manifest dictionary'si
|
13
|
+
|
14
|
+
Raises:
|
15
|
+
FileNotFoundError: Dosya bulunamadığında
|
16
|
+
json.JSONDecodeError: JSON parse hatası
|
17
|
+
"""
|
18
|
+
if not os.path.exists(manifest_path):
|
19
|
+
raise FileNotFoundError(f"Manifest dosyası bulunamadı: {manifest_path}")
|
20
|
+
|
21
|
+
with open(manifest_path, 'r', encoding='utf-8') as f:
|
22
|
+
return json.load(f)
|
23
|
+
|
24
|
+
def validate_manifest(manifest):
|
25
|
+
"""
|
26
|
+
Manifest dosyasının gerekli alanları içerip içermediğini ve tiplerinin doğru olup olmadığını kontrol eder.
|
27
|
+
|
28
|
+
Args:
|
29
|
+
manifest (dict): Doğrulanacak manifest dictionary'si
|
30
|
+
|
31
|
+
Returns:
|
32
|
+
bool: Manifest geçerliyse True, değilse False
|
33
|
+
"""
|
34
|
+
# Gerekli alanlar
|
35
|
+
required_fields = {
|
36
|
+
'name': str,
|
37
|
+
'version': str,
|
38
|
+
'language': str,
|
39
|
+
'entry': str
|
40
|
+
}
|
41
|
+
|
42
|
+
# Opsiyonel alanlar
|
43
|
+
optional_fields = {
|
44
|
+
'description': str,
|
45
|
+
'dependencies': list
|
46
|
+
}
|
47
|
+
|
48
|
+
# Gerekli alanları kontrol et
|
49
|
+
for field, expected_type in required_fields.items():
|
50
|
+
if field not in manifest:
|
51
|
+
return False
|
52
|
+
if not isinstance(manifest[field], expected_type):
|
53
|
+
return False
|
54
|
+
|
55
|
+
# Dil kontrolü
|
56
|
+
if manifest['language'] not in ['python', 'lua']:
|
57
|
+
return False
|
58
|
+
|
59
|
+
# Opsiyonel alanları kontrol et (varsa)
|
60
|
+
for field, expected_type in optional_fields.items():
|
61
|
+
if field in manifest and not isinstance(manifest[field], expected_type):
|
62
|
+
return False
|
63
|
+
|
64
|
+
return True
|
65
|
+
|
66
|
+
def get_schema():
|
67
|
+
"""
|
68
|
+
Manifest şemasını döndürür.
|
69
|
+
|
70
|
+
Returns:
|
71
|
+
dict: Manifest şeması
|
72
|
+
"""
|
73
|
+
return {
|
74
|
+
"required_fields": {
|
75
|
+
"name": "string",
|
76
|
+
"version": "string",
|
77
|
+
"language": "string (python or lua)",
|
78
|
+
"entry": "string"
|
79
|
+
},
|
80
|
+
"optional_fields": {
|
81
|
+
"description": "string",
|
82
|
+
"dependencies": "list"
|
83
|
+
}
|
84
|
+
}
|
@@ -0,0 +1,245 @@
|
|
1
|
+
from manifest_schema import validate_manifest, get_schema
|
2
|
+
|
3
|
+
def validate_manifest_verbose(manifest):
|
4
|
+
"""
|
5
|
+
Manifest dosyasını doğrular ve detaylı hata mesajları döndürür.
|
6
|
+
|
7
|
+
Args:
|
8
|
+
manifest (dict): Doğrulanacak manifest dictionary'si
|
9
|
+
|
10
|
+
Returns:
|
11
|
+
tuple: (is_valid: bool, errors: list of strings)
|
12
|
+
"""
|
13
|
+
errors = []
|
14
|
+
|
15
|
+
if not isinstance(manifest, dict):
|
16
|
+
return False, ["Manifest geçerli bir JSON objesi değil"]
|
17
|
+
|
18
|
+
# Şema bilgilerini al
|
19
|
+
schema = get_schema()
|
20
|
+
required_fields = schema["required_fields"]
|
21
|
+
|
22
|
+
# Gerekli alanları kontrol et
|
23
|
+
for field, field_type in required_fields.items():
|
24
|
+
if field not in manifest:
|
25
|
+
errors.append(f"Gerekli alan eksik: '{field}'")
|
26
|
+
continue
|
27
|
+
|
28
|
+
# Tip kontrolü
|
29
|
+
value = manifest[field]
|
30
|
+
|
31
|
+
if field == "name":
|
32
|
+
if not isinstance(value, str) or not value.strip():
|
33
|
+
errors.append(f"'{field}' alanı boş olmayan bir string olmalı")
|
34
|
+
elif field == "version":
|
35
|
+
if not isinstance(value, str) or not value.strip():
|
36
|
+
errors.append(f"'{field}' alanı boş olmayan bir string olmalı")
|
37
|
+
elif not is_valid_version(value):
|
38
|
+
errors.append(f"'{field}' alanı geçerli bir sürüm formatında olmalı (örn: 1.0.0)")
|
39
|
+
elif field == "language":
|
40
|
+
if not isinstance(value, str):
|
41
|
+
errors.append(f"'{field}' alanı string olmalı")
|
42
|
+
elif value.lower() not in ["python", "lua"]:
|
43
|
+
errors.append(f"'{field}' alanı 'python' veya 'lua' olmalı, '{value}' geçersiz")
|
44
|
+
elif field == "entry":
|
45
|
+
if not isinstance(value, str) or not value.strip():
|
46
|
+
errors.append(f"'{field}' alanı boş olmayan bir string olmalı")
|
47
|
+
elif not is_valid_filename(value):
|
48
|
+
errors.append(f"'{field}' alanı geçerli bir dosya adı olmalı")
|
49
|
+
|
50
|
+
# Opsiyonel alanları kontrol et
|
51
|
+
if "description" in manifest:
|
52
|
+
if not isinstance(manifest["description"], str):
|
53
|
+
errors.append("'description' alanı string olmalı")
|
54
|
+
|
55
|
+
if "dependencies" in manifest:
|
56
|
+
if not isinstance(manifest["dependencies"], list):
|
57
|
+
errors.append("'dependencies' alanı liste olmalı")
|
58
|
+
else:
|
59
|
+
for i, dep in enumerate(manifest["dependencies"]):
|
60
|
+
if not isinstance(dep, str) or not dep.strip():
|
61
|
+
errors.append(f"'dependencies[{i}]' boş olmayan bir string olmalı")
|
62
|
+
|
63
|
+
# Bilinmeyen alanları kontrol et
|
64
|
+
known_fields = set(required_fields.keys()) | {"description", "dependencies"}
|
65
|
+
for field in manifest.keys():
|
66
|
+
if field not in known_fields:
|
67
|
+
errors.append(f"Bilinmeyen alan: '{field}' (göz ardı edilecek)")
|
68
|
+
|
69
|
+
return len(errors) == 0, errors
|
70
|
+
|
71
|
+
def is_valid_version(version_string):
|
72
|
+
"""
|
73
|
+
Sürüm string'inin geçerli olup olmadığını kontrol eder.
|
74
|
+
|
75
|
+
Args:
|
76
|
+
version_string (str): Sürüm string'i
|
77
|
+
|
78
|
+
Returns:
|
79
|
+
bool: Geçerliyse True
|
80
|
+
"""
|
81
|
+
try:
|
82
|
+
# Basit sürüm formatı kontrolü (x.y.z veya x.y)
|
83
|
+
parts = version_string.split('.')
|
84
|
+
if len(parts) < 2 or len(parts) > 3:
|
85
|
+
return False
|
86
|
+
|
87
|
+
for part in parts:
|
88
|
+
if not part.isdigit():
|
89
|
+
return False
|
90
|
+
|
91
|
+
return True
|
92
|
+
except:
|
93
|
+
return False
|
94
|
+
|
95
|
+
def is_valid_filename(filename):
|
96
|
+
"""
|
97
|
+
Dosya adının geçerli olup olmadığını kontrol eder.
|
98
|
+
|
99
|
+
Args:
|
100
|
+
filename (str): Dosya adı
|
101
|
+
|
102
|
+
Returns:
|
103
|
+
bool: Geçerliyse True
|
104
|
+
"""
|
105
|
+
import os
|
106
|
+
|
107
|
+
# Boş string kontrolü
|
108
|
+
if not filename or not filename.strip():
|
109
|
+
return False
|
110
|
+
|
111
|
+
# Geçersiz karakterler
|
112
|
+
invalid_chars = ['<', '>', ':', '"', '|', '?', '*', '\0']
|
113
|
+
for char in invalid_chars:
|
114
|
+
if char in filename:
|
115
|
+
return False
|
116
|
+
|
117
|
+
# Sistem dosya adları (Windows)
|
118
|
+
reserved_names = [
|
119
|
+
'CON', 'PRN', 'AUX', 'NUL',
|
120
|
+
'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9',
|
121
|
+
'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9'
|
122
|
+
]
|
123
|
+
|
124
|
+
name_without_ext = os.path.splitext(filename)[0].upper()
|
125
|
+
if name_without_ext in reserved_names:
|
126
|
+
return False
|
127
|
+
|
128
|
+
return True
|
129
|
+
|
130
|
+
def validate_manifest_file(manifest_path):
|
131
|
+
"""
|
132
|
+
Manifest dosyasını doğrular.
|
133
|
+
|
134
|
+
Args:
|
135
|
+
manifest_path (str): Manifest dosyasının yolu
|
136
|
+
|
137
|
+
Returns:
|
138
|
+
tuple: (is_valid: bool, errors: list of strings)
|
139
|
+
"""
|
140
|
+
import json
|
141
|
+
import os
|
142
|
+
|
143
|
+
# Dosya varlığını kontrol et
|
144
|
+
if not os.path.exists(manifest_path):
|
145
|
+
return False, [f"Manifest dosyası bulunamadı: {manifest_path}"]
|
146
|
+
|
147
|
+
# JSON dosyasını yüklemeye çalış
|
148
|
+
try:
|
149
|
+
with open(manifest_path, 'r', encoding='utf-8') as f:
|
150
|
+
manifest = json.load(f)
|
151
|
+
except json.JSONDecodeError as e:
|
152
|
+
return False, [f"JSON formatı hatalı: {e}"]
|
153
|
+
except Exception as e:
|
154
|
+
return False, [f"Dosya okuma hatası: {e}"]
|
155
|
+
|
156
|
+
# Manifest içeriğini doğrula
|
157
|
+
return validate_manifest_verbose(manifest)
|
158
|
+
|
159
|
+
def get_validation_summary(errors):
|
160
|
+
"""
|
161
|
+
Doğrulama hatalarının özetini döndürür.
|
162
|
+
|
163
|
+
Args:
|
164
|
+
errors (list): Hata mesajları listesi
|
165
|
+
|
166
|
+
Returns:
|
167
|
+
str: Hata özeti
|
168
|
+
"""
|
169
|
+
if not errors:
|
170
|
+
return "✅ Manifest dosyası geçerli"
|
171
|
+
|
172
|
+
summary = f"❌ {len(errors)} hata bulundu:\n"
|
173
|
+
for i, error in enumerate(errors, 1):
|
174
|
+
summary += f"{i}. {error}\n"
|
175
|
+
|
176
|
+
return summary
|
177
|
+
|
178
|
+
def suggest_fixes(errors):
|
179
|
+
"""
|
180
|
+
Hatalara göre düzeltme önerileri sunar.
|
181
|
+
|
182
|
+
Args:
|
183
|
+
errors (list): Hata mesajları listesi
|
184
|
+
|
185
|
+
Returns:
|
186
|
+
list: Düzeltme önerileri
|
187
|
+
"""
|
188
|
+
suggestions = []
|
189
|
+
|
190
|
+
for error in errors:
|
191
|
+
if "Gerekli alan eksik" in error:
|
192
|
+
field = error.split("'")[1]
|
193
|
+
if field == "name":
|
194
|
+
suggestions.append("Uygulama adını 'name' alanına ekleyin")
|
195
|
+
elif field == "version":
|
196
|
+
suggestions.append("Sürüm bilgisini 'version' alanına ekleyin (örn: '1.0.0')")
|
197
|
+
elif field == "language":
|
198
|
+
suggestions.append("Programlama dilini 'language' alanına ekleyin ('python' veya 'lua')")
|
199
|
+
elif field == "entry":
|
200
|
+
suggestions.append("Giriş dosyasını 'entry' alanına ekleyin (örn: 'main.py')")
|
201
|
+
|
202
|
+
elif "geçerli bir sürüm formatında olmalı" in error:
|
203
|
+
suggestions.append("Sürüm formatını düzeltin (örn: '1.0.0', '2.1.5')")
|
204
|
+
|
205
|
+
elif "python' veya 'lua' olmalı" in error:
|
206
|
+
suggestions.append("Desteklenen dil kullanın: 'python' veya 'lua'")
|
207
|
+
|
208
|
+
elif "geçerli bir dosya adı olmalı" in error:
|
209
|
+
suggestions.append("Giriş dosyası adını düzeltin (geçersiz karakterler içermemeli)")
|
210
|
+
|
211
|
+
return suggestions
|
212
|
+
|
213
|
+
if __name__ == "__main__":
|
214
|
+
# Test için örnek manifest'ler
|
215
|
+
|
216
|
+
# Geçerli manifest
|
217
|
+
valid_manifest = {
|
218
|
+
"name": "test-app",
|
219
|
+
"version": "1.0.0",
|
220
|
+
"language": "python",
|
221
|
+
"entry": "main.py",
|
222
|
+
"description": "Test uygulaması"
|
223
|
+
}
|
224
|
+
|
225
|
+
# Geçersiz manifest
|
226
|
+
invalid_manifest = {
|
227
|
+
"name": "",
|
228
|
+
"version": "abc",
|
229
|
+
"language": "javascript",
|
230
|
+
"entry": "main.py",
|
231
|
+
"unknown_field": "value"
|
232
|
+
}
|
233
|
+
|
234
|
+
print("Geçerli manifest testi:")
|
235
|
+
is_valid, errors = validate_manifest_verbose(valid_manifest)
|
236
|
+
print(get_validation_summary(errors))
|
237
|
+
|
238
|
+
print("\nGeçersiz manifest testi:")
|
239
|
+
is_valid, errors = validate_manifest_verbose(invalid_manifest)
|
240
|
+
print(get_validation_summary(errors))
|
241
|
+
|
242
|
+
print("\nDüzeltme önerileri:")
|
243
|
+
suggestions = suggest_fixes(errors)
|
244
|
+
for suggestion in suggestions:
|
245
|
+
print(f"- {suggestion}")
|