Use standard directories when running on Linux (#91)

* Use standard Linux directories for application data (https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard)

* Use standard system directories

* Cleanup all Polaris files during uninstall

* Expose get_pid_directory to rest of the crate

* Add separate targets for install binary and data files, clean up makefile

* Use environment variables for directory locations during install process

* On Linux, read locations from environment variables at compile time

* Split static_directory in two (web and swagger directories)

* Follow recommendations from the Make manual

* Avoid redundant directories

* Added workflow to validate installer setup

* Added CLI options to locate log file, pid file and cache directory

* Fixed an issue where build command did not support the xdg/system switch

* Renamed log option to log-level

* Fixed an issue where xdg install would do a system build

* Use re-usable action to make linux release

* Avoid nested actions (see https://github.com/actions/runner/issues/646)

* Updated installation instructions

* Replaced deprecated use of set-env
This commit is contained in:
Antoine Gersant 2020-11-26 15:57:08 -08:00 committed by GitHub
parent 0927f3815e
commit 538b41a2b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 421 additions and 188 deletions

View file

@ -0,0 +1,28 @@
name: 'Make a Linux Release'
description: 'Creates archive containing files to install Polaris on on a Linux system'
inputs:
version-number:
description: 'Polaris version number'
required: true
default: '0.0'
output-file:
description: 'File path where the resulting archive should be stored'
required: false
default: 'polaris.tar.gz'
runs:
using: "composite"
steps:
- name: Download Polaris Web
run: |
curl -L -o web.zip https://github.com/agersant/polaris-web/releases/latest/download/web.zip
unzip web.zip
shell: bash
- name: Set Polaris version
run: echo "POLARIS_VERSION=${{ inputs.version-number }}" >> $GITHUB_ENV
shell: bash
- name: Build archive
run: res/unix/release_script.sh
shell: bash
- name: Copy archive to output location
run: cp release/polaris.tar.gz ${{ inputs.output-file }}
shell: bash

View file

@ -0,0 +1,28 @@
name: 'Make a Windows Release'
description: 'Creates archive containing files to install Polaris on on a Windows system'
inputs:
version-number:
description: 'Polaris version number'
required: true
default: '0.0'
output-file:
description: 'File path where the resulting installer should be stored'
required: false
default: 'polaris.msi'
runs:
using: "composite"
steps:
- name: Download Polaris Web
run: |
curl -L -o web.zip https://github.com/agersant/polaris-web/releases/latest/download/web.zip
unzip web.zip
shell: bash
- name: Set Polaris Version
run: echo "POLARIS_VERSION=${{ inputs.version-number }}" >> $GITHUB_ENV
shell: bash
- name: Build Installer
run: res/windows/release_script
shell: pwsh
- name: Copy installer to output location
run: cp release/polaris.msi ${{ inputs.output-file }}
shell: bash

View file

@ -13,7 +13,7 @@ jobs:
steps: steps:
- name: Read Polaris Version - name: Read Polaris Version
run: echo ::set-env name=POLARIS_VERSION::${GITHUB_REF:10} run: echo "POLARIS_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV
- name: Create Github Release - name: Create Github Release
id: create_release id: create_release
uses: actions/create-release@v1.0.0 uses: actions/create-release@v1.0.0
@ -40,35 +40,30 @@ jobs:
steps: steps:
- name: Checkout Polaris - name: Checkout Polaris
uses: actions/checkout@v1 uses: actions/checkout@v1
- name: Download Polaris Web - name: Read Polaris Version
run: | shell: bash
curl -L -o web.zip https://github.com/agersant/polaris-web/releases/latest/download/web.zip run: echo "POLARIS_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV
unzip web.zip
- name: Install Rust Toolchain - name: Install Rust Toolchain
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
toolchain: nightly toolchain: nightly
profile: minimal profile: minimal
default: true default: true
- name: Read Polaris Version - name: Make release
shell: bash uses: ./.github/actions/make-windows-release
run: echo ::set-env name=POLARIS_VERSION::${GITHUB_REF:10}
- name: Build Installer
run: res/windows/release_script
- name: Retrieve Upload URL
uses: actions/download-artifact@v1
with: with:
name: release version-number: ${{ env.POLARIS_VERSION }}
output-file: polaris.msi
- name: Read Upload URL - name: Read Upload URL
shell: bash shell: bash
run: echo ::set-env name=UPLOAD_URL::$(cat release/upload-url) run: echo "UPLOAD_URL=$(cat release/upload-url)" >> $GITHUB_ENV
- name: Upload Installer To Github Release - name: Upload Installer To Github Release
uses: actions/upload-release-asset@v1.0.1 uses: actions/upload-release-asset@v1.0.1
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
upload_url: ${{ env.UPLOAD_URL }} upload_url: ${{ env.UPLOAD_URL }}
asset_path: ./release/Polaris_${{ env.POLARIS_VERSION }}.msi asset_path: polaris.msi
asset_name: Polaris_${{ env.POLARIS_VERSION }}.msi asset_name: Polaris_${{ env.POLARIS_VERSION }}.msi
asset_content_type: application/x-msi asset_content_type: application/x-msi
@ -80,26 +75,25 @@ jobs:
steps: steps:
- name: Checkout Polaris - name: Checkout Polaris
uses: actions/checkout@v1 uses: actions/checkout@v1
- name: Download Polaris Web
run: |
curl -L -o web.zip https://github.com/agersant/polaris-web/releases/latest/download/web.zip
unzip web.zip
- name: Read Polaris Version - name: Read Polaris Version
run: echo ::set-env name=POLARIS_VERSION::${GITHUB_REF:10} run: echo "POLARIS_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV
- name: Build Archive - name: Make release
run: res/unix/release_script.sh uses: ./.github/actions/make-linux-release
with:
version-number: ${{ env.POLARIS_VERSION }}
output-file: polaris.tar.gz
- name: Retrieve Upload URL - name: Retrieve Upload URL
uses: actions/download-artifact@v1 uses: actions/download-artifact@v1
with: with:
name: release name: release
- name: Read Upload URL - name: Read Upload URL
run: echo ::set-env name=UPLOAD_URL::$(cat release/upload-url) run: echo "UPLOAD_URL=$(cat release/upload-url)" >> $GITHUB_ENV
- name: Upload To Github Release - name: Upload To Github Release
uses: actions/upload-release-asset@v1.0.1 uses: actions/upload-release-asset@v1.0.1
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
upload_url: ${{ env.UPLOAD_URL }} upload_url: ${{ env.UPLOAD_URL }}
asset_path: ./release/Polaris_${{ env.POLARIS_VERSION }}.tar.gz asset_path: polaris.tar.gz
asset_name: Polaris_${{ env.POLARIS_VERSION }}.tar.gz asset_name: Polaris_${{ env.POLARIS_VERSION }}.tar.gz
asset_content_type: application/gzip asset_content_type: application/gzip

139
.github/workflows/validate-install.yml vendored Normal file
View file

@ -0,0 +1,139 @@
on:
pull_request:
push:
name: Validate Install
jobs:
package_linux_release:
name: Package Linux Release
runs-on: ubuntu-latest
steps:
- name: Checkout Polaris
uses: actions/checkout@v1
- name: Make release
uses: ./.github/actions/make-linux-release
with:
version-number: '0.0'
output-file: polaris.tar.gz
- name: Upload packaged release
uses: actions/upload-artifact@v2
with:
name: linux-release
path: polaris.tar.gz
validate_linux_system_install:
name: Linux System Install
runs-on: ubuntu-latest
needs: package_linux_release
steps:
- name: Download release
uses: actions/download-artifact@v2
with:
name: linux-release
path: .
- name: Extract release
run: tar -xzvf polaris.tar.gz --strip-components=1
- name: Preview Install
run: make preview
- name: Preview Install w/ Custom Prefix
run: make preview PREFIX=/some/random/prefix
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: minimal
default: true
- name: Install
run: sudo --preserve-env=PATH make install
- name: Run Polaris
run: sudo /usr/local/bin/polaris && sleep 5s
- name: Make a request
run: curl -f http://localhost:5050
- name: Stop Polaris
run: sudo kill -KILL $(cat /usr/local/var/run/polaris/polaris.pid)
- name: Uninstall
run: sudo make uninstall
validate_linux_xdg_install:
name: Linux XDG Install
runs-on: ubuntu-latest
needs: package_linux_release
steps:
- name: Download release
uses: actions/download-artifact@v2
with:
name: linux-release
path: .
- name: Extract release
run: tar -xzvf polaris.tar.gz --strip-components=1
- name: Preview Install
run: make preview-xdg
- name: Preview Install w/ Custom XDG_DATA_HOME
run: make preview-xdg XDG_DATA_HOME=/my/own/xdg/home
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: minimal
default: true
- name: Install
run: make install-xdg
- name: Run Polaris
run: $HOME/.local/bin/polaris && sleep 5s
- name: Make a request
run: curl -f http://localhost:5050
- name: Stop Polaris
run: kill -KILL $(cat /tmp/polaris-1001/polaris.pid)
- name: Uninstall
run: make uninstall-xdg
package_windows_release:
name: Package Windows Release
runs-on: windows-latest
steps:
- name: Checkout Polaris
uses: actions/checkout@v1
- name: Install Rust Toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: minimal
default: true
- name: Make release
uses: ./.github/actions/make-windows-release
with:
version-number: '0.0'
output-file: polaris.msi
- name: Upload packaged release
uses: actions/upload-artifact@v2
with:
name: windows-release
path: polaris.msi
validate_windows_install:
name: Windows Install
runs-on: windows-latest
needs: package_windows_release
steps:
- name: Download release
uses: actions/download-artifact@v2
with:
name: windows-release
path: .
- name: Install
run: msiexec /i polaris.msi /qn
- name: Run Polaris
run: |
start $env:LOCALAPPDATA/Permafrost/Polaris/polaris-cli.exe
sleep 5
- name: Make a request
run: curl -f http://localhost:5050
- name: Stop Polaris
run: taskkill /IM polaris-cli.exe
- name: Uninstall
run: msiexec /x polaris.msi /qn

6
.gitignore vendored
View file

@ -10,6 +10,10 @@ index-flame-graph.html
# Local config for quick iteration # Local config for quick iteration
TestConfig.toml TestConfig.toml
# Release process artefacts (usually runs on CI) # Runtime artifacts
*.sqlite
thumbnails
# Release process artifacts (usually runs on CI)
release release
*.res *.res

39
Cargo.lock generated
View file

@ -100,18 +100,6 @@ dependencies = [
"byteorder", "byteorder",
] ]
[[package]]
name = "app_dirs"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d"
dependencies = [
"ole32-sys",
"shell32-sys",
"winapi 0.2.8",
"xdg",
]
[[package]] [[package]]
name = "atty" name = "atty"
version = "0.2.14" version = "0.2.14"
@ -1647,16 +1635,6 @@ dependencies = [
"byteorder", "byteorder",
] ]
[[package]]
name = "ole32-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c"
dependencies = [
"winapi 0.2.8",
"winapi-build",
]
[[package]] [[package]]
name = "opaque-debug" name = "opaque-debug"
version = "0.2.3" version = "0.2.3"
@ -1833,7 +1811,6 @@ version = "0.12.4"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"ape", "ape",
"app_dirs",
"base64 0.12.3", "base64 0.12.3",
"cookie 0.14.3", "cookie 0.14.3",
"crossbeam-channel 0.4.4", "crossbeam-channel 0.4.4",
@ -2518,16 +2495,6 @@ dependencies = [
"opaque-debug 0.3.0", "opaque-debug 0.3.0",
] ]
[[package]]
name = "shell32-sys"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c"
dependencies = [
"winapi 0.2.8",
"winapi-build",
]
[[package]] [[package]]
name = "simplelog" name = "simplelog"
version = "0.8.0" version = "0.8.0"
@ -3328,12 +3295,6 @@ dependencies = [
"winapi-build", "winapi-build",
] ]
[[package]]
name = "xdg"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
[[package]] [[package]]
name = "yansi" name = "yansi"
version = "0.5.0" version = "0.5.0"

View file

@ -6,14 +6,13 @@ edition = "2018"
[features] [features]
default = ["service-rocket"] default = ["service-rocket"]
ui = [] ui = ["uuid", "winapi"]
profile-index = ["flame", "flamer"] profile-index = ["flame", "flamer"]
service-rocket = ["rocket", "rocket_contrib"] service-rocket = ["rocket", "rocket_contrib"]
[dependencies] [dependencies]
anyhow = "1.0.31" anyhow = "1.0.31"
ape = "0.3.0" ape = "0.3.0"
app_dirs = "1.1.1"
base64 = "0.12.1" base64 = "0.12.1"
crossbeam-channel = "0.4" crossbeam-channel = "0.4"
diesel = { version = "1.4.4", features = ["sqlite", "r2d2"] } diesel = { version = "1.4.4", features = ["sqlite", "r2d2"] }
@ -54,11 +53,8 @@ features = ["json", "serve"]
optional = true optional = true
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
uuid = "0.8" uuid = { version="0.8", optional = true }
winapi = { version = "0.3.3", features = ["winuser", "libloaderapi", "shellapi", "errhandlingapi"], optional = true }
[target.'cfg(windows)'.dependencies.winapi]
version = "0.3.3"
features = ["winuser", "libloaderapi", "shellapi", "errhandlingapi"]
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
sd-notify = "0.1.0" sd-notify = "0.1.0"

View file

@ -4,7 +4,7 @@
Compiling and running Polaris is very easy as it only depends on the Rust toolchain. Compiling and running Polaris is very easy as it only depends on the Rust toolchain.
1. [Install Rust](https://www.rust-lang.org/en-US/install.html) 1. [Install Rust](https://www.rust-lang.org/en-US/install.html), you need the `nightly` version of the toolchain
2. Clone the polaris depot with this command: `git clone --recursive https://github.com/agersant/polaris.git` 2. Clone the polaris depot with this command: `git clone --recursive https://github.com/agersant/polaris.git`
3. You can now run compile and run polaris from the newly created directory with the command: `cargo run` 3. You can now run compile and run polaris from the newly created directory with the command: `cargo run`

View file

@ -6,8 +6,6 @@ One of the following:
- Windows 7 or newer - Windows 7 or newer
- Linux (any reasonably modern distribution should do) - Linux (any reasonably modern distribution should do)
## Installation
### Windows ### Windows
1. Download the [latest installer](https://github.com/agersant/polaris/releases/latest) (you want the .msi file) 1. Download the [latest installer](https://github.com/agersant/polaris/releases/latest) (you want the .msi file)
2. Run the installer 2. Run the installer
@ -24,14 +22,14 @@ You can now start Polaris from the start menu or from your desktop, Polaris will
#### Polaris installation #### Polaris installation
1. Download the [latest release]((https://github.com/agersant/polaris/releases/latest)) of Polaris (you want the .tar.gz file) 1. Download the [latest release]((https://github.com/agersant/polaris/releases/latest)) of Polaris (you want the .tar.gz file)
2. Extract the polaris archive in a directory and open a terminal in that directory 2. Extract the Polaris archive in a directory and open a terminal in that directory
3. Execute `make install` (this may take several minutes) 3. To install Polaris within your home directory, execute `make install-xdg`. This installation follows the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html). You can use `make preview-xdg` to see which directories the install process would use.
4. If you prefer a system-wide install, execute `make install` (without the `-xdg` suffix). If you use `sudo` to perform such a system install, you may need the `-E` option so that your sudo user find the Rust binaries: `sudo -E make install`. This installation follows the [GNU Standard Installation Directories](https://www.gnu.org/prep/standards/html_node/Directory-Variables.html). You can use `make preview` to see which directories the install process would use.
This installation process puts the polaris executable in `~/.local/bin/polaris` and several data files under `~/.local/share/polaris`.
From here, you might want to adjust your system to run Polaris on login using Cron, Systemd or whichever method your distribution endorses. From here, you might want to adjust your system to run Polaris on login using Systemd, Cron or whichever method your distribution endorses.
If you want to uninstall Polaris, execute `make uninstall` from the extracted archive's directory. This will simply delete the directories created by the install process. If you want to uninstall Polaris, execute `make uninstall` from the extracted archive's directory. This will delete all the files and directories listed above **including your Polaris database**. If you customized the install process by specifying environment variables like `PREFIX`, make sure they are set to the same values when running `make uninstall`.
### In a docker container ### In a docker container
@ -39,6 +37,6 @@ To run polaris from a Docker container, please follow instructions from the [doc
## Test Run ## Test Run
- Start Polaris using the shortcut on your desktop (Windows) or by running the executable in `~/.local/bin/polaris` (Linux) - Start Polaris using the shortcut on your desktop (Windows) or by running the Polaris executable
- In your Web browser, access http://localhost:5050 - In your Web browser, access http://localhost:5050
- You will see a welcome page that will guide you through the Polaris configuration - You will see a welcome page that will guide you through the Polaris configuration

View file

@ -1,22 +1,96 @@
POLARIS_BIN_DIR := ~/.local/bin/polaris .PHONY: all build build-system build-xdg cargo-build clean preview preview-system preview-xdg list-paths install install-bin install-data install-system install-xdg uninstall uninstall-bin uninstall-data uninstall-system uninstall-xdg
POLARIS_DATA_DIR := ~/.local/share/polaris
all: build UID := $(shell id -u)
build: PREFIX ?= /usr/local
EXEC_PREFIX ?= $(PREFIX)
BINDIR ?= $(EXEC_PREFIX)/bin
DATAROOTDIR ?= $(PREFIX)/share
DATADIR ?= $(DATAROOTDIR)
LOCALSTATEDIR ?= $(PREFIX)/var
RUNSTATEDIR ?= $(LOCALSTATEDIR)/run
%-system: POLARIS_BIN_PATH := $(BINDIR)/polaris
%-system: export POLARIS_WEB_DIR := $(DATADIR)/polaris/web
%-system: export POLARIS_SWAGGER_DIR := $(DATADIR)/polaris/swagger
%-system: export POLARIS_DB_DIR := $(LOCALSTATEDIR)/lib/polaris
%-system: export POLARIS_LOG_DIR := $(LOCALSTATEDIR)/log/polaris
%-system: export POLARIS_CACHE_DIR := $(LOCALSTATEDIR)/cache/polaris
%-system: export POLARIS_PID_DIR := $(RUNSTATEDIR)/polaris
XDG_CACHE_HOME ?= $(HOME)/.cache
XDG_DATA_HOME ?= $(HOME)/.local/share
XDG_BINDIR ?= $(HOME)/.local/bin
XDG_DATADIR ?= $(XDG_DATA_HOME)/polaris
XDG_CACHEDIR ?= $(XDG_CACHE_HOME)/polaris
ifdef $(XDG_RUNTIME_DIR)
XDG_PIDDIR ?= $(XDG_RUNTIME_DIR)/polaris
else
XDG_PIDDIR ?= /tmp/polaris-$(UID)
endif
%-xdg: POLARIS_BIN_PATH := $(XDG_BINDIR)/polaris
%-xdg: export POLARIS_WEB_DIR := $(XDG_DATADIR)/web
%-xdg: export POLARIS_SWAGGER_DIR := $(XDG_DATADIR)/swagger
%-xdg: export POLARIS_DB_DIR := $(XDG_DATADIR)
%-xdg: export POLARIS_LOG_DIR := $(XDG_CACHEDIR)
%-xdg: export POLARIS_CACHE_DIR := $(XDG_CACHEDIR)
%-xdg: export POLARIS_PID_DIR := $(XDG_PIDDIR)
# Build
build-system: cargo-build
build-xdg: cargo-build
build: build-system
all: build-system
cargo-build:
cargo build --release cargo build --release
install: build
install -d $(POLARIS_BIN_DIR)
install -d $(POLARIS_DATA_DIR)
install ./target/release/polaris $(POLARIS_BIN_DIR)
cp -r ./web $(POLARIS_DATA_DIR)
cp -r ./swagger $(POLARIS_DATA_DIR)
@echo "Polaris installation complete!"
clean: clean:
cargo clean cargo clean
uninstall: # Preview
rm -r $(POLARIS_BIN_DIR)
rm -r $(POLARIS_DATA_DIR) preview-system: list-paths
preview-xdg: list-paths
preview: preview-system
list-paths:
$(info POLARIS_BIN_PATH is $(POLARIS_BIN_PATH))
$(info POLARIS_WEB_DIR is $(POLARIS_WEB_DIR))
$(info POLARIS_SWAGGER_DIR is $(POLARIS_SWAGGER_DIR))
$(info POLARIS_DB_DIR is $(POLARIS_DB_DIR))
$(info POLARIS_LOG_DIR is $(POLARIS_LOG_DIR))
$(info POLARIS_CACHE_DIR is $(POLARIS_CACHE_DIR))
$(info POLARIS_PID_DIR is $(POLARIS_PID_DIR))
# Install
install-system: install-bin install-data
install-xdg: install-bin install-data
install: install-system
install-bin: cargo-build
install -Dm755 ./target/release/polaris $(POLARIS_BIN_PATH)
install-data:
install -d $(POLARIS_WEB_DIR)
install -d $(POLARIS_SWAGGER_DIR)
cp -rT ./web $(POLARIS_WEB_DIR)
cp -rT ./swagger $(POLARIS_SWAGGER_DIR)
# Uninstall
uninstall-system: uninstall-bin uninstall-data
uninstall-xdg: uninstall-bin uninstall-data
uninstall: uninstall-system
uninstall-bin:
rm $(POLARIS_BIN_PATH)
uninstall-data:
rm -rf $(POLARIS_WEB_DIR)
rm -rf $(POLARIS_SWAGGER_DIR)
rm -rf $(POLARIS_DB_DIR)
rm -rf $(POLARIS_LOG_DIR)
rm -rf $(POLARIS_CACHE_DIR)
rm -rf $(POLARIS_PID_DIR)

View file

@ -6,8 +6,7 @@ echo "Copying package files"
cp -r web docs/swagger src migrations test-data Cargo.toml Cargo.lock res/unix/Makefile release/tmp/polaris cp -r web docs/swagger src migrations test-data Cargo.toml Cargo.lock res/unix/Makefile release/tmp/polaris
echo "Creating tarball" echo "Creating tarball"
POLARIS_VERSION=$(grep -m 1 ^version Cargo.toml | awk '{print $3}' | tr -d '"\r\n') tar -zc -C release/tmp -f release/polaris.tar.gz polaris
tar -zc -C release/tmp -f release/Polaris_$POLARIS_VERSION.tar.gz polaris
echo "Cleaning up" echo "Cleaning up"
rm -rf release/tmp rm -rf release/tmp

View file

@ -1,7 +1,5 @@
Get-ChildItem "Cargo.toml" | ForEach-Object { if (!(Test-Path env:POLARIS_VERSION)) {
$conf = $_ | Get-Content -raw throw "POLARIS_VERSION environment variable is not defined"
$conf -match 'version\s+=\s+"(.*)"' | out-null
$script:POLARIS_VERSION = $matches[1]
} }
"Compiling resource file" "Compiling resource file"
@ -10,6 +8,13 @@ $rc_exe = Join-Path "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64
"" ""
"Compiling executable" "Compiling executable"
$script:INSTALL_DIR = "$env:LOCALAPPDATA\Permafrost\Polaris"
$env:POLARIS_WEB_DIR = "$INSTALL_DIR\web"
$env:POLARIS_SWAGGER_DIR = "$INSTALL_DIR\swagger"
$env:POLARIS_DB_DIR = "$INSTALL_DIR"
$env:POLARIS_LOG_DIR = "$INSTALL_DIR"
$env:POLARIS_CACHE_DIR = "$INSTALL_DIR"
$env:POLARIS_PID_DIR = "$INSTALL_DIR"
cargo rustc --release --features "ui" -- -C link-args="/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup res\windows\application\application.res" cargo rustc --release --features "ui" -- -C link-args="/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup res\windows\application\application.res"
cargo rustc --release -- -o ".\target\release\polaris-cli.exe" -C link-args="res\windows\application\application.res" cargo rustc --release -- -o ".\target\release\polaris-cli.exe" -C link-args="res\windows\application\application.res"
@ -31,7 +36,7 @@ Copy-Item .\docs\swagger .\release\tmp\swagger -recurse
"" ""
"Inserting version number in installer config" "Inserting version number in installer config"
[xml]$wxs = Get-Content .\res\windows\installer\installer.wxs [xml]$wxs = Get-Content .\res\windows\installer\installer.wxs
$wxs.Wix.Product.SetAttribute("Version", $POLARIS_VERSION) $wxs.Wix.Product.SetAttribute("Version", $env:POLARIS_VERSION)
$wxs.Save('.\res\windows\installer\installer.wxs') $wxs.Save('.\res\windows\installer\installer.wxs')
"" ""
@ -46,7 +51,7 @@ $candle_exe = Join-Path $env:WIX bin\candle.exe
& $candle_exe -wx -ext WixUtilExtension -arch x64 -out .\release\tmp\installer.wixobj .\res\windows\installer\installer.wxs & $candle_exe -wx -ext WixUtilExtension -arch x64 -out .\release\tmp\installer.wixobj .\res\windows\installer\installer.wxs
$light_exe = Join-Path $env:WIX bin\light.exe $light_exe = Join-Path $env:WIX bin\light.exe
& $light_exe -dWebUIDir=".\release\tmp\web" -dSwaggerUIDir=".\release\tmp\swagger" -wx -ext WixUtilExtension -ext WixUIExtension -spdb -sw1076 -sice:ICE38 -sice:ICE64 -out .\release\Polaris_$POLARIS_VERSION.msi .\release\tmp\installer.wixobj .\release\tmp\web_ui_fragment.wixobj .\release\tmp\swagger_ui_fragment.wixobj & $light_exe -dWebUIDir=".\release\tmp\web" -dSwaggerUIDir=".\release\tmp\swagger" -wx -ext WixUtilExtension -ext WixUIExtension -spdb -sw1076 -sice:ICE38 -sice:ICE64 -out .\release\polaris.msi .\release\tmp\installer.wixobj .\release\tmp\web_ui_fragment.wixobj .\release\tmp\swagger_ui_fragment.wixobj
"Cleaning up" "Cleaning up"
Remove-Item -Recurse .\release\tmp Remove-Item -Recurse .\release\tmp

View file

@ -3,7 +3,6 @@ use diesel::r2d2::{self, ConnectionManager, PooledConnection};
use diesel::sqlite::SqliteConnection; use diesel::sqlite::SqliteConnection;
use diesel::RunQueryDsl; use diesel::RunQueryDsl;
use diesel_migrations; use diesel_migrations;
use log::info;
use std::path::Path; use std::path::Path;
mod schema; mod schema;
@ -42,7 +41,6 @@ impl diesel::r2d2::CustomizeConnection<SqliteConnection, diesel::r2d2::Error>
impl DB { impl DB {
pub fn new(path: &Path) -> Result<DB> { pub fn new(path: &Path) -> Result<DB> {
info!("Database file path: {}", path.to_string_lossy());
let manager = ConnectionManager::<SqliteConnection>::new(path.to_string_lossy()); let manager = ConnectionManager::<SqliteConnection>::new(path.to_string_lossy());
let pool = diesel::r2d2::Pool::builder() let pool = diesel::r2d2::Pool::builder()
.connection_customizer(Box::new(ConnectionCustomizer {})) .connection_customizer(Box::new(ConnectionCustomizer {}))

View file

@ -14,8 +14,6 @@ use log::error;
#[cfg(unix)] #[cfg(unix)]
use sd_notify::{self, NotifyState}; use sd_notify::{self, NotifyState};
#[cfg(unix)] #[cfg(unix)]
use std::fs::File;
#[cfg(unix)]
use std::io::prelude::*; use std::io::prelude::*;
#[cfg(unix)] #[cfg(unix)]
use unix_daemonize::{daemonize_redirect, ChdirMode}; use unix_daemonize::{daemonize_redirect, ChdirMode};
@ -24,7 +22,8 @@ use anyhow::*;
use getopts::Options; use getopts::Options;
use log::info; use log::info;
use simplelog::{LevelFilter, SimpleLogger, TermLogger, TerminalMode}; use simplelog::{LevelFilter, SimpleLogger, TermLogger, TerminalMode};
use std::path::Path; use std::fs;
use std::path::PathBuf;
mod config; mod config;
mod db; mod db;
@ -52,15 +51,33 @@ fn daemonize(options: &getopts::Matches) -> Result<()> {
if options.opt_present("f") { if options.opt_present("f") {
return Ok(()); return Ok(());
} }
let mut log_file = utils::get_data_root()?;
log_file.push("polaris.log"); let log_path = options
let pid = match daemonize_redirect(Some(&log_file), Some(&log_file), ChdirMode::NoChdir) { .opt_str("log")
.map(PathBuf::from)
.unwrap_or_else(|| {
let mut path = PathBuf::from(option_env!("POLARIS_LOG_DIR").unwrap_or("."));
path.push("polaris.log");
path
});
fs::create_dir_all(&log_path.parent().unwrap())?;
let pid = match daemonize_redirect(Some(&log_path), Some(&log_path), ChdirMode::NoChdir) {
Ok(p) => p, Ok(p) => p,
Err(e) => bail!("Daemonize error: {:#?}", e), Err(e) => bail!("Daemonize error: {:#?}", e),
}; };
let mut pid_path = utils::get_data_root()?;
pid_path.push("polaris.pid"); let pid_path = options
let mut file = File::create(pid_path)?; .opt_str("pid")
.map(PathBuf::from)
.unwrap_or_else(|| {
let mut path = PathBuf::from(option_env!("POLARIS_PID_DIR").unwrap_or("."));
path.push("polaris.pid");
path
});
fs::create_dir_all(&pid_path.parent().unwrap())?;
let mut file = fs::File::create(pid_path)?;
file.write_all(pid.to_string().as_bytes())?; file.write_all(pid.to_string().as_bytes())?;
Ok(()) Ok(())
} }
@ -113,8 +130,16 @@ fn main() -> Result<()> {
options.optopt("w", "web", "set the path to web client files", "DIRECTORY"); options.optopt("w", "web", "set the path to web client files", "DIRECTORY");
options.optopt("s", "swagger", "set the path to swagger files", "DIRECTORY"); options.optopt("s", "swagger", "set the path to swagger files", "DIRECTORY");
options.optopt( options.optopt(
"l", "",
"log", "cache",
"set the directory to use as cache",
"DIRECTORY",
);
options.optopt("", "log", "set the path to the log file", "FILE");
options.optopt("", "pid", "set the path to the pid file", "FILE");
options.optopt(
"",
"log-level",
"set the log level to a value between 0 (off) and 3 (debug)", "set the log level to a value between 0 (off) and 3 (debug)",
"LEVEL", "LEVEL",
); );
@ -137,7 +162,7 @@ fn main() -> Result<()> {
return Ok(()); return Ok(());
} }
let log_level = match matches.opt_str("l").as_ref().map(String::as_ref) { let log_level = match matches.opt_str("log-level").as_ref().map(String::as_ref) {
Some("0") => LevelFilter::Off, Some("0") => LevelFilter::Off,
Some("1") => LevelFilter::Error, Some("1") => LevelFilter::Error,
Some("2") => LevelFilter::Info, Some("2") => LevelFilter::Info,
@ -151,60 +176,73 @@ fn main() -> Result<()> {
daemonize(&matches)?; daemonize(&matches)?;
// Init DB // Init DB
info!("Starting up database"); let db_path = matches.opt_str("d").map(PathBuf::from).unwrap_or_else(|| {
let db_path = matches.opt_str("d"); let mut path = PathBuf::from(option_env!("POLARIS_DB_DIR").unwrap_or("."));
let mut default_db_path = utils::get_data_root()?; path.push("db.sqlite");
default_db_path.push("db.sqlite"); path
let db_path = db_path });
.map(|n| Path::new(n.as_str()).to_path_buf()) fs::create_dir_all(&db_path.parent().unwrap())?;
.unwrap_or(default_db_path); info!("Database file path is {}", db_path.display());
let db = db::DB::new(&db_path)?; let db = db::DB::new(&db_path)?;
// Parse config // Parse config
info!("Parsing configuration"); if let Some(config_path) = matches.opt_str("c").map(PathBuf::from) {
let config_file_name = matches.opt_str("c"); let config = config::parse_toml_file(&config_path)?;
let config_file_path = config_file_name.map(|p| Path::new(p.as_str()).to_path_buf()); info!("Applying configuration from {}", config_path.display());
if let Some(path) = config_file_path {
let config = config::parse_toml_file(&path)?;
info!("Applying configuration");
config::amend(&db, &config)?; config::amend(&db, &config)?;
} }
let auth_secret = config::get_auth_secret(&db)?; let auth_secret = config::get_auth_secret(&db)?;
// Init index // Locate web client files
info!("Initializing index"); let web_dir_path = match matches
let index = index::builder(db.clone()).periodic_updates(true).build(); .opt_str("w")
.or(option_env!("POLARIS_WEB_DIR").map(String::from))
// API mount target {
let api_url = "/api".to_owned(); Some(s) => PathBuf::from(s),
info!("Mounting API on {}", api_url); None => [".", "web"].iter().collect(),
};
// Web client mount target fs::create_dir_all(&web_dir_path)?;
let web_dir_name = matches.opt_str("w");
let mut default_web_dir = utils::get_data_root()?;
default_web_dir.push("web");
let web_dir_path = web_dir_name
.map(|n| Path::new(n.as_str()).to_path_buf())
.unwrap_or(default_web_dir);
info!("Static files location is {}", web_dir_path.display()); info!("Static files location is {}", web_dir_path.display());
let web_url = "/".to_owned();
info!("Mounting web client files on {}", web_url);
// Swagger files mount target // Locate swagger files
let swagger_dir_name = matches.opt_str("s"); let swagger_dir_path = match matches
let mut default_swagger_dir = utils::get_data_root()?; .opt_str("s")
default_swagger_dir.push("swagger"); .or(option_env!("POLARIS_SWAGGER_DIR").map(String::from))
let swagger_dir_path = swagger_dir_name {
.map(|n| Path::new(n.as_str()).to_path_buf()) Some(s) => PathBuf::from(s),
.unwrap_or(default_swagger_dir); None => [".", "docs", "swagger"].iter().collect(),
};
fs::create_dir_all(&swagger_dir_path)?;
info!("Swagger files location is {}", swagger_dir_path.display()); info!("Swagger files location is {}", swagger_dir_path.display());
// Initialize thumbnails manager
let mut thumbnails_path = PathBuf::from(
matches
.opt_str("cache")
.or(option_env!("POLARIS_CACHE_DIR").map(String::from))
.unwrap_or(".".to_owned()),
);
thumbnails_path.push("thumbnails");
fs::create_dir_all(&thumbnails_path)?;
info!("Thumbnails location is {}", thumbnails_path.display());
let thumbnails_manager = thumbnails::ThumbnailsManager::new(&thumbnails_path);
// Endpoints
let api_url = "/api".to_owned();
let swagger_url = "/swagger".to_owned(); let swagger_url = "/swagger".to_owned();
let web_url = "/".to_owned();
info!("Mounting API on {}", api_url);
info!("Mounting web client files on {}", web_url);
info!("Mounting swagger files on {}", swagger_url); info!("Mounting swagger files on {}", swagger_url);
// Thumbnails manager // Init index
let mut thumbnails_path = utils::get_data_root()?; let index = index::builder(db.clone()).periodic_updates(true).build();
thumbnails_path.push("thumbnails");
let thumbnails_manager = thumbnails::ThumbnailsManager::new(thumbnails_path.as_path()); // Start DDNS updates
let db_ddns = db.clone();
std::thread::spawn(move || {
ddns::run(&db_ddns);
});
// Start server // Start server
info!("Starting up server"); info!("Starting up server");
@ -229,12 +267,6 @@ fn main() -> Result<()> {
); );
}); });
// Start DDNS updates
let db_ddns = db.clone();
std::thread::spawn(move || {
ddns::run(&db_ddns);
});
// Send readiness notification // Send readiness notification
notify_ready(); notify_ready();

View file

@ -1,7 +1,4 @@
use anyhow::*; use std::path::Path;
use app_dirs::{app_root, AppDataType, AppInfo};
use std::fs;
use std::path::{Path, PathBuf};
#[macro_export] #[macro_export]
macro_rules! match_ignore_case { macro_rules! match_ignore_case {
@ -15,26 +12,6 @@ macro_rules! match_ignore_case {
} }
pub use crate::match_ignore_case; pub use crate::match_ignore_case;
#[cfg(target_family = "windows")]
const APP_INFO: AppInfo = AppInfo {
name: "Polaris",
author: "Permafrost",
};
#[cfg(not(target_family = "windows"))]
const APP_INFO: AppInfo = AppInfo {
name: "polaris",
author: "permafrost",
};
pub fn get_data_root() -> Result<PathBuf> {
if let Ok(root) = app_root(AppDataType::UserData, &APP_INFO) {
fs::create_dir_all(&root)?;
return Ok(root);
}
bail!("Could not retrieve data directory root");
}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum AudioFormat { pub enum AudioFormat {
APE, APE,