Skip to content

Commit d19b06d

Browse files
authored
fix pip
1 parent 7e9ccb2 commit d19b06d

1 file changed

Lines changed: 289 additions & 8 deletions

File tree

lib/util.lua

Lines changed: 289 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,10 @@ function linuxCompile(ctx)
234234
error("python build failed")
235235
end
236236
print("Build python success!")
237+
238+
-- Fix shebang lines in Python scripts after successful build
239+
fixShebangLines(path)
240+
237241
print("Cleaning up ...")
238242
status = os.execute("rm -rf " .. dest_pyenv_path)
239243
if status ~= 0 then
@@ -354,39 +358,316 @@ function parseVersionFromPyenv()
354358
end
355359

356360
local versions = jsonObj.versions;
357-
361+
358362
local numericVersions = {}
359363
local namedVersions = {}
360-
364+
361365
for _, version in ipairs(versions) do
362366
if string.match(version, "^%d") then
363367
table.insert(numericVersions, version)
364368
else
365369
table.insert(namedVersions, version)
366370
end
367371
end
368-
372+
369373
table.sort(numericVersions, function(a, b)
370374
return compare_versions(a, b) > 0
371375
end)
372-
376+
373377
table.sort(namedVersions, function(a, b)
374378
return compare_versions(a, b) > 0
375379
end)
376-
380+
377381
for _, version in ipairs(numericVersions) do
378382
table.insert(result, {
379383
version = version,
380384
note = ""
381385
})
382386
end
383-
387+
384388
for _, version in ipairs(namedVersions) do
385389
table.insert(result, {
386390
version = version,
387391
note = ""
388392
})
389393
end
390-
394+
391395
return result
392-
end
396+
end
397+
398+
-- Fix shebang lines in Python scripts that point to temporary directories
399+
function fixShebangLines(installPath)
400+
return fixShebangForVersion(installPath, nil)
401+
end
402+
403+
-- Fix shebang lines for a specific Python version installation
404+
function fixShebangForVersion(installPath, version)
405+
local versionInfo = version and (" for version " .. version) or ""
406+
print("Fixing shebang lines in Python scripts" .. versionInfo .. "...")
407+
408+
local binPath = installPath .. "/bin"
409+
local pythonExecutable = installPath .. "/bin/python"
410+
411+
-- Check if bin directory exists
412+
local binDirCheck = io.open(binPath, "r")
413+
if not binDirCheck then
414+
print("No bin directory found at " .. binPath .. ", skipping shebang fix")
415+
return false, 0
416+
end
417+
binDirCheck:close()
418+
419+
-- Use find command to get all files in bin directory (macOS compatible)
420+
local findCmd = "find " .. binPath .. " -type f -perm +111 2>/dev/null"
421+
local findResult = io.popen(findCmd)
422+
if not findResult then
423+
print("Could not scan bin directory, skipping shebang fix")
424+
return false, 0
425+
end
426+
427+
local fixedCount = 0
428+
local checkedCount = 0
429+
430+
-- Process each executable file
431+
for filePath in findResult:lines() do
432+
if filePath and filePath ~= "" then
433+
checkedCount = checkedCount + 1
434+
-- Check if it's a Python script by examining the first line
435+
local file = io.open(filePath, "r")
436+
if file then
437+
local firstLine = file:read("*l")
438+
file:close()
439+
440+
-- Check if it has a shebang line pointing to a temporary directory
441+
if firstLine and firstLine:match("^#!/.*%.version%-fox/temp/[^/]+/") then
442+
local filename = filePath:match("([^/]+)$")
443+
print("Fixing shebang in: " .. filename)
444+
if fixSingleShebang(filePath, pythonExecutable) then
445+
fixedCount = fixedCount + 1
446+
end
447+
end
448+
end
449+
end
450+
end
451+
452+
findResult:close()
453+
print("Shebang fix completed" .. versionInfo .. ". Checked " .. checkedCount .. " files, fixed " .. fixedCount .. " files.")
454+
return true, fixedCount
455+
end
456+
457+
-- Fix shebang line in a single file
458+
function fixSingleShebang(filePath, newPythonPath)
459+
-- Read the entire file
460+
local file = io.open(filePath, "r")
461+
if not file then
462+
print("Warning: Could not open file for reading: " .. filePath)
463+
return false
464+
end
465+
466+
local content = file:read("*all")
467+
file:close()
468+
469+
if not content or content == "" then
470+
print("Warning: File is empty: " .. filePath)
471+
return false
472+
end
473+
474+
-- Replace the shebang line - match any path containing .version-fox/temp/
475+
local newContent, replacements = content:gsub("^#!/[^\n]*%.version%-fox/temp/[^/]+/[^\n]*", "#!" .. newPythonPath)
476+
477+
if replacements == 0 then
478+
-- No replacement made, file might not have the problematic shebang
479+
return false
480+
end
481+
482+
-- Create backup of original file
483+
local backupPath = filePath .. ".bak"
484+
local backupFile = io.open(backupPath, "w")
485+
if backupFile then
486+
backupFile:write(content)
487+
backupFile:close()
488+
end
489+
490+
-- Write the file back
491+
local file = io.open(filePath, "w")
492+
if not file then
493+
print("Warning: Could not open file for writing: " .. filePath)
494+
return false
495+
end
496+
497+
file:write(newContent)
498+
file:close()
499+
500+
-- Preserve executable permissions
501+
local chmodResult = os.execute("chmod +x " .. filePath)
502+
if chmodResult ~= 0 then
503+
print("Warning: Could not set executable permissions on: " .. filePath)
504+
end
505+
506+
-- Remove backup file if everything succeeded
507+
os.remove(backupPath)
508+
509+
return true
510+
end
511+
512+
-- Check Python installation health and return detailed status
513+
function checkPythonHealth(installPath, version)
514+
local versionInfo = version and (" " .. version) or ""
515+
print("Checking Python" .. versionInfo .. " installation health...")
516+
517+
local binPath = installPath .. "/bin"
518+
local pythonExecutable = installPath .. "/bin/python"
519+
520+
local healthReport = {
521+
installPath = installPath,
522+
version = version,
523+
binPath = binPath,
524+
pythonExecutable = pythonExecutable,
525+
binDirExists = false,
526+
pythonExists = false,
527+
scriptsChecked = {},
528+
problemsFound = {},
529+
overallHealth = "unknown"
530+
}
531+
532+
-- Check if bin directory exists
533+
local binDirCheck = io.open(binPath, "r")
534+
if not binDirCheck then
535+
healthReport.overallHealth = "critical"
536+
table.insert(healthReport.problemsFound, "Bin directory not found: " .. binPath)
537+
return healthReport
538+
end
539+
binDirCheck:close()
540+
healthReport.binDirExists = true
541+
542+
-- Check if Python executable exists
543+
local pythonCheck = io.open(pythonExecutable, "r")
544+
if not pythonCheck then
545+
healthReport.overallHealth = "critical"
546+
table.insert(healthReport.problemsFound, "Python executable not found: " .. pythonExecutable)
547+
return healthReport
548+
end
549+
pythonCheck:close()
550+
healthReport.pythonExists = true
551+
552+
-- Check critical Python scripts
553+
local criticalScripts = {"pip", "pip3", "easy_install"}
554+
local problemCount = 0
555+
556+
for _, scriptName in ipairs(criticalScripts) do
557+
local scriptPath = binPath .. "/" .. scriptName
558+
local scriptInfo = {
559+
name = scriptName,
560+
path = scriptPath,
561+
exists = false,
562+
executable = false,
563+
shebangOk = false,
564+
shebangLine = ""
565+
}
566+
567+
-- Check if script exists
568+
local scriptFile = io.open(scriptPath, "r")
569+
if scriptFile then
570+
scriptInfo.exists = true
571+
local firstLine = scriptFile:read("*l")
572+
scriptFile:close()
573+
574+
if firstLine then
575+
scriptInfo.shebangLine = firstLine
576+
-- Check if shebang points to temporary directory
577+
if firstLine:match("^#!/.*%.version%-fox/temp/[^/]+/") then
578+
scriptInfo.shebangOk = false
579+
problemCount = problemCount + 1
580+
table.insert(healthReport.problemsFound, scriptName .. " has problematic shebang: " .. firstLine)
581+
else
582+
scriptInfo.shebangOk = true
583+
end
584+
end
585+
586+
-- Check if script is executable
587+
local execCheck = os.execute("test -x " .. scriptPath .. " 2>/dev/null")
588+
scriptInfo.executable = (execCheck == 0)
589+
if not scriptInfo.executable then
590+
problemCount = problemCount + 1
591+
table.insert(healthReport.problemsFound, scriptName .. " is not executable")
592+
end
593+
else
594+
table.insert(healthReport.problemsFound, scriptName .. " not found")
595+
end
596+
597+
table.insert(healthReport.scriptsChecked, scriptInfo)
598+
end
599+
600+
-- Determine overall health
601+
if problemCount == 0 then
602+
healthReport.overallHealth = "healthy"
603+
elseif problemCount <= 2 then
604+
healthReport.overallHealth = "warning"
605+
else
606+
healthReport.overallHealth = "critical"
607+
end
608+
609+
return healthReport
610+
end
611+
612+
-- Fix shebang issues for all installed Python versions
613+
function fixAllPythonVersions(sdkCachePath)
614+
print("Starting batch fix for all Python installations...")
615+
616+
if not sdkCachePath then
617+
print("Error: SDK cache path not provided")
618+
return false
619+
end
620+
621+
local pythonCachePath = sdkCachePath .. "/python"
622+
623+
-- Check if Python cache directory exists
624+
local pythonCacheCheck = io.open(pythonCachePath, "r")
625+
if not pythonCacheCheck then
626+
print("No Python installations found at: " .. pythonCachePath)
627+
return false
628+
end
629+
pythonCacheCheck:close()
630+
631+
-- Find all Python version directories
632+
local findCmd = "find " .. pythonCachePath .. " -maxdepth 1 -type d -name 'v-*' 2>/dev/null"
633+
local findResult = io.popen(findCmd)
634+
if not findResult then
635+
print("Could not scan Python installations directory")
636+
return false
637+
end
638+
639+
local totalFixed = 0
640+
local versionsProcessed = 0
641+
642+
for versionPath in findResult:lines() do
643+
if versionPath and versionPath ~= "" then
644+
local version = versionPath:match("v%-(.+)$")
645+
if version then
646+
versionsProcessed = versionsProcessed + 1
647+
print("\n--- Processing Python " .. version .. " ---")
648+
649+
-- Check health first
650+
local healthReport = checkPythonHealth(versionPath, version)
651+
652+
if healthReport.overallHealth == "healthy" then
653+
print("Python " .. version .. " is healthy, skipping")
654+
else
655+
print("Python " .. version .. " has " .. #healthReport.problemsFound .. " issues, fixing...")
656+
local success, fixedCount = fixShebangForVersion(versionPath, version)
657+
if success then
658+
totalFixed = totalFixed + fixedCount
659+
end
660+
end
661+
end
662+
end
663+
end
664+
665+
findResult:close()
666+
667+
print("\n=== Batch Fix Summary ===")
668+
print("Versions processed: " .. versionsProcessed)
669+
print("Total files fixed: " .. totalFixed)
670+
print("Batch fix completed!")
671+
672+
return true
673+
end

0 commit comments

Comments
 (0)