Compare commits

...
38 Commits
Author SHA1 Message Date
Murphy 670de20b01 Add r2 5.7.0 profile 2022-06-07 12:35:59 +02:00
Murphy 019e941dfa Update to v0.5.2 2022-04-28 18:25:51 +02:00
pancake 26925a29d6 Update for 5.6.8 2022-04-19 17:09:31 +02:00
Murphy 1a1f3fcde5 Fixing tests 2022-03-25 21:33:56 +01:00
Murphy 0c838e7d08 Fixing lints 2022-03-25 21:33:56 +01:00
Murphy b3852a92d3 Adding 5.6.6 profile 2022-03-25 21:33:56 +01:00
Murphy 6f81459f70 Raising an error using Windows with ACR 2022-03-25 21:33:56 +01:00
Murphy 3f16036689 Use git if version not defined 2022-03-25 21:33:56 +01:00
Murphy 00782ae62f Fix shell command using arguments 2022-03-25 21:33:56 +01:00
Murphy 93bd2b0e1e Skip C901 to run_action 2022-03-25 20:45:13 +01:00
Murphy 100dc1a9d0 Minor fix 2022-03-25 20:45:13 +01:00
Murphy e5677a03ae Fix version cmd 2022-03-25 20:45:13 +01:00
Murphy 35d769e73b Fix shell cmd with parameters 2022-03-25 20:45:13 +01:00
Murphy 587ce7ef96 Improve use and shell cmds 2022-03-25 20:45:13 +01:00
pancake edfe363401 Fix missing libs issue in meson builds on macos-sip targets 2022-03-25 20:39:59 +01:00
pancake 9d521d7f0e fix 2022-03-25 20:38:48 +01:00
pancake 2c0f8d48c9 Minor tweaks in the meson build function 2022-03-25 20:38:48 +01:00
Murphy d8a948c61b Fix tests 2022-03-15 11:36:37 +01:00
Murphy 374e93bf2b Raising exception when using pacakge not installed in use cmd 2022-03-15 11:36:37 +01:00
Murphy 9459ab1f72 checkout master when clonning a repo 2022-03-15 11:36:37 +01:00
Murphy 61b9bafdcb Fix some pylint lints 2022-03-15 11:36:37 +01:00
Murphy e7d1a24683 Fix minor issues 2022-03-15 11:36:37 +01:00
Murphy ac6a072246 Update profiles.json 2022-03-15 11:36:37 +01:00
Murphy ffa0f87d9c Add tests to package manager 2022-03-15 11:36:37 +01:00
Murphy bf35b36959 Refactor package manager 2022-03-15 11:36:37 +01:00
Murphy e6bcd7c4d4 Refactoring package manager 2022-03-15 11:36:37 +01:00
Murphy 25d26bb0f9 Add dependency to release-job 2022-03-15 11:36:37 +01:00
Murphy db54437130 Add unit tests to CI 2022-03-15 11:36:37 +01:00
Murphy 4ffe814c42 Fix some lints 2022-03-15 11:36:37 +01:00
Murphy 89272008ca Refactor package manager and add tests 2022-03-15 11:36:37 +01:00
Murphy a1b6363f26 Refactor r2env core and add tests 2022-03-15 11:36:37 +01:00
Murphy 47eeb599b6 Refactor r2env core and add tests 2022-03-15 11:36:37 +01:00
Murphy c89615d0fb Refactor repl and add tests 2022-03-15 11:36:37 +01:00
asoler e449e41971 Refactoring Repl 2022-03-15 11:36:37 +01:00
murphy 56426fd1f2 Fix some codechecks 2022-03-15 11:36:37 +01:00
murphy e27ce149b3 Update gitignore 2022-03-15 11:36:37 +01:00
murphy 5cb3f75f35 Add 5.5.2 version 2022-03-15 11:36:37 +01:00
Murphy 2200ddcb50 Create codeql-analysis.yml 2022-03-15 11:34:47 +01:00
21 changed files with 1268 additions and 281 deletions

No files matched your search

