forked from NavicoOS/ac2git
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrecover_state_from_log.py
executable file
·111 lines (91 loc) · 4.27 KB
/
recover_state_from_log.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/python3
# Helper script for the transactions method that can read the log file
# and use it to detect and recover the state to one of the transactions
# at which the script had previously been restarted.
import sys
import os
import re
import json
import subprocess
import codecs
import argparse
import tempfile
import git
branchRe = re.compile(r'^.* - Branch ([^ \t\r\n]+) at ([0-9a-fA-F]+)(, current)?.$')
def GetBranch(logLine):
m = branchRe.match(logLine)
if m:
br = m.group(1)
hash = m.group(2)
isCurrent = m.group(3) is not None
return { "name": br, "commit": hash, "is_current": isCurrent}
return None
lastStateRe = re.compile(r'^.*Loaded last state at transaction ([0-9]+) as:$')
def GetTransaction(logLine):
m = lastStateRe.match(logLine)
if m is not None:
return int(m.group(1))
return None
def Restore(repoPath, branchList, transaction):
print("Restoring state for transaction: {tr}".format(tr=transaction))
print("branch list:")
for br in branchList:
print(" - Branch {br} at {hash}.{current}".format(br=br["name"], hash=br["commit"], current=' Current.' if br["is_current"] else ''))
state = { "transaction": transaction, "branch_list": branchList }
repo = git.open(repoPath)
if repo is None:
print("Failed to open git repository '{r}'".format(r=repoPath))
return 1
stateFilePath = None
with tempfile.NamedTemporaryFile(mode='w+', prefix='ac2git_state_', delete=False) as stateFile:
stateFilePath = stateFile.name
stateFile.write(json.dumps(state))
hashObj = repo.raw_cmd(['git', 'hash-object', '-w', stateFilePath ])
if hashObj is None:
raise Exception("Failed to restore state! git hash-object -w {f}, returned {r}.".format(f=stateFilePath, r=hashObj))
else:
os.remove(stateFilePath)
refResult = repo.raw_cmd(['git', 'update-ref', 'refs/ac2git/state', hashObj])
if refResult is None:
raise Exception("Failed to restore state! git update-ref refs/ac2git/state {h}, returned {r}.".format(h=hashObj, r=refResult))
return 0
def Main(argv):
argparser = argparse.ArgumentParser(description='Processes a logfile previously generated by the ac2git.py script for restore points and optionally restores the state of a git repository to a selected point. Only works for the transactions method conversions.')
argparser.add_argument('-f', '--file', dest='file', help='The log file from which the state information will be parsed.')
argparser.add_argument('-t', '--transaction', dest='transaction', help='The transaction, from the log file, to which the state will be restored to. If omitted then all potential restore points are printed and the script exits with a return code of 1.')
argparser.add_argument('-r', '--git-repo', dest='repo', help='The path to the git repository whose state will be restored.')
args = argparser.parse_args()
if not os.path.exists(args.file):
print("Failed to open log file '{f}'.".format(f=args.file))
return 1
trList = []
with codecs.open(args.file) as f:
line = f.readline()
while len(line) > 0:
line = line.strip()
tr = GetTransaction(line)
if tr is not None:
branchList = []
line = f.readline()
while len(line) > 0:
line = line.strip()
br = GetBranch(line)
if br is not None:
branchList.append(br)
else:
break
line=f.readline()
if args.transaction is not None and int(tr) == int(args.transaction):
return Restore(args.repo, branchList, int(args.transaction))
elif tr not in trList:
trList.append(tr)
print("Found transaction {tr}.".format(tr=tr))
line = f.readline()
if len(trList) > 0:
print("Please choose one of the transactions listed above to restore the state to and re-run the script with the -t option.")
return 0
else:
print("Found no usable transaction state information in the log file '{f}'".format(f=args.file))
return 1
if __name__ == "__main__":
Main(sys.argv)