settings.py is a module now, make sure we "compile" it.
[hgct.git] / git.py
blobdd21320a80a49ebda014262316d90111b9a025ef
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 if not os.environ.has_key('GIT_OBJECT_DIRECTORY'):
10 os.environ['GIT_OBJECT_DIRECTORY'] = os.environ['GIT_DIR'] + '/objects'
12 if not (os.path.exists(os.environ['GIT_DIR']) and
13 os.path.exists(os.environ['GIT_DIR'] + '/refs') and
14 os.path.exists(os.environ['GIT_OBJECT_DIRECTORY']) and
15 os.path.exists(os.environ['GIT_OBJECT_DIRECTORY'] + '/00')):
16 print "Git archive not found."
17 print "Make sure that the current working directory contains a '.git' directory, or\nthat GIT_DIR is set appropriately."
18 sys.exit(1)
20 parseDiffRE = re.compile(':([0-9]+) ([0-9]+) ([0-9a-f]{40}) ([0-9a-f]{40}) ([MCRNADUT])([0-9]*)')
21 def parseDiff(prog):
22 inp = runProgram(prog)
23 ret = []
24 try:
25 recs = inp.split("\0")
26 recs.pop() # remove last entry (which is '')
27 it = recs.__iter__()
28 while True:
29 rec = it.next()
30 m = parseDiffRE.match(rec)
32 if not m:
33 print "Unknown output from " + str(prog) + "!: " + rec + "\n"
34 continue
36 f = File()
37 f.srcMode = m.group(1)
38 f.dstMode = m.group(2)
39 f.srcSHA = m.group(3)
40 f.dstSHA = m.group(4)
41 if m.group(5) == 'N':
42 f.change = 'A'
43 else:
44 f.change = m.group(5)
45 f.score = m.group(6)
46 f.srcName = f.dstName = it.next()
48 if f.change == 'C' or f.change == 'R':
49 f.dstName = it.next()
50 f.patch = getPatch(f.srcName, f.dstName)
51 else:
52 f.patch = getPatch(f.srcName)
54 ret.append(f)
55 except StopIteration:
56 pass
57 return ret
60 # HEAD is src in the returned File objects. That is, srcName is the
61 # name in HEAD and dstName is the name in the cache.
62 def getFiles():
63 files = parseDiff('git-diff-files -z')
64 for f in files:
65 doUpdateCache(f.srcName)
67 files = parseDiff('git-diff-cache -z -M --cached HEAD')
68 for f in files:
69 c = f.change
70 if c == 'C':
71 f.text = 'Copy from ' + f.srcName + ' to ' + f.dstName
72 elif c == 'R':
73 f.text = 'Rename from ' + f.srcName + ' to ' + f.dstName
74 elif c == 'A':
75 f.text = 'New file: ' + f.srcName
76 elif c == 'D':
77 f.text = 'Deleted file: ' + f.srcName
78 elif c == 'T':
79 f.text = 'Type change: ' + f.srcName
80 else:
81 f.text = f.srcName
83 return files
85 def getPatch(file, otherFile = None):
86 if otherFile:
87 f = [file, otherFile]
88 else:
89 f = [file]
90 return runProgram(['git-diff-cache', '-p', '-M', '--cached', 'HEAD'] + f)
92 def doUpdateCache(filename):
93 runProgram(['git-update-cache', '--remove', '--add', '--replace', filename])
95 def doCommit(filesToKeep, fileRealNames, msg):
96 for file in filesToKeep:
97 # If we have a new file in the cache which we do not want to
98 # commit we have to remove it from the cache. We will add this
99 # cache entry back in to the cache at the end of this
100 # function.
101 if file.change == 'A':
102 runProgram(['git-update-cache', '--force-remove', file.srcName])
103 else:
104 runProgram(['git-update-cache', '--add', '--replace', '--cacheinfo',
105 file.srcMode, file.srcSHA, file.srcName])
107 tree = runProgram(['git-write-tree'])
108 tree = tree.rstrip()
109 commit = runProgram(['git-commit-tree', tree, '-p', 'HEAD'], msg)
111 try:
112 f = open(os.environ['GIT_DIR'] + '/HEAD', 'w+')
113 f.write(commit)
114 f.close()
115 except OSError, e:
116 raise CommitError('write to ' + os.environ['GIT_DIR'] + '/HEAD', e.strerror)
118 try:
119 os.unlink(os.environ['GIT_DIR'] + '/MERGE_HEAD')
120 except OSError:
121 pass
123 for file in filesToKeep:
124 # Don't add files that are going to be deleted back to the cache
125 if file.change != 'D':
126 runProgram(['git-update-cache', '--add', '--replace', '--cacheinfo',
127 file.dstMode, file.dstSHA, file.dstName])
129 def discardFile(file):
130 runProgram(['git-read-tree', 'HEAD'])
131 c = file.change
132 if c == 'M' or c == 'T':
133 runProgram(['git-checkout-cache', '-f', '-q', '--', file.dstName])
134 elif c == 'A' or c == 'C':
135 # The file won't be tracked by git now. We could unlink it
136 # from the working directory, but that seems a little bit
137 # too dangerous.
138 pass
139 elif c == 'D':
140 runProgram(['git-checkout-cache', '-f', '-q', '--', file.dstName])
141 elif c == 'R':
142 # Same comment applies here as to the 'A' or 'C' case.
143 runProgram(['git-checkout-cache', '-f', '-q', '--', file.srcName])
145 def ignoreFile(file):
146 # Not yet implemented
147 pass