1 # Copyright (c) 2005 Fredrik Kuivinen <freku045@student.liu.se>
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License version 2 as
5 # published by the Free Software Foundation.
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
12 # You should have received a copy of the GNU General Public License
13 # along with this program; if not, write to the Free Software
14 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 if not os
.environ
.has_key('GIT_DIR'):
22 os
.environ
['GIT_DIR'] = '.git'
24 if not os
.environ
.has_key('GIT_OBJECT_DIRECTORY'):
25 os
.environ
['GIT_OBJECT_DIRECTORY'] = os
.environ
['GIT_DIR'] + '/objects'
27 if not (os
.path
.exists(os
.environ
['GIT_DIR']) and
28 os
.path
.exists(os
.environ
['GIT_DIR'] + '/refs') and
29 os
.path
.exists(os
.environ
['GIT_OBJECT_DIRECTORY']) and
30 os
.path
.exists(os
.environ
['GIT_OBJECT_DIRECTORY'] + '/00')):
31 print "Git archive not found."
32 print "Make sure that the current working directory contains a '.git' directory, or\nthat GIT_DIR is set appropriately."
35 parseDiffRE
= re
.compile(':([0-9]+) ([0-9]+) ([0-9a-f]{40}) ([0-9a-f]{40}) ([MCRNADUT])([0-9]*)')
37 inp
= runProgram(prog
)
40 recs
= inp
.split("\0")
41 recs
.pop() # remove last entry (which is '')
45 m
= parseDiffRE
.match(rec
)
48 print "Unknown output from " + str(prog
) + "!: " + rec
+ "\n"
52 f
.srcMode
= m
.group(1)
53 f
.dstMode
= m
.group(2)
61 f
.srcName
= f
.dstName
= it
.next()
63 if f
.change
== 'C' or f
.change
== 'R':
65 f
.patch
= getPatch(f
.srcName
, f
.dstName
)
67 f
.patch
= getPatch(f
.srcName
)
75 # HEAD is src in the returned File objects. That is, srcName is the
76 # name in HEAD and dstName is the name in the cache.
78 files
= parseDiff('git-diff-files -z')
80 doUpdateCache(f
.srcName
)
82 files
= parseDiff('git-diff-cache -z -M --cached HEAD')
86 f
.text
= 'Copy from ' + f
.srcName
+ ' to ' + f
.dstName
88 f
.text
= 'Rename from ' + f
.srcName
+ ' to ' + f
.dstName
90 f
.text
= 'New file: ' + f
.srcName
92 f
.text
= 'Deleted file: ' + f
.srcName
94 f
.text
= 'Type change: ' + f
.srcName
100 def getPatch(file, otherFile
= None):
102 f
= [file, otherFile
]
105 return runProgram(['git-diff-cache', '-p', '-M', '--cached', 'HEAD'] + f
)
107 def doUpdateCache(filename
):
108 runProgram(['git-update-cache', '--remove', '--add', '--replace', filename
])
110 def doCommit(filesToKeep
, fileRealNames
, msg
):
111 for file in filesToKeep
:
112 # If we have a new file in the cache which we do not want to
113 # commit we have to remove it from the cache. We will add this
114 # cache entry back in to the cache at the end of this
116 if file.change
== 'A':
117 runProgram(['git-update-cache', '--force-remove',
119 elif file.change
== 'R':
120 runProgram(['git-update-cache', '--force-remove',
122 runProgram(['git-update-cache', '--add', '--replace',
123 '--cacheinfo', file.srcMode
, file.srcSHA
, file.srcName
])
125 runProgram(['git-update-cache', '--add', '--replace',
126 '--cacheinfo', file.srcMode
, file.srcSHA
, file.srcName
])
128 tree
= runProgram(['git-write-tree'])
132 merge
= ['-p', 'MERGE_HEAD']
135 commit
= runProgram(['git-commit-tree', tree
, '-p', 'HEAD'] + merge
, msg
)
138 f
= open(os
.environ
['GIT_DIR'] + '/HEAD', 'w+')
142 raise CommitError('write to ' + os
.environ
['GIT_DIR'] + '/HEAD', e
.strerror
)
145 os
.unlink(os
.environ
['GIT_DIR'] + '/MERGE_HEAD')
149 for file in filesToKeep
:
150 # Don't add files that are going to be deleted back to the cache
151 if file.change
!= 'D':
152 runProgram(['git-update-cache', '--add', '--replace', '--cacheinfo',
153 file.dstMode
, file.dstSHA
, file.dstName
])
155 if file.change
== 'R':
156 runProgram(['git-update-cache', '--remove', '--', file.srcName
])
158 def discardFile(file):
159 runProgram(['git-read-tree', 'HEAD'])
161 if c
== 'M' or c
== 'T':
162 runProgram(['git-checkout-cache', '-f', '-q', '--', file.dstName
])
163 elif c
== 'A' or c
== 'C':
164 # The file won't be tracked by git now. We could unlink it
165 # from the working directory, but that seems a little bit
169 runProgram(['git-checkout-cache', '-f', '-q', '--', file.dstName
])
171 # Same comment applies here as to the 'A' or 'C' case.
172 runProgram(['git-checkout-cache', '-f', '-q', '--', file.srcName
])
174 def ignoreFile(file):
175 # Not yet implemented
180 os
.stat(os
.environ
['GIT_DIR'] + '/MERGE_HEAD')
186 return '''This is a merge commit if you do not want to commit a ''' + \
187 '''merge remove the file $GIT_DIR/MERGE_HEAD.'''