mirror of
https://github.com/kiviktnm/decman.git
synced 2026-09-19 12:08:28 +00:00
Run flatpak commands on users with UID>=1000
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
# Decman
|
||||
|
||||
> 🎉 Support for Flatpaks was just added! 🎉
|
||||
> By default flatpak management this feature is disabled. Take a look at the example to learn how to use flatpaks. You can install to the user as well as the system installation.
|
||||
> 🎉 Early support for Flatpaks was just added! 🎉
|
||||
> By default flatpak management is disabled. Support is in early stages so expect bugs.
|
||||
|
||||
> 🎉 Decman now has a AUR package! 🎉
|
||||
>
|
||||
> To start using the AUR package simply add `decman` to `decman.aur_packages`. To ensure a smooth change, add decman-git to ignored_packages during the conversion.
|
||||
>
|
||||
> ```py
|
||||
> import decman
|
||||
> decman.aur_packages += ["decman"]
|
||||
> decman.ignored_packages += ["decman-git"]
|
||||
> import decman.config
|
||||
> decman.config.enable_flatpak = True
|
||||
> # You can add system wide packages as well as user packages
|
||||
> decman.flatpak_packages += ["org.signal.Signal"]
|
||||
> decman.flatpak_user_packages["user"] = decman.flatpak_user_packages.get("user", [])
|
||||
> decman.flatpak_user_packages["user"].append("dev.zed.Zed")
|
||||
> ```
|
||||
|
||||
Decman is a declarative package & configuration manager for Arch Linux. It allows you to manage installed packages, your dotfiles, enabled systemd units, and run commands automatically. Your system is configured using python so your configuration can be very adaptive.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# from import is ok for importing classes and functions
|
||||
# just remember to not import variables this way
|
||||
from typing import override
|
||||
from decman import Module, File, Directory, UserPackage, sh, prg
|
||||
|
||||
from decman import Directory, File, Module, UserPackage, prg, sh
|
||||
|
||||
|
||||
class MyModule(Module):
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
# This example covers all decman features and many useful ways of configuring a system.
|
||||
# Configuration can be as simple or as complex as is needed.
|
||||
|
||||
import socket
|
||||
import os
|
||||
import socket
|
||||
|
||||
# Note: Do NOT use from imports for global variables
|
||||
# BAD: from decman import packages/modules/etc
|
||||
@@ -10,7 +10,7 @@ import decman
|
||||
import decman.config
|
||||
|
||||
# This is fine since the thing being imported is a class and not a global variable.
|
||||
from decman import UserPackage, File, Directory, UserRaisedError
|
||||
from decman import Directory, File, UserPackage, UserRaisedError
|
||||
|
||||
# Flatpaks are disabled by default. This way no already installed flatpaks will get suddenly deleted.
|
||||
decman.config.enable_flatpak = True
|
||||
|
||||
+37
-32
@@ -5,11 +5,10 @@ Module containing the CLI Application.
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import pwd
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import traceback
|
||||
import pwd
|
||||
|
||||
import decman
|
||||
import decman.config as conf
|
||||
@@ -291,7 +290,7 @@ class Core:
|
||||
|
||||
l.print_list("Removing pacman packages:", to_remove)
|
||||
|
||||
if conf.enable_flatpak:
|
||||
if conf.enable_flatpak and self.update_flatpaks:
|
||||
l.print_list("Removing flatpak packages:", to_remove_flatpak)
|
||||
self._remove_user_flatpaks(only_print=True)
|
||||
|
||||
@@ -306,20 +305,15 @@ class Core:
|
||||
self._remove_user_flatpaks()
|
||||
|
||||
def _remove_user_flatpaks(self, only_print: bool = False):
|
||||
"""
|
||||
# get all users through a command instead of pwd because pwd also lists all 'virtual' users. add root since they can also have user installed packages
|
||||
users = (
|
||||
subprocess.run(["users"], check=True, stdout=subprocess.PIPE)
|
||||
.stdout.decode()
|
||||
.strip()
|
||||
.split("\n")
|
||||
)
|
||||
print()
|
||||
users.append("root")"""
|
||||
|
||||
users = pwd.getpwall()
|
||||
# Get all non system users (users that have uid >= 1000), also ignore nobody
|
||||
users = [
|
||||
u.pw_name
|
||||
for u in pwd.getpwall()
|
||||
if u.pw_uid >= 1000 and u.pw_name not in ("nobody",)
|
||||
]
|
||||
# Add root to users
|
||||
users.append("root")
|
||||
for user in users:
|
||||
user = user.pw_name
|
||||
currently_installed_flatpak = self.flatpak.get_installed(
|
||||
as_user=True, which_user=user
|
||||
)
|
||||
@@ -353,7 +347,18 @@ class Core:
|
||||
|
||||
# flatpak
|
||||
if conf.enable_flatpak and self.update_flatpaks:
|
||||
l.print_summary("Upgrading flatpak packages.")
|
||||
self.flatpak.upgrade()
|
||||
users = [
|
||||
u.pw_name
|
||||
for u in pwd.getpwall()
|
||||
if u.pw_uid >= 1000 and u.pw_name not in ("nobody",)
|
||||
]
|
||||
# Add root to users
|
||||
users.append("root")
|
||||
for user in users:
|
||||
l.print_summary(f"Upgrading flatpak packages for {user}.")
|
||||
self.flatpak.upgrade(True, user)
|
||||
|
||||
def _install_pkgs(self):
|
||||
"""
|
||||
@@ -373,13 +378,15 @@ class Core:
|
||||
|
||||
l.print_list("Installing pacman packages:", to_install_pacman)
|
||||
|
||||
if conf.enable_flatpak:
|
||||
l.print_list("Installing flatpak packages:", to_install_flatpak)
|
||||
self._install_user_flatpaks(only_print=True)
|
||||
|
||||
# fpm prints a summary so no need to print it twice
|
||||
if self.only_print:
|
||||
l.print_list("Installing foreign packages:", to_install_fpm)
|
||||
|
||||
if conf.enable_flatpak and self.update_flatpaks:
|
||||
l.print_list("Installing flatpak packages:", to_install_flatpak)
|
||||
|
||||
if self.only_print:
|
||||
self._install_user_flatpaks(only_print=True)
|
||||
return
|
||||
|
||||
self.pacman.install(to_install_pacman)
|
||||
@@ -388,22 +395,20 @@ class Core:
|
||||
|
||||
if conf.enable_flatpak and self.update_flatpaks:
|
||||
self.flatpak.install(to_install_flatpak)
|
||||
# Print summary before the action
|
||||
self._install_user_flatpaks(only_print=True)
|
||||
self._install_user_flatpaks()
|
||||
|
||||
def _install_user_flatpaks(self, only_print: bool = False):
|
||||
"""# get all users through a command instead of pwd because pwd also lists all 'virtual' users. add root since they can also have user installed packages
|
||||
users = (
|
||||
subprocess.run(["users"], check=True, stdout=subprocess.PIPE)
|
||||
.stdout.decode()
|
||||
.strip()
|
||||
.split("\n")
|
||||
)
|
||||
users.append("root")"""
|
||||
|
||||
users = pwd.getpwall()
|
||||
|
||||
# Get all non system users (users that have uid >= 1000), also ignore nobody
|
||||
users = [
|
||||
u.pw_name
|
||||
for u in pwd.getpwall()
|
||||
if u.pw_uid >= 1000 and u.pw_name not in ("nobody",)
|
||||
]
|
||||
# Add root to users
|
||||
users.append("root")
|
||||
for user in users:
|
||||
user = user.pw_name
|
||||
currently_installed_flatpak = self.flatpak.get_installed(
|
||||
as_user=True, which_user=user
|
||||
)
|
||||
|
||||
+15
-2
@@ -102,7 +102,13 @@ class Commands:
|
||||
"""
|
||||
Updates all installed flatpak REFs including runtimes and dependencies.
|
||||
"""
|
||||
return ["flatpak", "update", "-y", "--user" if as_user else "--system"]
|
||||
return [
|
||||
"flatpak",
|
||||
"update",
|
||||
"--noninteractive",
|
||||
"-y",
|
||||
"--user" if as_user else "--system",
|
||||
]
|
||||
|
||||
def remove(self, pkgs: list[str]) -> list[str]:
|
||||
"""
|
||||
@@ -115,7 +121,13 @@ class Commands:
|
||||
"""
|
||||
Running this command will remove the listed REFs. Unused dependencies might be kept, but to remove them another command needs to be run.
|
||||
"""
|
||||
return ["flatpak", "remove", "-y", "--user" if as_user else "--system"] + pkgs
|
||||
return [
|
||||
"flatpak",
|
||||
"remove",
|
||||
"--noninteractive",
|
||||
"-y",
|
||||
"--user" if as_user else "--system",
|
||||
] + pkgs
|
||||
|
||||
def remove_unused_flatpak(self, as_user: bool = False) -> list[str]:
|
||||
"""
|
||||
@@ -124,6 +136,7 @@ class Commands:
|
||||
return [
|
||||
"flatpak",
|
||||
"remove",
|
||||
"--noninteractive",
|
||||
"-y",
|
||||
"--unused",
|
||||
"--user" if as_user else "--system",
|
||||
|
||||
@@ -5,11 +5,11 @@ Library module for decman.
|
||||
import json
|
||||
import os
|
||||
import pty
|
||||
import pwd
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
import typing
|
||||
import pwd
|
||||
|
||||
import decman
|
||||
import decman.config as conf
|
||||
@@ -1035,7 +1035,9 @@ class Flatpak:
|
||||
user_facing_msg=f"Failed to get installed flatpak packages using '{error.cmd}'. Output: {error.stdout}."
|
||||
) from error
|
||||
|
||||
def install(self, packages: list[str], as_user: bool = False, which_user: str = ""):
|
||||
def install(
|
||||
self, packages: list[str], as_user: bool = False, which_user: str = "root"
|
||||
):
|
||||
"""
|
||||
Install the listed flatpak packages.
|
||||
"""
|
||||
@@ -1053,7 +1055,6 @@ class Flatpak:
|
||||
proc = subprocess.run(
|
||||
conf.commands.install_flatpak_pkgs(packages, as_user),
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
user=uinfo[0],
|
||||
group=uinfo[1],
|
||||
env=user_env if as_user else env,
|
||||
@@ -1064,19 +1065,33 @@ class Flatpak:
|
||||
f"Failed to install flatpak packages. Process exited with code {proc.returncode}."
|
||||
)
|
||||
|
||||
def upgrade(self) -> None:
|
||||
def upgrade(self, as_user: bool = False, which_user: str = "root") -> None:
|
||||
"""
|
||||
Upgrade all flatpak packages.
|
||||
"""
|
||||
uinfo: tuple[int, int] = (0, 0)
|
||||
if as_user:
|
||||
uinfo = get_user_info(which_user)
|
||||
|
||||
env = os.environ.copy()
|
||||
user_env = env.copy()
|
||||
user_env["HOME"] = os.path.expanduser(f"~{which_user}")
|
||||
|
||||
proc = subprocess.run(
|
||||
conf.commands.upgrade_flatpak(), check=True, stdout=subprocess.PIPE
|
||||
conf.commands.upgrade_flatpak(as_user=True),
|
||||
check=True,
|
||||
user=uinfo[0],
|
||||
group=uinfo[1],
|
||||
env=user_env if as_user else env,
|
||||
)
|
||||
if not proc.returncode == 0:
|
||||
raise err.UserFacingError(
|
||||
f"Failed to upgrade flatpak packages. Process exited with code {proc.returncode}."
|
||||
)
|
||||
|
||||
def remove(self, packages: list[str], as_user: bool = False, which_user: str = ""):
|
||||
def remove(
|
||||
self, packages: list[str], as_user: bool = False, which_user: str = "root"
|
||||
):
|
||||
"""
|
||||
Remove all the listed packages and their unused dependecies. This has to happen in two steps.
|
||||
"""
|
||||
@@ -1094,7 +1109,6 @@ class Flatpak:
|
||||
proc = subprocess.run(
|
||||
conf.commands.remove_flatpak(packages, as_user),
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
user=uinfo[0],
|
||||
group=uinfo[1],
|
||||
env=user_env if as_user else env,
|
||||
@@ -1108,7 +1122,6 @@ class Flatpak:
|
||||
proc = subprocess.run(
|
||||
conf.commands.remove_unused_flatpak(as_user),
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
user=uinfo[0] if as_user else 0,
|
||||
group=uinfo[1] if as_user else 0,
|
||||
env=user_env if as_user else env,
|
||||
|
||||
Reference in New Issue
Block a user