Skip to content

Commit 68dbc09

Browse files
committed
Add support for installing packages from local .pkg files
1 parent 8bf07d2 commit 68dbc09

File tree

2 files changed

+178
-0
lines changed

2 files changed

+178
-0
lines changed

lilith/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ COMMANDS:
4747
install [options] <package> Install a package and its dependencies
4848
Options: --full-deps (install all dependencies)
4949
--no-deps (skip dependencies)
50+
install-local [options] <file> Install a package from a local .pkg file
51+
Options: --force (force reinstall if already installed)
5052
update <package> Update a package to the latest version
5153
remove [options] <package> Remove a package from the system
5254
Options: --force (remove even if required by others)

lilith/lilith.sh

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)