2016-02-15 2 views
2

Недавно я использовал сценарий для увеличения номера сборки проекта, связанного с git commits, и я столкнулся с бесконечным циклом.Как избежать бесконечного цикла, используя номер git commit, как номер сборки xcode

Я строю, затем номер сборки изменяется, затем я фиксирую, потому что изменен info.plist, после чего номер сборки будет изменен в следующий раз, когда я буду строить, поэтому я должен выполнить его снова, так как info.plist изменилось, тогда вы знаете, что произойдет.

Есть ли способ избежать этого? или есть лучший способ автоматически увеличить номер сборки?

пс. так как я работал над проектом с другими, меняйте количество вручную или удары каждый раз, когда я строю довольно сложно поддерживать номер.

+0

я использую что-то подобное [этот вопрос] (https://stackoverflow.com/questions/21114376/how-to-auto-increment-the-build-number-in-xcode-5), но вместо для увеличения числа, я рассчитываю количество коммитов с начала проекта с помощью 'git rev-list HEAD --count'. –

+0

См. Также http://blog.jaredsinclair.com/post/97193356620/the-best-of-all-possible-xcode-automated-build –

+0

@GuillaumeAlgis: я использую 'git rev-list HEAD --count'. :( – Maxismo

ответ

1

Да, это классический вопрос. Я использую подобную технику, но я не отношу номер сборки к git commits, вместо этого я обнаруживаю изменения в файлах в дереве источников в зависимости от измененного времени файла версии (простой файл, содержащий версию и номер сборки). Если есть изменения, я нажимаю номер сборки.

Здесь используется сценарий python. Вы должны сделать это отдельной целью в своем проекте Xcode, а затем сделать другие цели зависимыми от этой цели. Он по необходимости обновит ваши файлы .plist с новым номером версии/сборки. Это предполагает источник дерева ниже расположения версии файла:

#!/usr/bin/env python 
# 
# Bump build number in Info.plist files if a source file have changed. 
# 
# usage: bump_buildnum.py buildnum.ver Info.plist [ ... Info.plist ] 
# 
# [email protected], 2014. 
# 

import sys, os, subprocess, re 

def read_verfile(name): 
    version = None 
    build = None 
    verfile = open(name, "r") 
    for line in verfile: 
     match = re.match(r"^version\s+(\S+)", line) 
     if match: 
      version = match.group(1).rstrip() 
     match = re.match(r"^build\s+(\S+)", line) 
     if match: 
      build = int(match.group(1).rstrip()) 
    verfile.close() 
    return (version, build) 

def write_verfile(name, version, build): 
    verfile = open(name, "w") 
    verfile.write("version {0}\n".format(version)) 
    verfile.write("build {0}\n".format(build)) 
    verfile.close() 
    return True 

def set_plist_version(plistname, version, build): 
    if not os.path.exists(plistname): 
     print("{0} does not exist".format(plistname)) 
     return False 

    plistbuddy = '/usr/libexec/Plistbuddy' 
    if not os.path.exists(plistbuddy): 
     print("{0} does not exist".format(plistbuddy)) 
     return False 

    cmdline = [plistbuddy, 
     "-c", "Set CFBundleShortVersionString {0}".format(version), 
     "-c", "Set CFBundleVersion {0}".format(build), 
     plistname] 
    if subprocess.call(cmdline) != 0: 
     print("Failed to update {0}".format(plistname)) 
     return False 

    print("Updated {0} with v{1} ({2})".format(plistname, version, build)) 
    return True 

def should_bump(vername, dirname): 
    verstat = os.stat(vername) 
    allnames = [] 
    for dirname, dirnames, filenames in os.walk(dirname): 
     for filename in filenames: 
      allnames.append(os.path.join(dirname, filename)) 

    for filename in allnames: 
     filestat = os.stat(filename) 
     if filestat.st_mtime > verstat.st_mtime: 
      print("{0} is newer than {1}".format(filename, vername)) 
      return True 

    return False 

def upver(vername): 
    (version, build) = read_verfile(vername) 
    if version == None or build == None: 
     print("Failed to read version/build from {0}".format(vername)) 
     return False 

    # Bump the version number if any files in the same directory as the version file 
    # have changed, including sub-directories. 
    srcdir = os.path.dirname(vername) 
    bump = should_bump(vername, srcdir) 

    if bump: 
     build += 1 
     print("Incremented to build {0}".format(build)) 
     write_verfile(vername, version, build) 
     print("Written {0}".format(vername)) 
    else: 
     print("Staying at build {0}".format(build)) 

    return (version, build) 

if __name__ == "__main__": 
    if os.environ.has_key('ACTION') and os.environ['ACTION'] == 'clean': 
     print("{0}: Not running while cleaning".format(sys.argv[0])) 
     sys.exit(0) 

    if len(sys.argv) < 3: 
     print("Usage: {0} buildnum.ver Info.plist [... Info.plist]".format(sys.argv[0])) 
     sys.exit(1) 
    vername = sys.argv[1] 

    (version, build) = upver(vername) 
    if version == None or build == None: 
     sys.exit(2) 

    for i in range(2, len(sys.argv)): 
     plistname = sys.argv[i] 
     set_plist_version(plistname, version, build)   

    sys.exit(0) 
0

Подход, который я использую, чтобы иметь заполнитель в файле, который содержит номер версии, а затем с сервера сборки заменить этот заполнитель с правильным номером версии локально перед созданием которого распространяется дистрибутив. Версия info.plist, находящаяся в репозитории, не изменяется; он всегда имеет местозаполнитель.

0

Я сделал версию ответа @ trojanfoe в чистом баше. Это предполагает файл с именем versions, помещенным в корневую директорию проекта.

#!/bin/bash 

beginswith() { case $2 in "$1"*) true;; *) false;; esac; } 

shopt -s dotglob 

versionModifiedAt=$(date -r versions +%s) 
needsUpdate=false 

processEntry() { 
    if [[ "$1" == "versions" ]]; then return; fi 
    if [[ "$1" == ".git" ]];  then return; fi 
    if beginswith ".git/" "$1"; then return; fi 

    if [ $(date -r "$1" +%s) -gt "$versionModifiedAt" ]; then 
    needsUpdate=true 
    fi 
} 

# Top level 
for entry in *; do 
    processEntry "$entry" 
    if [[ $needsUpdate == true ]]; then 
    break; 
    fi 
done 

# Nested 
if [[ $needsUpdate != true ]]; then 
    for entry in **/*; do 
    processEntry "$entry" 
    if [[ $needsUpdate == true ]]; then 
     break; 
    fi 
    done 
fi 

if [[ $needsUpdate != true ]]; then 
    echo "No update needed" 
    exit 0 
fi 
echo "Updating version and build info" 


buildPlist=${PROJECT_DIR}/${INFOPLIST_FILE} 

# Increment build number 
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$buildPlist") 
buildNumber=$((0x$buildNumber)) 
buildNumber=$(($buildNumber + 1)) 
buildNumber=$(printf "%04X" $buildNumber) 
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$buildPlist" 

echo -e "${git_release_version#*v}\n$buildNumber" > versions