Skip to content

Commit

Permalink
feat: add ll-convert-tool
Browse files Browse the repository at this point in the history
添加 ll-convert-tool 命令用来提供,转换 deb、appimage、flatpak 的功能。

Log: add command
  • Loading branch information
chenchongbiao committed Dec 27, 2024
1 parent 74166dc commit 89e423a
Show file tree
Hide file tree
Showing 12 changed files with 3,358 additions and 1 deletion.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ install:
install -Dm0755 cmd/ll-pica-flatpak/ll-pica-flatpak ${DESTDIR}/${PREFIX}/${BINARY_DIR}/ll-pica-flatpak
install -Dm0755 cmd/ll-pica-flatpak/ll-pica-flatpak-convert ${DESTDIR}/${PREFIX}/${BINARY_DIR}/ll-pica-flatpak-convert
install -Dm0755 cmd/ll-pica-flatpak/ll-pica-flatpak-utils ${DESTDIR}/${PREFIX}/${BINARY_DIR}/ll-pica-flatpak-utils
install -Dm0755 cmd/ll-convert-tool/ll-convert-tool ${DESTDIR}/${PREFIX}/${BINARY_DIR}/ll-convert-tool

install -d ${DESTDIR}/${PREFIX}/share/linglong/builder/helper/
install -Dm0755 misc/libexec/linglong/builder/helper/install_dep ${DESTDIR}/${PREFIX}/libexec/linglong/builder/helper/install_dep
Expand Down
517 changes: 517 additions & 0 deletions cmd/ll-convert-tool/cli/convert.ab

Large diffs are not rendered by default.

82 changes: 82 additions & 0 deletions cmd/ll-convert-tool/cli/generator.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { echo_info, echo_error, env_const_get } from "std/env"
import { dir_exists, dir_create, file_exists } from "std/fs"

import { get_linglong_convert_tool_name } from "../tools/global.ab"
import { ll_cli_install_by_layer, get_linglong_id, get_linglong_name, get_linglong_version, get_linglong_arch, get_linglong_command, get_linglong_base, get_linglong_runtime, get_linglong_description, get_linglong_package_path, generator_linglong_yaml } from "../core/linglong.ab"

fun help() {
echo("Generate content related to Linglong

Usage:
{get_linglong_convert_tool_name()} generator [target] [flags]

Available Target:
ll-file linglong.yaml

Flags:
-l, --layer linglong layer file
-h, --help help info
")
}

fun generator_linglong_file(layer) {
let layer_with_full_path=trust $readlink -f {layer}$

echo_info("install layer")
ll_cli_install_by_layer(layer_with_full_path)

let package_info = trust $ll-cli info {layer_with_full_path}$
let package_id = get_linglong_id(package_info)
let package_name = get_linglong_name(package_info)
let package_command = get_linglong_command(package_info)
let package_base = get_linglong_base(package_info)
let package_runtime = get_linglong_runtime(package_info)
let package_version = get_linglong_version(package_info)
let package_description = get_linglong_description(package_info)

if not dir_exists(package_id): dir_create(package_id)

let package_path = get_linglong_package_path(package_id)

echo_info("copy package data")
$sudo cp -a {package_path} {package_id}$ failed {
echo_error("copy package data echo_error")
}

echo_info("change {package_id} owner")
let user = trust env_const_get("USER")
$sudo chown -R {user}:{user} {package_id}$ failed {
echo_error("Error in changing the owner of {package_id} to {user}")
}

let linglong_file_path = "{package_id}/linglong.yaml"
if not file_exists(package_id) {
echo_info("generator linglng.yaml")
generator_linglong_yaml(package_id, package_name, package_version, package_description, package_base, package_runtime, package_command, linglong_file_path)
}
}

pub fun generator_cmd(target, layer, is_help) {
if target == "" or is_help == true {
help()
}

if {
target == "ll-file" {
if {
layer != "" {
generator_linglong_file(layer)
}

else {
echo_error("not set flags, please use {get_linglong_convert_tool_name()} generator --help")
}
}
}


else {
echo_error("unknown target: {target}")
}
}
}
51 changes: 51 additions & 0 deletions cmd/ll-convert-tool/core/appimage.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { echo_error, echo_info } from "std/env"
import { text_contains, replace } from "std/text"
import { dir_exists, dir_create } from "std/fs"

pub fun extract_appimage(appimage_path, appimage_extra_dir) {
echo_info("unzip appimage")

let cur_path = trust $pwd$
silent $cd {appimage_extra_dir} && \
chmod +x {appimage_path} && \
{appimage_path} --appimage-extract$ failed {
echo_error("extract appimage echo_error")
}
trust $cd {cur_path}$
}

pub fun copy_appimage_data(appimage_extra_dir, target_path) {
let squashfs_root_path = "{appimage_extra_dir}/squashfs-root"
if dir_exists(squashfs_root_path) {
$cp -a {squashfs_root_path}/* {target_path}$ failed {
echo_error("cp {squashfs_root_path} to {target_path} error")
}
}

if dir_exists("{target_path}/usr"): trust $cp -a {target_path}/usr/* {target_path}/ && rm -rf {target_path}/usr$

let applications_path = "{target_path}/share/applications"
if not dir_exists(applications_path): dir_create(applications_path)

let desktop_path = trust $find {applications_path} -name "*.desktop"$

if desktop_path == "" {
desktop_path = trust $find {target_path} -name "*.desktop"$
// 有人做了软链接,获取实际路径
desktop_path = trust $readlink -f {desktop_path}$
trust $mv {desktop_path} {applications_path}$
}

// 如果是软链接,会读取路径,如果是文件,读取为空
let apprun_list = ["AppRun", "AppRun.wrapped"]
for i, apprun in apprun_list {
let real_apprun = trust $readlink -n {target_path}/{apprun}$
if real_apprun != "" {
if {
text_contains(real_apprun, "usr/bin"): real_apprun = replace(real_apprun, "usr/", "")
}
silent trust $rm {target_path}/{apprun} && ln -s {real_apprun} {target_path}/{apprun}$
}
}

}
39 changes: 39 additions & 0 deletions cmd/ll-convert-tool/core/chroot.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { echo_info } from "std/env"

pub fun mount_chroot(path) {
trust {
$sudo mount -t tmpfs -o \"size=99%\" tmpfs {path}/tmp$
$sudo mount -t tmpfs -o \"size=99%\" tmpfs {path}/var/tmp$
$sudo mount -t proc chproc {path}/proc$
$sudo mount -t sysfs chsys {path}/sys$
$sudo mount --bind /dev {path}/dev$
}
}

pub fun umount_chroot(path) {
loop {
let mount_path = trust $grep -E {path}\"/(dev|proc|sys|tmp|var/tmp)\" /proc/mounts$
if mount_path == "": break

silent trust {
$sudo umount -l --recursive {path}/dev || true$
$sudo umount {path}/proc || true$
$sudo umount {path}/sys || true$
$sudo umount {path}/tmp || true$
$sudo umount {path}/var/tmp || true$
}
}
}

pub fun run_command_in_chroot(rootfs_path, command): Text {
return trust $sudo chroot {rootfs_path} /usr/bin/env bash -e -o pipefail -c \"\
export DEBIAN_FRONTEND=noninteractive && \
unset LC_ALL && \
unset LANG && \
unset LANG_UAGE && \
{command}\"$
}

pub fun chroot_apt_install(rootfs_path, deb): Text {
return run_command_in_chroot(rootfs_path, "apt-get update && apt-get install -y {deb}")
}
66 changes: 66 additions & 0 deletions cmd/ll-convert-tool/core/deb.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { echo_error, echo_warning } from "std/env"
import { echo_info } from "std/env"
import { dir_exists } from "std/fs"

import { tar_extract_cmd } from "../tools/file.ab"

pub fun get_deb_package_name_from_control(control_file): Text {
let package_name = $gawk '/^Package:/ \{ split(\$0,a,\" \"); print a[2]}' {control_file}$ failed {
echo_error("Error in obtaining Package from {control_file}")
}
return package_name
}

pub fun get_deb_version_from_control(control_file): Text {
let version = $gawk '/^Version:/ \{ split(\$0,a,\" \"); print a[2]}' {control_file}$ failed {
echo_error("Error in obtaining Version from {control_file}")
}
return version
}

pub fun get_deb_description_from_control(control_file): Text {
// let description = $gawk '/^Description:/ \{flag=1; next} flag && /^\$/ \{flag=0; print \"\"; next} flag \{print}' {control_file}$ failed {
let description = $gawk '/^Description:/ \{flag=1; print substr(\$0, index(\$0, \$2)); next} flag \{if (\$1 ~ /^[A-Za-z0-9-]+:/) \{flag=0; print ""} else \{print}}' {control_file}$ failed {
echo_error("Error in obtaining Description from {control_file}")
}
return description
}

pub fun extract_deb(deb_path, target_path) {
let control_tar_check=trust $ar t {deb_path} | grep -m 1 "control\.tar"$
let control_extract = tar_extract_cmd(target_path, control_tar_check)
echo_info("unzip deb")
trust $ar p {deb_path} {control_tar_check} | {control_extract}$

let data_tar_check=trust $ar t {deb_path} | grep -m 1 "data\.tar"$
let data_extract = tar_extract_cmd(target_path, data_tar_check)
trust $ar p {deb_path} {data_tar_check} | {data_extract}$
}

// 拷贝deb的数据
pub fun copy_deb_data(deb_extra_dir, target_path) {
let prefix = ""
let deb_opt_apps_path = "{deb_extra_dir}/opt/apps"
if dir_exists(deb_opt_apps_path) {
prefix = trust $ls -1 {deb_opt_apps_path}$
$cp -a {deb_opt_apps_path}/{prefix}/files/* {target_path} &&\
cp -a {deb_opt_apps_path}/{prefix}/entries/* {target_path}/share$ failed {
echo_warning("cp {deb_opt_apps_path}/{prefix} to {target_path} error")
}
}

let deb_usr_path = "{deb_extra_dir}/usr"
if dir_exists(deb_usr_path) {
$cp -a {deb_usr_path}/* {target_path}$ failed {
echo_warning("cp {deb_usr_path} to {target_path} error")
}
}

let deb_opt_path = "{deb_extra_dir}/opt/"
if dir_exists(deb_opt_path) and not dir_exists(deb_opt_apps_path) {
prefix = trust $ls -1 {deb_opt_path}$
$cp -a {deb_opt_path}/{prefix}/* {target_path}$ failed {
echo_warning("cp {deb_opt_path}/{prefix} to {target_path} error")
}
}
}
Loading

0 comments on commit 89e423a

Please sign in to comment.