Remove the non-synchronized cache mess.
[hgct.git] / git.py
blob8274cdac2f10fe7a2c528e7a2697bfd864a60aad
1 import sys, os, re
3 from ctcore import *
5 def repoValid():
6 if not os.environ.has_key('GIT_DIR'):
7 os.environ['GIT_DIR'] = '.git'
9 def basicsFailed(msg):
10 print "'git-cat-file -t HEAD' failed: " + msg
11 print "Make sure that the current working directory contains a '.git' directory, or\nthat GIT_DIR is set appropriately."
12 sys.exit(1)
14 try:
15 runProgram('git-cat-file -t HEAD')
16 except OSError, e:
17 basicsFailed(e.strerror)
18 except ProgramError, e:
19 basicsFailed(e.error)
23 parseDiffRE = re.compile(':([0-9]+) ([0-9]+) ([0-9a-f]{40}) ([0-9a-f]{40}) ([MCRNADUT])([0-9]*)')
24 def parseDiff(prog):
25 inp = runProgram(prog)
26 ret = []
27 try:
28 recs = inp.split("\0")
29 recs.pop() # remove last entry (which is '')
30 it = recs.__iter__()
31 while True:
32 rec = it.next()
33 m = parseDiffRE.match(rec)
35 if not m:
36 print "Unknown output from " + str(prog) + "!: " + rec + "\n"
37 continue
39 f = File()
40 f.srcMode = m.group(1)
41 f.dstMode = m.group(2)
42 f.srcSHA = m.group(3)
43 f.dstSHA = m.group(4)
44 if m.group(5) == 'N':
45 f.change = 'A'
46 else:
47 f.change = m.group(5)
48 f.score = m.group(6)
49 f.srcName = f.dstName = it.next()
51 if f.change == 'C' or f.change == 'R':
52 f.dstName = it.next()
53 f.patch = getPatch(f.srcName, f.dstName)
54 else:
55 f.patch = getPatch(f.srcName)
57 ret.append(f)
58 except StopIteration:
59 pass
60 return ret
63 # HEAD is src in the returned File objects. That is, srcName is the
64 # name in HEAD and dstName is the name in the cache.
65 def getFiles():
66 files = parseDiff('git-diff-files -z')
67 for f in files:
68 doUpdateCache(f.srcName)
70 files = parseDiff('git-diff-cache -z -M --cached HEAD')
71 for f in files:
72 c = f.change
73 if c == 'C':
74 f.text = 'Copy from ' + f.srcName + ' to ' + f.dstName
75 elif c == 'R':
76 f.text = 'Rename from ' + f.srcName + ' to ' + f.dstName
77 elif c == 'A':
78 f.text = 'New file: ' + f.srcName
79 elif c == 'D':
80 f.text = 'Deleted file: ' + f.srcName
81 elif c == 'T':
82 f.text = 'Type change: ' + f.srcName
83 else:
84 f.text = f.srcName
86 return files
88 def getPatch(file, otherFile = None):
89 if otherFile:
90 f = [file, otherFile]
91 else:
92 f = [file]
93 return runProgram(['git-diff-cache', '-p', '-M', '--cached', 'HEAD'] + f)
95 def doUpdateCache(filename):
96 runProgram(['git-update-cache', '--remove', '--add', '--replace', filename])
98 def doCommit(filesToKeep, fileRealNames, msg):
99 for file in filesToKeep:
100 # If we have a new file in the cache which we do not want to
101 # commit we have to remove it from the cache. We will add this
102 # cache entry back in to the cache at the end of this
103 # function.
104 if file.change == 'A':
105 runProgram(['git-update-cache', '--force-remove', file.srcName])
106 else:
107 runProgram(['git-update-cache', '--add', '--replace', '--cacheinfo',
108 file.srcMode, file.srcSHA, file.srcName])
110 tree = runProgram(['git-write-tree'])
111 tree = tree.rstrip()
112 commit = runProgram(['git-commit-tree', tree, '-p', 'HEAD'], msg)
113 commit = commit.rstrip()
115 try:
116 f = open(os.environ['GIT_DIR'] + '/HEAD', 'w+')
117 f.write(commit)
118 f.close()
119 except OSError, e:
120 raise CommitError('write to ' + os.environ['GIT_DIR'] + '/HEAD', e.strerror)
122 try:
123 os.unlink(os.environ['GIT_DIR'] + '/MERGE_HEAD')
124 except OSError:
125 pass
127 for file in filesToKeep:
128 # Don't add files that are going to be deleted back to the cache
129 if file.change != 'D':
130 runProgram(['git-update-cache', '--add', '--replace', '--cacheinfo',
131 file.dstMode, file.dstSHA, file.dstName])