From 7a94ecd3a7aa7389ef628c7fa6bd5813c3259624 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Sat, 23 May 2020 23:22:16 -0400 Subject: [PATCH 01/39] Getting started on the improved manifest. --- packages/README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 packages/README.md diff --git a/packages/README.md b/packages/README.md new file mode 100644 index 0000000..c24705e --- /dev/null +++ b/packages/README.md @@ -0,0 +1,24 @@ +# planutils packages + +Each package must contain the files `manifest.json`, `install`, and `uninstall`. Optionally, `run` can be included if the package installs a command-line executable (e.g., planners). An example of all four files can be found in the `TEMPLATE` directory, and a description of each follows. + +## manifest.json + +Details on the package. Must include: + +1. **name**: Long-form name of the package. +2. **shortname**: Short-form name that will be used for installation, running, etc. +3. **description**: General description of the package. +4. **dependencies**: List of shortnames for other `planutils` packages that are required. + +## install + +Script to install the package along with any dependencies not part of `planutils`. + +## uninstall + +Cleanup script to remove the package installation. + +## run + +(optional) Script to run the installed package. `shortname` specified in the `manifest.json` file will be used for the command-line invocation of this script. From 8a197d61b6c676b536a5268808fdc107d7081407 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Sun, 24 May 2020 23:23:09 -0400 Subject: [PATCH 02/39] Initial draft of a package template. --- MANIFEST.in | 3 ++- packages/TEMPLATE/install | 11 +++++++++++ packages/TEMPLATE/manifest.json | 6 ++++++ packages/TEMPLATE/run | 3 +++ packages/TEMPLATE/uninstall | 10 ++++++++++ 5 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 packages/TEMPLATE/install create mode 100644 packages/TEMPLATE/manifest.json create mode 100644 packages/TEMPLATE/run create mode 100644 packages/TEMPLATE/uninstall diff --git a/MANIFEST.in b/MANIFEST.in index 994c0f0..ad2657f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1,2 @@ -include planutils/planner_configs/*.json \ No newline at end of file +include planutils/planner_configs/*.json +include packages/ \ No newline at end of file diff --git a/packages/TEMPLATE/install b/packages/TEMPLATE/install new file mode 100644 index 0000000..b9c2847 --- /dev/null +++ b/packages/TEMPLATE/install @@ -0,0 +1,11 @@ +#!/bin/bash + +# To use if root is required +[ "$UID" -eq 0 ] || (echo "installation requires root access"; exec sudo "$0" "$@") + +# Install general linux dependencies + +# General setup / configuration + +# No need to install planutils dependencies +# No need to check if already installed \ No newline at end of file diff --git a/packages/TEMPLATE/manifest.json b/packages/TEMPLATE/manifest.json new file mode 100644 index 0000000..51716f3 --- /dev/null +++ b/packages/TEMPLATE/manifest.json @@ -0,0 +1,6 @@ +{ + "name": "Full name of package", + "shortname": "code-used-to-isntall-run-etc", + "description": "General description of the package", + "dependencies": ["list", "of", "dependencies"] +} \ No newline at end of file diff --git a/packages/TEMPLATE/run b/packages/TEMPLATE/run new file mode 100644 index 0000000..0638e73 --- /dev/null +++ b/packages/TEMPLATE/run @@ -0,0 +1,3 @@ +#!/bin/bash + +# whatever command-line method needs to be used to run this package \ No newline at end of file diff --git a/packages/TEMPLATE/uninstall b/packages/TEMPLATE/uninstall new file mode 100644 index 0000000..257235b --- /dev/null +++ b/packages/TEMPLATE/uninstall @@ -0,0 +1,10 @@ +#!/bin/bash + +# To use if root is required +[ "$UID" -eq 0 ] || (echo "installation requires root access"; exec sudo "$0" "$@") + +# Only uninstall general linux dependencies in rare circumstances -- if another package requires it, there is risk of breaking their dependency. + +# Remove general setup / configuration + +# No need to uninstall planutils dependencies \ No newline at end of file From 5320d8a5201093712203bc84d45c6913c1dd97fd Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Mon, 25 May 2020 22:44:09 -0400 Subject: [PATCH 03/39] Finished the initial config for the new package format. Still needs to be implemented in the code / packaging system. --- packages/TEMPLATE/install | 10 ++++++++++ packages/TEMPLATE/uninstall | 6 +++++- packages/fd/install | 4 ++++ packages/fd/manifest.json | 6 ++++++ packages/fd/run | 3 +++ packages/fd/uninstall | 3 +++ packages/lama/install | 3 +++ packages/lama/manifest.json | 6 ++++++ packages/lama/run | 3 +++ packages/lama/uninstall | 3 +++ 10 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 packages/fd/install create mode 100644 packages/fd/manifest.json create mode 100644 packages/fd/run create mode 100644 packages/fd/uninstall create mode 100644 packages/lama/install create mode 100644 packages/lama/manifest.json create mode 100644 packages/lama/run create mode 100644 packages/lama/uninstall diff --git a/packages/TEMPLATE/install b/packages/TEMPLATE/install index b9c2847..85d83f0 100644 --- a/packages/TEMPLATE/install +++ b/packages/TEMPLATE/install @@ -7,5 +7,15 @@ # General setup / configuration + +# Recipe for singularity images +## Fetch the image +singularity pull --name + +## Move it to the right place +mv ~/.planutils/bin/images/ + + +# No need to move the "run" script -- if it exists, this will be handled for you # No need to install planutils dependencies # No need to check if already installed \ No newline at end of file diff --git a/packages/TEMPLATE/uninstall b/packages/TEMPLATE/uninstall index 257235b..f61dcf1 100644 --- a/packages/TEMPLATE/uninstall +++ b/packages/TEMPLATE/uninstall @@ -7,4 +7,8 @@ # Remove general setup / configuration -# No need to uninstall planutils dependencies \ No newline at end of file +# Recipe for singularity images +rm ~/.planutils/bin/images/ + +# No need to uninstall planutils dependencies +# No need to revert the "run" script if it exists \ No newline at end of file diff --git a/packages/fd/install b/packages/fd/install new file mode 100644 index 0000000..8656377 --- /dev/null +++ b/packages/fd/install @@ -0,0 +1,4 @@ +#!/bin/bash + +singularity pull --name downward.simg shub://aibasel/downward +mv downward.simg ~/.planutils/bin/images/ diff --git a/packages/fd/manifest.json b/packages/fd/manifest.json new file mode 100644 index 0000000..04f33af --- /dev/null +++ b/packages/fd/manifest.json @@ -0,0 +1,6 @@ +{ + "name": "Fast Downward", + "shortname": "fd", + "description": "http://fast-downward.org/", + "dependencies": [] +} \ No newline at end of file diff --git a/packages/fd/run b/packages/fd/run new file mode 100644 index 0000000..8487b1a --- /dev/null +++ b/packages/fd/run @@ -0,0 +1,3 @@ +#!/bin/bash + +singularity run ~/.planutils/bin/images/downward.simg $@ diff --git a/packages/fd/uninstall b/packages/fd/uninstall new file mode 100644 index 0000000..4fa0a8d --- /dev/null +++ b/packages/fd/uninstall @@ -0,0 +1,3 @@ +#!/bin/bash + +rm ~/.planutils/bin/images/downward.simg \ No newline at end of file diff --git a/packages/lama/install b/packages/lama/install new file mode 100644 index 0000000..3b981a2 --- /dev/null +++ b/packages/lama/install @@ -0,0 +1,3 @@ +#!/bin/bash + +# Nothing to do! diff --git a/packages/lama/manifest.json b/packages/lama/manifest.json new file mode 100644 index 0000000..71ec946 --- /dev/null +++ b/packages/lama/manifest.json @@ -0,0 +1,6 @@ +{ + "name": "LAMA", + "shortname": "lama", + "description": "http://fast-downward.org/", + "dependencies": ["fd"] +} \ No newline at end of file diff --git a/packages/lama/run b/packages/lama/run new file mode 100644 index 0000000..59342ca --- /dev/null +++ b/packages/lama/run @@ -0,0 +1,3 @@ +#!/bin/bash + +fd --alias lama-first $@ diff --git a/packages/lama/uninstall b/packages/lama/uninstall new file mode 100644 index 0000000..3b981a2 --- /dev/null +++ b/packages/lama/uninstall @@ -0,0 +1,3 @@ +#!/bin/bash + +# Nothing to do! From 284e0a53c8d049cdeb03810402f731f6bfd9e39a Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Tue, 26 May 2020 22:38:58 -0400 Subject: [PATCH 04/39] Added some generic planutils directory variable. --- packages/TEMPLATE/install | 15 +++++++-------- packages/TEMPLATE/uninstall | 4 ++-- packages/fd/install | 2 +- packages/fd/run | 2 +- packages/fd/uninstall | 2 +- planutils/__init__.py | 3 ++- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/TEMPLATE/install b/packages/TEMPLATE/install index 85d83f0..3d702e3 100644 --- a/packages/TEMPLATE/install +++ b/packages/TEMPLATE/install @@ -1,7 +1,11 @@ #!/bin/bash +# No need to move the "run" script -- if it exists, this will be handled for you +# No need to install planutils dependencies +# No need to check if already installed + # To use if root is required -[ "$UID" -eq 0 ] || (echo "installation requires root access"; exec sudo "$0" "$@") +#[ "$UID" -eq 0 ] || (echo "installation requires root access"; exec sudo "$0" "$@") # Install general linux dependencies @@ -10,12 +14,7 @@ # Recipe for singularity images ## Fetch the image -singularity pull --name +#singularity pull --name ## Move it to the right place -mv ~/.planutils/bin/images/ - - -# No need to move the "run" script -- if it exists, this will be handled for you -# No need to install planutils dependencies -# No need to check if already installed \ No newline at end of file +#mv $PLANUTILS_PREFIX/bin/images/ \ No newline at end of file diff --git a/packages/TEMPLATE/uninstall b/packages/TEMPLATE/uninstall index f61dcf1..d4f4235 100644 --- a/packages/TEMPLATE/uninstall +++ b/packages/TEMPLATE/uninstall @@ -1,14 +1,14 @@ #!/bin/bash # To use if root is required -[ "$UID" -eq 0 ] || (echo "installation requires root access"; exec sudo "$0" "$@") +#[ "$UID" -eq 0 ] || (echo "installation requires root access"; exec sudo "$0" "$@") # Only uninstall general linux dependencies in rare circumstances -- if another package requires it, there is risk of breaking their dependency. # Remove general setup / configuration # Recipe for singularity images -rm ~/.planutils/bin/images/ +#rm $PLANUTILS_PREFIX/bin/images/ # No need to uninstall planutils dependencies # No need to revert the "run" script if it exists \ No newline at end of file diff --git a/packages/fd/install b/packages/fd/install index 8656377..2be4e59 100644 --- a/packages/fd/install +++ b/packages/fd/install @@ -1,4 +1,4 @@ #!/bin/bash singularity pull --name downward.simg shub://aibasel/downward -mv downward.simg ~/.planutils/bin/images/ +mv downward.simg $PLANUTILS_PREFIX/bin/images/ diff --git a/packages/fd/run b/packages/fd/run index 8487b1a..5a28a4d 100644 --- a/packages/fd/run +++ b/packages/fd/run @@ -1,3 +1,3 @@ #!/bin/bash -singularity run ~/.planutils/bin/images/downward.simg $@ +singularity run $PLANUTILS_PREFIX/bin/images/downward.simg $@ diff --git a/packages/fd/uninstall b/packages/fd/uninstall index 4fa0a8d..ec62009 100644 --- a/packages/fd/uninstall +++ b/packages/fd/uninstall @@ -1,3 +1,3 @@ #!/bin/bash -rm ~/.planutils/bin/images/downward.simg \ No newline at end of file +rm $PLANUTILS_PREFIX/bin/images/downward.simg \ No newline at end of file diff --git a/planutils/__init__.py b/planutils/__init__.py index 0eaa9ee..608125b 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -12,7 +12,8 @@ def setup(): os.mkdir(os.path.join(os.path.expanduser('~'), '.planutils', 'bin', 'images')) print("Adding bin folder to path (assuming ~/.bashrc exists)...") - os.system('echo \'export PATH="$HOME/.planutils/bin:$PATH"\' >> ~/.bashrc') + os.system("echo 'export PLANUTILS_PREFIX=\"%s\"' >> ~/.bashrc" % prefix) + os.system("echo 'export PATH=\"$PLANUTILS_PREFIX/bin:$PATH\"' >> ~/.bashrc") print("Installing planner scripts...") from planutils.planner_installation import PLANNERS From 00c015c7744efa5e1e821546c6b96ddb2c9b2c1f Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Tue, 26 May 2020 22:39:18 -0400 Subject: [PATCH 05/39] Updating the fast-downward shortcode. --- packages/fd/manifest.json | 2 +- packages/lama/manifest.json | 2 +- packages/lama/run | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/fd/manifest.json b/packages/fd/manifest.json index 04f33af..5b774e9 100644 --- a/packages/fd/manifest.json +++ b/packages/fd/manifest.json @@ -1,6 +1,6 @@ { "name": "Fast Downward", - "shortname": "fd", + "shortname": "downward", "description": "http://fast-downward.org/", "dependencies": [] } \ No newline at end of file diff --git a/packages/lama/manifest.json b/packages/lama/manifest.json index 71ec946..92e5d86 100644 --- a/packages/lama/manifest.json +++ b/packages/lama/manifest.json @@ -2,5 +2,5 @@ "name": "LAMA", "shortname": "lama", "description": "http://fast-downward.org/", - "dependencies": ["fd"] + "dependencies": ["downward"] } \ No newline at end of file diff --git a/packages/lama/run b/packages/lama/run index 59342ca..ac3fa91 100644 --- a/packages/lama/run +++ b/packages/lama/run @@ -1,3 +1,3 @@ #!/bin/bash -fd --alias lama-first $@ +downward --alias lama-first $@ From ba451db8a59b1ce245c109df401bdd2cc225f6d4 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Tue, 26 May 2020 23:43:42 -0400 Subject: [PATCH 06/39] Redirect for the run scripts. --- planutils/__init__.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 608125b..1c7f7b1 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -6,11 +6,16 @@ def setup(): assert not_setup_yet(), "Error: planutils is already setup. Remove ~/.planutils to reset (warning: all cached planners will be lost)." + CUR_DIR = os.path.dirname(os.path.abspath(__file__)) + print("\nCreating ~/.planutils...") os.mkdir(os.path.join(os.path.expanduser('~'), '.planutils')) os.mkdir(os.path.join(os.path.expanduser('~'), '.planutils', 'bin')) os.mkdir(os.path.join(os.path.expanduser('~'), '.planutils', 'bin', 'images')) + os.symlink(os.path.join(CUR_DIR, 'packages'), + os.path.join(os.path.expanduser('~'), '.planutils', 'packages')) + print("Adding bin folder to path (assuming ~/.bashrc exists)...") os.system("echo 'export PLANUTILS_PREFIX=\"%s\"' >> ~/.bashrc" % prefix) os.system("echo 'export PATH=\"$PLANUTILS_PREFIX/bin:$PATH\"' >> ~/.bashrc") @@ -19,14 +24,19 @@ def setup(): from planutils.planner_installation import PLANNERS for p in PLANNERS: script = "#!/bin/bash\n" - script += "echo\n" - script += "echo 'Planner not installed!'\n" - script += "read -p \"Download & install? [y/n] \" varchoice\n" - script += "if [ $varchoice == \"y\" ]\n" + script += "if [ \"$(planutils --check-installed %s)\" == \"True\" ]\n" % p script += "then\n" - script += " planutils --install " + p + "\n" - script += "fi\n" - script += "echo" + script += " $PLANUTILS_PREFIX/packages/%s/run $@\n" % p + script += "else\n" + script += " echo\n" + script += " echo 'Planner not installed!'\n" + script += " read -p \"Download & install? [y/n] \" varchoice\n" + script += " if [ $varchoice == \"y\" ]\n" + script += " then\n" + script += " planutils --install " + p + "\n" + script += " fi\n" + script += " echo\n" + script += "fi" with open(os.path.join(os.path.expanduser('~'), '.planutils', 'bin', p), 'w') as f: f.write(script) os.chmod(os.path.join(os.path.expanduser('~'), '.planutils', 'bin', p), 0o0755) @@ -44,6 +54,8 @@ def main(): help="install an individual or collection of planners ('list' shows the options)", metavar="{planner or collection or list}") + parser.add_argument("--check_installed", help="check if a package is installed") + parser.add_argument("-s", "--setup", help="setup planutils for current user", action="store_true") args = parser.parse_args() @@ -53,6 +65,9 @@ def main(): elif not_setup_yet(): print("\nPlease run 'planutils --setup' before using utility.\n") exit() + + if args.check_installed: + raise NotImplementedError if args.install: from planutils.planner_installation import install From 652734693c925bc614f79b707c5451ce40e289e6 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Tue, 26 May 2020 23:52:28 -0400 Subject: [PATCH 07/39] Changing image extension and simplifying singularity example. --- packages/TEMPLATE/install | 5 +---- packages/TEMPLATE/manifest.json | 1 - packages/TEMPLATE/uninstall | 8 ++++---- packages/fd/install | 3 +-- packages/fd/manifest.json | 1 - packages/fd/run | 2 +- packages/fd/uninstall | 2 +- packages/lama/manifest.json | 1 - 8 files changed, 8 insertions(+), 15 deletions(-) diff --git a/packages/TEMPLATE/install b/packages/TEMPLATE/install index 3d702e3..de31e78 100644 --- a/packages/TEMPLATE/install +++ b/packages/TEMPLATE/install @@ -1,8 +1,8 @@ #!/bin/bash -# No need to move the "run" script -- if it exists, this will be handled for you # No need to install planutils dependencies # No need to check if already installed +# The install script will be run from the package's directory # To use if root is required #[ "$UID" -eq 0 ] || (echo "installation requires root access"; exec sudo "$0" "$@") @@ -15,6 +15,3 @@ # Recipe for singularity images ## Fetch the image #singularity pull --name - -## Move it to the right place -#mv $PLANUTILS_PREFIX/bin/images/ \ No newline at end of file diff --git a/packages/TEMPLATE/manifest.json b/packages/TEMPLATE/manifest.json index 51716f3..b745777 100644 --- a/packages/TEMPLATE/manifest.json +++ b/packages/TEMPLATE/manifest.json @@ -1,6 +1,5 @@ { "name": "Full name of package", - "shortname": "code-used-to-isntall-run-etc", "description": "General description of the package", "dependencies": ["list", "of", "dependencies"] } \ No newline at end of file diff --git a/packages/TEMPLATE/uninstall b/packages/TEMPLATE/uninstall index d4f4235..42cb6f5 100644 --- a/packages/TEMPLATE/uninstall +++ b/packages/TEMPLATE/uninstall @@ -1,5 +1,8 @@ #!/bin/bash +# No need to uninstall planutils dependencies +# The uninstall script will be run from the package's directory + # To use if root is required #[ "$UID" -eq 0 ] || (echo "installation requires root access"; exec sudo "$0" "$@") @@ -8,7 +11,4 @@ # Remove general setup / configuration # Recipe for singularity images -#rm $PLANUTILS_PREFIX/bin/images/ - -# No need to uninstall planutils dependencies -# No need to revert the "run" script if it exists \ No newline at end of file +#rm diff --git a/packages/fd/install b/packages/fd/install index 2be4e59..80d4ae0 100644 --- a/packages/fd/install +++ b/packages/fd/install @@ -1,4 +1,3 @@ #!/bin/bash -singularity pull --name downward.simg shub://aibasel/downward -mv downward.simg $PLANUTILS_PREFIX/bin/images/ +singularity pull --name downward.sif shub://aibasel/downward diff --git a/packages/fd/manifest.json b/packages/fd/manifest.json index 5b774e9..00e3f19 100644 --- a/packages/fd/manifest.json +++ b/packages/fd/manifest.json @@ -1,6 +1,5 @@ { "name": "Fast Downward", - "shortname": "downward", "description": "http://fast-downward.org/", "dependencies": [] } \ No newline at end of file diff --git a/packages/fd/run b/packages/fd/run index 5a28a4d..d41fc8d 100644 --- a/packages/fd/run +++ b/packages/fd/run @@ -1,3 +1,3 @@ #!/bin/bash -singularity run $PLANUTILS_PREFIX/bin/images/downward.simg $@ +singularity run $(dirname $0)/downward.sif $@ diff --git a/packages/fd/uninstall b/packages/fd/uninstall index ec62009..365e504 100644 --- a/packages/fd/uninstall +++ b/packages/fd/uninstall @@ -1,3 +1,3 @@ #!/bin/bash -rm $PLANUTILS_PREFIX/bin/images/downward.simg \ No newline at end of file +rm downward.sif \ No newline at end of file diff --git a/packages/lama/manifest.json b/packages/lama/manifest.json index 92e5d86..70df52e 100644 --- a/packages/lama/manifest.json +++ b/packages/lama/manifest.json @@ -1,6 +1,5 @@ { "name": "LAMA", - "shortname": "lama", "description": "http://fast-downward.org/", "dependencies": ["downward"] } \ No newline at end of file From 4f61025c6852dfe75f98022410ceb9c3be7c1e5c Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Tue, 26 May 2020 23:54:14 -0400 Subject: [PATCH 08/39] Renaming fd -> downward --- packages/{fd => downward}/install | 0 packages/{fd => downward}/manifest.json | 0 packages/{fd => downward}/run | 0 packages/{fd => downward}/uninstall | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename packages/{fd => downward}/install (100%) rename packages/{fd => downward}/manifest.json (100%) rename packages/{fd => downward}/run (100%) rename packages/{fd => downward}/uninstall (100%) diff --git a/packages/fd/install b/packages/downward/install similarity index 100% rename from packages/fd/install rename to packages/downward/install diff --git a/packages/fd/manifest.json b/packages/downward/manifest.json similarity index 100% rename from packages/fd/manifest.json rename to packages/downward/manifest.json diff --git a/packages/fd/run b/packages/downward/run similarity index 100% rename from packages/fd/run rename to packages/downward/run diff --git a/packages/fd/uninstall b/packages/downward/uninstall similarity index 100% rename from packages/fd/uninstall rename to packages/downward/uninstall From 26b6331ba488af0e90cbbcad619544594da10095 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 27 May 2020 00:04:51 -0400 Subject: [PATCH 09/39] Minor bug. --- planutils/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 1c7f7b1..0d4ed53 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -17,7 +17,7 @@ def setup(): os.path.join(os.path.expanduser('~'), '.planutils', 'packages')) print("Adding bin folder to path (assuming ~/.bashrc exists)...") - os.system("echo 'export PLANUTILS_PREFIX=\"%s\"' >> ~/.bashrc" % prefix) + os.system("echo 'export PLANUTILS_PREFIX=\"~/.planutils\"' >> ~/.bashrc") os.system("echo 'export PATH=\"$PLANUTILS_PREFIX/bin:$PATH\"' >> ~/.bashrc") print("Installing planner scripts...") From b3efa88e523dcb6cab511f1b649957e0d6f3ae08 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 27 May 2020 22:52:38 -0400 Subject: [PATCH 10/39] Shift to packages. --- MANIFEST.in | 3 +- {packages => planutils/packages}/README.md | 0 .../packages}/TEMPLATE/install | 0 .../packages}/TEMPLATE/manifest.json | 0 {packages => planutils/packages}/TEMPLATE/run | 0 .../packages}/TEMPLATE/uninstall | 0 .../packages}/downward/install | 0 .../packages}/downward/manifest.json | 0 {packages => planutils/packages}/downward/run | 0 .../packages}/downward/uninstall | 0 {packages => planutils/packages}/lama/install | 0 .../packages}/lama/manifest.json | 0 {packages => planutils/packages}/lama/run | 0 .../packages}/lama/uninstall | 0 planutils/planner_configs/fd.json | 11 --- planutils/planner_configs/lama.json | 10 --- planutils/planner_installation.py | 67 +++++-------------- 17 files changed, 17 insertions(+), 74 deletions(-) rename {packages => planutils/packages}/README.md (100%) rename {packages => planutils/packages}/TEMPLATE/install (100%) rename {packages => planutils/packages}/TEMPLATE/manifest.json (100%) rename {packages => planutils/packages}/TEMPLATE/run (100%) rename {packages => planutils/packages}/TEMPLATE/uninstall (100%) rename {packages => planutils/packages}/downward/install (100%) rename {packages => planutils/packages}/downward/manifest.json (100%) rename {packages => planutils/packages}/downward/run (100%) rename {packages => planutils/packages}/downward/uninstall (100%) rename {packages => planutils/packages}/lama/install (100%) rename {packages => planutils/packages}/lama/manifest.json (100%) rename {packages => planutils/packages}/lama/run (100%) rename {packages => planutils/packages}/lama/uninstall (100%) delete mode 100644 planutils/planner_configs/fd.json delete mode 100644 planutils/planner_configs/lama.json diff --git a/MANIFEST.in b/MANIFEST.in index ad2657f..fbb4186 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1 @@ -include planutils/planner_configs/*.json -include packages/ \ No newline at end of file +include planutils/packages/ \ No newline at end of file diff --git a/packages/README.md b/planutils/packages/README.md similarity index 100% rename from packages/README.md rename to planutils/packages/README.md diff --git a/packages/TEMPLATE/install b/planutils/packages/TEMPLATE/install similarity index 100% rename from packages/TEMPLATE/install rename to planutils/packages/TEMPLATE/install diff --git a/packages/TEMPLATE/manifest.json b/planutils/packages/TEMPLATE/manifest.json similarity index 100% rename from packages/TEMPLATE/manifest.json rename to planutils/packages/TEMPLATE/manifest.json diff --git a/packages/TEMPLATE/run b/planutils/packages/TEMPLATE/run similarity index 100% rename from packages/TEMPLATE/run rename to planutils/packages/TEMPLATE/run diff --git a/packages/TEMPLATE/uninstall b/planutils/packages/TEMPLATE/uninstall similarity index 100% rename from packages/TEMPLATE/uninstall rename to planutils/packages/TEMPLATE/uninstall diff --git a/packages/downward/install b/planutils/packages/downward/install similarity index 100% rename from packages/downward/install rename to planutils/packages/downward/install diff --git a/packages/downward/manifest.json b/planutils/packages/downward/manifest.json similarity index 100% rename from packages/downward/manifest.json rename to planutils/packages/downward/manifest.json diff --git a/packages/downward/run b/planutils/packages/downward/run similarity index 100% rename from packages/downward/run rename to planutils/packages/downward/run diff --git a/packages/downward/uninstall b/planutils/packages/downward/uninstall similarity index 100% rename from packages/downward/uninstall rename to planutils/packages/downward/uninstall diff --git a/packages/lama/install b/planutils/packages/lama/install similarity index 100% rename from packages/lama/install rename to planutils/packages/lama/install diff --git a/packages/lama/manifest.json b/planutils/packages/lama/manifest.json similarity index 100% rename from packages/lama/manifest.json rename to planutils/packages/lama/manifest.json diff --git a/packages/lama/run b/planutils/packages/lama/run similarity index 100% rename from packages/lama/run rename to planutils/packages/lama/run diff --git a/packages/lama/uninstall b/planutils/packages/lama/uninstall similarity index 100% rename from packages/lama/uninstall rename to planutils/packages/lama/uninstall diff --git a/planutils/planner_configs/fd.json b/planutils/planner_configs/fd.json deleted file mode 100644 index 5090802..0000000 --- a/planutils/planner_configs/fd.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "FastDownward", - "shortname": "fd", - "description": "Coming soon...", - "method": "singularity", - "details": { - "type": "hub", - "name": "downward.simg", - "shub": "shub://aibasel/downward" - } -} \ No newline at end of file diff --git a/planutils/planner_configs/lama.json b/planutils/planner_configs/lama.json deleted file mode 100644 index dcafc4f..0000000 --- a/planutils/planner_configs/lama.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "Lama First", - "shortname": "lama", - "description": "Coming soon...", - "method": "proxy", - "details": { - "base": "fd", - "suffix": "--alias lama-first" - } -} \ No newline at end of file diff --git a/planutils/planner_installation.py b/planutils/planner_installation.py index 633b9e2..7fc52a4 100644 --- a/planutils/planner_installation.py +++ b/planutils/planner_installation.py @@ -1,65 +1,30 @@ -import json, os, glob +import json, os, glob, subprocess -PLANNERS = {} +PACKAGES = {} CUR_DIR = os.path.dirname(os.path.abspath(__file__)) -for conf_file in glob.glob(os.path.join(CUR_DIR, 'planner_configs', '*.json')): - with open(conf_file, 'r') as f: - config = json.load(f) - assert config['shortname'] not in PLANNERS, "Error: Duplicate planner config -- %s" % config['shortname'] - PLANNERS[config['shortname']] = config +for conf_file in glob.glob(os.path.join(CUR_DIR, 'packages', '*')): + base = os.path.basename(conf_file) + if base not in ['README.md', 'TEMPLATE']: + with open(os.path.join(conf_file, 'manifest.json'), 'r') as f: + config = json.load(f) + assert base not in PACKAGES, "Error: Duplicate package config -- %s" % base + PACKAGES[base] = config -# TODO: Pull in the collection configs and setup the dict -COLLECTIONS = {} def install(target): if 'list' == target: - print("\nCollections:") - for c in COLLECTIONS: - print(" - %s" % c) - - print("\nPlanners:") - for p in PLANNERS: - print(" - %s: %s" % (p, PLANNERS[p]['name'])) - + print("\nPackages:") + for p in PACKAGES: + print(" - %s: %s" % (p, PACKAGES[p]['name'])) print() - elif target in PLANNERS: - install_planner(target) - - elif target in COLLECTIONS: - install_planners(target) - - -def bin_path(): - return os.path.join(os.path.expanduser('~'), '.planutils', 'bin') - -def binary_path(planner): - return os.path.join(bin_path(), planner) + assert target in PACKAGES, "Error: Package not found -- %s" % target -def install_planners(planner_set): - raise NotImplementedError - -def install_planner(planner): - - assert planner in PLANNERS, "Error: Planner not found -- %s" % planner - - if PLANNERS[planner]['method'] == 'proxy': - install_planner(PLANNERS[planner]['details']['base']) - cmd = "%s %s" % (PLANNERS[planner]['details']['base'], PLANNERS[planner]['details']['suffix']) + for dep in PACKAGES[target]['dependencies']: + install(dep) - elif PLANNERS[planner]['method'] == 'singularity': - image_path = os.path.join(bin_path(), 'images', PLANNERS[planner]['details']['name']) - os.system("singularity pull --name %s %s" % \ - (PLANNERS[planner]['details']['name'], PLANNERS[planner]['details']['shub'])) - os.system("mv %s %s" % (PLANNERS[planner]['details']['name'], image_path)) - cmd = "singularity run %s" % image_path - - script = "#!/bin/bash\n" - script += "%s $@\n" % cmd - - with open(binary_path(planner), 'w') as f: - f.write(script) + subprocess.Popen('install', cwd=os.path.join(CUR_DIR, 'packages', target)) From bfa7c70ef2fd1b51816eb1d7de73a26d49f2b3a1 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 27 May 2020 23:38:22 -0400 Subject: [PATCH 11/39] Manifest fix. --- MANIFEST.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index fbb4186..3d21d9a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1 @@ -include planutils/packages/ \ No newline at end of file +recursive-include planutils/packages * \ No newline at end of file From f996c1f536e90114b71fc2b106fa15556bd51d2e Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 27 May 2020 23:39:19 -0400 Subject: [PATCH 12/39] Some bug fixes and filename change. --- planutils/__init__.py | 16 ++++++++-------- ...r_installation.py => package_installation.py} | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) rename planutils/{planner_installation.py => package_installation.py} (89%) diff --git a/planutils/__init__.py b/planutils/__init__.py index 0d4ed53..0d70302 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -4,7 +4,7 @@ def setup(): - assert not_setup_yet(), "Error: planutils is already setup. Remove ~/.planutils to reset (warning: all cached planners will be lost)." + assert not_setup_yet(), "Error: planutils is already setup. Remove ~/.planutils to reset (warning: all cached packages will be lost)." CUR_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -20,16 +20,16 @@ def setup(): os.system("echo 'export PLANUTILS_PREFIX=\"~/.planutils\"' >> ~/.bashrc") os.system("echo 'export PATH=\"$PLANUTILS_PREFIX/bin:$PATH\"' >> ~/.bashrc") - print("Installing planner scripts...") - from planutils.planner_installation import PLANNERS - for p in PLANNERS: + print("Installing package scripts...") + from planutils.package_installation import PACKAGES + for p in PACKAGES: script = "#!/bin/bash\n" script += "if [ \"$(planutils --check-installed %s)\" == \"True\" ]\n" % p script += "then\n" script += " $PLANUTILS_PREFIX/packages/%s/run $@\n" % p script += "else\n" script += " echo\n" - script += " echo 'Planner not installed!'\n" + script += " echo 'Package not installed!'\n" script += " read -p \"Download & install? [y/n] \" varchoice\n" script += " if [ $varchoice == \"y\" ]\n" script += " then\n" @@ -51,8 +51,8 @@ def main(): parser = argparse.ArgumentParser() parser.add_argument("-i", "--install", - help="install an individual or collection of planners ('list' shows the options)", - metavar="{planner or collection or list}") + help="install an individual package such as a planner ('list' shows the options)", + metavar="{package name}") parser.add_argument("--check_installed", help="check if a package is installed") @@ -70,5 +70,5 @@ def main(): raise NotImplementedError if args.install: - from planutils.planner_installation import install + from planutils.package_installation import install install(args.install) diff --git a/planutils/planner_installation.py b/planutils/package_installation.py similarity index 89% rename from planutils/planner_installation.py rename to planutils/package_installation.py index 7fc52a4..566a10b 100644 --- a/planutils/planner_installation.py +++ b/planutils/package_installation.py @@ -21,10 +21,11 @@ def install(target): for p in PACKAGES: print(" - %s: %s" % (p, PACKAGES[p]['name'])) print() + return assert target in PACKAGES, "Error: Package not found -- %s" % target for dep in PACKAGES[target]['dependencies']: install(dep) - subprocess.Popen('install', cwd=os.path.join(CUR_DIR, 'packages', target)) + subprocess.Popen('./install', cwd=os.path.join(CUR_DIR, 'packages', target)) From 4ddefc0e3be6e2852c4136c73e9f5b85ffa737a0 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Thu, 28 May 2020 23:40:15 -0400 Subject: [PATCH 13/39] Put in the settings, and recording what is installed. --- planutils/__init__.py | 14 ++++++++++---- planutils/package_installation.py | 13 ++++++++++++- planutils/settings.py | 16 ++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 planutils/settings.py diff --git a/planutils/__init__.py b/planutils/__init__.py index 0d70302..6eb978e 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -1,6 +1,8 @@ import argparse, os +from planutils import settings + def setup(): @@ -11,7 +13,10 @@ def setup(): print("\nCreating ~/.planutils...") os.mkdir(os.path.join(os.path.expanduser('~'), '.planutils')) os.mkdir(os.path.join(os.path.expanduser('~'), '.planutils', 'bin')) - os.mkdir(os.path.join(os.path.expanduser('~'), '.planutils', 'bin', 'images')) + + settings.save({ + 'installed': [] + }) os.symlink(os.path.join(CUR_DIR, 'packages'), os.path.join(os.path.expanduser('~'), '.planutils', 'packages')) @@ -24,9 +29,9 @@ def setup(): from planutils.package_installation import PACKAGES for p in PACKAGES: script = "#!/bin/bash\n" - script += "if [ \"$(planutils --check-installed %s)\" == \"True\" ]\n" % p + script += "if [ \"$(planutils --check_installed %s)\" == \"True\" ]\n" % p script += "then\n" - script += " $PLANUTILS_PREFIX/packages/%s/run $@\n" % p + script += " ~/.planutils/packages/%s/run $@\n" % p script += "else\n" script += " echo\n" script += " echo 'Package not installed!'\n" @@ -67,7 +72,8 @@ def main(): exit() if args.check_installed: - raise NotImplementedError + from planutils.package_installation import check_installed + print(check_installed(args.check_installed)) if args.install: from planutils.package_installation import install diff --git a/planutils/package_installation.py b/planutils/package_installation.py index 566a10b..6b2de79 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -1,6 +1,7 @@ import json, os, glob, subprocess +from planutils import settings PACKAGES = {} @@ -15,6 +16,10 @@ PACKAGES[base] = config +def check_installed(target): + return target in settings.load()['installed'] + + def install(target): if 'list' == target: print("\nPackages:") @@ -28,4 +33,10 @@ def install(target): for dep in PACKAGES[target]['dependencies']: install(dep) - subprocess.Popen('./install', cwd=os.path.join(CUR_DIR, 'packages', target)) + if check_installed(target): + print("%s is already installed." % target) + else: + subprocess.call('./install', cwd=os.path.join(CUR_DIR, 'packages', target)) + s = settings.load() + s['installed'].append(target) + settings.save(s) diff --git a/planutils/settings.py b/planutils/settings.py new file mode 100644 index 0000000..3132097 --- /dev/null +++ b/planutils/settings.py @@ -0,0 +1,16 @@ + +import json, os + +# This should eventually be changed once the prefix is customizable +PLANUTILS_PREFIX = os.path.join(os.path.expanduser('~'), '.planutils') + +SETTINGS_FILE = os.path.join(PLANUTILS_PREFIX, 'settings.json') + +def load(): + with open(SETTINGS_FILE, 'r') as f: + settings = json.loads(f.read()) + return settings + +def save(s): + with open(SETTINGS_FILE, 'w') as f: + f.write(json.dumps(s)) From 9b87f4cf0e56e52707497a1fa0275dbe05f53588 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Fri, 29 May 2020 23:45:52 -0400 Subject: [PATCH 14/39] Version bump and docker fix. --- Dockerfile | 1 + setup.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1d2358a..a7417b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -50,6 +50,7 @@ RUN apt-get update \ && rm -rf /var/lib/apt/lists/* RUN pip3 install --upgrade pip +RUN pip3 install setuptools # Install & setup the planutils RUN pip3 install planutils --trusted-host pypi.org --trusted-host files.pythonhosted.org diff --git a/setup.py b/setup.py index 65c9d37..d49fc1f 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ long_description = fh.read() setuptools.setup(name='planutils', - version='0.1.1', + version='0.1.2', description='General library for setting up linux-based environments for developing, running, and evaluating planners.', long_description=long_description, long_description_content_type="text/markdown", From ac44d538db81d111fbd9e1b0472802d65f328f84 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Fri, 29 May 2020 23:46:02 -0400 Subject: [PATCH 15/39] Added uninstall functionality. --- planutils/__init__.py | 8 ++++++ planutils/package_installation.py | 46 +++++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 6eb978e..15207b4 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -59,6 +59,10 @@ def main(): help="install an individual package such as a planner ('list' shows the options)", metavar="{package name}") + parser.add_argument("-u", "--uninstall", + help="uninstall a package, and any dependencies that are no longer required ('list' shows those that are installed)", + metavar="{package name}") + parser.add_argument("--check_installed", help="check if a package is installed") parser.add_argument("-s", "--setup", help="setup planutils for current user", action="store_true") @@ -78,3 +82,7 @@ def main(): if args.install: from planutils.package_installation import install install(args.install) + + if args.uninstall: + from planutils.package_installation import uninstall + uninstall(args.uninstall) diff --git a/planutils/package_installation.py b/planutils/package_installation.py index 6b2de79..1082d79 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -20,22 +20,62 @@ def check_installed(target): return target in settings.load()['installed'] +def uninstall(target): + if 'list' == target: + print("\nInstalled Packages:") + for p in PACKAGES: + if check_installed(p): + print(" - %s: %s" % (p, PACKAGES[p]['name'])) + print() + return + + if target not in PACKAGES: + print("Error: Package not found -- %s" % target) + return + + if not check_installed(target): + print("%s isn't installed." % target) + else: + print ("Uninstalling %s..." % target) + s = settings.load() + # map a package to all those that depend on it + deps = {} + for p in s['installed']: + for dep in PACKAGES[p]['dependencies']: + if dep not in deps: + deps[dep] = set() + deps[dep].add(p) + + if target in deps and len(deps[target]) > 0: + print("Error: Package is required for the following: %s" % ', '.join(deps[target])) + return + subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', target)) + s['installed'].remove(target) + settings.save(s) + + + def install(target): if 'list' == target: print("\nPackages:") for p in PACKAGES: - print(" - %s: %s" % (p, PACKAGES[p]['name'])) + print(" - %s: %s (installed: %s)" % \ + (p, PACKAGES[p]['name'], str(check_installed(p)))) print() return - assert target in PACKAGES, "Error: Package not found -- %s" % target + if target not in PACKAGES: + print("Error: Package not found -- %s" % target) + return for dep in PACKAGES[target]['dependencies']: - install(dep) + if not check_installed(dep): + install(dep) if check_installed(target): print("%s is already installed." % target) else: + print("Installing %s..." % target) subprocess.call('./install', cwd=os.path.join(CUR_DIR, 'packages', target)) s = settings.load() s['installed'].append(target) From ac84c2e45f52292186391acba2ffdf808cc44025 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 3 Jun 2020 22:42:56 -0400 Subject: [PATCH 16/39] Improved parsing with subcommands. --- planutils/__init__.py | 55 ++++++++++++++++++------------- planutils/package_installation.py | 21 ++++-------- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 15207b4..86ed524 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -2,11 +2,14 @@ import argparse, os from planutils import settings +from planutils.package_installation import PACKAGES def setup(): - assert not_setup_yet(), "Error: planutils is already setup. Remove ~/.planutils to reset (warning: all cached packages will be lost)." + if not not_setup_yet(): + print("Error: planutils is already setup. Remove ~/.planutils to reset (warning: all cached packages will be lost).") + return CUR_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -52,37 +55,45 @@ def setup(): def not_setup_yet(): return not os.path.exists(os.path.join(os.path.expanduser('~'), '.planutils')) + def main(): - parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser(prog="planutils") + subparsers = parser.add_subparsers(help='sub-command help', dest='command') - parser.add_argument("-i", "--install", - help="install an individual package such as a planner ('list' shows the options)", - metavar="{package name}") - - parser.add_argument("-u", "--uninstall", - help="uninstall a package, and any dependencies that are no longer required ('list' shows those that are installed)", - metavar="{package name}") - - parser.add_argument("--check_installed", help="check if a package is installed") - - parser.add_argument("-s", "--setup", help="setup planutils for current user", action="store_true") + parser_install = subparsers.add_parser('install', help='install an individual package such as a planner') + parser_install.add_argument('package', help='package name') + + parser_uninstall = subparsers.add_parser('uninstall', help='uninstall an individual package') + parser_uninstall.add_argument('package', help='package name') + + parser_checkinstalled = subparsers.add_parser('check-installed', help='check if a package is installed') + parser_uninstall.add_argument('package', help='package name') + + parser_setup = subparsers.add_parser('setup', help='setup planutils for current user') + parser_list = subparsers.add_parser('list', help='list the available packages') args = parser.parse_args() - if args.setup: + if 'setup' == args.command: setup() elif not_setup_yet(): print("\nPlease run 'planutils --setup' before using utility.\n") - exit() - - if args.check_installed: + + elif 'check-installed' == args.command: from planutils.package_installation import check_installed - print(check_installed(args.check_installed)) + print(check_installed(args.package)) - if args.install: + elif 'install' == args.command: from planutils.package_installation import install - install(args.install) + install(args.package) - if args.uninstall: + elif 'uninstall' == args.command: from planutils.package_installation import uninstall - uninstall(args.uninstall) + uninstall(args.package) + + elif 'list' == args.command: + from planutils.package_installation import package_list + package_list() + + else: + parser.print_help() diff --git a/planutils/package_installation.py b/planutils/package_installation.py index 1082d79..f49a751 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -21,13 +21,6 @@ def check_installed(target): def uninstall(target): - if 'list' == target: - print("\nInstalled Packages:") - for p in PACKAGES: - if check_installed(p): - print(" - %s: %s" % (p, PACKAGES[p]['name'])) - print() - return if target not in PACKAGES: print("Error: Package not found -- %s" % target) @@ -53,16 +46,14 @@ def uninstall(target): s['installed'].remove(target) settings.save(s) - +def package_list(): + print("\nPackages:") + for p in PACKAGES: + print(" - %s: %s (installed: %s)" % \ + (p, PACKAGES[p]['name'], str(check_installed(p)))) + print() def install(target): - if 'list' == target: - print("\nPackages:") - for p in PACKAGES: - print(" - %s: %s (installed: %s)" % \ - (p, PACKAGES[p]['name'], str(check_installed(p)))) - print() - return if target not in PACKAGES: print("Error: Package not found -- %s" % target) From 03fe6decff6d39276a316f5746b7217c650067b6 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 3 Jun 2020 22:45:50 -0400 Subject: [PATCH 17/39] Improved redirect script for installable packages. --- planutils/__init__.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 86ed524..001d27a 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -29,22 +29,33 @@ def setup(): os.system("echo 'export PATH=\"$PLANUTILS_PREFIX/bin:$PATH\"' >> ~/.bashrc") print("Installing package scripts...") - from planutils.package_installation import PACKAGES for p in PACKAGES: script = "#!/bin/bash\n" - script += "if [ \"$(planutils --check_installed %s)\" == \"True\" ]\n" % p + script += "if [ \"$(planutils check-installed %s)\" == \"True\" ]\n" % p script += "then\n" script += " ~/.planutils/packages/%s/run $@\n" % p script += "else\n" script += " echo\n" script += " echo 'Package not installed!'\n" - script += " read -p \"Download & install? [y/n] \" varchoice\n" - script += " if [ $varchoice == \"y\" ]\n" + script += " read -r -p \"Download & install? [y/N] \" varchoice\n" + script += " varchoice=${varchoice,,}\n" # tolower + script += " if [[ \"$varchoice\" =~ ^(yes|y)$ ]]\n" script += " then\n" - script += " planutils --install " + p + "\n" + script += " planutils install " + p + "\n" + script += " if [ \"$(planutils check-installed %s)\" == \"True\" ]\n" % p + script += " then\n" + script += " echo 'Successfully installed %s!'\n" % p + script += " echo \"Original command: %s $@\"\n" % p + script += " read -r -p \"Re-run command? [Y/n] \" varchoice\n" + script += " varchoice=${varchoice,,}\n" # tolower + script += " if ! [[ \"$varchoice\" =~ ^(no|n)$ ]]\n" + script += " then\n" + script += " ~/.planutils/packages/%s/run $@\n" % p + script += " fi\n" + script += " fi\n" script += " fi\n" script += " echo\n" - script += "fi" + script += "fi\n" with open(os.path.join(os.path.expanduser('~'), '.planutils', 'bin', p), 'w') as f: f.write(script) os.chmod(os.path.join(os.path.expanduser('~'), '.planutils', 'bin', p), 0o0755) @@ -77,7 +88,7 @@ def main(): if 'setup' == args.command: setup() elif not_setup_yet(): - print("\nPlease run 'planutils --setup' before using utility.\n") + print("\nPlease run 'planutils setup' before using utility.\n") elif 'check-installed' == args.command: from planutils.package_installation import check_installed From b1b82e7a2f6b9c050e5e163314fab65bb1e789ab Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 3 Jun 2020 22:51:49 -0400 Subject: [PATCH 18/39] Small bug fix. --- planutils/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 001d27a..9653bf8 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -78,7 +78,7 @@ def main(): parser_uninstall.add_argument('package', help='package name') parser_checkinstalled = subparsers.add_parser('check-installed', help='check if a package is installed') - parser_uninstall.add_argument('package', help='package name') + parser_checkinstalled.add_argument('package', help='package name') parser_setup = subparsers.add_parser('setup', help='setup planutils for current user') parser_list = subparsers.add_parser('list', help='list the available packages') From 46dc0e53cfd6cfa769873969e79cbb852757ac04 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 3 Jun 2020 22:52:21 -0400 Subject: [PATCH 19/39] Only create new command-line utilities for runnable packages. --- planutils/__init__.py | 59 ++++++++++++++++--------------- planutils/package_installation.py | 3 +- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 9653bf8..8c14af6 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -30,35 +30,36 @@ def setup(): print("Installing package scripts...") for p in PACKAGES: - script = "#!/bin/bash\n" - script += "if [ \"$(planutils check-installed %s)\" == \"True\" ]\n" % p - script += "then\n" - script += " ~/.planutils/packages/%s/run $@\n" % p - script += "else\n" - script += " echo\n" - script += " echo 'Package not installed!'\n" - script += " read -r -p \"Download & install? [y/N] \" varchoice\n" - script += " varchoice=${varchoice,,}\n" # tolower - script += " if [[ \"$varchoice\" =~ ^(yes|y)$ ]]\n" - script += " then\n" - script += " planutils install " + p + "\n" - script += " if [ \"$(planutils check-installed %s)\" == \"True\" ]\n" % p - script += " then\n" - script += " echo 'Successfully installed %s!'\n" % p - script += " echo \"Original command: %s $@\"\n" % p - script += " read -r -p \"Re-run command? [Y/n] \" varchoice\n" - script += " varchoice=${varchoice,,}\n" # tolower - script += " if ! [[ \"$varchoice\" =~ ^(no|n)$ ]]\n" - script += " then\n" - script += " ~/.planutils/packages/%s/run $@\n" % p - script += " fi\n" - script += " fi\n" - script += " fi\n" - script += " echo\n" - script += "fi\n" - with open(os.path.join(os.path.expanduser('~'), '.planutils', 'bin', p), 'w') as f: - f.write(script) - os.chmod(os.path.join(os.path.expanduser('~'), '.planutils', 'bin', p), 0o0755) + if PACKAGES[p]['runnable']: + script = "#!/bin/bash\n" + script += "if [ \"$(planutils check-installed %s)\" == \"True\" ]\n" % p + script += "then\n" + script += " ~/.planutils/packages/%s/run $@\n" % p + script += "else\n" + script += " echo\n" + script += " echo 'Package not installed!'\n" + script += " read -r -p \"Download & install? [y/N] \" varchoice\n" + script += " varchoice=${varchoice,,}\n" # tolower + script += " if [[ \"$varchoice\" =~ ^(yes|y)$ ]]\n" + script += " then\n" + script += " planutils install " + p + "\n" + script += " if [ \"$(planutils check-installed %s)\" == \"True\" ]\n" % p + script += " then\n" + script += " echo 'Successfully installed %s!'\n" % p + script += " echo \"Original command: %s $@\"\n" % p + script += " read -r -p \"Re-run command? [Y/n] \" varchoice\n" + script += " varchoice=${varchoice,,}\n" # tolower + script += " if ! [[ \"$varchoice\" =~ ^(no|n)$ ]]\n" + script += " then\n" + script += " ~/.planutils/packages/%s/run $@\n" % p + script += " fi\n" + script += " fi\n" + script += " fi\n" + script += " echo\n" + script += "fi\n" + with open(os.path.join(os.path.expanduser('~'), '.planutils', 'bin', p), 'w') as f: + f.write(script) + os.chmod(os.path.join(os.path.expanduser('~'), '.planutils', 'bin', p), 0o0755) print("\nAll set! Be sure to start a new bash session or update your PATH variable to include ~/.planutils/bin\n") diff --git a/planutils/package_installation.py b/planutils/package_installation.py index f49a751..e4553a6 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -14,6 +14,7 @@ config = json.load(f) assert base not in PACKAGES, "Error: Duplicate package config -- %s" % base PACKAGES[base] = config + PACKAGES[base]['runnable'] = os.path.exists(os.path.join(conf_file, 'run')) def check_installed(target): @@ -21,7 +22,7 @@ def check_installed(target): def uninstall(target): - + if target not in PACKAGES: print("Error: Package not found -- %s" % target) return From c8b367bb2729b5b128e094cb3aca3176570ea501 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 3 Jun 2020 23:00:24 -0400 Subject: [PATCH 20/39] Improved handling of the dependency mapping. --- planutils/package_installation.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/planutils/package_installation.py b/planutils/package_installation.py index e4553a6..c77d09b 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -1,5 +1,6 @@ import json, os, glob, subprocess +from collections import defaultdict from planutils import settings @@ -33,15 +34,13 @@ def uninstall(target): print ("Uninstalling %s..." % target) s = settings.load() # map a package to all those that depend on it - deps = {} + dependency_mapping = defaultdict(set) for p in s['installed']: for dep in PACKAGES[p]['dependencies']: - if dep not in deps: - deps[dep] = set() - deps[dep].add(p) + dependency_mapping[dep].add(p) - if target in deps and len(deps[target]) > 0: - print("Error: Package is required for the following: %s" % ', '.join(deps[target])) + if target in dependency_mapping and len(dependency_mapping[target]) > 0: + print("Error: Package is required for the following: %s" % ', '.join(dependency_mapping[target])) return subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', target)) s['installed'].remove(target) From f041490ed6d7e584a6fb5f61aa59b00f5b1ed71d Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 3 Jun 2020 23:01:49 -0400 Subject: [PATCH 21/39] Making lama lama --- planutils/packages/lama/run | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planutils/packages/lama/run b/planutils/packages/lama/run index ac3fa91..676b954 100644 --- a/planutils/packages/lama/run +++ b/planutils/packages/lama/run @@ -1,3 +1,3 @@ #!/bin/bash -downward --alias lama-first $@ +downward --alias lama $@ From a0b450980337ce51fc36783b38a4be64410e648f Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 3 Jun 2020 23:07:25 -0400 Subject: [PATCH 22/39] Cleanup. --- planutils/__init__.py | 8 ++++---- planutils/package_installation.py | 2 +- planutils/packages/TEMPLATE/manifest.json | 2 +- planutils/packages/TEMPLATE/run | 2 +- planutils/packages/downward/manifest.json | 2 +- planutils/packages/downward/uninstall | 2 +- planutils/packages/lama/manifest.json | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 8c14af6..8d0c9de 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -83,7 +83,7 @@ def main(): parser_setup = subparsers.add_parser('setup', help='setup planutils for current user') parser_list = subparsers.add_parser('list', help='list the available packages') - + args = parser.parse_args() if 'setup' == args.command: @@ -98,14 +98,14 @@ def main(): elif 'install' == args.command: from planutils.package_installation import install install(args.package) - + elif 'uninstall' == args.command: from planutils.package_installation import uninstall uninstall(args.package) - + elif 'list' == args.command: from planutils.package_installation import package_list package_list() - + else: parser.print_help() diff --git a/planutils/package_installation.py b/planutils/package_installation.py index c77d09b..5e07407 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -62,7 +62,7 @@ def install(target): for dep in PACKAGES[target]['dependencies']: if not check_installed(dep): install(dep) - + if check_installed(target): print("%s is already installed." % target) else: diff --git a/planutils/packages/TEMPLATE/manifest.json b/planutils/packages/TEMPLATE/manifest.json index b745777..4f8293c 100644 --- a/planutils/packages/TEMPLATE/manifest.json +++ b/planutils/packages/TEMPLATE/manifest.json @@ -2,4 +2,4 @@ "name": "Full name of package", "description": "General description of the package", "dependencies": ["list", "of", "dependencies"] -} \ No newline at end of file +} diff --git a/planutils/packages/TEMPLATE/run b/planutils/packages/TEMPLATE/run index 0638e73..cf2d02f 100644 --- a/planutils/packages/TEMPLATE/run +++ b/planutils/packages/TEMPLATE/run @@ -1,3 +1,3 @@ #!/bin/bash -# whatever command-line method needs to be used to run this package \ No newline at end of file +# whatever command-line method needs to be used to run this package diff --git a/planutils/packages/downward/manifest.json b/planutils/packages/downward/manifest.json index 00e3f19..5fb6af8 100644 --- a/planutils/packages/downward/manifest.json +++ b/planutils/packages/downward/manifest.json @@ -2,4 +2,4 @@ "name": "Fast Downward", "description": "http://fast-downward.org/", "dependencies": [] -} \ No newline at end of file +} diff --git a/planutils/packages/downward/uninstall b/planutils/packages/downward/uninstall index 365e504..08c44a7 100644 --- a/planutils/packages/downward/uninstall +++ b/planutils/packages/downward/uninstall @@ -1,3 +1,3 @@ #!/bin/bash -rm downward.sif \ No newline at end of file +rm downward.sif diff --git a/planutils/packages/lama/manifest.json b/planutils/packages/lama/manifest.json index 70df52e..8d02878 100644 --- a/planutils/packages/lama/manifest.json +++ b/planutils/packages/lama/manifest.json @@ -2,4 +2,4 @@ "name": "LAMA", "description": "http://fast-downward.org/", "dependencies": ["downward"] -} \ No newline at end of file +} From 58115c511e11f1039b24e1cbc67bea28131be2e1 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Thu, 4 Jun 2020 22:19:26 -0400 Subject: [PATCH 23/39] Confirm installation of all (recursively computed) dependencies. --- planutils/package_installation.py | 38 ++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/planutils/package_installation.py b/planutils/package_installation.py index 5e07407..99a3021 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -59,15 +59,31 @@ def install(target): print("Error: Package not found -- %s" % target) return - for dep in PACKAGES[target]['dependencies']: - if not check_installed(dep): - install(dep) - - if check_installed(target): - print("%s is already installed." % target) + # Compute all those that will need to be installed + done = set() + to_check = [target] + to_install = [] + while to_check: + check = to_check.pop(0) + if check not in done: + done.add(check) + if not check_installed(check): + to_install.append(check) + to_check.extend(PACKAGES[check]['dependencies']) + + to_install.reverse() + + if to_install: + print("\nAbout to install the following packages: %s" % ', '.join(to_install)) + if input("Proceed? [Y/n] ").lower() in ['', 'y', 'yes']: + s = settings.load() + for package in to_install: + print("Installing %s..." % package) + subprocess.call('./install', cwd=os.path.join(CUR_DIR, 'packages', package)) + s['installed'].append(package) + settings.save(s) + else: + print("Aborting installation.") else: - print("Installing %s..." % target) - subprocess.call('./install', cwd=os.path.join(CUR_DIR, 'packages', target)) - s = settings.load() - s['installed'].append(target) - settings.save(s) + print("%s is already installed." % target) + From 6a15d1d9d1acf441053d097321b4a151608301ae Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Thu, 4 Jun 2020 23:24:19 -0400 Subject: [PATCH 24/39] Rollback failed installation process. --- planutils/package_installation.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/planutils/package_installation.py b/planutils/package_installation.py index 99a3021..a200b00 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -75,12 +75,21 @@ def install(target): if to_install: print("\nAbout to install the following packages: %s" % ', '.join(to_install)) - if input("Proceed? [Y/n] ").lower() in ['', 'y', 'yes']: - s = settings.load() + if input(" Proceed? [Y/n] ").lower() in ['', 'y', 'yes']: + installed = [] for package in to_install: print("Installing %s..." % package) - subprocess.call('./install', cwd=os.path.join(CUR_DIR, 'packages', package)) - s['installed'].append(package) + try: + installed.append(package) + subprocess.call('./install', cwd=os.path.join(CUR_DIR, 'packages', package)) + except subprocess.CalledProcessError: + print("Error installing %s. Rolling back changes..." % package) + for p in installed: + subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', p)) + return + + s = settings.load() + s['installed'].extend(installed) settings.save(s) else: print("Aborting installation.") From 38908878160f885e81654461eb25678ad7618031 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Thu, 4 Jun 2020 23:25:37 -0400 Subject: [PATCH 25/39] Collect & delete (after confirmation) all of the dependencies requested --- planutils/package_installation.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/planutils/package_installation.py b/planutils/package_installation.py index a200b00..3068b11 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -31,7 +31,6 @@ def uninstall(target): if not check_installed(target): print("%s isn't installed." % target) else: - print ("Uninstalling %s..." % target) s = settings.load() # map a package to all those that depend on it dependency_mapping = defaultdict(set) @@ -39,12 +38,21 @@ def uninstall(target): for dep in PACKAGES[p]['dependencies']: dependency_mapping[dep].add(p) - if target in dependency_mapping and len(dependency_mapping[target]) > 0: - print("Error: Package is required for the following: %s" % ', '.join(dependency_mapping[target])) - return - subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', target)) - s['installed'].remove(target) - settings.save(s) + # compute all the packages that will be removed + to_check = [target] + to_remove = set() + while to_check: + check = to_check.pop(0) + to_remove.add(check) + to_check.extend(list(dependency_mapping[check])) + + print("\nAbout to remove the following packages: %s" % ', '.join(to_remove)) + if input(" Proceed? [y/N] ").lower() in ['y', 'yes']: + for package in to_remove: + print ("Uninstalling %s..." % package) + subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', package)) + s['installed'].remove(package) + settings.save(s) def package_list(): print("\nPackages:") From c676dcb92b26b7589874ebe3f026a59a39c0320a Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Thu, 4 Jun 2020 23:26:09 -0400 Subject: [PATCH 26/39] Minor output touchup and allow for setup to be forced. --- planutils/__init__.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 8d0c9de..0b0ba8f 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -8,8 +8,11 @@ def setup(): if not not_setup_yet(): - print("Error: planutils is already setup. Remove ~/.planutils to reset (warning: all cached packages will be lost).") - return + print("\nError: planutils is already setup. Setting up again will wipe all cached packages and settings.") + if input(" Proceed? [y/N] ").lower() in ['y', 'yes']: + os.system("rm -rf %s" % os.path.join(os.path.expanduser('~'), '.planutils')) + else: + return CUR_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -38,7 +41,7 @@ def setup(): script += "else\n" script += " echo\n" script += " echo 'Package not installed!'\n" - script += " read -r -p \"Download & install? [y/N] \" varchoice\n" + script += " read -r -p \" Download & install? [y/N] \" varchoice\n" script += " varchoice=${varchoice,,}\n" # tolower script += " if [[ \"$varchoice\" =~ ^(yes|y)$ ]]\n" script += " then\n" @@ -47,7 +50,7 @@ def setup(): script += " then\n" script += " echo 'Successfully installed %s!'\n" % p script += " echo \"Original command: %s $@\"\n" % p - script += " read -r -p \"Re-run command? [Y/n] \" varchoice\n" + script += " read -r -p \" Re-run command? [Y/n] \" varchoice\n" script += " varchoice=${varchoice,,}\n" # tolower script += " if ! [[ \"$varchoice\" =~ ^(no|n)$ ]]\n" script += " then\n" From 15951111e59f258c34a7584bd252a9d5d204f8ae Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Thu, 4 Jun 2020 23:41:39 -0400 Subject: [PATCH 27/39] Fixing bug with main installation call. --- planutils/package_installation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planutils/package_installation.py b/planutils/package_installation.py index 3068b11..a81afc2 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -89,7 +89,7 @@ def install(target): print("Installing %s..." % package) try: installed.append(package) - subprocess.call('./install', cwd=os.path.join(CUR_DIR, 'packages', package)) + subprocess.check_call('./install', cwd=os.path.join(CUR_DIR, 'packages', package)) except subprocess.CalledProcessError: print("Error installing %s. Rolling back changes..." % package) for p in installed: From a930f8ea1d18ac9d6ebc3fc1f842c42db3d60415 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Thu, 4 Jun 2020 23:41:56 -0400 Subject: [PATCH 28/39] Adding upgrade functionality. --- planutils/__init__.py | 7 ++++++- planutils/package_installation.py | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 0b0ba8f..2a65f3c 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -84,8 +84,9 @@ def main(): parser_checkinstalled = subparsers.add_parser('check-installed', help='check if a package is installed') parser_checkinstalled.add_argument('package', help='package name') - parser_setup = subparsers.add_parser('setup', help='setup planutils for current user') parser_list = subparsers.add_parser('list', help='list the available packages') + parser_setup = subparsers.add_parser('setup', help='setup planutils for current user') + parser_upgrade = subparsers.add_parser('upgrade', help='upgrade all of the installed packages') args = parser.parse_args() @@ -110,5 +111,9 @@ def main(): from planutils.package_installation import package_list package_list() + elif 'upgrade' == args.command: + from planutils.package_installation import upgrade + upgrade() + else: parser.print_help() diff --git a/planutils/package_installation.py b/planutils/package_installation.py index a81afc2..9355a1a 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -61,6 +61,13 @@ def package_list(): (p, PACKAGES[p]['name'], str(check_installed(p)))) print() +def upgrade(): + s = settings.load() + for package in s['installed']: + print("Upgrading %s..." % package) + subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', package)) + subprocess.call('./install', cwd=os.path.join(CUR_DIR, 'packages', package)) + def install(target): if target not in PACKAGES: From c40829bff2615b99ad9393b58331322d205b27fb Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Thu, 4 Jun 2020 23:47:07 -0400 Subject: [PATCH 29/39] Improved display of installed/available packages. --- planutils/package_installation.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/planutils/package_installation.py b/planutils/package_installation.py index 9355a1a..e2039cc 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -55,10 +55,15 @@ def uninstall(target): settings.save(s) def package_list(): - print("\nPackages:") + print("\nInstalled:") + installed = set(settings.load()['installed']) + for p in installed: + print(" %s: %s" % (p, PACKAGES[p]['name'])) + + print("\nAvailable:") for p in PACKAGES: - print(" - %s: %s (installed: %s)" % \ - (p, PACKAGES[p]['name'], str(check_installed(p)))) + if p not in installed: + print(" %s: %s" % (p, PACKAGES[p]['name'])) print() def upgrade(): From c629d0716024b3266cdf96d0a7f0d498fa2ea70e Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Fri, 5 Jun 2020 22:34:02 -0400 Subject: [PATCH 30/39] Better return codes and function naming. --- planutils/__init__.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 2a65f3c..5621ae1 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -1,5 +1,5 @@ -import argparse, os +import argparse, os, sys from planutils import settings from planutils.package_installation import PACKAGES @@ -7,7 +7,7 @@ def setup(): - if not not_setup_yet(): + if setup_done(): print("\nError: planutils is already setup. Setting up again will wipe all cached packages and settings.") if input(" Proceed? [y/N] ").lower() in ['y', 'yes']: os.system("rm -rf %s" % os.path.join(os.path.expanduser('~'), '.planutils')) @@ -28,14 +28,15 @@ def setup(): os.path.join(os.path.expanduser('~'), '.planutils', 'packages')) print("Adding bin folder to path (assuming ~/.bashrc exists)...") - os.system("echo 'export PLANUTILS_PREFIX=\"~/.planutils\"' >> ~/.bashrc") - os.system("echo 'export PATH=\"$PLANUTILS_PREFIX/bin:$PATH\"' >> ~/.bashrc") + with open(os.path.join(os.path.expanduser('~'), '.bashrc'), "a+") as f: + f.write("export PLANUTILS_PREFIX=\"~/.planutils\"") + f.write("export PATH=\"$PLANUTILS_PREFIX/bin:$PATH\"") print("Installing package scripts...") for p in PACKAGES: if PACKAGES[p]['runnable']: script = "#!/bin/bash\n" - script += "if [ \"$(planutils check-installed %s)\" == \"True\" ]\n" % p + script += "if [ $(planutils check-installed %s) ]\n" % p script += "then\n" script += " ~/.planutils/packages/%s/run $@\n" % p script += "else\n" @@ -46,7 +47,7 @@ def setup(): script += " if [[ \"$varchoice\" =~ ^(yes|y)$ ]]\n" script += " then\n" script += " planutils install " + p + "\n" - script += " if [ \"$(planutils check-installed %s)\" == \"True\" ]\n" % p + script += " if [ $(planutils check-installed %s) ]\n" % p script += " then\n" script += " echo 'Successfully installed %s!'\n" % p script += " echo \"Original command: %s $@\"\n" % p @@ -67,8 +68,8 @@ def setup(): print("\nAll set! Be sure to start a new bash session or update your PATH variable to include ~/.planutils/bin\n") -def not_setup_yet(): - return not os.path.exists(os.path.join(os.path.expanduser('~'), '.planutils')) +def setup_done(): + return os.path.exists(os.path.join(os.path.expanduser('~'), '.planutils')) def main(): @@ -92,12 +93,12 @@ def main(): if 'setup' == args.command: setup() - elif not_setup_yet(): + elif not setup_done(): print("\nPlease run 'planutils setup' before using utility.\n") elif 'check-installed' == args.command: from planutils.package_installation import check_installed - print(check_installed(args.package)) + sys.exit({True:0, False:1}[check_installed(args.package)]) elif 'install' == args.command: from planutils.package_installation import install From 54a6f27f32d14f43e7f5b19e2501b3ff8f76cf80 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Fri, 5 Jun 2020 22:40:50 -0400 Subject: [PATCH 31/39] Fixing bug with bash scripts. --- planutils/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 5621ae1..cff9d7b 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -1,5 +1,5 @@ -import argparse, os, sys +import argparse, os from planutils import settings from planutils.package_installation import PACKAGES @@ -36,7 +36,7 @@ def setup(): for p in PACKAGES: if PACKAGES[p]['runnable']: script = "#!/bin/bash\n" - script += "if [ $(planutils check-installed %s) ]\n" % p + script += "if $(planutils check-installed %s)\n" % p script += "then\n" script += " ~/.planutils/packages/%s/run $@\n" % p script += "else\n" @@ -47,7 +47,7 @@ def setup(): script += " if [[ \"$varchoice\" =~ ^(yes|y)$ ]]\n" script += " then\n" script += " planutils install " + p + "\n" - script += " if [ $(planutils check-installed %s) ]\n" % p + script += " if $(planutils check-installed %s)\n" % p script += " then\n" script += " echo 'Successfully installed %s!'\n" % p script += " echo \"Original command: %s $@\"\n" % p @@ -98,7 +98,7 @@ def main(): elif 'check-installed' == args.command: from planutils.package_installation import check_installed - sys.exit({True:0, False:1}[check_installed(args.package)]) + exit({True:0, False:1}[check_installed(args.package)]) elif 'install' == args.command: from planutils.package_installation import install From 6533802f0801e1101927af14d6c09f3bc05e16cf Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Fri, 5 Jun 2020 23:06:53 -0400 Subject: [PATCH 32/39] Simplify the installation check using return codes. --- planutils/__init__.py | 5 ++--- planutils/package_installation.py | 7 +++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index cff9d7b..6d9c4fd 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -46,8 +46,7 @@ def setup(): script += " varchoice=${varchoice,,}\n" # tolower script += " if [[ \"$varchoice\" =~ ^(yes|y)$ ]]\n" script += " then\n" - script += " planutils install " + p + "\n" - script += " if $(planutils check-installed %s)\n" % p + script += " if planutils install %s;\n" % p script += " then\n" script += " echo 'Successfully installed %s!'\n" % p script += " echo \"Original command: %s $@\"\n" % p @@ -102,7 +101,7 @@ def main(): elif 'install' == args.command: from planutils.package_installation import install - install(args.package) + exit({True:0, False:1}[install(args.package)]) elif 'uninstall' == args.command: from planutils.package_installation import uninstall diff --git a/planutils/package_installation.py b/planutils/package_installation.py index e2039cc..64c9889 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -77,7 +77,7 @@ def install(target): if target not in PACKAGES: print("Error: Package not found -- %s" % target) - return + return False # Compute all those that will need to be installed done = set() @@ -106,13 +106,16 @@ def install(target): print("Error installing %s. Rolling back changes..." % package) for p in installed: subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', p)) - return + return False s = settings.load() s['installed'].extend(installed) settings.save(s) + return True else: print("Aborting installation.") else: print("%s is already installed." % target) + return False + From eb5bd2a234547d18438e65259631e47c825f2ca6 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Fri, 5 Jun 2020 23:32:50 -0400 Subject: [PATCH 33/39] Allow for installing/uninstalling multiple packages. --- planutils/__init__.py | 8 +-- planutils/package_installation.py | 82 +++++++++++++++++-------------- 2 files changed, 50 insertions(+), 40 deletions(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 6d9c4fd..55d34a9 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -75,11 +75,11 @@ def main(): parser = argparse.ArgumentParser(prog="planutils") subparsers = parser.add_subparsers(help='sub-command help', dest='command') - parser_install = subparsers.add_parser('install', help='install an individual package such as a planner') - parser_install.add_argument('package', help='package name') + parser_install = subparsers.add_parser('install', help='install package(s) such as a planner') + parser_install.add_argument('package', help='package name', nargs='+') - parser_uninstall = subparsers.add_parser('uninstall', help='uninstall an individual package') - parser_uninstall.add_argument('package', help='package name') + parser_uninstall = subparsers.add_parser('uninstall', help='uninstall package(s)') + parser_uninstall.add_argument('package', help='package name', nargs='+') parser_checkinstalled = subparsers.add_parser('check-installed', help='check if a package is installed') parser_checkinstalled.add_argument('package', help='package name') diff --git a/planutils/package_installation.py b/planutils/package_installation.py index 64c9889..6e30fb9 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -22,37 +22,41 @@ def check_installed(target): return target in settings.load()['installed'] -def uninstall(target): +def uninstall(targets): - if target not in PACKAGES: - print("Error: Package not found -- %s" % target) - return + for target in targets: + if target not in PACKAGES: + print("Error: Package not found -- %s" % target) + return - if not check_installed(target): - print("%s isn't installed." % target) - else: - s = settings.load() - # map a package to all those that depend on it - dependency_mapping = defaultdict(set) - for p in s['installed']: - for dep in PACKAGES[p]['dependencies']: - dependency_mapping[dep].add(p) - - # compute all the packages that will be removed - to_check = [target] - to_remove = set() - while to_check: - check = to_check.pop(0) - to_remove.add(check) - to_check.extend(list(dependency_mapping[check])) - - print("\nAbout to remove the following packages: %s" % ', '.join(to_remove)) - if input(" Proceed? [y/N] ").lower() in ['y', 'yes']: - for package in to_remove: - print ("Uninstalling %s..." % package) - subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', package)) - s['installed'].remove(package) - settings.save(s) + to_check = [] + for target in targets: + if check_installed(target): + to_check.append(target) + else: + print("%s isn't installed." % target) + + s = settings.load() + # map a package to all those that depend on it + dependency_mapping = defaultdict(set) + for p in s['installed']: + for dep in PACKAGES[p]['dependencies']: + dependency_mapping[dep].add(p) + + # compute all the packages that will be removed + to_remove = set() + while to_check: + check = to_check.pop(0) + to_remove.add(check) + to_check.extend(list(dependency_mapping[check])) + + print("\nAbout to remove the following packages: %s" % ', '.join(to_remove)) + if input(" Proceed? [y/N] ").lower() in ['y', 'yes']: + for package in to_remove: + print ("Uninstalling %s..." % package) + subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', package)) + s['installed'].remove(package) + settings.save(s) def package_list(): print("\nInstalled:") @@ -73,15 +77,21 @@ def upgrade(): subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', package)) subprocess.call('./install', cwd=os.path.join(CUR_DIR, 'packages', package)) -def install(target): - - if target not in PACKAGES: - print("Error: Package not found -- %s" % target) - return False +def install(targets): + for target in targets: + if target not in PACKAGES: + print("Error: Package not found -- %s" % target) + return False # Compute all those that will need to be installed + to_check = [] + for target in targets: + if check_installed(target): + print("%s is already installed." % target) + else: + to_check.append(target) + done = set() - to_check = [target] to_install = [] while to_check: check = to_check.pop(0) @@ -115,7 +125,7 @@ def install(target): else: print("Aborting installation.") else: - print("%s is already installed." % target) + print("Nothing left to install.") return False From 87f659d1878b9ec11701172df65c4eea3bdefcb9 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Fri, 5 Jun 2020 23:47:31 -0400 Subject: [PATCH 34/39] Make sure packages are set up properly. --- planutils/package_installation.py | 12 +++++++++++- setup.py | 3 +++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/planutils/package_installation.py b/planutils/package_installation.py index 6e30fb9..ab85559 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -8,12 +8,22 @@ CUR_DIR = os.path.dirname(os.path.abspath(__file__)) + +def check_package(target, manifest): + assert os.path.exists(manifest), "Error: Manifest must be defined for %s" % target + with open(manifest, 'r') as f: + config = json.load(f) + for key in ['name', 'description', 'dependencies']: + assert key in config, "Error: Manifest for %s must include '%s'" % (base, key) + + for conf_file in glob.glob(os.path.join(CUR_DIR, 'packages', '*')): base = os.path.basename(conf_file) if base not in ['README.md', 'TEMPLATE']: + assert base not in PACKAGES, "Error: Duplicate package config -- %s" % base + check_package(base, os.path.join(conf_file, 'manifest.json')) with open(os.path.join(conf_file, 'manifest.json'), 'r') as f: config = json.load(f) - assert base not in PACKAGES, "Error: Duplicate package config -- %s" % base PACKAGES[base] = config PACKAGES[base]['runnable'] = os.path.exists(os.path.join(conf_file, 'run')) diff --git a/setup.py b/setup.py index d49fc1f..3e67c4e 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,9 @@ import setuptools +# Will force a check on the packages setup +from planutils.package_installation import PACKAGES + with open("README.md", "r") as fh: long_description = fh.read() From be1c2b961e6d7fc4e60e6d50dcd998641194fd68 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Sat, 6 Jun 2020 00:22:24 -0400 Subject: [PATCH 35/39] Requiring an estimated size, and outputting a predicted size on install --- planutils/package_installation.py | 17 ++++++++++++----- planutils/packages/TEMPLATE/manifest.json | 1 + planutils/packages/downward/manifest.json | 1 + planutils/packages/lama/manifest.json | 1 + 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/planutils/package_installation.py b/planutils/package_installation.py index ab85559..5ecf3e0 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -13,7 +13,7 @@ def check_package(target, manifest): assert os.path.exists(manifest), "Error: Manifest must be defined for %s" % target with open(manifest, 'r') as f: config = json.load(f) - for key in ['name', 'description', 'dependencies']: + for key in ['name', 'description', 'dependencies', 'size']: assert key in config, "Error: Manifest for %s must include '%s'" % (base, key) @@ -114,16 +114,23 @@ def install(targets): to_install.reverse() if to_install: - print("\nAbout to install the following packages: %s" % ', '.join(to_install)) + to_install_desc = ["%s (%s)" % (pkg, PACKAGES[pkg]['size']) for pkg in to_install] + print("\nAbout to install the following packages: %s" % ', '.join(to_install_desc)) if input(" Proceed? [Y/n] ").lower() in ['', 'y', 'yes']: installed = [] for package in to_install: - print("Installing %s..." % package) + package_path = os.path.join(CUR_DIR, 'packages', package) + print("Installing %s..." % package, end='') try: installed.append(package) - subprocess.check_call('./install', cwd=os.path.join(CUR_DIR, 'packages', package)) + subprocess.check_call('./install', cwd=package_path) + size = subprocess.check_output('du -sh .', + cwd=package_path, + shell=True, + encoding='utf-8').split('\t')[0] + print("done. (size: %s)" % size) except subprocess.CalledProcessError: - print("Error installing %s. Rolling back changes..." % package) + print("\nError installing %s. Rolling back changes..." % package) for p in installed: subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', p)) return False diff --git a/planutils/packages/TEMPLATE/manifest.json b/planutils/packages/TEMPLATE/manifest.json index 4f8293c..d2a2aa7 100644 --- a/planutils/packages/TEMPLATE/manifest.json +++ b/planutils/packages/TEMPLATE/manifest.json @@ -1,5 +1,6 @@ { "name": "Full name of package", "description": "General description of the package", + "size": "unknown", "dependencies": ["list", "of", "dependencies"] } diff --git a/planutils/packages/downward/manifest.json b/planutils/packages/downward/manifest.json index 5fb6af8..84ce7c9 100644 --- a/planutils/packages/downward/manifest.json +++ b/planutils/packages/downward/manifest.json @@ -1,5 +1,6 @@ { "name": "Fast Downward", "description": "http://fast-downward.org/", + "size": "36M", "dependencies": [] } diff --git a/planutils/packages/lama/manifest.json b/planutils/packages/lama/manifest.json index 8d02878..6cbef67 100644 --- a/planutils/packages/lama/manifest.json +++ b/planutils/packages/lama/manifest.json @@ -1,5 +1,6 @@ { "name": "LAMA", "description": "http://fast-downward.org/", + "size": "20K", "dependencies": ["downward"] } From ffb00f959c78cff95c1af2db5e2d1f7db82e50a5 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Sat, 6 Jun 2020 00:26:35 -0400 Subject: [PATCH 36/39] Refactored the size config name. --- planutils/package_installation.py | 4 ++-- planutils/packages/TEMPLATE/manifest.json | 2 +- planutils/packages/downward/manifest.json | 2 +- planutils/packages/lama/manifest.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/planutils/package_installation.py b/planutils/package_installation.py index 5ecf3e0..a8a4364 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -13,7 +13,7 @@ def check_package(target, manifest): assert os.path.exists(manifest), "Error: Manifest must be defined for %s" % target with open(manifest, 'r') as f: config = json.load(f) - for key in ['name', 'description', 'dependencies', 'size']: + for key in ['name', 'description', 'dependencies', 'install-size']: assert key in config, "Error: Manifest for %s must include '%s'" % (base, key) @@ -114,7 +114,7 @@ def install(targets): to_install.reverse() if to_install: - to_install_desc = ["%s (%s)" % (pkg, PACKAGES[pkg]['size']) for pkg in to_install] + to_install_desc = ["%s (%s)" % (pkg, PACKAGES[pkg]['install-size']) for pkg in to_install] print("\nAbout to install the following packages: %s" % ', '.join(to_install_desc)) if input(" Proceed? [Y/n] ").lower() in ['', 'y', 'yes']: installed = [] diff --git a/planutils/packages/TEMPLATE/manifest.json b/planutils/packages/TEMPLATE/manifest.json index d2a2aa7..32e70d5 100644 --- a/planutils/packages/TEMPLATE/manifest.json +++ b/planutils/packages/TEMPLATE/manifest.json @@ -1,6 +1,6 @@ { "name": "Full name of package", "description": "General description of the package", - "size": "unknown", + "install-size": "unknown", "dependencies": ["list", "of", "dependencies"] } diff --git a/planutils/packages/downward/manifest.json b/planutils/packages/downward/manifest.json index 84ce7c9..f40a8dc 100644 --- a/planutils/packages/downward/manifest.json +++ b/planutils/packages/downward/manifest.json @@ -1,6 +1,6 @@ { "name": "Fast Downward", "description": "http://fast-downward.org/", - "size": "36M", + "install-size": "36M", "dependencies": [] } diff --git a/planutils/packages/lama/manifest.json b/planutils/packages/lama/manifest.json index 6cbef67..621fd1f 100644 --- a/planutils/packages/lama/manifest.json +++ b/planutils/packages/lama/manifest.json @@ -1,6 +1,6 @@ { "name": "LAMA", "description": "http://fast-downward.org/", - "size": "20K", + "install-size": "20K", "dependencies": ["downward"] } From 660260f1b4df4ffd227f7d9b8a7dc5380c32b8e4 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Sat, 6 Jun 2020 22:14:32 -0400 Subject: [PATCH 37/39] Minor fixes to the default behaviour of uninstalled package scripts. --- planutils/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 55d34a9..3da99de 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -42,13 +42,14 @@ def setup(): script += "else\n" script += " echo\n" script += " echo 'Package not installed!'\n" - script += " read -r -p \" Download & install? [y/N] \" varchoice\n" + script += " read -r -p \" Download & install? [Y/n] \" varchoice\n" script += " varchoice=${varchoice,,}\n" # tolower - script += " if [[ \"$varchoice\" =~ ^(yes|y)$ ]]\n" + script += " if [[ \"$varchoice\" =~ ^(yes|y|)$ ]]\n" script += " then\n" script += " if planutils install %s;\n" % p script += " then\n" script += " echo 'Successfully installed %s!'\n" % p + script += " echo\n" script += " echo \"Original command: %s $@\"\n" % p script += " read -r -p \" Re-run command? [Y/n] \" varchoice\n" script += " varchoice=${varchoice,,}\n" # tolower From 6f906767730e4bc9a676f1e0979213cf29b32ff6 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Sat, 6 Jun 2020 22:16:58 -0400 Subject: [PATCH 38/39] Optionally iterate through packages that may be no longer required. --- planutils/package_installation.py | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/planutils/package_installation.py b/planutils/package_installation.py index a8a4364..28ede03 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -63,10 +63,32 @@ def uninstall(targets): print("\nAbout to remove the following packages: %s" % ', '.join(to_remove)) if input(" Proceed? [y/N] ").lower() in ['y', 'yes']: for package in to_remove: - print ("Uninstalling %s..." % package) + print ("Uninstalling %s..." % package, end='') subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', package)) + print ("done.") s['installed'].remove(package) - settings.save(s) + + # Search for any packages that may be no longer required + dependency_mapping = defaultdict(set) + for p in PACKAGES: + for dep in PACKAGES[p]['dependencies']: + dependency_mapping[dep].add(p) + + possible_deletions = [d for p in to_remove for d in PACKAGES[p]['dependencies']] + while possible_deletions: + package = possible_deletions.pop(0) + # Consider removing if (1) it's installed; and (2) nothing that requires this is installed + if (package in s['installed']) and (not any([p in s['installed'] for p in dependency_mapping[package]])): + print("\nPackage may no longer be required: %s" % package) + if input(" Remove? [y/N] ").lower() in ['y', 'yes']: + print ("Uninstalling %s..." % package, end='') + subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', package)) + print ("done.") + s['installed'].remove(package) + possible_deletions.extend(PACKAGES[package]['dependencies']) + + settings.save(s) + def package_list(): print("\nInstalled:") From 150b7e35c884ba4aec53bdf289df110f0293cca2 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Fri, 12 Jun 2020 22:59:50 -0400 Subject: [PATCH 39/39] Fixing a couple of bugs. --- planutils/__init__.py | 2 +- planutils/package_installation.py | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/planutils/__init__.py b/planutils/__init__.py index 3da99de..8b6a9d1 100644 --- a/planutils/__init__.py +++ b/planutils/__init__.py @@ -44,7 +44,7 @@ def setup(): script += " echo 'Package not installed!'\n" script += " read -r -p \" Download & install? [Y/n] \" varchoice\n" script += " varchoice=${varchoice,,}\n" # tolower - script += " if [[ \"$varchoice\" =~ ^(yes|y|)$ ]]\n" + script += " if ! [[ \"$varchoice\" =~ ^(no|n)$ ]]\n" script += " then\n" script += " if planutils install %s;\n" % p script += " then\n" diff --git a/planutils/package_installation.py b/planutils/package_installation.py index 28ede03..8f3de18 100644 --- a/planutils/package_installation.py +++ b/planutils/package_installation.py @@ -46,6 +46,9 @@ def uninstall(targets): else: print("%s isn't installed." % target) + if not to_check: + return + s = settings.load() # map a package to all those that depend on it dependency_mapping = defaultdict(set) @@ -63,9 +66,9 @@ def uninstall(targets): print("\nAbout to remove the following packages: %s" % ', '.join(to_remove)) if input(" Proceed? [y/N] ").lower() in ['y', 'yes']: for package in to_remove: - print ("Uninstalling %s..." % package, end='') + print ("Uninstalling %s..." % package) subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', package)) - print ("done.") + print ("Finished uninstalling %s" % package) s['installed'].remove(package) # Search for any packages that may be no longer required @@ -81,9 +84,9 @@ def uninstall(targets): if (package in s['installed']) and (not any([p in s['installed'] for p in dependency_mapping[package]])): print("\nPackage may no longer be required: %s" % package) if input(" Remove? [y/N] ").lower() in ['y', 'yes']: - print ("Uninstalling %s..." % package, end='') + print ("Uninstalling %s..." % package) subprocess.call('./uninstall', cwd=os.path.join(CUR_DIR, 'packages', package)) - print ("done.") + print ("Finished uninstalling %s" % package) s['installed'].remove(package) possible_deletions.extend(PACKAGES[package]['dependencies']) @@ -142,7 +145,7 @@ def install(targets): installed = [] for package in to_install: package_path = os.path.join(CUR_DIR, 'packages', package) - print("Installing %s..." % package, end='') + print("Installing %s..." % package) try: installed.append(package) subprocess.check_call('./install', cwd=package_path) @@ -150,7 +153,7 @@ def install(targets): cwd=package_path, shell=True, encoding='utf-8').split('\t')[0] - print("done. (size: %s)" % size) + print("Finished installing %s (size: %s)" % (package, size)) except subprocess.CalledProcessError: print("\nError installing %s. Rolling back changes..." % package) for p in installed: