mirror of https://github.com/oxen-io/session-ios
Audit for missing reverse integration upon committing to master
This is meant as a nag. I'm not sure there'd be a good way to catch-us-in-the-act unless we migrate to some merge tools a la git-flow. // FREEBIEpull/1/head
parent
b023e77d0e
commit
72428350c2
@ -0,0 +1 @@
|
|||||||
|
Copy these git hooks into .git/hooks
|
@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
Scripts/reverse_integration_check.py
|
@ -0,0 +1,141 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import datetime
|
||||||
|
import argparse
|
||||||
|
import commands
|
||||||
|
|
||||||
|
|
||||||
|
git_repo_path = os.path.abspath(subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).strip())
|
||||||
|
|
||||||
|
|
||||||
|
def splitall(path):
|
||||||
|
allparts = []
|
||||||
|
while 1:
|
||||||
|
parts = os.path.split(path)
|
||||||
|
if parts[0] == path: # sentinel for absolute paths
|
||||||
|
allparts.insert(0, parts[0])
|
||||||
|
break
|
||||||
|
elif parts[1] == path: # sentinel for relative paths
|
||||||
|
allparts.insert(0, parts[1])
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
path = parts[0]
|
||||||
|
allparts.insert(0, parts[1])
|
||||||
|
return allparts
|
||||||
|
|
||||||
|
|
||||||
|
def process(filepath):
|
||||||
|
|
||||||
|
short_filepath = filepath[len(git_repo_path):]
|
||||||
|
if short_filepath.startswith(os.sep):
|
||||||
|
short_filepath = short_filepath[len(os.sep):]
|
||||||
|
|
||||||
|
filename = os.path.basename(filepath)
|
||||||
|
if filename.startswith('.'):
|
||||||
|
return
|
||||||
|
file_ext = os.path.splitext(filename)[1]
|
||||||
|
if file_ext in ('.swift'):
|
||||||
|
env_copy = os.environ.copy()
|
||||||
|
env_copy["SCRIPT_INPUT_FILE_COUNT"] = "1"
|
||||||
|
env_copy["SCRIPT_INPUT_FILE_0"] = '%s' % ( short_filepath, )
|
||||||
|
lint_output = subprocess.check_output(['swiftlint', 'autocorrect', '--use-script-input-files'], env=env_copy)
|
||||||
|
print lint_output
|
||||||
|
try:
|
||||||
|
lint_output = subprocess.check_output(['swiftlint', 'lint', '--use-script-input-files'], env=env_copy)
|
||||||
|
except subprocess.CalledProcessError, e:
|
||||||
|
lint_output = e.output
|
||||||
|
print lint_output
|
||||||
|
|
||||||
|
with open(filepath, 'rt') as f:
|
||||||
|
text = f.read()
|
||||||
|
original_text = text
|
||||||
|
|
||||||
|
lines = text.split('\n')
|
||||||
|
while lines and lines[0].startswith('//'):
|
||||||
|
lines = lines[1:]
|
||||||
|
text = '\n'.join(lines)
|
||||||
|
text = text.strip()
|
||||||
|
|
||||||
|
header = '''//
|
||||||
|
// Copyright (c) %s Open Whisper Systems. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
''' % (
|
||||||
|
datetime.datetime.now().year,
|
||||||
|
)
|
||||||
|
text = header + text + '\n'
|
||||||
|
|
||||||
|
if original_text == text:
|
||||||
|
return
|
||||||
|
|
||||||
|
print 'Updating:', short_filepath
|
||||||
|
|
||||||
|
with open(filepath, 'wt') as f:
|
||||||
|
f.write(text)
|
||||||
|
|
||||||
|
|
||||||
|
def should_ignore_path(path):
|
||||||
|
ignore_paths = [
|
||||||
|
os.path.join(git_repo_path, '.git')
|
||||||
|
]
|
||||||
|
for ignore_path in ignore_paths:
|
||||||
|
if path.startswith(ignore_path):
|
||||||
|
return True
|
||||||
|
for component in splitall(path):
|
||||||
|
if component.startswith('.'):
|
||||||
|
return True
|
||||||
|
if component.endswith('.framework'):
|
||||||
|
return True
|
||||||
|
if component in ('Pods', 'ThirdParty', 'Carthage',):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def process_if_appropriate(filepath):
|
||||||
|
filename = os.path.basename(filepath)
|
||||||
|
if filename.startswith('.'):
|
||||||
|
return
|
||||||
|
file_ext = os.path.splitext(filename)[1]
|
||||||
|
if file_ext not in ('.h', '.hpp', '.cpp', '.m', '.mm', '.pch', '.swift'):
|
||||||
|
return
|
||||||
|
if should_ignore_path(filepath):
|
||||||
|
return
|
||||||
|
process(filepath)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='Precommit script.')
|
||||||
|
parser.add_argument('--all', action='store_true', help='process all files in or below current dir')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.all:
|
||||||
|
for rootdir, dirnames, filenames in os.walk(git_repo_path):
|
||||||
|
for filename in filenames:
|
||||||
|
file_path = os.path.abspath(os.path.join(rootdir, filename))
|
||||||
|
process_if_appropriate(file_path)
|
||||||
|
else:
|
||||||
|
filepaths = []
|
||||||
|
|
||||||
|
# Staging
|
||||||
|
output = commands.getoutput('git diff --cached --name-only --diff-filter=ACMR')
|
||||||
|
filepaths.extend([line.strip() for line in output.split('\n')])
|
||||||
|
|
||||||
|
# Working
|
||||||
|
output = commands.getoutput('git diff --name-only --diff-filter=ACMR')
|
||||||
|
filepaths.extend([line.strip() for line in output.split('\n')])
|
||||||
|
|
||||||
|
# Only process each path once.
|
||||||
|
filepaths = sorted(set(filepaths))
|
||||||
|
|
||||||
|
for filepath in filepaths:
|
||||||
|
filepath = os.path.abspath(os.path.join(git_repo_path, filepath))
|
||||||
|
process_if_appropriate(filepath)
|
||||||
|
|
||||||
|
print 'git clang-format...'
|
||||||
|
print commands.getoutput('git clang-format')
|
@ -0,0 +1,45 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
# When we make a hotfix, we need to reverse integrate our hotfix back into
|
||||||
|
# master. After commiting to master, this script audits that all tags have been
|
||||||
|
# reverse integrated.
|
||||||
|
import subprocess
|
||||||
|
from distutils.version import LooseVersion
|
||||||
|
import logging
|
||||||
|
|
||||||
|
#logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
|
def is_on_master():
|
||||||
|
output = subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]).strip()
|
||||||
|
logging.debug("branch output: %s" % output)
|
||||||
|
return output == "master"
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if not is_on_master():
|
||||||
|
# Don't interfere while on a feature or hotfix branch
|
||||||
|
logging.debug("not on master branch")
|
||||||
|
return
|
||||||
|
|
||||||
|
logging.debug("on master branch")
|
||||||
|
|
||||||
|
unmerged_tags_output = subprocess.check_output(["git", "tag", "--no-merged", "master"])
|
||||||
|
unmerged_tags = [line.strip() for line in unmerged_tags_output.split("\n") if len(line) > 0]
|
||||||
|
|
||||||
|
logging.debug("All unmerged tags: %s" % unmerged_tags)
|
||||||
|
|
||||||
|
# Before this point we weren't always reverse integrating our tags. As we
|
||||||
|
# audit old tags, we can ratchet this version number back.
|
||||||
|
epoch_tag="2.21.0"
|
||||||
|
|
||||||
|
logging.debug("ignoring tags before epoch_tag: %s" % epoch_tag)
|
||||||
|
|
||||||
|
tags_of_concern = [unmerged_tag for unmerged_tag in unmerged_tags if LooseVersion(unmerged_tag) > LooseVersion(epoch_tag)]
|
||||||
|
|
||||||
|
if len(tags_of_concern) > 0:
|
||||||
|
logging.debug("Found unmerged tags newer than epoch: %s" % tags_of_concern)
|
||||||
|
raise RuntimeError("Found unmerged tags: %s" % tags_of_concern)
|
||||||
|
else:
|
||||||
|
logging.debug("No unmerged tags newer than epoch. All good!")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue