nixenvironment 0.0.59 → 0.0.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/README.md +14 -14
  4. data/bin/Config +2 -2
  5. data/bin/nixenvironment +420 -842
  6. data/legacy/CleanWorkingCopy.sh +69 -0
  7. data/legacy/Deploy.sh +44 -0
  8. data/legacy/DeployAPK.py +58 -0
  9. data/legacy/DeployIPA.sh +125 -0
  10. data/legacy/DetectSCM.sh +11 -0
  11. data/legacy/GenerateCodeCoverageForXCTests.sh +134 -0
  12. data/legacy/GenerateCodeDuplicationReport.sh +24 -0
  13. data/legacy/IncrementBuildNumber.py +129 -0
  14. data/legacy/LoadBuildEnvVars.sh +116 -0
  15. data/legacy/MakeTag.sh +94 -0
  16. data/legacy/RemoveTemporaryFiles.sh +9 -0
  17. data/legacy/SaveRevision.sh +122 -0
  18. data/legacy/UnityBuildAndroid.py +84 -0
  19. data/legacy/UnityBuildAutomationScripts/CommandLineReader.cs +130 -0
  20. data/legacy/UnityBuildAutomationScripts/NIXBuilder.cs +105 -0
  21. data/legacy/UnityBuildEnvVars.py +41 -0
  22. data/legacy/VerifyBinarySigning.py +80 -0
  23. data/legacy/svn-clean.pl +246 -0
  24. data/legacy/svncopy.pl +1134 -0
  25. data/lib/nixenvironment.rb +5 -0
  26. data/lib/nixenvironment/archiver.rb +690 -0
  27. data/lib/nixenvironment/build_env_vars_loader.rb +24 -0
  28. data/lib/nixenvironment/cmd_executor.rb +33 -0
  29. data/lib/nixenvironment/config.rb +127 -14
  30. data/lib/nixenvironment/git.rb +107 -0
  31. data/lib/nixenvironment/plist.rb +52 -0
  32. data/lib/nixenvironment/version.rb +1 -1
  33. data/lib/nixenvironment/xcodebuild.rb +167 -0
  34. data/nixenvironment.gemspec +6 -0
  35. data/utils/XcodeIconTagger/IconTagger +0 -0
  36. data/utils/XcodeIconTagger/masks/OneLineMask.png +0 -0
  37. data/utils/XcodeIconTagger/masks/TwoLineMask.png +0 -0
  38. data/utils/aapt +0 -0
  39. data/utils/gcovr +986 -0
  40. data/utils/identitieslist +0 -0
  41. data/utils/simian-2.3.33.jar +0 -0
  42. metadata +118 -2
