| 
						 
							
							
							
						 
					 | 
				
			
			 | 
			 | 
			
				@ -1,162 +0,0 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#!/usr/bin/python3
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				# Usage: ./deploy-to-multiple-worktrees.py REPO_PATH WORKTREE_DEVELOPMENT_PATH WORKTREE_PRODUCTION_PATH
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import sys
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import os
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import subprocess
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import re
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				WORKTREE_REGEX = r"^worktree (.*)\nHEAD ([a-f0-9]*)\n(?:branch refs\/heads\/(.*)|detached)$"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				if len(sys.argv) < 4:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    print("Usage: ./deploy-to-multiple-worktrees.py REPO_PATH WORKTREE_DEVELOPMENT_PATH WORKTREE_PRODUCTION_PATH")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    exit(1)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				REPO = os.path.abspath(sys.argv[1])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				WORKTREE_DEVELOPMENT = os.path.abspath(sys.argv[2])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				WORKTREE_PRODUCTION = os.path.abspath(sys.argv[3])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				class Worktree:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    def __init__(self, path, branch, revision, version):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.path = path
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.branch = branch
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.revision = revision
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.version = version
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.newRevision = None
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.newVersion = None
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def getDataForWorktrees():
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    ret = subprocess.check_output(["git", "worktree", "list", "--porcelain"], cwd=REPO).decode().strip()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    blocks = ret.split("\n\n")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    worktrees = []
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    for block in blocks:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        matches = re.search(WORKTREE_REGEX, block)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if matches:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            path = matches.group(1)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            revision = matches.group(2)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            branch = matches.group(3)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            version = getVersion(revision)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            worktrees.append(Worktree(path, branch, revision, version))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return worktrees
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def findWorktree(path):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    for worktree in worktrees:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if worktree.path == path:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            return worktree
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return None
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def getVersion(branch):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return subprocess.check_output(["git", "describe", "--tags", "--always", "--match", "Release_*", branch], cwd=REPO).decode().strip()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def getRevisionForRef(ref):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return subprocess.check_output(["git", "rev-list", "-1", ref], cwd=REPO).decode().strip()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def getLatestReleaseTag():
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    process = subprocess.Popen(["git", "for-each-ref", "refs/tags/Release*", "--sort=-creatordate", "--format=%(refname:short)"], stdout=subprocess.PIPE, cwd=REPO)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    for line in process.stdout:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        tag = line.decode().rstrip()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if isTagVerified(tag):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            return tag
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        print(f"[WARNING] Tag '{tag}' is not verified, skipping.")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    raise Exception("No verified 'Release*' tag found!")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def isTagVerified(tag):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    process = subprocess.run(["git", "tag", "--verify", tag], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=REPO)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return process.returncode == 0
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def updateRepoFromRemote():
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    subprocess.call(["git", "fetch", "origin", "--prune", "--prune-tags"], cwd=REPO)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def checkoutWorktree(worktreePath, ref):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    subprocess.call(["git", "checkout", "-f", ref], cwd=worktreePath)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def cleanWorktree(worktreePath):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    subprocess.call(["git", "clean", "-f", "-d"], cwd=worktreePath)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def updateAppInWorktree(worktreePath):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    subprocess.call([worktreePath + "/scripts/update.sh"], cwd=worktreePath)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def updateAppVersionInWorktree(worktreePath):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    subprocess.call([worktreePath + "/scripts/update-version.sh"], cwd=worktreePath)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				worktrees = getDataForWorktrees()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				updateRepoFromRemote()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				print("Repo is updated from origin")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				print("----------------------------------------------")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				print("----------------------------------------------")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				developmentWorktree = findWorktree(WORKTREE_DEVELOPMENT)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				developmentWorktree.newRevision = getRevisionForRef(developmentWorktree.branch)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				developmentWorktree.newVersion = getVersion(developmentWorktree.revision)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				print("DEVELOPMENT (" + developmentWorktree.path + ") is on branch " + developmentWorktree.branch)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				print(developmentWorktree.revision + " = " + developmentWorktree.branch + " (" + developmentWorktree.version + ")")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				print(developmentWorktree.newRevision + " = origin/" + developmentWorktree.branch + " (" + developmentWorktree.newVersion + ")")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				if developmentWorktree.revision != developmentWorktree.newRevision:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    print("-> DEVELOPMENT (" + developmentWorktree.path + ") will be UPDATED")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    print("----------------------------------------------")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    checkoutWorktree(developmentWorktree.path, developmentWorktree.branch)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    cleanWorktree(developmentWorktree.path)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    print(developmentWorktree.path + " is checked out to " + developmentWorktree.branch + " and cleaned")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    updateAppInWorktree(developmentWorktree.path)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    updateAppVersionInWorktree(developmentWorktree.path)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    print("RVR is updated in " + developmentWorktree.path)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				elif developmentWorktree.version != developmentWorktree.newVersion:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    print("-> DEVELOPMENT " + developmentWorktree.path + "'s version info will be UPDATED")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    updateAppVersionInWorktree(developmentWorktree.path)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    print("RVR version is updated in " + developmentWorktree.path)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    print("-> DEVELOPMENT (" + developmentWorktree.path + ") WON'T be updated")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				print("----------------------------------------------")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				print("----------------------------------------------")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				productionWorktree = findWorktree(WORKTREE_PRODUCTION)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				productionWorktree.newVersion = getLatestReleaseTag()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				productionWorktree.newRevision = getRevisionForRef(productionWorktree.newVersion)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				print("PRODUCTION (" + productionWorktree.path + ")")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				print(productionWorktree.revision + " = " + productionWorktree.version)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				print(productionWorktree.newRevision + " = " + productionWorktree.newVersion)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				if productionWorktree.revision != productionWorktree.newRevision:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    print("-> PRODUCTION (" + productionWorktree.path + ") will be UPDATED")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    checkoutWorktree(productionWorktree.path, productionWorktree.newRevision)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    cleanWorktree(productionWorktree.path)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    print(productionWorktree.path + " is checked out to " + productionWorktree.newRevision + " and cleaned")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    updateAppInWorktree(productionWorktree.path)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    updateAppVersionInWorktree(productionWorktree.path)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    print("RVR is updated in " + productionWorktree.path)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				else:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    print("-> PRODUCTION (" + productionWorktree.path + ") WON'T be updated")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				print("----------------------------------------------")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				print("----------------------------------------------")
 |