~mdw
/
stgit
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Add a boundary to parse_patches()
[stgit]
/
stgit
/
git.py
diff --git
a/stgit/git.py
b/stgit/git.py
index
05d851d
..
0e83ffc
100644
(file)
--- a/
stgit/git.py
+++ b/
stgit/git.py
@@
-22,6
+22,7
@@
import sys, os, popen2, re, gitmergeonefile
from stgit import basedir
from stgit.utils import *
from stgit import basedir
from stgit.utils import *
+from stgit.config import config
# git exception class
class GitException(Exception):
# git exception class
class GitException(Exception):
@@
-39,7
+40,6
@@
class Commit:
self.__id_hash = id_hash
lines = _output_lines('git-cat-file commit %s' % id_hash)
self.__id_hash = id_hash
lines = _output_lines('git-cat-file commit %s' % id_hash)
- self.__parents = []
for i in range(len(lines)):
line = lines[i]
if line == '\n':
for i in range(len(lines)):
line = lines[i]
if line == '\n':
@@
-47,8
+47,6
@@
class Commit:
field = line.strip().split(' ', 1)
if field[0] == 'tree':
self.__tree = field[1]
field = line.strip().split(' ', 1)
if field[0] == 'tree':
self.__tree = field[1]
- elif field[0] == 'parent':
- self.__parents.append(field[1])
if field[0] == 'author':
self.__author = field[1]
if field[0] == 'committer':
if field[0] == 'author':
self.__author = field[1]
if field[0] == 'committer':
@@
-62,10
+60,15
@@
class Commit:
return self.__tree
def get_parent(self):
return self.__tree
def get_parent(self):
- return self.__parents[0]
+ parents = self.get_parents()
+ if parents:
+ return parents[0]
+ else:
+ return None
def get_parents(self):
def get_parents(self):
- return self.__parents
+ return _output_lines('git-rev-list --parents --max-count=1 %s'
+ % self.__id_hash)[0].split()[1:]
def get_author(self):
return self.__author
def get_author(self):
return self.__author
@@
-76,6
+79,9
@@
class Commit:
def get_log(self):
return self.__log
def get_log(self):
return self.__log
+ def __str__(self):
+ return self.get_id_hash()
+
# dictionary of Commit objects, used to avoid multiple calls to git
__commits = dict()
# dictionary of Commit objects, used to avoid multiple calls to git
__commits = dict()
@@
-117,20
+123,23
@@
def _input(cmd, file_desc):
p.tochild.write(line)
p.tochild.close()
if p.wait():
p.tochild.write(line)
p.tochild.close()
if p.wait():
- raise GitException, '%s failed' % str(cmd)
+ raise GitException, '%s failed (%s)' % (str(cmd),
+ p.childerr.read().strip())
def _input_str(cmd, string):
p = popen2.Popen3(cmd, True)
p.tochild.write(string)
p.tochild.close()
if p.wait():
def _input_str(cmd, string):
p = popen2.Popen3(cmd, True)
p.tochild.write(string)
p.tochild.close()
if p.wait():
- raise GitException, '%s failed' % str(cmd)
+ raise GitException, '%s failed (%s)' % (str(cmd),
+ p.childerr.read().strip())
def _output(cmd):
p=popen2.Popen3(cmd, True)
output = p.fromchild.read()
if p.wait():
def _output(cmd):
p=popen2.Popen3(cmd, True)
output = p.fromchild.read()
if p.wait():
- raise GitException, '%s failed' % str(cmd)
+ raise GitException, '%s failed (%s)' % (str(cmd),
+ p.childerr.read().strip())
return output
def _output_one_line(cmd, file_desc = None):
return output
def _output_one_line(cmd, file_desc = None):
@@
-141,14
+150,16
@@
def _output_one_line(cmd, file_desc = None):
p.tochild.close()
output = p.fromchild.readline().strip()
if p.wait():
p.tochild.close()
output = p.fromchild.readline().strip()
if p.wait():
- raise GitException, '%s failed' % str(cmd)
+ raise GitException, '%s failed (%s)' % (str(cmd),
+ p.childerr.read().strip())
return output
def _output_lines(cmd):
p=popen2.Popen3(cmd, True)
lines = p.fromchild.readlines()
if p.wait():
return output
def _output_lines(cmd):
p=popen2.Popen3(cmd, True)
lines = p.fromchild.readlines()
if p.wait():
- raise GitException, '%s failed' % str(cmd)
+ raise GitException, '%s failed (%s)' % (str(cmd),
+ p.childerr.read().strip())
return lines
def __run(cmd, args=None):
return lines
def __run(cmd, args=None):
@@
-171,9
+182,14
@@
def __run(cmd, args=None):
return 0
def __tree_status(files = None, tree_id = 'HEAD', unknown = False,
return 0
def __tree_status(files = None, tree_id = 'HEAD', unknown = False,
- noexclude = True):
+ noexclude = True
, verbose = False
):
"""Returns a list of pairs - [status, filename]
"""
"""Returns a list of pairs - [status, filename]
"""
+ if verbose:
+ print >> sys.stderr, \
+ 'Checking for changes in the working directory...',
+ sys.stderr.flush()
+
refresh_index()
if not files:
refresh_index()
if not files:
@@
-205,17
+221,20
@@
def __tree_status(files = None, tree_id = 'HEAD', unknown = False,
cache_files += [('C', filename) for filename in conflicts]
# the rest
cache_files += [('C', filename) for filename in conflicts]
# the rest
- for line in _output_lines(['git-diff-index', tree_id] + files):
+ for line in _output_lines(['git-diff-index', tree_id
, '--'
] + files):
fs = tuple(line.rstrip().split(' ',4)[-1].split('\t',1))
if fs[1] not in conflicts:
cache_files.append(fs)
fs = tuple(line.rstrip().split(' ',4)[-1].split('\t',1))
if fs[1] not in conflicts:
cache_files.append(fs)
+ if verbose:
+ print >> sys.stderr, 'done'
+
return cache_files
def local_changes():
"""Return true if there are local changes in the tree
"""
return cache_files
def local_changes():
"""Return true if there are local changes in the tree
"""
- return len(__tree_status()) != 0
+ return len(__tree_status(
verbose = True
)) != 0
# HEAD value cached
__head = None
# HEAD value cached
__head = None
@@
-390,7
+409,7
@@
def update_cache(files = None, force = False):
if not files:
files = []
if not files:
files = []
- cache_files = __tree_status(files)
+ cache_files = __tree_status(files
, verbose = False
)
# everything is up-to-date
if len(cache_files) == 0:
# everything is up-to-date
if len(cache_files) == 0:
@@
-433,7
+452,9
@@
def commit(message, files = None, parents = None, allowempty = False,
raise GitException, 'No changes to commit'
# get the commit message
raise GitException, 'No changes to commit'
# get the commit message
- if message[-1:] != '\n':
+ if not message:
+ message = '\n'
+ elif message[-1:] != '\n':
message += '\n'
must_switch = True
message += '\n'
must_switch = True
@@
-495,8
+516,12
@@
def merge(base, head1, head2):
local tree
"""
refresh_index()
local tree
"""
refresh_index()
- if __run('git-read-tree -u -m --aggressive', [base, head1, head2]) != 0:
- raise GitException, 'git-read-tree failed (local changes maybe?)'
+
+ try:
+ # use _output() to mask the verbose prints of the tool
+ _output('git-merge-recursive %s -- %s %s' % (base, head1, head2))
+ except GitException:
+ pass
# check the index for unmerged entries
files = {}
# check the index for unmerged entries
files = {}
@@
-566,13
+591,13
@@
def diff(files = None, rev1 = 'HEAD', rev2 = None, out_fd = None):
files = []
if rev1 and rev2:
files = []
if rev1 and rev2:
- diff_str = _output(['git-diff-tree', '-p', rev1, rev2] + files)
+ diff_str = _output(['git-diff-tree', '-p', rev1, rev2
, '--'
] + files)
elif rev1 or rev2:
refresh_index()
if rev2:
elif rev1 or rev2:
refresh_index()
if rev2:
- diff_str = _output(['git-diff-index', '-p', '-R', rev2] + files)
+ diff_str = _output(['git-diff-index', '-p', '-R', rev2
, '--'
] + files)
else:
else:
- diff_str = _output(['git-diff-index', '-p', rev1] + files)
+ diff_str = _output(['git-diff-index', '-p', rev1
, '--'
] + files)
else:
diff_str = ''
else:
diff_str = ''
@@
-641,12
+666,13
@@
def checkout(files = None, tree_id = None, force = False):
if __run(checkout_cmd, files) != 0:
raise GitException, 'Failed git-checkout-index'
if __run(checkout_cmd, files) != 0:
raise GitException, 'Failed git-checkout-index'
-def switch(tree_id):
+def switch(tree_id
, keep = False
):
"""Switch the tree to the given id
"""
"""Switch the tree to the given id
"""
- refresh_index()
- if __run('git-read-tree -u -m', [get_head(), tree_id]) != 0:
- raise GitException, 'git-read-tree failed (local changes maybe?)'
+ if not keep:
+ refresh_index()
+ if __run('git-read-tree -u -m', [get_head(), tree_id]) != 0:
+ raise GitException, 'git-read-tree failed (local changes maybe?)'
__set_head(tree_id)
__set_head(tree_id)
@@
-681,34
+707,48
@@
def pull(repository = 'origin', refspec = None):
if refspec:
args.append(refspec)
if refspec:
args.append(refspec)
- if __run(
'git-pull'
, args) != 0:
+ if __run(
config.get('stgit', 'pullcmd')
, args) != 0:
raise GitException, 'Failed "git-pull %s"' % repository
raise GitException, 'Failed "git-pull %s"' % repository
-def apply_patch(filename = None, base = None):
+def repack():
+ """Repack all objects into a single pack
+ """
+ __run('git-repack -a -d -f')
+
+def apply_patch(filename = None, diff = None, base = None,
+ fail_dump = True):
"""Apply a patch onto the current or given index. There must not
be any local changes in the tree, otherwise the command fails
"""
"""Apply a patch onto the current or given index. There must not
be any local changes in the tree, otherwise the command fails
"""
- def __apply_patch():
- if filename:
- return __run('git-apply --index', [filename]) == 0
- else:
- try:
- _input('git-apply --index', sys.stdin)
- except GitException:
- return False
- return True
-
if base:
orig_head = get_head()
switch(base)
else:
if base:
orig_head = get_head()
switch(base)
else:
- refresh_index()
# needed since __apply_patch() doesn't do it
+ refresh_index()
- if not __apply_patch():
+ if diff is None:
+ if filename:
+ f = file(filename)
+ else:
+ f = sys.stdin
+ diff = f.read()
+ if filename:
+ f.close()
+
+ try:
+ _input_str('git-apply --index', diff)
+ except GitException:
if base:
switch(orig_head)
if base:
switch(orig_head)
- raise GitException, 'Patch does not apply cleanly'
- elif base:
+ if fail_dump:
+ # write the failed diff to a file
+ f = file('.stgit-failed.patch', 'w+')
+ f.write(diff)
+ f.close()
+
+ raise
+
+ if base:
top = commit(message = 'temporary commit used for applying a patch',
parents = [base])
switch(orig_head)
top = commit(message = 'temporary commit used for applying a patch',
parents = [base])
switch(orig_head)