Compare commits

..
1 Commits
Author SHA1 Message Date
Murphy 8c0577ad14 Create codeql-analysis.yml 2022-03-15 11:22:46 +01:00
21 changed files with 286 additions and 1248 deletions

No files matched your search

BIN
View File
Binary file not shown.
+1 -12
View File
@@ -36,17 +36,6 @@ jobs:
run: pip install -r requirements/test.txt
- name: Run
run: tox -e py38-codecheck-flake8
unit-tests:
name: linux-unit-tests
runs-on: ubuntu-20.04
continue-on-error: true
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install dependencies
run: pip install -r requirements/test.txt
- name: Run
run: tox -e py38-tests
integration-tests:
name: linux-integration-tests
runs-on: ubuntu-20.04
@@ -74,7 +63,7 @@ jobs:
release-job:
name: Publish package
runs-on: ubuntu-20.04
needs: [integration-tests, unit-tests, flake8, pylint]
needs: [integration-tests, flake8, pylint]
if: github.event_name == 'release' && github.event.action == 'published'
steps:
- name: Checkout
-1
View File
@@ -1,4 +1,3 @@
.coverage
.idea
**/__pycache__/
venv
-2
View File
@@ -4,8 +4,6 @@ disable=
C0116, # Missing function or method docstring (missing-function-docstring)
C0115, # Missing class docstring (missing-class-docstring)
R0913, # Too many arguments (7/5) (too-many-arguments)
W0511, # TODO (fixme)
C0103, # invalid-name
[FORMAT]
max-line-length=120
+3 -4
View File
@@ -1,8 +1,7 @@
PYTHON?=python3
PIP?=pip3
all:
$(PIP) install .
pip install .
pub:
rm -rf dist
@@ -10,9 +9,9 @@ pub:
twine upload --repository=pypi --verbose dist/*
install:
$(PIP) install .
pip install .
uninstall:
$(PIP) uninstall r2env
pip uninstall r2env
.PHONY: all clean pub install uninstall
-132
View File
@@ -83,138 +83,6 @@
"deb_x64": "radare2_5.5.0_amd64.deb"
}
},
{
"id": "5.5.2",
"packages": {
"w32": "radare2-5.5.2-w32.zip",
"w64": "radare2-5.5.2-w64.zip",
"mac_x64": "radare2-5.5.2-amd64.pkg",
"mac_arm64": "radare2-5.5.2-m1.pkg",
"deb_i386": "radare2_5.5.2_i386.deb",
"deb_x64": "radare2_5.5.2_amd64.deb"
}
},
{
"id": "5.5.4",
"packages": {
"w32": "radare2-5.5.4-w32.zip",
"w64": "radare2-5.5.4-w64.zip",
"mac_x64": "radare2-5.5.4-amd64.pkg",
"mac_arm64": "radare2-5.5.4-m1.pkg",
"deb_i386": "radare2_5.5.4_i386.deb",
"deb_x64": "radare2_5.5.4_amd64.deb"
}
},
{
"id": "5.6.0",
"packages": {
"w32": "radare2-5.6.0-w32.zip",
"w64": "radare2-5.6.0-w64.zip",
"mac_x64": "radare2-5.6.0-amd64.pkg",
"mac_arm64": "radare2-5.6.0-m1.pkg",
"deb_i386": "radare2_5.6.0_i386.deb",
"deb_x64": "radare2_5.6.0_amd64.deb"
}
},
{
"id": "5.6.2",
"packages": {
"w32": "radare2-5.6.2-w32.zip",
"w64": "radare2-5.6.2-w64.zip",
"mac_x64": "radare2-5.6.2-amd64.pkg",
"mac_arm64": "radare2-5.6.2-m1.pkg",
"deb_i386": "radare2_5.6.2_i386.deb",
"deb_x64": "radare2_5.6.2_amd64.deb"
}
},
{
"id": "5.6.4",
"packages": {
"w32": "radare2-5.6.4-w32.zip",
"w64": "radare2-5.6.4-w64.zip",
"mac_x64": "radare2-5.6.4-amd64.pkg",
"mac_arm64": "radare2-5.6.4-m1.pkg",
"deb_i386": "radare2_5.6.4_i386.deb",
"deb_x64": "radare2_5.6.4_amd64.deb"
}
},
{
"id": "5.6.6",
"packages": {
"w32": "radare2-5.6.6-w32.zip",
"w64": "radare2-5.6.6-w64.zip",
"mac_x64": "radare2-5.6.6-amd64.pkg",
"mac_arm64": "radare2-5.6.6-m1.pkg",
"deb_i386": "radare2_5.6.6_i386.deb",
"deb_x64": "radare2_5.6.6_amd64.deb"
}
},
{
"id": "5.6.8",
"packages": {
"w32": "radare2-5.6.8-w32.zip",
"w64": "radare2-5.6.8-w64.zip",
"mac_x64": "radare2-5.6.8-amd64.pkg",
"mac_arm64": "radare2-5.6.8-m1.pkg",
"deb_i386": "radare2_5.6.8_i386.deb",
"deb_x64": "radare2_5.6.8_amd64.deb"
}
},
{
"id": "5.7.0",
"packages": {
"w32": "radare2-5.7.0-w32.zip",
"w64": "radare2-5.7.0-w64.zip",
"mac_x64": "radare2-5.7.0-amd64.pkg",
"mac_arm64": "radare2-5.7.0-m1.pkg",
"deb_i386": "radare2_5.7.0_i386.deb",
"deb_x64": "radare2_5.7.0_amd64.deb"
}
},
{
"id": "5.7.2",
"packages": {
"w32": "radare2-5.7.2-w32.zip",
"w64": "radare2-5.7.2-w64.zip",
"mac_x64": "radare2-5.7.2-amd64.pkg",
"mac_arm64": "radare2-5.7.2-m1.pkg",
"deb_i386": "radare2_5.7.2_i386.deb",
"deb_x64": "radare2_5.7.2_amd64.deb"
}
},
{
"id": "5.7.4",
"packages": {
"w32": "radare2-5.7.4-w32.zip",
"w64": "radare2-5.7.4-w64.zip",
"mac_x64": "radare2-5.7.4-amd64.pkg",
"mac_arm64": "radare2-5.7.4-m1.pkg",
"deb_i386": "radare2_5.7.4_i386.deb",
"deb_x64": "radare2_5.7.4_amd64.deb"
}
},
{
"id": "5.7.6",
"packages": {
"w32": "radare2-5.7.6-w32.zip",
"w64": "radare2-5.7.6-w64.zip",
"mac_x64": "radare2-5.7.6-amd64.pkg",
"mac_arm64": "radare2-5.7.6-m1.pkg",
"deb_i386": "radare2_5.7.6_i386.deb",
"deb_x64": "radare2_5.7.6_amd64.deb"
}
},
{
"id": "5.7.8",
"packages": {
"w32": "radare2-5.7.8-w32.zip",
"w64": "radare2-5.7.8-w64.zip",
"mac_x64": "radare2-5.7.8-amd64.pkg",
"mac_arm64": "radare2-5.7.8-m1.pkg",
"deb_i386": "radare2_5.7.8_i386.deb",
"deb_x64": "radare2_5.7.8_amd64.deb"
}
},
{
"id": "git",
"packages": {}
+55 -68
View File
@@ -4,14 +4,11 @@ import os
import shutil
import json
import sys
from pathlib import Path
import re
from dploy import stow, unstow
from r2env.exceptions import R2EnvException
from r2env.package_manager import PackageManager
from r2env.tools import print_console, load_json_file, WARNING, ERROR, host_platform
from r2env.tools import print_console, load_json_file, WARNING, ERROR
class R2Env:
@@ -26,16 +23,16 @@ class R2Env:
def init(self):
if os.path.isdir(self._r2env_path):
print_console(f"[x] r2env already initialized. Path {self._r2env_path} already exists.", ERROR)
print_console("[x] r2env already initialized. Path {} already exists.".format(self._r2env_path), ERROR)
return
os.mkdir(self._r2env_path)
print_console(f"[*] r2env initialized at {self._r2env_path}")
print_console("[*] r2env initialized at {}".format(self._r2env_path))
def get_r2_path(self):
self.check_if_r2env_initialized()
self.exit_if_r2env_not_initialized()
r2_version = self._get_current_version()
r2_path = self._package_manager.get_package_path(r2_version) if r2_version else "Radare package not configured"
print_console(f" [*] {r2_version} ({r2_path})")
print_console(" [*] {0} ({1})".format(r2_version, r2_path))
def show_config(self):
print_console("[*] Current r2env config:")
@@ -49,100 +46,88 @@ class R2Env:
print_console("- Available")
packages = self._package_manager.list_available_packages()
for profile in packages:
print_console(f" - {profile}:", WARNING)
print_console(" - {}:".format(profile), WARNING)
for version in packages[profile]['versions']:
dists = ", ".join(version['packages'].keys())
print_console(f" - {profile}@{version['id']} - {dists}", formatter=1)
print_console(" - {}@{} - {}".format(profile, version['id'], dists), formatter=1)
def list_installed_packages(self):
self.check_if_r2env_initialized()
self.exit_if_r2env_not_initialized()
print_console("- Installed")
for pkg in self._package_manager.list_installed_packages():
if pkg == self._get_current_version():
print_console(f" - {pkg} (in use)")
print_console(" - {} (in use)".format(pkg))
else:
print_console(f" - {pkg}")
print_console(" - {}".format(pkg))
def install(self, package, **kwargs):
self.check_if_r2env_initialized()
use_meson = kwargs["use_meson"] if "use_meson" in kwargs else False
use_dist = kwargs["use_dist"] if "use_dist" in kwargs else False
if "@" not in package:
package = f"{package}@git"
def install(self, package, use_meson=False, use_dist=False):
self.exit_if_r2env_not_initialized()
if not self._check_package_format(package):
raise R2EnvException("[x] Invalid package format.")
print_console("[x] Invalid package format.", level=ERROR)
return
try:
profile, version = package.split('@')
except ValueError:
except:
profile = package
version = "git"
self._package_manager.install_package(profile, version, use_meson=use_meson, use_dist=use_dist)
print_console("[*] Add $HOME/.r2env/bin to your PATH or use 'r2env shell'.")
def uninstall(self, package, **kwargs):
self.check_if_r2env_initialized()
use_dist = kwargs["use_dist"] if "use_dist" in kwargs else False
def uninstall(self, package, use_meson, use_dist):
self.exit_if_r2env_not_initialized()
if not self._check_package_format(package):
raise R2EnvException("[x] Invalid package format.")
print_console("[x] Invalid package format.", level=ERROR)
return
self._package_manager.uninstall_package(package, use_dist)
def purge(self):
print_console(f"[*] Removing {self._r2env_path}")
print("Removing " + self._r2env_path)
shutil.rmtree(self._r2env_path)
def use(self, package=None, **_kwargs):
self.check_if_r2env_initialized()
def use(self, package=None):
self.exit_if_r2env_not_initialized()
if not package:
print_console("[x] Package not defined.", ERROR)
self.list_installed_packages()
raise R2EnvException("Package not defined.")
if package not in self._package_manager.list_installed_packages():
raise R2EnvException(f"Package {package} not installed.")
return
cur_ver = self._get_current_version()
new_dst_dir = self._package_manager.get_package_path(package)
if cur_ver:
unstow([self._package_manager.get_package_path(cur_ver)], self._r2env_path)
stow([new_dst_dir], self._r2env_path)
self._set_current_version(package)
print_console(f"[*] Using {package} package")
print_console("[*] Using {} package".format(package))
@staticmethod
def version():
thispath = os.path.dirname(os.path.realpath(__file__))
with open(f"{thispath}/version.txt", "r", encoding="utf-8") as version:
print_console(version.read())
with open(thispath + "/version.txt", "r") as version:
return version.read()
def shell(self, cmd=None, **_kwargs):
bin_path = os.path.join(self._r2env_path, "bin")
if host_platform() == "windows":
os.system(f"set PATH={bin_path};%PATH% && cmd")
def shell(self, cmd=""):
if os.name== "nt":
os.system("set PATH="+self._r2env_path+"\\bin;%PATH% && cmd")
return True
pkgconfig_path = os.path.join(self._r2env_path, "lib", "pkgconfig")
bin_path = os.path.join(self._r2env_path, "bin")
export_ps1 = f"export PS1=\"r2env ({self._get_current_version()})\\$ \";"
export_pkg_config = f"export PKG_CONFIG_PATH=\"{pkgconfig_path}\";"
export_path = f"export PATH=\"{bin_path}:$PATH\";"
cmd_shell = "$SHELL -f"
full_cmd = export_ps1 + export_pkg_config + export_path + cmd_shell
if host_platform() == "android": # hack for pre-dtag builds of r2
library_path = os.path.join(self._r2env_path, "lib")
full_cmd = f"export LD_LIBRARY_PATH=\"{library_path}\";" + full_cmd
if host_platform() == "osx":
library_path = os.path.join(self._r2env_path, "lib")
# XXX this doesnt work on sip-enabled macs, that's why we use install_name_tool after install
full_cmd = f"export DYLD_LIBRARY_PATH=\"{library_path}\";" + full_cmd
if cmd is None:
return os.system(full_cmd) == 0
return os.system(f"{full_cmd} -c '{cmd}'") == 0
line = "export PS1=\"r2env\\$ \";export PKG_CONFIG_PATH=\""
line = line + self._r2env_path+"/lib/pkgconfig\";export PATH=\""
line = line + self._r2env_path + "/bin:$PATH\"; $SHELL -f"
if os.path.isfile("/default.prop"): # hack for pre-dtag builds of r2
line = "export LD_LIBRARY_PATH=\"" + self._r2env_path + "/lib\";" + line
if os.uname().sysname == "Darwin":
line = "export DYLD_LIBRARY_PATH=\"" + self._r2env_path + "/lib\";" + line
if cmd.strip() == "":
return os.system(line)
return os.system(line + " -c '" + cmd + "'")
@staticmethod
def _load_config():
filename = os.path.join(os.path.dirname(__file__), 'config', 'config.json')
config = load_json_file(filename)
environment_path = os.getenv("R2ENV_PATH")
if environment_path is not None:
config["r2env_path"] = environment_path
ep = os.getenv("R2ENV_PATH")
if ep is not None:
config["r2env_path"] = ep
if not config:
config = {}
sys.exit(-1)
return config
@staticmethod
@@ -152,24 +137,26 @@ class R2Env:
@staticmethod
def _check_package_format(package):
regexp = r"[a-z0-9]+@(\d\.\d\.\d|git)"
if not package:
return False
return re.search(regexp, package) is not None
if package == "":
return True
return True
# regexp = re.compile(r"\w+\d@(?:\d\.\d\.\d|git)")
# return regexp.match(package)
def _get_current_version(self):
version_file = os.path.join(self._r2env_path, self.VERSION_FILE)
if not os.path.isfile(version_file):
return ''
with open(version_file, 'r', encoding="utf-8") as file_desc:
with open(version_file, 'r') as file_desc:
version = file_desc.read()
return version
def _set_current_version(self, package):
version_file = os.path.join(self._r2env_path, self.VERSION_FILE)
with open(version_file, 'w', encoding="utf-8") as file_desc:
with open(version_file, 'w') as file_desc:
file_desc.write(package)
def check_if_r2env_initialized(self):
def exit_if_r2env_not_initialized(self):
if not os.path.isdir(self._r2env_path):
raise R2EnvException("Not r2env initialized. Execute 'r2env init' first.")
print_console("Not r2env initialized. Execute 'r2env init' first.", ERROR)
sys.exit(-1)
-10
View File
@@ -1,10 +0,0 @@
class R2EnvException(Exception):
pass
class ActionException(R2EnvException):
pass
class PackageManagerException(R2EnvException):
pass
+98 -118
View File
@@ -2,21 +2,19 @@
import os
import shutil
import time
from urllib.error import URLError
import zipfile
import wget
import sys
import time
from zipfile import ZipFile
from r2env.exceptions import PackageManagerException
from r2env.tools import load_json_file, git_fetch, git_clean, print_console, ERROR, exit_if_not_exists, host_distname
class PackageManager:
LOG_DIR = "log"
PACKAGES_DIR = "versions"
SOURCE_DIR = "src"
DOWNLOAD_URL = "https://github.com/radareorg/radare2/releases/download/"
def __init__(self, r2env_path):
self._packages = self._load_profiles()
@@ -42,15 +40,14 @@ class PackageManager:
filename = os.path.join(os.path.dirname(__file__), 'config', 'profiles.json')
profiles = load_json_file(filename)
if not profiles:
raise PackageManagerException("No profiles configured.")
sys.exit(-1)
return profiles
def install_package(self, profile, version, use_meson, use_dist):
log_path = os.path.join(self._r2env_path, self.LOG_DIR)
timestamp = round(time.monotonic() * 1000)
logfile = os.path.join(log_path, f"{profile}_{version}_{timestamp}_build.txt")
logfile = os.path.join(log_path, "{}_{}_{}_build.txt".format(profile, version, round(time.monotonic() * 1000)))
source_path = os.path.join(os.path.join(self._r2env_path, self.SOURCE_DIR, profile))
dst_dir = os.path.join(os.path.join(self._r2env_path, self.PACKAGES_DIR), f"{profile}@{version}")
dst_dir = os.path.join(os.path.join(self._r2env_path, self.PACKAGES_DIR), "{}@{}".format(profile, version))
if not os.path.isdir(log_path):
os.makedirs(log_path)
if not os.path.isdir(source_path):
@@ -59,18 +56,17 @@ class PackageManager:
os.makedirs(dst_dir)
self._exit_if_package_not_available(profile, version)
if use_dist:
if self._install_from_dist(profile, version):
print_console(f"[*] Binary package {profile}@{version} installed successfully")
if self._install_from_dist(profile, version, source_path, dst_dir, logfile, use_meson=use_meson):
print_console("[*] Binary package {}@{} installed successfully".format(profile, version))
else:
raise PackageManagerException(f"[x] Failed to install {profile}@{version}.")
print_console("Error.")
elif self._build_from_source(profile, version, source_path, dst_dir, logfile, use_meson=use_meson):
print_console("[*] Package {}@{} installed successfully".format(profile, version))
else:
if self._build_from_source(profile, version, source_path, dst_dir, logfile, use_meson=use_meson):
print_console(f"[*] Package {profile}@{version} installed successfully")
else:
if os.path.isdir(dst_dir):
shutil.rmtree(dst_dir)
raise PackageManagerException(f"[x] Failed to build {profile}@{version}. "
f"Check {logfile} for more information.")
print_console("[x] Something wrong happened during the build process. Check {} for more information.".format
(logfile), level=ERROR)
if os.path.isdir(dst_dir):
shutil.rmtree(dst_dir)
def uninstall_package(self, package_name, use_dist):
pkg_found = False
@@ -78,19 +74,18 @@ class PackageManager:
if package_name == package:
pkg_found = True
if use_dist:
profile, version = package.split("@")
self._uninstall_from_dist(profile, version)
kv = package.split("@")
self._uninstall_from_dist(kv[0], kv[1])
else:
pkg_dir = os.path.join(self._r2env_path, self.PACKAGES_DIR, package)
pkg_dir = os.path.join(os.path.join(self._r2env_path, self.PACKAGES_DIR), package_name)
try:
shutil.rmtree(pkg_dir)
print_console(f"[-] Removed package {package_name}")
print_console("Removed package {}".format(package_name))
except OSError as err:
raise PackageManagerException(f"[x] Unable to remove package {package_name}. Error: {err}") \
from err
print_console("[x] Unable to remove package {0}. Error: {1}".format(package_name, err), ERROR)
break
if not pkg_found:
raise PackageManagerException(f"[x] Unable to find installed package {package_name}")
print_console("[x] Unable to find installed package {0}".format(package_name), ERROR)
def _get_pkgname(self, profile, version, cos):
for pkgv in self._packages[profile]["versions"]:
@@ -101,85 +96,82 @@ class PackageManager:
return None
def _get_disturl(self, profile, version, cos):
pkgname = self._get_pkgname(profile, version, cos)
if pkgname is not None:
return "/".join([self.DOWNLOAD_URL, version, pkgname])
gh = "https://github.com/radareorg/radare2/releases/download/"
f = self._get_pkgname(profile, version, cos)
if f is not None:
return "/".join([gh, version, f])
return None
def _install_from_dist(self, profile, version):
print_console(f"[*] Installing {profile}@{version} package from binary dist")
dist_name = host_distname()
disturl = self._get_disturl(profile, version, dist_name)
pkgname = self._get_pkgname(profile, version, dist_name)
pkgfile = "/".join([self._r2env_path, "src", pkgname])
def _install_from_dist(self, profile, version, source_path, dst_path, logfile, use_meson=False):
print_console("[*] Installing {}@{} package from binary dist".format(profile, version))
dn = host_distname()
disturl = self._get_disturl(profile, version, dn)
pkgname = self._get_pkgname(profile, version, dn)
ofile = "/".join([self._r2env_path, "src", pkgname])
# os.system("wget -O " + ofile + " -qc " + disturl)
wget.download(disturl, ofile);
try:
wget.download(disturl, pkgfile)
except (URLError, ConnectionResetError) as err:
raise PackageManagerException(f"Failed to download {profile} package. Error: {err}") from err
# TODO: check package checksum
if dist_name in ("mac_x64", "mac_arm64"):
return os.system(f"sudo installer -pkg {pkgfile} -target /") == 0
if dist_name in "w64":
return self._install_windows_package(pkgfile)
if dist_name in ("deb_x64", "deb_i386"):
return os.system(f"sudo dpkg -i {pkgfile}") == 0
if dist_name in "android": # termux
return os.system("apt install radare2") == 0
raise PackageManagerException(f"Operative System not supported: {os.uname()}")
def _install_windows_package(self, pkgfile):
try:
with zipfile.ZipFile(pkgfile, 'r') as zip_file:
zip_file.extractall()
dst_folder = os.path.sep.join([self._r2env_path, "bin"])
if not os.path.isdir(dst_folder):
os.makedirs(dst_folder, 493) # 0755)
for file_path in zip_file.namelist():
if file_path.endswith(".exe") or file_path.endswith(".dll") and file_path.find("bin") != -1:
file_name = os.path.basename(file_path)
dst_filepath = os.path.sep.join([dst_folder, file_name])
shutil.copyfile(file_path, dst_filepath)
print_console(f"[-] Copying {file_path}")
radare2_bin_file_path = os.path.sep.join([self._r2env_path, "bin", "radare2.exe"])
r2_bin_file_path = os.path.sep.join([self._r2env_path, "bin", "r2.exe"])
shutil.copyfile(radare2_bin_file_path, r2_bin_file_path)
sysname = os.uname().sysname
except:
sysname = "Windows"
# TODO: checksum
if sysname == "Darwin":
if os.system("sudo installer -pkg " + ofile + " -target /") == 0:
return True
except (FileNotFoundError, IOError) as err:
print_console(f"[x] An error occurred when installing {pkgfile}. Error: {err}", level=ERROR)
self._uninstall_from_dist("radare2", "latest")
raise PackageManagerException(f"Unable to install Windows package {pkgfile}.") from err
if sysname == "Windows":
with ZipFile(ofile, 'r') as z:
z.extractall()
dst = os.path.sep.join([self._r2env_path, "bin"])
for f in z.namelist():
if f.endswith(".exe") or f.endswith(".dll") and f.find("bin") != -1:
fname = os.path.basename(f)
d = os.path.sep.join([dst, fname])
dname = os.path.dirname(d)
if not os.path.isdir(dname):
os.makedirs(dname, 493) # 0755)
shutil.copyfile(f, d)
print(f)
f = os.path.sep.join([self._r2env_path, "bin", "radare2.exe"])
d = os.path.sep.join([self._r2env_path, "bin", "r2.exe"])
shutil.copyfile(f, d)
if sysname == "Linux" and os.path.exists("/usr/bin/dpkg"):
if os.system("sudo dpkg -i " + ofile) == 0:
return True
if os.path.isfile("/default.prop"): # termux
if os.system("apt install radare2") == 0:
return True
return False
return False
def _uninstall_from_dist(self, profile, version):
print_console(f"[*] Cleaning {profile}@{version} package from binary dist")
dist_name = host_distname()
if dist_name in "w64":
dst = os.path.sep.join([self._r2env_path, "bin"])
print_console(f"[*] Removing {dst}")
try:
shutil.rmtree(dst)
return True
except OSError as err:
raise PackageManagerException(f"An issue occurred while removing {dst}. Error: {err}") from err
if dist_name in ("mac_x64", "mac_arm64"):
result_code = 0
print_console("[*] Uninstalling {}@{} package from binary dist".format(profile, version))
try:
sysname = os.uname().sysname
except:
sysname = "Windows"
if sysname == "Darwin":
pkgname = "org.radare.radare2"
result_code += os.system("pkgutil --pkg-info " + pkgname)
result_code += os.system(f"cd / && pkgutil --only-files --files {pkgname} | "
f"tr '\\n' '\\0' | xargs -n 1 -0 sudo rm -f")
result_code += os.system(f"cd / && pkgutil --only-dirs --files {pkgname} | "
f"tail -r | tr '\\n' '\\0' | xargs -n 1 -0 sudo rmdir 2>/dev/null")
result_code += os.system(f"sudo pkgutil --forget {pkgname}")
return result_code == 0
if dist_name in ("deb_x64", "deb_i386"):
return os.system("sudo dpkg -r " + profile) == 0
if dist_name in "android": # termux
return os.system("sudo dpkg -r radare2") == 0
raise PackageManagerException(f"Operative System not supported: {os.uname()}")
os.system("pkgutil --pkg-info " + pkgname)
os.system("cd / && pkgutil --only-files --files "+pkgname+" | tr '\\n' '\\0' | xargs -n 1 -0 sudo rm -f")
os.system("cd / && pkgutil --only-dirs --files "+pkgname+" | tail -r | tr '\\n' '\\0' | xargs -n 1 -0 sudo rmdir 2>/dev/null")
os.system("sudo pkgutil --forget " + pkgname)
if sysname == "Linux" and os.path.exists("/usr/bin/dpkg"):
try:
pkgname = profile.split("@")[0]
except:
pkgname = profile
if os.system("sudo dpkg -r " + pkgname) == 0:
return True
if os.path.isfile("/default.prop"): # termux
if os.system("sudo dpkg -r radare2") == 0:
return True
return False
return True
def _build_from_source(self, profile, version, source_path, dst_path, logfile, use_meson=False):
exit_if_not_exists(['git'])
print_console(f"[*] Installing {profile}@{version} package from source")
print_console(f"[-] Cloning {version} version")
print_console("[*] Installing {}@{} package from source".format(profile, version))
print_console("[-] Cloning {} version".format(version))
git_fetch(self._packages[profile]["source"], version, source_path)
print_console("[-] Cleaning Repo")
git_clean(source_path)
@@ -190,36 +182,23 @@ class PackageManager:
@staticmethod
def _build_using_acr(source_path, dst_path, logfile, r2env_path):
"""Only works in Unix systems"""
if host_distname() in "w64":
raise PackageManagerException("acr is not supported on Windows platform. Use meson instead.")
exit_if_not_exists(['make'])
print_console("[-] Building package using acr...")
extra_flags = ""
if os.path.isfile("/default.prop"):
extra_flags = " --with-compiler=termux"
config_path = r2env_path + "/lib/pkgconfig"
cmd = f"(export PKG_CONFIG_PATH=\"{config_path}\";" \
f"cd {source_path} && " \
f"rm -rf shlr/capstone && " \
f"./configure {extra_flags} --with-rpath --prefix={dst_path} 2>&1 && " \
f"make -j4 2>&1 && " \
f"make install) > {logfile}"
print_console(f"Executing {cmd}")
cmd = "(export PKG_CONFIG_PATH=\"{4}\";cd {0} && rm -rf shlr/capstone && ./configure {1}" \
" --with-rpath --prefix={2} 2>&1 && make -j4 2>&1" \
"&& make install) > {3}".format(source_path, extra_flags, dst_path, logfile, r2env_path + "/lib/pkgconfig")
print(cmd)
return os.system(cmd) == 0
@staticmethod
def _build_using_meson(source_path, dst_path, logfile, r2env_path):
exit_if_not_exists(['meson', 'ninja'])
print_console("[-] Building package using meson ...")
config_path = r2env_path + "/lib/pkgconfig"
# TODO: ensure source_path logfile or dst_path have no spaces
cmd = f"(export PKG_CONFIG_PATH=\"{config_path}\";" \
f"cd \"{source_path}\" && rm -rf build && " \
f"meson build --buildtype=release --prefix={dst_path} -Dlocal=true 2>&1 && " \
f"ninja -C build && " \
f"ninja -C build install) > {logfile} && " \
f"for a in {dst_path}/bin/* ; do install_name_tool -add_rpath {dst_path}/lib $a ; done"
print_console(f"Executing {cmd}")
cmd = "(export PKG_CONFIG_PATH=\"{4}\";cd {0} && rm -rf build && meson . build --buildtype=release --prefix={1} -Dlocal=true 2>&1" \
"&& ninja -C build && ninja -C build install) > {2}".format(source_path, dst_path, logfile,r2env_path + "/lib/pkgconfig")
return os.system(cmd) == 0
def _exit_if_package_not_available(self, profile, version):
@@ -229,5 +208,6 @@ class PackageManager:
pkg_found = True
break
if not pkg_found:
raise PackageManagerException(
f"{profile}@{version} package not available. Use 'list' command to see available packages.")
print_console("{}@{} package not available. Use 'list' command to see available packages."
.format(profile, version), level=ERROR)
sys.exit(-1)
+89 -94
View File
@@ -3,124 +3,119 @@
import argparse
import sys
from r2env.exceptions import ActionException, R2EnvException, PackageManagerException
from r2env.tools import print_console, ERROR
from r2env.core import R2Env
class REPL:
HELP_MESSAGE = """
Usage: r2env [-flags] [action] [args...]
HELP_MESSAGE = """
Usage: r2env [-flags] [action] [args...]
Flags:
Flags:
-h, --help - show this help.
-v, --version - display r2env version.
-m, --meson - use meson instead of acr.
-p, --package - install the dist package instead of building
-l, --list - list available and installed packages
-h, --help - show this help.
-v, --version - display r2env version.
-m, --meson - use meson instead of acr.
-p, --package - install the dist package instead of building
-l, --list - list available and installed packages
Actions:
Actions:
init - create ~/.r2env directory.
config - display current .r2env settings.
add [pkg] - build and install given package. See -p and -m
use [pkg] - stow a specific version to be the default.
rm [pkg] - remove package from ~/.r2env
path - show path of current r2 in use.
list - list all packages available to r2env.
shell - enter a new shell with PATH env var set.
purge - remove ~/.r2env
init - create ~/.r2env directory.
config - display current .r2env settings.
add [pkg] - build and install given package. See -p and -m
use [pkg] - stow a specific version to be the default.
rm [pkg] - remove package from ~/.r2env
path - show path of current r2 in use.
list - list all packages available to r2env.
shell - enter a new shell with PATH env var set.
purge - remove ~/.r2env
Environment
Environment
R2ENV_PATH - specify different path other than ~/.r2env
R2ENV_PATH - specify different path other than ~/.r2env
"""
"""
def __init__(self):
self.actions_with_arguments = ["add", "install", "rm", "uninstall", "use"]
self._core = R2Env()
self.actions = {
"init": self._core.init,
"v": self._core.version,
"version": self._core.version,
"path": self._core.get_r2_path,
"sh": self._core.shell,
"shell": self._core.shell,
"config": self._core.show_config,
"ls": self._core.list_packages,
"list": self._core.list_packages,
"add": self._core.install,
"install": self._core.install,
"installed": self._core.list_installed_packages,
"uninstall": self._core.uninstall,
"rm": self._core.uninstall,
"use": self._core.use,
"purge": self._core.purge,
"h": self.show_help,
"help": self.show_help
}
def show_help(self):
print_console(self.HELP_MESSAGE)
def show_help():
print_console(HELP_MESSAGE)
def run_action(self, action_args): # noqa: C901
args = []
if not action_args:
self.show_help()
raise ActionException("No action selected")
if action_args.version:
self.actions["version"]()
return
if action_args.list:
list_method = self.actions["list"]
list_method()
if len(action_args.args) == 0:
self.show_help()
raise ActionException("No action selected")
if len(action_args.args) > 1:
args = action_args.args[1:]
action = action_args.args[0]
if action not in self.actions:
raise ActionException("Invalid action selected")
if len(args) < 1 and action in self.actions_with_arguments:
if action in ["add", "install"]:
self._core.list_packages()
if action in ["use", "rm", "uninstall"]:
self._core.list_installed_packages()
raise ActionException(f"Action {action} requires a package as an argument.")
if action in self.actions_with_arguments:
self.actions[action](args[0], use_meson=action_args.meson, use_dist=action_args.package)
elif action in "shell" and len(args) > 0:
self.actions[action](args[0])
def show_version():
print_console(R2Env().version())
actions_with_argument = ["add", "install", "rm", "uninstall"]
actions_with_arguments = ["sh", "shell", "use"]
actions = {
"init": R2Env().init,
"v": show_version,
"version": show_version,
"path": R2Env().get_r2_path,
"sh": R2Env().shell,
"shell": R2Env().shell,
"config": R2Env().show_config,
"ls": R2Env().list_packages,
"list": R2Env().list_packages,
"add": R2Env().install,
"install": R2Env().install,
"installed": R2Env().list_installed_packages,
"uninstall": R2Env().uninstall,
"rm": R2Env().uninstall,
"use": R2Env().use,
"purge": R2Env().purge,
"h": show_help,
"help": show_help
}
def run_action(argp):
action = ""
args = []
if len(argp.args) > 0:
action = argp.args[0]
if len(argp.args) > 1:
args = argp.args[1:]
if argp.version:
print_console(R2Env().version())
elif argp.list:
actions["list"]()
elif action == "":
show_help()
elif action not in actions:
print_console("Invalid action", ERROR)
elif action in actions_with_arguments:
actions[action](" ".join(args))
elif action in actions_with_argument:
exit_if_not_argument_is_set(args, action)
actions[action](args[0], use_meson=argp.meson, use_dist=argp.package)
else:
actions[action]()
def exit_if_not_argument_is_set(args, action):
if len(args) < 1:
if action in ["use", "rm", "uninstall"]:
print_console("[x] Package not defined.", ERROR)
R2Env().list_installed_packages()
else:
self.actions[action]()
print_console("[x] Missing package argument.", ERROR)
R2Env().list_available_packages()
sys.exit(-1)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("args", help="run specified action. (Run r2env help for more information)",
action="store", nargs="*", default=[])
# parser.add_argument('args', metavar='args', nargs='+', type=str, help='Specified arguments')
#parser.add_argument('args', metavar='args', nargs='+', type=str, help='Specified arguments')
parser.add_argument("-v", "--version", dest="version", help="Show r2env version", action="store_true")
parser.add_argument("-m", "--meson", dest="meson", help="Use meson instead of acr to compile", action="store_true")
parser.add_argument("-p", "--package", dest="package", help="Use binary package for target system if available",
action="store_true")
parser.add_argument("-p", "--package", dest="package", help="Use binary package for target system if available", action="store_true")
parser.add_argument("-l", "--list", dest="list", help="List available and installed packages", action="store_true")
parser.print_help = REPL().show_help
action_args = parser.parse_args()
try:
REPL().run_action(action_args)
except ActionException as err:
print_console(f"[x] Parameter error. Details: {err}", level=ERROR)
sys.exit(-1)
except PackageManagerException as err:
print_console(f"[x] Package Error: {err}", level=ERROR)
sys.exit(-1)
except R2EnvException as err:
print_console(f"[x] r2Env Error: {err}", level=ERROR)
sys.exit(-1)
parser.print_help = show_help
argp = parser.parse_args()
run_action(argp)
if __name__ == "__main__":
-297
View File
@@ -1,297 +0,0 @@
from doublex import assert_that
from hamcrest import equal_to
from mock import patch
import unittest
from r2env.core import R2Env
from r2env.exceptions import R2EnvException
class TestCore(unittest.TestCase):
def setUp(self):
self.packages_dir = ["5.3.0"]
self.profiles = {
"radare2": {
"source": "https://github.com/radareorg/radare2",
"versions": [
{
"id": "5.3.0",
"packages": {
"w64": "radare2-5.3.0-w64.zip",
"deb_x64": "radare2_5.3.0_amd64.deb"
}
}
]
}
}
def tearDown(self):
patch.stopall()
@patch("r2env.core.R2Env._get_default_path")
def test_default_config(self, mock_default_path):
_ = R2Env()
mock_default_path.assert_called()
@patch("r2env.core.load_json_file")
def test_custom_config_using_json_file(self, mock_load_json_file):
custom_r2_path = "custom_r2_path"
mock_load_json_file.return_value = {"r2env_path": "custom_r2_path"}
r2env = R2Env()
assert_that(r2env._r2env_path, equal_to(custom_r2_path))
@patch("os.getenv")
def test_custom_config_using_envvar(self, mock_getenv):
custom_r2_path = "custom_r2_path"
mock_getenv.return_value = custom_r2_path
r2env = R2Env()
assert_that(r2env._r2env_path, equal_to(custom_r2_path))
@patch("os.mkdir")
@patch("os.path.isdir")
def test_init_failed(self, mock_isdir, mock_mkdir):
mock_isdir.return_value = True
R2Env().init()
mock_mkdir.assert_not_called()
@patch("os.mkdir")
@patch("os.path.isdir")
def test_init_successfully(self, mock_isdir, mock_mkdir):
mock_isdir.return_value = False
r2env= R2Env()
r2env.init()
mock_mkdir.assert_called_with(r2env._r2env_path)
@patch("os.path.isdir")
def test_check_if_r2env_not_initialized(self, mock_isdir):
mock_isdir.return_value = False
with self.assertRaises(R2EnvException):
R2Env().check_if_r2env_initialized()
@patch("r2env.core.print_console")
@patch("r2env.core.PackageManager.list_available_packages")
def test_list_available_pkg_successfully(self, mock_list_pkg, mock_print_console):
mock_list_pkg.return_value = self.profiles
R2Env().list_available_packages()
mock_print_console.assert_called_with(" - [email protected] - w64, deb_x64", formatter=1)
@patch("r2env.core.R2Env._get_current_version")
@patch("r2env.core.print_console")
@patch("os.path.isdir")
@patch("r2env.core.PackageManager.list_installed_packages")
def test_list_installed_pkg_successfully(self, mock_list_pkg, mock_isdir, mock_print, mock_current):
mock_list_pkg.return_value = self.packages_dir
mock_isdir.return_value = True
R2Env().list_installed_packages()
mock_print.assert_called_with(" - 5.3.0")
mock_current.return_value = "5.3.0"
R2Env().list_installed_packages()
mock_print.assert_called_with(" - 5.3.0 (in use)")
def test_check_package_format(self):
r2env = R2Env()
assert_that(r2env._check_package_format("radare2@git"), equal_to(True))
assert_that(r2env._check_package_format("[email protected]"), equal_to(True))
assert_that(r2env._check_package_format("[email protected]"), equal_to(False))
assert_that(r2env._check_package_format("[email protected]"), equal_to(False))
assert_that(r2env._check_package_format("radare2git"), equal_to(False))
@patch("r2env.core.R2Env._check_package_format")
@patch("r2env.core.R2Env.check_if_r2env_initialized")
@patch("r2env.core.PackageManager.install_package")
def test_install_successfully_default(self, mock_pkg_install, mock_initialized, mock_valid_format):
mock_initialized.return_value = True
mock_valid_format.return_value = True
package = "radare2"
version = "5.3.0"
R2Env().install(f"{package}@{version}")
mock_pkg_install.assert_called_with(package, version, use_meson=False, use_dist=False)
@patch("r2env.core.R2Env._check_package_format")
@patch("r2env.core.R2Env.check_if_r2env_initialized")
@patch("r2env.core.PackageManager.install_package")
def test_install_successfully_meson(self, mock_pkg_install, mock_initialized, mock_valid_format):
mock_initialized.return_value = True
mock_valid_format.return_value = True
package = "radare2"
version = "5.3.0"
R2Env().install(f"{package}@{version}", use_meson=True)
mock_pkg_install.assert_called_with(package, version, use_meson=True, use_dist=False)
@patch("r2env.core.R2Env._check_package_format")
@patch("r2env.core.R2Env.check_if_r2env_initialized")
@patch("r2env.core.PackageManager.install_package")
def test_install_successfully_dist(self, mock_pkg_install, mock_initialized, mock_valid_format):
mock_initialized.return_value = True
mock_valid_format.return_value = True
package = "radare2"
version = "5.3.0"
R2Env().install(f"{package}@{version}", use_dist=True)
mock_pkg_install.assert_called_with(package, version, use_meson=False, use_dist=True)
@patch("r2env.core.R2Env.check_if_r2env_initialized")
def test_install_successfully_failed(self, mock_initialized):
mock_initialized.return_value = True
package = "radare2@"
version = ""
with self.assertRaises(R2EnvException):
R2Env().install(f"{package}{version}", use_dist=True)
@patch("r2env.core.R2Env._check_package_format")
@patch("r2env.core.R2Env.check_if_r2env_initialized")
@patch("r2env.core.PackageManager.install_package")
def test_install_successfully_failed_with_default(self, mock_pkg_install, mock_initialized, mock_valid_format):
mock_initialized.return_value = True
mock_valid_format.return_value = True
package = "radare2"
R2Env().install(package)
mock_pkg_install.assert_called_with(package, "git", use_meson=False, use_dist=False)
@patch("r2env.core.R2Env._check_package_format")
@patch("r2env.core.R2Env.check_if_r2env_initialized")
@patch("r2env.core.PackageManager.uninstall_package")
def test_uninstall_successfully_default(self, mock_pkg_uninstall, mock_initialized, mock_valid_format):
mock_initialized.return_value = True
mock_valid_format.return_value = True
package = "[email protected]"
R2Env().uninstall(package)
mock_pkg_uninstall.assert_called_with(package, False)
@patch("r2env.core.R2Env._check_package_format")
@patch("r2env.core.R2Env.check_if_r2env_initialized")
@patch("r2env.core.PackageManager.uninstall_package")
def test_uninstall_successfully_dist(self, mock_pkg_uninstall, mock_initialized, mock_valid_format):
mock_initialized.return_value = True
mock_valid_format.return_value = True
package = "[email protected]"
R2Env().uninstall(package, use_dist=True)
mock_pkg_uninstall.assert_called_with(package, True)
@patch("r2env.core.R2Env._check_package_format")
@patch("r2env.core.R2Env.check_if_r2env_initialized")
def test_uninstall_failed(self, mock_initialized, mock_valid_format):
mock_initialized.return_value = True
mock_valid_format.return_value = False
package = "[email protected]"
with self.assertRaises(R2EnvException):
R2Env().uninstall(package, use_dist=True)
@patch("shutil.rmtree")
def test_purge(self, mock_rmtree):
r2env = R2Env()
r2env.purge()
mock_rmtree.assert_called_with(r2env._r2env_path)
@patch("r2env.core.PackageManager.list_installed_packages")
@patch("r2env.core.R2Env.check_if_r2env_initialized")
def test_use_package_not_installed(self, mock_initialized, mock_list_pkg):
package = "radare2@not_existing"
mock_list_pkg.return_value = ["[email protected]"]
mock_initialized.return_value = True
r2env = R2Env()
with self.assertRaises(R2EnvException):
r2env.use(package)
@patch("r2env.core.PackageManager.list_installed_packages")
@patch("r2env.core.PackageManager.get_package_path")
@patch("r2env.core.unstow")
@patch("r2env.core.stow")
@patch("r2env.core.R2Env._set_current_version")
@patch("r2env.core.R2Env._get_current_version")
@patch("r2env.core.R2Env.check_if_r2env_initialized")
def test_use_successfully(self, mock_initialized, mock_get_cur_ver, mock_set_cur_ver, mock_stow, mock_unstow,
mock_pkg_path, mock_list_pkg):
package = "[email protected]"
mock_initialized.return_value = True
mock_get_cur_ver.return_value = "5.3.0"
mock_list_pkg.return_value = ["[email protected]"]
new_path = f"new_path/{package}"
curr_path = f"new_path/old_package"
mock_pkg_path.side_effect = [new_path, curr_path]
r2env = R2Env()
r2env.use(package)
mock_set_cur_ver.assert_called_once_with(package)
mock_stow.assert_called_once_with([new_path], r2env._r2env_path)
mock_unstow.assert_called_once_with([curr_path], r2env._r2env_path)
@patch("r2env.core.PackageManager.list_installed_packages")
@patch("r2env.core.R2Env.check_if_r2env_initialized")
def test_use_with_no_none_package(self, mock_initialized, mock_list_pkg):
mock_initialized.return_value = True
r2env = R2Env()
with self.assertRaises(R2EnvException):
r2env.use(None)
mock_list_pkg.assert_called_once()
@patch("r2env.core.PackageManager.list_installed_packages")
@patch("r2env.core.R2Env.check_if_r2env_initialized")
def test_use_with_no_package(self, mock_initialized, mock_list_pkg):
mock_initialized.return_value = True
r2env = R2Env()
with self.assertRaises(R2EnvException):
r2env.use()
mock_list_pkg.assert_called_once()
@patch("r2env.core.PackageManager")
@patch("r2env.core.os.path.join")
@patch("r2env.core.host_platform")
@patch("r2env.core.os.system")
@patch("r2env.core.load_json_file")
def test_shell_windows(self, mock_load_json_file, mock_system, mock_host_platform, mock_join, _):
def side_effect(path1, path2, *args):
return f"{path1}\\{path2}"
r2env_path = "c:\\windows\\temp\\r2env\\"
mock_join.side_effect = side_effect
mock_host_platform.return_value = "windows"
mock_load_json_file.return_value = {"r2env_path": r2env_path}
cmd = "r2 -v"
R2Env().shell(cmd)
mock_system.assert_called_with(f"set PATH={r2env_path}\\bin;%PATH% && cmd")
@patch("r2env.core.host_platform")
@patch("r2env.core.os.system")
@patch("r2env.core.load_json_file")
def test_shell_android(self, mock_load_json_file, mock_system, mock_host_platform):
mock_host_platform.return_value = "android"
r2env_path = "/tmp/r2env"
mock_load_json_file.return_value = {"r2env_path": r2env_path}
cmd = "r2 -v"
R2Env().shell(cmd)
mock_system.assert_called_with(f"export LD_LIBRARY_PATH=\"{r2env_path}/lib\";"
f"export PS1=\"r2env ()\\$ \";"
f"export PKG_CONFIG_PATH=\"{r2env_path}/lib/pkgconfig\";"
f"export PATH=\"{r2env_path}/bin:$PATH\";"
f"$SHELL -f -c \'{cmd}\'")
@patch("r2env.core.host_platform")
@patch("r2env.core.os.system")
@patch("r2env.core.load_json_file")
def test_shell_osx(self, mock_load_json_file, mock_system, mock_host_platform):
mock_host_platform.return_value = "osx"
r2env_path = "/tmp/r2env"
mock_load_json_file.return_value = {"r2env_path": r2env_path}
cmd = "r2 -v"
R2Env().shell(cmd)
mock_system.assert_called_with(f"export DYLD_LIBRARY_PATH=\"{r2env_path}/lib\";"
f"export PS1=\"r2env ()\\$ \";"
f"export PKG_CONFIG_PATH=\"{r2env_path}/lib/pkgconfig\";"
f"export PATH=\"{r2env_path}/bin:$PATH\";"
f"$SHELL -f -c \'{cmd}\'")
@patch("r2env.core.host_platform")
@patch("r2env.core.os.system")
@patch("r2env.core.load_json_file")
def test_shell_linux(self, mock_load_json_file, mock_system, mock_host_platform):
mock_host_platform.return_value = "linux"
r2env_path = "/tmp/r2env"
mock_load_json_file.return_value = {"r2env_path": r2env_path}
cmd = "r2 -v"
R2Env().shell(cmd)
mock_system.assert_called_with(f"export PS1=\"r2env ()\\$ \";"
f"export PKG_CONFIG_PATH=\"{r2env_path}/lib/pkgconfig\";"
f"export PATH=\"{r2env_path}/bin:$PATH\";"
f"$SHELL -f -c \'{cmd}\'")
View File
Whitespace-only changes.
-403
View File
@@ -1,403 +0,0 @@
import os
from unittest.mock import MagicMock
from urllib.error import URLError
from doublex import assert_that
from hamcrest import equal_to
from mock import patch
import unittest
from r2env.exceptions import PackageManagerException
from r2env.package_manager import PackageManager
class TestPackageManager(unittest.TestCase):
def setUp(self):
self.profile = "radare2"
self.version = "5.3.0"
self.profiles = {
self.profile: {
"source": "https://github.com/radareorg/radare2",
"versions": [
{
"id": self.version,
"packages": {
"w64": "radare2-5.3.0-w64.zip",
"deb_x64": "radare2_5.3.0_amd64.deb"
}
}
]
}
}
self.load_json_mock = patch("r2env.package_manager.load_json_file").start()
self.load_json_mock.return_value = self.profiles
self.default_r2env_path = "/tmp/r2env"
self.package_manager = PackageManager(self.default_r2env_path)
def tearDown(self):
patch.stopall()
def test_constructor(self):
assert_that(self.package_manager._packages, equal_to(self.profiles))
assert_that(self.package_manager._r2env_path, equal_to(self.default_r2env_path))
def test_constructor_with_no_profiles(self):
self.load_json_mock.return_value = []
with self.assertRaises(PackageManagerException):
PackageManager(self.default_r2env_path)
def test_get_package_path(self):
package_name = "test"
package_path = self.package_manager.get_package_path(package_name)
assert_that(package_path, equal_to(os.path.join(self.default_r2env_path, "versions", package_name)))
def test_list_available_packages(self):
assert_that(self.package_manager.list_available_packages(), equal_to(self.profiles))
@patch("r2env.package_manager.os")
def test_list_installed_packages(self, os_mock):
packages = ["PKG1", "PKG2", "PKG3"]
os_mock.path.isdir.return_value = True
os_mock.listdir.return_value = packages
assert_that(self.package_manager.list_installed_packages(), equal_to(packages))
@patch("r2env.package_manager.os.makedirs")
@patch("r2env.package_manager.os.path.isdir")
def test_install_package_with_no_log_path(self, mock_isdir, mock_makedirs):
patch("r2env.package_manager.PackageManager._build_from_source").start()
patch("r2env.package_manager.PackageManager._install_from_dist").start()
mock_isdir.side_effect = [False, True, True]
self.package_manager.install_package(self.profile, self.version, True, True)
mock_makedirs.assert_called_once()
@patch("r2env.package_manager.os.makedirs")
@patch("r2env.package_manager.os.path.isdir")
def test_install_package_with_no_source_path(self, mock_isdir, mock_makedirs):
patch("r2env.package_manager.PackageManager._build_from_source").start()
patch("r2env.package_manager.PackageManager._install_from_dist").start()
mock_isdir.side_effect = [True, False, True]
self.package_manager.install_package(self.profile, self.version, True, True)
source_path = os.path.join(os.path.join(self.package_manager._r2env_path,
self.package_manager.SOURCE_DIR, self.profile))
mock_makedirs.assert_called_once_with(source_path)
@patch("r2env.package_manager.os.makedirs")
@patch("r2env.package_manager.os.path.isdir")
def test_install_package_with_no_dstdir(self, mock_isdir, mock_makedirs):
patch("r2env.package_manager.PackageManager._build_from_source").start()
patch("r2env.package_manager.PackageManager._install_from_dist").start()
mock_isdir.side_effect = [True, True, False]
self.package_manager.install_package(self.profile, self.version, True, True)
dst_dir = os.path.join(self.package_manager._r2env_path,
self.package_manager.PACKAGES_DIR,
f"{self.profile}@{self.version}")
mock_makedirs.assert_called_once_with(dst_dir)
@patch("r2env.package_manager.PackageManager._install_from_dist")
@patch("r2env.package_manager.os.path.isdir")
def test_install_package_from_dist_success(self, mock_isdir,
mock_dist):
mock_isdir.return_value = True
mock_dist.return_value = True
self.package_manager.install_package(self.profile, self.version, True, True)
mock_dist.assert_called_once_with(self.profile, self.version)
@patch("r2env.package_manager.PackageManager._install_from_dist")
@patch("r2env.package_manager.os.path.isdir")
def test_install_package_from_dist_failed(self, mock_isdir,
mock_dist):
mock_isdir.return_value = True
mock_dist.return_value = False
with self.assertRaises(PackageManagerException):
self.package_manager.install_package(self.profile, self.version, True, True)
mock_dist.assert_called_once_with(self.profile, self.version)
@patch("r2env.package_manager.PackageManager._build_from_source")
@patch("r2env.package_manager.os.path.isdir")
def test_install_package_from_build_success(self, mock_isdir,
mock_build):
mock_isdir.return_value = True
mock_build.return_value = True
self.package_manager.install_package(self.profile, self.version, True, False)
mock_build.assert_called_once()
@patch("r2env.package_manager.shutil.rmtree")
@patch("r2env.package_manager.PackageManager._build_from_source")
@patch("r2env.package_manager.os.path.isdir")
def test_install_package_from_build_failed(self, mock_isdir,
mock_build, mock_rmtree):
mock_isdir.return_value = True
mock_build.return_value = False
with self.assertRaises(PackageManagerException):
self.package_manager.install_package(self.profile, self.version, True, False)
mock_build.assert_called_once()
mock_rmtree.assert_called_once()
@patch("r2env.package_manager.PackageManager.list_installed_packages")
@patch("r2env.package_manager.PackageManager._uninstall_from_dist")
def test_uninstall_package_from_dist_successfully(self, mock_uninstall, mock_list_pkg):
mock_list_pkg.return_value = ["[email protected]", "[email protected]"]
profile = "radare2"
version = "2.0.0"
package = f"{profile}@{version}"
self.package_manager.uninstall_package(package, True)
mock_uninstall.assert_called_once_with(profile, version)
@patch("r2env.package_manager.PackageManager.list_installed_packages")
@patch("r2env.package_manager.shutil.rmtree")
def test_uninstall_package_from_build_successfully(self, mock_rmtree, mock_list_pkg):
mock_list_pkg.return_value = ["[email protected]", "[email protected]"]
package = "[email protected]"
self.package_manager.uninstall_package(package, False)
pkg_dir = os.path.join(self.package_manager._r2env_path,
self.package_manager.PACKAGES_DIR,
package)
mock_rmtree.assert_called_once_with(pkg_dir)
@patch("r2env.package_manager.PackageManager.list_installed_packages")
@patch("r2env.package_manager.shutil.rmtree")
def test_uninstall_package_from_build_failed(self, mock_rmtree, mock_list_pkg):
mock_list_pkg.return_value = ["[email protected]", "[email protected]"]
package = "[email protected]"
mock_rmtree.side_effect = OSError("fail")
with self.assertRaises(PackageManagerException):
self.package_manager.uninstall_package(package, False)
@patch("r2env.package_manager.PackageManager.list_installed_packages")
def test_uninstall_package_not_found(self, mock_list_pkg):
mock_list_pkg.return_value = ["[email protected]"]
package = "[email protected]"
with self.assertRaises(PackageManagerException):
self.package_manager.uninstall_package(package, False)
def test_get_pkgname_success(self):
target_pkg = "radare2-5.3.1-w64.zip"
target_os = "w64"
target_version = "5.3.1"
packages_mock = {"radare2": {
"versions": [
{
"id": "5.3.0",
"packages": {
"w64": "radare2-5.3.0-w64.zip",
}
},
{
"id": target_version,
"packages": {
target_os: target_pkg,
"mac_x64": "radare2-5.3.1.pkg",
}
}]
}}
self.package_manager._packages = packages_mock
assert_that(self.package_manager._get_pkgname("radare2", target_version, target_os), equal_to(target_pkg))
def test_get_pkgname_failed(self):
target_os = "w64"
target_version = "5.3.1"
packages_mock = {"radare2": {
"versions": [
{
"id": "5.3.0",
"packages": {
"w64": "radare2-5.3.0-w64.zip",
}
},
]
}}
self.package_manager._packages = packages_mock
assert_that(self.package_manager._get_pkgname("radare2", target_version, target_os), equal_to(None))
@patch("r2env.package_manager.PackageManager._get_pkgname")
def test_get_disturl_success(self, mock_getpkg):
target_pkg = "radare2-5.3.1-w64.zip"
version = "5.2.0"
mock_getpkg.return_value = target_pkg
dist_url = self.package_manager._get_disturl("mock_profile", version, "mock_cos")
expected_url = "/".join([self.package_manager.DOWNLOAD_URL, version, target_pkg])
assert_that(dist_url, equal_to(expected_url))
@patch("r2env.package_manager.PackageManager._get_pkgname")
def test_get_disturl_failed(self, mock_getpkg):
target_pkg = None
mock_getpkg.return_value = target_pkg
dist_url = self.package_manager._get_disturl("mock_profile", "mock_version", "mock_cos")
assert_that(dist_url, equal_to(None))
@patch("r2env.package_manager.wget")
@patch("r2env.package_manager.PackageManager._get_pkgname")
@patch("r2env.package_manager.PackageManager._get_disturl")
@patch("r2env.package_manager.host_distname")
def test_install_from_dist_wget_is_called(self, mock_host_distname,
mock__get_disturl,
mock__get_pkgname,
mock_wget):
patch("r2env.package_manager.os.system").start()
pkgname = "radare2-5.3.1-w64.zip"
disturl = "http://example.org"
pkgfile = "/".join([self.package_manager._r2env_path, "src", pkgname])
mock__get_pkgname.return_value = pkgname
mock__get_disturl.return_value = disturl
mock_host_distname.return_value = "mac_arm64"
profile = "radare2"
version = "5.6.0"
self.package_manager._install_from_dist(profile, version)
mock_wget.download.assert_called_once_with(disturl, pkgfile)
@patch("r2env.package_manager.wget")
def test_install_from_dist_wget_error_url(self, mock_wget):
pkgname_mock = patch("r2env.package_manager.PackageManager._get_pkgname").start()
get_disturl_mock = patch("r2env.package_manager.PackageManager._get_disturl").start()
pkgname_mock.return_value = "radare2-5.3.1-w64.zip"
get_disturl_mock.return_value = "http://example.org"
mock_wget.download.side_effect = URLError("error")
with self.assertRaises(PackageManagerException):
self.package_manager._install_from_dist("profile", "version")
@patch("r2env.package_manager.wget")
def test_install_from_dist_wget_error_connection(self, mock_wget):
pkgname_mock = patch("r2env.package_manager.PackageManager._get_pkgname").start()
get_disturl_mock = patch("r2env.package_manager.PackageManager._get_disturl").start()
pkgname_mock.return_value = "radare2-5.3.1-w64.zip"
get_disturl_mock.return_value = "http://example.org"
mock_wget.download.side_effect = ConnectionResetError("error")
with self.assertRaises(PackageManagerException):
self.package_manager._install_from_dist("profile", "version")
@patch("r2env.package_manager.wget")
def test_install_from_dist_wget_error_connection(self, mock_wget):
pkgname_mock = patch("r2env.package_manager.PackageManager._get_pkgname").start()
get_disturl_mock = patch("r2env.package_manager.PackageManager._get_disturl").start()
pkgname_mock.return_value = "radare2-5.3.1-w64.zip"
get_disturl_mock.return_value = "http://example.org"
mock_wget.download.side_effect = ConnectionResetError("error")
with self.assertRaises(PackageManagerException):
self.package_manager._install_from_dist("profile", "version")
@patch("r2env.package_manager.os.system")
@patch("r2env.package_manager.PackageManager._get_pkgname")
@patch("r2env.package_manager.PackageManager._get_disturl")
@patch("r2env.package_manager.host_distname")
def test_install_from_dist_mac(self, mock_host_distname,
mock__get_disturl,
mock__get_pkgname,
mock_system):
pkgname = "radare2-5.3.1-mac.pkg"
pkgfile = "/".join([self.package_manager._r2env_path, "src", pkgname])
mock__get_pkgname.return_value = pkgname
mock__get_disturl.return_value = "http://example.org"
mock_host_distname.return_value = "mac_arm64"
profile = "radare2"
version = "5.6.0"
patch("r2env.package_manager.wget.download").start()
mock_system.return_value = 0
assert_that(self.package_manager._install_from_dist(profile, version), equal_to(True))
mock_system.assert_called_once_with(f"sudo installer -pkg {pkgfile} -target /")
@patch("r2env.package_manager.os.system")
@patch("r2env.package_manager.PackageManager._get_pkgname")
@patch("r2env.package_manager.PackageManager._get_disturl")
@patch("r2env.package_manager.host_distname")
def test_install_from_dist_linux_deb(self, mock_host_distname,
mock__get_disturl,
mock__get_pkgname,
mock_system):
pkgname = "radare2-5.3.1-linux.deb"
pkgfile = "/".join([self.package_manager._r2env_path, "src", pkgname])
mock__get_pkgname.return_value = pkgname
mock__get_disturl.return_value = "http://example.org"
mock_host_distname.return_value = "deb_x64"
profile = "radare2"
version = "5.6.0"
patch("r2env.package_manager.wget.download").start()
mock_system.return_value = 0
assert_that(self.package_manager._install_from_dist(profile, version), equal_to(True))
mock_system.assert_called_once_with(f"sudo dpkg -i {pkgfile}")
@patch("r2env.package_manager.os.system")
@patch("r2env.package_manager.PackageManager._get_pkgname")
@patch("r2env.package_manager.PackageManager._get_disturl")
@patch("r2env.package_manager.host_distname")
def test_install_from_dist_mac_os_not_supported(self, mock_host_distname,
mock__get_disturl,
mock__get_pkgname,
mock_system):
mock__get_pkgname.return_value = "radare2-5.3.1-mac.zip"
mock__get_disturl.return_value = "http://example.org"
mock_host_distname.return_value = "not_existing_so"
patch("r2env.package_manager.wget.download").start()
with self.assertRaises(PackageManagerException):
self.package_manager._install_from_dist("radare2", "5.6.0")
mock_system.assert_not_called()
@patch("r2env.package_manager.PackageManager._uninstall_from_dist")
@patch("r2env.package_manager.zipfile.ZipFile")
def test_install_windows_package_file_not_found(self, zipfile_mock, uninstall_mock):
zipfile_mock.extractall.side_effect = FileNotFoundError()
with self.assertRaises(PackageManagerException):
self.package_manager._install_windows_package("radare2")
uninstall_mock.assert_called_once()
@patch("r2env.package_manager.os.path.isdir")
@patch("r2env.package_manager.os.makedirs")
def test_install_windows_package_create_dst_folder(self, makedirs_mock, isdir_mock):
patch("r2env.package_manager.shutil.copyfile").start()
patch("r2env.package_manager.zipfile").start()
isdir_mock.return_value = False
patch("r2env.package_manager.shutil.copyfile").start()
self.package_manager._install_windows_package("radare2")
makedirs_mock.assert_called_once_with(os.path.join(self.package_manager._r2env_path, "bin"), 493)
@patch("r2env.package_manager.os.path.isdir")
def test_install_windows_package_successfully(self, isdir_mock):
with patch("r2env.package_manager.zipfile.ZipFile") as mock_ZipFile:
mock_zip = MagicMock()
mock_zip.return_value = ["1", "2", "3"]
mock_ZipFile.return_value = mock_zip
mock_copy = patch("r2env.package_manager.shutil.copyfile").start()
isdir_mock.return_value = True
assert_that(self.package_manager._install_windows_package("radare2"), equal_to(True))
mock_copy.assert_called_once()
@patch("r2env.package_manager.host_distname")
def test_uninstall_from_dist_windows(self, mock_distname):
mock_distname.return_value = "w64"
mock_rmtree = patch("r2env.package_manager.shutil.rmtree").start()
dst_folder = os.path.join(self.package_manager._r2env_path, "bin")
assert_that(self.package_manager._uninstall_from_dist("radare2", "1.0.0"), equal_to(True))
mock_rmtree.assert_called_once_with(dst_folder)
@patch("r2env.package_manager.host_distname")
def test_uninstall_from_dist_mac(self, mock_distname):
mock_distname.return_value = "mac_arm64"
mock_system = patch("r2env.package_manager.os.system").start()
mock_system.side_effect = [0,0,0,0]
assert_that(self.package_manager._uninstall_from_dist("radare2", "1.0.0"), equal_to(True))
@patch("r2env.package_manager.host_distname")
def test_uninstall_from_dist_mac_failed(self, mock_distname):
mock_distname.return_value = "mac_arm64"
mock_system = patch("r2env.package_manager.os.system").start()
mock_system.side_effect = [0,1,0,0]
assert_that(self.package_manager._uninstall_from_dist("radare2", "1.0.0"), equal_to(False))
@patch("r2env.package_manager.host_distname")
def test_uninstall_from_dist_linux(self, mock_distname):
mock_distname.return_value = "deb_x64"
mock_system = patch("r2env.package_manager.os.system").start()
mock_system.return_value = 0
assert_that(self.package_manager._uninstall_from_dist("radare2", "1.0.0"), equal_to(True))
mock_system.assert_called_once_with("sudo dpkg -r radare2")
@patch("r2env.package_manager.host_distname")
def test_uninstall_from_dist_os_not_supported(self, mock_distname):
mock_distname.return_value = "non_existent"
with self.assertRaises(PackageManagerException):
self.package_manager._uninstall_from_dist("radare2", "1.0.0")
@patch("r2env.package_manager.host_distname")
def test_acr_not_supported_on_windows(self, mock_distname):
mock_distname.return_value = "w64"
with self.assertRaises(PackageManagerException):
self.package_manager._build_using_acr("source", "dest", "logfile", "r2env")
View File
Whitespace-only changes.
-55
View File
@@ -1,55 +0,0 @@
from mock import patch
import unittest
from r2env.repl import REPL
from r2env.exceptions import ActionException
class MockActions:
def __init__(self):
self.args = []
self.version = False
self.list = False
class TestRepl(unittest.TestCase):
def setUp(self):
self.repl = REPL()
def tearDown(self):
patch.stopall()
def test_invalid_run_with_no_action(self):
with self.assertRaises(ActionException):
self.repl.run_action(None)
no_action = MockActions()
with self.assertRaises(ActionException):
self.repl.run_action(no_action)
@patch("r2env.repl.R2Env.list_packages")
@patch("r2env.repl.R2Env.list_installed_packages")
def test_invalid_run_action_with_no_arguments(self,mock_list_installed_packages, mock_list_packages):
use_action = MockActions()
use_action.args.append("use")
with self.assertRaises(ActionException):
self.repl.run_action(use_action)
mock_list_installed_packages.assert_called()
install_action = MockActions()
install_action.args.append("install")
with self.assertRaises(ActionException):
self.repl.run_action(install_action)
mock_list_packages.assert_called()
@patch("r2env.repl.REPL.show_help")
def test_print_help(self, mock_help):
help_action = MockActions()
with self.assertRaises(ActionException):
self.repl.run_action(help_action)
mock_help.assert_called()
def test_invalid_action(self):
invalid_action = MockActions()
invalid_action.args.append("invalid_action")
with self.assertRaises(ActionException):
self.repl.run_action(invalid_action)
+31 -40
View File
@@ -2,16 +2,14 @@
import json
import os
import sys
from shutil import which
import git
from colorama import Fore, Style
from git import Repo
from r2env.exceptions import PackageManagerException
# Global Vars
INFO = 0
WARNING = 1
ERROR = 2
@@ -33,53 +31,45 @@ def print_console(msg, level=INFO, formatter=0):
def host_platform():
if os.name == "nt":
return "windows"
return "w64"
if os.path.isfile("/default.prop"):
return "android"
if os.uname().sysname == "Darwin":
return "osx"
return "unix"
# TODO :improve to support all archs
def host_distname(): # noqa: C901
dist_name = None
def host_distname():
try:
sysname = os.uname().sysname
machine = os.uname().machine
except AttributeError:
sysname = "Windows"
except:
sysname = "w64"
machine = "amd64"
if sysname in "Windows" and os.name in "nt":
dist_name = "w64"
elif sysname in "Darwin":
if machine in "x86_64":
dist_name = "mac_x64"
if machine in "arm64":
dist_name = "mac_arm64"
elif sysname == "Linux":
if os.path.exists("/usr/bin/dpkg"):
if machine == "x86_64":
dist_name = "deb_x64"
else:
dist_name = "deb_i386"
if sysname == "Darwin":
if machine == "x86_64":
return "mac_x64"
if machine == "arm64":
return "mac_arm64"
return None
if sysname == "Linux":
if not os.path.exists("/usr/bin/dpkg"):
return None
if machine == "x86_64":
return "deb_x64"
return "deb_i386"
if os.name == "nt":
return "w64"
if os.path.isfile("/default.prop"):
dist_name = "android"
return dist_name
return "android"
return None
def git_fetch(url, version, source_path):
try:
if os.path.isdir(os.path.join(source_path, ".git")):
repo = Repo(source_path)
repo.git.checkout("master")
repo.remotes.origin.pull("master")
else:
repo = Repo.clone_from(url, source_path)
except git.GitCommandError as err:
raise PackageManagerException("An error occured clonning the repo. "
f"Verify the source path is not dirty. Error: {err}") \
from err
if os.path.isdir(os.path.join(source_path, ".git")):
repo = Repo(source_path)
repo.remotes.origin.pull("master")
else:
repo = Repo.clone_from(url, source_path)
if version != "git":
repo.git.checkout(version)
sms = repo.submodules
@@ -100,13 +90,14 @@ def exists(tool):
def exit_if_not_exists(tools):
for tool in tools:
if not exists(tool):
raise PackageManagerException(f"[x] {tool} is required. Please install it first")
print_console("[x] {} is required. Please install it first", level=ERROR)
sys.exit(-1)
def load_json_file(filepath):
try:
with open(filepath, encoding="utf-8") as json_file:
with open(filepath) as json_file:
return json.load(json_file)
except OSError as err:
print_console(f"File {filepath} not found. Msg: {err}", ERROR)
print_console("File {} not found. Msg: {}".format(filepath, err), ERROR)
return None
+1 -1
View File
@@ -1 +1 @@
0.5.5
0.4.2
+1 -1
View File
@@ -7,4 +7,4 @@ mock
pytest
coverage
doublex
tox
tox
Executable → Regular
+1 -1
View File
@@ -6,7 +6,7 @@ readlink=$(which greadlink 2>/dev/null) || readlink=$(which readlink)
base_dir=$(cd $(dirname $(${readlink} -f "$0")); pwd)
echo "Cleaning *.pyc files ..."
find . -name \*.pyc | xargs rm 2>/dev/null
find $base_dir -name \*.pyc | xargs rm 2>/dev/null
python -m coverage run -m pytest -v -rsx -k "test_" --ignore=bin/
ecode=$?
+1 -4
View File
@@ -5,8 +5,5 @@ from setuptools import setup
setup(
setup_requires=['pbr'],
pbr=True,
package_files=[
('config', ['r2env/config/config.json', 'r2env/config/profiles.json']),
('', ['version.txt'])
]
package_files=[('config', ['r2env/config/config.json', 'r2env/config/profiles.json'])]
)
+5 -5
View File
@@ -1,15 +1,15 @@
[tox]
envlist = py{38,39,310}-{tests},{py38,py39,310}-codecheck-{pylint,flake8,bandit}
envlist = py{38,39}-{tests},{py38,py39}-codecheck-{pylint,flake8,bandit}
skipsdist = True
[testenv]
deps = -r {toxinidir}/requirements/test.txt
passenv = *
commands =
py{38,39,310}-tests: {toxinidir}/run_tests.sh unit
py{38,39,310}-codecheck-pylint: pylint r2env
py{38,39,310}-codecheck-flake8: flake8 r2env
py{38,39,310}-codecheck-bandit: bandit -c .bandit.yml -r r2env
py{38,39}-tests: {toxinidir}/run_tests.sh unit
py{38,39}-codecheck-pylint: pylint r2env
py{38,39}-codecheck-flake8: flake8 r2env
py{38,39}-codecheck-bandit: bandit -c .bandit.yml -r r2env
[flake8]
# to ignore complete files, add to the file: # flake8: noqa