Update make.py to 0.8 (#4579)

* Update make.py to 0.8

* Remove redundant extras folder obsolete handling

* Fix version updating in files when version changes number of digits

* Satisfy bux
This commit is contained in:
jonpas
2016-10-25 20:11:05 +02:00
committed by Glowbal
parent 07068260fe
commit ffd1f0aff2
4 changed files with 189 additions and 127 deletions

View File

@ -30,7 +30,7 @@
###############################################################################
__version__ = "0.7"
__version__ = "0.8"
import sys
@ -51,8 +51,7 @@ import traceback
import time
import timeit
import re
from tempfile import mkstemp
import fileinput
if sys.platform == "win32":
import winreg
@ -329,7 +328,6 @@ def print_yellow(msg):
def copy_important_files(source_dir,destination_dir):
originalDir = os.getcwd()
# Copy importantFiles
@ -340,17 +338,17 @@ def copy_important_files(source_dir,destination_dir):
for file in importantFiles:
filePath = os.path.join(module_root_parent, file)
# Take only file name for destination path (to put it into root of release dir)
if "\\" in file:
count = file.count("\\")
file = file.split("\\", count)[-1]
print_green("Copying file => {}".format(os.path.join(source_dir,file)))
shutil.copyfile(os.path.join(source_dir,filePath),os.path.join(destination_dir,file))
if os.path.exists(filePath):
print_green("Copying file => {}".format(filePath))
shutil.copy(os.path.join(source_dir,filePath), destination_dir)
else:
missingFiles.append("{}".format(filePath))
print_error("Failed copying file => {}".format(filePath))
except:
print_error("COPYING IMPORTANT FILES.")
raise
#copy all extension dlls
# Copy all extension DLL's
try:
os.chdir(os.path.join(source_dir))
print_blue("\nSearching for DLLs in {}".format(os.getcwd()))
@ -370,13 +368,13 @@ def copy_important_files(source_dir,destination_dir):
os.chdir(originalDir)
def copy_optionals_for_building(mod,pbos):
src_directories = os.listdir(optionals_root)
current_dir = os.getcwd()
print_blue("\nChecking Optionals folder...")
print_blue("\nChecking optionals folder...")
try:
#special server.pbo processing
files = glob.glob(os.path.join(release_dir, project, "optionals", "*.pbo"))
for file in files:
@ -400,7 +398,6 @@ def copy_optionals_for_building(mod,pbos):
finally:
os.chdir(current_dir)
print("")
try:
for dir_name in src_directories:
mod.append(dir_name)
@ -467,9 +464,10 @@ def cleanup_optionals(mod):
def purge(dir, pattern, friendlyPattern="files"):
print_green("Deleting {} files from directory: {}".format(friendlyPattern,dir))
for f in os.listdir(dir):
if re.search(pattern, f):
os.remove(os.path.join(dir, f))
if os.path.exists(dir):
for f in os.listdir(dir):
if re.search(pattern, f):
os.remove(os.path.join(dir, f))
def build_signature_file(file_name):
@ -525,13 +523,13 @@ def addon_restore(modulePath):
return True
def get_project_version():
def get_project_version(version_increments=[]):
global project_version
versionStamp = project_version
#do the magic based on https://github.com/acemod/ACE3/issues/806#issuecomment-95639048
try:
scriptModPath = os.path.join(work_drive, prefix, "main\script_mod.hpp")
scriptModPath = os.path.join(module_root, "main\script_version.hpp")
if os.path.isfile(scriptModPath):
f = open(scriptModPath, "r")
@ -541,11 +539,36 @@ def get_project_version():
if hpptext:
majorText = re.search(r"#define MAJOR (.*\b)", hpptext).group(1)
minorText = re.search(r"#define MINOR (.*\b)", hpptext).group(1)
patchlvlText = re.search(r"#define PATCHLVL (.*\b)", hpptext).group(1)
patchText = re.search(r"#define PATCHLVL (.*\b)", hpptext).group(1)
buildText = re.search(r"#define BUILD (.*\b)", hpptext).group(1)
# Increment version (reset all below except build)
if version_increments != []:
if "major" in version_increments:
majorText = int(majorText) + 1
minorText = 0
patchText = 0
elif "minor" in version_increments:
minorText = int(minorText) + 1
patchText = 0
elif "patch" in version_increments:
patchText = int(patchText) + 1
# Always increment build
if "build" in version_increments:
buildText = int(buildText) + 1
print_green("Incrementing version to {}.{}.{}.{}".format(majorText,minorText,patchText,buildText))
with open(scriptModPath, "w", newline="\n") as file:
file.writelines([
"#define MAJOR {}\n".format(majorText),
"#define MINOR {}\n".format(minorText),
"#define PATCHLVL {}\n".format(patchText),
"#define BUILD {}\n".format(buildText)
])
if majorText:
versionStamp = "{major}.{minor}.{patchlvl}.{build}".format(major=majorText,minor=minorText,patchlvl=patchlvlText,build=buildText)
versionStamp = "{}.{}.{}.{}".format(majorText,minorText,patchText,buildText)
else:
print_error("A Critical file seems to be missing or inaccessible: {}".format(scriptModPath))
@ -565,22 +588,15 @@ def get_project_version():
def replace_file(filePath, oldSubstring, newSubstring):
#Create temp file
fh, absPath = mkstemp()
with open(absPath,'w') as newFile:
with open(filePath) as oldFile:
for line in oldFile:
newFile.write(line.replace(oldSubstring, newSubstring))
newFile.close()
#Remove original file
os.remove(filePath)
#Move new file
shutil.move(absPath, filePath)
for line in fileinput.input(filePath, inplace=True):
# Use stdout directly, print() adds newlines automatically
sys.stdout.write(line.replace(oldSubstring,newSubstring))
def set_version_in_files():
newVersion = project_version # MAJOR.MINOR.PATCH.BUILD
newVersionShort = newVersion[:-2] # MAJOR.MINOR.PATCH
newVersionArr = newVersion.split(".")
newVersionShort = ".".join((newVersionArr[0],newVersionArr[1],newVersionArr[2])) # MAJOR.MINOR.PATCH
# Regex patterns
pattern = re.compile(r"([\d]+\.[\d]+\.[\d]+\.[\d]+)") # MAJOR.MINOR.PATCH.BUILD
@ -598,28 +614,26 @@ def set_version_in_files():
f.close()
if fileText:
# Search and save version stamp, search short if long not found
versionFound = re.findall(pattern, fileText)
if not versionFound:
versionFound = re.findall(patternShort, fileText)
# Version string files
# Search and save version stamp
versionsFound = re.findall(pattern, fileText) + re.findall(patternShort, fileText)
# Filter out sub-versions of other versions
versionsFound = [j for i, j in enumerate(versionsFound) if all(j not in k for k in versionsFound[i + 1:])]
# Replace version stamp if any of the new version parts is higher than the one found
if versionFound:
# First item in the list findall returns
versionFound = versionFound[0]
newVersionUsed = ""
# Use the same version length as the one found
if len(versionFound) == len(newVersion):
newVersionUsed = newVersion
if len(versionFound) == len(newVersionShort):
newVersionUsed = newVersionShort
# Print change and modify the file if changed
if versionFound != newVersionUsed:
print_green("Changing version {} => {} in {}".format(versionFound, newVersionUsed, filePath))
replace_file(filePath, versionFound, newVersionUsed)
for versionFound in versionsFound:
if versionFound:
# Use the same version length as the one found
newVersionUsed = "" # In case undefined
if versionFound.count(".") == newVersion.count("."):
newVersionUsed = newVersion
if versionFound.count(".") == newVersionShort.count("."):
newVersionUsed = newVersionShort
# Print change and modify the file if changed
if newVersionUsed and versionFound != newVersionUsed:
print_green("Changing version {} => {} in {}".format(versionFound, newVersionUsed, filePath))
replace_file(filePath, versionFound, newVersionUsed)
except WindowsError as e:
# Temporary file is still "in use" by Python, pass this exception
pass
@ -634,13 +648,17 @@ def stash_version_files_for_building():
try:
for file in versionFiles:
filePath = os.path.join(module_root_parent, file)
# Take only file name for stash location if in subfolder (otherwise it gets removed when removing folders from release dir)
if "\\" in file:
count = file.count("\\")
file = file.split("\\", count)[-1]
stashPath = os.path.join(release_dir, file)
print("Temporarily stashing {} => {}.bak for version update".format(filePath, stashPath))
shutil.copy(filePath, "{}.bak".format(stashPath))
if os.path.exists(filePath):
# Take only file name for stash location if in subfolder (otherwise it gets removed when removing folders from release dir)
if "\\" in file:
count = file.count("\\")
file = file.split("\\", count)[-1]
stashPath = os.path.join(release_dir, file)
print("Temporarily stashing {} => {}.bak for version update".format(filePath, stashPath))
shutil.copy(filePath, "{}.bak".format(stashPath))
else:
print_error("Failed temporarily stashing {} for version update".format(filePath))
missingFiles.append("{}".format(filePath))
except:
print_error("Stashing version files failed")
raise
@ -652,6 +670,8 @@ def stash_version_files_for_building():
def restore_version_files():
try:
print_blue("\nRestoring version files...")
for file in versionFiles:
filePath = os.path.join(module_root_parent, file)
# Take only file name for stash path if in subfolder (otherwise it gets removed when removing folders from release dir)
@ -659,8 +679,9 @@ def restore_version_files():
count = file.count("\\")
file = file.split("\\", count)[-1]
stashPath = os.path.join(release_dir, file)
print("Restoring {}".format(filePath))
shutil.move("{}.bak".format(stashPath), filePath)
if os.path.exists(filePath):
print("Restoring {}".format(filePath))
shutil.move("{}.bak".format(stashPath), filePath)
except:
print_error("Restoring version files failed")
raise
@ -669,9 +690,9 @@ def restore_version_files():
def get_private_keyname(commitID,module="main"):
global pbo_name_prefix
global project_version
aceVersion = get_project_version()
keyName = str("{prefix}{version}-{commit_id}".format(prefix=pbo_name_prefix,version=aceVersion,commit_id=commitID))
keyName = str("{prefix}{version}-{commit_id}".format(prefix=pbo_name_prefix,version=project_version,commit_id=commitID))
return keyName
@ -786,6 +807,7 @@ def main(argv):
global prefix
global pbo_name_prefix
global ciBuild
global missingFiles
if sys.platform != "win32":
print_error("Non-Windows platform (Cygwin?). Please re-run from cmd.")
@ -854,12 +876,9 @@ See the make.cfg file for additional build options.
if "release" in argv:
make_release_zip = True
release_version = argv[argv.index("release") + 1]
argv.remove(release_version)
argv.remove("release")
else:
make_release_zip = False
release_version = project_version
if "target" in argv:
make_target = argv[argv.index("target") + 1]
@ -889,8 +908,22 @@ See the make.cfg file for additional build options.
else:
version_update = False
if "--ci" in argv:
argv.remove("--ci")
version_increments = []
if "increment_build" in argv:
argv.remove("increment_build")
version_increments.append("build")
if "increment_patch" in argv:
argv.remove("increment_patch")
version_increments.append("patch")
if "increment_minor" in argv:
argv.remove("increment_minor")
version_increments.append("minor")
if "increment_major" in argv:
argv.remove("increment_major")
version_increments.append("major")
if "ci" in argv:
argv.remove("ci")
ciBuild = True
print_yellow("\nCheck external references is set to {}".format(str(check_external)))
@ -956,21 +989,21 @@ See the make.cfg file for additional build options.
optionals_root = os.path.join(module_root_parent, "optionals")
extensions_root = os.path.join(module_root_parent, "extensions")
commit_id = get_commit_ID()
key_name = versionStamp = get_private_keyname(commit_id)
print_green ("module_root: {}".format(module_root))
if (os.path.isdir(module_root)):
os.chdir(module_root)
else:
print_error ("Directory {} does not exist.".format(module_root))
sys.exit()
sys.exit(1)
commit_id = get_commit_ID()
get_project_version(version_increments)
key_name = versionStamp = get_private_keyname(commit_id)
print_green ("module_root: {}".format(module_root))
if (os.path.isdir(optionals_root)):
print_green ("optionals_root: {}".format(optionals_root))
else:
print_error ("Directory {} does not exist.".format(optionals_root))
sys.exit()
print("optionals_root does not exist: {}".format(optionals_root))
print_green ("release_dir: {}".format(release_dir))
@ -1022,7 +1055,6 @@ See the make.cfg file for additional build options.
cache = {}
# Check the build version (from main) with cached version - forces a full rebuild when version changes
project_version = get_project_version()
cacheVersion = "None";
if 'cacheVersion' in cache:
cacheVersion = cache['cacheVersion']
@ -1046,6 +1078,9 @@ See the make.cfg file for additional build options.
print_error("Cannot create release directory")
raise
failedBuilds = []
missingFiles = []
# Update version stamp in all files that contain it
# Update version only for release if full update not requested (backup and restore files)
print_blue("\nChecking for obsolete version numbers...")
@ -1056,14 +1091,12 @@ See the make.cfg file for additional build options.
set_version_in_files();
print("Version in files has been changed, make sure you commit and push the updates!")
amountOfBuildsFailed = 0
namesOfBuildsFailed = []
try:
# Temporarily copy optionals_root for building. They will be removed later.
optionals_modules = []
optional_files = []
copy_optionals_for_building(optionals_modules,optional_files)
if (os.path.isdir(optionals_root)):
optionals_modules = []
optional_files = []
copy_optionals_for_building(optionals_modules,optional_files)
# Get list of subdirs in make root.
dirs = next(os.walk(module_root))[1]
@ -1128,15 +1161,14 @@ See the make.cfg file for additional build options.
if (file.endswith(".pbo") and os.path.isfile(os.path.join(obsolete_check_path,file))):
if check_for_obsolete_pbos(module_root, file):
fileName = os.path.splitext(file)[0]
print_yellow("Removing obsolete file => {}".format(file))
print_yellow("Removing obsolete pbo => {}".format(file))
purge(obsolete_check_path, "{}\..".format(fileName), "{}.*".format(fileName))
obsolete_check_path = os.path.join(module_root, release_dir, project)
for file in os.listdir(obsolete_check_path):
if (file.endswith(".dll") and os.path.isfile(os.path.join(obsolete_check_path,file))):
if check_for_obsolete_pbos(extensions_root, file):
fileName = os.path.splitext(file)[0]
print_yellow("Removing obsolete file => {}".format(file))
if not os.path.exists(os.path.join(module_root_parent, file)):
print_yellow("Removing obsolete dll => {}".format(file))
try:
os.remove(os.path.join(obsolete_check_path,file))
except:
@ -1282,8 +1314,7 @@ See the make.cfg file for additional build options.
print_error("pboProject return code == {}".format(str(ret)))
print_error("Module not successfully built/signed. Check your {}temp\{}_packing.log for more info.".format(work_drive,module))
print ("Resuming build...")
amountOfBuildsFailed += 1
namesOfBuildsFailed.append("{}".format(module))
failedBuilds.append("{}".format(module))
continue
# Back to the root
@ -1379,7 +1410,8 @@ See the make.cfg file for additional build options.
finally:
copy_important_files(module_root_parent,os.path.join(release_dir, project))
cleanup_optionals(optionals_modules)
if (os.path.isdir(optionals_root)):
cleanup_optionals(optionals_modules)
if not version_update:
restore_version_files()
@ -1399,8 +1431,7 @@ See the make.cfg file for additional build options.
# Make release
if make_release_zip:
release_name = "{}_{}".format(zipPrefix, release_version)
print_blue("\nMaking release: {}.zip".format(release_name))
release_name = "{}_{}".format(zipPrefix, project_version)
try:
# Delete all log files
@ -1415,7 +1446,10 @@ See the make.cfg file for additional build options.
os.remove(os.path.join(release_dir, file))
# Create a zip with the contents of release folder in it
print_blue("\nMaking release: {}.zip ...".format(release_name))
print("Packing...")
release_zip = shutil.make_archive("{}".format(release_name), "zip", release_dir)
# Move release zip to release folder
shutil.copy(release_zip, release_dir)
os.remove(release_zip)
@ -1450,15 +1484,23 @@ See the make.cfg file for additional build options.
except:
print_error("Could not copy files. Is Arma 3 running?")
if amountOfBuildsFailed > 0:
print_error("Build failed. {} pbos failed.".format(amountOfBuildsFailed))
if len(failedBuilds) > 0 or len(missingFiles) > 0:
if len(failedBuilds) > 0:
print()
print_error("Build failed! {} PBOs failed!".format(len(failedBuilds)))
for failedBuild in failedBuilds:
print("- {} failed.".format(failedBuild))
for failedModuleName in namesOfBuildsFailed:
print("- {} failed.".format(failedModuleName))
if len(missingFiles) > 0:
missingFiles = set(missingFiles)
print()
print_error("Missing files! {} files not found!".format(len(missingFiles)))
for missingFile in missingFiles:
print("- {} failed.".format(missingFile))
sys.exit(1)
else:
print_green("\Completed with 0 errors.")
print_green("\nCompleted with 0 errors.")
if __name__ == "__main__":
start_time = timeit.default_timer()