nixenvironment 0.0.59 → 0.0.60

Sign up to get free protection for your applications and to get access to all the features.
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