@@ -0,0 +1,24 @@
1
+ #!/bin/sh -e
2
+
3
+ # Script generates code duplication report for Violations or DRY Jenkins plugins.
4
+
5
+ if [[ $# < 2 ]]
6
+ then
7
+ echo "usage: $0 EXCLUDE_PATTERN OUTPUT_FILENAME"
8
+ exit 1
9
+ fi
10
+
11
+ # load variables
12
+ patterns="$1"
13
+ output="$2"
14
+ excludes=""
15
+
16
+ for pattern in $(echo ${patterns} | tr "|" "\n")
17
+ do
18
+ excludes="${excludes} -excludes=/${pattern}"
19
+ done
20
+
21
+ currentScriptDir="$(dirname "$0")"
22
+ source "${currentScriptDir}/LoadBuildEnvVars.sh"
23
+
24
+ java -jar "${currentScriptDir}/Utils/simian-2.3.33.jar" "**/*.m" "**/*.h" ${excludes} -threshold=5 -failOnDuplication- -formatter=xml:${output}
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/python
2
+
3
+ # Created by Yuri Govorushchenko on 11/29/10.
4
+ # Copyright 2010 nix. All rights reserved.
5
+
6
+ import os
7
+ import sys
8
+ import optparse
9
+ import plistlib
10
+ import thread
11
+ from threading import Timer
12
+ from subprocess import Popen, PIPE
13
+
14
+ PLIST_BUILD_NUMBER_KEY = "CFBundleVersion"
15
+ DEFAULT_INCREMENT_STEP = 1
16
+ WAITING_TIME_FOR_REPOSITORY = 10.0
17
+
18
+ timer = None
19
+
20
+ def main():
21
+ parser = optparse.OptionParser(description='Script gets latest build number from repository, increments it and writes into local info plist file',
22
+ prog='IncrementBuildNumber')
23
+
24
+ parser.add_option("-f", "--plist", dest="plist_path", help="full path to project info plist file", metavar="PLIST")
25
+ parser.add_option("-u", "--username", dest="username", help="authorization username", metavar="USERNAME")
26
+ parser.add_option("-p", "--password", dest="password", help="authorization password", metavar="PASSWORD")
27
+ parser.add_option("-i", "--increment", dest="increment_step", help="increment step. Should be more than 0. Default value is 1.(optional)", metavar="INCREMENT_NUMBER")
28
+
29
+ (options, args) = parser.parse_args()
30
+
31
+ if options.plist_path is None or options.username is None or options.password is None:
32
+ parser.error('All arguments must be specified. Use option -h to see the usage.')
33
+
34
+ increment_step = DEFAULT_INCREMENT_STEP
35
+
36
+ if options.increment_step is not None:
37
+ parsed_increment_step = int(options.increment_step)
38
+ if parsed_increment_step > 1:
39
+ increment_step = parsed_increment_step
40
+
41
+ plist_path = options.plist_path
42
+ username = options.username
43
+ password = options.password
44
+
45
+ if not os.path.isfile(plist_path):
46
+ print_error('file does not exist: %s' % plist_path)
47
+ return 1
48
+
49
+ try:
50
+ head_build_number = get_head_build_number(plist_path, username, password)
51
+ write_build_number(head_build_number, plist_path)
52
+ update_file(plist_path, username, password)
53
+ write_build_number(head_build_number+increment_step, plist_path)
54
+ except Exception, e:
55
+ timer.cancel()
56
+ print_warning("Couldn't get current app build version from repository. App build version is not increased. (exception: %s)" % e)
57
+
58
+ return 0
59
+
60
+ def print_error(error_message):
61
+ """ Prints error message with predefined prefix.
62
+
63
+ Args:
64
+ error_message: Error message.
65
+ """
66
+
67
+ XCODE_ERROR_PREFIX = 'error: ' # log messages with such prefix are highlighted in XCode as errors
68
+
69
+ print('%s%s' % (XCODE_ERROR_PREFIX, error_message))
70
+
71
+ def print_warning(warning_message):
72
+ """ Prints warning message with predefined prefix.
73
+
74
+ Args:
75
+ warning_message: Warning message.
76
+ """
77
+
78
+ XCODE_WARNING_PREFIX = 'warning: ' # log messages with such prefix are highlighted in XCode as warning
79
+
80
+ print('%s%s' % (XCODE_WARNING_PREFIX, warning_message))
81
+
82
+ def get_head_build_number(plist_path, username, password):
83
+ url = get_svn_url_for_path(plist_path)
84
+ head_build_number = get_build_number_from_svn_plist(url, username, password)
85
+
86
+ return head_build_number
87
+
88
+ def get_svn_url_for_path(plist_path):
89
+ svn_info = Popen(["svn", "info", plist_path], stdin=PIPE, stdout=PIPE)
90
+ output = svn_info.communicate()[0]
91
+
92
+ SVN_INFO_URL_PREFIX = "URL: "
93
+
94
+ for line in output.split("\n"):
95
+ if line.startswith(SVN_INFO_URL_PREFIX):
96
+ url = line[len(SVN_INFO_URL_PREFIX):]
97
+ return url
98
+
99
+ def get_build_number_from_svn_plist(url, username, password):
100
+ svn_get = Popen(["svn", "cat", url, "--username", username, "--password", password], stdin=PIPE, stdout=PIPE)
101
+
102
+ global timer
103
+ timer = Timer(WAITING_TIME_FOR_REPOSITORY, timeout_waiting_for_repository, [svn_get])
104
+ timer.start()
105
+
106
+ output = svn_get.communicate()[0]
107
+
108
+ timer.cancel()
109
+
110
+ plist = plistlib.readPlistFromString(output)
111
+
112
+ return int(plist[PLIST_BUILD_NUMBER_KEY])
113
+
114
+ def update_file(plist_path, username, password):
115
+ plist_updating = Popen(["svn", "update", plist_path, "--username", username, "--password", password], stdin=PIPE, stdout=PIPE)
116
+ plist_updating.communicate()
117
+
118
+ def write_build_number(build_number, plist_path):
119
+ plist = plistlib.readPlist(plist_path)
120
+ plist[PLIST_BUILD_NUMBER_KEY] = str(build_number)
121
+ plistlib.writePlist(plist, plist_path)
122
+
123
+ def timeout_waiting_for_repository(svn_process):
124
+ print_warning("Timeout waiting for repository. App build version is not increased.")
125
+
126
+ svn_process.kill()
127
+
128
+ if __name__ == '__main__':
129
+ sys.exit(main())
@@ -0,0 +1,116 @@
1
+ #!/bin/sh -e
2
+
3
+ # Created by Yuri Govorushchenko on 7/5/11.
4
+ # Copyright 2010 nix. All rights reserved.
5
+
6
+ # Script loads variables specified in _last_revision.sh and _last_build_vars.sh and checks that all specified files and dirs exist.
7
+
8
+ #############
9
+
10
+ function checkFileExists {
11
+ if [ ! -f "$1" ]; then
12
+ echo "error: file '$1' must exist ($2)." 1>&2
13
+ exit 1
14
+ fi
15
+ }
16
+
17
+ function checkDirExists {
18
+ if [ ! -d "$1" ]; then
19
+ echo "error: directory '$1' must exist ($2)." 1>&2
20
+ exit 1
21
+ fi
22
+ }
23
+
24
+ function checkAppOrIPAProductExists {
25
+ if [ ! -d "${APP_PRODUCT}" ]; then
26
+ if [ ! -f "${IPA_PRODUCT}" ]; then
27
+ echo "error: app product directory '${APP_PRODUCT}' or ipa file '${IPA_PRODUCT}' must exist." 1>&2
28
+ exit 1
29
+ fi
30
+ fi
31
+ }
32
+
33
+ #############
34
+
35
+ function checkWorkingCopyIsClean {
36
+ if [ ${WORKING_COPY_IS_CLEAN} -eq 1 ]; then
37
+ echo "Working copy is clean. Continuing..."
38
+ else
39
+ echo "error: working copy must not have local modifications." 1>&2
40
+ echo "You must add following files and folders to .gitignore:"
41
+ echo "$(git status --porcelain)"
42
+ exit 1
43
+ fi
44
+ }
45
+
46
+ #############
47
+
48
+ # set some default values to vars to catch errors quickly:
49
+ REVISION="unknown_revision"
50
+ PROJECT="unknown_project"
51
+ BUILT_PRODUCTS_DIR="unknown_build_prodcuts_dir"
52
+ OBJECTS_NORMAL_DIR="unknown_objects_normal_dir"
53
+ EXECUTABLE_NAME="unknown_executable_name"
54
+ APP_PRODUCT="unknown_app_product"
55
+ IPA_PRODUCT="unknown_ipa_product"
56
+ APP_DSYM="unknown_app_dsym"
57
+ APP_INFOPLIST_FILE="unknown_app_infoplist_file"
58
+ EMBEDDED_PROFILE="unknown_embedded_profile"
59
+ TARGET_NAME="unknown_target_name"
60
+ CONFIGURATION="unknown_configuration"
61
+ SDK_NAME="unknown_sdk_name"
62
+ IPA_BUNDLE_ID="unknwon_ipa_bundle_id"
63
+ RESIGNED_BUNDLE_ID="unknown_resigned_bundle_id"
64
+ RESIGNED_BUNDLE_NAME="unknown_resigned_bundle_name"
65
+ RESIGNED_ENTITLEMENTS_PATH="unknown_resigned_entitlements_path"
66
+ NAME_FOR_DEPLOYMENT="unknown_name_for_deployment"
67
+
68
+ # these files should be already generated
69
+ LAST_REVISION_FILE="_last_revision.sh"
70
+ LAST_BUILD_VARS_FILE="_last_build_vars.sh"
71
+
72
+ checkFileExists ${LAST_REVISION_FILE}
73
+ checkFileExists ${LAST_BUILD_VARS_FILE}
74
+
75
+ source ${LAST_REVISION_FILE}
76
+ source ${LAST_BUILD_VARS_FILE}
77
+
78
+ echo "REVISION = ${REVISION}"
79
+ echo "MONOTONIC_REVISION = ${MONOTONIC_REVISION}"
80
+ echo "PROJECT = ${PROJECT}"
81
+ echo "BUILT_PRODUCTS_DIR = ${BUILT_PRODUCTS_DIR}"
82
+ echo "OBJECTS_NORMAL_DIR = ${OBJECTS_NORMAL_DIR}"
83
+ echo "EXECUTABLE_NAME = ${EXECUTABLE_NAME}"
84
+ echo "APP_PRODUCT = ${APP_PRODUCT}"
85
+ echo "IPA_PRODUCT = ${IPA_PRODUCT}"
86
+ echo "APP_DSYM = ${APP_DSYM}"
87
+ echo "APP_INFOPLIST_FILE = ${APP_INFOPLIST_FILE}"
88
+ echo "EMBEDDED_PROFILE = ${EMBEDDED_PROFILE}"
89
+ echo "TARGET_NAME = ${TARGET_NAME}"
90
+ echo "CONFIGURATION = ${CONFIGURATION}"
91
+ echo "SDK_NAME = ${SDK_NAME}"
92
+ echo "IPA_BUNDLE_ID = ${IPA_BUNDLE_ID}"
93
+ echo "RESIGNED_BUNDLE_ID = ${RESIGNED_BUNDLE_ID}"
94
+ echo "RESIGNED_BUNDLE_NAME = ${RESIGNED_BUNDLE_NAME}"
95
+ echo "RESIGNED_ENTITLEMENTS_PATH = ${RESIGNED_ENTITLEMENTS_PATH}"
96
+ echo "NAME_FOR_DEPLOYMENT = ${NAME_FOR_DEPLOYMENT}"
97
+
98
+ checkDirExists "${BUILT_PRODUCTS_DIR}" "build products dir"
99
+ checkAppOrIPAProductExists
100
+ checkFileExists "${APP_INFOPLIST_FILE}" "app info plist"
101
+
102
+ if [ -f "${EMBEDDED_PROFILE}" ]; then
103
+ # get name of embedded provisioning profile; see http://stackoverflow.com/questions/2327257/name-of-provisioning-profile-used-to-sign-an-iphone-app
104
+ EMBEDDED_PROFILE_NAME=$(security cms -D -i "${EMBEDDED_PROFILE}" > /tmp/tmp.plist && /usr/libexec/PlistBuddy -c 'Print :Name' /tmp/tmp.plist)
105
+ else
106
+ EMBEDDED_PROFILE_NAME="SIMULATOR"
107
+ fi
108
+
109
+ echo "EMBEDDED_PROFILE_NAME = ${EMBEDDED_PROFILE_NAME}"
110
+
111
+ CURRENT_APP_VERSION="`/usr/libexec/PlistBuddy -c 'Print CFBundleShortVersionString' \
112
+ "${APP_INFOPLIST_FILE}"`"
113
+ CURRENT_BUILD_VERSION=${MONOTONIC_REVISION}
114
+
115
+ echo "CURRENT_APP_VERSION = ${CURRENT_APP_VERSION}"
116
+ echo "CURRENT_BUILD_VERSION = ${CURRENT_BUILD_VERSION}"
data/legacy/MakeTag.sh ADDED
@@ -0,0 +1,94 @@
1
+ #!/bin/sh -e
2
+
3
+ # Created by Yuri Govorushchenko on 11/15/10.
4
+ # Copyright 2010 nix. All rights reserved.
5
+
6
+ # Script creates SVN/git tag
7
+ # Note that the SVN source code snapshot will be taken from the repository, not the working copy
8
+
9
+ if [[ $# < 2 ]]; then
10
+ echo "usage: $0 USERNAME PASSWORD (specify empty username and password in order to indicate that script must use default credentials)"
11
+ exit 1
12
+ fi
13
+
14
+ # load variables
15
+ username=$1
16
+ password=$2
17
+
18
+ USE_DEFAULT_CREDENTIALS=0
19
+ if [ "${username}" == "" -a "${password}" == "" ]; then
20
+ echo "--- Username and password are not specified, using default SCM credentials"
21
+ USE_DEFAULT_CREDENTIALS=1
22
+ fi
23
+
24
+ currentScriptDir=$(cd "$(dirname "$0")"; pwd)
25
+ source "${currentScriptDir}/LoadBuildEnvVars.sh"
26
+
27
+ # make sure developer tags the same source snapshot as in the working copy
28
+ checkWorkingCopyIsClean
29
+
30
+ TAG_NAME="${PROJECT}-${CURRENT_APP_VERSION}b${CURRENT_BUILD_VERSION}"
31
+
32
+ SCM_TYPE=$("${currentScriptDir}/DetectSCM.sh")
33
+
34
+ # Subversion
35
+ if [[ "${SCM_TYPE}" = "svn" ]]; then
36
+ SVN_URL="$(svn info | grep '^URL:' | sed -e 's/^URL: //')"
37
+ SVN_ROOT_URL="$(svn info | grep '^URL:' | sed -e 's/^URL: //' | (sed -e 's/\/branches\/.*//' | sed -e 's/\/trunk\/.*//'))"
38
+ TAG_DIR="${SVN_ROOT_URL}/tags/${TAG_NAME}"
39
+
40
+ echo "--- Check if tag exists at '${TAG_DIR}'"
41
+
42
+ if [ ${USE_DEFAULT_CREDENTIALS} == 0 ]; then
43
+ TAG_CONTENTS=$(svn list "${TAG_DIR}" --username="${username}" --password="${password}" 2>/dev/null || true)
44
+ else
45
+ TAG_CONTENTS=$(svn list "${TAG_DIR}" 2>/dev/null || true)
46
+ fi
47
+
48
+ if [ "${TAG_CONTENTS}" == "" ]; then
49
+ echo "--- Make tag at '${TAG_DIR}'"
50
+
51
+ if [ ${USE_DEFAULT_CREDENTIALS} == 0 ]; then
52
+ perl "${currentScriptDir}/svncopy.pl" --revision "${REVISION}" --tag --verbose "${SVN_URL}" "${TAG_DIR}" --username="${username}" --password="${password}"
53
+ else
54
+ perl "${currentScriptDir}/svncopy.pl" --revision "${REVISION}" --tag --verbose "${SVN_URL}" "${TAG_DIR}"
55
+ fi
56
+
57
+ echo "--- Tag from branch '${SVN_URL}' was created at '${TAG_DIR}'"
58
+ else
59
+ echo "--- Tag from branch '${SVN_URL}' already exists at '${TAG_DIR}'"
60
+ fi
61
+
62
+ # git
63
+ elif [[ "${SCM_TYPE}" = "git" ]]; then
64
+ GIT_ORIGINAL_REMOTE_URL="$(git remote -v | head -n1 | sed 's/.*http/http/; s/ .*//')"
65
+ GIT_ROOT_URL="$(echo $GIT_ORIGINAL_REMOTE_URL | sed 's/.*\/\///; s/ .*//')"
66
+
67
+ if [ ${USE_DEFAULT_CREDENTIALS} == 0 ]; then
68
+ # set remote url credentials
69
+ git config remote.origin.url https://${username}:${password}@${GIT_ROOT_URL}
70
+
71
+ # original username and password must be restored
72
+ trap 'git config remote.origin.url "${GIT_ORIGINAL_REMOTE_URL}"' EXIT
73
+ fi
74
+
75
+ BRANCH_NAME="$(git rev-parse --abbrev-ref HEAD)"
76
+ PROJECT_TAGS="$(git ls-remote --tags)"
77
+
78
+ if [[ "${PROJECT_TAGS}" != *"${TAG_NAME}"* ]]; then
79
+ git tag -a ${TAG_NAME} "${REVISION}" -m 'create tag ${TAG_NAME}'
80
+ git push --tags
81
+
82
+ echo "--- Tag '${TAG_NAME}' from branch '${BRANCH_NAME}' with revision '${REVISION}' was created"
83
+ else
84
+ echo "--- Tag '${TAG_NAME}' from branch '${BRANCH_NAME}' with revision '${REVISION}' already exists"
85
+ fi
86
+
87
+ # mercurial
88
+ elif [[ "${SCM_TYPE}" = "mercurial" ]]; then
89
+ echo "make tag doesn't work for mercurial"
90
+
91
+ else
92
+ echo "error: tag was not created, because script must be run from a working copy" 1>&2
93
+ exit 1
94
+ fi
@@ -0,0 +1,9 @@
1
+ #!/bin/sh -e
2
+
3
+ # Created by Yuri Govorushchenko on 2/21/11.
4
+ # Copyright 2011 nix. All rights reserved.
5
+
6
+ rm -f _last_revision.sh
7
+ rm -f _last_build_vars.sh
8
+ rm -f coverage.xml
9
+ rm -f duplication.xml
@@ -0,0 +1,122 @@
1
+ #!/bin/sh -e
2
+
3
+ # Created by Yuri Govorushchenko on 6/24/11.
4
+ # Copyright 2011 nix. All rights reserved.
5
+
6
+ # Script which saves next vars into _last_revision.sh:
7
+ # SCM revision of working copy
8
+ # "monotonic" revision (good for build numbers) of working copy
9
+ # checks if working copy is not modified
10
+
11
+ currentScriptDir=$(cd "$(dirname "$0")"; pwd)
12
+ SCM_TYPE=$("${currentScriptDir}/DetectSCM.sh")
13
+
14
+ # Subversion
15
+ if [[ "${SCM_TYPE}" = "svn" ]]; then
16
+ echo "SVN working copy detected"
17
+ CURRENT_REVISION="$(svnversion)"
18
+ CURRENT_MONOTONIC_REVISION=${CURRENT_REVISION} # SVN revision is already an incrementing number
19
+
20
+ # simply check that the SVN version is a digit
21
+ if [[ ${CURRENT_REVISION} =~ ^[0-9]+$ ]]; then
22
+ WORKING_COPY_IS_CLEAN=1
23
+ else
24
+ echo "Working copy is not clean because of svnversion returning ${CURRENT_REVISION}"
25
+ WORKING_COPY_IS_CLEAN=0
26
+ fi
27
+
28
+ # git
29
+ elif [[ "${SCM_TYPE}" = "git" ]]; then
30
+ echo "GIT working copy detected"
31
+ CURRENT_REVISION="$(git rev-parse HEAD | xargs)"
32
+ LAST_REVISION_IN_REPO="$(git rev-list --all | head -n 1 | xargs)"
33
+
34
+ if [[ $CURRENT_REVISION == $LAST_REVISION_IN_REPO ]]; then
35
+ UNLESS_STARTS_FROM=1
36
+ else
37
+ UNLESS_STARTS_FROM=2
38
+ fi
39
+
40
+ CURRENT_MONOTONIC_REVISION=$(git rev-list --all | perl -ne "print unless $UNLESS_STARTS_FROM../$CURRENT_REVISION/" | wc -l | xargs) # number of pushes before current
41
+
42
+ if [[ $UNLESS_STARTS_FROM == 1 ]]; then
43
+ CURRENT_MONOTONIC_REVISION=$(($CURRENT_MONOTONIC_REVISION + 1))
44
+ fi
45
+
46
+ STATUS="$(git status --porcelain)"
47
+
48
+ if [[ "${STATUS}" = "" ]]; then
49
+ WORKING_COPY_IS_CLEAN=1
50
+ else
51
+ # ignore changes to build folder, because it's created by Xcode before the script runs as a build phase
52
+ LINES_COUNT=$(echo "$STATUS" | wc -l)
53
+
54
+ if [ ${LINES_COUNT} != 1 ]; then
55
+ printf "Working copy is not clean because of status:\n${STATUS}"
56
+ WORKING_COPY_IS_CLEAN=0
57
+ else
58
+ MODIFIED_PATH=$(echo "$STATUS" | colrm 1 3)
59
+ WC_ROOT=$(git rev-parse --show-toplevel)
60
+ ABS_MODIFIED_PATH="${WC_ROOT}/${MODIFIED_PATH}"
61
+
62
+ # compare path to Xcode env var
63
+ if [[ "${ABS_MODIFIED_PATH}" -ef "${BUILD_ROOT}" ]]; then
64
+ WORKING_COPY_IS_CLEAN=1
65
+ else
66
+ printf "Working copy is not clean because of status:\n${STATUS}"
67
+ WORKING_COPY_IS_CLEAN=0
68
+ fi
69
+ fi
70
+ fi
71
+
72
+ # mercurial
73
+ elif [[ "${SCM_TYPE}" = "mercurial" ]]; then
74
+ echo "Mercurial working copy detected"
75
+ CURRENT_REVISION="$(hg id -i)"
76
+ CURRENT_MONOTONIC_REVISION="$(hg log --template '{rev}:{node|short} {desc|firstline} ({author})\n' | wc -l | tr -d ' ')" # number of pushes in current branch
77
+
78
+ STATUS="$(hg status)"
79
+
80
+ if [[ "${STATUS}" = "" ]]; then
81
+ WORKING_COPY_IS_CLEAN=1
82
+ else
83
+ # ignore changes to build folder, because it's created by Xcode before the script runs as a build phase
84
+ LINES_COUNT=$(echo "$STATUS" | wc -l)
85
+
86
+ if [ ${LINES_COUNT} != 1 ]; then
87
+ printf "Working copy is not clean because of status:\n${STATUS}"
88
+ WORKING_COPY_IS_CLEAN=0
89
+ else
90
+ MODIFIED_PATH=$(echo "$STATUS" | colrm 1 3)
91
+ WC_ROOT=$(git rev-parse --show-toplevel)
92
+ ABS_MODIFIED_PATH="${WC_ROOT}/${MODIFIED_PATH}"
93
+
94
+ # compare path to Xcode env var
95
+ if [[ "${ABS_MODIFIED_PATH}" -ef "${BUILD_ROOT}" ]]; then
96
+ WORKING_COPY_IS_CLEAN=1
97
+ else
98
+ printf "Working copy is not clean because of status:\n${STATUS}"
99
+ WORKING_COPY_IS_CLEAN=0
100
+ fi
101
+ fi
102
+ fi
103
+
104
+ # undefined SCM
105
+ else
106
+ echo "warning: script must be run from working copy. Revision is undefined."
107
+
108
+ CURRENT_REVISION="undefined"
109
+ CURRENT_MONOTONIC_REVISION="undefined"
110
+ WORKING_COPY_IS_CLEAN=0
111
+ fi
112
+
113
+ OUTPUT="
114
+ REVISION=\"${CURRENT_REVISION}\"
115
+ MONOTONIC_REVISION=\"${CURRENT_MONOTONIC_REVISION}\"
116
+ WORKING_COPY_IS_CLEAN=\"${WORKING_COPY_IS_CLEAN}\"
117
+ "
118
+
119
+ echo "${OUTPUT}"
120
+ echo "#!/bin/sh
121
+ ### AUTOGENERATED BY SaveRevision.sh; DO NOT EDIT ###
122
+ ${OUTPUT}" > _last_revision.sh