Skip to content

Commit 8a18a5d

Browse files
yurekamiclaude
andcommitted
fix: add support for non-Debian Linux package managers
Added support for multiple Linux distributions: - Arch Linux (pacman) - Gentoo (emerge) - Alpine Linux (apk) - openSUSE (zypper) Also improved error messages when package managers are not found, directing users to documentation for manual installation. Fixes #251 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 4845125 commit 8a18a5d

File tree

1 file changed

+68
-8
lines changed

1 file changed

+68
-8
lines changed

unsloth_zoo/llama_cpp.py

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,27 @@ def use_local_gguf():
145145
def install_package(package, sudo = False, print_output = False, print_outputs = None, system_type = "debian"):
146146
# All Unsloth Zoo code licensed under LGPLv3
147147
# Choose package manager based on system type
148+
sudo_prefix = 'sudo ' if sudo else ''
148149
if system_type == "rpm":
149150
pkg_manager = "yum" if os.path.exists('/usr/bin/yum') else "dnf"
150-
install_cmd = f"{'sudo ' if sudo else ''}{pkg_manager} install {package} -y"
151+
install_cmd = f"{sudo_prefix}{pkg_manager} install {package} -y"
152+
elif system_type == "arch":
153+
install_cmd = f"{sudo_prefix}pacman -S --noconfirm {package}"
154+
elif system_type == "gentoo":
155+
install_cmd = f"{sudo_prefix}emerge --ask=n {package}"
156+
elif system_type == "alpine":
157+
install_cmd = f"{sudo_prefix}apk add {package}"
158+
elif system_type == "suse":
159+
install_cmd = f"{sudo_prefix}zypper install -y {package}"
160+
elif system_type == "unknown":
161+
raise RuntimeError(
162+
f"[FAIL] Unsloth: Could not detect your Linux distribution's package manager.\n"
163+
f"Supported: apt-get (Debian/Ubuntu), yum/dnf (RHEL/Fedora), pacman (Arch), emerge (Gentoo), apk (Alpine), zypper (openSUSE).\n"
164+
f"Please manually install the required package: {package}\n"
165+
f"See: https://docs.unsloth.ai/basics/troubleshooting-and-faqs#how-do-i-manually-save-to-gguf"
166+
)
151167
else: # Default to debian/apt-get
152-
install_cmd = f"{'sudo ' if sudo else ''}apt-get install {package} -y"
168+
install_cmd = f"{sudo_prefix}apt-get install {package} -y"
153169

154170
print(f"Unsloth: Installing packages: {package}")
155171
if not (IS_COLAB_ENVIRONMENT or IS_KAGGLE_ENVIRONMENT):
@@ -170,8 +186,16 @@ def install_package(package, sudo = False, print_output = False, print_outputs =
170186
)
171187
elif line.endswith(COMMANDS_NOT_FOUND):
172188
sp.terminate()
173-
pkg_mgr_name = "yum/dnf" if system_type == "rpm" else "apt-get"
174-
raise RuntimeError(f"[FAIL] Unsloth: {pkg_mgr_name} does not exist when installing {package}? Is this NOT a Linux / Mac based computer?")
189+
pkg_mgr_names = {
190+
"rpm": "yum/dnf", "arch": "pacman", "gentoo": "emerge",
191+
"alpine": "apk", "suse": "zypper", "debian": "apt-get"
192+
}
193+
pkg_mgr_name = pkg_mgr_names.get(system_type, "package manager")
194+
raise RuntimeError(
195+
f"[FAIL] Unsloth: {pkg_mgr_name} does not exist when installing {package}.\n"
196+
f"Please manually install the required packages.\n"
197+
f"See: https://docs.unsloth.ai/basics/troubleshooting-and-faqs#how-do-i-manually-save-to-gguf"
198+
)
175199
elif "Unable to locate package" in line:
176200
sp.terminate()
177201
raise RuntimeError(f"[FAIL] Unsloth: Could not install package {package} since it does not exist.")
@@ -184,15 +208,27 @@ def install_package(package, sudo = False, print_output = False, print_outputs =
184208

185209
def do_we_need_sudo(system_type="debian"):
186210
# All Unsloth Zoo code licensed under LGPLv3
187-
# Check apt-get updating
211+
# Check if we need sudo for package operations
188212
sudo = False
189213
print("Unsloth: Updating system package directories")
190214

191215
# Choose update command based on system type
192216
if system_type == "rpm":
193217
pkg_manager = "yum" if os.path.exists('/usr/bin/yum') else "dnf"
194218
update_cmd = f"{pkg_manager} check-update"
195-
else:
219+
elif system_type == "arch":
220+
update_cmd = "pacman -Sy"
221+
elif system_type == "gentoo":
222+
update_cmd = "emerge --sync"
223+
elif system_type == "alpine":
224+
update_cmd = "apk update"
225+
elif system_type == "suse":
226+
update_cmd = "zypper refresh"
227+
elif system_type == "unknown":
228+
# For unknown systems, skip the update check and assume sudo is needed
229+
print("Unsloth: Unknown Linux distribution, skipping package manager check")
230+
return True
231+
else: # Default to debian/apt-get
196232
update_cmd = "apt-get update -y"
197233

198234
start_time = time.time()
@@ -205,8 +241,16 @@ def do_we_need_sudo(system_type="debian"):
205241
break
206242
elif line.endswith(COMMANDS_NOT_FOUND):
207243
sp.terminate()
208-
pkg_mgr_name = "yum/dnf" if system_type == "rpm" else "apt-get"
209-
raise RuntimeError(f"[FAIL] Unsloth: {pkg_mgr_name} does not exist? Is this NOT a Linux / Mac based computer?")
244+
pkg_mgr_names = {
245+
"rpm": "yum/dnf", "arch": "pacman", "gentoo": "emerge",
246+
"alpine": "apk", "suse": "zypper", "debian": "apt-get"
247+
}
248+
pkg_mgr_name = pkg_mgr_names.get(system_type, "package manager")
249+
raise RuntimeError(
250+
f"[FAIL] Unsloth: {pkg_mgr_name} does not exist.\n"
251+
f"Please manually install the required packages.\n"
252+
f"See: https://docs.unsloth.ai/basics/troubleshooting-and-faqs#how-do-i-manually-save-to-gguf"
253+
)
210254
elif "failure resolving" in line or "Err:" in line:
211255
sp.terminate()
212256
raise RuntimeError("[FAIL] Unsloth: You do not have internet connection!")
@@ -1249,6 +1293,22 @@ def check_linux_type():
12491293
elif any(os.path.exists(f) for f in ['/etc/redhat-release', '/etc/fedora-release']):
12501294
return 'rpm'
12511295

1296+
# Check if it's Arch-based (Arch, Manjaro, EndeavourOS):
1297+
elif os.path.exists('/etc/arch-release') or os.path.exists('/usr/bin/pacman'):
1298+
return 'arch'
1299+
1300+
# Check if it's Gentoo-based:
1301+
elif os.path.exists('/etc/gentoo-release') or os.path.exists('/usr/bin/emerge'):
1302+
return 'gentoo'
1303+
1304+
# Check if it's Alpine-based:
1305+
elif os.path.exists('/etc/alpine-release') or os.path.exists('/sbin/apk'):
1306+
return 'alpine'
1307+
1308+
# Check if it's openSUSE-based:
1309+
elif os.path.exists('/etc/SuSE-release') or os.path.exists('/etc/SUSE-brand'):
1310+
return 'suse'
1311+
12521312
return 'unknown'
12531313
pass
12541314

0 commit comments

Comments
 (0)