mirror of
https://github.com/tp7309/TTDeDroid.git
synced 2026-10-29 05:46:34 +08:00
343 lines
11 KiB
Python
343 lines
11 KiB
Python
#!/usr/bin python3
|
|
# library update helper
|
|
|
|
import subprocess
|
|
import shutil
|
|
import stat
|
|
import os
|
|
import glob
|
|
from typing import Tuple
|
|
import zipfile
|
|
import showjar
|
|
import urllib.request
|
|
import ssl
|
|
import json
|
|
import re
|
|
from datetime import datetime, timedelta
|
|
|
|
|
|
_ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
|
|
_SOURCE_DIR = os.path.join(_ROOT_PATH, 'sources')
|
|
|
|
_last_update_time = datetime.now()
|
|
|
|
|
|
def sh(command, print_msg=True):
|
|
p = subprocess.Popen(
|
|
command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
bytes_result = p.stdout.read()
|
|
try:
|
|
result = bytes_result.decode('utf-8')
|
|
except Exception:
|
|
# fix some window system error
|
|
result = bytes_result.decode('gbk')
|
|
if print_msg:
|
|
print(result)
|
|
return result
|
|
|
|
|
|
def run(command):
|
|
print(command + '...')
|
|
subprocess.call(command, shell=True)
|
|
|
|
|
|
def ensure_dir(dirpath):
|
|
if not os.path.exists(dirpath):
|
|
os.makedirs(dirpath)
|
|
|
|
|
|
def readonly_handler(func, path, execinfo):
|
|
# or os.chmod(path, stat.S_IWRITE) from "stat" module
|
|
os.chmod(path, stat.S_IWRITE)
|
|
func(path)
|
|
|
|
|
|
def rmtree(path):
|
|
if os.path.exists(path):
|
|
if os.path.isdir(path):
|
|
shutil.rmtree(path, onerror=readonly_handler)
|
|
else:
|
|
os.remove(path)
|
|
|
|
|
|
def copy_git_repo(src, dest):
|
|
app_ignore = shutil.ignore_patterns('build', '.git', '.gradle', '.idea', '*.idea')
|
|
overwrite_tree(src, dest, ignore=app_ignore)
|
|
|
|
|
|
def lastest_tag():
|
|
return sh("git describe --tags --abbrev=0")
|
|
|
|
|
|
def gradle_path():
|
|
return 'gradlew' if os.name == 'nt' else './gradlew'
|
|
|
|
|
|
def ensure_repo(origin_url, dirname):
|
|
if os.path.exists(dirname):
|
|
os.chdir(os.path.join(_SOURCE_DIR, dirname))
|
|
print("changed dir to %s"%(os.getcwd()))
|
|
run('git reset --hard HEAD')
|
|
run('git pull --rebase')
|
|
else:
|
|
run("git clone --depth=1 %s"%(origin_url))
|
|
os.chdir(os.path.join(_SOURCE_DIR, dirname))
|
|
print("changed dir to %s"%(os.getcwd()))
|
|
|
|
|
|
def overwrite_tree(src, dest, ignore=None):
|
|
if os.path.isdir(src):
|
|
if not os.path.isdir(dest):
|
|
os.makedirs(dest)
|
|
files = os.listdir(src)
|
|
if ignore is not None:
|
|
ignored = ignore(src, files)
|
|
else:
|
|
ignored = set()
|
|
for f in files:
|
|
if f not in ignored:
|
|
overwrite_tree(os.path.join(src, f),
|
|
os.path.join(dest, f),
|
|
ignore)
|
|
else:
|
|
shutil.copyfile(src, dest)
|
|
|
|
|
|
def download_file(url, store_path):
|
|
print("found download url: %s, download file to: %s"%(url, store_path))
|
|
|
|
def reporthook(a, b, c):
|
|
print("\rdownloading: %5.1f%%" % (a * b * 100.0 / c), end="")
|
|
try:
|
|
if url.lower().startswith('http'):
|
|
req = urllib.request.Request(url)
|
|
else:
|
|
raise ValueError from None
|
|
urllib.request.urlretrieve(req.get_full_url(), store_path, reporthook=reporthook)
|
|
if not os.path.exists(store_path):
|
|
print("download file failed: %s"%(store_path))
|
|
return False
|
|
except Exception as e:
|
|
print("download file error:")
|
|
print(e)
|
|
return True
|
|
|
|
|
|
def download_release(repo_owner, repo_name, last_update_time, refile, destpath):
|
|
"""download lastest release file from github"""
|
|
url = "https://api.github.com/repos/%s/%s/releases/latest"%(repo_owner, repo_name)
|
|
try:
|
|
print("download_release: %s/%s, min_publish_time: %s, destpath: %s"
|
|
% (repo_owner, repo_name, last_update_time, destpath))
|
|
response = ''
|
|
if url.lower().startswith('http'):
|
|
req = urllib.request.Request(url)
|
|
else:
|
|
raise ValueError from None
|
|
with urllib.request.urlopen(req.get_full_url()) as f:
|
|
response = json.loads(f.read().decode('utf-8'))
|
|
publish_time = datetime.strptime(response['published_at'], '%Y-%m-%dT%H:%M:%SZ')
|
|
# debug
|
|
# publish_time = datetime.strptime('2023-02-20T11:33:37Z', '%Y-%m-%dT%H:%M:%SZ')
|
|
print("min_publish_time: %s, repo publish time: %s"%(str(last_update_time), str(publish_time)))
|
|
if publish_time.timetuple() <= last_update_time.timetuple():
|
|
print("ignore update '%s/%s'"%(repo_owner, repo_name))
|
|
return
|
|
browser_download_url = ''
|
|
for asset in response['assets']:
|
|
browser_download_url = asset['browser_download_url']
|
|
if re.search(refile, browser_download_url):
|
|
break
|
|
if not browser_download_url:
|
|
print("can not find download url %s/%s"%(repo_owner, repo_name))
|
|
return
|
|
store_path = os.path.join(_SOURCE_DIR, os.path.basename(browser_download_url))
|
|
if not download_file(browser_download_url, store_path):
|
|
return
|
|
|
|
# # unzip file
|
|
rmtree(showjar.CACHE_DIR)
|
|
if store_path.endswith('.zip'):
|
|
with zipfile.ZipFile(store_path, 'r') as z:
|
|
z.extractall(showjar.CACHE_DIR)
|
|
overwrite_tree(showjar.CACHE_DIR, destpath)
|
|
else:
|
|
destpath2 = destpath
|
|
if os.path.isdir(destpath):
|
|
destpath2 = os.path.join(destpath, os.path.basename(store_path))
|
|
shutil.copyfile(store_path, destpath2)
|
|
|
|
except Exception as e:
|
|
print("download release error:")
|
|
print(e)
|
|
|
|
|
|
def dex2jar_updater():
|
|
print("---------------------------dex2jar_updater start---------------------------")
|
|
rawdir = os.getcwd()
|
|
os.chdir(_SOURCE_DIR)
|
|
ensure_repo('https://github.com/pxb1988/dex2jar.git', 'dex2jar')
|
|
os.chdir(os.path.join(_SOURCE_DIR, 'dex2jar'))
|
|
|
|
run("git checkout 2.x")
|
|
run("%s clean distZip"%(gradle_path()))
|
|
|
|
distzipdir = os.path.join('dex-tools', 'build', 'distributions')
|
|
distzips = glob.glob("%s/dex-tools*.zip"%(distzipdir))
|
|
if distzips:
|
|
rmtree(showjar.CACHE_DIR)
|
|
with zipfile.ZipFile(distzips[0], 'r') as z:
|
|
z.extractall(showjar.CACHE_DIR)
|
|
src = os.path.join(showjar.CACHE_DIR, os.listdir(showjar.CACHE_DIR)[0])
|
|
overwrite_tree(src, showjar.DEX2JAR)
|
|
os.chdir(rawdir)
|
|
|
|
|
|
def enjarify_updater():
|
|
print("---------------------------enjarify_updater start---------------------------")
|
|
rawdir = os.getcwd()
|
|
os.chdir(_SOURCE_DIR)
|
|
ensure_repo('https://github.com/Storyyeller/enjarify.git', 'enjarify')
|
|
os.chdir(os.path.join(_SOURCE_DIR, 'enjarify'))
|
|
src = os.path.join(_SOURCE_DIR, 'enjarify')
|
|
copy_git_repo(src, showjar.ENJARIFY)
|
|
# delete tests/
|
|
rmtree(os.path.join(showjar.ENJARIFY, 'tests'))
|
|
# 升级enjarify.bat中python3为python
|
|
batpath = os.path.join(showjar.ENJARIFY, 'enjarify.bat')
|
|
content = ''
|
|
with open(batpath, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
with open(batpath, 'w', encoding='utf-8') as f:
|
|
content = content.replace('python3 ', 'python ')
|
|
content = content.replace('py -3 ', 'python ')
|
|
f.write(content)
|
|
|
|
os.chdir(rawdir)
|
|
|
|
|
|
def jadx_updater():
|
|
print("---------------------------jadx_updater start---------------------------")
|
|
# webbrowser.open_new_tab("https://github.com/skylot/jadx/releases")
|
|
download_release('skylot', 'jadx', _last_update_time, r'jadx-\d.+\.zip', showjar.JADX)
|
|
|
|
rawdir = os.getcwd()
|
|
os.chdir(showjar.JADX)
|
|
|
|
# remove unused files
|
|
rmtree('README.md')
|
|
rmtree('NOTICE')
|
|
rmtree('LICENSE')
|
|
print("\n")
|
|
|
|
# update jadx script config, fix issues #7.
|
|
def update_jvm_opts(script_path):
|
|
script_path = os.path.abspath(script_path)
|
|
if not script_path.startswith(showjar.JADX):
|
|
return
|
|
print("update_jvm_opts: %s"%(script_path))
|
|
content = ''
|
|
with open(script_path, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
content = content.replace('"-XX:MaxRAMPercentage=70.0"', '')
|
|
with open(script_path, 'w', encoding='utf-8') as f:
|
|
f.write(content)
|
|
|
|
update_jvm_opts('bin/jadx')
|
|
update_jvm_opts('bin/jadx-gui')
|
|
update_jvm_opts('bin/jadx-gui.bat')
|
|
update_jvm_opts('bin/jadx.bat')
|
|
|
|
os.chdir(rawdir)
|
|
|
|
|
|
def apktool_updater():
|
|
print("---------------------------apktool_updater start---------------------------")
|
|
# webbrowser.open_new_tab("https://ibotpeaches.github.io/Apktool/")
|
|
download_release('iBotPeaches', 'Apktool', _last_update_time, r'apktool-\d.+\.jar', showjar.APKTOOL)
|
|
|
|
|
|
def fernflower_updater():
|
|
print("---------------------------fernflower_updater start---------------------------")
|
|
rawdir = os.getcwd()
|
|
os.chdir(_SOURCE_DIR)
|
|
maven_version = sh("mvn -v")
|
|
if "not found" in maven_version or "无法将" in maven_version:
|
|
print("please configure maven first!")
|
|
return
|
|
ensure_dir(os.path.join(_SOURCE_DIR, 'fernflower'))
|
|
os.chdir(os.path.join(_SOURCE_DIR, 'fernflower'))
|
|
# Try to resolve a concrete latest version from JetBrains metadata instead of using LATEST
|
|
version = 'LATEST'
|
|
try:
|
|
metadata_url_https = (
|
|
"https://www.jetbrains.com/intellij-repository/releases/"
|
|
"com/jetbrains/intellij/java/java-decompiler-engine/maven-metadata.xml"
|
|
)
|
|
metadata_url_http = metadata_url_https.replace("https://", "http://")
|
|
try:
|
|
meta = urllib.request.urlopen(metadata_url_https, context=ssl._create_unverified_context()).read().decode('utf-8')
|
|
except Exception:
|
|
meta = urllib.request.urlopen(metadata_url_http).read().decode('utf-8')
|
|
|
|
m = re.search(r"<release>([^<]+)</release>", meta)
|
|
if m:
|
|
version = m.group(1)
|
|
else:
|
|
m = re.search(r"<latest>([^<]+)</latest>", meta)
|
|
if m:
|
|
version = m.group(1)
|
|
else:
|
|
vs = re.findall(r"<version>([^<]+)</version>", meta)
|
|
if vs:
|
|
version = vs[-1]
|
|
except Exception as e:
|
|
print("could not fetch maven metadata, falling back to LATEST: %s" % e)
|
|
|
|
artifact = "com.jetbrains.intellij.java:java-decompiler-engine:%s" % version
|
|
run("mvn dependency:get -DremoteRepositories=jetbrains::default::https://www.jetbrains.com/intellij-repository/releases/ -Dartifact=%s -Ddest=." % artifact)
|
|
jars = glob.glob("%s/%s" % (os.getcwd(), "java-decompiler-engine*.jar"))
|
|
jar = None
|
|
if jars:
|
|
jar = jars[0]
|
|
else:
|
|
# fallback: check local maven repository
|
|
m2_path = os.path.expanduser(os.path.join('~', '.m2', 'repository'))
|
|
local_jar = os.path.join(m2_path, 'com', 'jetbrains', 'intellij', 'java', 'java-decompiler-engine', version, 'java-decompiler-engine-%s.jar' % version)
|
|
if os.path.exists(local_jar):
|
|
jar = local_jar
|
|
if not jar:
|
|
print("expected jar is not found!")
|
|
return
|
|
print("latest jar: %s"%(jar))
|
|
shutil.copyfile(jar, showjar.fernflowerpath())
|
|
os.chdir(rawdir)
|
|
|
|
|
|
def initEnv():
|
|
ensure_dir(_SOURCE_DIR)
|
|
|
|
global _last_update_time
|
|
readme_path = os.path.join(_ROOT_PATH, 'README.md')
|
|
with open(readme_path, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
datestring = re.search(r"update\sat\s(\d+-\d+-\d+)", content)
|
|
_last_update_time = datetime.strptime(datestring.group(1), '%Y-%m-%d')
|
|
|
|
# debug code
|
|
_last_update_time = _last_update_time - timedelta(days=0)
|
|
print("last update time: %s"%(_last_update_time))
|
|
|
|
|
|
def main():
|
|
initEnv()
|
|
enjarify_updater()
|
|
dex2jar_updater()
|
|
jadx_updater()
|
|
apktool_updater()
|
|
fernflower_updater()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|