2023-11-22 22:44:04 +03:00
|
|
|
|
#!/usr/bin/python3.7
|
|
|
|
|
|
2023-11-20 22:29:46 +03:00
|
|
|
|
import os
|
2023-11-20 23:01:54 +03:00
|
|
|
|
import pathlib
|
2023-11-20 22:29:46 +03:00
|
|
|
|
import re
|
|
|
|
|
import requests
|
|
|
|
|
from subprocess import call
|
|
|
|
|
import threading
|
|
|
|
|
import pygments
|
2023-11-20 23:01:54 +03:00
|
|
|
|
from pygments.lexers import get_lexer_for_filename
|
|
|
|
|
import pygments.token
|
2023-11-20 22:29:46 +03:00
|
|
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
|
|
|
|
|
|
|
|
### Проверен на python 3.7.5
|
|
|
|
|
### Для установки:
|
|
|
|
|
### python3.7 -m pip install requests re
|
|
|
|
|
### Перед запуском надо стереть поддиректорию cloned_repos, если она есть, иначе повторная обработка ранее обработанных URL-ов
|
|
|
|
|
### будет неверной. Запуск без параметров. Список репозиториев - простой текст, repos.txt.
|
|
|
|
|
### Вы должны настроить клонирование репозиториев с гитхаба по URL вида git@github.com:user/repo, т.е. добавить свой
|
|
|
|
|
### ssh-ключ на гитхаб.
|
|
|
|
|
|
|
|
|
|
возможныеПутиК_README_mdВнутриРепозитория = ["/blob/main/README.md", "/blob/master/README.md", "/README.md", "/", ""]
|
|
|
|
|
найденныеЯзыкиКоторыеМыНеЗаказывали = []
|
2023-11-20 23:01:54 +03:00
|
|
|
|
интересныеЯзыки = ['Ruby', 'VB.net', 'GLSL', 'Perl', 'PHP', 'Python', 'Common Lisp', 'OCaml', 'Java',
|
2023-11-22 22:44:04 +03:00
|
|
|
|
'C#', 'JavaScript', 'C', 'C++', 'Prolog', 'Go', 'Rust', 'Scheme', 'Transact-SQL', 'PL-SQL', 'tsql', 'PL/1', 'plsql', 'pli', 'Pascal', 'Delphi', 'Modula-2',
|
|
|
|
|
'Modelica', 'Lua', 'TypeScript', 'Haskell']
|
2023-11-20 22:29:46 +03:00
|
|
|
|
|
2023-11-20 23:47:14 +03:00
|
|
|
|
неинтересныеРасширенияФайлов = ['.md','.txt','.html','.xml','.XML','.json','.jpg','.png','.svg','.ttf','.sample']
|
2023-11-20 22:29:46 +03:00
|
|
|
|
|
2023-11-20 23:01:54 +03:00
|
|
|
|
|
|
|
|
|
def НайденЯзыкКоторыйМыНеЗаказывали(lexer_name, url, log, файлДляНезаказанныхЯзыков):
|
2023-11-20 22:29:46 +03:00
|
|
|
|
if lexer_name not in найденныеЯзыкиКоторыеМыНеЗаказывали:
|
|
|
|
|
найденныеЯзыкиКоторыеМыНеЗаказывали.append(lexer_name)
|
2023-11-20 23:01:54 +03:00
|
|
|
|
log.write(f"{url} - Лексер определил язык, который не включён в список разрешённых. {lexer_name} \n")
|
|
|
|
|
print(f"{url} - Лексер определил язык, который не включён в список разрешённых. {lexer_name} ")
|
|
|
|
|
файлДляНезаказанныхЯзыков.write("%s\n" % lexer_name)
|
2023-11-20 22:29:46 +03:00
|
|
|
|
|
|
|
|
|
def download_repo(url, log):
|
|
|
|
|
httpsPrefix = "https://github.com/"
|
|
|
|
|
assert(url.startswith(httpsPrefix))
|
2023-11-20 23:01:54 +03:00
|
|
|
|
repo_dir = os.path.join("cloned_repos",*url.split('/')[3:])
|
2023-11-20 22:29:46 +03:00
|
|
|
|
gitUrl = url.replace(httpsPrefix, "git@github.com:")
|
|
|
|
|
try:
|
|
|
|
|
call(['git', 'clone', '--depth', '1', gitUrl, repo_dir])
|
|
|
|
|
#git.Repo.clone_from(url, repo_dir)
|
|
|
|
|
return repo_dir
|
|
|
|
|
except Exception as e:
|
|
|
|
|
log.write(f"{gitUrl} - Произошла ошибка при клонирровании репозитория:: {str(e)} \n")
|
|
|
|
|
print(f"{gitUrl} - Произошла ошибка при клонирровании репозитория: {str(e)}")
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
def analyze_readme(url, log):
|
|
|
|
|
for suburl in возможныеПутиК_README_mdВнутриРепозитория:
|
|
|
|
|
try:
|
|
|
|
|
readme_url = url + suburl
|
|
|
|
|
response = requests.get(readme_url)
|
|
|
|
|
if response.status_code == 200:
|
|
|
|
|
content = response.text
|
|
|
|
|
if not(re.search('[а-яА-Я]', content)):
|
|
|
|
|
log.write(f"{readme_url} - Нет русских символов в README. \n")
|
|
|
|
|
print(f"{readme_url} - Нет русских символов в README.")
|
|
|
|
|
return 0
|
|
|
|
|
else:
|
|
|
|
|
return 1
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"{readme_url} - Не найден README.")
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
2023-11-20 23:01:54 +03:00
|
|
|
|
def analyze_repo(url, log, файлДляНезаказанныхЯзыков):
|
2023-11-20 22:29:46 +03:00
|
|
|
|
try:
|
|
|
|
|
print(f"{url} STP загрузуа и анализ README")
|
|
|
|
|
res = analyze_readme(url, log)
|
|
|
|
|
if not (res == 1):
|
|
|
|
|
return
|
|
|
|
|
print(f"{url} STP Загрузка репозитория")
|
|
|
|
|
res = download_repo(url, log)
|
|
|
|
|
if res == 0:
|
|
|
|
|
return
|
|
|
|
|
print(f"{url} Анализ репозитория")
|
|
|
|
|
files_with_russian = []
|
|
|
|
|
for root, dirs, files in os.walk(res):
|
|
|
|
|
for file in files:
|
|
|
|
|
file_path = os.path.join(root, file)
|
|
|
|
|
file_ext = os.path.splitext(file_path)[1]
|
2023-11-20 23:01:54 +03:00
|
|
|
|
неинтересноеРасширение = False
|
|
|
|
|
for расш in неинтересныеРасширенияФайлов:
|
|
|
|
|
if file_ext.endswith(расш):
|
|
|
|
|
неинтересноеРасширение = True
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if неинтересноеРасширение:
|
|
|
|
|
continue
|
|
|
|
|
|
2023-11-20 22:29:46 +03:00
|
|
|
|
lexer = None
|
2023-11-20 23:01:54 +03:00
|
|
|
|
if file_ext:
|
|
|
|
|
try:
|
|
|
|
|
lexer = get_lexer_for_filename(file_ext)
|
|
|
|
|
except:
|
|
|
|
|
print(f"{url}...{file_ext} - Лексер не определил язык. ")
|
|
|
|
|
lexer = None
|
|
|
|
|
if lexer is None:
|
|
|
|
|
continue
|
|
|
|
|
if not(lexer.name in интересныеЯзыки):
|
|
|
|
|
НайденЯзыкКоторыйМыНеЗаказывали(lexer.name, url, log, файлДляНезаказанныхЯзыков)
|
|
|
|
|
if (lexer.name in интересныеЯзыки):
|
2023-11-20 22:29:46 +03:00
|
|
|
|
def ИщиРусскиеИменаВТакойКодировке(encoding):
|
|
|
|
|
try:
|
2023-11-20 23:47:14 +03:00
|
|
|
|
with open(file_path, 'r', encoding=encoding) as f:
|
2023-11-20 22:29:46 +03:00
|
|
|
|
content = f.read()
|
|
|
|
|
if not re.search('[а-яА-ЯёЁ]',content):
|
|
|
|
|
return False
|
2023-11-20 23:47:14 +03:00
|
|
|
|
with open(file_path, 'r', encoding=encoding) as f:
|
2023-11-20 23:01:54 +03:00
|
|
|
|
лексемы = pygments.lex(f.read(), lexer)
|
|
|
|
|
for token, value in лексемы:
|
|
|
|
|
# print(token)
|
|
|
|
|
if pygments.token.is_token_subtype(token, pygments.token.Name):
|
2023-11-20 22:29:46 +03:00
|
|
|
|
if re.search('[а-яА-ЯёЁ]', value):
|
2023-11-20 23:47:14 +03:00
|
|
|
|
# аномалия с cp1251, во всяком случае, в минифицированных файлах
|
|
|
|
|
if not (encoding=='cp1251' and value == 'п'):
|
|
|
|
|
return True
|
2023-11-20 22:29:46 +03:00
|
|
|
|
return False
|
|
|
|
|
except:
|
|
|
|
|
print(f"{url} - Ошибка при разборе файла.")
|
2023-11-20 23:47:14 +03:00
|
|
|
|
return None
|
2023-11-20 22:29:46 +03:00
|
|
|
|
|
2023-11-20 23:47:14 +03:00
|
|
|
|
успех = ИщиРусскиеИменаВТакойКодировке('utf-8')
|
|
|
|
|
if успех is None:
|
|
|
|
|
успех = ИщиРусскиеИменаВТакойКодировке('cp1251')
|
|
|
|
|
if успех == True:
|
2023-11-20 22:29:46 +03:00
|
|
|
|
files_with_russian.append(file_path)
|
2023-11-20 23:47:14 +03:00
|
|
|
|
|
2023-11-20 22:29:46 +03:00
|
|
|
|
if len(files_with_russian) == 0:
|
|
|
|
|
log.write(f"{url} - Не обнаруженно файлов содержащих русские символы. \n")
|
|
|
|
|
print(f"{url} - Не обнаруженно файлов содержащих русские символы.")
|
|
|
|
|
else:
|
|
|
|
|
log.write(f"{url} - Русский язык был найден в этом репозитории: {files_with_russian} \n")
|
2023-11-20 23:01:54 +03:00
|
|
|
|
log.flush()
|
2023-11-20 22:29:46 +03:00
|
|
|
|
print(f"{url} - Русский язык был найден в этом репозитории: {files_with_russian}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
log.write(f"{url} - Произошла ошибка: {str(e)} \n")
|
|
|
|
|
print(f"{url} - Произошла ошибка: {str(e)}")
|
|
|
|
|
log.flush()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
# Чтение ссылок из файла
|
2023-11-20 23:01:54 +03:00
|
|
|
|
with open("ЯзыкиКоторыеМыНеЗаказывали.txt", "w") as файлДляНезаказанныхЯзыков:
|
2023-11-20 22:29:46 +03:00
|
|
|
|
with open("repos.txt", "r") as file:
|
|
|
|
|
urls = file.readlines()
|
|
|
|
|
urls = [url.strip() for url in urls]
|
|
|
|
|
with open("log.txt", "w") as log:
|
|
|
|
|
for url in urls:
|
2023-11-20 23:01:54 +03:00
|
|
|
|
analyze_repo(url,log,файлДляНезаказанныхЯзыков)
|
2023-11-20 22:29:46 +03:00
|
|
|
|
|
|
|
|
|
main()
|
|
|
|
|
|