mirror of
https://github.com/tcsenpai/nixvenv.git
synced 2025-06-02 17:20:07 +00:00
Initial commit
This commit is contained in:
commit
b262b2e0dc
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
alternative.json
|
||||
localenv
|
||||
altenv
|
||||
.cache
|
53
README.md
Normal file
53
README.md
Normal file
@ -0,0 +1,53 @@
|
||||
# NixVenv
|
||||
|
||||
## A pythonesque venv like approach to system virtual environments
|
||||
|
||||
### What is this?
|
||||
|
||||
Just as Python's venv allows developers to specify virtual environments for their python projects, NixVenv goal is to provide developers with the possibility to create virtual environments for their whole system.
|
||||
|
||||
Have you ever met a dependency that is required but would break your code elsewhere in your system? With NixVenv you can create a virtual environment for that specific application and run it with customized files, environment variables and configurations. Once you have finished, just deactivate it and you will be back in your usual shell environment.
|
||||
|
||||
### Features
|
||||
|
||||
• Customizable environment variables
|
||||
• Easy to set up configuration
|
||||
• Local files support
|
||||
• Local binaries support and priority
|
||||
|
||||
### Installation
|
||||
|
||||
To install NixVenv, execute in a terminal:
|
||||
|
||||
git clone https://github.com/thecookingsenpai/nixvenv
|
||||
cd nixvenv
|
||||
pip install -r requirements.txt
|
||||
|
||||
Alternatively, you can install NixVenv using pip:
|
||||
|
||||
pip install nixvenv
|
||||
|
||||
Or by building the pip package yourself:
|
||||
|
||||
git clone https://github.com/thecookingsenpai/nixvenv
|
||||
cd nixvenv
|
||||
python -m pip install -e pip_package
|
||||
|
||||
In both these cases, you will have to provide (or copy from here) your own config.json file
|
||||
|
||||
### Usage
|
||||
|
||||
python nvenv.py operation=<operation> config_file=<configuration_json>
|
||||
|
||||
### Command Line Arguments
|
||||
|
||||
#### operation=
|
||||
|
||||
• run: activate the nvenv environment specified by the configuration
|
||||
• activate: same as above
|
||||
• new: create and activate the nvenv environment specified by the configuration if not already present
|
||||
• remove: remove the nvenv environment specified by the configuration
|
||||
|
||||
#### config_file=
|
||||
|
||||
Any valid json file containing a nvenv configuration (relative path).
|
20
config.json
Normal file
20
config.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"nvenv_name": "localenv",
|
||||
"working_dir": "./localenv",
|
||||
"local_bin": "bin",
|
||||
"load_file": "load.sh",
|
||||
"init_cmds": {
|
||||
"nvenv_folder": "mkdir test",
|
||||
"local_bin_folder": "echo '#!/bin/bash \necho It is working!' > nvenv_test && chmod +x nvenv_test",
|
||||
"here": "mkdir .cache"
|
||||
},
|
||||
"overwrites" : {
|
||||
"IS_VENV": "true"
|
||||
},
|
||||
"files": [
|
||||
["./test", ".cache/test"]
|
||||
],
|
||||
"additions" : {
|
||||
"PATH": "/usr/local/sbin:/home/tcsenpai/bin"
|
||||
}
|
||||
}
|
159
nvenv.py
Normal file
159
nvenv.py
Normal file
@ -0,0 +1,159 @@
|
||||
import os
|
||||
import subprocess
|
||||
import json
|
||||
from pprint import pprint
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
environment = os.environ.copy()
|
||||
config = {}
|
||||
nvenv_name = ""
|
||||
local_bin_folder = ""
|
||||
load_file = ""
|
||||
hostname = ""
|
||||
username = ""
|
||||
|
||||
# INFO Entry point
|
||||
def main(config_file="./config.json", new=False, delete=False):
|
||||
print("[ Welcome to NixVenv, the *nix compatible virtual shell environment manager ]")
|
||||
global environment, config, cmds, local_bin_folder, load_file, nvenv_name, shell, hostname, username
|
||||
p = subprocess.run("whoami", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
username = p.stdout.decode('utf-8').strip()
|
||||
p = subprocess.run("hostname", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
hostname = p.stdout.decode('utf-8').strip()
|
||||
p = subprocess.run("echo $SHELL", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
shell = p.stdout.decode('utf-8').strip()
|
||||
print(shell)
|
||||
cmds = 'echo "[ Setting environment variables ]"\n'
|
||||
config = open(config_file, "r")
|
||||
config = json.loads(config.read())
|
||||
print("[*] Config file loaded: " + config_file)
|
||||
nvenv_name = config["nvenv_name"]
|
||||
# Halt if we have to delete the environment
|
||||
if delete:
|
||||
if not os.path.exists(nvenv_name):
|
||||
print("[*] Environment does not exist: " + nvenv_name)
|
||||
else:
|
||||
shutil.rmtree(nvenv_name, ignore_errors=True)
|
||||
print("[*] Deleted environment: " + nvenv_name)
|
||||
os._exit(0)
|
||||
# Else we use the environment
|
||||
print("[*] Reading from environment: " + nvenv_name)
|
||||
local_bin_folder = os.getcwd() + "/" + nvenv_name + "/" + config["local_bin"]
|
||||
print("[*] Local bin folder: " + local_bin_folder)
|
||||
load_file = os.getcwd() + "/" + nvenv_name + "/" + config["load_file"]
|
||||
new_environment(new)
|
||||
load_config()
|
||||
load_environment()
|
||||
|
||||
# INFO Load a configuration file
|
||||
def load_config():
|
||||
global cmds, local_bin_folder, load_file, hostname
|
||||
# Overwrites replace environment variables fully or create a new one
|
||||
overwrites = config['overwrites']
|
||||
for key in overwrites:
|
||||
cmds += "export " + key + "=" + overwrites[key] + "\n"
|
||||
print("[*] Overwriting enviromental variable: " + key)
|
||||
# Additions add the value to the environment variable preserving the original value
|
||||
additions = config["additions"]
|
||||
for key in additions:
|
||||
cmds += "export " + key + "=${" + key + "}:" + additions[key] + "\n"
|
||||
print("[*] Adding to enviromental variable: " + key)
|
||||
# Setting our environment variables
|
||||
print("[*] Setting our environment variables")
|
||||
cmds += "export PATH=" + local_bin_folder + ":" + os.environ["PATH"]
|
||||
# Loading the static environment variables defined in the config file
|
||||
print("[*] Setting the environment name as " + config["nvenv_name"])
|
||||
cmds += "export NVENV_NAME=" + config["nvenv_name"] + "\n"
|
||||
print("[*] Changing to: " + config["working_dir"])
|
||||
cmds += "cd " + config["working_dir"] + "\n"
|
||||
cmds += 'echo "nvenv environment loaded: $NVENV_NAME"\n'
|
||||
# Setting up customizations
|
||||
cmds += 'export PS1="' + username + ' [' + config["nvenv_name"] + '@' + hostname+ '] :> "\n'
|
||||
# Finally, writing to the load file
|
||||
print("[*] Writing to the load file: " + load_file)
|
||||
with open(load_file, "w") as f:
|
||||
f.write(cmds)
|
||||
|
||||
# INFO Loading the local environment fully
|
||||
def load_environment():
|
||||
print("[*] Loading the environment")
|
||||
global environment, load_file, shell
|
||||
# Multiple shells are supported
|
||||
if "zsh" in shell:
|
||||
cmd = "source " + load_file + " && " + shell + " -f -d"
|
||||
else:
|
||||
cmd = shell + " --rcfile " + load_file
|
||||
# Finally, loading the environment by sourcing the load file
|
||||
print("[+] Executing: " + cmd)
|
||||
print("\nNOTE: Digit 'exit' and press ENTER to return to the previous environment\n")
|
||||
os.system(cmd)
|
||||
|
||||
# INFO Environemnt creation
|
||||
def new_environment(new_flag=False):
|
||||
global cmds, local_bin_folder
|
||||
if os.path.exists(os.getcwd() + "/" + nvenv_name):
|
||||
if not new_flag:
|
||||
raise Exception("[x] Environment already exists: " + nvenv_name)
|
||||
print("[+] Environment already exists: " + nvenv_name)
|
||||
return
|
||||
# Creating the local_bin_folder if it doesn't exist
|
||||
if not os.path.exists(local_bin_folder):
|
||||
os.makedirs(local_bin_folder)
|
||||
# Reading the init commands
|
||||
init_cmds_list = config["init_cmds"]
|
||||
for cmd in init_cmds_list:
|
||||
# Replacing folders if needed
|
||||
if (cmd == "here"):
|
||||
running_dir = os.getcwd()
|
||||
elif (cmd == "nvenv_folder"):
|
||||
running_dir = os.getcwd() + "/" + nvenv_name
|
||||
elif (cmd == "local_bin_folder"):
|
||||
running_dir = local_bin_folder
|
||||
else:
|
||||
# Support for custom directories
|
||||
# REVIEW Security note: limit it to the current working directory
|
||||
if not os.path.exists(running_dir):
|
||||
raise Exception("Running directory does not exist: " + running_dir)
|
||||
# Compiling the command to be executed before the environment is activated
|
||||
single_cmd = init_cmds_list[cmd]
|
||||
actual_cmd = "cd '" + running_dir + "' && " + single_cmd
|
||||
print("[*] Executing: " + actual_cmd)
|
||||
os.system(actual_cmd)
|
||||
# Support files
|
||||
files = config["files"]
|
||||
for file in files:
|
||||
origin = file[0]
|
||||
destination = file[1]
|
||||
if not os.path.exists(origin):
|
||||
raise Exception("[x] Origin file does not exist: " + origin)
|
||||
if os.path.exists(destination):
|
||||
raise Exception("[x] Destination file already exists: " + destination)
|
||||
print("[*] Copying file: " + origin + " to: " + destination)
|
||||
shutil.copy(origin, destination)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Argument parsing
|
||||
args_len = len(sys.argv)
|
||||
print(sys.argv)
|
||||
filename = sys.argv[0]
|
||||
params = {
|
||||
"operation": "run",
|
||||
"config_file": "config.json",
|
||||
}
|
||||
# Getting parameters
|
||||
for param in sys.argv[1:]:
|
||||
if "operation=" in param:
|
||||
params["operation"] = param.split("=")[1]
|
||||
if "config_file=" in param:
|
||||
params["config_file"] = param.split("=")[1]
|
||||
# Sanity checks
|
||||
if not os.path.exists(params["config_file"]):
|
||||
raise Exception("[x] Config file does not exist: " + params["config_file"])
|
||||
# Runs based on operation
|
||||
if params["operation"] == "activate" or params["operation"] == "run":
|
||||
main(config_file=params["config_file"])
|
||||
elif params["operation"] == "new":
|
||||
main(config_file=params["config_file"], new=True)
|
||||
elif params["operation"] == "remove":
|
||||
main(config_file=params["config_file"], delete=True)
|
0
pip_package/LICENSE
Normal file
0
pip_package/LICENSE
Normal file
0
pip_package/MANIFEST.in
Normal file
0
pip_package/MANIFEST.in
Normal file
47
pip_package/README.md
Normal file
47
pip_package/README.md
Normal file
@ -0,0 +1,47 @@
|
||||
# NixVenv
|
||||
|
||||
## A pythonesque venv like approach to system virtual environments
|
||||
|
||||
### What is this?
|
||||
|
||||
Just as Python's venv allows developers to specify virtual environments for their python projects, NixVenv goal is to provide developers with the possibility to create virtual environments for their whole system.
|
||||
|
||||
Have you ever met a dependency that is required but would break your code elsewhere in your system? With NixVenv you can create a virtual environment for that specific application and run it with customized files, environment variables and configurations. Once you have finished, just deactivate it and you will be back in your usual shell environment.
|
||||
|
||||
### Features
|
||||
|
||||
• Customizable environment variables
|
||||
• Easy to set up configuration
|
||||
• Local files support
|
||||
• Local binaries support and priority
|
||||
|
||||
### Installation
|
||||
|
||||
To install NixVenv, execute in a terminal:
|
||||
|
||||
git clone https://github.com/thecookingsenpai/nixvenv
|
||||
cd nixvenv
|
||||
pip install -r requirements.txt
|
||||
|
||||
Alternatively, you can install NixVenv using pip:
|
||||
|
||||
pip install nixvenv
|
||||
|
||||
In this case, you will have to provide (or copy from here) your own config.json file
|
||||
|
||||
### Usage
|
||||
|
||||
python nvenv.py operation=<operation> config_file=<configuration_json>
|
||||
|
||||
### Command Line Arguments
|
||||
|
||||
#### operation=
|
||||
|
||||
• run: activate the nvenv environment specified by the configuration
|
||||
• activate: same as above
|
||||
• new: create and activate the nvenv environment specified by the configuration if not already present
|
||||
• remove: remove the nvenv environment specified by the configuration
|
||||
|
||||
#### config_file=
|
||||
|
||||
Any valid json file containing a nvenv configuration (relative path).
|
0
pip_package/pyproject.toml
Normal file
0
pip_package/pyproject.toml
Normal file
4
pip_package/src/nixvenv.egg-info/PKG-INFO
Normal file
4
pip_package/src/nixvenv.egg-info/PKG-INFO
Normal file
@ -0,0 +1,4 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: nixvenv
|
||||
Version: 0.0.0
|
||||
License-File: LICENSE
|
10
pip_package/src/nixvenv.egg-info/SOURCES.txt
Normal file
10
pip_package/src/nixvenv.egg-info/SOURCES.txt
Normal file
@ -0,0 +1,10 @@
|
||||
LICENSE
|
||||
MANIFEST.in
|
||||
README.md
|
||||
pyproject.toml
|
||||
src/nixvenv/__init__.py
|
||||
src/nixvenv/__main__.py
|
||||
src/nixvenv.egg-info/PKG-INFO
|
||||
src/nixvenv.egg-info/SOURCES.txt
|
||||
src/nixvenv.egg-info/dependency_links.txt
|
||||
src/nixvenv.egg-info/top_level.txt
|
1
pip_package/src/nixvenv.egg-info/dependency_links.txt
Normal file
1
pip_package/src/nixvenv.egg-info/dependency_links.txt
Normal file
@ -0,0 +1 @@
|
||||
|
1
pip_package/src/nixvenv.egg-info/top_level.txt
Normal file
1
pip_package/src/nixvenv.egg-info/top_level.txt
Normal file
@ -0,0 +1 @@
|
||||
nixvenv
|
1
pip_package/src/nixvenv/__init__.py
Normal file
1
pip_package/src/nixvenv/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__version__ = "0.0.1"
|
159
pip_package/src/nixvenv/__main__.py
Normal file
159
pip_package/src/nixvenv/__main__.py
Normal file
@ -0,0 +1,159 @@
|
||||
import os
|
||||
import subprocess
|
||||
import json
|
||||
from pprint import pprint
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
environment = os.environ.copy()
|
||||
config = {}
|
||||
nvenv_name = ""
|
||||
local_bin_folder = ""
|
||||
load_file = ""
|
||||
hostname = ""
|
||||
username = ""
|
||||
|
||||
# INFO Entry point
|
||||
def main(config_file="./config.json", new=False, delete=False):
|
||||
print("[ Welcome to NixVenv, the *nix compatible virtual shell environment manager ]")
|
||||
global environment, config, cmds, local_bin_folder, load_file, nvenv_name, shell, hostname, username
|
||||
p = subprocess.run("whoami", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
username = p.stdout.decode('utf-8').strip()
|
||||
p = subprocess.run("hostname", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
hostname = p.stdout.decode('utf-8').strip()
|
||||
p = subprocess.run("echo $SHELL", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
shell = p.stdout.decode('utf-8').strip()
|
||||
print(shell)
|
||||
cmds = 'echo "[ Setting environment variables ]"\n'
|
||||
config = open(config_file, "r")
|
||||
config = json.loads(config.read())
|
||||
print("[*] Config file loaded: " + config_file)
|
||||
nvenv_name = config["nvenv_name"]
|
||||
# Halt if we have to delete the environment
|
||||
if delete:
|
||||
if not os.path.exists(nvenv_name):
|
||||
print("[*] Environment does not exist: " + nvenv_name)
|
||||
else:
|
||||
shutil.rmtree(nvenv_name, ignore_errors=True)
|
||||
print("[*] Deleted environment: " + nvenv_name)
|
||||
os._exit(0)
|
||||
# Else we use the environment
|
||||
print("[*] Reading from environment: " + nvenv_name)
|
||||
local_bin_folder = os.getcwd() + "/" + nvenv_name + "/" + config["local_bin"]
|
||||
print("[*] Local bin folder: " + local_bin_folder)
|
||||
load_file = os.getcwd() + "/" + nvenv_name + "/" + config["load_file"]
|
||||
new_environment(new)
|
||||
load_config()
|
||||
load_environment()
|
||||
|
||||
# INFO Load a configuration file
|
||||
def load_config():
|
||||
global cmds, local_bin_folder, load_file, hostname
|
||||
# Overwrites replace environment variables fully or create a new one
|
||||
overwrites = config['overwrites']
|
||||
for key in overwrites:
|
||||
cmds += "export " + key + "=" + overwrites[key] + "\n"
|
||||
print("[*] Overwriting enviromental variable: " + key)
|
||||
# Additions add the value to the environment variable preserving the original value
|
||||
additions = config["additions"]
|
||||
for key in additions:
|
||||
cmds += "export " + key + "=${" + key + "}:" + additions[key] + "\n"
|
||||
print("[*] Adding to enviromental variable: " + key)
|
||||
# Setting our environment variables
|
||||
print("[*] Setting our environment variables")
|
||||
cmds += "export PATH=" + local_bin_folder + ":" + os.environ["PATH"]
|
||||
# Loading the static environment variables defined in the config file
|
||||
print("[*] Setting the environment name as " + config["nvenv_name"])
|
||||
cmds += "export NVENV_NAME=" + config["nvenv_name"] + "\n"
|
||||
print("[*] Changing to: " + config["working_dir"])
|
||||
cmds += "cd " + config["working_dir"] + "\n"
|
||||
cmds += 'echo "nvenv environment loaded: $NVENV_NAME"\n'
|
||||
# Setting up customizations
|
||||
cmds += 'export PS1="' + username + ' [' + config["nvenv_name"] + '@' + hostname+ '] :> "\n'
|
||||
# Finally, writing to the load file
|
||||
print("[*] Writing to the load file: " + load_file)
|
||||
with open(load_file, "w") as f:
|
||||
f.write(cmds)
|
||||
|
||||
# INFO Loading the local environment fully
|
||||
def load_environment():
|
||||
print("[*] Loading the environment")
|
||||
global environment, load_file, shell
|
||||
# Multiple shells are supported
|
||||
if "zsh" in shell:
|
||||
cmd = "source " + load_file + " && " + shell + " -f -d"
|
||||
else:
|
||||
cmd = shell + " --rcfile " + load_file
|
||||
# Finally, loading the environment by sourcing the load file
|
||||
print("[+] Executing: " + cmd)
|
||||
print("\nNOTE: Digit 'exit' and press ENTER to return to the previous environment\n")
|
||||
os.system(cmd)
|
||||
|
||||
# INFO Environemnt creation
|
||||
def new_environment(new_flag=False):
|
||||
global cmds, local_bin_folder
|
||||
if os.path.exists(os.getcwd() + "/" + nvenv_name):
|
||||
if not new_flag:
|
||||
raise Exception("[x] Environment already exists: " + nvenv_name)
|
||||
print("[+] Environment already exists: " + nvenv_name)
|
||||
return
|
||||
# Creating the local_bin_folder if it doesn't exist
|
||||
if not os.path.exists(local_bin_folder):
|
||||
os.makedirs(local_bin_folder)
|
||||
# Reading the init commands
|
||||
init_cmds_list = config["init_cmds"]
|
||||
for cmd in init_cmds_list:
|
||||
# Replacing folders if needed
|
||||
if (cmd == "here"):
|
||||
running_dir = os.getcwd()
|
||||
elif (cmd == "nvenv_folder"):
|
||||
running_dir = os.getcwd() + "/" + nvenv_name
|
||||
elif (cmd == "local_bin_folder"):
|
||||
running_dir = local_bin_folder
|
||||
else:
|
||||
# Support for custom directories
|
||||
# REVIEW Security note: limit it to the current working directory
|
||||
if not os.path.exists(running_dir):
|
||||
raise Exception("Running directory does not exist: " + running_dir)
|
||||
# Compiling the command to be executed before the environment is activated
|
||||
single_cmd = init_cmds_list[cmd]
|
||||
actual_cmd = "cd '" + running_dir + "' && " + single_cmd
|
||||
print("[*] Executing: " + actual_cmd)
|
||||
os.system(actual_cmd)
|
||||
# Support files
|
||||
files = config["files"]
|
||||
for file in files:
|
||||
origin = file[0]
|
||||
destination = file[1]
|
||||
if not os.path.exists(origin):
|
||||
raise Exception("[x] Origin file does not exist: " + origin)
|
||||
if os.path.exists(destination):
|
||||
raise Exception("[x] Destination file already exists: " + destination)
|
||||
print("[*] Copying file: " + origin + " to: " + destination)
|
||||
shutil.copy(origin, destination)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Argument parsing
|
||||
args_len = len(sys.argv)
|
||||
print(sys.argv)
|
||||
filename = sys.argv[0]
|
||||
params = {
|
||||
"operation": "run",
|
||||
"config_file": "config.json",
|
||||
}
|
||||
# Getting parameters
|
||||
for param in sys.argv[1:]:
|
||||
if "operation=" in param:
|
||||
params["operation"] = param.split("=")[1]
|
||||
if "config_file=" in param:
|
||||
params["config_file"] = param.split("=")[1]
|
||||
# Sanity checks
|
||||
if not os.path.exists(params["config_file"]):
|
||||
raise Exception("[x] Config file does not exist: " + params["config_file"])
|
||||
# Runs based on operation
|
||||
if params["operation"] == "activate" or params["operation"] == "run":
|
||||
main(config_file=params["config_file"])
|
||||
elif params["operation"] == "new":
|
||||
main(config_file=params["config_file"], new=True)
|
||||
elif params["operation"] == "remove":
|
||||
main(config_file=params["config_file"], delete=True)
|
BIN
pip_package/src/nixvenv/__pycache__/__init__.cpython-39.pyc
Normal file
BIN
pip_package/src/nixvenv/__pycache__/__init__.cpython-39.pyc
Normal file
Binary file not shown.
BIN
pip_package/src/nixvenv/__pycache__/__main__.cpython-39.pyc
Normal file
BIN
pip_package/src/nixvenv/__pycache__/__main__.cpython-39.pyc
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user