From 701726a2f1d49b604b524c85c8df8a10bd2411ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sat, 16 Feb 2019 13:13:43 +0100 Subject: [PATCH 01/21] Added support for running MediaWEB as a windows service. Also, added a script build.bat to install and uninstall windows service --- .gitignore | 3 ++ appveyor.yml | 2 +- main.go => main_common.go | 5 +-- main_linux.go | 8 ++++ main_windows.go | 58 +++++++++++++++++++++++++++ scripts/build.bat | 2 +- scripts/install_deps.bat | 3 +- scripts/service.bat | 82 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 157 insertions(+), 6 deletions(-) rename main.go => main_common.go (84%) create mode 100644 main_linux.go create mode 100644 main_windows.go create mode 100644 scripts/service.bat diff --git a/.gitignore b/.gitignore index 72836fc..873023e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ tmpcache main-packr.go a_main-packr.go packrd +mediaweb +mediaweb.exe +mediaweb.log diff --git a/appveyor.yml b/appveyor.yml index 12d06e9..2cb758e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -33,7 +33,7 @@ build_script: # Windows and publish result on coveralls.io - cmd: '%GOPATH%/bin/goveralls -coverprofile=coverage.out -service=appveyor-ci -repotoken=%COVERALLS_TOKEN%' - cmd: '%GOPATH%\src\github.com\midstar\mediaweb\scripts\build.bat %APPVEYOR_BUILD_VERSION%' - - cmd: 7z a mediaweb_windows_x64.zip mediaweb.conf %GOPATH%\bin\mediaweb.exe + - cmd: 7z a mediaweb_windows_x64.zip mediaweb.conf mediaweb.exe # Linux PC/x64 - sh: 'sh $GOPATH/src/github.com/midstar/mediaweb/scripts/build.sh $APPVEYOR_BUILD_VERSION' diff --git a/main.go b/main_common.go similarity index 84% rename from main.go rename to main_common.go index ca37518..0ef6dc4 100644 --- a/main.go +++ b/main_common.go @@ -5,7 +5,7 @@ import ( "github.com/midstar/llog" ) -func main() { +func mainCommon() *WebAPI { s := loadSettings(findConfFile()) llog.SetLevel(s.logLevel) if s.logFile != "" { @@ -17,6 +17,5 @@ func main() { media := createMedia(s.mediaPath, s.thumbPath, s.enableThumbCache, s.autoRotate) box := packr.New("templates", "./templates") webAPI := CreateWebAPI(s.port, "templates", media, box) - httpServerDone := webAPI.Start() - <-httpServerDone // Block until http server is done + return webAPI } diff --git a/main_linux.go b/main_linux.go new file mode 100644 index 0000000..82c8f4a --- /dev/null +++ b/main_linux.go @@ -0,0 +1,8 @@ +// Main method for Linux systems +package main + +func main() { + webAPI := mainCommon() + httpServerDone := webAPI.Start() + <-httpServerDone // Block until http server is done +} diff --git a/main_windows.go b/main_windows.go new file mode 100644 index 0000000..195b16d --- /dev/null +++ b/main_windows.go @@ -0,0 +1,58 @@ +// Main method for Windows systems +package main + +import ( + "log" + "os" + + "github.com/kardianos/service" +) + +var logger service.Logger + +type program struct { + webAPI *WebAPI + workingDir string +} + +func (p *program) Start(s service.Service) error { + // Start should not block. Do the actual work async. + os.Chdir(p.workingDir) + p.webAPI = mainCommon() + go p.run() + return nil +} +func (p *program) run() { + p.webAPI.Start() +} +func (p *program) Stop(s service.Service) error { + // Stop should not block. Return with a few seconds. + p.webAPI.Stop() + return nil +} + +func main() { + workingDir := "" + if len(os.Args) > 1 { + workingDir = os.Args[1] + } + svcConfig := &service.Config{ + Name: "MediaWEB", + DisplayName: "MediaWEB", + Description: "WEB server for photos and videos", + } + + prg := &program{workingDir: workingDir} + s, err := service.New(prg, svcConfig) + if err != nil { + log.Fatal(err) + } + logger, err = s.Logger(nil) + if err != nil { + log.Fatal(err) + } + err = s.Run() + if err != nil { + logger.Error(err) + } +} diff --git a/scripts/build.bat b/scripts/build.bat index 2db354c..ea93131 100644 --- a/scripts/build.bat +++ b/scripts/build.bat @@ -17,6 +17,6 @@ set PACKRCMD=packr2 --legacy echo %PACKRCMD% %PACKRCMD% type main-packr.go -set INSTALLCMD=go install -ldflags="-X 'main.applicationBuildTime=%DATE% %TIME%' -X main.applicationVersion=%VERSION% -X main.applicationGitHash=%GITHASH%" github.com/midstar/mediaweb +set INSTALLCMD=go build -ldflags="-X 'main.applicationBuildTime=%DATE% %TIME%' -X main.applicationVersion=%VERSION% -X main.applicationGitHash=%GITHASH%" github.com/midstar/mediaweb echo %INSTALLCMD% %INSTALLCMD% diff --git a/scripts/install_deps.bat b/scripts/install_deps.bat index bdd300e..277dbc2 100644 --- a/scripts/install_deps.bat +++ b/scripts/install_deps.bat @@ -3,4 +3,5 @@ go get github.com/midstar/gocfg go get github.com/disintegration/imaging go get github.com/rwcarlsen/goexif/exif go get -u github.com/gobuffalo/packr/v2/... -go get -u github.com/gobuffalo/packr/v2/packr2 \ No newline at end of file +go get -u github.com/gobuffalo/packr/v2/packr2 +go get github.com/kardianos/service \ No newline at end of file diff --git a/scripts/service.bat b/scripts/service.bat new file mode 100644 index 0000000..27b4373 --- /dev/null +++ b/scripts/service.bat @@ -0,0 +1,82 @@ +@echo off + +REM MediaWEB windows service (un)installation batch script + +if [%1] EQU [install] ( + + if not exist mediaweb.exe ( + echo ERROR! mediaweb.exe needs to be in current directory + exit /b 1 + ) + + if not exist mediaweb.conf ( + echo ERROR! mediaweb.conf needs to be in current directory + exit /b 1 + ) + + echo ------------------------------------------ + echo Installing MediaWEB windows service + echo ------------------------------------------ + sc create mediaweb binpath="\"%cd%\mediaweb.exe\" \"%cd%\"" start= auto DisplayName= "MediaWEB" || ( + echo ERROR! Unable to create mediaweb service + exit /b 1 + ) + sc description mediaweb "MediaWEB Service" || ( + echo ERROR! Unable to create description for mediaweb service + echo. + echo Make sure you are running cmd.exe as an administrator + exit /b 1 + ) + sc start mediaweb || ( + echo ERROR! Unable to start mediaweb service + exit /b 1 + ) + sc query mediaweb || ( + echo ERROR! Unable to query mediaweb service + exit /b 1 + ) + + echo MediaWEB service successfully installed! + exit /b 0 + +) else if [%1] EQU [uninstall] ( + + echo ------------------------------------------ + echo Uninstalling MediaWEB windows service + echo ------------------------------------------ + + sc stop mediaweb + sc delete mediaweb || ( + exit /b 1 + ) + + echo Uninstallation complete! + exit /b 0 + +) else if [%1] EQU [] ( + call :print_usage +) else ( + echo ERROR! Unknown command '%1' + call :print_usage +) + +exit /b 0 + +:print_usage + echo. + echo Usage: + echo. + echo.NOTE! Start cmd.exe with administrator privileges. + echo. + echo.Update mediaweb.conf before installation. + echo. + echo For MediaWEB service installation: + echo. + echo service.bat install + echo. + echo. + echo For MediaWEB service uninstallation: + echo. + echo sudo sh service.sh uninstall + echo. + exit /b 1 From 43e6778a2152472c7dcdc6b2c658292be60a58d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sat, 16 Feb 2019 13:25:10 +0100 Subject: [PATCH 02/21] Added instructions on how to install windows service --- README.md | 12 +++++++++++- appveyor.yml | 2 +- mediaweb.conf | 6 +++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f75fc21..2231849 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,13 @@ Update the mediapath setting in mediaweb.conf. You might also want to change the Just start the mediaweb executable. It will look for the mediaweb.conf in the same folder. -It is currently not possible to run MediaWEB as a system service on Windows without any external software. +If you want to install mediaweb as a service, start cmd.exe in administrator mode and run: + + service.bat install + +To uinstall the service run: + + service.bat uninstall ## Build from source (any platform) @@ -97,6 +103,10 @@ The mediaweb executable and an example configuration file will be in $GOPATH/src/github.com/midstar/mediaweb. Edit the configuration file and then run the mediaweb executable. +To install as a Windows service start cmd.exe in administrator mode and run: + + scripts\service.bat install + On Linux platforms execute following to install MediaWEB as a service: sudo sh scripts/service.sh install diff --git a/appveyor.yml b/appveyor.yml index 2cb758e..552ca37 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -33,7 +33,7 @@ build_script: # Windows and publish result on coveralls.io - cmd: '%GOPATH%/bin/goveralls -coverprofile=coverage.out -service=appveyor-ci -repotoken=%COVERALLS_TOKEN%' - cmd: '%GOPATH%\src\github.com\midstar\mediaweb\scripts\build.bat %APPVEYOR_BUILD_VERSION%' - - cmd: 7z a mediaweb_windows_x64.zip mediaweb.conf mediaweb.exe + - cmd: 7z a mediaweb_windows_x64.zip mediaweb.conf mediaweb.exe scripts\service.bat # Linux PC/x64 - sh: 'sh $GOPATH/src/github.com/midstar/mediaweb/scripts/build.sh $APPVEYOR_BUILD_VERSION' diff --git a/mediaweb.conf b/mediaweb.conf index 90d0954..79cfa0c 100644 --- a/mediaweb.conf +++ b/mediaweb.conf @@ -23,9 +23,9 @@ thumbpath = tmpcache # to disable auto rotate of JPEG. #autorotate = off -# Logging is by default output on stderr. Uncomment -# below to log to a file. -#logfile = /yourdrive/mediaweb.log +# Uncomment below to log to to on stderr instead of a +# file +logfile = mediaweb.log # Logging level is by default info. Available levels # are trace, debug, info, warn, error and panic. From 7e9cb60cf172f5bd3f659895c7f7876f14dd0c38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sat, 16 Feb 2019 16:32:26 +0100 Subject: [PATCH 03/21] Fixed failure in Linux --- appveyor.yml | 3 ++- configs/mediaweb.conf | 36 ++++++++++++++++++++++++++++++++++++ main_windows.go | 4 +++- mediaweb.conf | 6 +++--- 4 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 configs/mediaweb.conf diff --git a/appveyor.yml b/appveyor.yml index 552ca37..d596949 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -33,11 +33,12 @@ build_script: # Windows and publish result on coveralls.io - cmd: '%GOPATH%/bin/goveralls -coverprofile=coverage.out -service=appveyor-ci -repotoken=%COVERALLS_TOKEN%' - cmd: '%GOPATH%\src\github.com\midstar\mediaweb\scripts\build.bat %APPVEYOR_BUILD_VERSION%' - - cmd: 7z a mediaweb_windows_x64.zip mediaweb.conf mediaweb.exe scripts\service.bat + - cmd: 7z a mediaweb_windows_x64.zip mediaweb.exe configs\mediaweb.conf scripts\service.bat # Linux PC/x64 - sh: 'sh $GOPATH/src/github.com/midstar/mediaweb/scripts/build.sh $APPVEYOR_BUILD_VERSION' - sh: 'cp scripts/service.sh .' + - sh: 'cp configs/mediaweb.conf .' - sh: tar -zcvf mediaweb_linux_x64.tar.gz mediaweb.conf mediaweb service.sh # Test service installation/uninstallation script diff --git a/configs/mediaweb.conf b/configs/mediaweb.conf new file mode 100644 index 0000000..385550c --- /dev/null +++ b/configs/mediaweb.conf @@ -0,0 +1,36 @@ +####################################################### +# This is a configuration file for mediaweb +####################################################### + +# Server network port. +# This parameter is MANDATORY +port = 9834 + +# Media path, i.e. where is your media located +# This parameter is MANADTORY +# +# For example: +# mediapath = /home/fobar/pictures +# mediapath = c:\users\fobar\pictures +mediapath = pictures + +# Thumb cache path is by default your operating systems +# temp folder + mediaweb. Uncomment below to set to +# another location. Not used if enablethumbcache = off. +# thumbpath = tmpcache + +# Thumb cache is by default on. Uncomment below to +# disable thumb cache +#enablethumbcache = off + +# Auto rotate of JPEG is by default on. Uncomment below +# to disable auto rotate of JPEG. +#autorotate = off + +# Logging is by default output on stderr. +logfile = mediaweb.log + +# Logging level is by default info. Available levels +# are trace, debug, info, warn, error and panic. +#loglevel = trace + diff --git a/main_windows.go b/main_windows.go index 195b16d..d6bb1bd 100644 --- a/main_windows.go +++ b/main_windows.go @@ -17,7 +17,9 @@ type program struct { func (p *program) Start(s service.Service) error { // Start should not block. Do the actual work async. - os.Chdir(p.workingDir) + if p.workingDir != "" { + os.Chdir(p.workingDir) + } p.webAPI = mainCommon() go p.run() return nil diff --git a/mediaweb.conf b/mediaweb.conf index 79cfa0c..470bdda 100644 --- a/mediaweb.conf +++ b/mediaweb.conf @@ -23,9 +23,9 @@ thumbpath = tmpcache # to disable auto rotate of JPEG. #autorotate = off -# Uncomment below to log to to on stderr instead of a -# file -logfile = mediaweb.log +# Logging is by default output on stderr. Uncomment +# below to log to a file. +#logfile = mediaweb.log # Logging level is by default info. Available levels # are trace, debug, info, warn, error and panic. From 2dc9f72a0f3b9536677bd4e96e092eae27e0e96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sat, 16 Feb 2019 16:39:57 +0100 Subject: [PATCH 04/21] Fixed so that config and service.bat is in not in a folder in the windows zip --- appveyor.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index d596949..da32541 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -33,13 +33,15 @@ build_script: # Windows and publish result on coveralls.io - cmd: '%GOPATH%/bin/goveralls -coverprofile=coverage.out -service=appveyor-ci -repotoken=%COVERALLS_TOKEN%' - cmd: '%GOPATH%\src\github.com\midstar\mediaweb\scripts\build.bat %APPVEYOR_BUILD_VERSION%' - - cmd: 7z a mediaweb_windows_x64.zip mediaweb.exe configs\mediaweb.conf scripts\service.bat + - sh: 'copy scripts\service.bat .' + - sh: 'copy configs\mediaweb.conf .' + - cmd: 7z a mediaweb_windows_x64.zip mediaweb.exe mediaweb.conf service.bat # Linux PC/x64 - sh: 'sh $GOPATH/src/github.com/midstar/mediaweb/scripts/build.sh $APPVEYOR_BUILD_VERSION' - sh: 'cp scripts/service.sh .' - sh: 'cp configs/mediaweb.conf .' - - sh: tar -zcvf mediaweb_linux_x64.tar.gz mediaweb.conf mediaweb service.sh + - sh: tar -zcvf mediaweb_linux_x64.tar.gz mediaweb mediaweb.conf service.sh # Test service installation/uninstallation script - sh: 'sudo -E sh scripts/service_test.sh' @@ -47,7 +49,7 @@ build_script: # Linux ARM (cross compile from linux x64) - sh: rm mediaweb - sh: 'sh $GOPATH/src/github.com/midstar/mediaweb/scripts/build_cross_arm.sh $APPVEYOR_BUILD_VERSION' - - sh: tar -zcvf mediaweb_linux_arm.tar.gz mediaweb.conf mediaweb service.sh + - sh: tar -zcvf mediaweb_linux_arm.tar.gz mediaweb mediaweb.conf service.sh # Deploy to GitHub (only on master AND on tags) deploy: From 6eaa39e783acf0bf556d4a0d1ab22145ef689a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sat, 16 Feb 2019 17:10:01 +0100 Subject: [PATCH 05/21] Added windows service script test --- appveyor.yml | 9 ++++++--- scripts/service_test.bat | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 scripts/service_test.bat diff --git a/appveyor.yml b/appveyor.yml index da32541..81c4706 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -33,17 +33,20 @@ build_script: # Windows and publish result on coveralls.io - cmd: '%GOPATH%/bin/goveralls -coverprofile=coverage.out -service=appveyor-ci -repotoken=%COVERALLS_TOKEN%' - cmd: '%GOPATH%\src\github.com\midstar\mediaweb\scripts\build.bat %APPVEYOR_BUILD_VERSION%' - - sh: 'copy scripts\service.bat .' - - sh: 'copy configs\mediaweb.conf .' + - cmd: 'copy scripts\service.bat .' + - cmd: 'copy configs\mediaweb.conf .' - cmd: 7z a mediaweb_windows_x64.zip mediaweb.exe mediaweb.conf service.bat + # Windows Test service installation/uninstallation script + - cmd: 'scripts/service_test.bat' + # Linux PC/x64 - sh: 'sh $GOPATH/src/github.com/midstar/mediaweb/scripts/build.sh $APPVEYOR_BUILD_VERSION' - sh: 'cp scripts/service.sh .' - sh: 'cp configs/mediaweb.conf .' - sh: tar -zcvf mediaweb_linux_x64.tar.gz mediaweb mediaweb.conf service.sh - # Test service installation/uninstallation script + # Linux Test service installation/uninstallation script - sh: 'sudo -E sh scripts/service_test.sh' # Linux ARM (cross compile from linux x64) diff --git a/scripts/service_test.bat b/scripts/service_test.bat new file mode 100644 index 0000000..c05e8fe --- /dev/null +++ b/scripts/service_test.bat @@ -0,0 +1,17 @@ +@echo off +REM Test of service.bat - both installation and uninstallation +cd %GOPATH%\src\github.com\midstar\mediaweb\ +call scripts\service.bat install || exit \b 1 +echo Waiting 2 seconds +timeout 2 > NUL +echo Testing connection +FOR /F "tokens=*" %%g IN ('curl -s -o /dev/null -w "%%{http_code}" http://localhost:9834') do (SET HTTP_STATUS=%%g) +if [%HTTP_STATUS%] NEQ [200] ( + echo Test Failed! Unable to connect to MediaWEB. + echo. + echo Expected status code 200, but got %HTTP_STATUS% + exit /b 1 +) +echo MediaWEB connected +call scripts\service.bat uninstall || exit \b 1 +echo Test passed! \ No newline at end of file From 799a6435619acc4f0789a26d0522159256868998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sat, 16 Feb 2019 19:26:25 +0100 Subject: [PATCH 06/21] Added NSIS installer script --- .gitignore | 1 + MediaWEB.url | 8 ++ scripts/windows_installer.nsi | 234 ++++++++++++++++++++++++++++++++++ testmedia/logo.ico | Bin 0 -> 129691 bytes 4 files changed, 243 insertions(+) create mode 100644 MediaWEB.url create mode 100644 scripts/windows_installer.nsi create mode 100644 testmedia/logo.ico diff --git a/.gitignore b/.gitignore index 873023e..d2a95f0 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ packrd mediaweb mediaweb.exe mediaweb.log +mediaweb_windows_x64_setup.exe diff --git a/MediaWEB.url b/MediaWEB.url new file mode 100644 index 0000000..6dabe4d --- /dev/null +++ b/MediaWEB.url @@ -0,0 +1,8 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,2 +[InternetShortcut] +IDList= +URL=http://localhost:9834/ +IconIndex=0 +HotKey=0 +IconFile=C:\Users\Joel\Go\src\github.com\midstar\mediaweb\testmedia\logo.ico diff --git a/scripts/windows_installer.nsi b/scripts/windows_installer.nsi new file mode 100644 index 0000000..ddc8797 --- /dev/null +++ b/scripts/windows_installer.nsi @@ -0,0 +1,234 @@ +; MediaWEB installer creator NSIS script +; +; Prerequisities: +; - GOPATH environment variable needs to be set correctly +; - mediaweb needs to be built (go build github.com/midstar/mediaweb) +; and the exe must be in the mediaweb folder +; +; Usage: +; - makensis -DVERSION= windows_installer.nsi +; ( should be in the format 1.1.1.1) +; +; The installer will be put in GOPATH\src\github.com\midstar\mediaweb folder +; +; +;------------------------------------------------- + +;-------------------------------- +;External dependencies / libraries + +; Use the NSIS Modern UI 2 +!include MUI2.nsh +!include x64.nsh + +;-------------------------------- +;Common definitions + +!define APPLICATION_NAME "MediaWEB" +!define APPLICATION_FOLDER "MediaWEB" +!define APPLICATION_SOURCE "$%GOPATH%\src\github.com\midstar\mediaweb" +!define APPLICATION_BINARY "$%GOPATH%\bin" + +; The application version. Override with /DVERSION flag +!ifndef VERSION +!define VERSION "0.0.0.0" +!endif + +; The name of the installer +Name "${APPLICATION_NAME} ${VERSION}" + +; The file to write +OutFile "${APPLICATION_SOURCE}\mediaweb_windows_x64_setup.exe" + +; The default installation directory +InstallDir $PROGRAMFILES64\${APPLICATION_FOLDER} + +; Registry key to check for directory (so if you install again, it will +; overwrite the old one automatically) +InstallDirRegKey HKLM "Software\${APPLICATION_FOLDER}" "Install_Dir" + +; Request application privileges +RequestExecutionLevel admin + +;-------------------------------- +;Interface Settings + +!define MUI_ABORTWARNING +!define MUI_ICON "${APPLICATION_SOURCE}\testmedia\logo.ico" + +;-------------------------------- +;Pages + +!insertmacro MUI_PAGE_LICENSE "${APPLICATION_SOURCE}\LICENSE.txt" +!insertmacro MUI_PAGE_COMPONENTS +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES +!define MUI_FINISHPAGE_RUN +!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink" +!define MUI_FINISHPAGE_RUN_TEXT "Launch MediaWEB User Interface" +!insertmacro MUI_PAGE_FINISH + +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +;-------------------------------- +;Languages + +!insertmacro MUI_LANGUAGE "English" + +;-------------------------------- +;Version Information + +VIProductVersion "${VERSION}" +VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "${APPLICATION_NAME}" +VIAddVersionKey /LANG=${LANG_ENGLISH} "Comments" "Share photos and videos on Internet" +VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "Joel Midstjarna" +VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalTrademarks" "-" +VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "Copyright Joel Midstjarna" +VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "${APPLICATION_NAME} Setup" +VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "${VERSION}" +VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductVersion" "${VERSION}" + +;----------------------------------------------------------------------------- +; Init function - executed before the installation starts +Function .onInit + + ;--------------------------------------------------------------------------- + ; Check if already installed + + ReadRegStr $R0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPLICATION_FOLDER}" "UninstallString" + StrCmp $R0 "" noPreviousInstaller + + MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "${APPLICATION_NAME} is already installed. $\n$\n\ + Click `OK` to remove the previous version or `Cancel` to cancel this upgrade." IDOK uninst + Abort + + ;Run the uninstaller + uninst: + ClearErrors + Exec $R0 + + noPreviousInstaller: + +FunctionEnd + + +;====================================================================================================================== +; Application install section +Section "${APPLICATION_NAME}" SectionMain + + SectionIn RO + + ; Set output path to the installation directory. + SetOutPath $INSTDIR + + ; Copy mediaweb binary + File "${APPLICATION_BINARY}\mediaweb.exe" + + ; Copy mediaweb default configuration + File "${APPLICATION_SOURCE}\configs\mediaweb.conf" + + ; Copy mediaweb URL + File "${APPLICATION_SOURCE}\MediaWEB.url" + + ; Copy mediaweb icon + File "${APPLICATION_SOURCE}\testmedia\logo.ico" + + ; Copy the templates + SetOutPath "$INSTDIR\templates" + File "${APPLICATION_SOURCE}\templates\*.*" + + ; Copy mediaweb + SetOutPath "$INSTDIR\client" + File "${APPLICATION_BINARY}\mediaweb.exe" + + + + ; Write the installation path into the registry + WriteRegStr HKLM SOFTWARE\${APPLICATION_FOLDER} "Install_Dir" "$INSTDIR" + + ; Write the version into the registry + WriteRegStr HKLM SOFTWARE\${APPLICATION_FOLDER} "Version" "${VERSION}" + + + ; Write the uninstall keys for Windows + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPLICATION_FOLDER}" "DisplayName" "${APPLICATION_NAME} ${VERSION}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPLICATION_FOLDER}" "Publisher" "Joel Midstjarna" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPLICATION_FOLDER}" "UninstallString" '"$INSTDIR\uninstall.exe"' + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPLICATION_FOLDER}" "DisplayIcon" "$\"$INSTDIR\logo.ico$\"" + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPLICATION_FOLDER}" "NoModify" 1 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPLICATION_FOLDER}" "NoRepair" 1 + WriteUninstaller "uninstall.exe" + + ;--------------------------------------------------------------- + ; Install and start the windows service + ClearErrors + ExecWait "sc create mediaweb binpath= $\"\$\"$INSTDIR\mediaweb.exe\$\" \$\"$INSTDIR\$\"$\" start= auto DisplayName= $\"MediaWEB$\"" + IfErrors 0 createOk + MessageBox MB_OK|MB_ICONSTOP "Unable to install mediaweb as a service." + Goto endService + + createOk: + ExecWait "sc description mediaweb $\"MediaWEB Service$\"" + IfErrors 0 descriptionOk + MessageBox MB_OK|MB_ICONSTOP "Unable to add description to mediaweb service." + Goto endService + + descriptionOk: + ExecWait "sc start mediaweb" + IfErrors 0 endService + MessageBox MB_OK|MB_ICONSTOP "Unable to start mediaweb service." + Goto endService + + endService: + +SectionEnd + + +;====================================================================================================================== +; Start menu shortcuts install section (can be disabled by the user) +Section "Start Menu Shortcuts" SectionStartMenu + + CreateDirectory "$SMPROGRAMS\${APPLICATION_FOLDER}" + CreateShortcut "$SMPROGRAMS\${APPLICATION_FOLDER}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 + CreateShortcut "$SMPROGRAMS\${APPLICATION_FOLDER}\MediaWEB.lnk" "$INSTDIR\MediaWEB.url" "" "$INSTDIR\logo.ico" 0 + +SectionEnd + + +;====================================================================================================================== +; Description of the sections +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${SectionMain} "Install and start ${APPLICATION_NAME}." + !insertmacro MUI_DESCRIPTION_TEXT ${SectionStartMenu} "Create Shortcuts on Start Menu." +!insertmacro MUI_FUNCTION_DESCRIPTION_END + + +;====================================================================================================================== +; Uninstaller section +Section "Uninstall" + + ; -------------------------------------------------------------------------- + ; Uninstall and stop mediaweb service + execWait "sc stop mediaweb" + execWait "sc delete mediaweb" + + ; Remove registry keys + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPLICATION_FOLDER}" + DeleteRegKey HKLM SOFTWARE\${APPLICATION_FOLDER} + + ; Remove shortcuts, if any + Delete "$SMPROGRAMS\${APPLICATION_FOLDER}\*.*" + RMDir "$SMPROGRAMS\${APPLICATION_FOLDER}" + + ; Remove installation directory + RMDir /r $INSTDIR\* + +SectionEnd + +;====================================================================================================================== +; Helper functions + +Function LaunchLink + ExecShell "" "$INSTDIR\MediaWEB.url" +FunctionEnd diff --git a/testmedia/logo.ico b/testmedia/logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..86c65d1ecd7a054c6c5d99341286abede5646093 GIT binary patch literal 129691 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�*5HQw~fEyI@=vP7>;liMK1wyy*KU^3Me?aZ!x8 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

)Vj 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 uzWXDt+rn#k5ASW Date: Sat, 16 Feb 2019 19:46:05 +0100 Subject: [PATCH 07/21] Better error printout when mediapath is wrong --- scripts/windows_installer.nsi | 10 +--------- templates/index.html | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/scripts/windows_installer.nsi b/scripts/windows_installer.nsi index ddc8797..da3637b 100644 --- a/scripts/windows_installer.nsi +++ b/scripts/windows_installer.nsi @@ -27,7 +27,7 @@ !define APPLICATION_NAME "MediaWEB" !define APPLICATION_FOLDER "MediaWEB" !define APPLICATION_SOURCE "$%GOPATH%\src\github.com\midstar\mediaweb" -!define APPLICATION_BINARY "$%GOPATH%\bin" +!define APPLICATION_BINARY "$%GOPATH%\src\github.com\midstar\mediaweb" ; The application version. Override with /DVERSION flag !ifndef VERSION @@ -134,14 +134,6 @@ Section "${APPLICATION_NAME}" SectionMain ; Copy mediaweb icon File "${APPLICATION_SOURCE}\testmedia\logo.ico" - ; Copy the templates - SetOutPath "$INSTDIR\templates" - File "${APPLICATION_SOURCE}\templates\*.*" - - ; Copy mediaweb - SetOutPath "$INSTDIR\client" - File "${APPLICATION_BINARY}\mediaweb.exe" - ; Write the installation path into the registry diff --git a/templates/index.html b/templates/index.html index 4e55dde..c9b1c84 100644 --- a/templates/index.html +++ b/templates/index.html @@ -356,7 +356,7 @@ success(JSON.parse(xhr.responseText)); } else { if (error) - error(xhr); + error(xhr.responseText + "\n\nMake sure you have updated the mediapath \nproperty in mediaweb.conf correctly!"); } } }; From dc1e8b9697ef472363e1539b3bd35ed8b89e602d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sat, 16 Feb 2019 19:49:14 +0100 Subject: [PATCH 08/21] Building setup in appveyor --- appveyor.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 81c4706..37e4e49 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -40,6 +40,9 @@ build_script: # Windows Test service installation/uninstallation script - cmd: 'scripts/service_test.bat' + # Windows create windows setup (installer) + - cmd: 'makensis -DVERSION=%APPVEYOR_BUILD_VERSION% %GOPATH%\src\github.com\midstar\mediaweb\scripts\windows_installer.nsi' + # Linux PC/x64 - sh: 'sh $GOPATH/src/github.com/midstar/mediaweb/scripts/build.sh $APPVEYOR_BUILD_VERSION' - sh: 'cp scripts/service.sh .' @@ -82,6 +85,8 @@ for: artifacts: - path: mediaweb_windows_x64.zip name: mediaweb_windows_x64.zip + - path: mediaweb_windows_x64_setup.exe + name: mediaweb_windows_x64_setup.exe # Special configurations for Linux - From 83c7200a7a9d293e3fd414873eaac095d4257527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sat, 16 Feb 2019 22:59:33 +0100 Subject: [PATCH 09/21] Added media directory selection --- scripts/windows_installer.nsi | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/scripts/windows_installer.nsi b/scripts/windows_installer.nsi index da3637b..0e56e58 100644 --- a/scripts/windows_installer.nsi +++ b/scripts/windows_installer.nsi @@ -62,6 +62,7 @@ RequestExecutionLevel admin !insertmacro MUI_PAGE_LICENSE "${APPLICATION_SOURCE}\LICENSE.txt" !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY +Page custom selectMediaPathPage selectMediaPathPageLeave !insertmacro MUI_PAGE_INSTFILES !define MUI_FINISHPAGE_RUN !define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink" @@ -112,10 +113,57 @@ Function .onInit FunctionEnd +;====================================================================================================================== +; Custom dialog Select Media Path + +Var Dialog +Var TextMediaPath + +Function selectMediaPathPage + !insertmacro MUI_HEADER_TEXT "Media Directory" "Provide photo and video directory to share." + + #Create Dialog and quit if error + nsDialogs::Create 1018 + Pop $Dialog + ${If} $Dialog == error + Abort + ${EndIf} + + ${NSD_CreateGroupBox} 5% 16u 90% 34u "Media directory" + Pop $0 + + ReadEnvStr $0 USERPROFILE + ${NSD_CreateDirRequest} 15% 30u 49% 12u "$0\Pictures" + Pop $TextMediaPath + + ${NSD_CreateBrowseButton} 65% 30u 20% 12u "Browse..." + Pop $0 + ${NSD_OnClick} $0 OnDirBrowse + + ${NSD_CreateLabel} 5% 70u 100% 12u "Note! You can always change this later by updating mediaweb.conf" + Pop $0 + + nsDialogs::Show +FunctionEnd + +Function OnDirBrowse + ${NSD_GetText} $TextMediaPath $0 + nsDialogs::SelectFolderDialog "Select Media Directory" "$0" + Pop $0 + ${If} $0 != error + ${NSD_SetText} $TextMediaPath "$0" + ${EndIf} +FunctionEnd + +Function selectMediaPathPageLeave + ${NSD_GetText} $TextMediaPath $0 +FunctionEnd ;====================================================================================================================== ; Application install section Section "${APPLICATION_NAME}" SectionMain + MessageBox MB_OK|MB_ICONSTOP "Mediapath = $0" + Quit SectionIn RO From ac74cfdb7b18a6ff2dc507951ad922a25a6347f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sat, 16 Feb 2019 23:43:48 +0100 Subject: [PATCH 10/21] Windows installer is done --- scripts/windows_installer.nsi | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/scripts/windows_installer.nsi b/scripts/windows_installer.nsi index 0e56e58..a91f293 100644 --- a/scripts/windows_installer.nsi +++ b/scripts/windows_installer.nsi @@ -162,20 +162,39 @@ FunctionEnd ;====================================================================================================================== ; Application install section Section "${APPLICATION_NAME}" SectionMain - MessageBox MB_OK|MB_ICONSTOP "Mediapath = $0" - Quit SectionIn RO ; Set output path to the installation directory. SetOutPath $INSTDIR + ; Create configuration file + FileOpen $4 "$INSTDIR\mediaweb.conf" w + + FileWrite $4 "port = 9834$\r$\n" + FileWrite $4 "$\r$\n" + FileWrite $4 "mediapath = $0$\r$\n" + FileWrite $4 "$\r$\n" + FileWrite $4 "# Thumb cache path is by default your operating systems$\r$\n" + FileWrite $4 "# temp folder + mediaweb. Uncomment below to set to$\r$\n" + FileWrite $4 "# another location. Not used if enablethumbcache = off.$\r$\n" + FileWrite $4 "#thumbpath =$\r$\n" + FileWrite $4 "$\r$\n" + FileWrite $4 "# Thumbnail cache is on by default$\r$\n" + FileWrite $4 "#enablethumbcache = off$\r$\n" + FileWrite $4 "$\r$\n" + FileWrite $4 "#autorotate = off$\r$\n" + FileWrite $4 "$\r$\n" + FileWrite $4 "logfile = mediaweb.log$\r$\n" + FileWrite $4 "$\r$\n" + FileWrite $4 "# Log level is 'info' by default$\r$\n" + FileWrite $4 "#loglevel = trace$\r$\n" + + FileClose $4 + ; Copy mediaweb binary File "${APPLICATION_BINARY}\mediaweb.exe" - ; Copy mediaweb default configuration - File "${APPLICATION_SOURCE}\configs\mediaweb.conf" - ; Copy mediaweb URL File "${APPLICATION_SOURCE}\MediaWEB.url" @@ -230,7 +249,7 @@ SectionEnd Section "Start Menu Shortcuts" SectionStartMenu CreateDirectory "$SMPROGRAMS\${APPLICATION_FOLDER}" - CreateShortcut "$SMPROGRAMS\${APPLICATION_FOLDER}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 + CreateShortcut "$SMPROGRAMS\${APPLICATION_FOLDER}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\logo.ico" 0 CreateShortcut "$SMPROGRAMS\${APPLICATION_FOLDER}\MediaWEB.lnk" "$INSTDIR\MediaWEB.url" "" "$INSTDIR\logo.ico" 0 SectionEnd From 8802d58464eb0b20e2e518aef2e464120c429faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sat, 16 Feb 2019 23:46:34 +0100 Subject: [PATCH 11/21] Updated readme --- README.md | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 2231849..7ba67d8 100644 --- a/README.md +++ b/README.md @@ -64,19 +64,12 @@ To uninstall MediaWEB run: ## Download and install on Windows (64bit) -Download mediaweb_windows_x64.zip [here on GitHub](https://github.com/midstar/mediaweb/releases). +Download mediaweb_windows_x64_setup.exe [here on GitHub](https://github.com/midstar/mediaweb/releases). -Update the mediapath setting in mediaweb.conf. You might also want to change the port setting. +Run the installer and follow the instructions. -Just start the mediaweb executable. It will look for the mediaweb.conf in the same folder. - -If you want to install mediaweb as a service, start cmd.exe in administrator mode and run: - - service.bat install - -To uinstall the service run: - - service.bat uninstall +To modyfy changes just edit mediaweb.conf in the installation directory and restart the mediaweb +service in task manager. ## Build from source (any platform) @@ -116,7 +109,7 @@ On Linux platforms execute following to install MediaWEB as a service: * Create thumbnails for videos (probably using ffmpeg) * Add support for TLS/SSL -* Add Windows installer (install MediaWEB as a service on Windows) + ## Author and license From 01dd37d3542e30c5b0f9ec3cf2f8d7e828352afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sat, 16 Feb 2019 23:49:51 +0100 Subject: [PATCH 12/21] Fixed ineffassign from goreport --- media.go | 3 +-- media_test.go | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/media.go b/media.go index 3d2682f..197314e 100644 --- a/media.go +++ b/media.go @@ -272,8 +272,7 @@ func (m *Media) writeEXIFThumbnail(w io.Writer, relativeFilePath string) error { case 8: outImg = imaging.Rotate90(img) } - err = imaging.Encode(w, outImg, imaging.JPEG) - //return err + imaging.Encode(w, outImg, imaging.JPEG) } else { // No rotation is needed w.Write(thumbBytes) diff --git a/media_test.go b/media_test.go index bb818bf..84f775b 100644 --- a/media_test.go +++ b/media_test.go @@ -153,7 +153,7 @@ func TestFullPath(t *testing.T) { assertExpectNoErr(t, "unable to get valid full path", err) assertEqualsStr(t, "invalid path", "afile.jpg", p) - p, err = media.getFullMediaPath("../../secret_file") + _, err = media.getFullMediaPath("../../secret_file") assertExpectErr(t, "hackers shall not be allowed", err) // Relative path @@ -162,7 +162,7 @@ func TestFullPath(t *testing.T) { assertExpectNoErr(t, "unable to get valid full path", err) assertEqualsStr(t, "invalid path", "arelative/path/afile.jpg", p) - p, err = media.getFullMediaPath("../../secret_file") + _, err = media.getFullMediaPath("../../secret_file") assertExpectErr(t, "hackers shall not be allowed", err) // Absolute path @@ -171,7 +171,7 @@ func TestFullPath(t *testing.T) { assertExpectNoErr(t, "unable to get valid full path", err) assertEqualsStr(t, "invalid path", "/root/absolute/path/afile.jpg", p) - p, err = media.getFullMediaPath("../../secret_file") + _, err = media.getFullMediaPath("../../secret_file") assertExpectErr(t, "hackers shall not be allowed", err) } @@ -190,10 +190,10 @@ func TestThumbnailPath(t *testing.T) { assertExpectNoErr(t, "", err) assertEqualsStr(t, "", "/d/thumbpath/subdrive/_myimage.jpg", thumbPath) - thumbPath, err = media.thumbnailPath("subdrive/myimage") + _, err = media.thumbnailPath("subdrive/myimage") assertExpectErr(t, "", err) - thumbPath, err = media.thumbnailPath("subdrive/../../hacker") + _, err = media.thumbnailPath("subdrive/../../hacker") assertExpectErr(t, "", err) } From feae672285a5769b82067c59aff1a0e51e38f10c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sat, 16 Feb 2019 23:52:58 +0100 Subject: [PATCH 13/21] Fixed typo in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ba67d8..70938f9 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ Download mediaweb_windows_x64_setup.exe [here on GitHub](https://github.com/mids Run the installer and follow the instructions. -To modyfy changes just edit mediaweb.conf in the installation directory and restart the mediaweb +To modify changes just edit mediaweb.conf in the installation directory and restart the mediaweb service in task manager. ## Build from source (any platform) From 017be230f938d0081723245e8abced1851c31ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sun, 17 Feb 2019 00:16:58 +0100 Subject: [PATCH 14/21] Added some debugging since packr does not seem to work on windows --- scripts/build.bat | 2 +- webapi.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/build.bat b/scripts/build.bat index ea93131..317dce2 100644 --- a/scripts/build.bat +++ b/scripts/build.bat @@ -16,7 +16,7 @@ REM of relative paths. We use --legacy to fix this set PACKRCMD=packr2 --legacy echo %PACKRCMD% %PACKRCMD% -type main-packr.go set INSTALLCMD=go build -ldflags="-X 'main.applicationBuildTime=%DATE% %TIME%' -X main.applicationVersion=%VERSION% -X main.applicationGitHash=%GITHASH%" github.com/midstar/mediaweb echo %INSTALLCMD% +dir %INSTALLCMD% diff --git a/webapi.go b/webapi.go index 60b350f..75a8112 100644 --- a/webapi.go +++ b/webapi.go @@ -59,6 +59,7 @@ func (wa *WebAPI) Stop() { func (wa *WebAPI) ServeHTTP(w http.ResponseWriter, r *http.Request) { var head string originalURL := r.URL.Path + llog.Trace("Got request: %s", r.URL.Path) head, r.URL.Path = shiftPath(r.URL.Path) if head == "shutdown" && r.Method == "POST" { wa.Stop() @@ -89,7 +90,7 @@ func (wa *WebAPI) serveHTTPStatic(w http.ResponseWriter, r *http.Request) { bytes, err := wa.box.Find(fileName) if err != nil || len(bytes) == 0 { w.WriteHeader(http.StatusNotFound) - fmt.Fprintf(w, "This is not a valid path: %s!", r.URL.Path) + fmt.Fprintf(w, "Unable to find: %s!", fileName) } else { if filepath.Ext(fileName) == ".html" { w.Header().Set("Content-Type", "text/html") From 46f79c6a44f9c0a4c0ad8d75f37f86ba00e01ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sun, 17 Feb 2019 07:32:51 +0100 Subject: [PATCH 15/21] Fixed so that service_test.bat also verifies that packr is ok --- scripts/service_test.bat | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/scripts/service_test.bat b/scripts/service_test.bat index c05e8fe..3c421b2 100644 --- a/scripts/service_test.bat +++ b/scripts/service_test.bat @@ -1,9 +1,23 @@ @echo off REM Test of service.bat - both installation and uninstallation -cd %GOPATH%\src\github.com\midstar\mediaweb\ -call scripts\service.bat install || exit \b 1 + +pushd %GOPATH%\src\github.com\midstar\mediaweb\ + +REM Move files to a temporary folder to secure that packr +REM (embedded resources) works as expected +if not exist "tmpout" mkdir "tmpout" || exit \b 1 +mkdir tmpout\servicetest +copy mediaweb.exe tmpout\servicetest\mediaweb.exe || exit \b 1 +copy configs\mediaweb.conf tmpout\servicetest\mediaweb.conf || exit \b 1 +cd tmpout\servicetest || exit \b 1 + +set SCRIPTPATH=%GOPATH%\src\github.com\midstar\mediaweb\scripts + +call %SCRIPTPATH%\service.bat install || exit \b 1 + echo Waiting 2 seconds timeout 2 > NUL + echo Testing connection FOR /F "tokens=*" %%g IN ('curl -s -o /dev/null -w "%%{http_code}" http://localhost:9834') do (SET HTTP_STATUS=%%g) if [%HTTP_STATUS%] NEQ [200] ( @@ -13,5 +27,14 @@ if [%HTTP_STATUS%] NEQ [200] ( exit /b 1 ) echo MediaWEB connected -call scripts\service.bat uninstall || exit \b 1 -echo Test passed! \ No newline at end of file + +call %SCRIPTPATH%\service.bat uninstall || exit \b 1 + +if not exist mediaweb.log ( + echo Fail: mediaweb.log was not created! + exit \b 1 +) + +echo Test passed! + +popd \ No newline at end of file From 014331ae3553f0b5df6ff417bf87322b7a60000a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sun, 17 Feb 2019 07:39:32 +0100 Subject: [PATCH 16/21] Did the same for linux --- scripts/service_test.sh | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/scripts/service_test.sh b/scripts/service_test.sh index 7bb93af..8fcc5e6 100644 --- a/scripts/service_test.sh +++ b/scripts/service_test.sh @@ -1,6 +1,16 @@ # Test of service.sh - both installation and uninstallation cd $GOPATH/src/github.com/midstar/mediaweb/ -sh scripts/service.sh install $GOPATH/src/github.com/midstar/mediaweb/testmedia + +# Move files to a temporary folder to secure that packr +# (embedded resources) works as expected +mkdir -p tmpout +mkdir -p tmpout/servicetest +cp mediaweb tmpout/servicetest/mediaweb +cd tmpout/servicetest + +export SCRIPTPATH=$GOPATH/src/github.com/midstar/mediaweb/scripts + +sh $SCRIPTPATH/service.sh install $GOPATH/src/github.com/midstar/mediaweb/testmedia echo "Waiting 2 seconds" sleep 2 echo "Testing connection" @@ -11,5 +21,10 @@ if ! [ "$HTTP_STATUS" = "200" ]; then echo "Expected status code 200, but got $HTTP_STATUS" exit 1 fi -echo "Test passed :-)" -sh scripts/service.sh uninstall \ No newline at end of file +if ! [ -f "/var/mediaweb.log" ]; then + echo "Test Failed! No log file was created in /var/mediaweb.log" + echo + exit 1 +fi +sh $SCRIPTPATH/service.sh uninstall +echo "Test passed :-)" \ No newline at end of file From 18673516edcb4e5e6454c431c4f02133cf19253f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sun, 17 Feb 2019 07:44:21 +0100 Subject: [PATCH 17/21] Fixed bug in service test Linux --- scripts/service_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/service_test.sh b/scripts/service_test.sh index 8fcc5e6..f2dc4b7 100644 --- a/scripts/service_test.sh +++ b/scripts/service_test.sh @@ -21,7 +21,7 @@ if ! [ "$HTTP_STATUS" = "200" ]; then echo "Expected status code 200, but got $HTTP_STATUS" exit 1 fi -if ! [ -f "/var/mediaweb.log" ]; then +if ! [ -f "/var/log/mediaweb.log" ]; then echo "Test Failed! No log file was created in /var/mediaweb.log" echo exit 1 From 982a39c683e36e34a15d839f9f97664ce10245f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sun, 17 Feb 2019 07:53:30 +0100 Subject: [PATCH 18/21] More debug info on packr --- scripts/build.bat | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/build.bat b/scripts/build.bat index 317dce2..5cafb9c 100644 --- a/scripts/build.bat +++ b/scripts/build.bat @@ -16,6 +16,7 @@ REM of relative paths. We use --legacy to fix this set PACKRCMD=packr2 --legacy echo %PACKRCMD% %PACKRCMD% +type a_main-packr.go set INSTALLCMD=go build -ldflags="-X 'main.applicationBuildTime=%DATE% %TIME%' -X main.applicationVersion=%VERSION% -X main.applicationGitHash=%GITHASH%" github.com/midstar/mediaweb echo %INSTALLCMD% dir From 9955339f57253c88e920b7ff1c64f7c2c187cb7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sun, 17 Feb 2019 08:15:20 +0100 Subject: [PATCH 19/21] Added debugging for windows --- appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 37e4e49..f7accc3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -37,6 +37,10 @@ build_script: - cmd: 'copy configs\mediaweb.conf .' - cmd: 7z a mediaweb_windows_x64.zip mediaweb.exe mediaweb.conf service.bat + # Windows Debugging - remove later + - cmd: 'rename templates old_templates' + + # Windows Test service installation/uninstallation script - cmd: 'scripts/service_test.bat' From 20c6b9eed07b4ba7171298cb5029d8786db1c872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sun, 17 Feb 2019 08:24:13 +0100 Subject: [PATCH 20/21] Fixes that hopefully fixe packr bug --- appveyor.yml | 2 +- scripts/build.bat | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index f7accc3..099125c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -37,7 +37,7 @@ build_script: - cmd: 'copy configs\mediaweb.conf .' - cmd: 7z a mediaweb_windows_x64.zip mediaweb.exe mediaweb.conf service.bat - # Windows Debugging - remove later + # Windows rename tempates directory to secure that packr is working - cmd: 'rename templates old_templates' diff --git a/scripts/build.bat b/scripts/build.bat index 5cafb9c..0b2d0d9 100644 --- a/scripts/build.bat +++ b/scripts/build.bat @@ -13,11 +13,9 @@ echo building / installing cd %GOPATH%\src\github.com\midstar\mediaweb REM packr2 has a bug in Windows where absolute paths are generated instead REM of relative paths. We use --legacy to fix this -set PACKRCMD=packr2 --legacy -echo %PACKRCMD% -%PACKRCMD% -type a_main-packr.go -set INSTALLCMD=go build -ldflags="-X 'main.applicationBuildTime=%DATE% %TIME%' -X main.applicationVersion=%VERSION% -X main.applicationGitHash=%GITHASH%" github.com/midstar/mediaweb +REM set PACKRCMD=packr2 --legacy +REM echo %PACKRCMD% +REM %PACKRCMD% +set INSTALLCMD=packr2 build -ldflags="-X 'main.applicationBuildTime=%DATE% %TIME%' -X main.applicationVersion=%VERSION% -X main.applicationGitHash=%GITHASH%" github.com/midstar/mediaweb echo %INSTALLCMD% -dir %INSTALLCMD% From 0984e46ae7e1d2f0bda837ddc654ad257bc30e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Midstj=C3=A4rna?= Date: Sun, 17 Feb 2019 08:37:15 +0100 Subject: [PATCH 21/21] Workaround for packr bug --- scripts/build.bat | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/scripts/build.bat b/scripts/build.bat index 0b2d0d9..ba05131 100644 --- a/scripts/build.bat +++ b/scripts/build.bat @@ -11,11 +11,15 @@ for /f %%i in ('git rev-parse HEAD') do set GITHASH=%%i echo git hash: %GITHASH% echo building / installing cd %GOPATH%\src\github.com\midstar\mediaweb -REM packr2 has a bug in Windows where absolute paths are generated instead -REM of relative paths. We use --legacy to fix this -REM set PACKRCMD=packr2 --legacy -REM echo %PACKRCMD% -REM %PACKRCMD% -set INSTALLCMD=packr2 build -ldflags="-X 'main.applicationBuildTime=%DATE% %TIME%' -X main.applicationVersion=%VERSION% -X main.applicationGitHash=%GITHASH%" github.com/midstar/mediaweb +set PACKRCMD=packr2 +echo %PACKRCMD% +%PACKRCMD% +REM There is a bug in packr that creates absolute paths in main-packr.go on some +REM build machines (uncertain why). Replace main-packr.go with a new file +echo Replacing main-packr.go due to a bug in packr library +echo // +build !skippackr > main-packr.go +echo package main >> main-packr.go +echo import _ "github.com/midstar/mediaweb/packrd" >> main-packr.go +set INSTALLCMD=go build -ldflags="-X 'main.applicationBuildTime=%DATE% %TIME%' -X main.applicationVersion=%VERSION% -X main.applicationGitHash=%GITHASH%" github.com/midstar/mediaweb echo %INSTALLCMD% %INSTALLCMD%