@@ -482,6 +482,172 @@ install_package_file() {
482482 return 0
483483}
484484
485+ #
486+ # Install a package from local .pkg file
487+ #
488+ install_local_package_file () {
489+ local pkg_file=" $1 "
490+ local force=" $2 "
491+
492+ if [ ! -f " $pkg_file " ]; then
493+ print_error " Package file not found: $pkg_file "
494+ return 1
495+ fi
496+
497+ # Verify it's a .pkg file
498+ if ! echo " $pkg_file " | grep -q ' \.pkg$' ; then
499+ print_error " File must have .pkg extension: $pkg_file "
500+ return 1
501+ fi
502+
503+ print_info " Installing from local file: $pkg_file "
504+
505+ # Create a temporary extraction directory
506+ local temp_extract=" $TEMP_DIR /extract_$$ "
507+ mkdir -p " $temp_extract "
508+
509+ # Extract the package to temporary directory
510+ if ! tar -xf " $pkg_file " -C " $temp_extract " 2> /dev/null; then
511+ print_error " Failed to extract: $pkg_file "
512+ rm -rf " $temp_extract "
513+ return 1
514+ fi
515+
516+ local package_name=" "
517+
518+ # Try to get package name from manifest first
519+ if [ -f " $temp_extract /+MANIFEST" ]; then
520+ package_name=$( jq -r ' .name // empty' " $temp_extract /+MANIFEST" 2> /dev/null)
521+ if [ -n " $package_name " ]; then
522+ print_info " Detected package name from manifest: $package_name "
523+ fi
524+ fi
525+
526+ # If no manifest or no name in manifest, extract from filename
527+ if [ -z " $package_name " ]; then
528+ local filename
529+ filename=$( basename " $pkg_file " .pkg)
530+ # Remove version information (everything after last dash followed by digit)
531+ package_name=$( echo " $filename " | sed ' s/-[0-9].*$//' )
532+ if [ -n " $package_name " ]; then
533+ print_info " Detected package name from filename: $package_name "
534+ fi
535+ fi
536+
537+ if [ -z " $package_name " ]; then
538+ print_error " Could not determine package name from manifest or filename"
539+ rm -rf " $temp_extract "
540+ return 1
541+ fi
542+
543+ # Check if package is already installed
544+ if is_package_installed " $package_name " ; then
545+ if [ " $force " -eq 1 ]; then
546+ print_warning " Package already installed: $package_name (forcing reinstall)"
547+ # Remove only the main package files (not dependencies)
548+ print_info " Removing existing package files: $package_name "
549+ if ! remove_package_files " $package_name " ; then
550+ print_warning " Failed to remove some existing files for: $package_name "
551+ fi
552+ # Remove from installed list
553+ remove_from_installed " $package_name "
554+ # Remove manifest file
555+ rm -f " $MANIFESTS_DIR /${package_name} .manifest"
556+ else
557+ print_warning " Package already installed: $package_name (use --force to reinstall)"
558+ rm -rf " $temp_extract "
559+ return 0
560+ fi
561+ fi
562+
563+ print_info " Extracting: $package_name "
564+
565+ # Save the manifest file for future removal
566+ if [ -f " $temp_extract /+MANIFEST" ]; then
567+ cp " $temp_extract /+MANIFEST" " $MANIFESTS_DIR /${package_name} .manifest"
568+ fi
569+
570+ # Move files from usr/local/* to ~/.lilith/*
571+ if [ -d " $temp_extract /usr/local" ]; then
572+ # Copy files, preserving directory structure
573+ (cd " $temp_extract /usr/local" && tar -cf - .) | (cd " $LILITH_DIR " && tar -xf -)
574+
575+ # Create symlinks for shared libraries in subdirectories
576+ create_library_symlinks
577+ fi
578+
579+ # Clean up
580+ rm -rf " $temp_extract "
581+
582+ # Get package info from manifest for installed packages list
583+ local package_fullname=" $package_name "
584+ local manifest_file=" $MANIFESTS_DIR /${package_name} .manifest"
585+ if [ -f " $manifest_file " ]; then
586+ local manifest_name
587+ manifest_name=$( jq -r ' .name // empty' " $manifest_file " 2> /dev/null)
588+ if [ -n " $manifest_name " ]; then
589+ package_fullname=" $manifest_name "
590+ fi
591+ fi
592+
593+ add_to_installed " $package_fullname " " $package_name "
594+
595+ print_success " Successfully installed from local file: $package_name "
596+ return 0
597+ }
598+
599+ #
600+ # Install a package from local .pkg file (command interface)
601+ #
602+ cmd_install_local () {
603+ local pkg_file=" "
604+ local force=0
605+
606+ # Parse arguments
607+ while [ $# -gt 0 ]; do
608+ case " $1 " in
609+ --force)
610+ force=1
611+ ;;
612+ -h | --help)
613+ print_info " Usage: lilith install-local [options] <package_file.pkg>"
614+ print_info " Install a package from a local .pkg archive file."
615+ print_info " Options:"
616+ print_info " --force Force reinstall if package is already installed"
617+ print_info " -h, --help Show this help message"
618+
619+ return 0
620+ ;;
621+ -* )
622+ print_error " Unknown option: $1 "
623+ return 1
624+ ;;
625+ * )
626+ pkg_file=" $1 "
627+ ;;
628+ esac
629+ shift
630+ done
631+
632+ if [ -z " $pkg_file " ]; then
633+ print_error " Package file required"
634+ print_info " Usage: lilith install-local [options] <package_file.pkg>"
635+ print_info " Use 'lilith install-local --help' for more information"
636+ return 1
637+ fi
638+
639+ if ! init_lilith_dir; then
640+ return 1
641+ fi
642+
643+ # Install the package from local file
644+ if ! install_local_package_file " $pkg_file " " $force " ; then
645+ return 1
646+ fi
647+
648+ return 0
649+ }
650+
485651#
486652# Install a package and its dependencies
487653#
@@ -1069,6 +1235,8 @@ COMMANDS:
10691235 install [options] <package> Install a package and its dependencies
10701236 Options: --full-deps (install all dependencies)
10711237 --no-deps (skip dependencies)
1238+ install-local [options] <file> Install a package from a local .pkg file
1239+ Options: --force (force reinstall if already installed)
10721240 update <package> Update a package to the latest version
10731241 remove [options] <package> Remove a package from the system
10741242 Options: --force (remove even if required by others)
@@ -1163,6 +1331,14 @@ main() {
11631331 show_environment_setup
11641332 fi
11651333 ;;
1334+ install-local)
1335+ shift
1336+ if cmd_install_local " $@ " ; then
1337+ # Show environment setup instructions only after successful installation
1338+ print_info " "
1339+ show_environment_setup
1340+ fi
1341+ ;;
11661342 update)
11671343 cmd_update " $2 "
11681344 ;;
0 commit comments