Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save sathyarajshetigar/1ae6533da2226e4cfd4a8fa4c086c3fb to your computer and use it in GitHub Desktop.
Save sathyarajshetigar/1ae6533da2226e4cfd4a8fa4c086c3fb to your computer and use it in GitHub Desktop.
cocoapods.cmd
@echo off
rem // iOS build environment CocoaPods daemon control script by Pierre-Marie Baty <[email protected]>
setlocal enableextensions enabledelayedexpansion
goto startup
:usage
echo.
echo %SCRIPT_NAME% - Pierre-Marie Baty's cocoapods daemon for Windows
echo Part of the iOS Build Environment - https://www.pmbaty.com/iosbuildenv/
echo.
echo This daemon implements an almost Darwin-compatible BSD UNIX subsystem that
echo is able to run CocoaPods unmodified, without the crippling NTFS limitations
echo imposed by Microsoft on their operating systems.
echo.
echo Usage: cocoapods ^<start^|stop^|status^|command^>
echo.
echo start: starts up the CocoaPods daemon ^(this can take up to one minute^)
echo stop: shuts down a running CocoaPods daemon
echo wait: waits until the CocoaPods daemon becomes ready
echo status: reports the daemon status ^(ready, busy or stopped^)
echo.
echo command: CocoaPods command to issue ^(for example "pod install"^)
echo.
echo "cd" to where your Podfile is, then issue your CocoaPods command, e.g. run
echo "%SCRIPT_NAME% pod install".
echo -- "Please, one miracle at a time."
goto exit_success
:startup
rem // DO NOT switch to the UTF-8 codepage, IT BREAKS THE find.exe UTILITY AND POSSIBLY OTHERS!
rem // chcp 65001 > nul
rem // figure out where we are
set SCRIPT_NAME=%~nx0
set SCRIPT_ARGS=%*
set SCRIPT_DIRECTORY=%~dp0
rem // CocoaPod daemon options. Max memory is in megabytes.
set MAX_MEMORY=4096
set LISTEN_PORT=15051
set AUTOSHUTDOWN_SECONDS=600
rem // cocoapods.img MD5
set VALID_MD5=dd6ca337e9797111bc50d1115508e42a
rem // useful shortcuts
set SSH=.\ssh.exe -p %LISTEN_PORT% -o StrictHostKeyChecking=no -i cocoapods.key
set SEND_COMMAND_AS_ROOT=%SSH% [email protected]
set SEND_COMMAND_AS_USER=%SSH% [email protected]
set IS_DAEMON_RUNNING=tasklist^|find "cocoapods-daemon.exe" ^> nul 2^>^&1
set IS_DAEMON_READY=%SEND_COMMAND_AS_ROOT% -o ConnectTimeout=1 -o ConnectionAttempts=1 "if ps ax|grep cocoapods@|grep -v grep > /dev/null; then false; else true; fi" ^> nul 2^>^&1
set WAIT_ONE_SECOND=timeout /t 1 /nobreak ^> nul
rem // position ourselves in the script directory
set ORIGINAL_DIR=%CD%
pushd
cd /d "!SCRIPT_DIRECTORY!"
rem // unless already running, make sure we have enough physical memory to run: !MAX_MEMORY! Mb minimum.
wmic os get FreePhysicalMemory|find /v "FreePhysicalMemory" > .memtest.txt 2> nul & set AVAILABLE_MEMORY=0& set /p AVAILABLE_MEMORY=< .memtest.txt & del /f /q .memtest.txt > nul 2>&1
set /a AVAILABLE_MEMORY=%AVAILABLE_MEMORY%/1024
rem // DO NOT CHANGE A SINGLE CHARACTER OF THE LINE BELOW: DELAYED EVALUATION WON'T WORK
%IS_DAEMON_RUNNING% || if %AVAILABLE_MEMORY% LSS %MAX_MEMORY% (
echo.
echo It seems your computer doesn't have enough free memory to safely run the
echo cocoaPods daemon. You need %MAX_MEMORY% Mb free to run the BSD subsystem
echo and it seems you have only %AVAILABLE_MEMORY% Mb available.
echo Close a few memory-hungry programs if possible and try again.
echo.
goto :exit_error
)
rem // check for proper registration
if not exist cocoapods.key (
echo.
echo It appears your version of the CocoaPods daemon hasn't been registered yet.
echo This service is a separate, optional module of the build environment and
echo requires separate activation.
echo.
echo To use the Windows CocoaPods daemon, please obtain your credentials from
echo https://www.pmbaty.com/iosbuildenv/cocoapods/
echo [InternetShortcut]> activation.url
echo URL=https://www.pmbaty.com/iosbuildenv/cocoapods/>> activation.url
start /I "" activation.url
echo.
echo When you have received them by e-mail, enter them here:
set /p ACTIVATION_EMAIL=Activation email:
if "_!ACTIVATION_EMAIL!_"=="__" goto :exit_error
set /p ACTIVATION_CODE=Associated code:
if "_!ACTIVATION_CODE!_"=="__" goto :exit_error
del /f /q activation.url > nul 2>&1
.\curl.exe -# -f -o cocoapods.key.tmp https://www.pmbaty.com/iosbuildenv/cocoapods/keys/!ACTIVATION_EMAIL!-!ACTIVATION_CODE! && (
echo Bag Attributes> cocoapods.key
echo friendlyName: CocoaPods daemon private key for !ACTIVATION_EMAIL!>>cocoapods.key
type cocoapods.key.tmp >> cocoapods.key
del cocoapods.key.tmp > nul 2>&1
echo.
echo Your key was successfully installed. Thank you^!
) || (
echo.
echo There was an error retrieving your private key. Maybe you misspelled
echo the activation email or its associated code. Please try again.
echo.
goto :exit_error
)
)
rem // check for presence of the BSD filesystem
if not exist cocoapods.img (
echo.
echo Downloading and setting up the BSD UNIX filesystem, please wait...
echo This step is only done once. Around 350 Mb are being downloaded.
echo The process will continue when this step is finished.
echo.
:download_again
.\curl.exe -# -f -o cocoapods.img https://www.pmbaty.com/iosbuildenv/cocoapods/cocoapods.img || (
rem // delete any partially downloaded filesystem
del /f /q cocoapods.img > nul 2>&1
echo.
echo It seems the download couldn't complete. Maybe your Internet link is having
echo problems? Please try again later.
echo Anyway, the CocoaPods daemon cannot start without this file. Exiting.
echo.
goto :exit_error
)
rem // verify the downloaded file
certutil -hashfile cocoapods.img MD5|find /v "cocoapods.img"|find /v "hashfile" > .hash.txt 2> nul & set CURRENT_MD5=& set /p CURRENT_MD5=< .hash.txt & del /f /q .hash.txt > nul 2>&1
set CURRENT_MD5=!CURRENT_MD5: =!
if /i "_!CURRENT_MD5!_" NEQ "_!VALID_MD5!_" (
echo.
echo The MD5 checksum of the downloaded file is wrong. Looks like the download
echo was corrupt. Trying again...
echo.
goto :download_again
)
rem // cocoapods.img was downloaded and its MD5 is good
echo.
echo Download complete.
echo.
echo NOTICE: when run for the first time, CocoaPods downloads more than a GIGABYTE
echo of data to create a local database of all the available Pods. Be warned that
echo it *WILL* take time ^(maybe hours^) and occupy quite some disk space.
echo.
)
rem // interpret and run the requested command
if "_%1"=="_" goto :usage
if "_%1"=="_start" (
rem // start up the CocoaPods daemon
%IS_DAEMON_RUNNING% && (
echo The CocoaPods daemon is already running.
goto :exit_error
)
rem // DO NOT USE ACCELERATION - boot times are dramatically lenghtened. Bug still affecting FreeBSD 12 on qemu. No known fix.
rem //
rem // rem // ACCELERATION:
rem // rem // Neither Microsoft Hyper-V nor its predecessor Microsoft Hypervisor Platform are guaranteed to be available on Windows 7.
rem // rem // To use an ubiquitous hypervisor driver we need to rely on the Intel HAXM driver.
set ACCEL_FLAG=
rem // rem // is the VT-D functionality simply not available on this platform ?
rem // haxm\haxm_check.exe|find /c " -- yes"|find "2" > nul || (
rem // echo.
rem // echo INFO: your processor doesn't support hardware accelerated virtualization. The
rem // echo CocoaPods daemon will run in software emulation mode. This will be very slow^!
rem // )
rem // rem // is ***OUR*** HAXM driver NOT installed yet ? if so, install it
rem // if not exist "haxm\.haxm_install\haxm_install.log" (
rem // echo.
rem // echo INFO: it is highly recommended that you install the Intel Hardware Accelerated
rem // echo eXecution Manager to greatly accelerate the CocoaPods daemon. Please allow the
rem // echo following installer to do so. It requires Administrator permissions.
rem // echo.
rem // rem //powershell Start-Process -Wait -FilePath "haxm\haxm_install.bat" -verb runas
rem // if "_!PROCESSOR_ARCHITECTURE!_"=="_AMD64_" set MSI_NAME=hax64.msi
rem // if not "_!PROCESSOR_ARCHITECTURE!_"=="_AMD64_" set MSI_NAME=hax.msi
rem // haxm\haxm_install.exe -f haxm\.haxm_install -a /qn /le haxm_install.log MEMSIZETYPE=1 CUSTOMMEMSIZE=0 NOTCHECKVTENABLE=1 && echo Intel Hardware Accelerated eXecution Manager successfully installed.|| (
rem // echo Intel Hardware Accelerated eXecution Manager installation failed.
rem // echo.
rem // echo Install log:
rem // type haxm\.haxm_install\haxm_install.log
rem // )
rem // echo.
rem // )
rem // rem // now, is the HAXM driver installed AND available ? if so, use it
rem // haxm\haxm_check.exe|find /c " -- yes"|find "2" > nul && if exist "%WINDIR%\system32\drivers\IntelHaxm.sys" set ACCEL_FLAG=-accel hax
rem // finally, start the CocoaPods daemon
echo Starting CocoaPods daemon ^(this can take some time, please wait...^)
rem // need to use this VBS trick to effectively detach from the Win10 console. Watch your eyes.
echo CreateObject^("WScript.Shell"^).Run ".\cocoapods-daemon.exe -nodefaults -nographic !ACCEL_FLAG! -m !MAX_MEMORY!M -hda cocoapods.img -net nic -net user,hostfwd=tcp::!LISTEN_PORT!-:22", 0 1> daemon-start.vbs & wscript daemon-start.vbs
%WAIT_ONE_SECOND%
%IS_DAEMON_RUNNING% || (
rem // daemon still not kicked up. If we were trying the accelerated version, try the software emulation mode.
if not "_!ACCEL_FLAG!_"=="__" (
echo Looks like the CocoaPods daemon refused to start. Trying again with acceleration disabled.
echo CreateObject^("WScript.Shell"^).Run ".\cocoapods-daemon.exe -nodefaults -nographic -m !MAX_MEMORY!M -hda cocoapods.img -net nic -net user,hostfwd=tcp::!LISTEN_PORT!-:22", 0 1> daemon-start.vbs & wscript daemon-start.vbs
%WAIT_ONE_SECOND%
)
%IS_DAEMON_RUNNING% || (echo ERROR: The CocoaPods daemon definitely won't start. Something's wrong with your installation.& del /f /q daemon-start.vbs& goto :exit_error)
)
del /f /q daemon-start.vbs
rem // waits for the CocoaPods daemon to be in a ready state
set WAITED_SECONDS=0
set MAX_SECONDS=120
if not "_%2"=="_" set /a MAX_SECONDS=%2>nul
:start_wait
%IS_DAEMON_READY% || (
%WAIT_ONE_SECOND%
set /a WAITED_SECONDS=!WAITED_SECONDS!+1> nul
if !WAITED_SECONDS! LSS !MAX_SECONDS! goto :start_wait
)
if !WAITED_SECONDS! GEQ !MAX_SECONDS! (
echo CocoaPods daemon still busy after !MAX_SECONDS! seconds. Aborting start.
taskkill /im cocoapods-daemon.exe
%WAIT_ONE_SECOND%
goto :exit_error
)
rem // at this point the CocoaPods daemon is started and ready to accept commands
rem // send him the inactivity watchdog to bark around the place. If no opened SSH session in AUTOSHUTDOWN_SECONDS, shutdown the subsystem.
!SEND_COMMAND_AS_ROOT! "IDLE_COUNT=0; while true; do sleep 10; ps ax|grep 'sshd: '|grep -v grep > /dev/null && IDLE_COUNT=0 || IDLE_COUNT=$((IDLE_COUNT+1)); test $((IDLE_COUNT*10)) -gt %AUTOSHUTDOWN_SECONDS% && poweroff; done >&- 2>&- <&- &"
goto :exit_success
) else if "_%1"=="_stop" (
rem // shuts down the CocoaPods daemon
%IS_DAEMON_RUNNING% || (
echo The CocoaPods daemon is already stopped.
goto :exit_error
)
echo Stopping CocoaPods daemon...
!SEND_COMMAND_AS_ROOT! poweroff > nul 2>&1
set WAITED_SECONDS=0
set MAX_SECONDS=30
if not "_%2"=="_" set /a MAX_SECONDS=%2>nul
:stop_wait
%IS_DAEMON_RUNNING% && (
%WAIT_ONE_SECOND%
set /a WAITED_SECONDS=!WAITED_SECONDS!+1> nul
if !WAITED_SECONDS! LSS !MAX_SECONDS! goto :stop_wait
)
if !WAITED_SECONDS! GEQ !MAX_SECONDS! (
echo CocoaPods daemon still running after !MAX_SECONDS! seconds. Killing it.
taskkill /im cocoapods-daemon.exe
%WAIT_ONE_SECOND%
goto :stop_wait
)
goto :exit_success
) else if "_%1"=="_wait" (
rem // waits for the CocoaPods daemon to be in a ready state
%IS_DAEMON_RUNNING% || (
echo The CocoaPods daemon is not running.
goto :exit_error
)
echo Waiting for CocoaPods daemon to be ready...
set WAITED_SECONDS=0
set MAX_SECONDS=120
if not "_%2"=="_" set /a MAX_SECONDS=%2>nul
:wait_wait
%IS_DAEMON_READY% || (
%WAIT_ONE_SECOND%
set /a WAITED_SECONDS=!WAITED_SECONDS!+1> nul
if !WAITED_SECONDS! LSS !MAX_SECONDS! goto :wait_wait
)
if !WAITED_SECONDS! GEQ !MAX_SECONDS! (
echo CocoaPods daemon still busy after !MAX_SECONDS! seconds. Aborting wait.
goto :exit_error
)
goto :exit_success
) else if "_%1"=="_status" (
rem // returns whether the CocoaPods daemon is "ready", "busy" or "stopped"
set STATE=in an unknown state
%IS_DAEMON_READY% && set STATE=ready|| (%IS_DAEMON_RUNNING% && set STATE=busy|| set STATE=stopped)
echo The CocoaPods daemon is !STATE!.
goto :exit_success
) else if "_%1"=="_reset" (
rem // undocumented: nuke the CocoaPods database and cache
%IS_DAEMON_RUNNING% || call %0 start
%IS_DAEMON_READY% || call %0 wait
rem // clear the working directory on both sides of the pipe, and the CocoaPods caches on the subsystem side
echo Resetting CocoaPods...
rmdir /s /q staging & mkdir staging
!SEND_COMMAND_AS_USER! "killall -q pod && sleep 3; killall -q -KILL pod; rm -rf .cocoapods Library/Caches/CocoaPods staging/*"
set RET=!errorlevel!
goto :exit
) else (
rem // sends a command to the CocoaPods daemon
%IS_DAEMON_RUNNING% || call %0 start
%IS_DAEMON_READY% || call %0 wait
rem // clear the working directory on both sides of the pipe
rem // note that if the ".podspecs_cloning_succeeded" file doesn't exist yet, it's a good idea to wipe the CocoaPods specs cache so as to let it start again cleanly
echo Preparing staging directory...
rmdir /s /q staging 2>nul & mkdir staging
!SEND_COMMAND_AS_USER! "cd staging && rm -rf *; if [ ! -f ~/.podspecs_cloning_succeeded ]; then killall -q pod && sleep 3; killall -q -KILL pod; rm -rf .cocoapods Library/Caches/CocoaPods; fi"
rem // for a reason unknown to me, /dev/null seems to switch to 600 permissions sometimes. Fix that
!SEND_COMMAND_AS_ROOT! "chmod 666 /dev/null"
rem // populate our working directory with our Podfile and project(s)
if exist "!ORIGINAL_DIR!\Podfile" (
echo Sending Podfile and context...
rem // copy the Podfile
copy /b "!ORIGINAL_DIR!\Podfile" staging > nul
rem // copy ANY project.pbxproj file from inside the directory where we are, no matter its location, preserving directory structure
(for /f "tokens=1* delims=\" %%A in ('forfiles /p "!ORIGINAL_DIR!" /s /m project.pbxproj /c "cmd /c echo @relpath"') do for %%F in (^"%%B) do (mkdir "staging\%%~F"& rmdir "staging\%%~F"& copy /b "!ORIGINAL_DIR!\%%~F" "staging\%%~F" >nul)) 2>nul
rem // update CocoaPods daemon working directory from our working directory
.\rsync.exe -rtu -e "!SSH!" staging/* [email protected]:/Users/cocoapods/staging
rem // rsync breaks the UNIX ownerships and permissions when stupidly trying to map then from NTFS permissions. Reset them to something safe.
!SEND_COMMAND_AS_ROOT! "chown -R cocoapods:cocoapods /Users/cocoapods/staging; chmod -R 777 /Users/cocoapods/staging"
)
rem // the way is clear
shift
echo Sending command: %*
echo ========================== CocoaPods output BEGIN ===========================
!SEND_COMMAND_AS_USER! "cd staging && (%*) && if [ ! -f ~/.podspecs_cloning_succeeded ]; then touch ~/.podspecs_cloning_succeeded; fi"
set RET=!errorlevel!
echo =========================== CocoaPods output END ============================
rem // update working directory from the Cocoapods daemon working directory, resolving symlinks (-L)
if "_!RET!_"=="_0_" if exist "!ORIGINAL_DIR!\Podfile" (
echo Propagating filesystem changes ^(this can take some time, please wait^)...
set FILTERED_DIR=!ORIGINAL_DIR:\=/!
set DRIVE_LETTER=!FILTERED_DIR:~0,1!
set FILTERED_DIR=/cygdrive/!DRIVE_LETTER!/!FILTERED_DIR:~3!
rem // IMPORTANT: rsync MUST preserve symlinks when retrieving files from the CocoaPods staging directory, else
rem // clang will have no way to tell that an original header file and its symlinked version are the same file.
rem // Note that this version of rsync will create Cygwin-style symlinks, until I fix that.
.\rsync.exe -rtul -e "!SSH!" [email protected]:/Users/cocoapods/staging/* "!FILTERED_DIR!"
rem // rsync breaks the NTFS permissions stupidly trying to map then to UNIX permissions. Reset them.
takeown /r /f "!ORIGINAL_DIR!" > nul
icacls "!ORIGINAL_DIR!" /t /q /c /reset > nul
echo Done.
)
goto :exit
)
:exit_success
set RET=0
goto :exit
:exit_error
set RET=1
goto :exit
:exit
rem // return to where we were
popd
exit /b !RET!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment