forked from charleso/git-cc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcheckin.py
135 lines (126 loc) · 4.26 KB
/
checkin.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
"""Checkin new git changesets to Clearcase"""
from common import *
from clearcase import cc
from status import Modify, Add, Delete, Rename, SymLink
import filecmp
from os import listdir
from os.path import isdir
import cache, reset
IGNORE_CONFLICTS=False
LOG_FORMAT = '%H%x01%B'
CC_LABEL = ''
ARGS = {
'force': 'ignore conflicts and check-in anyway',
'no_deliver': 'do not deliver in UCM mode',
'initial': 'checkin everything from the beginning',
'all': 'checkin all parents, not just the first',
'cclabel': 'optionally specify an existing Clearcase label type to apply to each element checked in',
}
def main(force=False, no_deliver=False, initial=False, all=False, cclabel=''):
validateCC()
global IGNORE_CONFLICTS
global CC_LABEL
if cclabel:
CC_LABEL=cclabel
if force:
IGNORE_CONFLICTS=True
cc_exec(['update', '.'], errors=False)
log = ['log', '-z', '--reverse', '--pretty=format:'+ LOG_FORMAT ]
if not all:
log.append('--first-parent')
if not initial:
log.append(CI_TAG + '..')
log = git_exec(log)
if not log:
return
cc.rebase()
for line in log.split('\x00'):
id, comment = line.split('\x01')
statuses = getStatuses(id, initial)
checkout(statuses, comment.strip(), initial)
tag(CI_TAG, id)
if not no_deliver:
cc.commit()
if initial:
git_exec(['commit', '--allow-empty', '-m', 'Empty commit'])
reset.main('HEAD')
def getStatuses(id, initial):
cmd = ['diff','--name-status', '-M', '-z', '--ignore-submodules', '%s^..%s' % (id, id)]
if initial:
cmd = cmd[:-1]
cmd[0] = 'show'
cmd.extend(['--pretty=format:', id])
status = git_exec(cmd)
status = status.strip()
status = status.strip("\x00")
types = {'M':Modify, 'R':Rename, 'D':Delete, 'A':Add, 'C':Add, 'S':SymLink}
list = []
split = status.split('\x00')
while len(split) > 1:
char = split.pop(0)[0] # first char
args = [split.pop(0)]
# check if file is really a symlink
cmd = ['ls-tree', '-z', id, '--', args[0]]
if git_exec(cmd).split(' ')[0] == '120000':
char = 'S'
args.append(id)
if char == 'R':
args.append(split.pop(0))
elif char == 'C':
args = [split.pop(0)]
if args[0] == cache.FILE:
continue
type = types[char](args)
type.id = id
list.append(type)
return list
def checkout(stats, comment, initial):
"""Poor mans two-phase commit"""
transaction = ITransaction(comment) if initial else Transaction(comment)
for stat in stats:
try:
stat.stage(transaction)
except:
transaction.rollback()
raise
for stat in stats:
stat.commit(transaction)
transaction.commit(comment);
class ITransaction(object):
def __init__(self, comment):
self.checkedout = []
self.cc_label = CC_LABEL
cc.mkact(comment)
def add(self, file):
self.checkedout.append(file)
def co(self, file):
cc_exec(['co', '-reserved', '-nc', file])
if CC_LABEL:
cc_exec(['mklabel', '-replace', '-nc', CC_LABEL, file])
self.add(file)
def stageDir(self, file):
file = file if file else '.'
if file not in self.checkedout:
self.co(file)
def stage(self, file):
self.co(file)
def rollback(self):
for file in self.checkedout:
cc_exec(['unco', '-rm', file])
cc.rmactivity()
def commit(self, comment):
for file in self.checkedout:
cc_exec(['ci', '-identical', '-c', comment, file])
class Transaction(ITransaction):
def __init__(self, comment):
super(Transaction, self).__init__(comment)
self.base = git_exec(['merge-base', CI_TAG, 'HEAD']).strip()
def stage(self, file):
super(Transaction, self).stage(file)
ccid = git_exec(['hash-object', join(CC_DIR, file)])[0:-1]
gitid = getBlob(self.base, file)
if ccid != gitid:
if not IGNORE_CONFLICTS:
raise Exception('File has been modified: %s. Try rebasing.' % file)
else:
print ('WARNING: Detected possible confilct with',file,'...ignoring...')