BIN
View File
Binary file not shown.
+12 -1
View File
@@ -36,6 +36,17 @@ 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
@@ -63,7 +74,7 @@ jobs:
release-job:
name: Publish package
runs-on: ubuntu-20.04
needs: [integration-tests, flake8, pylint]
needs: [integration-tests, unit-tests, flake8, pylint]
if: github.event_name == 'release' && github.event.action == 'published'
steps:
- name: Checkout
+70
View File
@@ -0,0 +1,70 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '34 6 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
+1
View File
@@ -1,3 +1,4 @@
.coverage
.idea
**/__pycache__/
venv
+2
View File
@@ -4,6 +4,8 @@ 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
+88
View File
@@ -83,6 +83,94 @@
"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": "git",
"packages": {}
+68 -55
View File
@@ -4,11 +4,14 @@ 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
from r2env.tools import print_console, load_json_file, WARNING, ERROR, host_platform
class R2Env:
@@ -23,16 +26,16 @@ class R2Env:
def init(self):
if os.path.isdir(self._r2env_path):
print_console("[x] r2env already initialized. Path {} already exists.".format(self._r2env_path), ERROR)
print_console(f"[x] r2env already initialized. Path {self._r2env_path} already exists.", ERROR)
return
os.mkdir(self._r2env_path)
print_console("[*] r2env initialized at {}".format(self._r2env_path))
print_console(f"[*] r2env initialized at {self._r2env_path}")
def get_r2_path(self):
self.exit_if_r2env_not_initialized()
self.check_if_r2env_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(" [*] {0} ({1})".format(r2_version, r2_path))
print_console(f" [*] {r2_version} ({r2_path})")
def show_config(self):
print_console("[*] Current r2env config:")
@@ -46,88 +49,100 @@ class R2Env:
print_console("- Available")
packages = self._package_manager.list_available_packages()
for profile in packages:
print_console(" - {}:".format(profile), WARNING)
print_console(f" - {profile}:", WARNING)
for version in packages[profile]['versions']:
dists = ", ".join(version['packages'].keys())
print_console(" - {}@{} - {}".format(profile, version['id'], dists), formatter=1)
print_console(f" - {profile}@{version['id']} - {dists}", formatter=1)
def list_installed_packages(self):
self.exit_if_r2env_not_initialized()
self.check_if_r2env_initialized()
print_console("- Installed")
for pkg in self._package_manager.list_installed_packages():
if pkg == self._get_current_version():
print_console(" - {} (in use)".format(pkg))
print_console(f" - {pkg} (in use)")
else:
print_console(" - {}".format(pkg))
print_console(f" - {pkg}")
def install(self, package, use_meson=False, use_dist=False):
self.exit_if_r2env_not_initialized()
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"
if not self._check_package_format(package):
print_console("[x] Invalid package format.", level=ERROR)
return
raise R2EnvException("[x] Invalid package format.")
try:
profile, version = package.split('@')
except:
except ValueError:
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, use_meson, use_dist):
self.exit_if_r2env_not_initialized()
def uninstall(self, package, **kwargs):
self.check_if_r2env_initialized()
use_dist = kwargs["use_dist"] if "use_dist" in kwargs else False
if not self._check_package_format(package):
print_console("[x] Invalid package format.", level=ERROR)
return
raise R2EnvException("[x] Invalid package format.")
self._package_manager.uninstall_package(package, use_dist)
def purge(self):
print("Removing " + self._r2env_path)
print_console(f"[*] Removing {self._r2env_path}")
shutil.rmtree(self._r2env_path)
def use(self, package=None):
self.exit_if_r2env_not_initialized()
def use(self, package=None, **_kwargs):
self.check_if_r2env_initialized()
if not package:
print_console("[x] Package not defined.", ERROR)
self.list_installed_packages()
return
raise R2EnvException("Package not defined.")
if package not in self._package_manager.list_installed_packages():
raise R2EnvException(f"Package {package} not installed.")
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("[*] Using {} package".format(package))
print_console(f"[*] Using {package} package")
@staticmethod
def version():
thispath = os.path.dirname(os.path.realpath(__file__))
with open(thispath + "/version.txt", "r") as version:
return version.read()
with open(f"{thispath}/version.txt", "r", encoding="utf-8") as version:
print_console(version.read())
def shell(self, cmd=""):
if os.name== "nt":
os.system("set PATH="+self._r2env_path+"\\bin;%PATH% && cmd")
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")
return True
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 + "'")
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
@staticmethod
def _load_config():
filename = os.path.join(os.path.dirname(__file__), 'config', 'config.json')
config = load_json_file(filename)
ep = os.getenv("R2ENV_PATH")
if ep is not None:
config["r2env_path"] = ep
environment_path = os.getenv("R2ENV_PATH")
if environment_path is not None:
config["r2env_path"] = environment_path
if not config:
sys.exit(-1)
config = {}
return config
@staticmethod
@@ -137,26 +152,24 @@ class R2Env:
@staticmethod
def _check_package_format(package):
if package == "":
return True
return True
# regexp = re.compile(r"\w+\d@(?:\d\.\d\.\d|git)")
# return regexp.match(package)
regexp = r"[a-z0-9]+@(\d\.\d\.\d|git)"
if not package:
return False
return re.search(regexp, package) is not None
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') as file_desc:
with open(version_file, 'r', encoding="utf-8") 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') as file_desc:
with open(version_file, 'w', encoding="utf-8") as file_desc:
file_desc.write(package)
def exit_if_r2env_not_initialized(self):
def check_if_r2env_initialized(self):
if not os.path.isdir(self._r2env_path):
print_console("Not r2env initialized. Execute 'r2env init' first.", ERROR)
sys.exit(-1)
raise R2EnvException("Not r2env initialized. Execute 'r2env init' first.")
+10
View File
@@ -0,0 +1,10 @@
class R2EnvException(Exception):
pass
class ActionException(R2EnvException):
pass
class PackageManagerException(R2EnvException):
pass
+116 -96
View File
@@ -2,19 +2,21 @@
import os
import shutil
import wget
import sys
import time
from urllib.error import URLError
import zipfile
from zipfile import ZipFile
import wget
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:
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()
@@ -40,14 +42,15 @@ class PackageManager:
filename = os.path.join(os.path.dirname(__file__), 'config', 'profiles.json')
profiles = load_json_file(filename)
if not profiles:
sys.exit(-1)
raise PackageManagerException("No profiles configured.")
return profiles
def install_package(self, profile, version, use_meson, use_dist):
log_path = os.path.join(self._r2env_path, self.LOG_DIR)
logfile = os.path.join(log_path, "{}_{}_{}_build.txt".format(profile, version, round(time.monotonic() * 1000)))
timestamp = round(time.monotonic() * 1000)
logfile = os.path.join(log_path, f"{profile}_{version}_{timestamp}_build.txt")
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), "{}@{}".format(profile, version))
dst_dir = os.path.join(os.path.join(self._r2env_path, self.PACKAGES_DIR), f"{profile}@{version}")
if not os.path.isdir(log_path):
os.makedirs(log_path)
if not os.path.isdir(source_path):
@@ -56,17 +59,18 @@ class PackageManager:
os.makedirs(dst_dir)
self._exit_if_package_not_available(profile, version)
if use_dist:
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))
if self._install_from_dist(profile, version):
print_console(f"[*] Binary package {profile}@{version} installed successfully")
else:
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))
raise PackageManagerException(f"[x] Failed to install {profile}@{version}.")
else:
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)
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.")
def uninstall_package(self, package_name, use_dist):
pkg_found = False
@@ -74,18 +78,19 @@ class PackageManager:
if package_name == package:
pkg_found = True
if use_dist:
kv = package.split("@")
self._uninstall_from_dist(kv[0], kv[1])
profile, version = package.split("@")
self._uninstall_from_dist(profile, version)
else:
pkg_dir = os.path.join(os.path.join(self._r2env_path, self.PACKAGES_DIR), package_name)
pkg_dir = os.path.join(self._r2env_path, self.PACKAGES_DIR, package)
try:
shutil.rmtree(pkg_dir)
print_console("Removed package {}".format(package_name))
print_console(f"[-] Removed package {package_name}")
except OSError as err:
print_console("[x] Unable to remove package {0}. Error: {1}".format(package_name, err), ERROR)
raise PackageManagerException(f"[x] Unable to remove package {package_name}. Error: {err}") \
from err
break
if not pkg_found:
print_console("[x] Unable to find installed package {0}".format(package_name), ERROR)
raise PackageManagerException(f"[x] Unable to find installed package {package_name}")
def _get_pkgname(self, profile, version, cos):
for pkgv in self._packages[profile]["versions"]:
@@ -96,82 +101,85 @@ class PackageManager:
return None
def _get_disturl(self, profile, version, cos):
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])
pkgname = self._get_pkgname(profile, version, cos)
if pkgname is not None:
return "/".join([self.DOWNLOAD_URL, version, pkgname])
return None
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);
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])
try:
sysname = os.uname().sysname
except:
sysname = "Windows"
# TODO: checksum
if sysname == "Darwin":
if os.system("sudo installer -pkg " + ofile + " -target /") == 0:
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)
return True
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
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
def _uninstall_from_dist(self, profile, version):
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"
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"):
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:
pkgname = profile.split("@")[0]
except:
pkgname = profile
if os.system("sudo dpkg -r " + pkgname) == 0:
shutil.rmtree(dst)
return True
if os.path.isfile("/default.prop"): # termux
if os.system("sudo dpkg -r radare2") == 0:
return True
return False
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
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()}")
def _build_from_source(self, profile, version, source_path, dst_path, logfile, use_meson=False):
exit_if_not_exists(['git'])
print_console("[*] Installing {}@{} package from source".format(profile, version))
print_console("[-] Cloning {} version".format(version))
print_console(f"[*] Installing {profile}@{version} package from source")
print_console(f"[-] Cloning {version} version")
git_fetch(self._packages[profile]["source"], version, source_path)
print_console("[-] Cleaning Repo")
git_clean(source_path)
@@ -182,23 +190,36 @@ 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"
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)
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}")
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 ...")
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")
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}")
return os.system(cmd) == 0
def _exit_if_package_not_available(self, profile, version):
@@ -208,6 +229,5 @@ class PackageManager:
pkg_found = True
break
if not pkg_found:
print_console("{}@{} package not available. Use 'list' command to see available packages."
.format(profile, version), level=ERROR)
sys.exit(-1)
raise PackageManagerException(
f"{profile}@{version} package not available. Use 'list' command to see available packages.")
+94 -89
View File
@@ -3,119 +3,124 @@
import argparse
import sys
from r2env.exceptions import ActionException, R2EnvException, PackageManagerException
from r2env.tools import print_console, ERROR
from r2env.core import R2Env
HELP_MESSAGE = """
Usage: r2env [-flags] [action] [args...]
class REPL:
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():
print_console(HELP_MESSAGE)
def show_help(self):
print_console(self.HELP_MESSAGE)
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()
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])
else:
print_console("[x] Missing package argument.", ERROR)
R2Env().list_available_packages()
sys.exit(-1)
self.actions[action]()
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 = show_help
argp = parser.parse_args()
run_action(argp)
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)
if __name__ == "__main__":
+297
View File
@@ -0,0 +1,297 @@
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
@@ -0,0 +1,403 @@
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
@@ -0,0 +1,55 @@
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)
+40 -31
View File
@@ -2,14 +2,16 @@
import json
import os
import sys
from shutil import which
import git
from colorama import Fore, Style
from git import Repo
# Global Vars
from r2env.exceptions import PackageManagerException
INFO = 0
WARNING = 1
ERROR = 2
@@ -31,45 +33,53 @@ def print_console(msg, level=INFO, formatter=0):
def host_platform():
if os.name == "nt":
return "w64"
return "windows"
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():
def host_distname(): # noqa: C901
dist_name = None
try:
sysname = os.uname().sysname
machine = os.uname().machine
except:
sysname = "w64"
except AttributeError:
sysname = "Windows"
machine = "amd64"
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 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 os.path.isfile("/default.prop"):
return "android"
return None
dist_name = "android"
return dist_name
def git_fetch(url, version, source_path):
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)
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 version != "git":
repo.git.checkout(version)
sms = repo.submodules
@@ -90,14 +100,13 @@ def exists(tool):
def exit_if_not_exists(tools):
for tool in tools:
if not exists(tool):
print_console("[x] {} is required. Please install it first", level=ERROR)
sys.exit(-1)
raise PackageManagerException(f"[x] {tool} is required. Please install it first")
def load_json_file(filepath):
try:
with open(filepath) as json_file:
with open(filepath, encoding="utf-8") as json_file:
return json.load(json_file)
except OSError as err:
print_console("File {} not found. Msg: {}".format(filepath, err), ERROR)
print_console(f"File {filepath} not found. Msg: {err}", ERROR)
return None
+1 -1
View File
@@ -1 +1 @@
0.4.2
0.5.2
+1 -1
View File
@@ -7,4 +7,4 @@ mock
pytest
coverage
doublex
tox
tox
Regular → Executable
+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 $base_dir -name \*.pyc | xargs rm 2>/dev/null
find . -name \*.pyc | xargs rm 2>/dev/null
python -m coverage run -m pytest -v -rsx -k "test_" --ignore=bin/
ecode=$?
+4 -1
View File
@@ -5,5 +5,8 @@ from setuptools import setup
setup(
setup_requires=['pbr'],
pbr=True,
package_files=[('config', ['r2env/config/config.json', 'r2env/config/profiles.json'])]
package_files=[
('config', ['r2env/config/config.json', 'r2env/config/profiles.json']),
('', ['version.txt'])
]
)
+5 -5
View File
@@ -1,15 +1,15 @@
[tox]
envlist = py{38,39}-{tests},{py38,py39}-codecheck-{pylint,flake8,bandit}
envlist = py{38,39,310}-{tests},{py38,py39,310}-codecheck-{pylint,flake8,bandit}
skipsdist = True
[testenv]
deps = -r {toxinidir}/requirements/test.txt
passenv = *
commands =
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
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
[flake8]
# to ignore complete files, add to the file: # flake8: noqa