Skip to content

Instantly share code, notes, and snippets.

@keitaoouchi
Last active December 19, 2015 11:19
Show Gist options
  • Save keitaoouchi/5946604 to your computer and use it in GitHub Desktop.
Save keitaoouchi/5946604 to your computer and use it in GitHub Desktop.
git-svnでリビジョン番号かチケット番号でデプロイファイルの一覧を出力する
#!/usr/bin/env python3
"""git-svnでリビジョン番号かチケット番号でデプロイファイルの一覧を出力する
python gitsvn.py -d /path/to/repos -r 1 2 3
python gitsvn.py -d /path/to/repos -t 1000
"""
import re
import os
import subprocess
import argparse
PIPE = subprocess.PIPE
def listup_revisions(ticket):
pattern = re.compile("r(\d+) .+ #{} .+".format(ticket))
git = which_git()
process = subprocess.Popen([git, "svn", "log", "--oneline"], stdout=PIPE, stderr=PIPE)
out = process.communicate()[0]
lines = out.splitlines()
revisions = []
for line in lines:
matcher = pattern.match(str(line, encoding="utf-8"))
if matcher:
revision, = matcher.groups()
revisions.append(revision)
return sorted(set(revisions))
def which_git():
process = subprocess.Popen(["which", "git"], stdout=PIPE, stderr=PIPE)
out = process.communicate()[0]
return str(out.strip(b"\n"), encoding="utf-8")
def svn_log(revision):
git = which_git()
process = subprocess.Popen([git, "svn", "log", "-r", revision, "-v"], stdout=PIPE, stderr=PIPE)
return process.communicate()[0]
def analize_log(log_message):
result = {'A': set(), 'M': set(), 'D': set()}
parser = re.compile("\s+(A|M|D)\s(.+)$")
lines = log_message.splitlines(False)
for line in lines:
matcher = parser.match(str(line, encoding="utf-8"))
if matcher:
edit_type, path = matcher.groups()
result[edit_type].add(path)
return result
def aggregate(list_of_log_maps):
result = {'A': set(), 'M': set(), 'D': set()}
for log_map in list_of_log_maps:
deleted_files = log_map['D']
for deleted_file in deleted_files:
if deleted_file in result['A']:
result['A'].remove(deleted_file)
elif deleted_file in result['M']:
result['M'].remove(deleted_file)
else:
result['D'].add(deleted_file)
modified_files = log_map['M']
for modified_file in modified_files:
if modified_file in result['A']:
result['A'].remove(modified_file)
result['M'].add(modified_file)
append_files = log_map['A']
result['A'].update(append_files)
return result
def main(root, ticket, revisions=None):
os.chdir(root)
revisions = revisions if revisions else listup_revisions(ticket)
print("--------target revisions--------")
print(revisions)
log_maps = []
for revision in revisions:
r = str(revision) if isinstance(revision, int) else revision
log = svn_log(r)
log_map = analize_log(log)
log_maps.append(log_map)
result = aggregate(log_maps)
upload_target = set()
delete_target = set()
upload_target.update(result['A'])
upload_target.update(result['M'])
delete_target.update(result['D'])
return upload_target, delete_target
def parse_args():
parser = argparse.ArgumentParser(description='Parse arguments')
parser.add_argument('-d', '--dir', action="store", required=True,
help='path to repository root directory')
parser.add_argument('-r', '--revisions', action="append",
type=int, nargs='+', help='revision strings')
parser.add_argument('-t', '--ticket', action="store",
nargs='?', type=int, help='ticket number')
args = parser.parse_args()
return args.dir, args.revisions[0] if args.revisions else [], args.ticket
if __name__ == '__main__':
root, revisions, ticket = parse_args()
u, d = main(root, ticket, revisions)
up = sorted(u)
de = sorted(d)
print("------Upload------")
for f in up:
print(f)
print("")
print("------Delete------")
for f in de:
print(f)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment