85 lines
4 KiB
Python
85 lines
4 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
Patch PKTransaction.cpp to add verbose logging so we can diagnose
|
||
|
|
why installs hang on "Installing..." status.
|
||
|
|
"""
|
||
|
|
import sys
|
||
|
|
|
||
|
|
def replace_once(src, old, new, label):
|
||
|
|
count = src.count(old)
|
||
|
|
if count != 1:
|
||
|
|
print(f"ERROR: '{label}' matched {count} times (expected 1)", file=sys.stderr)
|
||
|
|
sys.exit(1)
|
||
|
|
return src.replace(old, new)
|
||
|
|
|
||
|
|
path = sys.argv[1]
|
||
|
|
with open(path) as f:
|
||
|
|
src = f.read()
|
||
|
|
|
||
|
|
# 1. trigger(): log what phase we're entering and with what flags
|
||
|
|
src = replace_once(src,
|
||
|
|
'void PKTransaction::trigger(PackageKit::Transaction::TransactionFlags flags)\n{',
|
||
|
|
'void PKTransaction::trigger(PackageKit::Transaction::TransactionFlags flags)\n{\n'
|
||
|
|
' qWarning() << "[DISCOVER] trigger(): flags=" << flags << "role=" << role();',
|
||
|
|
'trigger() header'
|
||
|
|
)
|
||
|
|
|
||
|
|
# 2. statusChanged(): log the raw PK status instead of the collapsed UI status
|
||
|
|
src = replace_once(src,
|
||
|
|
'void PKTransaction::statusChanged()\n{'
|
||
|
|
'\n setStatus(m_trans->status() == PackageKit::Transaction::StatusDownload ? Transaction::DownloadingStatus : Transaction::CommittingStatus);',
|
||
|
|
'void PKTransaction::statusChanged()\n{'
|
||
|
|
'\n qWarning() << "[DISCOVER] statusChanged(): pk_status=" << m_trans->status()'
|
||
|
|
' << "percentage=" << m_trans->percentage()'
|
||
|
|
' << "lastPackage=" << m_trans->lastPackage();'
|
||
|
|
'\n setStatus(m_trans->status() == PackageKit::Transaction::StatusDownload ? Transaction::DownloadingStatus : Transaction::CommittingStatus);',
|
||
|
|
'statusChanged() body'
|
||
|
|
)
|
||
|
|
|
||
|
|
# 3. progressChanged(): log when percentage updates (or fails to)
|
||
|
|
src = replace_once(src,
|
||
|
|
' auto percent = m_trans->percentage();\n if (percent == 101) {\n qWarning() << "percentage cannot be calculated";',
|
||
|
|
' auto percent = m_trans->percentage();\n'
|
||
|
|
' qWarning() << "[DISCOVER] progressChanged(): raw_pct=" << percent << "pk_status=" << m_trans->status();\n'
|
||
|
|
' if (percent == 101) {\n qWarning() << "percentage cannot be calculated";',
|
||
|
|
'progressChanged() body'
|
||
|
|
)
|
||
|
|
|
||
|
|
# 4. cleanup(): log the exit/cancel/failed/simulate flags
|
||
|
|
src = replace_once(src,
|
||
|
|
'void PKTransaction::cleanup(PackageKit::Transaction::Exit exit, uint runtime)\n{',
|
||
|
|
'void PKTransaction::cleanup(PackageKit::Transaction::Exit exit, uint runtime)\n{\n'
|
||
|
|
' const bool _simulate_flag = m_trans && (m_trans->transactionFlags() & PackageKit::Transaction::TransactionFlagSimulate);\n'
|
||
|
|
' qWarning() << "[DISCOVER] cleanup(): exit=" << exit << "runtime=" << runtime'
|
||
|
|
' << "simulate=" << _simulate_flag'
|
||
|
|
' << "proceedFunctions=" << m_proceedFunctions.size();',
|
||
|
|
'cleanup() header'
|
||
|
|
)
|
||
|
|
|
||
|
|
# 5. errorFound(): log every error, including ones currently silently swallowed
|
||
|
|
src = replace_once(src,
|
||
|
|
'void PKTransaction::errorFound(PackageKit::Transaction::Error err, const QString &error)\n{'
|
||
|
|
'\n if (err == PackageKit::Transaction::ErrorNoLicenseAgreement || err == PackageKit::Transaction::ErrorTransactionCancelled'
|
||
|
|
'\n || err == PackageKit::Transaction::ErrorNotAuthorized) {'
|
||
|
|
'\n return;\n }',
|
||
|
|
'void PKTransaction::errorFound(PackageKit::Transaction::Error err, const QString &error)\n{'
|
||
|
|
'\n qWarning() << "[DISCOVER] errorFound(): err=" << err << "detail=" << error;'
|
||
|
|
'\n if (err == PackageKit::Transaction::ErrorNoLicenseAgreement || err == PackageKit::Transaction::ErrorTransactionCancelled'
|
||
|
|
'\n || err == PackageKit::Transaction::ErrorNotAuthorized) {'
|
||
|
|
'\n return;\n }',
|
||
|
|
'errorFound() body'
|
||
|
|
)
|
||
|
|
|
||
|
|
# 6. LocalFilePKResource path: log the .deb path being installed
|
||
|
|
src = replace_once(src,
|
||
|
|
' m_trans = PackageKit::Daemon::installFile(QUrl(app->packageName()).toLocalFile(), flags);',
|
||
|
|
' qWarning() << "[DISCOVER] installFile():" << QUrl(app->packageName()).toLocalFile() << "flags=" << flags;\n'
|
||
|
|
' m_trans = PackageKit::Daemon::installFile(QUrl(app->packageName()).toLocalFile(), flags);',
|
||
|
|
'installFile() call'
|
||
|
|
)
|
||
|
|
|
||
|
|
with open(path, 'w') as f:
|
||
|
|
f.write(src)
|
||
|
|
|
||
|
|
print(f"Patched {path}")
|