diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 826a964d..c7cfc85a 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -95,8 +95,7 @@ jobs: - uses: actions/upload-artifact@v3 with: name: PharoLauncher-linux-${{ env.LAUNCHER_VERSION }}-${{ env.FILE_NAME_ARCH_SUFFIX }} - path: | - build/ + path: pharo-launcher-linux.tar outputs: launcherVersion: ${{ env.LAUNCHER_VERSION }} diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml new file mode 100644 index 00000000..efb1f95e --- /dev/null +++ b/.github/workflows/doc.yml @@ -0,0 +1,29 @@ +name: documentation +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + inputs: + deploy-to-gh-pages: + type: boolean + description: Deploy the documentation built with mkdocs to GitHub pages? + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.x + - run: pip install mkdocs + + - run: mkdocs build + if: github.event.inputs.deploy-to-gh-pages == 'false' + - uses: actions/upload-artifact@v3 + with: + name: pharo-launcher-documentation + path: site + if: github.event.inputs.deploy-to-gh-pages == 'false' + + - run: mkdocs gh-deploy + if: github.event.inputs.deploy-to-gh-pages == 'true' diff --git a/.gitignore b/.gitignore index c7248c9f..a321203e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ site/ *.html *.swp + +.DS_Store diff --git a/PharoLauncherCmdLine-description.md b/PharoLauncherCmdLine-description.md deleted file mode 100644 index 4a4d1d27..00000000 --- a/PharoLauncherCmdLine-description.md +++ /dev/null @@ -1,17 +0,0 @@ -# Introduction -Purpose of this document is to describe command line interface for Pharo launcher with description of necessary commands. - -# Plans -1. At first, estabilish structure/design of cmd-line interface and what operations, arguments should be supported (this document). -2. Implement stub of cmd-line interface using CLAP. It won't contain necessary connection to Pharo launcher commands yet. -3. If cmd-line design is good to go, we can start on moving Pharo launcher backend code to dedicated package, which could be used by CLAP commands in previous step. -4. Build of headless Pharo launcher (resulting in change of Pharo launcher baseline and change of corresponding Github actions) can be then initiated. Resulting app (executable) will no longer open UI of Pharo launcher. - -# Open questions -1. What if there is some interaction needed? E.g. network is unavailable, should we offer dialog-like options (e.g.: "Reconnect Y/N?"), or rather to avoid that? -2. What is priority of every command? I guess some of them are more important than others (order of how it should be implemented). -3. How to escape path parameters? What type of quotes should be used? (single like 'path to dir' or rathter "this is path" -4. How to print-out errors? Some kind of formatting? (E.g. "ERROR: Could not create image to directory: usr/local/Pharo/images") -5. How to display progress (if ever)? This could be useful during downlaod commands, like "INFO: Fetching from remote-site URL..." (dot's added every second, or maybe percentage?). - - diff --git a/README.md b/README.md index e94299c9..1708699b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ The Pharo Launcher is a cross-platform application that - lets you create new images from any template, - automatically find and download the appropriate VM to launch your images. -A Pharo Launcher screenshot +A Pharo Launcher screenshot The idea behind the Pharo Launcher is that you should be able to access it very rapidly from your OS application launcher. As a result, launching any image is never more than 3 clicks away. @@ -84,4 +84,4 @@ Metacello new load ``` -Then evaluate "PharoLauncher open". You can also launch it from the World menu. +Then evaluate "PharoLauncherApplication open". You can also launch it from the World menu. diff --git a/build.sh b/build.sh index 86e43647..4fdf0776 100755 --- a/build.sh +++ b/build.sh @@ -65,7 +65,7 @@ function package_linux_version() { OUTPUT_PATH=build RESOURCES_PATH=$OUTPUT_PATH/shared rm -f $OUTPUT_PATH; mkdir $OUTPUT_PATH - mkdir $OUTPUT_PATH/icons; cp icons/pharo-launcher.png $OUTPUT_PATH/ + mkdir $OUTPUT_PATH/icons; cp icons/pharo-launcher.png $OUTPUT_PATH/icons/ cp linux/pharo-launcher-ui $OUTPUT_PATH/ cp scripts/pharo-launcher.sh $OUTPUT_PATH/pharo-launcher mkdir $RESOURCES_PATH @@ -74,9 +74,11 @@ function package_linux_version() { cp PharoLauncher.image $RESOURCES_PATH cp PharoLauncher.changes $RESOURCES_PATH cp Pharo*.sources $RESOURCES_PATH - fetch_current_vm_to $(pwd)/$RESOURCES_PATH + fetch_current_vm_to $OUTPUT_PATH # ensure the linux scripts are executable chmod +x "$OUTPUT_PATH/pharo-launcher" "$OUTPUT_PATH/pharo-launcher-ui" || true + mv build pharo-launcher + tar -cvf pharo-launcher-linux.tar pharo-launcher } function copy_mac_icon_files_to() { diff --git a/docs/commands-cmd-line.md b/doc/commands-cmd-line.md similarity index 80% rename from docs/commands-cmd-line.md rename to doc/commands-cmd-line.md index caf363ef..2da253b1 100644 --- a/docs/commands-cmd-line.md +++ b/doc/commands-cmd-line.md @@ -1,6 +1,6 @@ # Pharo Laucher command-line This is list of subject oriented CLI commands of Pharo launcher, where subjects are Pharo VM, image or image template of launcher. -Use: `pharo-launcher.sh ` +Use: `pharo-launcher ` | Command | Sub-command | | Description | | ------- | ----------- | ----------------- | ----------- | @@ -14,12 +14,13 @@ Use: `pharo-launcher.sh ` | | | [fromSHA](#Image-create-from-SHA-commit) | Downloads and creates new image based on the commit SHA (7 letter string contained in the name of Pharo dev template). | | | [delete](#image-delete) | | Deletes the local image, including image directory content. | | | [info](#image-info) | | Prints information about image: name, description, origin template, etc. | -| | [kill](#image-kill) | | Kills the running process(es) of given local image. | | | [launch](#image-launch) | | Launches image with using default (auto-detected) VM. | | | [list](#image-list) | | Lists all local images from Pharo laucher repository. | | | [package](#image-package) | | Creates a package containing all necessary artefacts to launch the image. | -| | [processList](#image-process-list) | | Lists all running Pharo image processes. | | | [recreate](#image-recreate) | | Recreates the local image, the image argument determines the image name to recreate. | +| [process](#process) | | | All sub-commands related to Pharo processes. (Prints help only) | +| | [kill](#process-kill) | | Kills the running Pharo process(es) of given image. | +| | [list](#process-list) | | Lists all running Pharo image processes. | | [template](#template) | | | All sub-commands related to image templates. (Prints help only) | | | [categories](#template-categories) | | Lists all image template categories, based on which are image templates categorized. | | | [info](#template-info) | | Prints information about image template name, origin url. | @@ -33,9 +34,9 @@ Use: `pharo-launcher.sh ` # Getting started Command line interface of Pharo Launcher is avaliable from directory, where launcher is installed. -Pharo Launcher CLI can be executed using: `pharo-launcher.sh ` (choosing on of the commands above). +Pharo Launcher CLI can be executed using: `pharo-launcher ` (choosing on of the commands above). ## 1. List Pharo images -You can start listing Pharo images deployed by Pharo launcher by: `pharo-launcher.sh image list` +You can start listing Pharo images deployed by Pharo launcher by: `pharo-launcher image list` This will give output like: ``` # Name Architecture Pharo version Last modified @@ -47,7 +48,7 @@ This will give output like: 5 Pharo 10.0 - 64bit (stable) 64 100 2022-06-17 12:26:09 ``` ## 2. Create new Pharo image -New Pharo image can be created by executing: `pharo-launcher.sh image create myImage` +New Pharo image can be created by executing: `pharo-launcher image create myImage` This will efectively create Pharo image based on latest stable Pharo release template. Output looks like this: ``` @@ -59,27 +60,27 @@ You could check result by listing Pharo images again. > __Note__: There are other ways to create images, check sub-commands. ## 3. Launching Pharo image -To launch image, execute following: `pharo-launcher.sh image launch myImage` +To launch image, execute following: `pharo-launcher image launch myImage` This will start new Pharo process and window with Pharo should be visible. Check command options, to see how to pass launch configuration. ## 4. Listing running Pharo images -To see, which Pharo images are running: `pharo-launcher.sh image processList` +To see, which Pharo images are running: `pharo-launcher process list` Output will look similar like this: ``` 3093 /home/dbajger/Pharo/vms/100-x64/lib/pharo /home/dbajger/Pharo/images/myImage/myImage.image ``` ## 5. Kill running Pharo image process -To kill running Pharo process execute: `pharo-launcher.sh image kill myImage` +To kill running Pharo process execute: `pharo-launcher process kill myImage` This will kill all running images with name `myImage`. You can also use specific PID, to precisely specify process to kill instead of name of image. ## 6. Create package with Pharo image -To pack existing image with VM and all artefacts you can run: `pharo-launcher.sh image package myImage /home/dbajger/fresh` +To pack existing image with VM and all artefacts you can run: `pharo-launcher image package myImage /home/dbajger/fresh` This will create new directory in `/home/dbajger/fresh` with image and all artefacts. > __Note__: You can also use `--zip` option to have just zip archive with image artifacts (see details below). ## 7. Deleting existing image -To delete image and its directory, run: `pharo-launcher.sh image delete myImage` +To delete image and its directory, run: `pharo-launcher image delete myImage` You can list Pharo images again to check that image is deleted. # Description of all Pharo Launcher CLI commands @@ -88,19 +89,19 @@ You can list Pharo images again to check that image is deleted. This is help for command line interface of Pharo Launcher. Common purpose of laucher is to create Pharo image locally from remote site template, launch Pharo, eventually delete an image, update VMs, etc. -Run: `pharo-launcher.sh help` +Run: `pharo-launcher help` # Image commands ## Image Root command of all image commands, prints help only. -Run: `pharo-launcher.sh image` to see help. +Run: `pharo-launcher image` to see help. ## Image copy Creates copy of given image with new name. ### Usage ```bash -pharo-launcher.sh image copy [--help] [] [] +pharo-launcher image copy [--help] [] [] ``` ### Parameters @@ -114,13 +115,13 @@ pharo-launcher.sh image copy [--help] [] [] ### Examples **#1:** To copy existing image `myImage` and create new copy `newImage` from it, run: ``` -pharo-launcher.sh image copy myImage newImage +pharo-launcher image copy myImage newImage ``` ## Image create Downloads and creates new image on local computer from remote site based on template name (latest stable template is used by default). ### Usage ```bash -pharo-launcher.sh image create [--help] [--templateName ] [--templateCategory ] [] +pharo-launcher image create [--help] [--templateName ] [--templateCategory ] [] ``` ### Parameters @@ -139,15 +140,15 @@ pharo-launcher.sh image create [--help] [--templateName ] [- ### Examples **#1:** Creates an image (passing new image name as argument) based on the last pharo stable 64bits version: ``` -pharo-launcher.sh image create myNewImageName +pharo-launcher image create myNewImageName ``` **#2:** Creates an image based on the template `Pharo 7.0 - 64bit (old stable)` listed in `Official distributions` (default) template category: ``` -pharo-launcher.sh image create myNewImageName "Pharo 7.0 - 64bit (old stable)" +pharo-launcher image create myNewImageName "Pharo 7.0 - 64bit (old stable)" ``` **#3:** Creates an image based on the template `Pharo Mooc` from template category `Pharo Mooc`: ``` -pharo-launcher.sh image create myNewImageName "Pharo Mooc" --templateCategory "Pharo Mooc" +pharo-launcher image create myNewImageName "Pharo Mooc" --templateCategory "Pharo Mooc" ``` ## Image create from build number @@ -155,7 +156,7 @@ Downloads and creates new image based on a the build number contained in the Pha ### Usage ```bash -pharo-launcher.sh image create fromBuild [--help] [--pharoVersion ] [--newImageName ] [] +pharo-launcher image create fromBuild [--help] [--pharoVersion ] [--newImageName ] [] ``` ### Parameters @@ -175,7 +176,7 @@ Downloads and creates new image based on a Github pull request number from the s ### Usage ```bash -pharo-launcher.sh image create fromPR [--help] [--newImageName ] [--templateName ] [--templateCategory ] [] +pharo-launcher image create fromPR [--help] [--newImageName ] [--templateName ] [--templateCategory ] [] ``` ### Parameters @@ -196,7 +197,7 @@ Downloads and creates new image based on a template and loads user defined proje ### Usage ```bash -pharo-launcher.sh image create fromRepo [--help] [--newImageName ] [--templateName ] [--templateCategory ] [--subfolder ] [--baseline ] [--group ] [] +pharo-launcher image create fromRepo [--help] [--newImageName ] [--templateName ] [--templateCategory ] [--subfolder ] [--baseline ] [--group ] [] ``` ### Parameters @@ -225,7 +226,7 @@ Downloads and creates new image based on the commit SHA (7 letter string) of Pha ### Usage ```bash -pharo-launcher.sh image create fromSHA [--help] [--pharoVersion ] [--newImageName ] [] +pharo-launcher image create fromSHA [--help] [--pharoVersion ] [--newImageName ] [] ``` ### Parameters Commit SHA (7 letters) of Pharo image development template, from which will be image created. @@ -244,7 +245,7 @@ Deletes the local image, including image directory content. ### Usage ```bash -pharo-launcher.sh image delete [--help] [] +pharo-launcher image delete [--help] [] ``` ### Parameters @@ -261,7 +262,7 @@ Prints information about image: name, description, origin template, etc. ### Usage ```bash -pharo-launcher.sh image info [--help] [--brief] [--rowMode] [--delimiter ] [--ston] [] +pharo-launcher image info [--help] [--brief] [--rowMode] [--delimiter ] [--ston] [] ``` ### Parameters @@ -277,31 +278,12 @@ pharo-launcher.sh image info [--help] [--brief] [--rowMode] [--delimiter ] -``` - -### Parameters - - Specifies the local image name to kill its process. - -### Options - --help Prints this documentation - --all Determines whether to kill all running Pharo image processes. - -### Examples -No examples yet. - ## Image launch Launches image with using default (auto-detected) VM. ### Usage ```bash -pharo-launcher.sh image launch [--help] [--script ] [] +pharo-launcher image launch [--help] [--script ] [] ``` ### Parameters @@ -315,11 +297,11 @@ pharo-launcher.sh image launch [--help] [--script ] [] [--brief] [--rowMode] [--delimiter ] [--ston] +pharo-launcher image list [--help] [--nameFilter ] [--brief] [--rowMode] [--delimiter ] [--ston] ``` ### Options --help Prints this documentation - --name - Determines the name of image (or its sub-part) to list local images. + --nameFilter + Images listing will be filtered by the provided name filter. --brief Prints only name attribute (with leading sequence number). --rowMode Prints one attribute per line only. --delimiter @@ -347,7 +329,7 @@ Creates a package containing all necessary artefacts to launch the image. ### Usage ```bash -pharo-launcher.sh image package [--help] [--zip] [--vm ] [] [] +pharo-launcher image package [--help] [--zip] [--vm ] [] [] ``` ### Parameters @@ -364,43 +346,72 @@ pharo-launcher.sh image package [--help] [--zip] [--vm ] [] ``` +### Parameters + + Local image name to recreate. + ### Options --help Prints this documentation -### Examples -No examples yet. -## Image recreate -Recreates the local image, the image argument determines the image name to recreate. +# Process commands + +## Process +Root command of all process commands, prints help only. +Run: `pharo-launcher process` to see help. + +## Process kill +Kills the running Pharo process(es) of given local image. ### Usage ```bash -pharo-launcher.sh image recreate [--help] [] +pharo-launcher process kill [--help] [--all] [] ``` + ### Parameters - Local image name to recreate. + Specifies the local image name to kill its process. ### Options --help Prints this documentation + --all Determines whether to kill all running Pharo image processes. + +### Examples +No examples yet. + +## Process list +Lists all running Pharo image processes. + +### Usage +```bash +pharo-launcher process list [--help] +``` +### Options + --help Prints this documentation + +### Examples +No examples yet. + + # Template commands + ## Template Root command of all template commands, prints help only. -Run: `pharo-launcher.sh template` to see help. +Run: `pharo-launcher template` to see help. ## Template categories Prints list of image template categories. ### Usage ```bash -pharo-launcher.sh template categories [--help] [--brief] [--rowMode] [--delimiter ] [--ston] +pharo-launcher template categories [--help] [--brief] [--rowMode] [--delimiter ] [--ston] ``` ### Options @@ -418,7 +429,7 @@ Prints information about image template name, origin url. ### Usage ```bash -pharo-launcher.sh template info [--help] [--templateCategory ] [] +pharo-launcher template info [--help] [--templateCategory ] [] ``` ### Parameters @@ -437,7 +448,7 @@ Prints list of image templates. ### Usage ```bash -pharo-launcher.sh template list [--help] [--templateCategory ] [--brief] [--rowMode] [--delimiter ] [--ston] +pharo-launcher template list [--help] [--templateCategory ] [--brief] [--rowMode] [--delimiter ] [--ston] ``` ### Options @@ -453,18 +464,19 @@ pharo-launcher.sh template list [--help] [--templateCategory ] +pharo-launcher vm delete [--help] [] ``` ### Parameters @@ -482,7 +494,7 @@ Prints information about VM: name, remote-site URL, last update status, etc. ### Usage ```bash -pharo-launcher.sh vm info [--help] [] +pharo-launcher vm info [--help] [] ``` ### Parameters @@ -499,7 +511,7 @@ Lists all available VMs, with status. ### Usage ```bash -pharo-launcher.sh vm list [--help] [--brief] [--rowMode] [--delimiter ] [--ston] [] +pharo-launcher vm list [--help] [--brief] [--rowMode] [--delimiter ] [--ston] [] ``` ### Parameters @@ -521,7 +533,7 @@ Updates VM executable, including dependent libs to latest version from remote si ### Usage ```bash -pharo-launcher.sh vm update [--help] [] +pharo-launcher vm update [--help] [] ``` ### Parameters diff --git a/docs/commands.md b/doc/commands.md similarity index 100% rename from docs/commands.md rename to doc/commands.md diff --git a/docs/contribute.md b/doc/contribute.md similarity index 100% rename from docs/contribute.md rename to doc/contribute.md diff --git a/docs/create-images.md b/doc/create-images.md similarity index 100% rename from docs/create-images.md rename to doc/create-images.md diff --git a/docs/images/about-command.png b/doc/images/about-command.png similarity index 100% rename from docs/images/about-command.png rename to doc/images/about-command.png diff --git a/docs/images/basic-launch-command.png b/doc/images/basic-launch-command.png similarity index 100% rename from docs/images/basic-launch-command.png rename to doc/images/basic-launch-command.png diff --git a/docs/images/delete-command.png b/doc/images/delete-command.png similarity index 100% rename from docs/images/delete-command.png rename to doc/images/delete-command.png diff --git a/docs/images/edit-script-button.png b/doc/images/edit-script-button.png similarity index 100% rename from docs/images/edit-script-button.png rename to doc/images/edit-script-button.png diff --git a/docs/images/global-commands.png b/doc/images/global-commands.png similarity index 100% rename from docs/images/global-commands.png rename to doc/images/global-commands.png diff --git a/docs/images/image-contextual-menu-commands.png b/doc/images/image-contextual-menu-commands.png similarity index 100% rename from docs/images/image-contextual-menu-commands.png rename to doc/images/image-contextual-menu-commands.png diff --git a/docs/images/image-creation-filled.png b/doc/images/image-creation-filled.png similarity index 100% rename from docs/images/image-creation-filled.png rename to doc/images/image-creation-filled.png diff --git a/docs/images/image-creation.png b/doc/images/image-creation.png similarity index 100% rename from docs/images/image-creation.png rename to doc/images/image-creation.png diff --git a/docs/images/image-description.png b/doc/images/image-description.png similarity index 100% rename from docs/images/image-description.png rename to doc/images/image-description.png diff --git a/docs/images/image-name-not-valid.png b/doc/images/image-name-not-valid.png similarity index 100% rename from docs/images/image-name-not-valid.png rename to doc/images/image-name-not-valid.png diff --git a/docs/images/import-command.png b/doc/images/import-command.png similarity index 100% rename from docs/images/import-command.png rename to doc/images/import-command.png diff --git a/docs/images/init-script-editor.png b/doc/images/init-script-editor.png similarity index 100% rename from docs/images/init-script-editor.png rename to doc/images/init-script-editor.png diff --git a/docs/images/initialization-script-dropbox.png b/doc/images/initialization-script-dropbox.png similarity index 100% rename from docs/images/initialization-script-dropbox.png rename to doc/images/initialization-script-dropbox.png diff --git a/docs/images/install-dmg.png b/doc/images/install-dmg.png similarity index 100% rename from docs/images/install-dmg.png rename to doc/images/install-dmg.png diff --git a/docs/images/launch-command.png b/doc/images/launch-command.png similarity index 100% rename from docs/images/launch-command.png rename to doc/images/launch-command.png diff --git a/docs/images/launch-configuration-editor.png b/doc/images/launch-configuration-editor.png similarity index 100% rename from docs/images/launch-configuration-editor.png rename to doc/images/launch-configuration-editor.png diff --git a/docs/images/launch-configuration-toolbar.png b/doc/images/launch-configuration-toolbar.png similarity index 100% rename from docs/images/launch-configuration-toolbar.png rename to doc/images/launch-configuration-toolbar.png diff --git a/docs/images/launch-from-disk-command.png b/doc/images/launch-from-disk-command.png similarity index 100% rename from docs/images/launch-from-disk-command.png rename to doc/images/launch-from-disk-command.png diff --git a/docs/images/new-command.png b/doc/images/new-command.png similarity index 100% rename from docs/images/new-command.png rename to doc/images/new-command.png diff --git a/docs/images/pharo-launcher-launch-linux.png b/doc/images/pharo-launcher-launch-linux.png similarity index 100% rename from docs/images/pharo-launcher-launch-linux.png rename to doc/images/pharo-launcher-launch-linux.png diff --git a/docs/images/pharo-launcher-main-window.png b/doc/images/pharo-launcher-main-window.png similarity index 100% rename from docs/images/pharo-launcher-main-window.png rename to doc/images/pharo-launcher-main-window.png diff --git a/docs/images/pharo-launcher-settings-browser.png b/doc/images/pharo-launcher-settings-browser.png similarity index 100% rename from docs/images/pharo-launcher-settings-browser.png rename to doc/images/pharo-launcher-settings-browser.png diff --git a/docs/images/pharo-launcher-unzip-linux.png b/doc/images/pharo-launcher-unzip-linux.png similarity index 100% rename from docs/images/pharo-launcher-unzip-linux.png rename to doc/images/pharo-launcher-unzip-linux.png diff --git a/docs/images/pharo-launcher.png b/doc/images/pharo-launcher.png similarity index 100% rename from docs/images/pharo-launcher.png rename to doc/images/pharo-launcher.png diff --git a/docs/images/quit-command.png b/doc/images/quit-command.png similarity index 100% rename from docs/images/quit-command.png rename to doc/images/quit-command.png diff --git a/docs/images/refresh-command.png b/doc/images/refresh-command.png similarity index 100% rename from docs/images/refresh-command.png rename to doc/images/refresh-command.png diff --git a/docs/images/settings-command.png b/doc/images/settings-command.png similarity index 100% rename from docs/images/settings-command.png rename to doc/images/settings-command.png diff --git a/docs/images/show-command.png b/doc/images/show-command.png similarity index 100% rename from docs/images/show-command.png rename to doc/images/show-command.png diff --git a/docs/images/taskbar.png b/doc/images/taskbar.png similarity index 100% rename from docs/images/taskbar.png rename to doc/images/taskbar.png diff --git a/docs/images/template-categories.png b/doc/images/template-categories.png similarity index 100% rename from docs/images/template-categories.png rename to doc/images/template-categories.png diff --git a/docs/images/template-commands.png b/doc/images/template-commands.png similarity index 100% rename from docs/images/template-commands.png rename to doc/images/template-commands.png diff --git a/docs/images/vm-command.png b/doc/images/vm-command.png similarity index 100% rename from docs/images/vm-command.png rename to doc/images/vm-command.png diff --git a/docs/images/vm-presenter-private.png b/doc/images/vm-presenter-private.png similarity index 100% rename from docs/images/vm-presenter-private.png rename to doc/images/vm-presenter-private.png diff --git a/docs/images/vm-presenter.png b/doc/images/vm-presenter.png similarity index 100% rename from docs/images/vm-presenter.png rename to doc/images/vm-presenter.png diff --git a/docs/images/vm-private-toggle-command.png b/doc/images/vm-private-toggle-command.png similarity index 100% rename from docs/images/vm-private-toggle-command.png rename to doc/images/vm-private-toggle-command.png diff --git a/docs/images/warning-osx-gatekeeper.png b/doc/images/warning-osx-gatekeeper.png similarity index 100% rename from docs/images/warning-osx-gatekeeper.png rename to doc/images/warning-osx-gatekeeper.png diff --git a/docs/images/warning-osx-not-appstore.png b/doc/images/warning-osx-not-appstore.png similarity index 100% rename from docs/images/warning-osx-not-appstore.png rename to doc/images/warning-osx-not-appstore.png diff --git a/docs/images/windows-installer-2-folder.png b/doc/images/windows-installer-2-folder.png similarity index 100% rename from docs/images/windows-installer-2-folder.png rename to doc/images/windows-installer-2-folder.png diff --git a/docs/images/windows-installer-3-finish.png b/doc/images/windows-installer-3-finish.png similarity index 100% rename from docs/images/windows-installer-3-finish.png rename to doc/images/windows-installer-3-finish.png diff --git a/docs/images/windows-installer.png b/doc/images/windows-installer.png similarity index 100% rename from docs/images/windows-installer.png rename to doc/images/windows-installer.png diff --git a/docs/images/windows-shorcut.png b/doc/images/windows-shorcut.png similarity index 100% rename from docs/images/windows-shorcut.png rename to doc/images/windows-shorcut.png diff --git a/docs/index.md b/doc/index.md similarity index 100% rename from docs/index.md rename to doc/index.md diff --git a/docs/installation.md b/doc/installation.md similarity index 100% rename from docs/installation.md rename to doc/installation.md diff --git a/docs/launch-configurations.md b/doc/launch-configurations.md similarity index 100% rename from docs/launch-configurations.md rename to doc/launch-configurations.md diff --git a/docs/manage-vms.md b/doc/manage-vms.md similarity index 100% rename from docs/manage-vms.md rename to doc/manage-vms.md diff --git a/docs/settings.md b/doc/settings.md similarity index 100% rename from docs/settings.md rename to doc/settings.md diff --git a/docs/templates.md b/doc/templates.md similarity index 100% rename from docs/templates.md rename to doc/templates.md diff --git a/mkdocs.yml b/mkdocs.yml index 1f2fbc85..5dd05b2d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,6 +1,7 @@ site_name: Pharo Launcher documentation repo_url: https://github.com/pharo-project/pharo-launcher/ -edit_uri: edit/dev/docs/ +docs_dir: doc +edit_uri: edit/dev/doc/ nav: - Home: index.md - installation.md diff --git a/scripts/pharo-launcher.sh b/scripts/pharo-launcher.sh index a97d3565..ceadc06e 100755 --- a/scripts/pharo-launcher.sh +++ b/scripts/pharo-launcher.sh @@ -30,7 +30,7 @@ fi # RUN THE VM and pass along all arguments as is ================================ if [ "$OS" = "linux" ]; then - "$ROOT"/pharo-vm/pharo --headless "$ROOT"/shared/PharoLauncher.image clap launcher "$@" + "$ROOT"/pharo-vm/pharo --headless "$ROOT"/shared/PharoLauncher.image --no-default-preferences clap launcher "$@" elif [ "$OS" = "mac" ]; then - "$ROOT"/Pharo --headless "$ROOT"/../Resources/PharoLauncher.image clap launcher "$@" + "$ROOT"/Pharo --headless "$ROOT"/../Resources/PharoLauncher.image --no-default-preferences clap launcher "$@" fi diff --git a/sources.list b/sources.list index 2f87b591..d0b40a64 100644 --- a/sources.list +++ b/sources.list @@ -147,7 +147,7 @@ OrderedCollection [ #type : #HttpListing, #name : 'Pharo 12.0 (development version)', #url : 'https://files.pharo.org/image/120/', - #filterPattern : 'href="(Pharo-?12-SNAPSHOT.build.[^"]*.zip)"' + #filterPattern : 'href="(Pharo-?12(.[0-9]+)?-SNAPSHOT.build.[^"]*.zip)"' }, PhLTemplateSource { #type : #HttpListing, diff --git a/src/PharoLauncher-CLI-Tests/ConsoleListFormatterTest.class.st b/src/PharoLauncher-CLI-Tests/ConsoleListFormatterTest.class.st index a481cb14..7ebec14b 100644 --- a/src/PharoLauncher-CLI-Tests/ConsoleListFormatterTest.class.st +++ b/src/PharoLauncher-CLI-Tests/ConsoleListFormatterTest.class.st @@ -20,7 +20,7 @@ ConsoleListFormatterTest >> setUp [ command cliFormatter: formatter. ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testAttributeValuesFrom [ formatter attributeValueBlocks: { @@ -31,14 +31,14 @@ ConsoleListFormatterTest >> testAttributeValuesFrom [ self assert: (formatter attributeValuesFrom: 2) equals: #('2' '4' '8'). ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testFormatterAccessors [ formatter attributeLabels: #(). ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testGetColumnWidthsFrom [ formatter attributeLabels: #('1234567890' 'x' 'x'). formatter attributeValueBlocks: @@ -57,11 +57,11 @@ ConsoleListFormatterTest >> testGetMaxPrintStringWidthForPrintBlock [ | size | size := formatter getMaxPrintStringWidthFor: #(1 2 3) printBlock: [ :aNumber | aNumber asWords ]. - "three is the longest word and has a size of 5" + "Array of 1,2,3 are converted to #('one 'two' 'three') so the longest word is 'three' has a size of 5" self assert: size equals: 5. ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testPrintAttributeHeadersBy [ formatter printAttributeHeaders: #('label1' 'label2' 'label3') @@ -78,7 +78,7 @@ ConsoleListFormatterTest >> testPrintAttributeHeadersBy [ newLine ]) ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testPrintAttributeHeadersByNoSequence [ "formatted header should not contain sequence column" @@ -99,7 +99,7 @@ ConsoleListFormatterTest >> testPrintAttributeHeadersByNoSequence [ newLine ]) ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testPrintAttributeRowsBy [ |expectedString| @@ -118,7 +118,7 @@ ConsoleListFormatterTest >> testPrintAttributeRowsBy [ self assert: formatter outStream contents equals: expectedString. ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testPrintAttributeTable [ |expectedString| @@ -140,31 +140,58 @@ ConsoleListFormatterTest >> testPrintAttributeTable [ ] -{ #category : #test } +{ #category : #tests } +ConsoleListFormatterTest >> testPrintAttributeTableWithDefaultValue [ + + |expectedString| + formatter attributeLabels: #('Value' 'Squared' 'Raised to 3'). + formatter attributeValueBlocks: { [:a |a asWords ]. [:a |a squared asWords ]. [:a |(a **3) asWords ] }. + formatter domainObjects: #(1 2 3) defaultValue: 2. + formatter printAttributeTable. + + expectedString := String streamContents: [:aStream | + aStream + nextPutAll: '# *Value*Squared*Raised to 3 '; newLine; + nextPutAll: '---*-----*-------*------------'; newLine; + nextPutAll: ' 1 *one *one *one '; newLine; + nextPutAll: '*2 *two *four *eight '; newLine; + nextPutAll: ' 3 *three*nine *twenty-seven'; newLine + ]. + + self assert: formatter outStream contents equals: expectedString. + +] + +{ #category : #tests } ConsoleListFormatterTest >> testPrintCellWidth [ formatter printCell: 'value' width: 10. self assert: command outStream contents equals: 'value '. command resetOutStream. + formatter printCell: 'value' width: 0. self assert: command outStream contents equals: 'value'. + + command resetOutStream. + formatter printCell: 'some very long string' width: 15. + self assert: command outStream contents equals: 'some ... string'. ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testPrintDelimiter [ formatter printDelimiter. self assert: command outStream contents equals: command delimiter. ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testPrintHeaderLinesBy [ formatter printHeaderLinesBy: #(1 1 2 2). self assert: command outStream contents equals: (String streamContents: [:aStream | aStream nextPutAll: '--*-*-*--*--'; newLine]). ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testPrintHeaderLinesByNoSequence [ "formatted header line should not contain sequence column" @@ -173,14 +200,14 @@ ConsoleListFormatterTest >> testPrintHeaderLinesByNoSequence [ self assert: command outStream contents equals: (String streamContents: [:aStream | aStream nextPutAll: '--*--'; newLine]). ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testPrintLineSized [ formatter printLineSized: 5. self assert: command outStream contents equals: '-----'. ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testPrintListAsSton [ | domainObjects deserialized | @@ -194,7 +221,7 @@ ConsoleListFormatterTest >> testPrintListAsSton [ self assert: deserialized first class equals: PhLImageMock. ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testPrintListShouldPrintAttributesTableWhenStonAndRowModesDisabled [ | tableModeString | formatter attributeLabels: #('Value' 'Squared' 'Raised to 3'). @@ -213,7 +240,7 @@ ConsoleListFormatterTest >> testPrintListShouldPrintAttributesTableWhenStonAndRo self assert: formatter outStream contents equals: tableModeString ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testPrintListShouldPrintAttributesTableWhenStonDisabledAndRowModeEnabled [ | rowModeString | @@ -235,7 +262,7 @@ ConsoleListFormatterTest >> testPrintListShouldPrintAttributesTableWhenStonDisab self assert: formatter outStream contents equals: rowModeString ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testPrintOneAttrPerRow [ |expectedString| formatter attributeLabels: #('Value' 'Squared' 'Raised to 3'). @@ -262,7 +289,7 @@ ConsoleListFormatterTest >> testPrintOneAttrPerRow [ self assert: formatter outStream contents equals: expectedString. ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testPrintOneAttrPerRowNoSequence [ |expectedString| "row output should not contain sequence number" @@ -281,7 +308,7 @@ ConsoleListFormatterTest >> testPrintOneAttrPerRowNoSequence [ self assert: formatter outStream contents equals: expectedString. ] -{ #category : #test } +{ #category : #tests } ConsoleListFormatterTest >> testPrintRowValuesBy [ formatter printRowValues: #('One' 'Two' 'Three') by: #(5 3 5). @@ -294,3 +321,16 @@ ConsoleListFormatterTest >> testPrintRowValuesBy [ nextPutAll: 'One *Two*Three'; newLine ]) ] + +{ #category : #tests } +ConsoleListFormatterTest >> testTableColumnWidthLimit [ + + | size short longer longest| + short := 'short'. + longer := 'more long text'. + longest := 'some very very very very very very very long string exceeding column width limit'. + size := formatter getMaxPrintStringWidthFor: {longer. longest. short.} printBlock: [ :aStr | aStr asString ]. + + "longest string exceeds the table column width limit, so the maximum column size should be equal to that limit" + self assert: size equals: formatter tableColumnWidthLimit. +] diff --git a/src/PharoLauncher-CLI-Tests/PhLCliCommandTest.class.st b/src/PharoLauncher-CLI-Tests/PhLCliCommandTest.class.st index ca00d089..cb1d6ea4 100644 --- a/src/PharoLauncher-CLI-Tests/PhLCliCommandTest.class.st +++ b/src/PharoLauncher-CLI-Tests/PhLCliCommandTest.class.st @@ -73,19 +73,12 @@ PhLCliCommandTest >> testExecuteLauncherCommandToPrintHelp [ ] { #category : #tests } -PhLCliCommandTest >> testExecuteOSShellCommand [ - - "nothing is executed" - self assert: PhLCliCommand new executeOSShellCommand isEmptyOrNil. +PhLCliCommandTest >> testExecuteLauncherCommandToPrintVersion [ + |expectedPrintout| + expectedPrintout := PhLAboutCommand new launcherVersion. -] + self assertCommand: #('launcher' '--version') toPrintHelpWith: expectedPrintout. -{ #category : #tests } -PhLCliCommandTest >> testExecuteOSShellCommandWithArgs [ - |aCmd| - aCmd := PhLCliCommand new. - self deny: (aCmd executeOSShellCommandWithArgs: #('ls')) isEmptyOrNil. - self should: [aCmd executeOSShellCommandWithArgs: #('bleh')] raise: PhLProcessCommandError description: 'Invoking invalid OS shell command should end up with domain error exception: PHLProcessCommandError'. ] { #category : #tests } diff --git a/src/PharoLauncher-CLI-Tests/PhLImageCreateCliCommandTest.class.st b/src/PharoLauncher-CLI-Tests/PhLImageCreateCliCommandTest.class.st index 410600e7..7f8e020a 100644 --- a/src/PharoLauncher-CLI-Tests/PhLImageCreateCliCommandTest.class.st +++ b/src/PharoLauncher-CLI-Tests/PhLImageCreateCliCommandTest.class.st @@ -26,6 +26,14 @@ PhLImageCreateCliCommandTest >> addTemplateNamed: aName inCategory: aCategoryNam inCategory: aCategoryName ] +{ #category : #adding } +PhLImageCreateCliCommandTest >> addTemplateNamed: aName shortName: aShortName inCategory: aCategoryName [ + ^ self launcherModel templateRepository + createTemplateNamed: aName + shortName: aShortName + inCategory: aCategoryName +] + { #category : #instance } PhLImageCreateCliCommandTest >> defaultTemplateCategoryName [ ^ 'Official distributions' @@ -53,6 +61,61 @@ PhLImageCreateCliCommandTest >> testCreateImageShouldSucceed [ self assertSuccess. self assert: self imageRepository imagesName equals: #( 'myImage1' 'myImage3' 'myImage2' ) asSet. + self assert: (self imageRepository imageNamed: 'myimage3') isLaunched +] + +{ #category : #tests } +PhLImageCreateCliCommandTest >> testCreateImageWithDevFlagUsesDevImage [ + | template devTemplate | + self addTemplateCategoryNamed: self defaultTemplateCategoryName. + self addTemplateNamed: 'Pharo 9 64bit stable' inCategory: self defaultTemplateCategoryName. + devTemplate := self addTemplateNamed: 'Pharo 10 64bit (development version, latest)' inCategory: self defaultTemplateCategoryName. + context arguments: #('launcher' 'image' 'create' '--dev' 'myImage'). + + template := context command findTemplate. + + self assert: template equals: devTemplate +] + +{ #category : #tests } +PhLImageCreateCliCommandTest >> testCreateImageWithNoFlagUsesDefaultImage [ + | template stableTemplate | + self addTemplateCategoryNamed: self defaultTemplateCategoryName. + stableTemplate := self addTemplateNamed: 'Pharo 9 64bit stable' inCategory: self defaultTemplateCategoryName. + self addTemplateNamed: 'Pharo 10 64bit (development version)' inCategory: self defaultTemplateCategoryName. + context arguments: {'launcher' . 'image' . 'create' . 'myImage'}. + + template := context command findTemplate. + + self assert: template equals: stableTemplate +] + +{ #category : #tests } +PhLImageCreateCliCommandTest >> testCreateImageWithNoFlagUsesUserDefaultImageWhenSpecified [ + | template devTemplate | + + context pharoLauncherModel configuration: + (context pharoLauncherModel configuration + defaultTemplate: #dev; + yourself). + self addTemplateCategoryNamed: self defaultTemplateCategoryName. + self addTemplateNamed: 'Pharo 9 64bit stable' inCategory: self defaultTemplateCategoryName. + devTemplate := self addTemplateNamed: 'Pharo 10 64bit (development version, latest)' inCategory: self defaultTemplateCategoryName. + context arguments: {'launcher' . 'image' . 'create' . 'myImage'}. + + template := context command findTemplate. + + self assert: template equals: devTemplate +] + +{ #category : #tests } +PhLImageCreateCliCommandTest >> testCreateImageWithNoLaunchFlagShouldNotLaunchImage [ + self addLocalTemplateNamed: 'fakeTemplate'. + + self runCommand: {'launcher' . 'image' . 'create' . 'myImage' . '--no-launch' . '--templateName'. 'fakeTemplate' . '--templateCategory' . self templateRepository localTemplatesGroupName}. + + self assertSuccess. + self deny: (self imageRepository imageNamed: 'myimage') isLaunched ] { #category : #tests } @@ -121,3 +184,34 @@ PhLImageCreateCliCommandTest >> testCreateImageWrongCategoryNameShouldRaiseError self assert: (self errorString includesSubstring: 'wrong category name not found'). ] + +{ #category : #tests } +PhLImageCreateCliCommandTest >> testTemplateCanBeFoundByShortName [ + + | createdTemplate foundTemplate | + + self addTemplateCategoryNamed: self defaultTemplateCategoryName. + createdTemplate := self addTemplateNamed: 'fakeTemplate' shortName: 'foo' inCategory: self defaultTemplateCategoryName. + context arguments: {'launcher' . 'image' . 'create' . 'myImage3' . '--templateName'. 'foo' }. + context match. + + foundTemplate := context command findUserTemplate. + + self assert: foundTemplate equals: createdTemplate +] + +{ #category : #tests } +PhLImageCreateCliCommandTest >> testTemplateIsFirstSearchByName [ + + | createdTemplate foundTemplate | + + self addTemplateCategoryNamed: self defaultTemplateCategoryName. + createdTemplate := self addTemplateNamed: 'fakeTemplate' shortName: 'foo' inCategory: self defaultTemplateCategoryName. + self addTemplateNamed: 'foo' inCategory: self defaultTemplateCategoryName. + context arguments: {'launcher' . 'image' . 'create' . 'myImage3' . '--templateName'. 'fakeTemplate' }. + context match. + + foundTemplate := context command findUserTemplate. + + self assert: foundTemplate equals: createdTemplate +] diff --git a/src/PharoLauncher-CLI-Tests/PhLImageCreateFromPullRequestCliCommandTest.class.st b/src/PharoLauncher-CLI-Tests/PhLImageCreateFromPullRequestCliCommandTest.class.st index d5156b51..7520e9a3 100644 --- a/src/PharoLauncher-CLI-Tests/PhLImageCreateFromPullRequestCliCommandTest.class.st +++ b/src/PharoLauncher-CLI-Tests/PhLImageCreateFromPullRequestCliCommandTest.class.st @@ -11,7 +11,9 @@ PhLImageCreateFromPullRequestCliCommandTest >> testExecuteFromPR [ command := (context arguments: #('launcher' 'image' 'create' 'fromPR' '9588')) command. command imageFinderClass: PhLImageFinderStub. + command execute. + self assert: self errorString isEmpty. self assert: (self outputString includesSubstring: 'PR-9588'). diff --git a/src/PharoLauncher-CLI-Tests/PhLImageCreateFromRemoteRepoCliCommandTest.class.st b/src/PharoLauncher-CLI-Tests/PhLImageCreateFromRemoteRepoCliCommandTest.class.st index f8d1edbf..c8478110 100644 --- a/src/PharoLauncher-CLI-Tests/PhLImageCreateFromRemoteRepoCliCommandTest.class.st +++ b/src/PharoLauncher-CLI-Tests/PhLImageCreateFromRemoteRepoCliCommandTest.class.st @@ -75,14 +75,21 @@ PhLImageCreateFromRemoteRepoCliCommandTest >> testValidCreateFromRemoteRepoWithA { #category : #tests } PhLImageCreateFromRemoteRepoCliCommandTest >> testValidateRepoFullName [ - | commandSpec validRepoNames | + | commandSpec validRepoNames invalidRepoName createCommand | commandSpec := PhLImageCreateFromRemoteRepoCliCommand asCliCommand. - validRepoNames := #('owner/project' 'owner/project:branch' 'owner/some-project:feature/branch-name'). + validRepoNames := #('owner/project' 'owner/project:branch' 'owner/some-project:feature/branch-name' 'owner/project:v1' 'owner/project:v1.1' 'owner/project:v1.1a' 'owner/project:V1.1.1a' 'owner/project:1.0-RC-somecomment'). validRepoNames do: [:repoName | - |createCommand| - createCommand := (commandSpec activationWith: { 'fromRepo'. repoName. } asArray) command. - createCommand validateRepoFullName - ] + createCommand := (commandSpec activationWith: { 'fromRepo'. repoName }) command. + self + assert: createCommand isValidRepoFullName + description: 'Valid repository name not validated: ', repoName. + ]. + + invalidRepoName := 'owner/project:'. + createCommand := (commandSpec activationWith: { 'fromRepo'. invalidRepoName }) command. + self + deny: createCommand isValidRepoFullName + description: 'Invalid repository name validated: ', invalidRepoName. ] diff --git a/src/PharoLauncher-CLI-Tests/PhLImageListCliCommandTest.class.st b/src/PharoLauncher-CLI-Tests/PhLImageListCliCommandTest.class.st index e19b3ace..cac5ab3f 100644 --- a/src/PharoLauncher-CLI-Tests/PhLImageListCliCommandTest.class.st +++ b/src/PharoLauncher-CLI-Tests/PhLImageListCliCommandTest.class.st @@ -39,8 +39,8 @@ PhLImageListCliCommandTest >> testListImageShouldSucceed [ self runCommand: #('launcher' 'image' 'list' '--brief' '--delimiter' '+'). self assertSuccess. - self assert: (self outputString includesSubstring:'1 +myImage1'). - self assert: (self outputString includesSubstring:'2 +myImage2'). + self assert: (self outputString includesSubstring:' +myImage1'). + self assert: (self outputString includesSubstring:' +myImage2'). ] { #category : #tests } @@ -53,19 +53,20 @@ PhLImageListCliCommandTest >> testListImageShouldSucceedOutputInSTON [ self assertSuccess. images := STON fromString: self outputString. - self assert: images size equals: 2. - self assert: images first name equals: 'myImage1'. + self + assertCollection: (images collect: #name) + hasSameElements: #('myImage1' 'myImage2'). ] { #category : #tests } -PhLImageListCliCommandTest >> testListImageWithImageNameShouldSucceed [ +PhLImageListCliCommandTest >> testListImageWithImageNameFilterShouldSucceed [ self addImageNamed: 'myImage1'. self addImageNamed: 'myImage2'. self addImageNamed: 'shouldNotBeListed'. self addImageNamed: 'myImage3'. - self runCommand: #('launcher' 'image' 'list' '--name' 'myImage'). + self runCommand: #('launcher' 'image' 'list' '--nameFilter' 'myImage'). self assertSuccess. self assert: (self outputString includesSubstring:'myImage1'). diff --git a/src/PharoLauncher-CLI-Tests/PhLImageProcessListCliCommandTest.class.st b/src/PharoLauncher-CLI-Tests/PhLImageProcessListCliCommandTest.class.st deleted file mode 100644 index 973b41b8..00000000 --- a/src/PharoLauncher-CLI-Tests/PhLImageProcessListCliCommandTest.class.st +++ /dev/null @@ -1,32 +0,0 @@ -" -A PhLImageProcessListCliCommandTest is a test class for testing the behavior of PhLImageProcessListCliCommand -" -Class { - #name : #PhLImageProcessListCliCommandTest, - #superclass : #PhLImageCliCommandTest, - #category : #'PharoLauncher-CLI-Tests' -} - -{ #category : #tests } -PhLImageProcessListCliCommandTest >> testExecute [ - - self runCommand: #('launcher' 'image' 'processList'). - - self assertSuccess. - - "either there isn't running any image (except currently running launcher) or some image is running (cotaining Pharo term in image arguement of VM path" - self assert: (self outputString isEmpty or: [ self outputString includesSubstring: 'Pharo']) -] - -{ #category : #test } -PhLImageProcessListCliCommandTest >> testOsShellArgArray [ - - |processListCmd argArray| - processListCmd := PhLImageProcessListCliCommand new. - argArray := processListCmd osShellArgArray. - - "test whether current PID of vm is filtered from list" - - self assert: (argArray third includesSubstring: 'pgrep'). - self assert: (argArray third includesSubstring: ('grep -v ', (processListCmd currentVMPid asString))). -] diff --git a/src/PharoLauncher-CLI-Tests/PhLProcessCliCommandTest.class.st b/src/PharoLauncher-CLI-Tests/PhLProcessCliCommandTest.class.st new file mode 100644 index 00000000..0b31fbab --- /dev/null +++ b/src/PharoLauncher-CLI-Tests/PhLProcessCliCommandTest.class.st @@ -0,0 +1,27 @@ +Class { + #name : #PhLProcessCliCommandTest, + #superclass : #PhLCliCommandTest, + #category : #'PharoLauncher-CLI-Tests' +} + +{ #category : #tests } +PhLProcessCliCommandTest >> testExecuteOSShellCommand [ + + "nothing is executed" + self assert: PhLProcessCliCommand new executeOSShellCommand isEmptyOrNil. + +] + +{ #category : #tests } +PhLProcessCliCommandTest >> testExecuteOSShellCommandWithArgs [ + + | aCmd | + aCmd := PhLProcessCliCommand new. + + self deny: + (aCmd executeOSShellCommandWithArgs: #( 'ls' )) isEmptyOrNil. + self + should: [ aCmd executeOSShellCommandWithArgs: #( 'non-existing-command' ) ] + raise: PhLProcessCommandError + description: 'Invoking invalid OS shell command should end up with domain error exception: PHLProcessCommandError' +] diff --git a/src/PharoLauncher-CLI-Tests/PhLImageKillCliCommandTest.class.st b/src/PharoLauncher-CLI-Tests/PhLProcessKillCliCommandTest.class.st similarity index 57% rename from src/PharoLauncher-CLI-Tests/PhLImageKillCliCommandTest.class.st rename to src/PharoLauncher-CLI-Tests/PhLProcessKillCliCommandTest.class.st index 7ed9e08a..3b917af2 100644 --- a/src/PharoLauncher-CLI-Tests/PhLImageKillCliCommandTest.class.st +++ b/src/PharoLauncher-CLI-Tests/PhLProcessKillCliCommandTest.class.st @@ -2,68 +2,71 @@ A PhLImageKillCliCommandTest is a test class for testing the behavior of PhLImageKillCliCommand " Class { - #name : #PhLImageKillCliCommandTest, - #superclass : #PhLImageCliCommandTest, + #name : #PhLProcessKillCliCommandTest, + #superclass : #PhLProcessCliCommandTest, #category : #'PharoLauncher-CLI-Tests' } { #category : #tests } -PhLImageKillCliCommandTest >> testHasAllFlag [ +PhLProcessKillCliCommandTest >> testHasAllFlag [ | killCliCommand | - killCliCommand := (PhLImageKillCliCommand asCliCommand activationWith: #('kill' '--all')) command. + killCliCommand := (PhLProcessKillCliCommand asCliCommand activationWith: #('kill' '--all')) command. self assert: killCliCommand hasAllFlag. - killCliCommand := (PhLImageKillCliCommand asCliCommand activationWith: #('kill' 'someImageName')) command. + killCliCommand := (PhLProcessKillCliCommand asCliCommand activationWith: #('kill' 'someImageName')) command. self deny: killCliCommand hasAllFlag. ] { #category : #tests } -PhLImageKillCliCommandTest >> testKillArgString [ +PhLProcessKillCliCommandTest >> testKillArgString [ | killCliCommand aResult | - killCliCommand := (PhLImageKillCliCommand asCliCommand activationWith: #('kill' 'someImage.image')) command. + killCliCommand := (PhLProcessKillCliCommand asCliCommand activationWith: #('kill' 'someImage.image')) command. aResult := killCliCommand killArgString. "test if command includes grep of image name" self assert: (aResult includesSubstring: 'grep someImage.image'). - "test whether current PID of vm is filtered from list" - self assert: (aResult includesSubstring: ('grep -v ', (killCliCommand currentVMPid asString))). - + self assert: (aResult includesSubstring: ('grep -v ', (killCliCommand currentVMPid asString))). "avoid doubling pipes in cascading" self deny: (aResult includesSubstring: '||'). +] + +{ #category : #tests } +PhLProcessKillCliCommandTest >> testKillArgStringWithAllFlag [ + + | killCliCommand aResult | - "test same method with --all argument present" - killCliCommand := (PhLImageKillCliCommand asCliCommand activationWith: #('kill' '--all')) command. + killCliCommand := (PhLProcessKillCliCommand asCliCommand activationWith: #('kill' '--all')) command. aResult := killCliCommand killArgString. "grep of image name shound not be included anymore" self deny: (aResult includesSubstring: 'grep someImage.image'). - "test whether current PID of vm is filtered from list" self assert: (aResult includesSubstring: ('grep -v ', (killCliCommand currentVMPid asString))). ] { #category : #tests } -PhLImageKillCliCommandTest >> testMissingImageName [ - self runCommand: #('launcher' 'image' 'kill'). +PhLProcessKillCliCommandTest >> testMissingImageName [ + self runCommand: #('launcher' 'process' 'kill'). + self assertFailure. self assert: ( self errorString includesSubstring: 'specify the local image name to kill it process') ] { #category : #tests } -PhLImageKillCliCommandTest >> testOsShellArgArray [ +PhLProcessKillCliCommandTest >> testOsShellArgArray [ | killCliCommand result| - - killCliCommand := (PhLImageKillCliCommand asCliCommand activationWith: #('kill' 'someImageName')) command. + killCliCommand := (PhLProcessKillCliCommand asCliCommand activationWith: #('kill' 'someImageName')) command. + result := killCliCommand osShellArgArray. self assert: (result first includesSubstring: 'kill'). diff --git a/src/PharoLauncher-CLI-Tests/PhLProcessListCliCommand.extension.st b/src/PharoLauncher-CLI-Tests/PhLProcessListCliCommand.extension.st new file mode 100644 index 00000000..fdd46577 --- /dev/null +++ b/src/PharoLauncher-CLI-Tests/PhLProcessListCliCommand.extension.st @@ -0,0 +1,7 @@ +Extension { #name : #PhLProcessListCliCommand } + +{ #category : #'*PharoLauncher-CLI-Tests' } +PhLProcessListCliCommand >> shellOutput: aString [ + + shellOutput := aString +] diff --git a/src/PharoLauncher-CLI-Tests/PhLProcessListCliCommandTest.class.st b/src/PharoLauncher-CLI-Tests/PhLProcessListCliCommandTest.class.st new file mode 100644 index 00000000..aab2b682 --- /dev/null +++ b/src/PharoLauncher-CLI-Tests/PhLProcessListCliCommandTest.class.st @@ -0,0 +1,58 @@ +" +A PhLImageProcessListCliCommandTest is a test class for testing the behavior of PhLImageProcessListCliCommand +" +Class { + #name : #PhLProcessListCliCommandTest, + #superclass : #PhLProcessCliCommandTest, + #category : #'PharoLauncher-CLI-Tests' +} + +{ #category : #tests } +PhLProcessListCliCommandTest >> testExecute [ + + self runCommand: #('launcher' 'process' 'list'). + + self assertSuccess. + + "either there isn't running any image (except currently running launcher) or some image is running (cotaining Pharo term in image arguement of VM path" + self assert: (self outputString isEmpty or: [ self outputString includesSubstring: 'Pharo' caseSensitive: false]) +] + +{ #category : #tests } +PhLProcessListCliCommandTest >> testImageProcesListFrom [ + + | processListCmd resultArray | + processListCmd := PhLProcessListCliCommand new. + processListCmd shellOutput: (String streamContents: [: aStream | + aStream + nextPutAll: '933 /tmp/PhLLaunchImageTest.61d1f200-02cc-0d00-88d2-05d60e98deae/110-x64/pharo /tmp/Yann-Gaël Bérès.61d1f200-02cc-0d00-88d2-05d60e98deae/PharoLauncher.image'; + nextPutAll: OSPlatform current lineEnding; + nextPutAll: '1974 /tmp/PhLLaunchImageTest.bb602801-02cc-0d00-88d6-4ed30e98deae/110-x64/pharo /tmp/Yann-Gaël Bérès.bb602801-02cc-0d00-88d6-4ed30e98deae/PharoLauncher.image'; + nextPutAll: OSPlatform current lineEnding; + nextPutAll: '2021 /home/runner/Pharo/vms/110-x64/lib/pharo --headless /tmp/pharo-launcher-tests-launch-image-command.a59b0202-02cc-0d00-88da-288c0e98deae/PharoLauncher.image --no-quit'; + nextPutAll: OSPlatform current lineEnding; + nextPutAll: '2048 /home/runner/Pharo/vms/110-x64/lib/pharo --headless /tmp/pharo-launcher-tests-launch-image-from-disk-command.509e2802-02cc-0d00-88e0-81d90e98deae/PharoLauncher.image --no-quit'; + nextPutAll: OSPlatform current lineEnding; + nextPutAll: '2304 /home/runner/Pharo/vms/100-x64/lib/pharo --headless /home/runner/Pharo/images/PhLTestImage/PhLTestImage.image --no-quit '; + nextPutAll: OSPlatform current lineEnding; + nextPutAll: '57499 /Users/dbajger/Documents/Pharo/vms/110-x64/Pharo.app/Contents/MacOS/Pharo /Users/dbajger/Documents/Pharo/images/P11-launcher-dev/P11-launcher-dev.image' ]). + + "each of string lines above represents information about one Pharo process, so there should be 6 processes (PhLImageProcess instances) determined from these lines" + resultArray := processListCmd imageProcesList. + + self assert: resultArray size equals: 6. + +] + +{ #category : #tests } +PhLProcessListCliCommandTest >> testOsShellArgArray [ + + | processListCmd argArray | + processListCmd := PhLProcessListCliCommand new. + argArray := processListCmd osShellArgArray. + + "test whether current PID of vm is filtered from list" + + self assert: (argArray first includesSubstring: 'pgrep'). + self assert: (argArray first includesSubstring: 'grep -v ' , processListCmd currentVMPid asString) +] diff --git a/src/PharoLauncher-CLI-Tests/PharoLauncherCLIConfigurationTest.class.st b/src/PharoLauncher-CLI-Tests/PharoLauncherCLIConfigurationTest.class.st index 5f740aad..7ae16a21 100644 --- a/src/PharoLauncher-CLI-Tests/PharoLauncherCLIConfigurationTest.class.st +++ b/src/PharoLauncher-CLI-Tests/PharoLauncherCLIConfigurationTest.class.st @@ -108,16 +108,16 @@ PharoLauncherCLIConfigurationTest >> testGetConfigurationWhenInvalidConfiguratio ] { #category : #tests } -PharoLauncherCLIConfigurationTest >> testProcessWithExplicitWorkingDirectory [ - | dir config configurator | - dir := root / 'foo' / 'bar'. - config := PhLLaunchConfiguration new - workingDirectory: dir. - configurator := PhLLaunchImageProcessConfigurator new - launchConfiguration: config; - yourself. +PharoLauncherCLIConfigurationTest >> testGetStableTemplateWhenGivingWrongDefaultTemplateValue [ + + | config deserializeConfig | + config := PharoLauncherCLIConfiguration new. + self assert: config defaultTemplate equals: #stable. - self assert: configurator workingDirectory equals: dir + config defaultTemplate: #foo. + deserializeConfig := STON fromString: (STON toString: config). + self assert: deserializeConfig defaultTemplate equals: #stable. + ] { #category : #tests } diff --git a/src/PharoLauncher-CLI-Tests/StringTest.extension.st b/src/PharoLauncher-CLI-Tests/StringTest.extension.st new file mode 100644 index 00000000..74e5a5e7 --- /dev/null +++ b/src/PharoLauncher-CLI-Tests/StringTest.extension.st @@ -0,0 +1,13 @@ +Extension { #name : #StringTest } + +{ #category : #'*PharoLauncher-CLI-Tests' } +StringTest >> testShortenTo [ + |shortened| + shortened := String new shortForm. + self assert: ('ABCDEF' shortenTo: 0) equals: shortened. + self assert: ('ABCDEF' shortenTo: 5) equals: shortened. + self assert: ('ABCDEF' shortenTo: 6) equals: 'ABCDEF'. + self assert: ('ABCDEF' shortenTo: 7) equals: 'ABCDEF'. + self assert: ('ABCDEFGHIJ' shortenTo: 9) equals: 'A', shortened, 'HIJ'. + self assert: ('ABCDEFGHIJK' shortenTo: 10) equals: 'AB', shortened, 'IJK'. +] diff --git a/src/PharoLauncher-CLI/ConsoleListFormatter.class.st b/src/PharoLauncher-CLI/ConsoleListFormatter.class.st index ad7ecd87..ddbee4db 100644 --- a/src/PharoLauncher-CLI/ConsoleListFormatter.class.st +++ b/src/PharoLauncher-CLI/ConsoleListFormatter.class.st @@ -33,7 +33,8 @@ Class { 'outStream', 'outputAsSton', 'printSequence', - 'rowMode' + 'rowMode', + 'defaultValue' ], #category : #'PharoLauncher-CLI-Utility' } @@ -121,7 +122,15 @@ ConsoleListFormatter >> domainObjects [ { #category : #'accessing - public' } ConsoleListFormatter >> domainObjects: anObjects [ - domainObjects := anObjects + domainObjects := anObjects. + defaultValue := nil. +] + +{ #category : #'accessing - public' } +ConsoleListFormatter >> domainObjects: someObjects defaultValue: anObject [ + + domainObjects := someObjects. + defaultValue := anObject. ] { #category : #private } @@ -139,10 +148,28 @@ ConsoleListFormatter >> getColumnWidthsFrom: someObjects [ ConsoleListFormatter >> getMaxPrintStringWidthFor: someObjects printBlock: printBlock [ "evaluate print block and obtain string size, return max value from collection" - ^ (someObjects collect: [ :item | (printBlock value: item) size ]) + ^ (someObjects collect: [ :item | (printBlock value: item) size min: self tableColumnWidthLimit ]) max ] +{ #category : #testing } +ConsoleListFormatter >> hasDefaultValue [ + + ^ defaultValue notNil +] + +{ #category : #private } +ConsoleListFormatter >> indexColumnDefaultSize [ + ^ 2 +] + +{ #category : #private } +ConsoleListFormatter >> indexColumnSize [ + ^ self hasDefaultValue + ifTrue: [ self indexColumnDefaultSize + 1 ] + ifFalse: [ self indexColumnDefaultSize ] +] + { #category : #'accessing - command' } ConsoleListFormatter >> outStream [ @@ -168,44 +195,57 @@ ConsoleListFormatter >> outputAsSton: aBoolean [ ] { #category : #private } -ConsoleListFormatter >> printAttributeHeaders: labels by: colWidths [ +ConsoleListFormatter >> printAttributeHeaders: labels by: columnWidths [ "print header labels and header line" "print sequence nr. eventually" self printSequence ifTrue: [ - self printCell: '#' width: 2. + self printCell: '#' width: self indexColumnSize. self printDelimiter ]. - self printRowValues: labels by: colWidths. - self printHeaderLinesBy: colWidths. + self printRowValues: labels by: columnWidths. + self printHeaderLinesBy: columnWidths. ] { #category : #private } -ConsoleListFormatter >> printAttributeRows: someObjects by: colWidths [ +ConsoleListFormatter >> printAttributeRows: someObjects by: columnWidths [ someObjects withIndexDo: [:listedObject :idx| - self printCell: idx asString width: 2. + self hasDefaultValue ifTrue: [ self printDefaultValueMark: listedObject ]. + self printCell: idx asString width: self indexColumnDefaultSize. self printDelimiter. - self printRowValues: (self attributeValuesFrom: listedObject) by: colWidths + self printRowValues: (self attributeValuesFrom: listedObject) by: columnWidths ] ] { #category : #private } ConsoleListFormatter >> printAttributeTable [ - |colWidths | - colWidths := self getColumnWidthsFrom: self domainObjects. - "no header if brief print is enabled" - self briefPrint ifFalse: [self printAttributeHeaders: self attributeLabels by: colWidths]. - self printAttributeRows: self domainObjects by: colWidths. - + | columnWidths | + columnWidths := self getColumnWidthsFrom: self domainObjects. + "no header if brief print is enabled" + self briefPrint + ifFalse: [ self printAttributeHeaders: self attributeLabels by: columnWidths ]. + self printAttributeRows: self domainObjects by: columnWidths ] { #category : #private } ConsoleListFormatter >> printCell: aString width: widthSize [ + + |shortened| + shortened := widthSize isZero + ifTrue: [ aString ] + ifFalse: [ aString shortenTo: widthSize ]. + self outStream nextPutAll: (shortened padRightTo: widthSize) - self outStream nextPutAll: (aString padRightTo: widthSize) +] +{ #category : #private } +ConsoleListFormatter >> printDefaultValueMark: listedObject [ + + self outStream nextPut: (listedObject == defaultValue + ifTrue: [ $* ] + ifFalse: [ Character space ]) ] { #category : #private } @@ -215,15 +255,15 @@ ConsoleListFormatter >> printDelimiter [ ] { #category : #private } -ConsoleListFormatter >> printHeaderLinesBy: colWidths [ +ConsoleListFormatter >> printHeaderLinesBy: columnWidths [ "print header line" self printSequence ifTrue: [ - self printLineSized: 2. + self printLineSized: self indexColumnSize. self printDelimiter. ]. - colWidths withIndexDo: [:aWidth :idx| self printLineSized: aWidth. - idx = colWidths size ifFalse: [ self printDelimiter]]. + columnWidths withIndexDo: [:aWidth :idx| self printLineSized: aWidth. + idx = columnWidths size ifFalse: [ self printDelimiter]]. self outStream newLine. ] @@ -273,12 +313,11 @@ ConsoleListFormatter >> printOneAttrPerRow [ ] { #category : #private } -ConsoleListFormatter >> printRowValues: aStringColl by: colWidths [ +ConsoleListFormatter >> printRowValues: values by: columnWidths [ - "print string values by column widths" - aStringColl withIndexDo: [:aLabel :idx | - self printCell: aLabel width: (colWidths at: idx). - idx = aStringColl size ifFalse: [ self printDelimiter]. + values withIndexDo: [:aLabel :idx | + self printCell: aLabel width: (columnWidths at: idx). + idx = values size ifFalse: [ self printDelimiter]. ]. self outStream newLine. ] @@ -306,3 +345,10 @@ ConsoleListFormatter >> rowMode: aBool [ rowMode := aBool ] + +{ #category : #private } +ConsoleListFormatter >> tableColumnWidthLimit [ + + "this is max size of table column, in case value in cell is exceeded, it will be shortened to this limit" + ^ 75 +] diff --git a/src/PharoLauncher-CLI/MacOSPlatform.extension.st b/src/PharoLauncher-CLI/MacOSPlatform.extension.st new file mode 100644 index 00000000..d80de68d --- /dev/null +++ b/src/PharoLauncher-CLI/MacOSPlatform.extension.st @@ -0,0 +1,14 @@ +Extension { #name : #MacOSPlatform } + +{ #category : #'*PharoLauncher-CLI' } +MacOSPlatform >> processListArgs [ + + ^ 'pgrep -ai -f "pharo.*\.image" | xargs ps -o pid,args= -p | grep -v -e "PID"' + +] + +{ #category : #'*PharoLauncher-CLI' } +MacOSPlatform >> processStartDateArgs [ + + ^ 'LANG=C xargs -I{} date -jf "%a %b %d %H:%M:%S %Y" "{}" ''+%Y-%m-%d %H:%M:%S''' +] diff --git a/src/PharoLauncher-CLI/PhLAbstractTemplate.extension.st b/src/PharoLauncher-CLI/PhLAbstractTemplate.extension.st index ba807e22..2972c1e5 100644 --- a/src/PharoLauncher-CLI/PhLAbstractTemplate.extension.st +++ b/src/PharoLauncher-CLI/PhLAbstractTemplate.extension.st @@ -4,7 +4,7 @@ Extension { #name : #PhLAbstractTemplate } PhLAbstractTemplate class >> listPrintAttributeBlocks [ ^ {[:template | template name]. - [:template | template url]} + [:template | template url asString]} ] { #category : #'*PharoLauncher-CLI' } diff --git a/src/PharoLauncher-CLI/PhLCliCommand.class.st b/src/PharoLauncher-CLI/PhLCliCommand.class.st index 3b5a8b12..1d30a448 100644 --- a/src/PharoLauncher-CLI/PhLCliCommand.class.st +++ b/src/PharoLauncher-CLI/PhLCliCommand.class.st @@ -49,9 +49,10 @@ PhLCliCommand class >> addDelimiterFlagTo: aCommandSpec [ { #category : #'command line - arguments' } PhLCliCommand class >> addLauncherFlagsTo: aCommandSpec [ - "No positionals on root spec class - use on subclasses e.g.: aCommandSpec addFlag: #someFlag + "Only version flag to launcher commmand. + Use on subclasses e.g.: aCommandSpec addFlag: #someFlag " + self addVersionFlagTo: aCommandSpec ] { #category : #'command line - arguments' } @@ -94,6 +95,14 @@ PhLCliCommand class >> addStonFlagTo: aCommandSpec [ description: 'Prints information in STON format.' ] +{ #category : #'command line - arguments' } +PhLCliCommand class >> addVersionFlagTo: aCommandSpec [ + + aCommandSpec + addFlag: #version + description: 'Prints version of the Pharo Launcher.' +] + { #category : #'command line - converting' } PhLCliCommand class >> asCliCommand [ ^ self newLauncherCommandSpec: #launcher @@ -157,6 +166,7 @@ PhLCliCommand class >> raiseMissingDelimiter [ PhLCliCommand >> basicExecute [ "should be implemented on all sub-classed commands that have business logic, otherwise will print just help" + self hasVersionFlag ifTrue: [ ^ self printVersion ]. self printHelp ] @@ -178,10 +188,12 @@ PhLCliCommand >> cliFormatter: aFormatter [ cliFormatter := aFormatter ] -{ #category : #accessing } -PhLCliCommand >> currentVMPid [ - - ^ OSSVMProcess vmProcess pid +{ #category : #default } +PhLCliCommand >> defaultTemplate [ + + ^ self pharoLauncherModel defaultTemplate = #dev + ifTrue: [ self latestDevTemplate ] + ifFalse: [ self latestStableTemplate ] ] { #category : #default } @@ -220,21 +232,6 @@ PhLCliCommand >> execute [ ] ] -{ #category : #'command execution' } -PhLCliCommand >> executeOSShellCommand [ - - ^ self executeOSShellCommandWithArgs: self osShellArgArray -] - -{ #category : #'command execution' } -PhLCliCommand >> executeOSShellCommandWithArgs: argArray [ - -^ PhLProcessWrapper new - shellCommand; - addAllArguments: argArray; - runAndWaitWithStdOutput -] - { #category : #private } PhLCliCommand >> filterPrintAttributesFrom: attrCollection [ @@ -248,6 +245,12 @@ PhLCliCommand >> findLatestPharoStableVersionIn: aTemplateGroup [ ^ aTemplateGroup latestStableTemplate ] +{ #category : #'accessing arguments' } +PhLCliCommand >> hasVersionFlag [ + + ^ self hasFlag: #version +] + { #category : #accessing } PhLCliCommand >> imageRepository [ ^ self pharoLauncherModel imageRepository @@ -266,6 +269,30 @@ PhLCliCommand >> initialize [ self cliFormatter: (ConsoleListFormatter on: self). ] +{ #category : #default } +PhLCliCommand >> isDefaultTemplateCategory: aCategory ifTrue: trueBlock ifFalse: falseBlock [ + + [ aCategory == self defaultTemplateCategory + ifTrue: trueBlock + ifFalse: falseBlock ] + on: NotFound "default template category not found" + do: falseBlock +] + +{ #category : #default } +PhLCliCommand >> latestDevTemplate [ + + "from default 'Official distributions' obtain latest development template" + ^ self defaultTemplateCategory latestDevelopmentTemplate +] + +{ #category : #default } +PhLCliCommand >> latestStableTemplate [ + + "from default 'Official distributions' obtain latest Pharo version stable template" + ^ self defaultTemplateCategory latestStableTemplate +] + { #category : #printing } PhLCliCommand >> list: domainObjects [ @@ -274,6 +301,13 @@ PhLCliCommand >> list: domainObjects [ printList. ] +{ #category : #printing } +PhLCliCommand >> list: domainObjects default: defaultValue [ + self cliFormatter + domainObjects: domainObjects defaultValue: defaultValue; + printList. +] + { #category : #private } PhLCliCommand >> listPrintAttributeBlocks [ @@ -345,6 +379,12 @@ PhLCliCommand >> printSequence [ ^ true ] +{ #category : #printing } +PhLCliCommand >> printVersion [ + + self logInfoMessage: PhLAboutCommand new launcherVersion +] + { #category : #'accessing arguments' } PhLCliCommand >> rowMode [ diff --git a/src/PharoLauncher-CLI/PhLImageCliCommand.class.st b/src/PharoLauncher-CLI/PhLImageCliCommand.class.st index 9c336341..cff773ab 100644 --- a/src/PharoLauncher-CLI/PhLImageCliCommand.class.st +++ b/src/PharoLauncher-CLI/PhLImageCliCommand.class.st @@ -39,12 +39,6 @@ PhLImageCliCommand class >> raiseNewImageNotFound [ ^ NotFound signal: 'An argument is missing. Please specify the name for the new Pharo image.' ] -{ #category : #private } -PhLImageCliCommand >> checkOS [ - - OSPlatform current isWindows ifTrue: [ self raiseOperationNotSupported ] -] - { #category : #'find-select' } PhLImageCliCommand >> findByPath: anImageName [ (anImageName asFileReference exists @@ -81,12 +75,6 @@ PhLImageCliCommand >> modelClass [ ^ self class environment at: #PhLImage ] -{ #category : #'error signalling' } -PhLImageCliCommand >> raiseOperationNotSupported [ - - ^ PhLProcessCommandError signal: 'Launcher command currently not supported on OS Windows.' -] - { #category : #accessing } PhLImageCliCommand >> targetName [ diff --git a/src/PharoLauncher-CLI/PhLImageCreateCliCommand.class.st b/src/PharoLauncher-CLI/PhLImageCreateCliCommand.class.st index d37fd756..a64a8a28 100644 --- a/src/PharoLauncher-CLI/PhLImageCreateCliCommand.class.st +++ b/src/PharoLauncher-CLI/PhLImageCreateCliCommand.class.st @@ -34,9 +34,19 @@ Class { #category : #'PharoLauncher-CLI-Commands' } +{ #category : #'command line - arguments' } +PhLImageCreateCliCommand class >> addDevFlagTo: aCommandSpec [ + + aCommandSpec + addFlag: #'dev' + description: 'When flag is present, the last development image will be used as template. Will take precedence if templateName is specified.' +] + { #category : #'command line - arguments' } PhLImageCreateCliCommand class >> addLauncherFlagsTo: aCommandSpec [ + self addDevFlagTo: aCommandSpec. + self addNoLaunchFlagTo: aCommandSpec. self addTemplateNameFlagTo: aCommandSpec. self addTemplateCategoryFlagTo: aCommandSpec. ] @@ -59,6 +69,14 @@ PhLImageCreateCliCommand class >> addNewImageFlagTo: aCommandSpec [ positionalSpec: [ :positional | positional defaultValue: [ :arg :app | app implicitImageName ] ] ] +{ #category : #'command line - arguments' } +PhLImageCreateCliCommand class >> addNoLaunchFlagTo: aCommandSpec [ + + aCommandSpec + addFlag: #'no-launch' + description: 'When flag is present, the just created image will not be launched after its creation.' +] + { #category : #'command line - arguments' } PhLImageCreateCliCommand class >> addPharoVersionFlagTo: aCommandSpec [ @@ -74,17 +92,7 @@ PhLImageCreateCliCommand class >> addTemplateCategoryFlagTo: aCommandSpec [ aCommandSpec addFlag: #templateCategory description: 'Specifies the template category to search the target template.' - positionalSpec: [ :positional | positional defaultValue: [ :arg :app | app defaultTemplateCategoryName ]]. - -"^ (ClapFlag id: #templateCategory) - description: 'Specifies the template category to search the target template.'; - meaning: [ :arg :app | (arg at: #templateCategoryArg) value ]; - implicitMeaning: [ :arg :app | app defaultTemplateCategoryName ]; - add: ((ClapPositional id: #templateCategoryArg) - description: 'Template category argument.'; - meaning: [ :pos | pos word asSymbol . ]; - implicitMeaning: [ :arg :app | app defaultTemplateCategoryName]); - yourself" + positionalSpec: [ :positional | positional defaultValue: [ :arg :app | app defaultTemplateCategoryName ]] ] { #category : #'command line - arguments' } @@ -92,17 +100,7 @@ PhLImageCreateCliCommand class >> addTemplateNameFlagTo: aCommandSpec [ aCommandSpec addFlagWithPositional: #templateName - description: 'Template which will be used to create the image'. -" ^ (ClapFlag id: #templateName) - description: 'Template which will be used to create the image.'; - meaning: [ :arg :app | (arg at: #templateNameArg) value ]; - implicitMeaning: [ :arg :app | ]; - add: ((ClapPositional id: #templateNameArg) - description: 'Template name argument.'; - meaning: [ :pos | pos word asString ]; - implicitMeaning: [ :arg :app | NotFound signal: self missingTemplateNameArgMessage]); - yourself -" + description: 'Template which will be used to create the image' ] { #category : #'command line' } @@ -130,8 +128,11 @@ PhLImageCreateCliCommand class >> raiseMissingTemplateName [ { #category : #'command execution' } PhLImageCreateCliCommand >> basicExecute [ - - self findTemplateAndCreateImage + | image | + + image := self findTemplateAndCreateImage. + self shouldLaunchImage + ifTrue: [ image launch ] ] { #category : #'command execution' } @@ -148,12 +149,13 @@ PhLImageCreateCliCommand >> createImage: newImageName from: template [ { #category : #querying } PhLImageCreateCliCommand >> findTemplate [ + (self hasFlag: #dev) ifTrue: [ ^ self latestDevTemplate ]. "find template defined by user" (self hasFlag: #templateName) ifTrue: [ ^ self findUserTemplate ]. "otherwise latest stable Pharo version template" - ^ self latestStableTemplate + ^ self defaultTemplate ] { #category : #'command execution' } @@ -164,7 +166,15 @@ PhLImageCreateCliCommand >> findTemplateAndCreateImage [ ] { #category : #querying } -PhLImageCreateCliCommand >> findUserTemplate [ +PhLImageCreateCliCommand >> findUserTemplate [ + + ^ [ self findUserTemplateFromName ] + on: NotFound + do: [ self findUserTemplateFromShortName ] +] + +{ #category : #querying } +PhLImageCreateCliCommand >> findUserTemplateFromName [ ^ self templateRepository templateNamed: self templateName @@ -172,6 +182,15 @@ PhLImageCreateCliCommand >> findUserTemplate [ ] +{ #category : #querying } +PhLImageCreateCliCommand >> findUserTemplateFromShortName [ + + ^ self templateRepository + templateShortNamed: self templateName + inCategoryNamed: self templateCategory + +] + { #category : #accessing } PhLImageCreateCliCommand >> imageFinderClass [ @@ -202,20 +221,6 @@ PhLImageCreateCliCommand >> implicitPharoVersion [ ^ self imageFinderClass findLatestPharoDevelopmentVersion ] -{ #category : #default } -PhLImageCreateCliCommand >> latestDevTemplate [ - - "from default 'Official distributions' obtain latest development template" - ^ self defaultTemplateCategory latestDevelopmentTemplate -] - -{ #category : #default } -PhLImageCreateCliCommand >> latestStableTemplate [ - - "from default 'Official distributions' obtain latest Pharo version stable template" - ^ self defaultTemplateCategory latestStableTemplate -] - { #category : #logging } PhLImageCreateCliCommand >> logCannotFindTemplate: templateName [ @@ -251,12 +256,9 @@ PhLImageCreateCliCommand >> pharoVersionNumber [ ^ self positional: #pharoVersion ] -{ #category : #'command execution' } -PhLImageCreateCliCommand >> printSubCommandsHelp [ - - arguments positionalValues isEmpty ifTrue:[ - (ClapDocumenter on: self outStream) explain: arguments parent specification - ] +{ #category : #asserting } +PhLImageCreateCliCommand >> shouldLaunchImage [ + ^ (self hasFlag: #'no-launch') not ] { #category : #querying } diff --git a/src/PharoLauncher-CLI/PhLImageCreateFromRemoteRepoCliCommand.class.st b/src/PharoLauncher-CLI/PhLImageCreateFromRemoteRepoCliCommand.class.st index a40190dd..a5a17243 100644 --- a/src/PharoLauncher-CLI/PhLImageCreateFromRemoteRepoCliCommand.class.st +++ b/src/PharoLauncher-CLI/PhLImageCreateFromRemoteRepoCliCommand.class.st @@ -206,13 +206,16 @@ PhLImageCreateFromRemoteRepoCliCommand >> raiseRepoNameInvalid [ { #category : #private } PhLImageCreateFromRemoteRepoCliCommand >> regexForRepoName [ - |stringWithDash| - + |stringWithDash versionOrBranch| + "e.g. some-project-123" stringWithDash := '[\w]+-?[\w]+'. - "should match {alphanumeric-chars with dash}/{alphanumeric-chars with dash}:{feature}/{alphanumeric-chars with dash}" - ^ stringWithDash, '\/', stringWithDash, '(\:?', stringWithDash, '(\/', stringWithDash, ')?', ')?' + "e.g. v1.2.3b or 1.0-RC-somecomment" + versionOrBranch := '[a-zA-Z0-9_\-./]+$'. + + "should match {alphanumeric-chars with dash}/{alphanumeric-chars with dash}:{versionOrBranch})" + ^ '{dashString}\\/{dashString}(\\:?({versionOrBranchString}))' format: { 'dashString' -> stringWithDash. 'versionOrBranchString' -> versionOrBranch. } asDictionary. ] { #category : #private } diff --git a/src/PharoLauncher-CLI/PhLImageListCliCommand.class.st b/src/PharoLauncher-CLI/PhLImageListCliCommand.class.st index 0f875d8e..4b369fc0 100644 --- a/src/PharoLauncher-CLI/PhLImageListCliCommand.class.st +++ b/src/PharoLauncher-CLI/PhLImageListCliCommand.class.st @@ -17,8 +17,8 @@ Class { PhLImageListCliCommand class >> addLauncherFlagsTo: aCommandSpec [ aCommandSpec - addFlagWithPositional: #name - description: 'Determines the name of image (or its sub-part) to list local images.'. + addFlagWithPositional: #nameFilter + description: 'Images listing will be filtered by the provided name filter'. self addPrintFlagsTo: aCommandSpec. ] @@ -52,15 +52,15 @@ PhLImageListCliCommand >> imagesFromName: aSubtring [ PhLImageListCliCommand >> listImages [ | images | - images := (self hasFlag: #name) - ifTrue: [ self imagesFromName: self name ] + images := (self hasFlag: #nameFilter) + ifTrue: [ self imagesFromName: self nameFilter ] ifFalse: [ self imageRepository images ]. - self list: images + self list: (images sorted: [:a :b | b lastModification <= a lastModification]) ] { #category : #'accessing arguments' } -PhLImageListCliCommand >> name [ +PhLImageListCliCommand >> nameFilter [ - ^ self positional: #name + ^ self positional: #nameFilter ] diff --git a/src/PharoLauncher-CLI/PhLImagePackageCliCommand.class.st b/src/PharoLauncher-CLI/PhLImagePackageCliCommand.class.st index 513bf892..9a4eca08 100644 --- a/src/PharoLauncher-CLI/PhLImagePackageCliCommand.class.st +++ b/src/PharoLauncher-CLI/PhLImagePackageCliCommand.class.st @@ -107,7 +107,9 @@ PhLImagePackageCliCommand >> createDirectoryForImageToPack [ |aPath| aPath := self location , '/' , self image name. (self directoryAlreadyExists: aPath) ifTrue: [self raiseDirectoryAlreadyExists: aPath]. - ^ aPath asFileReference ensureCreateDirectory + ^ [aPath asFileReference ensureCreateDirectory] + on: PrimitiveFailed + do: [ self raiseCannotCreateDirectory: self location] ] { #category : #private } @@ -208,6 +210,12 @@ PhLImagePackageCliCommand >> location [ ^ self positional: #location ] +{ #category : #'error signalling' } +PhLImagePackageCliCommand >> raiseCannotCreateDirectory: aPath [ + + ^PhLCommandError signal: ('Cannot write to target directory: ''{1}'', please check write permissions.' format: { aPath }) +] + { #category : #'error signalling' } PhLImagePackageCliCommand >> raiseDirectoryAlreadyExists: aPath [ diff --git a/src/PharoLauncher-CLI/PhLImageProcess.extension.st b/src/PharoLauncher-CLI/PhLImageProcess.extension.st new file mode 100644 index 00000000..ffe2b8f5 --- /dev/null +++ b/src/PharoLauncher-CLI/PhLImageProcess.extension.st @@ -0,0 +1,8 @@ +Extension { #name : #PhLImageProcess } + +{ #category : #'*PharoLauncher-CLI' } +PhLImageProcess class >> newFrom: osOutputLine [ + + "initialize image process instance from line represented by OS command output line" + ^ (PhLProcessListEntry with: osOutputLine) asImageProcess +] diff --git a/src/PharoLauncher-CLI/PhLImageProcessListCliCommand.class.st b/src/PharoLauncher-CLI/PhLImageProcessListCliCommand.class.st deleted file mode 100644 index 0db24b10..00000000 --- a/src/PharoLauncher-CLI/PhLImageProcessListCliCommand.class.st +++ /dev/null @@ -1,48 +0,0 @@ -" -Command to list all the running images. -" -Class { - #name : #PhLImageProcessListCliCommand, - #superclass : #PhLImageCliCommand, - #category : #'PharoLauncher-CLI-Commands' -} - -{ #category : #'command line' } -PhLImageProcessListCliCommand class >> asCliCommand [ - ^ self newLauncherCommandSpec: #processList -] - -{ #category : #'command line' } -PhLImageProcessListCliCommand class >> launcherCmdDescription [ - - ^ 'Lists all running Pharo image processes.' -] - -{ #category : #'command execution' } -PhLImageProcessListCliCommand >> basicExecute [ - - "TODO rewrite this to more meaningful output with columns like PID, datetime started, vm name, image name" - "TODO: Win Powershell version should be something like this: Get-Process | Where-Object { $_.Path -like '*Pharo*' -and $_.Path -like '*.image*' -and $_.Id -ne 2232 } | Select-Object Id, Path, StartTime, CommandLine" - self checkOS. - self outStream - nextPutAll: self executeOSShellCommand. - ^ self context exitSuccess -] - -{ #category : #'command execution' } -PhLImageProcessListCliCommand >> execute [ - - "TODO rewrite this to more meaningful output with columns like PID, datetime started, vm name, image name" - "TODO: Win Powershell version should be something like this: Get-Process | Where-Object { $_.Path -like '*Pharo*' -and $_.Path -like '*.image*' -and $_.Id -ne 2232 } | Select-Object Id, Path, StartTime, CommandLine" - self checkOS. - self outStream - nextPutAll: self executeOSShellCommand. - ^ self context exitSuccess -] - -{ #category : #'command execution' } -PhLImageProcessListCliCommand >> osShellArgArray [ - - ^ Array with: 'echo' with: '-n' with: ('$(pgrep -a -f Pharo | grep ''.image'' | grep -v ''.bash''| grep -v {1})' format: {self currentVMPid asString}) - -] diff --git a/src/PharoLauncher-CLI/PhLImageRecreateCliCommand.class.st b/src/PharoLauncher-CLI/PhLImageRecreateCliCommand.class.st index ae265353..584e5074 100644 --- a/src/PharoLauncher-CLI/PhLImageRecreateCliCommand.class.st +++ b/src/PharoLauncher-CLI/PhLImageRecreateCliCommand.class.st @@ -13,7 +13,7 @@ PhLImageRecreateCliCommand class >> addLauncherPositionalsTo: aCommandSpec [ (aCommandSpec addPositional: #existingImageName description: 'Local image name to recreate.') - implicitMeaning: [:arg :app | app raiseMissingImageToRecreate] + implicitMeaning: [:arg :app | self raiseMissingImageToRecreate] ] { #category : #'command line' } diff --git a/src/PharoLauncher-CLI/PhLProcessCliCommand.class.st b/src/PharoLauncher-CLI/PhLProcessCliCommand.class.st new file mode 100644 index 00000000..4a32f8e6 --- /dev/null +++ b/src/PharoLauncher-CLI/PhLProcessCliCommand.class.st @@ -0,0 +1,64 @@ +" +I represent a Pharo process sub-command of Pharo Launcher. My responsibility is to take care of Pharo process sub-commands. + +I use: +- Pharo launcher root command to declare my other sub-commands. + +I declare: + +• list, kill + + +I execute: + +• just printing help about my sub-commands relevant for Pharo templates +" +Class { + #name : #PhLProcessCliCommand, + #superclass : #PhLCliCommand, + #category : #'PharoLauncher-CLI-Commands' +} + +{ #category : #'command line - converting' } +PhLProcessCliCommand class >> asCliCommand [ + ^ self newLauncherCommandSpec: #process +] + +{ #category : #'command line - description' } +PhLProcessCliCommand class >> launcherCmdDescription [ + + ^ 'All sub-commands related to Pharo processes.' +] + +{ #category : #private } +PhLProcessCliCommand >> checkOS [ + + OSPlatform current isWindows ifTrue: [ self raiseOperationNotSupported ] +] + +{ #category : #accessing } +PhLProcessCliCommand >> currentVMPid [ + + ^ OSSVMProcess vmProcess pid +] + +{ #category : #'command execution' } +PhLProcessCliCommand >> executeOSShellCommand [ + + ^ self executeOSShellCommandWithArgs: self osShellArgArray +] + +{ #category : #'command execution' } +PhLProcessCliCommand >> executeOSShellCommandWithArgs: argArray [ + +^ PhLProcessWrapper new + shellCommand; + addAllArguments: argArray; + runAndWaitWithStdOutput +] + +{ #category : #'error signalling' } +PhLProcessCliCommand >> raiseOperationNotSupported [ + + ^ PhLProcessCommandError signal: 'Launcher command currently not supported on OS Windows.' +] diff --git a/src/PharoLauncher-CLI/PhLImageKillCliCommand.class.st b/src/PharoLauncher-CLI/PhLProcessKillCliCommand.class.st similarity index 59% rename from src/PharoLauncher-CLI/PhLImageKillCliCommand.class.st rename to src/PharoLauncher-CLI/PhLProcessKillCliCommand.class.st index 29c8826f..c364a074 100644 --- a/src/PharoLauncher-CLI/PhLImageKillCliCommand.class.st +++ b/src/PharoLauncher-CLI/PhLProcessKillCliCommand.class.st @@ -1,14 +1,14 @@ " -Command to kill one image if given in option or all the images if the --all flag is set +Command to kill one image if given in option or all the images if the --all flag is set " Class { - #name : #PhLImageKillCliCommand, - #superclass : #PhLImageCliCommand, + #name : #PhLProcessKillCliCommand, + #superclass : #PhLProcessCliCommand, #category : #'PharoLauncher-CLI-Commands' } { #category : #'command line - arguments' } -PhLImageKillCliCommand class >> addLauncherFlagsTo: aCommandSpec [ +PhLProcessKillCliCommand class >> addLauncherFlagsTo: aCommandSpec [ aCommandSpec addFlag: #all @@ -16,7 +16,7 @@ PhLImageKillCliCommand class >> addLauncherFlagsTo: aCommandSpec [ ] { #category : #'command line - arguments' } -PhLImageKillCliCommand class >> addLauncherPositionalsTo: aCommandSpec [ +PhLProcessKillCliCommand class >> addLauncherPositionalsTo: aCommandSpec [ (aCommandSpec addPositional: #existingImageName @@ -24,39 +24,46 @@ PhLImageKillCliCommand class >> addLauncherPositionalsTo: aCommandSpec [ implicitMeaning: [ :arg :app | self raiseMissingImageToKill] ] -{ #category : #'command line' } -PhLImageKillCliCommand class >> asCliCommand [ +{ #category : #'command line - converting' } +PhLProcessKillCliCommand class >> asCliCommand [ ^ self newLauncherCommandSpec: #kill ] -{ #category : #'command line' } -PhLImageKillCliCommand class >> launcherCmdDescription [ +{ #category : #'command line - description' } +PhLProcessKillCliCommand class >> launcherCmdDescription [ ^ 'Kills the running process(es) of given local image.' ] { #category : #'error signalling' } -PhLImageKillCliCommand class >> raiseMissingImageToKill [ +PhLProcessKillCliCommand class >> raiseMissingImageToKill [ ^ NotFound signal: 'An argument is missing, please specify the local image name to kill it process.' ] { #category : #'command execution' } -PhLImageKillCliCommand >> basicExecute [ +PhLProcessKillCliCommand >> basicExecute [ "currently unsupported on Windows" self checkOS. + ^ self executeOSShellCommand ] -{ #category : #accessing } -PhLImageKillCliCommand >> hasAllFlag [ +{ #category : #testing } +PhLProcessKillCliCommand >> hasAllFlag [ ^ self hasFlag: #all ] +{ #category : #accessing } +PhLProcessKillCliCommand >> imageName [ + + ^ self positional: #existingImageName +] + { #category : #commands } -PhLImageKillCliCommand >> killArgString [ +PhLProcessKillCliCommand >> killArgString [ ^ String streamContents: [ :aStream | @@ -69,8 +76,11 @@ PhLImageKillCliCommand >> killArgString [ ] { #category : #'command execution' } -PhLImageKillCliCommand >> osShellArgArray [ +PhLProcessKillCliCommand >> osShellArgArray [ + "provide the command and its args in array" - "provide list of command and its args in array" - ^ Array with: 'kill' with: self killArgString with: '/dev/null' + ^ Array + with: 'kill' + with: self killArgString + with: '/dev/null' ] diff --git a/src/PharoLauncher-CLI/PhLProcessListCliCommand.class.st b/src/PharoLauncher-CLI/PhLProcessListCliCommand.class.st new file mode 100644 index 00000000..2b35956e --- /dev/null +++ b/src/PharoLauncher-CLI/PhLProcessListCliCommand.class.st @@ -0,0 +1,97 @@ +" +Command to list all the Pharo processes, i.e. all running Pharo images. +" +Class { + #name : #PhLProcessListCliCommand, + #superclass : #PhLProcessCliCommand, + #instVars : [ + 'shellOutput' + ], + #category : #'PharoLauncher-CLI-Commands' +} + +{ #category : #'command line - arguments' } +PhLProcessListCliCommand class >> addLauncherFlagsTo: aCommandSpec [ + + self addPrintFlagsTo: aCommandSpec. +] + +{ #category : #'command line - converting' } +PhLProcessListCliCommand class >> asCliCommand [ + ^ self newLauncherCommandSpec: #list +] + +{ #category : #'command line - description' } +PhLProcessListCliCommand class >> launcherCmdDescription [ + + ^ 'Lists all running Pharo image processes.' +] + +{ #category : #'command execution' } +PhLProcessListCliCommand >> basicExecute [ + |processList| + "TODO: Win Powershell version should be something like this: Get-Process | Where-Object { $_.Path -like '*Pharo*' -and $_.Path -like '*.image*' -and $_.Id -ne 2232 } | Select-Object Id, Path, StartTime, CommandLine" + self checkOS. + + "trim trailing newlines" + shellOutput := self executeOSShellCommand trim. + processList := self imageProcesList. + self list: processList +] + +{ #category : #private } +PhLProcessListCliCommand >> getImageProcessFrom: lineString [ + + | imageProcess | + + imageProcess := PhLImageProcess newFrom: lineString. + imageProcess startDateTime: (self startDateOfPid: imageProcess pid). + ^ imageProcess +] + +{ #category : #'command execution' } +PhLProcessListCliCommand >> imageProcesList [ + + ^ (shellOutput substrings: OSPlatform current lineEnding) + collect: [:line | self getImageProcessFrom: line ] +] + +{ #category : #private } +PhLProcessListCliCommand >> modelClass [ + + ^ self class environment at: #PhLImageProcess +] + +{ #category : #'command execution' } +PhLProcessListCliCommand >> osShellArgArray [ + + ^ Array with: self processListCmdArgs +] + +{ #category : #'command execution' } +PhLProcessListCliCommand >> processListCmdArgs [ + + "process grep of all processes with 'pharo' (case-insensitive), where launcher process is ommited as well as export commands for path env. variables" + ^ String streamContents: [:aStream | + aStream + nextPutAll: OSPlatform current processListArgs; + nextPutAll: ' | grep -v ".bash"| grep -v "export LD_LIBRARY_PATH" | grep -v '; + nextPutAll: self currentVMPid asString; + "returns 0 exit code also for cases, when no process is found. (default for no match is 1)" + nextPutAll: '; pgrep_exit_code=$?; if [ "$pgrep_exit_code" -eq 1 ]; then exit 0; else exit "$pgrep_exit_code"; fi' + ] +] + +{ #category : #private } +PhLProcessListCliCommand >> startDateOfPid: pidString [ + + | pidDateCmd | + pidDateCmd := String streamContents: [: aStream | + aStream + nextPutAll: 'LANG=C ps -o lstart= -p "'; + nextPutAll: pidString; + nextPutAll: '" | '; + nextPutAll: OSPlatform current processStartDateArgs. + ]. + ^ (self executeOSShellCommandWithArgs: (Array with: pidDateCmd)) trim +] diff --git a/src/PharoLauncher-CLI/PhLProcessListEntry.class.st b/src/PharoLauncher-CLI/PhLProcessListEntry.class.st new file mode 100644 index 00000000..fdc65438 --- /dev/null +++ b/src/PharoLauncher-CLI/PhLProcessListEntry.class.st @@ -0,0 +1,100 @@ +" +I represent the output of a Shell process listing command for one entry. +I can parse this output to retrieve the Pharo VM and image. + +Example of input string from a process listing command: +'933 /tmp/61d1f200-02cc-0d00-88d2-05d60e98deae/110-x64/pharo /tmp/61d1f200-02cc-0d00-88d2-05d60e98deae/PharoLauncher.image' +" +Class { + #name : #PhLProcessListEntry, + #superclass : #Object, + #instVars : [ + 'words', + 'vmIndex', + 'imageIndex' + ], + #category : #'PharoLauncher-CLI-Utility' +} + +{ #category : #'instance creation' } +PhLProcessListEntry class >> with: aString [ + + ^ self new + shellString: aString; + yourself +] + +{ #category : #converting } +PhLProcessListEntry >> asImageProcess [ + + ^ PhLImageProcess new + pid: self pidString; + imagePath: self imagePath; + vmPath: self vmPath +] + +{ #category : #private } +PhLProcessListEntry >> computeImageIndex [ + + imageIndex := words + detectIndex: [ :word | word includesSubstring: '.image' caseSensitive: false ] + ifNone: [ 0 ] +] + +{ #category : #private } +PhLProcessListEntry >> computeVmIndex [ + + vmIndex := words + detectIndex: [ :word | word includesSubstring: 'pharo' caseSensitive: false ] + ifNone: [ nil ] +] + +{ #category : #accessing } +PhLProcessListEntry >> imagePath [ + + vmIndex ifNil: [ ^ '' ]. + + ^ ( + String streamContents: [ :aStream | + words + from: vmIndex + 1 to: imageIndex + do: [ :word | (word beginsWith: '--') ifFalse: [ aStream nextPutAll: word; nextPut: Character space ] ]. + words + from: imageIndex + 1 to: words size + do: [ :word | (word beginsWith: '--') ifTrue: [ aStream nextPutAll: word; nextPut: Character space ] ] ] + ) trim +] + +{ #category : #private } +PhLProcessListEntry >> pidIndex [ + + ^ 1 +] + +{ #category : #accessing } +PhLProcessListEntry >> pidString [ + + ^ words at: self pidIndex +] + +{ #category : #initialization } +PhLProcessListEntry >> shellString: aString [ + + words := aString substrings. + self computeVmIndex. + self computeImageIndex +] + +{ #category : #accessing } +PhLProcessListEntry >> vmPath [ + + vmIndex ifNil: [ ^ '' ]. + + ^ (String streamContents: [:aStream | + words + from: self pidIndex + 1 to: vmIndex + do: [ :word | aStream nextPutAll: word; nextPut: Character space ]. + words from: vmIndex to: imageIndex + do: [ :word | (word beginsWith: '--') ifTrue: [ aStream nextPutAll: word; nextPut: Character space ] ] + ]) trim +] diff --git a/src/PharoLauncher-CLI/PhLTemplateCategoriesCliCommand.class.st b/src/PharoLauncher-CLI/PhLTemplateCategoriesCliCommand.class.st index e649409c..28533b11 100644 --- a/src/PharoLauncher-CLI/PhLTemplateCategoriesCliCommand.class.st +++ b/src/PharoLauncher-CLI/PhLTemplateCategoriesCliCommand.class.st @@ -33,7 +33,9 @@ PhLTemplateCategoriesCliCommand class >> launcherCmdDescription [ { #category : #'command execution' } PhLTemplateCategoriesCliCommand >> basicExecute [ - self list: self templateRepository roots + [ self list: self templateRepository roots default: self defaultTemplateCategory ] + on: NotFound + do: [ self list: self templateRepository roots ] ] { #category : #private } diff --git a/src/PharoLauncher-CLI/PhLTemplateInfoCliCommand.class.st b/src/PharoLauncher-CLI/PhLTemplateInfoCliCommand.class.st index 6c9b5e36..685e5686 100644 --- a/src/PharoLauncher-CLI/PhLTemplateInfoCliCommand.class.st +++ b/src/PharoLauncher-CLI/PhLTemplateInfoCliCommand.class.st @@ -28,7 +28,7 @@ PhLTemplateInfoCliCommand class >> addLauncherPositionalsTo: aCommandSpec [ (aCommandSpec addPositional: #templateName description: 'Specifies the template name to print information.') - implicitMeaning: [:arg :app | app raiseMissingTemplateToPrint] + implicitMeaning: [:arg :app | self raiseMissingTemplateToPrint] ] { #category : #'command line - converting' } diff --git a/src/PharoLauncher-CLI/PhLTemplateListCliCommand.class.st b/src/PharoLauncher-CLI/PhLTemplateListCliCommand.class.st index 7d8777f8..0847bcf6 100644 --- a/src/PharoLauncher-CLI/PhLTemplateListCliCommand.class.st +++ b/src/PharoLauncher-CLI/PhLTemplateListCliCommand.class.st @@ -41,8 +41,11 @@ PhLTemplateListCliCommand >> basicExecute [ categoryNamed: self templateCategory ] on: NotFound do: [ ^ self raiseCategoryNotFound: self templateCategory ]. - - self list: templateCategory templatesAndGroups asOrderedCollection + + self + isDefaultTemplateCategory: templateCategory + ifTrue: [ self list: templateCategory templatesAndGroups asOrderedCollection default: self defaultTemplate ] + ifFalse: [ self list: templateCategory templatesAndGroups asOrderedCollection ] ] { #category : #message } diff --git a/src/PharoLauncher-CLI/PhLVmCliCommand.class.st b/src/PharoLauncher-CLI/PhLVmCliCommand.class.st index 56ac87d3..f7a34edd 100644 --- a/src/PharoLauncher-CLI/PhLVmCliCommand.class.st +++ b/src/PharoLauncher-CLI/PhLVmCliCommand.class.st @@ -21,7 +21,7 @@ PhLVmCliCommand class >> addLauncherPositionalsTo: aCommandSpec [ (aCommandSpec addPositional: #existingVirtualMachineId description: 'Specifies the local Virtual Machine ID.') - implicitMeaning: [:arg :app | app raiseMissingVM] + implicitMeaning: [:arg :app | self raiseMissingVM] ] { #category : #'command line - converting' } diff --git a/src/PharoLauncher-CLI/PharoLauncherCLIConfiguration.class.st b/src/PharoLauncher-CLI/PharoLauncherCLIConfiguration.class.st index 4bccbc2b..85e789d5 100644 --- a/src/PharoLauncher-CLI/PharoLauncherCLIConfiguration.class.st +++ b/src/PharoLauncher-CLI/PharoLauncherCLIConfiguration.class.st @@ -8,7 +8,8 @@ Class { 'imagesDirectory', 'vmsDirectory', 'launchImageFromALoginShell', - 'initScriptsDirectory' + 'initScriptsDirectory', + 'defaultTemplate' ], #category : #'PharoLauncher-CLI-Model' } @@ -87,6 +88,19 @@ PharoLauncherCLIConfiguration >> = anObject [ and: [ vmsDirectory = anObject vmsDirectory ] ] ] ] +{ #category : #accessing } +PharoLauncherCLIConfiguration >> defaultTemplate [ + ^ defaultTemplate ifNil: [ #stable ] +] + +{ #category : #accessing } +PharoLauncherCLIConfiguration >> defaultTemplate: aString [ + "default template can only be the stable Pharo version or the dev Pharo version" + + (#(dev stable) includes: aString) + ifTrue: [ defaultTemplate := aString asSymbol ] +] + { #category : #comparing } PharoLauncherCLIConfiguration >> hash [ ^ imagesDirectory hash diff --git a/src/PharoLauncher-CLI/PharoLauncherCLIModel.class.st b/src/PharoLauncher-CLI/PharoLauncherCLIModel.class.st index cb76c048..ba8dc591 100644 --- a/src/PharoLauncher-CLI/PharoLauncherCLIModel.class.st +++ b/src/PharoLauncher-CLI/PharoLauncherCLIModel.class.st @@ -29,12 +29,23 @@ PharoLauncherCLIModel class >> fromDefaultConfiguration [ ^ self fromConfiguration: PharoLauncherCLIConfiguration defaultConfiguration ] +{ #category : #accessing } +PharoLauncherCLIModel >> configuration [ + + ^ configuration +] + { #category : #accessing } PharoLauncherCLIModel >> configuration: aPharoLauncherConfiguration [ configuration := aPharoLauncherConfiguration ] +{ #category : #accessing } +PharoLauncherCLIModel >> defaultTemplate [ + ^ configuration defaultTemplate +] + { #category : #accessing } PharoLauncherCLIModel >> imageRepository [ ^ imageRepository diff --git a/src/PharoLauncher-CLI/String.extension.st b/src/PharoLauncher-CLI/String.extension.st new file mode 100644 index 00000000..20ada39d --- /dev/null +++ b/src/PharoLauncher-CLI/String.extension.st @@ -0,0 +1,32 @@ +Extension { #name : #String } + +{ #category : #'*PharoLauncher-CLI' } +String >> shortForm [ + "this is string abbreviation used when shortening string to given size" + ^ ' ... ' +] + +{ #category : #'*PharoLauncher-CLI' } +String >> shortenTo: aSizeLimit [ + "returns shortened string up to desired limit, puts ' ... ' in the middle of shortened string." + "('ABCDEF' shortenTo: 5) >>> ' ... '" + "('ABCDEF' shortenTo: 6) >>> 'ABCDEF'" + "('ABCDEF' shortenTo: 7) >>> 'ABCDEF'" + "('ABCDEFGHIJ' shortenTo: 9) >>> 'A ... HIJ'" + "('ABCDEFGHIJK' shortenTo: 10) >>> 'AB ... IJK'" + + |prefixIndex suffixIndex| + + self size <= aSizeLimit ifTrue: [ ^ self ]. + aSizeLimit <= 5 ifTrue: [ ^ self shortForm ]. + prefixIndex := (aSizeLimit / 2) asInteger - 3. + suffixIndex := self size - prefixIndex. + aSizeLimit odd ifTrue: [ suffixIndex := suffixIndex -1 ]. + + ^ self class streamContents: [: aStream | + aStream + nextPutAll: (self copyFrom: 1 to: prefixIndex); + nextPutAll: self shortForm; + nextPutAll: (self copyFrom: suffixIndex to: self size) + ] +] diff --git a/src/PharoLauncher-CLI/UnixPlatform.extension.st b/src/PharoLauncher-CLI/UnixPlatform.extension.st new file mode 100644 index 00000000..af6df615 --- /dev/null +++ b/src/PharoLauncher-CLI/UnixPlatform.extension.st @@ -0,0 +1,14 @@ +Extension { #name : #UnixPlatform } + +{ #category : #'*PharoLauncher-CLI' } +UnixPlatform >> processListArgs [ + + ^ 'pgrep -ai -f "pharo.*\.image"' + +] + +{ #category : #'*PharoLauncher-CLI' } +UnixPlatform >> processStartDateArgs [ + + ^ 'xargs -I{} date -d "{}" ''+%Y-%m-%d %H:%M:%S''' +] diff --git a/src/PharoLauncher-Core/PhLAbstractTemplate.class.st b/src/PharoLauncher-Core/PhLAbstractTemplate.class.st index 86df44d8..d400c9e5 100644 --- a/src/PharoLauncher-Core/PhLAbstractTemplate.class.st +++ b/src/PharoLauncher-Core/PhLAbstractTemplate.class.st @@ -8,7 +8,8 @@ Class { #name : #PhLAbstractTemplate, #superclass : #PhLObject, #instVars : [ - 'name' + 'name', + 'shortName' ], #category : #'PharoLauncher-Core-Model' } @@ -114,6 +115,16 @@ PhLAbstractTemplate >> renameTo: aString [ name := aString ] +{ #category : #accessing } +PhLAbstractTemplate >> shortName [ + ^ shortName +] + +{ #category : #accessing } +PhLAbstractTemplate >> shortName: aString [ + shortName := aString +] + { #category : #testing } PhLAbstractTemplate >> shouldComputeChildrenLazily [ ^ false diff --git a/src/PharoLauncher-Core/PhLAbstractTemplateGroup.class.st b/src/PharoLauncher-Core/PhLAbstractTemplateGroup.class.st index b6ad9df5..e16c6d90 100644 --- a/src/PharoLauncher-Core/PhLAbstractTemplateGroup.class.st +++ b/src/PharoLauncher-Core/PhLAbstractTemplateGroup.class.st @@ -85,6 +85,16 @@ PhLAbstractTemplateGroup >> templateNamed: aTemplateName [ , ' not found, please enter a correct template name' ] ] +{ #category : #querying } +PhLAbstractTemplateGroup >> templateShortNamed: aTemplateShortName [ + ^ self templatesAndGroups + detect: [ :aTemplate | aTemplate shortName = aTemplateShortName ] + ifNone: [ NotFound + signal: + aTemplateShortName asString + , ' not found, please enter a correct short template name' ] +] + { #category : #accessing } PhLAbstractTemplateGroup >> templatesAndGroups [ "Return a collection of all the templates and subgroups I contain" diff --git a/src/PharoLauncher-Core/PhLImageFinder.class.st b/src/PharoLauncher-Core/PhLImageFinder.class.st index 52d14f34..d813f8bc 100644 --- a/src/PharoLauncher-Core/PhLImageFinder.class.st +++ b/src/PharoLauncher-Core/PhLImageFinder.class.st @@ -163,7 +163,7 @@ PhLImageFinder >> pullRequest: aString [ { #category : #private } PhLImageFinder >> pullRequestBuildArtifactsUrlString [ - ^ 'https://ci.inria.fr/pharo-ci-jenkins2/job/Test%20pending%20pull%20request%20and%20branch%20Pipeline/view/change-requests/job/PR-{1}/lastSuccessfulBuild/artifact/bootstrap-cache/' + ^ 'https://ci.inria.fr/pharo-ci-jenkins2/job/Test%20pending%20pull%20request%20and%20branch%20Pipeline/view/change-requests/job/PR-{1}/lastSuccessfulBuild/artifact/build/bootstrap-cache/' format: { self pullRequest } ] diff --git a/src/PharoLauncher-Core/PhLImageProcess.class.st b/src/PharoLauncher-Core/PhLImageProcess.class.st new file mode 100644 index 00000000..221632db --- /dev/null +++ b/src/PharoLauncher-Core/PhLImageProcess.class.st @@ -0,0 +1,98 @@ +" +I represent running Pharo image process. I have a known PID of running Pharo image process, image name, vm path, image Path start datetime of process. I am used mainly for pretty printing to user output. +" +Class { + #name : #PhLImageProcess, + #superclass : #PhLObject, + #instVars : [ + 'pid', + 'vmPath', + 'imagePath', + 'startDateTime' + ], + #category : #'PharoLauncher-Core-Model' +} + +{ #category : #private } +PhLImageProcess class >> listPrintAttributeBlocks [ + + ^ { + [ :imgProcess | imgProcess pid asString ]. + [ :imgProcess | imgProcess imageName ]. + [ :imgProcess | imgProcess vmPath ]. + [ :imgProcess | imgProcess imagePath ]. + [ :imgProcess | imgProcess startDateTime ] } +] + +{ #category : #private } +PhLImageProcess class >> listPrintAttributeLabels [ + + ^ #( 'PID' 'Image name' 'VM path' 'Image path' 'Date/Time started' ) +] + +{ #category : #accessing } +PhLImageProcess >> imageName [ + + |fileName| + self imagePath ifEmpty: [ ^ '' ]. + fileName := self imagePath copyAfterLast: FileSystem disk delimiter. + fileName ifEmpty: [ fileName := self imagePath ]. + ^ fileName copyUpTo: $. +] + +{ #category : #accessing } +PhLImageProcess >> imagePath [ + + ^ imagePath +] + +{ #category : #accessing } +PhLImageProcess >> imagePath: anObject [ + + imagePath := anObject +] + +{ #category : #initialization } +PhLImageProcess >> initializeFrom: processLineArray [ + + self pid: processLineArray first. + self vmPath: processLineArray second. + self imagePath: processLineArray third. + self startDateTime: processLineArray fourth. +] + +{ #category : #accessing } +PhLImageProcess >> pid [ + + ^ pid +] + +{ #category : #accessing } +PhLImageProcess >> pid: anObject [ + + pid := anObject +] + +{ #category : #accessing } +PhLImageProcess >> startDateTime [ + + ^ startDateTime +] + +{ #category : #accessing } +PhLImageProcess >> startDateTime: anObject [ + + startDateTime := anObject +] + +{ #category : #accessing } +PhLImageProcess >> vmPath [ + + ^ vmPath +] + +{ #category : #accessing } +PhLImageProcess >> vmPath: anObject [ + + vmPath := anObject +] diff --git a/src/PharoLauncher-Core/PhLRemoteTemplate.class.st b/src/PharoLauncher-Core/PhLRemoteTemplate.class.st index 722ea1db..97b4d1fe 100644 --- a/src/PharoLauncher-Core/PhLRemoteTemplate.class.st +++ b/src/PharoLauncher-Core/PhLRemoteTemplate.class.st @@ -15,6 +15,15 @@ PhLRemoteTemplate class >> example [ ^ self name: 'Pharo Mooc' url: 'https://mooc.pharo.org/image/PharoWeb.zip' ] +{ #category : #'instance creation' } +PhLRemoteTemplate class >> name: aString shortName: shortNameString url: anUrl username: anotherString password: yetAnotherString [ + ^ (self name: aString url: anUrl) + shortName: shortNameString; + username: anotherString; + password: yetAnotherString; + yourself +] + { #category : #'instance creation' } PhLRemoteTemplate class >> name: aString url: anUrl [ ^ self new @@ -24,10 +33,7 @@ PhLRemoteTemplate class >> name: aString url: anUrl [ { #category : #'instance creation' } PhLRemoteTemplate class >> name: aString url: anUrl username: anotherString password: yetAnotherString [ - ^ (self name: aString url: anUrl) - username: anotherString; - password: yetAnotherString; - yourself + ^ self name: aString shortName: nil url: anUrl username: anotherString password: yetAnotherString ] { #category : #comparing } diff --git a/src/PharoLauncher-Core/PhLTemplateGroupRepository.class.st b/src/PharoLauncher-Core/PhLTemplateGroupRepository.class.st index c7d353ea..fad94d80 100644 --- a/src/PharoLauncher-Core/PhLTemplateGroupRepository.class.st +++ b/src/PharoLauncher-Core/PhLTemplateGroupRepository.class.st @@ -163,3 +163,10 @@ PhLTemplateGroupRepository >> templateNamed: aTemplateName inCategoryNamed: aCat category := self categoryNamed: aCategoryName. ^ category templateNamed: aTemplateName ] + +{ #category : #querying } +PhLTemplateGroupRepository >> templateShortNamed: aTemplateName inCategoryNamed: aCategoryName [ + | category | + category := self categoryNamed: aCategoryName. + ^ category templateShortNamed: aTemplateName +] diff --git a/src/PharoLauncher-Core/PhLTemplateSource.class.st b/src/PharoLauncher-Core/PhLTemplateSource.class.st index db69c421..0e8a222f 100644 --- a/src/PharoLauncher-Core/PhLTemplateSource.class.st +++ b/src/PharoLauncher-Core/PhLTemplateSource.class.st @@ -10,6 +10,7 @@ Class { #instVars : [ 'type', 'name', + 'shortName', 'url', 'filterPattern', 'templates', @@ -293,6 +294,7 @@ PhLTemplateSource >> asTemplate [ type == self class urlType ifTrue: [ ^ PhLRemoteTemplate name: name + shortName: shortName url: url asUrl username: username password: password ]. @@ -356,6 +358,11 @@ PhLTemplateSource >> printOn: aStream [ nextPut: $) ] +{ #category : #accessing } +PhLTemplateSource >> shortName [ + ^ shortName +] + { #category : #accessing } PhLTemplateSource >> templateNameFormat [ ^ templateNameFormat diff --git a/src/PharoLauncher-Tests-SpecUI/PhLErrorDialogPresenter.class.st b/src/PharoLauncher-Spec2/PhLErrorDialogPresenter.class.st similarity index 96% rename from src/PharoLauncher-Tests-SpecUI/PhLErrorDialogPresenter.class.st rename to src/PharoLauncher-Spec2/PhLErrorDialogPresenter.class.st index dc33d9de..376853ab 100644 --- a/src/PharoLauncher-Tests-SpecUI/PhLErrorDialogPresenter.class.st +++ b/src/PharoLauncher-Spec2/PhLErrorDialogPresenter.class.st @@ -21,15 +21,13 @@ Class { #traits : 'TDebugger', #classTraits : 'TDebugger classTrait', #instVars : [ - 'acceptButton', - 'cancelButton', 'debugSession', 'description' ], - #category : #'PharoLauncher-Tests-SpecUI' + #category : #'PharoLauncher-Spec2' } -{ #category : #accessing } +{ #category : #closing } PhLErrorDialogPresenter class >> closeAllDebuggers [
h5ai 0.22.1⚡ JavaScript is disabled! ⚡⚡ Some features disabled! Works best in modern browsers. ⚡
' +] + +{ #category : #helpers } +PhLHTTPListingTemplateGroupTest >> pharo12ExampleUrl [ + ^ 'https://files.pharo.org/image/120/' asZnUrl +] + { #category : #running } PhLHTTPListingTemplateGroupTest >> setUp [ super setUp. - self downloadManager atUrl: self exampleUrl answer: self exampleContent + self downloadManager atUrl: self exampleUrl answer: self exampleContent. + self downloadManager atUrl: self pharo12ExampleUrl answer: self pharo12ExampleContent +] + +{ #category : #tests } +PhLHTTPListingTemplateGroupTest >> testCanMatchPharo12Templates [ + | group templatesAndGroups | + group := self newPharo12Group. + + templatesAndGroups := group templatesAndGroups. + + self assert: (templatesAndGroups noneSatisfy: [ :template | template isTemplateGroup ]). + self + assertCollection: (templatesAndGroups collect: #name) + hasSameElements: #('Pharo12.0-SNAPSHOT.build.1329.sha.25a911c.arch.64bit' + 'Pharo12.0-SNAPSHOT.build.1328.sha.10f5de5.arch.64bit' + 'Pharo12-SNAPSHOT.build.1229.sha.ed99075.arch.64bit' + 'Pharo12-SNAPSHOT.build.1228.sha.826d9bb.arch.64bit') ] { #category : #tests } diff --git a/test/testImageCommands.sh b/test/testImageCommands.sh index 5baec285..d86faef7 100755 --- a/test/testImageCommands.sh +++ b/test/testImageCommands.sh @@ -14,7 +14,7 @@ SAMPLE_IMAGE_PATH="$HOME"/Pharo/images/$SAMPLE_IMAGE # setup commands for sample image manipulation createSampleImageCommand () { - runLauncherScript image create $SAMPLE_IMAGE --templateName "$SAMPLE_TEMPLATE" + runLauncherScript image create $SAMPLE_IMAGE --no-launch --templateName "$SAMPLE_TEMPLATE" cp -f "$ROOT"/$IMAGE_METADATA_FILE $SAMPLE_IMAGE_PATH/$IMAGE_METADATA_FILE } @@ -23,7 +23,7 @@ launchSampleImageCommand () { } killSampleImageCommand () { - runLauncherScript image kill $SAMPLE_IMAGE + runLauncherScript process kill $SAMPLE_IMAGE } deleteSampleImageCommand () { @@ -31,7 +31,7 @@ deleteSampleImageCommand () { } processListCommand () { - runLauncherScript image processList + runLauncherScript process list } killAllCommand () {